working with dnd-kit/react
This commit is contained in:
18
package-lock.json
generated
18
package-lock.json
generated
@@ -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"
|
||||
},
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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() {
|
||||
<p>Are you sure you want to change the framework? This will clear the canvas.</p>
|
||||
</Modal> */}
|
||||
|
||||
<DndContext autoScroll={false}>
|
||||
<DragDropProvider onDragStart={(e) => {console.log("Drag start event: ", e)}}>
|
||||
<div className="tw-w-full tw-h-[94vh] tw-flex">
|
||||
<Sidebar tabs={sidebarTabs}/>
|
||||
|
||||
@@ -241,7 +242,7 @@ function App() {
|
||||
)
|
||||
}
|
||||
|
||||
</DndContext>
|
||||
</DragDropProvider>
|
||||
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 (
|
||||
<div
|
||||
{...props}
|
||||
ref={draggableRef}
|
||||
ref={ref}
|
||||
className={`${props.className}`}
|
||||
// style={!disableStyle ? style : null} //enable this to show like the original item is moving, if commented out the original item will not have css effects
|
||||
draggable
|
||||
data-drag-start-within // this attribute indicates that the drag is occurring from within the project and not a outside file drop
|
||||
data-draggable-type={dragElementType}
|
||||
|
||||
{...listeners}
|
||||
{...attributes}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
|
||||
@@ -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 (
|
||||
<div ref={droppableRef} style={style} className={props.className || ''}>
|
||||
<div ref={ref} style={style} className={props.className || ''}>
|
||||
{props.children}
|
||||
{/* {
|
||||
showDroppable.show &&
|
||||
@@ -171,7 +197,7 @@ function Droppable(props) {
|
||||
} */}
|
||||
|
||||
{
|
||||
isOver &&
|
||||
isDropTarget &&
|
||||
<div className={`${allowDrop ? "tw-bg-[#82ff1c6e]" : "tw-bg-[#eb5d366e]"}
|
||||
tw-absolute tw-top-0 tw-left-0 tw-w-full tw-h-full tw-z-[999]
|
||||
tw-border-2 tw-border-dashed tw-rounded-lg tw-pointer-events-none
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { createContext, useContext, useState } from 'react'
|
||||
import { isSubClassOfWidget } from '../../utils/widget'
|
||||
import { useDndContext } from '@dnd-kit/core'
|
||||
// import Widget from '../../canvas/widgets/base'
|
||||
|
||||
export const DragContext = createContext()
|
||||
@@ -11,13 +12,14 @@ export const DragProvider = ({ children }) => {
|
||||
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 (
|
||||
<DragContext.Provider value={{ draggedElement, overElement, setOverElement,
|
||||
widgetClass, onDragStart, onDragEnd, isDragging,
|
||||
dragElementMetaData, setDragElementMetaData
|
||||
dragElementMetaData, setDragElementMetaData,
|
||||
}}>
|
||||
{children}
|
||||
</DragContext.Provider>
|
||||
|
||||
Reference in New Issue
Block a user