Files
PyUIBuilder/src/components/draggable/droppable.js

143 lines
4.8 KiB
JavaScript
Raw Normal View History

import { memo, useEffect, useState } from "react"
2024-09-16 12:23:15 +05:30
import { useDragContext } from "./draggableContext"
/**
* @param {{include: [], exclude: []} || {} || null} - droppableTags - if empty object, allows everything to be dropped, if null nothing can be dropped, define include to allow only included widgets, define exclude to exclude
*/
const DroppableWrapper = memo(({onDrop, droppableTags={}, ...props}) => {
2024-09-16 12:23:15 +05:30
2025-03-06 14:32:00 +05:30
const { draggedElement, posMetaData, setOverElement, widgetClass } = useDragContext()
2024-09-16 12:23:15 +05:30
const [showDroppable, setShowDroppable] = useState({
show: false,
allow: false
})
useEffect(() => {
if (draggedElement === null){
setShowDroppable({
show: false,
allow: false
})
}
}, [draggedElement])
2024-09-16 12:23:15 +05:30
const handleDragEnter = (e) => {
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
}
2024-09-16 12:23:15 +05:30
const dragElementType = draggedElement.getAttribute("data-draggable-type")
setOverElement(e.currentTarget)
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))
))
if (allowDrop){
2024-09-16 12:23:15 +05:30
setShowDroppable({
allow: true,
show: true
})
}else{
setShowDroppable({
allow: false,
show: true
})
}
}
const handleDragOver = (e) => {
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
}
2024-09-16 12:23:15 +05:30
// 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))
))
if (allowDrop){
2024-09-16 12:23:15 +05:30
e.preventDefault() // this is necessary to allow drop to take place
}
}
const handleDropEvent = (e) => {
setShowDroppable({
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
}
e.stopPropagation()
2024-09-16 12:23:15 +05:30
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))
))
2024-09-16 12:23:15 +05:30
if(onDrop && allowDrop){
2025-03-06 14:32:00 +05:30
onDrop(e, draggedElement, widgetClass, posMetaData)
2024-09-16 12:23:15 +05:30
}
}
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}
>
{props.children}
2024-09-16 12:23:15 +05:30
{
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 tw-pointer-events-none
2024-09-16 12:23:15 +05:30
`}>
</div>
}
</div>
)
})
export default DroppableWrapper