/**
 * Copyright Aquera Inc 2023
 *
 * This source code is licensed under the BSD-3-Clause license found in the
 * LICENSE file in the root directory of this source tree.
 */
import { __decorate } from "tslib";
import { html, } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { styles } from './nile-select.css';
import '../nile-icon';
import '../nile-popup/nile-popup';
import '../nile-tag/nile-tag';
import { animateTo, stopAnimations } from '../internal/animate';
import { classMap } from 'lit/directives/class-map.js';
import { query, state } from 'lit/decorators.js';
import { defaultValue } from '../internal/default-value';
import { FormControlController } from '../internal/form';
import { getAnimation, setDefaultAnimation, } from '../utilities/animation-registry';
import { HasSlotController } from '../internal/slot';
import { scrollIntoView } from '../internal/scroll';
import { waitForEvent } from '../internal/event';
import { watch } from '../internal/watch';
import NileElement from '../internal/nile-element';
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import '../nile-virtual-select/nile-virtual-select';
import { VirtualScrollHelper } from './virtual-scroll-helper';
import { ResizeController } from '@lit-labs/observers/resize-controller.js';
import { PortalManager } from './portal-manager';
import { VisibilityManager } from '../utilities/visibility-manager';
/**
 * Nile icon component.
 *
 * @tag nile-select
 *
 */
/**
 * @summary Selects allow you to choose items from a menu of predefined options.
 * @status stable
 * @since 2.0
 *
 * @dependency nile-icon
 * @dependency nile-popup
 * @dependency nile-tag
 * @dependency nile-virtual-select
 *
 * @slot - The listbox options. Must be `<nile-option>` elements. You can use `<nile-divider>` to group items visually.
 * @slot label - The input's label. Alternatively, you can use the `label` attribute.
 * @slot prefix - Used to prepend a presentational icon or similar element to the combobox.
 * @slot clear-icon - An icon to use in lieu of the default clear icon.
 * @slot expand-icon - The icon to show when the control is expanded and collapsed. Rotates on open and close.
 * @slot help-text - Text that describes how to use the input. Alternatively, you can use the `help-text` attribute.
 * @slot pre-footer - Content to display at the bottom of the dropdown listbox. Useful for action buttons like "Create New". In multi-select mode, appears above the "Show Selected" / "Clear All" bar.
 *
 * @event nile-change - Emitted when the control's value changes.
 * @event nile-clear - Emitted when the control's value is cleared.
 * @event nile-input - Emitted when the control receives input.
 * @event nile-focus - Emitted when the control gains focus.
 * @event nile-blur - Emitted when the control loses focus.
 * @event nile-show - Emitted when the select's menu opens.
 * @event nile-after-show - Emitted after the select's menu opens and all animations are complete.
 * @event nile-hide - Emitted when the select's menu closes.
 * @event nile-after-hide - Emitted after the select's menu closes and all animations are complete.
 * @event nile-invalid - Emitted when the form control has been checked for validity and its constraints aren't satisfied.
 * @event nile-search - Emitted when the user types in the search input. The event payload includes the search query for backend search functionality.
 * @event nile-scroll - Emitted when the user scrolls within the listbox. The event payload includes scroll position information.
 * @event nile-scroll-start - Emitted when the user starts scrolling within the listbox.
 * @event nile-scroll-end - Emitted when the user stops scrolling and reaches the bottom of the listbox (debounced).
 *
 * @csspart form-control - The form control that wraps the label, input, and help text.
 * @csspart form-control-label - The label's wrapper.
 * @csspart form-control-input - The select's wrapper.
 * @csspart form-control-help-text - The help text's wrapper.
 * @csspart combobox - The container the wraps the prefix, combobox, clear icon, and expand button.
 * @csspart prefix - The container that wraps the prefix slot.
 * @csspart display-input - The element that displays the selected option's label, an `<input>` element.
 * @csspart listbox - The listbox container where options are slotted.
 * @csspart tags - The container that houses option tags when `multiselect` is used.
 * @csspart tag - The individual tags that represent each multiselect option.
 * @csspart tag__base - The tag's base part.
 * @csspart tag__content - The tag's content part.
 * @csspart tag__remove-button - The tag's remove button.
 * @csspart tag__remove-button__base - The tag's remove button base part.
 * @csspart clear-button - The clear button.
 * @csspart expand-icon - The container that wraps the expand icon.
 * @csspart custom-footer - The container that wraps the custom footer slot content.
 * @csspart footer-area - The sticky wrapper around the custom footer and the built-in multi-select footer.
 */
