diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts index 4af8c8ee8ee8..bacc17c6ec2a 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts @@ -51,17 +51,13 @@ export function runGridRearrangeMove( selectedElement: ElementPath, jsxMetadata: ElementInstanceMetadataMap, interactionData: DragInteractionData, + grid: ElementInstanceMetadata, ): CanvasCommand[] { if (interactionData.drag == null) { return [] } - const parentGridPath = EP.parentPath(selectedElement) - const grid = MetadataUtils.findElementByElementPath(jsxMetadata, parentGridPath) - - if (grid == null) { - return [] - } + const isReparent = !EP.isParentOf(grid.elementPath, selectedElement) const { gridCellGlobalFrames, containerGridProperties: gridTemplate } = grid.specialSizeMeasurements @@ -76,39 +72,25 @@ export function runGridRearrangeMove( return [] } - const draggingFromCellCoords = getClosestGridCellToPoint( - gridCellGlobalFrames, - interactionData.dragStart, - )?.gridCellCoordinates - if (draggingFromCellCoords == null) { + const originalElementGridConfiguration = isReparent + ? { + originalElementMetadata: null, + originalCellBounds: { width: 1, height: 1 }, //when reparenting, we just put it in a single cell + mouseCellPosInOriginalElement: { row: 0, column: 0 }, + } + : getOriginalElementGridConfiguration( + gridCellGlobalFrames, + interactionData, + jsxMetadata, + selectedElement, + grid, + ) + if (originalElementGridConfiguration == null) { return [] } - const originalElementMetadata = MetadataUtils.findElementByElementPath( - jsxMetadata, - selectedElement, - ) - if (originalElementMetadata == null) { - return [] - } - - // measured cell coord bounds on the canvas, this is the default when the cell position is not explicitly set - const originalElementCellCoordsOnCanvas = getGridChildCellCoordBoundsFromCanvas( - originalElementMetadata, - grid, - ) - - // get the bounds from the props, or the canvas, or just default to the cell of the starting mouse position - const originalCellBounds = getGridChildCellCoordBoundsFromProps( - originalElementMetadata, - originalElementCellCoordsOnCanvas ?? draggingFromCellCoords, - ) - - // the cell position of the mouse relative to the original element (we have to keep this offset while dragging) - const mouseCellPosInOriginalElement = getCellCoordsDelta( - draggingFromCellCoords, - originalCellBounds, - ) + const { originalElementMetadata, originalCellBounds, mouseCellPosInOriginalElement } = + originalElementGridConfiguration // get the new adjusted row const row = targetCellCoords.row - mouseCellPosInOriginalElement.row @@ -135,7 +117,7 @@ export function runGridRearrangeMove( }) // The siblings of the grid element being moved - const siblings = MetadataUtils.getChildrenUnordered(jsxMetadata, EP.parentPath(selectedElement)) + const siblings = MetadataUtils.getChildrenUnordered(jsxMetadata, grid.elementPath) .filter((s) => !EP.pathsEqual(s.elementPath, selectedElement)) .map( (s, index): SortableGridElementProperties => ({ @@ -165,15 +147,18 @@ export function runGridRearrangeMove( EP.pathsEqual(selectedElement, s.path), ) - const moveType = getGridMoveType({ - originalElementMetadata: originalElementMetadata, - possiblyReorderIndex: possiblyReorderIndex, - cellsSortedByPosition: cellsSortedByPosition, - }) + const moveType = + originalElementMetadata == null + ? 'rearrange' + : getGridMoveType({ + originalElementMetadata: originalElementMetadata, + possiblyReorderIndex: possiblyReorderIndex, + cellsSortedByPosition: cellsSortedByPosition, + }) const updateGridControlsCommand = showGridControls( 'mid-interaction', - parentGridPath, + grid.elementPath, targetCellData?.gridCellCoordinates ?? null, gridCellCoordinates(row, column), ) @@ -768,3 +753,51 @@ export function getMetadataWithGridCellBounds( customStrategyState: null, } } + +function getOriginalElementGridConfiguration( + gridCellGlobalFrames: GridCellGlobalFrames, + interactionData: DragInteractionData, + jsxMetadata: ElementInstanceMetadataMap, + selectedElement: ElementPath, + grid: ElementInstanceMetadata, +) { + const draggingFromCellCoords = getClosestGridCellToPoint( + gridCellGlobalFrames, + interactionData.dragStart, + )?.gridCellCoordinates + if (draggingFromCellCoords == null) { + return null + } + + const originalElementMetadata = MetadataUtils.findElementByElementPath( + jsxMetadata, + selectedElement, + ) + if (originalElementMetadata == null) { + return null + } + + // measured cell coord bounds on the canvas, this is the default when the cell position is not explicitly set + const originalElementCellCoordsOnCanvas = getGridChildCellCoordBoundsFromCanvas( + originalElementMetadata, + grid, + ) + + // get the bounds from the props, or the canvas, or just default to the cell of the starting mouse position + const originalCellBounds = getGridChildCellCoordBoundsFromProps( + originalElementMetadata, + originalElementCellCoordsOnCanvas ?? draggingFromCellCoords, + ) + + // the cell position of the mouse relative to the original element (we have to keep this offset while dragging) + const mouseCellPosInOriginalElement = getCellCoordsDelta( + draggingFromCellCoords, + originalCellBounds, + ) + + return { + originalElementMetadata, + originalCellBounds, + mouseCellPosInOriginalElement, + } +} diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-duplicate-strategy.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-duplicate-strategy.ts index 039583c1077c..18e54ec97035 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-duplicate-strategy.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-duplicate-strategy.ts @@ -72,11 +72,20 @@ export const gridRearrangeMoveDuplicateStrategy: CanvasStrategyFactory = ( const targetElement = EP.appendToPath(EP.parentPath(selectedElement), newUid) + const grid = MetadataUtils.findElementByElementPath( + canvasState.startingMetadata, + EP.parentPath(selectedElement), + ) + if (grid == null) { + return emptyStrategyApplicationResult + } + const moveCommands = runGridRearrangeMove( targetElement, selectedElement, canvasState.startingMetadata, interactionSession.interactionData, + grid, ) if (moveCommands.length === 0) { return emptyStrategyApplicationResult diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-strategy.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-strategy.ts index d79b46d21b00..01692a94abed 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-strategy.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-rearrange-move-strategy.ts @@ -16,13 +16,7 @@ import { } from '../../commands/set-property-command' import type { CanvasStrategyFactory } from '../canvas-strategies' import { onlyFitWhenDraggingThisControl } from '../canvas-strategies' -import type { - ControlWithProps, - CustomStrategyState, - CustomStrategyStatePatch, - InteractionCanvasState, - InteractionLifecycle, -} from '../canvas-strategy-types' +import type { ControlWithProps, InteractionCanvasState } from '../canvas-strategy-types' import { getTargetPathsFromInteractionTarget, emptyStrategyApplicationResult, @@ -30,20 +24,12 @@ import { } from '../canvas-strategy-types' import type { DragInteractionData, InteractionSession } from '../interaction-state' import { runGridRearrangeMove } from './grid-helpers' -import type { CanvasRectangle } from '../../../../core/shared/math-utils' -import { isInfinityRectangle, offsetPoint } from '../../../../core/shared/math-utils' -import { findReparentStrategies } from './reparent-helpers/reparent-strategy-helpers' -import { applyAbsoluteReparent, controlsForAbsoluteReparent } from './absolute-reparent-strategy' +import { isInfinityRectangle } from '../../../../core/shared/math-utils' import type { CanvasCommand } from '../../commands/commands' -import { applyStaticReparent, controlsForStaticReparent } from './reparent-as-static-strategy' -import type { FindReparentStrategyResult } from './reparent-helpers/reparent-strategy-parent-lookup' -import { applyGridReparent, controlsForGridReparent } from './grid-reparent-strategy' -import { assertNever } from '../../../../core/shared/utils' export const gridRearrangeMoveStrategy: CanvasStrategyFactory = ( canvasState: InteractionCanvasState, interactionSession: InteractionSession | null, - customState: CustomStrategyState, ) => { const selectedElements = getTargetPathsFromInteractionTarget(canvasState.interactionTarget) if ( @@ -129,7 +115,7 @@ export const gridRearrangeMoveStrategy: CanvasStrategyFactory = ( ), ] - const { commands, patch, elementsToRerender } = getCommandsAndPatchForGridRearrange( + const { commands, elementsToRerender } = getCommandsAndPatchForGridRearrange( canvasState, interactionSession.interactionData, selectedElement, @@ -142,7 +128,6 @@ export const gridRearrangeMoveStrategy: CanvasStrategyFactory = ( return strategyApplicationResult( [...midInteractionCommands, ...onCompleteCommands, ...commands], elementsToRerender, - patch, ) }, } @@ -154,11 +139,18 @@ function getCommandsAndPatchForGridRearrange( selectedElement: ElementPath, ): { commands: CanvasCommand[] - patch: CustomStrategyStatePatch elementsToRerender: ElementPath[] } { if (interactionData.drag == null) { - return { commands: [], patch: {}, elementsToRerender: [] } + return { commands: [], elementsToRerender: [] } + } + + const grid = MetadataUtils.findElementByElementPath( + canvasState.startingMetadata, + EP.parentPath(selectedElement), + ) + if (grid == null) { + return { commands: [], elementsToRerender: [] } } const commands = runGridRearrangeMove( @@ -166,11 +158,11 @@ function getCommandsAndPatchForGridRearrange( selectedElement, canvasState.startingMetadata, interactionData, + grid, ) return { commands: commands, - patch: {}, elementsToRerender: [EP.parentPath(selectedElement)], } } diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategy.tsx b/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategy.tsx index f98ee00f7680..419b1633ca7a 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategy.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategy.tsx @@ -5,11 +5,11 @@ import { mapDropNulls } from '../../../../core/shared/array-utils' import * as EP from '../../../../core/shared/element-path' import type { ElementPathTrees } from '../../../../core/shared/element-path-tree' import { - gridPositionValue, + type ElementInstanceMetadata, type ElementInstanceMetadataMap, } from '../../../../core/shared/element-template' import type { CanvasRectangle } from '../../../../core/shared/math-utils' -import { canvasVector, isInfinityRectangle, offsetPoint } from '../../../../core/shared/math-utils' +import { isInfinityRectangle } from '../../../../core/shared/math-utils' import type { ElementPath } from '../../../../core/shared/project-file-types' import * as PP from '../../../../core/shared/property-path' import type { AllElementProps } from '../../../editor/store/editor-state' @@ -39,13 +39,12 @@ import { import type { DragInteractionData, InteractionSession, UpdatedPathMap } from '../interaction-state' import { honoursPropsPosition, shouldKeepMovingDraggedGroupChildren } from './absolute-utils' import { replaceFragmentLikePathsWithTheirChildrenRecursive } from './fragment-like-helpers' -import { getMetadataWithGridCellBounds, setGridPropsCommands } from './grid-helpers' +import { getMetadataWithGridCellBounds, runGridRearrangeMove } from './grid-helpers' import { ifAllowedToReparent, isAllowedToReparent } from './reparent-helpers/reparent-helpers' import { removeAbsolutePositioningProps } from './reparent-helpers/reparent-property-changes' import type { ReparentTarget } from './reparent-helpers/reparent-strategy-helpers' import { getReparentOutcome, pathToReparent } from './reparent-utils' import { flattenSelection } from './shared-move-strategies-helpers' -import { getClosestGridCellToPointFromMetadata, type GridCellCoordinates } from './grid-cell-bounds' export function gridReparentStrategy( reparentTarget: ReparentTarget, @@ -190,16 +189,6 @@ export function applyGridReparent( return emptyStrategyApplicationResult } - const mousePos = offsetPoint( - interactionData.dragStart, - interactionData.drag ?? canvasVector({ x: 0, y: 0 }), - ) - - const targetCellData = getClosestGridCellToPointFromMetadata(grid, mousePos) - - if (targetCellData == null) { - return strategyApplicationResult([], [newParent.intendedParentPath]) - } const outcomes = mapDropNulls( (selectedElement) => gridReparentCommands( @@ -211,7 +200,8 @@ export function applyGridReparent( nodeModules, selectedElement, newParent, - targetCellData.gridCellCoordinates, + interactionData, + grid, ), selectedElements, ) @@ -253,12 +243,6 @@ export function applyGridReparent( gridContainerCommands, updateSelectedViews('always', newPaths), setCursorCommand(CSSCursor.Reparent), - showGridControls( - 'mid-interaction', - reparentTarget.newParent.intendedParentPath, - targetCellData.gridCellCoordinates, - null, - ), ], elementsToRerender, customStrategyStatePatch, @@ -268,35 +252,6 @@ export function applyGridReparent( } } -function getGridPositioningCommands( - jsxMetadata: ElementInstanceMetadataMap, - hoveredCoordinates: GridCellCoordinates, - { - parentPath, - target, - }: { - parentPath: ElementPath - target: ElementPath - }, -) { - const containerMetadata = MetadataUtils.findElementByElementPath(jsxMetadata, parentPath) - if (containerMetadata == null) { - return null - } - const { column, row } = hoveredCoordinates - - const gridTemplate = containerMetadata.specialSizeMeasurements.containerGridProperties - - const gridPropsCommands = setGridPropsCommands(target, gridTemplate, { - gridColumnStart: gridPositionValue(column), - gridColumnEnd: gridPositionValue(column), - gridRowEnd: gridPositionValue(row), - gridRowStart: gridPositionValue(row), - }) - - return gridPropsCommands -} - function gridReparentCommands( jsxMetadata: ElementInstanceMetadataMap, tree: ElementPathTrees, @@ -306,7 +261,8 @@ function gridReparentCommands( nodeModules: NodeModules, target: ElementPath, newParent: InsertionPath, - hoveredCoordinates: GridCellCoordinates, + interactionData: DragInteractionData, + grid: ElementInstanceMetadata, ) { const reparentResult = getReparentOutcome( jsxMetadata, @@ -324,11 +280,7 @@ function gridReparentCommands( if (reparentResult == null) { return null } - - const gridPropsCommands = getGridPositioningCommands(jsxMetadata, hoveredCoordinates, { - parentPath: newParent.intendedParentPath, - target: target, - }) + const gridPropsCommands = runGridRearrangeMove(target, target, jsxMetadata, interactionData, grid) if (gridPropsCommands == null) { return null