'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.EuiComboBox = undefined;

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _lodash = require('lodash');

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _propTypes = require('prop-types');

var _propTypes2 = _interopRequireDefault(_propTypes);

var _classnames = require('classnames');

var _classnames2 = _interopRequireDefault(_classnames);

var _tabbable = require('tabbable');

var _tabbable2 = _interopRequireDefault(_tabbable);

var _services = require('../../services');

var _key_codes = require('../../services/key_codes');

var _portal = require('../portal');

var _combo_box_input = require('./combo_box_input');

var _combo_box_options_list = require('./combo_box_options_list');

var _matching_options = require('./matching_options');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * 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.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */

var EuiComboBox = exports.EuiComboBox = function (_Component) {
  _inherits(EuiComboBox, _Component);

  function EuiComboBox(props) {
    _classCallCheck(this, EuiComboBox);

    var _this = _possibleConstructorReturn(this, (EuiComboBox.__proto__ || Object.getPrototypeOf(EuiComboBox)).call(this, props));

    _initialiseProps.call(_this);

    var initialSearchValue = '';
    var options = props.options,
        selectedOptions = props.selectedOptions;


    _this.state = {
      matchingOptions: (0, _matching_options.getMatchingOptions)(options, selectedOptions, initialSearchValue, props.async),
      listElement: undefined,
      searchValue: initialSearchValue,
      isListOpen: false,
      listPosition: 'bottom',
      activeOptionIndex: undefined
    };

    // Refs.
    _this.comboBox = undefined;
    _this.autoSizeInput = undefined;
    _this.searchInput = undefined;
    _this.optionsList = undefined;
    _this.options = [];
    return _this;
  }

  _createClass(EuiComboBox, [{
    key: 'componentDidMount',
    value: function componentDidMount() {
      var _this2 = this;

      this._isMounted = true;

      // TODO: This will need to be called once the actual stylesheet loads.
      setTimeout(function () {
        if (_this2.autoSizeInput) {
          _this2.autoSizeInput.copyInputStyles();
        }
      }, 100);
    }
  }, {
    key: 'updateMatchingOptionsIfDifferent',
    value: function updateMatchingOptionsIfDifferent(newMatchingOptions) {
      var matchingOptions = this.state.matchingOptions;


      var areOptionsDifferent = false;

      if (matchingOptions.length !== newMatchingOptions.length) {
        areOptionsDifferent = true;
      } else {
        for (var i = 0; i < matchingOptions.length; i++) {
          if (matchingOptions[i].label !== newMatchingOptions[i].label) {
            areOptionsDifferent = true;
            break;
          }
        }
      }

      if (areOptionsDifferent) {
        this.options = [];
        this.setState({ matchingOptions: newMatchingOptions });

        if (!newMatchingOptions.length) {
          // Prevent endless setState -> componentWillUpdate -> setState loop.
          if (this.state.hasActiveOption) {
            this.clearActiveOption();
          }
        }
      }
    }
  }, {
    key: 'componentDidUpdate',
    value: function componentDidUpdate() {
      var _props = this.props,
          options = _props.options,
          selectedOptions = _props.selectedOptions;
      var searchValue = this.state.searchValue;

      // React 16.3 has a bug (fixed in 16.4) where getDerivedStateFromProps
      // isn't called after a state change, and we track `searchValue` in state
      // instead we need to react to a change in searchValue here

      this.updateMatchingOptionsIfDifferent((0, _matching_options.getMatchingOptions)(options, selectedOptions, searchValue, this.props.async));

      this.focusActiveOption();
    }
  }, {
    key: 'componentWillUnmount',
    value: function componentWillUnmount() {
      this.incrementActiveOptionIndex.cancel();
      this._isMounted = false;
      document.removeEventListener('click', this.onDocumentFocusChange);
      document.removeEventListener('focusin', this.onDocumentFocusChange);
    }
  }, {
    key: 'render',
    value: function render() {
      var _props2 = this.props,
          id = _props2.id,
          isDisabled = _props2.isDisabled,
          className = _props2.className,
          isLoading = _props2.isLoading,
          options = _props2.options,
          selectedOptions = _props2.selectedOptions,
          onCreateOption = _props2.onCreateOption,
          placeholder = _props2.placeholder,
          noSuggestions = _props2.noSuggestions,
          renderOption = _props2.renderOption,
          singleSelection = _props2.singleSelection,
          onChange = _props2.onChange,
          onSearchChange = _props2.onSearchChange,
          async = _props2.async,
          isInvalid = _props2.isInvalid,
          rowHeight = _props2.rowHeight,
          isClearable = _props2.isClearable,
          rest = _objectWithoutProperties(_props2, ['id', 'isDisabled', 'className', 'isLoading', 'options', 'selectedOptions', 'onCreateOption', 'placeholder', 'noSuggestions', 'renderOption', 'singleSelection', 'onChange', 'onSearchChange', 'async', 'isInvalid', 'rowHeight', 'isClearable']);

      var _state = this.state,
          searchValue = _state.searchValue,
          isListOpen = _state.isListOpen,
          listPosition = _state.listPosition,
          width = _state.width,
          activeOptionIndex = _state.activeOptionIndex;


      var classes = (0, _classnames2.default)('euiComboBox', className, {
        'euiComboBox-isOpen': isListOpen,
        'euiComboBox-isInvalid': isInvalid,
        'euiComboBox-isDisabled': isDisabled
      });

      var value = selectedOptions.map(function (selectedOption) {
        return selectedOption.label;
      }).join(', ');

      var optionsList = void 0;

      if (!noSuggestions && isListOpen) {
        optionsList = _react2.default.createElement(
          _portal.EuiPortal,
          null,
          _react2.default.createElement(_combo_box_options_list.EuiComboBoxOptionsList, {
            isLoading: isLoading,
            options: options,
            selectedOptions: selectedOptions,
            onCreateOption: onCreateOption,
            searchValue: searchValue,
            matchingOptions: this.state.matchingOptions,
            listRef: this.optionsListRef,
            optionRef: this.optionRef,
            onOptionClick: this.onOptionClick,
            onOptionEnterKey: this.onOptionEnterKey,
            areAllOptionsSelected: this.areAllOptionsSelected(),
            getSelectedOptionForSearchValue: _matching_options.getSelectedOptionForSearchValue,
            updatePosition: this.updateListPosition,
            position: listPosition,
            renderOption: renderOption,
            width: width,
            scrollToIndex: activeOptionIndex,
            onScroll: this.focusActiveOption,
            rowHeight: rowHeight
          })
        );
      }

      return _react2.default.createElement(
        'div',
        _extends({
          className: classes,
          onFocus: this.onComboBoxFocus,
          onKeyDown: this.onKeyDown,
          ref: this.comboBoxRef
        }, rest),
        _react2.default.createElement(_combo_box_input.EuiComboBoxInput, {
          id: id,
          placeholder: placeholder,
          selectedOptions: selectedOptions,
          onRemoveOption: this.onRemoveOption,
          onClick: this.onComboBoxClick,
          onChange: this.onSearchChange,
          onFocus: this.onFocus,
          value: value,
          searchValue: searchValue,
          autoSizeInputRef: this.autoSizeInputRef,
          inputRef: this.searchInputRef,
          updatePosition: this.updateListPosition,
          onClear: isClearable && !isDisabled ? this.clearSelectedOptions : undefined,
          hasSelectedOptions: selectedOptions.length > 0,
          isListOpen: isListOpen,
          onOpenListClick: this.onOpenListClick,
          onCloseListClick: this.onCloseListClick,
          singleSelection: singleSelection,
          isDisabled: isDisabled,
          toggleButtonRef: this.toggleButtonRef
        }),
        optionsList
      );
    }
  }], [{
    key: 'getDerivedStateFromProps',
    value: function getDerivedStateFromProps(nextProps, prevState) {
      var options = nextProps.options,
          selectedOptions = nextProps.selectedOptions;
      var 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 = (0, _matching_options.getMatchingOptions)(options, selectedOptions, searchValue, nextProps.async);

      return { matchingOptions: matchingOptions };
    }
  }]);

  return EuiComboBox;
}(_react.Component);