let NileSelect = class NileSelect extends NileElement {
    /** Gets the validity state object */
    get validity() {
        return this.valueInput?.validity;
    }
    /** Gets the validation message */
    get validationMessage() {
        return this.valueInput?.validationMessage;
    }
    constructor() {
        super();
        this.portalManager = new PortalManager(this);
        this.hasSlotController = new HasSlotController(this, 'help-text', 'label', 'pre-footer');
        this.typeToSelectString = '';
        this.scrolling = false;
        this.options = [];
        this.hasFocus = false;
        this.displayLabel = '';
        this.selectedOptions = [];
        this.oldValue = '';
        /** The name of the select, submitted as a name/value pair with form data. */
        this.name = '';
        /**
         * The current value of the select, submitted as a name/value pair with form data. When `multiple` is enabled, the
         * value will be a space-delimited list of values based on the options selected.
         */
        this.value = '';
        /** The default value of the form control. Primarily used for resetting the form control. */
        this.defaultValue = '';
        /** The select's size. */
        this.size = 'medium';
        /** Placeholder text to show as a hint when the select is empty. */
        this.placeholder = 'Select...';
        /** Placeholder text to show as a hint when the select is empty. */
        this.searchValue = '';
        this.searchEnabled = false;
        this.internalSearchPlaceHolder = 'Search...';
        this.enableVisibilityEffect = false;
        this.blockValueChange = false;
        this.disableLocalSearch = false;
        this.optionsLoading = false;
        this.noWidthSync = false;
        /**
         * When true, the listbox will be appended to the document body instead of the parent container.
         * This is useful when the parent has overflow: hidden, clip-path, or transform applied.
         */
        this.portal = false;
        /** Allows more than one option to be selected. */
        this.multiple = false;
        this.helpText = '';
        this.help_text = '';
        this.autoResize = false;
        this.errorMessage = '';
        /** Sets the input to a warning state, changing its visual appearance. */
        this.warning = false;
        /** Sets the input to an error state, changing its visual appearance. */
        this.error = false;
        /** Sets the input to a success state, changing its visual appearance. */
        this.success = false;
        /**
         * The maximum number of selected options to show when `multiple` is true. After the maximum, "+n" will be shown to
         * indicate the number of additional items that are selected. Set to 0 to remove the limit.
         */
        this.maxOptionsVisible = 3;
        /** Disables the select control. */
        this.disabled = false;
        /** Adds a clear button when the select is not empty. */
        this.clearable = false;
        /**
         * Indicates whether or not the select is open. You can toggle this attribute to show and hide the menu, or you can
         * use the `show()` and `hide()` methods and this attribute will reflect the select's open state.
         */
        this.open = false;
        /**
         * Enable this option to prevent the listbox from being clipped when the component is placed inside a container with
         * `overflow: auto|scroll`. Hoisting uses a fixed positioning strategy that works in many, but not all, scenarios.
         */
        this.hoist = false;
        /** Draws a filled select. */
        this.filled = false;
        /** Draws a pill-style select with rounded edges. */
        this.pill = false;
        /** The select's label. If you need to display HTML, use the `label` slot instead. */
        this.label = '';
        /**
         * The preferred placement of the select's menu. Note that the actual placement may vary as needed to keep the listbox
         * inside of the viewport.
         */
        this.placement = 'bottom';
        /**
         * By default, form controls are associated with the nearest containing `<form>` element. This attribute allows you
         * to place the form control outside of a form and associate it with the form that has this `id`. The form must be in
         * the same document or shadow root for this to work.
         */
        this.form = '';
        /** The select's required attribute. */
        this.required = false;
        this.showSelected = false;
        this.oldMaxOptionsVisible = 1;
        this.enableTabClose = false;
        this.showNoResults = false;
        this.noResultsMessage = 'No results found';
        this.data = [];
        this.enableVirtualScroll = false;
        /** To enable the group header in the select */
        this.enableGroupHeader = false;
        /** To auto focus the search input when the select is opened */
        this.autoFocusSearch = false;
        /** loading indicator for virtual select */
        this.loading = false;
        this.stickyHeader = false;
        this.descriptionSearchEnabled = false;
        this.enableDescription = false;
        this.allowHtmlLabel = true;
        this.handleWindowResize = () => {
            this.portalManager.updatePortalAppendPosition();
        };
        this.handleWindowScroll = () => {
            this.portalManager.updatePortalAppendPosition();
        };
    }
    connectedCallback() {
        super.connectedCallback();
        if (!this.enableVirtualScroll) {
            this.formControlController = new FormControlController(this, {
                assumeInteractionOn: ['nile-blur', 'nile-input'],
            });
        }
        this.virtualScrollHelper = new VirtualScrollHelper(this);
        this.handleDocumentFocusIn = this.handleDocumentFocusIn.bind(this);
        this.handleDocumentKeyDown = this.handleDocumentKeyDown.bind(this);
        this.handleDocumentMouseDown = this.handleDocumentMouseDown.bind(this);
        this.handleWindowResize = this.handleWindowResize.bind(this);
        this.handleWindowScroll = this.handleWindowScroll.bind(this);
        // Because this is a form control, it shouldn't be opened initially
        this.open = false;
        this.emit('nile-init');
    }
    disconnectedCallback() {
        super.disconnectedCallback();
        // Clear any pending scroll timeout to prevent memory leaks
        if (this.scrollTimeout) {
            clearTimeout(this.scrollTimeout);
            this.scrollTimeout = undefined;
        }
        this.visibilityManager?.cleanup();
        // Clean up body append elements
        this.portalManager.cleanupPortalAppend();
        this.emit('nile-destroy');
    }
    setupResizeObserver() {
        if (this.autoResize) {
            const tagsContainer = this.shadowRoot?.querySelector('.select__tags');
            if (tagsContainer) {
                this.resizeController = new ResizeController(this, {
                    callback: () => this.calculateTotalWidthOfTags()
                });
                this.resizeController.observe(tagsContainer);
            }
        }
        else {
            this.resizeController?.unobserve?.(this.shadowRoot?.querySelector('.select__tags'));
            this.resizeController = undefined;
        }
    }
    updated(_changedProperties) {
        if (_changedProperties.has('searchEnabled')) {
            this.updateGroupStickyOffsets();
        }
        if (_changedProperties.has('multiple')) {
            this.setCheckBoxInOption(this.multiple);
        }
        if (_changedProperties.has('autoResize')) {
            this.setupResizeObserver();
        }
        if (_changedProperties.has('enableDescription')) {
            this.setEnableDescriptionInOptions();
        }
    }
    firstUpdated(_changedProperties) {
        if (this.enableGroupHeader) {
            if (!this.disableLocalSearch) {
                this.handleGroupSearchChange();
            }
            this.applyStickyToGroups();
        }
        this.setupResizeObserver();
        if (_changedProperties.has('multiple')) {
            this.setCheckBoxInOption(this.multiple);
        }
        if (_changedProperties.has('enableDescription')) {
            this.setEnableDescriptionInOptions();
        }
        this.visibilityManager = new VisibilityManager({
            host: this,
            target: this.combobox,
            enableVisibilityEffect: this.enableVisibilityEffect,
            enableTabClose: this.enableTabClose,
            isOpen: () => this.open,
            onAnchorOutOfView: () => {
                this.hide();
                this.emit('nile-visibility-change', {
                    visible: false,
                    reason: 'anchor-out-of-view',
                    name: this.name,
                });
            },
            onDocumentHidden: () => {
                this.hide();
                this.emit('nile-visibility-change', {
                    visible: false,
                    reason: 'document-hidden',
                    name: this.name,
                });
            },
            emit: (event, detail) => this.emit(`nile-${event}`, detail),
        });
    }
    setCheckBoxInOption(checked) {
        if (!this.options.length) {
            this.options = this.getAllOptions();
        }
        this.options.forEach((option) => {
            option.showCheckbox = checked;
        });
    }
    setEnableDescriptionInOptions() {
        this.options = this.getAllOptions();
        this.options.forEach((option) => {
            (option?.updateComplete ?? Promise.resolve())
                .then(() => {
                option.isDescriptionEnabled = this.enableDescription;
            })
                .catch(() => {
                // ignore individual option update failures
            });
        });
    }
    addOpenListeners() {
        document.addEventListener('focusin', this.handleDocumentFocusIn);
        document.addEventListener('keydown', this.handleDocumentKeyDown);
        document.addEventListener('mousedown', this.handleDocumentMouseDown);
        if (this.portal) {
            window.addEventListener('resize', this.handleWindowResize);
            window.addEventListener('scroll', this.handleWindowScroll, true);
        }
    }
    removeOpenListeners() {
        document.removeEventListener('focusin', this.handleDocumentFocusIn);
        document.removeEventListener('keydown', this.handleDocumentKeyDown);
        document.removeEventListener('mousedown', this.handleDocumentMouseDown);
        window.removeEventListener('resize', this.handleWindowResize);
        window.removeEventListener('scroll', this.handleWindowScroll, true);
    }
    handleFocus() {
        this.hasFocus = true;
        this.displayInput.setSelectionRange(0, 0);
        this.emit('nile-focus', { value: this.value, name: this.name });
    }
    handleBlur() {
        this.hasFocus = false;
        this.emit('nile-blur', { value: this.value, name: this.name });
    }
    handleDocumentFocusIn(event) {
        if (!this.open)
            return;
        const path = event.composedPath();
        const hitSelf = path.includes(this);
        const hitPopup = this.popup && path.includes(this.popup);
        const hitPortalAppend = this.portal && this.portalManager.portalContainerElement && path.includes(this.portalManager.portalContainerElement);
        if (!hitSelf && !hitPopup && !hitPortalAppend) {
            this.hide();
        }
    }
    updateGroupStickyOffsets() {
        const groups = this.querySelectorAll('nile-option-group');
        groups.forEach(g => {
            if (this.searchEnabled) {
                g.setAttribute('search-enabled', '');
            }
            else {
                g.removeAttribute('search-enabled');
            }
        });
    }
    /**
     * Handles the click event on the footer.
     * @param event - The click event.
     */
    handleFooterClick(event) {
        event.stopPropagation();
        event.preventDefault();
    }
    handlePreFooterClick() {
        this.hide();
    }
    /**
     * Toggles the display of selected options in the dropdown
     * @param event - the event object
     */
    toggleShowSelected(event) {
        event.stopPropagation();
        event.preventDefault();
        // Only toggle if there are selected options
        if (this.selectedOptions?.length === 0) {
            return;
        }
        // Toggle the showSelected property
        this.showSelected = !this.showSelected;
        // Hide unselected options if showSelected is true
        const allOptions = this.getAllOptions();
        allOptions.forEach(el => {
            if (!el.selected) {
                el.hidden = this.showSelected;
            }
        });
        if (this.enableGroupHeader) {
            this.handleGroupShowSelected();
        }
        // Update portal content if portal is active
        if (this.portal && this.open) {
            this.portalManager.updatePortalOptions();
        }
        // this.requestUpdate();
    }
    /**
     * Deselects all options and updates the value, selectedOptions, and displayLabel properties accordingly
     */
    unSlectAll() {
        this.showSelected = false;
        const allOptions = this.getAllOptions();
        allOptions.forEach(el => {
            el.selected = false;
            el.hidden = false;
        });
        if (this.enableGroupHeader) {
            this.handleGroupShowSelected();
        }
        this.value = '';
        this.selectionChanged();
        this.emit('nile-change', { value: this.value, name: this.name });
        this.emit('nile-clear', { value: this.multiple ? this.value : '', name: this.name });
        // Update portal content if portal is active
        if (this.portal && this.open) {
            this.portalManager.updatePortalOptions();
        }
    }
    handleDocumentKeyDown(event) {
        const target = event.target;
        const isClearButton = target.closest('.select__clear') !== null;
        const isIconButton = target.closest('nile-icon-button') !== null;
        // Ignore presses when the target is an icon button (e.g. the remove button in <nile-tag>)
        if (isClearButton || isIconButton) {
            return;
        }
        // Close when pressing escape
        if (event.key === 'Escape' && this.open) {
            event.preventDefault();
            event.stopPropagation();
            this.hide();
            this.displayInput.focus({ preventScroll: true });
        }
        // Handle enter and space. When pressing space, we allow for type to select behaviors so if there's anything in the
        // buffer we _don't_ close it.
        if (event.key === 'Enter' ||
            (event.key === ' ' && this.typeToSelectString === '')) {
            event.preventDefault();
            event.stopImmediatePropagation();
            // If it's not open, open it
            if (!this.open) {
                this.show();
                return;
            }
            // If it is open, update the value based on the current selection and close it
            if (this.currentOption && !this.currentOption.disabled) {
                if (this.multiple) {
                    this.toggleOptionSelection(this.currentOption);
                }
                else {
                    this.setSelectedOptions(this.currentOption);
                }
                // Emit after updating
                this.updateComplete.then(() => {
                    this.nileInput({ value: this.value, name: this.name });
                    this.nileChange({ value: this.value, name: this.name });
                });
                if (!this.multiple) {
                    this.hide();
                    this.displayInput.focus({ preventScroll: true });
                }
            }
            return;
        }
        // All other "printable" keys trigger type to select
        if (event.key.length === 1 || event.key === 'Backspace') {
            const allOptions = this.getAllOptions();
            // Don't block important key combos like CMD+R
            if (event.metaKey || event.ctrlKey || event.altKey) {
                return;
            }
            // Open, unless the key that triggered is backspace
            if (!this.open) {
                if (event.key === 'Backspace') {
                    return;
                }
                this.show();
            }
            event.stopPropagation();
            event.preventDefault();
            clearTimeout(this.typeToSelectTimeout);
            this.typeToSelectTimeout = window.setTimeout(() => (this.typeToSelectString = ''), 1000);
            if (event.key === 'Backspace') {
                this.typeToSelectString = this.typeToSelectString.slice(0, -1);
            }
            else {
                this.typeToSelectString += event.key.toLowerCase();
            }
            for (const option of allOptions) {
                const label = option.getTextLabel().toLowerCase();
                if (label.startsWith(this.typeToSelectString)) {
                    this.setCurrentOption(option);
                    break;
                }
            }
        }
    }
    handleDocumentMouseDown(event) {
        if (!this.open)
            return;
        const path = event.composedPath();
        const hitSelf = path.includes(this);
        const hitPopup = this.popup && path.includes(this.popup);
        const hitPortalAppend = this.portal && this.portalManager.portalContainerElement && path.includes(this.portalManager.portalContainerElement);
        if (!hitSelf && !hitPopup && !hitPortalAppend) {
            this.hide();
        }
    }
    handleLabelClick() {
        this.displayInput.focus();
        this.hide();
    }
    handleComboboxMouseDown(event) {
        const path = event.composedPath();
        const isIconButton = path.some(el => el instanceof Element && el.tagName.toLowerCase() === 'nile-icon-button');
        // Ignore disabled controls and clicks on tags (remove buttons)
        if (this.disabled || isIconButton) {
            return;
        }
        event.preventDefault();
        this.displayInput.focus({ preventScroll: true });
        this.open = !this.open;
    }
    handleComboboxKeyDown(event) {
        event.stopPropagation();
        this.handleDocumentKeyDown(event);
    }
    handleClearClick(event) {
        event.stopPropagation();
        if (this.value !== '') {
            this.setSelectedOptions([]);
            this.showSelected = false;
            this.value = '';
            this.displayInput.focus({ preventScroll: true });
            if (this.enableGroupHeader) {
                this.handleGroupShowSelected();
            }
            // Emit after update
            this.updateComplete.then(() => {
                const val = { value: this.multiple ? this.value : '', name: this.name };
                this.emit('nile-clear', val);
                this.nileInput(val);
                this.nileChange(val);
            });
        }
    }
    handleClearMouseDown(event) {
        // Don't lose focus or propagate events when clicking the clear button
        event.stopPropagation();
        event.preventDefault();
    }
    handleOptionClick(event) {
        const target = event.target;
        const option = target.closest('nile-option');
        if (this.blockValueChange && option) {
            this.emit('nile-block-change', { value: option?.value, name: this.name });
            this.hide();
            return;
        }
        const oldValue = this.value;
        this.oldValue = oldValue;
        if (option && !option.disabled) {
            if (this.multiple) {
                this.toggleOptionSelection(option);
            }
            else {
                this.setSelectedOptions(option);
            }
            // Set focus after updating so the value is announced by screen readers
            this.updateComplete.then(() => this.displayInput.focus({ preventScroll: true }));
            if (this.value !== oldValue) {
                // Emit after updating
                this.updateComplete.then(() => {
                    this.nileInput({ value: this.value, name: this.name });
                    this.nileChange({ value: this.value, name: this.name });
                });
            }
            if (!this.multiple) {
                this.hide();
                this.displayInput.focus({ preventScroll: true });
            }
        }
        if (this.showSelected) {
            const allOptions = this.getAllOptions();
            allOptions.forEach(el => {
                if (!el.selected) {
                    el.hidden = this.showSelected;
                }
            });
            if (this.enableGroupHeader) {
                this.handleGroupShowSelected();
            }
            this.requestUpdate();
        }
        // Update portal content if portal is active
        if (this.portal && this.open) {
            this.portalManager.updatePortalOptions();
        }
    }
    applyStickyToGroups() {
        const groups = this.querySelectorAll('nile-option-group');
        groups.forEach(g => {
            if (this.stickyHeader) {
                g.setAttribute('sticky', '');
            }
            else {
                g.removeAttribute('sticky');
            }
        });
    }
    handleDefaultSlotChange() {
        const allOptions = this.getAllOptions();
        const value = Array.isArray(this.value) ? this.value : [this.value];
        const values = [];
        this.updateGroupStickyOffsets();
        this.applyStickyToGroups();
        // Check for duplicate values in menu items
        if (customElements.get('nile-option')) {
            allOptions.forEach(option => values.push(option.value));
            // Select only the options that match the new value
            this.setSelectedOptions(allOptions.filter(el => value.map(String).includes(el.value)));
        }
        else {
            // Rerun this handler when <nile-option> is registered
            customElements
                .whenDefined('nile-option')
                .then(() => this.handleDefaultSlotChange());
        }
        // Update portal content if portal is active
        if (this.portal && this.open) {
            this.portalManager.updatePortalOptions();
        }
        this.setEnableDescriptionInOptions();
    }
    handleTagRemove(event, option) {
        event.stopPropagation();
        if (!this.disabled) {
            this.toggleOptionSelection(option, false);
            const allOptions = this.getAllOptions();
            allOptions.forEach(el => {
                if (!el.selected) {
                    el.hidden = this.showSelected;
                }
            });
            if (this.enableGroupHeader) {
                this.handleGroupShowSelected();
            }
            // Emit after updating
            this.updateComplete.then(() => {
                this.nileInput({ value: this.value, name: this.name });
                this.nileChange({ value: this.value, name: this.name });
                this.emit('nile-tag-remove', { value: this.value, name: this.name, removedtagvalue: option.value });
            });
        }
    }
    // Gets an array of all <nile-option> elements
    getAllOptions() {
        // Get all options as an array
        const options = [...this.querySelectorAll('nile-option')];
        // Sort the options based on the order of values selected
        if (this.multiple && this.oldValue?.length > 0) {
            options.sort((a, b) => {
                let indexA = this.oldValue.indexOf(a.value);
                let indexB = this.oldValue.indexOf(b.value);
                // Handle cases where a __value is not found
                if (indexA === -1) {
                    indexA = Infinity; // Place at the end if not found
                }
                if (indexB === -1) {
                    indexB = Infinity; // Place at the end if not found
                }
                if (indexA < indexB) {
                    return -1;
                }
                if (indexA > indexB) {
                    return 1;
                }
                return 0;
            });
        }
        return options;
    }
    getOptionPrefix(option) {
        const prefixSlot = option.shadowRoot?.querySelector('slot[name="prefix"]');
        if (!prefixSlot)
            return '';
        const assignedNodes = prefixSlot.assignedNodes();
        const htmlStrings = [];
        assignedNodes.forEach(node => {
            if (node instanceof HTMLElement) {
                htmlStrings.push(node.outerHTML);
            }
            else if (node.nodeType === Node.TEXT_NODE) {
                // Text node
                htmlStrings.push(node.textContent || '');
            }
        });
        return htmlStrings.join('');
    }
    // Gets the first <nile-option> element
    getFirstOption() {
        return this.querySelector('nile-option');
    }
    // Sets the current option, which is the option the user is currently interacting with (e.g. via keyboard). Only one
    // option may be "current" at a time.
    setCurrentOption(option) {
        const allOptions = this.getAllOptions();
        // Clear selection
        allOptions.forEach(el => {
            el.current = false;
            el.tabIndex = -1;
        });
        // Select the target option
        if (option) {
            this.currentOption = option;
            option.current = true;
            option.tabIndex = 0;
            option.focus();
        }
    }
    // Sets the selected option(s)
    setSelectedOptions(option) {
        const allOptions = this.getAllOptions();
        const newSelectedOptions = Array.isArray(option) ? option : [option];
        // Clear existing selection
        allOptions.forEach(el => (el.selected = false));
        // Set the new selection
        if (newSelectedOptions.length) {
            newSelectedOptions.forEach(el => (el.selected = true));
        }
        // Update selection, value, and display label
        this.selectionChanged();
        // Update portal content if portal is active
        if (this.portal && this.open) {
            this.portalManager.updatePortalOptions();
        }
    }
    // Toggles an option's selected state
    toggleOptionSelection(option, force) {
        if (force === true || force === false) {
            option.selected = force;
        }
        else {
            option.selected = !option.selected;
        }
        this.selectionChanged();
    }
    // This method must be called whenever the selection changes. It will update the selected options cache, the current
    // value, and the display value
    selectionChanged() {
        // Update selected options cache
        this.selectedOptions = this.getAllOptions().filter(el => el.selected);
        // Update the value and display label
        if (this.multiple) {
            this.value = this.selectedOptions.map(el => el.value);
            if (this.placeholder && this.value.length === 0) {
                // When no items are selected, keep the value empty so the placeholder shows
                this.displayLabel = '';
            }
            else {
                this.displayLabel = this.selectedOptions.length + ' selected';
            }
            if (this.selectedOptions.length === 0) {
                this.showSelected = false;
                const allOptions = this.getAllOptions();
                allOptions.forEach(el => {
                    if (!el.selected) {
                        el.hidden = this.showSelected;
                    }
                    else { }
                });
                this.requestUpdate();
            }
        }
        else {
            this.value = this.selectedOptions[0]?.value ?? this.value;
            this.displayLabel = this.selectedOptions[0]?.getTextLabel()
                ? this.selectedOptions[0].getTextLabel()
                : this.value ?? '';
        }
        // Update validity
        this.updateComplete.then(() => {
            this.formControlController?.updateValidity();
        });
        this.calculateTotalWidthOfTags();
    }
    handleSearchFocus() {
        document.removeEventListener('keydown', this.handleDocumentKeyDown);
    }
    handleSearchBlur() {
        document.addEventListener('keydown', this.handleDocumentKeyDown);
    }
    handleSearchChange(e) {
        this.searchValue = e.detail.value;
        this.emit('nile-search', {
            query: this.searchValue,
            name: this.name
        });
        if (this.enableGroupHeader && !this.disableLocalSearch) {
            this.handleGroupSearchChange();
        }
        if (!this.disableLocalSearch) {
            let filteredOptions = this.filterOptions(this.searchValue);
            if (filteredOptions.length === 0) {
                // Display 'No results found' message.
                this.showNoResults = true;
            }
            else {
                this.showNoResults = false;
            }
        }
    }
    handleScroll(e) {
        const target = e.target;
        this.emit('nile-scroll', {
            scrollTop: target.scrollTop,
            scrollLeft: target.scrollLeft,
            name: this.name
        });
        if (!this.scrolling) {
            this.scrolling = true;
            this.emit('nile-scroll-start', {
                scrollTop: target.scrollTop,
                scrollLeft: target.scrollLeft,
                name: this.name
            });
        }
        clearTimeout(this.scrollTimeout);
        this.scrollTimeout = window.setTimeout(() => {
            if (this.scrolling) {
                this.scrolling = false;
            }
        }, 300);
        const isAtBottom = Math.ceil(target.scrollTop) >= Math.floor(target.scrollHeight - target.offsetHeight);
        if (isAtBottom) {
            this.emit('nile-scroll-end', {
                scrollTop: target.scrollTop,
                scrollLeft: target.scrollLeft,
                name: this.name,
                isAtBottom: true
            });
        }
    }
    filterOptions(searchValue) {
        const allOptions = this.getAllOptions();
        const lowerCaseSearchValue = searchValue.toLowerCase();
        let filteredOptions = [];
        allOptions.forEach(el => {
            const lowerCaseLabel = el.getTextLabel().toLowerCase();
            const lowerCaseValue = (el.value || '').toLowerCase();
            const lowerCaseDescription = (el.description || '').toLowerCase();
            const matches = lowerCaseLabel.includes(lowerCaseSearchValue) ||
                lowerCaseValue.includes(lowerCaseSearchValue) ||
                (this.descriptionSearchEnabled && lowerCaseDescription.includes(lowerCaseSearchValue));
            el.hidden = !matches;
            if (matches)
                filteredOptions.push(el);
        });
        // Update portal content if portal is active
        if (this.portal && this.open) {
            this.portalManager.updatePortalOptions();
        }
        return filteredOptions;
    }
    handleInvalid(event) {
        this.formControlController?.setValidity(false);
        this.formControlController?.emitInvalidEvent(event);
    }
    handleDisabledChange() {
        // Close the listbox when the control is disabled
        if (this.disabled) {
            this.open = false;
            this.handleOpenChange();
        }
    }
    handleValueChange() {
        const allOptions = this.getAllOptions();
        const value = Array.isArray(this.value) ? this.value : [this.value];
        if (!this.enableVirtualScroll) {
            this.setSelectedOptions(allOptions.filter(el => value.includes(el.value)));
        }
    }
    handlePortalAppendChange() {
        if (this.open) {
            if (this.portal) {
                this.portalManager.setupPortalAppend();
            }
            else {
                this.portalManager.cleanupPortalAppend();
            }
        }
    }
    async handleOpenChange() {
        if (this.open && !this.disabled) {
            // Reset the current option
            this.setCurrentOption(this.selectedOptions[0] || this.getFirstOption());
            this.emit('nile-show', { value: this.value, name: this.name });
            if (this.enableGroupHeader) {
                this.getAllGroupAttributes().forEach((el) => {
                    el.element.classList.remove('nile-group-hidden');
                });
            }
            this.addOpenListeners();
            this.visibilityManager?.setup();
            this.showNoResults = !this.getAllOptions()?.length;
            await stopAnimations(this);
            this.listbox.hidden = false;
            this.popup.active = true;
            // Select the appropriate option based on value after the listbox opens
            requestAnimationFrame(() => {
                this.setCurrentOption(this.currentOption);
            });
            const { keyframes, options } = getAnimation(this, 'select.show', {
                dir: 'ltr',
            });
            await animateTo(this.popup.popup, keyframes, options);
            // Make sure the current option is scrolled into view (required for Safari)
            if (this.currentOption) {
                scrollIntoView(this.currentOption, this.listbox, 'vertical', 'auto');
            }
            this.searchValue = '';
            this.filterOptions(this.searchValue);
            if (this.portal) {
                this.portalManager.setupPortalAppend();
            }
            this.emit('nile-after-show', { value: this.value, name: this.name });
            if (this.autoFocusSearch) {
                this.handleInputAfterInit();
            }
        }
        else {
            // Hide
            this.emit('nile-hide', { value: this.value, name: this.name });
            this.showSelected = false;
            this.removeOpenListeners();
            this.visibilityManager?.cleanup();
            await stopAnimations(this);
            const { keyframes, options } = getAnimation(this, 'select.hide', {
                dir: 'ltr',
            });
            await animateTo(this.popup.popup, keyframes, options);
            this.listbox.hidden = true;
            this.popup.active = false;
            if (this.portal) {
                this.portalManager.cleanupPortalAppend();
            }
            this.searchValue = '';
            this.emit('nile-after-hide', { value: this.value, name: this.name });
        }
    }
    getAllGroupAttributes() {
        return Array.from(this.querySelectorAll('nile-option-group[name]')).map((el) => ({
            name: el?.getAttribute('name') || '',
            data: el?.getAttribute('data'),
            element: el
        }));
    }
    getUniqueGroupNames(arr) {
        return Array.from(new Set(arr.map(obj => obj?.groupName)));
    }
    handleGroupSearchChange() {
        const filtered = new Set(this.getUniqueGroupNames(this.filterOptions(this.searchValue)));
        this.getAllGroupAttributes().forEach(({ name, element }) => {
            element?.classList.toggle('nile-group-hidden', !filtered.has(name));
        });
    }
    handleGroupShowSelected() {
        const visibleGroups = new Set();
        if (this.showSelected) {
            this.getAllOptions().forEach((option) => {
                if (!option.hidden)
                    visibleGroups.add(option.groupName);
            });
        }
        this.getAllGroupAttributes().forEach(({ name, element }) => {
            element?.classList.toggle('nile-group-hidden', this.showSelected && !visibleGroups.has(name));
        });
    }
    /** Shows the listbox. */
    async show() {
        if (this.open || this.disabled) {
            this.open = false;
            return undefined;
        }
        this.open = true;
        return waitForEvent(this, 'nile-after-show');
    }
    /** Hides the listbox. */
    async hide() {
        if (!this.open || this.disabled) {
            this.open = false;
            return undefined;
        }
        this.open = false;
        return waitForEvent(this, 'nile-after-hide');
    }
    /** Checks for validity but does not show a validation message. Returns `true` when valid and `false` when invalid. */
    checkValidity() {
        return this.valueInput.checkValidity();
    }
    /** Gets the associated form, if one exists. */
    getForm() {
        return this.formControlController?.getForm() || null;
    }
    /** Checks for validity and shows the browser's validation message if the control is invalid. */
    reportValidity() {
        return this.valueInput.reportValidity();
    }
    /** Sets a custom validation message. Pass an empty string to restore validity. */
    setCustomValidity(message) {
        this.valueInput.setCustomValidity(message);
        this.formControlController?.updateValidity();
    }
    /** Sets focus on the control. */
    focus(options) {
        this.displayInput.focus(options);
    }
    /** Removes focus from the control. */
    blur() {
        this.displayInput.blur();
    }
    onInputChange(event) {
        // This will stop the event from bubbling up to the parent `nile-select` component
        event.stopPropagation();
    }
    calculateWidthOfSelectTagsDiv() {
        if (this.shadowRoot) {
            const selectTagsDiv = this.shadowRoot.querySelector('div.select__tags');
            if (selectTagsDiv instanceof HTMLElement) {
                const width = selectTagsDiv.offsetWidth;
                return width - 70;
            }
        }
    }
    calculateTotalWidthOfTags() {
        if (this.maxOptionsVisible !== Infinity) {
            this.oldMaxOptionsVisible = this.maxOptionsVisible;
        }
        this.maxOptionsVisible = Infinity;
        setTimeout(() => {
            let widths = [];
            if (this.shadowRoot) {
                const tags = this.shadowRoot.querySelectorAll('nile-tag');
                tags.forEach(tag => {
                    if (tag instanceof HTMLElement) {
                        widths.push(tag.offsetWidth);
                    }
                });
            }
            if (this.value.length !== widths.length) {
                return;
            }
            let sum = widths.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
            const widthOfSelectTagsDiv = this.calculateWidthOfSelectTagsDiv();
            if (!widthOfSelectTagsDiv) {
                return;
            }
            let summ = 0;
            let lastindex = 0;
            for (let i = 0; i < widths.length; i++) {
                summ += widths[i];
                if (summ > widthOfSelectTagsDiv) {
                    lastindex = i;
                    break;
                }
            }
            this.maxOptionsVisible = lastindex;
        }, 1);
    }
    handleInputAfterInit() {
        this.shadowRoot?.querySelector('nile-input')?.inputFocus();
    }
    render() {
        if (this.enableVirtualScroll) {
            return this.virtualScrollHelper.renderVirtualizedContent();
        }
        const hasLabelSlot = this.hasSlotController.test('label');
        const hasHelpTextSlot = this.hasSlotController.test('help-text');
        const hasLabelSuffixSlot = this.hasSlotController.test('label-suffix');
        const hasCustomSelect = this.hasSlotController.test('custom-select');
        const hasLabel = this.label ? true : !!hasLabelSlot;
        const hasClearIcon = this.clearable && !this.disabled && this.value.length > 0;
        const isPlaceholderVisible = this.placeholder && this.value.length === 0;
        const hasHelpText = (this.helpText || this.help_text) ? true : false;
        const hasErrorMessage = this.errorMessage ? true : false;
        const prefixContent = this.selectedOptions[0]
            ? this.getOptionPrefix(this.selectedOptions[0])
            : '';
        return html `
      <div
        part="form-control"
        class=${classMap({
            'form-control': true,
            'form-control--small': this.size === 'small',
            'form-control--medium': this.size === 'medium',
            'form-control--large': this.size === 'large',
            'form-control--has-label': hasLabel,
            'form-control--has-help-text': hasHelpText,
        })}
      >
        <label
          id="label"
          part="form-control-label"
          class="form-control__label"
          aria-hidden=${hasLabel ? 'false' : 'true'}
          @click=${this.handleLabelClick}
        >
          <slot name="label">${this.label}</slot>
        </label>

        ${hasLabelSuffixSlot ? html ` <slot name="label-suffix"></slot> ` : ``}

        <div part="form-control-input" class="form-control-input">
          <nile-popup
            class=${classMap({
            select: true,
            'select--warning': this.warning,
            'select--error': this.error,
            'select--success': this.success,
            'select--standard': true,
            'select--filled': this.filled,
            'select--pill': this.pill,
            'select--open': this.open,
            'select--disabled': this.disabled,
            'select--multiple': this.multiple,
            'select--focused': this.hasFocus,
            'select--placeholder-visible': isPlaceholderVisible,
            'select--top': this.placement === 'top',
            'select--bottom': this.placement === 'bottom',
            'select--small': this.size === 'small',
            'select--medium': this.size === 'medium',
            'select--large': this.size === 'large',
        })}
            placement=${this.placement}
            strategy=${this.portal ? 'fixed' : (this.hoist ? 'fixed' : 'absolute')}
            distance="6"
            ?flip=${!this.portal}
            ?shift=${!this.portal}
            sync=${ifDefined(!this.noWidthSync ? 'width' : undefined)}
            auto-size="vertical"
            auto-size-padding="10"
          >
            ${hasCustomSelect
            ? html `<slot
                  slot="anchor"
                  name="custom-select"
                  class="custom-select"
                  @keydown=${this.handleComboboxKeyDown}
                  @mousedown=${this.handleComboboxMouseDown}
                ></slot>`
            : html ``}
            <div
              part="combobox"
              class=${classMap({
            select__combobox: true,
            'select__hide-default': hasCustomSelect,
        })}
              slot="anchor"
              @keydown=${this.handleComboboxKeyDown}
              @mousedown=${this.handleComboboxMouseDown}
            >
              ${prefixContent && !this.multiple
            ? html `<div class="select__prefix--from-options">
                    ${unsafeHTML(prefixContent)}
                  </div>`
            : html `<slot
                    part="prefix"
                    name="prefix"
                    class=${classMap({
                select__prefix: true,
                multiple: this.multiple,
            })}
                  ></slot>`}

              <input
                part="display-input"
                class="select__display-input"
                type="text"
                placeholder=${this.placeholder}
                .disabled=${this.disabled}
                .value=${this.displayLabel}
                autocomplete="off"
                spellcheck="false"
                autocapitalize="off"
                readonly
                aria-controls="listbox"
                aria-expanded=${this.open ? 'true' : 'false'}
                aria-haspopup="listbox"
                aria-labelledby="label"
                aria-disabled=${this.disabled ? 'true' : 'false'}
                aria-describedby="help-text"
                role="combobox"
                tabindex="0"
                @focus=${this.handleFocus}
                @blur=${this.handleBlur}
              />

              ${this.multiple
            ? html `
                    <div part="tags" class="select__tags">
                      ${this.selectedOptions.map((option, index) => {
                if (index < this.maxOptionsVisible ||
                    this.maxOptionsVisible <= 0) {
                    const classes = {
                        select__invisible: index + 1 > this.oldMaxOptionsVisible &&
                            this.maxOptionsVisible === Infinity,
                    };
                    return html `
                            <nile-tag
                              class=${classMap(classes)}
                              part="tag"
                              exportparts="
                                  base:tag__base,
                                  content:tag__content,
                                  remove-button:tag__remove-button,
                                  remove-button__base:tag__remove-button__base,
                                  prefix:tag__prefix,
                                  prefix_content_wrapper:tag__prefix_content_wrapper
                                "
                              ?pill=${this.pill}
                              size=${this.size}
                              removable
                              @nile-remove=${(event) => this.handleTagRemove(event, option)}
                            >
                              ${this.getOptionPrefix(option)
                        ? html `<span class="tag__prefix" slot="prefix"
                                    >${unsafeHTML(this.getOptionPrefix(option))}</span
                                  >`
                        : ''}
                              ${option.getTextLabel()}
                            </nile-tag>
                          `;
                }
                else if (index === this.maxOptionsVisible) {
                    return html `
                            <span class="select__tags-count"
                              >+${this.selectedOptions.length - index} More
                            </span>
                          `;
                }
                else {
                    return null;
                }
            })}
                    </div>
                  `
            : ''}

              <input
                class="select__value-input"
                type="text"
                ?disabled=${this.disabled}
                ?required=${this.required}
                .value=${Array.isArray(this.value)
            ? this.value.join(', ')
            : this.value}
                tabindex="-1"
                aria-hidden="true"
                @focus=${() => this.focus()}
                @invalid=${this.handleInvalid}
              />

              ${hasClearIcon
            ? html `
                    <button
                      part="clear-button"
                      class="select__clear"
                      type="button"
                      aria-label="clearEntry"
                      @mousedown=${this.handleClearMouseDown}
                      @click=${this.handleClearClick}
                      tabindex="-1"
                    >
                      <slot name="clear-icon">
                        <nile-icon name="var(--nile-icon-close, var(--ng-icon-x-close))" size="var(--nile-height-14px, var(--ng-height-16px))" method="var(--nile-svg-method-fill, var(--ng-svg-method-stroke))" library="system"  color="var(--nile-colors-dark-500, var(--ng-colors-fg-quaternary-400))"></nile-icon>
                      </slot>
                    </button>
                  `
            : ''}

              <slot
                part="suffix"
                name="suffix"
                class=${classMap({
            select__suffix: true,
        })}
              ></slot>

              <slot
                name="expand-icon"
                part="expand-icon"
                class="select__expand-icon"
              >
                <nile-icon library="system" name="var(--nile-icon-arrow-down, var(--ng-icon-chevron-down))" method="var(--nile-svg-method-fill, var(--ng-svg-method-stroke))" color="var(--nile-colors-dark-500, var(--ng-colors-fg-quaternary-400))"></nile-icon>
              </slot>
            </div>

            <div
              id="listbox"
              role="listbox"
              aria-expanded=${this.open ? 'true' : 'false'}
              aria-multiselectable=${this.multiple ? 'true' : 'false'}
              aria-labelledby="label"
              part="listbox"
              class="select__listbox ${this.searchEnabled
            ? 'select__search-enabled '
            : ''} ${this.portal ? 'select__portal-append-hidden' : ''}"
              tabindex="-1"
              @mouseup=${this.handleOptionClick}
              @slotchange=${this.handleDefaultSlotChange}
              @scroll=${this.handleScroll}
              style=${this.portal ? 'display: none;' : ''}
            >
              ${this.searchEnabled
            ? html ` <div class="select__search">
                    <nile-input
                      size="small"
                      clearable
                      .value=${this.searchValue}
                      placeholder="${this.internalSearchPlaceHolder}"
                      @nile-input=${this.handleSearchChange}
                      @nile-focus=${this.handleSearchFocus}
                      @nile-change="${this.onInputChange}"
                      @nile-after-init=${this.handleInputAfterInit}
                    >
                      <nile-icon name="var(--nile-icon-search, var(--ng-icon-search-lg))" method="var(--nile-svg-method-fill, var(--ng-svg-method-stroke))" slot="suffix"> </nile-icon>
                    </nile-input>
                  </div>`
            : ``}
              ${this.optionsLoading
            ? html `
                    <span class="select__loader">
                      <nile-icon
                        class="select__loader--icon"
                        name="var(--nile-icon-button-loading-blue, var(--ng-icon-button-loading-blue))"
                        method="var(--nile-svg-method-fill, var(--ng-svg-method-stroke))"
                      ></nile-icon>
                    </span>
                  `
            : ''}

              <div
                class="select__options ${this.searchEnabled
            ? 'select__options__search-enabled'
            : ``}"
              >
                ${this.showNoResults
            ? html `
                      <div class="select__no-results">
                        ${this.noResultsMessage}
                      </div>
                    `
            : ''}
                <slot></slot>
              </div>

              ${this.hasSlotController.test('pre-footer') || this.multiple
            ? html `<div part="footer-area" class="select__pre-footer-area">
                    ${this.hasSlotController.test('pre-footer')
                ? html `
                      <div part="pre-footer" @click=${this.handlePreFooterClick}>  
                        <slot
                          name="pre-footer"
                          class="select__custom-footer"
                        ></slot> </div>`
                : ''}
                    ${this.multiple
                ? html `<div
                          part="footer"
                          class="select__footer"
                          @click="${this.handleFooterClick}"
                        >
                          <span
                            @click="${this.toggleShowSelected}"
                            style="cursor: pointer;"
                          >
                            <nile-checkbox
                              ?disabled="${this.selectedOptions.length === 0}"
                              ?checked="${this.showSelected}"
                            >
                              &nbsp; Show Selected</nile-checkbox
                            >
                          </span>
                          ${this.selectedOptions.length !== 0
                    ? html `<span
                                class="select__clear"
                                @click="${this.unSlectAll}"
                                >Clear All</span
                              >`
                    : ``}
                        </div>`
                : ``}
                  </div>`
            : ``}
            </div>
          </nile-popup>
        </div>

        ${hasHelpText
            ? html ` <nile-form-help-text>${(this.helpText || this.help_text)}</nile-form-help-text> `
            : ``}
        ${hasErrorMessage
            ? html `
              <nile-form-error-message
                >${this.errorMessage}</nile-form-error-message
              >
            `
            : ``}
      </div>
    `;
    }
    nileInput(value) {
        this.emit('nile-input', value);
    }
    nileChange(value) {
        this.emit('nile-change', value);
    }
};
NileSelect.styles = styles;
__decorate([
    query('.select')
], NileSelect.prototype, "popup", void 0);
__decorate([
    query('.select__combobox')
], NileSelect.prototype, "combobox", void 0);
__decorate([
    query('.select__display-input')
], NileSelect.prototype, "displayInput", void 0);
__decorate([
    query('.select__value-input')
], NileSelect.prototype, "valueInput", void 0);
__decorate([
    query('.select__listbox')
], NileSelect.prototype, "listbox", void 0);
__decorate([
    state()
], NileSelect.prototype, "hasFocus", void 0);
__decorate([
    state()
], NileSelect.prototype, "displayLabel", void 0);
__decorate([
    state()
], NileSelect.prototype, "currentOption", void 0);
__decorate([
    state()
], NileSelect.prototype, "selectedOptions", void 0);
__decorate([
    state()
], NileSelect.prototype, "oldValue", void 0);
__decorate([
    property()
], NileSelect.prototype, "name", void 0);
__decorate([
    property({
        converter: {
            fromAttribute: (value) => value.split(' '),
            toAttribute: (value) => value.join(' '),
        },
    })
], NileSelect.prototype, "value", void 0);
__decorate([
    defaultValue()
], NileSelect.prototype, "defaultValue", void 0);
__decorate([
    property()
], NileSelect.prototype, "size", void 0);
__decorate([
    property()
], NileSelect.prototype, "placeholder", void 0);
__decorate([
    state()
], NileSelect.prototype, "searchValue", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], NileSelect.prototype, "searchEnabled", void 0);
__decorate([
    property({ attribute: 'internal-search-placeholder' })
], NileSelect.prototype, "internalSearchPlaceHolder", void 0);
__decorate([
    property({ type: Boolean, reflect: true, attribute: true })
], NileSelect.prototype, "enableVisibilityEffect", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], NileSelect.prototype, "blockValueChange", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], NileSelect.prototype, "disableLocalSearch", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], NileSelect.prototype, "optionsLoading", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], NileSelect.prototype, "noWidthSync", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], NileSelect.prototype, "portal", void 0);
__decorate([
    property({
        reflect: true,
        converter: {
            fromAttribute(value) {
                if (value === '' || value === 'true')
                    return true;
                if (value === 'false')
                    return false;
                return value;
            },
            toAttribute(value) {
                return typeof value === 'boolean' ? String(value) : value;
            }
        }
    })
], NileSelect.prototype, "multiple", void 0);
__decorate([
    property({ attribute: true, reflect: true })
], NileSelect.prototype, "helpText", void 0);
__decorate([
    property({ attribute: 'help-text', reflect: true })
], NileSelect.prototype, "help_text", void 0);
__decorate([
    property({ type: Boolean, attribute: true, reflect: true })
], NileSelect.prototype, "autoResize", void 0);
__decorate([
    property({ attribute: 'error-message', reflect: true })
], NileSelect.prototype, "errorMessage", void 0);
__decorate([
    property({ type: Boolean })
], NileSelect.prototype, "warning", void 0);
__decorate([
    property({ type: Boolean })
], NileSelect.prototype, "error", void 0);
__decorate([
    property({ type: Boolean })
], NileSelect.prototype, "success", void 0);
__decorate([
    property({ attribute: 'max-options-visible', type: Number })
], NileSelect.prototype, "maxOptionsVisible", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], NileSelect.prototype, "disabled", void 0);
__decorate([
    property({ type: Boolean })
], NileSelect.prototype, "clearable", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], NileSelect.prototype, "open", void 0);
__decorate([
    property({ type: Boolean })
], NileSelect.prototype, "hoist", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], NileSelect.prototype, "filled", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], NileSelect.prototype, "pill", void 0);
__decorate([
    property()
], NileSelect.prototype, "label", void 0);
__decorate([
    property({ reflect: true })
], NileSelect.prototype, "placement", void 0);
__decorate([
    property({ reflect: true })
], NileSelect.prototype, "form", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], NileSelect.prototype, "required", void 0);
__decorate([
    property({ type: Boolean })
], NileSelect.prototype, "showSelected", void 0);
__decorate([
    state()
], NileSelect.prototype, "oldMaxOptionsVisible", void 0);
__decorate([
    property({ type: Boolean, reflect: true, attribute: true })
], NileSelect.prototype, "enableTabClose", void 0);
__decorate([
    property({ type: Boolean })
], NileSelect.prototype, "showNoResults", void 0);
__decorate([
    property({ type: String })
], NileSelect.prototype, "noResultsMessage", void 0);
__decorate([
    property({ attribute: false })
], NileSelect.prototype, "renderItemConfig", void 0);
__decorate([
    property({ type: Array })
], NileSelect.prototype, "data", void 0);
__decorate([
    property({ type: Boolean })
], NileSelect.prototype, "enableVirtualScroll", void 0);
__decorate([
    property({ type: Boolean, reflect: true, attribute: true })
], NileSelect.prototype, "enableGroupHeader", void 0);
__decorate([
    property({ type: Boolean, reflect: true, attribute: true })
], NileSelect.prototype, "autoFocusSearch", void 0);
__decorate([
    property({ type: Boolean, reflect: true, attribute: true })
], NileSelect.prototype, "loading", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], NileSelect.prototype, "stickyHeader", void 0);
__decorate([
    property({ type: Boolean, reflect: true, attribute: true })
], NileSelect.prototype, "descriptionSearchEnabled", void 0);
__decorate([
    property({ type: Boolean, reflect: true, attribute: true })
], NileSelect.prototype, "enableDescription", void 0);
__decorate([
    property({
        type: Boolean,
        reflect: true,
        attribute: true,
        converter: {
            fromAttribute: (value) => value === 'true' || value === '',
            toAttribute: (value) => String(value),
        },
    })
], NileSelect.prototype, "allowHtmlLabel", void 0);
__decorate([
    watch('disabled', { waitUntilFirstUpdate: true })
], NileSelect.prototype, "handleDisabledChange", null);
__decorate([
    watch('value', { waitUntilFirstUpdate: true })
], NileSelect.prototype, "handleValueChange", null);
__decorate([
    watch('portal', { waitUntilFirstUpdate: true })
], NileSelect.prototype, "handlePortalAppendChange", null);
__decorate([
    watch('open', { waitUntilFirstUpdate: true })
], NileSelect.prototype, "handleOpenChange", null);
NileSelect = __decorate([
    customElement('nile-select')
], NileSelect);
export { NileSelect };
setDefaultAnimation('select.show', {
    keyframes: [
        { opacity: 0, scale: 0.9 },
        { opacity: 1, scale: 1 },
    ],
    options: { duration: 100, easing: 'ease' },
});
setDefaultAnimation('select.hide', {
    keyframes: [
        { opacity: 1, scale: 1 },
        { opacity: 0, scale: 0.9 },
    ],
    options: { duration: 100, easing: 'ease' },
});
export default NileSelect;
//# sourceMappingURL=nile-select.js.map