import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
var _excluded = ["prefixCls", "id", "open", "defaultOpen", "options", "children", "mode", "value", "defaultValue", "labelInValue", "showSearch", "inputValue", "searchValue", "filterOption", "optionFilterProp", "autoClearSearchValue", "onSearch", "allowClear", "clearIcon", "showArrow", "inputIcon", "menuItemSelectedIcon", "disabled", "loading", "defaultActiveFirstOption", "notFoundContent", "optionLabelProp", "backfill", "getInputElement", "getPopupContainer", "listHeight", "listItemHeight", "animation", "transitionName", "virtual", "dropdownStyle", "dropdownClassName", "dropdownMatchSelectWidth", "dropdownRender", "dropdownAlign", "showAction", "direction", "tokenSeparators", "tagRender", "onPopupScroll", "onDropdownVisibleChange", "onFocus", "onBlur", "onKeyup", "onKeydown", "onMousedown", "onChange", "onSelect", "onDeselect", "onClear", "internalProps"];
import { createTextVNode as _createTextVNode, createVNode as _createVNode, resolveDirective as _resolveDirective } from "vue";

/**
 * To match accessibility requirement, we always provide an input in the component.
 * Other element will not set `tabindex` to avoid `onBlur` sequence problem.
 * For focused select, we set `aria-live="polite"` to update the accessibility content.
 *
 * ref:
 * - keyboard: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/listbox_role#Keyboard_interactions
 */
import KeyCode from '../_util/KeyCode';
import classNames from '../_util/classNames';
import Selector from './Selector';
import SelectTrigger from './SelectTrigger';
import { INTERNAL_PROPS_MARK } from './interface/generator';
import { toInnerValue, toOuterValues, removeLastEnabledValue, getUUID } from './utils/commonUtil';
import TransBtn from './TransBtn';
import useLock from './hooks/useLock';
import useDelayReset from './hooks/useDelayReset';
import { getSeparatedContent } from './utils/valueUtil';
import useSelectTriggerControl from './hooks/useSelectTriggerControl';
import useCacheDisplayValue from './hooks/useCacheDisplayValue';
import useCacheOptions from './hooks/useCacheOptions';
import { getCurrentInstance, computed, defineComponent, onBeforeUnmount, onMounted, provide, ref, shallowRef, watch, watchEffect } from 'vue';
import createRef from '../_util/createRef';
import PropTypes from '../_util/vue-types';
import warning from '../_util/warning';
import isMobile from '../vc-util/isMobile';
var DEFAULT_OMIT_PROPS = ['children', 'removeIcon', 'placeholder', 'autofocus', 'maxTagCount', 'maxTagTextLength', 'maxTagPlaceholder', 'choiceTransitionName', 'onInputKeyDown', 'tabindex'];
export function selectBaseProps() {
  return {
    prefixCls: String,
    id: String,
    // Options
    options: {
      type: Array
    },
    mode: {
      type: String
    },
    // Value
    value: {
      type: [String, Number, Object, Array],
      default: undefined
    },
    defaultValue: {
      type: [String, Number, Object, Array],
      default: undefined
    },
    labelInValue: {
      type: Boolean,
      default: undefined
    },
    // Search
    inputValue: String,
    searchValue: String,
    optionFilterProp: String,

    /**
     * In Select, `false` means do nothing.
     * In TreeSelect, `false` will highlight match item.
     * It's by design.
     */
    filterOption: {
      type: [Boolean, Function],
      default: undefined
    },
    filterSort: {
      type: Function
    },
    showSearch: {
      type: Boolean,
      default: undefined
    },
    autoClearSearchValue: {
      type: Boolean,
      default: undefined
    },
    onSearch: {
      type: Function
    },
    onClear: {
      type: Function
    },
    // Icons
    allowClear: {
      type: Boolean,
      default: undefined
    },
    clearIcon: PropTypes.any,
    showArrow: {
      type: Boolean,
      default: undefined
    },
    inputIcon: PropTypes.VNodeChild,
    removeIcon: PropTypes.VNodeChild,
    menuItemSelectedIcon: PropTypes.VNodeChild,
    // Dropdown
    open: {
      type: Boolean,
      default: undefined
    },
    defaultOpen: {
      type: Boolean,
      default: undefined
    },
    listHeight: Number,
    listItemHeight: Number,
    dropdownStyle: {
      type: Object
    },
    dropdownClassName: String,
    dropdownMatchSelectWidth: {
      type: [Boolean, Number],
      default: undefined
    },
    virtual: {
      type: Boolean,
      default: undefined
    },
    dropdownRender: {
      type: Function
    },
    dropdownAlign: PropTypes.any,
    animation: String,
    transitionName: String,
    getPopupContainer: {
      type: Function
    },
    direction: String,
    // Others
    disabled: {
      type: Boolean,
      default: undefined
    },
    loading: {
      type: Boolean,
      default: undefined
    },
    autofocus: {
      type: Boolean,
      default: undefined
    },
    defaultActiveFirstOption: {
      type: Boolean,
      default: undefined
    },
    notFoundContent: PropTypes.any,
    placeholder: PropTypes.any,
    backfill: {
      type: Boolean,
      default: undefined
    },

    /** @private Internal usage. Do not use in your production. */
    getInputElement: {
      type: Function
    },
    optionLabelProp: String,
    maxTagTextLength: Number,
    maxTagCount: {
      type: [String, Number]
    },
    maxTagPlaceholder: PropTypes.any,
    tokenSeparators: {
      type: Array
    },
    tagRender: {
      type: Function
    },
    showAction: {
      type: Array
    },
    tabindex: {
      type: [Number, String]
    },
    // Events
    onKeyup: {
      type: Function
    },
    onKeydown: {
      type: Function
    },
    onPopupScroll: {
      type: Function
    },
    onDropdownVisibleChange: {
      type: Function
    },
    onSelect: {
      type: Function
    },
    onDeselect: {
      type: Function
    },
    onInputKeyDown: {
      type: Function
    },
    onClick: {
      type: Function
    },
    onChange: {
      type: Function
    },
    onBlur: {
      type: Function
    },
    onFocus: {
      type: Function
    },
    onMousedown: {
      type: Function
    },
    onMouseenter: {
      type: Function
    },
    onMouseleave: {
      type: Function
    },
    // Motion
    choiceTransitionName: String,
    // Internal props

    /**
     * Only used in current version for internal event process.
     * Do not use in production environment.
     */
    internalProps: {
      type: Object,
      default: undefined
    },
    children: {
      type: Array
    }
  };
}

