Skip to content

Commit 91c4bab

Browse files
authored
fix(grids) Handle Non-Offset Parent Grids. (#6649)
- `runGridMoveAbsolute` now checks to see if the grid provides layouting, if it does not then the closest offset global frame is identified. - Slightly widened the type of `zeroRectIfNullOrInfinity`.
1 parent bcde12d commit 91c4bab

File tree

3 files changed

+193
-7
lines changed

3 files changed

+193
-7
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
import * as EP from '../../../../core/shared/element-path'
2+
import type { WindowPoint } from '../../../../core/shared/math-utils'
3+
import { offsetPoint, windowPoint } from '../../../../core/shared/math-utils'
4+
import type { Modifiers } from '../../../../utils/modifiers'
5+
import { cmdModifier, emptyModifiers } from '../../../../utils/modifiers'
6+
import { CanvasControlsContainerID } from '../../controls/new-canvas-controls'
7+
import type { Point } from '../../event-helpers.test-utils'
8+
import {
9+
mouseClickAtPoint,
10+
mouseDownAtPoint,
11+
mouseMoveToPoint,
12+
mouseUpAtPoint,
13+
} from '../../event-helpers.test-utils'
14+
import type { EditorRenderResult } from '../../ui-jsx.test-utils'
15+
import { getPrintedUiJsCode, renderTestEditorWithCode } from '../../ui-jsx.test-utils'
16+
17+
async function dragElement(
18+
renderResult: EditorRenderResult,
19+
targetTestId: string,
20+
targetControlTestId: string,
21+
dragDelta: WindowPoint,
22+
modifiers: Modifiers,
23+
): Promise<void> {
24+
const targetElement = renderResult.renderedDOM.getByTestId(targetTestId)
25+
const targetElementBounds = targetElement.getBoundingClientRect()
26+
const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID)
27+
28+
const startPoint = windowPoint({ x: targetElementBounds.x + 5, y: targetElementBounds.y + 5 })
29+
const endPoint = offsetPoint(startPoint, dragDelta)
30+
31+
await mouseClickAtPoint(canvasControlsLayer, startPoint, { modifiers: cmdModifier })
32+
33+
const targetControl = renderResult.renderedDOM.getByTestId(targetControlTestId)
34+
35+
await mouseDownAtPoint(targetControl, startPoint, { modifiers: modifiers })
36+
37+
const delta: Point = {
38+
x: endPoint.x - startPoint.x,
39+
y: endPoint.y - startPoint.y,
40+
}
41+
await mouseMoveToPoint(
42+
targetControl,
43+
{
44+
x: endPoint.x,
45+
y: endPoint.y,
46+
},
47+
{
48+
modifiers: modifiers,
49+
eventOptions: {
50+
movementX: delta.x,
51+
movementY: delta.y,
52+
buttons: 1,
53+
},
54+
},
55+
)
56+
57+
await mouseUpAtPoint(canvasControlsLayer, endPoint, {
58+
modifiers: modifiers,
59+
})
60+
}
61+
62+
describe('grid move absolute strategy', () => {
63+
it('move an absolute element in a non-absolute grid', async () => {
64+
const editor = await renderTestEditorWithCode(
65+
`import * as React from 'react'
66+
import { Storyboard } from 'utopia-api'
67+
68+
export var storyboard = (
69+
<Storyboard data-uid='sb' data-testid='sb'>
70+
<div
71+
style={{
72+
height: 'max-content',
73+
position: 'absolute',
74+
left: 776,
75+
top: 6,
76+
}}
77+
data-uid='container'
78+
data-testid='container'
79+
>
80+
<div
81+
style={{
82+
backgroundColor: '#aaaaaa33',
83+
left: 100,
84+
top: 100,
85+
width: 1000,
86+
height: 1000,
87+
display: 'grid',
88+
gridTemplateColumns: '200px 200px 200px',
89+
gridTemplateRows: '200px 200px 200px',
90+
gridGap: 10,
91+
padding: 10,
92+
}}
93+
data-uid='grid'
94+
data-testid='grid'
95+
>
96+
<div
97+
style={{
98+
gridColumn: 1,
99+
gridRow: 1,
100+
backgroundColor: '#f0f',
101+
position: 'absolute',
102+
left: 500,
103+
top: 500,
104+
width: 79,
105+
height: 86,
106+
}}
107+
data-uid='dragme'
108+
data-testid='dragme'
109+
/>
110+
</div>
111+
</div>
112+
</Storyboard>
113+
)`,
114+
'await-first-dom-report',
115+
)
116+
117+
await dragElement(
118+
editor,
119+
'dragme',
120+
'grid-cell-sb/container/grid/dragme',
121+
windowPoint({ x: -200, y: -200 }),
122+
emptyModifiers,
123+
)
124+
125+
expect(getPrintedUiJsCode(editor.getEditorState())).toEqual(
126+
`import * as React from 'react'
127+
import { Storyboard } from 'utopia-api'
128+
129+
export var storyboard = (
130+
<Storyboard data-uid='sb' data-testid='sb'>
131+
<div
132+
style={{
133+
height: 'max-content',
134+
position: 'absolute',
135+
left: 776,
136+
top: 6,
137+
}}
138+
data-uid='container'
139+
data-testid='container'
140+
>
141+
<div
142+
style={{
143+
backgroundColor: '#aaaaaa33',
144+
left: 100,
145+
top: 100,
146+
width: 1000,
147+
height: 1000,
148+
display: 'grid',
149+
gridTemplateColumns: '200px 200px 200px',
150+
gridTemplateRows: '200px 200px 200px',
151+
gridGap: 10,
152+
padding: 10,
153+
}}
154+
data-uid='grid'
155+
data-testid='grid'
156+
>
157+
<div
158+
style={{
159+
backgroundColor: '#f0f',
160+
position: 'absolute',
161+
width: 79,
162+
height: 86,
163+
gridColumn: 1,
164+
gridRow: 1,
165+
top: 300,
166+
left: 300,
167+
}}
168+
data-uid='dragme'
169+
data-testid='dragme'
170+
/>
171+
</div>
172+
</div>
173+
</Storyboard>
174+
)
175+
`,
176+
)
177+
178+
expect(1).toEqual(1)
179+
})
180+
})

