UNPKG

yqcloud-ui

Version:

An enterprise-class UI design language and React-based implementation

677 lines (506 loc) 20.8 kB
'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;