@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
227 lines (217 loc) • 8.38 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
/**
* @jsxRuntime classic
* @jsx jsx
*/
import { useCallback, useLayoutEffect, useRef, useState } from 'react';
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
import { css, jsx } from '@emotion/react';
// eslint-disable-next-line import/no-extraneous-dependencies
import { isSameLocation } from '../../drag-drop-context/draggable-location';
import { getActualDestination } from '../../drag-drop-context/get-destination';
import { useDragDropContext } from '../../drag-drop-context/internal-context';
import { useMonitorForLifecycle } from '../../drag-drop-context/lifecycle-context';
import { rbdInvariant } from '../../drag-drop-context/rbd-invariant';
import { customAttributes } from '../../utils/attributes';
import { directionMapping, lineOffset, lineThickness } from './constants';
import { getIndicatorSizeAndOffset } from './get-dimensions';
var scrollMarginTop = lineThickness + 2 * lineOffset;
var baseStyles = css({
background: "var(--ds-border-brand, #0C66E4)",
/**
* Ensures that when the indicator is scrolled into view there is visual
* space around it.
*
* Otherwise it will hug the edge of the container and be hard to see.
*/
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766
scrollMarginTop: scrollMarginTop,
/**
* The bottom margin needs to be slightly bigger for the gap to look
* the same visually.
*
* It's unclear why, this was found through testing.
*/
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values, @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
scrollMarginBottom: scrollMarginTop + lineOffset
});
/**
* For virtual lists, the indicator might not be a sibling of the contents.
* This can lead to issues like wrapping.
*
* This style 'resets' it so that there is a consistent initial position.
*/
var virtualStyles = css({
position: 'absolute',
top: 0,
left: 0
});
/**
* When targeting the source location, we hide the drop indicator.
* But it should still be scrolled to, so we only want to hide it visually,
* instead of not rendering it.
*/
var visuallyHiddenStyles = css({
opacity: 0
});
var directionStyles = {
horizontal: css({
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766
width: lineThickness,
height: '100%',
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values, @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
marginLeft: -lineThickness
}),
vertical: css({
width: '100%',
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766
height: lineThickness,
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values, @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
marginTop: -lineThickness
})
};
function getDynamicStyles(_ref) {
var direction = _ref.direction,
dimensions = _ref.dimensions,
indicatorOffset = _ref.indicatorOffset;
if (dimensions === null) {
/**
* We hide the indicator initially until dimensions can be taken.
*/
return {
opacity: 0
};
}
var _directionMapping$dir = directionMapping[direction],
mainAxis = _directionMapping$dir.mainAxis,
crossAxis = _directionMapping$dir.crossAxis;
return _defineProperty(_defineProperty({
transform: "".concat(mainAxis.style.transform, "(").concat(dimensions.mainAxis.offset - indicatorOffset, "px)")
}, crossAxis.style.length, dimensions.crossAxis.length), crossAxis.style.offset, dimensions.crossAxis.offset);
}
var dropIndicatorData = _defineProperty({}, customAttributes.dropIndicator, '');
export var DropIndicator = function DropIndicator(_ref3) {
var direction = _ref3.direction,
mode = _ref3.mode;
var _useDragDropContext = useDragDropContext(),
contextId = _useDragDropContext.contextId,
getDragState = _useDragDropContext.getDragState;
var ref = useRef(null);
var _useState = useState(null),
_useState2 = _slicedToArray(_useState, 2),
dimensions = _useState2[0],
setDimensions = _useState2[1];
var _useState3 = useState(false),
_useState4 = _slicedToArray(_useState3, 2),
isHidden = _useState4[0],
setIsHidden = _useState4[1];
var monitorForLifecycle = useMonitorForLifecycle();
var updateIndicator = useCallback(function (_ref4) {
var targetLocation = _ref4.targetLocation,
source = _ref4.source,
destination = _ref4.destination;
if (!targetLocation) {
return setDimensions(null);
}
var isInHomeLocation = isSameLocation(source, destination);
/**
* Determines if the drop indicator should be hidden.
*
* This is desired when the current drop target would not change the position
* of the draggable.
*/
setIsHidden(isInHomeLocation);
return setDimensions(getIndicatorSizeAndOffset({
targetLocation: targetLocation,
isInHomeLocation: isInHomeLocation,
direction: direction,
mode: mode,
contextId: contextId
}));
}, [contextId, direction, mode]);
/**
* This is in a `useLayoutEffect` for immediacy.
*
* When mounting (cross-axis movement) the indicator should update into
* its correct position right away, so that the drag preview can be placed
* correctly.
*/
useLayoutEffect(function () {
var dragState = getDragState();
if (!dragState.isDragging) {
return;
}
/**
* If the indicator is only just mounting then it needs an immediate
* update to have it appear in the correct position.
*/
var targetLocation = dragState.targetLocation,
sourceLocation = dragState.sourceLocation;
var destination = getActualDestination({
start: sourceLocation,
target: targetLocation
});
updateIndicator({
targetLocation: targetLocation,
destination: destination,
source: sourceLocation
});
return monitorForLifecycle({
onPrePendingDragUpdate: function onPrePendingDragUpdate(_ref5) {
var update = _ref5.update,
targetLocation = _ref5.targetLocation;
var _update$destination = update.destination,
destination = _update$destination === void 0 ? null : _update$destination,
source = update.source;
updateIndicator({
targetLocation: targetLocation,
source: source,
destination: destination
});
}
});
}, [contextId, direction, getDragState, mode, monitorForLifecycle, updateIndicator]);
/**
* Scroll the indicator into view.
*
* This is in a `useLayoutEffect` for immediacy.
* Otherwise the keyboard drag preview can appear in the wrong (old) location.
*/
useLayoutEffect(function () {
if (dimensions === null) {
return;
}
/**
* If we are doing a mouse drag,
* then we don't want to scroll to the indicator.
*
* Otherwise, it will conflict with the auto-scroll addon.
*/
var dragState = getDragState();
if (!dragState.isDragging || dragState.mode !== 'SNAP') {
return;
}
var element = ref.current;
rbdInvariant(element instanceof HTMLElement);
element.scrollIntoView({
block: 'nearest'
});
}, [dimensions, getDragState]);
var mainAxis = directionMapping[direction].mainAxis;
var indicatorOffset = ref.current ? ref.current[mainAxis.offset] : 0;
var dynamicStyles = getDynamicStyles({
direction: direction,
dimensions: dimensions,
indicatorOffset: indicatorOffset
});
var isVirtual = mode === 'virtual';
return jsx("div", _extends({
ref: ref,
css: [baseStyles, directionStyles[direction], isVirtual && virtualStyles, isHidden && visuallyHiddenStyles]
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
,
style: dynamicStyles
}, dropIndicatorData));
};