@hello-pangea/dnd
Version:
Beautiful and accessible drag and drop for lists with React
67 lines (57 loc) • 2.07 kB
text/typescript
import { invariant } from '../../invariant';
import type { DimensionMarshal } from '../dimension-marshal/dimension-marshal-types';
import type { State, ScrollOptions, LiftRequest } from '../../types';
import type { Middleware } from '../store-types';
import {
completeDrop,
initialPublish,
flush,
beforeInitialCapture,
guard,
} from '../action-creators';
import validateDimensions from './util/validate-dimensions';
export default (marshal: DimensionMarshal): Middleware =>
({ getState, dispatch }) =>
(next) =>
(action) => {
if (!guard(action, 'LIFT')) {
next(action);
return;
}
const { id, clientSelection, movementMode } = action.payload;
const initial: State = getState();
// flush dropping animation if needed
// this can change the descriptor of the dragging item
// Will call the onDragEnd responders
if (initial.phase === 'DROP_ANIMATING') {
dispatch(completeDrop({ completed: initial.completed }));
}
invariant(getState().phase === 'IDLE', 'Unexpected phase to start a drag');
// Removing any placeholders before we capture any starting dimensions
dispatch(flush());
// Let consumers know we are just about to publish
// We are only publishing a small amount of information as
// things might change as a result of the onBeforeCapture callback
dispatch(beforeInitialCapture({ draggableId: id, movementMode }));
// will communicate with the marshal to start requesting dimensions
const scrollOptions: ScrollOptions = {
shouldPublishImmediately: movementMode === 'SNAP',
};
const request: LiftRequest = {
draggableId: id,
scrollOptions,
};
// Let's get the marshal started!
const { critical, dimensions, viewport } = marshal.startPublishing(request);
validateDimensions(critical, dimensions);
// Okay, we are good to start dragging now
dispatch(
initialPublish({
critical,
dimensions,
clientSelection,
movementMode,
viewport,
}),
);
};