/**
 * ldesign v0.2.14
 * (c) 2022/11/2 16:16 built by swimly
 * @license MIT
 */

import { h as helper } from '../../chunks/helper.js';
import { defineComponent, getCurrentInstance, ref, toRefs, computed, nextTick, watch, provide } from '@vue/composition-api';
import isFunction from 'lodash/isFunction';
import debounce from 'lodash/debounce';
import get from 'lodash/get';
import cloneDeep from 'lodash/cloneDeep';
import isArray from 'lodash/isArray';
import isObject from 'lodash/isObject';
import '../../chunks/index.js';
import useDefaultValue from '../../hooks/use-default-value.js';
import useVModel from '../../hooks/use-vmodel.js';
import { useLNodeJSX } from '../../hooks/lnode.js';
import { useConfig, usePrefixClass } from '../config-provider/useConfig.js';
import { Loading } from '../loading/index.js';
import { Popup } from '../popup/index.js';
import { Input } from '../input/index.js';
import { Tag } from '../tag/index.js';
import { SelectInput } from '../select-input/index.js';
import FakeArrow from '../common/fake-arrow.js';
import { on, off } from '../../utils/dom.js';
import useFormDisabled from '../../hooks/use-form-disabled.js';
import _Option from './option.js';
import SelectPanel from './select-panel.js';
import { getSingleContent, getMultipleContent, getNewMultipleValue } from './utils.js';
import useSelectOptions from './hooks/use-select-options.js';
import { SelectProps } from './props.js';
import { l as log } from '../../chunks/log.js';
import '../../chunks/_commonjsHelpers.js';
import '../../chunks/_commonjsHelpers-2e6815bd.js';
import 'lodash/kebabCase';
import 'lodash/isEmpty';
import 'lodash/camelCase';
import '../../hooks/render-lnode.js';
import 'lodash';
import '../config-provider/context.js';
import '../../chunks/zh_CN.js';
import '../config-provider/type.js';
import '../../utils/with-install.js';
import 'vue';
import '../../config.js';
import '../loading/loading.js';
import '../../utils/render-node.js';
import '../../utils/transfer-dom.js';
import '../config-provider/config-receiver.js';
import 'lodash/mergeWith';
import '../../utils/mixins.js';
import '../loading/props.js';
import '../loading/icon/gradient.js';
import '../../chunks/defineProperty-838e4192.js';
import '../../chunks/set-style.js';
import '../../chunks/helper2.js';
import 'raf';
import 'lodash/isString';
import '../../utils/easing.js';
import '../loading/style/css.js';
import '../loading/type.js';
import '../loading/plugin.js';
import '../../utils/map-props.js';
import '../popup/popup.js';
import '@popperjs/core';
import '../../utils/helper.js';
import '../popup/props.js';
import '../popup/container.js';
import '../popup/style/css.js';
import '../popup/type.js';
import '../input/input.js';
import '@ldesign/icons-vue';
import '../../utils/event.js';
import '../input/props.js';
import '../input/group.js';
import '../input/style/css.js';
import '../input/type.js';
import '../tag/tag.js';
import '../tag/props.js';
import '../tag/check-tag.js';
import '../tag/style/css.js';
import '../tag/type.js';
import '../select-input/select-input.js';
import '../select-input/props.js';
import '../select-input/hooks/use-single.js';
import 'lodash/pick';
import '../../hooks/use-config.js';
import '../select-input/hooks/use-multiple.js';
import '../tag-input/index.js';
import '../tag-input/tag-input.js';
import '../../hooks/use-global-icon.js';
import '../tag-input/props.js';
import '../tag-input/hooks/use-tag-scroll.js';
import '../tag-input/hooks/use-tag-list.js';
import '../tag-input/hooks/use-hover.js';
import '../tag-input/hooks/use-drag-sorter.js';
import '../tag-input/style/css.js';
import '../tag-input/type.js';
import '../select-input/hooks/use-overlay-innerstyle.js';
import '../select-input/style/css.js';
import '../select-input/type.js';
import '../../utils/ripple.js';
import '../checkbox/index.js';
import '../checkbox/group.js';
import 'lodash/intersection';
import '../checkbox/checkbox.js';
import '../checkbox/props.js';
import '../checkbox/style/css.js';
import '../checkbox/type.js';
import '../../hooks/use-lazy-load.js';
import '../../chunks/observe.js';
import '../../hooks/use-common-classname.js';
import '../../hooks/use-virtual-scroll.js';

