From d8143e34f62990ffc0a5e433d5c8ee8ea7abc627 Mon Sep 17 00:00:00 2001 From: Serge Pavlyuk Date: Fri, 26 Jul 2024 02:11:26 +0300 Subject: [PATCH] fix: drag between shared groups --- src/components/GridItem/GridItem.scss | 2 + src/components/GridLayout/GridLayout.js | 26 ++++-- src/components/GridLayout/ReactGridLayout.js | 90 ++++---------------- 3 files changed, 38 insertions(+), 80 deletions(-) diff --git a/src/components/GridItem/GridItem.scss b/src/components/GridItem/GridItem.scss index a8bcb7b..d90a19a 100644 --- a/src/components/GridItem/GridItem.scss +++ b/src/components/GridItem/GridItem.scss @@ -64,6 +64,8 @@ transition: none; z-index: 3; will-change: transform; + // needs for drag n drop between multiple groups + pointer-events: none; } .react-grid-item.dashkit-grid-item_is-focused { diff --git a/src/components/GridLayout/GridLayout.js b/src/components/GridLayout/GridLayout.js index 1610265..9619907 100644 --- a/src/components/GridLayout/GridLayout.js +++ b/src/components/GridLayout/GridLayout.js @@ -120,7 +120,7 @@ export default class GridLayout extends React.PureComponent { const onStop = this._onStop.bind(this, group); const onDrop = this._onDrop.bind(this, group); const onDropDragOver = this._onDropDragOver.bind(this, group); - const onDragExit = this._onDragExit.bind(this, group); + const onDragTargetRestore = this._onTargetRestore.bind(this, group); this._memoCallbacksForGroups[group] = { onDragStart, @@ -128,7 +128,7 @@ export default class GridLayout extends React.PureComponent { onResizeStop: onStop, onDrop, onDropDragOver, - onDragExit, + onDragTargetRestore, }; } @@ -240,10 +240,14 @@ export default class GridLayout extends React.PureComponent { }); }; - _onDragExit = () => { - this.setState({ - draggedOverGroup: null, - }); + _onTargetRestore = () => { + const {currentDraggingElement} = this.state; + + if (currentDraggingElement) { + this.setState({ + draggedOverGroup: currentDraggingElement[0], + }); + } }; _onStop = (group, newLayout) => { @@ -398,7 +402,7 @@ export default class GridLayout extends React.PureComponent { outerDnDEnable, } = this.context; - const {currentDraggingElement} = this.state; + const {currentDraggingElement, draggedOverGroup} = this.state; const properties = groupGridProperties ? groupGridProperties({ @@ -415,6 +419,11 @@ export default class GridLayout extends React.PureComponent { const hasSharedDragItem = Boolean( currentDraggingElement && currentDraggingElement[0] !== group, ); + const isDragCaptured = + currentDraggingElement && + group === currentDraggingElement[0] && + draggedOverGroup !== null && + draggedOverGroup !== group; return ( ({...item})); let hiddenElement; - const newLayout = compact( + const newLayout = utils.compact( layout.filter((item) => { if (item.i === i) { hiddenElement = item; @@ -112,7 +90,7 @@ class DragOverLayout extends ReactGridLayout { return true; }), - compactType(this.props), + utils.compactType(this.props), cols, ); @@ -124,29 +102,28 @@ class DragOverLayout extends ReactGridLayout { activeDrag: null, layout: newLayout, }); - this.resetExternalPlaceholder(); - return {layout: savedLayout, id: hiddenElement.i}; + return savedLayout; }; extendedOnDrag = (i, x, y, sintEv) => { - if (!this._isMouseOver) { - if (!this._savedDragoutState) { - this._savedDragoutState = this.hideLocalPlaceholder(i); + if (this.props.isDragCaptured) { + if (!this._savedDraggedOutLayout) { + this._savedDraggedOutLayout = this.hideLocalPlaceholder(i); } return; } - this._savedDragoutState = null; + this._savedDraggedOutLayout = null; // parent onDrag will show new placeholder again this.parentOnDrag(i, x, y, sintEv); }; extendedOnDragStop = (i, x, y, sintEv) => { // Restoring layout if item was dropped outside of the grid - if (this._savedDragoutState) { - const savedLayout = this._savedDragoutState.layout; + if (this._savedDraggedOutLayout) { + const savedLayout = this._savedDraggedOutLayout; const l = utils.getLayoutItem(savedLayout, i); // Create placeholder (display only) @@ -169,54 +146,34 @@ class DragOverLayout extends ReactGridLayout { }, ); - this._savedDragoutState = null; + this._savedDraggedOutLayout = null; } else { this.parentOnDragStop(i, x, y, sintEv); } }; - extendedOnDragEnter = (...args) => { - this._isMouseOver = true; - - this.parentOnDragEnter(...args); - }; - - extendedOnDragLeave = (...args) => { - this._isMouseOver = false; - - this.parentOnDragLeave(...args); - this.props.onDragExit?.(); - }; - // Proxy mouse events -> drag methods for dnd between groups mouseEnterHandler = (e) => { - this._isMouseOver = true; - if (this.props.hasSharedDragItem) { - this.parentOnDragEnter(e); + this.onDragEnter(e); + } else if (this.props.isDragCaptured) { + this.props.onDragTargetRestore?.(); } }; mouseLeaveHandler = (e) => { - this._isMouseOver = false; - if (this.props.hasSharedDragItem) { - this.parentOnDragLeave(e); - this.props.onDragExit?.(); + this.onDragLeave(e); } }; mouseMoveHandler = (e) => { - this._isMouseOver = true; - if (this.props.hasSharedDragItem) { this.onDragOver(e); } }; mouseUpHandler = (e) => { - this._isMouseOver = true; - if (this.props.hasSharedDragItem) { e.preventDefault(); const {droppingItem} = this.props; @@ -257,13 +214,11 @@ class DragOverLayout extends ReactGridLayout { const leftOffset = (((containerWidth / cols) * w) / 2 || 0) * transformScale; const topOffset = ((h * rowHeight + (h - 1) * margin[1]) / 2 || 0) * transformScale; - const dragStyles = this.props.hasSharedDragItem - ? DRAGGING_PLACEHOLDER_HIDDEN_STYLE - : DRAGGING_PLACEHOLDER_STYLE; - + const style = gridItem.props.style || null; // React.cloneElement is just cleaner then copy-paste whole processGridItem method return React.cloneElement(gridItem, { - style: itemProps.style ? {...itemProps.style, ...dragStyles} : dragStyles, + // hiding previre if dragging shared item + style: this.props.hasSharedDragItem ? {...style, opacity: 0} : style, className: OVERLAY_CLASS_NAME, droppingPosition: { ...droppingPosition, @@ -271,15 +226,6 @@ class DragOverLayout extends ReactGridLayout { top: droppingPosition.top - topOffset, }, }); - } else if ( - itemProps.i === this.state.activeDrag?.i || - itemProps.i === this._savedDragoutState?.id - ) { - const dragStyles = DRAGGING_PLACEHOLDER_STYLE; - - return React.cloneElement(gridItem, { - style: itemProps.style ? {...itemProps.style, ...dragStyles} : dragStyles, - }); } return gridItem;