@hello-pangea/dnd
Version:
Beautiful and accessible drag and drop for lists with React
58 lines (50 loc) • 1.86 kB
text/typescript
import type { Position } from 'css-box-model';
import type {
Viewport,
DraggableDimension,
DroppableDimension,
Scrollable,
DroppableDimensionMap,
DroppableId,
} from '../../types';
import { add } from '../position';
import offsetDraggable from './offset-draggable';
import getFrame from '../get-frame';
interface Args {
additions: DraggableDimension[];
updatedDroppables: DroppableDimensionMap;
viewport: Viewport;
}
export default ({
additions,
updatedDroppables,
viewport,
}: Args): DraggableDimension[] => {
// We need to adjust collected draggables so that they
// match the model we had when the drag started.
// When a draggable is dynamically collected it does not have
// the same relative client position. We need to unwind
// any changes in window scroll and droppable scroll so that
// the newly collected draggables fit in with our other draggables
// and give the same dimensions that would have had if they were
// collected at the start of the drag.
// Need to undo the displacement caused by window scroll changes
const windowScrollChange: Position = viewport.scroll.diff.value;
// These modified droppables have already had their scroll changes correctly updated
return additions.map((draggable: DraggableDimension): DraggableDimension => {
const droppableId: DroppableId = draggable.descriptor.droppableId;
const modified: DroppableDimension = updatedDroppables[droppableId];
const frame: Scrollable = getFrame(modified);
const droppableScrollChange: Position = frame.scroll.diff.value;
const totalChange: Position = add(
windowScrollChange,
droppableScrollChange,
);
const moved: DraggableDimension = offsetDraggable({
draggable,
offset: totalChange,
initialWindowScroll: viewport.scroll.initial,
});
return moved;
});
};