Skip to content

Commit af8bc63

Browse files
ksaxbergwuweiweiwu
authored andcommitted
Childless Nodes (frontend-collective#402)
* create configurable canNodeHaveChildren function * add to proptypes * simplify the documentation example * add story, modify example slightly * Add canNodeHaveChildren to props list in readme
1 parent ff980d8 commit af8bc63

File tree

6 files changed

+660
-1
lines changed

6 files changed

+660
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ export default class Tree extends Component {
106106
| rowDirection | string | Adds row direction support if set to `'rtl'` Defaults to `'ltr'`. |
107107
| canDrag | func or bool | Return false from callback to prevent node from dragging, by hiding the drag handle. Set prop to `false` to disable dragging on all nodes. Defaults to `true`. <div>`({ node: object, path: number[] or string[], treeIndex: number, lowerSiblingCounts: number[], isSearchMatch: bool, isSearchFocus: bool }): bool`</div> |
108108
| canDrop | func | Return false to prevent node from dropping in the given location. <div>`({ node: object, prevPath: number[] or string[], prevParent: object, prevTreeIndex: number, nextPath: number[] or string[], nextParent: object, nextTreeIndex: number }): bool`</div> |
109+
| canNodeHaveChildren | func | Function to determine whether a node can have children, useful for preventing hover preview when you have a `canDrop` condition. Default is set to a function that returns `true`. Functions should be of type `(node): bool`.
109110
| theme | object | Set an all-in-one packaged appearance for the tree. See the [Themes](#themes) section for more information. |
110111
| searchMethod | func | The method used to search nodes. Defaults to [`defaultSearchMethod`](https://github.com/frontend-collective/react-sortable-tree/blob/master/src/utils/default-handlers.js), which uses the `searchQuery` string to search for nodes with matching `title` or `subtitle` values. NOTE: Changing `searchMethod` will not update the search, but changing the `searchQuery` will.<div>`({ node: object, path: number[] or string[], treeIndex: number, searchQuery: any }): bool`</div> |
111112
| searchQuery | string or any | Used by the `searchMethod` to highlight and scroll to matched nodes. Should be a string for the default `searchMethod`, but can be anything when using a custom search. Defaults to `null`. |

src/react-sortable-tree.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,14 @@ class ReactSortableTree extends Component {
479479
this.moveNode(dropResult);
480480
}
481481

482+
canNodeHaveChildren(node) {
483+
const { canNodeHaveChildren } = this.props;
484+
if (canNodeHaveChildren) {
485+
return canNodeHaveChildren(node);
486+
}
487+
return true;
488+
}
489+
482490
// Load any children in the tree that are given by a function
483491
// calls the onChange callback on the new treeData
484492
static loadLazyChildren(props, state) {
@@ -859,6 +867,9 @@ ReactSortableTree.propTypes = {
859867
// Determine whether a node can be dropped based on its path and parents'.
860868
canDrop: PropTypes.func,
861869

870+
// Determine whether a node can have children
871+
canNodeHaveChildren: PropTypes.func,
872+
862873
// When true, or a callback returning true, dropping nodes to react-dnd
863874
// drop targets outside of this tree will not remove them from this tree
864875
shouldCopyOnOutsideDrop: PropTypes.oneOfType([
@@ -884,6 +895,7 @@ ReactSortableTree.propTypes = {
884895
ReactSortableTree.defaultProps = {
885896
canDrag: true,
886897
canDrop: null,
898+
canNodeHaveChildren: () => true,
887899
className: '',
888900
dndType: null,
889901
generateNodeProps: null,

src/utils/dnd-manager.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,15 @@ export default class DndManager {
6262

6363
const rowAbove = dropTargetProps.getPrevRow();
6464
if (rowAbove) {
65+
let { path } = rowAbove;
66+
const aboveNodeCannotHaveChildren = !this.treeRef.canNodeHaveChildren(rowAbove.node);
67+
if (aboveNodeCannotHaveChildren) {
68+
path = path.slice(0, path.length - 1);
69+
}
70+
6571
// Limit the length of the path to the deepest possible
6672
dropTargetDepth = Math.min(
67-
rowAbove.path.length,
73+
path.length,
6874
dropTargetProps.path.length
6975
);
7076
}

0 commit comments

Comments
 (0)