From 5ea54b104a5e41dcf63d51aa9b136fdad44b2869 Mon Sep 17 00:00:00 2001 From: tjz <415800467@qq.com> Date: Fri, 23 Mar 2018 21:30:20 +0800 Subject: [PATCH] add tree --- components/checkbox/Checkbox.jsx | 1 - components/dropdown/index.en-US.md | 4 +- components/dropdown/index.zh-CN.md | 4 +- components/trigger/index.md | 2 +- components/vc-tree/assets/icons.png | Bin 0 -> 11173 bytes components/vc-tree/assets/index.less | 192 ++++++++ components/vc-tree/assets/line.gif | Bin 0 -> 45 bytes components/vc-tree/assets/loading.gif | Bin 0 -> 381 bytes components/vc-tree/index.js | 3 + components/vc-tree/src/Tree.jsx | 610 ++++++++++++++++++++++++++ components/vc-tree/src/TreeNode.jsx | 585 ++++++++++++++++++++++++ components/vc-tree/src/index.js | 6 + components/vc-tree/src/util.js | 399 +++++++++++++++++ 13 files changed, 1800 insertions(+), 6 deletions(-) create mode 100644 components/vc-tree/assets/icons.png create mode 100644 components/vc-tree/assets/index.less create mode 100644 components/vc-tree/assets/line.gif create mode 100644 components/vc-tree/assets/loading.gif create mode 100644 components/vc-tree/index.js create mode 100644 components/vc-tree/src/Tree.jsx create mode 100644 components/vc-tree/src/TreeNode.jsx create mode 100644 components/vc-tree/src/index.js create mode 100644 components/vc-tree/src/util.js diff --git a/components/checkbox/Checkbox.jsx b/components/checkbox/Checkbox.jsx index 722ed86e9..3056fc5c1 100644 --- a/components/checkbox/Checkbox.jsx +++ b/components/checkbox/Checkbox.jsx @@ -20,7 +20,6 @@ export default { }, inject: { checkboxGroupContext: { default: null }, - test: { default: null }, }, data () { const { checkboxGroupContext, checked, defaultChecked, value } = this diff --git a/components/dropdown/index.en-US.md b/components/dropdown/index.en-US.md index 4c872bd8c..e0f7c5b56 100644 --- a/components/dropdown/index.en-US.md +++ b/components/dropdown/index.en-US.md @@ -8,7 +8,7 @@ | getPopupContainer | to set the container of the dropdown menu. The default is to create a `div` element in `body`, you can reset it to the scrolling area and make a relative reposition. [example](https://codepen.io/afc163/pen/zEjNOy?editors=0010) | Function(triggerNode) | `() => document.body` | | overlay(slot) | the dropdown menu | [Menu](#/us/components/menu) | - | | placement | placement of pop menu: `bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` | -| trigger | the trigger mode which executes the drop-down action | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` | +| trigger | the trigger mode which executes the drop-down action | Array<`click`\|`hover`\|`contextmenu`> | `['hover']` | | visible(v-model) | whether the dropdown menu is visible | boolean | - | ### events @@ -30,7 +30,7 @@ You should use [Menu](#/us/components/menu/) as `overlay`. The menu items and di | overlay(slot) | the dropdown menu | [Menu](#/us/components/menu) | - | | placement | placement of pop menu: `bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` | | size | size of the button, the same as [Button](#/us/components/button) | string | `default` | -| trigger | the trigger mode which executes the drop-down action | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` | +| trigger | the trigger mode which executes the drop-down action | Array<`click`\|`hover`\|`contextmenu`> | `['hover']` | | type | type of the button, the same as [Button](#/us/components/button) | string | `default` | | visible | whether the dropdown menu is visible | boolean | - | diff --git a/components/dropdown/index.zh-CN.md b/components/dropdown/index.zh-CN.md index 8c4f839ff..b65b5cf1d 100644 --- a/components/dropdown/index.zh-CN.md +++ b/components/dropdown/index.zh-CN.md @@ -8,7 +8,7 @@ | getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。 | Function(triggerNode) | `() => document.body` | | overlay(slot) | 菜单 | [Menu](#/cn/components/menu) | - | | placement | 菜单弹出位置:`bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` | -| trigger | 触发下拉的行为 | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` | +| trigger | 触发下拉的行为 | Array<`click`\|`hover`\|`contextmenu`> | `['hover']` | | visible(v-model) | 菜单是否显示 | boolean | - | `overlay` 菜单使用 [Menu](#/cn/components/menu/),还包括菜单项 `Menu.Item`,分割线 `Menu.Divider`。 @@ -31,7 +31,7 @@ | overlay(slot) | 菜单 | [Menu](#/cn/components/menu/) | - | | placement | 菜单弹出位置:`bottomLeft` `bottomCenter` `bottomRight` `topLeft` `topCenter` `topRight` | String | `bottomLeft` | | size | 按钮大小,和 [Button](#/cn/components/button/) 一致 | string | 'default' | -| trigger | 触发下拉的行为 | Array<`click`\|`hover`\|`contextMenu`> | `['hover']` | +| trigger | 触发下拉的行为 | Array<`click`\|`hover`\|`contextmenu`> | `['hover']` | | type | 按钮类型,和 [Button](#/cn/components/button/) 一致 | string | 'default' | | visible(v-model) | 菜单是否显示 | boolean | - | diff --git a/components/trigger/index.md b/components/trigger/index.md index 69f9cb643..bae1a0f2a 100644 --- a/components/trigger/index.md +++ b/components/trigger/index.md @@ -40,7 +40,7 @@ action string[] ['hover'] - which actions cause popup shown. enum of 'hover','click','focus','contextMenu' + which actions cause popup shown. enum of 'hover','click','focus','contextmenu' mouseEnterDelay diff --git a/components/vc-tree/assets/icons.png b/components/vc-tree/assets/icons.png new file mode 100644 index 0000000000000000000000000000000000000000..ffda01ef1cccc398ee4e2327f4093ba1130a4961 GIT binary patch literal 11173 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 X3wf1`XyoU;TL_tNiW1dgpn(4aGkUu% literal 0 HcmV?d00001 diff --git a/components/vc-tree/assets/index.less b/components/vc-tree/assets/index.less new file mode 100644 index 000000000..cde71e949 --- /dev/null +++ b/components/vc-tree/assets/index.less @@ -0,0 +1,192 @@ +@treePrefixCls: rc-tree; +.@{treePrefixCls} { + margin: 0; + padding: 5px; + li { + padding: 0; + margin: 0; + list-style: none; + white-space: nowrap; + outline: 0; + .draggable { + color: #333; + -moz-user-select: none; + -khtml-user-select: none; + -webkit-user-select: none; + user-select: none; + /* Required to make elements draggable in old WebKit */ + -khtml-user-drag: element; + -webkit-user-drag: element; + } + &.drag-over { + > .draggable { + background-color: #316ac5; + color: white; + border: 1px #316ac5 solid; + opacity: 0.8; + } + } + &.drag-over-gap-top { + > .draggable { + border-top: 2px blue solid; + } + } + &.drag-over-gap-bottom { + > .draggable { + border-bottom: 2px blue solid; + } + } + &.filter-node { + > .@{treePrefixCls}-node-content-wrapper { + color: #a60000!important; + font-weight: bold!important; + } + } + ul { + margin: 0; + padding: 0 0 0 18px; + } + .@{treePrefixCls}-node-content-wrapper { + display: inline-block; + padding: 1px 3px 0 0; + margin: 0; + cursor: pointer; + height: 17px; + text-decoration: none; + vertical-align: top; + } + span { + &.@{treePrefixCls}-switcher, + &.@{treePrefixCls}-checkbox, + &.@{treePrefixCls}-iconEle { + line-height: 16px; + margin-right: 2px; + width: 16px; + height: 16px; + display: inline-block; + vertical-align: middle; + border: 0 none; + cursor: pointer; + outline: none; + background-color: transparent; + background-repeat: no-repeat; + background-attachment: scroll; + background-image: url('data:image/png;base64,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'); + + &.@{treePrefixCls}-icon__customize { + background-image: none; + } + } + &.@{treePrefixCls}-icon_loading { + margin-right: 2px; + vertical-align: top; + background: url('data:image/gif;base64,R0lGODlhEAAQAKIGAMLY8YSx5HOm4Mjc88/g9Ofw+v///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgAGACwAAAAAEAAQAAADMGi6RbUwGjKIXCAA016PgRBElAVlG/RdLOO0X9nK61W39qvqiwz5Ls/rRqrggsdkAgAh+QQFCgAGACwCAAAABwAFAAADD2hqELAmiFBIYY4MAutdCQAh+QQFCgAGACwGAAAABwAFAAADD1hU1kaDOKMYCGAGEeYFCQAh+QQFCgAGACwKAAIABQAHAAADEFhUZjSkKdZqBQG0IELDQAIAIfkEBQoABgAsCgAGAAUABwAAAxBoVlRKgyjmlAIBqCDCzUoCACH5BAUKAAYALAYACgAHAAUAAAMPaGpFtYYMAgJgLogA610JACH5BAUKAAYALAIACgAHAAUAAAMPCAHWFiI4o1ghZZJB5i0JACH5BAUKAAYALAAABgAFAAcAAAMQCAFmIaEp1motpDQySMNFAgA7') no-repeat scroll 0 0 transparent; + } + &.@{treePrefixCls}-switcher { + &.@{treePrefixCls}-switcher-noop { + cursor: auto; + } + &.@{treePrefixCls}-switcher_open { + background-position: -93px -56px; + } + &.@{treePrefixCls}-switcher_close { + background-position: -75px -56px; + } + } + &.@{treePrefixCls}-checkbox { + width: 13px; + height: 13px; + margin: 0 3px; + background-position: 0 0; + &-checked { + background-position: -14px 0; + } + &-indeterminate { + background-position: -14px -28px; + } + &-disabled { + background-position: 0 -56px; + } + &.@{treePrefixCls}-checkbox-checked.@{treePrefixCls}-checkbox-disabled { + background-position: -14px -56px; + } + &.@{treePrefixCls}-checkbox-indeterminate.@{treePrefixCls}-checkbox-disabled { + position: relative; + background: #ccc; + border-radius: 3px; + &::after { + content: ' '; + -webkit-transform: scale(1); + transform: scale(1); + position: absolute; + left: 3px; + top: 5px; + width: 5px; + height: 0; + border: 2px solid #fff; + border-top: 0; + border-left: 0; + } + } + } + } + } + &:not(.@{treePrefixCls}-show-line) { + .@{treePrefixCls}-switcher-noop { + background: none; + } + } + &.@{treePrefixCls}-show-line { + li:not(:last-child) { + > ul { + background: url('data:image/gif;base64,R0lGODlhCQACAIAAAMzMzP///yH5BAEAAAEALAAAAAAJAAIAAAIEjI9pUAA7') 0 0 repeat-y; + } + > .@{treePrefixCls}-switcher-noop { + background-position: -56px -18px; + } + } + li:last-child { + > .@{treePrefixCls}-switcher-noop { + background-position: -56px -36px; + } + } + } + &-child-tree { + display: none; + &-open { + display: block; + } + } + &-treenode-disabled { + >span:not(.@{treePrefixCls}-switcher), + >a, + >a span { + color: #ccc; + cursor: not-allowed; + } + } + &-node-selected { + background-color: #ffe6b0; + border: 1px #ffb951 solid; + opacity: 0.8; + } + &-icon__open { + margin-right: 2px; + background-position: -110px -16px; + vertical-align: top; + } + &-icon__close { + margin-right: 2px; + background-position: -110px 0; + vertical-align: top; + } + &-icon__docu { + margin-right: 2px; + background-position: -110px -32px; + vertical-align: top; + } + &-icon__customize { + margin-right: 2px; + vertical-align: top; + } +} diff --git a/components/vc-tree/assets/line.gif b/components/vc-tree/assets/line.gif new file mode 100644 index 0000000000000000000000000000000000000000..d561d36a915776730eb3069cee4c949f027667ed GIT binary patch literal 45 xcmZ?wbhEHbT_)p@)n z{^qIIq1(T$e$~zMQ}6t1w^a|Cj;Amo3}FHq!p^`7G=x7ROJIXqM}S9S9}m;(SWbi* zHiVjpkZW$u7K%QH zEX1o> { + const { expandedKeys } = this.state + const { onDragEnter } = this.props + const { pos, eventKey } = node.props + + const dropPosition = calcDropPosition(event, node) + + // Skip if drag node is self + if ( + this.dragNode.props.eventKey === eventKey && + dropPosition === 0 + ) { + this.setState({ + dragOverNodeKey: '', + dropPosition: null, + }) + return + } + + // Ref: https://github.com/react-component/tree/issues/132 + // Add timeout to let onDragLevel fire before onDragEnter, + // so that we can clean drag props for onDragLeave node. + // Macro task for this: + // https://html.spec.whatwg.org/multipage/webappapis.html#clean-up-after-running-script + setTimeout(() => { + // Update drag over node + this.setState({ + dragOverNodeKey: eventKey, + dropPosition, + }) + + // Side effect for delay drag + if (!this.delayedDragEnterLogic) { + this.delayedDragEnterLogic = {} + } + Object.keys(this.delayedDragEnterLogic).forEach((key) => { + clearTimeout(this.delayedDragEnterLogic[key]) + }) + this.delayedDragEnterLogic[pos] = setTimeout(() => { + const newExpandedKeys = arrAdd(expandedKeys, eventKey) + this.setState({ + expandedKeys: newExpandedKeys, + }) + + if (onDragEnter) { + onDragEnter({ event, node, expandedKeys: newExpandedKeys }) + } + }, 400) + }, 0) + }; + onNodeDragOver = (event, node) => { + const { onDragOver } = this.props + if (onDragOver) { + onDragOver({ event, node }) + } + }; + onNodeDragLeave = (event, node) => { + const { onDragLeave } = this.props + + this.setState({ + dragOverNodeKey: '', + }) + + if (onDragLeave) { + onDragLeave({ event, node }) + } + }; + onNodeDragEnd = (event, node) => { + const { onDragEnd } = this.props + this.setState({ + dragOverNodeKey: '', + }) + if (onDragEnd) { + onDragEnd({ event, node }) + } + }; + onNodeDrop = (event, node) => { + const { dragNodesKeys, dropPosition } = this.state + const { onDrop } = this.props + const { eventKey, pos } = node.props + + this.setState({ + dragOverNodeKey: '', + dropNodeKey: eventKey, + }) + + if (dragNodesKeys.indexOf(eventKey) !== -1) { + warning(false, 'Can not drop to dragNode(include it\'s children node)') + return + } + + const posArr = posToArr(pos) + + const dropResult = { + event, + node, + dragNode: this.dragNode, + dragNodesKeys: dragNodesKeys.slice(), + dropPosition: dropPosition + Number(posArr[posArr.length - 1]), + } + + if (dropPosition !== 0) { + dropResult.dropToGap = true + } + + if (onDrop) { + onDrop(dropResult) + } + }; + + onNodeSelect = (e, treeNode) => { + let { selectedKeys } = this.state + const { onSelect, multiple, children } = this.props + const { selected, eventKey } = treeNode.props + const targetSelected = !selected + + // Update selected keys + if (!targetSelected) { + selectedKeys = arrDel(selectedKeys, eventKey) + } else if (!multiple) { + selectedKeys = [eventKey] + } else { + selectedKeys = arrAdd(selectedKeys, eventKey) + } + + // [Legacy] Not found related usage in doc or upper libs + // [Legacy] TODO: add optimize prop to skip node process + const selectedNodes = [] + if (selectedKeys.length) { + traverseTreeNodes(children, ({ node, key }) => { + if (selectedKeys.indexOf(key) !== -1) { + selectedNodes.push(node) + } + }) + } + + this.setUncontrolledState({ selectedKeys }) + + if (onSelect) { + const eventObj = { + event: 'select', + selected: targetSelected, + node: treeNode, + selectedNodes, + } + onSelect(selectedKeys, eventObj) + } + }; + + /** + * This will cache node check status to optimize update process. + * When Tree get trigger `onCheckConductFinished` will flush all the update. + */ + onBatchNodeCheck = (key, checked, halfChecked, startNode) => { + if (startNode) { + this.checkedBatch = { + treeNode: startNode, + checked, + list: [], + } + } + + // This code should never called + if (!this.checkedBatch) { + this.checkedBatch = { + list: [], + } + warning( + false, + 'Checked batch not init. This should be a bug. Please fire a issue.' + ) + } + + this.checkedBatch.list.push({ key, checked, halfChecked }) + }; + + /** + * When top `onCheckConductFinished` called, will execute all batch update. + * And trigger `onCheck` event. + */ + onCheckConductFinished = () => { + const { checkedKeys, halfCheckedKeys } = this.state + const { onCheck, checkStrictly, children } = this.props + + // Use map to optimize update speed + const checkedKeySet = {} + const halfCheckedKeySet = {} + + checkedKeys.forEach(key => { + checkedKeySet[key] = true + }) + halfCheckedKeys.forEach(key => { + halfCheckedKeySet[key] = true + }) + + // Batch process + this.checkedBatch.list.forEach(({ key, checked, halfChecked }) => { + checkedKeySet[key] = checked + halfCheckedKeySet[key] = halfChecked + }) + const newCheckedKeys = Object.keys(checkedKeySet).filter(key => checkedKeySet[key]) + const newHalfCheckedKeys = Object.keys(halfCheckedKeySet).filter(key => halfCheckedKeySet[key]) + + // Trigger onChecked + let selectedObj + + const eventObj = { + event: 'check', + node: this.checkedBatch.treeNode, + checked: this.checkedBatch.checked, + } + + if (checkStrictly) { + selectedObj = getStrictlyValue(newCheckedKeys, newHalfCheckedKeys) + + // [Legacy] TODO: add optimize prop to skip node process + eventObj.checkedNodes = [] + traverseTreeNodes(children, ({ node, key }) => { + if (checkedKeySet[key]) { + eventObj.checkedNodes.push(node) + } + }) + + this.setUncontrolledState({ checkedKeys: newCheckedKeys }) + } else { + selectedObj = newCheckedKeys + + // [Legacy] TODO: add optimize prop to skip node process + eventObj.checkedNodes = [] + eventObj.checkedNodesPositions = [] // [Legacy] TODO: not in API + eventObj.halfCheckedKeys = newHalfCheckedKeys // [Legacy] TODO: not in API + traverseTreeNodes(children, ({ node, pos, key }) => { + if (checkedKeySet[key]) { + eventObj.checkedNodes.push(node) + eventObj.checkedNodesPositions.push({ node, pos }) + } + }) + + this.setUncontrolledState({ + checkedKeys: newCheckedKeys, + halfCheckedKeys: newHalfCheckedKeys, + }) + } + + if (onCheck) { + onCheck(selectedObj, eventObj) + } + + // Clean up + this.checkedBatch = null + }; + + onNodeExpand = (e, treeNode) => { + let { expandedKeys } = this.state + const { onExpand, loadData } = this.props + const { eventKey, expanded } = treeNode.props + + // Update selected keys + const index = expandedKeys.indexOf(eventKey) + const targetExpanded = !expanded + + warning( + (expanded && index !== -1) || (!expanded && index === -1) + , 'Expand state not sync with index check') + + if (targetExpanded) { + expandedKeys = arrAdd(expandedKeys, eventKey) + } else { + expandedKeys = arrDel(expandedKeys, eventKey) + } + + this.setUncontrolledState({ expandedKeys }) + + if (onExpand) { + onExpand(expandedKeys, { node: treeNode, expanded: targetExpanded }) + } + + // Async Load data + if (targetExpanded && loadData) { + return loadData(treeNode).then(() => { + // [Legacy] Refresh logic + this.setUncontrolledState({ expandedKeys }) + }) + } + + return null + }; + + onNodeMouseEnter = (event, node) => { + const { onMouseEnter } = this.props + if (onMouseEnter) { + onMouseEnter({ event, node }) + } + }; + + onNodeMouseLeave = (event, node) => { + const { onMouseLeave } = this.props + if (onMouseLeave) { + onMouseLeave({ event, node }) + } + }; + + onNodeContextMenu = (event, node) => { + const { onRightClick } = this.props + if (onRightClick) { + event.preventDefault() + onRightClick({ event, node }) + } + }; + + /** + * Sync state with props if needed + */ + getSyncProps = (props = {}, prevProps) => { + let needSync = false + const newState = {} + const myPrevProps = prevProps || {} + + function checkSync (name) { + if (props[name] !== myPrevProps[name]) { + needSync = true + return true + } + return false + } + + // Children change will affect check box status. + // And no need to check when prev props not provided + if (prevProps && checkSync('children')) { + const { checkedKeys = [], halfCheckedKeys = [] } = + calcCheckedKeys(props.checkedKeys || this.state.checkedKeys, props) || {} + newState.checkedKeys = checkedKeys + newState.halfCheckedKeys = halfCheckedKeys + } + + if (checkSync('expandedKeys')) { + newState.expandedKeys = calcExpandedKeys(props.expandedKeys, props) + } + + if (checkSync('selectedKeys')) { + newState.selectedKeys = calcSelectedKeys(props.selectedKeys, props) + } + + if (checkSync('checkedKeys')) { + const { checkedKeys = [], halfCheckedKeys = [] } = + calcCheckedKeys(props.checkedKeys, props) || {} + newState.checkedKeys = checkedKeys + newState.halfCheckedKeys = halfCheckedKeys + } + + return needSync ? newState : null + }; + + /** + * Only update the value which is not in props + */ + setUncontrolledState = (state) => { + let needSync = false + const newState = {} + + Object.keys(state).forEach(name => { + if (name in this.props) return + + needSync = true + newState[name] = state[name] + }) + + this.setState(needSync ? newState : null) + }; + + isKeyChecked = (key) => { + const { checkedKeys = [] } = this.state + return checkedKeys.indexOf(key) !== -1 + }; + + /** + * [Legacy] Original logic use `key` as tracking clue. + * We have to use `cloneElement` to pass `key`. + */ + renderTreeNode = (child, index, level = 0) => { + const { + expandedKeys = [], selectedKeys = [], halfCheckedKeys = [], + dragOverNodeKey, dropPosition, + } = this.state + const {} = this.props + const pos = getPosition(level, index) + const key = child.key || pos + + return React.cloneElement(child, { + eventKey: key, + expanded: expandedKeys.indexOf(key) !== -1, + selected: selectedKeys.indexOf(key) !== -1, + checked: this.isKeyChecked(key), + halfChecked: halfCheckedKeys.indexOf(key) !== -1, + pos, + + // [Legacy] Drag props + dragOver: dragOverNodeKey === key && dropPosition === 0, + dragOverGapTop: dragOverNodeKey === key && dropPosition === -1, + dragOverGapBottom: dragOverNodeKey === key && dropPosition === 1, + }) + }; + + render () { + const { + prefixCls, className, focusable, + showLine, + children, + } = this.props + const domProps = {} + + // [Legacy] Commit: 0117f0c9db0e2956e92cb208f51a42387dfcb3d1 + if (focusable) { + domProps.tabIndex = '0' + domProps.onKeyDown = this.onKeyDown + } + + return ( +
    + {React.Children.map(children, this.renderTreeNode, this)} +
+ ) + } +} + +export default Tree diff --git a/components/vc-tree/src/TreeNode.jsx b/components/vc-tree/src/TreeNode.jsx new file mode 100644 index 000000000..155585404 --- /dev/null +++ b/components/vc-tree/src/TreeNode.jsx @@ -0,0 +1,585 @@ +import PropTypes from '../../_util/vue-types' +import classNames from 'classnames' +import warning from 'warning' +import { contextTypes } from './Tree' +import { getPosition, getNodeChildren, isCheckDisabled, traverseTreeNodes } from './util' +import { initDefaultProps, getOptionProps, filterEmpty } from '../../_util/props-util' + +const ICON_OPEN = 'open' +const ICON_CLOSE = 'close' + +const LOAD_STATUS_NONE = 0 +const LOAD_STATUS_LOADING = 1 +const LOAD_STATUS_LOADED = 2 +const LOAD_STATUS_FAILED = 0 // Action align, let's make failed same as init. + +const defaultTitle = '---' + +let onlyTreeNodeWarned = false // Only accept TreeNode + +export const nodeContextTypes = { + ...contextTypes, + rcTreeNode: PropTypes.shape({ + onUpCheckConduct: PropTypes.func, + }), +} + +const TreeNode = { + props: initDefaultProps({ + eventKey: PropTypes.string, // Pass by parent `cloneElement` + prefixCls: PropTypes.string, + // className: PropTypes.string, + root: PropTypes.object, + // onSelect: PropTypes.func, + + // By parent + expanded: PropTypes.bool, + selected: PropTypes.bool, + checked: PropTypes.bool, + halfChecked: PropTypes.bool, + title: PropTypes.node, + pos: PropTypes.string, + dragOver: PropTypes.bool, + dragOverGapTop: PropTypes.bool, + dragOverGapBottom: PropTypes.bool, + + // By user + isLeaf: PropTypes.bool, + selectable: PropTypes.bool, + disabled: PropTypes.bool, + disableCheckbox: PropTypes.bool, + icon: PropTypes.any, + }, { + title: defaultTitle, + }), + + data () { + return { + loadStatus: LOAD_STATUS_NONE, + dragNodeHighlight: false, + } + }, + inject: { + context: { default: {}}, + }, + provide: { + ...this.context, + rcTreeNode: this, + }, + + // Isomorphic needn't load data in server side + mounted () { + this.$nextTick(() => { + this.syncLoadData(this.$props) + }) + }, + + componentWillReceiveProps (nextProps) { + this.syncLoadData(nextProps) + }, + + onUpCheckConduct (treeNode, nodeChecked, nodeHalfChecked) { + const { pos: nodePos } = getOptionProps(treeNode) + const { eventKey, pos, checked, halfChecked } = this + const { + rcTree: { checkStrictly, isKeyChecked, onBatchNodeCheck, onCheckConductFinished }, + rcTreeNode: { onUpCheckConduct } = {}, + } = this.context + + // Stop conduct when current node is disabled + if (isCheckDisabled(this)) { + onCheckConductFinished() + return + } + + const children = this.getNodeChildren() + + let checkedCount = nodeChecked ? 1 : 0 + + // Statistic checked count + children.forEach((node, index) => { + const childPos = getPosition(pos, index) + + if (nodePos === childPos || isCheckDisabled(node)) { + return + } + + if (isKeyChecked(node.key || childPos)) { + checkedCount += 1 + } + }) + + // Static enabled children count + const enabledChildrenCount = children + .filter(node => !isCheckDisabled(node)) + .length + + // checkStrictly will not conduct check status + const nextChecked = checkStrictly ? checked : enabledChildrenCount === checkedCount + const 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(this, nextChecked, nextHalfChecked) + } else { + // Flush all the update + onCheckConductFinished() + } + } else { + // Flush all the update + onCheckConductFinished() + } + }, + + onDownCheckConduct (nodeChecked) { + const { $slots } = this + const children = $slots.default || [] + const { rcTree: { checkStrictly, isKeyChecked, onBatchNodeCheck }} = this.context + if (checkStrictly) return + + traverseTreeNodes(children, ({ node, key }) => { + if (isCheckDisabled(node)) return false + + if (nodeChecked !== isKeyChecked(key)) { + onBatchNodeCheck(key, nodeChecked, false) + } + }) + }, + + onSelectorClick (e) { + if (this.isSelectable()) { + this.onSelect(e) + } else { + this.onCheck(e) + } + }, + + onSelect (e) { + if (this.isDisabled()) return + + const { rcTree: { onNodeSelect }} = this.context + e.preventDefault() + onNodeSelect(e, this) + }, + + onCheck (e) { + if (this.isDisabled()) return + + const { disableCheckbox, checked, eventKey } = this + const { + rcTree: { checkable, onBatchNodeCheck, onCheckConductFinished }, + rcTreeNode: { onUpCheckConduct } = {}, + } = this.context + + if (!checkable || disableCheckbox) return + + e.preventDefault() + const targetChecked = !checked + onBatchNodeCheck(eventKey, targetChecked, false, this) + + // Children conduct + this.onDownCheckConduct(targetChecked) + + // Parent conduct + if (onUpCheckConduct) { + onUpCheckConduct(this, targetChecked, false) + } else { + onCheckConductFinished() + } + }, + + onMouseEnter (e) { + const { rcTree: { onNodeMouseEnter }} = this.context + onNodeMouseEnter(e, this) + }, + + onMouseLeave (e) { + const { rcTree: { onNodeMouseLeave }} = this.context + onNodeMouseLeave(e, this) + }, + + onContextMenu (e) { + const { rcTree: { onNodeContextMenu }} = this.context + onNodeContextMenu(e, this) + }, + + onDragStart (e) { + const { rcTree: { onNodeDragStart }} = this.context + + e.stopPropagation() + this.setState({ + dragNodeHighlight: true, + }) + onNodeDragStart(e, this) + + try { + // ie throw error + // firefox-need-it + e.dataTransfer.setData('text/plain', '') + } catch (error) { + // empty + } + }, + + onDragEnter (e) { + const { rcTree: { onNodeDragEnter }} = this.context + + e.preventDefault() + e.stopPropagation() + onNodeDragEnter(e, this) + }, + + onDragOver (e) { + const { rcTree: { onNodeDragOver }} = this.context + + e.preventDefault() + e.stopPropagation() + onNodeDragOver(e, this) + }, + + onDragLeave (e) { + const { rcTree: { onNodeDragLeave }} = this.context + + e.stopPropagation() + onNodeDragLeave(e, this) + }, + + onDragEnd (e) { + const { rcTree: { onNodeDragEnd }} = this.context + + e.stopPropagation() + this.setState({ + dragNodeHighlight: false, + }) + onNodeDragEnd(e, this) + }, + + onDrop (e) { + const { rcTree: { onNodeDrop }} = this.context + + e.preventDefault() + e.stopPropagation() + this.setState({ + dragNodeHighlight: false, + }) + onNodeDrop(e, this) + }, + + // Disabled item still can be switch + onExpand (e) { + const { rcTree: { onNodeExpand }} = this.context + const callbackPromise = onNodeExpand(e, this) + + // Promise like + if (callbackPromise && callbackPromise.then) { + this.setState({ loadStatus: LOAD_STATUS_LOADING }) + + callbackPromise.then(() => { + this.setState({ loadStatus: LOAD_STATUS_LOADED }) + }).catch(() => { + this.setState({ loadStatus: LOAD_STATUS_FAILED }) + }) + } + }, + + // Drag usage + setSelectHandle (node) { + this.selectHandle = node + }, + + getNodeChildren () { + const { $slots: { default: children }} = this + const originList = filterEmpty(children) + const targetList = getNodeChildren(originList) + + if (originList.length !== targetList.length && !onlyTreeNodeWarned) { + onlyTreeNodeWarned = true + warning(false, 'Tree only accept TreeNode as children.') + } + + return targetList + }, + + getNodeState () { + const { expanded } = this + + if (this.isLeaf()) { + return null + } + + return expanded ? ICON_OPEN : ICON_CLOSE + }, + + isLeaf () { + const { isLeaf, loadStatus } = this + const { rcTree: { loadData }} = this.context + + const hasChildren = this.getNodeChildren().length !== 0 + + return ( + isLeaf || + (!loadData && !hasChildren) || + (loadData && loadStatus === LOAD_STATUS_LOADED && !hasChildren) + ) + }, + + isDisabled () { + const { disabled } = this + const { rcTree: { disabled: treeDisabled }} = this.context + + // Follow the logic of Selectable + if (disabled === false) { + return false + } + + return !!(treeDisabled || disabled) + }, + + isSelectable () { + const { selectable } = this + const { rcTree: { selectable: treeSelectable }} = this.context + + // Ignore when selectable is undefined or null + if (typeof selectable === 'boolean') { + return selectable + } + + return treeSelectable + }, + + // Load data to avoid default expanded tree without data + syncLoadData (props) { + const { loadStatus } = this + const { expanded } = props + const { rcTree: { loadData }} = this.context + + if (loadData && loadStatus === LOAD_STATUS_NONE && expanded && !this.isLeaf()) { + this.setState({ loadStatus: LOAD_STATUS_LOADING }) + + loadData(this).then(() => { + this.setState({ loadStatus: LOAD_STATUS_LOADED }) + }).catch(() => { + this.setState({ loadStatus: LOAD_STATUS_FAILED }) + }) + } + }, + + // Switcher + renderSwitcher () { + const { expanded } = this + const { rcTree: { prefixCls }} = this.context + + if (this.isLeaf()) { + return + } + + return ( + + ) + }, + + // Checkbox + renderCheckbox () { + const { checked, halfChecked, disableCheckbox } = this + const { rcTree: { prefixCls, checkable }} = this.context + const disabled = this.isDisabled() + + if (!checkable) return null + + // [Legacy] Custom element should be separate with `checkable` in future + const $custom = typeof checkable !== 'boolean' ? checkable : null + + return ( + + {$custom} + + ) + }, + + renderIcon () { + const { loadStatus } = this + const { rcTree: { prefixCls }} = this.context + + return ( + + ) + }, + + // Icon + Title + renderSelector () { + const { title, selected, icon, loadStatus, dragNodeHighlight } = this + const { rcTree: { prefixCls, showIcon, draggable, loadData }} = this.context + const disabled = this.isDisabled() + + const wrapClass = `${prefixCls}-node-content-wrapper` + + // Icon - Still show loading icon when loading without showIcon + let $icon + + if (showIcon) { + $icon = icon ? ( + + {typeof icon === 'function' + ? icon(this.$props) : icon} + + ) : this.renderIcon() + } else if (loadData && loadStatus === LOAD_STATUS_LOADING) { + $icon = this.renderIcon() + } + + // Title + const $title = {title} + + return ( + + {$icon}{$title} + + ) + }, + + // Children list wrapped with `Animation` + renderChildren () { + const { expanded, pos } = this + const { rcTree: { + prefixCls, + openTransitionName, openAnimation, + renderTreeNode, + }} = this.context + + // [Legacy] Animation control + const renderFirst = this.renderFirst + this.renderFirst = 1 + let transitionAppear = true + if (!renderFirst && expanded) { + transitionAppear = false + } + + const animProps = {} + if (openTransitionName) { + animProps.transitionName = openTransitionName + } else if (typeof openAnimation === 'object') { + animProps.animation = { ...openAnimation } + if (!transitionAppear) { + delete animProps.animation.appear + } + } + + // Children TreeNode + const nodeList = this.getNodeChildren() + + if (nodeList.length === 0) { + return null + } + + let $children + if (expanded) { + $children = ( +
    + {nodeList.map((node, index) => ( + renderTreeNode(node, index, pos) + ))} +
