|
1 | 1 | // @flow
|
2 |
| -import type { Rect, Position } from 'css-box-model'; |
| 2 | +import type { Rect } from 'css-box-model'; |
3 | 3 | import type {
|
4 | 4 | DraggableId,
|
5 | 5 | Axis,
|
6 |
| - UserDirection, |
7 | 6 | DraggableDimension,
|
8 | 7 | DroppableDimension,
|
9 |
| - CombineImpact, |
10 | 8 | DragImpact,
|
11 |
| - DisplacementGroups, |
12 | 9 | LiftEffect,
|
13 | 10 | DisplacedBy,
|
14 | 11 | } from '../../types';
|
15 |
| -import isWithin from '../is-within'; |
16 | 12 | import { find } from '../../native-with-fallback';
|
17 |
| -import isUserMovingForward from '../user-direction/is-user-moving-forward'; |
18 |
| -import getCombinedItemDisplacement from '../get-combined-item-displacement'; |
19 |
| -import removeDraggableFromList from '../remove-draggable-from-list'; |
20 |
| -import calculateCombineImpact from '../calculate-drag-impact/calculate-combine-impact'; |
| 13 | +import getDidStartAfterCritical from '../did-start-after-critical'; |
21 | 14 | import getDisplacedBy from '../get-displaced-by';
|
22 |
| - |
23 |
| -function getWhenEntered( |
24 |
| - id: DraggableId, |
25 |
| - current: UserDirection, |
26 |
| - lastCombineImpact: ?CombineImpact, |
27 |
| -): UserDirection { |
28 |
| - if (!lastCombineImpact) { |
29 |
| - return current; |
30 |
| - } |
31 |
| - if (id !== lastCombineImpact.combine.draggableId) { |
32 |
| - return current; |
33 |
| - } |
34 |
| - return lastCombineImpact.whenEntered; |
35 |
| -} |
36 |
| - |
37 |
| -type IsCombiningWithArgs = {| |
38 |
| - id: DraggableId, |
39 |
| - currentCenter: Position, |
40 |
| - axis: Axis, |
41 |
| - borderBox: Rect, |
42 |
| - displaceBy: Position, |
43 |
| - currentUserDirection: UserDirection, |
44 |
| - lastCombineImpact: ?CombineImpact, |
45 |
| -|}; |
46 |
| - |
47 |
| -const isCombiningWith = ({ |
48 |
| - id, |
49 |
| - currentCenter, |
50 |
| - axis, |
51 |
| - borderBox, |
52 |
| - displaceBy, |
53 |
| - currentUserDirection, |
54 |
| - lastCombineImpact, |
55 |
| -}: IsCombiningWithArgs): boolean => { |
56 |
| - const start: number = borderBox[axis.start] + displaceBy[axis.line]; |
57 |
| - const end: number = borderBox[axis.end] + displaceBy[axis.line]; |
58 |
| - const size: number = borderBox[axis.size]; |
59 |
| - const twoThirdsOfSize: number = size * 0.666; |
60 |
| - |
61 |
| - const whenEntered: UserDirection = getWhenEntered( |
62 |
| - id, |
63 |
| - currentUserDirection, |
64 |
| - lastCombineImpact, |
65 |
| - ); |
66 |
| - const isMovingForward: boolean = isUserMovingForward(axis, whenEntered); |
67 |
| - const targetCenter: number = currentCenter[axis.line]; |
68 |
| - |
69 |
| - if (isMovingForward) { |
70 |
| - // combine when moving in the front 2/3 of the item |
71 |
| - return isWithin(start, start + twoThirdsOfSize)(targetCenter); |
72 |
| - } |
73 |
| - // combine when moving in the back 2/3 of the item |
74 |
| - return isWithin(end - twoThirdsOfSize, end)(targetCenter); |
75 |
| -}; |
76 |
| - |
77 |
| -function tryGetCombineImpact(impact: DragImpact): ?CombineImpact { |
78 |
| - if (impact.at && impact.at.type === 'COMBINE') { |
79 |
| - return impact.at; |
80 |
| - } |
81 |
| - return null; |
82 |
| -} |
| 15 | +import getIsDisplaced from '../get-is-displaced'; |
| 16 | +import removeDraggableFromList from '../remove-draggable-from-list'; |
83 | 17 |
|
84 | 18 | type Args = {|
|
85 | 19 | draggable: DraggableDimension,
|
86 |
| - pageBorderBoxCenterWithDroppableScrollChange: Position, |
| 20 | + pageBorderBoxWithDroppableScroll: Rect, |
87 | 21 | previousImpact: DragImpact,
|
88 | 22 | destination: DroppableDimension,
|
89 | 23 | insideDestination: DraggableDimension[],
|
90 |
| - userDirection: UserDirection, |
91 | 24 | afterCritical: LiftEffect,
|
92 | 25 | |};
|
| 26 | + |
| 27 | +// exported for testing |
| 28 | +export const combineThresholdDivisor: number = 4; |
| 29 | + |
93 | 30 | export default ({
|
94 | 31 | draggable,
|
95 |
| - pageBorderBoxCenterWithDroppableScrollChange: currentCenter, |
| 32 | + pageBorderBoxWithDroppableScroll: targetRect, |
96 | 33 | previousImpact,
|
97 | 34 | destination,
|
98 | 35 | insideDestination,
|
99 |
| - userDirection, |
100 | 36 | afterCritical,
|
101 | 37 | }: Args): ?DragImpact => {
|
102 | 38 | if (!destination.isCombineEnabled) {
|
103 | 39 | return null;
|
104 | 40 | }
|
105 |
| - |
106 | 41 | const axis: Axis = destination.axis;
|
107 |
| - const displaced: DisplacementGroups = previousImpact.displaced; |
108 |
| - const canBeDisplacedBy: DisplacedBy = getDisplacedBy( |
| 42 | + const displacedBy: DisplacedBy = getDisplacedBy( |
109 | 43 | destination.axis,
|
110 | 44 | draggable.displaceBy,
|
111 | 45 | );
|
112 |
| - const lastCombineImpact: ?CombineImpact = tryGetCombineImpact(previousImpact); |
| 46 | + const displacement: number = displacedBy.value; |
| 47 | + |
| 48 | + const targetStart: number = targetRect[axis.start]; |
| 49 | + const targetEnd: number = targetRect[axis.end]; |
| 50 | + |
| 51 | + const withoutDragging: DraggableDimension[] = removeDraggableFromList( |
| 52 | + draggable, |
| 53 | + insideDestination, |
| 54 | + ); |
113 | 55 |
|
114 | 56 | const combineWith: ?DraggableDimension = find(
|
115 |
| - removeDraggableFromList(draggable, insideDestination), |
| 57 | + withoutDragging, |
116 | 58 | (child: DraggableDimension): boolean => {
|
117 | 59 | const id: DraggableId = child.descriptor.id;
|
| 60 | + const childRect: Rect = child.page.borderBox; |
| 61 | + const childSize: number = childRect[axis.size]; |
| 62 | + const threshold: number = childSize / combineThresholdDivisor; |
118 | 63 |
|
119 |
| - const displaceBy: Position = getCombinedItemDisplacement({ |
120 |
| - displaced, |
| 64 | + const didStartAfterCritical: boolean = getDidStartAfterCritical( |
| 65 | + id, |
121 | 66 | afterCritical,
|
122 |
| - combineWith: id, |
123 |
| - displacedBy: canBeDisplacedBy, |
124 |
| - }); |
| 67 | + ); |
125 | 68 |
|
126 |
| - return isCombiningWith({ |
| 69 | + const isDisplaced: boolean = getIsDisplaced({ |
| 70 | + displaced: previousImpact.displaced, |
127 | 71 | id,
|
128 |
| - currentCenter, |
129 |
| - axis, |
130 |
| - borderBox: child.page.borderBox, |
131 |
| - displaceBy, |
132 |
| - currentUserDirection: userDirection, |
133 |
| - lastCombineImpact, |
134 | 72 | });
|
| 73 | + |
| 74 | + /* |
| 75 | + Only combining when in the combine region |
| 76 | + As soon as a boundary is hit then no longer combining |
| 77 | + */ |
| 78 | + |
| 79 | + if (didStartAfterCritical) { |
| 80 | + // In original position |
| 81 | + // Will combine with item when inside a band |
| 82 | + if (isDisplaced) { |
| 83 | + return ( |
| 84 | + targetEnd > childRect[axis.start] + threshold && |
| 85 | + targetEnd < childRect[axis.end] - threshold |
| 86 | + ); |
| 87 | + } |
| 88 | + |
| 89 | + // child is now 'displaced' backwards from where it started |
| 90 | + // want to combine when we move backwards onto it |
| 91 | + return ( |
| 92 | + targetStart > childRect[axis.start] - displacement + threshold && |
| 93 | + targetStart < childRect[axis.end] - displacement - threshold |
| 94 | + ); |
| 95 | + } |
| 96 | + |
| 97 | + // item has moved forwards |
| 98 | + if (isDisplaced) { |
| 99 | + return ( |
| 100 | + targetEnd > childRect[axis.start] + displacement + threshold && |
| 101 | + targetEnd < childRect[axis.end] + displacement - threshold |
| 102 | + ); |
| 103 | + } |
| 104 | + |
| 105 | + // is in resting position - being moved backwards on to |
| 106 | + return ( |
| 107 | + targetStart > childRect[axis.start] + threshold && |
| 108 | + targetStart < childRect[axis.end] - threshold |
| 109 | + ); |
135 | 110 | },
|
136 | 111 | );
|
137 | 112 |
|
138 | 113 | if (!combineWith) {
|
139 | 114 | return null;
|
140 | 115 | }
|
141 | 116 |
|
142 |
| - return calculateCombineImpact({ |
143 |
| - combineWithId: combineWith.descriptor.id, |
144 |
| - destinationId: destination.descriptor.id, |
145 |
| - previousImpact, |
146 |
| - userDirection, |
147 |
| - }); |
| 117 | + const impact: DragImpact = { |
| 118 | + // no change to displacement when combining |
| 119 | + displacedBy, |
| 120 | + displaced: previousImpact.displaced, |
| 121 | + at: { |
| 122 | + type: 'COMBINE', |
| 123 | + combine: { |
| 124 | + draggableId: combineWith.descriptor.id, |
| 125 | + droppableId: destination.descriptor.id, |
| 126 | + }, |
| 127 | + }, |
| 128 | + }; |
| 129 | + return impact; |
148 | 130 | };
|
0 commit comments