'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var vue = require('vue');
require('../../../utils/index.cjs');
var LegacyContext = require('../../vc-tree-select/src/LegacyContext.cjs');
var valueUtil = require('./utils/valueUtil.cjs');
var SelectTrigger = require('./SelectTrigger.cjs');
var index = require('./Selector/index.cjs');
var useSelectTriggerControl = require('./hooks/useSelectTriggerControl.cjs');
var useDelayReset = require('./hooks/useDelayReset.cjs');
var TransBtn = require('./TransBtn.cjs');
var useLock = require('./hooks/useLock.cjs');
var useBaseProps = require('./hooks/useBaseProps.cjs');
var vueTypes = require('../../../utils/vue/vueTypes.cjs');
var initDefaultProps = require('../../../utils/vue/initDefaultProps.cjs');
var is = require('../../../utils/is.cjs');
var createRef = require('../../../utils/vue/createRef.cjs');
var KeyCode = require('../../../utils/KeyCode.cjs');
var toReactive = require('../../../utils/vue/toReactive.cjs');
var _class = require('../../../utils/dom/class.cjs');
var vnode = require('../../../utils/vue/vnode.cjs');

const DEFAULT_OMIT_PROPS = ["value", "onChange", "removeIcon", "placeholder", "autofocus", "maxTagCount", "maxTagTextLength", "maxTagPlaceholder", "choiceTransitionName", "onInputKeyDown", "onPopupScroll", "tabindex", "OptionList", "notFoundContent"];
function baseSelectPrivateProps() {
  return {
    prefixCls: String,
    id: String,
    omitDomProps: Array,
    // >>> Value
    displayValues: Array,
    onDisplayValuesChange: Function,
    // >>> Active
    /** Current dropdown list active item string value */
    activeValue: String,
    /** Link search input with target element */
    activeDescendantId: String,
    onActiveValueChange: Function,
    // >>> Search
    searchValue: String,
    /** Trigger onSearch, return false to prevent trigger open event */
    onSearch: Function,
    /** Trigger when search text match the `tokenSeparators`. Will provide split content */
    onSearchSplit: Function,
    maxLength: Number,
    OptionList: vueTypes.default.any,
    /** Tell if provided `options` is empty */
    emptyOptions: Boolean
  };
}
function baseSelectPropsWithoutPrivate() {
  return {
    showSearch: {
      type: Boolean,
      default: void 0
    },
    tagRender: {
      type: Function
    },
    optionLabelRender: {
      type: Function
    },
    direction: {
      type: String
    },
    // MISC
    tabindex: Number,
    autofocus: Boolean,
    notFoundContent: vueTypes.default.any,
    placeholder: vueTypes.default.any,
    onClear: Function,
    choiceTransitionName: String,
    // >>> Mode
    mode: String,
    // >>> Status
    disabled: {
      type: Boolean,
      default: void 0
    },
    loading: {
      type: Boolean,
      default: void 0
    },
    // >>> Open
    open: {
      type: Boolean,
      default: void 0
    },
    defaultOpen: {
      type: Boolean,
      default: void 0
    },
    onDropdownVisibleChange: {
      type: Function
    },
    // >>> Customize Input
    /** @private Internal usage. Do not use in your production. */
    getInputElement: {
      type: Function
    },
    /** @private Internal usage. Do not use in your production. */
    getRawInputElement: {
      type: Function
    },
    // >>> Selector
    maxTagTextLength: Number,
    maxTagCount: {
      type: [String, Number]
    },
    maxTagPlaceholder: vueTypes.default.any,
    // >>> Search
    tokenSeparators: {
      type: Array
    },
    // >>> Icons
    allowClear: {
      type: Boolean,
      default: void 0
    },
    showArrow: {
      type: Boolean,
      default: void 0
    },
    inputIcon: vueTypes.default.any,
    /** Clear all icon */
    clearIcon: vueTypes.default.any,
    /** Selector remove icon */
    removeIcon: vueTypes.default.any,
    // >>> Dropdown
    animation: String,
    transitionName: String,
    dropdownStyle: {
      type: Object
    },
    dropdownClassName: String,
    dropdownMatchSelectWidth: {
      type: [Boolean, Number],
      default: void 0
    },
    dropdownRender: {
      type: Function
    },
    dropdownAlign: Object,
    placement: {
      type: String
    },
    getPopupContainer: {
      type: Function
    },
    // >>> Focus
    showAction: {
      type: Array
    },
    onBlur: {
      type: Function
    },
    onFocus: {
      type: Function
    },
    // >>> Rest Events
    onKeyup: Function,
    onKeydown: Function,
    onMousedown: Function,
    onPopupScroll: Function,
    onInputKeyDown: Function,
    onMouseenter: Function,
    onMouseleave: Function,
    onClick: Function
  };
}
function baseSelectProps() {
  return {
    ...baseSelectPrivateProps(),
    ...baseSelectPropsWithoutPrivate()
  };
}
function isMultiple(mode) {
  return mode === "tags" || mode === "multiple";
}
var BaseSelect = /* @__PURE__ */ vue.defineComponent({
  compatConfig: {
    MODE: 3
  },
  name: "BaseSelect",
  inheritAttrs: false,
  props: initDefaultProps.initDefaultProps(baseSelectProps(), {
    showAction: [],
    notFoundContent: "Not Found"
  }),
  setup(props, {
    attrs,
    expose,
    slots
  }) {
    const multiple = vue.computed(() => isMultiple(props.mode));
    const mergedShowSearch = vue.computed(() => props.showSearch !== void 0 ? props.showSearch : multiple.value || props.mode === "combobox");
    const mobile = vue.shallowRef(false);
    vue.onMounted(() => {
      mobile.value = is.isMobile();
    });
    const legacyTreeSelectContext = LegacyContext.default();
    const containerRef = vue.shallowRef(null);
    const selectorDomRef = createRef.createRef();
    const triggerRef = vue.shallowRef(null);
    const selectorRef = vue.shallowRef(null);
    const listRef = vue.shallowRef(null);
    const blurRef = vue.ref(false);
    const [mockFocused, setMockFocused, cancelSetMockFocused] = useDelayReset.default();
    const focus = () => {
      var _a;
      (_a = selectorRef.value) == null ? void 0 : _a.focus();
    };
    const blur = () => {
      var _a;
      (_a = selectorRef.value) == null ? void 0 : _a.blur();
    };
    expose({
      focus,
      blur,
      scrollTo: (arg) => {
        var _a;
        return (_a = listRef.value) == null ? void 0 : _a.scrollTo(arg);
      }
    });
    const mergedSearchValue = vue.computed(() => {
      var _a;
      if (props.mode !== "combobox")
        return props.searchValue;
      const val = (_a = props.displayValues[0]) == null ? void 0 : _a.value;
      return typeof val === "string" || typeof val === "number" ? String(val) : "";
    });
    const initOpen = props.open !== void 0 ? props.open : props.defaultOpen;
    const innerOpen = vue.shallowRef(initOpen);
    const mergedOpen = vue.shallowRef(initOpen);
    const setInnerOpen = (val) => {
      innerOpen.value = props.open !== void 0 ? props.open : val;
      mergedOpen.value = innerOpen.value;
    };
    vue.watch(() => props.open, () => {
      setInnerOpen(props.open);
    });
    const emptyListContent = vue.computed(() => !props.notFoundContent && props.emptyOptions);
    vue.watchEffect(() => {
      mergedOpen.value = innerOpen.value;
      if (props.disabled || emptyListContent.value && mergedOpen.value && props.mode === "combobox")
        mergedOpen.value = false;
    });
    const triggerOpen = vue.computed(() => emptyListContent.value ? false : mergedOpen.value);
    const onToggleOpen = (newOpen) => {
      const nextOpen = newOpen !== void 0 ? newOpen : !mergedOpen.value;
      if (mergedOpen.value !== nextOpen && !props.disabled) {
        setInnerOpen(nextOpen);
        props.onDropdownVisibleChange && props.onDropdownVisibleChange(nextOpen);
      }
    };
    const tokenWithEnter = vue.computed(() => (props.tokenSeparators || []).some((tokenSeparator) => ["\n", "\r\n"].includes(tokenSeparator)));
    const onInternalSearch = (searchText, fromTyping, isCompositing) => {
      var _a, _b;
      let ret = true;
      let newSearchText = searchText;
      (_a = props.onActiveValueChange) == null ? void 0 : _a.call(props, null);
      const patchLabels = isCompositing ? null : valueUtil.getSeparatedContent(searchText, props.tokenSeparators);
      if (props.mode !== "combobox" && patchLabels) {
        newSearchText = "";
        (_b = props.onSearchSplit) == null ? void 0 : _b.call(props, patchLabels);
        onToggleOpen(false);
        ret = false;
      }
      if (props.onSearch && mergedSearchValue.value !== newSearchText) {
        props.onSearch(newSearchText, {
          source: fromTyping ? "typing" : "effect"
        });
      }
      return ret;
    };
    const onInternalSearchSubmit = (searchText) => {
      var _a;
      if (!searchText || !searchText.trim())
        return;
      (_a = props.onSearch) == null ? void 0 : _a.call(props, searchText, {
        source: "submit"
      });
    };
    vue.watch(mergedOpen, () => {
      if (!mergedOpen.value && !multiple.value && props.mode !== "combobox")
        onInternalSearch("", false, false);
    }, {
      immediate: true,
      flush: "post"
    });
    vue.watch(() => props.disabled, () => {
      if (innerOpen.value && !!props.disabled)
        setInnerOpen(false);
      if (props.disabled && !blurRef.value)
        setMockFocused(false);
    }, {
      immediate: true
    });
    const [getClearLock, setClearLock] = useLock.default();
    const onInternalKeyDown = (event, ...rest) => {
      var _a;
      const clearLock = getClearLock();
      const {
        which
      } = event;
      if (which === KeyCode.KeyCode.ENTER) {
        if (props.mode !== "combobox")
          event.preventDefault();
        if (!mergedOpen.value)
          onToggleOpen(true);
      }
      setClearLock(!!mergedSearchValue.value);
      if (which === KeyCode.KeyCode.BACKSPACE && !clearLock && multiple.value && !mergedSearchValue.value && props.displayValues.length) {
        const cloneDisplayValues = [...props.displayValues];
        let removedDisplayValue = null;
        for (let i = cloneDisplayValues.length - 1; i >= 0; i -= 1) {
          const current = cloneDisplayValues[i];
          if (!current.disabled) {
            cloneDisplayValues.splice(i, 1);
            removedDisplayValue = current;
            break;
          }
        }
        if (removedDisplayValue) {
          props.onDisplayValuesChange(cloneDisplayValues, {
            type: "remove",
            values: [removedDisplayValue]
          });
        }
      }
      if (mergedOpen.value && listRef.value)
        listRef.value.onKeydown(event, ...rest);
      (_a = props.onKeydown) == null ? void 0 : _a.call(props, event, ...rest);
    };
    const onInternalKeyUp = (event, ...rest) => {
      if (mergedOpen.value && listRef.value)
        listRef.value.onKeyup(event, ...rest);
      if (props.onKeyup)
        props.onKeyup(event, ...rest);
    };
    const onSelectorRemove = (val) => {
      const newValues = props.displayValues.filter((i) => i !== val);
      props.onDisplayValuesChange(newValues, {
        type: "remove",
        values: [val]
      });
    };
    const focusRef = vue.shallowRef(false);
    const onContainerFocus = (...args) => {
      setMockFocused(true);
      if (!props.disabled) {
        if (props.onFocus && !focusRef.value)
          props.onFocus(...args);
        if (props.showAction && props.showAction.includes("focus"))
          onToggleOpen(true);
      }
      focusRef.value = true;
    };
    const popupFocused = vue.ref(false);
    const onContainerBlur = (...args) => {
      if (popupFocused.value)
        return;
      blurRef.value = true;
      setMockFocused(false, () => {
        focusRef.value = false;
        blurRef.value = false;
        onToggleOpen(false);
      });
      if (props.disabled)
        return;
      const searchVal = mergedSearchValue.value;
      if (searchVal) {
        if (props.mode === "tags") {
          props.onSearch(searchVal, {
            source: "submit"
          });
        } else if (props.mode === "multiple") {
          props.onSearch("", {
            source: "blur"
          });
        }
      }
      if (props.onBlur)
        props.onBlur(...args);
    };
    const onPopupFocusin = () => {
      popupFocused.value = true;
    };
    const onPopupFocusout = () => {
      popupFocused.value = false;
    };
    vue.provide("VCSelectContainerEvent", {
      focus: onContainerFocus,
      blur: onContainerBlur
    });
    const activeTimeoutIds = [];
    vue.onMounted(() => {
      activeTimeoutIds.forEach((timeoutId) => clearTimeout(timeoutId));
      activeTimeoutIds.splice(0, activeTimeoutIds.length);
    });
    vue.onBeforeUnmount(() => {
      activeTimeoutIds.forEach((timeoutId) => clearTimeout(timeoutId));
      activeTimeoutIds.splice(0, activeTimeoutIds.length);
    });
    const onInternalMouseDown = (event, ...restArgs) => {
      var _a, _b;
      const {
        target
      } = event;
      const popupElement = (_a = triggerRef.value) == null ? void 0 : _a.getPopupElement();
      if (popupElement && popupElement.contains(target)) {
        const timeoutId = setTimeout(() => {
          var _a2;
          const index = activeTimeoutIds.indexOf(timeoutId);
          if (index !== -1)
            activeTimeoutIds.splice(index, 1);
          cancelSetMockFocused();
          if (!mobile.value && !popupElement.contains(document.activeElement))
            (_a2 = selectorRef.value) == null ? void 0 : _a2.focus();
        });
        activeTimeoutIds.push(timeoutId);
      }
      (_b = props.onMousedown) == null ? void 0 : _b.call(props, event, ...restArgs);
    };
    const containerWidth = vue.shallowRef(null);
    const onPopupMouseEnter = () => {
    };
    vue.onMounted(() => {
      vue.watch(triggerOpen, () => {
        var _a;
        if (triggerOpen.value) {
          const newWidth = Math.ceil((_a = containerRef.value) == null ? void 0 : _a.offsetWidth);
          if (containerWidth.value !== newWidth && !Number.isNaN(newWidth))
            containerWidth.value = newWidth;
        }
      }, {
        immediate: true,
        flush: "post"
      });
    });
    useSelectTriggerControl.default([containerRef, triggerRef], triggerOpen, onToggleOpen);
    useBaseProps.useProvideBaseSelectProps(toReactive.toReactive({
      ...vue.toRefs(props),
      open: mergedOpen,
      triggerOpen,
      showSearch: mergedShowSearch,
      multiple,
      toggleOpen: onToggleOpen
    }));
    return () => {
      const {
        prefixCls,
        id,
        open,
        defaultOpen,
        mode,
        // Search related
        showSearch,
        searchValue,
        onSearch,
        // Icons
        allowClear,
        clearIcon,
        showArrow,
        inputIcon,
        // Others
        disabled,
        loading,
        getInputElement,
        getPopupContainer,
        placement,
        // Dropdown
        animation,
        transitionName,
        dropdownStyle,
        dropdownClassName,
        dropdownMatchSelectWidth,
        dropdownRender,
        dropdownAlign,
        showAction,
        direction,
        // Tags
        tokenSeparators,
        tagRender,
        optionLabelRender,
        // Events
        onPopupScroll,
        onDropdownVisibleChange,
        onFocus,
        onBlur,
        onKeyup,
        onKeydown,
        onMousedown,
        onClear,
        omitDomProps,
        getRawInputElement,
        displayValues,
        onDisplayValuesChange,
        emptyOptions,
        activeDescendantId,
        activeValue,
        OptionList,
        ...restProps
      } = {
        ...props,
        ...attrs
      };
      const customizeInputElement = mode === "combobox" && getInputElement && getInputElement() || null;
      const customizeRawInputElement = typeof getRawInputElement === "function" && getRawInputElement();
      const domProps = {
        ...restProps
      };
      let onTriggerVisibleChange;
      if (customizeRawInputElement) {
        onTriggerVisibleChange = (newOpen) => {
          onToggleOpen(newOpen);
        };
      }
      DEFAULT_OMIT_PROPS.forEach((propName) => {
        delete domProps[propName];
      });
      omitDomProps == null ? void 0 : omitDomProps.forEach((propName) => {
        delete domProps[propName];
      });
      const mergedShowArrow = showArrow !== void 0 ? showArrow : loading || !multiple.value && mode !== "combobox";
      let arrowNode;
      if (mergedShowArrow) {
        arrowNode = vue.createVNode(TransBtn.default, {
          "class": _class.classNames(`${prefixCls}-arrow`, {
            [`${prefixCls}-arrow-loading`]: loading
          }),
          "customizeIcon": inputIcon,
          "customizeIconProps": {
            loading,
            searchValue: mergedSearchValue.value,
            open: mergedOpen.value,
            focused: mockFocused.value,
            showSearch: mergedShowSearch.value
          }
        }, null);
      }
      let clearNode;
      const onClearMouseDown = () => {
        onClear == null ? void 0 : onClear();
        onDisplayValuesChange([], {
          type: "clear",
          values: displayValues
        });
        onInternalSearch("", false, false);
      };
      if (!disabled && allowClear && (displayValues.length || mergedSearchValue.value)) {
        clearNode = vue.createVNode(TransBtn.default, {
          "class": `${prefixCls}-clear`,
          "onMousedown": onClearMouseDown,
          "customizeIcon": clearIcon
        }, {
          default: () => [vue.createTextVNode("\xD7")]
        });
      }
      const optionList = vue.createVNode(OptionList, {
        "ref": listRef
      }, {
        ...legacyTreeSelectContext.customSlots,
        option: slots.option
      });
      const mergedClassName = _class.classNames(prefixCls, attrs.class, {
        [`${prefixCls}-focused`]: mockFocused.value,
        [`${prefixCls}-multiple`]: multiple.value,
        [`${prefixCls}-single`]: !multiple.value,
        [`${prefixCls}-allow-clear`]: allowClear,
        [`${prefixCls}-show-arrow`]: mergedShowArrow,
        [`${prefixCls}-disabled`]: disabled,
        [`${prefixCls}-loading`]: loading,
        [`${prefixCls}-open`]: mergedOpen.value,
        [`${prefixCls}-customize-input`]: customizeInputElement,
        [`${prefixCls}-show-search`]: mergedShowSearch.value
      });
      const selectorNode = vue.createVNode(SelectTrigger.default, {
        "ref": triggerRef,
        "disabled": disabled,
        "prefixCls": prefixCls,
        "visible": triggerOpen.value,
        "popupElement": optionList,
        "containerWidth": containerWidth.value,
        "animation": animation,
        "transitionName": transitionName,
        "dropdownStyle": dropdownStyle,
        "dropdownClassName": dropdownClassName,
        "direction": direction,
        "dropdownMatchSelectWidth": dropdownMatchSelectWidth,
        "dropdownRender": dropdownRender,
        "dropdownAlign": dropdownAlign,
        "placement": placement,
        "getPopupContainer": getPopupContainer,
        "empty": emptyOptions,
        "getTriggerDOMNode": () => selectorDomRef.current,
        "onPopupVisibleChange": onTriggerVisibleChange,
        "onPopupMouseEnter": onPopupMouseEnter,
        "onPopupFocusin": onPopupFocusin,
        "onPopupFocusout": onPopupFocusout
      }, {
        default: () => {
          return customizeRawInputElement ? is.isValidElement(customizeRawInputElement) && vnode.cloneElement(customizeRawInputElement, {
            ref: selectorDomRef
          }, false, true) : vue.createVNode(index.default, {
            ...props,
            "domRef": selectorDomRef,
            "prefixCls": prefixCls,
            "inputElement": customizeInputElement,
            "ref": selectorRef,
            "id": id,
            "showSearch": mergedShowSearch.value,
            "mode": mode,
            "activeDescendantId": activeDescendantId,
            "tagRender": tagRender,
            "optionLabelRender": optionLabelRender,
            "values": displayValues,
            "open": mergedOpen.value,
            "onToggleOpen": onToggleOpen,
            "activeValue": activeValue,
            "searchValue": mergedSearchValue.value,
            "onSearch": onInternalSearch,
            "onSearchSubmit": onInternalSearchSubmit,
            "onRemove": onSelectorRemove,
            "tokenWithEnter": tokenWithEnter.value
          }, null);
        }
      });
      let renderNode;
      if (customizeRawInputElement) {
        renderNode = selectorNode;
      } else {
        renderNode = vue.createVNode("div", {
          ...domProps,
          "class": mergedClassName,
          "ref": containerRef,
          "onMousedown": onInternalMouseDown,
          "onKeydown": onInternalKeyDown,
          "onKeyup": onInternalKeyUp
        }, [mockFocused.value && !mergedOpen.value && vue.createVNode("span", {
          "style": {
            width: 0,
            height: 0,
            position: "absolute",
            overflow: "hidden",
            opacity: 0
          },
          "aria-live": "polite"
        }, [`${displayValues.map(({
          label,
          value
        }) => ["number", "string"].includes(typeof label) ? label : value).join(", ")}`]), selectorNode, arrowNode, clearNode]);
      }
      return renderNode;
    };
  }
});

exports.baseSelectPropsWithoutPrivate = baseSelectPropsWithoutPrivate;
exports.default = BaseSelect;
exports.isMultiple = isMultiple;
//# sourceMappingURL=BaseSelect.cjs.map
