function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { polyfill } from 'react-lifecycles-compat';
import Menu, { SubMenu, Item as MenuItem } from 'rc-menu';
import closest from 'dom-closest';
import classNames from 'classnames';
import shallowequal from 'shallowequal';
import Dropdown from '../dropdown';
import Icon from '../icon';
import Checkbox from '../checkbox';
import Radio from '../radio';
import FilterDropdownMenuWrapper from './FilterDropdownMenuWrapper';
import { generateValueMaps } from './util';

function stopPropagation(e) {
  e.stopPropagation();

  if (e.nativeEvent.stopImmediatePropagation) {
    e.nativeEvent.stopImmediatePropagation();
  }
}

var FilterMenu = /*#__PURE__*/function (_React$Component) {
  _inherits(FilterMenu, _React$Component);

  var _super = _createSuper(FilterMenu);

  function FilterMenu(props) {
    var _this;

    _classCallCheck(this, FilterMenu);

    _this = _super.call(this, props);

    _this.setNeverShown = function (column) {
      var rootNode = ReactDOM.findDOMNode(_assertThisInitialized(_this));
      var filterBelongToScrollBody = !!closest(rootNode, ".ant-table-scroll");

      if (filterBelongToScrollBody) {
        // When fixed column have filters, there will be two dropdown menus
        // Filter dropdown menu inside scroll body should never be shown
        // To fix https://github.com/ant-design/ant-design/issues/5010 and
        // https://github.com/ant-design/ant-design/issues/7909
        _this.neverShown = !!column.fixed;
      }
    };

    _this.setSelectedKeys = function (_ref) {
      var selectedKeys = _ref.selectedKeys;

      _this.setState({
        selectedKeys: selectedKeys
      });
    };

    _this.handleClearFilters = function () {
      _this.setState({
        selectedKeys: []
      }, _this.handleConfirm);
    };

    _this.handleConfirm = function () {
      _this.setVisible(false); // Call `setSelectedKeys` & `confirm` in the same time will make filter data not up to date
      // https://github.com/ant-design/ant-design/issues/12284


      _this.setState({}, _this.confirmFilter);
    };

    _this.onVisibleChange = function (visible) {
      _this.setVisible(visible);

      var column = _this.props.column; // https://github.com/ant-design/ant-design/issues/17833

      if (!visible && !(column.filterDropdown instanceof Function)) {
        _this.confirmFilter();
      }
    };

    _this.handleMenuItemClick = function (info) {
      var selectedKeys = _this.state.selectedKeys;

      if (!info.keyPath || info.keyPath.length <= 1) {
        return;
      }

      var keyPathOfSelectedItem = _this.state.keyPathOfSelectedItem;

      if (selectedKeys && selectedKeys.indexOf(info.key) >= 0) {
        // deselect SubMenu child
        delete keyPathOfSelectedItem[info.key];
      } else {
        // select SubMenu child
        keyPathOfSelectedItem[info.key] = info.keyPath;
      }

      _this.setState({
        keyPathOfSelectedItem: keyPathOfSelectedItem
      });
    };

    _this.renderFilterIcon = function () {
      var _classNames;

      var _this$props = _this.props,
          column = _this$props.column,
          locale = _this$props.locale,
          prefixCls = _this$props.prefixCls,
          selectedKeys = _this$props.selectedKeys;
      var filtered = selectedKeys && selectedKeys.length > 0;
      var filterIcon = column.filterIcon;

      if (typeof filterIcon === 'function') {
        filterIcon = filterIcon(filtered);
      }

      var dropdownIconClass = classNames((_classNames = {}, _defineProperty(_classNames, "".concat(prefixCls, "-selected"), 'filtered' in column ? column.filtered : filtered), _defineProperty(_classNames, "".concat(prefixCls, "-open"), _this.getDropdownVisible()), _classNames));

      if (!filterIcon) {
        return /*#__PURE__*/React.createElement(Icon, {
          title: locale.filterTitle,
          type: "filter",
          theme: "filled",
          className: dropdownIconClass,
          onClick: stopPropagation
        });
      }

      if ( /*#__PURE__*/React.isValidElement(filterIcon)) {
        return /*#__PURE__*/React.cloneElement(filterIcon, {
          title: filterIcon.props.title || locale.filterTitle,
          className: classNames("".concat(prefixCls, "-icon"), dropdownIconClass, filterIcon.props.className),
          onClick: stopPropagation
        });
      }

      return /*#__PURE__*/React.createElement("span", {
        className: classNames("".concat(prefixCls, "-icon"), dropdownIconClass)
      }, filterIcon);
    };

    var visible = 'filterDropdownVisible' in props.column ? props.column.filterDropdownVisible : false;
    _this.state = {
      selectedKeys: props.selectedKeys,
      valueKeys: generateValueMaps(props.column.filters),
      keyPathOfSelectedItem: {},
      visible: visible,
      prevProps: props
    };
    return _this;
  }

  _createClass(FilterMenu, [{
    key: "componentDidMount",
    value: function componentDidMount() {
      var column = this.props.column;
      this.setNeverShown(column);
    }
  }, {
    key: "componentDidUpdate",
    value: function componentDidUpdate() {
      var column = this.props.column;
      this.setNeverShown(column);
    }
  }, {
    key: "getDropdownVisible",
    value: function getDropdownVisible() {
      return this.neverShown ? false : this.state.visible;
    }
  }, {
    key: "setVisible",
    value: function setVisible(visible) {
      var column = this.props.column;

      if (!('filterDropdownVisible' in column)) {
        this.setState({
          visible: visible
        });
      }

      if (column.onFilterDropdownVisibleChange) {
        column.onFilterDropdownVisibleChange(visible);
      }
    }
  }, {
    key: "hasSubMenu",
    value: function hasSubMenu() {
      var _this$props$column$fi = this.props.column.filters,
          filters = _this$props$column$fi === void 0 ? [] : _this$props$column$fi;
      return filters.some(function (item) {
        return !!(item.children && item.children.length > 0);
      });
    }
  }, {
    key: "confirmFilter",
    value: function confirmFilter() {
      var _this$props2 = this.props,
          column = _this$props2.column,
          propSelectedKeys = _this$props2.selectedKeys,
          confirmFilter = _this$props2.confirmFilter;
      var _this$state = this.state,
          selectedKeys = _this$state.selectedKeys,
          valueKeys = _this$state.valueKeys;
      var filterDropdown = column.filterDropdown;

      if (!shallowequal(selectedKeys, propSelectedKeys)) {
        confirmFilter(column, filterDropdown ? selectedKeys : selectedKeys.map(function (key) {
          return valueKeys[key];
        }).filter(function (key) {
          return key !== undefined;
        }));
      }
    }
  }, {
    key: "renderMenus",
    value: function renderMenus(items) {
      var _this2 = this;

      var _this$props3 = this.props,
          dropdownPrefixCls = _this$props3.dropdownPrefixCls,
          prefixCls = _this$props3.prefixCls;
      return items.map(function (item) {
        if (item.children && item.children.length > 0) {
          var keyPathOfSelectedItem = _this2.state.keyPathOfSelectedItem;
          var containSelected = Object.keys(keyPathOfSelectedItem).some(function (key) {
            return keyPathOfSelectedItem[key].indexOf(item.value) >= 0;
          });
          var subMenuCls = classNames("".concat(prefixCls, "-dropdown-submenu"), _defineProperty({}, "".concat(dropdownPrefixCls, "-submenu-contain-selected"), containSelected));
          return /*#__PURE__*/React.createElement(SubMenu, {
            title: item.text,
            popupClassName: subMenuCls,
            key: item.value.toString()
          }, _this2.renderMenus(item.children));
        }

        return _this2.renderMenuItem(item);
      });
    }
  }, {
    key: "renderMenuItem",
    value: function renderMenuItem(item) {
      var column = this.props.column;
      var selectedKeys = this.state.selectedKeys;
      var multiple = 'filterMultiple' in column ? column.filterMultiple : true; // We still need trade key as string since Menu render need string

      var internalSelectedKeys = (selectedKeys || []).map(function (key) {
        return key.toString();
      });
      var input = multiple ? /*#__PURE__*/React.createElement(Checkbox, {
        checked: internalSelectedKeys.indexOf(item.value.toString()) >= 0
      }) : /*#__PURE__*/React.createElement(Radio, {
        checked: internalSelectedKeys.indexOf(item.value.toString()) >= 0
      });
      return /*#__PURE__*/React.createElement(MenuItem, {
        key: item.value
      }, input, /*#__PURE__*/React.createElement("span", null, item.text));
    }
  }, {
    key: "render",
    value: function render() {
      var _this3 = this;

      var originSelectedKeys = this.state.selectedKeys;
      var _this$props4 = this.props,
          column = _this$props4.column,
          locale = _this$props4.locale,
          prefixCls = _this$props4.prefixCls,
          dropdownPrefixCls = _this$props4.dropdownPrefixCls,
          getPopupContainer = _this$props4.getPopupContainer; // default multiple selection in filter dropdown

      var multiple = 'filterMultiple' in column ? column.filterMultiple : true;
      var dropdownMenuClass = classNames(_defineProperty({}, "".concat(dropdownPrefixCls, "-menu-without-submenu"), !this.hasSubMenu()));
      var filterDropdown = column.filterDropdown;

      if (filterDropdown instanceof Function) {
        filterDropdown = filterDropdown({
          prefixCls: "".concat(dropdownPrefixCls, "-custom"),
          setSelectedKeys: function setSelectedKeys(selectedKeys) {
            return _this3.setSelectedKeys({
              selectedKeys: selectedKeys
            });
          },
          selectedKeys: originSelectedKeys,
          confirm: this.handleConfirm,
          clearFilters: this.handleClearFilters,
          filters: column.filters,
          visible: this.getDropdownVisible()
        });
      }

      var menus = filterDropdown ? /*#__PURE__*/React.createElement(FilterDropdownMenuWrapper, {
        className: "".concat(prefixCls, "-dropdown")
      }, filterDropdown) : /*#__PURE__*/React.createElement(FilterDropdownMenuWrapper, {
        className: "".concat(prefixCls, "-dropdown")
      }, /*#__PURE__*/React.createElement(Menu, {
        multiple: multiple,
        onClick: this.handleMenuItemClick,
        prefixCls: "".concat(dropdownPrefixCls, "-menu"),
        className: dropdownMenuClass,
        onSelect: this.setSelectedKeys,
        onDeselect: this.setSelectedKeys,
        selectedKeys: originSelectedKeys && originSelectedKeys.map(function (val) {
          return val.toString();
        }),
        getPopupContainer: getPopupContainer
      }, this.renderMenus(column.filters)), /*#__PURE__*/React.createElement("div", {
        className: "".concat(prefixCls, "-dropdown-btns")
      }, /*#__PURE__*/React.createElement("a", {
        className: "".concat(prefixCls, "-dropdown-link confirm"),
        onClick: this.handleConfirm
      }, locale.filterConfirm), /*#__PURE__*/React.createElement("a", {
        className: "".concat(prefixCls, "-dropdown-link clear"),
        onClick: this.handleClearFilters
      }, locale.filterReset)));
      return /*#__PURE__*/React.createElement(Dropdown, {
        trigger: ['click'],
        placement: "bottomRight",
        overlay: menus,
        visible: this.getDropdownVisible(),
        onVisibleChange: this.onVisibleChange,
        getPopupContainer: getPopupContainer,
        forceRender: true
      }, this.renderFilterIcon());
    }
  }], [{
    key: "getDerivedStateFromProps",
    value: function getDerivedStateFromProps(nextProps, prevState) {
      var column = nextProps.column;
      var prevProps = prevState.prevProps;
      var newState = {
        prevProps: nextProps
      };
      /**
       * if the state is visible the component should ignore updates on selectedKeys prop to avoid
       * that the user selection is lost
       * this happens frequently when a table is connected on some sort of realtime data
       * Fixes https://github.com/ant-design/ant-design/issues/10289 and
       * https://github.com/ant-design/ant-design/issues/10209
       */

      if ('selectedKeys' in nextProps && !shallowequal(prevProps.selectedKeys, nextProps.selectedKeys)) {
        newState.selectedKeys = nextProps.selectedKeys;
      }

      if (!shallowequal((prevProps.column || {}).filters, (nextProps.column || {}).filters)) {
        newState.valueKeys = generateValueMaps(nextProps.column.filters);
      }

      if ('filterDropdownVisible' in column) {
        newState.visible = column.filterDropdownVisible;
      }

      return newState;
    }
  }]);

  return FilterMenu;
}(React.Component);

FilterMenu.defaultProps = {
  column: {}
};
polyfill(FilterMenu);
export default FilterMenu;