├── .babelrc ├── .gitignore ├── .umirc.js ├── LICENSE ├── README.md ├── docs ├── README.md ├── README.zh.md ├── demo │ ├── basic.md │ ├── basic.zh.md │ ├── custom.md │ ├── custom.zh.md │ ├── expand.md │ ├── expand.zh.md │ ├── expandAll.md │ ├── expandAll.zh.md │ ├── horizontal.md │ ├── horizontal.zh.md │ ├── vertical.md │ └── vertical.zh.md ├── examples │ ├── basic.jsx │ ├── custom.jsx │ ├── expand.jsx │ ├── expandAll.jsx │ ├── horizontal.jsx │ └── vertical.jsx ├── guide │ ├── README.md │ └── README.zh.md └── img │ ├── logo.png │ └── logo.svg ├── img ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── dashang.jpeg ├── hb.jpeg ├── logo.png ├── logo.svg ├── logo1.svg ├── logo2.svg └── logo3.svg ├── jsconfig.json ├── package.json ├── src ├── index.js ├── org_tree.js ├── org_tree.jsx └── org_tree.less ├── webpack.config.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # dist 7 | /dist 8 | 9 | # testing 10 | /coverage 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | 23 | package.lock.json 24 | examples/demo/.idea/workspace.xml 25 | /**/**/.umi 26 | /**/**/.umi-production 27 | /docs-dist 28 | 29 | -------------------------------------------------------------------------------- /.umirc.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'dumi'; 2 | 3 | export default defineConfig({ 4 | mode: 'site', 5 | hash: true, 6 | favicon: 7 | 'https://raw.githubusercontent.com/artdong/react-org-tree/f9c418ef7b904c83c1aba36cfc3aabbb9b3da10f/img/logo.svg', 8 | logo: 9 | 'https://raw.githubusercontent.com/artdong/react-org-tree/f9c418ef7b904c83c1aba36cfc3aabbb9b3da10f/img/logo.svg', 10 | outputPath: 'docs-dist', 11 | base: 'react-org-tree', 12 | publicPath: '/react-org-tree/', 13 | resolve: { 14 | includes: ['docs'], 15 | previewLangs: [], 16 | }, 17 | locales: [ 18 | ['en', 'English'], 19 | ['zh', '中文'], 20 | ], 21 | navs: { 22 | en: [ 23 | null, 24 | { title: 'GitHub', path: 'https://github.com/artdong/react-org-tree' }, 25 | ], 26 | zh: [ 27 | null, 28 | { title: 'GitHub', path: 'https://github.com/artdong/react-org-tree' }, 29 | ], 30 | }, 31 | metas: [ 32 | { 33 | name: 'keywords', 34 | content: 35 | 'react, react-org-tree, react-components, javascript', 36 | }, 37 | { 38 | name: 'description', 39 | content: '🏆 一个react组织树组件', 40 | }, 41 | ], 42 | exportStatic: {}, 43 | // theme: { 44 | // '@c-primary': '#6451AB', 45 | // }, 46 | }); 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 art 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-org-tree 2 | 3 | [![npm version][npm-image]][npm-url] [![mnt-image](https://img.shields.io/maintenance/yes/2023.svg?style=flat-square)](../../commits/master) [![GitHub stars](https://img.shields.io/github/stars/artdong/react-org-tree.svg?style=flat-square)](https://github.com/artdong/react-org-tree/stargazers) [![GitHub forks](https://img.shields.io/github/forks/artdong/react-org-tree.svg?style=flat-square)](https://github.com/artdong/react-org-tree/network) [![npm download][download-image]][download-url] [![dumi](https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square)](https://github.com/umijs/dumi) [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://github.com/artdong/react-org-tree/blob/master/LICENSE) 4 | 5 | [npm-image]: http://img.shields.io/npm/v/react-org-tree.svg?style=flat-square 6 | [npm-url]: http://npmjs.org/package/react-org-tree 7 | [download-image]: https://img.shields.io/npm/dm/react-org-tree.svg?style=flat-square 8 | [download-url]: https://npmjs.org/package/react-org-tree 9 | [bundlephobia-url]: https://bundlephobia.com/result?p=react-org-tree 10 | [bundlephobia-image]: https://badgen.net/bundlephobia/minzip/react-org-tree 11 | 12 | > A simple organization tree component based on react 13 | 14 | > If you are using vue, see [vue-org-tree](https://github.com/hukaibaihu/vue-org-tree) 15 | 16 | ### Installation 17 | 18 | ``` 19 | # use npm 20 | npm i react-org-tree 21 | 22 | # use yarn 23 | yarn add react-org-tree 24 | ``` 25 | ### Usage 26 | 27 | ``` js 28 | import OrgTree from 'react-org-tree'; 29 | 30 | const horizontal = false; // true:横向 false:纵向 31 | const collapsable = true; // true:可折叠 false:不可折叠 32 | const expandAll = true; // true: 全部展开 false:全部折叠 33 | 34 | const data = { 35 | id: 0, 36 | label: 'XXX股份有限公司', 37 | children: [{ 38 | id: 1, 39 | label: '技术部', 40 | children: [{ 41 | id: 4, 42 | label: '后端工程师' 43 | }, { 44 | id: 5, 45 | label: '前端工程师' 46 | }, { 47 | id: 6, 48 | label: '运维工程师' 49 | }] 50 | }, { 51 | id: 2, 52 | label: '人事部' 53 | }, { 54 | id: 3, 55 | label: '销售部' 56 | }] 57 | } 58 | 59 | 65 | ``` 66 | 67 | ### Preview 68 | 69 | `横向(horizontal)` 70 | 71 | 72 | 73 | `纵向(vertical)` 74 | 75 | 76 | 77 | `部分展开(expand)` 78 | 79 | 80 | 81 | `全部展开(expandAll)` 82 | 83 | 84 | 85 | ## API 86 | 87 | 参数(prop) | 说明(descripton) | 类型(type) | 默认值(default) 88 | -----------|-----------------------------------------|:----------------------:|:---------------------------------------------------------: 89 | data | 树结构数据 | `Object` | {} 90 | horizontal | 是否横向 | `Boolean` | `false` 91 | collapsable | 是否可折叠 | `Boolean` | `false` 92 | expandAll | 是否展开全部 | `Boolean` | `false` 93 | labelWidth | 树节点宽度 | `Number` | `auto` 94 | labelClassName | 树节点样式 | `String` | `white` 95 | onClick | 点击事件 | Function(e:Event, data) 96 | 97 | ## Example 98 | 99 | https://artdong.github.io/react-org-tree/demo 100 | 101 | ## License 102 | 103 | react-org-tree is released under the MIT license. 104 | #### 欢迎关注微信公众号`全栈弄潮儿` ,获取更多学习资源及技术文章等 105 | 106 | * 微信公众号二维码,扫一扫或者搜索"全栈弄潮儿"即可关注 107 | 108 |

