import { _ as _export } from './export-ecf4b1cb.js';
import { a as arrayIteration } from './array-iteration-dec5536e.js';
import { a as addToUnscopables } from './es.array.includes-1f433385.js';
import './es.array.from-3ef944e4.js';
import './es.string.iterator-eb7ab984.js';
import { i as i18n } from './i18n-e25edebe.js';
import './es.object.to-string-5a59fbfc.js';
import './es.object.keys-6369b884.js';
import { n as normalizeComponent } from './normalize-component-63e8c7a0.js';
import './function-bind-context-b3fabf77.js';
import './array-species-create-afb281e6.js';
import './object-keys-a5d351f7.js';
import './create-property-c00b5c27.js';
import './classof-b10e7604.js';
import './string-multibyte-88926e02.js';
import './set-to-string-tag-452fb9b0.js';
import './object-set-prototype-of-9853ad1a.js';
import './regexp-exec-abstract-04d119fc.js';
import './regexp-flags-b5fc4ddb.js';
import './es.string.split-cd1f3afc.js';
import './is-regexp-5558fd03.js';

var $findIndex = arrayIteration.findIndex;


var FIND_INDEX = 'findIndex';
var SKIPS_HOLES = true;

// Shouldn't skip holes
if (FIND_INDEX in []) Array(1)[FIND_INDEX](function () { SKIPS_HOLES = false; });

