/*!
 * KoliBri - The accessible HTML-Standard
 */
import { h, Fragment, proxyCustomElement, HTMLElement } from '@stencil/core/internal/client';
import { a as __rest, _ as __decorate } from './tslib.es6.js';
import { c as clsx } from './clsx.js';
import { a as getMsgType, i as isMsgDefinedAndInputTouched, c as getDefaultProps, g as getRenderStates, F as FormFieldStateWrapper } from './controller3.js';
import { I as InputIconController, a as InputContainerStateWrapperFc } from './controller-icon.js';
import './common.js';
import { G as watchJsonArrayString } from './prop.validators.js';
import { c as createUniqueId } from './dev.utils.js';
import { c as createCtaRef, b as directFocus, e as directClick } from './element-interaction.js';
import { p as propagateSubmitEventToForm } from './controller2.js';
import { v as validateMultiple } from './multiple.js';
import { f as fillKeyOptionMap, v as validateOptionsWithOptgroup } from './controller4.js';
import { v as validateRequired } from './required.js';
import { v as validateRows } from './rows.js';

const NativeOptionFc = (_a) => {
    var { baseClassName = 'kol-select', class: classNames, index, selectedValue, selected, value, label, disabled } = _a, other = __rest(_a, ["baseClassName", "class", "index", "selectedValue", "selected", "value", "label", "disabled"]);
    if (selectedValue === undefined) {
        selectedValue = [];
    }
    else if (!Array.isArray(selectedValue)) {
        selectedValue = [selectedValue];
    }
    const isSelected = selected || selectedValue.includes(value);
    return (h("option", Object.assign({ class: clsx(`${baseClassName}__option`, {
            [`${baseClassName}__option--selected`]: isSelected,
            [`${baseClassName}__option--disabled`]: disabled,
        }, classNames), selected: isSelected, disabled: disabled, value: index }, other), label));
};

const NativeOptionListFc = ({ baseClassName, preKey, options, disabled, value: selectedValue, OptionProps = {}, OptionGroupProps = {}, }) => {
    if (!(options === null || options === void 0 ? void 0 : options.length)) {
        return null;
    }
    return (h(Fragment, null, options.map((option, index) => {
        const key = [preKey, `-${index}`].join('');
        if ('options' in option) {
            if (!options.length) {
                return null;
            }
            const { label } = option, other = __rest(option, ["label"]);
            return (h("optgroup", Object.assign({ class: clsx(`${baseClassName}__optgroup`, { [`${baseClassName}__optgroup--disabled`]: disabled }), key: key }, OptionGroupProps, { label: label === null || label === void 0 ? void 0 : label.toString(), disabled: disabled }), h(NativeOptionListFc, Object.assign({ baseClassName: baseClassName, OptionGroupProps: OptionGroupProps, OptionProps: OptionProps, value: selectedValue, preKey: key }, other))));
        }
        if ('value' in option) {
            return h(NativeOptionFc, Object.assign({ key: key, baseClassName: baseClassName }, OptionProps, { index: key, selectedValue: selectedValue }, option));
        }
        return null;
    })));
};

const NativeSelectFc = (props) => {
    const { class: classNames, msg, touched, disabled, required, options, value, OptionProps, OptionGroupProps, ariaDescribedBy, hideLabel, label } = props, other = __rest(props, ["class", "msg", "touched", "disabled", "required", "options", "value", "OptionProps", "OptionGroupProps", "ariaDescribedBy", "hideLabel", "label"]);
    const stateCssClasses = {
        ['kol-select--disabled']: Boolean(disabled),
        ['kol-select--required']: Boolean(required),
        ['kol-select--touched']: Boolean(touched),
        [`kol-select--${getMsgType(msg)}`]: isMsgDefinedAndInputTouched(msg, touched),
    };
    const inputProps = Object.assign(Object.assign({ class: clsx('kol-select', stateCssClasses, classNames), required: required, disabled: disabled }, getDefaultProps({ ariaDescribedBy, hideLabel, label })), other);
    return (h("select", Object.assign({}, inputProps), h(NativeOptionListFc, { baseClassName: "kol-select", options: options, value: value, OptionGroupProps: OptionGroupProps, OptionProps: OptionProps })));
};

