UNPKG

react-beautiful-dnd

Version:

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

562 lines (443 loc) 14.8 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _keys = require('babel-runtime/core-js/object/keys'); var _keys2 = _interopRequireDefault(_keys); var _defineProperty2 = require('babel-runtime/helpers/defineProperty'); var _defineProperty3 = _interopRequireDefault(_defineProperty2); var _extends4 = require('babel-runtime/helpers/extends'); var _extends5 = _interopRequireDefault(_extends4); var _memoizeOne = require('memoize-one'); var _memoizeOne2 = _interopRequireDefault(_memoizeOne); var _position = require('./position'); var _noImpact = require('./no-impact'); var _getDragImpact = require('./get-drag-impact/'); var _getDragImpact2 = _interopRequireDefault(_getDragImpact); var _moveToNextIndex = require('./move-to-next-index/'); var _moveToNextIndex2 = _interopRequireDefault(_moveToNextIndex); var _moveCrossAxis = require('./move-cross-axis/'); var _moveCrossAxis2 = _interopRequireDefault(_moveCrossAxis); var _dimension = require('./dimension'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var noDimensions = { request: null, draggable: {}, droppable: {} }; var origin = { x: 0, y: 0 }; var clean = (0, _memoizeOne2.default)(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, windowScroll = _ref.windowScroll, impact = _ref.impact; 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 currentWindowScroll = windowScroll || previous.windowScroll; var client = function () { var offset = (0, _position.subtract)(clientSelection, initial.client.selection); var result = { offset: offset, selection: clientSelection, center: (0, _position.add)(offset, initial.client.center) }; return result; }(); var page = { selection: (0, _position.add)(client.selection, currentWindowScroll), offset: (0, _position.add)(client.offset, currentWindowScroll), center: (0, _position.add)(client.center, currentWindowScroll) }; var current = { client: client, page: page, shouldAnimate: shouldAnimate, windowScroll: currentWindowScroll }; var newImpact = impact || (0, _getDragImpact2.default)({ pageCenter: page.center, draggable: state.dimension.draggable[initial.descriptor.id], draggables: state.dimension.draggable, droppables: state.dimension.droppable, previousImpact: last.impact }); var drag = { initial: initial, impact: newImpact, current: current }; return (0, _extends5.default)({}, state, { drag: drag }); }; var updateStateAfterDimensionChange = function updateStateAfterDimensionChange(newState) { 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 }); }; exports.default = 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 id = action.payload; return { phase: 'COLLECTING_INITIAL_DIMENSIONS', drag: null, drop: null, dimension: { request: id, draggable: {}, droppable: {} } }; } if (action.type === 'PUBLISH_DRAGGABLE_DIMENSIONS') { var dimensions = action.payload; if (!canPublishDimension(state.phase)) { console.warn('dimensions rejected as no longer allowing dimension capture in phase', state.phase); return state; } var additions = dimensions.reduce(function (previous, current) { previous[current.descriptor.id] = current; return previous; }, {}); var newState = (0, _extends5.default)({}, state, { dimension: { request: state.dimension.request, droppable: state.dimension.droppable, draggable: (0, _extends5.default)({}, state.dimension.draggable, additions) } }); return updateStateAfterDimensionChange(newState); } if (action.type === 'PUBLISH_DROPPABLE_DIMENSIONS') { var _dimensions = action.payload; if (!canPublishDimension(state.phase)) { console.warn('dimensions rejected as no longer allowing dimension capture in phase', state.phase); return state; } var _additions = _dimensions.reduce(function (previous, current) { previous[current.descriptor.id] = current; return previous; }, {}); var _newState = (0, _extends5.default)({}, state, { dimension: { request: state.dimension.request, draggable: state.dimension.draggable, droppable: (0, _extends5.default)({}, state.dimension.droppable, _additions) } }); return updateStateAfterDimensionChange(_newState); } if (action.type === 'COMPLETE_LIFT') { if (state.phase !== 'COLLECTING_INITIAL_DIMENSIONS') { console.error('trying complete lift without collecting dimensions'); return state; } var _action$payload = action.payload, _id = _action$payload.id, client = _action$payload.client, _windowScroll = _action$payload.windowScroll, isScrollAllowed = _action$payload.isScrollAllowed; var page = { selection: (0, _position.add)(client.selection, _windowScroll), center: (0, _position.add)(client.center, _windowScroll) }; var draggable = state.dimension.draggable[_id]; if (!draggable) { console.error('could not find draggable in store after lift'); return clean(); } var descriptor = draggable.descriptor; var initial = { descriptor: descriptor, isScrollAllowed: isScrollAllowed, client: client, page: page, windowScroll: _windowScroll }; var current = { client: { selection: client.selection, center: client.center, offset: origin }, page: { selection: page.selection, center: page.center, offset: origin }, windowScroll: _windowScroll, shouldAnimate: false }; var home = state.dimension.droppable[descriptor.droppableId]; if (!home) { console.error('Cannot find home dimension for initial lift'); return clean(); } var destination = { index: descriptor.index, droppableId: descriptor.droppableId }; var _impact = { movement: _noImpact.noMovement, direction: home.axis.direction, destination: destination }; return (0, _extends5.default)({}, state, { phase: 'DRAGGING', drag: { initial: initial, current: current, impact: _impact } }); } if (action.type === 'UPDATE_DROPPABLE_DIMENSION_SCROLL') { if (state.phase !== 'DRAGGING') { console.error('cannot update a droppable dimensions scroll when not dragging'); return clean(); } if (state.drag == null) { console.error('invalid store state'); return clean(); } if (!state.drag.initial.isScrollAllowed) { return clean(); } var _action$payload2 = action.payload, _id2 = _action$payload2.id, offset = _action$payload2.offset; var target = state.dimension.droppable[_id2]; if (!target) { console.warn('cannot update scroll for droppable as it has not yet been collected'); return state; } var dimension = (0, _dimension.scrollDroppable)(target, offset); var _newState2 = (0, _extends5.default)({}, state, { dimension: { request: state.dimension.request, draggable: state.dimension.draggable, droppable: (0, _extends5.default)({}, state.dimension.droppable, (0, _defineProperty3.default)({}, _id2, dimension)) } }); return updateStateAfterDimensionChange(_newState2); } if (action.type === 'UPDATE_DROPPABLE_DIMENSION_IS_ENABLED') { if (!(0, _keys2.default)(state.dimension.droppable).length) { return state; } var _action$payload3 = action.payload, _id3 = _action$payload3.id, isEnabled = _action$payload3.isEnabled; var _target = state.dimension.droppable[_id3]; if (!_target) { console.warn('cannot update enabled state for droppable as it has not yet been collected'); return state; } if (_target.isEnabled === isEnabled) { console.warn('trying to set droppable isEnabled to ' + String(isEnabled) + ' but it is already ' + String(isEnabled)); return state; } var updatedDroppableDimension = (0, _extends5.default)({}, _target, { isEnabled: isEnabled }); var result = (0, _extends5.default)({}, state, { dimension: (0, _extends5.default)({}, state.dimension, { droppable: (0, _extends5.default)({}, state.dimension.droppable, (0, _defineProperty3.default)({}, _id3, updatedDroppableDimension)) }) }); return updateStateAfterDimensionChange(result); } if (action.type === 'MOVE') { var _action$payload4 = action.payload, _client = _action$payload4.client, _windowScroll2 = _action$payload4.windowScroll; return move({ state: state, clientSelection: _client, windowScroll: _windowScroll2, shouldAnimate: false }); } if (action.type === 'MOVE_BY_WINDOW_SCROLL') { var _windowScroll3 = action.payload.windowScroll; if (!state.drag) { console.error('cannot move with window scrolling if no current drag'); return clean(); } return move({ state: state, clientSelection: state.drag.current.client.selection, windowScroll: _windowScroll3, shouldAnimate: false }); } if (action.type === 'MOVE_FORWARD' || action.type === 'MOVE_BACKWARD') { if (state.phase !== 'DRAGGING') { console.error('cannot move while not dragging', action); return clean(); } if (!state.drag) { console.error('cannot move if there is no drag information'); return clean(); } var existing = state.drag; var isMovingForward = action.type === 'MOVE_FORWARD'; if (!existing.impact.destination) { console.error('cannot move if there is no previous destination'); return clean(); } var droppable = state.dimension.droppable[existing.impact.destination.droppableId]; var _result = (0, _moveToNextIndex2.default)({ isMovingForward: isMovingForward, draggableId: existing.initial.descriptor.id, droppable: droppable, draggables: state.dimension.draggable, previousImpact: existing.impact }); if (!_result) { return state; } var _impact2 = _result.impact; var _page = _result.pageCenter; var _client2 = (0, _position.subtract)(_page, existing.current.windowScroll); return move({ state: state, impact: _impact2, clientSelection: _client2, shouldAnimate: true }); } if (action.type === 'CROSS_AXIS_MOVE_FORWARD' || action.type === 'CROSS_AXIS_MOVE_BACKWARD') { if (state.phase !== 'DRAGGING') { console.error('cannot move cross axis when not dragging'); return clean(); } if (!state.drag) { console.error('cannot move cross axis if there is no drag information'); return clean(); } if (!state.drag.impact.destination) { console.error('cannot move cross axis if not in a droppable'); return clean(); } var _current = state.drag.current; var _descriptor = state.drag.initial.descriptor; var draggableId = _descriptor.id; var center = _current.page.center; var droppableId = state.drag.impact.destination.droppableId; var _home = { index: _descriptor.index, droppableId: _descriptor.droppableId }; var _result2 = (0, _moveCrossAxis2.default)({ isMovingForward: action.type === 'CROSS_AXIS_MOVE_FORWARD', pageCenter: center, draggableId: draggableId, droppableId: droppableId, home: _home, draggables: state.dimension.draggable, droppables: state.dimension.droppable, previousImpact: state.drag.impact }); if (!_result2) { return state; } var _page2 = _result2.pageCenter; var _client3 = (0, _position.subtract)(_page2, _current.windowScroll); return move({ state: state, clientSelection: _client3, impact: _result2.impact, shouldAnimate: true }); } if (action.type === 'DROP_ANIMATE') { var _action$payload5 = action.payload, trigger = _action$payload5.trigger, newHomeOffset = _action$payload5.newHomeOffset, _impact3 = _action$payload5.impact, _result3 = _action$payload5.result; if (state.phase !== 'DRAGGING') { console.error('cannot animate drop while not dragging', action); return state; } if (!state.drag) { console.error('cannot animate drop - invalid drag state'); return clean(); } var pending = { trigger: trigger, newHomeOffset: newHomeOffset, result: _result3, impact: _impact3 }; return { phase: 'DROP_ANIMATING', drag: null, drop: { pending: pending, result: null }, dimension: state.dimension }; } if (action.type === 'DROP_COMPLETE') { var _result4 = action.payload; return { phase: 'DROP_COMPLETE', drag: null, drop: { pending: null, result: _result4 }, dimension: noDimensions }; } return state; };