UNPKG

react-beautiful-dnd

Version:

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

1,651 lines (1,450 loc) 183 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var _extends = _interopDefault(require('@babel/runtime-corejs2/helpers/extends')); var invariant = _interopDefault(require('tiny-invariant')); var cssBoxModel = require('css-box-model'); var _Object$keys = _interopDefault(require('@babel/runtime-corejs2/core-js/object/keys')); var memoizeOne = _interopDefault(require('memoize-one')); var redux = require('redux'); var _Object$assign = _interopDefault(require('@babel/runtime-corejs2/core-js/object/assign')); var rafSchd = _interopDefault(require('raf-schd')); var _inheritsLoose = _interopDefault(require('@babel/runtime-corejs2/helpers/inheritsLoose')); var React = require('react'); var React__default = _interopDefault(React); var PropTypes = _interopDefault(require('prop-types')); var reactRedux = require('react-redux'); var reactMotion = require('react-motion'); 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 origin = { x: 0, y: 0 }; 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, otherValue) { var _ref; if (otherValue === void 0) { otherValue = 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 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 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 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 clip = function clip(frame, subject) { var result = cssBoxModel.getRect({ 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 getDroppableDimension = function getDroppableDimension(_ref) { var descriptor = _ref.descriptor, isEnabled = _ref.isEnabled, direction = _ref.direction, client = _ref.client, page = _ref.page, closest$$1 = _ref.closest; var scrollable = function () { if (!closest$$1) { return null; } var maxScroll = getMaxScroll({ scrollHeight: closest$$1.scrollHeight, scrollWidth: closest$$1.scrollWidth, height: closest$$1.client.paddingBox.height, width: closest$$1.client.paddingBox.width }); return { framePageMarginBox: closest$$1.page.marginBox, shouldClipSubject: closest$$1.shouldClipSubject, scroll: { initial: closest$$1.scroll, current: closest$$1.scroll, max: maxScroll, diff: { value: origin, displacement: origin } } }; }(); var subjectPageMarginBox = page.marginBox; var clippedPageMarginBox = scrollable && scrollable.shouldClipSubject ? clip(scrollable.framePageMarginBox, subjectPageMarginBox) : subjectPageMarginBox; var viewport = { closestScrollable: scrollable, subjectPageMarginBox: subjectPageMarginBox, clippedPageMarginBox: clippedPageMarginBox }; var dimension = { descriptor: descriptor, axis: direction === 'vertical' ? vertical : horizontal, isEnabled: isEnabled, client: client, page: page, viewport: viewport }; return dimension; }; var scrollDroppable = function scrollDroppable(droppable, newScroll) { !droppable.viewport.closestScrollable ? process.env.NODE_ENV !== "production" ? invariant(false) : invariant(false) : void 0; var scrollable = droppable.viewport.closestScrollable; var framePageMarginBox = scrollable.framePageMarginBox; var scrollDiff = subtract(newScroll, scrollable.scroll.initial); var scrollDisplacement = negate(scrollDiff); var closestScrollable = { framePageMarginBox: scrollable.framePageMarginBox, shouldClipSubject: scrollable.shouldClipSubject, scroll: { initial: scrollable.scroll.initial, current: newScroll, diff: { value: scrollDiff, displacement: scrollDisplacement }, max: scrollable.scroll.max } }; var displacedSubject = offsetByPosition(droppable.viewport.subjectPageMarginBox, scrollDisplacement); var clippedPageMarginBox = closestScrollable.shouldClipSubject ? clip(framePageMarginBox, displacedSubject) : cssBoxModel.getRect(displacedSubject); var viewport = { closestScrollable: closestScrollable, subjectPageMarginBox: droppable.viewport.subjectPageMarginBox, clippedPageMarginBox: clippedPageMarginBox }; var result = _extends({}, droppable, { viewport: viewport }); return result; }; var toDroppableMap = memoizeOne(function (droppables) { return droppables.reduce(function (previous, current) { previous[current.descriptor.id] = current; return previous; }, {}); }); var toDraggableMap = memoizeOne(function (draggables) { return draggables.reduce(function (previous, current) { previous[current.descriptor.id] = current; return previous; }, {}); }); var toDroppableList = memoizeOne(function (droppables) { return _Object$keys(droppables).map(function (id) { return droppables[id]; }); }); var toDraggableList = memoizeOne(function (draggables) { return _Object$keys(draggables).map(function (id) { return draggables[id]; }); }); var getDraggablesInsideDroppable = memoizeOne(function (droppable, draggables) { return toDraggableList(draggables).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 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 cssBoxModel.getRect(expandByPosition(area, growth)); }); var getClippedRectWithPlaceholder = function getClippedRectWithPlaceholder(_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 clippedPageMarginBox = droppable.viewport.clippedPageMarginBox; if (!clippedPageMarginBox) { return clippedPageMarginBox; } if (isHome || !wasOver) { return clippedPageMarginBox; } var requiredGrowth = getRequiredGrowth(draggable, draggables, droppable); if (!requiredGrowth) { return clippedPageMarginBox; } var subjectWithGrowth = getWithGrowth(clippedPageMarginBox, requiredGrowth); var closestScrollable = droppable.viewport.closestScrollable; if (!closestScrollable) { return subjectWithGrowth; } if (!closestScrollable.shouldClipSubject) { return subjectWithGrowth; } return clip(closestScrollable.framePageMarginBox, subjectWithGrowth); }; var getDroppableOver = (function (_ref2) { var target = _ref2.target, draggable = _ref2.draggable, draggables = _ref2.draggables, droppables = _ref2.droppables, previousDroppableOverId = _ref2.previousDroppableOverId; var maybe = toDroppableList(droppables).filter(function (droppable) { return droppable.isEnabled; }).find(function (droppable) { var withPlaceholder = getClippedRectWithPlaceholder({ draggable: draggable, draggables: draggables, droppable: droppable, previousDroppableOverId: previousDroppableOverId }); if (!withPlaceholder) { return false; } return isPositionInFrame(withPlaceholder)(target); }); return maybe ? maybe.descriptor.id : null; }); var noMovement = { displaced: [], amount: origin, isBeyondStartPosition: false }; var noImpact = { movement: noMovement, direction: null, destination: 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 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; var withDisplacement = offsetByPosition(target, displacement); if (!destination.viewport.clippedPageMarginBox) { return false; } var isVisibleInDroppable = isVisibleThroughFrameFn(destination.viewport.clippedPageMarginBox)(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 pageBorderBoxCenter = _ref.pageBorderBoxCenter, 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, pageBorderBoxCenter); 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 borderBox = child.page.borderBox; if (isBeyondStartPosition) { if (borderBox.center[axis.line] < originalCenter[axis.line]) { return false; } return currentCenter[axis.line] > borderBox[axis.start]; } if (originalCenter[axis.line] < borderBox.center[axis.line]) { return false; } return currentCenter[axis.line] < borderBox[axis.end]; }).map(function (dimension) { return getDisplacement({ draggable: dimension, destination: home, previousImpact: previousImpact, viewport: viewport.frame }); }); var ordered = isBeyondStartPosition ? displaced.reverse() : displaced; var index = function () { var startIndex = draggable.descriptor.index; 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 pageBorderBoxCenter = _ref.pageBorderBoxCenter, draggable = _ref.draggable, destination = _ref.destination, insideDestination = _ref.insideDestination, previousImpact = _ref.previousImpact, viewport = _ref.viewport; var axis = destination.axis; var currentCenter = withDroppableScroll(destination, pageBorderBoxCenter); 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.frame }); }); 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 pageBorderBoxCenter = _ref.pageBorderBoxCenter, 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: pageBorderBoxCenter, 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({ pageBorderBoxCenter: pageBorderBoxCenter, draggable: draggable, home: home, insideHome: insideDestination, previousImpact: previousImpact || noImpact, viewport: viewport }); } return inForeignList({ pageBorderBoxCenter: pageBorderBoxCenter, draggable: draggable, destination: destination, insideDestination: insideDestination, previousImpact: previousImpact || noImpact, viewport: viewport }); }); var getHomeLocation = (function (critical) { return { index: critical.draggable.index, droppableId: critical.droppable.id }; }); var getSafeClipped = function getSafeClipped(droppable) { var rect = droppable.viewport.clippedPageMarginBox; !rect ? process.env.NODE_ENV !== "production" ? invariant(false, 'Cannot get clipped area from droppable') : invariant(false) : void 0; return rect; }; var getBestCrossAxisDroppable = (function (_ref) { var isMovingForward = _ref.isMovingForward, pageBorderBoxCenter = _ref.pageBorderBoxCenter, source = _ref.source, droppables = _ref.droppables, viewport = _ref.viewport; var sourceClipped = source.viewport.clippedPageMarginBox; if (!sourceClipped) { return null; } var axis = source.axis; var isBetweenSourceClipped = isWithin(sourceClipped[axis.start], sourceClipped[axis.end]); var candidates = toDroppableList(droppables).filter(function (droppable) { return droppable !== source; }).filter(function (droppable) { return droppable.isEnabled; }).filter(function (droppable) { var clippedPageMarginBox = droppable.viewport.clippedPageMarginBox; if (!clippedPageMarginBox) { return false; } return isPartiallyVisibleThroughFrame(viewport.frame)(clippedPageMarginBox); }).filter(function (droppable) { var targetClipped = getSafeClipped(droppable); if (isMovingForward) { return sourceClipped[axis.crossAxisEnd] < targetClipped[axis.crossAxisEnd]; } return targetClipped[axis.crossAxisStart] < 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(pageBorderBoxCenter[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(pageBorderBoxCenter, getCorners(getSafeClipped(a))); var second = closest(pageBorderBoxCenter, getCorners(getSafeClipped(b))); if (first !== second) { return first - second; } return getSafeClipped(a)[axis.start] - getSafeClipped(b)[axis.start]; })[0]; }); var withDroppableDisplacement = (function (droppable, point) { var closestScrollable = droppable.viewport.closestScrollable; if (!closestScrollable) { return point; } return add(point, closestScrollable.scroll.diff.displacement); }); var getClosestDraggable = (function (_ref) { var axis = _ref.axis, viewport = _ref.viewport, pageBorderBoxCenter = _ref.pageBorderBoxCenter, destination = _ref.destination, insideDestination = _ref.insideDestination; if (!insideDestination.length) { return null; } var result = insideDestination.filter(function (draggable) { return isTotallyVisible({ target: draggable.page.borderBox, destination: destination, viewport: viewport.frame }); }).sort(function (a, b) { var distanceToA = distance(pageBorderBoxCenter, withDroppableDisplacement(destination, a.page.borderBox.center)); var distanceToB = distance(pageBorderBoxCenter, withDroppableDisplacement(destination, b.page.borderBox.center)); if (distanceToA < distanceToB) { return -1; } if (distanceToB < distanceToA) { return 1; } return a.page.borderBox[axis.start] - b.page.borderBox[axis.start]; }); return result.length ? result[0] : null; }); 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 toHomeList = (function (_ref) { var amount = _ref.amount, homeIndex = _ref.homeIndex, movingRelativeTo = _ref.movingRelativeTo, insideDestination = _ref.insideDestination, draggable = _ref.draggable, destination = _ref.destination, previousImpact = _ref.previousImpact, viewport = _ref.viewport; var axis = destination.axis; var targetIndex = insideDestination.indexOf(movingRelativeTo); !(targetIndex !== -1) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Unable to find target in destination droppable') : invariant(false) : void 0; if (targetIndex === homeIndex) { var _newCenter = draggable.page.borderBox.center; var _newImpact = { movement: { displaced: [], amount: amount, isBeyondStartPosition: false }, direction: destination.axis.direction, destination: { droppableId: destination.descriptor.id, index: homeIndex } }; return { pageBorderBoxCenter: withDroppableDisplacement(destination, _newCenter), impact: _newImpact }; } var isMovingPastOriginalIndex = targetIndex > homeIndex; var edge = isMovingPastOriginalIndex ? 'end' : 'start'; var newCenter = moveToEdge({ source: draggable.page.borderBox, sourceEdge: edge, destination: isMovingPastOriginalIndex ? movingRelativeTo.page.borderBox : movingRelativeTo.page.marginBox, destinationEdge: edge, destinationAxis: axis }); var modified = function () { if (!isMovingPastOriginalIndex) { return insideDestination.slice(targetIndex, homeIndex); } var from = homeIndex + 1; var to = targetIndex + 1; return insideDestination.slice(from, to).reverse(); }(); var displaced = modified.map(function (dimension) { return getDisplacement({ draggable: dimension, destination: destination, previousImpact: previousImpact, viewport: viewport.frame }); }); var newImpact = { movement: { displaced: displaced, amount: amount, isBeyondStartPosition: isMovingPastOriginalIndex }, direction: axis.direction, destination: { droppableId: destination.descriptor.id, index: targetIndex } }; return { pageBorderBoxCenter: withDroppableDisplacement(destination, newCenter), impact: newImpact }; }); var toForeignList = (function (_ref) { var amount = _ref.amount, pageBorderBoxCenter = _ref.pageBorderBoxCenter, movingRelativeTo = _ref.movingRelativeTo, insideDestination = _ref.insideDestination, draggable = _ref.draggable, destination = _ref.destination, previousImpact = _ref.previousImpact, viewport = _ref.viewport; var axis = destination.axis; var isGoingBeforeTarget = Boolean(movingRelativeTo && pageBorderBoxCenter[destination.axis.line] < movingRelativeTo.page.borderBox.center[destination.axis.line]); if (!movingRelativeTo) { var _newCenter = moveToEdge({ source: draggable.page.borderBox, sourceEdge: 'start', destination: destination.page.contentBox, destinationEdge: 'start', destinationAxis: axis }); var _newImpact = { movement: { displaced: [], amount: amount, isBeyondStartPosition: false }, direction: axis.direction, destination: { droppableId: destination.descriptor.id, index: 0 } }; return { pageBorderBoxCenter: withDroppableDisplacement(destination, _newCenter), impact: _newImpact }; } var targetIndex = insideDestination.indexOf(movingRelativeTo); !(targetIndex !== -1) ? process.env.NODE_ENV !== "production" ? invariant(false, 'The target was not found within its droppable') : invariant(false) : void 0; var proposedIndex = isGoingBeforeTarget ? targetIndex : targetIndex + 1; var newCenter = moveToEdge({ source: draggable.page.borderBox, sourceEdge: 'start', destination: movingRelativeTo.page.marginBox, destinationEdge: isGoingBeforeTarget ? 'start' : 'end', destinationAxis: axis }); var displaced = insideDestination.slice(proposedIndex, insideDestination.length).map(function (dimension) { return getDisplacement({ draggable: dimension, destination: destination, viewport: viewport.frame, previousImpact: previousImpact }); }); var newImpact = { movement: { displaced: displaced, amount: amount, isBeyondStartPosition: false }, direction: axis.direction, destination: { droppableId: destination.descriptor.id, index: proposedIndex } }; return { pageBorderBoxCenter: withDroppableDisplacement(destination, newCenter), impact: newImpact }; }); var moveToNewDroppable = (function (_ref) { var pageBorderBoxCenter = _ref.pageBorderBoxCenter, destination = _ref.destination, insideDestination = _ref.insideDestination, draggable = _ref.draggable, movingRelativeTo = _ref.movingRelativeTo, home = _ref.home, 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) { !movingRelativeTo ? process.env.NODE_ENV !== "production" ? invariant(false, 'There will always be a target in the original list') : invariant(false) : void 0; return toHomeList({ amount: amount, homeIndex: home.index, movingRelativeTo: movingRelativeTo, insideDestination: insideDestination, draggable: draggable, destination: destination, previousImpact: previousImpact, viewport: viewport }); } return toForeignList({ amount: amount, pageBorderBoxCenter: pageBorderBoxCenter, movingRelativeTo: movingRelativeTo, insideDestination: insideDestination, draggable: draggable, destination: destination, previousImpact: previousImpact, viewport: viewport }); }); var moveCrossAxis = (function (_ref) { var isMovingForward = _ref.isMovingForward, pageBorderBoxCenter = _ref.pageBorderBoxCenter, 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, pageBorderBoxCenter: pageBorderBoxCenter, source: source, droppables: droppables, viewport: viewport }); if (!destination) { return null; } var insideDestination = getDraggablesInsideDroppable(destination, draggables); var movingRelativeTo = getClosestDraggable({ axis: destination.axis, pageBorderBoxCenter: pageBorderBoxCenter, destination: destination, insideDestination: insideDestination, viewport: viewport }); if (insideDestination.length && !movingRelativeTo) { return null; } return moveToNewDroppable({ pageBorderBoxCenter: pageBorderBoxCenter, destination: destination, draggable: draggable, movingRelativeTo: movingRelativeTo, insideDestination: insideDestination, home: home, previousImpact: previousImpact || noImpact, viewport: viewport }); }); var isTotallyVisibleInNewLocation = (function (_ref) { var draggable = _ref.draggable, destination = _ref.destination, newPageBorderBoxCenter = _ref.newPageBorderBoxCenter, viewport = _ref.viewport; var diff = subtract(newPageBorderBoxCenter, draggable.page.borderBox.center); var shifted = offsetByPosition(draggable.page.borderBox, diff); return isTotallyVisible({ target: shifted, destination: destination, viewport: viewport }); }); 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.frame }); 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; !last.length ? process.env.NODE_ENV !== "production" ? invariant(false, 'Cannot remove displacement from empty list') : invariant(false) : void 0; 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, previousPageBorderBoxCenter = _ref.previousPageBorderBoxCenter, previousImpact = _ref.previousImpact, droppable = _ref.droppable, draggables = _ref.draggables, viewport = _ref.viewport; var location = previousImpact.destination; !location ? process.env.NODE_ENV !== "production" ? invariant(false, 'Cannot move to next index in home list when there is no previous destination') : invariant(false) : void 0; 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 (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 newPageBorderBoxCenter = moveToEdge({ source: draggable.page.borderBox, sourceEdge: edge, destination: destination.page.borderBox, destinationEdge: edge, destinationAxis: droppable.axis }); var isVisibleInNewLocation = isTotallyVisibleInNewLocation({ draggable: draggable, destination: droppable, newPageBorderBoxCenter: newPageBorderBoxCenter, viewport: viewport.frame }); var displaced = isMovingTowardStart ? withFirstRemoved({ dragging: draggableId, isVisibleInNewLocation: isVisibleInNewLocation, previousImpact: previousImpact, droppable: droppable, draggables: draggables }) : 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 { pageBorderBoxCenter: withDroppableDisplacement(droppable, newPageBorderBoxCenter), impact: newImpact, scrollJumpRequest: null }; } var distance$$1 = subtract(newPageBorderBoxCenter, previousPageBorderBoxCenter); var distanceWithScroll = withDroppableDisplacement(droppable, distance$$1); return { pageBorderBoxCenter: previousPageBorderBoxCenter, impact: newImpact, scrollJumpRequest: distanceWithScroll }; }); var inForeignList$1 = (function (_ref) { var isMovingForward = _ref.isMovingForward, draggableId = _ref.draggableId, previousImpact = _ref.previousImpact, previousPageBorderBoxCenter = _ref.previousPageBorderBoxCenter, droppable = _ref.droppable, draggables = _ref.draggables, viewport = _ref.viewport; !previousImpact.destination ? process.env.NODE_ENV !== "production" ? invariant(false, 'Cannot move to next index where there is no previous destination') : invariant(false) : void 0; 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 newPageBorderBoxCenter = moveToEdge({ source: draggable.page.borderBox, sourceEdge: sourceEdge, destination: movingRelativeTo.page.marginBox, destinationEdge: destinationEdge, destinationAxis: droppable.axis }); var isVisibleInNewLocation = isTotallyVisibleInNewLocation({ draggable: draggable, destination: droppable, newPageBorderBoxCenter: newPageBorderBoxCenter, viewport: viewport.frame }); 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 { pageBorderBoxCenter: withDroppableDisplacement(droppable, newPageBorderBoxCenter), impact: newImpact, scrollJumpRequest: null }; } var distanceMoving = subtract(newPageBorderBoxCenter, previousPageBorderBoxCenter); var distanceWithScroll = withDroppableDisplacement(droppable, distanceMoving); return { pageBorderBoxCenter: previousPageBorderBoxCenter, 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 getClientSelection = function getClientSelection(pageBorderBoxCenter, currentScroll) { return subtract(pageBorderBoxCenter, currentScroll); }; var moveInDirection = (function (_ref) { var state = _ref.state, type = _ref.type; var _ref2 = function () { if (state.impact.destination) { return { droppable: state.dimensions.droppables[state.impact.destination.droppableId], isMainAxisMovementAllowed: true }; } return { droppable: state.dimensions.droppables[state.critical.droppable.id], isMainAxisMovementAllowed: false }; }(), droppable = _ref2.droppable, isMainAxisMovementAllowed = _ref2.isMainAxisMovementAllowed; var direction = droppable.axis.direction; var isMovingOnMainAxis = direction === 'vertical' && (type === 'MOVE_UP' || type === 'MOVE_DOWN') || direction === 'horizontal' && (type === 'MOVE_LEFT' || type === 'MOVE_RIGHT'); if (isMovingOnMainAxis && !isMainAxisMovementAllowed) { return null; } var isMovingForward = type === 'MOVE_DOWN' || type === 'MOVE_RIGHT'; if (isMovingOnMainAxis) { var _result = moveToNextIndex({ isMovingForward: isMovingForward, draggableId: state.critical.draggable.id, droppable: droppable, draggables: state.dimensions.draggables, previousPageBorderBoxCenter: state.current.page.borderBoxCenter, previousImpact: state.impact, viewport: state.viewport }); if (!_result) { return null; } return { impact: _result.impact, clientSelection: getClientSelection(_result.pageBorderBoxCenter, state.viewport.scroll.current), scrollJumpRequest: _result.scrollJumpRequest }; } var home = getHomeLocation(state.critical); var result = moveCrossAxis({ isMovingForward: isMovingForward, pageBorderBoxCenter: state.current.page.borderBoxCenter, draggableId: state.critical.draggable.id, droppableId: droppable.descriptor.id, home: home, draggables: state.dimensions.draggables, droppables: state.dimensions.droppables, previousImpact: state.impact, viewport: state.viewport }); if (!result) { return null; } return { clientSelection: getClientSelection(result.pageBorderBoxCenter, state.viewport.scroll.current), impact: result.impact, scrollJumpRequest: null }; }); var scrollViewport = (function (viewport, newScroll) { var diff = subtract(newScroll, viewport.scroll.initial); var displacement = negate(diff); var frame = cssBoxModel.getRect({ top: newScroll.y, bottom: newScroll.y + viewport.frame.height, left: newScroll.x, right: newScroll.x + viewport.frame.width }); var updated = { frame: frame, scroll: { initial: viewport.scroll.initial, max: viewport.scroll.max, current: newScroll, diff: { value: diff, displacement: displacement } } }; return updated; }); var getHomeImpact = (function (critical, dimensions) { var home = dimensions.droppables[critical.droppable.id]; var axis = home.axis; var draggable = dimensions.draggables[critical.draggable.id]; return { movement: { displaced: [], isBeyondStartPosition: false, amount: patch(axis.line, draggable.client.marginBox[axis.size]) }, direction: axis.direction, destination: getHomeLocation(critical) }; }); var getPageItemPositions = (function (client, windowScroll) { return { selection: add(client.selection, windowScroll), borderBoxCenter: add(client.borderBoxCenter, windowScroll), offset: add(client.offset, windowScroll) }; }); function isMovementAllowed(state) { return state.phase === 'DRAGGING' || state.phase === 'COLLECTING'; } var idle = { phase: 'IDLE' }; var preparing = { phase: 'PREPARING' }; var moveWithPositionUpdates = function moveWithPositionUpdates(_ref) { var state = _ref.state, clientSelection = _ref.clientSelection, shouldAnimate = _ref.shouldAnimate, viewport = _ref.viewport, impact = _ref.impact, scrollJumpRequest = _ref.scrollJumpRequest; var newViewport = viewport || state.viewport; var currentWindowScroll = newViewport.scroll.current; var client = function () { var offset = subtract(clientSelection, state.initial.client.selection); return { offset: offset, selection: clientSelection, borderBoxCenter: add(state.initial.client.borderBoxCenter, offset) }; }(); var page = getPageItemPositions(client, currentWindowScroll); var current = { client: client, page: page }; if (state.phase === 'COLLECTING') { return _extends({ phase: 'COLLECTING' }, state, { current: current }); } var newImpact = impact || getDragImpact({ pageBorderBoxCenter: page.borderBoxCenter, draggable: state.dimensions.draggables[state.critical.draggable.id], draggables: state.dimensions.draggables, droppables: state.dimensions.droppables, previousImpact: state.impact, viewport: newViewport }); var result = _extends({}, state, { current: current, shouldAnimate: shouldAnimate, impact: newImpact, scrollJumpRequest: scrollJumpRequest || null, viewport: newViewport }); return result; }; var reducer = (function (state, action) { if (state === void 0) { state = idle; } if (action.type === 'CLEAN') { return idle; } if (action.type === 'PREPARE') { return preparing; } if (action.type === 'INITIAL_PUBLISH') { !(state.phase === 'PREPARING') ? process.env.NODE_ENV !== "production" ? invariant(false, 'INITIAL_PUBLISH must come after a PREPARING phase') : invariant(false) : void 0; var _action$payload = action.payload, critical = _action$payload.critical, client = _action$payload.client, viewport = _action$payload.viewport, dimensions = _action$payload.dimensions, autoScrollMode = _action$payload.autoScrollMode; var initial = { client: client, page: { selection: add(client.selection, viewport.scroll.initial), borderBoxCenter: add(client.selection, viewport.scroll.initial), offset: origin } }; var result = { phase: 'DRAGGING', isDragging: true, critical: critical, autoScrollMode: autoScrollMode, dimensions: dimensions, initial: initial, current: initial, impact: getHomeImpact(critical, dimensions), viewport: viewport, scrollJumpRequest: null, shouldAnimate: false }; return result; } if (action.type === 'COLLECTION_STARTING') { var _extends2; if (state.phase === 'COLLECTING' || state.phase === 'DROP_PENDING') { return state; } !(state.phase === 'DRAGGING') ? process.env.NODE_ENV !== "production" ? invariant(false, "Collection cannot start from phase " + state.phase) : invariant(false) : void 0; var _result = _extends({ phase: 'COLLECTING' }, state, (_extends2 = {}, _extends2["phase"] = 'COLLECTING', _extends2)); return _result; } if (action.type === 'PUBLISH') { !(state.phase === 'COLLECTING' || state.phase === 'DROP_PENDING') ? process.env.NODE_ENV !== "production" ? invariant(false, "Unexpected " + action.type + " received in phase " + state.