"use strict";
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
const aria = require("../../../constants/aria.js");
const event = require("../../../utils/dom/event.js");
const types = require("../../../utils/types.js");
const index = require("../../../hooks/use-namespace/index.js");
const useProps = require("./useProps.js");
const fixedSizeList = require("../../virtual-list/src/components/fixed-size-list.js");
const dynamicSizeList = require("../../virtual-list/src/components/dynamic-size-list.js");
const groupItem = require("./group-item.js");
const token = require("./token.js");
const optionItem = require("./option-item.js");
const Vue = require("vue");
const shared_esmBundler = require("../../../../../@vue/shared/dist/shared.esm-bundler.js");
const get = require("../../../../../lodash-es/get.js");
const index$1 = require("../../../../node_modules/@vueuse/shared/index.js");
const props = {
  loading: Boolean,
  data: {
    type: Array,
    required: true
  },
  hoveringIndex: Number,
  width: Number,
  id: String,
  ariaLabel: String
};
var select_dropdown_default = /* @__PURE__ */ Vue.defineComponent({
  name: "ElSelectDropdown",
  props,
  setup(props2, { slots, expose }) {
    const select = Vue.inject(token.selectV2InjectionKey);
    const ns = index.useNamespace("select");
    const { getLabel, getValue, getDisabled } = useProps.useProps(select.props);
    const cachedHeights = Vue.ref([]);
    const listRef = Vue.ref();
    const size = Vue.computed(() => props2.data.length);
    Vue.watch(() => size.value, () => {
      var _a, _b;
      (_b = (_a = select.tooltipRef.value) == null ? void 0 : _a.updatePopper) == null ? void 0 : _b.call(_a);
    });
    const isSized = Vue.computed(() => types.isUndefined(select.props.estimatedOptionHeight));
    const listProps = Vue.computed(() => {
      if (isSized.value) return { itemSize: select.props.itemHeight };
      return {
        estimatedSize: select.props.estimatedOptionHeight,
        itemSize: (idx) => cachedHeights.value[idx]
      };
    });
    const contains = (arr = [], target) => {
      const { props: { valueKey } } = select;
      if (!shared_esmBundler.isObject(target)) return arr.includes(target);
      return arr && arr.some((item) => {
        return Vue.toRaw(get.default(item, valueKey)) === get.default(target, valueKey);
      });
    };
    const isEqual = (selected, target) => {
      if (!shared_esmBundler.isObject(target)) return selected === target;
      else {
        const { valueKey } = select.props;
        return get.default(selected, valueKey) === get.default(target, valueKey);
      }
    };
    const isItemSelected = (modelValue, target) => {
      if (select.props.multiple) return contains(modelValue, getValue(target));
      return isEqual(modelValue, getValue(target));
    };
    const isItemDisabled = (modelValue, selected) => {
      const { disabled, multiple, multipleLimit } = select.props;
      return disabled || !selected && (multiple ? multipleLimit > 0 && modelValue.length >= multipleLimit : false);
    };
    const isItemHovering = (target) => props2.hoveringIndex === target;
    const scrollToItem = (index2) => {
      const list = listRef.value;
      if (list) list.scrollToItem(index2);
    };
    const resetScrollTop = () => {
      const list = listRef.value;
      if (list) list.resetScrollTop();
    };
    expose({
      listRef,
      isSized,
      isItemDisabled,
      isItemHovering,
      isItemSelected,
      scrollToItem,
      resetScrollTop
    });
    const Item = (itemProps) => {
      const { index: index2, data, style } = itemProps;
      const sized = Vue.unref(isSized);
      const { itemSize, estimatedSize } = Vue.unref(listProps);
      const { modelValue } = select.props;
      const { onSelect, onHover } = select;
      const item = data[index2];
      if (item.type === "Group") return Vue.createVNode(groupItem.default, {
        "item": item,
        "style": style,
        "height": sized ? itemSize : estimatedSize
      }, null);
      const isSelected = isItemSelected(modelValue, item);
      const isDisabled = isItemDisabled(modelValue, isSelected);
      const isHovering = isItemHovering(index2);
      return Vue.createVNode(optionItem.default, Vue.mergeProps(itemProps, {
        "selected": isSelected,
        "disabled": getDisabled(item) || isDisabled,
        "created": !!item.created,
        "hovering": isHovering,
        "item": item,
        "onSelect": onSelect,
        "onHover": onHover
      }), { default: (props3) => {
        var _a;
        return ((_a = slots.default) == null ? void 0 : _a.call(slots, props3)) || Vue.createVNode("span", null, [getLabel(item)]);
      } });
    };
    const { onKeyboardNavigate, onKeyboardSelect } = select;
    const onForward = () => {
      onKeyboardNavigate("forward");
    };
    const onBackward = () => {
      onKeyboardNavigate("backward");
    };
    const onKeydown = (e) => {
      const code = event.getEventCode(e);
      const { tab, esc, down, up, enter, numpadEnter } = aria.EVENT_CODE;
      if ([
        esc,
        down,
        up,
        enter,
        numpadEnter
      ].includes(code)) {
        e.preventDefault();
        e.stopPropagation();
      }
      switch (code) {
        case tab:
        case esc:
          break;
        case down:
          onForward();
          break;
        case up:
          onBackward();
          break;
        case enter:
        case numpadEnter:
          onKeyboardSelect();
          break;
      }
    };
    return () => {
      var _a, _b, _c, _d;
      const { data, width } = props2;
      const { height, multiple, scrollbarAlwaysOn } = select.props;
      const isScrollbarAlwaysOn = Vue.computed(() => {
        return index$1.isIOS ? true : scrollbarAlwaysOn;
      });
      const List = Vue.unref(isSized) ? fixedSizeList.default : dynamicSizeList.default;
      return Vue.createVNode("div", {
        "class": [ns.b("dropdown"), ns.is("multiple", multiple)],
        "style": { width: `${width}px` }
      }, [
        (_a = slots.header) == null ? void 0 : _a.call(slots),
        ((_b = slots.loading) == null ? void 0 : _b.call(slots)) || ((_c = slots.empty) == null ? void 0 : _c.call(slots)) || Vue.createVNode(List, Vue.mergeProps({ "ref": listRef }, Vue.unref(listProps), {
          "className": ns.be("dropdown", "list"),
          "scrollbarAlwaysOn": isScrollbarAlwaysOn.value,
          "data": data,
          "height": height,
          "width": width,
          "total": data.length,
          "innerElement": "ul",
          "innerProps": {
            id: props2.id,
            role: "listbox",
            "aria-label": props2.ariaLabel,
            "aria-orientation": "vertical"
          },
          "onKeydown": onKeydown
        }), { default: (props3) => Vue.createVNode(Item, props3, null) }),
        (_d = slots.footer) == null ? void 0 : _d.call(slots)
      ]);
    };
  }
});
exports.default = select_dropdown_default;
