'use strict';

var index = require('./index-TwNDE7ev.js');
var tslib_es6 = require('./tslib.es6-DrfCPgT9.js');
var attributes = require('./attributes-Cp0kpySW.js');
var bem = require('./bem-p0PWVN8n.js');
var config_decorator = require('./config.decorator-D_YTqpYj.js');
var array = require('./array-Db63Hhl1.js');
var formInput = require('./form-input-DBZuEpuy.js');
var focusVisible = require('./focus-visible-DFZa8IIA.js');
var option = require('./option-kGk4eTdA.js');
var floatingUi = require('./floating-ui-T_yqQ0TC.js');
var index$1 = require('./index-BZ67Dcnb.js');
var aria = require('./aria-BzkqcV7W.js');
var form = require('./form-BSlIiqcR.js');
var keyboard_helpers = require('./keyboard.helpers-BkZpVT-9.js');
var elementStates_decorator = require('./element-states.decorator-0udYH_TL.js');
var utils = require('./utils-Bl0u6rg1.js');
require('./index-BobQkZjn.js');
require('./_commonjsHelpers-BJu3ubxk.js');
require('./listener-h1eTpBYL.js');

class DropdownAutoFillUtil {
    constructor() {
        this.handleAutoFill = async (ev) => {
            formInput.stopEventBubbling(ev);
            if (this.isAutoFillAllowed()) {
                this.component.isAutoFilled = true;
                const autoFillValue = this.component.nativeEl.value;
                const newValue = await this.parseAutoFillValueWithOptions(autoFillValue);
                if (newValue === undefined) {
                    this.component.isAutoFilled = false;
                    return;
                }
                if (!array.areArraysEqual(newValue, this.component.rawValue)) {
                    this.component.valueUtil.updateRawValueBySelection(newValue, true);
                }
            }
        };
    }
    connectedCallback(component) {
        this.component = component;
    }
    isAutoFillAllowed() {
        return !this.component.multiple;
    }
    async parseAutoFillValueWithOptions(autoFillValue) {
        const options = await this.component.listEl.getOptions();
        const value = undefined;
        for (let index = 0; index < options.length; index++) {
            const option = options[index];
            if (option.value === autoFillValue || option.label === autoFillValue) {
                return [option.value];
            }
        }
        return value;
    }
}

const i18nBalDropdown = {
    de: {
        clearable: 'Löschen',
        open: 'Öffnen',
        close: 'Schließen',
    },
    en: {
        clearable: 'clear',
        open: 'Open',
        close: 'Close',
    },
    fr: {
        clearable: 'Effacer',
        open: 'Ouvrir',
        close: 'Fermer',
    },
    it: {
        clearable: 'Cancellare',
        open: 'Apri',
        close: 'Chiudi',
    },
    nl: {
        clearable: 'Wissen',
        open: 'Open',
        close: 'Sluiten',
    },
    es: {
        clearable: 'Limpiar',
        open: 'Abrir',
        close: 'Cerrar',
    },
    pl: {
        clearable: 'Wyczyść',
        open: 'Otwórz',
        close: 'Zamknij',
    },
    pt: {
        clearable: 'Limpar',
        open: 'Abrir',
        close: 'Fechar',
    },
    sv: {
        clearable: 'Rensa',
        open: 'Öppna',
        close: 'Stäng',
    },
    fi: {
        clearable: 'Tyhjennä',
        open: 'Avaa',
        close: 'Sulje',
    },
};

class DropdownEventsUtil {
    constructor() {
        this.handlePointerDown = () => {
            this.component.isKeyboardMode = false;
        };
        this.handleKeydown = (ev) => {
            this.component.isKeyboardMode = focusVisible.FOCUS_KEYS.includes(ev.key);
        };
    }
    connectedCallback(component) {
        this.component = component;
    }
    handleFocus(ev) {
        this.component.hasFocus = true;
        this.component.balFocus.emit(ev);
    }
    handleBlur(ev) {
        if (!this.component.isExpanded) {
            this.component.hasFocus = false;
            index.rIC(() => this.component.balBlur.emit(ev));
        }
    }
    handleClick(ev) {
        if (!this.component.valueUtil.isDisabled()) {
            if (this.component.chips) {
                const targetEl = ev.target;
                const closeEl = targetEl.closest('bal-close');
                if (closeEl) {
                    return;
                }
            }
            if (this.component.clearable) {
                const targetEl = ev.target;
                const clearEl = targetEl.closest('.bal-dropdown__clear');
                if (clearEl) {
                    this.component.valueUtil.updateRawValueBySelection([]);
                    return;
                }
            }
            this.component.popupUtil.toggleList();
        }
    }
    handleOutsideClick(ev) {
        var _a;
        if (this.component.isExpanded) {
            if (!this.component.el.contains(ev.target)) {
                this.component.isExpanded = false;
                (_a = this.component.listEl) === null || _a === void 0 ? void 0 : _a.resetFocus();
                this.component.hasFocus = false;
                index.rIC(() => this.component.balBlur.emit(ev));
            }
        }
    }
}

class DropdownFocusUtil {
    connectedCallback(component) {
        this.component = component;
    }
    focusOptionByLabel(key, options = {}) {
        this.component.labelToFocus = (this.component.labelToFocus + key).trim();
        if (this.component.labelToFocus.length > 0) {
            clearTimeout(this.keyHitTimeout);
            this.keyHitTimeout = setTimeout(() => {
                var _a;
                (_a = this.component.listEl) === null || _a === void 0 ? void 0 : _a.focusByLabel(this.component.labelToFocus, options);
            }, 100);
            clearTimeout(this.timeout);
            this.timeout = setTimeout(async () => {
                this.component.labelToFocus = '';
            }, 1000);
        }
    }
}

class DropdownFormSubmitUtil {
    connectedCallback(component) {
        this.component = component;
        this.component.initialValue = this.component.value;
    }
    componentDidRender() {
        if (this.component.selectEl) {
            const options = this.component.selectEl.querySelectorAll('option');
            options.forEach(option => {
                if (this.component.rawValue.includes(option.value)) {
                    option.selected = true;
                }
            });
        }
    }
    // @Listen('reset', { capture: true, target: 'document' })
    handle(ev) {
        const formElement = ev.target;
        if (formElement === null || formElement === void 0 ? void 0 : formElement.contains(this.component.el)) {
            if (this.resetHandlerTimer) {
                clearTimeout(this.resetHandlerTimer);
            }
            this.resetHandlerTimer = setTimeout(() => {
                const newRawValue = this.component.valueUtil.parseValueString(this.component.initialValue);
                this.component.valueUtil.updateRawValueBySelection(newRawValue);
            }, 0);
        }
    }
}
const DropdownNativeSelect = ({ name, httpFormSubmit, multiple, required, disabled, rawValue, refSelectEl, }) => {
    const block = bem.BEM.block('dropdown');
    return httpFormSubmit ? (index.h("select", { class: Object.assign({}, block.element('root').element('select').class()), "aria-hidden": "true", name: name, multiple: multiple, required: required, disabled: disabled, tabindex: -1, ref: refSelectEl }, rawValue.map((value) => (index.h("option", { key: value, value: value, selected: true }, value))))) : ('');
};

const DropdownIcon = ({ size, theme, icon, language, loading, clearable, invalid, filled, expanded, disabled, }) => {
    const block = bem.BEM.block('dropdown');
    if (loading) {
        return (index.h("bal-spinner", { class: Object.assign({}, block.element('rear').class()), small: true, variation: "circle", color: "white" }));
    }
    else if (clearable && filled && !disabled) {
        return (index.h("button", { title: i18nBalDropdown[language].clearable, type: 'button', tabIndex: -1, class: Object.assign(Object.assign(Object.assign(Object.assign({}, block.element('rear').class()), block.element('clear').class()), block.element('clear').modifier('invalid').class(invalid)), block
                .element('clear')
                .modifier('theme-purple')
                .class(theme === 'purple')) },
            index.h("bal-icon", { class: Object.assign({}, block.element('rear').class()), name: theme === 'purple' ? 'close' : 'close-circle', size: size, color: theme === 'purple' ? 'primary' : 'grey' })));
    }
    else {
        return (index.h("bal-icon", { class: Object.assign({}, block.element('rear').class()), name: icon, size: size, turn: expanded, color: disabled ? 'grey' : invalid ? 'danger' : 'primary' }));
    }
};

