react-beautiful-dnd-next
Version:
Beautiful and accessible drag and drop for lists with React
93 lines (81 loc) • 2.53 kB
JavaScript
// @flow
import invariant from 'tiny-invariant';
import type { Position } from 'css-box-model';
import { isEqual, subtract, add, origin, negate } from '../position';
import type {
DragPositions,
Viewport,
ClientPositions,
PagePositions,
} from '../../types';
type Args = {|
initial: DragPositions,
current: DragPositions,
oldClientBorderBoxCenter: Position,
newClientBorderBoxCenter: Position,
viewport: Viewport,
|};
type Result = {|
initial: DragPositions,
current: DragPositions,
|};
export default ({
initial: oldInitial,
current: oldCurrent,
oldClientBorderBoxCenter,
newClientBorderBoxCenter,
viewport,
}: Args): Result => {
// TODO: what about page shifts?
// how much the dragging item has shifted in the DOM
const shift: Position = subtract(
newClientBorderBoxCenter,
oldClientBorderBoxCenter,
);
// Correcting its new original position
const initial: DragPositions = (() => {
const client: ClientPositions = {
selection: add(oldInitial.client.selection, shift),
borderBoxCenter: newClientBorderBoxCenter,
offset: origin,
};
const page: PagePositions = {
selection: add(client.selection, viewport.scroll.initial),
borderBoxCenter: add(client.selection, viewport.scroll.initial),
};
return {
client,
page,
};
})();
const current: DragPositions = (() => {
// We need to undo the shift to keep the dragging item
// in the same visual spot
const reverse: Position = negate(shift);
const offset: Position = add(oldCurrent.client.offset, reverse);
const client: ClientPositions = {
selection: add(initial.client.selection, offset),
// this should be the same as the previous client borderBox center
borderBoxCenter: add(initial.client.borderBoxCenter, offset),
offset,
};
const page: PagePositions = {
selection: add(client.selection, viewport.scroll.current),
// this should be the same as the previous client borderBox center
borderBoxCenter: add(client.borderBoxCenter, viewport.scroll.current),
};
invariant(
isEqual(oldCurrent.client.borderBoxCenter, client.borderBoxCenter),
`
Incorrect new client center position.
Expected (${oldCurrent.client.borderBoxCenter.x}, ${oldCurrent.client.borderBoxCenter.y})
to equal (${client.borderBoxCenter.x}, ${client.borderBoxCenter.y})
`,
);
return {
client,
page,
};
})();
return { current, initial };
};