import * as i0 from '@angular/core';
import { inject, TemplateRef, Input, Directive, InjectionToken, isDevMode, ViewChild, Inject, ViewEncapsulation, ChangeDetectionStrategy, Component, Pipe, EventEmitter, input, ElementRef, DestroyRef, Injector, forwardRef, ContentChild, ContentChildren, Output, NgModule } from '@angular/core';
import { observeOn } from 'rxjs/operators';
import { MobileModeBase, MobileModeControl } from '@fundamental-ngx/core/mobile-mode';
import { NgTemplateOutlet } from '@angular/common';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import * as i2 from '@fundamental-ngx/cdk/utils';
import { TemplateDirective, InitialFocusDirective, KeyUtil, AutoCompleteDirective, TruncatedTitleDirective, DisplayFnPipe, SearchHighlightPipe, DynamicComponentService } from '@fundamental-ngx/cdk/utils';
import { BarMiddleDirective, BarElementDirective, ButtonBarComponent } from '@fundamental-ngx/core/bar';
import { DialogHeaderComponent, DialogCloseButtonComponent, DialogComponent, DialogBodyComponent, DialogFooterComponent } from '@fundamental-ngx/core/dialog';
import { TitleComponent } from '@fundamental-ngx/core/title';
import { asyncScheduler, Subscription, fromEvent } from 'rxjs';
import { ESCAPE, ENTER, LEFT_ARROW, RIGHT_ARROW, DOWN_ARROW, UP_ARROW, CONTROL, TAB, SHIFT, BACKSPACE, SPACE } from '@angular/cdk/keycodes';
import * as i4 from '@angular/forms';
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
import { registerFormItemControl } from '@fundamental-ngx/core/form';
import { MenuKeyboardService } from '@fundamental-ngx/core/menu';
import { PopoverComponent, PopoverControlComponent, PopoverBodyComponent } from '@fundamental-ngx/core/popover';
import * as i1 from '@angular/cdk/overlay';
import { ButtonComponent } from '@fundamental-ngx/core/button';
import * as i3 from '@fundamental-ngx/core/content-density';
import { ContentDensityModule, contentDensityObserverProviders } from '@fundamental-ngx/core/content-density';
import { FD_DEFAULT_ICON_FONT_FAMILY, IconComponent } from '@fundamental-ngx/core/icon';
import { InputGroupComponent, InputGroupInputDirective } from '@fundamental-ngx/core/input-group';
import { ListComponent, ListItemComponent, ListTitleDirective, FD_LIST_MESSAGE_DIRECTIVE } from '@fundamental-ngx/core/list';
import { resolveTranslationSignal, FdTranslatePipe } from '@fundamental-ngx/i18n';

class ComboboxItemDirective {
    constructor() {
        /** Template reference. */
        this.templateRef = inject((TemplateRef));
    }
    /** @hidden */
    static ngTemplateContextGuard(dir, ctx) {
        return true;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ComboboxItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.0", type: ComboboxItemDirective, isStandalone: true, selector: "[fdComboboxItem]", inputs: { fdComboboxItemUse: "fdComboboxItemUse" }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ComboboxItemDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[fdComboboxItem]',
                    standalone: true
                }]
        }], propDecorators: { fdComboboxItemUse: [{
                type: Input
            }] } });

const COMBOBOX_COMPONENT = new InjectionToken('ComboboxInterface');

