react-beautiful-dnd
Version:
Beautiful, accessible drag and drop for lists with React.js
1,855 lines (1,502 loc) • 180 kB
JavaScript
import _Object$keys from 'babel-runtime/core-js/object/keys';
import memoizeOne from 'memoize-one';
import _extends from 'babel-runtime/helpers/extends';
import invariant from 'tiny-invariant';
import _typeof from 'babel-runtime/helpers/typeof';
import { applyMiddleware, createStore, compose } from 'redux';
import thunk from 'redux-thunk';
import _Object$assign from 'babel-runtime/core-js/object/assign';
import rafSchd from 'raf-schd';
import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
import _inherits from 'babel-runtime/helpers/inherits';
import React, { Component, PureComponent, Fragment } from 'react';
import PropTypes from 'prop-types';
import { createSelector } from 'reselect';
import { connect } from 'react-redux';
import { Motion, spring } from 'react-motion';
var add = function add(point1, point2) {
return {
x: point1.x + point2.x,
y: point1.y + point2.y
};
};
var subtract = function subtract(point1, point2) {
return {
x: point1.x - point2.x,
y: point1.y - point2.y
};
};
var isEqual = function isEqual(point1, point2) {
return point1.x === point2.x && point1.y === point2.y;
};
var negate = function negate(point) {
return {
x: point.x !== 0 ? -point.x : 0,
y: point.y !== 0 ? -point.y : 0
};
};
var absolute = function absolute(point) {
return {
x: Math.abs(point.x),
y: Math.abs(point.y)
};
};
var patch = function patch(line, value) {
var _ref;
var otherValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
return _ref = {}, _ref[line] = value, _ref[line === 'x' ? 'y' : 'x'] = otherValue, _ref;
};
var distance = function distance(point1, point2) {
return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2));
};
var closest = function closest(target, points) {
return Math.min.apply(Math, points.map(function (point) {
return distance(target, point);
}));
};
var apply = function apply(fn) {
return function (point) {
return {
x: fn(point.x),
y: fn(point.y)
};
};
};
var origin = { x: 0, y: 0 };
var noMovement = {
displaced: [],
amount: origin,
isBeyondStartPosition: false
};
var noImpact = {
movement: noMovement,
direction: null,
destination: null
};
var getArea = (function (_ref) {
var top = _ref.top,
right = _ref.right,
bottom = _ref.bottom,
left = _ref.left;
return {
top: top,
right: right,
bottom: bottom,
left: left,
width: right - left,
height: bottom - top,
center: {
x: (right + left) / 2,
y: (bottom + top) / 2
}
};
});
var getDraggablesInsideDroppable = memoizeOne(function (droppable, draggables) {
return _Object$keys(draggables).map(function (id) {
return draggables[id];
}).filter(function (draggable) {
return droppable.descriptor.id === draggable.descriptor.droppableId;
}).sort(function (a, b) {
return a.descriptor.index - b.descriptor.index;
});
});
var isWithin = (function (lowerBound, upperBound) {
return function (value) {
return value <= upperBound && value >= lowerBound;
};
});
var isPositionInFrame = (function (frame) {
var isWithinVertical = isWithin(frame.top, frame.bottom);
var isWithinHorizontal = isWithin(frame.left, frame.right);
return function (point) {
return isWithinVertical(point.y) && isWithinVertical(point.y) && isWithinHorizontal(point.x) && isWithinHorizontal(point.x);
};
});
var offsetByPosition = function offsetByPosition(spacing, point) {
return {
top: spacing.top + point.y,
left: spacing.left + point.x,
bottom: spacing.bottom + point.y,
right: spacing.right + point.x
};
};
var expandByPosition = function expandByPosition(spacing, position) {
return {
top: spacing.top - position.y,
left: spacing.left - position.x,
right: spacing.right + position.x,
bottom: spacing.bottom + position.y
};
};
var expandBySpacing = function expandBySpacing(spacing1, spacing2) {
return {
top: spacing1.top - spacing2.top,
left: spacing1.left - spacing2.left,
bottom: spacing1.bottom + spacing2.bottom,
right: spacing1.right + spacing2.right
};
};
var shrinkBySpacing = function shrinkBySpacing(spacing1, spacing2) {
return {
top: spacing1.top + spacing2.top,
left: spacing1.left + spacing2.left,
bottom: spacing1.bottom - spacing2.bottom,
right: spacing1.right - spacing2.right
};
};
var getCorners = function getCorners(spacing) {
return [{ x: spacing.left, y: spacing.top }, { x: spacing.right, y: spacing.top }, { x: spacing.left, y: spacing.bottom }, { x: spacing.right, y: spacing.bottom }];
};
var vertical = {
direction: 'vertical',
line: 'y',
crossAxisLine: 'x',
start: 'top',
end: 'bottom',
size: 'height',
crossAxisStart: 'left',
crossAxisEnd: 'right',
crossAxisSize: 'width'
};
var horizontal = {
direction: 'horizontal',
line: 'x',
crossAxisLine: 'y',
start: 'left',
end: 'right',
size: 'width',
crossAxisStart: 'top',
crossAxisEnd: 'bottom',
crossAxisSize: 'height'
};
var getMaxScroll = (function (_ref) {
var scrollHeight = _ref.scrollHeight,
scrollWidth = _ref.scrollWidth,
height = _ref.height,
width = _ref.width;
var maxScroll = subtract({ x: scrollWidth, y: scrollHeight }, { x: width, y: height });
var adjustedMaxScroll = {
x: Math.max(0, maxScroll.x),
y: Math.max(0, maxScroll.y)
};
return adjustedMaxScroll;
});
var origin$1 = { x: 0, y: 0 };
var noSpacing = {
top: 0,
right: 0,
bottom: 0,
left: 0
};
var getDraggableDimension = function getDraggableDimension(_ref) {
var descriptor = _ref.descriptor,
borderBox = _ref.borderBox,
_ref$tagName = _ref.tagName,
tagName = _ref$tagName === undefined ? 'div' : _ref$tagName,
_ref$display = _ref.display,
display = _ref$display === undefined ? 'block' : _ref$display,
_ref$margin = _ref.margin,
margin = _ref$margin === undefined ? noSpacing : _ref$margin,
_ref$windowScroll = _ref.windowScroll,
windowScroll = _ref$windowScroll === undefined ? origin$1 : _ref$windowScroll;
var pageBorderBox = offsetByPosition(borderBox, windowScroll);
var dimension = {
descriptor: descriptor,
placeholder: {
borderBox: borderBox,
margin: margin,
tagName: tagName,
display: display
},
client: {
borderBox: borderBox,
marginBox: getArea(expandBySpacing(borderBox, margin))
},
page: {
borderBox: getArea(pageBorderBox),
marginBox: getArea(expandBySpacing(pageBorderBox, margin))
}
};
return dimension;
};
var clip = function clip(frame, subject) {
var result = getArea({
top: Math.max(subject.top, frame.top),
right: Math.min(subject.right, frame.right),
bottom: Math.min(subject.bottom, frame.bottom),
left: Math.max(subject.left, frame.left)
});
if (result.width <= 0 || result.height <= 0) {
return null;
}
return result;
};
var scrollDroppable = function scrollDroppable(droppable, newScroll) {
if (!droppable.viewport.closestScrollable) {
console.error('Cannot scroll droppble that does not have a closest scrollable');
return droppable;
}
var existingScrollable = droppable.viewport.closestScrollable;
var frame = existingScrollable.frame;
var scrollDiff = subtract(newScroll, existingScrollable.scroll.initial);
var scrollDisplacement = negate(scrollDiff);
var closestScrollable = {
frame: existingScrollable.frame,
shouldClipSubject: existingScrollable.shouldClipSubject,
scroll: {
initial: existingScrollable.scroll.initial,
current: newScroll,
diff: {
value: scrollDiff,
displacement: scrollDisplacement
},
max: existingScrollable.scroll.max
}
};
var displacedSubject = offsetByPosition(droppable.viewport.subject, scrollDisplacement);
var clipped = closestScrollable.shouldClipSubject ? clip(frame, displacedSubject) : getArea(displacedSubject);
var viewport = {
closestScrollable: closestScrollable,
subject: droppable.viewport.subject,
clipped: clipped
};
var result = _extends({}, droppable, {
viewport: viewport
});
return result;
};
var getDroppableDimension = function getDroppableDimension(_ref2) {
var descriptor = _ref2.descriptor,
borderBox = _ref2.borderBox,
closest$$1 = _ref2.closest,
_ref2$direction = _ref2.direction,
direction = _ref2$direction === undefined ? 'vertical' : _ref2$direction,
_ref2$margin = _ref2.margin,
margin = _ref2$margin === undefined ? noSpacing : _ref2$margin,
_ref2$padding = _ref2.padding,
padding = _ref2$padding === undefined ? noSpacing : _ref2$padding,
_ref2$border = _ref2.border,
border = _ref2$border === undefined ? noSpacing : _ref2$border,
_ref2$windowScroll = _ref2.windowScroll,
windowScroll = _ref2$windowScroll === undefined ? origin$1 : _ref2$windowScroll,
_ref2$isEnabled = _ref2.isEnabled,
isEnabled = _ref2$isEnabled === undefined ? true : _ref2$isEnabled;
var marginBox = getArea(expandBySpacing(borderBox, margin));
var paddingBox = getArea(shrinkBySpacing(borderBox, border));
var contentBox = getArea(shrinkBySpacing(paddingBox, padding));
var client = {
borderBox: borderBox,
marginBox: marginBox,
contentBox: contentBox
};
var page = {
marginBox: getArea(offsetByPosition(marginBox, windowScroll)),
borderBox: getArea(offsetByPosition(borderBox, windowScroll)),
contentBox: getArea(offsetByPosition(contentBox, windowScroll))
};
var subject = page.marginBox;
var closestScrollable = function () {
if (!closest$$1) {
return null;
}
var frame = getArea(offsetByPosition(closest$$1.frameBorderBox, windowScroll));
var maxScroll = getMaxScroll({
scrollHeight: closest$$1.scrollHeight,
scrollWidth: closest$$1.scrollWidth,
height: frame.height,
width: frame.width
});
var result = {
frame: frame,
shouldClipSubject: closest$$1.shouldClipSubject,
scroll: {
initial: closest$$1.scroll,
current: closest$$1.scroll,
max: maxScroll,
diff: {
value: origin$1,
displacement: origin$1
}
}
};
return result;
}();
var clipped = closestScrollable && closestScrollable.shouldClipSubject ? clip(closestScrollable.frame, subject) : subject;
var viewport = {
closestScrollable: closestScrollable,
subject: subject,
clipped: clipped
};
var dimension = {
descriptor: descriptor,
isEnabled: isEnabled,
axis: direction === 'vertical' ? vertical : horizontal,
client: client,
page: page,
viewport: viewport
};
return dimension;
};
var getRequiredGrowth = memoizeOne(function (draggable, draggables, droppable) {
var getResult = function getResult(existingSpace) {
var requiredSpace = draggable.page.marginBox[droppable.axis.size];
if (requiredSpace <= existingSpace) {
return null;
}
var requiredGrowth = patch(droppable.axis.line, requiredSpace - existingSpace);
return requiredGrowth;
};
var dimensions = getDraggablesInsideDroppable(droppable, draggables);
if (!dimensions.length) {
var _existingSpace = droppable.page.marginBox[droppable.axis.size];
return getResult(_existingSpace);
}
var endOfDraggables = dimensions[dimensions.length - 1].page.marginBox[droppable.axis.end];
var endOfDroppable = droppable.page.marginBox[droppable.axis.end];
var existingSpace = endOfDroppable - endOfDraggables;
return getResult(existingSpace);
});
var getWithGrowth = memoizeOne(function (area, growth) {
return getArea(expandByPosition(area, growth));
});
var getClippedAreaWithPlaceholder = function getClippedAreaWithPlaceholder(_ref) {
var draggable = _ref.draggable,
draggables = _ref.draggables,
droppable = _ref.droppable,
previousDroppableOverId = _ref.previousDroppableOverId;
var isHome = draggable.descriptor.droppableId === droppable.descriptor.id;
var wasOver = Boolean(previousDroppableOverId && previousDroppableOverId === droppable.descriptor.id);
var clipped = droppable.viewport.clipped;
if (!clipped) {
return clipped;
}
if (isHome || !wasOver) {
return clipped;
}
var requiredGrowth = getRequiredGrowth(draggable, draggables, droppable);
if (!requiredGrowth) {
return clipped;
}
var subjectWithGrowth = getWithGrowth(clipped, requiredGrowth);
var closestScrollable = droppable.viewport.closestScrollable;
if (!closestScrollable) {
return subjectWithGrowth;
}
if (!closestScrollable.shouldClipSubject) {
return subjectWithGrowth;
}
return clip(closestScrollable.frame, subjectWithGrowth);
};
var getDroppableOver = (function (_ref2) {
var target = _ref2.target,
draggable = _ref2.draggable,
draggables = _ref2.draggables,
droppables = _ref2.droppables,
previousDroppableOverId = _ref2.previousDroppableOverId;
var maybe = _Object$keys(droppables).map(function (id) {
return droppables[id];
}).filter(function (droppable) {
return droppable.isEnabled;
}).find(function (droppable) {
var withPlaceholder = getClippedAreaWithPlaceholder({
draggable: draggable, draggables: draggables, droppable: droppable, previousDroppableOverId: previousDroppableOverId
});
if (!withPlaceholder) {
return false;
}
return isPositionInFrame(withPlaceholder)(target);
});
return maybe ? maybe.descriptor.id : null;
});
var getDisplacementMap = memoizeOne(function (displaced) {
return displaced.reduce(function (map, displacement) {
map[displacement.draggableId] = displacement;
return map;
}, {});
});
var isPartiallyVisibleThroughFrame = (function (frame) {
var isWithinVertical = isWithin(frame.top, frame.bottom);
var isWithinHorizontal = isWithin(frame.left, frame.right);
return function (subject) {
var isContained = isWithinVertical(subject.top) && isWithinVertical(subject.bottom) && isWithinHorizontal(subject.left) && isWithinHorizontal(subject.right);
if (isContained) {
return true;
}
var isPartiallyVisibleVertically = isWithinVertical(subject.top) || isWithinVertical(subject.bottom);
var isPartiallyVisibleHorizontally = isWithinHorizontal(subject.left) || isWithinHorizontal(subject.right);
var isPartiallyContained = isPartiallyVisibleVertically && isPartiallyVisibleHorizontally;
if (isPartiallyContained) {
return true;
}
var isBiggerVertically = subject.top < frame.top && subject.bottom > frame.bottom;
var isBiggerHorizontally = subject.left < frame.left && subject.right > frame.right;
var isTargetBiggerThanFrame = isBiggerVertically && isBiggerHorizontally;
if (isTargetBiggerThanFrame) {
return true;
}
var isTargetBiggerOnOneAxis = isBiggerVertically && isPartiallyVisibleHorizontally || isBiggerHorizontally && isPartiallyVisibleVertically;
return isTargetBiggerOnOneAxis;
};
});
var isTotallyVisibleThroughFrame = (function (frame) {
var isWithinVertical = isWithin(frame.top, frame.bottom);
var isWithinHorizontal = isWithin(frame.left, frame.right);
return function (subject) {
var isContained = isWithinVertical(subject.top) && isWithinVertical(subject.bottom) && isWithinHorizontal(subject.left) && isWithinHorizontal(subject.right);
return isContained;
};
});
var origin$2 = { x: 0, y: 0 };
var isVisible = function isVisible(_ref) {
var target = _ref.target,
destination = _ref.destination,
viewport = _ref.viewport,
isVisibleThroughFrameFn = _ref.isVisibleThroughFrameFn;
var displacement = destination.viewport.closestScrollable ? destination.viewport.closestScrollable.scroll.diff.displacement : origin$2;
var withDisplacement = offsetByPosition(target, displacement);
if (!destination.viewport.clipped) {
return false;
}
var isVisibleInDroppable = isVisibleThroughFrameFn(destination.viewport.clipped)(withDisplacement);
var isVisibleInViewport = isVisibleThroughFrameFn(viewport)(withDisplacement);
return isVisibleInDroppable && isVisibleInViewport;
};
var isPartiallyVisible = function isPartiallyVisible(_ref2) {
var target = _ref2.target,
destination = _ref2.destination,
viewport = _ref2.viewport;
return isVisible({
target: target,
destination: destination,
viewport: viewport,
isVisibleThroughFrameFn: isPartiallyVisibleThroughFrame
});
};
var isTotallyVisible = function isTotallyVisible(_ref3) {
var target = _ref3.target,
destination = _ref3.destination,
viewport = _ref3.viewport;
return isVisible({
target: target,
destination: destination,
viewport: viewport,
isVisibleThroughFrameFn: isTotallyVisibleThroughFrame
});
};
var getDisplacement = (function (_ref) {
var draggable = _ref.draggable,
destination = _ref.destination,
previousImpact = _ref.previousImpact,
viewport = _ref.viewport;
var id = draggable.descriptor.id;
var map = getDisplacementMap(previousImpact.movement.displaced);
var isVisible = isPartiallyVisible({
target: draggable.page.marginBox,
destination: destination,
viewport: viewport
});
var shouldAnimate = function () {
if (!isVisible) {
return false;
}
var previous = map[id];
if (!previous) {
return true;
}
return previous.shouldAnimate;
}();
var displacement = {
draggableId: id,
isVisible: isVisible,
shouldAnimate: shouldAnimate
};
return displacement;
});
var withDroppableScroll = (function (droppable, point) {
var closestScrollable = droppable.viewport.closestScrollable;
if (!closestScrollable) {
return point;
}
return add(point, closestScrollable.scroll.diff.value);
});
var inHomeList = (function (_ref) {
var pageCenter = _ref.pageCenter,
draggable = _ref.draggable,
home = _ref.home,
insideHome = _ref.insideHome,
previousImpact = _ref.previousImpact,
viewport = _ref.viewport;
var axis = home.axis;
var originalCenter = draggable.page.borderBox.center;
var currentCenter = withDroppableScroll(home, pageCenter);
var isBeyondStartPosition = currentCenter[axis.line] - originalCenter[axis.line] > 0;
var amount = patch(axis.line, draggable.client.marginBox[axis.size]);
var displaced = insideHome.filter(function (child) {
if (child === draggable) {
return false;
}
var area = child.page.borderBox;
if (isBeyondStartPosition) {
if (area.center[axis.line] < originalCenter[axis.line]) {
return false;
}
return currentCenter[axis.line] > area[axis.start];
}
if (originalCenter[axis.line] < area.center[axis.line]) {
return false;
}
return currentCenter[axis.line] < area[axis.end];
}).map(function (dimension) {
return getDisplacement({
draggable: dimension,
destination: home,
previousImpact: previousImpact,
viewport: viewport.subject
});
});
var ordered = isBeyondStartPosition ? displaced.reverse() : displaced;
var index = function () {
var startIndex = insideHome.indexOf(draggable);
var length = ordered.length;
if (!length) {
return startIndex;
}
if (isBeyondStartPosition) {
return startIndex + length;
}
return startIndex - length;
}();
var movement = {
amount: amount,
displaced: ordered,
isBeyondStartPosition: isBeyondStartPosition
};
var impact = {
movement: movement,
direction: axis.direction,
destination: {
droppableId: home.descriptor.id,
index: index
}
};
return impact;
});
var inForeignList = (function (_ref) {
var pageCenter = _ref.pageCenter,
draggable = _ref.draggable,
destination = _ref.destination,
insideDestination = _ref.insideDestination,
previousImpact = _ref.previousImpact,
viewport = _ref.viewport;
var axis = destination.axis;
var currentCenter = withDroppableScroll(destination, pageCenter);
var displaced = insideDestination.filter(function (child) {
var threshold = child.page.borderBox[axis.end];
return threshold > currentCenter[axis.line];
}).map(function (dimension) {
return getDisplacement({
draggable: dimension,
destination: destination,
previousImpact: previousImpact,
viewport: viewport.subject
});
});
var newIndex = insideDestination.length - displaced.length;
var movement = {
amount: patch(axis.line, draggable.page.marginBox[axis.size]),
displaced: displaced,
isBeyondStartPosition: false
};
var impact = {
movement: movement,
direction: axis.direction,
destination: {
droppableId: destination.descriptor.id,
index: newIndex
}
};
return impact;
});
var getDragImpact = (function (_ref) {
var pageCenter = _ref.pageCenter,
draggable = _ref.draggable,
draggables = _ref.draggables,
droppables = _ref.droppables,
previousImpact = _ref.previousImpact,
viewport = _ref.viewport;
var previousDroppableOverId = previousImpact.destination && previousImpact.destination.droppableId;
var destinationId = getDroppableOver({
target: pageCenter,
draggable: draggable,
draggables: draggables,
droppables: droppables,
previousDroppableOverId: previousDroppableOverId
});
if (!destinationId) {
return noImpact;
}
var destination = droppables[destinationId];
if (!destination.isEnabled) {
return noImpact;
}
var home = droppables[draggable.descriptor.droppableId];
var isWithinHomeDroppable = home.descriptor.id === destinationId;
var insideDestination = getDraggablesInsideDroppable(destination, draggables);
if (isWithinHomeDroppable) {
return inHomeList({
pageCenter: pageCenter,
draggable: draggable,
home: home,
insideHome: insideDestination,
previousImpact: previousImpact || noImpact,
viewport: viewport
});
}
return inForeignList({
pageCenter: pageCenter,
draggable: draggable,
destination: destination,
insideDestination: insideDestination,
previousImpact: previousImpact || noImpact,
viewport: viewport
});
});
var withDroppableDisplacement = (function (droppable, point) {
var closestScrollable = droppable.viewport.closestScrollable;
if (!closestScrollable) {
return point;
}
return add(point, closestScrollable.scroll.diff.displacement);
});
var isTotallyVisibleInNewLocation = (function (_ref) {
var draggable = _ref.draggable,
destination = _ref.destination,
newPageCenter = _ref.newPageCenter,
viewport = _ref.viewport;
var diff = subtract(newPageCenter, draggable.page.borderBox.center);
var shifted = offsetByPosition(draggable.page.borderBox, diff);
return isTotallyVisible({
target: shifted,
destination: destination,
viewport: viewport
});
});
var moveToEdge = (function (_ref) {
var source = _ref.source,
sourceEdge = _ref.sourceEdge,
destination = _ref.destination,
destinationEdge = _ref.destinationEdge,
destinationAxis = _ref.destinationAxis;
var getCorner = function getCorner(area) {
return patch(destinationAxis.line, area[destinationAxis[destinationEdge]], area[destinationAxis.crossAxisStart]);
};
var corner = getCorner(destination);
var centerDiff = absolute(subtract(source.center, getCorner(source)));
var signed = patch(destinationAxis.line, (sourceEdge === 'end' ? -1 : 1) * centerDiff[destinationAxis.line], centerDiff[destinationAxis.crossAxisLine]);
return add(corner, signed);
});
var withFirstAdded = function withFirstAdded(_ref) {
var add = _ref.add,
previousImpact = _ref.previousImpact,
droppable = _ref.droppable,
draggables = _ref.draggables,
viewport = _ref.viewport;
var newDisplacement = {
draggableId: add,
isVisible: true,
shouldAnimate: true
};
var added = [newDisplacement].concat(previousImpact.movement.displaced);
var withUpdatedVisibility = added.map(function (current) {
if (current === newDisplacement) {
return current;
}
var updated = getDisplacement({
draggable: draggables[current.draggableId],
destination: droppable,
previousImpact: previousImpact,
viewport: viewport.subject
});
return updated;
});
return withUpdatedVisibility;
};
var forceVisibleDisplacement = function forceVisibleDisplacement(current) {
if (current.isVisible) {
return current;
}
return {
draggableId: current.draggableId,
isVisible: true,
shouldAnimate: false
};
};
var withFirstRemoved = function withFirstRemoved(_ref2) {
var dragging = _ref2.dragging,
isVisibleInNewLocation = _ref2.isVisibleInNewLocation,
previousImpact = _ref2.previousImpact,
droppable = _ref2.droppable,
draggables = _ref2.draggables;
var last = previousImpact.movement.displaced;
if (!last.length) {
console.error('cannot remove displacement from empty list');
return [];
}
var withFirstRestored = last.slice(1, last.length);
if (!withFirstRestored.length) {
return withFirstRestored;
}
if (isVisibleInNewLocation) {
return withFirstRestored;
}
var axis = droppable.axis;
var sizeOfRestored = draggables[last[0].draggableId].page.marginBox[axis.size];
var sizeOfDragging = draggables[dragging].page.marginBox[axis.size];
var buffer = sizeOfRestored + sizeOfDragging;
var withUpdatedVisibility = withFirstRestored.map(function (displacement, index) {
if (index === 0) {
return forceVisibleDisplacement(displacement);
}
if (buffer > 0) {
var current = draggables[displacement.draggableId];
var size = current.page.marginBox[axis.size];
buffer -= size;
return forceVisibleDisplacement(displacement);
}
return {
draggableId: displacement.draggableId,
isVisible: false,
shouldAnimate: false
};
});
return withUpdatedVisibility;
};
var inHomeList$1 = (function (_ref) {
var isMovingForward = _ref.isMovingForward,
draggableId = _ref.draggableId,
previousPageCenter = _ref.previousPageCenter,
previousImpact = _ref.previousImpact,
droppable = _ref.droppable,
draggables = _ref.draggables,
viewport = _ref.viewport;
var location = previousImpact.destination;
if (!location) {
console.error('cannot move to next index when there is not previous destination');
return null;
}
var draggable = draggables[draggableId];
var axis = droppable.axis;
var insideDroppable = getDraggablesInsideDroppable(droppable, draggables);
var startIndex = draggable.descriptor.index;
var currentIndex = location.index;
var proposedIndex = isMovingForward ? currentIndex + 1 : currentIndex - 1;
if (startIndex === -1) {
console.error('could not find draggable inside current droppable');
return null;
}
if (proposedIndex > insideDroppable.length - 1) {
return null;
}
if (proposedIndex < 0) {
return null;
}
var destination = insideDroppable[proposedIndex];
var isMovingTowardStart = isMovingForward && proposedIndex <= startIndex || !isMovingForward && proposedIndex >= startIndex;
var edge = function () {
if (!isMovingTowardStart) {
return isMovingForward ? 'end' : 'start';
}
return isMovingForward ? 'start' : 'end';
}();
var newPageCenter = moveToEdge({
source: draggable.page.borderBox,
sourceEdge: edge,
destination: destination.page.borderBox,
destinationEdge: edge,
destinationAxis: droppable.axis
});
var isVisibleInNewLocation = isTotallyVisibleInNewLocation({
draggable: draggable,
destination: droppable,
newPageCenter: newPageCenter,
viewport: viewport.subject
});
var displaced = function () {
if (isMovingTowardStart) {
return withFirstRemoved({
dragging: draggableId,
isVisibleInNewLocation: isVisibleInNewLocation,
previousImpact: previousImpact,
droppable: droppable,
draggables: draggables
});
}
return withFirstAdded({
add: destination.descriptor.id,
previousImpact: previousImpact,
droppable: droppable,
draggables: draggables,
viewport: viewport
});
}();
var newImpact = {
movement: {
displaced: displaced,
amount: patch(axis.line, draggable.page.marginBox[axis.size]),
isBeyondStartPosition: proposedIndex > startIndex
},
destination: {
droppableId: droppable.descriptor.id,
index: proposedIndex
},
direction: droppable.axis.direction
};
if (isVisibleInNewLocation) {
return {
pageCenter: withDroppableDisplacement(droppable, newPageCenter),
impact: newImpact,
scrollJumpRequest: null
};
}
var distance$$1 = subtract(newPageCenter, previousPageCenter);
var distanceWithScroll = withDroppableDisplacement(droppable, distance$$1);
return {
pageCenter: previousPageCenter,
impact: newImpact,
scrollJumpRequest: distanceWithScroll
};
});
var inForeignList$1 = (function (_ref) {
var isMovingForward = _ref.isMovingForward,
draggableId = _ref.draggableId,
previousImpact = _ref.previousImpact,
previousPageCenter = _ref.previousPageCenter,
droppable = _ref.droppable,
draggables = _ref.draggables,
viewport = _ref.viewport;
if (!previousImpact.destination) {
console.error('cannot move to next index when there is not previous destination');
return null;
}
var location = previousImpact.destination;
var draggable = draggables[draggableId];
var axis = droppable.axis;
var insideForeignDroppable = getDraggablesInsideDroppable(droppable, draggables);
var currentIndex = location.index;
var proposedIndex = isMovingForward ? currentIndex + 1 : currentIndex - 1;
var lastIndex = insideForeignDroppable.length - 1;
if (proposedIndex > insideForeignDroppable.length) {
return null;
}
if (proposedIndex < 0) {
return null;
}
var movingRelativeTo = insideForeignDroppable[Math.min(proposedIndex, lastIndex)];
var isMovingPastLastIndex = proposedIndex > lastIndex;
var sourceEdge = 'start';
var destinationEdge = function () {
if (isMovingPastLastIndex) {
return 'end';
}
return 'start';
}();
var newPageCenter = moveToEdge({
source: draggable.page.borderBox,
sourceEdge: sourceEdge,
destination: movingRelativeTo.page.marginBox,
destinationEdge: destinationEdge,
destinationAxis: droppable.axis
});
var isVisibleInNewLocation = isTotallyVisibleInNewLocation({
draggable: draggable,
destination: droppable,
newPageCenter: newPageCenter,
viewport: viewport.subject
});
var displaced = function () {
if (isMovingForward) {
return withFirstRemoved({
dragging: draggableId,
isVisibleInNewLocation: isVisibleInNewLocation,
previousImpact: previousImpact,
droppable: droppable,
draggables: draggables
});
}
return withFirstAdded({
add: movingRelativeTo.descriptor.id,
previousImpact: previousImpact,
droppable: droppable,
draggables: draggables,
viewport: viewport
});
}();
var newImpact = {
movement: {
displaced: displaced,
amount: patch(axis.line, draggable.page.marginBox[axis.size]),
isBeyondStartPosition: false
},
destination: {
droppableId: droppable.descriptor.id,
index: proposedIndex
},
direction: droppable.axis.direction
};
if (isVisibleInNewLocation) {
return {
pageCenter: withDroppableDisplacement(droppable, newPageCenter),
impact: newImpact,
scrollJumpRequest: null
};
}
var distanceMoving = subtract(newPageCenter, previousPageCenter);
var distanceWithScroll = withDroppableDisplacement(droppable, distanceMoving);
return {
pageCenter: previousPageCenter,
impact: newImpact,
scrollJumpRequest: distanceWithScroll
};
});
var moveToNextIndex = (function (args) {
var draggableId = args.draggableId,
draggables = args.draggables,
droppable = args.droppable;
var draggable = draggables[draggableId];
var isInHomeList = draggable.descriptor.droppableId === droppable.descriptor.id;
if (!droppable.isEnabled) {
return null;
}
if (isInHomeList) {
return inHomeList$1(args);
}
return inForeignList$1(args);
});
var getSafeClipped = function getSafeClipped(droppable) {
var area = droppable.viewport.clipped;
invariant(area, 'Cannot get clipped area from droppable');
return area;
};
var getBestCrossAxisDroppable = (function (_ref) {
var isMovingForward = _ref.isMovingForward,
pageCenter = _ref.pageCenter,
source = _ref.source,
droppables = _ref.droppables,
viewport = _ref.viewport;
var sourceClipped = source.viewport.clipped;
if (!sourceClipped) {
return null;
}
var axis = source.axis;
var isBetweenSourceClipped = isWithin(sourceClipped[axis.start], sourceClipped[axis.end]);
var candidates = _Object$keys(droppables).map(function (id) {
return droppables[id];
}).filter(function (droppable) {
return droppable !== source;
}).filter(function (droppable) {
return droppable.isEnabled;
}).filter(function (droppable) {
var clipped = droppable.viewport.clipped;
if (!clipped) {
return false;
}
return isPartiallyVisibleThroughFrame(viewport.subject)(clipped);
}).filter(function (droppable) {
var targetClipped = getSafeClipped(droppable);
if (isMovingForward) {
return sourceClipped[axis.crossAxisEnd] <= targetClipped[axis.crossAxisStart];
}
return targetClipped[axis.crossAxisEnd] <= sourceClipped[axis.crossAxisStart];
}).filter(function (droppable) {
var targetClipped = getSafeClipped(droppable);
var isBetweenDestinationClipped = isWithin(targetClipped[axis.start], targetClipped[axis.end]);
return isBetweenSourceClipped(targetClipped[axis.start]) || isBetweenSourceClipped(targetClipped[axis.end]) || isBetweenDestinationClipped(sourceClipped[axis.start]) || isBetweenDestinationClipped(sourceClipped[axis.end]);
}).sort(function (a, b) {
var first = getSafeClipped(a)[axis.crossAxisStart];
var second = getSafeClipped(b)[axis.crossAxisStart];
if (isMovingForward) {
return first - second;
}
return second - first;
}).filter(function (droppable, index, array) {
return getSafeClipped(droppable)[axis.crossAxisStart] === getSafeClipped(array[0])[axis.crossAxisStart];
});
if (!candidates.length) {
return null;
}
if (candidates.length === 1) {
return candidates[0];
}
var contains = candidates.filter(function (droppable) {
var isWithinDroppable = isWithin(getSafeClipped(droppable)[axis.start], getSafeClipped(droppable)[axis.end]);
return isWithinDroppable(pageCenter[axis.line]);
});
if (contains.length === 1) {
return contains[0];
}
if (contains.length > 1) {
return contains.sort(function (a, b) {
return getSafeClipped(a)[axis.start] - getSafeClipped(b)[axis.start];
})[0];
}
return candidates.sort(function (a, b) {
var first = closest(pageCenter, getCorners(getSafeClipped(a)));
var second = closest(pageCenter, getCorners(getSafeClipped(b)));
if (first !== second) {
return first - second;
}
return getSafeClipped(a)[axis.start] - getSafeClipped(b)[axis.start];
})[0];
});
var getClosestDraggable = (function (_ref) {
var axis = _ref.axis,
viewport = _ref.viewport,
pageCenter = _ref.pageCenter,
destination = _ref.destination,
insideDestination = _ref.insideDestination;
if (!insideDestination.length) {
return null;
}
var result = insideDestination.filter(function (draggable) {
return isTotallyVisible({
target: draggable.page.marginBox,
destination: destination,
viewport: viewport.subject
});
}).sort(function (a, b) {
var distanceToA = distance(pageCenter, withDroppableDisplacement(destination, a.page.marginBox.center));
var distanceToB = distance(pageCenter, withDroppableDisplacement(destination, b.page.marginBox.center));
if (distanceToA < distanceToB) {
return -1;
}
if (distanceToB < distanceToA) {
return 1;
}
return a.page.marginBox[axis.start] - b.page.marginBox[axis.start];
});
return result.length ? result[0] : null;
});
var toHomeList = (function (_ref) {
var amount = _ref.amount,
originalIndex = _ref.originalIndex,
target = _ref.target,
insideDroppable = _ref.insideDroppable,
draggable = _ref.draggable,
droppable = _ref.droppable,
previousImpact = _ref.previousImpact,
viewport = _ref.viewport;
if (!target) {
console.error('there will always be a target in the original list');
return null;
}
var axis = droppable.axis;
var targetIndex = insideDroppable.indexOf(target);
if (targetIndex === -1) {
console.error('unable to find target in destination droppable');
return null;
}
if (targetIndex === originalIndex) {
var _newCenter = draggable.page.borderBox.center;
var _newImpact = {
movement: {
displaced: [],
amount: amount,
isBeyondStartPosition: false
},
direction: droppable.axis.direction,
destination: {
droppableId: droppable.descriptor.id,
index: originalIndex
}
};
return {
pageCenter: withDroppableDisplacement(droppable, _newCenter),
impact: _newImpact
};
}
var isMovingPastOriginalIndex = targetIndex > originalIndex;
var edge = isMovingPastOriginalIndex ? 'end' : 'start';
var newCenter = moveToEdge({
source: draggable.page.borderBox,
sourceEdge: edge,
destination: isMovingPastOriginalIndex ? target.page.borderBox : target.page.marginBox,
destinationEdge: edge,
destinationAxis: axis
});
var modified = function () {
if (!isMovingPastOriginalIndex) {
return insideDroppable.slice(targetIndex, originalIndex);
}
var from = originalIndex + 1;
var to = targetIndex + 1;
return insideDroppable.slice(from, to).reverse();
}();
var displaced = modified.map(function (dimension) {
return getDisplacement({
draggable: dimension,
destination: droppable,
previousImpact: previousImpact,
viewport: viewport.subject
});
});
var newImpact = {
movement: {
displaced: displaced,
amount: amount,
isBeyondStartPosition: isMovingPastOriginalIndex
},
direction: axis.direction,
destination: {
droppableId: droppable.descriptor.id,
index: targetIndex
}
};
return {
pageCenter: withDroppableDisplacement(droppable, newCenter),
impact: newImpact
};
});
var toForeignList = (function (_ref) {
var amount = _ref.amount,
pageCenter = _ref.pageCenter,
target = _ref.target,
insideDroppable = _ref.insideDroppable,
draggable = _ref.draggable,
droppable = _ref.droppable,
previousImpact = _ref.previousImpact,
viewport = _ref.viewport;
var axis = droppable.axis;
var isGoingBeforeTarget = Boolean(target && pageCenter[droppable.axis.line] < target.page.marginBox.center[droppable.axis.line]);
if (!target) {
var _newCenter = moveToEdge({
source: draggable.page.borderBox,
sourceEdge: 'start',
destination: droppable.page.contentBox,
destinationEdge: 'start',
destinationAxis: axis
});
var _newImpact = {
movement: {
displaced: [],
amount: amount,
isBeyondStartPosition: false
},
direction: axis.direction,
destination: {
droppableId: droppable.descriptor.id,
index: 0
}
};
return {
pageCenter: withDroppableDisplacement(droppable, _newCenter),
impact: _newImpact
};
}
var targetIndex = insideDroppable.indexOf(target);
var proposedIndex = isGoingBeforeTarget ? targetIndex : targetIndex + 1;
if (targetIndex === -1) {
console.error('could not find target inside destination');
return null;
}
var newCenter = moveToEdge({
source: draggable.page.borderBox,
sourceEdge: 'start',
destination: target.page.marginBox,
destinationEdge: isGoingBeforeTarget ? 'start' : 'end',
destinationAxis: axis
});
var displaced = insideDroppable.slice(proposedIndex, insideDroppable.length).map(function (dimension) {
return getDisplacement({
draggable: dimension,
destination: droppable,
viewport: viewport.subject,
previousImpact: previousImpact
});
});
var newImpact = {
movement: {
displaced: displaced,
amount: amount,
isBeyondStartPosition: false
},
direction: axis.direction,
destination: {
droppableId: droppable.descriptor.id,
index: proposedIndex
}
};
return {
pageCenter: withDroppableDisplacement(droppable, newCenter),
impact: newImpact
};
});
var moveToNewDroppable = (function (_ref) {
var pageCenter = _ref.pageCenter,
destination = _ref.destination,
draggable = _ref.draggable,
target = _ref.target,
home = _ref.home,
insideDestination = _ref.insideDestination,
previousImpact = _ref.previousImpact,
viewport = _ref.viewport;
var amount = patch(destination.axis.line, draggable.client.marginBox[destination.axis.size]);
if (destination.descriptor.id === draggable.descriptor.droppableId) {
return toHomeList({
amount: amount,
originalIndex: home.index,
target: target,
insideDroppable: insideDestination,
draggable: draggable,
droppable: destination,
previousImpact: previousImpact,
viewport: viewport
});
}
return toForeignList({
amount: amount,
pageCenter: pageCenter,
target: target,
insideDroppable: insideDestination,
draggable: draggable,
droppable: destination,
previousImpact: previousImpact,
viewport: viewport
});
});
var moveCrossAxis = (function (_ref) {
var isMovingForward = _ref.isMovingForward,
pageCenter = _ref.pageCenter,
draggableId = _ref.draggableId,
droppableId = _ref.droppableId,
home = _ref.home,
draggables = _ref.draggables,
droppables = _ref.droppables,
previousImpact = _ref.previousImpact,
viewport = _ref.viewport;
var draggable = draggables[draggableId];
var source = droppables[droppableId];
var destination = getBestCrossAxisDroppable({
isMovingForward: isMovingForward,
pageCenter: pageCenter,
source: source,
droppables: droppables,
viewport: viewport
});
if (!destination) {
return null;
}
var insideDestination = getDraggablesInsideDroppable(destination, draggables);
var target = getClosestDraggable({
axis: destination.axis,
pageCenter: pageCenter,
destination: destination,
insideDestination: insideDestination,
viewport: viewport
});
if (insideDestination.length && !target) {
return null;
}
return moveToNewDroppable({
pageCenter: pageCenter,
destination: destination,
draggable: draggable,
target: target,
insideDestination: insideDestination,
home: home,
previousImpact: previousImpact || noImpact,
viewport: viewport
});
});
var noDimensions = {
request: null,
draggable: {},
droppable: {}
};
var origin$3 = { x: 0, y: 0 };
var clean = memoizeOne(function () {
var phase = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'IDLE';
return {
phase: phase,
drag: null,
drop: null,
dimension: noDimensions
};
});
var canPublishDimension = function canPublishDimension(phase) {
return ['IDLE', 'DROP_ANIMATING', 'DROP_COMPLETE'].indexOf(phase) === -1;
};
var move = function move(_ref) {
var state = _ref.state,
clientSelection = _ref.clientSelection,
shouldAnimate = _ref.shouldAnimate,
proposedViewport = _ref.viewport,
impact = _ref.impact,
scrollJumpRequest = _ref.scrollJumpRequest;
if (state.phase !== 'DRAGGING') {
console.error('cannot move while not dragging');
return clean();
}
var last = state.drag;
if (last == null) {
console.error('cannot move if there is no drag information');
return clean();
}
var previous = last.current;
var initial = last.initial;
var viewport = proposedViewport || previous.viewport;
var currentWindowScroll = viewport.scroll;
var client = function () {
var offset = subtract(clientSelection, initial.client.selection);
var result = {
offset: offset,
selection: clientSelection,
center: add(offset, initial.client.center)
};
return result;
}();
var page = {
selection: add(client.selection, currentWindowScroll),
offset: add(client.offset, currentWindowScroll),
center: add(client.center, currentWindowScroll)
};
var current = {
client: client,
page: page,
shouldAnimate: shouldAnimate,
viewport: viewport,
hasCompletedFirstBulkPublish: previous.hasCompletedFirstBulkPublish
};
var newImpact = impact || getDragImpact({
pageCenter: page.center,
draggable: state.dimension.draggable[initial.descriptor.id],
draggables: state.dimension.draggable,
droppables: state.dimension.droppable,
previousImpact: last.impact,
viewport: viewport
});
var drag = {
initial: initial,
impact: newImpact,
current: current,
scrollJumpRequest: scrollJumpRequest
};
return _extends({}, state, {
drag: drag
});
};
var updateStateAfterDimensionChange = function updateStateAfterDimensionChange(newState, impact) {
if (newState.phase === 'COLLECTING_INITIAL_DIMENSIONS') {
return newState;
}
if (newState.phase !== 'DRAGGING') {
return newState;
}
if (!newState.drag) {
console.error('cannot update a draggable dimension in an existing drag as there is invalid drag state');
return clean();
}
return move({
state: newState,
clientSelection: newState.drag.current.client.selection,
shouldAnimate: newState.drag.current.shouldAnimate,
impact: impact
});
};
var reducer = (function () {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : clean('IDLE');
var action = arguments[1];
if (action.type === 'CLEAN') {
return clean();
}
if (action.type === 'PREPARE') {
return clean('PREPARING');
}
if (action.type === 'REQUEST_DIMENSIONS') {
if (state.phase !== 'PREPARING') {
console.error('trying to start a lift while not preparing for a lift');
return clean();
}
var request = action.payload;
return {
phase: 'COLLECTING_INITIAL_DIMENSIONS',
drag: null,
drop: null,
dimension: {
request: request,
draggable: {},
droppable: {}
}
};
}
if (action.type === 'PUBLISH_DRAGGABLE_DIMENSION') {
var _extends2;
var dimension = action.payload;
if (!canPublishDimension(state.phase)) {
console.warn('dimensions rejected as no longer allowing dimension capture in phase', state.phase);
return state;
}
var newState = _extends({}, state, {
dimension: {
request: state.dimension.request,
droppable: state.dimension.droppable,
draggable: _extends({}, state.dimension.draggable, (_extends2 = {}, _extends2[dimension.descriptor.id] = dimension, _extends2))
}
});
return updateStateAfterDimensionChange(newState);
}
if (action.type === 'PUBLISH_DROPPABLE_DIMENSION') {
var _extends3;
var _dimension = action.payload;
if (!canPublishDimension(state.phase)) {
console.warn('dimensions rejected as no longer allowing dimension capture in phase', state.phase);
return state;
}
var _newState = _extends({}, state, {
dimension: {
request: state.dimension.request,
draggable: state.dimension.draggable,
droppable: _extends({}, state.dimension.droppable, (_extends3 = {}, _extends3[_dimension.descriptor.id] = _dimension, _extends3))
}
});
return updateStateAfterDimensionChange(_newState);
}
if (action.type === 'BULK_DIMENSION_PUBLISH') {
var draggables = action.payload.draggables;
var droppables = action.payload.droppables;
if (!canPublishDimension(state.phase)) {
console.warn('dimensions rejected as no longer allowing dimension capture in phase', state.phase);
return state;
}
var newDraggables = draggables.reduce(function (previous, current) {
previous[current.descriptor.id] = current;
return previous;
}, {});
var newDroppables = droppables.reduce(function (previous, current) {
previous[current.descriptor.id] = current;
return previous;
}, {});
var drag = function () {
var existing = state.drag;
if (!existing) {
return null;
}
if (existing.current.hasCompletedFirstBulkPublish) {
return existing;
}
var newDrag = _extends({}, existing, {
current: _extends({}, existing.current, {
hasCompletedFirstBulkPublish: true
})
});
return newDrag;
}();
var _newState2 = _extends({}, state, {
drag: drag,
dimension: {
request: state.dimension.request,
draggable: _extends({}, state.dimension.draggable, newDraggables),
droppable: _extends({}, state.dimension.droppable, newDroppables)
}
});
return updateStateAf