7
7
TreeItemIndex ,
8
8
} from '../types' ;
9
9
import { useTreeEnvironment } from './ControlledTreeEnvironment' ;
10
- import { useOnDragOverTreeHandler } from './useOnDragOverTreeHandler' ;
11
10
import { useCanDropAt } from './useCanDropAt' ;
12
11
import { useGetViableDragPositions } from './useGetViableDragPositions' ;
13
12
import { useSideEffect } from '../useSideEffect' ;
@@ -16,6 +15,8 @@ import { useCallSoon } from '../useCallSoon';
16
15
import { computeItemHeight } from './layoutUtils' ;
17
16
import { useStableHandler } from '../useStableHandler' ;
18
17
import { useGetOriginalItemOrder } from '../useGetOriginalItemOrder' ;
18
+ import { DropPositionEvaluation } from './DropPositionEvaluation' ;
19
+ import { useGetGetParentOfLinearItem } from './useGetParentOfLinearItem' ;
19
20
20
21
const DragAndDropContext = React . createContext < DragAndDropContextProps > (
21
22
null as any
@@ -29,17 +30,20 @@ export const DragAndDropProvider: React.FC<React.PropsWithChildren> = ({
29
30
const environment = useTreeEnvironment ( ) ;
30
31
const [ isProgrammaticallyDragging , setIsProgrammaticallyDragging ] =
31
32
useState ( false ) ;
32
- const [ itemHeight , setItemHeight ] = useState ( 4 ) ;
33
33
const [ viableDragPositions , setViableDragPositions ] = useState < {
34
34
[ treeId : string ] : DraggingPosition [ ] ;
35
35
} > ( { } ) ;
36
36
const [ programmaticDragIndex , setProgrammaticDragIndex ] = useState ( 0 ) ;
37
- const [ draggingItems , setDraggingItems ] = useState < TreeItem [ ] > ( ) ;
38
37
const [ draggingPosition , setDraggingPosition ] = useState < DraggingPosition > ( ) ;
39
- const [ dragCode , setDragCode ] = useState ( '_nodrag' ) ;
38
+ const [ dragCode , setDragCode ] = useState ( '_nodrag' ) ; // TODO should be moved into evaluator
40
39
const getViableDragPositions = useGetViableDragPositions ( ) ;
41
40
const callSoon = useCallSoon ( ) ;
42
41
const getOriginalItemOrder = useGetOriginalItemOrder ( ) ;
42
+ const getParentOfLinearItem = useGetGetParentOfLinearItem ( ) ;
43
+
44
+ const [ dropPositionEvaluator , setDropPositionEvaluator ] = useState <
45
+ DropPositionEvaluation | undefined
46
+ > ( undefined ) ;
43
47
44
48
const resetProgrammaticDragIndexForCurrentTree = useCallback (
45
49
(
@@ -93,12 +97,11 @@ export const DragAndDropProvider: React.FC<React.PropsWithChildren> = ({
93
97
94
98
const resetState = useCallback ( ( ) => {
95
99
setIsProgrammaticallyDragging ( false ) ;
96
- setItemHeight ( 4 ) ;
97
100
setViableDragPositions ( { } ) ;
98
101
setProgrammaticDragIndex ( 0 ) ;
99
- setDraggingItems ( undefined ) ;
100
102
setDraggingPosition ( undefined ) ;
101
103
setDragCode ( '_nodrag' ) ;
104
+ setDropPositionEvaluator ( undefined ) ;
102
105
} , [ ] ) ;
103
106
104
107
useSideEffect (
@@ -110,12 +113,12 @@ export const DragAndDropProvider: React.FC<React.PropsWithChildren> = ({
110
113
) {
111
114
resetProgrammaticDragIndexForCurrentTree (
112
115
viableDragPositions [ environment . activeTreeId ] ,
113
- draggingItems
116
+ dropPositionEvaluator ?. draggingItems
114
117
) ;
115
118
}
116
119
} ,
117
120
[
118
- draggingItems ,
121
+ dropPositionEvaluator ?. draggingItems ,
119
122
environment . activeTreeId ,
120
123
environment . linearItems ,
121
124
resetProgrammaticDragIndexForCurrentTree ,
@@ -144,32 +147,66 @@ export const DragAndDropProvider: React.FC<React.PropsWithChildren> = ({
144
147
const canDropAt = useCanDropAt ( ) ;
145
148
146
149
const performDrag = ( draggingPosition : DraggingPosition ) => {
147
- if ( draggingItems && ! canDropAt ( draggingPosition , draggingItems ) ) {
150
+ if (
151
+ dropPositionEvaluator ?. draggingItems &&
152
+ ! canDropAt ( draggingPosition , dropPositionEvaluator . draggingItems )
153
+ ) {
148
154
return ;
149
155
}
150
156
151
157
setDraggingPosition ( draggingPosition ) ;
152
158
environment . setActiveTree ( draggingPosition . treeId ) ;
153
159
154
- if ( draggingItems && environment . activeTreeId !== draggingPosition . treeId ) {
160
+ if (
161
+ dropPositionEvaluator ?. draggingItems &&
162
+ environment . activeTreeId !== draggingPosition . treeId
163
+ ) {
155
164
// TODO maybe do only if draggingItems are different to selectedItems
156
165
environment . onSelectItems ?.(
157
- draggingItems . map ( item => item . index ) ,
166
+ dropPositionEvaluator . draggingItems . map ( item => item . index ) ,
158
167
draggingPosition . treeId
159
168
) ;
160
169
}
161
170
} ;
162
171
163
- const onDragOverTreeHandler = useOnDragOverTreeHandler (
164
- dragCode ,
165
- setDragCode ,
166
- draggingItems ,
167
- itemHeight ,
168
- setDraggingPosition ,
169
- performDrag
172
+ const onDragOverTreeHandler = useStableHandler (
173
+ (
174
+ e : DragEvent ,
175
+ treeId : string ,
176
+ containerRef : React . MutableRefObject < HTMLElement | undefined >
177
+ ) => {
178
+ // TODO move dragcode check into evaluator
179
+ if ( ! dropPositionEvaluator ) return ;
180
+ const hoveringPosition = dropPositionEvaluator . getHoveringPosition (
181
+ e ,
182
+ treeId ,
183
+ containerRef
184
+ ) ;
185
+ const newDragCode = dropPositionEvaluator . getDragCode (
186
+ e ,
187
+ treeId ,
188
+ hoveringPosition
189
+ ) ;
190
+ if ( newDragCode === dragCode ) {
191
+ return ;
192
+ }
193
+ setDragCode ( newDragCode ) ;
194
+ const newDraggingPosition = dropPositionEvaluator . getDraggingPosition (
195
+ e ,
196
+ hoveringPosition ,
197
+ treeId
198
+ ) ;
199
+ if ( ! newDraggingPosition ) {
200
+ setDraggingPosition ( undefined ) ;
201
+ return ;
202
+ }
203
+ // setItemHeight(dropPositionEvaluator.itemHeight);
204
+ performDrag ( newDraggingPosition ) ;
205
+ }
170
206
) ;
171
207
172
208
const onDropHandler = useStableHandler ( ( ) => {
209
+ const draggingItems = dropPositionEvaluator ?. draggingItems ;
173
210
if ( draggingItems && draggingPosition && environment . onDrop ) {
174
211
environment . onDrop ( draggingItems , draggingPosition ) ;
175
212
@@ -187,10 +224,16 @@ export const DragAndDropProvider: React.FC<React.PropsWithChildren> = ({
187
224
treeId => getViableDragPositions ( treeId , items )
188
225
) ;
189
226
227
+ setDropPositionEvaluator (
228
+ new DropPositionEvaluation (
229
+ environment ,
230
+ getParentOfLinearItem ,
231
+ items ,
232
+ computeItemHeight ( treeId )
233
+ )
234
+ ) ;
235
+
190
236
// TODO what if trees have different heights and drag target changes?
191
- const height = computeItemHeight ( treeId ) ;
192
- setItemHeight ( height ) ;
193
- setDraggingItems ( items ) ;
194
237
setViableDragPositions ( treeViableDragPositions ) ;
195
238
196
239
if ( environment . activeTreeId ) {
@@ -201,8 +244,8 @@ export const DragAndDropProvider: React.FC<React.PropsWithChildren> = ({
201
244
}
202
245
} ,
203
246
[
204
- environment . activeTreeId ,
205
- environment . treeIds ,
247
+ environment ,
248
+ getParentOfLinearItem ,
206
249
getViableDragPositions ,
207
250
resetProgrammaticDragIndexForCurrentTree ,
208
251
]
@@ -273,9 +316,9 @@ export const DragAndDropProvider: React.FC<React.PropsWithChildren> = ({
273
316
completeProgrammaticDrag,
274
317
programmaticDragUp,
275
318
programmaticDragDown,
276
- draggingItems,
319
+ draggingItems : dropPositionEvaluator ?. draggingItems ,
277
320
draggingPosition,
278
- itemHeight,
321
+ itemHeight : dropPositionEvaluator ?. itemHeight ?? 4 ,
279
322
isProgrammaticallyDragging,
280
323
onDragOverTreeHandler,
281
324
viableDragPositions,
@@ -287,9 +330,9 @@ export const DragAndDropProvider: React.FC<React.PropsWithChildren> = ({
287
330
completeProgrammaticDrag ,
288
331
programmaticDragUp ,
289
332
programmaticDragDown ,
290
- draggingItems ,
333
+ dropPositionEvaluator ?. draggingItems ,
334
+ dropPositionEvaluator ?. itemHeight ,
291
335
draggingPosition ,
292
- itemHeight ,
293
336
isProgrammaticallyDragging ,
294
337
onDragOverTreeHandler ,
295
338
viableDragPositions ,
0 commit comments