react-beautiful-dnd-next
Version:
Beautiful and accessible drag and drop for lists with React
80 lines (73 loc) • 2.32 kB
JavaScript
// @flow
import { type Position } from 'css-box-model';
import type {
Viewport,
DraggableDimension,
DroppableDimension,
OnLift,
} from '../../../types';
import { distance } from '../../position';
import { isTotallyVisible } from '../../visibility/is-visible';
import withDroppableDisplacement from '../../with-scroll-change/with-droppable-displacement';
import {
getCurrentPageBorderBox,
getCurrentPageBorderBoxCenter,
} from './without-starting-displacement';
type Args = {|
pageBorderBoxCenter: Position,
viewport: Viewport,
// the droppable that is being moved to
destination: DroppableDimension,
// the droppables inside the destination
insideDestination: DraggableDimension[],
onLift: OnLift,
|};
export default ({
pageBorderBoxCenter,
viewport,
destination,
insideDestination,
onLift,
}: Args): ?DraggableDimension => {
const sorted: DraggableDimension[] = insideDestination
.filter((draggable: DraggableDimension): boolean =>
// Allowing movement to draggables that are not visible in the viewport
// but must be visible in the droppable
// We can improve this, but this limitation is easier for now
isTotallyVisible({
target: getCurrentPageBorderBox(draggable, onLift),
destination,
viewport: viewport.frame,
withDroppableDisplacement: true,
}),
)
.sort((a: DraggableDimension, b: DraggableDimension): number => {
// Need to consider the change in scroll in the destination
const distanceToA = distance(
pageBorderBoxCenter,
withDroppableDisplacement(
destination,
getCurrentPageBorderBoxCenter(a, onLift),
),
);
const distanceToB = distance(
pageBorderBoxCenter,
withDroppableDisplacement(
destination,
getCurrentPageBorderBoxCenter(b, onLift),
),
);
// if a is closer - return a
if (distanceToA < distanceToB) {
return -1;
}
// if b is closer - return b
if (distanceToB < distanceToA) {
return 1;
}
// if the distance to a and b are the same:
// return the one with the lower index (it will be higher on the main axis)
return a.descriptor.index - b.descriptor.index;
});
return sorted[0] || null;
};