// `Array.prototype.findIndex` method
// https://tc39.es/ecma262/#sec-array.prototype.findindex
_export({ target: 'Array', proto: true, forced: SKIPS_HOLES }, {
  findIndex: function findIndex(callbackfn /* , that = undefined */) {
    return $findIndex(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
  }
});

// https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
addToUnscopables(FIND_INDEX);

/** a multipurpose drop down list */
// TODO: currently only taking objects not strings??

var script = {
  name: 'BaseDropDownList',
  mixins: [i18n],
  props: {
    /**
     * list of options to select from
     */
    dropDownOptions: {
      type: Array,
      default: function _default() {
        return [];
      }
    },

    /**
     * specify the name of a property that can be used as identifier
     * // TODO: need handling if no identifier provided!!
     */
    identifierPropertyName: {
      type: String,
      default: 'id'
    },

    /**
     * specify the name of the property that should be displayed
     */
    labelPropertyName: {
      type: String,
      default: 'value'
    },

    /**
     * specify the currently active option (will have gray background
     * if not disabled by setting activeStyled false) for example for
     * combination with input and keyboard use
     */
    activeOption: {
      type: [Object, String],
      default: function _default() {
        return {};
      }
    },

    /**
     * specify the currently selected option (will appear in app color if not disabled
     * by setting selectStyled false, but also used for aria-selected)<br>
     *   the .sync modifier can be used here
     */
    selectedOption: {
      type: [Object, String],
      default: function _default() {
        return {};
      }
    },

    /**
     * in order to link the drop down body to an input element specify a list
     * id and use the list attribute on the input
     */
    listId: {
      type: String,
      default: ''
    },

    /**
     * add styling to the list body (e.g. max-height)
     */
    listBodyStyle: {
      type: Object,
      default: function _default() {
        return {};
      }
    },

    /**
     * flag if the currently active element should be styled
     * (gray background)
     */
    activeStyled: {
      type: Boolean,
      default: true
    },

    /**
     * flag if the currently selected entry should be styled
     * (only makes sense for single select, color: app-color)
     */
    selectStyled: {
      type: Boolean,
      default: false
    },

    /**
     * if true the element will be styled as a drop down element with
     * box-shadow
     */
    displayAsDropDown: {
      type: Boolean,
      default: true
    },

    /**
     * message displayed when no selectable options are available
     */
    dropDownNoOptionsInfo: {
      type: String,
      default: 'No options available'
    },

    /**
     * specify a language (ISO 639-1) (used for label if label is language specific object
     * e.g. { de: 'xxx', en: 'yyy' }
     */
    language: {
      type: String,
      default: ''
    },

    /**
     * this adds the possibility of nested options (thus a second list nested within the first one),
     * if this is set true this will have consequences for scroll adjustment of list on keyboard use
     * and how the active option is determined (the identifier property will be used)
     */
    hasSubOptions: {
      type: Boolean,
      default: false
    },

    /**
     * in case a custom option background should be set to the currently active option<br>
     *   (this will also apply if 'activeStyled' is set false)<br>
     * if you want to use this option please set the css variable --option-background
     * in your app
     */
    useCustomOptionActiveBackgroundColor: {
      type: Boolean,
      default: false
    }
  },
  data: function data() {
    return {
      /**
       * if there is any (associated by id) store the related input element
       * in this variable
       * @type {HTMLElement}
       */
      inputElement: null
    };
  },
  computed: {
    /**
     * variable to store if values provided in the list are strings
     * (or an object with language specific strings e.g. { de: 'xxx', en: 'yyy' }) or
     * if list contains other objects (e.g. for AdvancedSearch)
     * @returns {boolean}
     */
    valueIsString: function valueIsString() {
      return this.dropDownOptions && this.dropDownOptions.length && typeof this.getLangLabel(this.dropDownOptions[0][this.labelPropertyName], true) === 'string';
    },

    /**
     * the index of the currently active option provided by parent
     * @returns {number}
     */
    activeOptionIndex: function activeOptionIndex() {
      var _this = this;

      // check if options has submenu
      if (this.hasSubOptions && (!this.activeOption || this.activeOption[this.identifierPropertyName] !== undefined)) {
        return this.dropDownOptions.findIndex(function (opt) {
          return opt[_this.identifierPropertyName] === _this.activeOption[_this.identifierPropertyName];
        });
      }

      return this.dropDownOptions.indexOf(this.activeOption);
    }
  },
  mounted: function mounted() {
    var _this2 = this;

    // check if this element is associated with an input element
    var htmlInputElements = document.getElementsByTagName('input'); // check if an input element exists

    if (htmlInputElements && htmlInputElements.length) {
      var inputElementsArray = Array.from(htmlInputElements); // get the element that has the equal list id

      this.inputElement = inputElementsArray.find(function (el) {
        return el.getAttribute('list') === _this2.listId;
      }); // if the parent also has a input field that should be connected - it will need to
      // have the same id! (input attribute 'list') (this is to avoid unwanted side effects)

      if (this.inputElement) {
        this.inputElement.addEventListener('keydown', this.navigateOptions);
      }
    }
  },
  destroyed: function destroyed() {
    // check if there is an associated input element
    if (this.inputElement) {
      // if yes - remove the event listener again
      this.inputElement.removeEventListener('keydown', this.navigateOptions);
    }
  },
  methods: {
    /**
     * triggered if option was selected by click
     *
     * @param {Object} option - the selected option
     */
    selected: function selected(option) {
      /**
       * inform parent if option was selected by mouse click
       * (the .sync modifier on prop selectedOption can be used)
       *
       * @event update:selected-option
       * @property {Object} option - the selected option
       */
      this.$emit('update:selected-option', option);
    },

    /**
     * check if an option has data (and should be displayed)
     *
     * @param {Object} option - the option in question
     * @returns {boolean}
     */
    optionHasData: function optionHasData(option) {
      if (typeof option === 'string') {
        return !!option;
      }

      if (option && option.length) {
        return !!option.length;
      }

      return !!(option && Object.keys(option).length);
    },

    /**
     * a function to navigate the dropdown list by keyboard, used in
     * event listener 'keydown'
     *
     * @property {KeyboardEvent} event - the keydown event from the input
     * field associated by 'id'
     */
    navigateOptions: function navigateOptions(event) {
      var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
          _ref$activeOptionHeig = _ref.activeOptionHeight,
          activeOptionHeight = _ref$activeOptionHeig === void 0 ? 0 : _ref$activeOptionHeig,
          _ref$activeOptionTop = _ref.activeOptionTop,
          activeOptionTop = _ref$activeOptionTop === void 0 ? 0 : _ref$activeOptionTop;

      var key = event.key;

      if (['ArrowDown', 'ArrowUp'].includes(key)) {
        // check if it is necessary to adjust scrolltop of container (to
        // always have entry steered to with arrow keys in view)
        // if list has suboptions this should be navigated from suboptions
        if ((!this.hasSubOptions || activeOptionHeight) && this.$refs.option && this.$refs.option[this.activeOptionIndex]) {
          // save the active option in a variable
          var activeOptionTemp = this.$refs.option[this.activeOptionIndex]; // get the option height

          var activeOptionHeightTemp = activeOptionHeight || activeOptionTemp.clientHeight; // get the option top position

          var activeOptionTopTemp = activeOptionTop || activeOptionTemp.offsetTop;

          if (this.$parent.$refs.dropDownContainer) {
            this.$parent.navigateOptions(event, {
              activeOptionHeight: activeOptionHeightTemp,
              activeOptionTop: activeOptionTopTemp
            });
          } else {
            // save the container element in a variable
            var dropDownContainerTemp = this.$refs.dropDownContainer; // get the current scroll position of the container

            var dropDownContainerScrollTop = dropDownContainerTemp.scrollTop; // get the container height

            var dropDownContainerHeight = dropDownContainerTemp.clientHeight; // check if current active option is out of view

            var optionOutOfView = activeOptionTopTemp + activeOptionHeightTemp < dropDownContainerScrollTop || activeOptionTopTemp > dropDownContainerScrollTop + dropDownContainerHeight; // if active option index is 0 - return to top

            if (!this.hasSubOptions && !this.activeOptionIndex) {
              dropDownContainerTemp.scrollTop = 0; // else if index is last entry of options list - bring last item into view
            } else if (!this.hasSubOptions && this.activeOptionIndex === this.dropDownOptions.length - 1) {
              dropDownContainerTemp.scrollTo({
                top: activeOptionTopTemp + activeOptionHeightTemp
              }); // dropDownContainerTemp.scrollTop = activeOptionTopTemp
              //   + activeOptionHeightTemp;
              // else check if key was arrow down
            } else if (event.key === 'ArrowDown') {
              // if option is out of sight set container scrollTop to option position
              if (optionOutOfView) {
                dropDownContainerTemp.scrollTo({
                  top: activeOptionTopTemp
                }); // dropDownContainerTemp.scrollTop = activeOptionTopTemp;
                // else if the option position is larger then container height
                // add the height of one option row to scroll top
              } else if (activeOptionTopTemp + activeOptionHeightTemp > dropDownContainerHeight + dropDownContainerScrollTop) {
                // dropDownContainerTemp.scrollTop += activeOptionHeightTemp;
                dropDownContainerTemp.scrollTo({
                  top: dropDownContainerScrollTop + activeOptionHeightTemp
                });
              } // else check if key was arrow up

            } else if (event.key === 'ArrowUp') {
              // if option is out of sight set scrollTop to option position so it shows
              // up as last option in container
              if (optionOutOfView) {
                dropDownContainerTemp.scrollTop = activeOptionTopTemp + activeOptionHeightTemp - dropDownContainerHeight; // else if index is smaller than previous index (navigating up) and the container
                // top position is larger than the option top position subtract one option row
                // height
              } else if (dropDownContainerScrollTop > activeOptionTopTemp) {
                dropDownContainerTemp.scrollTop -= activeOptionHeightTemp;
              }
            }
          }
        }
      }
    }
  }
};

/* script */
var __vue_script__ = script;
/* template */

var __vue_render__ = function __vue_render__() {
  var _vm = this;

  var _h = _vm.$createElement;

  var _c = _vm._self._c || _h;

  return _c('div', {
    ref: "dropDownContainer",
    staticClass: "base-drop-down-list__container",
    class: ['base-drop-down-list__container', {
      'base-drop-down-list__container-drop-down-style': _vm.displayAsDropDown
    }]
  }, [_vm._t("before-list"), _vm._v(" "), _c('ul', {
    staticClass: "base-drop-down-list",
    style: _vm.listBodyStyle,
    attrs: {
      "id": _vm.listId,
      "aria-activedescendant": _vm.activeOption ? _vm.activeOption[_vm.identifierPropertyName] : false,
      "role": "listbox"
    }
  }, [_vm._l(_vm.dropDownOptions, function (option, optionIndex) {
    return [_vm.optionHasData(option[_vm.labelPropertyName]) ? _c('li', {
      key: optionIndex,
      ref: "option",
      refInFor: true,
      class: ['base-drop-down-list__option', {
        'base-drop-down-list__option__hover': _vm.activeStyled
      }, {
        'base-drop-down-list__option__selected': _vm.selectStyled && option === _vm.selectedOption
      }, {
        'base-drop-down-list__option__active': _vm.activeStyled && optionIndex === _vm.activeOptionIndex
      }, {
        'base-drop-down-list__option__active-custom': _vm.useCustomOptionActiveBackgroundColor && optionIndex === _vm.activeOptionIndex
      }],
      attrs: {
        "id": option[_vm.identifierPropertyName],
        "value": _vm.valueIsString ? _vm.getLangLabel(option[_vm.labelPropertyName], true) : option[_vm.identifierPropertyName],
        "aria-selected": _vm.selectStyled && option[_vm.identifierPropertyName] === _vm.selectedOption,
        "role": "option"
      },
      on: {
        "click": function click($event) {
          return _vm.selected(option);
        }
      }
    }, [_vm._t("option", function () {
      return [_vm._v("\n          " + _vm._s(_vm.getLangLabel(option[_vm.labelPropertyName], true)) + "\n        ")];
    }, {
      "option": option
    })], 2) : _vm._e()];
  }), _vm._v(" "), !_vm.dropDownOptions.length ? _c('div', {
    class: ['base-drop-down-list__option', 'base-drop-down-list__no-options']
  }, [!_vm.dropDownOptions.length ? _vm._t("no-options", function () {
    return [_vm._v("\n        " + _vm._s(_vm.dropDownNoOptionsInfo) + "\n      ")];
  }) : _vm._e()], 2) : _vm._e()], 2), _vm._v(" "), _vm._t("after-list")], 2);
};

var __vue_staticRenderFns__ = [];
/* style */

var __vue_inject_styles__ = undefined;
/* scoped */

var __vue_scope_id__ = "data-v-cc29a7cc";
/* module identifier */

var __vue_module_identifier__ = undefined;
/* functional template */

var __vue_is_functional_template__ = false;
/* style inject */

/* style inject SSR */

/* style inject shadow dom */

var __vue_component__ = /*#__PURE__*/normalizeComponent({
  render: __vue_render__,
  staticRenderFns: __vue_staticRenderFns__
}, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, false, undefined, undefined, undefined);

var BaseDropDownList = __vue_component__;

export { BaseDropDownList as default };
