From f79b6514dbbb48001b9126958a41ade52f53a851 Mon Sep 17 00:00:00 2001 From: paul Date: Mon, 16 Sep 2024 12:23:15 +0530 Subject: [PATCH] reworking on drag context --- src/App.js | 36 +------- src/canvas/canvas.js | 25 +++--- src/canvas/toolbar.js | 2 +- src/components/cards.js | 6 +- src/components/draggable/draggable.js | 51 +++++++++++ src/components/draggable/draggableContext.js | 24 ++++++ src/components/draggable/droppable.js | 90 ++++++++++++++++++++ src/components/utils/draggable.js | 32 ------- src/components/utils/draggableDnd.js | 1 + src/components/utils/droppable.js | 68 --------------- 10 files changed, 184 insertions(+), 151 deletions(-) create mode 100644 src/components/draggable/draggable.js create mode 100644 src/components/draggable/draggableContext.js create mode 100644 src/components/draggable/droppable.js delete mode 100644 src/components/utils/draggable.js delete mode 100644 src/components/utils/droppable.js diff --git a/src/App.js b/src/App.js index 88734fd..d5389e1 100644 --- a/src/App.js +++ b/src/App.js @@ -12,6 +12,7 @@ import WidgetsContainer from './sidebar/widgetsContainer' import Widget from './canvas/widgets/base' import { DraggableWidgetCard } from './components/cards' +import { DragProvider } from './components/draggable/draggableContext' function App() { @@ -95,15 +96,6 @@ function App() { return } setDropAnimation(null) - - // FIXME: drop offset is not correct - // Calculate the dragged item's bounding rectangle - const itemRect = activeItemElement.getBoundingClientRect(); - const itemCenterX = itemRect.left + itemRect.width / 2 - const itemCenterY = itemRect.top + itemRect.height / 2 - - console.log("widget overlay: ", delta, itemRect) - // Get widget dimensions (assuming you have a way to get these) const widgetWidth = activeItemElement.offsetWidth; // Adjust this based on how you get widget size @@ -114,11 +106,6 @@ function App() { const canvasTranslate = canvasRef.current.getCanvasTranslation() const zoom = canvasRef.current.getZoom() - // let finalPosition = { - // x: (delta.x - canvasContainerRect.x - canvasTranslate.x) / zoom, - // y: (delta.y - canvasContainerRect.y - canvasTranslate.y) / zoom, - // } - let finalPosition = { x: (initialPosition.x + delta.x - canvasContainerRect.x - canvasTranslate.x) / zoom - (widgetWidth / 2), y: (initialPosition.y + delta.y - canvasContainerRect.y - canvasTranslate.y) / zoom - (widgetHeight / 2), @@ -151,32 +138,15 @@ function App() {
- +
{/* dragOverlay (dnd-kit) helps move items from one container to another */} - - {activeSidebarWidget ? ( - - ): - null} - -
+
) } diff --git a/src/canvas/canvas.js b/src/canvas/canvas.js index 5046b94..453ec94 100644 --- a/src/canvas/canvas.js +++ b/src/canvas/canvas.js @@ -18,7 +18,7 @@ import { WidgetContext } from './context/widgetContext' // import {ReactComponent as DotsBackground} from "../assets/background/dots.svg" import DotsBackground from "../assets/background/dots.svg" -import DroppableWrapper from "../components/utils/droppable" +import DroppableWrapper from "../components/draggable/droppable" // const DotsBackground = require("../assets/background/dots.svg") @@ -527,28 +527,23 @@ class Canvas extends React.Component { } + /** + * Handles drop event to canvas from the sidebar + * @param {DragEvent} e + */ handleDropEvent = (e) => { e.preventDefault() - console.log("event: ", e, this.canvasContainerRef.current.offsetTop) - // const canvasContainerRect = this.getCanvasContainerBoundingRect() const canvasRect = this.canvasRef.current.getBoundingClientRect() - - console.log("canvas rect: ", canvasRect) - const { clientX, clientY } = e - let finalPosition = { - x: (e.clientX - canvasRect.left) / this.state.zoom, - y: (e.clientY - canvasRect.top) / this.state.zoom, + const finalPosition = { + x: (clientX - canvasRect.left) / this.state.zoom, + y: (clientY - canvasRect.top) / this.state.zoom, } - - - console.log("final: ", finalPosition, finalPosition.x*this.state.zoom, finalPosition.y*this.state.zoom, this.state.zoom) - this.addWidget(Widget, ({id, widgetRef}) => { widgetRef.current.setPos(finalPosition.x, finalPosition.y) }) @@ -606,10 +601,10 @@ class Canvas extends React.Component { {/* */} - {/* */} + /> ) } diff --git a/src/canvas/toolbar.js b/src/canvas/toolbar.js index d51bb57..b5a3d6d 100644 --- a/src/canvas/toolbar.js +++ b/src/canvas/toolbar.js @@ -116,7 +116,7 @@ const CanvasToolBar = memo(({ isOpen, widgetType, attrs = {} }) => { return (
- + +
{ + + const { onDragStart, onDragEnd } = useDragContext() + + const draggableRef = useRef(null) + + /** + * + * @param {DragEvent} event + */ + const handleDragStart = (event) => { + + // event.dataTransfer.setData("text/plain", "") + + if (onDragStart) + onDragStart(draggableRef?.current) + + + } + + const handleDragEnd = (e) => { + // console.log("Drag end: ", e, e.target.closest('div')) + + onDragEnd() + } + + return ( +
+ {children} +
+ ) + +}) + + +export default DraggableWrapper \ No newline at end of file diff --git a/src/components/draggable/draggableContext.js b/src/components/draggable/draggableContext.js new file mode 100644 index 0000000..7d77f15 --- /dev/null +++ b/src/components/draggable/draggableContext.js @@ -0,0 +1,24 @@ +import React, { createContext, useContext, useState } from 'react'; + +const DragContext = createContext() + +export const useDragContext = () => useContext(DragContext) + +// Provider component to wrap around parts of your app that need drag-and-drop functionality +export const DragProvider = ({ children }) => { + const [draggedElement, setDraggedElement] = useState(null) + + const onDragStart = (element) => { + setDraggedElement(element) + } + + const onDragEnd = () => { + setDraggedElement(null) + } + + return ( + + {children} + + ) +} diff --git a/src/components/draggable/droppable.js b/src/components/draggable/droppable.js new file mode 100644 index 0000000..569f33f --- /dev/null +++ b/src/components/draggable/droppable.js @@ -0,0 +1,90 @@ +import { memo, useState } from "react" +import { useDragContext } from "./draggableContext" + + +const DroppableWrapper = memo(({onDrop, droppableTags=["widget"], ...props}) => { + + + const { draggedElement } = useDragContext() + + const [showDroppable, setShowDroppable] = useState({ + show: false, + allow: false + }) + + + const handleDragEnter = (e) => { + console.log("Drag Enter", draggedElement) + + const dragElementType = draggedElement.getAttribute("data-draggable-type") + + if (droppableTags.length === 0 || droppableTags.includes(dragElementType)){ + setShowDroppable({ + allow: true, + show: true + }) + }else{ + setShowDroppable({ + allow: false, + show: true + }) + } + } + + const handleDragOver = (e) => { + // console.log("Drag over: ", e.dataTransfer.getData("text/plain"), e.dataTransfer) + const dragElementType = draggedElement.getAttribute("data-draggable-type") + + if (droppableTags.length === 0 || droppableTags.includes(dragElementType)){ + e.preventDefault() // this is necessary to allow drop to take place + } + + } + + const handleDropEvent = (e) => { + console.log("Drag over: ", e.dataTransfer.getData("text/plain"), e.dataTransfer) + + setShowDroppable({ + allow: false, + show: false + }) + + if(onDrop){ + onDrop(e) + } + } + + + const handleDragLeave = (e) => { + if (!e.currentTarget.contains(e.relatedTarget)) { + setShowDroppable({ + allow: false, + show: false + }) + } + } + + return ( +
+ { + showDroppable.show && +
+
+ } + {props.children} + +
+ ) + +}) + + +export default DroppableWrapper \ No newline at end of file diff --git a/src/components/utils/draggable.js b/src/components/utils/draggable.js deleted file mode 100644 index 6b0b7eb..0000000 --- a/src/components/utils/draggable.js +++ /dev/null @@ -1,32 +0,0 @@ - - -const DraggableWrapper = (props) => { - - - const handleDragStart = () => { - console.log("Drag start") - } - - const handleDragOver = () => { - // console.log("Drag over") - } - - const handleDragEnd = (e) => { - // console.log("Drag end: ", e, e.target.closest('div')) - - } - - return ( -
- {props.children} -
- ) - -} - - -export default DraggableWrapper \ No newline at end of file diff --git a/src/components/utils/draggableDnd.js b/src/components/utils/draggableDnd.js index 7cca531..2cb3238 100644 --- a/src/components/utils/draggableDnd.js +++ b/src/components/utils/draggableDnd.js @@ -2,6 +2,7 @@ import React from "react" import {useDraggable} from "@dnd-kit/core" import { CSS } from "@dnd-kit/utilities" + function Draggable(props) { const {attributes, listeners, setNodeRef, transform} = useDraggable({ id: props.id, diff --git a/src/components/utils/droppable.js b/src/components/utils/droppable.js deleted file mode 100644 index 6c6c259..0000000 --- a/src/components/utils/droppable.js +++ /dev/null @@ -1,68 +0,0 @@ -import { useState } from "react" - - -const DroppableWrapper = ({onDrop, ...props}) => { - - - const [showDroppable, setShowDroppable] = useState({ - show: false, - allow: false - }) - - const handleDragEnter = () => { - console.log("Drag start") - setShowDroppable({ - allow: true, - show: true - }) - } - - const handleDragOver = (e) => { - // console.log("Drag over: ", e) - e.preventDefault() - } - - const handleDropEvent = (e) => { - - setShowDroppable({ - allow: false, - show: false - }) - - if(onDrop){ - onDrop(e) - } - } - - - const handleDragLeave = (e) => { - if (!e.currentTarget.contains(e.relatedTarget)) { - setShowDroppable({ - allow: false, - show: false - }) - } - } - - return ( -
- {/* { - showDroppable.show && -
-
- } */} - {props.children} - -
- ) - -} - - -export default DroppableWrapper \ No newline at end of file