diff --git a/roadmap.md b/roadmap.md index b422298..786ef74 100644 --- a/roadmap.md +++ b/roadmap.md @@ -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 diff --git a/src/canvas/canvas.js b/src/canvas/canvas.js index 580568a..fc3a4c7 100644 --- a/src/canvas/canvas.js +++ b/src/canvas/canvas.js @@ -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 diff --git a/src/canvas/widgets/base.js b/src/canvas/widgets/base.js index ef8a0c1..1f3075f 100644 --- a/src/canvas/widgets/base.js +++ b/src/canvas/widgets/base.js @@ -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 ( - { ({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 */}
-
{ - }, []) - return ( // - +