UNPKG

react-beautiful-dnd-next

Version:

Beautiful and accessible drag and drop for lists with React

100 lines (83 loc) 2.6 kB
// @flow import invariant from 'tiny-invariant'; import type { DraggableDimension, DroppableDimension, DragImpact, CombineImpact, DraggableLocation, } from '../../../../types'; import { forward, backward, } from '../../../user-direction/user-direction-preset'; export type Args = {| isMovingForward: boolean, isInHomeList: boolean, draggable: DraggableDimension, destination: DroppableDimension, insideDestination: DraggableDimension[], previousImpact: DragImpact, |}; export default ({ isMovingForward, isInHomeList, draggable, destination, insideDestination: originalInsideDestination, previousImpact, }: Args): ?DragImpact => { if (!destination.isCombineEnabled) { return null; } // we move from a merge to a reorder if (previousImpact.merge) { return null; } // we are on a location, and we are trying to combine onto a sibling // that sibling might be displaced const location: ?DraggableLocation = previousImpact.destination; invariant(location, 'Need a previous location to move from into a combine'); const currentIndex: number = location.index; // update the insideDestination list to reflect the current list order // TODO: cleanup const currentInsideDestination: DraggableDimension[] = (() => { const shallow = originalInsideDestination.slice(); // if we are in the home list we need to remove the item from its original position // before we insert it into its new position if (isInHomeList) { shallow.splice(draggable.descriptor.index, 1); } // put the draggable into its current position in the list shallow.splice(location.index, 0, draggable); return shallow; })(); const targetIndex: number = isMovingForward ? currentIndex + 1 : currentIndex - 1; if (targetIndex < 0) { return null; } // The last item that can be grouped with is the last one if (targetIndex > currentInsideDestination.length - 1) { return null; } // TODO: what if target is original!? const target: DraggableDimension = currentInsideDestination[targetIndex]; invariant(target !== draggable, 'Cannot combine with self'); const merge: CombineImpact = { whenEntered: isMovingForward ? forward : backward, combine: { draggableId: target.descriptor.id, droppableId: destination.descriptor.id, }, }; const impact: DragImpact = { // grouping does not modify the existing displacement movement: previousImpact.movement, // grouping removes the destination destination: null, merge, }; return impact; };