chowa
Version:
UI component library based on React
269 lines (268 loc) • 11.4 kB
JavaScript
/**
* @license chowa v1.1.3
*
* Copyright (c) Chowa Techonlogies Co.,Ltd.(http://www.chowa.cn).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const React = require("react");
const PropTypes = require("prop-types");
const classNames = require("classnames");
const react_dnd_1 = require("react-dnd");
const react_dnd_html5_backend_1 = require("react-dnd-html5-backend");
const utils_1 = require("../utils");
const icon_1 = require("../icon");
const input_1 = require("../input");
const tree_node_1 = require("./tree-node");
const tree_node_list_1 = require("./tree-node-list");
const tool_1 = require("./tool");
class Tree extends React.PureComponent {
constructor(props) {
super(props);
const params = this.compileRenderParams(props);
this.state = Object.assign(Object.assign({}, params), { searchValue: '', selfSelectedIndexs: props.selectedIndexs || [], selfExpandIndexs: props.defaultExpandAll
? tool_1.findHasChildNodeIndexs(params.renderNodes)
: props.expandIndexs || [], fetchingIndexs: [] });
[
'onSelectHandler',
'onCheckHandler',
'onLoadDataHandler',
'onExpandHandler',
'onSearchHandler',
'onDragSorter'
].forEach((fn) => {
this[fn] = this[fn].bind(this);
});
}
componentDidUpdate(preProps) {
if (!utils_1.isEqual(preProps.nodes, this.props.nodes)
|| !utils_1.isEqual(preProps.children, this.props.children)
|| !utils_1.isEqual(preProps.checkedIndexs, this.props.checkedIndexs)
|| preProps.checkStrictly !== this.props.checkStrictly) {
this.setState(Object.assign({}, this.compileRenderParams(this.props)));
}
if (!utils_1.isEqual(preProps.expandIndexs, this.props.expandIndexs)
&& !utils_1.isEqual(this.props.expandIndexs, this.state.selfExpandIndexs)) {
this.setState({ selfExpandIndexs: this.props.expandIndexs });
}
if (!utils_1.isEqual(preProps.selectedIndexs, this.props.selectedIndexs)) {
this.setState({ selfSelectedIndexs: this.props.selectedIndexs });
}
}
compileRenderParams(props) {
const renderNodes = tool_1.complutedNodes(props.nodes) || tool_1.transformReactNodeToNodes(props.children);
const checkedIndexs = props.checkedIndexs || [];
const selfCheckedIndexs = props.checkStrictly
? checkedIndexs
: tool_1.computedCheckedNodeIndexs(checkedIndexs, renderNodes, true);
const indeterminateIndexs = props.checkStrictly
? []
: tool_1.compuntedIndeterminteNodeIndexs(checkedIndexs, renderNodes);
return {
renderNodes,
selfCheckedIndexs,
indeterminateIndexs
};
}
onSelectHandler(node) {
const { index } = node;
const { multiple, onSelect, onDeSelect } = this.props;
const selfSelectedIndexs = [].concat(this.state.selfSelectedIndexs);
const pos = selfSelectedIndexs.indexOf(index);
const isSelect = pos === -1;
if (multiple) {
if (isSelect) {
selfSelectedIndexs.push(index);
}
else {
selfSelectedIndexs.splice(pos, 1);
}
}
else {
if (isSelect) {
selfSelectedIndexs.splice(0, 1, index);
}
else {
selfSelectedIndexs.splice(0, 1);
}
}
this.setState({ selfSelectedIndexs });
if (onSelect && isSelect) {
onSelect(node, selfSelectedIndexs);
}
else if (onDeSelect && !isSelect) {
onDeSelect(node, selfSelectedIndexs);
}
}
onCheckHandler(node, e) {
const { index } = node;
const { renderNodes } = this.state;
const { onCheck, checkStrictly } = this.props;
let selfCheckedIndexs = [].concat(this.state.selfCheckedIndexs);
if (e.target.checked) {
selfCheckedIndexs.push(index);
}
else {
selfCheckedIndexs.splice(selfCheckedIndexs.indexOf(index), 1);
}
selfCheckedIndexs = checkStrictly
? selfCheckedIndexs
: tool_1.computedCheckedNodeIndexs(selfCheckedIndexs, renderNodes, e.target.checked);
this.setState({
selfCheckedIndexs,
indeterminateIndexs: checkStrictly
? []
: tool_1.compuntedIndeterminteNodeIndexs(selfCheckedIndexs, renderNodes)
});
if (onCheck) {
onCheck(node, e, selfCheckedIndexs);
}
}
onLoadDataHandler(node, parentIndexs) {
const fetchingIndexs = [].concat(this.state.fetchingIndexs);
const { index } = node;
const { loadData } = this.props;
if (!loadData) {
return;
}
fetchingIndexs.push(index);
this.setState({ fetchingIndexs });
loadData(node)
.then((nodes) => {
const { renderNodes, selfExpandIndexs } = this.state;
const preFetchingIndexs = [].concat(this.state.fetchingIndexs);
preFetchingIndexs.splice(preFetchingIndexs.indexOf(index), 1);
this.setState({
fetchingIndexs: preFetchingIndexs,
selfExpandIndexs: [].concat(selfExpandIndexs, index),
renderNodes: tool_1.updateNodeChildren(renderNodes, parentIndexs, tool_1.complutedNodes(nodes))
});
});
}
onExpandHandler(node) {
const { index } = node;
const { onExpand } = this.props;
const selfExpandIndexs = [].concat(this.state.selfExpandIndexs);
const visible = !selfExpandIndexs.includes(index);
if (visible) {
selfExpandIndexs.push(index);
}
else {
selfExpandIndexs.splice(selfExpandIndexs.indexOf(index), 1);
}
this.setState({ selfExpandIndexs });
if (onExpand) {
onExpand(node, visible);
}
}
onSearchHandler(e) {
this.setState({
searchValue: e.target.value
});
if (this.props.onSearch) {
this.props.onSearch(e.target.value);
}
}
onDragSorter(dragSelfIndexs, dropSelfIndexs, dropPosition) {
const nodes = tool_1.cloneNodes(this.state.renderNodes);
const dragNode = tool_1.getNodeBySelfIndexs(nodes, dragSelfIndexs);
const dropNode = tool_1.getNodeBySelfIndexs(nodes, dropSelfIndexs);
const insertIndex = dropSelfIndexs[dropSelfIndexs.length - 1];
let removeIndex = dragSelfIndexs[dragSelfIndexs.length - 1];
if (dropPosition === 'self') {
dropNode.children.push(dragNode);
}
else {
const dropChildNodes = tool_1.getChildNodesBySelfIndexs(nodes, dropSelfIndexs);
if (dropPosition === 'top') {
dropChildNodes.splice(insertIndex, 1, dragNode, dropNode);
if (tool_1.isDropInSamePreParent(dragSelfIndexs, dropSelfIndexs)
&& insertIndex <= dragSelfIndexs[dragSelfIndexs.length - 2]) {
dragSelfIndexs[dropSelfIndexs.length - 1]++;
}
}
else {
dropChildNodes.splice(insertIndex, 1, dropNode, dragNode);
}
if (tool_1.isDropInSameParent(dropSelfIndexs, dragSelfIndexs) && removeIndex > insertIndex) {
removeIndex += 1;
}
}
const dragChildNodes = tool_1.getChildNodesBySelfIndexs(nodes, dragSelfIndexs);
dragChildNodes.splice(removeIndex, 1);
this.setState({
renderNodes: nodes
});
if (this.props.onDragEnd) {
this.props.onDragEnd(nodes, dragNode);
}
}
renderTree() {
const { blockNode, draggable, checkStrictly, checkable, selectable, disabled, className, style, formatter, withLine, onContextMenu, searchable, searchPlaceholder } = this.props;
const { searchValue, renderNodes, selfExpandIndexs, selfCheckedIndexs, selfSelectedIndexs, fetchingIndexs, indeterminateIndexs } = this.state;
const componentClass = classNames({
[utils_1.preClass('tree')]: true,
[utils_1.preClass('tree-draggable')]: draggable,
[utils_1.preClass('tree-block-node')]: blockNode || draggable,
[utils_1.preClass('tree-with-line')]: withLine,
[className]: utils_1.isExist(className)
});
return (React.createElement("section", { className: componentClass, style: style },
searchable &&
React.createElement(input_1.default, { className: utils_1.preClass('tree-search'), size: 'small', clearable: true, onChange: this.onSearchHandler, prefix: React.createElement(icon_1.default, { type: 'search' }), value: searchValue, placeholder: searchPlaceholder }),
React.createElement(tree_node_list_1.default, { selectable: selectable, draggable: draggable, checkStrictly: checkStrictly, globalCheckable: checkable, globalDisabled: disabled, expandIndexs: selfExpandIndexs, checkedIndexs: selfCheckedIndexs, indeterminateIndexs: indeterminateIndexs, selectedIndexs: selfSelectedIndexs, fetchingIndexs: fetchingIndexs, formatter: formatter, onSelectHandler: this.onSelectHandler, onCheckHandler: this.onCheckHandler, onExpandHandler: this.onExpandHandler, onLoadDataHandler: this.onLoadDataHandler, parentIndexs: [], onContextMenu: onContextMenu, searchable: searchable, searchValue: searchValue, nodes: renderNodes, dragSorter: this.onDragSorter })));
}
render() {
const { draggable } = this.props;
if (!draggable) {
return this.renderTree();
}
return (React.createElement(react_dnd_1.DndProvider, { backend: react_dnd_html5_backend_1.default }, this.renderTree()));
}
}
Tree.propTypes = {
className: PropTypes.string,
style: PropTypes.object,
selectable: PropTypes.bool,
checkable: PropTypes.bool,
multiple: PropTypes.bool,
disabled: PropTypes.bool,
blockNode: PropTypes.bool,
withLine: PropTypes.bool,
draggable: PropTypes.bool,
checkStrictly: PropTypes.bool,
searchable: PropTypes.bool,
onSearch: PropTypes.func,
searchPlaceholder: PropTypes.string,
defaultExpandAll: PropTypes.bool,
expandIndexs: PropTypes.array,
selectedIndexs: PropTypes.array,
checkedIndexs: PropTypes.array,
onSelect: PropTypes.func,
onDeSelect: PropTypes.func,
onCheck: PropTypes.func,
onExpand: PropTypes.func,
loadData: PropTypes.func,
formatter: PropTypes.func,
onDragEnd: PropTypes.func,
nodes: PropTypes.array,
onContextMenu: PropTypes.func
};
Tree.defaultProps = {
selectable: true,
searchPlaceholder: '请输入需要搜索的内容',
checkable: false,
multiple: false,
disabled: false,
blockNode: false,
withLine: false,
draggable: false,
checkStrictly: false,
searchable: false,
defaultExpandAll: false
};
Tree.Node = tree_node_1.default;
exports.default = Tree;