UNPKG

react-beautiful-dnd

Version:

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

1,846 lines (1,492 loc) 181 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var _Object$keys = _interopDefault(require('babel-runtime/core-js/object/keys')); var memoizeOne = _interopDefault(require('memoize-one')); var _extends = _interopDefault(require('babel-runtime/helpers/extends')); var invariant = _interopDefault(require('tiny-invariant')); var _typeof = _interopDefault(require('babel-runtime/helpers/typeof')); var redux = require('redux'); var thunk = _interopDefault(require('redux-thunk')); var _Object$assign = _interopDefault(require('babel-runtime/core-js/object/assign')); var rafSchd = _interopDefault(require('raf-schd')); var _classCallCheck = _interopDefault(require('babel-runtime/helpers/classCallCheck')); var _possibleConstructorReturn = _interopDefault(require('babel-runtime/helpers/possibleConstructorReturn')); var _inherits = _interopDefault(require('babel-runtime/helpers/inherits')); var React = require('react'); var React__default = _interopDefault(React); var PropTypes = _interopDefault(require('prop-types')); var reselect = require('reselect'); var reactRedux = require('react-redux'); var reactMotion = require('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, {