const DropdownOptionList = ({ inputId, isExpanded, rawOptions, isDisabled, hasPropOptions, required, filter, multiple, contentHeight, refPanelEl, refListEl, }) => {
    const block = bem.BEM.block('dropdown');
    return (index.h("div", { id: `${inputId}-menu`, class: Object.assign(Object.assign({}, block.element('list').class()), block.element('list').modifier('expanded').class(isExpanded)), ref: refPanelEl },
        index.h("bal-option-list", { multiple: multiple, disabled: isDisabled, filter: filter, required: required, contentHeight: contentHeight, ref: refListEl },
            index.h("slot", null),
            hasPropOptions
                ? rawOptions.map(option => (index.h("bal-option", { key: option.value, value: option.value, label: option.label, disabled: option.disabled, multiline: option.multiline, invalid: option.invalid, hidden: option.hidden, selected: option.selected, focused: option.focused }, option.label)))
                : '')));
};

class DropdownPopupUtil {
    constructor() {
        this.updatePanelPosition = (lib, referenceEl, floatingEl) => () => {
            lib
                .computePosition(referenceEl, floatingEl, {
                placement: 'bottom-start',
                middleware: [lib.flip(), lib.shift()],
            })
                .then(({ x, y }) => {
                Object.assign(floatingEl.style, {
                    left: `${x}px`,
                    top: `${y}px`,
                });
            });
        };
    }
    connectedCallback(component) {
        this.component = component;
    }
    toggleList() {
        if (!this.component.valueUtil.isDisabled()) {
            if (this.component.isExpanded) {
                this.collapseList();
            }
            else {
                this.expandList();
            }
        }
    }
    async expandList() {
        var _a;
        if (this.component.panelEl) {
            const lib = await floatingUi.balFloatingUi.load();
            this.component.panelCleanup = lib.autoUpdate(this.component.el, this.component.panelEl, this.updatePanelPosition(lib, this.component.el, this.component.panelEl));
        }
        this.component.isExpanded = true;
        await ((_a = this.component.listEl) === null || _a === void 0 ? void 0 : _a.focusSelected());
    }
    collapseList() {
        var _a;
        this.component.isExpanded = false;
        (_a = this.component.listEl) === null || _a === void 0 ? void 0 : _a.resetFocus();
        if (this.component.panelCleanup) {
            this.component.panelCleanup();
        }
    }
}

class DropdownValueUtil {
    connectedCallback(component) {
        this.component = component;
    }
    componentDidLoad() {
        setTimeout(() => this.valueChanged(this.component.value, undefined), 0);
    }
    isDisabled() {
        return this.component.disabled || this.component.readonly;
    }
    isFilled() {
        return this.component.rawValue && this.component.rawValue.length > 0;
    }
    valueChanged(newValue, oldValue) {
        const newValueType = typeof newValue;
        const oldValueType = typeof oldValue;
        if (newValueType !== oldValueType) {
            this.updateRawValueByValueProp(newValue);
        }
        if (newValueType === 'string' && newValue !== oldValue) {
            this.updateRawValueByValueProp(newValue);
        }
        if (Array.isArray(newValue) && Array.isArray(oldValue) && !array.areArraysEqual(newValue, oldValue)) {
            this.updateRawValueByValueProp(newValue);
        }
    }
    updateRawValueBySelection(newRawValue = [], isAutoFilled = false) {
        this.component.isAutoFilled = isAutoFilled;
        this.updateRawValue(newRawValue);
        if (this.component.multiple) {
            this.component.balChange.emit(this.component.rawValue);
        }
        else {
            this.component.balChange.emit(this.component.rawValue[0]);
        }
    }
    parseValueString(newValue = []) {
        let newRawValue = [];
        if (!index$1.isNil(newValue) && newValue !== '') {
            if (Array.isArray(newValue)) {
                newRawValue = [...newValue.filter(v => !index$1.isNil(v))];
            }
            else {
                if (newValue.split('').includes(',')) {
                    newRawValue = [
                        ...newValue
                            .split(',')
                            .filter(v => v)
                            .map(v => v.trim()),
                    ];
                }
                else {
                    newRawValue = [newValue];
                }
            }
        }
        return newRawValue;
    }
    updateRawValueByValueProp(newValue = []) {
        const newRawValue = this.parseValueString(newValue);
        this.updateRawValue(newRawValue);
    }
    async updateRawValue(newRawValue = []) {
        this.component.rawValue = newRawValue;
        if (this.component.listEl) {
            await this.component.listEl.updateSelected(this.component.rawValue);
        }
        await this.updateInputContent();
    }
    removeOption(option) {
        const newRawValue = this.component.rawValue.filter(value => value !== option.value);
        this.updateRawValueBySelection(newRawValue);
    }
    async updateInputContent() {
        await index.waitAfterFramePaint();
        if (this.component.listEl) {
            this.component.choices = await this.component.listEl.getSelectedOptions(this.component.rawValue);
            this.component.inputLabel = this.component.choices
                .map(option => option.label.trim())
                .sort()
                .join(',');
        }
    }
}
const DropdownValue = ({ inlineLabel, filled, chips, placeholder, choices, invalid, disabled, readonly, onRemoveChip, }) => {
    const block = bem.BEM.block('dropdown');
    if (filled) {
        if (chips) {
            return (index.h("div", { class: Object.assign({}, block.element('root').element('content').element('chips').class()) }, choices.map(option => (index.h("bal-tag", { key: option.value, "data-test": "bal-dropdown-chip", size: "small", invalid: invalid, disabled: disabled || readonly, closable: !(disabled || readonly), onBalCloseClick: () => onRemoveChip(option) }, option.label)))));
        }
        else {
            return (inlineLabel && `${inlineLabel}: `) + choices.map(option => option.label).join(', ');
        }
    }
    else {
        return placeholder;
    }
};

const DropdownInput = ({ inputId, httpFormSubmit, ariaForm, rawValue, autocomplete, required, disabled, readonly, placeholder, expanded, invalid, language, inputLabel, inheritedAttributes, refInputEl, onChange, onFocus, onBlur, onKeyDown, }) => {
    const block = bem.BEM.block('dropdown');
    const Input = () => (index.h("input", Object.assign({ id: ariaForm.controlId || `${inputId}-ctrl`, class: Object.assign({}, block.element('root').element('input').class()), type: "text", size: 1, inputmode: "none", tabindex: "0", autoComplete: autocomplete, value: rawValue.join(','), required: required, disabled: disabled, readonly: readonly, placeholder: placeholder, title: expanded ? i18nBalDropdown[language].close : i18nBalDropdown[language].open, "aria-label": expanded ? i18nBalDropdown[language].close : i18nBalDropdown[language].open, "aria-owns": `${inputId}-menu`, "aria-invalid": aria.ariaBooleanToString(invalid), "aria-disabled": aria.ariaBooleanToString(disabled || readonly), "aria-labelledby": ariaForm.labelId, "aria-describedby": ariaForm.messageId, "aria-haspopup": 'listbox', "data-native": true, "data-label": inputLabel, "data-value": rawValue.join(','), ref: el => refInputEl(el), onChange: ev => onChange(ev), onFocus: ev => onFocus(ev), onBlur: ev => onBlur(ev), onKeyDown: ev => onKeyDown(ev) }, inheritedAttributes)));
    if (httpFormSubmit) {
        return index.h(Input, null);
    }
    return (index.h("form", { novalidate: true },
        index.h(Input, null)));
};

