diff --git a/src/canvas/canvas.js b/src/canvas/canvas.js index bc7e156..6aa7033 100644 --- a/src/canvas/canvas.js +++ b/src/canvas/canvas.js @@ -665,9 +665,9 @@ class Canvas extends React.Component { * Handles drop event to canvas from the sidebar and on canvas widget movement * @param {DragEvent} e */ - handleDropEvent = (e, draggedElement, widgetClass = null, initialPos={x: 0, y: 0}) => { + handleDropEvent = (e, draggedElement, widgetClass = null, initialOffset={x: 0, y: 0}) => { - console.log("event: ", e, draggedElement, widgetClass, initialPos) + console.log("event: ", e, draggedElement, widgetClass, initialOffset) // e.preventDefault() @@ -690,17 +690,18 @@ class Canvas extends React.Component { const { clientX, clientY } = e.nativeEvent - const { initial } = e.operation.shape + const { transform } = e.operation console.log("event: ", e) // const { x: clientX, y: clientY} = e.delta; - // const {clientX: draggedElementInitialX, clientY: draggedElementInitialY} = e.activatorEvent + const {clientX: draggedElementInitialX, clientY: draggedElementInitialY} = e.operation.activatorEvent + const { initial, current } = e.operation.shape - // console.log("wirking: ", clientX, clientY, e, draggedElementInitialX, draggedElementInitialY) + console.log("wirking: ", transform) // TODO: + initial cursor position - final cursor position let finalPosition = { - x: ((clientX - canvasRect.left) / this.state.zoom) - (initial.left) / this.state.zoom, - y: ((clientY - canvasRect.top) / this.state.zoom) - (initial.top) / this.state.zoom, + x: ((clientX - canvasRect.left) / this.state.zoom), + y: ((clientY - canvasRect.top) / this.state.zoom), } console.log("container: ", container) @@ -726,6 +727,11 @@ class Canvas extends React.Component { // y: (clientY - canvasRect.top) / this.state.zoom - (elementHeight / 2) / this.state.zoom, // } + finalPosition = { + x: finalPosition.x - initialOffset.x, + y: finalPosition.y - initialOffset.y + } + console.log(initial, current) let widgetId = draggedElement.getAttribute("data-widget-id") const widgetObj = this.getWidgetById(widgetId) @@ -1083,6 +1089,7 @@ class Canvas extends React.Component { } render() { + // FIXME: inner canvas not recognized as droppable or some thing return (
@@ -1120,7 +1127,7 @@ class Canvas extends React.Component {
{/* Canvas */} -
{ diff --git a/src/canvas/widgets/base.js b/src/canvas/widgets/base.js index c063049..03d49a0 100644 --- a/src/canvas/widgets/base.js +++ b/src/canvas/widgets/base.js @@ -805,7 +805,7 @@ class Widget extends React.Component { handleDragStart = (e, ) => { // NOTE: this line will prevent problem's such as self-drop or dropping inside its own children - setTimeout(this.disablePointerEvents, 1) + // setTimeout(this.disablePointerEvents, 1) this.setState({ isDragging: true }) } @@ -972,7 +972,8 @@ class Widget extends React.Component { handleDragEnd = () => { this.setState({ isDragging: false }) - this.enablePointerEvents() + // this.enablePointerEvents() + // console.log("enable pointer events: ") // this.props.onWidgetDragEnd(this.elementRef?.current) } @@ -1062,15 +1063,14 @@ class Widget extends React.Component { } // const boundingRect = this.getBoundingRect - // TODO: rewrite Drag and drop // FIXME: if the parent container has tw-overflow-none, then the resizable indicator are also hidden - // FIXME: renable pointer events + // FIXME: re-enable pointer events return ( // { - ({ draggedElement, widgetClass }) => { + ({ draggedElement, widgetClass, setInitialOffset }) => { return ( @@ -1081,7 +1081,7 @@ class Widget extends React.Component { dragElementType={this.getWidgetType()} droppableTags={this.droppableTags} className="tw-shadow-xl tw-w-fit tw-h-fit" - initialPos={{ ...this.state.pos }} + currentPos={{ ...this.state.pos }} onDragStart={this.handleDragStart} onDragOver={(e) => {this.handleDragOver(e, draggedElement)}} onDragEnd={(e) => this.handleDragEnd()} @@ -1090,6 +1090,8 @@ class Widget extends React.Component { onDragEnter={(e) => this.handleDragEnter(e, draggedElement)} // this is by droppable widgetRef={this.elementRef} + canvas={this.canvas} + // onDragOver={(e) => this.handleDragOver(e, draggedElement)} // onDrop={(e) => {this.handleDropEvent(e, draggedElement, widgetClass); onDragEnd()}} diff --git a/src/canvas/widgets/widgetDnd.js b/src/canvas/widgets/widgetDnd.js index 3c8f6fc..7f86a56 100644 --- a/src/canvas/widgets/widgetDnd.js +++ b/src/canvas/widgets/widgetDnd.js @@ -2,21 +2,25 @@ import React, { useEffect, useRef, useState } from 'react' import { useDragDropManager, useDroppable, useDraggable } from '@dnd-kit/react' import { useDragContext } from '../../components/draggable/draggableContext' import WidgetContainer from '../constants/containers' +import { useSortable } from '@dnd-kit/react/sortable' // FIXME: widget class is null -function WidgetDnd({widgetId, widgetRef, droppableTags, onDrop, onDragStart, - onDragEnd, onDragEnter, onDragOver, initialPos, +function WidgetDnd({widgetId, canvas, widgetRef, droppableTags,onMousePress, onDrop, onDragStart, + onDragEnd, onDragEnter, onDragOver, currentPos={x: 0, y: 0}, ...props}) { const dndRef = useRef(null) const {dragElementType} = props - const { draggedElement, setOverElement, widgetClass } = useDragContext() + const { draggedElement, setOverElement, widgetClass, setInitialOffset } = useDragContext() - const { ref: dropRef, isDropTarget, droppable} = useDroppable({ + const [isDropDisabled, setIsDropDisabled] = useState(false); + + const { ref: dropRef, droppable} = useDroppable({ id: widgetId, + disabled: isDropDisabled, // accept: (draggable) => { // const allowDrop = (droppableTags && droppableTags !== null && (Object.keys(droppableTags).length === 0 || @@ -37,6 +41,8 @@ function WidgetDnd({widgetId, widgetRef, droppableTags, onDrop, onDragStart, // data: { title: props.children } }) + + // const sortable = useSortable() const manager = useDragDropManager() @@ -45,6 +51,18 @@ function WidgetDnd({widgetId, widgetRef, droppableTags, onDrop, onDragStart, const [allowDrop, setAllowDrop] = useState(false) // indicator if the draggable can be dropped on the droppable useEffect(() => { + + if (draggable.isDragging){ + setIsDropDisabled(true) + }else{ + setIsDropDisabled(false) + } + + }, [draggable.isDragging]) + + useEffect(() => { + + canvas?.addEventListener("mousedown", handleInitialPosOffset) manager?.monitor?.addEventListener("dragstart", handleDragEnter) manager?.monitor?.addEventListener("dragend", handleDropEvent) @@ -55,8 +73,10 @@ function WidgetDnd({widgetId, widgetRef, droppableTags, onDrop, onDragStart, manager?.monitor?.removeEventListener("dragstart", handleDragEnter) manager?.monitor?.removeEventListener("dragend", handleDropEvent) manager?.monitor?.removeEventListener("dragmove", handleDragOver) + canvas?.removeEventListener("mousedown", handleInitialPosOffset) + } - }, [manager, draggedElement, widgetClass]) + }, [manager, draggedElement, widgetClass, canvas]) const handleRef = (node) => { @@ -66,15 +86,32 @@ function WidgetDnd({widgetId, widgetRef, droppableTags, onDrop, onDragStart, dragRef(node) } + const handleInitialPosOffset = (e) => { + + console.log("canvas bounding rect: ", canvas.getBoundingClientRect()) + + const {clientX, clientY} = e + + const canvasBoundingRect = canvas.getBoundingClientRect() + + const initialOffset = { + x: clientX - (currentPos.x + canvasBoundingRect.left), + y: clientY - (currentPos.y + canvasBoundingRect.top) + } + + setInitialOffset(initialOffset) + console.log("initial position calc: ", initialOffset, clientX, clientY) + + } + const handleDragEnter = (e) => { if (draggable.isDragSource){ - - console.log("widget class: ", widgetClass) + // if the current widget is being dragged - onDragContextStart(dndRef?.current, widgetClass, {}, initialPos) + onDragContextStart(dndRef?.current, widgetClass, {}) dndRef.current.style.zIndex = 10 @@ -121,7 +158,7 @@ function WidgetDnd({widgetId, widgetRef, droppableTags, onDrop, onDragStart, (droppableTags.exclude?.length > 0 && !droppableTags.exclude?.includes(dragElementType)) )) - + console.log("Drop allowed: ", dropAllowed, dragElementType ) setAllowDrop(dropAllowed) onDragOver(e) @@ -136,7 +173,7 @@ function WidgetDnd({widgetId, widgetRef, droppableTags, onDrop, onDragStart, onDragEnd(e) }else if (droppable.isDropTarget){ - setAllowDrop(false) + // setAllowDrop(false) if (!draggedElement || !draggedElement.getAttribute("data-drag-start-within")) { @@ -167,14 +204,14 @@ function WidgetDnd({widgetId, widgetRef, droppableTags, onDrop, onDragStart, data-widget-id={widgetId} data-container={WidgetContainer.CANVAS} data-draggable-type={dragElementType} - className={`${props.className || ''} tw-relative tw-h-max tw-w-max tw-outline-none`} + className={`${props.className || ''} ${draggable.isDragging && "tw-pointer-events-none"} tw-relative tw-h-max tw-w-max tw-outline-none`} > {props.children} { (droppable.isDropTarget && !draggable.isDragSource) && -
diff --git a/src/components/draggable/dnd/droppableDnd.js b/src/components/draggable/dnd/droppableDnd.js index ea81115..ceb4bff 100644 --- a/src/components/draggable/dnd/droppableDnd.js +++ b/src/components/draggable/dnd/droppableDnd.js @@ -8,7 +8,7 @@ function Droppable(props) { const droppableRef = useRef(null) const { droppableTags, onDrop } = props - const { draggedElement, setOverElement, widgetClass, initialPosition } = useDragContext() + const { draggedElement, setOverElement, widgetClass, initialOffset } = useDragContext() const { ref, isDropTarget, droppable} = useDroppable({ id: props.id, @@ -40,7 +40,7 @@ function Droppable(props) { manager?.monitor?.removeEventListener("dragend", handleDragLeave) manager?.monitor?.removeEventListener("dragmove", handleDragOver) } - }, [manager, draggedElement, widgetClass, initialPosition]) + }, [manager, draggedElement, widgetClass, initialOffset]) const handleRef = (node) => { @@ -117,9 +117,6 @@ function Droppable(props) { return } - setAllowDrop({allow: false, show: false}) - - if (!draggedElement || !draggedElement.getAttribute("data-drag-start-within")) { // if the drag is starting from outside (eg: file drop) or if drag doesn't exist return @@ -135,18 +132,21 @@ function Droppable(props) { (droppableTags.exclude?.length > 0 && !droppableTags.exclude?.includes(dragElementType)) )) - console.log("initial POs: ", initialPosition) + console.log("initial POs: ", initialOffset) if (onDrop && dropAllowed) { - onDrop(e, draggedElement, widgetClass, initialPosition) + onDrop(e, draggedElement, widgetClass, initialOffset) } + + setTimeout(() => setAllowDrop({allow: true, show: false}), 10) + } const handleDragLeave = (e) => { - const {target} = e.operation + // const {target} = e.operation - if (target && target.id === props.id){ + if (droppable.isDropTarget){ handleDropEvent(e) }else{ setAllowDrop({allow: false, show: false}) @@ -161,11 +161,15 @@ function Droppable(props) { {props.children} { - allowDrop.show && -
+ +
+ +
} diff --git a/src/components/draggable/draggableContext.js b/src/components/draggable/draggableContext.js index 693ec1a..e37ba26 100644 --- a/src/components/draggable/draggableContext.js +++ b/src/components/draggable/draggableContext.js @@ -12,7 +12,7 @@ export const DragProvider = ({ children }) => { const [draggedElement, setDraggedElement] = useState(null) const [overElement, setOverElement] = useState(null) // the element the dragged items is over - const [initialPosition, setInitialPosition] = useState({x: 0, y: 0}) + const [initialOffset, setInitialOffset] = useState({x: 0, y: 0}) const [dragElementMetaData, setDragElementMetaData] = useState({}) @@ -20,11 +20,10 @@ export const DragProvider = ({ children }) => { const [isDragging, setIsDragging] = useState(false) - const onDragStart = (element, widgetClass=null, metaData={}, initialPos={x: 0, y: 0}) => { + const onDragStart = (element, widgetClass=null, metaData={}) => { setDraggedElement(element) setIsDragging(true) - setInitialPosition(initialPos) setDragElementMetaData(metaData) if (widgetClass && !isSubClassOfWidget(widgetClass)) @@ -48,7 +47,7 @@ export const DragProvider = ({ children }) => { {children}