reworking on drag context

This commit is contained in:
paul
2024-09-16 12:23:15 +05:30
parent f692af7f3f
commit f79b6514db
10 changed files with 184 additions and 151 deletions

View File

@@ -0,0 +1,51 @@
import { memo, useRef } from "react"
import { useDragContext } from "./draggableContext"
/**
*
* @param {string} - dragElementType - this will set the data-draggable-type which can be accessed on droppable to check if its allowed or not
* @returns
*/
const DraggableWrapper = memo(({dragElementType, className, children}) => {
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 (
<div className={`${className}`}
draggable
data-draggable-type={dragElementType}
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
ref={draggableRef}
>
{children}
</div>
)
})
export default DraggableWrapper

View File

@@ -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 (
<DragContext.Provider value={{ draggedElement, onDragStart, onDragEnd }}>
{children}
</DragContext.Provider>
)
}

View File

@@ -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 (
<div className={`${props.className}`}
onDragOver={handleDragOver}
onDrop={handleDropEvent}
onDragEnter={handleDragEnter}
onDragLeave={handleDragLeave}
>
{
showDroppable.show &&
<div className={`${showDroppable.allow ? "tw-border-green-600" : "tw-border-red-600"}
tw-absolute tw-top-0 tw-left-0 tw-w-full tw-h-full tw-z-[2]
tw-border-2 tw-border-dashed tw-rounded-lg
`}>
</div>
}
{props.children}
</div>
)
})
export default DroppableWrapper