+ ) + } + + return ( + + {$children} + + ) + }, + + render () { + const { + dragOver, dragOverGapTop, dragOverGapBottom, + } = this + const { rcTree: { + prefixCls, + filterTreeNode, + }} = this.context + const disabled = this.isDisabled() + + return ( +
  • + {this.renderSwitcher()} + {this.renderCheckbox()} + {this.renderSelector()} + {this.renderChildren()} +
  • + ) + }, +} + +TreeNode.isTreeNode = 1 + +export default TreeNode diff --git a/components/vc-tree/src/index.js b/components/vc-tree/src/index.js new file mode 100644 index 000000000..d053f4c9f --- /dev/null +++ b/components/vc-tree/src/index.js @@ -0,0 +1,6 @@ +import Tree from './Tree' +import TreeNode from './TreeNode' +Tree.TreeNode = TreeNode + +export { TreeNode } +export default Tree diff --git a/components/vc-tree/src/util.js b/components/vc-tree/src/util.js new file mode 100644 index 000000000..41e39ed08 --- /dev/null +++ b/components/vc-tree/src/util.js @@ -0,0 +1,399 @@ +/* eslint no-loop-func: 0*/ +import { Children } from 'react' +import warning from 'warning' + +export function arrDel (list, value) { + const clone = list.slice() + const index = clone.indexOf(value) + if (index >= 0) { + clone.splice(index, 1) + } + return clone +} + +export function arrAdd (list, value) { + const clone = list.slice() + if (clone.indexOf(value) === -1) { + clone.push(value) + } + return clone +} + +export function posToArr (pos) { + return pos.split('-') +} + +// Only used when drag, not affect SSR. +export function getOffset (ele) { + if (!ele.getClientRects().length) { + return { top: 0, left: 0 } + } + + const rect = ele.getBoundingClientRect() + if (rect.width || rect.height) { + const doc = ele.ownerDocument + const win = doc.defaultView + const docElem = doc.documentElement + + return { + top: rect.top + win.pageYOffset - docElem.clientTop, + left: rect.left + win.pageXOffset - docElem.clientLeft, + } + } + + return rect +} + +export function getPosition (level, index) { + return `${level}-${index}` +} + +export function getNodeChildren (children) { + const childList = Array.isArray(children) ? children : [children] + return childList + .filter(child => child && child.type && child.type.isTreeNode) +} + +export function isCheckDisabled (node) { + const { disabled, disableCheckbox } = node.props || {} + return !!(disabled || disableCheckbox) +} + +export function traverseTreeNodes (treeNodes, subTreeData, callback) { + if (typeof subTreeData === 'function') { + callback = subTreeData + subTreeData = false + } + + function processNode (node, index, parent) { + const children = node ? node.props.children : treeNodes + const pos = node ? getPosition(parent.pos, index) : 0 + + // Filter children + const childList = getNodeChildren(children) + + // Process node if is not root + if (node) { + const data = { + node, + index, + pos, + key: node.key || pos, + parentPos: parent.node ? parent.pos : null, + } + + // Children data is not must have + if (subTreeData) { + // Statistic children + const subNodes = [] + Children.forEach(childList, (subNode, subIndex) => { + // Provide limit snapshot + const subPos = getPosition(pos, index) + subNodes.push({ + node: subNode, + key: subNode.key || subPos, + pos: subPos, + index: subIndex, + }) + }) + data.subNodes = subNodes + } + + // Can break traverse by return false + if (callback(data) === false) { + return + } + } + + // Process children node + Children.forEach(childList, (subNode, subIndex) => { + processNode(subNode, subIndex, { node, pos }) + }) + } + + processNode(null) +} + +/** + * [Legacy] Return halfChecked when it has value. + * @param checkedKeys + * @param halfChecked + * @returns {*} + */ +export function getStrictlyValue (checkedKeys, halfChecked) { + if (halfChecked) { + return { checked: checkedKeys, halfChecked } + } + return checkedKeys +} + +export function getFullKeyList (treeNodes) { + const keyList = [] + traverseTreeNodes(treeNodes, ({ key }) => { + keyList.push(key) + }) + return keyList +} + +/** + * Check position relation. + * @param parentPos + * @param childPos + * @param directly only directly parent can be true + * @returns {boolean} + */ +export function isParent (parentPos, childPos, directly = false) { + if (!parentPos || !childPos || parentPos.length > childPos.length) return false + + const parentPath = posToArr(parentPos) + const childPath = posToArr(childPos) + + // Directly check + if (directly && parentPath.length !== childPath.length - 1) return false + + const len = parentPath.length + for (let i = 0; i < len; i += 1) { + if (parentPath[i] !== childPath[i]) return false + } + + return true +} + +/** + * Statistic TreeNodes info + * @param treeNodes + * @returns {{}} + */ +export function getNodesStatistic (treeNodes) { + const statistic = { + keyNodes: {}, + posNodes: {}, + nodeList: [], + } + + traverseTreeNodes(treeNodes, true, ({ node, index, pos, key, subNodes, parentPos }) => { + const data = { node, index, pos, key, subNodes, parentPos } + statistic.keyNodes[key] = data + statistic.posNodes[pos] = data + statistic.nodeList.push(data) + }) + + return statistic +} + +export function getDragNodesKeys (treeNodes, node) { + const { eventKey, pos } = node.props + const dragNodesKeys = [] + + traverseTreeNodes(treeNodes, ({ pos: nodePos, key }) => { + if (isParent(pos, nodePos)) { + dragNodesKeys.push(key) + } + }) + dragNodesKeys.push(eventKey || pos) + return dragNodesKeys +} + +export function calcDropPosition (event, treeNode) { + const offsetTop = getOffset(treeNode.selectHandle).top + const offsetHeight = treeNode.selectHandle.offsetHeight + const pageY = event.pageY + const gapHeight = 2 // [Legacy] TODO: remove hard code + if (pageY > offsetTop + offsetHeight - gapHeight) { + return 1 + } + if (pageY < offsetTop + gapHeight) { + return -1 + } + return 0 +} + +/** + * Auto expand all related node when sub node is expanded + * @param keyList + * @param props + * @returns [string] + */ +export function calcExpandedKeys (keyList, props) { + if (!keyList) { + return [] + } + + const { autoExpandParent, children } = props + + // Do nothing if not auto expand parent + if (!autoExpandParent) { + return keyList + } + + // Fill parent expanded keys + const { keyNodes, nodeList } = getNodesStatistic(children) + const needExpandKeys = {} + const needExpandPathList = [] + + // Fill expanded nodes + keyList.forEach((key) => { + const node = keyNodes[key] + if (node) { + needExpandKeys[key] = true + needExpandPathList.push(node.pos) + } + }) + + // Match parent by path + nodeList.forEach(({ pos, key }) => { + if (needExpandPathList.some(childPos => isParent(pos, childPos))) { + needExpandKeys[key] = true + } + }) + + const calcExpandedKeyList = Object.keys(needExpandKeys) + + // [Legacy] Return origin keyList if calc list is empty + return calcExpandedKeyList.length ? calcExpandedKeyList : keyList +} + +/** + * Return selectedKeys according with multiple prop + * @param selectedKeys + * @param props + * @returns [string] + */ +export function calcSelectedKeys (selectedKeys, props) { + if (!selectedKeys) { + return undefined + } + + const { multiple } = props + if (multiple) { + return selectedKeys.slice() + } + + if (selectedKeys.length) { + return [selectedKeys[0]] + } + return selectedKeys +} + +/** + * Check conduct is by key level. It pass though up & down. + * When conduct target node is check means already conducted will be skip. + * @param treeNodes + * @param checkedKeys + * @returns {{checkedKeys: Array, halfCheckedKeys: Array}} + */ +export function calcCheckStateConduct (treeNodes, checkedKeys) { + const { keyNodes, posNodes } = getNodesStatistic(treeNodes) + + const tgtCheckedKeys = {} + const tgtHalfCheckedKeys = {} + + // Conduct up + function conductUp (key, halfChecked) { + if (tgtCheckedKeys[key]) return + + const { subNodes = [], parentPos, node } = keyNodes[key] + if (isCheckDisabled(node)) return + + const allSubChecked = !halfChecked && subNodes + .filter(sub => !isCheckDisabled(sub.node)) + .every(sub => tgtCheckedKeys[sub.key]) + + if (allSubChecked) { + tgtCheckedKeys[key] = true + } else { + tgtHalfCheckedKeys[key] = true + } + + if (parentPos !== null) { + conductUp(posNodes[parentPos].key, !allSubChecked) + } + } + + // Conduct down + function conductDown (key) { + if (tgtCheckedKeys[key]) return + const { subNodes = [], node } = keyNodes[key] + + if (isCheckDisabled(node)) return + + tgtCheckedKeys[key] = true + + subNodes.forEach((sub) => { + conductDown(sub.key) + }) + } + + function conduct (key) { + if (!keyNodes[key]) { + warning(false, `'${key}' does not exist in the tree.`) + return + } + + const { subNodes = [], parentPos, node } = keyNodes[key] + if (isCheckDisabled(node)) return + + tgtCheckedKeys[key] = true + + // Conduct down + subNodes + .filter(sub => !isCheckDisabled(sub.node)) + .forEach((sub) => { + conductDown(sub.key) + }) + + // Conduct up + if (parentPos !== null) { + conductUp(posNodes[parentPos].key) + } + } + + checkedKeys.forEach((key) => { + conduct(key) + }) + + return { + checkedKeys: Object.keys(tgtCheckedKeys), + halfCheckedKeys: Object.keys(tgtHalfCheckedKeys) + .filter(key => !tgtCheckedKeys[key]), + } +} + +/** + * Calculate the value of checked and halfChecked keys. + * This should be only run in init or props changed. + */ +export function calcCheckedKeys (keys, props) { + const { checkable, children, checkStrictly } = props + + if (!checkable || !keys) { + return null + } + + // Convert keys to object format + let keyProps + if (Array.isArray(keys)) { + // [Legacy] Follow the api doc + keyProps = { + checkedKeys: keys, + halfCheckedKeys: undefined, + } + } else if (typeof keys === 'object') { + keyProps = { + checkedKeys: keys.checked || undefined, + halfCheckedKeys: keys.halfChecked || undefined, + } + } else { + warning(false, '`CheckedKeys` is not an array or an object') + return null + } + + // Do nothing if is checkStrictly mode + if (checkStrictly) { + return keyProps + } + + // Conduct calculate the check status + const { checkedKeys = [] } = keyProps + return calcCheckStateConduct(children, checkedKeys) +}