UNPKG

element-plus

Version:

A Component Library for Vue3.0

1,413 lines (1,395 loc) 50.1 kB
'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.optionsArray.indexOf(instance); } }; const queryChange = (query) => { if (!query) { states.visible = !props.created; } else { const regexp = new RegExp(util.escapeRegexpString(query), "i"); states.visible = regexp.test(currentLabel.value); if (!states.visible && !props.created) { 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(); } }); vue.watch(() => selectGroup.disabled, () => { states.groupDisabled = selectGroup.disabled; }, { immediate: true }); select.selectEmitter.on(selectEvents.queryChange, queryChange); vue.onBeforeUnmount(() => { select.selectEmitter.off(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, Boolean, 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]; const doesExist = select.cachedOptions.has(props.value); const doesSelected = selectedOptions.some((item) => { return item.value === vm.value; }); if (doesExist && !doesSelected) { select.cachedOptions.delete(props.value); } select.onOptionDestroy(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) ]) ], 34)), [ [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 ? 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); } 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: new Map(), cachedOptions: new Map(), 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, prefixWidth: null, tagInMultiLine: false }); } 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 !== void 0 && 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.size === 0) return false; if (props.filterable && states.query && states.options.size > 0 && states.filteredOptionsCount === 0) { return props.noMatchText || locale.t("el.select.noMatch"); } if (states.options.size === 0) { return props.noDataText || locale.t("el.select.noData"); } } return null; }); const optionsArray = vue.computed(() => Array.from(states.options.values())); const cachedOptionsArray = vue.computed(() => Array.from(states.cachedOptions.values())); const showNewOption = vue.computed(() => { const hasExistingOption = optionsArray.value.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 ? void 0 : _a.emit("el.form.change", val); } }, { flush: "post", deep: true }); 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 ? void 0 : _a.update) == null ? void 0 : _b.call(_a); if (props.filterable) { states.filteredOptionsCount = states.optionsCount; states.query = props.remote ? "" : states.selectedLabel; if (props.multiple) { input.value.focus(); } else { if (states.selectedLabel) { states.currentPlaceholder = states.selectedLabel; states.selectedLabel = ""; } } handleQueryChange(states.query); if (!props.multiple && !props.remote) { states.selectEmitter.emit("elOptionQueryChange", ""); states.selectEmitter.emit("elOptionGroupQueryChange"); } } } ctx.emit("visible-change", val); }); vue.watch(() => states.options.entries(), () => { var _a, _b, _c; if (isServer__default['default']) return; (_b = (_a = popper.value) == null ? void 0 : _a.update) == null ? void 0 : _b.call(_a); if (props.multiple) { resetInputHeight(); } const inputs = ((_c = selectWrapper.value) == null ? void 0 : _c.querySelectorAll("input")) || []; if ([].indexOf.call(inputs, document.activeElement) === -1) { setSelected(); } if (props.defaultFirstOption && (props.filterable || props.remote) && states.filteredOptionsCount) { checkDefaultFirstOption(); } }, { flush: "post" }); vue.watch(() => states.hoverIndex, (val) => { if (typeof val === "number" && val > -1) { hoverOption.value = optionsArray.value[val] || {}; } optionsArray.value.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 input2 = [].filter.call(inputChildNodes, (item) => item.tagName === "INPUT")[0]; const _tags = tags.value; const sizeInMap = states.initialInputHeight || 40; input2.style.height = states.selected.length === 0 ? sizeInMap + "px" : Math.max(_tags ? _tags.clientHeight + (_tags.clientHeight > sizeInMap ? 6 : 0) : 0, sizeInMap) + "px"; states.tagInMultiLine = parseFloat(input2.style.height) > sizeInMap; if (states.visible && emptyText.value !== false) { (_b = (_a = popper.value) == null ? void 0 : _a.update) == null ? 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 ? void 0 : _a.update) == null ? 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.value ? "" : states.cachedPlaceHolder; } }; const checkDefaultFirstOption = () => { const optionsInDropdown = optionsArray.value.filter((n) => n.visible && !n.disabled && !n.groupDisabled); const userCreatedOption = optionsInDropdown.filter((n) => n.created)[0]; const firstOriginOption = optionsInDropdown[0]; states.hoverIndex = getValueIndex(optionsArray.value, userCreatedOption || firstOriginOption); }; const setSelected = () => { var _a; if (!props.multiple) { const option = getOption(props.modelValue); if ((_a = option.props) == null ? 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.size - 1; i >= 0; i--) { const cachedOption = cachedOptionsArray.value[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, isDisabled: cachedOption.isDisabled }; 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(() => { const valueKey = props.valueKey; if (!props.multiple) { states.hoverIndex = optionsArray.value.findIndex((item) => { return util.getValueByPath(item, valueKey) === util.getValueByPath(states.selected, valueKey); }); } else { if (states.selected.length > 0) { states.hoverIndex = Math.min.apply(null, states.selected.map((selected) => { return optionsArray.value.findIndex((item) => { return util.getValueByPath(item, valueKey) === util.getValueByPath(selected, valueKey); }); })); } else { states.hoverIndex = -1; } } }, 300); }; const handleResize = () => { var _a, _b; resetInputWidth(); (_b = (_a = popper.value) == null ? void 0 : _a.update) == null ? void 0 : _b.call(_a); if (props.multiple) resetInputHeight(); }; const resetInputWidth = () => { var _a; states.inputWidth = (_a = reference.value) == null ? 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); } if (e.target.value.length === 1 && props.modelValue.length === 0) { states.currentPlaceholder = states.cachedPlaceHolder; } }; 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 ? [] : ""; if (typeof value !== "string") { for (const item of states.selected) { if (item.isDisabled) value.push(item.value); } } 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 scrollToOption = (option) => { var _a, _b, _c, _d; const targetOption = Array.isArray(option) ? option[0] : option; let target = null; if (targetOption == null ? void 0 : targetOption.value) { const options = optionsArray.value.filter((item) => item.value === targetOption.value); if (options.length > 0) { target = options[0].$el; } } if (popper.value && target) { const menu = (_c = (_b = (_a = popper.value) == null ? void 0 : _a.popperRef) == null ? void 0 : _b.querySelector) == null ? void 0 : _c.call(_b, ".el-select-dropdown__wrap"); if (menu) { scrollIntoView__default['default'](menu, target); } } (_d = scrollbar.value) == null ? void 0 : _d.handleScroll(); }; const onOptionCreate = (vm) => { states.optionsCount++; states.filteredOptionsCount++; states.options.set(vm.value, vm); states.cachedOptions.set(vm.value, vm); }; const onOptionDestroy = (key) => { states.optionsCount--; states.filteredOptionsCount--; states.options.delete(key); }; 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 (optionsArray.value[states.hoverIndex]) { handleOptionSelect(optionsArray.value[states.hoverIndex], void 0); } } }; const getValueKey = (item) => { return isObject(item.value) ? util.getValueByPath(item.value, props.valueKey) : item.value; }; const optionsAllDisabled = vue.computed(() => optionsArray.value.filter((option) => option.visible).every((option) => option.disabled)); const navigateOptions = (direction) => { if (!states.visible) { states.visible = true; return; } if (states.options.size === 0 || states.filteredOptionsCount === 0) return; if (!optionsAllDisabled.value) { if (direction === "next") { states.hoverIndex++; if (states.hoverIndex === states.options.size) { states.hoverIndex = 0; } } else if (direction === "prev") { states.hoverIndex--; if (states.hoverIndex < 0) { states.hoverIndex = states.options.size - 1; } } const option = optionsArray.value[states.hoverIndex]; if (option.disabled === true || option.groupDisabled === true || !option.visible) { navigateOptions(direction); } vue.nextTick(() => scrollToOption(hoverOption.value)); } }; return { optionsArray, 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 { optionsArray, 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, prefixWidth, tagInMultiLine } = vue.toRefs(states); vue.provide(selectKey, vue.reactive({ props, options, optionsArray, 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 input2 = reference.value.input; states.initialInputHeight = input2.getBoundingClientRect().height || sizeMap[selectSize.value]; } if (props.remote && props.multiple) { resetInputHeight(); } vue.nextTick(() => { if (reference.value.$el) { inputWidth.value = reference.value.$el.getBoundingClientRect().width; } if (ctx.slots.prefix) { const inputChildNodes = reference.value.$el.childNodes; const input2 = [].filter.call(inputChildNodes, (item) => item.tagName === "INPUT")[0]; const prefix = reference.value.$el.querySelector(".el-input__prefix"); prefixWidth.value = Math.max(prefix.getBoundingClientRect().width + 5, 30); if (states.prefixWidth) { input2.style.paddingLeft = `${Math.max(states.prefixWidth, 30)}px`; } } }); 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 ? void 0 : _a.popperRef; }); return { tagInMultiLine, prefixWidth, 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 = { style: { "height": "100%", "display": "flex", "justify-content": "center", "align-items": "center" } }; const _hoisted_5 = { 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}`, "fallback-placements": ["bottom-start", "top-start", "right", "left"], "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 && !_ctx.selected[0].isDisabled, 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) ]), _: 1 }, 8, ["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) ]), _: 1 }, 8, ["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", { style: { marginLeft: _ctx.prefixWidth && _ctx.selected.length ? `${_ctx.prefixWidth}px` : 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 && !item.isDisabled, 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) ]), _: 2 }, 1032, ["closable", "size", "hit", "onClose"]); }), 128)) ], 4) ]), _: 1 }, 8, ["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: { marginLeft: _ctx.prefixWidth && !_ctx.selected.length || _ctx.tagInMultiLine ? `${_ctx.prefixWidth}px` : null, flexGrow: "1", width: `${_ctx.inputLength / (_ctx.inputWidth - 32)}%`, maxWidth: `${_ctx.inputWidth - 42}px` }, onFocus: _cache[3] || (_cache[3] = (...args) => _ctx.handleFocus && _ctx.handleFocus(...args)), onBlur: _cache[4] || (_cache[4] = (...args) => _ctx.handleBlur && _ctx.handleBlur(...args)), 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.handleComposition(...args)), onInput: _cache[16] || (_cache[16] = (...args) => _ctx.debouncedQueryChange && _ctx.debouncedQueryChange(...args)) }, null, 46, ["disabled", "autocomplete"])), [ [vue.vModelText, _ctx.query] ]) : vue.createCommentVNode("v-if", true) ], 4)) : vue.createCommentVNode("v-if", true), vue.createVNode(_component_el_input, { id: _ctx.id, ref: "reference", modelValue: _ctx.selectedLabel, "onUpdate:modelValue": _cache[18] || (_cache[18] = ($event) => _ctx.selectedLabel = $event), type: "text", placeholder: _ctx.currentPlaceholder, name: _ctx.name, autocomplete: _ctx.autocomplete, size: _ctx.selectSize, disabled: _ctx.selectDisabled, readonly: _ctx.readonly, "validate-event": false, class: { "is-focus": _ctx.visible }, tabindex: _ctx.multiple && _ctx.filterable ? "-1" : null, onFocus: _ctx.handleFocus, onBlur: _ctx.handleBlur, onInput: _ctx.debouncedOnInputChange, onPaste: _ctx.debouncedOnInputChange, onKeydown: [ _cache[19] || (_cache[19] = vue.withKeys(vue.withModifiers(($event) => _ctx.navigateOptions("next"), ["stop", "prevent"]), ["down"])), _cache[20] || (_cache[20] = vue.withKeys(vue.withModifiers(($event) => _ctx.navigateOptions("prev"), ["stop", "prevent"]), ["up"])), vue.withKeys(vue.withModifiers(_ctx.selectOption, ["stop", "prevent"]), ["enter"]), _cache[21] || (_cache[21] = vue.withKeys(vue.withModifiers(($event) => _ctx.visible = false, ["stop", "prevent"]), ["esc"])), _cache[22] || (_cache[22] = vue.withKeys(($event) => _ctx.visible = false, ["tab"])) ], onMouseenter: _cache[23] || (_cache[23] = ($event) => _ctx.inputHovering = true), onMouseleave: _cache[24] || (_cache[24] = ($event) => _ctx.inputHovering = false) }, vue.createSlots({ suffix: vue.withCtx(() => [ vue.withDirectives(vue.createVNode("i", { class: ["el-select__caret", "el-input__icon", "el-icon-" + _ctx.iconClass] }, null, 2), [ [vue.vShow, !_ctx.showClose] ]), _ctx.showClose ? (vue.openBlock(), vue.createBlock("i", { key: 0, class: `el-select__caret el-input__icon ${_ctx.clearIcon}`, onClick: _cache[17] || (_cache[17] = (...args) => _ctx.handleClearClick && _ctx.handleClearClick(...args)) }, null, 2)) : vue.createCommentVNode("v-if", true) ]), _: 2 }, [ _ctx.$slots.prefix ? { name: "prefix", fn: vue.withCtx(() => [ vue.createVNode("div", _hoisted_4, [ vue.renderSlot(_ctx.$slots, "prefix") ]) ]) } : void 0 ]), 1032, ["id", "modelValue", "placeholder", "name", "autocomplete", "size", "disabled", "readonly", "class", "tabindex", "onFocus", "onBlur", "onInput", "onPaste", "onKeydown"]) ]) ]), default: vue.withCtx(() => [ vue.createVNode(_component_el_select_menu, null, { default: vue.withCtx(() => [ vue.withDirectives(vue.createVNode(_component_el_scrollbar, { ref: "scrollbar", tag: "ul", "wrap-class": "el-select-dropdown__wrap", "view-class": "el-select-dropdown__list", class: { "is-empty": !_ctx.allowCreate && _ctx.query && _ctx.filteredOptionsCount === 0 } }, { default: vue.withCtx(() => [ _ctx.showNewOption ? (vue.openBlock(), vue.createBlock(_component_el_option, { key: 0, value: _ctx.query, created: true }, null, 8, ["value"])) : vue.createCommentVNode("v-if", true), vue.renderSlot(_ctx.$slots, "default") ]), _: 3 }, 8, ["class"]), [ [vue.vShow, _ctx.options.size > 0 && !_ctx.loading] ]), _ctx.emptyText && (!_ctx.allowCreate || _ctx.loading || _ctx.allowCreate && _ctx.options.size === 0) ? (vue.openBlock(), vue.createBlock(vue.Fragment, { key: 0 }, [ _ctx.$slots.empty ? vue.renderSlot(_ctx.$slots, "empty", { key: 0 }) : (vue.openBlock(), vue.createBlock("p", _hoisted_5, vue.toDisplayString(_ctx.emptyText), 1)) ], 2112)) : vue.createCommentVNode("v-if", true) ]), _: 3 }) ]), _: 1 }, 8, ["visible", "append-to-body", "popper-class", "onBeforeEnter"]) ], 2)), [ [_directive_click_outside, _ctx.handleClose, _ctx.popperPaneRef] ]); } script$2.render = render$2; script$2.__file = "packages/select/src/select.vue"; script$2.install = (app) => { app.component(script$2.name, script$2)