EuiComboBox.propTypes = {
  id: _propTypes2.default.string,
  isDisabled: _propTypes2.default.bool,
  className: _propTypes2.default.string,
  placeholder: _propTypes2.default.string,
  isLoading: _propTypes2.default.bool,
  async: _propTypes2.default.bool,
  singleSelection: _propTypes2.default.bool,
  noSuggestions: _propTypes2.default.bool,
  options: _propTypes2.default.array,
  selectedOptions: _propTypes2.default.array,
  onChange: _propTypes2.default.func,
  onSearchChange: _propTypes2.default.func,
  onCreateOption: _propTypes2.default.func,
  renderOption: _propTypes2.default.func,
  isInvalid: _propTypes2.default.bool,
  rowHeight: _propTypes2.default.number,
  isClearable: _propTypes2.default.bool
};
EuiComboBox.defaultProps = {
  options: [],
  selectedOptions: [],
  isClearable: true,
  singleSelection: false
};

var _initialiseProps = function _initialiseProps() {
  var _this3 = this;

  this.openList = function () {
    _this3.setState({
      isListOpen: true
    });
  };

  this.closeList = function () {
    _this3.clearActiveOption();
    _this3.setState({
      isListOpen: false
    });
  };

  this.updateListPosition = function () {
    var listElement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _this3.state.listElement;

    if (!_this3._isMounted) {
      return;
    }

    if (!_this3.state.isListOpen) {
      return;
    }

    if (!listElement) {
      return;
    }

    var comboBoxBounds = _this3.comboBox.getBoundingClientRect();

    var _findPopoverPosition = (0, _services.findPopoverPosition)({
      anchor: _this3.comboBox,
      popover: listElement,
      position: 'bottom',
      allowCrossAxis: false
    }),
        position = _findPopoverPosition.position,
        top = _findPopoverPosition.top;

    _this3.optionsList.style.top = top + 'px';
    // listElement doesn't have its width set until after updating the position
    // which means the popover service won't know about the correct width
    // however, we already know where to position the element
    _this3.optionsList.style.left = comboBoxBounds.left + window.pageXOffset + 'px';
    _this3.optionsList.style.width = comboBoxBounds.width + 'px';

    // Cache for future calls.
    _this3.setState({
      listElement: listElement,
      width: comboBoxBounds.width,
      listPosition: position
    });
  };

  this.tabAway = function (amount) {
    if (![-1, 1].includes(amount)) {
      throw new Error('tabAway expects amount to be -1 or 1, but received ' + amount);
    }

    var tabbableItems = (0, _tabbable2.default)(document);

    if (document.activeElement === _this3.searchInput) {
      var searchInputIndex = tabbableItems.indexOf(_this3.searchInput);

      // Wrap to last tabbable if tabbing backwards.
      if (amount === -1) {
        if (searchInputIndex === 0) {
          tabbableItems[tabbableItems.length - 1].focus();
          return true;
        }
      }

      // Otherwise tab to the next adjacent item.
      tabbableItems[searchInputIndex + amount].focus();
      return true;
    }

    if (document.activeElement === _this3.toggleButton) {
      var toggleButtonIndex = tabbableItems.indexOf(_this3.toggleButton);

      // Wrap to first tabbable if tabbing forwards.
      if (amount === 1) {
        if (toggleButtonIndex === tabbableItems.length - 1) {
          tabbableItems[0].focus();
          return true;
        }
      }

      // Otherwise tab to the next adjacent item.
      tabbableItems[toggleButtonIndex + amount].focus();
      return true;
    }

    // Tab natively.
    return false;
  };

  this.incrementActiveOptionIndex = (0, _lodash.throttle)(function (amount) {
    // If there are no options available, reset the focus.
    if (!_this3.state.matchingOptions.length) {
      _this3.clearActiveOption();
      return;
    }

    _this3.setState(function (_ref) {
      var activeOptionIndex = _ref.activeOptionIndex,
          matchingOptions = _ref.matchingOptions;

      var nextActiveOptionIndex = void 0;

      if (!_this3.hasActiveOption()) {
        // If this is the beginning of the user's keyboard navigation of the menu, then we'll focus
        // either the first or last item.
        nextActiveOptionIndex = amount < 0 ? matchingOptions.length - 1 : 0;
      } else {
        nextActiveOptionIndex = activeOptionIndex + amount;

        if (nextActiveOptionIndex < 0) {
          nextActiveOptionIndex = matchingOptions.length - 1;
        } else if (nextActiveOptionIndex === matchingOptions.length) {
          nextActiveOptionIndex = 0;
        }
      }

      // Group titles are included in option list but are not selectable
      // Skip group title options
      var direction = amount > 0 ? 1 : -1;
      while (matchingOptions[nextActiveOptionIndex].isGroupLabelOption) {
        nextActiveOptionIndex = nextActiveOptionIndex + direction;

        if (nextActiveOptionIndex < 0) {
          nextActiveOptionIndex = matchingOptions.length - 1;
        } else if (nextActiveOptionIndex === matchingOptions.length) {
          nextActiveOptionIndex = 0;
        }
      }

      return { activeOptionIndex: nextActiveOptionIndex };
    });
  }, 200);

  this.hasActiveOption = function () {
    return _this3.state.activeOptionIndex !== undefined;
  };

  this.clearActiveOption = function () {
    _this3.setState({
      activeOptionIndex: undefined
    });
  };

  this.focusActiveOption = function () {
    // If an item is focused, focus it.
    if (_this3.hasActiveOption() && _this3.options[_this3.state.activeOptionIndex]) {
      _this3.options[_this3.state.activeOptionIndex].focus();
    }
  };

  this.focusSearchInput = function () {
    _this3.clearActiveOption();
    _this3.searchInput.focus();
  };

  this.clearSearchValue = function () {
    _this3.onSearchChange('');
  };

  this.removeLastOption = function () {
    if (_this3.hasActiveOption()) {
      return;
    }

    if (!_this3.props.selectedOptions.length) {
      return;
    }

    // Backspace will be used to delete the input, not a pill.
    if (_this3.state.searchValue.length) {
      return;
    }

    // Delete last pill.
    _this3.onRemoveOption(_this3.props.selectedOptions[_this3.props.selectedOptions.length - 1]);
  };

  this.addCustomOption = function () {
    if (_this3.doesSearchMatchOnlyOption()) {
      _this3.options[0].click();
      return;
    }

    if (!_this3.props.onCreateOption) {
      return;
    }

    // Don't create the value if it's already been selected.
    if ((0, _matching_options.getSelectedOptionForSearchValue)(_this3.state.searchValue, _this3.props.selectedOptions)) {
      return;
    }

    // Add new custom pill if this is custom input, even if it partially matches an option..
    if (!_this3.hasActiveOption() || _this3.doesSearchMatchOnlyOption()) {
      var isOptionCreated = _this3.props.onCreateOption(_this3.state.searchValue, (0, _matching_options.flattenOptionGroups)(_this3.props.options));

      // Expect the consumer to be explicit in rejecting a custom option.
      if (isOptionCreated === false) {
        return;
      }

      _this3.clearSearchValue();
    }
  };

  this.doesSearchMatchOnlyOption = function () {
    var searchValue = _this3.state.searchValue;

    if (_this3.state.matchingOptions.length !== 1) {
      return false;
    }
    return _this3.state.matchingOptions[0].label.toLowerCase() === searchValue.toLowerCase();
  };

  this.areAllOptionsSelected = function () {
    var _props3 = _this3.props,
        options = _props3.options,
        selectedOptions = _props3.selectedOptions,
        async = _props3.async;
    // Assume if this is async then there could be infinite options.

    if (async) {
      return false;
    }
    return (0, _matching_options.flattenOptionGroups)(options).length === selectedOptions.length;
  };

  this.onFocus = function () {
    document.addEventListener('click', _this3.onDocumentFocusChange);
    document.addEventListener('focusin', _this3.onDocumentFocusChange);
    _this3.openList();
  };

  this.onBlur = function () {
    document.removeEventListener('click', _this3.onDocumentFocusChange);
    document.removeEventListener('focusin', _this3.onDocumentFocusChange);
    _this3.closeList();
  };

  this.onDocumentFocusChange = function (event) {
    // Close the list if the combo box has lost focus.
    if (_this3.comboBox === event.target || _this3.comboBox.contains(event.target) || _this3.optionsList === event.target || _this3.optionsList && _this3.optionsList.contains(event.target)) {
      return;
    }

    // Wait for the DOM to update.
    requestAnimationFrame(function () {
      if (document.activeElement === _this3.searchInput) {
        return;
      }

      _this3.onBlur();
    });
  };

  this.onKeyDown = function (e) {
    switch (e.keyCode) {
      case _services.comboBoxKeyCodes.UP:
        e.preventDefault();
        _this3.incrementActiveOptionIndex(-1);
        break;

      case _services.comboBoxKeyCodes.DOWN:
        e.preventDefault();
        _this3.incrementActiveOptionIndex(1);
        break;

      case _key_codes.BACKSPACE:
        _this3.removeLastOption();
        break;

      case _key_codes.ESCAPE:
        // Move focus from options list to input.
        if (_this3.hasActiveOption()) {
          _this3.focusSearchInput();
        }
        break;

      case _services.comboBoxKeyCodes.ENTER:
        _this3.addCustomOption();
        break;

      case _key_codes.TAB:
        // Disallow tabbing when the user is navigating the options.
        if (_this3.hasActiveOption()) {
          e.preventDefault();
          e.stopPropagation();
          break;
        }

        var amount = e.shiftKey ? -1 : 1;
        if (_this3.tabAway(amount)) {
          e.preventDefault();
          e.stopPropagation();
        }
        break;
    }
  };

  this.onOptionEnterKey = function (option) {
    _this3.onAddOption(option);
  };

  this.onOptionClick = function (option) {
    _this3.onAddOption(option);
  };

  this.onAddOption = function (addedOption) {
    var _props4 = _this3.props,
        onChange = _props4.onChange,
        selectedOptions = _props4.selectedOptions,
        singleSelection = _props4.singleSelection;

    onChange(singleSelection ? [addedOption] : selectedOptions.concat(addedOption));

    _this3.clearSearchValue();

    if (singleSelection) {
      _this3.closeList();
      return;
    }

    _this3.focusSearchInput();
  };

  this.onRemoveOption = function (removedOption) {
    var _props5 = _this3.props,
        onChange = _props5.onChange,
        selectedOptions = _props5.selectedOptions;

    onChange(selectedOptions.filter(function (option) {
      return option !== removedOption;
    }));
    _this3.focusSearchInput();
  };

  this.clearSelectedOptions = function () {
    _this3.props.onChange([]);
    // 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,
    _this3.searchInput.focus();
  };

  this.onComboBoxClick = function () {
    // When the user clicks anywhere on the box, enter the interaction state.
    _this3.searchInput.focus();
    // If the user does this from a state in which an option has focus, then we need to clear it.
    _this3.clearActiveOption();
  };

  this.onComboBoxFocus = function (e) {
    // If the user has tabbed to the combo box, open it.
    if (e.target === _this3.searchInput) {
      _this3.searchInput.focus();
      return;
    }

    // If a user clicks on an option without selecting it, then it will take focus
    // and we need to update the index.
    var optionIndex = _this3.options.indexOf(e.target);
    if (optionIndex !== -1) {
      _this3.setState({
        activeOptionIndex: optionIndex
      });
    }
  };

  this.onOpenListClick = function () {
    _this3.searchInput.focus();
  };

  this.onCloseListClick = function () {
    _this3.closeList();
  };

  this.onSearchChange = function (searchValue) {
    if (_this3.props.onSearchChange) {
      _this3.props.onSearchChange(searchValue);
    }
    _this3.setState({ searchValue: searchValue });
  };

  this.comboBoxRef = function (node) {
    _this3.comboBox = node;
    if (_this3.comboBox) {
      var comboBoxBounds = _this3.comboBox.getBoundingClientRect();
      _this3.setState({
        width: comboBoxBounds.width
      });
    }
  };

  this.autoSizeInputRef = function (node) {
    _this3.autoSizeInput = node;
  };

  this.searchInputRef = function (node) {
    _this3.searchInput = node;
  };

  this.optionsListRef = function (node) {
    _this3.optionsList = node;
  };

  this.optionRef = function (index, node) {
    _this3.options[index] = node;
  };

  this.toggleButtonRef = function (node) {
    _this3.toggleButton = node;
  };
};

