UNPKG

react-beautiful-dnd

Version:

Beautiful, accessible drag and drop for lists with React.js

77 lines (66 loc) 2 kB
// @flow import memoizeOne from 'memoize-one'; import invariant from 'tiny-invariant'; import isPositionInFrame from '../visibility/is-position-in-frame'; import type { Position, DroppableId, DroppableDimension, DroppableDimensionMap, DraggableLocation, } from '../../types'; const getScrollableDroppables = memoizeOne( (droppables: DroppableDimensionMap): DroppableDimension[] => ( Object.keys(droppables) .map((id: DroppableId): DroppableDimension => droppables[id]) .filter((droppable: DroppableDimension): boolean => { // exclude disabled droppables if (!droppable.isEnabled) { return false; } // only want droppables that are scrollable if (!droppable.viewport.closestScrollable) { return false; } return true; }) ) ); const getScrollableDroppableOver = ( target: Position, droppables: DroppableDimensionMap ): ?DroppableDimension => { const maybe: ?DroppableDimension = getScrollableDroppables(droppables) .find((droppable: DroppableDimension): boolean => { invariant(droppable.viewport.closestScrollable, 'Invalid result'); return isPositionInFrame(droppable.viewport.closestScrollable.frame)(target); }); return maybe; }; type Api = {| center: Position, destination: ?DraggableLocation, droppables: DroppableDimensionMap, |} export default ({ center, destination, droppables, }: Api): ?DroppableDimension => { // We need to scroll the best droppable frame we can so that the // placeholder buffer logic works correctly if (destination) { const dimension: DroppableDimension = droppables[destination.droppableId]; if (!dimension.viewport.closestScrollable) { return null; } return dimension; } // 2. If we are not over a droppable - are we over a droppable frame? const dimension: ?DroppableDimension = getScrollableDroppableOver( center, droppables, ); return dimension; };