yqcloud-ui
Version:
An enterprise-class UI design language and React-based implementation
677 lines (506 loc) • 20.8 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.nodeContextTypes = undefined;
var _typeof2 = require('babel-runtime/helpers/typeof');
var _typeof3 = _interopRequireDefault(_typeof2);
var _defineProperty2 = require('babel-runtime/helpers/defineProperty');
var _defineProperty3 = _interopRequireDefault(_defineProperty2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
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 _warning = require('warning');
var _warning2 = _interopRequireDefault(_warning);
var _animate = require('../animate');
var _animate2 = _interopRequireDefault(_animate);
var _toArray = require('../util/Children/toArray');
var _toArray2 = _interopRequireDefault(_toArray);
var _Tree = require('./Tree');
var _icon = require('../../icon');
var _icon2 = _interopRequireDefault(_icon);
var _progress = require('../../progress');
var _progress2 = _interopRequireDefault(_progress);
var _util = require('./util');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var ICON_OPEN = 'open';
var ICON_CLOSE = 'close';
var LOAD_STATUS_NONE = 0;
var LOAD_STATUS_LOADING = 1;
var LOAD_STATUS_LOADED = 2;
var LOAD_STATUS_FAILED = 0; // Action align, let's make failed same as init.
var defaultTitle = '---';
var onlyTreeNodeWarned = false; // Only accept TreeNode
var nodeContextTypes = exports.nodeContextTypes = (0, _extends3['default'])({}, _Tree.contextTypes, {
rcTreeNode: _propTypes2['default'].shape({
onUpCheckConduct: _propTypes2['default'].func
})
});
var TreeNode = function (_React$Component) {
(0, _inherits3['default'])(TreeNode, _React$Component);
function TreeNode(props) {
(0, _classCallCheck3['default'])(this, TreeNode);
var _this = (0, _possibleConstructorReturn3['default'])(this, _React$Component.call(this, props));
_initialiseProps.call(_this);
_this.state = {
loadStatus: LOAD_STATUS_NONE,
dragNodeHighlight: false
};
return _this;
}
TreeNode.prototype.getChildContext = function getChildContext() {
return (0, _extends3['default'])({}, this.context, {
rcTreeNode: {
onUpCheckConduct: this.onUpCheckConduct
}
});
};
// Isomorphic needn't load data in server side
TreeNode.prototype.componentDidMount = function componentDidMount() {
this.syncLoadData(this.props);
};
TreeNode.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
this.syncLoadData(nextProps);
};
// Disabled item still can be switch
// Drag usage
TreeNode.prototype.isSelectable = function isSelectable() {
var selectable = this.props.selectable;
var treeSelectable = this.context.rcTree.selectable;
// Ignore when selectable is undefined or null
if (typeof selectable === 'boolean') {
return selectable;
}
return treeSelectable;
};
// Load data to avoid default expanded tree without data
// Switcher
// Checkbox
// Icon + Title
// Children list wrapped with `Animation`
TreeNode.prototype.render = function render() {
var _classNames;
var _props = this.props,
className = _props.className,
dragOver = _props.dragOver,
dragOverGapTop = _props.dragOverGapTop,
dragOverGapBottom = _props.dragOverGapBottom;
var _context$rcTree = this.context.rcTree,
prefixCls = _context$rcTree.prefixCls,
filterTreeNode = _context$rcTree.filterTreeNode;
var disabled = this.isDisabled();
return _react2['default'].createElement('li', {
className: (0, _classnames2['default'])(className, (_classNames = {}, (0, _defineProperty3['default'])(_classNames, prefixCls + '-treenode-disabled', disabled), (0, _defineProperty3['default'])(_classNames, 'drag-over', !disabled && dragOver), (0, _defineProperty3['default'])(_classNames, 'drag-over-gap-top', !disabled && dragOverGapTop), (0, _defineProperty3['default'])(_classNames, 'drag-over-gap-bottom', !disabled && dragOverGapBottom), (0, _defineProperty3['default'])(_classNames, 'filter-node', filterTreeNode && filterTreeNode(this)), _classNames)),
onDragEnter: this.onDragEnter,
onDragOver: this.onDragOver,
onDragLeave: this.onDragLeave,
onDrop: this.onDrop,
onDragEnd: this.onDragEnd
}, this.renderSwitcher(), this.renderCheckbox(), this.renderSelector(), this.renderChildren());
};
return TreeNode;
}(_react2['default'].Component);
TreeNode.propTypes = {
eventKey: _propTypes2['default'].string, // Pass by parent `cloneElement`
prefixCls: _propTypes2['default'].string,
className: _propTypes2['default'].string,
root: _propTypes2['default'].object,
onSelect: _propTypes2['default'].func,
// By parent
expanded: _propTypes2['default'].bool,
selected: _propTypes2['default'].bool,
checked: _propTypes2['default'].bool,
halfChecked: _propTypes2['default'].bool,
children: _propTypes2['default'].node,
title: _propTypes2['default'].node,
pos: _propTypes2['default'].string,
dragOver: _propTypes2['default'].bool,
dragOverGapTop: _propTypes2['default'].bool,
dragOverGapBottom: _propTypes2['default'].bool,
// By user
isLeaf: _propTypes2['default'].bool,
selectable: _propTypes2['default'].bool,
disabled: _propTypes2['default'].bool,
disableCheckbox: _propTypes2['default'].bool,
icon: _propTypes2['default'].oneOfType([_propTypes2['default'].node, _propTypes2['default'].func])
};
TreeNode.contextTypes = nodeContextTypes;
TreeNode.childContextTypes = nodeContextTypes;
TreeNode.defaultProps = {
title: defaultTitle
};
var _initialiseProps = function _initialiseProps() {
var _this2 = this;
this.onUpCheckConduct = function (treeNode, nodeChecked, nodeHalfChecked) {
var nodePos = treeNode.props.pos;
var _props2 = _this2.props,
eventKey = _props2.eventKey,
pos = _props2.pos,
checked = _props2.checked,
halfChecked = _props2.halfChecked;
var _context = _this2.context,
_context$rcTree2 = _context.rcTree,
checkStrictly = _context$rcTree2.checkStrictly,
isKeyChecked = _context$rcTree2.isKeyChecked,
onBatchNodeCheck = _context$rcTree2.onBatchNodeCheck,
onCheckConductFinished = _context$rcTree2.onCheckConductFinished,
_context$rcTreeNode = _context.rcTreeNode;
_context$rcTreeNode = _context$rcTreeNode === undefined ? {} : _context$rcTreeNode;
var onUpCheckConduct = _context$rcTreeNode.onUpCheckConduct;
// Stop conduct when current node is disabled
if ((0, _util.isCheckDisabled)(_this2)) {
onCheckConductFinished();
return;
}
var children = _this2.getNodeChildren();
var checkedCount = nodeChecked ? 1 : 0;
// Statistic checked count
children.forEach(function (node, index) {
var childPos = (0, _util.getPosition)(pos, index);
if (nodePos === childPos || (0, _util.isCheckDisabled)(node)) {
return;
}
if (isKeyChecked(node.key || childPos)) {
checkedCount += 1;
}
});
// Static enabled children count
var enabledChildrenCount = children.filter(function (node) {
return !(0, _util.isCheckDisabled)(node);
}).length;
// checkStrictly will not conduct check status
var nextChecked = checkStrictly ? checked : enabledChildrenCount === checkedCount;
var nextHalfChecked = checkStrictly ? // propagated or child checked
halfChecked : nodeHalfChecked || checkedCount > 0 && !nextChecked;
// Add into batch update
if (checked !== nextChecked || halfChecked !== nextHalfChecked) {
onBatchNodeCheck(eventKey, nextChecked, nextHalfChecked);
if (onUpCheckConduct) {
onUpCheckConduct(_this2, nextChecked, nextHalfChecked);
} else {
// Flush all the update
onCheckConductFinished();
}
} else {
// Flush all the update
onCheckConductFinished();
}
};
this.onDownCheckConduct = function (nodeChecked) {
var children = _this2.props.children;
var _context$rcTree3 = _this2.context.rcTree,
checkStrictly = _context$rcTree3.checkStrictly,
isKeyChecked = _context$rcTree3.isKeyChecked,
onBatchNodeCheck = _context$rcTree3.onBatchNodeCheck;
if (checkStrictly) return;
(0, _util.traverseTreeNodes)(children, function (_ref) {
var node = _ref.node,
key = _ref.key;
if ((0, _util.isCheckDisabled)(node)) return false;
if (nodeChecked !== isKeyChecked(key)) {
onBatchNodeCheck(key, nodeChecked, false);
}
});
};
this.onSelectorClick = function (e) {
if (_this2.isSelectable()) {
_this2.onSelect(e);
} else {
_this2.onCheck(e);
}
};
this.onSelect = function (e) {
if (_this2.isDisabled()) return;
var onNodeSelect = _this2.context.rcTree.onNodeSelect;
e.preventDefault();
onNodeSelect(e, _this2);
};
this.onCheck = function (e) {
if (_this2.isDisabled()) return;
var _props3 = _this2.props,
disableCheckbox = _props3.disableCheckbox,
checked = _props3.checked,
eventKey = _props3.eventKey;
var _context2 = _this2.context,
_context2$rcTree = _context2.rcTree,
checkable = _context2$rcTree.checkable,
onBatchNodeCheck = _context2$rcTree.onBatchNodeCheck,
onCheckConductFinished = _context2$rcTree.onCheckConductFinished,
_context2$rcTreeNode = _context2.rcTreeNode;
_context2$rcTreeNode = _context2$rcTreeNode === undefined ? {} : _context2$rcTreeNode;
var onUpCheckConduct = _context2$rcTreeNode.onUpCheckConduct;
if (!checkable || disableCheckbox) return;
e.preventDefault();
var targetChecked = !checked;
onBatchNodeCheck(eventKey, targetChecked, false, _this2);
// Children conduct
_this2.onDownCheckConduct(targetChecked);
// Parent conduct
if (onUpCheckConduct) {
onUpCheckConduct(_this2, targetChecked, false);
} else {
onCheckConductFinished();
}
};
this.onMouseEnter = function (e) {
var onNodeMouseEnter = _this2.context.rcTree.onNodeMouseEnter;
onNodeMouseEnter(e, _this2);
};
this.onMouseLeave = function (e) {
var onNodeMouseLeave = _this2.context.rcTree.onNodeMouseLeave;
onNodeMouseLeave(e, _this2);
};
this.onContextMenu = function (e) {
var onNodeContextMenu = _this2.context.rcTree.onNodeContextMenu;
onNodeContextMenu(e, _this2);
};
this.onDragStart = function (e) {
var onNodeDragStart = _this2.context.rcTree.onNodeDragStart;
e.stopPropagation();
_this2.setState({
dragNodeHighlight: true
});
onNodeDragStart(e, _this2);
try {
// ie throw error
// firefox-need-it
e.dataTransfer.setData('text/plain', '');
} catch (error) {
// empty
}
};
this.onDragEnter = function (e) {
var onNodeDragEnter = _this2.context.rcTree.onNodeDragEnter;
e.preventDefault();
e.stopPropagation();
onNodeDragEnter(e, _this2);
};
this.onDragOver = function (e) {
var onNodeDragOver = _this2.context.rcTree.onNodeDragOver;
e.preventDefault();
e.stopPropagation();
onNodeDragOver(e, _this2);
};
this.onDragLeave = function (e) {
var onNodeDragLeave = _this2.context.rcTree.onNodeDragLeave;
e.stopPropagation();
onNodeDragLeave(e, _this2);
};
this.onDragEnd = function (e) {
var onNodeDragEnd = _this2.context.rcTree.onNodeDragEnd;
e.stopPropagation();
_this2.setState({
dragNodeHighlight: false
});
onNodeDragEnd(e, _this2);
};
this.onDrop = function (e) {
var onNodeDrop = _this2.context.rcTree.onNodeDrop;
e.preventDefault();
e.stopPropagation();
_this2.setState({
dragNodeHighlight: false
});
onNodeDrop(e, _this2);
};
this.onExpand = function (e) {
var onNodeExpand = _this2.context.rcTree.onNodeExpand;
var callbackPromise = onNodeExpand(e, _this2);
// Promise like
if (callbackPromise && callbackPromise.then) {
_this2.setState({ loadStatus: LOAD_STATUS_LOADING });
callbackPromise.then(function () {
_this2.setState({ loadStatus: LOAD_STATUS_LOADED });
})['catch'](function () {
_this2.setState({ loadStatus: LOAD_STATUS_FAILED });
});
}
};
this.setSelectHandle = function (node) {
_this2.selectHandle = node;
};
this.getNodeChildren = function () {
var children = _this2.props.children;
var originList = (0, _toArray2['default'])(children).filter(function (node) {
return node;
});
var targetList = (0, _util.getNodeChildren)(originList);
if (originList.length !== targetList.length && !onlyTreeNodeWarned) {
onlyTreeNodeWarned = true;
(0, _warning2['default'])(false, 'Tree only accept TreeNode as children.');
}
return targetList;
};
this.getNodeState = function () {
var expanded = _this2.props.expanded;
if (_this2.isLeaf()) {
return null;
}
return expanded ? ICON_OPEN : ICON_CLOSE;
};
this.isLeaf = function () {
var loadStatus = _this2.state.loadStatus;
var isLeaf = _this2.props.isLeaf;
var loadData = _this2.context.rcTree.loadData;
var hasChildren = _this2.getNodeChildren().length !== 0;
return isLeaf || !loadData && !hasChildren || loadData && loadStatus === LOAD_STATUS_LOADED && !hasChildren;
};
this.isDisabled = function () {
var disabled = _this2.props.disabled;
var treeDisabled = _this2.context.rcTree.disabled;
// Follow the logic of Selectable
if (disabled === false) {
return false;
}
return !!(treeDisabled || disabled);
};
this.syncLoadData = function (props) {
var loadStatus = _this2.state.loadStatus;
var expanded = props.expanded;
var loadData = _this2.context.rcTree.loadData;
if (loadData && loadStatus === LOAD_STATUS_NONE && expanded && !_this2.isLeaf()) {
_this2.setState({ loadStatus: LOAD_STATUS_LOADING });
loadData(_this2).then(function () {
_this2.setState({ loadStatus: LOAD_STATUS_LOADED });
})['catch'](function () {
_this2.setState({ loadStatus: LOAD_STATUS_FAILED });
});
}
};
this.renderSwitcher = function () {
var expanded = _this2.props.expanded;
var prefixCls = _this2.context.rcTree.prefixCls;
if (_this2.isLeaf()) {
return _react2['default'].createElement('span', { className: prefixCls + '-switcher ' + prefixCls + '-switcher-noop' });
}
return _react2['default'].createElement('span', {
className: (0, _classnames2['default'])(prefixCls + '-switcher', (0, _defineProperty3['default'])({}, prefixCls + '-switcher-expanded', expanded)),
onClick: _this2.onExpand
});
};
this.renderCheckbox = function () {
var _props4 = _this2.props,
checked = _props4.checked,
halfChecked = _props4.halfChecked,
disableCheckbox = _props4.disableCheckbox;
var _context$rcTree4 = _this2.context.rcTree,
prefixCls = _context$rcTree4.prefixCls,
checkable = _context$rcTree4.checkable;
var disabled = _this2.isDisabled();
if (!checkable) return null;
// [Legacy] Custom element should be separate with `checkable` in future
var $custom = typeof checkable !== 'boolean' ? checkable : null;
return _react2['default'].createElement('span', {
className: (0, _classnames2['default'])(prefixCls + '-checkbox', checked && prefixCls + '-checkbox-checked', !checked && halfChecked && prefixCls + '-checkbox-indeterminate', (disabled || disableCheckbox) && prefixCls + '-checkbox-disabled'),
onClick: _this2.onCheck
}, $custom);
};
this.renderIcon = function () {
var loadStatus = _this2.state.loadStatus;
var prefixCls = _this2.context.rcTree.prefixCls;
return loadStatus === LOAD_STATUS_LOADING ? _react2['default'].createElement(_progress2['default'], {
type: 'loading',
width: 14,
className: prefixCls + '-icon_loading'
}) : _react2['default'].createElement('span', {
className: (0, _classnames2['default'])(prefixCls + '-iconEle', prefixCls + '-icon__' + (_this2.getNodeState() || 'docu'))
});
};
this.renderSelector = function () {
var _state = _this2.state,
loadStatus = _state.loadStatus,
dragNodeHighlight = _state.dragNodeHighlight;
var _props5 = _this2.props,
title = _props5.title,
selected = _props5.selected,
icon = _props5.icon;
var _context$rcTree5 = _this2.context.rcTree,
prefixCls = _context$rcTree5.prefixCls,
showIcon = _context$rcTree5.showIcon,
draggable = _context$rcTree5.draggable,
loadData = _context$rcTree5.loadData;
var disabled = _this2.isDisabled();
var wrapClass = prefixCls + '-node-content-wrapper';
// Icon - Still show loading icon when loading without showIcon
var $icon = void 0;
if (showIcon) {
$icon = icon ? _react2['default'].createElement('span', {
className: (0, _classnames2['default'])(prefixCls + '-iconEle', prefixCls + '-icon__customize')
}, typeof icon === 'function' ? _react2['default'].createElement(icon, _this2.props) : icon) : _this2.renderIcon();
} else if (loadData && loadStatus === LOAD_STATUS_LOADING) {
$icon = _this2.renderIcon();
}
// Title
var $title = _react2['default'].createElement('span', { className: prefixCls + '-title' }, title);
return _react2['default'].createElement('span', {
ref: _this2.setSelectHandle,
title: typeof title === 'string' ? title : '',
className: (0, _classnames2['default'])('' + wrapClass, wrapClass + '-' + (_this2.getNodeState() || 'normal'), !disabled && (selected || dragNodeHighlight) && prefixCls + '-node-selected', !disabled && draggable && 'draggable'),
draggable: !disabled && draggable || undefined,
'aria-grabbed': !disabled && draggable || undefined,
onMouseEnter: _this2.onMouseEnter,
onMouseLeave: _this2.onMouseLeave,
onContextMenu: _this2.onContextMenu,
onClick: _this2.onSelectorClick,
onDragStart: _this2.onDragStart
}, $icon, $title);
};
this.renderChildren = function () {
var _props6 = _this2.props,
expanded = _props6.expanded,
pos = _props6.pos;
var _context$rcTree6 = _this2.context.rcTree,
prefixCls = _context$rcTree6.prefixCls,
openTransitionName = _context$rcTree6.openTransitionName,
openAnimation = _context$rcTree6.openAnimation,
renderTreeNode = _context$rcTree6.renderTreeNode;
// [Legacy] Animation control
var renderFirst = _this2.renderFirst;
_this2.renderFirst = 1;
var transitionAppear = true;
if (!renderFirst && expanded) {
transitionAppear = false;
}
var animProps = {};
if (openTransitionName) {
animProps.transitionName = openTransitionName;
} else if ((typeof openAnimation === 'undefined' ? 'undefined' : (0, _typeof3['default'])(openAnimation)) === 'object') {
animProps.animation = (0, _extends3['default'])({}, openAnimation);
if (!transitionAppear) {
delete animProps.animation.appear;
}
}
// Children TreeNode
var nodeList = _this2.getNodeChildren();
if (nodeList.length === 0) {
return null;
}
var $children = void 0;
if (expanded) {
$children = _react2['default'].createElement('ul', {
className: (0, _classnames2['default'])(prefixCls + '-child-tree', expanded && prefixCls + '-child-tree-open'),
'data-expanded': expanded
}, _react2['default'].Children.map(nodeList, function (node, index) {
return renderTreeNode(node, index, pos);
}));
}
return _react2['default'].createElement(_animate2['default'], (0, _extends3['default'])({}, animProps, {
showProp: 'data-expanded',
transitionAppear: transitionAppear,
component: ''
}), $children);
};
};
TreeNode.isTreeNode = 1;
exports['default'] = TreeNode;