UNPKG

saagie-ui

Version:

Saagie UI from Saagie Design System

112 lines (95 loc) 2.93 kB
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;