From ffa24f69e3d51fedcaafddca2cb0a56032c101c5 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:01:24 +0100 Subject: [PATCH] Preserve span when changing grid item position (#6633) **Problem:** `span` values for grid child positioning props are wiped when using `gridChangeElementLocationStrategy`. **Fix:** Rework the way grid element props are calculated when changing element location pins, so that `spans` are respected and kept in place if present. The behavior is now so that: - when it makes sense to do so, return shorthand versions of grid positioning props - when moving an element with `span` values, support moving them when the span is in the starting prop as well as the ending prop Examples for moving a item one cell to the right: | Initial config | Result | |------------|------------| | `gridColumn: 'span 2'` | `gridColumn: 'span 2 / 4'` | | `gridColumn: '2 / span 2'` | `gridColumn: '3 / span 2'` | | `gridColumnStart: 'span 2'` | `gridColumn: 'span 2 / 4'` | | `gridColumnEnd: 'span 2'` | `gridColumn: '3 / span 2'` | **Note:** a subsequent PR will take care of also keepign `span` intact for the reorder strategy. Fixes #6639 --- ...ange-element-location-keyboard-strategy.ts | 4 +- .../grid-change-element-location-strategy.ts | 140 ++++++------ .../grid-draw-to-insert-strategy.tsx | 4 +- ...change-location-strategy.spec.browser2.tsx | 215 +++++++++++++++++- .../strategies/grid-helpers.ts | 196 +++++++++------- ...-resize-element-strategy.spec.browser2.tsx | 3 +- .../grid-resize-element-strategy.ts | 4 +- .../src/components/inspector/flex-section.tsx | 8 +- .../grid-cell-subsection.tsx | 16 +- 9 files changed, 415 insertions(+), 175 deletions(-) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-change-element-location-keyboard-strategy.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid-change-element-location-keyboard-strategy.ts index 3fcda3e09695..0bee8900873a 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-change-element-location-keyboard-strategy.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-change-element-location-keyboard-strategy.ts @@ -10,7 +10,7 @@ import { strategyApplicationResult, } from '../canvas-strategy-types' import type { InteractionSession } from '../interaction-state' -import { setGridPropsCommands } from './grid-helpers' +import { getCommandsForGridItemPlacement } from './grid-helpers' import { getGridChildCellCoordBoundsFromCanvas } from './grid-cell-bounds' import { accumulatePresses } from './shared-keyboard-strategy-helpers' import { gridItemIdentifier } from '../../../editor/store/editor-state' @@ -121,7 +121,7 @@ export function gridChangeElementLocationResizeKeyboardStrategy( } return strategyApplicationResult( - setGridPropsCommands(target, gridTemplate, { + getCommandsForGridItemPlacement(target, gridTemplate, { gridColumnStart, gridColumnEnd, gridRowStart, diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-change-element-location-strategy.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid-change-element-location-strategy.ts index b9afa1388885..fcef295fbbba 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-change-element-location-strategy.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-change-element-location-strategy.ts @@ -1,16 +1,18 @@ import type { ElementPath } from 'utopia-shared/src/types' import { MetadataUtils } from '../../../../core/model/element-metadata-utils' import * as EP from '../../../../core/shared/element-path' -import * as PP from '../../../../core/shared/property-path' import type { ElementInstanceMetadata, ElementInstanceMetadataMap, GridContainerProperties, GridElementProperties, + GridPositionOrSpan, } from '../../../../core/shared/element-template' -import { gridPositionValue, isJSXElement } from '../../../../core/shared/element-template' -import { isInfinityRectangle } from '../../../../core/shared/math-utils' +import { gridPositionValue, isGridSpan } from '../../../../core/shared/element-template' import { absolute } from '../../../../utils/utils' +import { gridItemIdentifier } from '../../../editor/store/editor-state' +import { cssKeyword } from '../../../inspector/common/css-utils' +import { getTargetGridCellData } from '../../../inspector/grid-helpers' import type { CanvasCommand } from '../../commands/commands' import { reorderElement } from '../../commands/reorder-element-command' import { showGridControls } from '../../commands/show-grid-controls-command' @@ -29,18 +31,10 @@ import { getOriginalElementGridConfiguration, getParentGridTemplatesFromChildMeasurements, gridMoveStrategiesExtraCommands, - setGridPropsCommands, + isAutoGridPin, + getCommandsForGridItemPlacement, sortElementsByGridPosition, } from './grid-helpers' -import { getTargetGridCellData } from '../../../inspector/grid-helpers' -import { forEachOf } from '../../../../core/shared/optics/optic-utilities' -import { - eitherRight, - fromField, - fromTypeGuard, -} from '../../../../core/shared/optics/optic-creators' -import { getJSXAttributesAtPath } from '../../../..//core/shared/jsx-attribute-utils' -import { gridItemIdentifier } from '../../../editor/store/editor-state' export const gridChangeElementLocationStrategy: CanvasStrategyFactory = ( canvasState: InteractionCanvasState, @@ -217,67 +211,83 @@ export function runGridChangeElementLocation( } const { targetCellCoords, targetRootCell } = targetGridCellData - const gridProps: Partial = { - gridColumnStart: gridPositionValue(targetRootCell.column), - gridColumnEnd: gridPositionValue(targetRootCell.column + originalCellBounds.width), - gridRowStart: gridPositionValue(targetRootCell.row), - gridRowEnd: gridPositionValue(targetRootCell.row + originalCellBounds.height), - } - - // TODO: Remove this logic once there is a fix for the handling of the track end fields. - let keepGridColumnEnd: boolean = true - let keepGridRowEnd: boolean = true - forEachOf( - fromField('element') - .compose(eitherRight()) - .compose(fromTypeGuard(isJSXElement)) - .compose(fromField('props')), - selectedElementMetadata, - (elementProperties) => { - function shouldKeep(shorthandProp: 'gridColumn' | 'gridRow'): boolean { - const longhandProp = shorthandProp === 'gridColumn' ? 'gridColumnEnd' : 'gridRowEnd' + const elementGridProperties = + selectedElementMetadata.specialSizeMeasurements.elementGridProperties - const shorthand = getJSXAttributesAtPath( - elementProperties, - PP.create('style', shorthandProp), - ) - if ( - shorthand.attribute.type === 'ATTRIBUTE_VALUE' && - typeof shorthand.attribute.value === 'string' && - shorthand.attribute.value.includes('/') - ) { - return true + function getUpdatedPins( + start: GridPositionOrSpan | null, + end: GridPositionOrSpan | null, + axis: 'row' | 'column', + dimension: number, + ): { + start: GridPositionOrSpan + end: GridPositionOrSpan + } { + const isSpanning = isGridSpan(start) || isGridSpan(end) + if (isSpanning) { + if (isGridSpan(start)) { + const isEndGridSpanArea = isGridSpan(end) || start.type === 'SPAN_AREA' + if (!isEndGridSpanArea) { + return { + start: start, + end: gridPositionValue(start.value + targetRootCell[axis]), + } } - - const longhand = getJSXAttributesAtPath(elementProperties, PP.create('style', longhandProp)) - if (longhand.attribute.type !== 'ATTRIBUTE_NOT_FOUND') { - return true + } else if (isGridSpan(end)) { + return { + start: gridPositionValue(targetRootCell[axis]), + end: end, } - - return false } - keepGridColumnEnd = shouldKeep('gridColumn') - keepGridRowEnd = shouldKeep('gridRow') - }, + } else { + const shouldSetEndPosition = end != null && !isAutoGridPin(end) + if (shouldSetEndPosition) { + return { + start: gridPositionValue(targetRootCell[axis]), + end: + dimension === 1 + ? cssKeyword('auto') + : gridPositionValue(targetRootCell[axis] + dimension), + } + } + return { + start: gridPositionValue(targetRootCell[axis]), + end: cssKeyword('auto'), + } + } + + return { + start: cssKeyword('auto'), + end: cssKeyword('auto'), + } + } + + const columnBounds = getUpdatedPins( + elementGridProperties.gridColumnStart, + elementGridProperties.gridColumnEnd, + 'column', + originalCellBounds.width, + ) + + const rowBounds = getUpdatedPins( + elementGridProperties.gridRowStart, + elementGridProperties.gridRowEnd, + 'row', + originalCellBounds.height, ) - const gridCellMoveCommands = setGridPropsCommands( + const gridProps: GridElementProperties = { + gridColumnStart: columnBounds.start, + gridColumnEnd: columnBounds.end, + gridRowStart: rowBounds.start, + gridRowEnd: rowBounds.end, + } + + const gridCellMoveCommands = getCommandsForGridItemPlacement( pathForCommands, gridTemplate, gridProps, - ).filter((command) => { - if (command.type === 'SET_PROPERTY') { - if (PP.pathsEqual(command.property, PP.create('style', 'gridColumnEnd'))) { - return keepGridColumnEnd - } else if (PP.pathsEqual(command.property, PP.create('style', 'gridRowEnd'))) { - return keepGridRowEnd - } else { - return true - } - } else { - return true - } - }) + ) // The siblings of the grid element being moved const siblings = MetadataUtils.getSiblingsUnordered( diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-draw-to-insert-strategy.tsx b/editor/src/components/canvas/canvas-strategies/strategies/grid-draw-to-insert-strategy.tsx index 67cd1ee92d96..530ad70803d7 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-draw-to-insert-strategy.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-draw-to-insert-strategy.tsx @@ -43,7 +43,7 @@ import { getStyleAttributesForFrameInAbsolutePosition, updateInsertionSubjectWithAttributes, } from './draw-to-insert-metastrategy' -import { setGridPropsCommands } from './grid-helpers' +import { getCommandsForGridItemPlacement } from './grid-helpers' import { newReparentSubjects } from './reparent-helpers/reparent-strategy-helpers' import { getReparentTargetUnified } from './reparent-helpers/reparent-strategy-parent-lookup' import { getGridCellUnderMouseFromMetadata } from './grid-cell-bounds' @@ -212,7 +212,7 @@ const gridDrawToInsertStrategyInner = [ insertionCommand, ...nukeAllAbsolutePositioningPropsCommands(insertedElementPath), // do not use absolute positioning in grid cells - ...setGridPropsCommands(insertedElementPath, gridTemplate, { + ...getCommandsForGridItemPlacement(insertedElementPath, gridTemplate, { gridRowStart: { numericalPosition: gridCellCoordinates.row }, gridColumnStart: { numericalPosition: gridCellCoordinates.column }, gridRowEnd: { numericalPosition: gridCellCoordinates.row + 1 }, 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 13fb04febe05..3251f3a7136b 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 @@ -174,7 +174,6 @@ describe('grid element change location strategy', () => { scale: 1, pathString: `sb/scene/grid/${testId}`, testId: testId, - tab: true, targetCell: { row: 3, column: 1 }, }) @@ -220,6 +219,112 @@ describe('grid element change location strategy', () => { }) }) + it('can change the location of an element with span (from start, implicit end)', async () => { + const editor = await renderTestEditorWithCode( + ProjectCodeWithSpanningItems, + 'await-first-dom-report', + ) + + const testId = 'pink' + const { gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd } = await runMoveTest(editor, { + scale: 1, + pathString: `sb/scene/grid/${testId}`, + testId: testId, + }) + + expect({ gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd }).toEqual({ + gridColumnEnd: '5', + gridColumnStart: 'span 2', + gridRowEnd: 'auto', + gridRowStart: '2', + }) + }) + + it('can change the location of an element with span (from start, explicit end)', async () => { + const editor = await renderTestEditorWithCode( + ProjectCodeWithSpanningItems, + 'await-first-dom-report', + ) + + const testId = 'cyan' + const { gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd } = await runMoveTest(editor, { + scale: 1, + pathString: `sb/scene/grid/${testId}`, + testId: testId, + }) + + expect({ gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd }).toEqual({ + gridColumnEnd: '5', + gridColumnStart: 'span 2', + gridRowEnd: 'auto', + gridRowStart: '2', + }) + }) + + it('can change the location of an element with span (from end, explicit start)', async () => { + const editor = await renderTestEditorWithCode( + ProjectCodeWithSpanningItems, + 'await-first-dom-report', + ) + + const testId = 'orange' + const { gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd } = await runMoveTest(editor, { + scale: 1, + pathString: `sb/scene/grid/${testId}`, + testId: testId, + targetCell: { row: 3, column: 2 }, + }) + + expect({ gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd }).toEqual({ + gridColumnEnd: 'span 3', + gridColumnStart: '2', + gridRowEnd: 'auto', + gridRowStart: '3', + }) + }) + + it('can change the location of an element with span (longhand start)', async () => { + const editor = await renderTestEditorWithCode( + ProjectCodeWithSpanningItems, + 'await-first-dom-report', + ) + + const testId = 'blue' + const { gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd } = await runMoveTest(editor, { + scale: 1, + pathString: `sb/scene/grid/${testId}`, + testId: testId, + }) + + expect({ gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd }).toEqual({ + gridColumnEnd: '5', + gridColumnStart: 'span 2', + gridRowEnd: 'auto', + gridRowStart: '2', + }) + }) + + it('can change the location of an element with span (longhand end)', async () => { + const editor = await renderTestEditorWithCode( + ProjectCodeWithSpanningItems, + 'await-first-dom-report', + ) + + const testId = 'purple' + const { gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd } = await runMoveTest(editor, { + scale: 1, + pathString: `sb/scene/grid/${testId}`, + testId: testId, + }) + + expect({ gridRowStart, gridRowEnd, gridColumnStart, gridColumnEnd }).toEqual({ + gridColumnEnd: 'span 2', + gridColumnStart: '3', + gridRowEnd: 'auto', + gridRowStart: '2', + }) + }) + describe('grids within grids', () => { it('can move a grid child that is a grid itself', async () => { const editor = await renderTestEditorWithCode( @@ -594,9 +699,9 @@ export var storyboard = ( child.style expect({ top, left, gridColumnStart, gridColumnEnd, gridRowStart, gridRowEnd }).toEqual({ gridColumnStart: '1', - gridColumnEnd: '', + gridColumnEnd: 'auto', gridRowStart: '1', - gridRowEnd: '', + gridRowEnd: 'auto', left: '59px', top: '59.5px', }) @@ -866,13 +971,7 @@ export var storyboard = ( 'await-first-dom-report', ) - const result = await runReorderTest( - editor, - 'sb/scene/grid', - 'orange', - { row: 1, column: 1 }, - { tab: true }, - ) + const result = await runReorderTest(editor, 'sb/scene/grid', 'orange', { row: 1, column: 1 }) expect({ gridRowStart: result.gridRowStart, gridRowEnd: result.gridRowEnd, @@ -1568,3 +1667,99 @@ export var storyboard = ( ) ` + +const ProjectCodeWithSpanningItems = `import * as React from 'react' +import { Scene, Storyboard } from 'utopia-api' + +export var storyboard = ( + + +
+
+
+
+
+
+
+ + +) +` 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 23a1bd1e8794..1bf896aac5d7 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts @@ -12,6 +12,7 @@ import type { } from '../../../../core/shared/element-template' import { isGridSpan, + stringifyGridSpan, type ElementInstanceMetadata, type GridContainerProperties, type GridElementProperties, @@ -21,6 +22,7 @@ import * as PP from '../../../../core/shared/property-path' import { assertNever } from '../../../../core/shared/utils' import type { GridDimension } from '../../../inspector/common/css-utils' import { + cssKeyword, gridCSSRepeat, isCSSKeyword, isGridCSSRepeat, @@ -70,7 +72,11 @@ export function gridPositionToValue( return p.numericalPosition } -export function setGridPropsCommands( +export function isAutoGridPin(v: GridPositionOrSpan): boolean { + return isCSSKeyword(v) && v.value === 'auto' +} + +export function getCommandsForGridItemPlacement( elementPath: ElementPath, gridTemplate: GridContainerProperties, gridProps: Partial, @@ -86,66 +92,105 @@ export function setGridPropsCommands( PP.create('style', 'gridRowEnd'), ]), ] - const columnStart = gridPositionToValue(gridProps.gridColumnStart, null) - const columnEnd = gridPositionToValue(gridProps.gridColumnEnd, gridProps.gridColumnStart ?? null) - const rowStart = gridPositionToValue(gridProps.gridRowStart, null) - const rowEnd = gridPositionToValue(gridProps.gridRowEnd, gridProps.gridRowStart ?? null) - - const lineColumnStart = asMaybeNamedLineOrValue(gridTemplate, 'column', columnStart) - const lineColumnEnd = asMaybeNamedLineOrValue(gridTemplate, 'column', columnEnd) - const lineRowStart = asMaybeNamedLineOrValue(gridTemplate, 'row', rowStart) - const lineRowEnd = asMaybeNamedLineOrValue(gridTemplate, 'row', rowEnd) - - if (columnStart != null && columnStart === columnEnd) { - commands.push( - setProperty('always', elementPath, PP.create('style', 'gridColumn'), lineColumnStart), - ) - } else if ( - columnStart != null && - typeof columnStart === 'number' && - columnEnd != null && - typeof columnEnd === 'number' && - columnStart === columnEnd - 1 - ) { - commands.push( - setProperty('always', elementPath, PP.create('style', 'gridColumn'), lineColumnStart), - ) - } else { - if (columnStart != null) { - commands.push( - setProperty('always', elementPath, PP.create('style', 'gridColumnStart'), lineColumnStart), - ) + + function printPin(pin: GridPositionOrSpan, axis: 'row' | 'column'): string | number { + if (isGridSpan(pin)) { + return stringifyGridSpan(pin) } - if (columnEnd != null) { - commands.push( - setProperty('always', elementPath, PP.create('style', 'gridColumnEnd'), lineColumnEnd), - ) + if (isCSSKeyword(pin)) { + return pin.value } + const tracks = + axis === 'column' ? gridTemplate.gridTemplateColumns : gridTemplate.gridTemplateRows + const maybeLineName = + tracks?.type === 'DIMENSIONS' + ? tracks.dimensions.find((_, index) => index + 1 === pin.numericalPosition)?.lineName + : null + if (maybeLineName != null) { + return maybeLineName + } + return pin.numericalPosition ?? 'auto' } - if (rowStart != null && rowStart === rowEnd) { - commands.push(setProperty('always', elementPath, PP.create('style', 'gridRow'), lineRowStart)) - } else if ( - rowStart != null && - typeof rowStart === 'number' && - rowEnd != null && - typeof rowEnd === 'number' && - rowStart === rowEnd - 1 - ) { - commands.push(setProperty('always', elementPath, PP.create('style', 'gridRow'), lineRowStart)) - } else { - if (rowStart != null) { - commands.push( - setProperty('always', elementPath, PP.create('style', 'gridRowStart'), lineRowStart), - ) + function serializeAxis( + startPosition: GridPositionOrSpan, + endPosition: GridPositionOrSpan, + axis: 'row' | 'column', + ): { + property: + | 'gridColumn' + | 'gridColumnStart' + | 'gridColumnEnd' + | 'gridRow' + | 'gridRowStart' + | 'gridRowEnd' + value: string | number + } { + const startValue = printPin(startPosition, axis) + const endValue = printPin(endPosition, axis) + + if (isAutoGridPin(startPosition) && !isAutoGridPin(endPosition)) { + return { + property: axis === 'column' ? 'gridColumnEnd' : 'gridRowEnd', + value: endValue, + } } - if (rowEnd != null) { - commands.push( - setProperty('always', elementPath, PP.create('style', 'gridRowEnd'), lineRowEnd), - ) + + function shouldReturnSingleValue(): boolean { + const isAutoPin = isAutoGridPin(endPosition) + if (isAutoPin) { + return true + } + + const printedValuedEqual = startValue === endValue + if (printedValuedEqual) { + return true + } + + const positionsAreNumeric = + isGridPositionNumericValue(endPosition) && isGridPositionNumericValue(startPosition) + if (positionsAreNumeric) { + const startNumericPosition = startPosition.numericalPosition ?? 0 + const endNumericPosition = endPosition.numericalPosition ?? 0 + const positionsDeltaAtMostOne = + endNumericPosition >= startNumericPosition && + endNumericPosition - startNumericPosition <= 1 + if (positionsDeltaAtMostOne) { + return true + } + } + + return false + } + if (shouldReturnSingleValue()) { + return { + property: axis === 'column' ? 'gridColumn' : 'gridRow', + value: startValue, + } + } + + return { + property: axis === 'column' ? 'gridColumn' : 'gridRow', + value: `${startValue} / ${endValue}`, } } + const gridColumn = serializeAxis( + gridProps.gridColumnStart ?? cssKeyword('auto'), + gridProps.gridColumnEnd ?? cssKeyword('auto'), + 'column', + ) + const gridColumnProp = PP.create('style', gridColumn.property) + commands.push(setProperty('always', elementPath, gridColumnProp, gridColumn.value)) + + const gridRow = serializeAxis( + gridProps.gridRowStart ?? cssKeyword('auto'), + gridProps.gridRowEnd ?? cssKeyword('auto'), + 'row', + ) + const gridRowProp = PP.create('style', gridRow.property) + commands.push(setProperty('always', elementPath, gridRowProp, gridRow.value)) + return commands } @@ -195,26 +240,6 @@ function getCellCoordsDelta( return gridCellCoordinates(rowDiff, columnDiff) } -function asMaybeNamedLineOrValue( - grid: GridContainerProperties, - axis: 'row' | 'column', - value: number | string | null, -): string | number { - if (value == null) { - return 1 - } else if (typeof value === 'number') { - const template = axis === 'row' ? grid.gridTemplateRows : grid.gridTemplateColumns - if (template?.type === 'DIMENSIONS') { - const maybeLineStart = template.dimensions.at(value - 1) - if (maybeLineStart != null && maybeLineStart.lineName != null) { - return maybeLineStart.lineName - } - } - return value === 0 ? 1 : value - } - return value -} - export type SortableGridElementProperties = GridElementProperties & { path: ElementPath index: number @@ -254,7 +279,7 @@ export function sortElementsByGridPosition(gridTemplateColumns: number) { } function isGridPositionNumericValue(p: GridPositionOrSpan | null): p is GridPositionValue { - return p != null && !(isCSSKeyword(p) && !isGridSpan(p) && p.value === 'auto') + return p != null && !isGridSpan(p) && !(isCSSKeyword(p) && p.value === 'auto') } export function getGridPositionIndex(props: { @@ -537,18 +562,22 @@ export function getGridElementPinState( elementGridPropertiesFromProps: GridElementProperties | null, ): GridElementPinState { if ( - elementGridPropertiesFromProps?.gridColumnEnd == null || - elementGridPropertiesFromProps?.gridColumnStart == null || - elementGridPropertiesFromProps?.gridRowEnd == null || + elementGridPropertiesFromProps?.gridColumnEnd == null && + elementGridPropertiesFromProps?.gridColumnStart == null && + elementGridPropertiesFromProps?.gridRowEnd == null && elementGridPropertiesFromProps?.gridRowStart == null ) { return 'not-pinned' } if ( - isGridPositionNumericValue(elementGridPropertiesFromProps?.gridColumnEnd ?? null) || - isGridPositionNumericValue(elementGridPropertiesFromProps?.gridColumnStart ?? null) || - isGridPositionNumericValue(elementGridPropertiesFromProps?.gridRowEnd ?? null) || - isGridPositionNumericValue(elementGridPropertiesFromProps?.gridRowStart ?? null) + isGridPositionNumericValue(elementGridPropertiesFromProps?.gridColumnEnd) || + isGridSpan(elementGridPropertiesFromProps?.gridColumnEnd) || + isGridPositionNumericValue(elementGridPropertiesFromProps?.gridColumnStart) || + isGridSpan(elementGridPropertiesFromProps?.gridColumnStart) || + isGridPositionNumericValue(elementGridPropertiesFromProps?.gridRowEnd) || + isGridSpan(elementGridPropertiesFromProps?.gridRowEnd) || + isGridPositionNumericValue(elementGridPropertiesFromProps?.gridRowStart) || + isGridSpan(elementGridPropertiesFromProps?.gridRowStart) ) { return 'pinned' } @@ -556,10 +585,7 @@ export function getGridElementPinState( } export function isFlowGridChild(child: ElementInstanceMetadata) { - return ( - getGridElementPinState(child.specialSizeMeasurements.elementGridPropertiesFromProps) !== - 'pinned' - ) + return getGridElementPinState(child.specialSizeMeasurements.elementGridProperties) !== 'pinned' } function restoreGridTemplateFromProps(params: { 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 7b37b16fa49b..44de26cbb02c 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 @@ -527,8 +527,7 @@ describe('grid resize element strategy', () => { ['backgroundColor', '#db48f6'], ['width', '100%'], ['height', '100%'], - ['gridColumnStart', 7], - ['gridColumnEnd', 11], + ['gridColumn', '7 / 11'], ['gridRow', 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 dc75ed69ef55..8fe12fcc8849 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 @@ -21,7 +21,7 @@ import { strategyApplicationResult, } from '../canvas-strategy-types' import type { InteractionSession } from '../interaction-state' -import { findOriginalGrid, setGridPropsCommands } from './grid-helpers' +import { findOriginalGrid, getCommandsForGridItemPlacement } from './grid-helpers' import { resizeBoundingBoxFromSide } from './resize-helpers' export const gridResizeElementStrategy: CanvasStrategyFactory = ( @@ -114,7 +114,7 @@ export const gridResizeElementStrategy: CanvasStrategyFactory = ( selectedElementMetadata.specialSizeMeasurements.parentContainerGridProperties return strategyApplicationResult( - setGridPropsCommands(selectedElement, gridTemplate, gridProps), + getCommandsForGridItemPlacement(selectedElement, gridTemplate, gridProps), [EP.parentPath(selectedElement)], ) }, diff --git a/editor/src/components/inspector/flex-section.tsx b/editor/src/components/inspector/flex-section.tsx index 6912329ed34b..5e3a768f4237 100644 --- a/editor/src/components/inspector/flex-section.tsx +++ b/editor/src/components/inspector/flex-section.tsx @@ -72,7 +72,7 @@ import { } from '../../core/shared/element-template' import { isJustAutoGridDimension, - setGridPropsCommands, + getCommandsForGridItemPlacement, } from '../canvas/canvas-strategies/strategies/grid-helpers' import { type CanvasCommand } from '../canvas/commands/commands' import type { DropdownMenuItem } from '../../uuiui/radix-components' @@ -357,7 +357,9 @@ const TemplateDimensionControl = React.memo( } } - commands.push(...setGridPropsCommands(child.elementPath, adjustedGridTemplate, updated)) + commands.push( + ...getCommandsForGridItemPlacement(child.elementPath, adjustedGridTemplate, updated), + ) } dispatch([applyCommandsAction(commands)]) @@ -434,7 +436,7 @@ const TemplateDimensionControl = React.memo( const children = MetadataUtils.getChildrenUnordered(metadataRef.current, grid.elementPath) for (const child of children) { commands.push( - ...setGridPropsCommands( + ...getCommandsForGridItemPlacement( child.elementPath, adjustedGridTemplate, child.specialSizeMeasurements.elementGridPropertiesFromProps, diff --git a/editor/src/components/inspector/sections/style-section/container-subsection/grid-cell-subsection.tsx b/editor/src/components/inspector/sections/style-section/container-subsection/grid-cell-subsection.tsx index f672852d4394..81c23e952892 100644 --- a/editor/src/components/inspector/sections/style-section/container-subsection/grid-cell-subsection.tsx +++ b/editor/src/components/inspector/sections/style-section/container-subsection/grid-cell-subsection.tsx @@ -27,7 +27,7 @@ import { } from '../../../../../uuiui' import type { KeywordForControl } from '../../../../../uuiui/inputs/number-or-keyword-control' import { NumberOrKeywordControl } from '../../../../../uuiui/inputs/number-or-keyword-control' -import { setGridPropsCommands } from '../../../../canvas/canvas-strategies/strategies/grid-helpers' +import { getCommandsForGridItemPlacement } from '../../../../canvas/canvas-strategies/strategies/grid-helpers' import { applyCommandsAction } from '../../../../editor/actions/action-creators' import { useDispatch } from '../../../../editor/store/dispatch-context' import { Substores, useEditorState } from '../../../../editor/store/store-hook' @@ -97,7 +97,7 @@ export const GridPlacementSubsection = React.memo(() => { return } - const commands = setGridPropsCommands( + const commands = getCommandsForGridItemPlacement( cell.elementPath, gridTemplate, cell.specialSizeMeasurements.elementGridProperties, @@ -271,7 +271,11 @@ const DimensionsControls = React.memo( } break } - const commands = setGridPropsCommands(cell.elementPath, gridTemplate, newValues) + const commands = getCommandsForGridItemPlacement( + cell.elementPath, + gridTemplate, + newValues, + ) dispatch([applyCommandsAction(commands)]) }, @@ -395,7 +399,11 @@ const BoundariesControls = React.memo( ...cell.specialSizeMeasurements.elementGridProperties, [dimension]: value, } - const commands = setGridPropsCommands(cell.elementPath, gridTemplate, newValues) + const commands = getCommandsForGridItemPlacement( + cell.elementPath, + gridTemplate, + newValues, + ) dispatch([applyCommandsAction(commands)]) },