From fac5a93eb650a2d5c9f2548ad4975ba866b22b4a Mon Sep 17 00:00:00 2001 From: Federico Ruggi Date: Fri, 15 Nov 2024 11:38:51 +0100 Subject: [PATCH 01/10] only show placeholders when selecting grid or during child interaction --- .../canvas/controls/grid-controls.tsx | 44 ++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index b47891511c1e..114c18771da9 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -1136,6 +1136,26 @@ export const GridControlsComponent = ({ targets }: GridControlsProps) => { }), ) + const isItemInteractionActive = useEditorState( + Substores.canvas, + (store) => { + if (store.editor.canvas.interactionSession == null) { + return false + } + return ( + // movement + store.editor.canvas.interactionSession.activeControl.type === 'GRID_CELL_HANDLE' || + // resize (cell) + store.editor.canvas.interactionSession.activeControl.type === 'GRID_RESIZE_HANDLE' || + // resize (abs) + store.editor.canvas.interactionSession.activeControl.type === 'RESIZE_HANDLE' + ) + }, + 'GridControlsComponent isItemInteractionActive', + ) + + const selectedViewsRef = useRefEditorState((store) => store.editor.selectedViews) + if (grids.length === 0) { return null } @@ -1144,20 +1164,34 @@ export const GridControlsComponent = ({ targets }: GridControlsProps) => {
{grids.map((grid) => { + const gridItemSelected = selectedViewsRef.current.some((path) => + EP.isDescendantOf(path, grid.identifier.path), + ) + const gridPath = grid.identifier.type === 'GRID_CONTAINER' ? grid.identifier.path : EP.parentPath(grid.identifier.path) - const shouldHaveVisibleControls = gridsWithVisibleControls.some((g) => { - const visibleControlPath = g.type === 'GRID_CONTAINER' ? g.path : EP.parentPath(g.path) - return EP.pathsEqual(gridPath, visibleControlPath) - }) + + function shouldHaveVisibleControls(): boolean { + const isGridChildSelectedWihtoutInteraction = + gridItemSelected && !isItemInteractionActive + if (isGridChildSelectedWihtoutInteraction) { + return false + } + + return gridsWithVisibleControls.some((g) => { + const visibleControlPath = + g.type === 'GRID_CONTAINER' ? g.path : EP.parentPath(g.path) + return EP.pathsEqual(gridPath, visibleControlPath) + }) + } return ( ) })} From 3c4188ce367624d515d8e9798d8fe474652f5d1f Mon Sep 17 00:00:00 2001 From: Federico Ruggi Date: Fri, 15 Nov 2024 13:55:02 +0100 Subject: [PATCH 02/10] fix test helper --- .../strategies/grid.test-utils.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid.test-utils.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid.test-utils.ts index 26eae7685310..919fd6166c5b 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid.test-utils.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid.test-utils.ts @@ -43,6 +43,14 @@ export async function runGridMoveTest( props.draggedCell.column, ), ) + + const sourceRect = sourceGridCell.getBoundingClientRect() + const dragFrom = { + x: sourceRect.x + 10, + y: sourceRect.y + 10, + } + await mouseDownAtPoint(sourceGridCell, dragFrom) + const targetGridCell = editor.renderedDOM.getByTestId( gridCellTargetId( EP.fromString('sb/scene/grid'), @@ -51,13 +59,8 @@ export async function runGridMoveTest( ), ) - const sourceRect = sourceGridCell.getBoundingClientRect() const targetRect = targetGridCell.getBoundingClientRect() - const dragFrom = { - x: sourceRect.x + 10, - y: sourceRect.y + 10, - } const endPoint = getRectCenter( localRectangle({ x: targetRect.x, @@ -67,7 +70,6 @@ export async function runGridMoveTest( }), ) - await mouseDownAtPoint(sourceGridCell, dragFrom) await mouseMoveToPoint(sourceGridCell, endPoint) if (props.tab) { await keyDown('Tab') From c5e13f16ce4c690ace431a1e08a16a91f06ce0b4 Mon Sep 17 00:00:00 2001 From: Federico Ruggi Date: Fri, 15 Nov 2024 13:55:13 +0100 Subject: [PATCH 03/10] hide resize pills --- .../canvas/controls/grid-controls.tsx | 102 ++++++++++-------- 1 file changed, 58 insertions(+), 44 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index 114c18771da9..d1f78bb9c60c 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -535,6 +535,8 @@ export const GridRowColumnResizingControlsComponent = ({ 'GridRowColumnResizingControls scale', ) + const selectedGridItemWithoutInteraction = useSelectedGridItemWithoutInteraction() + const gridsWithVisibleResizeControls = React.useMemo(() => { return grids.filter((grid) => { if ( @@ -570,6 +572,9 @@ export const GridRowColumnResizingControlsComponent = ({ return ( {gridsWithVisibleResizeControls.flatMap((grid) => { + if (selectedGridItemWithoutInteraction(grid)) { + return null + } return ( { + if (selectedGridItemWithoutInteraction(grid)) { + return null + } return ( { const gridsWithVisibleControls: Array = [...targets, ...hoveredGrids] + const selectedGridItemWithoutInteraction = useSelectedGridItemWithoutInteraction() + // Uniqify the grid paths, and then sort them by depth. // With the lowest depth grid at the end so that it renders on top and catches the events // before those above it in the hierarchy. @@ -1136,26 +1146,6 @@ export const GridControlsComponent = ({ targets }: GridControlsProps) => { }), ) - const isItemInteractionActive = useEditorState( - Substores.canvas, - (store) => { - if (store.editor.canvas.interactionSession == null) { - return false - } - return ( - // movement - store.editor.canvas.interactionSession.activeControl.type === 'GRID_CELL_HANDLE' || - // resize (cell) - store.editor.canvas.interactionSession.activeControl.type === 'GRID_RESIZE_HANDLE' || - // resize (abs) - store.editor.canvas.interactionSession.activeControl.type === 'RESIZE_HANDLE' - ) - }, - 'GridControlsComponent isItemInteractionActive', - ) - - const selectedViewsRef = useRefEditorState((store) => store.editor.selectedViews) - if (grids.length === 0) { return null } @@ -1164,34 +1154,25 @@ export const GridControlsComponent = ({ targets }: GridControlsProps) => {
{grids.map((grid) => { - const gridItemSelected = selectedViewsRef.current.some((path) => - EP.isDescendantOf(path, grid.identifier.path), - ) - - const gridPath = - grid.identifier.type === 'GRID_CONTAINER' - ? grid.identifier.path - : EP.parentPath(grid.identifier.path) - - function shouldHaveVisibleControls(): boolean { - const isGridChildSelectedWihtoutInteraction = - gridItemSelected && !isItemInteractionActive - if (isGridChildSelectedWihtoutInteraction) { - return false - } - - return gridsWithVisibleControls.some((g) => { - const visibleControlPath = - g.type === 'GRID_CONTAINER' ? g.path : EP.parentPath(g.path) - return EP.pathsEqual(gridPath, visibleControlPath) - }) - } - return ( { + const gridPath = + grid.identifier.type === 'GRID_CONTAINER' + ? grid.identifier.path + : EP.parentPath(grid.identifier.path) + + const visibleControlPath = + g.type === 'GRID_CONTAINER' ? g.path : EP.parentPath(g.path) + return EP.pathsEqual(gridPath, visibleControlPath) + }) + ? 'visible' + : 'not-visible' + } /> ) })} @@ -2112,3 +2093,36 @@ function useAllGrids(metadata: ElementInstanceMetadataMap) { return MetadataUtils.getAllGrids(metadata) }, [metadata]) } + +function useSelectedGridItemWithoutInteraction() { + const selectedViewsRef = useRefEditorState((store) => store.editor.selectedViews) + + const isItemInteractionActive = useEditorState( + Substores.canvas, + (store) => { + if (store.editor.canvas.interactionSession == null) { + return false + } + return ( + // movement + store.editor.canvas.interactionSession.activeControl.type === 'GRID_CELL_HANDLE' || + // resize (cell) + store.editor.canvas.interactionSession.activeControl.type === 'GRID_RESIZE_HANDLE' || + // resize (abs) + store.editor.canvas.interactionSession.activeControl.type === 'RESIZE_HANDLE' + ) + }, + 'useShouldHaveVisibleControls isItemInteractionActive', + ) + + return React.useCallback( + (grid: GridData) => { + const gridItemSelected = selectedViewsRef.current.some((path) => + EP.isDescendantOf(path, grid.identifier.path), + ) + + return gridItemSelected && !isItemInteractionActive + }, + [isItemInteractionActive, selectedViewsRef], + ) +} From 853d0d1813faa1b1bec854afb9108e9372c5ad06 Mon Sep 17 00:00:00 2001 From: Federico Ruggi Date: Fri, 15 Nov 2024 13:56:31 +0100 Subject: [PATCH 04/10] refactor --- .../canvas/controls/grid-controls.tsx | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index d1f78bb9c60c..3b537451b161 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -1154,25 +1154,24 @@ export const GridControlsComponent = ({ targets }: GridControlsProps) => {
{grids.map((grid) => { + const shouldHaveVisibleControls = + !selectedGridItemWithoutInteraction(grid) && + gridsWithVisibleControls.some((g) => { + const gridPath = + grid.identifier.type === 'GRID_CONTAINER' + ? grid.identifier.path + : EP.parentPath(grid.identifier.path) + + const visibleControlPath = + g.type === 'GRID_CONTAINER' ? g.path : EP.parentPath(g.path) + return EP.pathsEqual(gridPath, visibleControlPath) + }) + return ( { - const gridPath = - grid.identifier.type === 'GRID_CONTAINER' - ? grid.identifier.path - : EP.parentPath(grid.identifier.path) - - const visibleControlPath = - g.type === 'GRID_CONTAINER' ? g.path : EP.parentPath(g.path) - return EP.pathsEqual(gridPath, visibleControlPath) - }) - ? 'visible' - : 'not-visible' - } + controlsVisible={shouldHaveVisibleControls ? 'visible' : 'not-visible'} /> ) })} From 6644bbdb0231254858fc17452e07de039ae630bc Mon Sep 17 00:00:00 2001 From: Federico Ruggi Date: Fri, 15 Nov 2024 13:57:09 +0100 Subject: [PATCH 05/10] rename --- .../src/components/canvas/controls/grid-controls.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index 3b537451b161..74ec0427c2c6 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -535,7 +535,7 @@ export const GridRowColumnResizingControlsComponent = ({ 'GridRowColumnResizingControls scale', ) - const selectedGridItemWithoutInteraction = useSelectedGridItemWithoutInteraction() + const isSelectedGridItemWithoutInteraction = useIsSelectedGridItemWithoutInteraction() const gridsWithVisibleResizeControls = React.useMemo(() => { return grids.filter((grid) => { @@ -572,7 +572,7 @@ export const GridRowColumnResizingControlsComponent = ({ return ( {gridsWithVisibleResizeControls.flatMap((grid) => { - if (selectedGridItemWithoutInteraction(grid)) { + if (isSelectedGridItemWithoutInteraction(grid)) { return null } return ( @@ -595,7 +595,7 @@ export const GridRowColumnResizingControlsComponent = ({ ) })} {gridsWithVisibleResizeControls.flatMap((grid) => { - if (selectedGridItemWithoutInteraction(grid)) { + if (isSelectedGridItemWithoutInteraction(grid)) { return null } return ( @@ -1133,7 +1133,7 @@ export const GridControlsComponent = ({ targets }: GridControlsProps) => { const gridsWithVisibleControls: Array = [...targets, ...hoveredGrids] - const selectedGridItemWithoutInteraction = useSelectedGridItemWithoutInteraction() + const isSelectedGridItemWithoutInteraction = useIsSelectedGridItemWithoutInteraction() // Uniqify the grid paths, and then sort them by depth. // With the lowest depth grid at the end so that it renders on top and catches the events @@ -1155,7 +1155,7 @@ export const GridControlsComponent = ({ targets }: GridControlsProps) => { {grids.map((grid) => { const shouldHaveVisibleControls = - !selectedGridItemWithoutInteraction(grid) && + !isSelectedGridItemWithoutInteraction(grid) && gridsWithVisibleControls.some((g) => { const gridPath = grid.identifier.type === 'GRID_CONTAINER' @@ -2093,7 +2093,7 @@ function useAllGrids(metadata: ElementInstanceMetadataMap) { }, [metadata]) } -function useSelectedGridItemWithoutInteraction() { +function useIsSelectedGridItemWithoutInteraction() { const selectedViewsRef = useRefEditorState((store) => store.editor.selectedViews) const isItemInteractionActive = useEditorState( From 685ac41f9442b88f6025531de32884d81870234b Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:30:07 +0100 Subject: [PATCH 06/10] update tests --- ...change-location-strategy.spec.browser2.tsx | 70 ++++---------- .../grid-reorder-strategy.spec.browser2.tsx | 13 ++- .../strategies/grid.test-utils.ts | 95 +++++++++++-------- 3 files changed, 86 insertions(+), 92 deletions(-) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-element-change-location-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/grid-element-change-location-strategy.spec.browser2.tsx index cca92c289c76..3af80a89cd37 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-element-change-location-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-element-change-location-strategy.spec.browser2.tsx @@ -1,16 +1,10 @@ import * as EP from '../../../../core/shared/element-path' -import { - getRectCenter, - localRectangle, - offsetPoint, - windowPoint, -} from '../../../../core/shared/math-utils' +import { offsetPoint, windowPoint } from '../../../../core/shared/math-utils' import { selectComponentsForTest } from '../../../../utils/utils.test-utils' import CanvasActions from '../../canvas-actions' import { GridCellTestId } from '../../controls/grid-controls-for-strategies' import { mouseDownAtPoint, mouseMoveToPoint, mouseUpAtPoint } from '../../event-helpers.test-utils' import { renderTestEditorWithCode } from '../../ui-jsx.test-utils' -import { gridCellTargetId } from './grid-cell-bounds' import { runGridMoveTest } from './grid.test-utils' describe('grid element change location strategy', () => { @@ -22,7 +16,7 @@ describe('grid element change location strategy', () => { editor, { scale: 1, - pathString: `sb/scene/grid/${testId}`, + gridPath: 'sb/scene/grid', testId: testId, }, ) @@ -52,7 +46,7 @@ describe('grid element change location strategy', () => { editor, { scale: 1, - pathString: `sb/scene/grid/${testId}`, + gridPath: 'sb/scene/grid', testId: testId, }, ) @@ -79,7 +73,7 @@ describe('grid element change location strategy', () => { editor, { scale: 1, - pathString: `sb/scene/grid/${testId}`, + gridPath: 'sb/scene/grid', testId: testId, }, (ed) => { @@ -108,7 +102,7 @@ describe('grid element change location strategy', () => { editor, { scale: 1, - pathString: `sb/scene/grid/${testId}`, + gridPath: 'sb/scene/grid', testId: testId, }, ) @@ -129,7 +123,7 @@ describe('grid element change location strategy', () => { editor, { scale: 1, - pathString: `sb/scene/grid/${testId}`, + gridPath: 'sb/scene/grid', testId: testId, targetCell: { row: 2, column: 1 }, draggedCell: { row: 2, column: 2 }, @@ -151,7 +145,7 @@ describe('grid element change location strategy', () => { editor, { scale: 1, - pathString: `sb/scene/grid/${testId}`, + gridPath: 'sb/scene/grid', testId: testId, tab: true, }, @@ -176,7 +170,7 @@ describe('grid element change location strategy', () => { editor, { scale: 1, - pathString: `sb/scene/grid/${testId}`, + gridPath: 'sb/scene/grid', testId: testId, targetCell: { row: 3, column: 1 }, }, @@ -198,7 +192,7 @@ describe('grid element change location strategy', () => { editor, { scale: 0.5, - pathString: `sb/scene/grid/${testId}`, + gridPath: 'sb/scene/grid', testId: testId, }, ) @@ -218,7 +212,7 @@ describe('grid element change location strategy', () => { editor, { scale: 2, - pathString: `sb/scene/grid/${testId}`, + gridPath: 'sb/scene/grid', testId: testId, }, ) @@ -241,7 +235,7 @@ describe('grid element change location strategy', () => { editor, { scale: 1, - pathString: `sb/scene/grid/${testId}`, + gridPath: 'sb/scene/grid', testId: testId, }, ) @@ -265,7 +259,7 @@ describe('grid element change location strategy', () => { editor, { scale: 1, - pathString: `sb/scene/grid/${testId}`, + gridPath: 'sb/scene/grid', testId: testId, }, ) @@ -289,7 +283,7 @@ describe('grid element change location strategy', () => { editor, { scale: 1, - pathString: `sb/scene/grid/${testId}`, + gridPath: 'sb/scene/grid', testId: testId, targetCell: { row: 3, column: 2 }, }, @@ -314,7 +308,7 @@ describe('grid element change location strategy', () => { editor, { scale: 1, - pathString: `sb/scene/grid/${testId}`, + gridPath: 'sb/scene/grid', testId: testId, }, ) @@ -338,7 +332,7 @@ describe('grid element change location strategy', () => { editor, { scale: 1, - pathString: `sb/scene/grid/${testId}`, + gridPath: 'sb/scene/grid', testId: testId, }, ) @@ -364,8 +358,6 @@ export var storyboard = ( data-testid='grid' style={{ position: 'absolute', - left: -94, - top: 698, display: 'grid', gap: 10, width: 600, @@ -426,33 +418,11 @@ export var storyboard = ( ) const testId = 'grid-inside-grid' - const elementPathToDrag = EP.fromString(`sb/grid/${testId}`) - - await selectComponentsForTest(editor, [elementPathToDrag]) - - const sourceGridCell = editor.renderedDOM.getByTestId(GridCellTestId(elementPathToDrag)) - const targetGridCell = editor.renderedDOM.getByTestId( - gridCellTargetId(EP.fromString('sb/grid'), 2, 3), - ) - - const sourceRect = sourceGridCell.getBoundingClientRect() - const targetRect = targetGridCell.getBoundingClientRect() - - const dragFrom = { - x: sourceRect.x + 10, - y: sourceRect.y + 10, - } - const dragTo = getRectCenter( - localRectangle({ - x: targetRect.x, - y: targetRect.y, - width: targetRect.width, - height: targetRect.height, - }), - ) - await mouseDownAtPoint(sourceGridCell, dragFrom) - await mouseMoveToPoint(sourceGridCell, dragTo) - await mouseUpAtPoint(sourceGridCell, dragTo) + await runGridMoveTest(editor, { + scale: 1, + gridPath: 'sb/grid', + testId: testId, + }) const { gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd } = editor.renderedDOM.getByTestId(testId).style diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-reorder-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/grid-reorder-strategy.spec.browser2.tsx index 9fffc31d25bd..0237876e04d5 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-reorder-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-reorder-strategy.spec.browser2.tsx @@ -6,6 +6,7 @@ import { renderTestEditorWithCode } from '../../ui-jsx.test-utils' import type { GridCellCoordinates } from './grid-cell-bounds' import { runGridMoveTest } from './grid.test-utils' import * as EP from '../../../../core/shared/element-path' +import { selectComponentsForTest } from '../../../../utils/utils.test-utils' describe('grid reorder', () => { it('reorders an element without setting positioning (inside contiguous area)', async () => { @@ -94,6 +95,8 @@ describe('grid reorder', () => { expect(first.cells).toEqual(['pink', 'cyan', 'blue', 'orange']) + await selectComponentsForTest(editor, []) + const second = await runReorderTest( editor, 'sb/scene/grid', @@ -225,7 +228,7 @@ describe('grid reorder', () => { async function runReorderTest( editor: EditorRenderResult, - gridTestId: string, + gridPath: string, testId: string, targetCell: GridCellCoordinates, options?: { tab?: boolean }, @@ -234,22 +237,22 @@ async function runReorderTest( editor, { scale: 1, - pathString: `${gridTestId}/${testId}`, + gridPath: gridPath, testId: testId, targetCell: targetCell, tab: options?.tab, }, ) - const element = editor.getEditorState().editor.jsxMetadata[gridTestId] - if (isLeft(element.element) || !isJSXElement(element.element.value)) { + const grid = editor.getEditorState().editor.jsxMetadata[gridPath] + if (isLeft(grid.element) || !isJSXElement(grid.element.value)) { throw new Error('expected jsx element') } const cells = MetadataUtils.getChildrenOrdered( editor.getEditorState().editor.jsxMetadata, editor.getEditorState().editor.elementPathTree, - element.elementPath, + EP.fromString(gridPath), ) return { diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid.test-utils.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid.test-utils.ts index 919fd6166c5b..2250a04742af 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid.test-utils.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid.test-utils.ts @@ -2,7 +2,6 @@ import { getRectCenter, localRectangle } from '../../../../core/shared/math-util import { selectComponentsForTest } from '../../../../utils/utils.test-utils' import CanvasActions from '../../canvas-actions' import { GridCellTestId } from '../../controls/grid-controls-for-strategies' -import { CanvasControlsContainerID } from '../../controls/new-canvas-controls' import { mouseDownAtPoint, mouseMoveToPoint, @@ -13,12 +12,14 @@ import type { EditorRenderResult } from '../../ui-jsx.test-utils' import type { GridCellCoordinates } from './grid-cell-bounds' import { gridCellTargetId } from './grid-cell-bounds' import * as EP from '../../../../core/shared/element-path' +import type { ElementPath } from 'utopia-shared/src/types' +import { CanvasControlsContainerID } from '../../controls/new-canvas-controls' export async function runGridMoveTest( editor: EditorRenderResult, props: { scale: number - pathString: string + gridPath: string testId: string targetCell?: GridCellCoordinates draggedCell?: GridCellCoordinates @@ -26,7 +27,7 @@ export async function runGridMoveTest( }, midDragCallback?: (editor: EditorRenderResult) => void, ) { - const elementPathToDrag = EP.fromString(props.pathString) + const elementPathToDrag = EP.appendToPath(EP.fromString(props.gridPath), props.testId) await selectComponentsForTest(editor, [elementPathToDrag]) @@ -34,51 +35,71 @@ export async function runGridMoveTest( await editor.dispatch([CanvasActions.zoom(props.scale)], true) } + // trigger the grid controls so we know where to find the cells + const { sourceGridCell, dragFrom, dragTo } = await getSafeGridMoveTestEndpoints( + editor, + elementPathToDrag, + props.gridPath, + { + draggedCell: props.draggedCell, + targetCell: props.targetCell, + }, + ) + + await mouseDownAtPoint(sourceGridCell, dragFrom) + await mouseMoveToPoint(sourceGridCell, dragTo) + if (props.tab) { + await keyDown('Tab') + } + if (midDragCallback != null) { + midDragCallback(editor) + } + + await mouseUpAtPoint(editor.renderedDOM.getByTestId(CanvasControlsContainerID), dragTo) + + return editor.renderedDOM.getByTestId(props.testId).style +} + +export async function getSafeGridMoveTestEndpoints( + editor: EditorRenderResult, + elementPathToDrag: ElementPath, + gridPath: string, + props?: { + draggedCell?: GridCellCoordinates + targetCell?: GridCellCoordinates + }, +) { + const gridCellTestId = GridCellTestId(elementPathToDrag) + const gridCellBaseElement = editor.renderedDOM.getByTestId(gridCellTestId) + const gridCellBaseElementBox = gridCellBaseElement.getBoundingClientRect() + const testPoint = getRectCenter(localRectangle(gridCellBaseElementBox)) + + await mouseDownAtPoint(gridCellBaseElement, testPoint) + const sourceGridCell = editor.renderedDOM.getByTestId( - props.draggedCell == null - ? GridCellTestId(elementPathToDrag) + props?.draggedCell == null + ? gridCellTestId : gridCellTargetId( - EP.fromString('sb/scene/grid'), - props.draggedCell.row, - props.draggedCell.column, + EP.fromString(gridPath), + props?.draggedCell.row, + props?.draggedCell.column, ), ) - const sourceRect = sourceGridCell.getBoundingClientRect() - const dragFrom = { - x: sourceRect.x + 10, - y: sourceRect.y + 10, - } - await mouseDownAtPoint(sourceGridCell, dragFrom) - const targetGridCell = editor.renderedDOM.getByTestId( gridCellTargetId( - EP.fromString('sb/scene/grid'), - props.targetCell?.row ?? 2, - props.targetCell?.column ?? 3, + EP.fromString(gridPath), + props?.targetCell?.row ?? 2, + props?.targetCell?.column ?? 3, ), ) + const sourceRect = sourceGridCell.getBoundingClientRect() + const dragFrom = { x: sourceRect.x + 5, y: sourceRect.y + 5 } const targetRect = targetGridCell.getBoundingClientRect() + const dragTo = { x: targetRect.x + 5, y: targetRect.y + 5 } - const endPoint = getRectCenter( - localRectangle({ - x: targetRect.x, - y: targetRect.y, - width: targetRect.width, - height: targetRect.height, - }), - ) + await mouseUpAtPoint(editor.renderedDOM.getByTestId(CanvasControlsContainerID), testPoint) - await mouseMoveToPoint(sourceGridCell, endPoint) - if (props.tab) { - await keyDown('Tab') - } - if (midDragCallback != null) { - midDragCallback(editor) - } - - await mouseUpAtPoint(editor.renderedDOM.getByTestId(CanvasControlsContainerID), endPoint) - - return editor.renderedDOM.getByTestId(props.testId).style + return { sourceGridCell, dragFrom, dragTo } } From 144f93cfe9cb31aa0eb36f236aba38233d44de84 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:03:48 +0100 Subject: [PATCH 07/10] fix resize tests --- .../grid-resize-element-strategy.spec.browser2.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-strategy.spec.browser2.tsx index 44de26cbb02c..18ff57b2eeeb 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-strategy.spec.browser2.tsx @@ -15,7 +15,7 @@ import { offsetPoint, } from '../../../../core/shared/math-utils' import { selectComponentsForTest } from '../../../../utils/utils.test-utils' -import { mouseDragFromPointToPoint } from '../../event-helpers.test-utils' +import { mouseDownAtPoint, mouseDragFromPointToPoint } from '../../event-helpers.test-utils' import type { EditorRenderResult } from '../../ui-jsx.test-utils' import { renderTestEditorWithCode } from '../../ui-jsx.test-utils' import type { GridResizeEdge } from '../interaction-state' @@ -34,6 +34,9 @@ async function runCellResizeTest( const resizeControl = editor.renderedDOM.getByTestId( ResizePointTestId(gridEdgeToEdgePosition(edge)), ) + + const resizeControlBox = resizeControl.getBoundingClientRect() + await mouseDownAtPoint(resizeControl, { x: resizeControlBox.x + 5, y: resizeControlBox.y + 5 }) const targetGridCell = editor.renderedDOM.getByTestId(dragToCellTestId) await mouseDragFromPointToPoint( From c7fcb276ed87a81f03fbc8c7265e73a16a4f29fa Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:21:27 +0100 Subject: [PATCH 08/10] fix resize grid tests --- .../resize-grid-strategy.spec.browser2.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/resize-grid-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/resize-grid-strategy.spec.browser2.tsx index a8bc6730953f..5a83237fe0ec 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/resize-grid-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/resize-grid-strategy.spec.browser2.tsx @@ -140,7 +140,7 @@ describe('resize a grid', () => { makeTestProject({ columns: '2.4fr 1fr 1fr', rows: '99px 109px 90px', shorthand: null }), 'await-first-dom-report', ) - const target = EP.fromString(`sb/grid/row-1-column-2`) + const target = EP.fromString(`sb/grid`) await renderResult.dispatch(selectComponents([target], false), true) await renderResult.getDispatchFollowUpActionsFinished() const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) @@ -316,7 +316,7 @@ export var storyboard = ( makeTestProject({ columns: '2.4fr 1fr 1fr', rows: '99px 109px 90px', shorthand: null }), 'await-first-dom-report', ) - const target = EP.fromString(`sb/grid/row-1-column-2`) + const target = EP.fromString(`sb/grid`) await renderResult.dispatch(selectComponents([target], false), true) await renderResult.getDispatchFollowUpActionsFinished() const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) @@ -431,7 +431,7 @@ export var storyboard = ( makeTestProject({ columns: 'repeat(3, 1fr)', rows: '99px 109px 90px', shorthand: null }), 'await-first-dom-report', ) - const target = EP.fromString(`sb/grid/row-1-column-2`) + const target = EP.fromString(`sb/grid`) await renderResult.dispatch(selectComponents([target], false), true) await renderResult.getDispatchFollowUpActionsFinished() const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) @@ -551,7 +551,7 @@ export var storyboard = ( }), 'await-first-dom-report', ) - const target = EP.fromString(`sb/grid/row-1-column-2`) + const target = EP.fromString(`sb/grid`) await renderResult.dispatch(selectComponents([target], false), true) await renderResult.getDispatchFollowUpActionsFinished() const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) @@ -670,7 +670,7 @@ export var storyboard = ( }), 'await-first-dom-report', ) - const target = EP.fromString(`sb/grid/row-1-column-2`) + const target = EP.fromString(`sb/grid`) await renderResult.dispatch(selectComponents([target], false), true) await renderResult.getDispatchFollowUpActionsFinished() const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) @@ -788,7 +788,7 @@ export var storyboard = ( }), 'await-first-dom-report', ) - const target = EP.fromString(`sb/grid/row-1-column-2`) + const target = EP.fromString(`sb/grid`) await renderResult.dispatch(selectComponents([target], false), true) await renderResult.getDispatchFollowUpActionsFinished() const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) From dd28d11bf0ff4b4e700686e8b7c3f9775bbf353f Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Mon, 18 Nov 2024 10:54:59 +0100 Subject: [PATCH 09/10] split hooks --- .../canvas/controls/grid-controls.tsx | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index 74ec0427c2c6..8a8c1d1673f5 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -535,7 +535,7 @@ export const GridRowColumnResizingControlsComponent = ({ 'GridRowColumnResizingControls scale', ) - const isSelectedGridItemWithoutInteraction = useIsSelectedGridItemWithoutInteraction() + const isGridItemSelected = useIsGridItemSelected() const gridsWithVisibleResizeControls = React.useMemo(() => { return grids.filter((grid) => { @@ -572,7 +572,7 @@ export const GridRowColumnResizingControlsComponent = ({ return ( {gridsWithVisibleResizeControls.flatMap((grid) => { - if (isSelectedGridItemWithoutInteraction(grid)) { + if (isGridItemSelected(grid)) { return null } return ( @@ -595,7 +595,7 @@ export const GridRowColumnResizingControlsComponent = ({ ) })} {gridsWithVisibleResizeControls.flatMap((grid) => { - if (isSelectedGridItemWithoutInteraction(grid)) { + if (isGridItemSelected(grid)) { return null } return ( @@ -1133,7 +1133,8 @@ export const GridControlsComponent = ({ targets }: GridControlsProps) => { const gridsWithVisibleControls: Array = [...targets, ...hoveredGrids] - const isSelectedGridItemWithoutInteraction = useIsSelectedGridItemWithoutInteraction() + const isGridItemSelected = useIsGridItemSelected() + const isGridItemInteractionActive = useIsGridItemInteractionActive() // Uniqify the grid paths, and then sort them by depth. // With the lowest depth grid at the end so that it renders on top and catches the events @@ -1154,8 +1155,10 @@ export const GridControlsComponent = ({ targets }: GridControlsProps) => {
{grids.map((grid) => { + const isGridItemSelectedWithoutInteraction = + isGridItemSelected(grid) && !isGridItemInteractionActive const shouldHaveVisibleControls = - !isSelectedGridItemWithoutInteraction(grid) && + !isGridItemSelectedWithoutInteraction && gridsWithVisibleControls.some((g) => { const gridPath = grid.identifier.type === 'GRID_CONTAINER' @@ -2093,10 +2096,8 @@ function useAllGrids(metadata: ElementInstanceMetadataMap) { }, [metadata]) } -function useIsSelectedGridItemWithoutInteraction() { - const selectedViewsRef = useRefEditorState((store) => store.editor.selectedViews) - - const isItemInteractionActive = useEditorState( +function useIsGridItemInteractionActive() { + return useEditorState( Substores.canvas, (store) => { if (store.editor.canvas.interactionSession == null) { @@ -2111,17 +2112,17 @@ function useIsSelectedGridItemWithoutInteraction() { store.editor.canvas.interactionSession.activeControl.type === 'RESIZE_HANDLE' ) }, - 'useShouldHaveVisibleControls isItemInteractionActive', + 'useIsGridItemInteractionActive isItemInteractionActive', ) +} + +function useIsGridItemSelected() { + const selectedViewsRef = useRefEditorState((store) => store.editor.selectedViews) return React.useCallback( (grid: GridData) => { - const gridItemSelected = selectedViewsRef.current.some((path) => - EP.isDescendantOf(path, grid.identifier.path), - ) - - return gridItemSelected && !isItemInteractionActive + return selectedViewsRef.current.some((path) => EP.isDescendantOf(path, grid.identifier.path)) }, - [isItemInteractionActive, selectedViewsRef], + [selectedViewsRef], ) } From 842ec482e3180ab68fc6e9df3e52259b54849f4e Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Mon, 18 Nov 2024 11:09:43 +0100 Subject: [PATCH 10/10] update usage --- .../canvas/controls/grid-controls.tsx | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index f0efb4868c90..ac23b73918e0 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -573,7 +573,7 @@ export const GridRowColumnResizingControlsComponent = ({ return ( {gridsWithVisibleResizeControls.flatMap((grid) => { - if (isGridItemSelected(grid)) { + if (isGridItemSelected) { return null } return ( @@ -596,7 +596,7 @@ export const GridRowColumnResizingControlsComponent = ({ ) })} {gridsWithVisibleResizeControls.flatMap((grid) => { - if (isGridItemSelected(grid)) { + if (isGridItemSelected) { return null } return ( @@ -1172,6 +1172,8 @@ export const GridControlsComponent = ({ targets }: GridControlsProps) => { }), ) + const isGridItemSelectedWithoutInteraction = isGridItemSelected && !isGridItemInteractionActive + if (grids.length === 0) { return null } @@ -1184,8 +1186,6 @@ export const GridControlsComponent = ({ targets }: GridControlsProps) => { grid.identifier, ) const shouldHaveVisibleControls = gridsWithVisibleControls.some((g) => { - const isGridItemSelectedWithoutInteraction = - isGridItemSelected(grid) && !isGridItemInteractionActive if (isGridItemSelectedWithoutInteraction) { return false } @@ -2150,11 +2150,8 @@ function useIsGridItemInteractionActive() { function useIsGridItemSelected() { const selectedViewsRef = useRefEditorState((store) => store.editor.selectedViews) - - return React.useCallback( - (grid: GridData) => { - return selectedViewsRef.current.some((path) => EP.isDescendantOf(path, grid.identifier.path)) - }, - [selectedViewsRef], + const jsxMetadataRef = useRefEditorState((store) => store.editor.jsxMetadata) + return selectedViewsRef.current.some((selected) => + MetadataUtils.isGridItem(jsxMetadataRef.current, selected), ) }