const balDropdownCss = ":root{--bal-dropdown-control-background:var(--bal-color-white);--bal-dropdown-control-background-hover:var(--bal-form-field-control-background-hover);--bal-dropdown-control-background-invalid:var(--bal-form-field-control-danger-background);--bal-dropdown-control-background-disabled:var(--bal-form-field-control-disabled-background);--bal-dropdown-control-input-background:var(--bal-color-grey-1);--bal-dropdown-control-native-input-background:transparent;--bal-dropdown-control-native-input-background-hover:transparent;--bal-dropdown-control-input-inverted-footer-background:transparent;--bal-dropdown-control-input-inverted-footer-background-hover:transparent;--bal-dropdown-control-input-multiple-background:transparent;--bal-dropdown-control-input-multiple-background-read-only-selection:transparent;--bal-dropdown-control-input-option-background:transparent;--bal-dropdown-control-input-option-background-selected:var(--bal-color-primary-1);--bal-dropdown-control-input-option-background-focused:var(--bal-color-grey-3);--bal-dropdown-control-input-option-background-hover:var(--bal-color-grey-3);--bal-dropdown-control-border-radius:var(--bal-form-field-control-radius);--bal-dropdown-popover-border-color:var(--bal-color-grey-2);--bal-dropdown-control-border-color:var(--bal-form-field-control-border-color);--bal-dropdown-control-border-color-focused:var(--bal-color-primary);--bal-dropdown-control-border-color-hover:var(--bal-form-field-control-border-color-hover);--bal-dropdown-control-border-color-invalid:var(--bal-form-field-control-danger-border-color);--bal-dropdown-control-border-color-disabled:var(--bal-form-field-control-disabled-border-color);--bal-dropdown-control-border-color-focus-within:var(--bal-color-primary);--bal-dropdown-option-border-top-color:var(--bal-color-grey-2);--bal-dropdown-popover-empty-text-color:var(--bal-form-field-control-color);--bal-dropdown-control-text-color:var(--bal-form-field-control-color);--bal-dropdown-control-text-color-focused:var(--bal-color-primary);--bal-dropdown-input-text-color-disabled:var(--bal-form-field-label-disabled-color);--bal-dropdown-control-inverted-footer-native-input-text-color:var(--bal-color-text-white);--bal-dropdown-option-content-label-text-color:var(--bal-form-field-control-color)}.bal-dropdown{display:block;position:relative;-ms-flex:1;flex:1;width:100%}.bal-dropdown__root{border-width:.125rem;border-style:solid;border-color:var(--bal-dropdown-control-border-color);border-radius:var(--bal-dropdown-control-border-radius);background:var(--bal-dropdown-control-background);font-weight:var(--bal-font-weight-regular);font-size:var(--bal-text-size-normal);font-family:var(--bal-font-family-text);color:var(--bal-dropdown-control-text-color);outline:none;-webkit-box-shadow:var(--bal-shadow-none);box-shadow:var(--bal-shadow-none);padding-right:1rem;height:auto;min-height:3rem;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:-ms-flexbox;display:flex;width:100%;text-align:left;gap:1rem;padding-left:calc(.75em - var(--bal-border-width-normal));padding-right:calc(.75em - var(--bal-border-width-normal));-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center}.bal-dropdown__root--autofill{background:#faffbd !important;background:light-dark(rgb(232, 240, 254), rgba(70, 90, 126, 0.4)) !important}.bal-dropdown__root>span{-ms-flex:1;flex:1;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.bal-dropdown__root--focused{border-color:var(--bal-dropdown-control-border-color-focused)}.bal-dropdown__root--invalid{border-color:var(--bal-dropdown-control-border-color-invalid);background:var(--bal-dropdown-control-background-invalid)}.bal-dropdown__root--disabled{border-color:var(--bal-dropdown-control-border-color-disabled);background:var(--bal-dropdown-control-background-disabled)}.bal-dropdown__root__content--placeholder{color:var(--bal-form-field-control-placeholder-color)}.bal-dropdown__root__content--disabled{color:var(--bal-dropdown-input-text-color-disabled)}@media (hover: hover)and (pointer: fine){.bal-dropdown__root:not(.bal-dropdown__root--disabled):not(.bal-dropdown__root--invalid):not(.bal-dropdown__root--theme-purple):not(.bal-dropdown__root--theme-purple-expanded):hover{background:var(--bal-dropdown-control-background-hover)}}.bal-dropdown__root__content__chips{--bal-tag-size-small-font-size:var(--bal-text-size-normal);display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;gap:var(--bal-space-xx-small);padding-top:var(--bal-space-x-small);padding-bottom:var(--bal-space-x-small)}.bal-dropdown__root__content__chips>bal-tag{z-index:1}.bal-dropdown__root__input{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;background:rgba(0,0,0,0);position:absolute;right:var(--bal-border-width-normal);left:var(--bal-border-width-normal);top:var(--bal-border-width-normal);bottom:var(--bal-border-width-normal);opacity:0;padding-left:calc(.75em - var(--bal-border-width-normal));padding-right:calc(.75em - var(--bal-border-width-normal));cursor:pointer}.bal-dropdown__root__input:disabled{cursor:default}.bal-dropdown__root__input:-webkit-autofill{opacity:1}.bal-dropdown__root__input:autofill{opacity:1}.bal-dropdown__root__input:-internal-autofill-selected{opacity:0}.bal-dropdown__root__select{position:absolute !important;left:0;top:0;margin:0;padding:0;opacity:0;outline:0;border:none;width:1px;height:1px;clip:rect(1px, 1px, 1px, 1px);overflow:hidden}.bal-dropdown__root--autofill .bal-dropdown__root__input{opacity:0}.bal-dropdown__list{display:none;visibility:hidden;opacity:0;width:100vw;position:absolute;top:0;left:0;will-change:left,top,opacity;background:var(--bal-color-white);border-radius:var(--bal-radius-normal);-webkit-box-shadow:var(--bal-shadow-normal);box-shadow:var(--bal-shadow-normal);z-index:var(--bal-z-index-popup)}@media screen and (min-width: 769px),print{.bal-dropdown__list{max-width:100vw;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;min-width:100%}}.bal-dropdown__list--expanded{display:block;visibility:visible;opacity:1}.bal-dropdown__native{bottom:0;left:0;position:absolute;opacity:0;pointer-events:none;width:100%}.bal-dropdown__clear{background:rgba(0,0,0,0);border:none;padding:0;margin:0;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center;cursor:pointer}.bal-dropdown__clear--theme-purple{height:2rem;width:2rem;border-top-right-radius:2px;border-bottom-right-radius:2px;margin-right:-10px}.bal-dropdown__clear--theme-purple::before{content:\"\";position:absolute;right:32px;background:var(--bal-color-white);width:2px;height:100%}.bal-dropdown__rear{z-index:1}.bal-dropdown__root--size-small{min-height:2rem}.bal-dropdown__root--theme-purple:not(.bal-dropdown__root--disabled) .bal-dropdown__root__content--placeholder{color:var(--bal-color-text-primary)}.bal-dropdown__root--theme-purple:not(.bal-dropdown__root--theme-purple-expanded){border:none;background:var(--bal-color-background-grey-light)}@media (hover: hover)and (pointer: fine){.bal-dropdown__root--theme-purple:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):hover{background:var(--bal-color-purple-1)}.bal-dropdown__root--theme-purple:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):hover .bal-dropdown__root__input,.bal-dropdown__root--theme-purple:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):hover .bal-dropdown__root__content{color:var(--bal-color-text-primary)}.bal-dropdown__root--theme-purple:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):hover .bal-icon__inner svg,.bal-dropdown__root--theme-purple:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):hover .bal-icon__inner g,.bal-dropdown__root--theme-purple:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):hover .bal-icon__inner path,.bal-dropdown__root--theme-purple:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):hover .bal-icon__inner circle{fill:var(--bal-color-text-primary)}.bal-dropdown__root--theme-purple:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):active{background:var(--bal-color-purple-2)}.bal-dropdown__root--theme-purple:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):active .bal-dropdown__root__input,.bal-dropdown__root--theme-purple:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):active .bal-dropdown__root__content{color:var(--bal-color-text-primary)}.bal-dropdown__root--theme-purple:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):active .bal-icon__inner svg,.bal-dropdown__root--theme-purple:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):active .bal-icon__inner g,.bal-dropdown__root--theme-purple:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):active .bal-icon__inner path,.bal-dropdown__root--theme-purple:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):active .bal-icon__inner circle{fill:var(--bal-color-text-primary)}}.bal-dropdown__root--theme-purple-filled:not(.bal-dropdown__root--theme-purple-expanded){border:none;background:var(--bal-color-purple-2)}@media (hover: hover)and (pointer: fine){.bal-dropdown__root--theme-purple-filled:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):hover{background:var(--bal-color-purple-3)}.bal-dropdown__root--theme-purple-filled:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):hover .bal-dropdown__root__input,.bal-dropdown__root--theme-purple-filled:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):hover .bal-dropdown__root__content{color:var(--bal-color-text-primary-pressed)}.bal-dropdown__root--theme-purple-filled:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):hover .bal-icon__inner svg,.bal-dropdown__root--theme-purple-filled:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):hover .bal-icon__inner g,.bal-dropdown__root--theme-purple-filled:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):hover .bal-icon__inner path,.bal-dropdown__root--theme-purple-filled:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):hover .bal-icon__inner circle{fill:var(--bal-color-text-primary-pressed)}.bal-dropdown__root--theme-purple-filled:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):active{background:var(--bal-color-purple-3)}.bal-dropdown__root--theme-purple-filled:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):active .bal-dropdown__root__input,.bal-dropdown__root--theme-purple-filled:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):active .bal-dropdown__root__content{color:var(--bal-color-text-primary)}.bal-dropdown__root--theme-purple-filled:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):active .bal-icon__inner svg,.bal-dropdown__root--theme-purple-filled:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):active .bal-icon__inner g,.bal-dropdown__root--theme-purple-filled:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):active .bal-icon__inner path,.bal-dropdown__root--theme-purple-filled:not(.bal-dropdown__root--theme-purple-expanded):not(.bal-dropdown__root--disabled):active .bal-icon__inner circle{fill:var(--bal-color-text-primary)}}.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled),.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled):hover,.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled):active{border:none;background:var(--bal-color-purple-2)}.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled) .bal-dropdown__root__input,.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled) .bal-dropdown__root__content,.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled):hover .bal-dropdown__root__input,.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled):hover .bal-dropdown__root__content,.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled):active .bal-dropdown__root__input,.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled):active .bal-dropdown__root__content{color:var(--bal-color-text-primary)}.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled) .bal-icon__inner svg,.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled) .bal-icon__inner g,.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled) .bal-icon__inner path,.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled) .bal-icon__inner circle,.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled):hover .bal-icon__inner svg,.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled):hover .bal-icon__inner g,.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled):hover .bal-icon__inner path,.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled):hover .bal-icon__inner circle,.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled):active .bal-icon__inner svg,.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled):active .bal-icon__inner g,.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled):active .bal-icon__inner path,.bal-dropdown__root--theme-purple-expanded:not(.bal-dropdown__root--disabled):active .bal-icon__inner circle{fill:var(--bal-color-text-primary)}.bal-dropdown__root--focused.bal-dropdown__root--theme-purple:before{content:\"\";border-width:var(--bal-border-width-normal);border-style:solid;border-color:var(--bal-focus-shadow-end-color);position:absolute;background:rgba(0,0,0,0);border-radius:var(--bal-radius-normal);top:-0.25rem;bottom:-0.25rem;left:-0.25rem;right:-0.25rem}.bal-dropdown__root__content--size-small{font-size:var(--bal-text-size-small);font-weight:var(--bal-font-weight-bold)}.bal-dropdown__clear--theme-purple{height:2rem;width:2rem;border-top-right-radius:2px;border-bottom-right-radius:2px;margin-right:-10px}.bal-dropdown__clear--theme-purple::before{content:\"\";position:absolute;right:32px;background:var(--bal-color-white);width:2px;height:100%}";

