diff --git a/README.md b/README.md index 81763f7..7c5015b 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,9 @@ yarn add react-org-tree import OrgTree from 'react-org-tree'; const horizontal = false; // true:横向 false:纵向 +const collapsable = true; // true:可折叠 false:不可折叠 +const expandAll = true; // true: 全部展开 false:全部折叠 + const data = { id: 0, label: 'XXX股份有限公司', @@ -45,18 +48,28 @@ const data = { ``` ### Preview -`horizontal` +`横向(horizontal)` + + + +`纵向(vertical)` + + + +`部分展开(expand)` - + -`vertical` +`全部展开(expandAll)` - + diff --git a/img/3.png b/img/3.png new file mode 100644 index 0000000..bfded19 Binary files /dev/null and b/img/3.png differ diff --git a/img/4.png b/img/4.png new file mode 100644 index 0000000..a78c5c5 Binary files /dev/null and b/img/4.png differ diff --git a/package.json b/package.json index 6677d04..743c313 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-org-tree", - "version": "0.1.0", + "version": "0.2.0", "description": "a simple organization tree component based on react", "main": "dist/bundle.js", "files": [ diff --git a/src/org_tree.js b/src/org_tree.js index eb3caab..b39e0e9 100644 --- a/src/org_tree.js +++ b/src/org_tree.js @@ -14,11 +14,13 @@ export const renderNode = (data, prop) => { if (isLeaf(data, prop)) { cls.push('is-leaf'); + } else if (prop.collapsable && !data[node.expand]) { + cls.push('collapsed'); } childNodes.push(renderLabel(data, prop)); - if (data[node.expand]) { + if (!prop.collapsable || data[node.expand]) { childNodes.push(renderChildren(data.children, prop)); } @@ -28,6 +30,23 @@ export const renderNode = (data, prop) => { }, childNodes); }; +// 创建展开折叠按钮 +export const renderBtn = (data, prop ) => { + const { onExpand } = prop; + const node = prop.node; + + let cls = ['org-tree-node-btn']; + + if (data[node.expand]) { + cls.push('expanded'); + } + + return React.createElement('span', { + className: cls.join(' '), + onClick: (e) => typeof onExpand === 'function' && onExpand(e, data) + }); +}; + // 创建 label 节点 export const renderLabel = (data, prop) => { const node = prop.node; @@ -43,12 +62,16 @@ export const renderLabel = (data, prop) => { childNodes.push(label); } + if (prop.collapsable && !isLeaf(data, prop)) { + childNodes.push(renderBtn(data, prop)); + } + const cls = ['org-tree-node-label-inner']; return React.createElement('div', { className: 'org-tree-node-label', }, [React.createElement('div', { - className: cls.join(' ') + className: cls.join(' '), }, childNodes)]); }; diff --git a/src/org_tree.jsx b/src/org_tree.jsx index 1d624b3..fe4f529 100644 --- a/src/org_tree.jsx +++ b/src/org_tree.jsx @@ -2,24 +2,38 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -import TreeNode from './org_tree.js'; +import TreeNode from './org_tree'; //组件 class OrgTree extends Component { constructor(props) { super(props); + this.handleExpand = this.handleExpand.bind(this); this.collapse = this.collapse.bind(this); this.toggleExpand = this.toggleExpand.bind(this); } componentDidMount() { - const { data } = this.props; - this.toggleExpand(data, true); + const { expandAll, data } = this.props; + if(expandAll) this.toggleExpand(data, true); } componentWillUnmount() { } + handleExpand(e, nodeData) { + if ('expand' in nodeData) { + nodeData.expand = !nodeData.expand; + if (!nodeData.expand && nodeData.children) { + this.collapse(nodeData.children); + } + this.forceUpdate(); + }else { + nodeData.expand = true; + this.forceUpdate(); + } + } + collapse(list) { let _this = this; list.forEach(function(child) { @@ -49,7 +63,7 @@ class OrgTree extends Component { } render() { - const { data, node, horizontal, renderContent } = this.props; + const { horizontal, node, data } = this.props; return
this.handleExpand(e, nodeData)} + {...this.props} />
; @@ -68,6 +83,8 @@ OrgTree.propTypes = { data: PropTypes.object, node: PropTypes.object, horizontal: PropTypes.bool, + collapsable: PropTypes.bool, + expandAll: PropTypes.bool, renderContent: PropTypes.func }; diff --git a/src/org_tree.less b/src/org_tree.less index 1eaa31c..a1ec4a3 100644 --- a/src/org_tree.less +++ b/src/org_tree.less @@ -91,7 +91,7 @@ display: table-cell; vertical-align: top; - &.is-leaf { + &.is-leaf, &.collapsed { padding-left: 10px; padding-right: 10px; } @@ -116,6 +116,19 @@ } } +.collapsable .org-tree-node.collapsed { + padding-bottom: 30px; + + .org-tree-node-label:after { + content: ''; + position: absolute; + top: 100%; + left: 0; + width: 50%; + height: 20px; + border-right: 1px solid #ddd; + } +} .org-tree > .org-tree-node { padding-top: 0; @@ -193,6 +206,26 @@ vertical-align: middle; } + &.collapsable .org-tree-node.collapsed { + padding-right: 30px; + + .org-tree-node-label:after { + top: 0; + left: 100%; + width: 20px; + height: 50%; + border-right: 0; + border-bottom: 1px solid #ddd; + } + } + + .org-tree-node-btn { + top: 50%; + left: 100%; + margin-top: -11px; + margin-left: 9px; + } + & > .org-tree-node:only-child:before { border-bottom: 0; } @@ -223,8 +256,4 @@ .text-center { text-align: center; -} - -.org-tree-node-label { - white-space: nowrap; } \ No newline at end of file