import { __decorate } from 'tslib';
import { html } from 'lit';
import { property, state, queryAsync } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { size } from '@floating-ui/dom';
import css_248z from '../components/Dropdown/dropdown-menu.js';
import css_248z$2 from '../styles/feedback.js';
import css_248z$1 from '../styles/form-hint.js';
import css_248z$3 from '../styles/form-text-control.js';
import { defaultValue } from '../utils/defaultvalue.js';
import genId from '../utils/generateId.js';
import { SgdsFormValidatorMixin } from '../utils/validatorMixin.js';
import { DropdownListElement } from './dropdown-list-element.js';
import css_248z$4 from './select.js';

class SelectElement extends SgdsFormValidatorMixin(DropdownListElement) {
    constructor() {
        super();
        /** The input's label  */
        this.label = "";
        /** The input's hint text below the label */
        this.hintText = "";
        /** Autofocus the input */
        this.autofocus = false;
        /** Disables the input. */
        this.disabled = false;
        /** Makes the input a required field. */
        this.required = false;
        /** Sets the loading state of the component */
        this.loading = false;
        /**
         * IMPORTANT:
         * We still expose `.value` externally, but this is now the underlying ID or data
         * (e.g. 1, 2, 'abc', ...), not the label that appears in the input box.
         */
        this.value = "";
        this.displayValue = "";
        /** @internal Gets or sets the default value used to reset this element. */
        this.defaultValue = "";
        /** Allows invalidFeedback, invalid and valid styles to be visible with the input */
        this.hasFeedback = false;
        /** Feedback text for error state when validated */
        this.invalidFeedback = "";
        /** Marks the component as invalid. Replace the pseudo :invalid selector. */
        this.invalid = false;
        /** The list of items to display in the dropdown.
         * `interface SgdsComboBoxItemData {
         * label: string;
         * value: string;
         * }`
         * @deprecated
         * Deprecated in favour of slots
         */
        this.menuList = [];
        /** Track selected items (even for single-select, but it will have at most one). */
        this.selectedItems = [];
        /** @internal Managed filtered menu on the fly with input change*/
        this.filteredList = [];
        this._isTouched = false;
        this._controlId = genId("input");
        this._labelId = genId("label");
        this.floatingOpts = {
            middleware: [
                size({
                    apply({ rects, elements }) {
                        elements.floating.style.width = `${rects.reference.width}px`;
                    }
                })
            ]
        };
    }
    connectedCallback() {
        super.connectedCallback();
        this.addEventListener("blur", async (e) => {
            var _a;
            const childName = this.constructor.childName;
            /** If user clicks the menu, we want to keep the input valid */
            const isSelf = ((_a = e.relatedTarget) === null || _a === void 0 ? void 0 : _a.tagName.toLowerCase()) === childName;
            this.invalid = isSelf ? false : !this._mixinReportValidity();
        });
    }
    /**
     * Checks for validity. Under the hood, HTMLFormElement's reportValidity method calls this method to check for component's validity state
     * Note that the native error popup is prevented for SGDS form components by default. Instead the validation message shows up in the feedback container of SgdsInput
     */
    reportValidity() {
        return this._mixinReportValidity();
    }
    /**
     * Checks for validity without any native error popup message
     */
    checkValidity() {
        return this._mixinCheckValidity();
    }
    /**
     * Returns the ValidityState object
     */
    get validity() {
        return this._mixinGetValidity();
    }
    /**
     * Returns the validation message based on the ValidityState
     */
    get validationMessage() {
        return this._mixinGetValidationMessage();
    }
    _renderFeedback() {
        return this.invalid && this.hasFeedback
            ? html ` <div class="invalid-feedback-container">
          <slot name="invalidIcon">
            <sgds-icon name="exclamation-circle-fill" size="md"></sgds-icon>
          </slot>
          <div id="${this._controlId}-invalid" class="invalid-feedback">
            ${this.invalidFeedback ? this.invalidFeedback : this.validationMessage}
          </div>
        </div>`
            : html `${this._renderHintText()}`;
    }
    _renderHintText() {
        const hintTextTemplate = html ` <div id="${this._controlId}Help" class="form-text">${this.hintText}</div> `;
        return this.hintText && hintTextTemplate;
    }
    _renderLabel() {
        const labelTemplate = html `
      <label
        for=${this._controlId}
        id=${this._labelId}
        class=${classMap({
            "form-label": true,
            required: this.required
        })}
        >${this.label}</label
      >
    `;
        return this.label && labelTemplate;
    }
    _handleClick() {
        if (this.readonly) {
            return null;
        }
        if (!this.menuIsOpen) {
            this.showMenu();
        }
        else {
            this.hideMenu();
        }
    }
    async _getMenuListFromOptions(assignedElements) {
        const readyOptions = assignedElements.map(async (e) => {
            await e.updateComplete;
            return e;
        });
        const options = await Promise.all(readyOptions);
        return options === null || options === void 0 ? void 0 : options.map((el) => {
            var _a;
            return ({
                label: el.innerText,
                value: el.getAttribute("value"),
                disabled: (_a = el.disabled) !== null && _a !== void 0 ? _a : undefined
            });
        });
    }
    _renderEmptyMenu() {
        return html ` <div class="empty-menu">No options</div> `;
    }
    _renderLoadingMenu() {
        return html `<div class="loading-menu"><sgds-spinner size="xs" tone="brand"></sgds-spinner>Loading...</div>`;
    }
}
SelectElement.styles = [
    ...DropdownListElement.styles,
    css_248z,
    css_248z$1,
    css_248z$2,
    css_248z$3,
    css_248z$4
];
__decorate([
    property({ reflect: true })
], SelectElement.prototype, "label", void 0);
__decorate([
    property({ reflect: true })
], SelectElement.prototype, "hintText", void 0);
__decorate([
    property({ reflect: true })
], SelectElement.prototype, "name", void 0);
__decorate([
    property({ type: String, reflect: true })
], SelectElement.prototype, "placeholder", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], SelectElement.prototype, "autofocus", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], SelectElement.prototype, "disabled", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], SelectElement.prototype, "required", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], SelectElement.prototype, "loading", void 0);
__decorate([
    property({ type: String, reflect: true })
], SelectElement.prototype, "value", void 0);
__decorate([
    state()
], SelectElement.prototype, "displayValue", void 0);
__decorate([
    defaultValue()
], SelectElement.prototype, "defaultValue", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], SelectElement.prototype, "hasFeedback", void 0);
__decorate([
    property({ type: String, reflect: true })
], SelectElement.prototype, "invalidFeedback", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], SelectElement.prototype, "invalid", void 0);
__decorate([
    property({ type: Array })
], SelectElement.prototype, "menuList", void 0);
__decorate([
    state()
], SelectElement.prototype, "selectedItems", void 0);
__decorate([
    state()
], SelectElement.prototype, "filteredList", void 0);
__decorate([
    queryAsync("input.form-control")
], SelectElement.prototype, "_input", void 0);

export { SelectElement };
//# sourceMappingURL=select-element.js.map
