1
+ /* eslint-disable no-continue */
1
2
import { useCallback } from 'react' ;
2
3
import { DraggingPosition , TreeItem } from '../types' ;
3
4
import { useGetGetParentOfLinearItem } from './useGetParentOfLinearItem' ;
@@ -9,54 +10,96 @@ export const useGetViableDragPositions = () => {
9
10
const getParentOfLinearItem = useGetGetParentOfLinearItem ( ) ;
10
11
const canDropAt = useCanDropAt ( ) ;
11
12
13
+ const isDescendant = useCallback (
14
+ ( treeId : string , itemLinearIndex : number , potentialParents : TreeItem [ ] ) => {
15
+ // based on DraggingPositionEvaluation.isDescendant()
16
+ const { parent, parentLinearIndex } = getParentOfLinearItem (
17
+ itemLinearIndex ,
18
+ treeId
19
+ ) ;
20
+ if ( potentialParents . some ( p => p . index === parent . item ) ) return true ;
21
+ if ( parent . depth === 0 ) return false ;
22
+ return isDescendant ( treeId , parentLinearIndex , potentialParents ) ;
23
+ } ,
24
+ [ getParentOfLinearItem ]
25
+ ) ;
26
+
12
27
return useCallback (
13
28
( treeId : string , draggingItems : TreeItem [ ] ) => {
14
29
const linearItems = environment . linearItems [ treeId ] ;
15
- return linearItems
16
- . map < DraggingPosition [ ] > ( ( { item, depth } , linearIndex ) => {
17
- const { parent } = getParentOfLinearItem ( linearIndex , treeId ) ;
18
- const childIndex =
19
- environment . items [ parent . item ] . children ! . indexOf ( item ) ;
30
+ const targets : DraggingPosition [ ] = [ ] ;
31
+ let skipUntilDepthIsLowerThan = - 1 ;
32
+
33
+ for (
34
+ let linearIndex = 0 ;
35
+ linearIndex < linearItems . length ;
36
+ // eslint-disable-next-line no-plusplus
37
+ linearIndex ++
38
+ ) {
39
+ const { item, depth } = linearItems [ linearIndex ] ;
40
+
41
+ if (
42
+ skipUntilDepthIsLowerThan !== - 1 &&
43
+ depth > skipUntilDepthIsLowerThan
44
+ ) {
45
+ continue ;
46
+ } else {
47
+ skipUntilDepthIsLowerThan = - 1 ;
48
+ }
49
+
50
+ const { parent } = getParentOfLinearItem ( linearIndex , treeId ) ;
51
+ const childIndex =
52
+ environment . items [ parent . item ] . children ! . indexOf ( item ) ;
53
+
54
+ if ( isDescendant ( treeId , linearIndex , draggingItems ) ) {
55
+ skipUntilDepthIsLowerThan = depth + 1 ;
56
+ continue ;
57
+ }
58
+
59
+ const itemPosition : DraggingPosition = {
60
+ targetType : 'item' ,
61
+ parentItem : parent . item ,
62
+ targetItem : item ,
63
+ linearIndex,
64
+ depth,
65
+ treeId,
66
+ } ;
20
67
21
- const itemPosition : DraggingPosition = {
22
- targetType : 'item' ,
23
- parentItem : parent . item ,
24
- targetItem : item ,
25
- linearIndex,
26
- depth,
27
- treeId,
28
- } ;
68
+ const topPosition : DraggingPosition = {
69
+ targetType : 'between-items' ,
70
+ parentItem : parent . item ,
71
+ linePosition : 'top' ,
72
+ childIndex,
73
+ depth,
74
+ treeId,
75
+ linearIndex,
76
+ } ;
29
77
30
- const topPosition : DraggingPosition = {
31
- targetType : 'between-items' ,
32
- parentItem : parent . item ,
33
- linePosition : 'top ' ,
34
- childIndex ,
35
- depth ,
36
- treeId ,
37
- linearIndex ,
38
- } ;
78
+ const bottomPosition : DraggingPosition = {
79
+ targetType : 'between-items' ,
80
+ parentItem : parent . item ,
81
+ linePosition : 'bottom ' ,
82
+ linearIndex : linearIndex + 1 ,
83
+ childIndex : childIndex + 1 ,
84
+ depth ,
85
+ treeId ,
86
+ } ;
39
87
40
- const bottomPosition : DraggingPosition = {
41
- targetType : 'between-items' ,
42
- parentItem : parent . item ,
43
- linePosition : 'bottom' ,
44
- linearIndex : linearIndex + 1 ,
45
- childIndex : childIndex + 1 ,
46
- depth,
47
- treeId,
48
- } ;
88
+ const skipTopPosition =
89
+ depth === ( linearItems [ linearIndex - 1 ] ?. depth ?? - 1 ) ;
49
90
50
- const skipTopPosition =
51
- depth === ( linearItems [ linearIndex - 1 ] ?. depth ?? - 1 ) ;
91
+ if ( ! skipTopPosition && canDropAt ( topPosition , draggingItems ) ) {
92
+ targets . push ( topPosition ) ;
93
+ }
94
+ if ( canDropAt ( itemPosition , draggingItems ) ) {
95
+ targets . push ( itemPosition ) ;
96
+ }
97
+ if ( canDropAt ( bottomPosition , draggingItems ) ) {
98
+ targets . push ( bottomPosition ) ;
99
+ }
100
+ }
52
101
53
- if ( skipTopPosition ) {
54
- return [ itemPosition , bottomPosition ] ;
55
- }
56
- return [ topPosition , itemPosition , bottomPosition ] ;
57
- } )
58
- . reduce ( ( a , b ) => [ ...a , ...b ] , [ ] )
59
- . filter ( position => canDropAt ( position , draggingItems ) ) ;
102
+ return targets ;
60
103
} ,
61
104
[
62
105
canDropAt ,
0 commit comments