const Dropdown = class {
    constructor(hostRef) {
        index.registerInstance(this, hostRef);
        this.balChange = index.createEvent(this, "balChange");
        this.balFocus = index.createEvent(this, "balFocus");
        this.balBlur = index.createEvent(this, "balBlur");
        this.inputId = `bal-dropdown-${balDropdownIds++}`;
        this.inheritedAttributes = {};
        this.initialValue = [];
        this.nativeOptions = [];
        this.rawOptions = [];
        this.choices = [];
        this.rawValue = [];
        this.hasFocus = false;
        this.isExpanded = false;
        this.isAutoFilled = false;
        this.isKeyboardMode = false;
        this.inputLabel = '';
        this.ariaForm = form.defaultBalAriaForm;
        this.language = index.defaultConfig.language;
        this.region = index.defaultConfig.region;
        this.httpFormSubmit = index.defaultConfig.httpFormSubmit;
        this.labelToFocus = '';
        this.valueUtil = new DropdownValueUtil();
        this.eventsUtil = new DropdownEventsUtil();
        this.popupUtil = new DropdownPopupUtil();
        this.optionUtil = new option.DropdownOptionUtil();
        this.formSubmitUtil = new DropdownFormSubmitUtil();
        this.focusUtil = new DropdownFocusUtil();
        this.autoFillUtil = new DropdownAutoFillUtil();
        /**
         * PUBLIC PROPERTY API
         * ------------------------------------------------------
         */
        /**
         * Indicates whether the value of the control can be automatically completed by the browser.
         */
        this.autocomplete = 'off';
        /**
         * The name of the control, which is submitted with the form data.
         */
        this.name = this.inputId;
        /**
         * Defines the placeholder of the component. Only shown when the value is empty
         */
        this.placeholder = '';
        /**
         * Defines a inline label to be shown before the value
         */
        this.inlineLabel = '';
        /**
         * If `true` there will be on trigger icon visible
         */
        this.icon = 'caret-down';
        /**
         * Defines the size of the control.
         */
        this.size = '';
        /**
         * Defines the color style of the control
         */
        this.theme = '';
        /**
         * If `true`, the user cannot interact with the option.
         */
        this.disabled = false;
        /**
         * If `true` the element can not mutated, meaning the user can not edit the control.
         */
        this.readonly = false;
        /**
         * If `true`, the user can select multiple options.
         */
        this.multiple = false;
        /**
         * If `true`, the selected options are shown as chips
         */
        this.chips = false;
        /**
         * If `true`, a cross at the end is visible to clear the selection
         */
        this.clearable = false;
        /**
         * If `true`, the component will be shown as invalid
         */
        this.invalid = false;
        /**
         * If `true`, the user must fill in a value before submitting a form.
         */
        this.required = false;
        /**
         * Defines if the select is in a loading state.
         */
        this.loading = false;
        /**
         * Defines the filter logic of the list
         */
        this.filter = 'includes';
        /**
         * Defines the max height of the list element
         */
        this.contentHeight = 262;
        /**
         * @internal
         * Set this to `true` when the component is placed on a dark background.
         */
        this.inverted = false;
        /**
         * Steps can be passed as a property or through HTML markup.
         */
        this.options = [];
        /**
         * The value of the selected options.
         */
        this.value = [];
        /**
         * LIFECYCLE
         * ------------------------------------------------------
         */
        this.hasConnected = false;
        this.listenToOptionChange = (ev) => {
            this.optionUtil.listenToOptionChange(ev);
        };
        this.listenOnClickOutside = (ev) => {
            this.eventsUtil.handleOutsideClick(ev);
        };
        this.resetHandler = (ev) => {
            this.formSubmitUtil.handle(ev);
        };
        /**
         * EVENT BINDING
         * ------------------------------------------------------
         */
        this.handleAutoFill = async (ev) => {
            this.log('(handleAutoFill)', ev, this.nativeEl.value);
            this.autoFillUtil.handleAutoFill(ev);
        };
        this.handleKeyDown = (ev) => {
            var _a, _b, _c, _d, _e;
            if (ev && ev.key) {
                if (this.isExpanded) {
                    /**
                     * ⬇️ Arrow up key
                     */
                    if (keyboard_helpers.isArrowDownKey(ev)) {
                        formInput.stopEventBubbling(ev);
                        (_a = this.listEl) === null || _a === void 0 ? void 0 : _a.focusNext();
                        /**
                         * ⬆️ Arrow up key
                         */
                    }
                    else if (keyboard_helpers.isArrowUpKey(ev)) {
                        formInput.stopEventBubbling(ev);
                        (_b = this.listEl) === null || _b === void 0 ? void 0 : _b.focusPrevious();
                        /**
                         * Go to top of the list
                         */
                    }
                    else if (ev.key === 'Home' || ev.key === 'PageUp') {
                        formInput.stopEventBubbling(ev);
                        (_c = this.listEl) === null || _c === void 0 ? void 0 : _c.focusFirst();
                        /**
                         * Go to bottom of the list
                         */
                    }
                    else if (ev.key === 'End' || ev.key === 'PageDown') {
                        formInput.stopEventBubbling(ev);
                        (_d = this.listEl) === null || _d === void 0 ? void 0 : _d.focusLast();
                        /**
                         * Select focused option
                         */
                    }
                    else if (keyboard_helpers.isEnterKey(ev)) {
                        formInput.stopEventBubbling(ev);
                        (_e = this.listEl) === null || _e === void 0 ? void 0 : _e.selectByFocus();
                        /**
                         * Close list
                         */
                    }
                    else if (ev.key === 'Tab' || keyboard_helpers.isEscapeKey(ev)) {
                        this.popupUtil.collapseList();
                        /**
                         * Focus on label
                         */
                    }
                    else if (ev.key.length === 1) {
                        this.focusUtil.focusOptionByLabel(ev.key);
                    }
                }
                else {
                    /**
                     * Open list
                     */
                    if (keyboard_helpers.isEnterKey(ev) || keyboard_helpers.isSpaceKey(ev)) {
                        formInput.stopEventBubbling(ev);
                        this.popupUtil.expandList();
                        /**
                         * Focus on label
                         */
                    }
                    else if (ev.key.length === 1) {
                        this.focusUtil.focusOptionByLabel(ev.key, { select: true });
                    }
                }
            }
            else {
                // Close the popup on autofill
                if (this.isExpanded) {
                    this.popupUtil.collapseList();
                }
            }
        };
    }
    createLogger(log) {
        this.log = log;
    }
    async optionChanged() {
        this.optionUtil.optionChanged();
    }
    valueChanged(newValue, oldValue) {
        this.valueUtil.valueChanged(newValue, oldValue);
    }
    connectedCallback() {
        if (!this.hasConnected) {
            this.eventsUtil.connectedCallback(this);
            this.valueUtil.connectedCallback(this);
            this.popupUtil.connectedCallback(this);
            this.optionUtil.connectedCallback(this);
            this.formSubmitUtil.connectedCallback(this);
            this.focusUtil.connectedCallback(this);
            this.autoFillUtil.connectedCallback(this);
        }
        index.addEventListener(this.el, 'balOptionChange', this.listenToOptionChange);
        if (index.balBrowser.hasDocument) {
            index.addEventListener(document, 'keydown', this.eventsUtil.handleKeydown);
            index.addEventListener(document, 'touchstart', this.eventsUtil.handlePointerDown);
            index.addEventListener(document, 'mousedown', this.eventsUtil.handlePointerDown);
            index.addEventListener(document, 'click', this.listenOnClickOutside);
            index.addEventListener(document, 'reset', this.resetHandler, {
                capture: true,
            });
        }
        this.hasConnected = true;
    }
    disconnectedCallback() {
        index.removeEventListener(this.el, 'balOptionChange', this.listenToOptionChange);
        if (index.balBrowser.hasDocument) {
            index.removeEventListener(document, 'keydown', this.eventsUtil.handleKeydown);
            index.removeEventListener(document, 'touchstart', this.eventsUtil.handlePointerDown);
            index.removeEventListener(document, 'mousedown', this.eventsUtil.handlePointerDown);
            index.removeEventListener(document, 'click', this.listenOnClickOutside);
            index.removeEventListener(document, 'reset', this.resetHandler, {
                capture: true,
            });
        }
    }
    async componentWillRender() {
        this.inheritedAttributes = attributes.inheritAttributes(this.el, ['tabindex', 'data-hj-allow']);
        await this.optionUtil.componentWillRender();
    }
    componentDidRender() {
        this.formSubmitUtil.componentDidRender();
    }
    componentDidLoad() {
        this.valueUtil.componentDidLoad();
    }
    /**
     * LISTENERS
     * ------------------------------------------------------
     */
    /**
     * @internal define config for the component
     */
    async configChanged(state) {
        this.language = state.language;
        this.region = state.region;
        this.httpFormSubmit = state.httpFormSubmit;
    }
    /**
     * PUBLIC METHODS
     * ------------------------------------------------------
     */
    /**
     * Sets the focus on the input element
     */
    async setFocus() {
        if (this.nativeEl && !this.valueUtil.isDisabled()) {
            await index.waitAfterIdleCallback();
            this.nativeEl.focus();
        }
    }
    /**
     * Returns the value of the component
     */
    async getValue() {
        return this.rawValue;
    }
    /**
     * Sets the value to `[]`, the input value to ´''´ and the focus index to ´0´.
     */
    async clear() {
        this.valueUtil.updateRawValueBySelection([]);
    }
    /**
     * Opens the popup with option list
     */
    async open() {
        if (!this.valueUtil.isDisabled() && this.panelEl) {
            await this.popupUtil.expandList();
        }
    }
    /**
     * Closes the popup with option list
     */
    async close() {
        if (!this.valueUtil.isDisabled() && this.panelEl) {
            await this.popupUtil.collapseList();
        }
    }
    /**
     * Select option by passed value
     */
    async select(newValue) {
        const parsedNewValue = this.valueUtil.parseValueString(newValue);
        this.valueUtil.updateRawValueBySelection(parsedNewValue);
    }
    /**
     * @internal
     */
    async setAriaForm(ariaForm) {
        this.ariaForm = Object.assign({}, ariaForm);
    }
    /**
     * RENDER
     * ------------------------------------------------------
     */
    render() {
        const block = bem.BEM.block('dropdown');
        const isFilled = this.valueUtil.isFilled();
        const hasSize = this.size !== '';
        const size = `size-${this.size}`;
        const hasTheme = this.theme !== '';
        const theme = `theme-${this.theme}`;
        const focused = this.theme === 'purple' ? this.hasFocus && this.isKeyboardMode : this.hasFocus;
        return (index.h(index.Host, { key: '713d45fe75018e22e55109784c914cbf41161d66', class: Object.assign({}, block.class()), tabindex: "-1", id: `${this.inputId}` }, index.h("div", { key: 'd846ee95ba439528691fc58c483b84ebc54e1b20', class: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, block.element('root').class()), block.element('root').modifier('focused').class(focused)), block.element('root').modifier('invalid').class(this.invalid)), block.element('root').modifier('disabled').class(this.valueUtil.isDisabled())), block.element('root').modifier('autofill').class(this.isAutoFilled)), block.element('root').modifier(size).class(hasSize)), block.element('root').modifier(theme).class(hasTheme)), block
                .element('root')
                .modifier(theme + '-filled')
                .class(isFilled && hasTheme)), block
                .element('root')
                .modifier(theme + '-expanded')
                .class(this.isExpanded && hasTheme)), "data-test": "bal-dropdown-trigger", onClick: ev => this.eventsUtil.handleClick(ev) }, index.h("span", { key: '2b385d34110fffd8272b19083601121a2520381a', class: Object.assign(Object.assign(Object.assign(Object.assign({}, block.element('root').element('content').class()), block.element('root').element('content').modifier('disabled').class(this.valueUtil.isDisabled())), block.element('root').element('content').modifier('placeholder').class(!this.valueUtil.isFilled())), block.element('root').element('content').modifier(size).class(hasSize)) }, index.h(DropdownValue, { key: '65df8cac6931a0a9ac49b01a93e88971e2afedf8', filled: this.valueUtil.isFilled(), inlineLabel: this.inlineLabel, chips: this.chips, placeholder: this.placeholder, choices: this.choices, invalid: this.invalid, disabled: this.disabled, readonly: this.readonly, onRemoveChip: option => this.valueUtil.removeOption(option) })), index.h(DropdownInput, { key: '0a97b36e6b72f4c559403d21a368a1021537bc85', inputId: this.inputId, httpFormSubmit: this.httpFormSubmit, ariaForm: this.ariaForm, rawValue: this.rawValue, autocomplete: this.autocomplete, required: this.required, disabled: this.disabled, readonly: this.readonly, placeholder: this.placeholder, expanded: this.isExpanded, invalid: this.invalid, language: this.language, inputLabel: this.inputLabel, inheritedAttributes: this.inheritedAttributes, refInputEl: el => (this.nativeEl = el), onChange: ev => this.handleAutoFill(ev), onFocus: ev => this.eventsUtil.handleFocus(ev), onBlur: ev => this.eventsUtil.handleBlur(ev), onKeyDown: ev => this.handleKeyDown(ev) }), index.h(DropdownNativeSelect, { key: '7f05f0d7538b6f82e54d184beaa86298e7d683c9', name: this.name, httpFormSubmit: this.httpFormSubmit, multiple: this.multiple, required: this.required, disabled: this.valueUtil.isDisabled(), rawValue: this.rawValue, refSelectEl: el => (this.selectEl = el) }), index.h(DropdownIcon, { key: '9ef218710b2e80ad73b382094074d7249a63c632', icon: this.icon, size: this.size, theme: this.theme, language: this.language, loading: this.loading, clearable: this.clearable, invalid: this.invalid, expanded: this.isExpanded, filled: isFilled, disabled: this.valueUtil.isDisabled() })), index.h(DropdownOptionList, { key: '58cd4f3169991ea56176c3ae69bf808e0c81d663', inputId: this.inputId, block: this.inputId, filter: this.filter, required: this.required, isExpanded: this.isExpanded, isDisabled: this.valueUtil.isDisabled(), hasPropOptions: this.optionUtil.hasPropOptions(), multiple: this.multiple, contentHeight: this.contentHeight, rawOptions: this.rawOptions, refPanelEl: el => (this.panelEl = el), refListEl: el => (this.listEl = el) }, index.h("slot", { key: '6196a395badb4b3f2a4caaee2490d68a7cf9a36c' }))));
    }
    get el() { return index.getElement(this); }
    static get watchers() { return {
        "options": ["optionChanged"],
        "value": ["valueChanged"]
    }; }
};
tslib_es6.__decorate([
    index.Logger('bal-dropdown'),
    tslib_es6.__metadata("design:type", Function),
    tslib_es6.__metadata("design:paramtypes", [Function]),
    tslib_es6.__metadata("design:returntype", void 0)
], Dropdown.prototype, "createLogger", null);
tslib_es6.__decorate([
    config_decorator.ListenToConfig(),
    tslib_es6.__metadata("design:type", Function),
    tslib_es6.__metadata("design:paramtypes", [Object]),
    tslib_es6.__metadata("design:returntype", Promise)
], Dropdown.prototype, "configChanged", null);
let balDropdownIds = 0;
Dropdown.style = balDropdownCss;

