element-plus
Version: 
A Component Library for Vue3.0
1,260 lines (1,242 loc) • 55.6 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var vue = require('vue');
var ElInput = require('../el-input');
var util = require('../utils/util');
var resizeEvent = require('../utils/resize-event');
var ElTag = require('../el-tag');
var ElPopper = require('../el-popper');
var ElScrollbar = require('../el-scrollbar');
var directives = require('../directives');
var locale = require('../locale');
var constants = require('../utils/constants');
var validators = require('../utils/validators');
var mitt = require('mitt');
var aria = require('../utils/aria');
var isServer = require('../utils/isServer');
var scrollIntoView = require('../utils/scroll-into-view');
var lodashDebounce = require('lodash/debounce');
var isDef = require('../utils/isDef');
var form = require('../el-form');
var isEqual = require('lodash/isEqual');
var hooks = require('../hooks');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var ElInput__default = /*#__PURE__*/_interopDefaultLegacy(ElInput);
var ElTag__default = /*#__PURE__*/_interopDefaultLegacy(ElTag);
var ElPopper__default = /*#__PURE__*/_interopDefaultLegacy(ElPopper);
var ElScrollbar__default = /*#__PURE__*/_interopDefaultLegacy(ElScrollbar);
var mitt__default = /*#__PURE__*/_interopDefaultLegacy(mitt);
var isServer__default = /*#__PURE__*/_interopDefaultLegacy(isServer);
var scrollIntoView__default = /*#__PURE__*/_interopDefaultLegacy(scrollIntoView);
var lodashDebounce__default = /*#__PURE__*/_interopDefaultLegacy(lodashDebounce);
var isEqual__default = /*#__PURE__*/_interopDefaultLegacy(isEqual);
const selectGroupKey = 'ElSelectGroup';
const selectKey = 'ElSelect';
const selectEvents = {
    queryChange: 'elOptionQueryChange',
    groupQueryChange: 'elOptionGroupQueryChange',
};
function useOption(props, states) {
    const select = vue.inject(selectKey);
    const selectGroup = vue.inject(selectGroupKey, { disabled: false });
    const isObject = vue.computed(() => {
        return Object.prototype.toString.call(props.value).toLowerCase() === '[object object]';
    });
    const itemSelected = vue.computed(() => {
        if (!select.props.multiple) {
            return isEqual(props.value, select.props.modelValue);
        }
        else {
            return contains(select.props.modelValue, props.value);
        }
    });
    const limitReached = vue.computed(() => {
        if (select.props.multiple) {
            const modelValue = (select.props.modelValue || []);
            return !itemSelected.value &&
                modelValue.length >= select.props.multipleLimit &&
                select.props.multipleLimit > 0;
        }
        else {
            return false;
        }
    });
    const currentLabel = vue.computed(() => {
        return props.label || (isObject.value ? '' : props.value);
    });
    const currentValue = vue.computed(() => {
        return props.value || props.label || '';
    });
    const isDisabled = vue.computed(() => {
        return props.disabled || states.groupDisabled || limitReached.value;
    });
    const instance = vue.getCurrentInstance();
    const contains = (arr = [], target) => {
        if (!isObject.value) {
            return arr && arr.indexOf(target) > -1;
        }
        else {
            const valueKey = select.props.valueKey;
            return arr && arr.some(item => {
                return util.getValueByPath(item, valueKey) === util.getValueByPath(target, valueKey);
            });
        }
    };
    const isEqual = (a, b) => {
        if (!isObject.value) {
            return a === b;
        }
        else {
            const { valueKey } = select.props;
            return util.getValueByPath(a, valueKey) === util.getValueByPath(b, valueKey);
        }
    };
    const hoverItem = () => {
        if (!props.disabled && !selectGroup.disabled) {
            select.hoverIndex = select.options.indexOf(instance);
        }
    };
    const queryChange = (query) => {
        const regexp = new RegExp(util.escapeRegexpString(query), 'i');
        states.visible = regexp.test(currentLabel.value) || props.created;
        if (!states.visible) {
            select.filteredOptionsCount--;
        }
    };
    vue.watch(() => currentLabel.value, () => {
        if (!props.created && !select.props.remote)
            select.setSelected();
    });
    vue.watch(() => props.value, (val, oldVal) => {
        const { remote, valueKey } = select.props;
        if (!props.created && !remote) {
            if (valueKey && typeof val === 'object' && typeof oldVal === 'object' && val[valueKey] === oldVal[valueKey]) {
                return;
            }
            select.setSelected();
        }
    });
    select.selectEmitter.on(selectEvents.queryChange, queryChange);
    return {
        select,
        currentLabel,
        currentValue,
        itemSelected,
        isDisabled,
        hoverItem,
    };
}
var script = vue.defineComponent({
    name: 'ElOption',
    componentName: 'ElOption',
    props: {
        value: {
            required: true,
            type: [String, Number, Object],
        },
        label: [String, Number],
        created: Boolean,
        disabled: {
            type: Boolean,
            default: false,
        },
    },
    setup(props) {
        const states = vue.reactive({
            index: -1,
            groupDisabled: false,
            visible: true,
            hitState: false,
            hover: false,
        });
        const { currentLabel, itemSelected, isDisabled, select, hoverItem, } = useOption(props, states);
        const { visible, hover, } = vue.toRefs(states);
        const vm = vue.getCurrentInstance().proxy;
        select.onOptionCreate(vm);
        vue.onBeforeUnmount(() => {
            const { selected } = select;
            let selectedOptions = select.props.multiple ? selected : [selected];
            let index = select.cachedOptions.indexOf(vm);
            let selectedIndex = selectedOptions.findIndex(item => {
                return item.value === vm.value;
            });
            if (index > -1 && selectedIndex < 0) {
                select.cachedOptions.splice(index, 1);
            }
            select.onOptionDestroy(select.options.map(item => item.value).indexOf(props.value));
        });
        function selectOptionClick() {
            if (props.disabled !== true && states.groupDisabled !== true) {
                select.handleOptionSelect(vm, true);
            }
        }
        return {
            currentLabel,
            itemSelected,
            isDisabled,
            select,
            hoverItem,
            visible,
            hover,
            selectOptionClick,
        };
    },
});
function render(_ctx, _cache, $props, $setup, $data, $options) {
  return vue.withDirectives((vue.openBlock(), vue.createBlock("li", {
    class: ["el-select-dropdown__item", {
      'selected': _ctx.itemSelected,
      'is-disabled': _ctx.isDisabled,
      'hover': _ctx.hover}],
    onMouseenter: _cache[1] || (_cache[1] = (...args) => (_ctx.hoverItem && _ctx.hoverItem(...args))),
    onClick: _cache[2] || (_cache[2] = vue.withModifiers((...args) => (_ctx.selectOptionClick && _ctx.selectOptionClick(...args)), ["stop"]))
  }, [
    vue.renderSlot(_ctx.$slots, "default", {}, () => [
      vue.createVNode("span", null, vue.toDisplayString(_ctx.currentLabel), 1 /* TEXT */)
    ])
  ], 34 /* CLASS, HYDRATE_EVENTS */)), [
    [vue.vShow, _ctx.visible]
  ])
}
script.render = render;
script.__file = "packages/select/src/option.vue";
var script$1 = vue.defineComponent({
    name: 'ElSelectDropdown',
    componentName: 'ElSelectDropdown',
    setup() {
        const select = vue.inject(selectKey);
        const popperClass = vue.computed(() => select.props.popperClass);
        const isMultiple = vue.computed(() => select.props.multiple);
        const minWidth = vue.ref('');
        function updateMinWidth() {
            var _a;
            minWidth.value = ((_a = select.selectWrapper) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().width) + 'px';
        }
        vue.onMounted(() => {
            resizeEvent.addResizeListener(select.selectWrapper, updateMinWidth);
        });
        vue.onBeforeUnmount(() => {
            resizeEvent.removeResizeListener(select.selectWrapper, updateMinWidth);
        });
        return {
            minWidth,
            popperClass,
            isMultiple,
        };
    },
});
function render$1(_ctx, _cache, $props, $setup, $data, $options) {
  return (vue.openBlock(), vue.createBlock("div", {
    class: ["el-select-dropdown", [{ 'is-multiple': _ctx.isMultiple }, _ctx.popperClass]],
    style: { minWidth: _ctx.minWidth }
  }, [
    vue.renderSlot(_ctx.$slots, "default")
  ], 6 /* CLASS, STYLE */))
}
script$1.render = render$1;
script$1.__file = "packages/select/src/select-dropdown.vue";
/**
 * Make a map and return a function for checking if a key
 * is in that map.
 * IMPORTANT: all calls of this function must be prefixed with
 * \/\*#\_\_PURE\_\_\*\/
 * So that rollup can tree-shake them if necessary.
 */