var Helper = function Helper() {
  _classCallCheck(this, Helper);

  _defineProperty(this, "SelectBaseProps", selectBaseProps());
};

/**
 * This function is in internal usage.
 * Do not use it in your prod env since we may refactor this.
 */
export default function generateSelector(config) {
  var _ref = config,
      defaultPrefixCls = _ref.prefixCls,
      OptionList = _ref.components.optionList,
      convertChildrenToData = _ref.convertChildrenToData,
      flattenOptions = _ref.flattenOptions,
      getLabeledValue = _ref.getLabeledValue,
      filterOptions = _ref.filterOptions,
      isValueDisabled = _ref.isValueDisabled,
      findValueOption = _ref.findValueOption,
      warningProps = _ref.warningProps,
      fillOptionsWithMissingValue = _ref.fillOptionsWithMissingValue,
      omitDOMProps = _ref.omitDOMProps;
  var Select = defineComponent({
    name: 'Select',
    slots: ['option'],
    inheritAttrs: false,
    props: selectBaseProps(),
    setup: function setup(props, _ref2) {
      var expose = _ref2.expose,
          attrs = _ref2.attrs,
          slots = _ref2.slots;
      var useInternalProps = computed(function () {
        return props.internalProps && props.internalProps.mark === INTERNAL_PROPS_MARK;
      });
      warning(props.optionFilterProp !== 'children', 'Select', 'optionFilterProp not support children, please use label instead');
      var containerRef = ref();
      var triggerRef = ref();
      var selectorRef = ref();
      var listRef = ref();
      var tokenWithEnter = computed(function () {
        return (props.tokenSeparators || []).some(function (tokenSeparator) {
          return ['\n', '\r\n'].includes(tokenSeparator);
        });
      });
      /** Used for component focused management */

      var _useDelayReset = useDelayReset(),
          _useDelayReset2 = _slicedToArray(_useDelayReset, 3),
          mockFocused = _useDelayReset2[0],
          setMockFocused = _useDelayReset2[1],
          cancelSetMockFocused = _useDelayReset2[2];

      var mergedId = computed(function () {
        return props.id || "rc_select_".concat(getUUID());
      }); // optionLabelProp

      var mergedOptionLabelProp = computed(function () {
        var mergedOptionLabelProp = props.optionLabelProp;

        if (mergedOptionLabelProp === undefined) {
          mergedOptionLabelProp = props.options ? 'label' : 'children';
        }

        return mergedOptionLabelProp;
      }); // labelInValue

      var mergedLabelInValue = computed(function () {
        return props.mode === 'combobox' ? false : props.labelInValue;
      });
      var isMultiple = computed(function () {
        return props.mode === 'tags' || props.mode === 'multiple';
      });
      var mergedShowSearch = computed(function () {
        return props.showSearch !== undefined ? props.showSearch : isMultiple.value || props.mode === 'combobox';
      });
      var mobile = ref(false);
      onMounted(function () {
        mobile.value = isMobile();
      }); // ============================== Ref ===============================

      var selectorDomRef = createRef();
      var innerSearchValue = ref('');

      var setInnerSearchValue = function setInnerSearchValue(val) {
        innerSearchValue.value = val;
      };

      var mergedValue = ref(props.value !== undefined ? props.value : props.defaultValue);
      watch(function () {
        return props.value;
      }, function () {
        mergedValue.value = props.value;
        innerSearchValue.value = '';
      }); // ============================= Value ==============================

      /** Unique raw values */

      var mergedRawValueArr = computed(function () {
        return toInnerValue(mergedValue.value, {
          labelInValue: mergedLabelInValue.value,
          combobox: props.mode === 'combobox'
        });
      });
      var mergedRawValue = computed(function () {
        return mergedRawValueArr.value[0];
      });
      var mergedValueMap = computed(function () {
        return mergedRawValueArr.value[1];
      });
      /** We cache a set of raw values to speed up check */

      var rawValues = computed(function () {
        return new Set(mergedRawValue.value);
      }); // ============================= Option =============================
      // Set by option list active, it will merge into search input when mode is `combobox`

      var activeValue = ref();

      var setActiveValue = function setActiveValue(val) {
        activeValue.value = val;
      };

      var mergedSearchValue = computed(function () {
        var mergedSearchValue = innerSearchValue.value;

        if (props.mode === 'combobox' && mergedValue.value !== undefined) {
          mergedSearchValue = mergedValue.value;
        } else if (props.searchValue !== undefined) {
          mergedSearchValue = props.searchValue;
        } else if (props.inputValue) {
          mergedSearchValue = props.inputValue;
        }

        return mergedSearchValue;
      });
      var mergedOptions = computed(function () {
        var newOptions = props.options;

        if (newOptions === undefined) {
          newOptions = convertChildrenToData(props.children);
        }
        /**
         * `tags` should fill un-list item.
         * This is not cool here since TreeSelect do not need this
         */


        if (props.mode === 'tags' && fillOptionsWithMissingValue) {
          newOptions = fillOptionsWithMissingValue(newOptions, mergedValue.value, mergedOptionLabelProp.value, props.labelInValue);
        }

        return newOptions || [];
      });
      var mergedFlattenOptions = computed(function () {
        return flattenOptions(mergedOptions.value, props);
      });
      var getValueOption = useCacheOptions(mergedFlattenOptions); // Display options for OptionList

      var displayOptions = computed(function () {
        if (!mergedSearchValue.value || !mergedShowSearch.value) {
          return _toConsumableArray(mergedOptions.value);
        }

        var _props$optionFilterPr = props.optionFilterProp,
            optionFilterProp = _props$optionFilterPr === void 0 ? 'value' : _props$optionFilterPr,
            mode = props.mode,
            filterOption = props.filterOption;
        var filteredOptions = filterOptions(mergedSearchValue.value, mergedOptions.value, {
          optionFilterProp: optionFilterProp,
          filterOption: mode === 'combobox' && filterOption === undefined ? function () {
            return true;
          } : filterOption
        });

        if (mode === 'tags' && filteredOptions.every(function (opt) {
          return opt[optionFilterProp] !== mergedSearchValue.value;
        })) {
          filteredOptions.unshift({
            value: mergedSearchValue.value,
            label: mergedSearchValue.value,
            key: '__RC_SELECT_TAG_PLACEHOLDER__'
          });
        }

        if (props.filterSort && Array.isArray(filteredOptions)) {
          return _toConsumableArray(filteredOptions).sort(props.filterSort);
        }

        return filteredOptions;
      });
      var displayFlattenOptions = computed(function () {
        return flattenOptions(displayOptions.value, props);
      });
      onMounted(function () {
        watch(mergedSearchValue, function () {
          if (listRef.value && listRef.value.scrollTo) {
            listRef.value.scrollTo(0);
          }
        }, {
          flush: 'post',
          immediate: true
        });
      }); // ============================ Selector ============================

      var displayValues = computed(function () {
        var tmpValues = mergedRawValue.value.map(function (val) {
          var valueOptions = getValueOption([val]);
          var displayValue = getLabeledValue(val, {
            options: valueOptions,
            prevValueMap: mergedValueMap.value,
            labelInValue: mergedLabelInValue.value,
            optionLabelProp: mergedOptionLabelProp.value
          });
          return _objectSpread(_objectSpread({}, displayValue), {}, {
            disabled: isValueDisabled(val, valueOptions),
            option: valueOptions[0]
          });
        });

        if (!props.mode && tmpValues.length === 1 && tmpValues[0].value === null && tmpValues[0].label === null) {
          return [];
        }

        return tmpValues;
      }); // Polyfill with cache label

      displayValues = useCacheDisplayValue(displayValues);

      var triggerSelect = function triggerSelect(newValue, isSelect, source) {
        var newValueOption = getValueOption([newValue]);
        var outOption = findValueOption([newValue], newValueOption)[0];
        var _props$internalProps = props.internalProps,
            internalProps = _props$internalProps === void 0 ? {} : _props$internalProps;

        if (!internalProps.skipTriggerSelect) {
          // Skip trigger `onSelect` or `onDeselect` if configured
          var selectValue = mergedLabelInValue.value ? getLabeledValue(newValue, {
            options: newValueOption,
            prevValueMap: mergedValueMap.value,
            labelInValue: mergedLabelInValue.value,
            optionLabelProp: mergedOptionLabelProp.value
          }) : newValue;

          if (isSelect && props.onSelect) {
            props.onSelect(selectValue, outOption);
          } else if (!isSelect && props.onDeselect) {
            props.onDeselect(selectValue, outOption);
          }
        } // Trigger internal event


        if (useInternalProps.value) {
          if (isSelect && internalProps.onRawSelect) {
            internalProps.onRawSelect(newValue, outOption, source);
          } else if (!isSelect && internalProps.onRawDeselect) {
            internalProps.onRawDeselect(newValue, outOption, source);
          }
        }
      }; // We need cache options here in case user update the option list


      var prevValueOptions = shallowRef([]);

      var setPrevValueOptions = function setPrevValueOptions(val) {
        prevValueOptions.value = val;
      };

      var triggerChange = function triggerChange(newRawValues) {
        if (useInternalProps.value && props.internalProps && props.internalProps.skipTriggerChange) {
          return;
        }

        var newRawValuesOptions = getValueOption(newRawValues);
        var outValues = toOuterValues(Array.from(newRawValues), {
          labelInValue: mergedLabelInValue.value,
          options: newRawValuesOptions,
          getLabeledValue: getLabeledValue,
          prevValueMap: mergedValueMap.value,
          optionLabelProp: mergedOptionLabelProp.value
        });
        var outValue = isMultiple.value ? outValues : outValues[0]; // Skip trigger if prev & current value is both empty

        if (props.onChange && (mergedRawValue.value.length !== 0 || outValues.length !== 0)) {
          var outOptions = findValueOption(newRawValues, newRawValuesOptions, {
            prevValueOptions: prevValueOptions.value
          }); // We will cache option in case it removed by ajax

          setPrevValueOptions(outOptions.map(function (option, index) {
            var clone = _objectSpread({}, option);

            Object.defineProperty(clone, '_INTERNAL_OPTION_VALUE_', {
              get: function get() {
                return newRawValues[index];
              }
            });
            return clone;
          }));
          props.onChange(outValue, isMultiple.value ? outOptions : outOptions[0]);
        }

        if (props.value === undefined) {
          mergedValue.value = outValue;
        }
      };

      var onInternalSelect = function onInternalSelect(newValue, _ref3) {
        var selected = _ref3.selected,
            source = _ref3.source;
        var _props$autoClearSearc = props.autoClearSearchValue,
            autoClearSearchValue = _props$autoClearSearc === void 0 ? true : _props$autoClearSearc;

        if (props.disabled) {
          return;
        }

        var newRawValue;

        if (isMultiple.value) {
          newRawValue = new Set(mergedRawValue.value);

          if (selected) {
            newRawValue.add(newValue);
          } else {
            newRawValue.delete(newValue);
          }
        } else {
          newRawValue = new Set();
          newRawValue.add(newValue);
        } // Multiple always trigger change and single should change if value changed


        if (isMultiple.value || !isMultiple.value && Array.from(mergedRawValue.value)[0] !== newValue) {
          triggerChange(Array.from(newRawValue));
        } // Trigger `onSelect`. Single mode always trigger select


        triggerSelect(newValue, !isMultiple.value || selected, source); // Clean search value if single or configured

        if (props.mode === 'combobox') {
          setInnerSearchValue(String(newValue));
          setActiveValue('');
        } else if (!isMultiple.value || autoClearSearchValue) {
          setInnerSearchValue('');
          setActiveValue('');
        }
      };

      var onInternalOptionSelect = function onInternalOptionSelect(newValue, info) {
        onInternalSelect(newValue, _objectSpread(_objectSpread({}, info), {}, {
          source: 'option'
        }));
      };

      var onInternalSelectionSelect = function onInternalSelectionSelect(newValue, info) {
        onInternalSelect(newValue, _objectSpread(_objectSpread({}, info), {}, {
          source: 'selection'
        }));
      }; // ============================== Open ==============================


      var initOpen = props.open !== undefined ? props.open : props.defaultOpen;
      var innerOpen = ref(initOpen);
      var mergedOpen = ref(initOpen);

      var setInnerOpen = function setInnerOpen(val) {
        innerOpen.value = props.open !== undefined ? props.open : val;
        mergedOpen.value = innerOpen.value;
      };

      watch(function () {
        return props.open;
      }, function () {
        setInnerOpen(props.open);
      }); // Not trigger `open` in `combobox` when `notFoundContent` is empty

      var emptyListContent = computed(function () {
        return !props.notFoundContent && !displayOptions.value.length;
      });
      watchEffect(function () {
        mergedOpen.value = innerOpen.value;

        if (props.disabled || emptyListContent.value && mergedOpen.value && props.mode === 'combobox') {
          mergedOpen.value = false;
        }
      });
      var triggerOpen = computed(function () {
        return emptyListContent.value ? false : mergedOpen.value;
      });

      var onToggleOpen = function onToggleOpen(newOpen) {
        var nextOpen = newOpen !== undefined ? newOpen : !mergedOpen.value;

        if (innerOpen.value !== nextOpen && !props.disabled) {
          setInnerOpen(nextOpen);

          if (props.onDropdownVisibleChange) {
            props.onDropdownVisibleChange(nextOpen);
          }
        }
      };

      useSelectTriggerControl([containerRef, triggerRef], triggerOpen, onToggleOpen); // ============================= Search =============================

      var triggerSearch = function triggerSearch(searchText, fromTyping, isCompositing) {
        var ret = true;
        var newSearchText = searchText;
        var preSearchValue = mergedSearchValue.value;
        setActiveValue(null); // Check if match the `tokenSeparators`

        var patchLabels = isCompositing ? null : getSeparatedContent(searchText, props.tokenSeparators);
        var patchRawValues = patchLabels;

        if (props.mode === 'combobox') {
          // Only typing will trigger onChange
          if (fromTyping) {
            triggerChange([newSearchText]);
          }
        } else if (patchLabels) {
          newSearchText = '';

          if (props.mode !== 'tags') {
            patchRawValues = patchLabels.map(function (label) {
              var item = mergedFlattenOptions.value.find(function (_ref4) {
                var data = _ref4.data;
                return data[mergedOptionLabelProp.value] === label;
              });
              return item ? item.data.value : null;
            }).filter(function (val) {
              return val !== null;
            });
          }

          var newRawValues = Array.from(new Set([].concat(_toConsumableArray(mergedRawValue.value), _toConsumableArray(patchRawValues))));
          triggerChange(newRawValues);
          newRawValues.forEach(function (newRawValue) {
            triggerSelect(newRawValue, true, 'input');
          }); // Should close when paste finish

          onToggleOpen(false); // Tell Selector that break next actions

          ret = false;
        }

        setInnerSearchValue(newSearchText);

        if (props.onSearch && preSearchValue !== newSearchText) {
          props.onSearch(newSearchText);
        }

        return ret;
      }; // Only triggered when menu is closed & mode is tags
      // If menu is open, OptionList will take charge
      // If mode isn't tags, press enter is not meaningful when you can't see any option


      var onSearchSubmit = function onSearchSubmit(searchText) {
        // prevent empty tags from appearing when you click the Enter button
        if (!searchText || !searchText.trim()) {
          return;
        }

        var newRawValues = Array.from(new Set([].concat(_toConsumableArray(mergedRawValue.value), [searchText])));
        triggerChange(newRawValues);
        newRawValues.forEach(function (newRawValue) {
          triggerSelect(newRawValue, true, 'input');
        });
        setInnerSearchValue('');
      }; // Close dropdown when disabled change


      watch(function () {
        return props.disabled;
      }, function () {
        if (innerOpen.value && !!props.disabled) {
          setInnerOpen(false);
        }
      }, {
        immediate: true
      }); // Close will clean up single mode search text

      watch(mergedOpen, function () {
        if (!mergedOpen.value && !isMultiple.value && props.mode !== 'combobox') {
          triggerSearch('', false, false);
        }
      }, {
        immediate: true
      }); // ============================ Keyboard ============================

      /**
       * We record input value here to check if can press to clean up by backspace
       * - null: Key is not down, this is reset by key up
       * - true: Search text is empty when first time backspace down
       * - false: Search text is not empty when first time backspace down
       */

      var _useLock = useLock(),
          _useLock2 = _slicedToArray(_useLock, 2),
          getClearLock = _useLock2[0],
          setClearLock = _useLock2[1]; // KeyDown


      var onInternalKeyDown = function onInternalKeyDown(event) {
        var clearLock = getClearLock();
        var which = event.which;

        if (which === KeyCode.ENTER) {
          // Do not submit form when type in the input
          if (props.mode !== 'combobox') {
            event.preventDefault();
          } // We only manage open state here, close logic should handle by list component


          if (!mergedOpen.value) {
            onToggleOpen(true);
          }
        }

        setClearLock(!!mergedSearchValue.value); // Remove value by `backspace`

        if (which === KeyCode.BACKSPACE && !clearLock && isMultiple.value && !mergedSearchValue.value && mergedRawValue.value.length) {
          var removeInfo = removeLastEnabledValue(displayValues.value, mergedRawValue.value);

          if (removeInfo.removedValue !== null) {
            triggerChange(removeInfo.values);
            triggerSelect(removeInfo.removedValue, false, 'input');
          }
        }

        if (mergedOpen.value && listRef.value) {
          listRef.value.onKeydown(event);
        }

        if (props.onKeydown) {
          props.onKeydown(event);
        }
      }; // KeyUp


      var onInternalKeyUp = function onInternalKeyUp(event) {
        if (mergedOpen.value && listRef.value) {
          listRef.value.onKeyup(event);
        }

        if (props.onKeyup) {
          props.onKeyup(event);
        }
      }; // ========================== Focus / Blur ==========================

      /** Record real focus status */


      var focusRef = ref(false);

      var onContainerFocus = function onContainerFocus() {
        setMockFocused(true);

        if (!props.disabled) {
          if (props.onFocus && !focusRef.value) {
            props.onFocus(arguments.length <= 0 ? undefined : arguments[0]);
          } // `showAction` should handle `focus` if set


          if (props.showAction && props.showAction.includes('focus')) {
            onToggleOpen(true);
          }
        }

        focusRef.value = true;
      };

      var onContainerBlur = function onContainerBlur() {
        setMockFocused(false, function () {
          focusRef.value = false;
          onToggleOpen(false);
        });

        if (props.disabled) {
          return;
        }

        var searchVal = mergedSearchValue.value;

        if (searchVal) {
          // `tags` mode should move `searchValue` into values
          if (props.mode === 'tags') {
            triggerSearch('', false, false);
            triggerChange(Array.from(new Set([].concat(_toConsumableArray(mergedRawValue.value), [searchVal]))));
          } else if (props.mode === 'multiple') {
            // `multiple` mode only clean the search value but not trigger event
            setInnerSearchValue('');
          }
        }

        if (props.onBlur) {
          props.onBlur(arguments.length <= 0 ? undefined : arguments[0]);
        }
      };

      provide('VCSelectContainerEvent', {
        focus: onContainerFocus,
        blur: onContainerBlur
      });
      var activeTimeoutIds = [];
      onMounted(function () {
        activeTimeoutIds.forEach(function (timeoutId) {
          return window.clearTimeout(timeoutId);
        });
        activeTimeoutIds.splice(0, activeTimeoutIds.length);
      });
      onBeforeUnmount(function () {
        activeTimeoutIds.forEach(function (timeoutId) {
          return window.clearTimeout(timeoutId);
        });
        activeTimeoutIds.splice(0, activeTimeoutIds.length);
      });

      var onInternalMouseDown = function onInternalMouseDown(event) {
        var target = event.target;
        var popupElement = triggerRef.value && triggerRef.value.getPopupElement(); // We should give focus back to selector if clicked item is not focusable

        if (popupElement && popupElement.contains(target)) {
          var timeoutId = window.setTimeout(function () {
            var index = activeTimeoutIds.indexOf(timeoutId);

            if (index !== -1) {
              activeTimeoutIds.splice(index, 1);
            }

            cancelSetMockFocused();

            if (!mobile.value && !popupElement.contains(document.activeElement)) {
              selectorRef.value.focus();
            }
          });
          activeTimeoutIds.push(timeoutId);
        }

        if (props.onMousedown) {
          props.onMousedown(event);
        }
      }; // ========================= Accessibility ==========================


      var accessibilityIndex = ref(0);
      var mergedDefaultActiveFirstOption = computed(function () {
        return props.defaultActiveFirstOption !== undefined ? props.defaultActiveFirstOption : props.mode !== 'combobox';
      });

      var onActiveValue = function onActiveValue(active, index) {
        var _ref5 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
            _ref5$source = _ref5.source,
            source = _ref5$source === void 0 ? 'keyboard' : _ref5$source;

        accessibilityIndex.value = index;

        if (props.backfill && props.mode === 'combobox' && active !== null && source === 'keyboard') {
          setActiveValue(String(active));
        }
      }; // ============================= Popup ==============================


      var containerWidth = ref(null);
      onMounted(function () {
        watch(triggerOpen, function () {
          if (triggerOpen.value) {
            var newWidth = Math.ceil(containerRef.value.offsetWidth);

            if (containerWidth.value !== newWidth) {
              containerWidth.value = newWidth;
            }
          }
        }, {
          immediate: true
        });
      });

      var focus = function focus() {
        selectorRef.value.focus();
      };

      var blur = function blur() {
        selectorRef.value.blur();
      };

      expose({
        focus: focus,
        blur: blur,
        scrollTo: function scrollTo() {
          var _listRef$value;

          for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
            args[_key] = arguments[_key];
          }

          return (_listRef$value = listRef.value) === null || _listRef$value === void 0 ? void 0 : _listRef$value.scrollTo.apply(_listRef$value, args);
        }
      });
      var instance = getCurrentInstance();

      var onPopupMouseEnter = function onPopupMouseEnter() {
        // We need force update here since popup dom is render async
        instance.update();
      };

      return function () {
        var _classNames2;

        var _props$attrs = _objectSpread(_objectSpread({}, props), attrs),
            _props$attrs$prefixCl = _props$attrs.prefixCls,
            prefixCls = _props$attrs$prefixCl === void 0 ? defaultPrefixCls : _props$attrs$prefixCl,
            id = _props$attrs.id,
            open = _props$attrs.open,
            defaultOpen = _props$attrs.defaultOpen,
            options = _props$attrs.options,
            children = _props$attrs.children,
            mode = _props$attrs.mode,
            value = _props$attrs.value,
            defaultValue = _props$attrs.defaultValue,
            labelInValue = _props$attrs.labelInValue,
            showSearch = _props$attrs.showSearch,
            inputValue = _props$attrs.inputValue,
            searchValue = _props$attrs.searchValue,
            filterOption = _props$attrs.filterOption,
            optionFilterProp = _props$attrs.optionFilterProp,
            autoClearSearchValue = _props$attrs.autoClearSearchValue,
            onSearch = _props$attrs.onSearch,
            allowClear = _props$attrs.allowClear,
            clearIcon = _props$attrs.clearIcon,
            showArrow = _props$attrs.showArrow,
            inputIcon = _props$attrs.inputIcon,
            menuItemSelectedIcon = _props$attrs.menuItemSelectedIcon,
            disabled = _props$attrs.disabled,
            loading = _props$attrs.loading,
            defaultActiveFirstOption = _props$attrs.defaultActiveFirstOption,
            _props$attrs$notFound = _props$attrs.notFoundContent,
            notFoundContent = _props$attrs$notFound === void 0 ? 'Not Found' : _props$attrs$notFound,
            optionLabelProp = _props$attrs.optionLabelProp,
            backfill = _props$attrs.backfill,
            getInputElement = _props$attrs.getInputElement,
            getPopupContainer = _props$attrs.getPopupContainer,
            _props$attrs$listHeig = _props$attrs.listHeight,
            listHeight = _props$attrs$listHeig === void 0 ? 200 : _props$attrs$listHeig,
            _props$attrs$listItem = _props$attrs.listItemHeight,
            listItemHeight = _props$attrs$listItem === void 0 ? 20 : _props$attrs$listItem,
            animation = _props$attrs.animation,
            transitionName = _props$attrs.transitionName,
            virtual = _props$attrs.virtual,
            dropdownStyle = _props$attrs.dropdownStyle,
            dropdownClassName = _props$attrs.dropdownClassName,
            dropdownMatchSelectWidth = _props$attrs.dropdownMatchSelectWidth,
            dropdownRender = _props$attrs.dropdownRender,
            dropdownAlign = _props$attrs.dropdownAlign,
            showAction = _props$attrs.showAction,
            direction = _props$attrs.direction,
            tokenSeparators = _props$attrs.tokenSeparators,
            tagRender = _props$attrs.tagRender,
            onPopupScroll = _props$attrs.onPopupScroll,
            onDropdownVisibleChange = _props$attrs.onDropdownVisibleChange,
            onFocus = _props$attrs.onFocus,
            onBlur = _props$attrs.onBlur,
            onKeyup = _props$attrs.onKeyup,
            onKeydown = _props$attrs.onKeydown,
            onMousedown = _props$attrs.onMousedown,
            onChange = _props$attrs.onChange,
            onSelect = _props$attrs.onSelect,
            onDeselect = _props$attrs.onDeselect,
            onClear = _props$attrs.onClear,
            _props$attrs$internal = _props$attrs.internalProps,
            internalProps = _props$attrs$internal === void 0 ? {} : _props$attrs$internal,
            restProps = _objectWithoutProperties(_props$attrs, _excluded); //as SelectProps<OptionType[], ValueType>;
        // ============================= Input ==============================
        // Only works in `combobox`


        var customizeInputElement = mode === 'combobox' && getInputElement && getInputElement() || null;
        var domProps = omitDOMProps ? omitDOMProps(restProps) : restProps;
        DEFAULT_OMIT_PROPS.forEach(function (prop) {
          delete domProps[prop];
        });

        var popupNode = _createVNode(OptionList, {
          "ref": listRef,
          "prefixCls": prefixCls,
          "id": mergedId.value,
          "open": mergedOpen.value,
          "childrenAsData": !options,
          "options": displayOptions.value,
          "flattenOptions": displayFlattenOptions.value,
          "multiple": isMultiple.value,
          "values": rawValues.value,
          "height": listHeight,
          "itemHeight": listItemHeight,
          "onSelect": onInternalOptionSelect,
          "onToggleOpen": onToggleOpen,
          "onActiveValue": onActiveValue,
          "defaultActiveFirstOption": mergedDefaultActiveFirstOption.value,
          "notFoundContent": notFoundContent,
          "onScroll": onPopupScroll,
          "searchValue": mergedSearchValue.value,
          "menuItemSelectedIcon": menuItemSelectedIcon,
          "virtual": virtual !== false && dropdownMatchSelectWidth !== false,
          "onMouseenter": onPopupMouseEnter
        }, slots); // ============================= Clear ==============================


        var clearNode;

        var onClearMouseDown = function onClearMouseDown() {
          // Trigger internal `onClear` event
          if (useInternalProps.value && internalProps.onClear) {
            internalProps.onClear();
          }

          if (onClear) {
            onClear();
          }

          triggerChange([]);
          triggerSearch('', false, false);
        };

        if (!disabled && allowClear && (mergedRawValue.value.length || mergedSearchValue.value)) {
          clearNode = _createVNode(TransBtn, {
            "class": "".concat(prefixCls, "-clear"),
            "onMousedown": onClearMouseDown,
            "customizeIcon": clearIcon
          }, {
            default: function _default() {
              return [_createTextVNode("\xD7")];
            }
          });
        } // ============================= Arrow ==============================


        var mergedShowArrow = showArrow !== undefined ? showArrow : loading || !isMultiple.value && mode !== 'combobox';
        var arrowNode;

        if (mergedShowArrow) {
          arrowNode = _createVNode(TransBtn, {
            "class": classNames("".concat(prefixCls, "-arrow"), _defineProperty({}, "".concat(prefixCls, "-arrow-loading"), loading)),
            "customizeIcon": inputIcon,
            "customizeIconProps": {
              loading: loading,
              searchValue: mergedSearchValue.value,
              open: mergedOpen.value,
              focused: mockFocused.value,
              showSearch: mergedShowSearch.value
            }
          }, null);
        } // ============================ Warning =============================


        if (process.env.NODE_ENV !== 'production' && warningProps) {
          warningProps(props);
        } // ============================= Render =============================


        var mergedClassName = classNames(prefixCls, attrs.class, (_classNames2 = {}, _defineProperty(_classNames2, "".concat(prefixCls, "-focused"), mockFocused.value), _defineProperty(_classNames2, "".concat(prefixCls, "-multiple"), isMultiple.value), _defineProperty(_classNames2, "".concat(prefixCls, "-single"), !isMultiple.value), _defineProperty(_classNames2, "".concat(prefixCls, "-allow-clear"), allowClear), _defineProperty(_classNames2, "".concat(prefixCls, "-show-arrow"), mergedShowArrow), _defineProperty(_classNames2, "".concat(prefixCls, "-disabled"), disabled), _defineProperty(_classNames2, "".concat(prefixCls, "-loading"), loading), _defineProperty(_classNames2, "".concat(prefixCls, "-open"), mergedOpen.value), _defineProperty(_classNames2, "".concat(prefixCls, "-customize-input"), customizeInputElement), _defineProperty(_classNames2, "".concat(prefixCls, "-show-search"), mergedShowSearch.value), _classNames2));
        return _createVNode("div", _objectSpread(_objectSpread({}, domProps), {}, {
          "class": mergedClassName,
          "ref": containerRef,
          "onMousedown": onInternalMouseDown,
          "onKeydown": onInternalKeyDown,
          "onKeyup": onInternalKeyUp
        }), [mockFocused.value && !mergedOpen.value && _createVNode("span", {
          "style": {
            width: 0,
            height: 0,
            display: 'flex',
            overflow: 'hidden',
            opacity: 0
          },
          "aria-live": "polite"
        }, ["".concat(mergedRawValue.value.join(', '))]), _createVNode(SelectTrigger, {
          "ref": triggerRef,
          "disabled": disabled,
          "prefixCls": prefixCls,
          "visible": triggerOpen.value,
          "popupElement": popupNode,
          "containerWidth": containerWidth.value,
          "animation": animation,
          "transitionName": transitionName,
          "dropdownStyle": dropdownStyle,
          "dropdownClassName": dropdownClassName,
          "direction": direction,
          "dropdownMatchSelectWidth": dropdownMatchSelectWidth,
          "dropdownRender": dropdownRender,
          "dropdownAlign": dropdownAlign,
          "getPopupContainer": getPopupContainer,
          "empty": !mergedOptions.value.length,
          "getTriggerDOMNode": function getTriggerDOMNode() {
            return selectorDomRef.current;
          }
        }, {
          default: function _default() {
            return [_createVNode(Selector, _objectSpread(_objectSpread({}, props), {}, {
              "domRef": selectorDomRef,
              "prefixCls": prefixCls,
              "inputElement": customizeInputElement,
              "ref": selectorRef,
              "id": mergedId.value,
              "showSearch": mergedShowSearch.value,
              "mode": mode,
              "accessibilityIndex": accessibilityIndex.value,
              "multiple": isMultiple.value,
              "tagRender": tagRender,
              "values": displayValues.value,
              "open": mergedOpen.value,
              "onToggleOpen": onToggleOpen,
              "searchValue": mergedSearchValue.value,
              "activeValue": activeValue.value,
              "onSearch": triggerSearch,
              "onSearchSubmit": onSearchSubmit,
              "onSelect": onInternalSelectionSelect,
              "tokenWithEnter": tokenWithEnter.value
            }), null)];
          }
        }), arrowNode, clearNode]);
      };
    }
  });
  return Select;
}