function _extends() { _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; }; return _extends.apply(this, arguments); }

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(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); return Constructor; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

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

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

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 } }); if (superClass) _setPrototypeOf(subClass, superClass); }

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

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; }

import React, { Component, Children } from 'react';
import { findDOMNode } from 'react-dom';
import PropTypes from 'prop-types';
import cx from 'classnames';
import Icon from '../../icon';
import Checkbox from '../../checkbox';
import Animate from '../../animate';
import { func, obj, KEYCODE } from '../../util';
import TreeNodeInput from './tree-node-input';
var Expand = Animate.Expand;
var bindCtx = func.bindCtx;
var isPromise = obj.isPromise,
    pickOthers = obj.pickOthers,
    pickAttrsWith = obj.pickAttrsWith;

var isRoot = function isRoot(pos) {
  return /^0-(\d)+$/.test(pos);
};
/**
 * Tree.Node
 */


var TreeNode =
/*#__PURE__*/
function (_Component) {
  _inherits(TreeNode, _Component);

  function TreeNode(props) {
    var _this;

    _classCallCheck(this, TreeNode);

    _this = _possibleConstructorReturn(this, _getPrototypeOf(TreeNode).call(this, props));
    _this.state = {
      editing: false,
      loading: false,
      label: props.label
    };
    bindCtx(_assertThisInitialized(_this), ['handleExpand', 'handleSelect', 'handleCheck', 'handleEditStart', 'handleEditFinish', 'handleRightClick', 'handleDragStart', 'handleDragEnter', 'handleDragOver', 'handleDragLeave', 'handleDragEnd', 'handleDrop', 'handleInputKeyDown', 'handleKeyDown']);
    return _this;
  }

  _createClass(TreeNode, [{
    key: "componentDidMount",
    value: function componentDidMount() {
      this.itemNode = findDOMNode(this.refs.node);
      this.setFocus();
    }
  }, {
    key: "UNSAFE_componentWillReceiveProps",
    value: function UNSAFE_componentWillReceiveProps(nextProps) {
      if ('label' in nextProps) {
        this.setState({
          label: nextProps.label
        });
      }
    }
  }, {
    key: "componentDidUpdate",
    value: function componentDidUpdate() {
      this.setFocus();
    }
  }, {
    key: "getParentNode",
    value: function getParentNode() {
      return this.props.root.getParentNode(this.props.pos);
    }
  }, {
    key: "focusable",
    value: function focusable() {
      var _this$props = this.props,
          root = _this$props.root,
          disabled = _this$props.disabled;
      var focusable = root.props.focusable;
      return focusable && !disabled;
    }
  }, {
    key: "getFocused",
    value: function getFocused() {
      var _this$props2 = this.props,
          _key = _this$props2._key,
          root = _this$props2.root;
      var focusedKey = root.state.focusedKey;
      return focusedKey === _key;
    }
  }, {
    key: "setFocus",
    value: function setFocus() {
      var focused = this.getFocused();

      if (focused && this.focusable()) {
        this.itemNode.focus({
          preventScroll: true
        });
      }
    }
  }, {
    key: "handleExpand",
    value: function handleExpand(e) {
      var _this2 = this;

      var _this$props3 = this.props,
          root = _this$props3.root,
          expanded = _this$props3.expanded,
          eventKey = _this$props3.eventKey;

      if (root.props.isNodeBlock) {
        e.stopPropagation();
      }

      var loading = this.state.loading;

      if (loading) {
        return;
      }

      var returnValue = root.handleExpand(!expanded, eventKey, this);

      if (isPromise(returnValue)) {
        this.setLoading(true);
        return returnValue.then(function () {
          _this2.setLoading(false);
        }, function () {
          _this2.setLoading(false);
        });
      }
    }
  }, {
    key: "setLoading",
    value: function setLoading(loading) {
      this.setState({
        loading: loading
      });
    }
  }, {
    key: "handleSelect",
    value: function handleSelect(e) {
      e.preventDefault();
      var _this$props4 = this.props,
          root = _this$props4.root,
          selected = _this$props4.selected,
          eventKey = _this$props4.eventKey;
      root.handleSelect(!selected, eventKey, this, e);
    }
  }, {
    key: "handleCheck",
    value: function handleCheck() {
      var _this$props5 = this.props,
          root = _this$props5.root,
          checked = _this$props5.checked,
          eventKey = _this$props5.eventKey;
      root.handleCheck(!checked, eventKey, this);
    }
  }, {
    key: "handleEditStart",
    value: function handleEditStart(e) {
      e.preventDefault();
      this.setState({
        editing: true
      });
    }
  }, {
    key: "handleEditFinish",
    value: function handleEditFinish(e) {
      var label = e.target.value;
      this.setState({
        editing: false,
        label: label
      });
      var _this$props6 = this.props,
          root = _this$props6.root,
          eventKey = _this$props6.eventKey;
      root.props.onEditFinish(eventKey, label, this);
    }
  }, {
    key: "handleRightClick",
    value: function handleRightClick(e) {
      this.props.root.props.onRightClick({
        event: e,
        node: this
      });
    }
  }, {
    key: "handleDragStart",
    value: function handleDragStart(e) {
      e.stopPropagation();
      this.props.root.handleDragStart(e, this);
    }
  }, {
    key: "handleDragEnter",
    value: function handleDragEnter(e) {
      e.preventDefault();
      e.stopPropagation();
      this.props.root.handleDragEnter(e, this);
    }
  }, {
    key: "handleDragOver",
    value: function handleDragOver(e) {
      if (this.props.root.canDrop(this)) {
        e.preventDefault();
        e.stopPropagation();
        this.props.root.handleDragOver(e, this);
      }
    }
  }, {
    key: "handleDragLeave",
    value: function handleDragLeave(e) {
      e.stopPropagation();
      this.props.root.handleDragLeave(e, this);
    }
  }, {
    key: "handleDragEnd",
    value: function handleDragEnd(e) {
      e.stopPropagation();
      this.props.root.handleDragEnd(e, this);
    }
  }, {
    key: "handleDrop",
    value: function handleDrop(e) {
      e.preventDefault();
      e.stopPropagation();
      this.props.root.handleDrop(e, this);
    }
  }, {
    key: "handleInputKeyDown",
    value: function handleInputKeyDown(e) {
      if (e.keyCode === KEYCODE.ENTER) {
        this.handleEditFinish(e);
      }
    }
  }, {
    key: "handleKeyDown",
    value: function handleKeyDown(e) {
      var _this$props7 = this.props,
          _key = _this$props7._key,
          root = _this$props7.root,
          disabled = _this$props7.disabled;

      if (disabled) {
        return;
      }

      if (this.focusable()) {
        root.handleItemKeyDown(_key, this, e);
      }

      this.props.onKeyDown && this.props.onKeyDown(e);
    }
  }, {
    key: "addCallbacks",
    value: function addCallbacks(props) {
      var _this$props8 = this.props,
          disabled = _this$props8.disabled,
          root = _this$props8.root;

      if (!disabled) {
        var selectable = typeof this.props.selectable !== 'undefined' ? this.props.selectable : root.props.selectable;

        if (selectable) {
          props.onClick = this.handleSelect;
        }

        var editable = typeof this.props.editable !== 'undefined' ? this.props.editable : root.props.editable;

        if (editable) {
          props.onDoubleClick = this.handleEditStart;
        }

        var draggable = typeof this.props.draggable !== 'undefined' ? this.props.draggable : root.props.draggable;

        if (draggable) {
          props.draggable = true;
          props.onDragStart = this.handleDragStart;
          props.onDragEnd = this.handleDragEnd;
        }

        props.onContextMenu = this.handleRightClick;
      }
    }
  }, {
    key: "renderSwitcher",
    value: function renderSwitcher() {
      var _cx;

      var _this$props9 = this.props,
          prefix = _this$props9.prefix,
          disabled = _this$props9.disabled,
          expanded = _this$props9.expanded,
          root = _this$props9.root;
      var loadData = root.props.loadData;
      var loading = this.state.loading;
      var showLine = this.showLine;
      var lineState = showLine ? 'line' : 'noline';
      var className = cx((_cx = {}, _defineProperty(_cx, "".concat(prefix, "tree-switcher"), true), _defineProperty(_cx, "".concat(prefix).concat(lineState), !loading), _defineProperty(_cx, "".concat(prefix, "close"), !loading && !expanded), _defineProperty(_cx, "".concat(prefix, "disabled"), disabled), _defineProperty(_cx, "".concat(prefix, "loading"), loading), _defineProperty(_cx, "".concat(prefix, "loading-").concat(lineState), loading), _cx));
      var iconType = loadData && loading ? 'loading' : 'triangle-down';
      return React.createElement("span", {
        className: className
      }, React.createElement(Icon, {
        className: "".concat(prefix, "tree-switcher-icon"),
        type: iconType
      }));
    }
  }, {
    key: "renderNoopSwitcher",
    value: function renderNoopSwitcher() {
      var _cx2;

      var _this$props10 = this.props,
          prefix = _this$props10.prefix,
          pos = _this$props10.pos;
      var showLine = this.showLine;
      var lineState = showLine ? 'line' : 'noline';
      var className = cx((_cx2 = {}, _defineProperty(_cx2, "".concat(prefix, "tree-switcher"), true), _defineProperty(_cx2, "".concat(prefix, "noop-").concat(lineState), true), _defineProperty(_cx2, "".concat(prefix, "noop-line-noroot"), showLine && !isRoot(pos)), _cx2));
      return React.createElement("span", {
        className: className
      }, this.renderRightAngle());
    }
  }, {
    key: "renderRightAngle",
    value: function renderRightAngle() {
      var _this$props11 = this.props,
          prefix = _this$props11.prefix,
          pos = _this$props11.pos;
      return null; // return this.showLine && !isRoot(pos) ? <span className={`${prefix}tree-right-angle`} /> : null;
    }
  }, {
    key: "renderCheckbox",
    value: function renderCheckbox() {
      var _this$props12 = this.props,
          checked = _this$props12.checked,
          indeterminate = _this$props12.indeterminate,
          disabled = _this$props12.disabled,
          checkboxDisabled = _this$props12.checkboxDisabled;
      var label = this.state.label;
      return React.createElement(Checkbox, {
        "aria-label": typeof label === 'string' ? label : null,
        checked: checked,
        tabIndex: -1,
        indeterminate: indeterminate,
        disabled: disabled || checkboxDisabled,
        onClick: function onClick(e) {
          return e.stopPropagation();
        },
        onChange: this.handleCheck
      });
    }
  }, {
    key: "renderLabel",
    value: function renderLabel() {
      var _cx3;

      var _this$props13 = this.props,
          prefix = _this$props13.prefix,
          root = _this$props13.root,
          disabled = _this$props13.disabled;
      var isNodeBlock = root.props.isNodeBlock;
      var label = this.state.label;
      var selectable = typeof this.props.selectable !== 'undefined' ? this.props.selectable : root.props.selectable;
      var labelProps = {
        className: cx((_cx3 = {}, _defineProperty(_cx3, "".concat(prefix, "tree-node-label"), true), _defineProperty(_cx3, "".concat(prefix, "tree-node-label-selectable"), selectable && !disabled), _cx3))
      };

      if (!isNodeBlock) {
        this.addCallbacks(labelProps);
      }

      return React.createElement("div", {
        className: "".concat(prefix, "tree-node-label-wrapper"),
        ref: "labelWrapper"
      }, React.createElement("div", labelProps, label));
    }
  }, {
    key: "renderInput",
    value: function renderInput() {
      var prefix = this.props.prefix;
      var label = this.state.label;
      return React.createElement("div", {
        className: "".concat(prefix, "tree-node-label-wrapper"),
        ref: "labelWrapper"
      }, React.createElement(TreeNodeInput, {
        prefix: prefix,
        defaultValue: label,
        onBlur: this.handleEditFinish,
        onKeyDown: this.handleInputKeyDown
      }));
    }
  }, {
    key: "renderChildTree",
    value: function renderChildTree(hasChildTree) {
      var _this$props14 = this.props,
          prefix = _this$props14.prefix,
          children = _this$props14.children,
          expanded = _this$props14.expanded,
          root = _this$props14.root;
      var animation = root.props.animation;
      var childTree = expanded && hasChildTree ? React.createElement("ul", {
        role: "group",
        className: "".concat(prefix, "tree-child-tree")
      }, children) : null;

      if (animation) {
        childTree = React.createElement(Expand, {
          animationAppear: false
        }, childTree);
      }

      return childTree;
    }
  }, {
    key: "render",
    value: function render() {
      var _cx4, _cx5;

      var _this$props15 = this.props,
          prefix = _this$props15.prefix,
          rtl = _this$props15.rtl,
          className = _this$props15.className,
          children = _this$props15.children,
          isLeaf = _this$props15.isLeaf,
          root = _this$props15.root,
          pos = _this$props15.pos,
          selected = _this$props15.selected,
          checked = _this$props15.checked,
          disabled = _this$props15.disabled,
          expanded = _this$props15.expanded,
          dragOver = _this$props15.dragOver,
          dragOverGapTop = _this$props15.dragOverGapTop,
          dragOverGapBottom = _this$props15.dragOverGapBottom,
          _key = _this$props15._key,
          size = _this$props15.size;
      var _root$props = root.props,
          loadData = _root$props.loadData,
          isNodeBlock = _root$props.isNodeBlock,
          showLine = _root$props.showLine,
          rootDraggable = _root$props.draggable,
          filterTreeNode = _root$props.filterTreeNode;
      var label = this.state.label;
      this.showLine = !isNodeBlock && showLine;
      var indexArr = pos.split('-');
      var ARIA_PREFIX = 'aria-';
      var ariaProps = pickAttrsWith(this.props, ARIA_PREFIX);
      var others = pickOthers(Object.keys(TreeNode.propTypes), this.props); // remove aria keys

      Object.keys(others).forEach(function (key) {
        if (key.match(ARIA_PREFIX)) {
          delete others[key];
        }
      });

      if (rootDraggable) {
        others.onDragEnter = this.handleDragEnter;
        others.onDragOver = this.handleDragOver;
        others.onDragLeave = this.handleDragLeave;
        others.onDrop = this.handleDrop;
      }

      var newClassName = cx((_cx4 = {}, _defineProperty(_cx4, "".concat(prefix, "tree-node"), true), _defineProperty(_cx4, "".concat(prefix, "filtered"), !!filterTreeNode && !!root.filterTreeNode(this)), _defineProperty(_cx4, className, !!className), _cx4));
      var innerClassName = cx((_cx5 = {}, _defineProperty(_cx5, "".concat(prefix, "tree-node-inner"), true), _defineProperty(_cx5, "".concat(prefix, "selected"), selected), _defineProperty(_cx5, "".concat(prefix, "disabled"), disabled), _defineProperty(_cx5, "".concat(prefix, "drag-over"), dragOver), _defineProperty(_cx5, "".concat(prefix, "drag-over-gap-top"), dragOverGapTop), _defineProperty(_cx5, "".concat(prefix, "drag-over-gap-bottom"), dragOverGapBottom), _cx5));
      var defaultPaddingLeft = _typeof(isNodeBlock) === 'object' ? parseInt(isNodeBlock.defaultPaddingLeft || 0) : 0;
      var indent = _typeof(isNodeBlock) === 'object' ? parseInt(isNodeBlock.indent || 24) : 24;
      var level = indexArr.length - 2;
      var paddingLeftProp = rtl ? 'paddingRight' : 'paddingLeft';
      var innerStyle = isNodeBlock ? _defineProperty({}, paddingLeftProp, "".concat(indent * level + defaultPaddingLeft, "px")) : null;

      var innerProps = _objectSpread({
        className: innerClassName,
        style: innerStyle,
        onKeyDown: this.handleKeyDown
      }, ariaProps);

      if (isNodeBlock) {
        this.addCallbacks(innerProps);
      } // this.addCallbacks(innerProps);


      var hasChildTree = children && Children.count(children);
      var canExpand = hasChildTree || loadData && !isLeaf;
      var checkable = typeof this.props.checkable !== 'undefined' ? this.props.checkable : root.props.checkable;
      var editing = this.state.editing;
      innerProps.tabIndex = root.tabbableKey === _key ? '0' : '-1';

      if (rtl) {
        others.dir = 'rtl';
      }

      return React.createElement("li", _extends({
        role: "presentation",
        className: newClassName
      }, others), React.createElement("div", _extends({
        onClick: disabled ? null : this.handleExpand,
        ref: "node",
        role: "treeitem",
        "aria-selected": selected,
        "aria-disabled": disabled,
        "aria-checked": checked,
        "aria-expanded": expanded && !!hasChildTree,
        "aria-label": typeof label === 'string' ? label : null,
        "aria-level": level + 1,
        "aria-posinset": Number(indexArr[indexArr.length - 1]) + 1,
        "aria-setsize": size
      }, innerProps), canExpand ? this.renderSwitcher() : this.renderNoopSwitcher(), checkable ? this.renderCheckbox() : null, editing ? this.renderInput() : this.renderLabel()), this.renderChildTree(hasChildTree));
    }
  }]);

  return TreeNode;
}(Component);