EuiComboBox.__docgenInfo = [{
  'description': '',
  'displayName': 'EuiComboBox',
  'methods': [{
    'name': 'openList',
    'docblock': null,
    'modifiers': [],
    'params': [],
    'returns': null
  }, {
    'name': 'closeList',
    'docblock': null,
    'modifiers': [],
    'params': [],
    'returns': null
  }, {
    'name': 'updateListPosition',
    'docblock': null,
    'modifiers': [],
    'params': [{
      'name': 'listElement',
      'type': null
    }],
    'returns': null
  }, {
    'name': 'tabAway',
    'docblock': null,
    'modifiers': [],
    'params': [{
      'name': 'amount',
      'type': null
    }],
    'returns': null
  }, {
    'name': 'hasActiveOption',
    'docblock': null,
    'modifiers': [],
    'params': [],
    'returns': null
  }, {
    'name': 'clearActiveOption',
    'docblock': null,
    'modifiers': [],
    'params': [],
    'returns': null
  }, {
    'name': 'focusActiveOption',
    'docblock': null,
    'modifiers': [],
    'params': [],
    'returns': null
  }, {
    'name': 'focusSearchInput',
    'docblock': null,
    'modifiers': [],
    'params': [],
    'returns': null
  }, {
    'name': 'clearSearchValue',
    'docblock': null,
    'modifiers': [],
    'params': [],
    'returns': null
  }, {
    'name': 'removeLastOption',
    'docblock': null,
    'modifiers': [],
    'params': [],
    'returns': null
  }, {
    'name': 'addCustomOption',
    'docblock': null,
    'modifiers': [],
    'params': [],
    'returns': null
  }, {
    'name': 'doesSearchMatchOnlyOption',
    'docblock': null,
    'modifiers': [],
    'params': [],
    'returns': null
  }, {
    'name': 'areAllOptionsSelected',
    'docblock': null,
    'modifiers': [],
    'params': [],
    'returns': null
  }, {
    'name': 'onFocus',
    'docblock': null,
    'modifiers': [],
    'params': [],
    'returns': null
  }, {
    'name': 'onBlur',
    'docblock': null,
    'modifiers': [],
    'params': [],
    'returns': null
  }, {
    'name': 'onDocumentFocusChange',
    'docblock': null,
    'modifiers': [],
    'params': [{
      'name': 'event',
      'type': null
    }],
    'returns': null
  }, {
    'name': 'onKeyDown',
    'docblock': null,
    'modifiers': [],
    'params': [{
      'name': 'e',
      'type': null
    }],
    'returns': null
  }, {
    'name': 'onOptionEnterKey',
    'docblock': null,
    'modifiers': [],
    'params': [{
      'name': 'option',
      'type': null
    }],
    'returns': null
  }, {
    'name': 'onOptionClick',
    'docblock': null,
    'modifiers': [],
    'params': [{
      'name': 'option',
      'type': null
    }],
    'returns': null
  }, {
    'name': 'onAddOption',
    'docblock': null,
    'modifiers': [],
    'params': [{
      'name': 'addedOption',
      'type': null
    }],
    'returns': null
  }, {
    'name': 'onRemoveOption',
    'docblock': null,
    'modifiers': [],
    'params': [{
      'name': 'removedOption',
      'type': null
    }],
    'returns': null
  }, {
    'name': 'clearSelectedOptions',
    'docblock': null,
    'modifiers': [],
    'params': [],
    'returns': null
  }, {
    'name': 'onComboBoxClick',
    'docblock': null,
    'modifiers': [],
    'params': [],
    'returns': null
  }, {
    'name': 'onComboBoxFocus',
    'docblock': null,
    'modifiers': [],
    'params': [{
      'name': 'e',
      'type': null
    }],
    'returns': null
  }, {
    'name': 'onOpenListClick',
    'docblock': null,
    'modifiers': [],
    'params': [],
    'returns': null
  }, {
    'name': 'onCloseListClick',
    'docblock': null,
    'modifiers': [],
    'params': [],
    'returns': null
  }, {
    'name': 'onSearchChange',
    'docblock': null,
    'modifiers': [],
    'params': [{
      'name': 'searchValue',
      'type': null
    }],
    'returns': null
  }, {
    'name': 'comboBoxRef',
    'docblock': null,
    'modifiers': [],
    'params': [{
      'name': 'node',
      'type': null
    }],
    'returns': null
  }, {
    'name': 'autoSizeInputRef',
    'docblock': null,
    'modifiers': [],
    'params': [{
      'name': 'node',
      'type': null
    }],
    'returns': null
  }, {
    'name': 'searchInputRef',
    'docblock': null,
    'modifiers': [],
    'params': [{
      'name': 'node',
      'type': null
    }],
    'returns': null
  }, {
    'name': 'optionsListRef',
    'docblock': null,
    'modifiers': [],
    'params': [{
      'name': 'node',
      'type': null
    }],
    'returns': null
  }, {
    'name': 'optionRef',
    'docblock': null,
    'modifiers': [],
    'params': [{
      'name': 'index',
      'type': null
    }, {
      'name': 'node',
      'type': null
    }],
    'returns': null
  }, {
    'name': 'toggleButtonRef',
    'docblock': null,
    'modifiers': [],
    'params': [{
      'name': 'node',
      'type': null
    }],
    'returns': null
  }, {
    'name': 'getDerivedStateFromProps',
    'docblock': null,
    'modifiers': ['static'],
    'params': [{
      'name': 'nextProps',
      'type': null
    }, {
      'name': 'prevState',
      'type': null
    }],
    'returns': null
  }, {
    'name': 'updateMatchingOptionsIfDifferent',
    'docblock': null,
    'modifiers': [],
    'params': [{
      'name': 'newMatchingOptions',
      'type': null
    }],
    'returns': null
  }],
  'props': {
    'id': {
      'type': {
        'name': 'string'
      },
      'required': false,
      'description': ''
    },
    'isDisabled': {
      'type': {
        'name': 'bool'
      },
      'required': false,
      'description': ''
    },
    'className': {
      'type': {
        'name': 'string'
      },
      'required': false,
      'description': ''
    },
    'placeholder': {
      'type': {
        'name': 'string'
      },
      'required': false,
      'description': ''
    },
    'isLoading': {
      'type': {
        'name': 'bool'
      },
      'required': false,
      'description': ''
    },
    'async': {
      'type': {
        'name': 'bool'
      },
      'required': false,
      'description': ''
    },
    'singleSelection': {
      'type': {
        'name': 'bool'
      },
      'required': false,
      'description': '',
      'defaultValue': {
        'value': 'false',
        'computed': false
      }
    },
    'noSuggestions': {
      'type': {
        'name': 'bool'
      },
      'required': false,
      'description': ''
    },
    'options': {
      'type': {
        'name': 'array'
      },
      'required': false,
      'description': '',
      'defaultValue': {
        'value': '[]',
        'computed': false
      }
    },
    'selectedOptions': {
      'type': {
        'name': 'array'
      },
      'required': false,
      'description': '',
      'defaultValue': {
        'value': '[]',
        'computed': false
      }
    },
    'onChange': {
      'type': {
        'name': 'func'
      },
      'required': false,
      'description': ''
    },
    'onSearchChange': {
      'type': {
        'name': 'func'
      },
      'required': false,
      'description': ''
    },
    'onCreateOption': {
      'type': {
        'name': 'func'
      },
      'required': false,
      'description': ''
    },
    'renderOption': {
      'type': {
        'name': 'func'
      },
      'required': false,
      'description': ''
    },
    'isInvalid': {
      'type': {
        'name': 'bool'
      },
      'required': false,
      'description': ''
    },
    'rowHeight': {
      'type': {
        'name': 'number'
      },
      'required': false,
      'description': ''
    },
    'isClearable': {
      'type': {
        'name': 'bool'
      },
      'required': false,
      'description': '',
      'defaultValue': {
        'value': 'true',
        'computed': false
      }
    }
  }
}];