diff --git a/package-lock.json b/package-lock.json index 60ed607..02cf4ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.0", "dependencies": { "@ant-design/icons": "^5.4.0", - "@dnd-kit/core": "^6.1.0", + "@dnd-kit/core": "^6.3.1", "@dnd-kit/dom": "^0.0.9", "@dnd-kit/modifiers": "^7.0.0", "@dnd-kit/react": "^0.0.9", @@ -2562,9 +2562,10 @@ } }, "node_modules/@dnd-kit/accessibility": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.0.tgz", - "integrity": "sha512-ea7IkhKvlJUv9iSHJOnxinBcoOI3ppGnnL+VDJ75O45Nss6HtZd8IdN8touXPDtASfeI2T2LImb8VOZcL47wjQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz", + "integrity": "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==", + "license": "MIT", "dependencies": { "tslib": "^2.0.0" }, @@ -2584,11 +2585,12 @@ } }, "node_modules/@dnd-kit/core": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.1.0.tgz", - "integrity": "sha512-J3cQBClB4TVxwGo3KEjssGEXNJqGVWx17aRTZ1ob0FliR5IjYgTxl5YJbKTzA6IzrtelotH19v6y7uoIRUZPSg==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz", + "integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==", + "license": "MIT", "dependencies": { - "@dnd-kit/accessibility": "^3.1.0", + "@dnd-kit/accessibility": "^3.1.1", "@dnd-kit/utilities": "^3.2.2", "tslib": "^2.0.0" }, diff --git a/package.json b/package.json index 6487559..29ff924 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ }, "dependencies": { "@ant-design/icons": "^5.4.0", - "@dnd-kit/core": "^6.1.0", + "@dnd-kit/core": "^6.3.1", "@dnd-kit/dom": "^0.0.9", "@dnd-kit/modifiers": "^7.0.0", "@dnd-kit/react": "^0.0.9", diff --git a/src/App.js b/src/App.js index 9608a0e..ea78a87 100644 --- a/src/App.js +++ b/src/App.js @@ -34,6 +34,7 @@ import TkMainWindow from './frameworks/tkinter/widgets/mainWindow' import CTkMainWindow from './frameworks/customtk/widgets/mainWindow' import { DndContext, DragOverlay } from '@dnd-kit/core' import { SidebarOverlayWidgetCard, SidebarWidgetCard } from './components/cards' +import { DragDropProvider } from '@dnd-kit/react' function App() { @@ -217,7 +218,7 @@ function App() {

Are you sure you want to change the framework? This will clear the canvas.