_defineProperty(TreeNode, "propTypes", {
  _key: PropTypes.string,
  prefix: PropTypes.string,
  rtl: PropTypes.bool,
  className: PropTypes.string,

  /**
   * 树节点
   */
  children: PropTypes.node,

  /**
   * 节点文本内容
   */
  label: PropTypes.node,

  /**
   * 单独设置是否支持选中，覆盖 Tree 的 selectable
   */
  selectable: PropTypes.bool,

  /**
   * 单独设置是否出现复选框，覆盖 Tree 的 checkable
   */
  checkable: PropTypes.bool,

  /**
   * 单独设置是否支持编辑，覆盖 Tree 的 editable
   */
  editable: PropTypes.bool,

  /**
   * 单独设置是否支持拖拽，覆盖 Tree 的 draggable
   */
  draggable: PropTypes.bool,

  /**
   * 是否禁止节点响应
   */
  disabled: PropTypes.bool,

  /**
   * 是否禁止勾选节点复选框
   */
  checkboxDisabled: PropTypes.bool,

  /**
   * 是否是叶子节点，设置loadData时生效
   */
  isLeaf: PropTypes.bool,
  root: PropTypes.object,
  eventKey: PropTypes.string,
  pos: PropTypes.string,
  expanded: PropTypes.bool,
  selected: PropTypes.bool,
  checked: PropTypes.bool,
  indeterminate: PropTypes.bool,
  dragOver: PropTypes.bool,
  dragOverGapTop: PropTypes.bool,
  dragOverGapBottom: PropTypes.bool,
  parentNode: PropTypes.object,
  onKeyDown: PropTypes.func,
  size: PropTypes.number
});

_defineProperty(TreeNode, "defaultProps", {
  label: '---',
  rtl: false,
  disabled: false,
  checkboxDisabled: false,
  isLeaf: false,
  size: 1
});

export { TreeNode as default };