UNPKG

react-beautiful-dnd-next

Version:

Beautiful and accessible drag and drop for lists with React

132 lines (118 loc) 3.63 kB
// @flow import type { Position } from 'css-box-model'; import type { DraggableDimension, DraggingState, ClientPositions, PagePositions, DragPositions, DragImpact, Viewport, DimensionMap, UserDirection, StateWhenUpdatesAllowed, DroppableDimensionMap, } from '../../../types'; import getDragImpact from '../../get-drag-impact'; import { add, subtract } from '../../position'; import getUserDirection from '../../user-direction/get-user-direction'; import recomputePlaceholders from '../../recompute-placeholders'; type Args = {| state: StateWhenUpdatesAllowed, clientSelection?: Position, dimensions?: DimensionMap, viewport?: Viewport, // force a custom drag impact impact?: ?DragImpact, // provide a scroll jump request (optionally provided - and can be null) scrollJumpRequest?: ?Position, |}; export default ({ state, clientSelection: forcedClientSelection, dimensions: forcedDimensions, viewport: forcedViewport, impact: forcedImpact, scrollJumpRequest, }: Args): StateWhenUpdatesAllowed => { // DRAGGING: can update position and impact // COLLECTING: can update position but cannot update impact const viewport: Viewport = forcedViewport || state.viewport; const currentWindowScroll: Position = viewport.scroll.current; const dimensions: DimensionMap = forcedDimensions || state.dimensions; const clientSelection: Position = forcedClientSelection || state.current.client.selection; const offset: Position = subtract( clientSelection, state.initial.client.selection, ); const client: ClientPositions = { offset, selection: clientSelection, borderBoxCenter: add(state.initial.client.borderBoxCenter, offset), }; const page: PagePositions = { selection: add(client.selection, currentWindowScroll), borderBoxCenter: add(client.borderBoxCenter, currentWindowScroll), }; const current: DragPositions = { client, page, }; const userDirection: UserDirection = getUserDirection( state.userDirection, state.current.page.borderBoxCenter, current.page.borderBoxCenter, ); // Not updating impact while bulk collecting if (state.phase === 'COLLECTING') { return { // adding phase to appease flow (even though it will be overwritten by spread) phase: 'COLLECTING', ...state, dimensions, viewport, current, userDirection, }; } const draggable: DraggableDimension = dimensions.draggables[state.critical.draggable.id]; const newImpact: DragImpact = forcedImpact || getDragImpact({ pageBorderBoxCenter: page.borderBoxCenter, draggable, draggables: dimensions.draggables, droppables: dimensions.droppables, previousImpact: state.impact, viewport, userDirection, onLift: state.onLift, }); const withUpdatedPlaceholders: DroppableDimensionMap = recomputePlaceholders({ draggable, impact: newImpact, previousImpact: state.impact, draggables: dimensions.draggables, droppables: dimensions.droppables, }); // dragging! const result: DraggingState = { ...state, current, userDirection, dimensions: { draggables: dimensions.draggables, droppables: withUpdatedPlaceholders, }, impact: newImpact, viewport, scrollJumpRequest: scrollJumpRequest || null, // client updates can be applied as a part of a jump scroll // this can be to immediately reverse movement to allow for a nice animation // into the final position forceShouldAnimate: scrollJumpRequest ? false : null, }; return result; };