import _extends from "@babel/runtime/helpers/extends";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
import _inherits from "@babel/runtime/helpers/inherits";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
var _excluded = ["data-test-subj", "async", "className", "compressed", "customOptionText", "fullWidth", "id", "inputRef", "isCaseSensitive", "isClearable", "isDisabled", "isInvalid", "isLoading", "noSuggestions", "onBlur", "onChange", "onCreateOption", "onSearchChange", "options", "placeholder", "renderOption", "rowHeight", "selectedOptions", "singleSelection", "prepend", "sortMatchesBy", "delimiter", "append", "autoFocus", "onFocusBadge", "truncationProps", "inputPopoverProps", "optionMatcher", "aria-label", "aria-labelledby", "aria-describedby"];
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0 and the Server Side Public License, v 1; you may not use this file except
 * in compliance with, at your election, the Elastic License 2.0 or the Server
 * Side Public License, v 1.
 */

/**
 * Elements within EuiComboBox which would normally be tabbable (inputs, buttons) have been removed
 * from the tab order with tabindex={-1} so that we can control the keyboard navigation interface.
 */
import React, { Component } from 'react';
import classNames from 'classnames';
import { RenderWithEuiTheme, htmlIdGenerator, keys } from '../../services';
import { logicalStyle } from '../../global_styling';
import { EuiInputPopover } from '../popover';
import { EuiI18n } from '../i18n';
import { euiFormMaxWidth } from '../form/form.styles';
import { getMatchingOptions, flattenOptionGroups, getSelectedOptionForSearchValue, transformForCaseSensitivity, createPartialStringEqualityOptionMatcher } from './matching_options';
import { EuiComboBoxInput } from './combo_box_input/combo_box_input';
import { EuiComboBoxOptionsList } from './combo_box_options_list';
import { euiComboBoxStyles as styles } from './combo_box.styles';

/**
 * Because of how TypeScript's LibraryManagedAttributes is designed to handle defaultProps (https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#support-for-defaultprops-in-jsx)
 * we can't directly export the above Props definitions, as the defaulted values are not made optional
 * as it isn't processed by LibraryManagedAttributes. To get around this, we:
 * - remove the props which have default values applied
 *   - additionally re-define `options` and `selectedOptions` defaults, necessary as static members can't access generics and become never[]
 * - export (Props - Defaults) & Partial<Defaults>
 */