const balOptionCss = ":root{--bal-option-padding-x:var(--bal-space-small);--bal-option-min-height:1.5rem;--bal-option-background:var(--bal-color-white);--bal-option-background-hovered:var(--bal-color-grey-3);--bal-option-background-selected:var(--bal-color-primary-1);--bal-option-background-selected-hovered:#dddfeb;--bal-option-background-invalid:var(--bal-color-danger-1);--bal-option-background-invalid-hovered:#fbe0de;--bal-option-border-width:var(--bal-border-width-normal);--bal-option-border-color:var(--bal-color-grey-2);--bal-option-font-family:var(--bal-font-family-text);--bal-option-font-weight:var(--bal-font-weight-regular);--bal-option-line-height:1.125rem;--bal-option-text-hovered:var(--bal-color-text-primary-hovered);--bal-option-text-pressed:var(--bal-color-text-primary-pressed);--bal-option-text-disabled:var(--bal-color-text-grey-light)}.bal-option{font-size:16px;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;display:block;list-style:none;cursor:pointer;border-bottom-width:var(--bal-option-border-width);border-bottom-color:var(--bal-option-border-color);border-bottom-style:solid;background:var(--bal-option-background);padding-left:var(--bal-option-padding-x);padding-right:var(--bal-option-padding-x);min-height:var(--bal-option-min-height)}.bal-option>bal-stack{min-height:var(--bal-option-min-height)}.bal-option:last-child{border-bottom:none}.bal-option::-moz-focus-inner{border:none}.bal-option--hidden{display:none;visibility:hidden}.bal-option__inner{font-family:var(--bal-option-font-family);font-weight:var(--bal-option-font-weight);line-height:var(--bal-option-line-height);word-break:break-word;white-space:normal;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;-ms-flex:1;flex:1}.bal-option__inner--multiline{white-space:normal}.bal-option--focused{background:var(--bal-option-background-hovered)}@media (hover: hover)and (pointer: fine){.bal-option:hover{background:var(--bal-option-background-hovered);color:var(--bal-option-text-hovered)}}.bal-option:active{background:var(--bal-option-background-hovered);color:var(--bal-option-text-pressed)}.bal-option--selected{background:var(--bal-option-background-selected)}@media (hover: hover)and (pointer: fine){.bal-option--selected:hover{background:var(--bal-option-background-selected-hovered)}}.bal-option--selected:active{background:var(--bal-option-background-selected-hovered)}.bal-option--selected .bal-option__inner{font-weight:var(--bal-font-weight-bold)}.bal-option--selected.bal-option--focused{background:var(--bal-option-background-selected-hovered)}.bal-option--selected.bal-option--focused .bal-option__inner{font-weight:var(--bal-font-weight-bold)}.bal-option--invalid{background:var(--bal-option-background-invalid)}@media (hover: hover)and (pointer: fine){.bal-option--invalid:hover{background:var(--bal-option-background-invalid-hovered)}}.bal-option--invalid:active{background:var(--bal-option-background-invalid-hovered)}.bal-option--invalid.bal-option--focused{background:var(--bal-option-background-invalid-hovered)}.bal-option--invalid .bal-option__inner{color:var(--bal-color-text-danger-hovered)}@media (hover: hover)and (pointer: fine){.bal-option--invalid:hover .bal-option__inner{color:var(--bal-color-text-danger-hovered)}}.bal-option--invalid:active .bal-option__inner{color:var(--bal-color-text-danger-pressed)}.bal-option--disabled,.bal-option--disabled.bal-option--focused{background:var(--bal-option-background) !important;color:var(--bal-option-text-disabled) !important;cursor:default !important}.bal-option--disabled:hover,.bal-option--disabled.bal-option--focused:hover{background:var(--bal-option-background) !important}.bal-option{--bal-check-size:1.25rem}";