const EMPTY_OBJ = (process.env.NODE_ENV !== 'production')
    ? Object.freeze({})
    : {};
const EMPTY_ARR = (process.env.NODE_ENV !== 'production') ? Object.freeze([]) : [];
const isObject = (val) => val !== null && typeof val === 'object';
const objectToString = Object.prototype.toString;
const toTypeString = (value) => objectToString.call(value);
const toRawType = (value) => {
    // extract "RawType" from strings like "[object RawType]"
    return toTypeString(value).slice(8, -1);
};
function useSelectStates(props) {
    const selectEmitter = mitt__default['default']();
    return vue.reactive({
        options: [],
        cachedOptions: [],
        createdLabel: null,
        createdSelected: false,
        selected: props.multiple ? [] : {},
        inputLength: 20,
        inputWidth: 0,
        initialInputHeight: 0,
        optionsCount: 0,
        filteredOptionsCount: 0,
        visible: false,
        softFocus: false,
        selectedLabel: '',
        hoverIndex: -1,
        query: '',
        previousQuery: null,
        inputHovering: false,
        cachedPlaceHolder: '',
        currentPlaceholder: locale.t('el.select.placeholder'),
        menuVisibleOnFocus: false,
        isOnComposition: false,
        isSilentBlur: false,
        selectEmitter,
    });
}
const useSelect = (props, states, ctx) => {
    const ELEMENT = util.useGlobalConfig();
    const reference = vue.ref(null);
    const input = vue.ref(null);
    const popper = vue.ref(null);
    const tags = vue.ref(null);
    const selectWrapper = vue.ref(null);
    const scrollbar = vue.ref(null);
    const hoverOption = vue.ref(-1);
    const elForm = vue.inject(form.elFormKey, {});
    const elFormItem = vue.inject(form.elFormItemKey, {});
    const readonly = vue.computed(() => !props.filterable || props.multiple || (!util.isIE() && !util.isEdge() && !states.visible));
    const selectDisabled = vue.computed(() => props.disabled || elForm.disabled);
    const showClose = vue.computed(() => {
        const hasValue = props.multiple
            ? Array.isArray(props.modelValue) && props.modelValue.length > 0
            : props.modelValue !== undefined && props.modelValue !== null && props.modelValue !== '';
        const criteria = props.clearable &&
            !selectDisabled.value &&
            states.inputHovering &&
            hasValue;
        return criteria;
    });
    const iconClass = vue.computed(() => props.remote && props.filterable ? '' : (states.visible ? 'arrow-up is-reverse' : 'arrow-up'));
    const debounce = vue.computed(() => props.remote ? 300 : 0);
    const emptyText = vue.computed(() => {
        if (props.loading) {
            return props.loadingText || locale.t('el.select.loading');
        }
        else {
            if (props.remote && states.query === '' && states.options.length === 0)
                return false;
            if (props.filterable && states.query && states.options.length > 0 && states.filteredOptionsCount === 0) {
                return props.noMatchText || locale.t('el.select.noMatch');
            }
            if (states.options.length === 0) {
                return props.noDataText || locale.t('el.select.noData');
            }
        }
        return null;
    });
    const showNewOption = vue.computed(() => {
        const hasExistingOption = states.options.filter(option => {
            return !option.created;
        }).some(option => {
            return option.currentLabel === states.query;
        });
        return props.filterable && props.allowCreate && states.query !== '' && !hasExistingOption;
    });
    const selectSize = vue.computed(() => props.size || elFormItem.size || ELEMENT.size);
    const collapseTagSize = vue.computed(() => ['small', 'mini'].indexOf(selectSize.value) > -1 ? 'mini' : 'small');
    const dropMenuVisible = vue.computed(() => states.visible && emptyText.value !== false);
    vue.watch(() => selectDisabled.value, () => {
        vue.nextTick(() => {
            resetInputHeight();
        });
    });
    vue.watch(() => props.placeholder, val => {
        states.cachedPlaceHolder = states.currentPlaceholder = val;
    });
    vue.watch(() => props.modelValue, (val, oldVal) => {
        var _a;
        if (props.multiple) {
            resetInputHeight();
            if ((val && val.length > 0) || (input.value && states.query !== '')) {
                states.currentPlaceholder = '';
            }
            else {
                states.currentPlaceholder = states.cachedPlaceHolder;
            }
            if (props.filterable && !props.reserveKeyword) {
                states.query = '';
                handleQueryChange(states.query);
            }
        }
        setSelected();
        if (props.filterable && !props.multiple) {
            states.inputLength = 20;
        }
        if (!isEqual__default['default'](val, oldVal)) {
            (_a = elFormItem.formItemMitt) === null || _a === void 0 ? void 0 : _a.emit('el.form.change', val);
        }
    }, {
        flush: 'post',
    });
    vue.watch(() => states.visible, val => {
        var _a, _b;
        if (!val) {
            input.value && input.value.blur();
            states.query = '';
            states.previousQuery = null;
            states.selectedLabel = '';
            states.inputLength = 20;
            states.menuVisibleOnFocus = false;
            resetHoverIndex();
            vue.nextTick(() => {
                if (input.value && input.value.value === '' && states.selected.length === 0) {
                    states.currentPlaceholder = states.cachedPlaceHolder;
                }
            });
            if (!props.multiple) {
                if (states.selected) {
                    if (props.filterable && props.allowCreate && states.createdSelected && states.createdLabel) {
                        states.selectedLabel = states.createdLabel;
                    }
                    else {
                        states.selectedLabel = states.selected.currentLabel;
                    }
                    if (props.filterable)
                        states.query = states.selectedLabel;
                }
                if (props.filterable) {
                    states.currentPlaceholder = states.cachedPlaceHolder;
                }
            }
        }
        else {
            (_b = (_a = popper.value) === null || _a === void 0 ? void 0 : _a.update) === null || _b === void 0 ? void 0 : _b.call(_a);
            if (props.filterable) {
                states.query = props.remote ? '' : states.selectedLabel;
                if (props.multiple) {
                    input.value.focus();
                }
                else {
                    if (states.selectedLabel) {
                        states.currentPlaceholder = states.selectedLabel;
                        states.selectedLabel = '';
                    }
                }
                if (!props.multiple && !props.remote) {
                    states.selectEmitter.emit('elOptionQueryChange', '');
                    states.selectEmitter.emit('elOptionGroupQueryChange');
                }
                else {
                    handleQueryChange(states.query);
                }
            }
        }
        ctx.emit('visible-change', val);
    });
    vue.watch(() => ([...states.options]), () => {
        var _a, _b, _c;
        if (isServer__default['default'])
            return;
        (_b = (_a = popper.value) === null || _a === void 0 ? void 0 : _a.update) === null || _b === void 0 ? void 0 : _b.call(_a);
        if (props.multiple) {
            resetInputHeight();
        }
        const inputs = ((_c = selectWrapper.value) === null || _c === void 0 ? void 0 : _c.querySelectorAll('input')) || [];
        if ([].indexOf.call(inputs, document.activeElement) === -1) {
            setSelected();
        }
        if (props.defaultFirstOption && (props.filterable || props.remote) && states.filteredOptionsCount) {
            checkDefaultFirstOption();
        }
    });
    vue.watch(() => states.hoverIndex, val => {
        if (typeof val === 'number' && val > -1) {
            hoverOption.value = states.options[val] || {};
        }
        states.options.forEach(option => {
            option.hover = hoverOption.value === option;
        });
    });
    const resetInputHeight = () => {
        if (props.collapseTags && !props.filterable)
            return;
        vue.nextTick(() => {
            var _a, _b;
            if (!reference.value)
                return;
            const inputChildNodes = reference.value.$el.childNodes;
            const input = [].filter.call(inputChildNodes, item => item.tagName === 'INPUT')[0];
            const _tags = tags.value;
            const sizeInMap = states.initialInputHeight || 40;
            input.style.height = states.selected.length === 0
                ? sizeInMap + 'px'
                : Math.max(_tags ? (_tags.clientHeight + (_tags.clientHeight > sizeInMap ? 6 : 0)) : 0, sizeInMap) + 'px';
            if (states.visible && emptyText.value !== false) {
                (_b = (_a = popper.value) === null || _a === void 0 ? void 0 : _a.update) === null || _b === void 0 ? void 0 : _b.call(_a);
            }
        });
    };
    const handleQueryChange = val => {
        if (states.previousQuery === val || states.isOnComposition)
            return;
        if (states.previousQuery === null &&
            (typeof props.filterMethod === 'function' || typeof props.remoteMethod === 'function')) {
            states.previousQuery = val;
            return;
        }
        states.previousQuery = val;
        vue.nextTick(() => {
            var _a, _b;
            if (states.visible)
                (_b = (_a = popper.value) === null || _a === void 0 ? void 0 : _a.update) === null || _b === void 0 ? void 0 : _b.call(_a);
        });
        states.hoverIndex = -1;
        if (props.multiple && props.filterable) {
            vue.nextTick(() => {
                const length = input.value.length * 15 + 20;
                states.inputLength = props.collapseTags ? Math.min(50, length) : length;
                managePlaceholder();
                resetInputHeight();
            });
        }
        if (props.remote && typeof props.remoteMethod === 'function') {
            states.hoverIndex = -1;
            props.remoteMethod(val);
        }
        else if (typeof props.filterMethod === 'function') {
            props.filterMethod(val);
            states.selectEmitter.emit('elOptionGroupQueryChange');
        }
        else {
            states.filteredOptionsCount = states.optionsCount;
            states.selectEmitter.emit('elOptionQueryChange', val);
            states.selectEmitter.emit('elOptionGroupQueryChange');
        }
        if (props.defaultFirstOption && (props.filterable || props.remote) && states.filteredOptionsCount) {
            checkDefaultFirstOption();
        }
    };
    const managePlaceholder = () => {
        if (states.currentPlaceholder !== '') {
            states.currentPlaceholder = input.value ? '' : states.cachedPlaceHolder;
        }
    };
    const checkDefaultFirstOption = () => {
        states.hoverIndex = -1;
        let hasCreated = false;
        for (let i = states.options.length - 1; i >= 0; i--) {
            if (states.options[i].created) {
                hasCreated = true;
                states.hoverIndex = i;
                break;
            }
        }
        if (hasCreated)
            return;
        for (let i = 0; i !== states.options.length; ++i) {
            const option = states.options[i];
            if (states.query) {
                if (!option.disabled && !option.groupDisabled && option.visible) {
                    states.hoverIndex = i;
                    break;
                }
            }
            else {
                if (option.itemSelected) {
                    states.hoverIndex = i;
                    break;
                }
            }
        }
    };
    const setSelected = () => {
        var _a;
        if (!props.multiple) {
            const option = getOption(props.modelValue);
            if ((_a = option.props) === null || _a === void 0 ? void 0 : _a.created) {
                states.createdLabel = option.props.value;
                states.createdSelected = true;
            }
            else {
                states.createdSelected = false;
            }
            states.selectedLabel = option.currentLabel;
            states.selected = option;
            if (props.filterable)
                states.query = states.selectedLabel;
            return;
        }
        const result = [];
        if (Array.isArray(props.modelValue)) {
            props.modelValue.forEach(value => {
                result.push(getOption(value));
            });
        }
        states.selected = result;
        vue.nextTick(() => {
            resetInputHeight();
        });
    };
    const getOption = value => {
        let option;
        const isObjectValue = toRawType(value).toLowerCase() === 'object';
        const isNull = toRawType(value).toLowerCase() === 'null';
        const isUndefined = toRawType(value).toLowerCase() === 'undefined';
        for (let i = states.cachedOptions.length - 1; i >= 0; i--) {
            const cachedOption = states.cachedOptions[i];
            const isEqualValue = isObjectValue
                ? util.getValueByPath(cachedOption.value, props.valueKey) === util.getValueByPath(value, props.valueKey)
                : cachedOption.value === value;
            if (isEqualValue) {
                option = {
                    value,
                    currentLabel: cachedOption.currentLabel,
                };
                break;
            }
        }
        if (option)
            return option;
        const label = (!isObjectValue && !isNull && !isUndefined) ? value : '';
        const newOption = {
            value,
            currentLabel: label,
        };
        if (props.multiple) {
            newOption.hitState = false;
        }
        return newOption;
    };
    const resetHoverIndex = () => {
        setTimeout(() => {
            if (!props.multiple) {
                states.hoverIndex = states.options.indexOf(states.selected);
            }
            else {
                if (states.selected.length > 0) {
                    states.hoverIndex = Math.min.apply(null, states.selected.map(item => states.options.indexOf(item)));
                }
                else {
                    states.hoverIndex = -1;
                }
            }
        }, 300);
    };
    const handleResize = () => {
        var _a, _b;
        resetInputWidth();
        (_b = (_a = popper.value) === null || _a === void 0 ? void 0 : _a.update) === null || _b === void 0 ? void 0 : _b.call(_a);
        if (props.multiple)
            resetInputHeight();
    };
    const resetInputWidth = () => {
        var _a;
        states.inputWidth = (_a = reference.value) === null || _a === void 0 ? void 0 : _a.$el.getBoundingClientRect().width;
    };
    const onInputChange = () => {
        if (props.filterable && states.query !== states.selectedLabel) {
            states.query = states.selectedLabel;
            handleQueryChange(states.query);
        }
    };
    const debouncedOnInputChange = lodashDebounce__default['default'](() => {
        onInputChange();
    }, debounce.value);
    const debouncedQueryChange = lodashDebounce__default['default'](e => {
        handleQueryChange(e.target.value);
    }, debounce.value);
    const emitChange = val => {
        if (!isEqual__default['default'](props.modelValue, val)) {
            ctx.emit(constants.CHANGE_EVENT, val);
        }
    };
    const deletePrevTag = e => {
        if (e.target.value.length <= 0 && !toggleLastOptionHitState()) {
            const value = props.modelValue.slice();
            value.pop();
            ctx.emit(constants.UPDATE_MODEL_EVENT, value);
            emitChange(value);
        }
    };
    const deleteTag = (event, tag) => {
        const index = states.selected.indexOf(tag);
        if (index > -1 && !selectDisabled.value) {
            const value = props.modelValue.slice();
            value.splice(index, 1);
            ctx.emit(constants.UPDATE_MODEL_EVENT, value);
            emitChange(value);
            ctx.emit('remove-tag', tag.value);
        }
        event.stopPropagation();
    };
    const deleteSelected = event => {
        event.stopPropagation();
        const value = props.multiple ? [] : '';
        ctx.emit(constants.UPDATE_MODEL_EVENT, value);
        emitChange(value);
        states.visible = false;
        ctx.emit('clear');
    };
    const handleOptionSelect = (option, byClick) => {
        if (props.multiple) {
            const value = (props.modelValue || []).slice();
            const optionIndex = getValueIndex(value, option.value);
            if (optionIndex > -1) {
                value.splice(optionIndex, 1);
            }
            else if (props.multipleLimit <= 0 || value.length < props.multipleLimit) {
                value.push(option.value);
            }
            ctx.emit(constants.UPDATE_MODEL_EVENT, value);
            emitChange(value);
            if (option.created) {
                states.query = '';
                handleQueryChange('');
                states.inputLength = 20;
            }
            if (props.filterable)
                input.value.focus();
        }
        else {
            ctx.emit(constants.UPDATE_MODEL_EVENT, option.value);
            emitChange(option.value);
            states.visible = false;
        }
        states.isSilentBlur = byClick;
        setSoftFocus();
        if (states.visible)
            return;
        vue.nextTick(() => {
            scrollToOption(option);
        });
    };
    const getValueIndex = (arr = [], value) => {
        if (!isObject(value))
            return arr.indexOf(value);
        const valueKey = props.valueKey;
        let index = -1;
        arr.some((item, i) => {
            if (util.getValueByPath(item, valueKey) === util.getValueByPath(value, valueKey)) {
                index = i;
                return true;
            }
            return false;
        });
        return index;
    };
    const setSoftFocus = () => {
        states.softFocus = true;
        const _input = input.value || reference.value;
        if (_input) {
            _input.focus();
        }
    };
    const getEl = option => {
        const options = states.options.filter(item => item.value === option.value);
        if (options.length > 0) {
            return options[0].$el;
        }
    };
    const scrollToOption = option => {
        var _a, _b, _c, _d;
        const target = Array.isArray(option) ? getEl(option[0]) : getEl(option);
        if (popper.value && target) {
            const menu = (_c = (_b = (_a = popper.value) === null || _a === void 0 ? void 0 : _a.popperRef) === null || _b === void 0 ? void 0 : _b.querySelector) === null || _c === void 0 ? void 0 : _c.call(_b, '.el-select-dropdown__wrap');
            if (menu) {
                scrollIntoView__default['default'](menu, target);
            }
        }
        (_d = scrollbar.value) === null || _d === void 0 ? void 0 : _d.handleScroll();
    };
    const onOptionCreate = (vm) => {
        states.optionsCount++;
        states.filteredOptionsCount++;
        states.options.push(vm);
        states.cachedOptions.push(vm);
    };
    const onOptionDestroy = (index) => {
        if (index > -1) {
            states.optionsCount--;
            states.filteredOptionsCount--;
            states.options.splice(index, 1);
        }
    };
    const resetInputState = (e) => {
        if (e.code !== aria.EVENT_CODE.backspace)
            toggleLastOptionHitState(false);
        states.inputLength = input.value.length * 15 + 20;
        resetInputHeight();
    };
    const toggleLastOptionHitState = (hit) => {
        if (!Array.isArray(states.selected))
            return;
        const option = states.selected[states.selected.length - 1];
        if (!option)
            return;
        if (hit === true || hit === false) {
            option.hitState = hit;
            return hit;
        }
        option.hitState = !option.hitState;
        return option.hitState;
    };
    const handleComposition = event => {
        const text = event.target.value;
        if (event.type === 'compositionend') {
            states.isOnComposition = false;
            vue.nextTick(() => handleQueryChange(text));
        }
        else {
            const lastCharacter = text[text.length - 1] || '';
            states.isOnComposition = !isDef.isKorean(lastCharacter);
        }
    };
    const handleMenuEnter = () => {
        vue.nextTick(() => scrollToOption(states.selected));
    };
    const handleFocus = event => {
        if (!states.softFocus) {
            if (props.automaticDropdown || props.filterable) {
                states.visible = true;
                if (props.filterable) {
                    states.menuVisibleOnFocus = true;
                }
            }
            ctx.emit('focus', event);
        }
        else {
            states.softFocus = false;
        }
    };
    const blur = () => {
        states.visible = false;
        reference.value.blur();
    };
    const handleBlur = (event) => {
        vue.nextTick(() => {
            if (states.isSilentBlur) {
                states.isSilentBlur = false;
            }
            else {
                ctx.emit('blur', event);
            }
        });
        states.softFocus = false;
    };
    const handleClearClick = (event) => {
        deleteSelected(event);
    };
    const handleClose = () => {
        states.visible = false;
    };
    const toggleMenu = () => {
        if (props.automaticDropdown)
            return;
        if (!selectDisabled.value) {
            if (states.menuVisibleOnFocus) {
                states.menuVisibleOnFocus = false;
            }
            else {
                states.visible = !states.visible;
            }
            if (states.visible) {
                (input.value || reference.value).focus();
            }
        }
    };
    const selectOption = () => {
        if (!states.visible) {
            toggleMenu();
        }
        else {
            if (states.options[states.hoverIndex]) {
                handleOptionSelect(states.options[states.hoverIndex], undefined);
            }
        }
    };
    const getValueKey = item => {
        return isObject(item.value)
            ? util.getValueByPath(item.value, props.valueKey)
            : item.value;
    };
    const optionsAllDisabled = vue.computed(() => states.options.filter(option => option.visible).every(option => option.disabled));
    const navigateOptions = direction => {
        if (!states.visible) {
            states.visible = true;
            return;
        }
        if (states.options.length === 0 || states.filteredOptionsCount === 0)
            return;
        if (!optionsAllDisabled.value) {
            if (direction === 'next') {
                states.hoverIndex++;
                if (states.hoverIndex === states.options.length) {
                    states.hoverIndex = 0;
                }
            }
            else if (direction === 'prev') {
                states.hoverIndex--;
                if (states.hoverIndex < 0) {
                    states.hoverIndex = states.options.length - 1;
                }
            }
            const option = states.options[states.hoverIndex];
            if (option.disabled === true ||
                option.groupDisabled === true ||
                !option.visible) {
                navigateOptions(direction);
            }
            vue.nextTick(() => scrollToOption(hoverOption.value));
        }
    };
    return {
        selectSize,
        handleResize,
        debouncedOnInputChange,
        debouncedQueryChange,
        deletePrevTag,
        deleteTag,
        deleteSelected,
        handleOptionSelect,
        scrollToOption,
        readonly,
        resetInputHeight,
        showClose,
        iconClass,
        showNewOption,
        collapseTagSize,
        setSelected,
        managePlaceholder,
        selectDisabled,
        emptyText,
        toggleLastOptionHitState,
        resetInputState,
        handleComposition,
        onOptionCreate,
        onOptionDestroy,
        handleMenuEnter,
        handleFocus,
        blur,
        handleBlur,
        handleClearClick,
        handleClose,
        toggleMenu,
        selectOption,
        getValueKey,
        navigateOptions,
        dropMenuVisible,
        reference,
        input,
        popper,
        tags,
        selectWrapper,
        scrollbar,
    };
};
var script$2 = vue.defineComponent({
    name: 'ElSelect',
    componentName: 'ElSelect',
    components: {
        ElInput: ElInput__default['default'],
        ElSelectMenu: script$1,
        ElOption: script,
        ElTag: ElTag__default['default'],
        ElScrollbar: ElScrollbar__default['default'],
        ElPopper: ElPopper__default['default'],
    },
    directives: { ClickOutside: directives.ClickOutside },
    props: {
        name: String,
        id: String,
        modelValue: [Array, String, Number, Boolean, Object],
        autocomplete: {
            type: String,
            default: 'off',
        },
        automaticDropdown: Boolean,
        size: {
            type: String,
            validator: validators.isValidComponentSize,
        },
        disabled: Boolean,
        clearable: Boolean,
        filterable: Boolean,
        allowCreate: Boolean,
        loading: Boolean,
        popperClass: {
            type: String,
            default: '',
        },
        remote: Boolean,
        loadingText: String,
        noMatchText: String,
        noDataText: String,
        remoteMethod: Function,
        filterMethod: Function,
        multiple: Boolean,
        multipleLimit: {
            type: Number,
            default: 0,
        },
        placeholder: {
            type: String,
        },
        defaultFirstOption: Boolean,
        reserveKeyword: Boolean,
        valueKey: {
            type: String,
            default: 'value',
        },
        collapseTags: Boolean,
        popperAppendToBody: {
            type: Boolean,
            default: true,
        },
        clearIcon: {
            type: String,
            default: 'el-icon-circle-close',
        },
    },
    emits: [constants.UPDATE_MODEL_EVENT, constants.CHANGE_EVENT, 'remove-tag', 'clear', 'visible-change', 'focus', 'blur'],
    setup(props, ctx) {
        const states = useSelectStates(props);
        const { selectSize, readonly, handleResize, collapseTagSize, debouncedOnInputChange, debouncedQueryChange, deletePrevTag, deleteTag, deleteSelected, handleOptionSelect, scrollToOption, setSelected, resetInputHeight, managePlaceholder, showClose, selectDisabled, iconClass, showNewOption, emptyText, toggleLastOptionHitState, resetInputState, handleComposition, onOptionCreate, onOptionDestroy, handleMenuEnter, handleFocus, blur, handleBlur, handleClearClick, handleClose, toggleMenu, selectOption, getValueKey, navigateOptions, dropMenuVisible, reference, input, popper, tags, selectWrapper, scrollbar, } = useSelect(props, states, ctx);
        const { focus } = hooks.useFocus(reference);
        const { inputWidth, selected, inputLength, filteredOptionsCount, visible, softFocus, selectedLabel, hoverIndex, query, inputHovering, currentPlaceholder, menuVisibleOnFocus, isOnComposition, isSilentBlur, options, cachedOptions, optionsCount, } = vue.toRefs(states);
        vue.provide(selectKey, vue.reactive({
            props,
            options,
            cachedOptions,
            optionsCount,
            filteredOptionsCount,
            hoverIndex,
            handleOptionSelect,
            selectEmitter: states.selectEmitter,
            onOptionCreate,
            onOptionDestroy,
            selectWrapper,
            selected,
            setSelected,
        }));
        vue.onMounted(() => {
            states.cachedPlaceHolder = currentPlaceholder.value = (props.placeholder || locale.t('el.select.placeholder'));
            if (props.multiple && Array.isArray(props.modelValue) && props.modelValue.length > 0) {
                currentPlaceholder.value = '';
            }
            resizeEvent.addResizeListener(selectWrapper.value, handleResize);
            if (reference.value && reference.value.$el) {
                const sizeMap = {
                    medium: 36,
                    small: 32,
                    mini: 28,
                };
                const input = reference.value.input;
                states.initialInputHeight = input.getBoundingClientRect().height || sizeMap[selectSize.value];
            }
            if (props.remote && props.multiple) {
                resetInputHeight();
            }
            vue.nextTick(() => {
                if (reference.value.$el) {
                    inputWidth.value = reference.value.$el.getBoundingClientRect().width;
                }
            });
            setSelected();
        });
        vue.onBeforeUnmount(() => {
            resizeEvent.removeResizeListener(selectWrapper.value, handleResize);
        });
        if (props.multiple && !Array.isArray(props.modelValue)) {
            ctx.emit(constants.UPDATE_MODEL_EVENT, []);
        }
        if (!props.multiple && Array.isArray(props.modelValue)) {
            ctx.emit(constants.UPDATE_MODEL_EVENT, '');
        }
        const popperPaneRef = vue.computed(() => {
            var _a;
            return (_a = popper.value) === null || _a === void 0 ? void 0 : _a.popperRef;
        });
        return {
            selectSize,
            readonly,
            handleResize,
            collapseTagSize,
            debouncedOnInputChange,
            debouncedQueryChange,
            deletePrevTag,
            deleteTag,
            deleteSelected,
            handleOptionSelect,
            scrollToOption,
            inputWidth,
            selected,
            inputLength,
            filteredOptionsCount,
            visible,
            softFocus,
            selectedLabel,
            hoverIndex,
            query,
            inputHovering,
            currentPlaceholder,
            menuVisibleOnFocus,
            isOnComposition,
            isSilentBlur,
            options,
            resetInputHeight,
            managePlaceholder,
            showClose,
            selectDisabled,
            iconClass,
            showNewOption,
            emptyText,
            toggleLastOptionHitState,
            resetInputState,
            handleComposition,
            handleMenuEnter,
            handleFocus,
            blur,
            handleBlur,
            handleClearClick,
            handleClose,
            toggleMenu,
            selectOption,
            getValueKey,
            navigateOptions,
            dropMenuVisible,
            focus,
            reference,
            input,
            popper,
            popperPaneRef,
            tags,
            selectWrapper,
            scrollbar,
        };
    },
});
const _hoisted_1 = { class: "select-trigger" };
const _hoisted_2 = { key: 0 };
const _hoisted_3 = { class: "el-select__tags-text" };
const _hoisted_4 = {
  key: 1,
  class: "el-select-dropdown__empty"
};
function render$2(_ctx, _cache, $props, $setup, $data, $options) {
  const _component_el_tag = vue.resolveComponent("el-tag");
  const _component_el_input = vue.resolveComponent("el-input");
  const _component_el_option = vue.resolveComponent("el-option");
  const _component_el_scrollbar = vue.resolveComponent("el-scrollbar");
  const _component_el_select_menu = vue.resolveComponent("el-select-menu");
  const _component_el_popper = vue.resolveComponent("el-popper");
  const _directive_click_outside = vue.resolveDirective("click-outside");
  return vue.withDirectives((vue.openBlock(), vue.createBlock("div", {
    ref: "selectWrapper",
    class: ["el-select", [_ctx.selectSize ? 'el-select--' + _ctx.selectSize : '']],
    onClick: _cache[26] || (_cache[26] = vue.withModifiers((...args) => (_ctx.toggleMenu && _ctx.toggleMenu(...args)), ["stop"]))
  }, [
    vue.createVNode(_component_el_popper, {
      ref: "popper",
      visible: _ctx.dropMenuVisible,
      "onUpdate:visible": _cache[25] || (_cache[25] = $event => (_ctx.dropMenuVisible = $event)),
      placement: "bottom-start",
      "append-to-body": _ctx.popperAppendToBody,
      "popper-class": `el-select__popper ${_ctx.popperClass}`,
      "manual-mode": "",
      effect: "light",
      pure: "",
      trigger: "click",
      transition: "el-zoom-in-top",
      "stop-popper-mouse-event": false,
      "gpu-acceleration": false,
      onBeforeEnter: _ctx.handleMenuEnter
    }, {
      trigger: vue.withCtx(() => [
        vue.createVNode("div", _hoisted_1, [
          (_ctx.multiple)
            ? (vue.openBlock(), vue.createBlock("div", {
                key: 0,
                ref: "tags",
                class: "el-select__tags",
                style: { 'max-width': _ctx.inputWidth - 32 + 'px', width: '100%' }
              }, [
                (_ctx.collapseTags && _ctx.selected.length)
                  ? (vue.openBlock(), vue.createBlock("span", _hoisted_2, [
                      vue.createVNode(_component_el_tag, {
                        closable: !_ctx.selectDisabled,
                        size: _ctx.collapseTagSize,
                        hit: _ctx.selected[0].hitState,
                        type: "info",
                        "disable-transitions": "",
                        onClose: _cache[1] || (_cache[1] = $event => (_ctx.deleteTag($event, _ctx.selected[0])))
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode("span", {
                            class: "el-select__tags-text",
                            style: { 'max-width': _ctx.inputWidth - 123 + 'px' }
                          }, vue.toDisplayString(_ctx.selected[0].currentLabel), 5 /* TEXT, STYLE */)
                        ]),
                        _: 1 /* STABLE */
                      }, 8 /* PROPS */, ["closable", "size", "hit"]),
                      (_ctx.selected.length > 1)
                        ? (vue.openBlock(), vue.createBlock(_component_el_tag, {
                            key: 0,
                            closable: false,
                            size: _ctx.collapseTagSize,
                            type: "info",
                            "disable-transitions": ""
                          }, {
                            default: vue.withCtx(() => [
                              vue.createVNode("span", _hoisted_3, "+ " + vue.toDisplayString(_ctx.selected.length - 1), 1 /* TEXT */)
                            ]),
                            _: 1 /* STABLE */
                          }, 8 /* PROPS */, ["size"]))
                        : vue.createCommentVNode("v-if", true)
                    ]))
                  : vue.createCommentVNode("v-if", true),
                vue.createCommentVNode(" <div> "),
                (!_ctx.collapseTags)
                  ? (vue.openBlock(), vue.createBlock(vue.Transition, {
                      key: 1,
                      onAfterLeave: _ctx.resetInputHeight
                    }, {
                      default: vue.withCtx(() => [
                        vue.createVNode("span", null, [
                          (vue.openBlock(true), vue.createBlock(vue.Fragment, null, vue.renderList(_ctx.selected, (item) => {
                            return (vue.openBlock(), vue.createBlock(_component_el_tag, {
                              key: _ctx.getValueKey(item),
                              closable: !_ctx.selectDisabled,
                              size: _ctx.collapseTagSize,
                              hit: item.hitState,
                              type: "info",
                              "disable-transitions": "",
                              onClose: $event => (_ctx.deleteTag($event, item))
                            }, {
                              default: vue.withCtx(() => [
                                vue.createVNode("span", {
                                  class: "el-select__tags-text",
                                  style: { 'max-width': _ctx.inputWidth - 75 + 'px' }
                                }, vue.toDisplayString(item.currentLabel), 5 /* TEXT, STYLE */)
                              ]),
                              _: 2 /* DYNAMIC */
                            }, 1032 /* PROPS, DYNAMIC_SLOTS */, ["closable", "size", "hit", "onClose"]))
                          }), 128 /* KEYED_FRAGMENT */))
                        ])
                      ]),
                      _: 1 /* STABLE */
                    }, 8 /* PROPS */, ["onAfterLeave"]))
                  : vue.createCommentVNode("v-if", true),
                vue.createCommentVNode(" </div> "),
                (_ctx.filterable)
                  ? vue.withDirectives((vue.openBlock(), vue.createBlock("input", {
                      key: 2,
                      ref: "input",
                      "onUpdate:modelValue": _cache[2] || (_cache[2] = $event => (_ctx.query = $event)),
                      type: "text",
                      class: ["el-select__input", [_ctx.selectSize ? `is-${ _ctx.selectSize }` : '']],
                      disabled: _ctx.selectDisabled,
                      autocomplete: _ctx.autocomplete,
                      style: { 'flex-grow': '1', width: _ctx.inputLength / (_ctx.inputWidth - 32) + '%', 'max-width': _ctx.inputWidth - 42 + 'px' },
                      onFocus: _cache[3] || (_cache[3] = (...args) => (_ctx.handleFocus && _ctx.handleFocus(...args))),
                      onBlur: _cache[4] || (_cache[4] = $event => (_ctx.softFocus = false)),
                      onKeyup: _cache[5] || (_cache[5] = (...args) => (_ctx.managePlaceholder && _ctx.managePlaceholder(...args))),
                      onKeydown: [
                        _cache[6] || (_cache[6] = (...args) => (_ctx.resetInputState && _ctx.resetInputState(...args))),
                        _cache[7] || (_cache[7] = vue.withKeys(vue.withModifiers($event => (_ctx.navigateOptions('next')), ["prevent"]), ["down"])),
                        _cache[8] || (_cache[8] = vue.withKeys(vue.withModifiers($event => (_ctx.navigateOptions('prev')), ["prevent"]), ["up"])),
                        _cache[9] || (_cache[9] = vue.withKeys(vue.withModifiers($event => (_ctx.visible = false), ["stop","prevent"]), ["esc"])),
                        _cache[10] || (_cache[10] = vue.withKeys(vue.withModifiers((...args) => (_ctx.selectOption && _ctx.selectOption(...args)), ["stop","prevent"]), ["enter"])),
                        _cache[11] || (_cache[11] = vue.withKeys((...args) => (_ctx.deletePrevTag && _ctx.deletePrevTag(...args)), ["delete"])),
                        _cache[12] || (_cache[12] = vue.withKeys($event => (_ctx.visible = false), ["tab"]))
                      ],
                      onCompositionstart: _cache[13] || (_cache[13] = (...args) => (_ctx.handleComposition && _ctx.handleComposition(...args))),
                      onCompositionupdate: _cache[14] || (_cache[14] = (...args) => (_ctx.handleComposition && _ctx.handleComposition(...args))),
                      onCompositionend: _cache[15] || (_cache[15] = (...args) => (_ctx.handleComposition && _ctx.handleComposit