@hello-pangea/dnd
Version:
Beautiful and accessible drag and drop for lists with React
99 lines (82 loc) • 2.23 kB
text/typescript
import {
addPlaceholder,
removePlaceholder,
} from './droppable/with-placeholder';
import whatIsDraggedOver from './droppable/what-is-dragged-over';
import type {
DroppableDimension,
DraggableDimensionMap,
DroppableDimensionMap,
DraggableDimension,
DragImpact,
DroppableId,
} from '../types';
import patchDroppableMap from './patch-droppable-map';
import isHomeOf from './droppable/is-home-of';
interface ClearArgs {
previousImpact: DragImpact;
impact: DragImpact;
droppables: DroppableDimensionMap;
}
const clearUnusedPlaceholder = ({
previousImpact,
impact,
droppables,
}: ClearArgs): DroppableDimensionMap => {
const last: DroppableId | null = whatIsDraggedOver(previousImpact);
const now: DroppableId | null = whatIsDraggedOver(impact);
if (!last) {
return droppables;
}
// no change - can keep the last state
if (last === now) {
return droppables;
}
const lastDroppable: DroppableDimension = droppables[last];
// nothing to clear
if (!lastDroppable.subject.withPlaceholder) {
return droppables;
}
const updated: DroppableDimension = removePlaceholder(lastDroppable);
return patchDroppableMap(droppables, updated);
};
interface Args {
draggable: DraggableDimension;
draggables: DraggableDimensionMap;
droppables: DroppableDimensionMap;
impact: DragImpact;
previousImpact: DragImpact;
}
export default ({
draggable,
draggables,
droppables,
previousImpact,
impact,
}: Args): DroppableDimensionMap => {
const cleaned: DroppableDimensionMap = clearUnusedPlaceholder({
previousImpact,
impact,
droppables,
});
const isOver: DroppableId | null = whatIsDraggedOver(impact);
if (!isOver) {
return cleaned;
}
const droppable: DroppableDimension = droppables[isOver];
// no need to add additional space to home droppable
if (isHomeOf(draggable, droppable)) {
return cleaned;
}
// already have a placeholder - nothing to do here!
if (droppable.subject.withPlaceholder) {
return cleaned;
}
// Need to patch the existing droppable
const patched: DroppableDimension = addPlaceholder(
droppable,
draggable,
draggables,
);
return patchDroppableMap(cleaned, patched);
};