const Option = class {
    constructor(hostRef) {
        index.registerInstance(this, hostRef);
        this.balOptionChange = index.createEvent(this, "balOptionChange");
        this.balOptionFocus = index.createEvent(this, "balOptionFocus");
        this.inputId = `bal-option-${balOptionIds++}`;
        this.checkbox = false;
        this.interactionState = elementStates_decorator.BalElementStateListener.DefaultState;
        /**
         * PUBLIC PROPERTY API
         * ------------------------------------------------------
         */
        /**
         * Label will be shown in the input element when it got selected
         */
        this.label = '';
        /**
         * The value of the select option. This value will be returned by the parent `<bal-select>` element.
         */
        this.value = '';
        /**
         * If `true`, the user cannot interact with the option.
         */
        this.disabled = false;
        /**
         * If `true`, the option can present in more than one line.
         */
        this.multiline = false;
        /**
         * If `true`, the option is shown in red.
         */
        this.invalid = false;
        /**
         * If `true`, the option is selected.
         */
        this.selected = false;
        /**
         * If `true`, the option is focused.
         */
        this.focused = false;
        /**
         * If `true`, the option is hidden.
         */
        this.hidden = false;
        /**
         * EVENT BINDING
         * ------------------------------------------------------
         */
        this.onClick = (ev) => {
            const listEl = this.el.closest('bal-option-list');
            if (this.disabled || (listEl && listEl.disabled)) {
                formInput.stopEventBubbling(ev);
            }
            else {
                if (listEl && listEl.required && !listEl.multiple) {
                    if (!this.selected) {
                        this.select(true);
                    }
                }
                else {
                    this.select(!this.selected);
                }
            }
        };
    }
    createLogger(log) {
        this.log = log;
    }
    /**
     * LIFECYCLE
     * ------------------------------------------------------
     */
    componentWillRender() {
        if (this.el) {
            const optionListEl = this.el.closest('bal-option-list');
            if (optionListEl) {
                this.checkbox = !!optionListEl.multiple;
            }
        }
    }
    /**
     * LISTENERS
     * ------------------------------------------------------
     */
    listenToMouseEnter() {
        const { label, value, selected, disabled, hidden } = this;
        if (!hidden && !disabled) {
            this.balOptionFocus.emit({ label, value, selected });
        }
    }
    elementStateListener(info) {
        this.interactionChildElements.forEach(element => {
            element.hovered = info.hovered;
            element.pressed = info.pressed;
        });
    }
    /**
     * PUBLIC METHODS
     * ------------------------------------------------------
     */
    /**
     * Selects or deselects the option and informs other components
     */
    async select(selected = true) {
        this.selected = selected;
        const { label, value } = this;
        this.balOptionChange.emit({ label, value, selected });
    }
    /**
     * PRIVATE METHODS
     * ------------------------------------------------------
     */
    get interactionChildElements() {
        return Array.from(this.el.querySelectorAll('bal-check'));
    }
    /**
     * RENDER
     * ------------------------------------------------------
     */
    render() {
        const block = bem.BEM.block('option');
        return (index.h(index.Host, { key: 'b1354e891bf0e8daf9dbd51f9f9c0343cb153cd7', class: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, block.class()), block.modifier('checkbox').class(this.checkbox)), block.modifier('focused').class(this.focused)), block.modifier('invalid').class(this.invalid)), block.modifier('selected').class(this.selected)), block.modifier('disabled').class(this.disabled)), block.modifier('hidden').class(this.hidden)), role: "option", id: this.inputId, "data-value": this.value, "data-label": this.label, "aria-label": this.label, "aria-hidden": aria.ariaBooleanToString(this.hidden), "aria-selected": aria.ariaBooleanToString(this.selected), "aria-checked": aria.ariaBooleanToString(this.selected), "aria-disabled": aria.ariaBooleanToString(this.disabled), "aria-invalid": aria.ariaBooleanToString(this.invalid), tabIndex: -1, onClick: this.onClick }, index.h("bal-stack", { key: '86b29daf65cebd3b742841eb2ab3785a74ddf620', py: "small", space: "x-small" }, this.checkbox ? (index.h("bal-check", { checked: this.selected, disabled: this.disabled, invalid: this.invalid, hovered: this.interactionState.hovered, pressed: this.interactionState.pressed, tabindex: -1 })) : (''), index.h("div", { key: '59f0e1afb3e543123dd891a5fc439f737c2454e4', class: Object.assign(Object.assign({}, block.element('inner').class()), block.element('inner').modifier('multiline').class(this.multiline)) }, index.h("slot", { key: 'f817c6d88b07f8113194fbf6ba5f0298c9e99f81' })), this.selected && !this.checkbox ? (index.h("bal-icon", { name: "check", size: "small", color: this.disabled ? 'grey' : this.invalid ? 'danger' : 'primary' })) : (''))));
    }
    get el() { return index.getElement(this); }
};
tslib_es6.__decorate([
    index.Logger('bal-option'),
    tslib_es6.__metadata("design:type", Function),
    tslib_es6.__metadata("design:paramtypes", [Function]),
    tslib_es6.__metadata("design:returntype", void 0)
], Option.prototype, "createLogger", null);
tslib_es6.__decorate([
    elementStates_decorator.ListenToElementStates(),
    tslib_es6.__metadata("design:type", Function),
    tslib_es6.__metadata("design:paramtypes", [Object]),
    tslib_es6.__metadata("design:returntype", void 0)
], Option.prototype, "elementStateListener", null);
let balOptionIds = 0;
Option.style = balOptionCss;