function getSelectProps(state) {
    const { ariaDescribedBy } = getRenderStates(state);
    const props = {
        id: state._id,
        hideLabel: state._hideLabel,
        label: state._label,
        value: state._value,
        options: state._options,
        accessKey: state._accessKey,
        disabled: state._disabled,
        name: state._name,
        ariaDescribedBy: ariaDescribedBy,
        size: state._rows,
        multiple: state._multiple,
        required: state._required,
        touched: state._touched,
        msg: state._msg,
    };
    if ('_shortKey' in state)
        props['aria-keyshortcuts'] = state._shortKey;
    return props;
}
const SelectStateWrapper = (_a) => {
    var { state } = _a, other = __rest(_a, ["state"]);
    return h(NativeSelectFc, Object.assign({}, getSelectProps(state), other));
};

class SelectController extends InputIconController {
    constructor(component, name, host) {
        super(component, name, host);
        this.keyOptionMap = new Map();
        this.getOptionByKey = (key) => this.keyOptionMap.get(key);
        this.isValueInOptions = (value, options) => {
            return (options.find((option) => typeof option.value === 'string'
                ? option.value === value
                : Array.isArray(option.options)
                    ? this.isValueInOptions(value, option.options)
                    : false) !== undefined);
        };
        this.filterValuesInOptions = (values, options) => {
            return values.filter((value) => this.isValueInOptions(value, options) !== undefined);
        };
        this.afterPatchOptions = (value, _state, _component, key) => {
            if (key === '_value') {
                this.setFormAssociatedValue(value);
            }
        };
        this.beforePatchOptions = (_value, nextState) => {
            const raw = nextState.get('_value');
            if (raw !== undefined && !Array.isArray(raw)) {
                nextState.set('_value', [raw]);
            }
            const options = nextState.has('_options') ? nextState.get('_options') : this.component.state._options;
            if (Array.isArray(options) && options.length > 0) {
                this.keyOptionMap.clear();
                fillKeyOptionMap(this.keyOptionMap, options);
                const value = nextState.has('_value') ? nextState.get('_value') : this.component.state._value;
                const selected = this.filterValuesInOptions(Array.isArray(value) && value.length > 0 ? value : [], options);
                if (this.component._multiple === false && selected.length === 0) {
                    nextState.set('_value', [
                        options[0].value,
                    ]);
                }
                else if (Array.isArray(value) && selected.length < value.length) {
                    nextState.set('_value', selected);
                }
            }
        };
        this.component = component;
    }
    validateOptions(value) {
        validateOptionsWithOptgroup(this.component, value, {
            hooks: {
                afterPatch: this.afterPatchOptions,
                beforePatch: this.beforePatchOptions,
            },
        });
    }
    validateMultiple(value) {
        this.assertComponentValueMatchesMultiplicity(value === true);
        validateMultiple(this.component, value, {
            hooks: {
                afterPatch: this.afterPatchOptions,
                beforePatch: this.beforePatchOptions,
            },
        });
    }
    validateRequired(value) {
        validateRequired(this.component, value);
    }
    validateRows(value) {
        validateRows(this.component, value);
    }
    validateValue(value) {
        this.assertValueMatchesMultiplicity(value);
        watchJsonArrayString(this.component, '_value', () => true, value === undefined ? [] : Array.isArray(value) ? value : [value], undefined, {
            hooks: {
                afterPatch: this.afterPatchOptions,
                beforePatch: this.beforePatchOptions,
            },
        });
    }
    componentWillLoad() {
        super.componentWillLoad();
        this.validateOptions(this.component._options);
        this.validateMultiple(this.component._multiple);
        this.validateRequired(this.component._required);
        this.validateRows(this.component._rows);
        this.validateValue(this.component._value);
    }
    assertValueMatchesMultiplicity(value) {
        const isArray = Array.isArray(value);
        const isMultiple = this.component._multiple === true;
        if (isMultiple) {
            if (value !== undefined && !isArray) {
                throw new Error(`↑ The schema for the property (_value) is not valid for multiple mode. Expected an array. The value will not be changed. (received = ${JSON.stringify(value)})`);
            }
        }
        else {
            if (isArray) {
                throw new Error(`↑ The schema for the property (_value) is not valid for single mode. Expected a single value. The value will not be changed. (received = ${JSON.stringify(value)})`);
            }
        }
    }
    assertComponentValueMatchesMultiplicity(isMultiple) {
        const rawValue = this.component._value;
        if (isMultiple) {
            if (rawValue !== undefined && !Array.isArray(rawValue)) {
                throw new Error(`↑ The schema for the property (_value) is not valid for multiple mode. Expected an array. The value will not be changed. (current = ${JSON.stringify(rawValue)})`);
            }
        }
        else {
            if (Array.isArray(rawValue)) {
                throw new Error(`↑ The schema for the property (_value) is not valid for single mode. Expected a single value. The value will not be changed. (current = ${JSON.stringify(rawValue)})`);
            }
        }
    }
}

