saagie-ui
Version:
Saagie UI from Saagie Design System
112 lines (95 loc) • 2.93 kB
JavaScript
import React, { useRef } from 'react';
import PropTypes from 'prop-types';
import { Draggable } from 'react-beautiful-dnd';
import { useDragContainerContext } from './PipelineDragContainer';
import { useMapInteractionContext } from '../mapInteraction/MapInteractionContext';
const propTypes = {
children: PropTypes.node,
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
index: PropTypes.number.isRequired,
};
const defaultProps = {
children: '',
};
const getOffset = (el, offset = { top: 0, left: 0 }) => {
if (!el) {
return offset;
}
const newOffset = {
top: offset.top + el.offsetTop,
left: offset.left + el.offsetLeft,
};
return getOffset(el.offsetParent, newOffset);
};
export const PipelineDragItem = ({
children, id, index,
}) => {
const baseItemStyleOnDrag = useRef({
top: 0,
left: 0,
});
const { containerEl, setPlaceholderStyle } = useDragContainerContext();
const mapContext = useMapInteractionContext();
const scale = mapContext ? mapContext.scale : 1;
const isFirstStyleCompute = useRef(true);
const itemRef = useRef();
const itemEl = itemRef.current;
const updateStyle = () => {
if (!containerEl || !itemEl || !isFirstStyleCompute.current) {
return;
}
const containerRect = getOffset(containerEl);
const itemRect = getOffset(itemEl);
setPlaceholderStyle({
width: itemEl.offsetWidth,
height: itemEl.offsetHeight,
});
baseItemStyleOnDrag.current = {
top: itemRect.top - containerRect.top,
left: itemRect.left - containerRect.left,
width: itemEl.offsetWidth,
height: itemEl.offsetHeight,
};
};
const getStyle = (style, isDragging) => {
const { transform } = style;
const translateRegex = /translate\((?<x>-?[0-9.]*)[px]*,\s?(?<y>-?[0-9.]*)[px]*\)/g;
const { x, y } = (translateRegex.exec(transform) || {}).groups || {};
const newTransform = `translate(${(x || 0) / scale}px, ${(y || 0) / scale}px)`;
if (!isDragging) {
isFirstStyleCompute.current = true;
return {
...style,
transform: newTransform,
};
}
updateStyle();
isFirstStyleCompute.current = false;
return {
...style,
...baseItemStyleOnDrag.current,
position: 'absolute',
transform: newTransform,
};
};
return (
<Draggable draggableId={id} index={index}>
{(provided, snapshot) => (
<div
ref={(el) => {
provided.innerRef(el);
itemRef.current = el;
}}
className="sui-prj-pipeline-drag-item"
{...provided.draggableProps}
{...provided.dragHandleProps}
style={getStyle(provided.draggableProps.style, snapshot.isDragging)}
>
{children}
</div>
)}
</Draggable>
);
};
PipelineDragItem.propTypes = propTypes;
PipelineDragItem.defaultProps = defaultProps;