"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/builtin/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/builtin/extends"));

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/builtin/defineProperty"));

var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/builtin/objectWithoutProperties"));

var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/builtin/objectSpread"));

var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/builtin/toConsumableArray"));

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/builtin/classCallCheck"));

var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/builtin/createClass"));

var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/builtin/possibleConstructorReturn"));

var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/builtin/inherits"));

var _react = _interopRequireDefault(require("react"));

var _propTypes = _interopRequireDefault(require("prop-types"));

var _classnames = _interopRequireDefault(require("classnames"));

var _keycode = _interopRequireDefault(require("keycode"));

var _warning = _interopRequireDefault(require("warning"));

var _Menu = _interopRequireDefault(require("../Menu/Menu"));

var _Input = require("../Input/Input");

/**
 * @ignore - internal component.
 */
var SelectInput =
/*#__PURE__*/
function (_React$Component) {
  (0, _inherits2.default)(SelectInput, _React$Component);

  function SelectInput() {
    var _ref;

    var _temp, _this;

    (0, _classCallCheck2.default)(this, SelectInput);

    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    return (0, _possibleConstructorReturn2.default)(_this, (_temp = _this = (0, _possibleConstructorReturn2.default)(this, (_ref = SelectInput.__proto__ || Object.getPrototypeOf(SelectInput)).call.apply(_ref, [this].concat(args))), _this.ignoreNextBlur = false, _this.displayNode = null, _this.isOpenControlled = _this.props.open !== undefined, _this.state = {
      menuMinWidth: null,
      open: false
    }, _this.update = function (_ref2) {
      var event = _ref2.event,
          open = _ref2.open;

      if (_this.isOpenControlled) {
        if (open) {
          _this.props.onOpen(event);
        } else {
          _this.props.onClose(event);
        }

        return;
      }

      _this.setState({
        // Perfom the layout computation outside of the render method.
        menuMinWidth: _this.props.autoWidth ? null : _this.displayNode.clientWidth,
        open: open
      });
    }, _this.handleClick = function (event) {
      // Opening the menu is going to blur the. It will be focused back when closed.
      _this.ignoreNextBlur = true;

      _this.update({
        open: true,
        event: event
      });
    }, _this.handleClose = function (event) {
      _this.update({
        open: false,
        event: event
      });
    }, _this.handleItemClick = function (child) {
      return function (event) {
        if (!_this.props.multiple) {
          _this.update({
            open: false,
            event: event
          });
        }

        var _this$props = _this.props,
            onChange = _this$props.onChange,
            name = _this$props.name;

        if (onChange) {
          var value;
          var target;

          if (event.target) {
            target = event.target;
          }

          if (_this.props.multiple) {
            value = Array.isArray(_this.props.value) ? (0, _toConsumableArray2.default)(_this.props.value) : [];
            var itemIndex = value.indexOf(child.props.value);

            if (itemIndex === -1) {
              value.push(child.props.value);
            } else {
              value.splice(itemIndex, 1);
            }
          } else {
            value = child.props.value;
          }

          event.persist();
          event.target = (0, _objectSpread2.default)({}, target, {
            value: value,
            name: name
          });
          onChange(event, child);
        }
      };
    }, _this.handleBlur = function (event) {
      if (_this.ignoreNextBlur === true) {
        // The parent components are relying on the bubbling of the event.
        event.stopPropagation();
        _this.ignoreNextBlur = false;
        return;
      }

      if (_this.props.onBlur) {
        _this.props.onBlur(event);
      }
    }, _this.handleKeyDown = function (event) {
      if (_this.props.readOnly) {
        return;
      }

      if (['space', 'up', 'down'].indexOf((0, _keycode.default)(event)) !== -1) {
        event.preventDefault(); // Opening the menu is going to blur the. It will be focused back when closed.

        _this.ignoreNextBlur = true;

        _this.update({
          open: true,
          event: event
        });
      }
    }, _this.handleDisplayRef = function (node) {
      _this.displayNode = node;
    }, _this.handleInputRef = function (node) {
      var inputRef = _this.props.inputRef;

      if (!inputRef) {
        return;
      }

      var nodeProxy = {
        node: node,
        // By pass the native input as we expose a rich object (array).
        value: _this.props.value
      };

      if (typeof inputRef === 'function') {
        inputRef(nodeProxy);
      } else {
        inputRef.current = nodeProxy;
      }
    }, _temp));
  }

  (0, _createClass2.default)(SelectInput, [{
    key: "componentDidMount",
    value: function componentDidMount() {
      if (this.isOpenControlled && this.props.open) {
        // Focus the display node so the focus is restored on this element once
        // the menu is closed.
        this.displayNode.focus(); // Rerender with the resolve `displayNode` reference.

        this.forceUpdate();
      }

      if (this.props.autoFocus) {
        this.displayNode.focus();
      }
    }
  }, {
    key: "render",
    value: function render() {
      var _this2 = this;

      var _props = this.props,
          autoWidth = _props.autoWidth,
          children = _props.children,
          classes = _props.classes,
          className = _props.className,
          disabled = _props.disabled,
          displayEmpty = _props.displayEmpty,
          IconComponent = _props.IconComponent,
          inputRef = _props.inputRef,
          _props$MenuProps = _props.MenuProps,
          MenuProps = _props$MenuProps === void 0 ? {} : _props$MenuProps,
          multiple = _props.multiple,
          name = _props.name,
          onBlur = _props.onBlur,
          onChange = _props.onChange,
          onClose = _props.onClose,
          onFocus = _props.onFocus,
          onOpen = _props.onOpen,
          openProp = _props.open,
          readOnly = _props.readOnly,
          renderValue = _props.renderValue,
          required = _props.required,
          SelectDisplayProps = _props.SelectDisplayProps,
          tabIndexProp = _props.tabIndex,
          _props$type = _props.type,
          type = _props$type === void 0 ? 'hidden' : _props$type,
          value = _props.value,
          other = (0, _objectWithoutProperties2.default)(_props, ["autoWidth", "children", "classes", "className", "disabled", "displayEmpty", "IconComponent", "inputRef", "MenuProps", "multiple", "name", "onBlur", "onChange", "onClose", "onFocus", "onOpen", "open", "readOnly", "renderValue", "required", "SelectDisplayProps", "tabIndex", "type", "value"]);
      var open = this.isOpenControlled && this.displayNode ? openProp : this.state.open;
      delete other['aria-invalid'];
      var display;
      var displaySingle = '';
      var displayMultiple = [];
      var computeDisplay = false; // No need to display any value if the field is empty.

      if ((0, _Input.isFilled)(this.props) || displayEmpty) {
        if (renderValue) {
          display = renderValue(value);
        } else {
          computeDisplay = true;
        }
      }

      var items = _react.default.Children.map(children, function (child) {
        if (!_react.default.isValidElement(child)) {
          return null;
        }

        process.env.NODE_ENV !== "production" ? (0, _warning.default)(child.type !== _react.default.Fragment, ["Material-UI: the Select component doesn't accept a Fragment as a child.", 'Consider providing an array instead.'].join('\n')) : void 0;
        var selected;

        if (multiple) {
          if (!Array.isArray(value)) {
            throw new Error('Material-UI: the `value` property must be an array ' + 'when using the `Select` component with `multiple`.');
          }

          selected = value.indexOf(child.props.value) !== -1;

          if (selected && computeDisplay) {
            displayMultiple.push(child.props.children);
          }
        } else {
          selected = value === child.props.value;

          if (selected && computeDisplay) {
            displaySingle = child.props.children;
          }
        }

        return _react.default.cloneElement(child, {
          onClick: _this2.handleItemClick(child),
          role: 'option',
          selected: selected,
          value: undefined,
          // The value is most likely not a valid HTML attribute.
          'data-value': child.props.value // Instead, we provide it as a data attribute.

        });
      });

      if (computeDisplay) {
        display = multiple ? displayMultiple.join(', ') : displaySingle;
      } // Avoid performing a layout computation in the render method.


      var menuMinWidth = this.state.menuMinWidth;

      if (!autoWidth && this.isOpenControlled && this.displayNode) {
        menuMinWidth = this.displayNode.clientWidth;
      }

      var tabIndex;

      if (typeof tabIndexProp !== 'undefined') {
        tabIndex = tabIndexProp;
      } else {
        tabIndex = disabled ? null : 0;
      }

      return _react.default.createElement("div", {
        className: classes.root
      }, _react.default.createElement("div", (0, _extends2.default)({
        className: (0, _classnames.default)(classes.select, classes.selectMenu, (0, _defineProperty2.default)({}, classes.disabled, disabled), className),
        ref: this.handleDisplayRef,
        "aria-pressed": open ? 'true' : 'false',
        tabIndex: tabIndex,
        role: "button",
        "aria-owns": open ? "menu-".concat(name || '') : null,
        "aria-haspopup": "true",
        onKeyDown: this.handleKeyDown,
        onBlur: this.handleBlur,
        onClick: disabled || readOnly ? null : this.handleClick,
        onFocus: onFocus
      }, SelectDisplayProps), display || _react.default.createElement("span", {
        dangerouslySetInnerHTML: {
          __html: '&#8203;'
        }
      })), _react.default.createElement("input", (0, _extends2.default)({
        value: Array.isArray(value) ? value.join(',') : value,
        name: name,
        ref: this.handleInputRef,
        type: type
      }, other)), _react.default.createElement(IconComponent, {
        className: classes.icon
      }), _react.default.createElement(_Menu.default, (0, _extends2.default)({
        id: "menu-".concat(name || ''),
        anchorEl: this.displayNode,
        open: open,
        onClose: this.handleClose
      }, MenuProps, {
        MenuListProps: (0, _objectSpread2.default)({
          role: 'listbox'
        }, MenuProps.MenuListProps),
        PaperProps: (0, _objectSpread2.default)({}, MenuProps.PaperProps, {
          style: (0, _objectSpread2.default)({
            minWidth: menuMinWidth
          }, MenuProps.PaperProps != null ? MenuProps.PaperProps.style : null)
        })
      }), items));
    }
  }]);
  return SelectInput;
}(_react.default.Component);

