'use strict';var objectSpread2=require('./objectSpread2-56f1d323.js');require('./es.number.constructor-daccdeab.js'),require('./es.array.map-4cfed4ef.js'),require('./es.array.concat-bb8715dc.js'),require('./es.array.filter-6fabfac0.js'),require('./es.object.to-string-f27a75a8.js'),require('./es.array.includes-3990bfec.js'),require('./es.string.includes-ec03e639.js'),require('./es.json.stringify-f88f52bf.js'),require('./i18n-68e039d3.js');var BaseInput=require('./BaseInput-35816f6e.js'),BaseDropDownList=require('./BaseDropDownList-1d65f819.js'),utils=require('./utils-2e136d65.js'),navigateList=require('./navigateList-84064d67.js'),normalizeComponent=require('./normalize-component-d9981c57.js');require('./export-61511812.js'),require('./object-set-prototype-of-dfa14cf5.js'),require('./array-iteration-f8b4483d.js'),require('./function-bind-context-e4685306.js'),require('./array-species-create-c414c2ec.js'),require('./array-method-has-species-support-983ac207.js'),require('./create-property-240c71a5.js'),require('./classof-819fc780.js'),require('./object-keys-12f2c5e5.js'),require('./is-regexp-d6f1551e.js'),require('./regexp-exec-abstract-216cd44a.js'),require('./string-multibyte-a2dff6e3.js'),require('./regexp-flags-abc49c4a.js'),require('./es.string.split-98e29ede.js'),require('./es.object.keys-c57f02bd.js'),require('./es.regexp.to-string-5606f728.js'),require('./index-9dadef01.js'),require('./BaseIcon-1ed3bf6e.js'),require('./es.array.join-88750c41.js'),require('./array-method-is-strict-99341ee3.js'),require('./typeof-6b9e62b8.js'),require('./unsupportedIterableToArray-40a00645.js'),require('./es.string.replace-25e9e098.js'),require('./es.array.sort-7d68b195.js'),require('./web.dom-collections.for-each-c07b0e22.js'),require('./dom-iterables-e2602b7e.js'),require('./es.array.from-6c133395.js'),require('./es.string.iterator-97f3177b.js'),require('./set-to-string-tag-240bb3b0.js');/**
 * Input component allowing to select single values from a drop down that are filled into
 * the input field as string
 */

