UNPKG

chowa

Version:

UI component library based on React

269 lines (268 loc) 11.4 kB
/** * @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;