Skip to content

Commit

Permalink
Snap on convert to absolute (#4371)
Browse files Browse the repository at this point in the history
* always calculate snap lines for requested elements

* todos

* test

* better test

* Revert "todos"

This reverts commit 5e31450.

* better test name
  • Loading branch information
bkrmendy authored Oct 13, 2023
1 parent c40fc7f commit 3a8a3c1
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,90 @@ describe('Convert to Absolute', () => {
getCodeForTestProject(childTagAfter),
)
})
it('snaps to parent and sibling after being converted', async () => {
const renderResult = await renderTestEditorWithCode(
makeTestProjectCodeWithSnippet(`<div
style={{
backgroundColor: '#aaaaaa33',
position: 'absolute',
left: 20,
top: 26,
width: 150,
height: 150,
}}
data-uid='container'
>
<div
style={{
backgroundColor: '#0075ff',
width: 50,
height: 50,
contain: 'layout',
position: 'absolute',
left: 0,
top: 0,
}}
data-uid='child'
data-testid='child'
/>
<div
style={{
backgroundColor: '#0075ff',
width: 50,
height: 65,
contain: 'layout',
position: 'absolute',
left: 100,
top: 86,
}}
/>
</div>`),
'await-first-dom-report',
)

const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID)
const element = renderResult.renderedDOM.getByTestId('child')
const elementBounds = element.getBoundingClientRect()

await mouseDownAtPoint(
canvasControlsLayer,
{
x: elementBounds.x + elementBounds.width / 2,
y: elementBounds.y + elementBounds.width / 2,
},
{ modifiers: cmdModifier },
)

// move so that the bottom right corner snaps to the center of the parent
await mouseMoveToPoint(canvasControlsLayer, {
x: elementBounds.x + elementBounds.width / 2 + 25,
y: elementBounds.y + elementBounds.width / 2 + 25,
})

{
const activeStrategy = renderResult.getEditorState().strategyState.currentStrategy
expect(activeStrategy).not.toBeNull()
expect(activeStrategy).not.toEqual(ConvertToAbsoluteAndMoveStrategyID)
expect(renderResult.getEditorState().editor.canvas.controls.snappingGuidelines).toHaveLength(
2,
)
}

// move so that the bottom edge snaps to the top edge of the sibling
await mouseMoveToPoint(canvasControlsLayer, {
x: elementBounds.x + elementBounds.width / 2 + 5,
y: elementBounds.y + elementBounds.width / 2 + 35,
})

{
const activeStrategy = renderResult.getEditorState().strategyState.currentStrategy
expect(activeStrategy).not.toBeNull()
expect(activeStrategy).not.toEqual(ConvertToAbsoluteAndMoveStrategyID)
expect(renderResult.getEditorState().editor.canvas.controls.snappingGuidelines).toHaveLength(
1,
)
}
})
})

describe('Convert to absolute/escape hatch', () => {
Expand Down
4 changes: 2 additions & 2 deletions editor/src/components/canvas/canvas-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -904,7 +904,7 @@ export function collectGuidelines(
// For any images create guidelines at the current multiplier setting.
if (resizingFromPosition != null) {
Utils.fastForEach(selectedViews, (selectedView) => {
if (MetadataUtils.isPinnedAndNotAbsolutePositioned(metadata, selectedView)) {
if (MetadataUtils.isLayoutedByFlowAndNotAbsolutePositioned(metadata, selectedView)) {
return
}

Expand Down Expand Up @@ -1218,7 +1218,7 @@ export function snapPoint(
guidelinesWithSnappingVector: Array<GuidelineWithSnappingVectorAndPointsOfRelevance>
} {
const anythingPinnedAndNotAbsolutePositioned = selectedViews.some((elementToTarget) => {
return MetadataUtils.isPinnedAndNotAbsolutePositioned(jsxMetadata, elementToTarget)
return MetadataUtils.isLayoutedByFlowAndNotAbsolutePositioned(jsxMetadata, elementToTarget)
})

const anyElementFragmentLike = selectedViews.some((elementPath) =>
Expand Down
28 changes: 5 additions & 23 deletions editor/src/components/canvas/controls/guideline-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,29 +67,11 @@ export function gatherParentAndSiblingTargets(
pathTrees: ElementPathTrees,
targets: Array<ElementPath>,
) {
return targets.flatMap((target) => {
const pinnedAndNotAbsolutePositioned = MetadataUtils.isPinnedAndNotAbsolutePositioned(
componentMetadata,
target,
)

const isElementFragmentLike = treatElementAsFragmentLike(
componentMetadata,
allElementProps,
pathTrees,
target,
)

if (isElementFragmentLike || !pinnedAndNotAbsolutePositioned) {
return getSnapTargetsForElementPath(
componentMetadata,
allElementProps,
pathTrees,
target,
).filter((snapTarget) => targets.every((t) => !EP.pathsEqual(snapTarget, t)))
}
return []
})
return targets.flatMap((target) =>
getSnapTargetsForElementPath(componentMetadata, allElementProps, pathTrees, target).filter(
(snapTarget) => targets.every((t) => !EP.pathsEqual(snapTarget, t)),
),
)
}

export function collectParentAndSiblingGuidelines(
Expand Down
8 changes: 4 additions & 4 deletions editor/src/core/model/element-metadata-utils.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,7 @@ describe('isPinnedAndNotAbsolutePositioned', () => {
},
}
expect(
MetadataUtils.isPinnedAndNotAbsolutePositioned(
MetadataUtils.isLayoutedByFlowAndNotAbsolutePositioned(
elementMapForTest,
EP.elementPath([[BakedInStoryboardUID, TestScenePath], ['View']]),
),
Expand All @@ -819,7 +819,7 @@ describe('isPinnedAndNotAbsolutePositioned', () => {
},
}
expect(
MetadataUtils.isPinnedAndNotAbsolutePositioned(
MetadataUtils.isLayoutedByFlowAndNotAbsolutePositioned(
elementMapForTest,
EP.elementPath([[BakedInStoryboardUID, TestScenePath], ['View']]),
),
Expand All @@ -837,7 +837,7 @@ describe('isPinnedAndNotAbsolutePositioned', () => {
},
}
expect(
MetadataUtils.isPinnedAndNotAbsolutePositioned(
MetadataUtils.isLayoutedByFlowAndNotAbsolutePositioned(
elementMapForTest,
EP.elementPath([[BakedInStoryboardUID, TestScenePath], ['View']]),
),
Expand All @@ -855,7 +855,7 @@ describe('isPinnedAndNotAbsolutePositioned', () => {
},
}
expect(
MetadataUtils.isPinnedAndNotAbsolutePositioned(
MetadataUtils.isLayoutedByFlowAndNotAbsolutePositioned(
elementMapForTest,
EP.elementPath([[BakedInStoryboardUID, TestScenePath], ['View']]),
),
Expand Down
3 changes: 1 addition & 2 deletions editor/src/core/model/element-metadata-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1830,11 +1830,10 @@ export const MetadataUtils = {
const elementName = MetadataUtils.getStaticElementName(path, rootElements)
return elementName != null && !isIntrinsicHTMLElement(elementName)
},
isPinnedAndNotAbsolutePositioned(
isLayoutedByFlowAndNotAbsolutePositioned(
metadata: ElementInstanceMetadataMap,
view: ElementPath,
): boolean {
// Disable snapping and guidelines for pinned elements marked with relative positioning:
const elementMetadata = MetadataUtils.findElementByElementPath(metadata, view)
return (
elementMetadata != null &&
Expand Down

0 comments on commit 3a8a3c1

Please sign in to comment.