44} from './DraggingPositionEvaluator' ;
55import {
66 DraggingPosition ,
7+ LinearItem ,
78 TreeEnvironmentContextProps ,
89 TreeItem ,
910} from '../types' ;
@@ -17,7 +18,13 @@ export class DraggingPositionEvaluation {
1718
1819 private readonly treeId : string ;
1920
20- private readonly hoveringPosition : HoveringPosition ;
21+ private linearIndex : number ;
22+
23+ private offset : 'bottom' | 'top' | undefined ;
24+
25+ private indentation : number ;
26+
27+ private targetItem : LinearItem ;
2128
2229 constructor (
2330 evaluator : DraggingPositionEvaluator ,
@@ -30,7 +37,10 @@ export class DraggingPositionEvaluation {
3037 this . env = env ;
3138 this . e = e ;
3239 this . treeId = treeId ;
33- this . hoveringPosition = hoveringPosition ;
40+ this . linearIndex = hoveringPosition . linearIndex ;
41+ this . offset = hoveringPosition . offset ;
42+ this . indentation = hoveringPosition . indentation ;
43+ this . targetItem = this . env . linearItems [ this . treeId ] [ this . linearIndex ] ;
3444 }
3545
3646 getDraggingPosition ( ) : DraggingPosition | undefined {
@@ -49,118 +59,139 @@ export class DraggingPositionEvaluation {
4959 } ;
5060 }
5161
52- // eslint-disable-next-line prefer-const
53- let { linearIndex, offset, veryBottom } = this . hoveringPosition ;
54-
5562 if (
56- linearIndex < 0 ||
57- linearIndex >= this . env . linearItems [ this . treeId ] . length
63+ this . linearIndex < 0 ||
64+ this . linearIndex >= this . env . linearItems [ this . treeId ] . length
5865 ) {
5966 return undefined ;
6067 }
6168
62- let targetItem = this . env . linearItems [ this . treeId ] [ linearIndex ] ;
6369 const redirectTargetToParent =
6470 ! this . env . canReorderItems &&
6571 ! this . env . canDropOnNonFolder &&
66- ! this . env . items [ targetItem . item ] . isFolder ;
72+ ! this . env . items [ this . targetItem . item ] . isFolder ;
6773
6874 if ( redirectTargetToParent ) {
6975 const { parentLinearIndex, parent } =
70- this . evaluator . getParentOfLinearItem ( linearIndex , this . treeId ) ;
71- targetItem = parent ;
72- linearIndex = parentLinearIndex ;
76+ this . evaluator . getParentOfLinearItem ( this . linearIndex , this . treeId ) ;
77+ this . targetItem = parent ;
78+ this . linearIndex = parentLinearIndex ;
7379 }
7480
7581 if (
76- this . isDescendant ( this . treeId , linearIndex , this . evaluator . draggingItems )
82+ this . isDescendant (
83+ this . treeId ,
84+ this . linearIndex ,
85+ this . evaluator . draggingItems
86+ )
7787 ) {
7888 return undefined ;
7989 }
8090
81- const nextItem = this . env . linearItems [ this . treeId ] [ linearIndex + 1 ] ;
91+ const treeLinearItems = this . env . linearItems [ this . treeId ] ;
92+ const deepestDepth = treeLinearItems [ this . linearIndex ] . depth ;
93+ const legalDropDepthCount = // itemDepthDifferenceToNextItem/isLastInGroup
94+ deepestDepth - ( treeLinearItems [ this . linearIndex + 1 ] ?. depth ?? 0 ) ;
95+ const canReparentUpwards =
96+ this . offset === 'bottom' && legalDropDepthCount > 0 ;
97+ // Default to zero on last position to allow dropping on root when
98+ // dropping at bottom
99+ if ( canReparentUpwards ) {
100+ const droppingIndent = Math . max (
101+ deepestDepth - legalDropDepthCount ,
102+ this . indentation
103+ ) ;
104+ let newParent = {
105+ parentLinearIndex : this . linearIndex ,
106+ parent : this . targetItem ,
107+ } ;
108+ for ( let i = deepestDepth ; i !== droppingIndent ; i -= 1 ) {
109+ newParent = this . evaluator . getParentOfLinearItem (
110+ newParent . parentLinearIndex ,
111+ this . treeId
112+ ) ;
113+ }
114+
115+ if ( this . indentation !== treeLinearItems [ this . linearIndex ] . depth ) {
116+ this . targetItem = newParent . parent ;
117+ }
118+ }
119+
120+ const nextItem = this . env . linearItems [ this . treeId ] [ this . linearIndex + 1 ] ;
82121 const redirectToFirstChild =
83122 ! this . env . canDropBelowOpenFolders &&
84123 nextItem &&
85- targetItem . depth === nextItem . depth - 1 &&
86- offset === 'bottom' ;
124+ this . targetItem . depth === nextItem . depth - 1 &&
125+ this . offset === 'bottom' ;
87126 if ( redirectToFirstChild ) {
88- targetItem = nextItem ;
89- linearIndex += 1 ;
90- offset = 'top' ;
127+ this . targetItem = nextItem ;
128+ this . linearIndex += 1 ;
129+ this . offset = 'top' ;
91130 }
92131
93- const { depth } = targetItem ;
94- const targetItemData = this . env . items [ targetItem . item ] ;
132+ const { depth } = this . targetItem ;
133+ const targetItemData = this . env . items [ this . targetItem . item ] ;
95134
96- if ( ! offset && ! this . env . canDropOnNonFolder && ! targetItemData . isFolder ) {
135+ if (
136+ ! this . offset &&
137+ ! this . env . canDropOnNonFolder &&
138+ ! targetItemData . isFolder
139+ ) {
97140 return undefined ;
98141 }
99142
100- if ( ! offset && ! this . env . canDropOnFolder && targetItemData . isFolder ) {
143+ if ( ! this . offset && ! this . env . canDropOnFolder && targetItemData . isFolder ) {
101144 return undefined ;
102145 }
103146
104- if ( offset && ! this . env . canReorderItems ) {
147+ if ( this . offset && ! this . env . canReorderItems ) {
105148 return undefined ;
106149 }
107150
108151 const { parent } = this . evaluator . getParentOfLinearItem (
109- linearIndex ,
152+ this . linearIndex ,
110153 this . treeId
111154 ) ;
112155
113156 if (
114157 this . evaluator . draggingItems . some (
115- draggingItem => draggingItem . index === targetItem . item
158+ draggingItem => draggingItem . index === this . targetItem . item
116159 )
117160 ) {
118161 return undefined ;
119162 }
120163
121164 const newChildIndex =
122- this . env . items [ parent . item ] . children ! . indexOf ( targetItem . item ) +
123- ( offset === 'top' ? 0 : 1 ) ;
165+ this . env . items [ parent . item ] . children ! . indexOf ( this . targetItem . item ) +
166+ ( this . offset === 'top' ? 0 : 1 ) ;
124167
125168 if (
126- offset === 'top' &&
169+ this . offset === 'top' &&
127170 depth ===
128- ( this . env . linearItems [ this . treeId ] [ linearIndex - 1 ] ?. depth ?? - 1 )
171+ ( this . env . linearItems [ this . treeId ] [ this . linearIndex - 1 ] ?. depth ?? - 1 )
129172 ) {
130- offset = 'bottom' ;
131- linearIndex -= 1 ;
173+ this . offset = 'bottom' ;
174+ this . linearIndex -= 1 ;
132175 }
133176
134- if ( veryBottom ) {
135- const { rootItem } = this . env . trees [ this . treeId ] ;
136- return {
137- targetType : 'between-items' ,
138- treeId : this . treeId ,
139- parentItem : rootItem ,
140- depth : 0 ,
141- linearIndex : linearIndex + 1 ,
142- childIndex : this . env . items [ rootItem ] . children ?. length ?? 0 ,
143- linePosition : 'bottom' ,
144- } ;
145- }
146- if ( offset ) {
177+ if ( this . offset ) {
147178 return {
148179 targetType : 'between-items' ,
149180 treeId : this . treeId ,
150181 parentItem : parent . item ,
151- depth : targetItem . depth ,
152- linearIndex : linearIndex + ( offset === 'top' ? 0 : 1 ) ,
182+ depth : this . targetItem . depth ,
183+ linearIndex : this . linearIndex + ( this . offset === 'top' ? 0 : 1 ) ,
153184 childIndex : newChildIndex ,
154- linePosition : offset ,
185+ linePosition : this . offset ,
155186 } ;
156187 }
157188 return {
158189 targetType : 'item' ,
159190 treeId : this . treeId ,
160191 parentItem : parent . item ,
161- targetItem : targetItem . item ,
162- depth : targetItem . depth ,
163- linearIndex,
192+ targetItem : this . targetItem . item ,
193+ depth : this . targetItem . depth ,
194+ linearIndex : this . linearIndex ,
164195 } ;
165196 }
166197
0 commit comments