import { createTextVNode as _createTextVNode, mergeProps as _mergeProps, createVNode as _createVNode, Fragment as _Fragment } from "vue";
// Styles
import "./VSelect.css";

// Components
import { filterVTextFieldProps, makeVTextFieldProps } from "../VTextField/VTextField.mjs";
import { VCheckboxBtn } from "../VCheckbox/index.mjs";
import { VChip } from "../VChip/index.mjs";
import { VDefaultsProvider } from "../VDefaultsProvider/index.mjs";
import { VDialogTransition } from "../transitions/index.mjs";
import { VList, VListItem } from "../VList/index.mjs";
import { VMenu } from "../VMenu/index.mjs";
import { VTextField } from "../VTextField/index.mjs"; // Composables
import { forwardRefs } from "../../composables/forwardRefs.mjs";
import { IconValue } from "../../composables/icons.mjs";
import { makeItemsProps, useItems } from "../../composables/items.mjs";
import { makeTransitionProps } from "../../composables/transition.mjs";
import { useForm } from "../../composables/form.mjs";
import { useLocale } from "../../composables/locale.mjs";
import { useProxiedModel } from "../../composables/proxiedModel.mjs"; // Utility
import { computed, mergeProps, ref } from 'vue';
import { deepEqual, genericComponent, omit, propsFactory, useRender, wrapInArray } from "../../util/index.mjs"; // Types
export const makeSelectProps = propsFactory({
  chips: Boolean,
  closableChips: Boolean,
  eager: Boolean,
  hideNoData: Boolean,
  hideSelected: Boolean,
  menu: Boolean,
  menuIcon: {
    type: IconValue,
    default: '$dropdown'
  },
  menuProps: {
    type: Object
  },
  multiple: Boolean,
  noDataText: {
    type: String,
    default: '$vuetify.noDataText'
  },
  openOnClear: Boolean,
  valueComparator: {
    type: Function,
    default: deepEqual
  },
  ...makeItemsProps({
    itemChildren: false
  })
}, 'v-select');
export const VSelect = genericComponent()({
  name: 'VSelect',
  props: {
    ...makeSelectProps(),
    ...omit(makeVTextFieldProps({
      modelValue: null
    }), ['validationValue', 'dirty', 'appendInnerIcon']),
    ...makeTransitionProps({
      transition: {
        component: VDialogTransition
      }
    })
  },
  emits: {
    'update:modelValue': val => true,
    'update:menu': val => true
  },
  setup(props, _ref) {
    let {
      slots
    } = _ref;
    const {
      t
    } = useLocale();
    const vTextFieldRef = ref();
    const menu = useProxiedModel(props, 'menu');
    const {
      items,
      transformIn,
      transformOut
    } = useItems(props);
    const model = useProxiedModel(props, 'modelValue', [], v => transformIn(wrapInArray(v)), v => {
      const transformed = transformOut(v);
      return props.multiple ? transformed : transformed[0] ?? null;
    });
    const form = useForm();
    const selections = computed(() => {
      return model.value.map(v => {
        return items.value.find(item => props.valueComparator(item.value, v.value)) || v;
      });
    });
    const selected = computed(() => selections.value.map(selection => selection.props.value));
    const displayItems = computed(() => {
      if (props.hideSelected) {
        return items.value.filter(item => !selections.value.some(s => s === item));
      }
      return items.value;
    });
    const listRef = ref();
    function onClear(e) {
      if (props.openOnClear) {
        menu.value = true;
      }
    }
    function onMousedownControl() {
      if (props.hideNoData && !items.value.length || props.readonly || form?.isReadonly.value) return;
      menu.value = !menu.value;
    }
    function onKeydown(e) {
      if (props.readonly || form?.isReadonly.value) return;
      if (['Enter', ' ', 'ArrowDown', 'ArrowUp', 'Home', 'End'].includes(e.key)) {
        e.preventDefault();
      }
      if (['Enter', 'ArrowDown', ' '].includes(e.key)) {
        menu.value = true;
      }
      if (['Escape', 'Tab'].includes(e.key)) {
        menu.value = false;
      }
      if (e.key === 'ArrowDown') {
        listRef.value?.focus('next');
      } else if (e.key === 'ArrowUp') {
        listRef.value?.focus('prev');
      } else if (e.key === 'Home') {
        listRef.value?.focus('first');
      } else if (e.key === 'End') {
        listRef.value?.focus('last');
      }
    }
    function select(item) {
      if (props.multiple) {
        const index = selected.value.findIndex(selection => props.valueComparator(selection, item.value));
        if (index === -1) {
          model.value = [...model.value, item];
        } else {
          const value = [...model.value];
          value.splice(index, 1);
          model.value = value;
        }
      } else {
        model.value = [item];
        menu.value = false;
      }
    }
    function onBlur(e) {
      if (!listRef.value?.$el.contains(e.relatedTarget)) {
        menu.value = false;
      }
    }
    function onFocusout(e) {
      if (e.relatedTarget == null) {
        vTextFieldRef.value?.focus();
      }
    }
    useRender(() => {
      const hasChips = !!(props.chips || slots.chip);
      const hasList = !!(!props.hideNoData || displayItems.value.length || slots.prepend || slots.append || slots['no-data']);
      const [textFieldProps] = filterVTextFieldProps(props);
      return _createVNode(VTextField, _mergeProps({
        "ref": vTextFieldRef
      }, textFieldProps, {
        "modelValue": model.value.map(v => v.props.value).join(', '),
        "onUpdate:modelValue": v => {
          if (v == null) model.value = [];
        },
        "validationValue": model.externalValue,
        "dirty": model.value.length > 0,
        "class": ['v-select', {
          'v-select--active-menu': menu.value,
          'v-select--chips': !!props.chips,
          [`v-select--${props.multiple ? 'multiple' : 'single'}`]: true,
          'v-select--selected': model.value.length
        }],
        "appendInnerIcon": props.menuIcon,
        "readonly": true,
        "onClick:clear": onClear,
        "onMousedown:control": onMousedownControl,
        "onBlur": onBlur,
        "onKeydown": onKeydown
      }), {
        ...slots,
        default: () => _createVNode(_Fragment, null, [_createVNode(VMenu, _mergeProps({
          "modelValue": menu.value,
          "onUpdate:modelValue": $event => menu.value = $event,
          "activator": "parent",
          "contentClass": "v-select__content",
          "eager": props.eager,
          "maxHeight": 310,
          "openOnClick": false,
          "closeOnContentClick": false,
          "transition": props.transition
        }, props.menuProps), {
          default: () => [hasList && _createVNode(VList, {
            "ref": listRef,
            "selected": selected.value,
            "selectStrategy": props.multiple ? 'independent' : 'single-independent',
            "onMousedown": e => e.preventDefault(),
            "onFocusout": onFocusout
          }, {
            default: () => [!displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? _createVNode(VListItem, {
              "title": t(props.noDataText)
            }, null)), slots['prepend-item']?.(), displayItems.value.map((item, index) => {
              if (slots.item) {
                return slots.item?.({
                  item,
                  index,
                  props: mergeProps(item.props, {
                    onClick: () => select(item)
                  })
                });
              }
              return _createVNode(VListItem, _mergeProps({
                "key": index
              }, item.props, {
                "onClick": () => select(item)
              }), {
                prepend: _ref2 => {
                  let {
                    isSelected
                  } = _ref2;
                  return props.multiple && !props.hideSelected ? _createVNode(VCheckboxBtn, {
                    "modelValue": isSelected,
                    "ripple": false
                  }, null) : undefined;
                }
              });
            }), slots['append-item']?.()]
          })]
        }), selections.value.map((item, index) => {
          function onChipClose(e) {
            e.stopPropagation();
            e.preventDefault();
            select(item);
          }
          const slotProps = {
            'onClick:close': onChipClose,
            modelValue: true,
            'onUpdate:modelValue': undefined
          };
          return _createVNode("div", {
            "key": item.value,
            "class": "v-select__selection"
          }, [hasChips ? _createVNode(VDefaultsProvider, {
            "defaults": {
              VChip: {
                closable: props.closableChips,
                size: 'small',
                text: item.title
              }
            }
          }, {
            default: () => [slots.chip ? slots.chip({
              item,
              index,
              props: slotProps
            }) : _createVNode(VChip, slotProps, null)]
          }) : slots.selection ? slots.selection({
            item,
            index
          }) : _createVNode("span", {
            "class": "v-select__selection-text"
          }, [item.title, props.multiple && index < selections.value.length - 1 && _createVNode("span", {
            "class": "v-select__selection-comma"
          }, [_createTextVNode(",")])])]);
        })])
      });
    });
    return forwardRefs({
      menu,
      select
    }, vTextFieldRef);
  }
});
//# sourceMappingURL=VSelect.mjs.map