import { jsx as ___EmotionJSX } from "@emotion/react";
var initialSearchValue = '';
export var EuiComboBox = /*#__PURE__*/function (_Component) {
  function EuiComboBox() {
    var _this;
    _classCallCheck(this, EuiComboBox);
    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }
    _this = _callSuper(this, EuiComboBox, [].concat(args));
    _defineProperty(_this, "state", {
      activeOptionIndex: -1,
      hasFocus: false,
      isListOpen: false,
      matchingOptions: getMatchingOptions({
        options: _this.props.options,
        selectedOptions: _this.props.selectedOptions,
        searchValue: initialSearchValue,
        optionMatcher: _this.props.optionMatcher,
        isCaseSensitive: _this.props.isCaseSensitive,
        isPreFiltered: _this.props.async,
        showPrevSelected: Boolean(_this.props.singleSelection),
        sortMatchesBy: _this.props.sortMatchesBy
      }),
      listOptionRefs: [],
      searchValue: initialSearchValue
    });
    _defineProperty(_this, "rootId", htmlIdGenerator());
    // Refs
    _defineProperty(_this, "comboBoxRefInstance", null);
    _defineProperty(_this, "comboBoxRefCallback", function (ref) {
      _this.comboBoxRefInstance = ref;
    });
    _defineProperty(_this, "searchInputRefInstance", null);
    _defineProperty(_this, "searchInputRefCallback", function (ref) {
      var _this$props$inputRef, _this$props;
      _this.searchInputRefInstance = ref;
      (_this$props$inputRef = (_this$props = _this.props).inputRef) === null || _this$props$inputRef === void 0 || _this$props$inputRef.call(_this$props, ref);
    });
    _defineProperty(_this, "listRefInstance", null);
    _defineProperty(_this, "listRefCallback", function (ref) {
      _this.listRefInstance = ref;
    });
    _defineProperty(_this, "setListOptionRefs", function (node, index) {
      var current = _this.state.listOptionRefs[index];
      // Skip updating if the ref is null (on cleanup) or didn't change
      if (node === null || node === current) return;
      _this.setState(function (_ref) {
        var listOptionRefs = _ref.listOptionRefs;
        var _listOptionRefs = listOptionRefs;
        _listOptionRefs[index] = node;
        return {
          listOptionRefs: _listOptionRefs
        };
      });
    });
    _defineProperty(_this, "openList", function () {
      _this.setState({
        isListOpen: true
      });
    });
    _defineProperty(_this, "closeList", function () {
      _this.clearActiveOption();
      _this.setState({
        isListOpen: false
      });
    });
    _defineProperty(_this, "findNextSelectableOptionIndex", function (options, startIndex) {
      var direction = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
      if (!options.length) return -1;
      var index = startIndex;
      for (var count = 0; count < options.length; count++) {
        var option = options[index];
        if (!option.isGroupLabelOption && !option.disabled) {
          return index;
        }
        index = (index + direction + options.length) % options.length;
      }
      return -1; // the remaining options can't be selected (group labels or disabled)
    });
    _defineProperty(_this, "incrementActiveOptionIndex", function (amount) {
      if (!_this.state.matchingOptions.length) return;
      _this.setState(function (_ref2) {
        var activeOptionIndex = _ref2.activeOptionIndex,
          matchingOptions = _ref2.matchingOptions;
        var direction = amount > 0 ? 1 : -1;
        var startIndex = activeOptionIndex < 0 ?
        // Inintial interaction: jump to first or last item
        amount < 0 ? matchingOptions.length - 1 : 0 :
        // Advance by amount, wrapping around
        (activeOptionIndex + amount + matchingOptions.length) % matchingOptions.length;
        return {
          activeOptionIndex: _this.findNextSelectableOptionIndex(matchingOptions, startIndex, direction)
        };
      });
    });
    _defineProperty(_this, "hasActiveOption", function () {
      return _this.state.activeOptionIndex > -1 && _this.state.activeOptionIndex < _this.state.matchingOptions.length;
    });
    _defineProperty(_this, "clearActiveOption", function () {
      _this.setState({
        activeOptionIndex: -1
      });
    });
    _defineProperty(_this, "clearSearchValue", function () {
      _this.onSearchChange('');
    });
    _defineProperty(_this, "addCustomOption", function (isContainerBlur, searchValue) {
      var _this$props2 = _this.props,
        isCaseSensitive = _this$props2.isCaseSensitive,
        onCreateOption = _this$props2.onCreateOption,
        options = _this$props2.options,
        selectedOptions = _this$props2.selectedOptions,
        singleSelection = _this$props2.singleSelection;
      var matchedOption = _this.doesSearchMatchOnlyOption();
      if (matchedOption) {
        return _this.onAddOption(matchedOption, isContainerBlur);
      }
      if (!onCreateOption) {
        return;
      }

      // Don't bother trying to create an option if the user hasn't typed anything.
      if (!searchValue) {
        return;
      }

      // Don't create the value if it's already been selected.
      if (getSelectedOptionForSearchValue({
        isCaseSensitive: isCaseSensitive,
        searchValue: searchValue,
        selectedOptions: selectedOptions
      })) {
        return;
      }

      // Add new custom pill if this is custom input, even if it partially matches an option.
      var isOptionCreated = onCreateOption(searchValue, flattenOptionGroups(options));

      // Expect the consumer to be explicit in rejecting a custom option.
      if (isOptionCreated === false) {
        return;
      }
      _this.clearSearchValue();
      if (Boolean(singleSelection)) {
        // Adding a custom option to a single select that does not appear in the list of options
        _this.closeList();
      }
    });
    _defineProperty(_this, "doesSearchMatchOnlyOption", function () {
      var isCaseSensitive = _this.props.isCaseSensitive;
      var _this$state = _this.state,
        matchingOptions = _this$state.matchingOptions,
        searchValue = _this$state.searchValue;
      if (!matchingOptions.length) return;
      var isMatchWithGroup = matchingOptions[0].isGroupLabelOption;
      var isOnlyOption = matchingOptions.length === (isMatchWithGroup ? 2 : 1);
      if (!isOnlyOption) return;
      var matchedOption = matchingOptions[isMatchWithGroup ? 1 : 0];
      var normalizedSearchSubject = transformForCaseSensitivity(matchedOption.label, isCaseSensitive);
      var normalizedSearchValue = transformForCaseSensitivity(searchValue, isCaseSensitive);
      if (normalizedSearchSubject === normalizedSearchValue) {
        return matchedOption;
      }
    });
    _defineProperty(_this, "areAllOptionsSelected", function () {
      var _this$props3 = _this.props,
        options = _this$props3.options,
        selectedOptions = _this$props3.selectedOptions,
        async = _this$props3.async,
        isCaseSensitive = _this$props3.isCaseSensitive;
      // Assume if this is async then there could be infinite options.
      if (async) {
        return false;
      }
      var flattenOptions = flattenOptionGroups(options).map(function (option) {
        return _objectSpread(_objectSpread({}, option), {}, {
          label: transformForCaseSensitivity(option.label.trim(), isCaseSensitive)
        });
      });
      var numberOfSelectedOptions = 0;
      selectedOptions.forEach(function (_ref3) {
        var label = _ref3.label;
        var trimmedLabel = transformForCaseSensitivity(label.trim(), isCaseSensitive);
        if (flattenOptions.findIndex(function (option) {
          return option.label === trimmedLabel;
        }) !== -1) numberOfSelectedOptions += 1;
      });
      return flattenOptions.length === numberOfSelectedOptions;
    });
    _defineProperty(_this, "onComboBoxFocus", function (event) {
      var _this$props$onFocus, _this$props4;
      (_this$props$onFocus = (_this$props4 = _this.props).onFocus) === null || _this$props$onFocus === void 0 || _this$props$onFocus.call(_this$props4, event);
      _this.openList();
      _this.setState({
        hasFocus: true
      });
    });
    _defineProperty(_this, "setCustomOptions", function (isContainerBlur) {
      var searchValue = _this.state.searchValue;
      var delimiter = _this.props.delimiter;
      if (delimiter) {
        var trimmed = searchValue.split(delimiter).map(function (value) {
          return value.trim();
        });
        var values = _toConsumableArray(new Set(_toConsumableArray(trimmed)));
        values.forEach(function (option) {
          if (option.length > 0) _this.addCustomOption(isContainerBlur, option);
        });
      } else {
        _this.addCustomOption(isContainerBlur, searchValue);
      }
    });
    _defineProperty(_this, "onContainerBlur", function (event) {
      // close the options list, unless the user clicked on an option
      var relatedTarget = event.relatedTarget;
      var focusedInOptionsList = relatedTarget && _this.listRefInstance && _this.listRefInstance.contains(relatedTarget);
      var focusedInInput = relatedTarget && _this.comboBoxRefInstance && _this.comboBoxRefInstance.contains(relatedTarget);
      if (!focusedInOptionsList && !focusedInInput) {
        var _this$props$onBlur, _this$props5;
        (_this$props$onBlur = (_this$props5 = _this.props).onBlur) === null || _this$props$onBlur === void 0 || _this$props$onBlur.call(_this$props5, event);
        _this.closeList();
        _this.setState({
          hasFocus: false
        });

        // If the user tabs away or changes focus to another element, take whatever input they've
        // typed and convert it into a pill, to prevent the combo box from looking like a text input.
        if (!_this.hasActiveOption()) {
          _this.setCustomOptions(true);
        }
      } else if (focusedInOptionsList) {
        // https://github.com/elastic/eui/issues/5179
        // need to restore focus to the input box when clicking non-interactive elements

        // firefox doesn't support calling .focus() during a blur event
        // https://bugzilla.mozilla.org/show_bug.cgi?id=53579
        requestAnimationFrame(function () {
          var _this$searchInputRefI;
          (_this$searchInputRefI = _this.searchInputRefInstance) === null || _this$searchInputRefI === void 0 || _this$searchInputRefI.focus();
        });
      }
    });
    _defineProperty(_this, "onKeyDown", function (event) {
      var _this$props$onKeyDown, _this$props6;
      if (_this.props.isDisabled) return;
      event.persist(); // TODO: Remove once React 16 support is dropped
      switch (event.key) {
        case keys.ARROW_UP:
          event.preventDefault();
          event.stopPropagation();
          if (_this.state.isListOpen) {
            _this.incrementActiveOptionIndex(-1);
          } else {
            _this.openList();
          }
          break;
        case keys.ARROW_DOWN:
          event.preventDefault();
          event.stopPropagation();
          if (_this.state.isListOpen) {
            _this.incrementActiveOptionIndex(1);
          } else {
            _this.openList();
          }
          break;
        case keys.ESCAPE:
          if (_this.state.isListOpen) {
            event.preventDefault();
            event.stopPropagation();
            _this.closeList();
          }
          break;
        case keys.ENTER:
          // Do not block enter keypresses for the clear button or delete selection buttons
          if (event.target === _this.searchInputRefInstance) {
            event.preventDefault();
            event.stopPropagation();
            if (_this.hasActiveOption()) {
              _this.onAddOption(_this.state.matchingOptions[_this.state.activeOptionIndex]);
            } else {
              _this.setCustomOptions(false);
            }
          }
          break;
        case keys.TAB:
          // Disallow tabbing when the user is navigating the options.
          if (_this.hasActiveOption() && _this.state.isListOpen) {
            event.preventDefault();
            event.stopPropagation();
          }
          break;
        default:
          (_this$props$onKeyDown = (_this$props6 = _this.props).onKeyDown) === null || _this$props$onKeyDown === void 0 || _this$props$onKeyDown.call(_this$props6, event);
      }
    });
    _defineProperty(_this, "onOptionEnterKey", function (option) {
      _this.onAddOption(option);
    });
    _defineProperty(_this, "onOptionClick", function (option) {
      _this.onAddOption(option);
    });
    _defineProperty(_this, "onAddOption", function (addedOption, isContainerBlur) {
      if (addedOption.disabled) {
        return;
      }
      var _this$props7 = _this.props,
        onChange = _this$props7.onChange,
        selectedOptions = _this$props7.selectedOptions,
        singleSelectionProp = _this$props7.singleSelection;
      var _this$state2 = _this.state,
        matchingOptions = _this$state2.matchingOptions,
        listOptionRefs = _this$state2.listOptionRefs;
      var singleSelection = Boolean(singleSelectionProp);
      var changeOptions = singleSelection ? [addedOption] : selectedOptions.concat(addedOption);
      onChange === null || onChange === void 0 || onChange(changeOptions);
      _this.clearSearchValue();
      if (singleSelection) {
        // List closes after single selection; return focus to the input
        _this.clearActiveOption();
        if (!isContainerBlur) {
          var _this$searchInputRefI2;
          (_this$searchInputRefI2 = _this.searchInputRefInstance) === null || _this$searchInputRefI2 === void 0 || _this$searchInputRefI2.focus();
        }
        requestAnimationFrame(function () {
          return _this.closeList();
        });
      } else if (isContainerBlur) {
        // User tabbed away. `onContainerBlur` will close the list. We're only cleaning up state
        _this.clearActiveOption();
      } else {
        var currentIndex = matchingOptions.indexOf(addedOption);
        var nextOptions = matchingOptions.filter(function (option) {
          return option !== addedOption;
        });
        _this.setState({
          listOptionRefs: listOptionRefs.slice(0, matchingOptions.length - 1),
          activeOptionIndex: _this.findNextSelectableOptionIndex(nextOptions, Math.min(currentIndex, nextOptions.length - 1)
          // direction defaults to 1 (forward)
          )
        });
      }
    });
    _defineProperty(_this, "onRemoveOption", function (removedOption) {
      var _this$props8 = _this.props,
        onChange = _this$props8.onChange,
        selectedOptions = _this$props8.selectedOptions;
      onChange === null || onChange === void 0 || onChange(selectedOptions.filter(function (option) {
        return option !== removedOption;
      }));
      _this.clearActiveOption();
    });
    _defineProperty(_this, "clearSelectedOptions", function () {
      var _this$props$onChange, _this$props9, _this$searchInputRefI3;
      (_this$props$onChange = (_this$props9 = _this.props).onChange) === null || _this$props$onChange === void 0 || _this$props$onChange.call(_this$props9, []);

      // Clicking the clear button will also cause it to disappear. This would result in focus
      // shifting unexpectedly to the body element so we set it to the input which is more reasonable,
      (_this$searchInputRefI3 = _this.searchInputRefInstance) === null || _this$searchInputRefI3 === void 0 || _this$searchInputRefI3.focus();
      if (!_this.state.isListOpen) {
        _this.openList();
      }
    });
    _defineProperty(_this, "onComboBoxClick", function () {
      var _this$searchInputRefI4;
      // When the user clicks anywhere on the box, enter the interaction state.
      (_this$searchInputRefI4 = _this.searchInputRefInstance) === null || _this$searchInputRefI4 === void 0 || _this$searchInputRefI4.focus();

      // If the user does this from a state in which an option has focus, then we need to reset it or clear it.
      if (Boolean(_this.props.singleSelection) && _this.props.selectedOptions.length === 1) {
        var selectedOptionIndex = _this.state.matchingOptions.findIndex(function (option) {
          return option.label === _this.props.selectedOptions[0].label && option.key === _this.props.selectedOptions[0].key;
        });
        _this.setState({
          activeOptionIndex: selectedOptionIndex
        });
      } else {
        _this.clearActiveOption();
      }
    });
    _defineProperty(_this, "onOpenListClick", function () {
      var _this$searchInputRefI5;
      (_this$searchInputRefI5 = _this.searchInputRefInstance) === null || _this$searchInputRefI5 === void 0 || _this$searchInputRefI5.focus();
      if (!_this.state.isListOpen) {
        _this.openList();
      }
    });
    _defineProperty(_this, "onOptionListScroll", function () {
      var _this$searchInputRefI6;
      (_this$searchInputRefI6 = _this.searchInputRefInstance) === null || _this$searchInputRefI6 === void 0 || _this$searchInputRefI6.focus();
    });
    _defineProperty(_this, "onSearchChange", function (searchValue) {
      var _this$props10 = _this.props,
        onSearchChange = _this$props10.onSearchChange,
        delimiter = _this$props10.delimiter;
      _this.setState({
        searchValue: searchValue
      }, function () {
        if (searchValue && _this.state.isListOpen === false) {
          _this.openList();
        }
        if (onSearchChange) {
          var hasMatchingOptions = _this.state.matchingOptions.length > 0;
          onSearchChange(searchValue, hasMatchingOptions);
        }
      });
      if (delimiter && searchValue.endsWith(delimiter)) {
        _this.setCustomOptions(false);
      }
    });
    return _this;
  }
  _inherits(EuiComboBox, _Component);
  return _createClass(EuiComboBox, [{
    key: "render",
    value: function render() {
      var _this2 = this;
      var _this$props11 = this.props,
        dataTestSubj = _this$props11['data-test-subj'],
        async = _this$props11.async,
        className = _this$props11.className,
        compressed = _this$props11.compressed,
        customOptionText = _this$props11.customOptionText,
        fullWidth = _this$props11.fullWidth,
        id = _this$props11.id,
        inputRef = _this$props11.inputRef,
        isCaseSensitive = _this$props11.isCaseSensitive,
        isClearable = _this$props11.isClearable,
        isDisabled = _this$props11.isDisabled,
        isInvalid = _this$props11.isInvalid,
        isLoading = _this$props11.isLoading,
        noSuggestions = _this$props11.noSuggestions,
        onBlur = _this$props11.onBlur,
        onChange = _this$props11.onChange,
        onCreateOption = _this$props11.onCreateOption,
        onSearchChange = _this$props11.onSearchChange,
        options = _this$props11.options,
        placeholder = _this$props11.placeholder,
        renderOption = _this$props11.renderOption,
        rowHeight = _this$props11.rowHeight,
        selectedOptions = _this$props11.selectedOptions,
        singleSelection = _this$props11.singleSelection,
        prepend = _this$props11.prepend,
        sortMatchesBy = _this$props11.sortMatchesBy,
        delimiter = _this$props11.delimiter,
        append = _this$props11.append,
        autoFocus = _this$props11.autoFocus,
        onFocusBadge = _this$props11.onFocusBadge,
        truncationProps = _this$props11.truncationProps,
        inputPopoverProps = _this$props11.inputPopoverProps,
        optionMatcher = _this$props11.optionMatcher,
        ariaLabel = _this$props11['aria-label'],
        ariaLabelledby = _this$props11['aria-labelledby'],
        ariaDescribedby = _this$props11['aria-describedby'],
        rest = _objectWithoutProperties(_this$props11, _excluded);
      var _this$state3 = this.state,
        activeOptionIndex = _this$state3.activeOptionIndex,
        hasFocus = _this$state3.hasFocus,
        isListOpen = _this$state3.isListOpen,
        searchValue = _this$state3.searchValue,
        matchingOptions = _this$state3.matchingOptions;

      // Make sure we have a valid ID if users don't pass one as a prop
      var inputId = id !== null && id !== void 0 ? id : this.rootId('_eui-combobox-id');

      // Visually indicate the combobox is in an invalid state if it has lost focus but there is text entered in the input.
      // When custom options are disabled and the user leaves the combo box after entering text that does not match any
      // options, this tells the user that they've entered invalid input.
      var markAsInvalid = !!(isInvalid || (hasFocus === false || isListOpen === false) && searchValue);
      var classes = classNames('euiComboBox', className, {
        'euiComboBox-isDisabled': isDisabled,
        'euiComboBox-isInvalid': markAsInvalid,
        'euiComboBox-isOpen': isListOpen
      });
      var value = selectedOptions.map(function (selectedOption) {
        return selectedOption.label;
      }).join(', ');
      var optionsList;
      if (!noSuggestions && isListOpen) {
        var optionsListDataTestSubj = dataTestSubj ? "".concat(dataTestSubj, "-optionsList") : undefined;
        optionsList = ___EmotionJSX(EuiI18n, {
          token: "euiComboBox.listboxAriaLabel",
          default: "Choose from the following options"
        }, function (listboxAriaLabel) {
          return ___EmotionJSX(EuiComboBoxOptionsList, {
            activeOptionIndex: _this2.state.activeOptionIndex,
            areAllOptionsSelected: _this2.areAllOptionsSelected(),
            customOptionText: customOptionText,
            "data-test-subj": optionsListDataTestSubj,
            fullWidth: fullWidth,
            isCaseSensitive: isCaseSensitive,
            isLoading: isLoading,
            listRef: _this2.listRefCallback,
            setListOptionRefs: _this2.setListOptionRefs,
            matchingOptions: matchingOptions,
            onCloseList: _this2.closeList,
            onCreateOption: onCreateOption,
            onOptionClick: _this2.onOptionClick,
            onOptionEnterKey: _this2.onOptionEnterKey,
            onScroll: _this2.onOptionListScroll,
            options: options,
            singleSelection: singleSelection,
            renderOption: renderOption,
            rootId: _this2.rootId,
            rowHeight: rowHeight,
            scrollToIndex: activeOptionIndex,
            searchValue: searchValue,
            selectedOptions: selectedOptions,
            delimiter: delimiter,
            getSelectedOptionForSearchValue: getSelectedOptionForSearchValue,
            listboxAriaLabel: listboxAriaLabel,
            truncationProps: truncationProps,
            onFocusBadge: onFocusBadge
          });
        });
      }
      return (
        /**
         * EuiComboBox follows the WAI-ARIA 1.2 spec for editable comboboxes
         * with list autocomplete. This pattern is an improvement on the user
         * experience for screen readers over the WAI-ARIA 1.1 pattern.
         *
         * https://www.w3.org/TR/wai-aria-practices-1.2/examples/combobox/combobox-autocomplete-list.html
         */
        ___EmotionJSX(RenderWithEuiTheme, null, function (euiTheme) {
          var _this2$state$listOpti, _this2$state$listOpti2;
          var cssStyles = [styles.euiComboBox, fullWidth ? styles.fullWidth : logicalStyle('max-width', euiFormMaxWidth(euiTheme))];
          return ___EmotionJSX("div", _extends({
            css: cssStyles
          }, rest, {
            className: classes,
            "data-test-subj": dataTestSubj,
            onKeyDown: _this2.onKeyDown,
            onBlur: _this2.onContainerBlur,
            ref: _this2.comboBoxRefCallback
          }), ___EmotionJSX(EuiInputPopover, _extends({
            fullWidth: fullWidth,
            panelPaddingSize: "s",
            disableFocusTrap: true,
            closeOnScroll: true
          }, inputPopoverProps, {
            isOpen: isListOpen && !noSuggestions,
            closePopover: _this2.closeList
            /* we don't want content changes to be announced via aria-live 
            because ComboBox uses a virtualized list that updates itself
            on scroll and would result in unexpected screen reader output */,
            "aria-live": "off",
            input: ___EmotionJSX(EuiComboBoxInput, {
              compressed: compressed,
              focusedOptionId: _this2.hasActiveOption() ? (_this2$state$listOpti = (_this2$state$listOpti2 = _this2.state.listOptionRefs[_this2.state.activeOptionIndex]) === null || _this2$state$listOpti2 === void 0 ? void 0 : _this2$state$listOpti2.id) !== null && _this2$state$listOpti !== void 0 ? _this2$state$listOpti :
              // uses the original `options` array to ensure a stable `id`, otherwise `aria-activedescendant`
              // loses focus on selecting an option (due to actively removing it from the list)
              _this2.rootId("_option-".concat(_this2.props.options.indexOf(matchingOptions[activeOptionIndex]))) : undefined,
              fullWidth: fullWidth,
              hasSelectedOptions: selectedOptions.length > 0,
              id: inputId,
              inputRef: _this2.searchInputRefCallback,
              isDisabled: isDisabled,
              isListOpen: isListOpen,
              noIcon: !!noSuggestions,
              onChange: _this2.onSearchChange,
              onClear: isClearable && !isDisabled ? _this2.clearSelectedOptions : undefined,
              onClick: _this2.onComboBoxClick,
              onCloseListClick: _this2.closeList,
              onFocus: _this2.onComboBoxFocus,
              onOpenListClick: _this2.onOpenListClick,
              onRemoveOption: _this2.onRemoveOption,
              placeholder: placeholder,
              rootId: _this2.rootId,
              searchValue: searchValue,
              selectedOptions: selectedOptions,
              singleSelection: singleSelection,
              value: value,
              append: singleSelection ? append : undefined,
              prepend: singleSelection ? prepend : undefined,
              isLoading: isLoading,
              isInvalid: markAsInvalid,
              autoFocus: autoFocus,
              "aria-label": ariaLabel,
              "aria-labelledby": ariaLabelledby,
              "aria-describedby": ariaDescribedby
            })
          }), optionsList));
        })
      );
    }
  }], [{
    key: "getDerivedStateFromProps",
    value: function getDerivedStateFromProps(nextProps, prevState) {
      var async = nextProps.async,
        isCaseSensitive = nextProps.isCaseSensitive,
        options = nextProps.options,
        selectedOptions = nextProps.selectedOptions,
        singleSelection = nextProps.singleSelection,
        sortMatchesBy = nextProps.sortMatchesBy,
        optionMatcher = nextProps.optionMatcher;
      var activeOptionIndex = prevState.activeOptionIndex,
        searchValue = prevState.searchValue;

      // Calculate and cache the options which match the searchValue, because we use this information
      // in multiple places and it would be expensive to calculate repeatedly.
      var matchingOptions = getMatchingOptions({
        options: options,
        selectedOptions: selectedOptions,
        searchValue: searchValue,
        isCaseSensitive: isCaseSensitive,
        isPreFiltered: async,
        showPrevSelected: Boolean(singleSelection),
        sortMatchesBy: sortMatchesBy,
        optionMatcher: optionMatcher
      });
      var stateUpdate = {
        matchingOptions: matchingOptions
      };
      if (activeOptionIndex >= matchingOptions.length) {
        stateUpdate.activeOptionIndex = -1;
      }
      return stateUpdate;
    }
  }]);
}(Component);
_defineProperty(EuiComboBox, "defaultProps", {
  async: false,
  compressed: false,
  fullWidth: false,
  isClearable: true,
  options: [],
  selectedOptions: [],
  singleSelection: false,
  prepend: undefined,
  append: undefined,
  sortMatchesBy: 'none',
  optionMatcher: createPartialStringEqualityOptionMatcher()
});