editor/src/components/canvas/canvas-strategies/strategies/grid-move-absolute.ts

+12-6
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,17 @@ function runGridMoveAbsolute(
215215
]
216216
}
217217

218+
function getContainingRect(): CanvasRectangle {
219+
if (selectedElementMetadata.specialSizeMeasurements.immediateParentProvidesLayout) {
220+
const gridCellGlobalFrame = getGlobalFrameOfGridCell(gridCellGlobalFrames, targetRootCell)
221+
return zeroRectIfNullOrInfinity(gridCellGlobalFrame)
222+
} else {
223+
return zeroRectIfNullOrInfinity(
224+
selectedElementMetadata.specialSizeMeasurements.coordinateSystemBounds,
225+
)
226+
}
227+
}
228+
218229
// otherwise, return a change location + absolute adjustment
219230
return [
220231
...runGridChangeElementLocation(
@@ -225,12 +236,7 @@ function runGridMoveAbsolute(
225236
gridTemplate,
226237
null,
227238
),
228-
...gridChildAbsoluteMoveCommands(
229-
selectedElementMetadata,
230-
getGlobalFrameOfGridCell(gridCellGlobalFrames, targetRootCell) ??
231-
canvasRectangle(zeroRectangle),
232-
interactionData,
233-
),
239+
...gridChildAbsoluteMoveCommands(selectedElementMetadata, getContainingRect(), interactionData),
234240
]
235241
}
236242

editor/src/core/shared/math-utils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ export function windowRectangle(
183183
}
184184

185185
export function zeroRectIfNullOrInfinity<C extends CoordinateMarker>(
186-
r: MaybeInfinityRectangle<C> | null,
186+
r: MaybeInfinityRectangle<C> | null | undefined,
187187
): Rectangle<C> {
188188
return r == null || isInfinityRectangle(r) ? (zeroRectangle as Rectangle<C>) : r
189189
}

0 commit comments

Comments
 (0)