109 | Build errors 110 |

111 | 112 | #### 程序员专属工具箱(微信小程序) 113 | 114 |

115 | 116 |

117 | 118 | #### 薅羊毛,大额红包码 119 | 120 |

121 | Build errors 122 |

123 | 124 | #### 打赏,请作者喝一杯咖啡 125 | 126 |

127 | Build errors 128 |

129 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: react-org-tree 3 | hero: 4 | title: react-org-tree 5 | desc: A simple organization tree component based on react 6 | actions: 7 | - text: Get Started → 8 | link: /guide 9 | features: 10 | - title: Support 11 | desc: It‘s based on react framework. 12 | - title: Features 13 | desc: Includes horizontal, vertical, expand, expandAll and so on. 14 | - title: Production-Ready 15 | desc: Has been published on npm. 16 | footer: MIT Licensed | Copyright © 2020-present
Powered by [artdong](https://github.com/artdong) 17 | --- 18 | 19 | # react-org-tree 20 | 21 | ### 📦 Installation 22 | 23 | ``` 24 | # use npm 25 | npm i react-org-tree 26 | 27 | # use yarn 28 | yarn add react-org-tree 29 | ``` 30 | ### 🔨 Usage 31 | 32 | ``` js 33 | import OrgTree from 'react-org-tree'; 34 | 35 | const horizontal = false; // true:横向 false:纵向 36 | const collapsable = true; // true:可折叠 false:不可折叠 37 | const expandAll = true; // true: 全部展开 false:全部折叠 38 | 39 | const data = { 40 | id: 0, 41 | label: 'XXX股份有限公司', 42 | children: [{ 43 | id: 1, 44 | label: '技术部', 45 | children: [{ 46 | id: 4, 47 | label: '后端工程师' 48 | }, { 49 | id: 5, 50 | label: '前端工程师' 51 | }, { 52 | id: 6, 53 | label: '运维工程师' 54 | }] 55 | }, { 56 | id: 2, 57 | label: '人事部' 58 | }, { 59 | id: 3, 60 | label: '销售部' 61 | }] 62 | } 63 | 64 | 70 | ``` 71 | 72 | See details:[Getting Started](/guide) 73 | 74 | ### Good deal,red lucky money 75 | 76 |

77 | hb.jpeg 78 |

79 | 80 | ### Support,buy me a coffee 81 | 82 |

83 | dashang.jpeg 84 |

-------------------------------------------------------------------------------- /docs/README.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: react-org-tree 3 | hero: 4 | title: react-org-tree 5 | desc: 一个基于react的组织树组件 6 | actions: 7 | - text: 快速开始 → 8 | link: /guide 9 | features: 10 | - title: 语言 11 | desc: 基于最流行的react框架. 12 | - title: 功能 13 | desc: 可以横向、纵向展示,支持展开、折叠,自定义颜色,自定义大小等. 14 | - title: 生产可用 15 | desc: 已经发布到npm上,可使用npm或者yarn安装. 16 | footer: MIT Licensed | Copyright © 2020-present
Powered by [artdong](https://github.com/artdong) 17 | --- 18 | 19 | # react-org-tree 20 | 21 | ### 📦 安装 22 | 23 | ``` 24 | # use npm 25 | npm i react-org-tree 26 | 27 | # use yarn 28 | yarn add react-org-tree 29 | ``` 30 | ### 🔨 示例 31 | 32 | ``` js 33 | import OrgTree from 'react-org-tree'; 34 | 35 | const horizontal = false; // true:横向 false:纵向 36 | const collapsable = true; // true:可折叠 false:不可折叠 37 | const expandAll = true; // true: 全部展开 false:全部折叠 38 | 39 | const data = { 40 | id: 0, 41 | label: 'XXX股份有限公司', 42 | children: [{ 43 | id: 1, 44 | label: '技术部', 45 | children: [{ 46 | id: 4, 47 | label: '后端工程师' 48 | }, { 49 | id: 5, 50 | label: '前端工程师' 51 | }, { 52 | id: 6, 53 | label: '运维工程师' 54 | }] 55 | }, { 56 | id: 2, 57 | label: '人事部' 58 | }, { 59 | id: 3, 60 | label: '销售部' 61 | }] 62 | } 63 | 64 | 70 | ``` 71 | 72 | See details:[Getting Started](/guide) 73 | 74 | ### 薅羊毛,大额红包码 75 | 76 |

77 | hb.jpeg 78 |

79 | 80 | ### 支持赞助,请作者喝一杯咖啡 81 | 82 |

83 | dashang.jpeg 84 |

-------------------------------------------------------------------------------- /docs/demo/basic.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: basic 3 | order: 0 4 | nav: 5 | title: Demo 6 | --- 7 | 8 | ## basic 9 | 10 | 11 | 12 | ## API 13 | 14 | 参数(prop) | 说明(descripton) | 类型(type) | 默认值(default) 15 | -----------|-----------------------------------------|:----------------------:|:---------------------------------------------------------: 16 | data | 树结构数据 | `Object` | {} 17 | horizontal | 是否横向 | `Boolean` | `false` 18 | collapsable | 是否可折叠 | `Boolean` | `false` 19 | expandAll | 是否展开全部 | `Boolean` | `false` 20 | labelWidth | 树节点宽度 | `Number` | `auto` 21 | labelClassName | 树节点样式 | `String` | `white` 22 | onClick | 点击事件 | Function(e:Event, data) -------------------------------------------------------------------------------- /docs/demo/basic.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 基础 3 | order: 0 4 | nav: 5 | title: 示例 6 | --- 7 | 8 | 9 | 10 | ## API 11 | 12 | 参数(prop) | 说明(descripton) | 类型(type) | 默认值(default) 13 | -----------|-----------------------------------------|:----------------------:|:---------------------------------------------------------: 14 | data | 树结构数据 | `Object` | {} 15 | horizontal | 是否横向 | `Boolean` | `false` 16 | collapsable | 是否可折叠 | `Boolean` | `false` 17 | expandAll | 是否展开全部 | `Boolean` | `false` 18 | labelWidth | 树节点宽度 | `Number` | `auto` 19 | labelClassName | 树节点样式 | `String` | `white` 20 | onClick | 点击事件 | Function(e:Event, data) -------------------------------------------------------------------------------- /docs/demo/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: custom 3 | order: 5 4 | nav: 5 | title: Demo 6 | --- 7 | 8 | ## custom 9 | 10 | 11 | 12 | ## API 13 | 14 | 参数(prop) | 说明(descripton) | 类型(type) | 默认值(default) 15 | -----------|-----------------------------------------|:----------------------:|:---------------------------------------------------------: 16 | data | 树结构数据 | `Object` | {} 17 | horizontal | 是否横向 | `Boolean` | `false` 18 | collapsable | 是否可折叠 | `Boolean` | `false` 19 | expandAll | 是否展开全部 | `Boolean` | `false` 20 | labelWidth | 树节点宽度 | `Number` | `auto` 21 | labelClassName | 树节点样式 | `String` | `white` 22 | onClick | 点击事件 | Function(e:Event, data) -------------------------------------------------------------------------------- /docs/demo/custom.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 自定义 3 | order: 5 4 | nav: 5 | title: 示例 6 | --- 7 | 8 | 9 | 10 | ## API 11 | 12 | 参数(prop) | 说明(descripton) | 类型(type) | 默认值(default) 13 | -----------|-----------------------------------------|:----------------------:|:---------------------------------------------------------: 14 | data | 树结构数据 | `Object` | {} 15 | horizontal | 是否横向 | `Boolean` | `false` 16 | collapsable | 是否可折叠 | `Boolean` | `false` 17 | expandAll | 是否展开全部 | `Boolean` | `false` 18 | labelWidth | 树节点宽度 | `Number` | `auto` 19 | labelClassName | 树节点样式 | `String` | `white` 20 | onClick | 点击事件 | Function(e:Event, data) -------------------------------------------------------------------------------- /docs/demo/expand.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: expand 3 | order: 1 4 | nav: 5 | title: Demo 6 | --- 7 | 8 | ## expand 9 | 10 | 11 | 12 | ## API 13 | 14 | 参数(prop) | 说明(descripton) | 类型(type) | 默认值(default) 15 | -----------|-----------------------------------------|:----------------------:|:---------------------------------------------------------: 16 | data | 树结构数据 | `Object` | {} 17 | horizontal | 是否横向 | `Boolean` | `false` 18 | collapsable | 是否可折叠 | `Boolean` | `false` 19 | expandAll | 是否展开全部 | `Boolean` | `false` 20 | labelWidth | 树节点宽度 | `Number` | `auto` 21 | labelClassName | 树节点样式 | `String` | `white` 22 | onClick | 点击事件 | Function(e:Event, data) -------------------------------------------------------------------------------- /docs/demo/expand.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 展开 3 | order: 1 4 | nav: 5 | title: 示例 6 | --- 7 | 8 | 9 | 10 | ## API 11 | 12 | 参数(prop) | 说明(descripton) | 类型(type) | 默认值(default) 13 | -----------|-----------------------------------------|:----------------------:|:---------------------------------------------------------: 14 | data | 树结构数据 | `Object` | {} 15 | horizontal | 是否横向 | `Boolean` | `false` 16 | collapsable | 是否可折叠 | `Boolean` | `false` 17 | expandAll | 是否展开全部 | `Boolean` | `false` 18 | labelWidth | 树节点宽度 | `Number` | `auto` 19 | labelClassName | 树节点样式 | `String` | `white` 20 | onClick | 点击事件 | Function(e:Event, data) -------------------------------------------------------------------------------- /docs/demo/expandAll.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: expandAll 3 | order: 2 4 | nav: 5 | title: Demo 6 | --- 7 | 8 | ## expandAll 9 | 10 | 11 | 12 | ## API 13 | 14 | 参数(prop) | 说明(descripton) | 类型(type) | 默认值(default) 15 | -----------|-----------------------------------------|:----------------------:|:---------------------------------------------------------: 16 | data | 树结构数据 | `Object` | {} 17 | horizontal | 是否横向 | `Boolean` | `false` 18 | collapsable | 是否可折叠 | `Boolean` | `false` 19 | expandAll | 是否展开全部 | `Boolean` | `false` 20 | labelWidth | 树节点宽度 | `Number` | `auto` 21 | labelClassName | 树节点样式 | `String` | `white` 22 | onClick | 点击事件 | Function(e:Event, data) -------------------------------------------------------------------------------- /docs/demo/expandAll.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 展开全部 3 | order: 2 4 | nav: 5 | title: 示例 6 | --- 7 | 8 | 9 | 10 | ## API 11 | 12 | 参数(prop) | 说明(descripton) | 类型(type) | 默认值(default) 13 | -----------|-----------------------------------------|:----------------------:|:---------------------------------------------------------: 14 | data | 树结构数据 | `Object` | {} 15 | horizontal | 是否横向 | `Boolean` | `false` 16 | collapsable | 是否可折叠 | `Boolean` | `false` 17 | expandAll | 是否展开全部 | `Boolean` | `false` 18 | labelWidth | 树节点宽度 | `Number` | `auto` 19 | labelClassName | 树节点样式 | `String` | `white` 20 | onClick | 点击事件 | Function(e:Event, data) -------------------------------------------------------------------------------- /docs/demo/horizontal.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: horizontal 3 | order: 3 4 | nav: 5 | title: Demo 6 | --- 7 | 8 | 9 | 10 | ## API 11 | 12 | 参数(prop) | 说明(descripton) | 类型(type) | 默认值(default) 13 | -----------|-----------------------------------------|:----------------------:|:---------------------------------------------------------: 14 | data | 树结构数据 | `Object` | {} 15 | horizontal | 是否横向 | `Boolean` | `false` 16 | collapsable | 是否可折叠 | `Boolean` | `false` 17 | expandAll | 是否展开全部 | `Boolean` | `false` 18 | labelWidth | 树节点宽度 | `Number` | `auto` 19 | labelClassName | 树节点样式 | `String` | `white` 20 | onClick | 点击事件 | Function(e:Event, data) -------------------------------------------------------------------------------- /docs/demo/horizontal.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 横向 3 | order: 3 4 | nav: 5 | title: 示例 6 | --- 7 | 8 | 9 | 10 | ## API 11 | 12 | 参数(prop) | 说明(descripton) | 类型(type) | 默认值(default) 13 | -----------|-----------------------------------------|:----------------------:|:---------------------------------------------------------: 14 | data | 树结构数据 | `Object` | {} 15 | horizontal | 是否横向 | `Boolean` | `false` 16 | collapsable | 是否可折叠 | `Boolean` | `false` 17 | expandAll | 是否展开全部 | `Boolean` | `false` 18 | labelWidth | 树节点宽度 | `Number` | `auto` 19 | labelClassName | 树节点样式 | `String` | `white` 20 | onClick | 点击事件 | Function(e:Event, data) -------------------------------------------------------------------------------- /docs/demo/vertical.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: vertical 3 | order: 4 4 | nav: 5 | title: Demo 6 | --- 7 | 8 | 9 | ## API 10 | 11 | 参数(prop) | 说明(descripton) | 类型(type) | 默认值(default) 12 | -----------|-----------------------------------------|:----------------------:|:---------------------------------------------------------: 13 | data | 树结构数据 | `Object` | {} 14 | horizontal | 是否横向 | `Boolean` | `false` 15 | collapsable | 是否可折叠 | `Boolean` | `false` 16 | expandAll | 是否展开全部 | `Boolean` | `false` 17 | labelWidth | 树节点宽度 | `Number` | `auto` 18 | labelClassName | 树节点样式 | `String` | `white` 19 | onClick | 点击事件 | Function(e:Event, data) -------------------------------------------------------------------------------- /docs/demo/vertical.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 竖向 3 | order: 4 4 | nav: 5 | title: 示例 6 | --- 7 | 8 | 9 | 10 | ## API 11 | 12 | 参数(prop) | 说明(descripton) | 类型(type) | 默认值(default) 13 | -----------|-----------------------------------------|:----------------------:|:---------------------------------------------------------: 14 | data | 树结构数据 | `Object` | {} 15 | horizontal | 是否横向 | `Boolean` | `false` 16 | collapsable | 是否可折叠 | `Boolean` | `false` 17 | expandAll | 是否展开全部 | `Boolean` | `false` 18 | labelWidth | 树节点宽度 | `Number` | `auto` 19 | labelClassName | 树节点样式 | `String` | `white` 20 | onClick | 点击事件 | Function(e:Event, data) -------------------------------------------------------------------------------- /docs/examples/basic.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import OrgTree from 'react-org-tree'; 4 | 5 | class OrgTreeDemo extends Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | data: { 10 | id: 0, 11 | label: 'XXX股份有限公司', 12 | children: [{ 13 | id: 1, 14 | label: '技术部', 15 | children: [{ 16 | id: 4, 17 | label: '后端工程师' 18 | }, { 19 | id: 5, 20 | label: '前端工程师' 21 | }, { 22 | id: 6, 23 | label: '运维工程师' 24 | }] 25 | }, { 26 | id: 2, 27 | label: '人事部' 28 | }, { 29 | id: 3, 30 | label: '销售部' 31 | }] 32 | }, 33 | horizontal: false, 34 | collapsable: false, 35 | expandAll: true, 36 | labelClassName: 'bg-white' 37 | }; 38 | } 39 | 40 | componentDidMount() { 41 | } 42 | 43 | componentWillUnmount() { 44 | } 45 | 46 | render() { 47 | const { data, horizontal, collapsable, expandAll, labelClassName } = this.state; 48 | 49 | return ( 50 |
51 | { 58 | return data.label; 59 | }} 60 | onClick={(e, data) => { 61 | //todo 62 | }} 63 | > 64 | 65 |
66 | ); 67 | } 68 | } 69 | 70 | export default OrgTreeDemo; -------------------------------------------------------------------------------- /docs/examples/custom.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import OrgTree from 'react-org-tree'; 4 | 5 | class OrgTreeDemo extends Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | data: { 10 | id: 0, 11 | label: 'XXX股份有限公司', 12 | children: [{ 13 | id: 1, 14 | label: '技术部', 15 | children: [{ 16 | id: 4, 17 | label: '后端工程师' 18 | }, { 19 | id: 5, 20 | label: '前端工程师' 21 | }, { 22 | id: 6, 23 | label: '运维工程师' 24 | }] 25 | }, { 26 | id: 2, 27 | label: '人事部' 28 | }, { 29 | id: 3, 30 | label: '销售部' 31 | }] 32 | }, 33 | horizontal: false, 34 | collapsable: true, 35 | expandAll: true, 36 | labelClassName: 'org-tree-node-label-inner-blue' 37 | }; 38 | } 39 | 40 | componentDidMount() { 41 | } 42 | 43 | componentWillUnmount() { 44 | } 45 | 46 | render() { 47 | const { data, horizontal, collapsable, expandAll, labelClassName } = this.state; 48 | 49 | return ( 50 |
51 | { 58 | return data.label; 59 | }} 60 | onClick={(e, data) => { 61 | //todo 62 | }} 63 | > 64 | 65 |
66 | ); 67 | } 68 | } 69 | 70 | export default OrgTreeDemo; -------------------------------------------------------------------------------- /docs/examples/expand.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import OrgTree from 'react-org-tree'; 4 | 5 | class OrgTreeDemo extends Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | data: { 10 | id: 0, 11 | label: 'XXX股份有限公司', 12 | children: [{ 13 | id: 1, 14 | label: '技术部', 15 | children: [{ 16 | id: 4, 17 | label: '后端工程师' 18 | }, { 19 | id: 5, 20 | label: '前端工程师' 21 | }, { 22 | id: 6, 23 | label: '运维工程师' 24 | }] 25 | }, { 26 | id: 2, 27 | label: '人事部' 28 | }, { 29 | id: 3, 30 | label: '销售部' 31 | }] 32 | }, 33 | horizontal: false, 34 | collapsable: true, 35 | expandAll: false, 36 | labelClassName: 'bg-white' 37 | }; 38 | } 39 | 40 | componentDidMount() { 41 | } 42 | 43 | componentWillUnmount() { 44 | } 45 | 46 | render() { 47 | const { data, horizontal, collapsable, expandAll, labelClassName } = this.state; 48 | 49 | return ( 50 |
51 | { 58 | return data.label; 59 | }} 60 | onClick={(e, data) => { 61 | //todo 62 | }} 63 | > 64 | 65 |
66 | ); 67 | } 68 | } 69 | 70 | export default OrgTreeDemo; -------------------------------------------------------------------------------- /docs/examples/expandAll.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import OrgTree from 'react-org-tree'; 4 | 5 | class OrgTreeDemo extends Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | data: { 10 | id: 0, 11 | label: 'XXX股份有限公司', 12 | children: [{ 13 | id: 1, 14 | label: '技术部', 15 | children: [{ 16 | id: 4, 17 | label: '后端工程师' 18 | }, { 19 | id: 5, 20 | label: '前端工程师' 21 | }, { 22 | id: 6, 23 | label: '运维工程师' 24 | }] 25 | }, { 26 | id: 2, 27 | label: '人事部' 28 | }, { 29 | id: 3, 30 | label: '销售部' 31 | }] 32 | }, 33 | horizontal: false, 34 | collapsable: true, 35 | expandAll: true, 36 | labelClassName: 'bg-white' 37 | }; 38 | } 39 | 40 | componentDidMount() { 41 | } 42 | 43 | componentWillUnmount() { 44 | } 45 | 46 | render() { 47 | const { data, horizontal, collapsable, expandAll, labelClassName } = this.state; 48 | 49 | return ( 50 |
51 | { 58 | return data.label; 59 | }} 60 | onClick={(e, data) => { 61 | //todo 62 | }} 63 | > 64 | 65 |
66 | ); 67 | } 68 | } 69 | 70 | export default OrgTreeDemo; -------------------------------------------------------------------------------- /docs/examples/horizontal.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import OrgTree from 'react-org-tree'; 4 | 5 | class OrgTreeDemo extends Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | data: { 10 | id: 0, 11 | label: 'XXX股份有限公司', 12 | children: [{ 13 | id: 1, 14 | label: '技术部', 15 | children: [{ 16 | id: 4, 17 | label: '后端工程师' 18 | }, { 19 | id: 5, 20 | label: '前端工程师' 21 | }, { 22 | id: 6, 23 | label: '运维工程师' 24 | }] 25 | }, { 26 | id: 2, 27 | label: '人事部' 28 | }, { 29 | id: 3, 30 | label: '销售部' 31 | }] 32 | }, 33 | horizontal: true, 34 | collapsable: true, 35 | expandAll: true, 36 | labelClassName: 'bg-white' 37 | }; 38 | } 39 | 40 | componentDidMount() { 41 | } 42 | 43 | componentWillUnmount() { 44 | } 45 | 46 | render() { 47 | const { data, horizontal, collapsable, expandAll, labelClassName } = this.state; 48 | 49 | return ( 50 |
51 | { 58 | return data.label; 59 | }} 60 | onClick={(e, data) => { 61 | //todo 62 | }} 63 | > 64 | 65 |
66 | ); 67 | } 68 | } 69 | 70 | export default OrgTreeDemo; -------------------------------------------------------------------------------- /docs/examples/vertical.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import OrgTree from 'react-org-tree'; 4 | 5 | class OrgTreeDemo extends Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | data: { 10 | id: 0, 11 | label: 'XXX股份有限公司', 12 | children: [{ 13 | id: 1, 14 | label: '技术部', 15 | children: [{ 16 | id: 4, 17 | label: '后端工程师' 18 | }, { 19 | id: 5, 20 | label: '前端工程师' 21 | }, { 22 | id: 6, 23 | label: '运维工程师' 24 | }] 25 | }, { 26 | id: 2, 27 | label: '人事部' 28 | }, { 29 | id: 3, 30 | label: '销售部' 31 | }] 32 | }, 33 | horizontal: false, 34 | collapsable: true, 35 | expandAll: true, 36 | labelClassName: 'bg-white' 37 | }; 38 | } 39 | 40 | componentDidMount() { 41 | } 42 | 43 | componentWillUnmount() { 44 | } 45 | 46 | render() { 47 | const { data, horizontal, collapsable, expandAll, labelClassName } = this.state; 48 | 49 | return ( 50 |
51 | { 58 | return data.label; 59 | }} 60 | onClick={(e, data) => { 61 | //todo 62 | }} 63 | > 64 | 65 |
66 | ); 67 | } 68 | } 69 | 70 | export default OrgTreeDemo; -------------------------------------------------------------------------------- /docs/guide/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | nav: 3 | order: 0 4 | toc: menu 5 | --- 6 | 7 | # Getting Started 8 | 9 | ### Installation 10 | 11 | ``` 12 | # use npm 13 | npm i react-org-tree 14 | 15 | # use yarn 16 | yarn add react-org-tree 17 | ``` 18 | 19 | ### Your First Example 20 | 21 | 22 | 23 | See more examples:[more](/demo) 24 | 25 | ### API 26 | 27 | 参数(prop) | 说明(descripton) | 类型(type) | 默认值(default) 28 | -----------|-----------------------------------------|:----------------------:|:---------------------------------------------------------: 29 | data | 树结构数据 | `Object` | {} 30 | horizontal | 是否横向 | `Boolean` | `false` 31 | collapsable | 是否可折叠 | `Boolean` | `false` 32 | expandAll | 是否展开全部 | `Boolean` | `false` 33 | labelWidth | 树节点宽度 | `Number` | `auto` 34 | labelClassName | 树节点样式 | `String` | `white` 35 | onClick | 点击事件 | Function(e:Event, data) 36 | -------------------------------------------------------------------------------- /docs/guide/README.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | nav: 3 | title: 指南 4 | order: 0 5 | toc: menu 6 | --- 7 | 8 | # 快速上手 9 | 10 | ### 安装 11 | 12 | ``` 13 | # use npm 14 | npm i react-org-tree 15 | 16 | # use yarn 17 | yarn add react-org-tree 18 | ``` 19 | 20 | ### 第一个例子 21 | 22 | 23 | 24 | 更多在线例子:[查看](/demo) 25 | 26 | ### API 27 | 28 | 参数(prop) | 说明(descripton) | 类型(type) | 默认值(default) 29 | -----------|-----------------------------------------|:----------------------:|:---------------------------------------------------------: 30 | data | 树结构数据 | `Object` | {} 31 | horizontal | 是否横向 | `Boolean` | `false` 32 | collapsable | 是否可折叠 | `Boolean` | `false` 33 | expandAll | 是否展开全部 | `Boolean` | `false` 34 | labelWidth | 树节点宽度 | `Number` | `auto` 35 | labelClassName | 树节点样式 | `String` | `white` 36 | onClick | 点击事件 | Function(e:Event, data) 37 | -------------------------------------------------------------------------------- /docs/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artdong/react-org-tree/2fa90bcec90f4987eae8530ddb5d90d3cd182a1c/docs/img/logo.png -------------------------------------------------------------------------------- /docs/img/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artdong/react-org-tree/2fa90bcec90f4987eae8530ddb5d90d3cd182a1c/img/1.png -------------------------------------------------------------------------------- /img/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artdong/react-org-tree/2fa90bcec90f4987eae8530ddb5d90d3cd182a1c/img/2.png -------------------------------------------------------------------------------- /img/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artdong/react-org-tree/2fa90bcec90f4987eae8530ddb5d90d3cd182a1c/img/3.png -------------------------------------------------------------------------------- /img/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artdong/react-org-tree/2fa90bcec90f4987eae8530ddb5d90d3cd182a1c/img/4.png -------------------------------------------------------------------------------- /img/dashang.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artdong/react-org-tree/2fa90bcec90f4987eae8530ddb5d90d3cd182a1c/img/dashang.jpeg -------------------------------------------------------------------------------- /img/hb.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artdong/react-org-tree/2fa90bcec90f4987eae8530ddb5d90d3cd182a1c/img/hb.jpeg -------------------------------------------------------------------------------- /img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artdong/react-org-tree/2fa90bcec90f4987eae8530ddb5d90d3cd182a1c/img/logo.png -------------------------------------------------------------------------------- /img/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/logo1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/logo2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/logo3.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "./", 4 | "paths": { 5 | "react-org-tree": ["src/index.js"] 6 | }, 7 | "target": "ES6", 8 | "module": "commonjs", 9 | "jsx": "react", 10 | "allowSyntheticDefaultImports": true 11 | }, 12 | "include": [ 13 | "src/**/*" 14 | ], 15 | "exclude": ["node_modules"] 16 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-org-tree", 3 | "version": "1.0.1", 4 | "description": "a simple organization tree component based on react", 5 | "main": "dist/bundle.js", 6 | "files": [ 7 | "dist", 8 | "lib" 9 | ], 10 | "scripts": { 11 | "dev": "dumi dev", 12 | "start": "dumi dev", 13 | "docs:start": "dumi dev", 14 | "docs:build": "dumi build", 15 | "predeploy": "dumi build", 16 | "deploy": "gh-pages -d docs-dist", 17 | "test": "echo \"Error: no test specified\" && exit 1", 18 | "build": "webpack" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/artdong/react-org-tree.git" 23 | }, 24 | "bugs": { 25 | "url": "https://github.com/artdong/react-org-tree/issues" 26 | }, 27 | "homepage": "https://artdong.github.io/react-org-tree", 28 | "keywords": [ 29 | "react", 30 | "org", 31 | "tree", 32 | "org-tree", 33 | "react-org-tree", 34 | "react-org-chart" 35 | ], 36 | "author": "artdong", 37 | "license": "MIT", 38 | "devDependencies": { 39 | "babel-core": "^6.26.0", 40 | "babel-loader": "^7.1.2", 41 | "babel-preset-env": "^1.6.1", 42 | "babel-preset-react": "^6.24.1", 43 | "css-loader": "^2.0.1", 44 | "node-sass": "^4.11.0", 45 | "less": "^3.9.0", 46 | "less-loader": "^4.1.0", 47 | "prop-types": "^15.6.0", 48 | "react": "^16.2.0", 49 | "sass-loader": "^7.1.0", 50 | "style-loader": "^0.23.1", 51 | "webpack": "^3.10.0", 52 | "webpack-node-externals": "^1.6.0", 53 | "dumi": "^1.1.4", 54 | "gh-pages": "^1.0.0" 55 | }, 56 | "dependencies": { 57 | "classnames": "^2.2.6" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import OrgTree from './org_tree.jsx'; 2 | 3 | export default OrgTree -------------------------------------------------------------------------------- /src/org_tree.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | // 判断是否叶子节点 4 | const isLeaf = (data, prop) => { 5 | const node = prop.node; 6 | return !(Array.isArray(data[node.children]) && data[node.children].length > 0); 7 | }; 8 | 9 | // 创建 node 节点 10 | export const renderNode = (data, prop) => { 11 | const node = prop.node; 12 | const cls = ['org-tree-node']; 13 | const childNodes = []; 14 | 15 | if (isLeaf(data, prop)) { 16 | cls.push('is-leaf'); 17 | } else if (prop.collapsable && !data[node.expand]) { 18 | cls.push('collapsed'); 19 | } 20 | 21 | childNodes.push(renderLabel(data, prop)); 22 | 23 | if (!prop.collapsable || data[node.expand]) { 24 | childNodes.push(renderChildren(data.children, prop)); 25 | } 26 | 27 | return React.createElement('div', { 28 | key: data.id, 29 | className: cls.join(' ') 30 | }, childNodes); 31 | }; 32 | 33 | // 创建展开折叠按钮 34 | export const renderBtn = (data, prop ) => { 35 | const { onExpand } = prop; 36 | const node = prop.node; 37 | 38 | let cls = ['org-tree-node-btn']; 39 | 40 | if (data[node.expand]) { 41 | cls.push('expanded'); 42 | } 43 | 44 | return React.createElement('span', { 45 | key: data.id, 46 | className: cls.join(' '), 47 | onClick: (e) => { 48 | e.stopPropagation(); 49 | typeof onExpand === 'function' && onExpand(e, data); 50 | } 51 | }); 52 | }; 53 | 54 | // 创建 label 节点 55 | export const renderLabel = (data, prop) => { 56 | const node = prop.node; 57 | const label = data[node.label]; 58 | const renderContent = prop.renderContent; 59 | const onClick = prop.onClick; 60 | 61 | const childNodes = []; 62 | if (typeof renderContent === 'function') { 63 | let vnode = renderContent(data); 64 | 65 | vnode && childNodes.push(vnode); 66 | } else { 67 | childNodes.push(label); 68 | } 69 | 70 | if (prop.collapsable && !isLeaf(data, prop)) { 71 | childNodes.push(renderBtn(data, prop)); 72 | } 73 | 74 | const cls = ['org-tree-node-label-inner']; 75 | 76 | let { labelWidth, labelClassName } = prop; 77 | 78 | if (typeof labelWidth === 'number') { 79 | labelWidth += 'px'; 80 | } 81 | 82 | labelClassName && cls.push(labelClassName); 83 | 84 | return React.createElement('div', { 85 | key: `label_${data.id}`, 86 | className: 'org-tree-node-label', 87 | onClick: (e) => typeof onClick === 'function' && onClick(e, data) 88 | }, [React.createElement('div', { 89 | key: `label_inner_${data.id}`, 90 | className: cls.join(' '), 91 | style: { width: labelWidth } 92 | }, childNodes)]); 93 | }; 94 | 95 | // 创建 node 子节点 96 | export const renderChildren = (list, prop) => { 97 | if (Array.isArray(list) && list.length) { 98 | const children = list.map(item => { 99 | return renderNode(item, prop); 100 | }); 101 | return React.createElement('div', { 102 | key: `children_${children[0].key}`, 103 | className: 'org-tree-node-children' 104 | }, children); 105 | } 106 | return ''; 107 | }; 108 | 109 | export const render = (props) => { 110 | return renderNode(props.data, props); 111 | }; 112 | 113 | export default render; 114 | -------------------------------------------------------------------------------- /src/org_tree.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classnames from 'classnames'; 4 | 5 | import TreeNode from './org_tree'; 6 | 7 | import './org_tree.less'; 8 | 9 | //组件 10 | class OrgTree extends Component { 11 | constructor(props) { 12 | super(props); 13 | this.handleExpand = this.handleExpand.bind(this); 14 | this.collapse = this.collapse.bind(this); 15 | this.toggleExpand = this.toggleExpand.bind(this); 16 | } 17 | 18 | componentDidMount() { 19 | const { expandAll, data } = this.props; 20 | if(expandAll) this.toggleExpand(data, true); 21 | } 22 | 23 | componentWillUnmount() { 24 | } 25 | 26 | handleExpand(e, nodeData) { 27 | if ('expand' in nodeData) { 28 | nodeData.expand = !nodeData.expand; 29 | if (!nodeData.expand && nodeData.children) { 30 | this.collapse(nodeData.children); 31 | } 32 | this.forceUpdate(); 33 | }else { 34 | nodeData.expand = true; 35 | this.forceUpdate(); 36 | } 37 | } 38 | 39 | collapse(list) { 40 | let _this = this; 41 | list.forEach(function(child) { 42 | if (child.expand) { 43 | child.expand = false; 44 | } 45 | child.children && _this.collapse(child.children); 46 | }); 47 | } 48 | 49 | toggleExpand(data, val) { 50 | let _this = this; 51 | if (Array.isArray(data)) { 52 | data.forEach(function(item) { 53 | item.expand = val; 54 | if (item.children) { 55 | _this.toggleExpand(item.children, val); 56 | } 57 | }); 58 | } else { 59 | data.expand = val; 60 | if (data.children) { 61 | _this.toggleExpand(data.children, val); 62 | } 63 | } 64 | this.forceUpdate(); 65 | } 66 | 67 | render() { 68 | const { horizontal, node, data, onClick } = this.props; 69 | return
70 |
73 | this.handleExpand(e, nodeData)} 77 | onClick={(e, nodeData)=> onClick && onClick(e, nodeData)} 78 | {...this.props} 79 | /> 80 |
81 |
; 82 | } 83 | } 84 | 85 | OrgTree.propTypes = { 86 | data: PropTypes.object, 87 | node: PropTypes.object, 88 | horizontal: PropTypes.bool, 89 | collapsable: PropTypes.bool, 90 | expandAll: PropTypes.bool, 91 | renderContent: PropTypes.func, 92 | labelWidth: PropTypes.number, 93 | labelClassName: PropTypes.string, 94 | onClick: PropTypes.func 95 | } 96 | 97 | OrgTree.defaultProps = { 98 | node: { 99 | label: 'label', 100 | expand: 'expand', 101 | children: 'children' 102 | }, 103 | renderContent: function(data) { 104 | return data.label; 105 | } 106 | }; 107 | 108 | export default OrgTree; -------------------------------------------------------------------------------- /src/org_tree.less: -------------------------------------------------------------------------------- 1 | .org-tree-container { 2 | display: inline-block; 3 | padding: 15px; 4 | background-color: #fff; 5 | } 6 | 7 | .org-tree { 8 | display: table; 9 | text-align: center; 10 | 11 | &:before, &:after { 12 | content: ''; 13 | display: table; 14 | } 15 | 16 | &:after { 17 | clear: both; 18 | } 19 | } 20 | 21 | .org-tree-node, 22 | .org-tree-node-children { 23 | position: relative; 24 | margin: 0; 25 | padding: 0; 26 | list-style-type: none; 27 | 28 | &:before, &:after { 29 | transition: all .35s; 30 | } 31 | } 32 | .org-tree-node-label { 33 | position: relative; 34 | display: inline-block; 35 | 36 | .org-tree-node-label-inner { 37 | padding: 10px 15px; 38 | text-align: center; 39 | color: black; 40 | border-radius: 3px; 41 | box-shadow: 0 1px 5px rgba(0, 0, 0, .15); 42 | } 43 | } 44 | .org-tree-node-btn { 45 | position: absolute; 46 | top: 100%; 47 | left: 50%; 48 | width: 20px; 49 | height: 20px; 50 | z-index: 10; 51 | margin-left: -11px; 52 | margin-top: 9px; 53 | background-color: #fff; 54 | border: 1px solid #ccc; 55 | border-radius: 50%; 56 | box-shadow: 0 0 2px rgba(0, 0, 0, .15); 57 | cursor: pointer; 58 | transition: all .35s ease; 59 | 60 | &:hover { 61 | background-color: #e7e8e9; 62 | transform: scale(1.15); 63 | } 64 | 65 | &:before, &:after { 66 | content: ''; 67 | position: absolute; 68 | } 69 | 70 | &:before { 71 | top: 50%; 72 | left: 4px; 73 | right: 4px; 74 | height: 0; 75 | border-top: 1px solid #ccc; 76 | } 77 | 78 | &:after { 79 | top: 4px; 80 | left: 50%; 81 | bottom: 4px; 82 | width: 0; 83 | border-left: 1px solid #ccc; 84 | } 85 | 86 | &.expanded:after { 87 | border: none; 88 | } 89 | } 90 | .org-tree-node { 91 | padding-top: 20px; 92 | display: table-cell; 93 | vertical-align: top; 94 | 95 | &.is-leaf, &.collapsed { 96 | padding-left: 10px; 97 | padding-right: 10px; 98 | } 99 | 100 | &:before, &:after { 101 | content: ''; 102 | position: absolute; 103 | top: 0; 104 | left: 0; 105 | width: 50%; 106 | height: 19px; 107 | } 108 | 109 | &:after { 110 | left: 50%; 111 | border-left: 1px solid #ddd; 112 | } 113 | 114 | &:not(:first-child):before, 115 | &:not(:last-child):after { 116 | border-top: 1px solid #ddd; 117 | } 118 | 119 | } 120 | .collapsable .org-tree-node.collapsed { 121 | padding-bottom: 30px; 122 | 123 | .org-tree-node-label:after { 124 | content: ''; 125 | position: absolute; 126 | top: 100%; 127 | left: 0; 128 | width: 50%; 129 | height: 20px; 130 | border-right: 1px solid #ddd; 131 | } 132 | } 133 | .org-tree > .org-tree-node { 134 | padding-top: 0; 135 | 136 | &:after { 137 | border-left: 0; 138 | } 139 | } 140 | .org-tree-node-children { 141 | padding-top: 20px; 142 | display: table; 143 | 144 | &:before { 145 | content: ''; 146 | position: absolute; 147 | top: 0; 148 | left: 50%; 149 | width: 0; 150 | height: 20px; 151 | border-left: 1px solid #ddd; 152 | } 153 | 154 | &:after { 155 | content: ''; 156 | display: table; 157 | clear: both; 158 | } 159 | } 160 | 161 | .horizontal { 162 | .org-tree-node { 163 | display: table-cell; 164 | float: none; 165 | padding-top: 0; 166 | padding-left: 20px; 167 | 168 | &.is-leaf, &.collapsed { 169 | padding-top: 10px; 170 | padding-bottom: 10px; 171 | } 172 | 173 | &:before, &:after { 174 | width: 19px; 175 | height: 50%; 176 | } 177 | 178 | &:after { 179 | top: 50%; 180 | left: 0; 181 | border-left: 0; 182 | } 183 | 184 | &:only-child:before { 185 | top: 1px; 186 | border-bottom: 1px solid #ddd; 187 | } 188 | 189 | &:not(:first-child):before, 190 | &:not(:last-child):after { 191 | border-top: 0; 192 | border-left: 1px solid #ddd; 193 | } 194 | 195 | &:not(:only-child):after { 196 | border-top: 1px solid #ddd; 197 | } 198 | 199 | .org-tree-node-inner { 200 | display: table; 201 | } 202 | 203 | } 204 | 205 | .org-tree-node-label { 206 | display: table-cell; 207 | vertical-align: middle; 208 | } 209 | 210 | &.collapsable .org-tree-node.collapsed { 211 | padding-right: 30px; 212 | 213 | .org-tree-node-label:after { 214 | top: 0; 215 | left: 100%; 216 | width: 20px; 217 | height: 50%; 218 | border-right: 0; 219 | border-bottom: 1px solid #ddd; 220 | } 221 | } 222 | 223 | .org-tree-node-btn { 224 | top: 50%; 225 | left: 100%; 226 | margin-top: -11px; 227 | margin-left: 9px; 228 | } 229 | 230 | & > .org-tree-node:only-child:before { 231 | border-bottom: 0; 232 | } 233 | 234 | .org-tree-node-children { 235 | display: table-cell; 236 | padding-top: 0; 237 | padding-left: 20px; 238 | 239 | &:before { 240 | top: 50%; 241 | left: 0; 242 | width: 20px; 243 | height: 0; 244 | border-left: 0; 245 | border-top: 1px solid #ddd; 246 | } 247 | 248 | &:after { 249 | display: none; 250 | } 251 | 252 | & > .org-tree-node { 253 | display: block; 254 | } 255 | } 256 | } 257 | 258 | .text-center { 259 | text-align: center; 260 | } 261 | 262 | .org-tree-node-label .org-tree-node-label-inner-blue { 263 | background: #1890ff; 264 | color: white; 265 | } 266 | 267 | .org-tree-node-label .org-tree-node-label-inner-green { 268 | background: #52c41a;; 269 | color: white; 270 | } 271 | 272 | .org-tree-node-label .org-tree-node-label-inner-cyan { 273 | background: #13c2c2; 274 | color: white; 275 | } 276 | 277 | .org-tree-node-label .org-tree-node-label-inner-pink { 278 | background: #eb2f96; 279 | color: white; 280 | } 281 | 282 | .org-tree-node-label .org-tree-node-label-inner-orange { 283 | background: #fa8c16; 284 | color: white; 285 | } 286 | 287 | .org-tree-node-label .org-tree-node-label-inner-yellow { 288 | background: #fadb14; 289 | color: white; 290 | } 291 | 292 | .org-tree-node-label .org-tree-node-label-inner-gold { 293 | background: #faad14; 294 | color: white; 295 | } 296 | 297 | .org-tree-node-label .org-tree-node-label-inner-red { 298 | background: #f5222d; 299 | color: white; 300 | } -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const nodeExternals = require('webpack-node-externals'); 3 | 4 | module.exports = { 5 | entry: './src/index.js', 6 | output: { 7 | filename: 'bundle.js', 8 | path: path.resolve(__dirname, 'dist'), 9 | libraryTarget: 'commonjs2' 10 | }, 11 | module: { 12 | rules: [ 13 | { 14 | test: /(\.js|\.jsx)$/, 15 | use: 'babel-loader', 16 | exclude: /node_modules/ 17 | }, 18 | { 19 | test: /(\.css|\.scss|\.less)$/, 20 | use: ['style-loader', 'css-loader', 'sass-loader', 'less-loader'] 21 | } 22 | ] 23 | }, 24 | resolve: { 25 | extensions: ['.js', '.jsx', '.json', '.less'], 26 | alias: { 27 | 'react-org-tree': path.resolve('src/index.js') 28 | } 29 | }, 30 | externals: [nodeExternals()] 31 | }; 32 | --------------------------------------------------------------------------------