fix: fixed problem where the widget wasn't dropping to nearby by position
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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] `}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -21,7 +21,8 @@ function WidgetsContainer({onWidgetsUpdate}){
|
||||
{
|
||||
name: "TopLevel",
|
||||
img: ButtonWidget,
|
||||
link: "https://github.com"
|
||||
link: "https://github.com",
|
||||
// widgetType: Widget
|
||||
},
|
||||
{
|
||||
name: "Frame",
|
||||
|
||||
Reference in New Issue
Block a user