const balOptionListCss = ".bal-option-list{display:block;position:relative;width:100%;list-style:none;margin:0;outline:0;max-height:var(--bal-option-list-max-height);border-radius:var(--bal-radius-normal);overflow:hidden auto}";

const OptionList = class {
    constructor(hostRef) {
        index.registerInstance(this, hostRef);
        this.inputId = `bal-option-list-${balOptionListIds++}`;
        this.inheritAttributes = {};
        this.ariaForm = form.defaultBalAriaForm;
        /**
         * PUBLIC PROPERTY API
         * ------------------------------------------------------
         */
        /**
         * If `true` the list supports multiple selections
         */
        this.multiple = false;
        /**
         * If `true`, the user cannot interact with the option.
         */
        this.disabled = false;
        /**
         * If `true`, the user must fill in a value before submitting a form.
         */
        this.required = false;
        /**
         * Defines the focused option with his index value
         */
        this.focusIndex = -1;
        /**
         * Defines the filter logic of the list
         */
        this.filter = 'includes';
        /**
         * Defines the max height of the list element
         */
        this.contentHeight = 262;
    }
    createLogger(log) {
        this.log = log;
    }
    contentHeightChanged(value) {
        if (value === undefined) {
            this.el.style.removeProperty('--bal-option-list-max-height');
        }
        else {
            this.el.style.setProperty('--bal-option-list-max-height', `${value}px`);
        }
    }
    /**
     * LIFECYCLE
     * ------------------------------------------------------
     */
    componentDidLoad() {
        this.contentHeightChanged(this.contentHeight);
    }
    componentWillRender() {
        this.inheritAttributes = attributes.inheritAttributes(this.el, ['aria-multiselectable', 'aria-labelledby']);
    }
    /**
     * LISTENERS
     * ------------------------------------------------------
     */
    listenToMouseEnter(ev) {
        const options = this.options;
        const indexToFocus = this.getOptionIndex(options, ev.detail.value);
        if (indexToFocus !== undefined) {
            this.updateFocus(options, indexToFocus);
        }
    }
    listenToOptionChange({ detail }) {
        if (!this.multiple) {
            this.options.filter(option => option.value !== detail.value).forEach(option => (option.selected = false));
        }
    }
    /**
     * PUBLIC METHODS
     * ------------------------------------------------------
     */
    /**
     * Focus the selected visible option in the list, if no option is selected it selects the first one
     */
    async focusSelected() {
        const options = this.options;
        const indexToFocus = this.getSelectedOptionIndex(options);
        if (indexToFocus > 0) {
            this.updateFocus(options, indexToFocus);
            await index.waitAfterFramePaint();
            return indexToFocus;
        }
        else {
            return await this.focusFirst();
        }
    }
    /**
     * Focus the first visible option in the list
     * @returns focusIndex
     */
    async focusFirst() {
        const options = this.options;
        const indexToFocus = this.getFirstOptionIndex(options);
        this.updateFocus(options, indexToFocus);
        const option = options[indexToFocus];
        this.updateScrollTopPosition(option);
        await index.waitAfterFramePaint();
        return indexToFocus;
    }
    /**
     * Focus the last visible option in the list
     * @returns focusIndex
     */
    async focusLast() {
        const options = this.options;
        const indexToFocus = this.getLastOptionIndex(options);
        this.updateFocus(options, indexToFocus);
        const option = options[indexToFocus];
        this.updateScrollBottomPosition(option);
        await index.waitAfterFramePaint();
        return indexToFocus;
    }
    /**
     * Focus the next visible option in the list
     * @returns focusIndex
     */
    async focusNext() {
        const options = this.options;
        const indexToFocus = this.getNextOptionIndex(options);
        this.updateFocus(options, indexToFocus);
        const option = options[indexToFocus];
        this.updateScrollBottomPosition(option);
        await index.waitAfterFramePaint();
        return indexToFocus;
    }
    /**
     * Focus the previous visible option in the list
     * @returns focusIndex
     */
    async focusPrevious() {
        const options = this.options;
        const indexToFocus = this.getPreviousOptionIndex(options);
        this.updateFocus(options, indexToFocus);
        const option = options[indexToFocus];
        this.updateScrollTopPosition(option);
        await index.waitAfterFramePaint();
        return indexToFocus;
    }
    /**
     * Focus the option with the label that starts with the search property
     * @returns focusIndex
     */
    async focusByLabel(search, config) {
        const options = this.options;
        const indexToFocus = this.getOptionIndexByLabel(options, search);
        this.updateFocus(options, indexToFocus);
        const option = options[indexToFocus];
        this.updateScrollTopPosition(option);
        await index.waitAfterFramePaint();
        if (config.select) {
            await option.select();
        }
        return indexToFocus;
    }
    /**
     * Filter the options by the given filter property and hides options
     * @returns focusIndex
     */
    async filterByContent(search) {
        const options = this.allOptions;
        this.filterOptions(options, search);
        await index.waitAfterFramePaint();
        return this.focusFirst();
    }
    /**
     * Shows or hides all options
     */
    async resetHidden(hidden = false) {
        this.options.forEach(option => (option.hidden = hidden));
        await index.waitAfterFramePaint();
        this.resetFocus();
    }
    /**
     * Selects or deselects all options
     */
    async resetSelected(selected = false) {
        this.options.forEach(option => (option.selected = selected));
        await index.waitAfterFramePaint();
    }
    /**
     * Updates options
     */
    async updateSelected(values) {
        this.options.forEach(option => (option.selected = values.includes(option.value)));
        await index.waitAfterFramePaint();
    }
    /**
     * Resets the focus index to pristine and scrolls to the top of the list
     */
    async resetFocus() {
        const options = this.options;
        const indexToFocus = -1;
        this.updateFocus(options, indexToFocus);
        this.scrollTo(0);
        await index.waitAfterFramePaint();
        return indexToFocus;
    }
    /**
     * Returns a list of option values
     */
    async getSelectedValues() {
        const options = this.options;
        return options.filter(option => option.selected).map(option => option.value);
    }
    /**
     * Returns a list of option labels
     */
    async getSelectedOptions(values) {
        const options = this.options;
        if (values && values.length > 0) {
            return options.filter(option => values.includes(option.value)).map(option => option);
        }
        return options.filter(option => option.selected).map(option => option);
    }
    /**
     * Returns a list of options
     */
    async getValues() {
        return this.options.map(option => option.value);
    }
    /**
     * Returns a list of options
     */
    async getLabels() {
        return this.options.map(option => option.label);
    }
    /**
     * Returns a list of accessible options
     */
    async getOptions() {
        return this.options.filter(o => !o.disabled || !o.hidden);
    }
    /**
     * Selects the option with the current focus
     */
    async selectByFocus() {
        const options = this.options;
        const option = options[this.focusIndex];
        if (option) {
            if (this.multiple) {
                option.select(!option.selected);
            }
            else {
                option.select(true);
            }
        }
    }
    /**
     * @internal
     */
    async setAriaForm(ariaForm) {
        this.ariaForm = Object.assign({}, ariaForm);
    }
    /**
     * GETTERS
     * ------------------------------------------------------
     */
    get options() {
        return Array.from(this.el.querySelectorAll('bal-option')).filter(o => !o.hidden);
    }
    get allOptions() {
        return Array.from(this.el.querySelectorAll('bal-option'));
    }
    /**
     * PRIVATE METHODS
     * ------------------------------------------------------
     */
    filterOptions(options, search) {
        const filteredOptions = [];
        const filter = this.filter === 'includes' ? utils.includes : utils.startsWith;
        for (let index = 0; index < options.length; index++) {
            const option = options[index];
            const content = option.textContent || '';
            if (filter(content, search)) {
                filteredOptions.push(option);
                option.hidden = false;
            }
            else {
                option.hidden = true;
            }
        }
        return filteredOptions;
    }
    isOptionVisible(option) {
        const visibleHeight = this.el.clientHeight;
        const topPosition = this.el.scrollTop;
        const bottomPosition = topPosition + visibleHeight;
        const isVisible = topPosition <= option.offsetTop && option.offsetTop + option.clientHeight <= bottomPosition;
        return isVisible;
    }
    updateScrollTopPosition(option) {
        if (option) {
            const isVisible = this.isOptionVisible(option);
            if (!isVisible) {
                this.scrollTo(this.getScrollTopForTopPosition(option));
            }
        }
    }
    updateScrollBottomPosition(option) {
        if (option) {
            const isVisible = this.isOptionVisible(option);
            if (!isVisible) {
                this.scrollTo(this.getScrollTopForBottomPosition(option));
            }
        }
    }
    getScrollTopForTopPosition(option) {
        const topPosition = option.offsetTop;
        const scrollTop = topPosition;
        if (scrollTop < 0) {
            return 0;
        }
        return scrollTop;
    }
    getScrollTopForBottomPosition(option) {
        const visibleHeight = this.el.clientHeight;
        const bottomPosition = option.offsetTop + option.clientHeight;
        const scrollTop = bottomPosition - visibleHeight;
        if (scrollTop < 0) {
            return 0;
        }
        return scrollTop;
    }
    async scrollTo(scrollTop) {
        if (scrollTop !== undefined && scrollTop !== null) {
            if (this.focusRaf !== undefined) {
                cancelAnimationFrame(this.focusRaf);
            }
            this.focusRaf = index.raf(async () => {
                this.el.scrollTop = scrollTop;
            });
        }
    }
    updateFocus(options, indexToFocus) {
        this.focusIndex = indexToFocus;
        for (let index = 0; index < options.length; index++) {
            const option = options[index];
            option.focused = index === indexToFocus;
        }
    }
    getOptionIndex(options, value) {
        for (let index = 0; index < options.length; index++) {
            const option = options[index];
            if (option.value === value) {
                return index;
            }
        }
        return undefined;
    }
    getSelectedOptionIndex(options) {
        for (let index = 0; index < options.length; index++) {
            const option = options[index];
            if (option.selected && !option.hidden) {
                return index;
            }
        }
        return this.focusIndex;
    }
    getFirstOptionIndex(options) {
        for (let index = 0; index < options.length; index++) {
            const option = options[index];
            if (!option.disabled && !option.hidden) {
                return index;
            }
        }
        return this.focusIndex;
    }
    getNextOptionIndex(options, index = this.focusIndex) {
        if (index < 0) {
            return this.getFirstOptionIndex(options);
        }
        const lastIndex = this.getLength(options);
        let newIndex = index;
        if (index < lastIndex) {
            newIndex = index + 1;
            if (options[newIndex].disabled) {
                return this.getNextOptionIndex(options, newIndex);
            }
        }
        return newIndex;
    }
    getPreviousOptionIndex(options, index = this.focusIndex) {
        const firstIndex = this.getFirstOptionIndex(options);
        if (index <= firstIndex) {
            return firstIndex;
        }
        let newIndex = index;
        newIndex = index - 1;
        if (options[newIndex].disabled) {
            return this.getPreviousOptionIndex(options, newIndex);
        }
        return newIndex;
    }
    getLastOptionIndex(options) {
        for (let index = options.length - 1; index >= 0; index--) {
            const option = options[index];
            if (!option.disabled) {
                return index;
            }
        }
        return this.focusIndex;
    }
    getOptionIndexByLabel(options, label) {
        if (label === undefined || label === '') {
            return this.focusIndex;
        }
        const option = options.find(o => utils.startsWith(o.label || '', label));
        if (!index$1.isNil(option) && option.id) {
            return options.indexOf(option);
        }
        return this.focusIndex;
    }
    getLength(options) {
        const indexes = options.map((option, index) => (option.disabled ? 0 : index));
        const length = Math.max(...indexes);
        return length;
    }
    /**
     * RENDER
     * ------------------------------------------------------
     */
    render() {
        const block = bem.BEM.block('option-list');
        const labelledby = this.labelledby || this.ariaForm.labelId;
        return (index.h(index.Host, { key: 'b232136a55b7116f1894fca167540d50b7d974db', class: Object.assign({}, block.class()), id: this.inputId }, index.h("div", Object.assign({ key: '2c8a33c3e9baf88f7acd26bb097690909c2fdacc', role: "listbox", "aria-labelledby": labelledby, "aria-disabled": aria.ariaBooleanToString(this.disabled), class: Object.assign({}, block.element('container').class()) }, this.inheritAttributes), index.h("slot", { key: 'ae72b336a225342786af05f2a722d3d2f6409871' }))));
    }
    get el() { return index.getElement(this); }
    static get watchers() { return {
        "contentHeight": ["contentHeightChanged"]
    }; }
};
tslib_es6.__decorate([
    index.Logger('bal-option-list'),
    tslib_es6.__metadata("design:type", Function),
    tslib_es6.__metadata("design:paramtypes", [Function]),
    tslib_es6.__metadata("design:returntype", void 0)
], OptionList.prototype, "createLogger", null);
let balOptionListIds = 0;
OptionList.style = balOptionListCss;

exports.bal_dropdown = Dropdown;
exports.bal_option = Option;
exports.bal_option_list = OptionList;
