"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _react = _interopRequireDefault(require("react"));
var _classnames = _interopRequireDefault(require("classnames"));
var _pickAttrs = _interopRequireDefault(require("rc-util/lib/pickAttrs"));
var _contextTypes = require("./contextTypes");
var _Indent = _interopRequireDefault(require("./Indent"));
var _keyUtil = _interopRequireDefault(require("./utils/keyUtil"));
var _treeUtil = require("./utils/treeUtil");
var _excluded = ["eventKey", "className", "style", "dragOver", "dragOverGapTop", "dragOverGapBottom", "isLeaf", "isStart", "isEnd", "expanded", "selected", "checked", "halfChecked", "loading", "domRef", "active", "data", "onMouseMove", "selectable"];
var ICON_OPEN = 'open';
var ICON_CLOSE = 'close';
var defaultTitle = '---';
var TreeNode = function TreeNode(props) {
  var _unstableContext$node, _context$filterTreeNo, _classNames4;
  var eventKey = props.eventKey,
    className = props.className,
    style = props.style,
    dragOver = props.dragOver,
    dragOverGapTop = props.dragOverGapTop,
    dragOverGapBottom = props.dragOverGapBottom,
    isLeaf = props.isLeaf,
    isStart = props.isStart,
    isEnd = props.isEnd,
    expanded = props.expanded,
    selected = props.selected,
    checked = props.checked,
    halfChecked = props.halfChecked,
    loading = props.loading,
    domRef = props.domRef,
    active = props.active,
    data = props.data,
    onMouseMove = props.onMouseMove,
    selectable = props.selectable,
    otherProps = (0, _objectWithoutProperties2.default)(props, _excluded);
  var context = _react.default.useContext(_contextTypes.TreeContext);
  var unstableContext = _react.default.useContext(_contextTypes.UnstableContext);
  var selectHandleRef = _react.default.useRef(null);
  var _React$useState = _react.default.useState(false),
    _React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
    dragNodeHighlight = _React$useState2[0],
    setDragNodeHighlight = _React$useState2[1];

  // ======= State: Disabled State =======
  var isDisabled = !!(context.disabled || props.disabled || (_unstableContext$node = unstableContext.nodeDisabled) !== null && _unstableContext$node !== void 0 && _unstableContext$node.call(unstableContext, data));
  var isCheckable = _react.default.useMemo(function () {
    // Return false if tree or treeNode is not checkable
    if (!context.checkable || props.checkable === false) {
      return false;
    }
    return context.checkable;
  }, [context.checkable, props.checkable]);

  // ======= Event Handlers: Selection and Check =======
  var onSelect = function onSelect(e) {
    if (isDisabled) {
      return;
    }
    context.onNodeSelect(e, (0, _treeUtil.convertNodePropsToEventData)(props));
  };
  var onCheck = function onCheck(e) {
    if (isDisabled) {
      return;
    }
    if (!isCheckable || props.disableCheckbox) {
      return;
    }
    context.onNodeCheck(e, (0, _treeUtil.convertNodePropsToEventData)(props), !checked);
  };

  // ======= State: Selectable Check =======
  var isSelectable = _react.default.useMemo(function () {
    // Ignore when selectable is undefined or null
    if (typeof selectable === 'boolean') {
      return selectable;
    }
    return context.selectable;
  }, [selectable, context.selectable]);
  var onSelectorClick = function onSelectorClick(e) {
    // Click trigger before select/check operation
    context.onNodeClick(e, (0, _treeUtil.convertNodePropsToEventData)(props));
    if (isSelectable) {
      onSelect(e);
    } else {
      onCheck(e);
    }
  };
  var onSelectorDoubleClick = function onSelectorDoubleClick(e) {
    context.onNodeDoubleClick(e, (0, _treeUtil.convertNodePropsToEventData)(props));
  };
  var onMouseEnter = function onMouseEnter(e) {
    context.onNodeMouseEnter(e, (0, _treeUtil.convertNodePropsToEventData)(props));
  };
  var onMouseLeave = function onMouseLeave(e) {
    context.onNodeMouseLeave(e, (0, _treeUtil.convertNodePropsToEventData)(props));
  };
  var onContextMenu = function onContextMenu(e) {
    context.onNodeContextMenu(e, (0, _treeUtil.convertNodePropsToEventData)(props));
  };

  // ======= Drag: Drag Enabled =======
  var isDraggable = _react.default.useMemo(function () {
    return !!(context.draggable && (!context.draggable.nodeDraggable || context.draggable.nodeDraggable(data)));
  }, [context.draggable, data]);

  // ======= Drag: Drag Event Handlers =======
  var onDragStart = function onDragStart(e) {
    e.stopPropagation();
    setDragNodeHighlight(true);
    context.onNodeDragStart(e, props);
    try {
      // ie throw error
      // firefox-need-it
      e.dataTransfer.setData('text/plain', '');
    } catch (_unused) {
      // empty
    }
  };
  var onDragEnter = function onDragEnter(e) {
    e.preventDefault();
    e.stopPropagation();
    context.onNodeDragEnter(e, props);
  };
  var onDragOver = function onDragOver(e) {
    e.preventDefault();
    e.stopPropagation();
    context.onNodeDragOver(e, props);
  };
  var onDragLeave = function onDragLeave(e) {
    e.stopPropagation();
    context.onNodeDragLeave(e, props);
  };
  var onDragEnd = function onDragEnd(e) {
    e.stopPropagation();
    setDragNodeHighlight(false);
    context.onNodeDragEnd(e, props);
  };
  var onDrop = function onDrop(e) {
    e.preventDefault();
    e.stopPropagation();
    setDragNodeHighlight(false);
    context.onNodeDrop(e, props);
  };

  // ======= Expand: Node Expansion =======
  var onExpand = function onExpand(e) {
    if (loading) {
      return;
    }
    context.onNodeExpand(e, (0, _treeUtil.convertNodePropsToEventData)(props));
  };

  // ======= State: Has Children =======
  var hasChildren = _react.default.useMemo(function () {
    var _ref = (0, _keyUtil.default)(context.keyEntities, eventKey) || {},
      children = _ref.children;
    return Boolean((children || []).length);
  }, [context.keyEntities, eventKey]);

  // ======= State: Leaf Check =======
  var memoizedIsLeaf = _react.default.useMemo(function () {
    if (isLeaf === false) {
      return false;
    }
    return isLeaf || !context.loadData && !hasChildren || context.loadData && props.loaded && !hasChildren;
  }, [isLeaf, context.loadData, hasChildren, props.loaded]);

  // ============== Effect ==============
  _react.default.useEffect(function () {
    // Load data to avoid default expanded tree without data
    if (loading) {
      return;
    }
    // read from state to avoid loadData at same time
    if (typeof context.loadData === 'function' && expanded && !memoizedIsLeaf && !props.loaded) {
      // We needn't reload data when has children in sync logic
      // It's only needed in node expanded
      context.onNodeLoad((0, _treeUtil.convertNodePropsToEventData)(props));
    }
  }, [loading, context.loadData, context.onNodeLoad, expanded, memoizedIsLeaf, props]);

  // ==================== Render: Drag Handler ====================
  var dragHandlerNode = _react.default.useMemo(function () {
    var _context$draggable;
    if (!((_context$draggable = context.draggable) !== null && _context$draggable !== void 0 && _context$draggable.icon)) {
      return null;
    }
    return /*#__PURE__*/_react.default.createElement("span", {
      className: "".concat(context.prefixCls, "-draggable-icon")
    }, context.draggable.icon);
  }, [context.draggable]);

  // ====================== Render: Switcher ======================
  var renderSwitcherIconDom = function renderSwitcherIconDom(isInternalLeaf) {
    var switcherIcon = props.switcherIcon || context.switcherIcon;
    // if switcherIconDom is null, no render switcher span
    if (typeof switcherIcon === 'function') {
      return switcherIcon((0, _objectSpread2.default)((0, _objectSpread2.default)({}, props), {}, {
        isLeaf: isInternalLeaf
      }));
    }
    return switcherIcon;
  };

  // Switcher
  var renderSwitcher = function renderSwitcher() {
    if (memoizedIsLeaf) {
      // if switcherIconDom is null, no render switcher span
      var _switcherIconDom = renderSwitcherIconDom(true);
      return _switcherIconDom !== false ? /*#__PURE__*/_react.default.createElement("span", {
        className: (0, _classnames.default)("".concat(context.prefixCls, "-switcher"), "".concat(context.prefixCls, "-switcher-noop"))
      }, _switcherIconDom) : null;
    }
    var switcherIconDom = renderSwitcherIconDom(false);
    return switcherIconDom !== false ? /*#__PURE__*/_react.default.createElement("span", {
      onClick: onExpand,
      className: (0, _classnames.default)("".concat(context.prefixCls, "-switcher"), "".concat(context.prefixCls, "-switcher_").concat(expanded ? ICON_OPEN : ICON_CLOSE))
    }, switcherIconDom) : null;
  };

  // ====================== Checkbox ======================
  var checkboxNode = _react.default.useMemo(function () {
    if (!isCheckable) {
      return null;
    }

    // [Legacy] Custom element should be separate with `checkable` in future
    var $custom = typeof isCheckable !== 'boolean' ? isCheckable : null;
    return /*#__PURE__*/_react.default.createElement("span", {
      className: (0, _classnames.default)("".concat(context.prefixCls, "-checkbox"), (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, "".concat(context.prefixCls, "-checkbox-checked"), checked), "".concat(context.prefixCls, "-checkbox-indeterminate"), !checked && halfChecked), "".concat(context.prefixCls, "-checkbox-disabled"), isDisabled || props.disableCheckbox)),
      onClick: onCheck,
      role: "checkbox",
      "aria-checked": halfChecked ? 'mixed' : checked,
      "aria-disabled": isDisabled || props.disableCheckbox,
      "aria-label": "Select ".concat(typeof props.title === 'string' ? props.title : 'tree node')
    }, $custom);
  }, [isCheckable, checked, halfChecked, isDisabled, props.disableCheckbox, props.title]);

  // ============== State: Node State (Open/Close) ==============
  var nodeState = _react.default.useMemo(function () {
    if (memoizedIsLeaf) {
      return null;
    }
    return expanded ? ICON_OPEN : ICON_CLOSE;
  }, [memoizedIsLeaf, expanded]);

  // ==================== Render: Title + Icon ====================
  var iconNode = _react.default.useMemo(function () {
    return /*#__PURE__*/_react.default.createElement("span", {
      className: (0, _classnames.default)("".concat(context.prefixCls, "-iconEle"), "".concat(context.prefixCls, "-icon__").concat(nodeState || 'docu'), (0, _defineProperty2.default)({}, "".concat(context.prefixCls, "-icon_loading"), loading))
    });
  }, [context.prefixCls, nodeState, loading]);

  // =================== Drop Indicator ===================
  var dropIndicatorNode = _react.default.useMemo(function () {
    var rootDraggable = Boolean(context.draggable);
    // allowDrop is calculated in Tree.tsx, there is no need for calc it here
    var showIndicator = !props.disabled && rootDraggable && context.dragOverNodeKey === eventKey;
    if (!showIndicator) {
      return null;
    }
    return context.dropIndicatorRender({
      dropPosition: context.dropPosition,
      dropLevelOffset: context.dropLevelOffset,
      indent: context.indent,
      prefixCls: context.prefixCls,
      direction: context.direction
    });
  }, [context.dropPosition, context.dropLevelOffset, context.indent, context.prefixCls, context.direction, context.draggable, context.dragOverNodeKey, context.dropIndicatorRender]);

  // Icon + Title
  var selectorNode = _react.default.useMemo(function () {
    var _props$title = props.title,
      title = _props$title === void 0 ? defaultTitle : _props$title;
    var wrapClass = "".concat(context.prefixCls, "-node-content-wrapper");

    // Icon - Still show loading icon when loading without showIcon
    var $icon;
    if (context.showIcon) {
      var currentIcon = props.icon || context.icon;
      $icon = currentIcon ? /*#__PURE__*/_react.default.createElement("span", {
        className: (0, _classnames.default)("".concat(context.prefixCls, "-iconEle"), "".concat(context.prefixCls, "-icon__customize"))
      }, typeof currentIcon === 'function' ? currentIcon(props) : currentIcon) : iconNode;
    } else if (context.loadData && loading) {
      $icon = iconNode;
    }

    // Title
    var titleNode;
    if (typeof title === 'function') {
      titleNode = title(data);
    } else if (context.titleRender) {
      titleNode = context.titleRender(data);
    } else {
      titleNode = title;
    }
    return /*#__PURE__*/_react.default.createElement("span", {
      ref: selectHandleRef,
      title: typeof title === 'string' ? title : '',
      className: (0, _classnames.default)(wrapClass, "".concat(wrapClass, "-").concat(nodeState || 'normal'), (0, _defineProperty2.default)({}, "".concat(context.prefixCls, "-node-selected"), !isDisabled && (selected || dragNodeHighlight))),
      onMouseEnter: onMouseEnter,
      onMouseLeave: onMouseLeave,
      onContextMenu: onContextMenu,
      onClick: onSelectorClick,
      onDoubleClick: onSelectorDoubleClick
    }, $icon, /*#__PURE__*/_react.default.createElement("span", {
      className: "".concat(context.prefixCls, "-title")
    }, titleNode), dropIndicatorNode);
  }, [context.prefixCls, context.showIcon, props, context.icon, iconNode, context.titleRender, data, nodeState, onMouseEnter, onMouseLeave, onContextMenu, onSelectorClick, onSelectorDoubleClick]);
  var dataOrAriaAttributeProps = (0, _pickAttrs.default)(otherProps, {
    aria: true,
    data: true
  });
  var _ref2 = (0, _keyUtil.default)(context.keyEntities, eventKey) || {},
    level = _ref2.level;
  var isEndNode = isEnd[isEnd.length - 1];
  var draggableWithoutDisabled = !isDisabled && isDraggable;
  var dragging = context.draggingNodeKey === eventKey;
  var ariaSelected = selectable !== undefined ? {
    'aria-selected': !!selectable
  } : undefined;
  return /*#__PURE__*/_react.default.createElement("div", (0, _extends2.default)({
    ref: domRef,
    role: "treeitem",
    "aria-expanded": isLeaf ? undefined : expanded,
    className: (0, _classnames.default)(className, "".concat(context.prefixCls, "-treenode"), (_classNames4 = {}, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)(_classNames4, "".concat(context.prefixCls, "-treenode-disabled"), isDisabled), "".concat(context.prefixCls, "-treenode-switcher-").concat(expanded ? 'open' : 'close'), !isLeaf), "".concat(context.prefixCls, "-treenode-checkbox-checked"), checked), "".concat(context.prefixCls, "-treenode-checkbox-indeterminate"), halfChecked), "".concat(context.prefixCls, "-treenode-selected"), selected), "".concat(context.prefixCls, "-treenode-loading"), loading), "".concat(context.prefixCls, "-treenode-active"), active), "".concat(context.prefixCls, "-treenode-leaf-last"), isEndNode), "".concat(context.prefixCls, "-treenode-draggable"), isDraggable), "dragging", dragging), (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)(_classNames4, 'drop-target', context.dropTargetKey === eventKey), 'drop-container', context.dropContainerKey === eventKey), 'drag-over', !isDisabled && dragOver), 'drag-over-gap-top', !isDisabled && dragOverGapTop), 'drag-over-gap-bottom', !isDisabled && dragOverGapBottom), 'filter-node', (_context$filterTreeNo = context.filterTreeNode) === null || _context$filterTreeNo === void 0 ? void 0 : _context$filterTreeNo.call(context, (0, _treeUtil.convertNodePropsToEventData)(props))), "".concat(context.prefixCls, "-treenode-leaf"), memoizedIsLeaf))),
    style: style
    // Draggable config
    ,
    draggable: draggableWithoutDisabled,
    onDragStart: draggableWithoutDisabled ? onDragStart : undefined
    // Drop config
    ,
    onDragEnter: isDraggable ? onDragEnter : undefined,
    onDragOver: isDraggable ? onDragOver : undefined,
    onDragLeave: isDraggable ? onDragLeave : undefined,
    onDrop: isDraggable ? onDrop : undefined,
    onDragEnd: isDraggable ? onDragEnd : undefined,
    onMouseMove: onMouseMove
  }, ariaSelected, dataOrAriaAttributeProps), /*#__PURE__*/_react.default.createElement(_Indent.default, {
    prefixCls: context.prefixCls,
    level: level,
    isStart: isStart,
    isEnd: isEnd
  }), dragHandlerNode, renderSwitcher(), checkboxNode, selectorNode);
};
TreeNode.isTreeNode = 1;
if (process.env.NODE_ENV !== 'production') {
  TreeNode.displayName = 'TreeNode';
}
var _default = exports.default = TreeNode;