@atlaskit/pragmatic-drag-and-drop-react-beautiful-dnd-migration
Version:
An optional Pragmatic drag and drop package that enables rapid migration from react-beautiful-dnd to Pragmatic drag and drop
255 lines (250 loc) • 11.3 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Droppable = Droppable;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireWildcard(require("react"));
var _reactDom = require("react-dom");
var _tinyInvariant = _interopRequireDefault(require("tiny-invariant"));
var _closestEdge = require("@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge");
var _combine = require("@atlaskit/pragmatic-drag-and-drop/combine");
var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
var _internalContext = require("../drag-drop-context/internal-context");
var _lifecycleContext = require("../drag-drop-context/lifecycle-context");
var _data = require("../draggable/data");
var _useIsomorphicLayoutEffect = require("../hooks/use-isomorphic-layout-effect");
var _attributes = require("../utils/attributes");
var _useStable = require("../utils/use-stable");
var _data2 = require("./data");
var _draggableClone = require("./draggable-clone");
var _dropIndicator = require("./drop-indicator");
var _droppableContext = require("./droppable-context");
var _state = require("./state");
var _virtualPlaceholder = require("./virtual-placeholder");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
// eslint-disable-next-line import/no-extraneous-dependencies
function Droppable(_ref) {
var children = _ref.children,
droppableId = _ref.droppableId,
_ref$type = _ref.type,
type = _ref$type === void 0 ? 'DEFAULT' : _ref$type,
_ref$direction = _ref.direction,
direction = _ref$direction === void 0 ? 'vertical' : _ref$direction,
_ref$mode = _ref.mode,
mode = _ref$mode === void 0 ? 'standard' : _ref$mode,
renderClone = _ref.renderClone,
getContainerForClone = _ref.getContainerForClone,
_ref$isDropDisabled = _ref.isDropDisabled,
isDropDisabled = _ref$isDropDisabled === void 0 ? false : _ref$isDropDisabled;
var getIsDropDisabled = (0, _useStable.useStable)(isDropDisabled);
var _useDragDropContext = (0, _internalContext.useDragDropContext)(),
contextId = _useDragDropContext.contextId,
droppableRegistry = _useDragDropContext.droppableRegistry;
var data = (0, _data2.useDroppableData)({
contextId: contextId,
droppableId: droppableId,
getIsDropDisabled: getIsDropDisabled
});
var elementRef = (0, _react.useRef)(null);
var setElement = (0, _react.useCallback)(function (element) {
if (element) {
(0, _attributes.setAttributes)(element, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, _attributes.customAttributes.droppable.type, type), _attributes.customAttributes.droppable.direction, direction), _attributes.attributes.droppable.id, droppableId), _attributes.attributes.droppable.contextId, contextId));
}
elementRef.current = element;
}, [contextId, direction, droppableId, type]);
var _useReducer = (0, _react.useReducer)(_state.reducer, _state.idleState),
_useReducer2 = (0, _slicedToArray2.default)(_useReducer, 2),
state = _useReducer2[0],
dispatch = _useReducer2[1];
var draggingFromThisWith = state.draggingFromThisWith,
draggingOverWith = state.draggingOverWith,
isDraggingOver = state.isDraggingOver;
var parentDroppableId = (0, _droppableContext.useParentDroppableId)();
(0, _react.useEffect)(function () {
var element = elementRef.current;
(0, _tinyInvariant.default)(element instanceof HTMLElement, 'innerRef must provide an `HTMLElement`');
return (0, _combine.combine)(droppableRegistry.register({
droppableId: droppableId,
type: type,
isDropDisabled: isDropDisabled,
parentDroppableId: parentDroppableId,
element: element,
direction: direction,
mode: mode
}), (0, _adapter.dropTargetForElements)({
element: element,
getData: function getData(_ref2) {
var input = _ref2.input;
return (0, _closestEdge.attachClosestEdge)(data, {
element: element,
input: input,
allowedEdges: direction === 'vertical' ? ['top', 'bottom'] : ['left', 'right']
});
},
canDrop: function canDrop(_ref3) {
var source = _ref3.source;
if (!(0, _data.isDraggableData)(source.data)) {
// not dragging something from the migration layer
// we should not allow dropping
return false;
}
if (isDropDisabled) {
return false;
}
return source.data.contextId === contextId && source.data.type === type;
},
onDragLeave: function onDragLeave() {
dispatch({
type: 'DRAG_CLEAR'
});
}
}));
}, [data, droppableId, contextId, isDropDisabled, type, droppableRegistry, parentDroppableId, direction, mode]);
var monitorForLifecycle = (0, _lifecycleContext.useMonitorForLifecycle)();
(0, _react.useEffect)(function () {
function isEventRelevant(data) {
var _data$destination;
/**
* If the draggable is of a different type to this droppable,
* then we can ignore it.
*/
var isSameType = data.type === type;
var isOverAfterUpdate = ((_data$destination = data.destination) === null || _data$destination === void 0 ? void 0 : _data$destination.droppableId) === droppableId;
var isDragEnter = !isDraggingOver && isOverAfterUpdate;
var isDragLeave = isDraggingOver && !isOverAfterUpdate;
/**
* A droppable will only have a meaningful state update if the user is entering or exiting it.
*/
var isDragEnterOrLeave = isDragEnter || isDragLeave;
return isSameType && isDragEnterOrLeave;
}
return monitorForLifecycle({
onPendingDragStart: function onPendingDragStart(_ref4) {
var start = _ref4.start;
if (!isEventRelevant({
destination: start.source,
type: start.type
})) {
return;
}
dispatch({
type: 'DRAG_START',
payload: {
droppableId: droppableId,
start: start
}
});
},
onPendingDragUpdate: function onPendingDragUpdate(_ref5) {
var update = _ref5.update;
if (!isEventRelevant(update)) {
return;
}
dispatch({
type: 'DRAG_UPDATE',
payload: {
droppableId: droppableId,
update: update
}
});
},
onBeforeDragEnd: function onBeforeDragEnd() {
/**
* This is safe to call optimistically as it uses a stable idle state.
*
* If the droppable is already idle, it will not rerender.
*/
dispatch({
type: 'DRAG_CLEAR'
});
}
});
}, [droppableId, isDraggingOver, monitorForLifecycle, type]);
var dropIndicator = (0, _react.useMemo)(function () {
if (!isDraggingOver) {
return null;
}
return /*#__PURE__*/_react.default.createElement(_dropIndicator.DropIndicator, {
direction: direction,
mode: mode
});
}, [direction, isDraggingOver, mode]);
var provided = (0, _react.useMemo)(function () {
return {
innerRef: setElement,
droppableProps: (0, _defineProperty2.default)((0, _defineProperty2.default)({}, _attributes.attributes.droppable.contextId, contextId), _attributes.attributes.droppable.id, droppableId),
/**
* We only provide a drop indicator as the placeholder for
* non-virtual lists. Otherwise it is portalled in.
*/
placeholder: mode === 'standard' ? dropIndicator : null
};
}, [contextId, dropIndicator, droppableId, mode, setElement]);
var snapshot = (0, _react.useMemo)(function () {
return {
draggingFromThisWith: draggingFromThisWith,
draggingOverWith: draggingOverWith,
isDraggingOver: isDraggingOver,
isUsingPlaceholder: isDraggingOver
};
}, [draggingFromThisWith, draggingOverWith, isDraggingOver]);
var element = elementRef.current;
var shouldPortalDropIndicator = isDraggingOver && mode === 'virtual' && element;
/**
* Assumes that the ref points to the scroll container.
*/
(0, _useIsomorphicLayoutEffect.useLayoutEffect)(function () {
if (!shouldPortalDropIndicator) {
return;
}
var _window$getComputedSt = window.getComputedStyle(element),
position = _window$getComputedSt.position;
if (position !== 'static') {
return;
}
var prevStyle = element.style.position;
element.style.position = 'relative';
return function () {
element.style.position = prevStyle;
};
}, [element, shouldPortalDropIndicator]);
/**
* Used to disable the dragging style for the real draggable.
*/
var shouldRenderCloneWhileDragging = Boolean(renderClone);
var contextValue = (0, _react.useMemo)(function () {
return {
direction: direction,
droppableId: droppableId,
shouldRenderCloneWhileDragging: shouldRenderCloneWhileDragging,
isDropDisabled: isDropDisabled,
type: type,
mode: mode
};
}, [direction, droppableId, shouldRenderCloneWhileDragging, isDropDisabled, type, mode]);
/**
* For virtual lists we portal a placeholder in when dragging from the list.
*
* This is because `<Draggable />`'s can be unmounted at any time, so we
* cannot rely on rendering the placeholder as a sibling.
*/
var shouldPortalPlaceholder = draggingFromThisWith && mode === 'virtual' && element;
return /*#__PURE__*/_react.default.createElement(_droppableContext.DroppableContextProvider, {
value: contextValue
}, children(provided, snapshot), shouldPortalDropIndicator && /*#__PURE__*/(0, _reactDom.createPortal)(dropIndicator, element), shouldPortalPlaceholder && /*#__PURE__*/(0, _reactDom.createPortal)( /*#__PURE__*/_react.default.createElement(_virtualPlaceholder.VirtualPlaceholder, {
droppableId: droppableId,
draggableId: draggingFromThisWith,
type: type,
direction: direction,
isDropDisabled: isDropDisabled
}), element), renderClone && /*#__PURE__*/_react.default.createElement(_draggableClone.DraggableClone, {
droppableId: droppableId,
type: type,
getContainerForClone: getContainerForClone
}, renderClone));
}