*/} - + {console.log("Drag start event: ", e)}}>
@@ -241,7 +242,7 @@ function App() { ) } - +
) diff --git a/src/canvas/canvas.js b/src/canvas/canvas.js index 95154d2..bcc4bb0 100644 --- a/src/canvas/canvas.js +++ b/src/canvas/canvas.js @@ -687,30 +687,38 @@ class Canvas extends React.Component { } const container = draggedElement.getAttribute("data-container") + const canvasRect = this.canvasRef.current.getBoundingClientRect() - const draggedElementRect = draggedElement.getBoundingClientRect() const elementWidth = draggedElementRect.width const elementHeight = draggedElementRect.height - const {x: draggedElementInitialX, y: draggedElementInitialY} = draggedElement.getBoundingClientRect() - + // const {x: draggedElementInitialX, y: draggedElementInitialY} = draggedElement.getBoundingClientRect() + // const { clientX, clientY } = e const { x: clientX, y: clientY} = e.delta; + const {clientX: draggedElementInitialX, clientY: draggedElementInitialY} = e.activatorEvent - console.log("wirking: ", clientX, clientY, draggedElement.getBoundingClientRect()) + console.log("wirking: ", clientX, clientY, e, draggedElementInitialX, draggedElementInitialY) // let finalPosition = { // x: (clientX - canvasRect.left) / this.state.zoom, // y: (clientY - canvasRect.top) / this.state.zoom, // } + // let finalPosition = { + // x: ((draggedElementInitialX + clientX) - canvasRect.left) / (this.state.zoom), + // y: ((draggedElementInitialY + clientY) - canvasRect.top) / (this.state.zoom), + // } let finalPosition = { - x: ((draggedElementInitialX + clientX) - canvasRect.left) / (1 || this.state.zoom), - y: ((draggedElementInitialY + clientY) - canvasRect.top) / (1 ||this.state.zoom), + x: (e.activatorEvent.pageX - canvasRect.left) / (this.state.zoom), + y: (e.activatorEvent.pageY - canvasRect.top) / (this.state.zoom), } - console.log("final position: ", finalPosition, draggedElementInitialX, clientX, canvasRect.left) + // FIXME: error in canvasRect.top + + console.log("final position: ", finalPosition, draggedElementInitialX, clientX, canvasRect, "Top: ", + canvasRect.top, clientY, draggedElementInitialY) if (container === WidgetContainer.SIDEBAR) { diff --git a/src/components/draggable/dnd/draggableDnd.js b/src/components/draggable/dnd/draggableDnd.js index aa15f90..4001a4c 100644 --- a/src/components/draggable/dnd/draggableDnd.js +++ b/src/components/draggable/dnd/draggableDnd.js @@ -1,5 +1,5 @@ import React, { useEffect, useRef } from "react" -import { useDndMonitor, useDraggable } from "@dnd-kit/core" +import { useDraggable } from "@dnd-kit/react" import { CSS } from "@dnd-kit/utilities" import { useDragContext } from "../draggableContext" @@ -8,37 +8,40 @@ function Draggable(props) { const draggableRef = useRef(null) - const { attributes, listeners, setNodeRef, transform } = useDraggable({ + const { ref } = useDraggable({ id: props.id, - data: { title: props.children } + feedback: "clone" + // data: { title: props.children } }) const {onDragStart, onDragEnd, disableStyle=false} = useDragContext() - useDndMonitor({ - onDragStart(event){ - if (event.active.id === props.id) { // Ensure only this element triggers it - handleDragStart() - } - }, - onDragEnd(event){ - if (event.active.id === props.id) { // Ensure only this element triggers it - handleDragEnd() - } - }, - }) + // TODO: add monitor and handle drag events ASAP - useEffect(() => { + // useDndMonitor({ + // onDragStart(event){ + // if (event.active.id === props.id) { // Ensure only this element triggers it + // handleDragStart() + // } + // }, + // onDragEnd(event){ + // if (event.active.id === props.id) { // Ensure only this element triggers it + // handleDragEnd() + // } + // }, + // }) + + // useEffect(() => { - if (draggableRef.current) - setNodeRef(draggableRef.current) + // if (draggableRef.current) + // setNodeRef(draggableRef.current) - }, [draggableRef.current, setNodeRef]) + // }, [draggableRef.current, setNodeRef]) const { dragElementType, dragWidgetClass = null, elementMetaData } = props - const style = transform ? { - transform: CSS.Translate.toString(transform), - } : undefined + // const style = transform ? { + // transform: CSS.Translate.toString(transform), + // } : undefined const handleDragStart = (event) => { @@ -61,15 +64,13 @@ function Draggable(props) { return (
{props.children}
diff --git a/src/components/draggable/dnd/droppableDnd.js b/src/components/draggable/dnd/droppableDnd.js index 7914050..bfa7d32 100644 --- a/src/components/draggable/dnd/droppableDnd.js +++ b/src/components/draggable/dnd/droppableDnd.js @@ -1,5 +1,5 @@ import React, { useEffect, useRef, useState } from 'react' -import { useDndMonitor, useDroppable } from '@dnd-kit/core' +import { useDragDropManager, useDroppable } from '@dnd-kit/react' import { useDragContext } from '../draggableContext' @@ -7,49 +7,60 @@ function Droppable(props) { const droppableRef = useRef(null) - // const [dragPosition, setDragPosition] = useState({ - // startX: 0, - // startY: 0, - // endX: 0, - // endY: 0 - // }) - - const { isOver, setNodeRef } = useDroppable({ + const { isOver, ref, isDropTarget, droppable } = useDroppable({ id: props.id, + }) const style = { backgroundColor: isOver ? 'green' : '', } - useDndMonitor({ - onDragStart: (event) => { - if (event.over?.id === props.id){ - handleDragEnter(event) - // setDragPosition({ - // ...dragPosition, - // startX: event.over. - // }) + // const manager = useDragDropManager({ + // onDragStart: (event) => { + // if (event.over?.id === props.id){ + // handleDragEnter(event) + // // setDragPosition({ + // // ...dragPosition, + // // startX: event.over. + // // }) - console.log("starting: ", event) - } - }, - onDragMove: (event) => { - console.log("Drag move: ", event.active.rect) - if (event.over?.id === props.id) - handleDragOver(event) - }, - onDragEnd: (event) => { + // } + // console.log("starting: ", event) + // }, + // onDragMove: (event) => { + // console.log("Drag move: ", event.active.rect) + // if (event.over?.id === props.id) + // handleDragOver(event) + // }, + // onDragEnd: (event) => { + + // if (event.over?.id === props.id){ + // if (event.over) { + // handleDropEvent(event) // Item was dropped inside a valid container + // } else { + // handleDragLeave(event) // Drag was canceled + // } + // } + // }, + // }) + + const manager = useDragDropManager() + + useEffect(() => { + + manager?.monitor?.addEventListener("dragstart", handleDragEnter) + manager?.monitor?.addEventListener("dragend", handleDragLeave) + manager?.monitor?.addEventListener("dragover", handleDragOver) + + + return () => { + manager?.monitor?.removeEventListener("dragstart", handleDragEnter) + manager?.monitor?.removeEventListener("dragend", handleDragLeave) + manager?.monitor?.removeEventListener("dragover", handleDragOver) + } + }, [manager]) - if (event.over?.id === props.id){ - if (event.over) { - handleDropEvent(event) // Item was dropped inside a valid container - } else { - handleDragLeave(event) // Drag was canceled - } - } - }, - }) const { droppableTags, onDrop } = props @@ -59,27 +70,24 @@ function Droppable(props) { const [allowDrop, setAllowDrop] = useState(false) // indicator if the draggable can be dropped on the droppable - useEffect(() => { + // useEffect(() => { - if (droppableRef.current) - setNodeRef(droppableRef.current) + // if (droppableRef.current) + // setNodeRef(droppableRef.current) - }, [droppableRef.current, setNodeRef]) + // }, [droppableRef.current, setNodeRef]) - useEffect(() => { - - if (draggedElement === null) { - setAllowDrop({ - show: false, - allow: false - }) - } - - }, [draggedElement]) // TODO: handle Drop on Canvas const handleDragEnter = (e) => { + + const {target} = e.operation + + if (target && target?.id !== props?.id){ + return + } + 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 @@ -100,6 +108,14 @@ function Droppable(props) { const handleDragOver = (e) => { + const {target} = e.operation + + if (target && target?.id !== props?.id){ + return + } + console.log("Over sir1: ", draggedElement) + + 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 @@ -107,12 +123,15 @@ function Droppable(props) { // console.log("Drag over: ", e.dataTransfer.getData("text/plain"), e.dataTransfer) const dragElementType = draggedElement.getAttribute("data-draggable-type") - + const allowDrop = (droppableTags && droppableTags !== null && (Object.keys(droppableTags).length === 0 || (droppableTags.include?.length > 0 && droppableTags.include?.includes(dragElementType)) || (droppableTags.exclude?.length > 0 && !droppableTags.exclude?.includes(dragElementType)) )) + console.log("Over sir: ", allowDrop) + + setAllowDrop(allowDrop) // if (allowDrop) { // e.preventDefault() // this is necessary to allow drop to take place @@ -122,10 +141,13 @@ function Droppable(props) { const handleDropEvent = (e) => { - setAllowDrop({ - allow: false, - show: false - }) + const {target} = e.operation + + if (target && target?.id !== props?.id){ + return + } + + setAllowDrop(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 @@ -150,16 +172,20 @@ function Droppable(props) { const handleDragLeave = (e) => { - if (!e.currentTarget.contains(e.relatedTarget)) { - setAllowDrop({ - allow: false, - show: false - }) + + const {target} = e.operation + + console.log("Drag: ", target?.id, props.id) + if (target && target.id === props.id){ + handleDropEvent(e) + }else{ + setAllowDrop(false) } + } return ( -
+
{props.children} {/* { showDroppable.show && @@ -171,7 +197,7 @@ function Droppable(props) { } */} { - isOver && + isDropTarget &&
{ const [draggedElement, setDraggedElement] = useState(null) const [overElement, setOverElement] = useState(null) // the element the dragged items is over + const [dragElementMetaData, setDragElementMetaData] = useState({}) const [widgetClass, setWidgetClass] = useState(null) // helper to help pass the widget type from sidebar to canvas const [isDragging, setIsDragging] = useState(false) - const onDragStart = (element, widgetClass=null, metaData={}) => { + const onDragStart = (element, widgetClass=null, metaData={}, pos={x: 0, y: 0}) => { setDraggedElement(element) setIsDragging(true) setDragElementMetaData(metaData) @@ -26,9 +28,11 @@ export const DragProvider = ({ children }) => { throw new Error("widgetClass must inherit from the Widget base class") setWidgetClass(() => widgetClass) // store the class so later it can be passed to the canvas from sidebar + + } - const onDragEnd = () => { + const onDragEnd = (pos) => { setDraggedElement(null) setWidgetClass(null) setIsDragging(false) @@ -40,7 +44,7 @@ export const DragProvider = ({ children }) => { return ( {children}