Skip to content

Commit

Permalink
Freeze grid template during child move (#6201)
Browse files Browse the repository at this point in the history
**Problem:**

Moving grid elements if the template is somewhat dynamic will result in
the grid elements likely jumping around because their template changes
constantly.

**Fix:**

Freeze the template during the interaction, by using the calculated
dimensions, and restore it once the interaction completes.

In the example below, one column is made `min-content` with some
fixed-sized elements inside.

| Before | After |
|-------|-------------|
| ![Kapture 2024-08-07 at 15 37
27](https://github.com/user-attachments/assets/da2d824a-ad02-494a-8ff6-7cc03e3b5c95)
| ![Kapture 2024-08-07 at 15 36
21](https://github.com/user-attachments/assets/283a5fc0-69b9-41e3-85d2-51be14279585)
|

Fixes #6200
  • Loading branch information
ruggi authored Aug 7, 2024
1 parent 0ea8d95 commit 846c1ff
Showing 1 changed file with 111 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +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 type {
ElementInstanceMetadataMap,
GridAutoOrTemplateBase,
} from '../../../../core/shared/element-template'
import * as PP from '../../../../core/shared/property-path'
import { printGridAutoOrTemplateBase } from '../../../inspector/common/css-utils'
import type { PropertyToUpdate } from '../../commands/set-property-command'
import {
propertyToDelete,
propertyToSet,
updateBulkProperties,
} from '../../commands/set-property-command'
import { GridControls } from '../../controls/grid-controls'
import type { CanvasStrategyFactory } from '../canvas-strategies'
import { onlyFitWhenDraggingThisControl } from '../canvas-strategies'
Expand Down Expand Up @@ -34,6 +47,13 @@ export const gridRearrangeMoveStrategy: CanvasStrategyFactory = (
return null
}

const gridPath = EP.parentPath(selectedElement)

const initialTemplates = getGridTemplates(canvasState.startingMetadata, gridPath)
if (initialTemplates == null) {
return null
}

return {
id: 'rearrange-grid-move-strategy',
name: 'Rearrange Grid (Move)',
Expand Down Expand Up @@ -83,14 +103,98 @@ export const gridRearrangeMoveStrategy: CanvasStrategyFactory = (
return emptyStrategyApplicationResult
}

return strategyApplicationResult(moveCommands, {
grid: {
targetCell: targetGridCell,
draggingFromCell: draggingFromCell,
originalRootCell: originalRootCell,
currentRootCell: targetRootCell,
const midInteractionCommands = [
// during the interaction, freeze the template with the calculated values…
updateBulkProperties('mid-interaction', gridPath, [
propertyToSet(
PP.create('style', 'gridTemplateColumns'),
printGridAutoOrTemplateBase(initialTemplates.calculated.columns),
),
propertyToSet(
PP.create('style', 'gridTemplateRows'),
printGridAutoOrTemplateBase(initialTemplates.calculated.rows),
),
]),
]

const onCompleteCommands = [
// …eventually, restore the grid template on complete.
updateBulkProperties(
'on-complete',
gridPath,
restoreGridTemplateFromProps(initialTemplates.fromProps),
),
]

return strategyApplicationResult(
[...moveCommands, ...midInteractionCommands, ...onCompleteCommands],
{
grid: {
targetCell: targetGridCell,
draggingFromCell: draggingFromCell,
originalRootCell: originalRootCell,
currentRootCell: targetRootCell,
},
},
})
)
},
}
}

function restoreGridTemplateFromProps(params: {
columns: GridAutoOrTemplateBase
rows: GridAutoOrTemplateBase
}): PropertyToUpdate[] {
let properties: PropertyToUpdate[] = []
const newCols = printGridAutoOrTemplateBase(params.columns)
const newRows = printGridAutoOrTemplateBase(params.rows)
if (newCols === '') {
properties.push(propertyToDelete(PP.create('style', 'gridTemplateColumns')))
} else {
properties.push(propertyToSet(PP.create('style', 'gridTemplateColumns'), newCols))
}
if (newRows === '') {
properties.push(propertyToDelete(PP.create('style', 'gridTemplateRows')))
} else {
properties.push(propertyToSet(PP.create('style', 'gridTemplateRows'), newRows))
}
return properties
}

function getGridTemplates(jsxMetadata: ElementInstanceMetadataMap, gridPath: ElementPath) {
const grid = MetadataUtils.findElementByElementPath(jsxMetadata, gridPath)
if (grid == null) {
return null
}

const templateFromProps = grid.specialSizeMeasurements.containerGridPropertiesFromProps
const templateRowsFromProps = templateFromProps.gridTemplateRows
if (templateRowsFromProps == null) {
return null
}
const templateColsFromProps = templateFromProps.gridTemplateColumns
if (templateColsFromProps == null) {
return null
}

const templateCalculated = grid.specialSizeMeasurements.containerGridProperties
const templateRowsCalculated = templateCalculated.gridTemplateRows
if (templateRowsCalculated == null) {
return null
}
const templateColsCalculated = templateCalculated.gridTemplateColumns
if (templateColsCalculated == null) {
return null
}

return {
calculated: {
columns: templateColsCalculated,
rows: templateRowsCalculated,
},
fromProps: {
columns: templateColsFromProps,
rows: templateRowsFromProps,
},
}
}

0 comments on commit 846c1ff

Please sign in to comment.