var TSelect = defineComponent({
  name: "LSelect",
  components: {
    TInput: Input,
    TLoading: Loading,
    Tag,
    Popup,
    TOption: _Option,
    FakeArrow,
    SelectPanel
  },
  props: {
    ...SelectProps
  },
  setup(props2, context) {
    const {
      t,
      global
    } = useConfig("select");
    const renderTNode = useLNodeJSX();
    const instance = getCurrentInstance();
    const selectInputRef = ref(null);
    const selectPanelRef = ref();
    const popupOpenTime = ref(250);
    const {
      formDisabled
    } = useFormDisabled();
    const COMPONENT_NAME = usePrefixClass("select");
    const {
      classPrefix
    } = useConfig("classPrefix");
    const {
      valueType,
      disabled,
      size,
      value: valueProps,
      multiple,
      placeholder,
      loading,
      max,
      reserveKeyword,
      inputValue,
      popupVisible,
      minCollapsedNum,
      creatable
    } = toRefs(props2);
    const keys = computed(() => {
      var _props2$keys, _props2$keys2;
      return {
        label: ((_props2$keys = props2.keys) === null || _props2$keys === void 0 ? void 0 : _props2$keys.label) || "label",
        value: ((_props2$keys2 = props2.keys) === null || _props2$keys2 === void 0 ? void 0 : _props2$keys2.value) || "value"
      };
    });
    const {
      options: innerOptions,
      optionsMap,
      optionsList
    } = useSelectOptions(props2, instance, keys);
    const [value, setValue] = useVModel(valueProps, props2.defaultValue, props2.onChange, "change");
    const innerValue = computed(() => {
      const isObjValue = valueType.value === "object";
      let _value = value.value;
      if (!multiple.value && isArray(_value)) {
        log.warn("Select", 'Invalid value for "value" props: got an Array when multiple was set to false');
        _value = isObjValue ? {} : "";
      }
      if (multiple.value && !isArray(_value)) {
        log.warn("Select", 'Invalid value for "value" props: expected an Array when multiple was set to true');
        _value = [];
      }
      if (isObjValue) {
        if (multiple.value) {
          return _value.filter(option => {
            const isObj2 = isObject(option);
            if (!isObj2) log.warn("Select", `Invalid value for "value" props: expected an Object, but got ${typeof option}`);
            return isObj2;
          }).map(option => option[keys.value.value]);
        }
        const isObj = isObject(_value);
        if (!isObj) {
          log.warn("Select", `Invalid value for "value" props: expected an Object, but got ${typeof _value}`);
          return "";
        }
        return _value[keys.value.value];
      }
      return _value;
    });
    const setInnerValue = (newVal, context2, optionValue) => {
      if (newVal === value.value) return;
      const selectedOptions = [];
      const {
        value: valueOfKeys,
        label: labelOfKeys
      } = keys.value;
      const oldValueMap = /* @__PURE__ */new Map();
      if (multiple.value) {
        value.value.forEach(option => {
          oldValueMap.set(option[valueOfKeys], option);
        });
      }
      const getOriginOptions = val => {
        const option = optionsMap.value.get(val);
        if (option) delete option.index;
        return option;
      };
      const getFormatOption = val => {
        const option = optionsMap.value.get(val) || oldValueMap.get(val);
        if (option) delete option.index;
        return {
          [valueOfKeys]: get(option, valueOfKeys),
          [labelOfKeys]: get(option, labelOfKeys)
        };
      };
      if (multiple.value) newVal.forEach(v => selectedOptions.push(getOriginOptions(v)));else selectedOptions.push(getOriginOptions(newVal));
      if (valueType.value === "object") {
        newVal = multiple.value ? newVal.map(val => getFormatOption(val)) : getFormatOption(newVal);
      }
      const outputContext = {
        ...context2,
        selectedOptions
      };
      if (optionValue) {
        outputContext["option"] = getOriginOptions(optionValue);
      }
      setValue(newVal, outputContext);
    };
    const [tInputValue, setTInputValue] = useDefaultValue(inputValue, props2.defaultInputValue || "", props2.onInputChange, "inputValue", "input-change");
    const [innerPopupVisible, setInnerPopupVisible] = useDefaultValue(popupVisible, props2.defaultPopupVisible, (visible, context2) => {
      var _props2$onPopupVisibl;
      (_props2$onPopupVisibl = props2.onPopupVisibleChange) === null || _props2$onPopupVisibl === void 0 ? void 0 : _props2$onPopupVisibl.call(props2, visible, context2);
      instance.emit("visible-change", visible);
    }, "popupVisible", "popup-visible-change");
    const isDisabled = computed(() => formDisabled.value || disabled.value);
    const isLoading = computed(() => loading.value && !isDisabled.value);
    const isFilterable = computed(() => Boolean(props2.filterable || global.value.filterable || isFunction(props2.filter)));
    const isReachMaxLimit = computed(() => multiple.value && max.value !== 0 && max.value <= innerValue.value.length);
    const placeholderText = computed(() => {
      var _value$value;
      return (!multiple.value && innerPopupVisible.value && (valueType.value === "object" && (((_value$value = value.value) === null || _value$value === void 0 ? void 0 : _value$value[keys.value.label]) || innerValue.value) || getSingleContent(innerValue.value, optionsList.value)) || placeholder.value) ?? t(global.value.placeholder);
    });
    const displayText = computed(() => {
      var _value$value2;
      if (multiple.value) {
        if (valueType.value === "object") return value.value.map(v => v[keys.value.label]);
        return getMultipleContent(innerValue.value, optionsList.value);
      }
      if (valueType.value === "object") return ((_value$value2 = value.value) === null || _value$value2 === void 0 ? void 0 : _value$value2[keys.value.label]) || innerValue.value;
      return getSingleContent(innerValue.value, optionsList.value);
    });
    const valueDisplayParams = computed(() => {
      const val = multiple.value ? innerValue.value.map(value2 => {
        var _optionsMap$value$get;
        return {
          value: value2,
          label: (_optionsMap$value$get = optionsMap.value.get(value2)) === null || _optionsMap$value$get === void 0 ? void 0 : _optionsMap$value$get.label
        };
      }) : innerValue.value;
      return {
        value: val,
        onClose: multiple.value ? index => removeTag(index) : () => {}
      };
    });
    const collapsedItemsParams = computed(() => multiple.value ? {
      value: innerValue.value,
      collapsedSelectedItems: innerValue.value.slice(minCollapsedNum.value),
      count: innerValue.value.length - minCollapsedNum.value
    } : {});
    const removeTag = (index, context2) => {
      var _props2$onRemove;
      const {
        e
      } = context2 || {};
      e === null || e === void 0 ? void 0 : e.stopPropagation();
      if (isDisabled.value) return;
      const selectValue = cloneDeep(innerValue.value);
      const value2 = selectValue[index];
      selectValue.splice(index, 1);
      setInnerValue(selectValue, {
        e,
        trigger: "tag-remove"
      });
      const evtObj = {
        value: value2,
        data: optionsMap.value.get(value2),
        e
      };
      instance.emit("remove", evtObj);
      (_props2$onRemove = props2.onRemove) === null || _props2$onRemove === void 0 ? void 0 : _props2$onRemove.call(props2, evtObj);
    };
    const handleCreate = () => {
      var _props2$onCreate;
      if (!tInputValue.value) return;
      const createVal = tInputValue.value;
      multiple.value && setTInputValue("");
      instance.emit("create", createVal);
      (_props2$onCreate = props2.onCreate) === null || _props2$onCreate === void 0 ? void 0 : _props2$onCreate.call(props2, createVal);
    };
    const handleClear = _ref => {
      var _props2$onClear;
      let {
        e
      } = _ref;
      e === null || e === void 0 ? void 0 : e.stopPropagation();
      if (multiple.value) setInnerValue([], {
        trigger: "clear",
        e
      });else setInnerValue("", {
        trigger: "clear",
        e
      });
      instance.emit("clear", {
        e
      });
      (_props2$onClear = props2.onClear) === null || _props2$onClear === void 0 ? void 0 : _props2$onClear.call(props2, {
        e
      });
    };
    const handleTInputValueChange = (val, context2) => {
      if (context2.trigger === "blur" || !innerPopupVisible.value) return;
      setTInputValue(val);
      debounceSearch();
    };
    const handleTagChange = (currentTags, context2) => {
      const {
        trigger,
        index,
        e
      } = context2;
      if (trigger === "clear") setInnerValue([], {
        trigger: "tag-remove",
        e
      });
      if (["tag-remove", "backspace"].includes(trigger)) removeTag(index);
    };
    const handleFocus = (value2, context2) => {
      var _props2$onFocus;
      instance.emit("focus", {
        value: value2,
        e: context2 === null || context2 === void 0 ? void 0 : context2.e
      });
      (_props2$onFocus = props2.onFocus) === null || _props2$onFocus === void 0 ? void 0 : _props2$onFocus.call(props2, {
        value: value2,
        e: context2 === null || context2 === void 0 ? void 0 : context2.e
      });
    };
    const handleBlur = (value2, context2) => {
      var _props2$onBlur;
      instance.emit("blur", {
        value: value2,
        e: context2 === null || context2 === void 0 ? void 0 : context2.e
      });
      (_props2$onBlur = props2.onBlur) === null || _props2$onBlur === void 0 ? void 0 : _props2$onBlur.call(props2, {
        value: value2,
        e: context2 === null || context2 === void 0 ? void 0 : context2.e
      });
    };
    const handleEnter = (value2, context2) => {
      var _props2$onEnter;
      instance.emit("enter", {
        value: value2,
        e: context2 === null || context2 === void 0 ? void 0 : context2.e,
        inputValue: tInputValue.value
      });
      (_props2$onEnter = props2.onEnter) === null || _props2$onEnter === void 0 ? void 0 : _props2$onEnter.call(props2, {
        value: value2,
        e: context2 === null || context2 === void 0 ? void 0 : context2.e,
        inputValue: tInputValue.value.toString()
      });
      creatable.value && hoverIndex.value < 1 && handleCreate();
    };
    const debounceSearch = debounce(() => {
      var _props2$onSearch;
      instance.emit("search", tInputValue.value);
      (_props2$onSearch = props2.onSearch) === null || _props2$onSearch === void 0 ? void 0 : _props2$onSearch.call(props2, tInputValue.value.toString());
    }, 300);
    const getOverlayElm = () => {
      let r;
      try {
        const popupRefs = context.refs.selectInputRef.$refs.selectInputRef.$refs;
        r = popupRefs.overlay || popupRefs.component.$refs.overlay;
      } catch (e) {
        log.warn("Select", e);
      }
      return r;
    };
    const updateScrollTop = content => {
      var _props2$scroll;
      if (((_props2$scroll = props2.scroll) === null || _props2$scroll === void 0 ? void 0 : _props2$scroll.type) === "virtual") return;
      const overlayEl = getOverlayElm();
      if (!overlayEl) return;
      const firstSelectedNode = overlayEl === null || overlayEl === void 0 ? void 0 : overlayEl.querySelector(`.${classPrefix.value}-is-selected`);
      nextTick(() => {
        if (firstSelectedNode && content) {
          const {
            paddingBottom
          } = getComputedStyle(firstSelectedNode);
          const {
            marginBottom
          } = getComputedStyle(content);
          const elementBottomHeight = parseInt(paddingBottom, 10) + parseInt(marginBottom, 10);
          const updateValue = firstSelectedNode.offsetTop - content.offsetTop - (content.clientHeight - firstSelectedNode.clientHeight) + elementBottomHeight;
          content.scrollTop = updateValue;
        }
      });
    };
    const hoverIndex = ref(-1);
    const keydownEvent = e => {
      var _selectPanelRef$value;
      const displayOptions = [];
      const getCurrentOptionsList = options => {
        options.forEach(option => {
          if (option.group) getCurrentOptionsList(option.children);else displayOptions.push(option);
        });
      };
      getCurrentOptionsList((_selectPanelRef$value = selectPanelRef.value) === null || _selectPanelRef$value === void 0 ? void 0 : _selectPanelRef$value.getDisplayOptions());
      const displayOptionsLength = displayOptions.length;
      const arrowDownOption = () => {
        let count = 0;
        while (hoverIndex.value < displayOptionsLength) {
          var _displayOptions$hover;
          if (!((_displayOptions$hover = displayOptions[hoverIndex.value]) !== null && _displayOptions$hover !== void 0 && _displayOptions$hover.disabled)) break;
          if (hoverIndex.value === displayOptionsLength - 1) hoverIndex.value = 0;else hoverIndex.value += 1;
          count += 1;
          if (count >= displayOptionsLength) break;
        }
      };
      const arrowUpOption = () => {
        let count = 0;
        while (hoverIndex.value > -1) {
          var _displayOptions$hover2;
          if (!((_displayOptions$hover2 = displayOptions[hoverIndex.value]) !== null && _displayOptions$hover2 !== void 0 && _displayOptions$hover2.disabled)) break;
          if (hoverIndex.value === 0) hoverIndex.value = displayOptionsLength - 1;else hoverIndex.value -= 1;
          count += 1;
          if (count >= displayOptionsLength) break;
        }
      };
      if (displayOptionsLength === 0) return;
      const preventKeys = ["ArrowDown", "ArrowUp", "Enter", "Escape", "Tab"];
      if (preventKeys.includes(e.code)) e.preventDefault();
      switch (e.code) {
        case "ArrowDown":
          if (hoverIndex.value === -1) {
            hoverIndex.value = 0;
            return;
          }
          if (hoverIndex.value < displayOptionsLength - 1) {
            hoverIndex.value += 1;
            arrowDownOption();
          } else {
            hoverIndex.value = 0;
            arrowDownOption();
          }
          break;
        case "ArrowUp":
          if (hoverIndex.value === -1) {
            hoverIndex.value = 0;
            return;
          }
          if (hoverIndex.value > 0) {
            hoverIndex.value -= 1;
            arrowUpOption();
          } else {
            hoverIndex.value = displayOptionsLength - 1;
            arrowUpOption();
          }
          break;
        case "Enter":
          if (hoverIndex.value === -1) return;
          if (displayOptions[hoverIndex.value].isCreated && multiple.value) handleCreate();
          if (!multiple.value) {
            const optionValue = displayOptions[hoverIndex.value].value;
            setInnerValue(optionValue, {
              e,
              trigger: "check"
            }, optionValue);
            setInnerPopupVisible(false, {
              e
            });
          } else {
            var _displayOptions$hover3;
            if (hoverIndex.value === -1) return;
            const optionValue = (_displayOptions$hover3 = displayOptions[hoverIndex.value]) === null || _displayOptions$hover3 === void 0 ? void 0 : _displayOptions$hover3.value;
            if (!optionValue) return;
            const newValue = getNewMultipleValue(innerValue.value, optionValue);
            setInnerValue(newValue.value, {
              e,
              trigger: newValue.isCheck ? "check" : "uncheck"
            }, optionValue);
          }
          break;
        case "Escape":
        case "Tab":
          setInnerPopupVisible(false, {
            trigger: "keydown-esc",
            e
          });
          setTInputValue("");
          break;
      }
    };
    watch(innerPopupVisible, val => {
      val && on(document, "keydown", keydownEvent);
      !val && off(document, "keydown", keydownEvent);
    }, {
      flush: "sync"
    });
    watch(innerPopupVisible, value2 => {
      if (value2) {
        hoverIndex.value = -1;
      } else {
        tInputValue.value && setTInputValue("");
      }
    });
    provide("tSelect", {
      size,
      multiple,
      popupOpenTime,
      hoverIndex,
      selectValue: innerValue,
      reserveKeyword,
      isReachMaxLimit,
      getOverlayElm,
      handleCreate,
      handleValueChange: setInnerValue,
      handlerInputChange: setTInputValue,
      handlePopupVisibleChange: setInnerPopupVisible
    });
    return {
      isFilterable,
      isDisabled,
      isLoading,
      innerOptions,
      placeholderText,
      selectInputRef,
      selectPanelRef,
      innerPopupVisible,
      displayText,
      tInputValue,
      collapsedItemsParams,
      valueDisplayParams,
      handleFocus,
      handleBlur,
      handleEnter,
      handleClear,
      handleTagChange,
      handleTInputValueChange,
      setInnerPopupVisible,
      removeTag,
      renderTNode,
      updateScrollTop,
      componentName: COMPONENT_NAME
    };
  },
  methods: {
    renderSuffixIcon() {
      const h = this.$createElement;
      const {
        isLoading,
        showArrow,
        innerPopupVisible,
        isDisabled
      } = this;
      if (isLoading) {
        return h("t-loading", {
          "class": [`${this.componentName}__right-icon`, `${this.componentName}__active-icon`],
          "attrs": {
            "size": "small"
          }
        });
      }
      return showArrow ? h("fake-arrow", {
        "attrs": {
          "overlayClassName": `${this.componentName}__right-icon`,
          "isActive": innerPopupVisible && !isDisabled
        }
      }) : null;
    }
  },
  render() {
    const h = arguments[0];
    const {
      renderTNode
    } = this;
    const prefixIcon = () => renderTNode("prefixIcon");
    const valueDisplay = () => renderTNode("valueDisplay", {
      params: this.valueDisplayParams
    });
    const collapsedItems = () => renderTNode("collapsedItems", {
      params: this.collapsedItemsParams
    });
    const {
      overlayClassName,
      ...restPopupProps
    } = this.popupProps || {};
    return h("div", {
      "ref": "select",
      "class": `${this.componentName}__wrap`
    }, [h(SelectInput, helper([{
      "ref": "selectInputRef",
      "class": this.componentName,
      "attrs": {
        "autoWidth": this.autoWidth,
        "borderless": this.borderless,
        "readonly": this.readonly,
        "allowInput": this.isFilterable,
        "multiple": this.multiple,
        "keys": this.keys,
        "status": this.status,
        "tips": this.tips,
        "value": this.displayText,
        "valueDisplay": valueDisplay,
        "clearable": this.clearable,
        "disabled": this.isDisabled,
        "label": prefixIcon,
        "suffixIcon": this.renderSuffixIcon,
        "placeholder": this.placeholderText,
        "inputValue": this.tInputValue,
        "inputProps": {
          size: this.size,
          ...this.inputProps
        },
        "tagInputProps": {
          autoWidth: true,
          ...this.tagInputProps
        },
        "tagProps": this.tagProps,
        "minCollapsedNum": this.minCollapsedNum,
        "collapsedItems": collapsedItems,
        "popupVisible": this.innerPopupVisible,
        "popupProps": {
          overlayClassName: [`${this.componentName}__dropdown`, overlayClassName],
          ...restPopupProps
        }
      }
    }, {
      "on": {
        "focus": this.handleFocus,
        "blur": this.handleBlur,
        "enter": this.handleEnter,
        "clear": this.handleClear,
        "input-change": this.handleTInputValueChange,
        "popup-visible-change": this.setInnerPopupVisible,
        "tag-change": this.handleTagChange
      }
    }, {}, this.selectInputProps, {
      "attrs": {
        "updateScrollTop": this.updateScrollTop
      }
    }]), [h("select-panel", {
      "ref": "selectPanelRef",
      "slot": "panel",
      "scopedSlots": this.$scopedSlots,
      "attrs": {
        "size": this.size,
        "options": this.innerOptions,
        "inputValue": this.tInputValue,
        "multiple": this.multiple,
        "empty": this.empty,
        "filter": this.filter,
        "filterable": this.isFilterable,
        "creatable": this.creatable,
        "scroll": this.scroll,
        "loading": this.isLoading,
        "loadingText": this.loadingText,
        "panelTopContent": this.panelTopContent,
        "panelBottomContent": this.panelBottomContent
      }
    })])]);
  }
});

export { TSelect as default };
//# sourceMappingURL=select.js.map
