fix: fixed problem where the widget wasn't dropping to nearby by position

This commit is contained in:
paul
2024-09-21 22:47:47 +05:30
parent 3ad39c74d6
commit a440b46e9b
5 changed files with 55 additions and 39 deletions

View File

@@ -7,6 +7,7 @@ Any feature that has 👑 beside it, is meant only for [premium users](./readme.
### 1.2.0
- [ ] UI fixes and enhancement
- [ ] Tree view for elements on the canvas
- [ ] Add text editor to support event handlers
- [ ] Rewrite DND for better feedback - (swappy/react-dnd-kit/ GSAP draggable)
- [ ] Duplicate widgets

View File

@@ -388,7 +388,6 @@ class Canvas extends React.Component {
* @returns
*/
handleResize = (event) => {
// FIXME: problem when resizing child element inside the child widget
if (this.state.resizing === "") return
const widget = this.state.selectedWidget
@@ -659,7 +658,7 @@ class Canvas extends React.Component {
if (swap) {
// If swapping, we need to find the common parent
const grandParentWidgetObj = this.findWidgetFromListById(dropWidgetObj.parent)
console.log("parent widget: ", grandParentWidgetObj, dropWidgetObj, this.state.widgets)
// console.log("parent widget: ", grandParentWidgetObj, dropWidgetObj, this.state.widgets)
if (grandParentWidgetObj) {
// Find the indices of the dragged and drop widgets in the grandparent's children array
const dragIndex = grandParentWidgetObj.children.findIndex(child => child.id === dragElementID)
@@ -846,21 +845,28 @@ class Canvas extends React.Component {
e.preventDefault()
const container = draggedElement.getAttribute("data-container")
console.log("Handle drop: ", container)
// console.log("Dropped on canvas",)
// const canvasContainerRect = this.getCanvasContainerBoundingRect()
const canvasRect = this.canvasRef.current.getBoundingClientRect()
const draggedElementRect = draggedElement.getBoundingClientRect()
const elementWidth = draggedElementRect.width
const elementHeight = draggedElementRect.height
const { clientX, clientY } = e
// const finalPosition = {
// x: (clientX - canvasRect.left) / this.state.zoom,
// y: (clientY - canvasRect.top) / this.state.zoom,
// }
// snaps to center
const finalPosition = {
x: (clientX - canvasRect.left) / this.state.zoom,
y: (clientY - canvasRect.top) / this.state.zoom,
x: (clientX - canvasRect.left) / this.state.zoom - (elementWidth / 2) / this.state.zoom,
y: (clientY - canvasRect.top) / this.state.zoom - (elementHeight / 2) / this.state.zoom,
}
if (container === WidgetContainer.SIDEBAR) {
// TODO: handle drop from sidebar
// if the widget is being dropped from the sidebar, use the info to create the widget first
this.createWidget(Widget, ({ id, widgetRef }) => {
widgetRef.current.setPos(finalPosition.x, finalPosition.y)
@@ -878,8 +884,6 @@ class Canvas extends React.Component {
} else if (container === WidgetContainer.WIDGET) {
// FIXME: move the widget out of the widget
// if the widget was inside another widget move it outside
let childWidgetObj = this.findWidgetFromListById(widgetObj.current.getId())
let parentWidgetObj = this.findWidgetFromListById(childWidgetObj.parent)
@@ -934,7 +938,6 @@ class Canvas extends React.Component {
renderWidget = (widget) => {
// FIXME: the child elements are being recreated instead of using the same object
const { id, widgetType: ComponentType, children = [], parent, initialData = {} } = widget

View File

@@ -602,12 +602,9 @@ class Widget extends React.Component {
handleDragStart = (e, callback) => {
e.stopPropagation()
this.setState({isDragging: true})
callback(this.elementRef?.current || null)
console.log("Drag start: ", this.elementRef)
// Create custom drag image with full opacity, this will ensure the image isn't taken from part of the canvas
const dragImage = this.elementRef?.current.cloneNode(true)
dragImage.style.opacity = '1' // Ensure full opacity
@@ -616,16 +613,31 @@ class Widget extends React.Component {
document.body.appendChild(dragImage)
const rect = this.elementRef?.current.getBoundingClientRect()
const offsetX = e.clientX - rect.left
const offsetY = e.clientY - rect.top
// snap to mouse pos
// const offsetX = e.clientX - rect.left
// const offsetY = e.clientY - rect.top
// snap to middle
const offsetX = rect.width / 2
const offsetY = rect.height / 2
// Set the custom drag image with correct offset to avoid snapping to the top-left corner
e.dataTransfer.setDragImage(dragImage, offsetX, offsetY)
// Remove the custom drag image after some time to avoid leaving it in the DOM
setTimeout(() => {
document.body.removeChild(dragImage)
}, 0)
setTimeout(() => {
// NOTE: this line will prevent problem's such as self-drop or dropping inside its own children
this.elementRef.current.style.pointerEvents = "none"
}, 1)
this.setState({isDragging: true})
}
handleDragEnter = (e, draggedElement, setOverElement) => {
@@ -700,20 +712,20 @@ class Widget extends React.Component {
return // prevent drop if the draggable element doesn't match
}
if (draggedElement === this.elementRef.current){
// prevent drop on itself, since the widget is invisible when dragging, if dropped on itself, it may consume itself
return
}
// if (draggedElement === this.elementRef.current){
// // prevent drop on itself, since the widget is invisible when dragging, if dropped on itself, it may consume itself
// return
// }
let currentElement = e.currentTarget
while (currentElement) {
if (currentElement === draggedElement) {
console.log("Dropped into a descendant element, ignoring drop")
return // Exit early to prevent the drop
}
currentElement = currentElement.parentElement // Traverse up to check ancestors
}
// let currentElement = e.currentTarget
// while (currentElement) {
// if (currentElement === draggedElement) {
// // if the parent is dropped accidentally into the child don't allow drop
// console.log("Dropped into a descendant element, ignoring drop")
// return // Exit early to prevent the drop
// }
// currentElement = currentElement.parentElement // Traverse up to check ancestors
// }
const container = draggedElement.getAttribute("data-container")
@@ -759,6 +771,7 @@ class Widget extends React.Component {
handleDragEnd = (callback) => {
callback()
this.setState({isDragging: false})
this.elementRef.current.style.pointerEvents = "auto"
}
@@ -787,14 +800,13 @@ class Widget extends React.Component {
left: `${this.state.pos.x}px`,
width: `${this.state.size.width}px`,
height: `${this.state.size.height}px`,
opacity: this.state.isDragging ? 0.3 : 1
opacity: this.state.isDragging ? 0.3 : 1,
}
// console.log("selected: ", this.state.dragEnabled)
return (
<DragContext.Consumer>
{
({draggedElement, onDragStart, onDragEnd, setOverElement}) => (
@@ -820,7 +832,7 @@ class Widget extends React.Component {
{/* FIXME: Swappable, when the parent layout is gap is 0, it doesn't work well */}
<div className="tw-relative tw-w-full tw-h-full tw-top-0 tw-left-0"
>
<div className={`tw-absolute tw-top-[-5px] tw-left-[-5px]
<div className={`tw-absolute tw-top-[-5px] tw-left-[-5px]
tw-border-1 tw-opacity-0 tw-border-solid tw-border-black
tw-w-full tw-h-full
tw-scale-[1.1] tw-opacity-1 tw-z-[-1] `}

View File

@@ -24,13 +24,12 @@ export function DraggableWidgetCard({ name, img, url, innerRef}){
}, [url])
useEffect(() => {
}, [])
return (
// <Draggable className="tw-cursor-pointer" id={name}>
<DraggableWrapper data-container={"sidebar"} dragElementType={"widget"} className="tw-cursor-pointer tw-w-fit tw-h-fit">
<DraggableWrapper data-container={"sidebar"}
dragElementType={"widget"}
className="tw-cursor-pointer tw-w-fit tw-h-fit">
<div ref={innerRef} className="tw-select-none tw-h-[200px] tw-w-[230px] tw-flex tw-flex-col
tw-rounded-md tw-overflow-hidden

View File

@@ -21,7 +21,8 @@ function WidgetsContainer({onWidgetsUpdate}){
{
name: "TopLevel",
img: ButtonWidget,
link: "https://github.com"
link: "https://github.com",
// widgetType: Widget
},
{
name: "Frame",