const KolSelectWc$1 = proxyCustomElement(class KolSelectWc extends HTMLElement {
    async getValue() {
        if (this._multiple) {
            return this.state._value;
        }
        else {
            return Array.isArray(this.state._value) && this.state._value.length > 0 ? this.state._value[0] : this.state._value;
        }
    }
    async focus(options) { }
    async click() { }
    getFormFieldProps() {
        return {
            state: this.state,
            class: clsx('kol-form-field-select', {
                'kol-form-field--has-value': this.state._hasValue,
            }),
            tooltipAlign: this._tooltipAlign,
            onClick: () => { var _a; return (_a = this.ctaRef.el) === null || _a === void 0 ? void 0 : _a.focus(); },
            alert: this.showAsAlert(),
        };
    }
    getSelectProps() {
        return Object.assign(Object.assign({ ref: this.ctaRef, state: this.state }, this.controller.onFacade), { onInput: this.onInput.bind(this), onChange: this.onChange.bind(this), onFocus: (event) => {
                this.controller.onFacade.onFocus(event);
                this.inputHasFocus = true;
            }, onBlur: (event) => {
                this.controller.onFacade.onBlur(event);
                this.inputHasFocus = false;
            } });
    }
    render() {
        return (h(FormFieldStateWrapper, Object.assign({ key: '1aa065d33eb61c13e5d46118820fb1517c116ef8' }, this.getFormFieldProps()), h(InputContainerStateWrapperFc, { key: '5c56852755b4dbf5f808d128bb221c7b9c50d59c', state: this.state }, h("form", { key: '6974fa1eef19077680e0825f50d576c7e8fb0ad1', onSubmit: (event) => {
                event.preventDefault();
                propagateSubmitEventToForm({
                    form: this.host});
            } }, h("input", { key: 'dca06d50c09696120b037147e9df5d2d7167cc9e', type: "submit", hidden: true }), h(SelectStateWrapper, Object.assign({ key: 'c382d84c4c6c8098f850eeaa68acc5e03a65e66b' }, this.getSelectProps()))))));
    }
    constructor(registerHost) {
        super();
        if (registerHost !== false) {
            this.__registerHost();
        }
        this.ctaRef = createCtaRef();
        this._disabled = false;
        this._hideMsg = false;
        this._hideLabel = false;
        this._hint = '';
        this._multiple = false;
        this._required = false;
        this._tooltipAlign = 'top';
        this._touched = false;
        this.state = {
            _hasValue: false,
            _hideMsg: false,
            _id: createUniqueId('select'),
            _label: '',
            _multiple: false,
            _options: [],
            _value: [],
        };
        this.inputHasFocus = false;
        this.controller = new SelectController(this, 'select', this.host);
    }
    showAsAlert() {
        return Boolean(this.state._touched) && !this.inputHasFocus;
    }
    validateAccessKey(value) {
        this.controller.validateAccessKey(value);
    }
    validateDisabled(value) {
        this.controller.validateDisabled(value);
    }
    validateHideMsg(value) {
        this.controller.validateHideMsg(value);
    }
    validateHideLabel(value) {
        this.controller.validateHideLabel(value);
    }
    validateHint(value) {
        this.controller.validateHint(value);
    }
    validateIcons(value) {
        this.controller.validateIcons(value);
    }
    validateLabel(value) {
        this.controller.validateLabel(value);
    }
    validateMsg(value) {
        this.controller.validateMsg(value);
    }
    validateMultiple(value) {
        this.controller.validateMultiple(value);
    }
    validateName(value) {
        this.controller.validateName(value);
    }
    validateOn(value) {
        this.controller.validateOn(value);
    }
    validateOptions(value) {
        this.controller.validateOptions(value);
    }
    validateRequired(value) {
        this.controller.validateRequired(value);
    }
    validateRows(value) {
        this.controller.validateRows(value);
    }
    validateShortKey(value) {
        this.controller.validateShortKey(value);
    }
    validateSyncValueBySelector(value) {
        this.controller.validateSyncValueBySelector(value);
    }
    validateTabIndex(value) {
        this.controller.validateTabIndex(value);
    }
    validateTouched(value) {
        this.controller.validateTouched(value);
    }
    validateValue(value) {
        this.controller.validateValue(value);
    }
    validateVariant(value) {
        this.controller.validateVariant(value);
    }
    componentWillLoad() {
        this._touched = this._touched === true;
        this.controller.componentWillLoad();
        this.state._hasValue = !!this.state._value;
        this.controller.addValueChangeListener((v) => (this.state._hasValue = !!v));
    }
    onInput(event) {
        var _a;
        const selectedValues = Array.from(((_a = this.ctaRef.el) === null || _a === void 0 ? void 0 : _a.options) || [])
            .filter((option) => option.selected)
            .map((option) => { var _a; return (_a = this.controller.getOptionByKey(option.value)) === null || _a === void 0 ? void 0 : _a.value; });
        if (this._multiple) {
            this._value = selectedValues;
            this.controller.onFacade.onInput(event, true, selectedValues);
        }
        else {
            const singleValue = selectedValues.length > 0 ? selectedValues[0] : undefined;
            this._value = singleValue;
            this.controller.onFacade.onInput(event, true, singleValue);
        }
    }
    onChange(event) {
        if (this._multiple) {
            this.controller.onFacade.onChange(event, this._value);
        }
        else {
            this.controller.onFacade.onChange(event, this._value);
        }
    }
    get host() { return this; }
    static get watchers() { return {
        "_accessKey": ["validateAccessKey"],
        "_disabled": ["validateDisabled"],
        "_hideMsg": ["validateHideMsg"],
        "_hideLabel": ["validateHideLabel"],
        "_hint": ["validateHint"],
        "_icons": ["validateIcons"],
        "_label": ["validateLabel"],
        "_msg": ["validateMsg"],
        "_multiple": ["validateMultiple"],
        "_name": ["validateName"],
        "_on": ["validateOn"],
        "_options": ["validateOptions"],
        "_required": ["validateRequired"],
        "_rows": ["validateRows"],
        "_shortKey": ["validateShortKey"],
        "_syncValueBySelector": ["validateSyncValueBySelector"],
        "_tabIndex": ["validateTabIndex"],
        "_touched": ["validateTouched"],
        "_value": ["validateValue"],
        "_variant": ["validateVariant"]
    }; }
}, [256, "kol-select-wc", {
        "_accessKey": [1, "_access-key"],
        "_disabled": [4],
        "_hideMsg": [4, "_hide-msg"],
        "_hideLabel": [4, "_hide-label"],
        "_hint": [1],
        "_icons": [1],
        "_label": [1],
        "_msg": [1],
        "_multiple": [4],
        "_name": [1],
        "_on": [16],
        "_options": [1],
        "_required": [4],
        "_shortKey": [1, "_short-key"],
        "_rows": [2],
        "_syncValueBySelector": [1, "_sync-value-by-selector"],
        "_tabIndex": [2, "_tab-index"],
        "_tooltipAlign": [1, "_tooltip-align"],
        "_touched": [1540],
        "_value": [1544],
        "_variant": [1],
        "state": [32],
        "inputHasFocus": [32],
        "getValue": [64],
        "focus": [64],
        "click": [64]
    }, undefined, {
        "_accessKey": ["validateAccessKey"],
        "_disabled": ["validateDisabled"],
        "_hideMsg": ["validateHideMsg"],
        "_hideLabel": ["validateHideLabel"],
        "_hint": ["validateHint"],
        "_icons": ["validateIcons"],
        "_label": ["validateLabel"],
        "_msg": ["validateMsg"],
        "_multiple": ["validateMultiple"],
        "_name": ["validateName"],
        "_on": ["validateOn"],
        "_options": ["validateOptions"],
        "_required": ["validateRequired"],
        "_rows": ["validateRows"],
        "_shortKey": ["validateShortKey"],
        "_syncValueBySelector": ["validateSyncValueBySelector"],
        "_tabIndex": ["validateTabIndex"],
        "_touched": ["validateTouched"],
        "_value": ["validateValue"],
        "_variant": ["validateVariant"]
    }]);
__decorate([
    directFocus('ctaRef')
], KolSelectWc$1.prototype, "focus", null);
__decorate([
    directClick('ctaRef')
], KolSelectWc$1.prototype, "click", null);
function defineCustomElement$1() {
    if (typeof customElements === "undefined") {
        return;
    }
    const components = ["kol-select-wc"];
    components.forEach(tagName => { switch (tagName) {
        case "kol-select-wc":
            if (!customElements.get(tagName)) {
                customElements.define(tagName, KolSelectWc$1);
            }
            break;
    } });
}

const KolSelectWc = KolSelectWc$1;
const defineCustomElement = defineCustomElement$1;

export { KolSelectWc, defineCustomElement };
//# sourceMappingURL=kol-select-wc.js.map

//# sourceMappingURL=kol-select-wc.js.map