From 268d4a1aef1cf6bb2711b5eaf5ad0beb80b39d31 Mon Sep 17 00:00:00 2001 From: Nakul Nagargade Date: Thu, 26 Jun 2025 15:34:45 +0530 Subject: [PATCH] Fixes --- .../src/AppBuilder/AppCanvas/Container.jsx | 3 +-- .../src/AppBuilder/AppCanvas/Grid/Grid.jsx | 27 +++++++++---------- .../AppBuilder/AppCanvas/appCanvasUtils.js | 22 ++++++++------- .../AppCanvas/useCanvasDropHandler.js | 20 +++++++------- .../ComponentManagerTab/DragLayer.jsx | 21 +++------------ .../src/AppBuilder/_hooks/useGhostMoveable.js | 18 +++---------- frontend/src/_stores/gridStore.js | 6 ++++- 7 files changed, 46 insertions(+), 71 deletions(-) diff --git a/frontend/src/AppBuilder/AppCanvas/Container.jsx b/frontend/src/AppBuilder/AppCanvas/Container.jsx index 4bdafa8a15..c9fe887257 100644 --- a/frontend/src/AppBuilder/AppCanvas/Container.jsx +++ b/frontend/src/AppBuilder/AppCanvas/Container.jsx @@ -105,7 +105,7 @@ export const Container = React.memo( const canvasId = closestCanvas?.getAttribute('data-parentId') || closestCanvas?.id?.replace('canvas-', '') || - (closestCanvas?.id === 'real-canvas' ? 'canvas' : null); + (closestCanvas?.id === 'real-canvas' ? 'real-canvas' : null); // Only update if this container is the most specific one under the mouse if (canvasId === id) { @@ -126,7 +126,6 @@ export const Container = React.memo( } }, drop: (item, monitor) => { - console.log('Container drop', item, monitor.getClientOffset()); handleDrop(item, monitor, id); }, collect: (monitor) => ({ diff --git a/frontend/src/AppBuilder/AppCanvas/Grid/Grid.jsx b/frontend/src/AppBuilder/AppCanvas/Grid/Grid.jsx index 297be699a0..b1e297c40e 100644 --- a/frontend/src/AppBuilder/AppCanvas/Grid/Grid.jsx +++ b/frontend/src/AppBuilder/AppCanvas/Grid/Grid.jsx @@ -86,6 +86,7 @@ export default function Grid({ gridWidth, currentLayout }) { const getExposedValueOfComponent = useStore((state) => state.getExposedValueOfComponent, shallow); const setReorderContainerChildren = useStore((state) => state.setReorderContainerChildren, shallow); const currentDragCanvasId = useGridStore((state) => state.currentDragCanvasId, shallow); + const groupedTargets = [...findHighestLevelofSelection().map((component) => '.ele-' + component.id)]; const snapContainer = useMemo(() => { if (currentDragCanvasId) { @@ -97,12 +98,12 @@ export default function Grid({ gridWidth, currentLayout }) { return '#real-canvas'; }, [currentDragCanvasId, dragParentId]); - const moveableTarget = useMemo(() => { + const getMoveableTarget = () => { if (virtualTarget) { return '#moveable-ghost-element'; } return groupedTargets?.length > 1 ? groupedTargets : '.target'; - }, [virtualTarget, groupedTargets]); + }; // Set moveable reference in grid store for access by other components useEffect(() => { @@ -326,8 +327,6 @@ export default function Grid({ gridWidth, currentLayout }) { }); }, [selectedComponents]); - const groupedTargets = [...findHighestLevelofSelection().map((component) => '.ele-' + component.id)]; - useEffect(() => { reloadGrid(); // eslint-disable-next-line react-hooks/exhaustive-deps @@ -601,7 +600,7 @@ export default function Grid({ gridWidth, currentLayout }) { multiComponentHandle: groupedTargets.length > 1, }} flushSync={flushSync} - target={moveableTarget} + target={getMoveableTarget()} origin={false} individualGroupable={virtualTarget ? false : groupedTargets.length <= 1} draggable={!shouldFreeze && mode !== 'view'} @@ -883,11 +882,8 @@ export default function Grid({ gridWidth, currentLayout }) { handleActivateNonDraggingComponents(); }} onDragEnd={(e) => { - console.log('e.lastEvent', moveableRef); handleDeactivateTargets(); if (e.target.id === 'moveable-ghost-element') { - console.log('e.target', false); - // e.target.remove(); return; } try { @@ -953,12 +949,13 @@ export default function Grid({ gridWidth, currentLayout }) { const _gridWidth = useGridStore.getState().subContainerWidths[currentDragCanvasId] || gridWidth; let left = e.translate[0]; let top = e.translate[1]; - // console.log('e.translate', e.translate); - // if (currentDragCanvasId === 'canvas') { - // console.log('e.translate', e.translate, _gridWidth); - left = Math.round(e.translate[0] / _gridWidth) * _gridWidth; - top = Math.round(e.translate[1] / GRID_HEIGHT) * GRID_HEIGHT; - console.log('e.translate', e.translate, left, top); + + if (currentDragCanvasId === 'canvas') { + left = Math.round(e.translate[0] / _gridWidth) * _gridWidth; + top = Math.round(e.translate[1] / GRID_HEIGHT) * GRID_HEIGHT; + } + + useGridStore.getState().actions.setGhostDragPosition({ left, top, e }); e.target.style.transform = `translate(${left}px, ${top}px)`; return false; } @@ -1152,7 +1149,7 @@ export default function Grid({ gridWidth, currentLayout }) { }} // snapGridAll={true} scrollable={true} - snapContainer={snapContainer} + // snapContainer={snapContainer} // snapGridWidth={100} /> diff --git a/frontend/src/AppBuilder/AppCanvas/appCanvasUtils.js b/frontend/src/AppBuilder/AppCanvas/appCanvasUtils.js index fd58bf2959..228af4225e 100644 --- a/frontend/src/AppBuilder/AppCanvas/appCanvasUtils.js +++ b/frontend/src/AppBuilder/AppCanvas/appCanvasUtils.js @@ -5,7 +5,7 @@ import useStore from '@/AppBuilder/_stores/store'; import { toast } from 'react-hot-toast'; import _, { debounce } from 'lodash'; import { useGridStore } from '@/_stores/gridStore'; -import { findHighestLevelofSelection } from './Grid/gridUtils'; +import { findHighestLevelofSelection, getMouseDistanceFromParentDiv } from './Grid/gridUtils'; import { CANVAS_WIDTHS, NO_OF_GRIDS, @@ -34,26 +34,28 @@ export const addNewWidgetToTheEditor = ( parentId, moduleInfo = undefined ) => { - const canvasBoundingRect = realCanvasRef?.current?.getBoundingClientRect() || realCanvasRef?.getBoundingClientRect(); + const canvasBoundingRect = realCanvasRef?.getBoundingClientRect(); const componentMeta = componentTypes.find((component) => component.component === componentType); const componentName = computeComponentName(componentType, useStore.getState().getCurrentPageComponents()); - + const parentCanvasType = realCanvasRef?.getAttribute('component-type'); const componentData = deepClone(componentMeta); const defaultWidth = componentData.defaultSize.width; const defaultHeight = componentData.defaultSize.height; - const offsetFromTopOfWindow = canvasBoundingRect?.top; - const offsetFromLeftOfWindow = canvasBoundingRect?.left; - const currentOffset = eventMonitorObject?.getSourceClientOffset(); + const { e } = useGridStore.getState().getGhostDragPosition(); const subContainerWidth = canvasBoundingRect?.width; - let left = Math.round(currentOffset?.x - offsetFromLeftOfWindow); - let top = Math.round(currentOffset?.y - offsetFromTopOfWindow); - - [left, top] = snapToGrid(subContainerWidth, left, top); + const { left: left3, top: top3 } = getMouseDistanceFromParentDiv( + e, + parentId === 'canvas' ? 'real-canvas' : parentId, + parentCanvasType + ); + // [left, top] = snapToGrid(subContainerWidth, left, top); + let [left, top] = snapToGrid(subContainerWidth, left3, top3); const gridWidth = subContainerWidth / NO_OF_GRIDS; left = Math.round(left / gridWidth); + // Adjust widget width based on the dropping canvas width const mainCanvasWidth = useGridStore.getState().subContainerWidths['canvas']; let width = Math.round((defaultWidth * mainCanvasWidth) / gridWidth); diff --git a/frontend/src/AppBuilder/AppCanvas/useCanvasDropHandler.js b/frontend/src/AppBuilder/AppCanvas/useCanvasDropHandler.js index 557ec8a697..b17bfc3880 100644 --- a/frontend/src/AppBuilder/AppCanvas/useCanvasDropHandler.js +++ b/frontend/src/AppBuilder/AppCanvas/useCanvasDropHandler.js @@ -9,6 +9,7 @@ import { isPDFSupported } from '@/_helpers/appUtils'; import toast from 'react-hot-toast'; import { useModuleContext } from '@/AppBuilder/_contexts/ModuleContext'; import { useGhostMoveable } from '../_hooks/useGhostMoveable'; +import { handleDeactivateTargets, hideGridLines } from '../AppCanvas/Grid/gridUtils'; export const useCanvasDropHandler = ({ appType }) => { const { moduleId } = useModuleContext(); @@ -20,20 +21,17 @@ export const useCanvasDropHandler = ({ appType }) => { const currentLayout = useStore((state) => state.currentLayout, shallow); const setCurrentDragCanvasId = useGridStore((state) => state.actions.setCurrentDragCanvasId); const { deactivateGhost } = useGhostMoveable(); - const currentDragCanvasId = useGridStore((state) => state.currentDragCanvasId, shallow); - - // console.log('currentDragCanvasId', currentDragCanvasId); - const handleDrop = ({ componentType: draggedComponentType, component }, monitor, canvasId) => { const realCanvasRef = - document.getElementById(`canvas-${currentDragCanvasId}`) || document.getElementById(`real-canvas`); - // Reset canvas ID when dropping - setCurrentDragCanvasId(null); + !canvasId || canvasId === 'canvas' + ? document.getElementById(`real-canvas`) + : document.getElementById(`canvas-${canvasId}`); // Ensure ghost is deactivated before processing drop deactivateGhost(); + handleDeactivateTargets(); + hideGridLines(); - // Deactivate ghost when dropping setShowModuleBorder(false); // Hide the module border when dropping if (currentMode === 'view' || (appType === 'module' && draggedComponentType !== 'ModuleContainer')) { @@ -69,7 +67,7 @@ export const useCanvasDropHandler = ({ appType }) => { monitor, currentLayout, realCanvasRef, - currentDragCanvasId, + canvasId, moduleInfo ); const childComponents = addChildrenWidgetsToParent(draggedComponentType, parentComponent?.id, currentLayout); @@ -82,12 +80,14 @@ export const useCanvasDropHandler = ({ appType }) => { monitor, currentLayout, realCanvasRef, - currentDragCanvasId, + canvasId, moduleInfo ); addComponentToCurrentPage([newComponent]); setActiveRightSideBarTab(RIGHT_SIDE_BAR_TAB.CONFIGURATION); } + // Reset canvas ID when dropping + setCurrentDragCanvasId(null); }; return handleDrop; diff --git a/frontend/src/AppBuilder/RightSideBar/ComponentManagerTab/DragLayer.jsx b/frontend/src/AppBuilder/RightSideBar/ComponentManagerTab/DragLayer.jsx index fb925d5cee..3f554a413f 100644 --- a/frontend/src/AppBuilder/RightSideBar/ComponentManagerTab/DragLayer.jsx +++ b/frontend/src/AppBuilder/RightSideBar/ComponentManagerTab/DragLayer.jsx @@ -16,7 +16,6 @@ export const DragLayer = ({ index, component, isModuleTab = false }) => { const { isModuleEditor } = useModuleContext(); const setShowModuleBorder = useStore((state) => state.setShowModuleBorder, shallow) || noop; const handleDrop = useCanvasDropHandler({ appType: isModuleTab ? 'module' : 'app' }) || noop; - const currentDragCanvasId = useGridStore((state) => state.currentDragCanvasId, shallow); const [{ isDragging }, drag, preview] = useDrag( () => ({ @@ -25,16 +24,10 @@ export const DragLayer = ({ index, component, isModuleTab = false }) => { collect: (monitor) => ({ isDragging: monitor.isDragging() }), end: (item, monitor) => { const clientOffset = monitor.getClientOffset(); - console.log('end', item, monitor.getDropResult(), monitor.getClientOffset()); - console.log('currentDragCanvasId', currentDragCanvasId); + const currentDragCanvasId = useGridStore.getState().currentDragCanvasId; if (clientOffset) { - // const canvas = document.getElementById(`canvas-${currentDragCanvasId}`); - const realCanvas = document.getElementById(`real-canvas`); - handleDrop(item, monitor, realCanvas, currentDragCanvasId); + handleDrop(item, monitor, currentDragCanvasId); } - // if (didDrop) { - // handleDrop(item, monitor); - // } }, }), [component.component] @@ -59,15 +52,7 @@ export const DragLayer = ({ index, component, isModuleTab = false }) => { return ( <> {/* {isDragging && } */} -
{ - // const realCanvas = document.getElementById(`real-canvas`); - // handleDrop(e, realCanvas, currentDragCanvasId); - // }} - > +
{isModuleTab ? : }
diff --git a/frontend/src/AppBuilder/_hooks/useGhostMoveable.js b/frontend/src/AppBuilder/_hooks/useGhostMoveable.js index cea7a461cb..0e5adaa9c1 100644 --- a/frontend/src/AppBuilder/_hooks/useGhostMoveable.js +++ b/frontend/src/AppBuilder/_hooks/useGhostMoveable.js @@ -44,10 +44,9 @@ export const useGhostMoveable = () => { const relativeY = mousePosition.y - canvasRect.top; // Apply grid snapping - const gridWidth = canvasRef.current.offsetWidth / NO_OF_GRIDS; - const snappedX = Math.round(relativeX / gridWidth) * gridWidth; - const snappedY = Math.round(relativeY / GRID_HEIGHT) * GRID_HEIGHT; - console.log(snappedX, snappedY); + // const gridWidth = canvasRef.current.offsetWidth / NO_OF_GRIDS; + // const snappedX = Math.round(relativeX / gridWidth) * gridWidth; + // const snappedY = Math.round(relativeY / GRID_HEIGHT) * GRID_HEIGHT; ghostElementRef.current.style.transform = `translate(${relativeX}px, ${relativeY}px)`; }; @@ -95,25 +94,14 @@ export const useGhostMoveable = () => { setVirtualTarget(null); ghostElementRef.current.remove(); ghostElementRef.current = null; - // End any active drag operation first - // moveableInstance.dragEnd(); } catch (error) { console.warn('Failed to trigger moveable dragEnd:', error); } } }; - // New function to update ghost position during continuous hover - const updateGhostOnHover = (mousePosition, canvasRef) => { - if (isActiveRef.current) { - updateGhostPosition(mousePosition, canvasRef); - } - }; - return { activateGhost, deactivateGhost, - updateGhostOnHover, // New function for continuous updates - isActive: isActiveRef.current, }; }; diff --git a/frontend/src/_stores/gridStore.js b/frontend/src/_stores/gridStore.js index d43799ff4a..6b9822f6dd 100644 --- a/frontend/src/_stores/gridStore.js +++ b/frontend/src/_stores/gridStore.js @@ -15,11 +15,12 @@ const initialState = { moveableRef: null, virtualTarget: null, currentDragCanvasId: null, + ghostDragPosition: null, }; export const useGridStore = create( zustandDevTools( - (set) => ({ + (set, get) => ({ ...initialState, actions: { setResizingComponentId: (id) => set({ resizingComponentId: id }), @@ -31,6 +32,7 @@ export const useGridStore = create( set((state) => ({ subContainerWidths: { ...state.subContainerWidths, [id]: width } })), setVirtualTarget: (target) => set({ virtualTarget: target }), setCurrentDragCanvasId: (canvasId) => set({ currentDragCanvasId: canvasId }), + setGhostDragPosition: (position) => set({ ghostDragPosition: position }), }, addToElementGuidelines: (selector) => set((state) => ({ @@ -42,6 +44,8 @@ export const useGridStore = create( })), clearDynamicElementGuidelines: () => set({ dynamicElementGuidelines: [] }), setMoveableRef: (ref) => set({ moveableRef: ref }), + + getGhostDragPosition: () => get().ghostDragPosition, }), { name: 'Grid Store' } )