SelectInput.propTypes = process.env.NODE_ENV !== "production" ? {
  /**
   * @ignore
   */
  autoFocus: _propTypes.default.bool,

  /**
   * If true, the width of the popover will automatically be set according to the items inside the
   * menu, otherwise it will be at least the width of the select input.
   */
  autoWidth: _propTypes.default.bool,

  /**
   * The option elements to populate the select with.
   * Can be some `<MenuItem>` elements.
   */
  children: _propTypes.default.node,

  /**
   * Override or extend the styles applied to the component.
   * See [CSS API](#css-api) below for more details.
   */
  classes: _propTypes.default.object.isRequired,

  /**
   * The CSS class name of the select element.
   */
  className: _propTypes.default.string,

  /**
   * If `true`, the select will be disabled.
   */
  disabled: _propTypes.default.bool,

  /**
   * If `true`, the selected item is displayed even if its value is empty.
   */
  displayEmpty: _propTypes.default.bool,

  /**
   * The icon that displays the arrow.
   */
  IconComponent: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.func, _propTypes.default.object]),

  /**
   * Use that property to pass a ref callback to the native select element.
   */
  inputRef: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object]),

  /**
   * Properties applied to the `Menu` element.
   */
  MenuProps: _propTypes.default.object,

  /**
   * If true, `value` must be an array and the menu will support multiple selections.
   */
  multiple: _propTypes.default.bool,

  /**
   * Name attribute of the `select` or hidden `input` element.
   */
  name: _propTypes.default.string,

  /**
   * @ignore
   */
  onBlur: _propTypes.default.func,

  /**
   * Callback function fired when a menu item is selected.
   *
   * @param {object} event The event source of the callback.
   * You can pull out the new value by accessing `event.target.value`.
   * @param {object} [child] The react element that was selected.
   */
  onChange: _propTypes.default.func,

  /**
   * Callback fired when the component requests to be closed.
   * Use in controlled mode (see open).
   *
   * @param {object} event The event source of the callback
   */
  onClose: _propTypes.default.func,

  /**
   * @ignore
   */
  onFocus: _propTypes.default.func,

  /**
   * Callback fired when the component requests to be opened.
   * Use in controlled mode (see open).
   *
   * @param {object} event The event source of the callback
   */
  onOpen: _propTypes.default.func,

  /**
   * Control `select` open state.
   */
  open: _propTypes.default.bool,

  /**
   * @ignore
   */
  readOnly: _propTypes.default.bool,

  /**
   * Render the selected value.
   *
   * @param {*} value The `value` provided to the component.
   * @returns {ReactElement}
   */
  renderValue: _propTypes.default.func,

  /**
   * @ignore
   */
  required: _propTypes.default.bool,

  /**
   * Properties applied to the clickable div element.
   */
  SelectDisplayProps: _propTypes.default.object,

  /**
   * @ignore
   */
  tabIndex: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),

  /**
   * @ignore
   */
  type: _propTypes.default.string,

  /**
   * The input value.
   */
  value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number, _propTypes.default.arrayOf(_propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]))]).isRequired
} : {};
var _default = SelectInput;
exports.default = _default;