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 04c6a3939405..0194fd87c4d4 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 @@ -1230,11 +1230,13 @@ export var storyboard = ( data-label='Playground' data-uid='scene' > - @@ -1277,37 +1279,10 @@ export var storyboard = ( }} data-uid='ddd' /> - + ) - -export function Grid(props) { - return ( -
-
- {props.children} -
-
-
- ) -} ` const ProjectCodeReorderwithMultiCellChildShorthand = `import * as React from 'react' 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 30699b6b2d84..28f14656066c 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 @@ -377,9 +377,15 @@ export var storyboard = ( data-label='Playground' data-uid='scene' > - - +
) - -export function Grid(props) { - return ( -
-
- {props.children} -
-
-
- ) -} ` const ProjectCodeReorderWithComponentItem = `import * as React from 'react' diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategies.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategies.spec.browser2.tsx index b1e296f1aec2..93b7f9182095 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategies.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategies.spec.browser2.tsx @@ -4,7 +4,7 @@ import type { WindowPoint } from '../../../../core/shared/math-utils' import { offsetPoint, windowPoint } from '../../../../core/shared/math-utils' import type { Modifiers } from '../../../../utils/modifiers' import { cmdModifier } from '../../../../utils/modifiers' -import { selectComponentsForTest, wait } from '../../../../utils/utils.test-utils' +import { selectComponentsForTest } from '../../../../utils/utils.test-utils' import { GridCellTestId } from '../../controls/grid-controls-for-strategies' import { CanvasControlsContainerID } from '../../controls/new-canvas-controls' import type { Point } from '../../event-helpers.test-utils' @@ -954,7 +954,7 @@ export var storyboard = ( left: 100, top: 100, width: 300, - height: 300, + height: 300, padding: 10, }} data-uid='grid' diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-ruler-strategy.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-ruler-strategy.ts index d8eeee81929c..4d1ede9c101f 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-ruler-strategy.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-ruler-strategy.ts @@ -16,7 +16,6 @@ import { assertNever } from '../../../../core/shared/utils' import { gridContainerIdentifier, gridItemIdentifier } from '../../../editor/store/editor-state' import { isCSSKeyword } from '../../../inspector/common/css-utils' import { - controlsForGridPlaceholders, controlsForGridRulers, GridResizeControls, } from '../../controls/grid-controls-for-strategies' @@ -82,7 +81,6 @@ export const gridResizeElementRulerStrategy: CanvasStrategyFactory = ( key: `grid-resize-controls-${EP.toString(selectedElement)}`, show: 'always-visible', }, - controlsForGridPlaceholders(gridItemIdentifier(selectedElement)), controlsForGridRulers(gridItemIdentifier(selectedElement)), ], fitness: onlyFitWhenDraggingThisControl(interactionSession, 'GRID_RESIZE_RULER_HANDLE', 1), 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 3231cf6bb4b3..62f10dd05710 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,12 @@ import { offsetPoint, } from '../../../../core/shared/math-utils' import { selectComponentsForTest } from '../../../../utils/utils.test-utils' -import { mouseDownAtPoint, mouseDragFromPointToPoint } from '../../event-helpers.test-utils' +import { + mouseDownAtPoint, + mouseDragFromPointToPoint, + mouseMoveToPoint, + mouseUpAtPoint, +} 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' @@ -26,9 +31,21 @@ import { gridEdgeToEdgePosition } from '../../controls/grid-controls-for-strateg async function runCellResizeTest( editor: EditorRenderResult, edge: GridResizeEdge, + gridPath: ElementPath, dragToCellTestId: string, elementPathToDrag: ElementPath = EP.fromString('sb/scene/grid/ddd'), ) { + await selectComponentsForTest(editor, [gridPath]) + const targetGridCell = editor.renderedDOM.getByTestId(dragToCellTestId) + const endPoint = getRectCenter( + localRectangle({ + x: targetGridCell.getBoundingClientRect().x, + y: targetGridCell.getBoundingClientRect().y, + width: targetGridCell.getBoundingClientRect().width, + height: targetGridCell.getBoundingClientRect().height, + }), + ) + await selectComponentsForTest(editor, [elementPathToDrag]) const resizeControl = editor.renderedDOM.getByTestId( @@ -36,27 +53,10 @@ async function runCellResizeTest( ) const resizeControlBox = resizeControl.getBoundingClientRect() - await mouseDownAtPoint(resizeControl, { x: resizeControlBox.x + 5, y: resizeControlBox.y + 5 }) - const targetGridCell = editor.renderedDOM.getByTestId(dragToCellTestId) - await mouseDragFromPointToPoint( - resizeControl, - { - x: resizeControl.getBoundingClientRect().x + 2, - y: resizeControl.getBoundingClientRect().y + 2, - }, - getRectCenter( - localRectangle({ - x: targetGridCell.getBoundingClientRect().x, - y: targetGridCell.getBoundingClientRect().y, - width: targetGridCell.getBoundingClientRect().width, - height: targetGridCell.getBoundingClientRect().height, - }), - ), - { - moveBeforeMouseDown: true, - }, - ) + await mouseDownAtPoint(resizeControl, { x: resizeControlBox.x + 1, y: resizeControlBox.y + 1 }) + await mouseMoveToPoint(resizeControl, endPoint) + await mouseUpAtPoint(resizeControl, endPoint) } async function runCellResizeTestWithDragVector( @@ -97,6 +97,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'column-end', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 2, 10), ) @@ -116,6 +117,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'column-end', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 2, 8), ) @@ -138,6 +140,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'column-end', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 2, 10), ) @@ -160,6 +163,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'column-end', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 2, 8), ) @@ -181,6 +185,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'column-start', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 2, 6), ) @@ -200,6 +205,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'column-start', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 2, 8), ) @@ -222,6 +228,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'column-start', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 2, 6), ) @@ -244,6 +251,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'column-start', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 2, 8), ) @@ -265,6 +273,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'row-end', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 3, 6), ) { @@ -281,6 +290,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'row-end', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 2, 8), ) { @@ -304,6 +314,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'row-end', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 3, 6), ) { @@ -320,6 +331,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'row-end', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 2, 8), ) { @@ -342,6 +354,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'row-start', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 1, 6), ) @@ -360,6 +373,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'row-start', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 2, 8), ) @@ -383,6 +397,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'row-start', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 1, 6), ) @@ -401,6 +416,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'row-start', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 2, 8), ) @@ -421,6 +437,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'column-end', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 1, 8), ) @@ -465,6 +482,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'column-end', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 1, 8), ) @@ -507,6 +525,7 @@ describe('grid resize element strategy', () => { await runCellResizeTest( editor, 'column-end', + EP.fromString('sb/scene/grid'), gridCellTargetId(EP.fromString('sb/scene/grid'), 2, 10), ) @@ -548,8 +567,6 @@ export var storyboard = ( data-testid='grid' style={{ position: 'absolute', - left: -94, - top: 698, display: 'grid', gap: 10, width: 600, @@ -570,8 +587,8 @@ export var storyboard = ( gridTemplateRows: '1fr', gridColumn: 1, gridRow: 2, - width: '100%', - height: '100%', + width: '100%', + height: '100%', }} >
- @@ -1142,37 +1175,10 @@ export var storyboard = ( data-uid='eee' data-testid='grid-child-stretch' /> - +
) - -export function Grid(props) { - return ( -
-
- {props.children} -
-
-
- ) -} ` const ProjectCodeWithGridArea = `import * as React from 'react' 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 2250a04742af..ca4c4d2b5687 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 @@ -27,14 +27,12 @@ export async function runGridMoveTest( }, midDragCallback?: (editor: EditorRenderResult) => void, ) { - const elementPathToDrag = EP.appendToPath(EP.fromString(props.gridPath), props.testId) - - await selectComponentsForTest(editor, [elementPathToDrag]) - if (props.scale !== 1) { await editor.dispatch([CanvasActions.zoom(props.scale)], true) } + await selectComponentsForTest(editor, [EP.fromString(props.gridPath)]) + const elementPathToDrag = EP.appendToPath(EP.fromString(props.gridPath), props.testId) // trigger the grid controls so we know where to find the cells const { sourceGridCell, dragFrom, dragTo } = await getSafeGridMoveTestEndpoints( editor, @@ -46,6 +44,8 @@ export async function runGridMoveTest( }, ) + await selectComponentsForTest(editor, [elementPathToDrag]) + await mouseDownAtPoint(sourceGridCell, dragFrom) await mouseMoveToPoint(sourceGridCell, dragTo) if (props.tab) { diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index 4a2475f88264..b8e2ee97453f 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -51,7 +51,7 @@ import type { Optic } from '../../../core/shared/optics/optics' import { optionalMap } from '../../../core/shared/optional-utils' import { assertNever, NO_OP } from '../../../core/shared/utils' import { Modifier } from '../../../utils/modifiers' -import { when } from '../../../utils/react-conditionals' +import { unless, when } from '../../../utils/react-conditionals' import type { UtopiColor } from '../../../uuiui' import { useColorTheme, UtopiaStyles } from '../../../uuiui' import { useDispatch } from '../../editor/store/dispatch-context' @@ -69,6 +69,7 @@ import { isGridCSSRepeat, printCSSNumberWithDefaultUnit, printGridCSSNumber, + stringifyGridDimension, } from '../../inspector/common/css-utils' import CanvasActions from '../canvas-actions' import type { GridResizeEdge } from '../canvas-strategies/interaction-state' @@ -2217,7 +2218,7 @@ const RulerMarkers = React.memo((props: RulerMarkersProps) => { const [frozenMarkers, setFrozenMarkers] = React.useState(null) const [showExtraMarkers, setShowExtraMarkers] = React.useState<'row' | 'column' | null>(null) - const gridRect: CanvasRectangle | null = useEditorState( + const gridData = useEditorState( Substores.metadata, (store) => { const originalGrid = findOriginalGrid(store.editor.jsxMetadata, EP.parentPath(props.path)) @@ -2225,7 +2226,13 @@ const RulerMarkers = React.memo((props: RulerMarkersProps) => { return null } - return MetadataUtils.getFrameOrZeroRectInCanvasCoords(originalGrid, store.editor.jsxMetadata) + return { + gridPath: originalGrid, + gridRect: MetadataUtils.getFrameOrZeroRectInCanvasCoords( + originalGrid, + store.editor.jsxMetadata, + ), + } }, 'RulerMarkers gridRect', ) @@ -2249,10 +2256,12 @@ const RulerMarkers = React.memo((props: RulerMarkersProps) => { const rulerMarkerData: RulerMarkerData | null = useEditorState( Substores.metadata, (store) => { - if (gridRect == null || parentGridCellGlobalFrames == null) { + if (gridData == null || parentGridCellGlobalFrames == null) { return null } + const gridRect = gridData.gridRect + const elementMetadata = MetadataUtils.findElementByElementPath( store.editor.jsxMetadata, props.path, @@ -2463,7 +2472,7 @@ const RulerMarkers = React.memo((props: RulerMarkersProps) => { [markerMouseUp, props, startResizeInteraction, rulerMarkerData, setForceShowGridPlaceholders], ) - if (rulerMarkerData == null || gridRect == null) { + if (rulerMarkerData == null || gridData == null) { return null } @@ -2473,7 +2482,7 @@ const RulerMarkers = React.memo((props: RulerMarkersProps) => { @@ -2514,7 +2523,7 @@ const RulerMarkers = React.memo((props: RulerMarkersProps) => { @@ -2587,8 +2596,8 @@ const RulerMarkers = React.memo((props: RulerMarkersProps) => { height={rulerMarkerData.cellRect.height + 1} /> - {/* Snap line during resize */} - { const colorTheme = useColorTheme() + const gridData = useGridMeasurementHelperData(props.gridPath, 'element') + const targetMarker = React.useMemo(() => { if (props.edge == null) { return null @@ -2704,7 +2716,10 @@ const SnapLine = React.memo( targetMarker == null || targetMarker.position == null || targetFrozenMarker == null || - targetFrozenMarker.position == null + targetFrozenMarker.position == null || + props.gridTemplate.gridTemplateColumns?.type !== 'DIMENSIONS' || + props.gridTemplate.gridTemplateRows?.type !== 'DIMENSIONS' || + gridData == null ) { return null } @@ -2723,49 +2738,122 @@ const SnapLine = React.memo( ? props.container.x : props.target.x + (props.edge === 'column-end' ? props.target.width : 0) + const columns = props.gridTemplate.gridTemplateColumns.dimensions + const rows = props.gridTemplate.gridTemplateRows.dimensions + + // TODO if hasGap === true, then maybe there shouldn't be duplicate lines for the same adjacent rows/cols + const hasGap = + (isColumn + ? gridData.gap ?? gridData.columnGap ?? 0 + : gridData.gap ?? gridData.rowGap ?? 0) !== 0 + return ( -
- {when( - showLabel, -
- + {/* The default snap lines for the current edge */} +
stringifyGridDimension(d)).join(' ') + : undefined, + gridTemplateRows: !isColumn + ? rows.map((d) => stringifyGridDimension(d)).join(' ') + : undefined, + gap: gridData.gap ?? undefined, + rowGap: gridData.rowGap ?? undefined, + columnGap: gridData.columnGap ?? undefined, + padding: + `${gridData.padding.top ?? 0}px ` + + `${gridData.padding.left ?? 0}px ` + + `${gridData.padding.bottom ?? 0}px ` + + `${gridData.padding.right ?? 0}px`, + }} + > + {when( + isColumn, + columns.map((_, index) => { + return ( +
0 && hasGap ? `1px solid ${colorTheme.grey65.value}` : undefined, + borderRight: + index < columns.length - 1 + ? `1px solid ${colorTheme.grey65.value}` + : undefined, + }} + /> + ) + }), + )} + {unless( + isColumn, + rows.map((_, index) => { + return ( +
0 && hasGap ? `1px solid ${colorTheme.grey65.value}` : undefined, + borderBottom: + index < rows.length - 1 ? `1px solid ${colorTheme.grey65.value}` : undefined, + }} + /> + ) + }), + )} +
+ {/* The current snapline */} +
+ {when( + showLabel, +
- {printPin(props.gridTemplate, targetMarker.position, axis)} - -
, - )} -
+ + {printPin(props.gridTemplate, targetMarker.position, axis)} + +
, + )} +
+ ) }, ) -SnapLine.displayName = 'SnapLine' +SnapLines.displayName = 'SnapLines' interface GridRulerProps { axis: 'row' | 'column'