var script = {
  name: 'BaseAutocompleteInput',
  components: {
    BaseInput: BaseInput["default"],
    BaseDropDownList: BaseDropDownList["default"]
  },
  mixins: [navigateList.n],
  model: {
    prop: 'input',
    event: 'input'
  },
  props: {
    /**
     * @model
     *
     * input field settable from outside
     */
    input: {
      type: [String, Number],
      default: ''
    },

    /**
     * provide a list of options for the drop down<br>
     * could be a list of strings or objects - if it is objects if necessary please adapt
     * the props labelPropertyName (value to be displayed) and identifierPropertyName (used for
     * identification) for correct handling
     */
    list: {
      type: Array,
      default: function _default() {
        return [];
      }
    },

    /** label for input field, required for usability purposes, handle
     * showing of label with property showLabel
     */
    label: {
      type: String,
      required: true
    },

    /**
     * defines if input label should be visible
     */
    showLabel: {
      type: Boolean,
      default: true
    },

    /**
     * if field is occurring more then once - set an id<br>
     * in case a custom input is used with the input slot it is important to
     * assign the same id to the input element
     */
    id: {
      type: String,
      default: ''
    },

    /**
     * set a placeholder for the input field
     */
    placeholder: {
      type: String,
      default: 'Enter Text Here'
    },

    /**
     * mark as required field (currently only used for aria-required)
     */
    required: {
      type: Boolean,
      default: false
    },

    /**
     * mark the form field as invalid and ideally also provide an error message
     * to display below the form field
     */
    invalid: {
      type: Boolean,
      default: false
    },

    /**
     * add an error message to be displayed below form field if field is invalid
     */
    errorMessage: {
      type: String,
      default: ''
    },

    /**
     * define if error icon should be shown
     */
    showErrorIcon: {
      type: Boolean,
      default: true
    },

    /**
     * set input field in active state from outside<br>
     * the .sync modifier can be used on this prop
     */
    isActive: {
      type: Boolean,
      default: null
    },

    /**
     * option to have the border of the input field not displayed
     */
    showInputBorder: {
      type: Boolean,
      default: true
    },

    /**
     * define if standard form field styling should be
     * used (otherwise no box shadow)
     */
    useFormFieldStyling: {
      type: Boolean,
      default: true
    },

    /**
     * if true a remove icon will be shown allowing to remove
     * all input at once
     */
    clearable: {
      type: Boolean,
      default: false
    },

    /**
     * if true space is reserved for a loader that can be activated
     * with the 'isLoading' prop
     */
    loadable: {
      type: Boolean,
      default: false
    },

    /**
     * show spinner to indicate that something is loading
     * (for dynamically fetched entries that need to do backend requests)
     */
    isLoading: {
      type: Boolean,
      default: false
    },

    /**
     * set a language (ISO 639-1)
     */
    language: {
      type: String,
      default: ''
    },

    /**
     * set true if input field should be disabled
     */
    disabled: {
      type: Boolean,
      default: false
    },

    /**
     * specify the object property that should be used as identifier
     */
    identifierPropertyName: {
      type: String,
      default: 'id'
    },

    /**
     * specify the object property that should be used as value to be displayed
     */
    labelPropertyName: {
      type: String,
      default: 'label'
    },

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

    /**
     * if this is true parent needs to take care of filling the options list on string
     * input etc. - useful for fetching autocomplete options from a backend
     */
    dynamicFetch: {
      type: Boolean,
      default: true
    }
  },
  data: function data() {
    return {
      /**
       * internal input representation passed on to BaseInput
       * @type {?string|Object}
       */
      inputInt: null,

      /**
       * needed for navigation via keyboard in drop down list
       * the index of the current active option in the list array
       * @type {number}
       */
      activeOptionIndex: -1,

      /**
       * internal representation for active state of input and drop down
       * @type {boolean}
       */
      isActiveInt: false
    };
  },
  computed: {
    inputListeners: function inputListeners() {
      return objectSpread2.a(objectSpread2.a({}, this.$listeners), {
        // keep this input from propagating and use own event
        // (handled this way because this input event is only triggered on
        // keyboard input not when I select from the drop down)
        input: function input() {}
      });
    },

    /**
     * compute an internal representation for the list to always have an
     * object with identifier provided to BaseDropDownList
     * @returns {Object[]}
     */
    listInt: function listInt() {
      var _this = this;

      // if list is array of objects - simply return the original prop value
      return !this.optionsIsListOfStrings // else map the array of strings with internal properties and an internal id
      ? this.list : this.list.map(function (option) {
        var _ref;

        return _ref = {}, objectSpread2._(_ref, _this.labelPropertyName, option), objectSpread2._(_ref, _this.identifierPropertyName, "".concat(option, "-").concat(utils.c())), _ref;
      });
    },

    /**
     * additionally if the list is not fetched dynamically filter already selected
     * options from the  list
     * (since inputInt is always only string now this can only be done by comparing
     * the label!)
     */
    filteredListInt: function filteredListInt() {
      var _this2 = this;

      // check if list content is fetched dynamically
      if (!this.dynamicFetch) {
        // if not filter input string by label property
        return this.listInt.filter(function (option) {
          return option[_this2.labelPropertyName].toLowerCase().includes(_this2.inputInt.toLowerCase());
        });
      } // else just return the unmodified list


      return this.listInt;
    },

    /**
     * determine if list prop is array of strings or objects
     * @returns {boolean}
     */
    optionsIsListOfStrings: function optionsIsListOfStrings() {
      return !!this.list && !!this.list.length && typeof this.list[0] === 'string';
    },

    /**
     * the currently active option object
     */
    activeOption: {
      /**
       * setter function of activeOption - will set active option index
       * @param {?Object} val - the active option (by hover or arrow key use)
       */
      set: function set(val) {
        this.activeOptionIndex = this.listInt.indexOf(val);
      },

      /**
       * getter function for activeOption - determined by active option index
       * @returns {?Object}
       */
      get: function get() {
        return this.listInt[this.activeOptionIndex];
      }
    }
  },
  watch: {
    /**
     * watch input prop to update internal representation
     */
    input: {
      handler: function handler(val) {
        if (val !== this.inputInt) {
          this.inputInt = val;
        }
      },
      immediate: true
    },

    /**
     * watch internal input variable to inform parent of changes if necessary
     * @param {Object|string} val
     */
    inputInt: function inputInt(val) {
      if (val !== this.input) {
        /**
         * event triggered when input changes - part of v-model
         * @event input
         * @type {string}
         */
        this.$emit('input', val);
      } // if options should be fetched dynamically trigger event when inputInt changes


      if (this.dynamicFetch) {
        /**
         * an event specifically triggered when drop down should be fetched anew
         * when dynamicFetch is set true
         * @event fetch-dropdown-entries
         * @type {Object}
         * @property {string} value
         */
        this.$emit('fetch-dropdown-entries', {
          value: val
        });
      }
    },
    isActive: {
      /**
       * watch prop isActive to sync with internal variable
       * @param {boolean} val - is input active
       */
      handler: function handler(val) {
        // check first if internal and external variable differ
        if (val !== this.isActiveInt) {
          this.isActiveInt = val;
        }
      },
      immediate: true
    },

    /**
     * watch internal is active variable to be able to inform parent about
     * changes
     * @param {boolean} val
     */
    isActiveInt: function isActiveInt(val) {
      // if input is not active anymore reset the active option index
      if (!val) {
        this.activeOptionIndex = -1;
      } // also inform parent of the state changes


      if (JSON.stringify(val) !== JSON.stringify(this.isActive)) {
        /**
         * update when active state of input field changes
         * the .sync modifier can be used on this event
         * @event update:is-active
         * @type {boolean}
         */
        this.$emit('update:is-active', val);
      }
    }
  },
  methods: {
    /**
     * event for keydown arrow (up, down) key use
     *
     * @param {KeyboardEvent} event - the keydown event
     */
    onArrowKey: function onArrowKey(event) {
      // check if the list has any options
      if (this.listInt.length) {
        // if yes trigger the navigate function
        this.activeOption = this.navigate(this.listInt, event.key === 'ArrowDown', this.activeOptionIndex, false, true);
      }
    },

    /**
     * triggered on keydown enter event and will add
     * a selected option
     */
    onEnter: function onEnter() {
      // check if there is a currently active option
      if (this.activeOption) {
        this.selectOption(this.activeOption); // if enter was not pressed to add an option from the drop down
        // use it to toggle the drop down
      } else {
        this.isActiveInt = false;
      }
    },

    /**
     * if user continues typing after 'enter' (which closes the drop down)
     * the dropdown should open again
     */
    onKeydown: function onKeydown(event) {
      var key = event.key;

      if (!['Tab', 'Enter'].includes(key)) {
        this.isActiveInt = true;
      }
    },

    /**
     * function to toggle the drop down e.g. on space or enter key
     */
    toggleDropDown: function toggleDropDown() {
      this.isActiveInt = !this.isActiveInt;
    },

    /**
     * @param {Object} selectedOption - the option selected from drop down or by keyboard
     * enter - always an object due to internal identifier prop added in case it was a string
     */
    selectOption: function selectOption(selectedOption) {
      var _this3 = this;

      // assign the newly selected value to the input field (only the string from label prop!)
      this.inputInt = selectedOption[this.labelPropertyName]; // if options list was objects also inform parent which option was selected separately

      if (!this.optionsIsListOfStrings) {
        // therefore identify the selected option from the list
        var originalOption = this.list.find(function (option) {
          return option[_this3.identifierPropertyName] === selectedOption[_this3.identifierPropertyName];
        });
        this.$emit('selected', originalOption);
      } else {
        /**
         * inform parent when an option was selected with all information provided in options list
         * (mainly useful when options list was array of objects - if strings this information
         * is provided with input event anyways)
         * @event selected
         * @type {string | Object}
         */
        this.$emit('selected', this.inputInt);
      } // close the drop down and blur input


      this.isActiveInt = false;
    }
  }
};/* 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', {
    staticClass: "base-autocomplete-input"
  }, [_c('BaseInput', _vm._g({
    staticClass: "base-autocomplete-input__input-field",
    attrs: {
      "id": _vm.id,
      "is-active": _vm.isActiveInt,
      "label": _vm.label,
      "show-label": _vm.showLabel,
      "placeholder": _vm.placeholder,
      "required": _vm.required,
      "invalid": _vm.invalid,
      "error-message": _vm.errorMessage,
      "show-error-icon": _vm.showErrorIcon,
      "use-form-field-styling": _vm.useFormFieldStyling,
      "show-input-border": _vm.showInputBorder,
      "clearable": _vm.clearable,
      "loadable": _vm.loadable,
      "is-loading": _vm.isLoading,
      "language": _vm.language,
      "disabled": _vm.disabled,
      "drop-down-list-id": _vm.id + "-list-identifier",
      "linked-list-option": _vm.activeOption ? _vm.activeOption[_vm.identifierPropertyName] : null
    },
    on: {
      "update:isActive": function updateIsActive($event) {
        _vm.isActiveInt = $event;
      },
      "update:is-active": function updateIsActive($event) {
        _vm.isActiveInt = $event;
      },
      "keydown": [function ($event) {
        if (!$event.type.indexOf('key') && _vm._k($event.keyCode, "enter", 13, $event.key, "Enter")) {
          return null;
        }

        $event.preventDefault();
        return _vm.onEnter.apply(null, arguments);
      }, function ($event) {
        if (!$event.type.indexOf('key') && _vm._k($event.keyCode, "up", 38, $event.key, ["Up", "ArrowUp"]) && _vm._k($event.keyCode, "down", 40, $event.key, ["Down", "ArrowDown"])) {
          return null;
        }

        $event.preventDefault();
        return _vm.onArrowKey.apply(null, arguments);
      }, _vm.onKeydown]
    },
    scopedSlots: _vm._u([{
      key: "below-input",
      fn: function fn() {
        return [_vm.isActiveInt ? _c('BaseDropDownList', {
          staticClass: "base-autocomplete-input__drop-down",
          attrs: {
            "drop-down-options": _vm.filteredListInt,
            "active-option": _vm.activeOption,
            "identifier-property-name": _vm.identifierPropertyName,
            "label-property-name": _vm.labelPropertyName,
            "list-id": _vm.id + "-list-identifier",
            "language": _vm.language,
            "drop-down-no-options-info": _vm.dropDownNoOptionsInfo
          },
          on: {
            "update:activeOption": function updateActiveOption($event) {
              _vm.activeOption = $event;
            },
            "update:active-option": function updateActiveOption($event) {
              _vm.activeOption = $event;
            },
            "update:selected-option": _vm.selectOption
          },
          nativeOn: {
            "click": function click($event) {
              $event.stopPropagation();
            },
            "touchstart": function touchstart($event) {
              $event.stopPropagation();
            }
          },
          scopedSlots: _vm._u([{
            key: "option",
            fn: function fn(ref) {
              var option = ref.option;
              return [_vm._t("drop-down-entry", null, {
                "item": option
              })];
            }
          }], null, true)
        }) : _vm._e()];
      },
      proxy: true
    }, {
      key: "label-addition",
      fn: function fn() {
        return [_vm._t("label-addition")];
      },
      proxy: true
    }, {
      key: "pre-input-field",
      fn: function fn() {
        return [_vm._t("pre-input-field")];
      },
      proxy: true
    }, {
      key: "input-field-addition-before",
      fn: function fn() {
        return [_vm._t("input-field-addition-before")];
      },
      proxy: true
    }, {
      key: "input-field-inline-before",
      fn: function fn() {
        return [_vm._t("input-field-inline-before")];
      },
      proxy: true
    }, {
      key: "input-field-addition-after",
      fn: function fn() {
        return [_vm._t("input-field-addition-after")];
      },
      proxy: true
    }, {
      key: "post-input-field",
      fn: function fn() {
        return [_vm._t("post-input-field")];
      },
      proxy: true
    }, {
      key: "error-icon",
      fn: function fn() {
        return [_vm._t("error-icon")];
      },
      proxy: true
    }, {
      key: "remove-icon",
      fn: function fn() {
        return [_vm._t("remove-icon")];
      },
      proxy: true
    }], null, true),
    model: {
      value: _vm.inputInt,
      callback: function callback($$v) {
        _vm.inputInt = $$v;
      },
      expression: "inputInt"
    }
  }, _vm.inputListeners))], 1);
};

var __vue_staticRenderFns__ = [];
/* style */

var __vue_inject_styles__ = undefined;
/* scoped */

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

var __vue_module_identifier__ = "data-v-0dee7fb3";
/* functional template */

var __vue_is_functional_template__ = false;
/* style inject */

/* style inject SSR */

/* style inject shadow dom */

var __vue_component__ = /*#__PURE__*/normalizeComponent.n({
  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 BaseAutocompleteInput = __vue_component__;exports["default"]=BaseAutocompleteInput;