diff --git a/README.md b/README.md index e5d23a3d..7670a2b7 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,9 @@ export default class Tree extends Component { | rowHeight | number or func | Used by react-sortable-tree. Defaults to `62`. Either a fixed row height (number) or a function that returns the height of a row given its index: `({ treeIndex: number, node: object, path: number[] or string[] }): number` | | slideRegionSize | number | Size in px of the region near the edges that initiates scrolling on dragover. Defaults to `100`. | | scaffoldBlockPxWidth | number | The width of the blocks containing the lines representing the structure of the tree. Defaults to `44`. | -| isVirtualized | bool | Set to false to disable virtualization. Defaults to `true`. **NOTE**: Auto-scrolling while dragging, and scrolling to the `searchFocusOffset` will be disabled. | +| isVirtualized | bool | Set to false to disable virtualization. Defaults to `true`. **NOTE**: Auto-scrolling while dragging, and scrolling to the `searchFocusOffset` will be disabled. +| isNodeDepthFixed | bool | Set to true to restrict drag and drop operation of every node to its original depth without allowing auto expand on drag for any node. Defaults to `false`. +| isParentNodeFixed | bool | Set to true to restrict drag and drop operation of every node to its parent without allowing auto expand on drag for any node. Defaults to `false`. `false`. | | nodeContentRenderer | any | Override the default component ([`NodeRendererDefault`](https://github.com/frontend-collective/react-sortable-tree/blob/master/src/node-renderer-default.js)) for rendering nodes (but keep the scaffolding generator). This is a last resort for customization - most custom styling should be able to be solved with `generateNodeProps`, a `theme` or CSS rules. If you must use it, is best to copy the component in `node-renderer-default.js` to use as a base, and customize as needed. | | placeholderRenderer | any | Override the default placeholder component ([`PlaceholderRendererDefault`](https://github.com/frontend-collective/react-sortable-tree/blob/master/src/placeholder-renderer-default.js)) which is displayed when the tree is empty. This is an advanced option, and in most cases should probably be solved with a `theme` or custom CSS instead. | diff --git a/src/react-sortable-tree.js b/src/react-sortable-tree.js index 9d200429..f8dd2b2d 100644 --- a/src/react-sortable-tree.js +++ b/src/react-sortable-tree.js @@ -109,6 +109,8 @@ class ReactSortableTree extends Component { searchMatches: [], searchFocusTreeIndex: null, dragging: false, + parentBeforeDrag: null, + sameParent: false, // props that need to be used in gDSFP or static functions will be stored here instanceProps: { @@ -254,6 +256,8 @@ class ReactSortableTree extends Component { depth, minimumTreeIndex, }) { + if(this.props.isParentNodeFixed && !this.sameParent) + return; const { treeData, treeIndex, @@ -361,6 +365,19 @@ class ReactSortableTree extends Component { getNodeKey: this.props.getNodeKey, }); + if(this.props.isParentNodeFixed) { + const addedResult = memoizedInsertNode({ + treeData: draggingTreeData, + newNode: draggedNode, + depth: path.length -1, + minimumTreeIndex: draggedMinimumTreeIndex, + expandParent: true, + getNodeKey: this.props.getNodeKey, + }); + + const rows = this.getRows(addedResult.treeData); + this.parentBeforeDrag = rows[addedResult.treeIndex].path; + } return { draggingTreeData, draggedNode, @@ -399,10 +416,23 @@ class ReactSortableTree extends Component { expandParent: true, getNodeKey: this.props.getNodeKey, }); - const rows = this.getRows(addedResult.treeData); const expandedParentPath = rows[addedResult.treeIndex].path; - + if(this.props.isParentNodeFixed) { + if(expandedParentPath.length === this.parentBeforeDrag.length) { + for(let i=0;i { this.startDrag(props); - return { node: props.node, parentNode: props.parentNode, @@ -235,13 +239,15 @@ export default class DndManager { if (!needsRedraw) { return; } - - this.dragHover({ - node: draggedNode, - path: monitor.getItem().path, - minimumTreeIndex: dropTargetProps.listIndex, - depth: targetDepth, - }); + + if((targetDepth === monitor.getItem().path.length-1 && this.isNodeDepthFixed) || !this.isNodeDepthFixed) { + this.dragHover({ + node: draggedNode, + path: monitor.getItem().path, + minimumTreeIndex: dropTargetProps.listIndex, + depth: targetDepth, + }); + } }, canDrop: this.canDrop.bind(this),