class ComboboxMobileComponent extends MobileModeBase {
    /** @hidden */
    constructor(comboboxComponent) {
        super(comboboxComponent, MobileModeControl.COMBOBOX);
        /**
         * @hidden
         * For internal usage
         * Control element, which will be rendered inside dialog.
         * List element, which will be rendered inside dialog.
         */
        this.childContent = null;
    }
    /** @hidden */
    ngOnInit() {
        this._listenOnMultiInputOpenChange();
    }
    /** @hidden */
    handleDismiss() {
        this.dialogRef.dismiss();
        this._component.dialogDismiss(this._selectedBackup);
    }
    /** @hidden */
    handleApprove() {
        this.dialogRef.close();
        this._component.dialogApprove();
    }
    /** @hidden */
    _toggleDialog(open) {
        if (open) {
            this._selectedBackup = this._component.getValue();
            if (!this._dialogService.hasOpenDialogs()) {
                this._open();
            }
        }
    }
    /** @hidden */
    _listenOnMultiInputOpenChange() {
        this._component.openChange
            .pipe(takeUntilDestroyed(this._destroyRef))
            .subscribe((isOpen) => this._toggleDialog(isOpen));
    }
    /** @hidden */
    _open() {
        this.dialogRef = this._dialogService.open(this.dialogTemplate, {
            mobile: true,
            ...this.dialogConfig,
            backdropClickCloseable: false,
            container: this._elementRef.nativeElement,
            disablePaddings: true
        });
        this._focusInputElementOnceOpened();
        const refSub = this.dialogRef.afterClosed.subscribe({
            error: (type) => {
                if (type === 'escape') {
                    this._component.dialogDismiss(this._selectedBackup);
                    refSub.unsubscribe();
                }
            }
        });
    }
    /** @hidden */
    _focusInputElementOnceOpened() {
        this.dialogRef.afterLoaded
            .pipe(observeOn(asyncScheduler), // making the listener async
        takeUntilDestroyed(this._destroyRef))
            .subscribe(() => {
            try {
                const input = this._elementRef.nativeElement.querySelector('fd-input-group input[role="combobox"]');
                input.focus();
            }
            catch (error) {
                if (isDevMode()) {
                    console.error('Failed to focus combobox search input', error);
                }
            }
        });
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ComboboxMobileComponent, deps: [{ token: COMBOBOX_COMPONENT }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: ComboboxMobileComponent, isStandalone: true, selector: "fd-combobox-mobile", viewQueries: [{ propertyName: "dialogTemplate", first: true, predicate: ["dialogTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<ng-template [fdDialogTemplate] let-dialog let-dialogConfig=\"dialogConfig\" #dialogTemplate>\n    <fd-dialog [dialogConfig]=\"dialogConfig\" [dialogRef]=\"dialog\">\n        <fd-dialog-header>\n            @if (mobileConfig.title) {\n                <h1 fd-title>{{ mobileConfig.title }}</h1>\n            }\n            @if (mobileConfig.hasCloseButton) {\n                <button title=\"Close\" fd-dialog-close-button [mobile]=\"true\" (click)=\"handleDismiss()\"></button>\n            }\n            <ng-template fdkTemplate=\"subheader\">\n                <div fd-bar-middle>\n                    <fd-bar-element [fullWidth]=\"true\">\n                        <ng-template [ngTemplateOutlet]=\"childContent?.controlTemplate || null\"></ng-template>\n                    </fd-bar-element>\n                </div>\n            </ng-template>\n        </fd-dialog-header>\n        <fd-dialog-body>\n            <ng-template [ngTemplateOutlet]=\"childContent?.listTemplate || null\"></ng-template>\n        </fd-dialog-body>\n        <fd-dialog-footer>\n            @if (mobileConfig.approveButtonText) {\n                <fd-button-bar fdType=\"emphasized\" [label]=\"mobileConfig.approveButtonText!\" (click)=\"handleApprove()\">\n                </fd-button-bar>\n            }\n            @if (mobileConfig.cancelButtonText) {\n                <fd-button-bar fdkInitialFocus [label]=\"mobileConfig.cancelButtonText!\" (click)=\"handleDismiss()\">\n                </fd-button-bar>\n            }\n        </fd-dialog-footer>\n    </fd-dialog>\n</ng-template>\n", dependencies: [{ kind: "directive", type: TemplateDirective, selector: "[fdkTemplate]", inputs: ["fdkTemplate"] }, { kind: "directive", type: BarMiddleDirective, selector: "[fd-bar-middle]", inputs: ["stackContentsVertically"] }, { kind: "directive", type: BarElementDirective, selector: "fd-bar-element", inputs: ["fullWidth"] }, { kind: "component", type: ButtonBarComponent, selector: "fd-button-bar", inputs: ["fullWidth", "fdType", "title", "ariaLabelledby", "id"] }, { kind: "component", type: DialogHeaderComponent, selector: "fd-dialog-header", inputs: ["inShellbar"] }, { kind: "component", type: DialogCloseButtonComponent, selector: "[fd-dialog-close-button]", inputs: ["mobile", "title", "ariaLabel"] }, { kind: "component", type: DialogComponent, selector: "fd-dialog", inputs: ["class", "dialogRef", "dialogConfig"] }, { kind: "component", type: DialogBodyComponent, selector: "fd-dialog-body", inputs: ["disablePaddings"] }, { kind: "component", type: DialogFooterComponent, selector: "fd-dialog-footer" }, { kind: "component", type: TitleComponent, selector: "[fd-title], [fdTitle]", inputs: ["twoLineClamp", "headerSize", "wrap"], exportAs: ["fd-title"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: InitialFocusDirective, selector: "[fdkInitialFocus]", inputs: ["fdkInitialFocus", "enabled", "focusLastElement"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ComboboxMobileComponent, decorators: [{
            type: Component,
            args: [{ selector: 'fd-combobox-mobile', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
                        TemplateDirective,
                        BarMiddleDirective,
                        BarElementDirective,
                        ButtonBarComponent,
                        DialogHeaderComponent,
                        DialogCloseButtonComponent,
                        DialogComponent,
                        DialogBodyComponent,
                        DialogFooterComponent,
                        TitleComponent,
                        TitleComponent,
                        TemplateDirective,
                        NgTemplateOutlet,
                        InitialFocusDirective
                    ], template: "<ng-template [fdDialogTemplate] let-dialog let-dialogConfig=\"dialogConfig\" #dialogTemplate>\n    <fd-dialog [dialogConfig]=\"dialogConfig\" [dialogRef]=\"dialog\">\n        <fd-dialog-header>\n            @if (mobileConfig.title) {\n                <h1 fd-title>{{ mobileConfig.title }}</h1>\n            }\n            @if (mobileConfig.hasCloseButton) {\n                <button title=\"Close\" fd-dialog-close-button [mobile]=\"true\" (click)=\"handleDismiss()\"></button>\n            }\n            <ng-template fdkTemplate=\"subheader\">\n                <div fd-bar-middle>\n                    <fd-bar-element [fullWidth]=\"true\">\n                        <ng-template [ngTemplateOutlet]=\"childContent?.controlTemplate || null\"></ng-template>\n                    </fd-bar-element>\n                </div>\n            </ng-template>\n        </fd-dialog-header>\n        <fd-dialog-body>\n            <ng-template [ngTemplateOutlet]=\"childContent?.listTemplate || null\"></ng-template>\n        </fd-dialog-body>\n        <fd-dialog-footer>\n            @if (mobileConfig.approveButtonText) {\n                <fd-button-bar fdType=\"emphasized\" [label]=\"mobileConfig.approveButtonText!\" (click)=\"handleApprove()\">\n                </fd-button-bar>\n            }\n            @if (mobileConfig.cancelButtonText) {\n                <fd-button-bar fdkInitialFocus [label]=\"mobileConfig.cancelButtonText!\" (click)=\"handleDismiss()\">\n                </fd-button-bar>\n            }\n        </fd-dialog-footer>\n    </fd-dialog>\n</ng-template>\n" }]
        }], ctorParameters: () => [{ type: undefined, decorators: [{
                    type: Inject,
                    args: [COMBOBOX_COMPONENT]
                }] }], propDecorators: { dialogTemplate: [{
                type: ViewChild,
                args: ['dialogTemplate']
            }] } });

class ListGroupPipe {
    /** Group items */
    transform(items, group) {
        return Object.entries(group(items)).map(([key, value]) => ({ key, value }));
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ListGroupPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
    static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.0", ngImport: i0, type: ListGroupPipe, isStandalone: true, name: "listGroupPipe" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ListGroupPipe, decorators: [{
            type: Pipe,
            args: [{
                    name: 'listGroupPipe',
                    standalone: true
                }]
        }] });

const FD_COMBOBOX_COMPONENT = new InjectionToken('FdComboboxComponent');

let comboboxUniqueId = 0;
/**
 * Allows users to filter through results and select a value.
 *
 * Supports Angular Forms.
 * ```html
 * <fd-combobox
 *      [(ngModel)]="searchTerm"
 *      [dropdownValues]="dropdownValues"
 *      placeholder="Type some text...">
 * </fd-combobox>
 * ```
 */
class ComboboxComponent {
    /** @hidden */
    get _customRenderer() {
        return this._comboboxItemRenderer?.templateRef || this.itemTemplate;
    }
    /** @hidden */
    constructor(_overlay, _cdRef, _injector, _viewContainerRef, _dynamicComponentService, _focusTrapService, _contentDensityObserver) {
        this._overlay = _overlay;
        this._cdRef = _cdRef;
        this._injector = _injector;
        this._viewContainerRef = _viewContainerRef;
        this._dynamicComponentService = _dynamicComponentService;
        this._focusTrapService = _focusTrapService;
        this._contentDensityObserver = _contentDensityObserver;
        /** Id for the Combobox. */
        this.comboboxId = `fd-combobox-${comboboxUniqueId++}`;
        /** Id attribute for input element inside Combobox component */
        this.inputId = '';
        /** If it is mandatory field */
        this.required = false;
        /** Values to be filtered in the search input. */
        this.dropdownValues = [];
        /** Filter function. Accepts an array of objects and a search term as arguments
         * and returns a string. See search input examples for details. */
        this.filterFn = this._defaultFilter;
        /**
         * Whether the Combobox is a Search Field
         */
        this.isSearch = false;
        /** Icon to display in the right-side button. */
        this.glyph = 'navigation-down-arrow';
        /** Glyph font family */
        this.glyphFont = FD_DEFAULT_ICON_FONT_FAMILY;
        /**
         * Whether to show the clear search term button
         */
        this.showClearButton = false;
        /**
         *  The trigger events that will open/close the options popover.
         *  Accepts any [HTML DOM Events](https://www.w3schools.com/jsref/dom_obj_event.asp).
         */
        this.triggers = [];
        /** Whether the combobox should close, when a click is performed outside its boundaries. True by default */
        this.closeOnOutsideClick = true;
        /**
         * Whether the combobox should open, when any key is pressed in input (except Escape, Space, Enter). True by default
         */
        this.openOnKeyboardEvent = true;
        /** Max height of the popover. Any overflowing elements will be accessible through scrolling. */
        this.maxHeight = '50vh';
        /** Max width of the dropdown in pixels. Default is 640px (40rem). */
        this.dropDownMaxWidthPx = 640;
        /**
         * Whether the dropdown should have max width.
         * Set to true if you want the dropdown to take the width of the control.
         * Default is false */
        this.noDropDownMaxWidth = false;
        /** Whether the matching string should be highlighted during filtration. */
        this.highlighting = true;
        /** Whether the popover should close when a user selects a result. */
        this.closeOnSelect = true;
        /** Whether the input field should be populated with the result picked by the user. */
        this.fillOnSelect = true;
        /** Whether the autocomplete should be enabled; Enabled by default */
        this.autoComplete = true;
        /**
         * Preset options for the Select body width, whatever is chosen, the body has a 600px limit.
         * * `at-least` will apply a minimum width to the body equivalent to the width of the control. - Default
         * * `equal` will apply a width to the body equivalent to the width of the control.
         * * 'fit-content' will apply width needed to properly display items inside, independent of control.
         */
        this.fillControlMode = 'at-least';
        /** Defines if combobox should behave same as dropdown. When it's enabled writing inside text input won't
         * trigger onChange function, until it matches one of displayed dropdown values. Also communicating with combobox
         * can be achieved only by objects with same type as dropdownValue */
        this.communicateByObject = false;
        /** Display function. Accepts an object of the same type as the
         * items passed to dropdownValues as argument, and outputs a string.
         * An arrow function can be used to access the *this* keyword in the calling component.
         * See search input examples for details. */
        this.displayFn = this._defaultDisplay;
        /**
         * Whether AddOn Button should be focusable
         * @default false
         */
        this.buttonFocusable = false;
        /**
         * Whether clear button should be focusable.
         * @default true
         */
        this.clearButtonFocusable = true;
        /** Whether the combobox is readonly. */
        this.readOnly = false;
        /** Whether the combobox should be built on mobile mode */
        this.mobile = false;
        /** Whether to display the addon button. */
        this.showDropdownButton = true;
        /**
         * Whether to return results where the input matches the entire string. By default, only results that start
         * with the input search term will be returned.
         */
        this.includes = false;
        /** Whether list item options should be rendered as byline. */
        this.byline = false;
        /**
         * Action to perform when the user shifts focus away from the dropdown (Tab or click outside).
         * - `close` will close the dropdown preserving previously selected value.
         * - `closeAndSelect` will close the dropdown and select last focused dropdown item.
         */
        this.tabOutStrategy = 'closeAndSelect';
        /** Event emitted when an item is clicked. Use *$event* to retrieve it. */
        this.itemClicked = new EventEmitter();
        /** Event emitted, when the combobox's popover body is opened or closed */
        this.openChange = new EventEmitter();
        /** Event emitted when the input text changes. */
        this.inputTextChange = new EventEmitter();
        /** When communicateByObject is true, specifies which property of the selected object
         * should be used as the form control value. If not specified, the entire object is returned.
         * Example: if dropdownValues = [{ displayedValue: 'Apple', code: 'A1' }] and valueProperty = 'code',
         * the form control value will be 'A1' instead of the entire object.
         * @default null
         */
        this.valueProperty = input(null, ...(ngDevMode ? [{ debugName: "valueProperty" }] : []));
        /** Whether the matching string should be highlighted after combobox value is selected. */
        this.filterHighlight = true;
        /** Keys, that won't trigger the popover's open state, when dispatched on search input */
        this.nonOpeningKeys = [
            ESCAPE,
            ENTER,
            LEFT_ARROW,
            RIGHT_ARROW,
            DOWN_ARROW,
            UP_ARROW,
            CONTROL,
            TAB,
            SHIFT
        ];
        /** @hidden */
        this._defaultFontFamily = FD_DEFAULT_ICON_FONT_FAMILY;
        /** Whether the combobox is opened. */
        this.open = false;
        /**
         * Whether or not the input coup is in the shellbar. Only for internal use by combobox component
         * @hidden
         */
        this.inShellbar = false;
        /** @hidden */
        this.displayedValues = [];
        /** @hidden */
        this.inputTextValue = '';
        /** @hidden */
        this.clearInputBtnFocused = false;
        /** @hidden */
        this._itemMousedown = false;
        /** @hidden */
        this._clearButtonTitle = resolveTranslationSignal('coreCombobox.clearButtonTitle');
        /** @hidden */
        this._subscriptions = new Subscription();
        this._elementRef = inject(ElementRef);
        this._destroyRef = inject(DestroyRef);
        /** @hidden */
        this.onChange = () => { };
        /** @hidden */
        this.onTouched = () => { };
        this._repositionScrollStrategy = this._overlay.scrollStrategies.reposition({ autoClose: true });
        fromEvent(document, 'mousedown')
            .pipe(takeUntilDestroyed(this._destroyRef))
            .subscribe((event) => {
            if (!this.closeOnOutsideClick) {
                return;
            }
            const target = event.target;
            if (this._elementRef.nativeElement.contains(target)) {
                return;
            }
            const overlayPane = this._popoverOverlayPane();
            if (overlayPane?.contains(target)) {
                return;
            }
            if (!this._isInputDirtyVsModel()) {
                return;
            }
            this._close();
        });
    }
    /** @hidden */
    ngOnInit() {
        if (this.readOnly) {
            this.showDropdownButton = false;
        }
        this._refreshDisplayedValues();
    }
    /** @hidden */
    ngOnChanges(changes) {
        if (this.dropdownValues && (changes.dropdownValues || changes.searchTerm)) {
            this._refreshDisplayedValues();
        }
    }
    /** @hidden */
    ngOnDestroy() {
        this._subscriptions.unsubscribe();
    }
    /** @hidden */
    ngAfterViewInit() {
        this._addShellbarClass();
        if (this.mobile) {
            this._setUpMobileMode();
        }
        this._setupValueSynchronization();
    }
    /** @hidden */
    onInputKeydownHandler(event) {
        if (this.readOnly) {
            return;
        }
        if (typeof event === 'string') {
            if (event === 'fromPaste') {
                this.isOpenChangeHandle(true);
            }
        }
        else {
            if (KeyUtil.isKeyCode(event, TAB) && this.open) {
                this._close();
                return;
            }
            if (KeyUtil.isKeyCode(event, ENTER)) {
                if (this.searchFn) {
                    this.searchFn();
                }
            }
            else if (KeyUtil.isKeyCode(event, DOWN_ARROW)) {
                if (event.altKey) {
                    this._resetDisplayedValues();
                    this.isOpenChangeHandle(true);
                }
                if (this.open && this.listComponent) {
                    this.listComponent.setItemActive(0);
                }
                else if (!this.open) {
                    this._chooseOtherItem(1);
                }
                event.preventDefault();
            }
            else if (KeyUtil.isKeyCode(event, UP_ARROW)) {
                this._chooseOtherItem(-1);
                event.preventDefault();
            }
            else if (this.openOnKeyboardEvent &&
                !event.ctrlKey &&
                !event.altKey &&
                !KeyUtil.isKeyCode(event, this.nonOpeningKeys)) {
                this.isOpenChangeHandle(true);
                if (this.isEmptyValue && KeyUtil.isKeyType(event, 'control') && !KeyUtil.isKeyCode(event, BACKSPACE)) {
                    this.listComponent.setItemActive(0);
                }
            }
        }
    }
    /** @hidden */
    onItemKeyDownHandler(event, value) {
        if (KeyUtil.isKeyCode(event, ENTER) || KeyUtil.isKeyCode(event, SPACE)) {
            this._itemMousedown = true;
            event.preventDefault();
            this.onMenuClickHandler(value);
        }
    }
    /** @hidden */
    onItemFocused(value) {
        if (!this._itemMousedown && !this.mobile) {
            this.onMenuClickHandler(value, false);
        }
        this._itemMousedown = false;
    }
    /** @hidden */
    onMenuClickHandler(value, shouldClosePopover = true) {
        if (value || value === 0) {
            const index = this.dropdownValues.findIndex((_value) => _value === value);
            this._handleClickActions(value, shouldClosePopover);
            this.filterHighlight = false;
            this.itemClicked.emit({ item: value, index });
        }
    }
    /** Handle dialog dismissing, closes popover and sets backup data. */
    dialogDismiss(term) {
        this.inputText = this.displayFn(term);
        this.setValue(term);
        this._lastConfirmedValue = term;
        this.isOpenChangeHandle(false);
    }
    /** Handle dialog approval, closes popover and propagates data changes. */
    dialogApprove() {
        this._propagateChange();
        this.isOpenChangeHandle(false);
    }
    /** If true value empty */
    get isEmptyValue() {
        return !this.inputText || this.inputText?.trim().length === 0;
    }
    /** Input text of the input. */
    set inputText(value) {
        this.inputTextValue = value;
        if (!this.communicateByObject) {
            this._value = value;
        }
        this.inputTextChange.emit(value);
        if (!this.mobile) {
            this._propagateChange();
        }
    }
    get inputText() {
        return this.inputTextValue;
    }
    /** Get the glyph value based on whether the combobox is used as a search field or not. */
    get glyphValue() {
        return this.isSearch ? 'search' : this.glyph;
    }
    /** @hidden */
    _handleClearSearchTerm() {
        this.inputTextValue = '';
        this.inputTextChange.emit('');
        this.displayedValues = this.dropdownValues || [];
        this.searchInputElement.nativeElement.value = '';
        this.searchInputElement.nativeElement.focus();
        if (!this.mobile) {
            this._propagateChange();
        }
        this._cdRef.detectChanges();
    }
    /** @hidden */
    writeValue(value) {
        // If valueProperty is specified, we need to find the object with matching property value
        let valueToDisplay = value;
        const valueProp = this.valueProperty();
        if (this.communicateByObject && valueProp && value !== null && value !== undefined) {
            // Find the object in dropdownValues that matches the given property value
            const matchingObject = this.dropdownValues?.find((item) => item != null && item[valueProp] === value);
            if (matchingObject) {
                valueToDisplay = matchingObject;
            }
        }
        this.inputTextValue = this.displayFn(valueToDisplay);
        this.setValue(valueToDisplay);
        this._lastConfirmedValue = valueToDisplay;
        this._cdRef.markForCheck();
    }
    /** @hidden */
    registerOnChange(fn) {
        this.onChange = fn;
    }
    /** @hidden */
    registerOnTouched(fn) {
        this.onTouched = fn;
    }
    /** Method passed to list component */
    handleListFocusEscape(direction) {
        if (direction === 'up') {
            this.searchInputElement.nativeElement.focus();
        }
    }
    /** @hidden */
    handleSearchTermChange() {
        this.displayedValues = this.filterFn(this.dropdownValues, this.inputText);
        this.popoverComponent?.refreshPosition();
    }
    /** @hidden */
    onPrimaryButtonClick() {
        // Prevent primary button click behaviour on mobiles
        if (this.mobile) {
            return;
        }
        if (this.searchFn) {
            this.searchFn();
        }
        this._resetDisplayedValues();
        this.isOpenChangeHandle(!this.open);
        this.searchInputElement.nativeElement.focus();
        this.filterHighlight = false;
        if (this.open) {
            this.searchInputElement?.nativeElement.focus();
        }
    }
    /** @hidden */
    isOpenChangeHandle(isOpen) {
        /** Reset displayed values on every mobile open */
        if (this.mobile && !this.open) {
            this._resetDisplayedValues();
        }
        if (this.open !== isOpen) {
            this.open = isOpen;
            this.openChange.emit(isOpen);
            /** Allow combobox up and down arrows to work properly when combobox is inside a dialog with a trapped focus */
            if (this.open) {
                this._focusTrapService.pauseCurrentFocusTrap();
            }
            else {
                this._focusTrapService.unpauseCurrentFocusTrap();
            }
        }
        if (!this.open && !this.mobile) {
            this.handleBlur();
            this.searchInputElement.nativeElement.focus({ preventScroll: true });
        }
        this._cdRef.detectChanges();
    }
    /** @hidden */
    setDisabledState(isDisabled) {
        this.disabled = isDisabled;
        this._cdRef.detectChanges();
    }
    /** Method that handles complete event from auto complete directive, setting the new value, and closing popover */
    handleAutoComplete(event) {
        if (this.inputText !== event.term) {
            this.inputText = event.term;
            this.handleSearchTermChange();
        }
        if (event.forceClose && this.inputText) {
            this.isOpenChangeHandle(false);
        }
    }
    /** @hidden */
    handleBlur() {
        if (!this.open) {
            this.onTouched();
            this.handleAutoComplete({
                term: this.searchInputElement.nativeElement.value,
                forceClose: false
            });
        }
    }
    /** @hidden */
    clearInputBtnFocus() {
        this.clearInputBtnFocused = true;
    }
    /** @hidden */
    clearInputBtnBlur() {
        this.clearInputBtnFocused = false;
    }
    /** Current select value */
    getValue() {
        return this._value;
    }
    /** @hidden */
    _close() {
        const revertText = this._lastConfirmedValue != null ? this.displayFn(this._lastConfirmedValue) : '';
        this.inputText = revertText;
        this.searchInputElement.nativeElement.value = revertText;
        if (this.tabOutStrategy === 'closeAndSelect') {
            const focusedItem = this.listComponent.getActiveItem();
            if (focusedItem && !this.inputText) {
                this._handleClickActions(focusedItem.value);
                return;
            }
        }
        this.isOpenChangeHandle(false);
        this.searchInputElement.nativeElement.focus();
    }
    /** @hidden */
    isSelected(term) {
        const termValue = this.communicateByObject ? term : this.displayFn(term);
        return this.getValue() === termValue;
    }
    /** @hidden */
    _popoverOverlayPane() {
        // The combobox template sets additionalBodyClass="fd-popover-custom-list" on the popover body.
        // That class is placed inside the .cdk-overlay-pane by the CDK overlay portal.
        // Walking up finds the pane, which contains all dropdown list content.
        return document.querySelector('.fd-popover-custom-list')?.closest('.cdk-overlay-pane') ?? null;
    }
    /** @hidden */
    _isInputDirtyVsModel() {
        const expected = this._lastConfirmedValue != null ? this.displayFn(this._lastConfirmedValue) : '';
        return this.inputText !== expected;
    }
    /** Method that picks other value moved from current one by offset, called only when combobox is closed */
    _chooseOtherItem(offset) {
        const activeValue = this._getOptionObjectByDisplayedValue(this.inputTextValue)[0];
        const index = this.dropdownValues.findIndex((value) => value === activeValue);
        if (this.dropdownValues[index + offset]) {
            this.onMenuClickHandler(this.dropdownValues[index + offset]);
        }
    }
    /** Method that reset filtering for displayed values. It overrides displayed values by all possible dropdown values */
    _resetDisplayedValues() {
        this.displayedValues = this.dropdownValues || [];
    }
    /** @hidden */
    _addShellbarClass() {
        if (this.inShellbar) {
            this.searchInputElement.nativeElement.classList.add('fd-shellbar__input-group-input');
            if (this.inputGroup) {
                this.inputGroup.setInShellbar(true);
            }
        }
    }
    /** @hidden */
    _defaultDisplay(str) {
        return `${str}`;
    }
    /** @hidden */
    _defaultFilter(contentArray, searchTerm) {
        this.filterHighlight = true;
        if (typeof searchTerm === 'string') {
            const searchLower = searchTerm.toLocaleLowerCase();
            return contentArray.filter((item) => {
                if (item) {
                    const term = this.displayFn(item).toLocaleLowerCase();
                    return this.includes ? term.includes(searchLower) : term.startsWith(searchLower);
                }
            });
        }
        else if (typeof searchTerm === 'object') {
            return contentArray.filter((item) => item === searchTerm);
        }
        return contentArray || [];
    }
    /** @hidden */
    _handleClickActions(term, shouldClosePopover = true) {
        if (this.closeOnSelect && shouldClosePopover) {
            this.isOpenChangeHandle(false);
        }
        this._lastConfirmedValue = term;
        if (this.fillOnSelect) {
            this.setValue(term);
            this.inputText = this.displayFn(term);
            this.searchInputElement.nativeElement.value = this.inputText;
            this._cdRef.detectChanges();
            if (this.mobile) {
                this._propagateChange();
            }
        }
        if (shouldClosePopover) {
            this.handleSearchTermChange();
        }
    }
    /** @hidden */
    _getOptionObjectByDisplayedValue(displayValue) {
        return this.dropdownValues.filter((value) => this.displayFn(value) === displayValue);
    }
    /** @hidden */
    _refreshDisplayedValues() {
        if (this.inputText) {
            this.displayedValues = this.filterFn(this.dropdownValues, this.inputText);
        }
        else {
            this.displayedValues = this.dropdownValues || [];
        }
    }
    /** @hidden */
    _propagateChange() {
        if (this.communicateByObject) {
            const values = this._getOptionObjectByDisplayedValue(this.inputText);
            if (values.length === 1 && this.displayFn(values[0]) !== this.displayFn(this.getValue())) {
                this.setValue(values[0]);
            }
            else if (values.length === 0) {
                this.setValue(null);
            }
            this.onChange(this.getValue());
        }
        else {
            this.onChange(this.inputText);
        }
    }
    /** @hidden */
    setValue(value) {
        if (this.communicateByObject) {
            // If valueProperty is specified, extract that property from the selected object
            const valueProp = this.valueProperty();
            if (valueProp && typeof value === 'object' && value !== null) {
                this._value = value[valueProp];
            }
            else {
                this._value = value;
            }
        }
        else {
            this._value = this.displayFn(value);
        }
    }
    /** @hidden */
    _setUpMobileMode() {
        const injector = Injector.create({
            providers: [{ provide: COMBOBOX_COMPONENT, useValue: this }],
            parent: this._injector
        });
        this._dynamicComponentService.createDynamicComponent({ listTemplate: this.listTemplate, controlTemplate: this.controlTemplate }, ComboboxMobileComponent, {
            containerRef: this._viewContainerRef
        }, {
            injector
        });
    }
    /** @hidden */
    _setupValueSynchronization() {
        if (!this.searchInputElement) {
            return;
        }
        // Listen for focus events to detect programmatic changes
        this._subscriptions.add(fromEvent(this.searchInputElement.nativeElement, 'focus').subscribe(() => {
            this._syncDomValueToModel();
        }));
    }
    /** @hidden */
    _syncDomValueToModel() {
        if (!this.searchInputElement) {
            return;
        }
        const domValue = this.searchInputElement.nativeElement.value;
        if (domValue !== this.inputText) {
            // Update the model and trigger change detection
            this.inputText = domValue;
            this.handleSearchTermChange();
            this._cdRef.detectChanges();
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ComboboxComponent, deps: [{ token: i1.Overlay }, { token: i0.ChangeDetectorRef }, { token: i0.Injector }, { token: i0.ViewContainerRef }, { token: i2.DynamicComponentService }, { token: i2.FocusTrapService }, { token: i3.ContentDensityObserver }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: ComboboxComponent, isStandalone: true, selector: "fd-combobox", inputs: { comboboxId: { classPropertyName: "comboboxId", publicName: "comboboxId", isSignal: false, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: false, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: false, isRequired: false, transformFunction: null }, ariaLabelledBy: { classPropertyName: "ariaLabelledBy", publicName: "ariaLabelledBy", isSignal: false, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: false, isRequired: false, transformFunction: null }, dropdownValues: { classPropertyName: "dropdownValues", publicName: "dropdownValues", isSignal: false, isRequired: false, transformFunction: null }, filterFn: { classPropertyName: "filterFn", publicName: "filterFn", isSignal: false, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: false, isRequired: false, transformFunction: null }, isSearch: { classPropertyName: "isSearch", publicName: "isSearch", isSignal: false, isRequired: false, transformFunction: null }, glyph: { classPropertyName: "glyph", publicName: "glyph", isSignal: false, isRequired: false, transformFunction: null }, glyphFont: { classPropertyName: "glyphFont", publicName: "glyphFont", isSignal: false, isRequired: false, transformFunction: null }, showClearButton: { classPropertyName: "showClearButton", publicName: "showClearButton", isSignal: false, isRequired: false, transformFunction: null }, triggers: { classPropertyName: "triggers", publicName: "triggers", isSignal: false, isRequired: false, transformFunction: null }, closeOnOutsideClick: { classPropertyName: "closeOnOutsideClick", publicName: "closeOnOutsideClick", isSignal: false, isRequired: false, transformFunction: null }, openOnKeyboardEvent: { classPropertyName: "openOnKeyboardEvent", publicName: "openOnKeyboardEvent", isSignal: false, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: false, isRequired: false, transformFunction: null }, itemTemplate: { classPropertyName: "itemTemplate", publicName: "itemTemplate", isSignal: false, isRequired: false, transformFunction: null }, groupFn: { classPropertyName: "groupFn", publicName: "groupFn", isSignal: false, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: false, isRequired: false, transformFunction: null }, dropDownMaxWidthPx: { classPropertyName: "dropDownMaxWidthPx", publicName: "dropDownMaxWidthPx", isSignal: false, isRequired: false, transformFunction: null }, noDropDownMaxWidth: { classPropertyName: "noDropDownMaxWidth", publicName: "noDropDownMaxWidth", isSignal: false, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: false, isRequired: false, transformFunction: null }, searchFn: { classPropertyName: "searchFn", publicName: "searchFn", isSignal: false, isRequired: false, transformFunction: null }, highlighting: { classPropertyName: "highlighting", publicName: "highlighting", isSignal: false, isRequired: false, transformFunction: null }, closeOnSelect: { classPropertyName: "closeOnSelect", publicName: "closeOnSelect", isSignal: false, isRequired: false, transformFunction: null }, fillOnSelect: { classPropertyName: "fillOnSelect", publicName: "fillOnSelect", isSignal: false, isRequired: false, transformFunction: null }, autoComplete: { classPropertyName: "autoComplete", publicName: "autoComplete", isSignal: false, isRequired: false, transformFunction: null }, fillControlMode: { classPropertyName: "fillControlMode", publicName: "fillControlMode", isSignal: false, isRequired: false, transformFunction: null }, communicateByObject: { classPropertyName: "communicateByObject", publicName: "communicateByObject", isSignal: false, isRequired: false, transformFunction: null }, displayFn: { classPropertyName: "displayFn", publicName: "displayFn", isSignal: false, isRequired: false, transformFunction: null }, buttonFocusable: { classPropertyName: "buttonFocusable", publicName: "buttonFocusable", isSignal: false, isRequired: false, transformFunction: null }, clearButtonFocusable: { classPropertyName: "clearButtonFocusable", publicName: "clearButtonFocusable", isSignal: false, isRequired: false, transformFunction: null }, readOnly: { classPropertyName: "readOnly", publicName: "readOnly", isSignal: false, isRequired: false, transformFunction: null }, mobile: { classPropertyName: "mobile", publicName: "mobile", isSignal: false, isRequired: false, transformFunction: null }, mobileConfig: { classPropertyName: "mobileConfig", publicName: "mobileConfig", isSignal: false, isRequired: false, transformFunction: null }, showDropdownButton: { classPropertyName: "showDropdownButton", publicName: "showDropdownButton", isSignal: false, isRequired: false, transformFunction: null }, includes: { classPropertyName: "includes", publicName: "includes", isSignal: false, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: false, isRequired: false, transformFunction: null }, byline: { classPropertyName: "byline", publicName: "byline", isSignal: false, isRequired: false, transformFunction: null }, tabOutStrategy: { classPropertyName: "tabOutStrategy", publicName: "tabOutStrategy", isSignal: false, isRequired: false, transformFunction: null }, valueProperty: { classPropertyName: "valueProperty", publicName: "valueProperty", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClicked: "itemClicked", openChange: "openChange", inputTextChange: "inputTextChange" }, host: { properties: { "class.fd-combobox-custom-class": "true", "class.fd-combobox-input": "true", "class.fd-combobox-custom-class--mobile": "mobile", "style.width": "width" } }, providers: [
            {
                provide: NG_VALUE_ACCESSOR,
                useExisting: forwardRef(() => ComboboxComponent),
                multi: true
            },
            registerFormItemControl(ComboboxComponent),
            MenuKeyboardService,
            DynamicComponentService,
            contentDensityObserverProviders(),
            {
                provide: FD_COMBOBOX_COMPONENT,
                useExisting: ComboboxComponent
            }
        ], queries: [{ propertyName: "_comboboxItemRenderer", first: true, predicate: ComboboxItemDirective, descendants: true }, { propertyName: "listMessages", predicate: FD_LIST_MESSAGE_DIRECTIVE }], viewQueries: [{ propertyName: "listComponent", first: true, predicate: ListComponent, descendants: true }, { propertyName: "searchInputElement", first: true, predicate: ["searchInputElement"], descendants: true }, { propertyName: "popoverComponent", first: true, predicate: PopoverComponent, descendants: true }, { propertyName: "inputGroup", first: true, predicate: InputGroupComponent, descendants: true }, { propertyName: "controlTemplate", first: true, predicate: ["controlTemplate"], descendants: true }, { propertyName: "listTemplate", first: true, predicate: ["listTemplate"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<ng-template [ngTemplateOutlet]=\"mobile ? mobileTemplate : desktopTemplate\"></ng-template>\n<ng-template #desktopTemplate>\n    <fd-popover\n        additionalBodyClass=\"fd-popover-custom-list\"\n        [class.fd-combobox-full-width]=\"isSearch || showClearButton\"\n        [isOpen]=\"open && displayedValues && displayedValues.length > 0\"\n        (isOpenChange)=\"isOpenChangeHandle($event)\"\n        [fillControlMode]=\"fillControlMode\"\n        [scrollStrategy]=\"_repositionScrollStrategy\"\n        [focusTrapped]=\"true\"\n        [focusAutoCapture]=\"false\"\n        [triggers]=\"triggers\"\n        [disabled]=\"disabled || readOnly\"\n        [maxWidth]=\"!mobile && noDropDownMaxWidth ? null : dropDownMaxWidthPx\"\n        [style.width]=\"width && '100%'\"\n        [closeOnOutsideClick]=\"closeOnOutsideClick\"\n    >\n        <fd-popover-control>\n            <ng-template [ngTemplateOutlet]=\"controlTemplate\"></ng-template>\n        </fd-popover-control>\n        <fd-popover-body [hidden]=\"!displayedValues.length\">\n            <ng-template [ngTemplateOutlet]=\"listTemplate\"></ng-template>\n            <ng-content></ng-content>\n        </fd-popover-body>\n    </fd-popover>\n</ng-template>\n<ng-template let-term=\"term\" #itemSource>\n    @if (!_customRenderer) {\n        <span\n            fd-list-title\n            fdTruncatedTitle\n            [innerHTML]=\"term | displayFnPipe: displayFn | highlight: inputText : highlighting && filterHighlight\"\n        >\n        </span>\n    } @else {\n        <ng-template\n            [ngTemplateOutlet]=\"_customRenderer\"\n            [ngTemplateOutletContext]=\"{ $implicit: term, inputText: inputText }\"\n        ></ng-template>\n    }\n</ng-template>\n<ng-template #mobileTemplate>\n    <ng-template [ngTemplateOutlet]=\"controlTemplate\"></ng-template>\n</ng-template>\n<ng-template #controlTemplate>\n    <fd-input-group\n        [button]=\"showDropdownButton\"\n        [glyph]=\"showDropdownButton ? glyphValue : null\"\n        [glyphFont]=\"isSearch ? _defaultFontFamily : glyphFont\"\n        [state]=\"state\"\n        [buttonFocusable]=\"buttonFocusable\"\n        [disabled]=\"disabled\"\n        [readonly]=\"readOnly\"\n        [isControl]=\"true\"\n        [isExpanded]=\"!mobile && open && displayedValues.length > 0\"\n        [showFocus]=\"!clearInputBtnFocused\"\n        [glyphAriaLabel]=\"ariaLabel || ('platformMultiCombobox.inputGlyphAriaLabel' | fdTranslate)()\"\n        [iconTitle]=\"title || ('platformMultiCombobox.inputGlyphAriaLabel' | fdTranslate)()\"\n        (addOnButtonClicked)=\"onPrimaryButtonClick()\"\n        (click)=\"mobile && isOpenChangeHandle(true)\"\n    >\n        <input\n            #searchInputElement\n            fdkAutoComplete\n            fd-input-group-input\n            type=\"text\"\n            role=\"combobox\"\n            autocomplete=\"off\"\n            [attr.aria-label]=\"ariaLabel\"\n            [attr.aria-labelledby]=\"ariaLabelledBy\"\n            [attr.aria-describedby]=\"comboboxId + '-list-results'\"\n            [attr.aria-autocomplete]=\"autoComplete && !mobile ? 'list' : null\"\n            [attr.aria-haspopup]=\"autoComplete && !mobile\"\n            [attr.aria-expanded]=\"!mobile && open && displayedValues.length\"\n            [attr.aria-required]=\"required\"\n            [attr.tabindex]=\"readOnly || disabled ? -1 : null\"\n            [enable]=\"autoComplete && !mobile\"\n            [displayFn]=\"displayFn\"\n            [options]=\"dropdownValues\"\n            [inputText]=\"inputText\"\n            [disabled]=\"disabled\"\n            [readonly]=\"readOnly\"\n            [attr.aria-readonly]=\"readOnly\"\n            [placeholder]=\"placeholder\"\n            [id]=\"inputId\"\n            [(ngModel)]=\"inputText\"\n            (onComplete)=\"handleAutoComplete($event)\"\n            (keydown)=\"onInputKeydownHandler($event)\"\n            (paste)=\"onInputKeydownHandler('fromPaste')\"\n            (ngModelChange)=\"handleSearchTermChange()\"\n            (blur)=\"handleBlur()\"\n        />\n        @if ((isSearch || showClearButton) && inputText && inputText.length > 0) {\n            <span\n                class=\"fd-input-group__addon fd-input-group__addon--button\"\n                [class.fd-shellbar__input-group-addon]=\"inShellbar\"\n            >\n                <button\n                    fd-button\n                    class=\"fd-input-group__button\"\n                    type=\"button\"\n                    [fdType]=\"inShellbar ? 'standard' : 'transparent'\"\n                    [title]=\"_clearButtonTitle()\"\n                    [class.fd-shellbar__button]=\"inShellbar\"\n                    [attr.tabindex]=\"clearButtonFocusable ? 0 : -1\"\n                    (focus)=\"clearInputBtnFocus()\"\n                    (blur)=\"clearInputBtnBlur()\"\n                    (click)=\"_handleClearSearchTerm()\"\n                >\n                    <fd-icon glyph=\"decline\"></fd-icon>\n                </button>\n            </span>\n        }\n    </fd-input-group>\n    <div [id]=\"comboboxId + '-list-results'\" class=\"fd-combobox-count-list-results\">\n        {{ displayedValues.length || 0 }} result list items\n    </div>\n</ng-template>\n<ng-template #listTemplate>\n    @if (groupFn) {\n        <div\n            class=\"fd-combobox-custom-list\"\n            [style.maxHeight]=\"!mobile && maxHeight\"\n            (keydown.tab)=\"_close()\"\n            (keydown.shift.tab)=\"_close()\"\n        >\n            <ng-content></ng-content>\n            @for (group of displayedValues | listGroupPipe: groupFn; track group.key; let groupIndex = $index) {\n                <label class=\"fd-list__group-header\" [id]=\"comboboxId + '-group-header-' + groupIndex\">\n                    <span fd-list-title>{{ group.key }}</span>\n                </label>\n                <ul\n                    fd-list\n                    [dropdownMode]=\"true\"\n                    [id]=\"comboboxId + '-result-' + groupIndex\"\n                    role=\"listbox\"\n                    [attr.aria-labelledby]=\"comboboxId + '-group-header-' + groupIndex\"\n                    [hasMessage]=\"listMessages && listMessages.length > 0\"\n                    [byline]=\"byline\"\n                    [tabindex]=\"groupIndex === 0 ? 0 : -1\"\n                    (focusEscapeList)=\"handleListFocusEscape($event)\"\n                >\n                    @for (term of group.value; track $index; let index = $index) {\n                        <li\n                            fd-list-item\n                            ariaRole=\"option\"\n                            [attr.aria-placeholder]=\"group.key\"\n                            [attr.aria-setsize]=\"group.value.length\"\n                            [attr.aria-posinset]=\"index + 1\"\n                            class=\"fd-combobox-list-item\"\n                            [selected]=\"isSelected(term)\"\n                            [value]=\"term\"\n                            (keydown)=\"onItemKeyDownHandler($event, term)\"\n                            (mousedown)=\"_itemMousedown = true\"\n                            (click)=\"onMenuClickHandler(term)\"\n                            (focus)=\"onItemFocused(term)\"\n                        >\n                            <ng-template\n                                [ngTemplateOutlet]=\"itemSource\"\n                                [ngTemplateOutletContext]=\"{ term: term }\"\n                            ></ng-template>\n                        </li>\n                    }\n                </ul>\n            }\n        </div>\n    } @else {\n        <ul\n            fd-list\n            class=\"fd-combobox-custom-list\"\n            [dropdownMode]=\"true\"\n            [id]=\"comboboxId + '-result'\"\n            role=\"listbox\"\n            [attr.aria-labelledby]=\"comboboxId + '-search'\"\n            [style.maxHeight]=\"!mobile && maxHeight\"\n            [hasMessage]=\"listMessages && listMessages.length > 0\"\n            [byline]=\"byline\"\n            [tabindex]=\"0\"\n            (keydown.tab)=\"_close()\"\n            (keydown.shift.tab)=\"_close()\"\n            (focusEscapeList)=\"handleListFocusEscape($event)\"\n        >\n            <ng-content></ng-content>\n            @for (term of displayedValues; track $index) {\n                <li\n                    fd-list-item\n                    ariaRole=\"option\"\n                    [tabindex]=\"0\"\n                    class=\"fd-combobox-list-item\"\n                    [selected]=\"isSelected(term)\"\n                    (keydown)=\"onItemKeyDownHandler($event, term)\"\n                    (mousedown)=\"_itemMousedown = true\"\n                    (click)=\"onMenuClickHandler(term)\"\n                    [value]=\"term\"\n                    (focus)=\"onItemFocused(term)\"\n                >\n                    <ng-template\n                        [ngTemplateOutlet]=\"itemSource\"\n                        [ngTemplateOutletContext]=\"{ term: term }\"\n                    ></ng-template>\n                </li>\n            }\n        </ul>\n    }\n</ng-template>\n", styles: [".fd-combobox-custom-class,.fd-combobox-custom-class .fd-combobox-shellbar-custom{display:inline-block}.fd-combobox-custom-list.fd-list--dropdown .fd-list__item.fd-list__group-header{border-bottom:var(--sapList_BorderWidth) solid var(--sapList_GroupHeaderBorderColor)}.fd-list__item.fd-combobox-list-item{cursor:pointer}.fd-combobox-full-width{width:100%}.fd-combobox-count-list-results{position:absolute;opacity:0;z-index:-1}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PopoverComponent, selector: "fd-popover", inputs: ["config", "title", "trigger", "id", "mobile", "mobileConfig", "preventSpaceKeyScroll", "placement", "maxWidth", "fillControlMode", "closeOnOutsideClick", "closeOnEscapeKey", "disabled", "triggers", "focusTrapped", "focusAutoCapture", "restoreFocusOnClose", "noArrow", "disableScrollbar", "appendTo", "placementContainer", "scrollStrategy", "cdkPositions", "applyOverlay", "additionalBodyClass", "additionalTriggerClass", "closeOnNavigation", "fixedPosition", "resizable", "bodyAriaLabel", "bodyRole", "bodyAriaLabelledBy", "isOpen"], outputs: ["triggerChange", "isOpenChange", "beforeOpen"] }, { kind: "component", type: PopoverControlComponent, selector: "fd-popover-control, [fdPopoverControl]" }, { kind: "component", type: PopoverBodyComponent, selector: "fd-popover-body", inputs: ["minWidth", "maxWidth", "minHeight", "maxHeight"], outputs: ["onClose"] }, { kind: "component", type: ListComponent, selector: "[fd-list], [fdList]", inputs: ["dropdownMode", "multiInputMode", "mobileMode", "hasMessage", "noBorder", "navigationIndicator", "selection", "keyboardSupport", "byline", "subline", "theme", "unreadIndicator", "role", "settingsList", "settingsListFooter", "searchResultsList"], outputs: ["focusEscapeList"] }, { kind: "component", type: ListItemComponent, selector: "[fdListItem] ,[fd-list-item]", inputs: ["selected", "noData", "action", "interactive", "growing", "counter", "counterRole", "counterAriaLabel", "active", "unread", "byline", "ariaRole", "id", "preventClick", "settingsListTpl", "suggestion"], outputs: ["keyDown"], exportAs: ["fdListItem"] }, { kind: "directive", type: ListTitleDirective, selector: "[fd-list-title], [fdListTitle]", inputs: ["wrap", "truncate", "scope"] }, { kind: "component", type: InputGroupComponent, selector: "fd-input-group", inputs: ["placement", "required", "inline", "addOnText", "buttonFocusable", "type", "glyph", "glyphFont", "button", "isControl", "showFocus", "isExpanded", "glyphAriaLabel", "addonButtonAriaHidden", "iconTitle", "ariaLabelledBy", "ariaLabel"], outputs: ["addOnButtonClicked", "search"] }, { kind: "directive", type: InputGroupInputDirective, selector: "[fdInputGroupInput], [fd-input-group-input]", inputs: ["class"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i4.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: AutoCompleteDirective, selector: "[fdkAutoComplete]", inputs: ["options", "inputText", "enable", "displayFn", "matcher"], outputs: ["onComplete"] }, { kind: "component", type: ButtonComponent, selector: "button[fd-button], a[fd-button], span[fd-button]", inputs: ["id"], exportAs: ["fd-button"] }, { kind: "component", type: IconComponent, selector: "fd-icon", inputs: ["glyph", "font", "color", "background", "size", "class", "ariaLabel", "ariaHidden"], outputs: ["ariaHiddenChange"] }, { kind: "ngmodule", type: ContentDensityModule }, { kind: "directive", type: TruncatedTitleDirective, selector: "[fdkTruncatedTitle], [fdTruncatedTitle], [fd-truncate-title]" }, { kind: "pipe", type: DisplayFnPipe, name: "displayFnPipe" }, { kind: "pipe", type: SearchHighlightPipe, name: "highlight" }, { kind: "pipe", type: FdTranslatePipe, name: "fdTranslate" }, { kind: "pipe", type: ListGroupPipe, name: "listGroupPipe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ComboboxComponent, decorators: [{
            type: Component,
            args: [{ selector: 'fd-combobox', providers: [
                        {
                            provide: NG_VALUE_ACCESSOR,
                            useExisting: forwardRef(() => ComboboxComponent),
                            multi: true
                        },
                        registerFormItemControl(ComboboxComponent),
                        MenuKeyboardService,
                        DynamicComponentService,
                        contentDensityObserverProviders(),
                        {
                            provide: FD_COMBOBOX_COMPONENT,
                            useExisting: ComboboxComponent
                        }
                    ], host: {
                        '[class.fd-combobox-custom-class]': 'true',
                        '[class.fd-combobox-input]': 'true',
                        '[class.fd-combobox-custom-class--mobile]': 'mobile',
                        '[style.width]': 'width'
                    }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
                        NgTemplateOutlet,
                        PopoverComponent,
                        PopoverControlComponent,
                        PopoverBodyComponent,
                        ListComponent,
                        ListItemComponent,
                        ListTitleDirective,
                        InputGroupComponent,
                        InputGroupInputDirective,
                        FormsModule,
                        AutoCompleteDirective,
                        ButtonComponent,
                        IconComponent,
                        ContentDensityModule,
                        DisplayFnPipe,
                        SearchHighlightPipe,
                        FdTranslatePipe,
                        ListGroupPipe,
                        TruncatedTitleDirective
                    ], template: "<ng-template [ngTemplateOutlet]=\"mobile ? mobileTemplate : desktopTemplate\"></ng-template>\n<ng-template #desktopTemplate>\n    <fd-popover\n        additionalBodyClass=\"fd-popover-custom-list\"\n        [class.fd-combobox-full-width]=\"isSearch || showClearButton\"\n        [isOpen]=\"open && displayedValues && displayedValues.length > 0\"\n        (isOpenChange)=\"isOpenChangeHandle($event)\"\n        [fillControlMode]=\"fillControlMode\"\n        [scrollStrategy]=\"_repositionScrollStrategy\"\n        [focusTrapped]=\"true\"\n        [focusAutoCapture]=\"false\"\n        [triggers]=\"triggers\"\n        [disabled]=\"disabled || readOnly\"\n        [maxWidth]=\"!mobile && noDropDownMaxWidth ? null : dropDownMaxWidthPx\"\n        [style.width]=\"width && '100%'\"\n        [closeOnOutsideClick]=\"closeOnOutsideClick\"\n    >\n        <fd-popover-control>\n            <ng-template [ngTemplateOutlet]=\"controlTemplate\"></ng-template>\n        </fd-popover-control>\n        <fd-popover-body [hidden]=\"!displayedValues.length\">\n            <ng-template [ngTemplateOutlet]=\"listTemplate\"></ng-template>\n            <ng-content></ng-content>\n        </fd-popover-body>\n    </fd-popover>\n</ng-template>\n<ng-template let-term=\"term\" #itemSource>\n    @if (!_customRenderer) {\n        <span\n            fd-list-title\n            fdTruncatedTitle\n            [innerHTML]=\"term | displayFnPipe: displayFn | highlight: inputText : highlighting && filterHighlight\"\n        >\n        </span>\n    } @else {\n        <ng-template\n            [ngTemplateOutlet]=\"_customRenderer\"\n            [ngTemplateOutletContext]=\"{ $implicit: term, inputText: inputText }\"\n        ></ng-template>\n    }\n</ng-template>\n<ng-template #mobileTemplate>\n    <ng-template [ngTemplateOutlet]=\"controlTemplate\"></ng-template>\n</ng-template>\n<ng-template #controlTemplate>\n    <fd-input-group\n        [button]=\"showDropdownButton\"\n        [glyph]=\"showDropdownButton ? glyphValue : null\"\n        [glyphFont]=\"isSearch ? _defaultFontFamily : glyphFont\"\n        [state]=\"state\"\n        [buttonFocusable]=\"buttonFocusable\"\n        [disabled]=\"disabled\"\n        [readonly]=\"readOnly\"\n        [isControl]=\"true\"\n        [isExpanded]=\"!mobile && open && displayedValues.length > 0\"\n        [showFocus]=\"!clearInputBtnFocused\"\n        [glyphAriaLabel]=\"ariaLabel || ('platformMultiCombobox.inputGlyphAriaLabel' | fdTranslate)()\"\n        [iconTitle]=\"title || ('platformMultiCombobox.inputGlyphAriaLabel' | fdTranslate)()\"\n        (addOnButtonClicked)=\"onPrimaryButtonClick()\"\n        (click)=\"mobile && isOpenChangeHandle(true)\"\n    >\n        <input\n            #searchInputElement\n            fdkAutoComplete\n            fd-input-group-input\n            type=\"text\"\n            role=\"combobox\"\n            autocomplete=\"off\"\n            [attr.aria-label]=\"ariaLabel\"\n            [attr.aria-labelledby]=\"ariaLabelledBy\"\n            [attr.aria-describedby]=\"comboboxId + '-list-results'\"\n            [attr.aria-autocomplete]=\"autoComplete && !mobile ? 'list' : null\"\n            [attr.aria-haspopup]=\"autoComplete && !mobile\"\n            [attr.aria-expanded]=\"!mobile && open && displayedValues.length\"\n            [attr.aria-required]=\"required\"\n            [attr.tabindex]=\"readOnly || disabled ? -1 : null\"\n            [enable]=\"autoComplete && !mobile\"\n            [displayFn]=\"displayFn\"\n            [options]=\"dropdownValues\"\n            [inputText]=\"inputText\"\n            [disabled]=\"disabled\"\n            [readonly]=\"readOnly\"\n            [attr.aria-readonly]=\"readOnly\"\n            [placeholder]=\"placeholder\"\n            [id]=\"inputId\"\n            [(ngModel)]=\"inputText\"\n            (onComplete)=\"handleAutoComplete($event)\"\n            (keydown)=\"onInputKeydownHandler($event)\"\n            (paste)=\"onInputKeydownHandler('fromPaste')\"\n            (ngModelChange)=\"handleSearchTermChange()\"\n            (blur)=\"handleBlur()\"\n        />\n        @if ((isSearch || showClearButton) && inputText && inputText.length > 0) {\n            <span\n                class=\"fd-input-group__addon fd-input-group__addon--button\"\n                [class.fd-shellbar__input-group-addon]=\"inShellbar\"\n            >\n                <button\n                    fd-button\n                    class=\"fd-input-group__button\"\n                    type=\"button\"\n                    [fdType]=\"inShellbar ? 'standard' : 'transparent'\"\n                    [title]=\"_clearButtonTitle()\"\n                    [class.fd-shellbar__button]=\"inShellbar\"\n                    [attr.tabindex]=\"clearButtonFocusable ? 0 : -1\"\n                    (focus)=\"clearInputBtnFocus()\"\n                    (blur)=\"clearInputBtnBlur()\"\n                    (click)=\"_handleClearSearchTerm()\"\n                >\n                    <fd-icon glyph=\"decline\"></fd-icon>\n                </button>\n            </span>\n        }\n    </fd-input-group>\n    <div [id]=\"comboboxId + '-list-results'\" class=\"fd-combobox-count-list-results\">\n        {{ displayedValues.length || 0 }} result list items\n    </div>\n</ng-template>\n<ng-template #listTemplate>\n    @if (groupFn) {\n        <div\n            class=\"fd-combobox-custom-list\"\n            [style.maxHeight]=\"!mobile && maxHeight\"\n            (keydown.tab)=\"_close()\"\n            (keydown.shift.tab)=\"_close()\"\n        >\n            <ng-content></ng-content>\n            @for (group of displayedValues | listGroupPipe: groupFn; track group.key; let groupIndex = $index) {\n                <label class=\"fd-list__group-header\" [id]=\"comboboxId + '-group-header-' + groupIndex\">\n                    <span fd-list-title>{{ group.key }}</span>\n                </label>\n                <ul\n                    fd-list\n                    [dropdownMode]=\"true\"\n                    [id]=\"comboboxId + '-result-' + groupIndex\"\n                    role=\"listbox\"\n                    [attr.aria-labelledby]=\"comboboxId + '-group-header-' + groupIndex\"\n                    [hasMessage]=\"listMessages && listMessages.length > 0\"\n                    [byline]=\"byline\"\n                    [tabindex]=\"groupIndex === 0 ? 0 : -1\"\n                    (focusEscapeList)=\"handleListFocusEscape($event)\"\n                >\n                    @for (term of group.value; track $index; let index = $index) {\n                        <li\n                            fd-list-item\n                            ariaRole=\"option\"\n                            [attr.aria-placeholder]=\"group.key\"\n                            [attr.aria-setsize]=\"group.value.length\"\n                            [attr.aria-posinset]=\"index + 1\"\n                            class=\"fd-combobox-list-item\"\n                            [selected]=\"isSelected(term)\"\n                            [value]=\"term\"\n                            (keydown)=\"onItemKeyDownHandler($event, term)\"\n                            (mousedown)=\"_itemMousedown = true\"\n                            (click)=\"onMenuClickHandler(term)\"\n                            (focus)=\"onItemFocused(term)\"\n                        >\n                            <ng-template\n                                [ngTemplateOutlet]=\"itemSource\"\n                                [ngTemplateOutletContext]=\"{ term: term }\"\n                            ></ng-template>\n                        </li>\n                    }\n                </ul>\n            }\n        </div>\n    } @else {\n        <ul\n            fd-list\n            class=\"fd-combobox-custom-list\"\n            [dropdownMode]=\"true\"\n            [id]=\"comboboxId + '-result'\"\n            role=\"listbox\"\n            [attr.aria-labelledby]=\"comboboxId + '-search'\"\n            [style.maxHeight]=\"!mobile && maxHeight\"\n            [hasMessage]=\"listMessages && listMessages.length > 0\"\n            [byline]=\"byline\"\n            [tabindex]=\"0\"\n            (keydown.tab)=\"_close()\"\n            (keydown.shift.tab)=\"_close()\"\n            (focusEscapeList)=\"handleListFocusEscape($event)\"\n        >\n            <ng-content></ng-content>\n            @for (term of displayedValues; track $index) {\n                <li\n                    fd-list-item\n                    ariaRole=\"option\"\n                    [tabindex]=\"0\"\n                    class=\"fd-combobox-list-item\"\n                    [selected]=\"isSelected(term)\"\n                    (keydown)=\"onItemKeyDownHandler($event, term)\"\n                    (mousedown)=\"_itemMousedown = true\"\n                    (click)=\"onMenuClickHandler(term)\"\n                    [value]=\"term\"\n                    (focus)=\"onItemFocused(term)\"\n                >\n                    <ng-template\n                        [ngTemplateOutlet]=\"itemSource\"\n                        [ngTemplateOutletContext]=\"{ term: term }\"\n                    ></ng-template>\n                </li>\n            }\n        </ul>\n    }\n</ng-template>\n", styles: [".fd-combobox-custom-class,.fd-combobox-custom-class .fd-combobox-shellbar-custom{display:inline-block}.fd-combobox-custom-list.fd-list--dropdown .fd-list__item.fd-list__group-header{border-bottom:var(--sapList_BorderWidth) solid var(--sapList_GroupHeaderBorderColor)}.fd-list__item.fd-combobox-list-item{cursor:pointer}.fd-combobox-full-width{width:100%}.fd-combobox-count-list-results{position:absolute;opacity:0;z-index:-1}\n"] }]
        }], ctorParameters: () => [{ type: i1.Overlay }, { type: i0.ChangeDetectorRef }, { type: i0.Injector }, { type: i0.ViewContainerRef }, { type: i2.DynamicComponentService }, { type: i2.FocusTrapService }, { type: i3.ContentDensityObserver }], propDecorators: { comboboxId: [{
                type: Input
            }], inputId: [{
                type: Input
            }], ariaLabel: [{
                type: Input
            }], ariaLabelledBy: [{
                type: Input
            }], required: [{
                type: Input
            }], dropdownValues: [{
                type: Input
            }], filterFn: [{
                type: Input
            }], disabled: [{
                type: Input
            }], placeholder: [{
                type: Input
            }], isSearch: [{
                type: Input
            }], glyph: [{
                type: Input
            }], glyphFont: [{
                type: Input
            }], showClearButton: [{
                type: Input
            }], triggers: [{
                type: Input
            }], closeOnOutsideClick: [{
                type: Input
            }], openOnKeyboardEvent: [{
                type: Input
            }], state: [{
                type: Input
            }], itemTemplate: [{
                type: Input
            }], groupFn: [{
                type: Input
            }], maxHeight: [{
                type: Input
            }], dropDownMaxWidthPx: [{
                type: Input
            }], noDropDownMaxWidth: [{
                type: Input
            }], width: [{
                type: Input
            }], searchFn: [{
                type: Input
            }], highlighting: [{
                type: Input
            }], closeOnSelect: [{
                type: Input
            }], fillOnSelect: [{
                type: Input
            }], autoComplete: [{
                type: Input
            }], fillControlMode: [{
                type: Input
            }], communicateByObject: [{
                type: Input
            }], displayFn: [{
                type: Input
            }], buttonFocusable: [{
                type: Input
            }], clearButtonFocusable: [{
                type: Input
            }], readOnly: [{
                type: Input
            }], mobile: [{
                type: Input
            }], mobileConfig: [{
                type: Input
            }], showDropdownButton: [{
                type: Input
            }], includes: [{
                type: Input
            }], title: [{
                type: Input
            }], byline: [{
                type: Input
            }], tabOutStrategy: [{
                type: Input
            }], itemClicked: [{
                type: Output
            }], openChange: [{
                type: Output
            }], inputTextChange: [{
                type: Output
            }], listComponent: [{
                type: ViewChild,
                args: [ListComponent]
            }], searchInputElement: [{
                type: ViewChild,
                args: ['searchInputElement']
            }], popoverComponent: [{
                type: ViewChild,
                args: [PopoverComponent]
            }], inputGroup: [{
                type: ViewChild,
                args: [InputGroupComponent]
            }], listMessages: [{
                type: ContentChildren,
                args: [FD_LIST_MESSAGE_DIRECTIVE]
            }], controlTemplate: [{
                type: ViewChild,
                args: ['controlTemplate']
            }], listTemplate: [{
                type: ViewChild,
                args: ['listTemplate']
            }], _comboboxItemRenderer: [{
                type: ContentChild,
                args: [ComboboxItemDirective]
            }], valueProperty: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueProperty", required: false }] }] } });

/**
 * @deprecated
 * Use `ComboboxComponent` import instead.
 */
class ComboboxModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ComboboxModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.0", ngImport: i0, type: ComboboxModule, imports: [ComboboxComponent, ComboboxItemDirective, ListGroupPipe], exports: [ComboboxComponent, ComboboxItemDirective, ListGroupPipe] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ComboboxModule, imports: [ComboboxComponent] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ComboboxModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [ComboboxComponent, ComboboxItemDirective, ListGroupPipe],
                    exports: [ComboboxComponent, ComboboxItemDirective, ListGroupPipe]
                }]
        }] });

/**
 * Generated bundle index. Do not edit.
 */

export { COMBOBOX_COMPONENT, ComboboxComponent, ComboboxItemDirective, ComboboxMobileComponent, ComboboxModule, FD_COMBOBOX_COMPONENT, ListGroupPipe };
//# sourceMappingURL=fundamental-ngx-core-combobox.mjs.map
