From ef76c9ff17458c14462b7958f67bc225852698b2 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Wed, 27 Nov 2024 12:57:01 +0100 Subject: [PATCH] prefer spans when resizing flow cells --- ...-resize-element-strategy.spec.browser2.tsx | 101 ++++++++++++++++++ .../grid-resize-element-strategy.ts | 40 +++++-- 2 files changed, 135 insertions(+), 6 deletions(-) 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 1f07c6144cce..3231cf6bb4b3 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 @@ -849,6 +849,107 @@ export var storyboard = ( }) } }) + it('uses spans for flow elements', async () => { + const editor = await renderTestEditorWithCode( + makeProjectCodeWithCustomPlacement({ gridColumn: 'auto', gridRow: 'auto' }), + 'await-first-dom-report', + ) + + // enlarge to the right, spans in flow + { + await runCellResizeTest( + editor, + 'column-end', + gridCellTargetId(EP.fromString('sb/grid'), 1, 3), + EP.fromString('sb/grid/cell'), + ) + + const { gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd } = + editor.renderedDOM.getByTestId('cell').style + expect({ gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd }).toEqual({ + gridColumnEnd: 'auto', + gridColumnStart: 'span 3', + gridRowEnd: 'auto', + gridRowStart: 'auto', + }) + } + + // enlarge to the bottom, still spans in flow + { + await runCellResizeTest( + editor, + 'row-end', + gridCellTargetId(EP.fromString('sb/grid'), 4, 3), + EP.fromString('sb/grid/cell'), + ) + + const { gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd } = + editor.renderedDOM.getByTestId('cell').style + expect({ gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd }).toEqual({ + gridColumnEnd: 'auto', + gridColumnStart: 'span 3', + gridRowEnd: 'auto', + gridRowStart: 'span 4', + }) + } + + // shrink from the right, still spans in flow + { + await runCellResizeTest( + editor, + 'column-end', + gridCellTargetId(EP.fromString('sb/grid'), 4, 2), + EP.fromString('sb/grid/cell'), + ) + + const { gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd } = + editor.renderedDOM.getByTestId('cell').style + expect({ gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd }).toEqual({ + gridColumnEnd: 'auto', + gridColumnStart: 'span 2', + gridRowEnd: 'auto', + gridRowStart: 'span 4', + }) + } + + // shrink from the bottom, still spans in flow + { + await runCellResizeTest( + editor, + 'row-end', + gridCellTargetId(EP.fromString('sb/grid'), 3, 2), + EP.fromString('sb/grid/cell'), + ) + + const { gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd } = + editor.renderedDOM.getByTestId('cell').style + expect({ gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd }).toEqual({ + gridColumnEnd: 'auto', + gridColumnStart: 'span 2', + gridRowEnd: 'auto', + gridRowStart: 'span 3', + }) + } + + // shrink from the top, it spans but now is pinned + { + await runCellResizeTest( + editor, + 'row-start', + gridCellTargetId(EP.fromString('sb/grid'), 2, 2), + EP.fromString('sb/grid/cell'), + ) + + const { gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd } = + editor.renderedDOM.getByTestId('cell').style + expect({ gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd }).toEqual({ + gridColumnEnd: 'auto', + gridColumnStart: 'span 2', + gridRowEnd: '4', + gridRowStart: 'span 2', + }) + } + }) }) }) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-strategy.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-strategy.ts index 7e3ec36af17c..95047968c676 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-strategy.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-strategy.ts @@ -27,8 +27,8 @@ import { emptyStrategyApplicationResult, strategyApplicationResult, } from '../canvas-strategy-types' -import type { InteractionSession } from '../interaction-state' -import { getCommandsForGridItemPlacement } from './grid-helpers' +import type { GridResizeEdge, InteractionSession } from '../interaction-state' +import { getCommandsForGridItemPlacement, isAutoGridPin } from './grid-helpers' import { resizeBoundingBoxFromSide } from './resize-helpers' export const gridResizeElementStrategy: CanvasStrategyFactory = ( @@ -138,6 +138,7 @@ export const gridResizeElementStrategy: CanvasStrategyFactory = ( 'start', elementGridPropertiesFromProps.gridColumnEnd, gridPropsNumeric.gridColumnEnd, + interactionSession.activeControl.edge, ), gridColumnEnd: normalizePositionAfterResize( elementGridPropertiesFromProps.gridColumnEnd, @@ -146,6 +147,7 @@ export const gridResizeElementStrategy: CanvasStrategyFactory = ( 'end', elementGridPropertiesFromProps.gridColumnStart, gridPropsNumeric.gridColumnStart, + interactionSession.activeControl.edge, ), gridRowStart: normalizePositionAfterResize( elementGridPropertiesFromProps.gridRowStart, @@ -154,6 +156,7 @@ export const gridResizeElementStrategy: CanvasStrategyFactory = ( 'start', elementGridPropertiesFromProps.gridRowEnd, gridPropsNumeric.gridRowEnd, + interactionSession.activeControl.edge, ), gridRowEnd: normalizePositionAfterResize( elementGridPropertiesFromProps.gridRowEnd, @@ -162,6 +165,7 @@ export const gridResizeElementStrategy: CanvasStrategyFactory = ( 'end', elementGridPropertiesFromProps.gridRowStart, gridPropsNumeric.gridRowStart, + interactionSession.activeControl.edge, ), } @@ -211,9 +215,12 @@ function getNewGridPropsFromResizeBox( } } -// After a resize happens and we know the numerical grid positioning of the new bounds, -// return a normalized version of the new position so that it respects any spans that -// may have been there before the resize, and/or default it to 'auto' when it would become redundant. +/* + After a resize happens and we know the numerical grid positioning of the new bounds, + return a normalized version of the new position so that it respects any spans that + may have been there before the resize, and/or default it to 'auto' when it would become redundant. + If the positions match a flow configuration, give priority to span notation. +*/ function normalizePositionAfterResize( position: GridPositionOrSpan | null, resizedPosition: GridPositionValue, @@ -221,13 +228,34 @@ function normalizePositionAfterResize( bound: 'start' | 'end', counterpart: GridPositionOrSpan | null, counterpartResizedPosition: GridPositionValue, + edge: GridResizeEdge, ): GridPositionOrSpan | null { - if (isGridSpan(position)) { + function isFlowResizeOnBound( + wantedBound: 'start' | 'end', + flowStart: GridPositionOrSpan | null, + flowEnd: GridPositionOrSpan | null, + ): boolean { + return ( + (edge === 'column-end' || edge === 'row-end') && + bound === wantedBound && + (isGridSpan(flowStart) || isAutoGridPin(flowStart) || flowStart == null) && + (isAutoGridPin(flowEnd) || flowEnd == null) + ) + } + + const isFlowStart = isFlowResizeOnBound('start', position, counterpart) + if (isFlowStart || isGridSpan(position)) { if (size === 1) { return cssKeyword('auto') } return gridSpanNumeric(size) } + + const isFlowEnd = isFlowResizeOnBound('end', counterpart, position) + if (isFlowEnd) { + return cssKeyword('auto') + } + if ( isGridSpan(counterpart) && counterpartResizedPosition.numericalPosition === 1 &&