Skip to content

Commit d1c1e6e

Browse files
authored
fix(grids) Handle Spans In Pin Outlines (#6644)
- Extracted out the `printPin` function. - Implemented `nullHandlingPrintPin` as a thin wrapper around `printPin`. - `GridElementContainingBlock` now uses `nullHandlingPrintPin` instead of `gridPositionToValue` to build the grid column/row start/end values.
1 parent 91c4bab commit d1c1e6e

File tree

3 files changed

+179
-39
lines changed

3 files changed

+179
-39
lines changed

editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts

+25-21
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,29 @@ export function isAutoGridPin(v: GridPositionOrSpan): boolean {
7777
return isCSSKeyword(v) && v.value === 'auto'
7878
}
7979

80+
export function printPin(
81+
gridTemplate: GridContainerProperties,
82+
pin: GridPositionOrSpan,
83+
axis: 'row' | 'column',
84+
): string | number {
85+
if (isGridSpan(pin)) {
86+
return stringifyGridSpan(pin)
87+
}
88+
if (isCSSKeyword(pin)) {
89+
return pin.value
90+
}
91+
const tracks =
92+
axis === 'column' ? gridTemplate.gridTemplateColumns : gridTemplate.gridTemplateRows
93+
const maybeLineName =
94+
tracks?.type === 'DIMENSIONS'
95+
? tracks.dimensions.find((_, index) => index + 1 === pin.numericalPosition)?.lineName
96+
: null
97+
if (maybeLineName != null) {
98+
return maybeLineName
99+
}
100+
return pin.numericalPosition ?? 'auto'
101+
}
102+
80103
export function getCommandsForGridItemPlacement(
81104
elementPath: ElementPath,
82105
gridTemplate: GridContainerProperties,
@@ -94,25 +117,6 @@ export function getCommandsForGridItemPlacement(
94117
]),
95118
]
96119

97-
function printPin(pin: GridPositionOrSpan, axis: 'row' | 'column'): string | number {
98-
if (isGridSpan(pin)) {
99-
return stringifyGridSpan(pin)
100-
}
101-
if (isCSSKeyword(pin)) {
102-
return pin.value
103-
}
104-
const tracks =
105-
axis === 'column' ? gridTemplate.gridTemplateColumns : gridTemplate.gridTemplateRows
106-
const maybeLineName =
107-
tracks?.type === 'DIMENSIONS'
108-
? tracks.dimensions.find((_, index) => index + 1 === pin.numericalPosition)?.lineName
109-
: null
110-
if (maybeLineName != null) {
111-
return maybeLineName
112-
}
113-
return pin.numericalPosition ?? 'auto'
114-
}
115-
116120
function serializeAxis(
117121
startPosition: GridPositionOrSpan,
118122
endPosition: GridPositionOrSpan,
@@ -127,8 +131,8 @@ export function getCommandsForGridItemPlacement(
127131
| 'gridRowEnd'
128132
value: string | number
129133
} {
130-
const startValue = printPin(startPosition, axis)
131-
const endValue = printPin(endPosition, axis)
134+
const startValue = printPin(gridTemplate, startPosition, axis)
135+
const endValue = printPin(gridTemplate, endPosition, axis)
132136

133137
if (isAutoGridPin(startPosition) && !isAutoGridPin(endPosition)) {
134138
return {

editor/src/components/canvas/controls/grid-controls.spec.browser2.tsx

+121
Original file line numberDiff line numberDiff line change
@@ -615,4 +615,125 @@ describe('Grid Pin Outlines', () => {
615615
bottom: { x: 1781.5, y: 555.5, width: 1, height: 5 },
616616
})
617617
})
618+
619+
it('pinned top and left, grid rows and columns fully specified and not absolutely positioned, with a row start span', async () => {
620+
const result = await testGridOutlines('storyboard/scene/grid/grid-child', {
621+
top: 5,
622+
left: 12,
623+
gridRowStart: 'span 2',
624+
gridColumnStart: 3,
625+
gridRowEnd: 2,
626+
gridColumnEnd: 3,
627+
width: 50,
628+
height: 50,
629+
})
630+
expect(result).toEqual({})
631+
})
632+
it('pinned top and left, grid rows and columns fully specified and absolutely positioned, with a row start span', async () => {
633+
const result = await testGridOutlines('storyboard/scene/grid/grid-child', {
634+
position: 'absolute',
635+
top: 5,
636+
left: 12,
637+
gridRowStart: 'span 2',
638+
gridColumnStart: 3,
639+
gridRowEnd: 2,
640+
gridColumnEnd: 3,
641+
width: 50,
642+
height: 50,
643+
})
644+
expect(result).toEqual({
645+
left: { x: 688.5, y: 190.5, width: 12, height: 1 },
646+
top: { x: 725.5, y: 160.5, width: 1, height: 5 },
647+
})
648+
})
649+
it('pinned bottom and right, grid rows and columns fully specified and not absolutely positioned, with a row start span', async () => {
650+
const result = await testGridOutlines('storyboard/scene/grid/grid-child', {
651+
bottom: 5,
652+
right: 12,
653+
gridRowStart: 'span 2',
654+
gridColumnStart: 3,
655+
gridRowEnd: 2,
656+
gridColumnEnd: 3,
657+
width: 50,
658+
height: 50,
659+
})
660+
expect(result).toEqual({})
661+
})
662+
it('pinned bottom and right, grid rows and columns fully specified and absolutely positioned, with a row start span', async () => {
663+
const result = await testGridOutlines('storyboard/scene/grid/grid-child', {
664+
position: 'absolute',
665+
bottom: 5,
666+
right: 12,
667+
gridRowStart: 'span 2',
668+
gridColumnStart: 3,
669+
gridRowEnd: 2,
670+
gridColumnEnd: 3,
671+
width: 50,
672+
height: 50,
673+
})
674+
expect(result).toEqual({
675+
right: { x: 777.5, y: 240.5, width: 12, height: 1 },
676+
bottom: { x: 751.5, y: 266.5, width: 1, height: 5 },
677+
})
678+
})
679+
it('pinned top and left, grid rows and columns fully specified and not absolutely positioned, with a row end span', async () => {
680+
const result = await testGridOutlines('storyboard/scene/grid/grid-child', {
681+
top: 5,
682+
left: 12,
683+
gridRowStart: 2,
684+
gridColumnStart: 3,
685+
gridRowEnd: 'span 2',
686+
gridColumnEnd: 3,
687+
width: 50,
688+
height: 50,
689+
})
690+
expect(result).toEqual({})
691+
})
692+
it('pinned top and left, grid rows and columns fully specified and absolutely positioned, with a row end span', async () => {
693+
const result = await testGridOutlines('storyboard/scene/grid/grid-child', {
694+
position: 'absolute',
695+
top: 5,
696+
left: 12,
697+
gridRowStart: 2,
698+
gridColumnStart: 3,
699+
gridRowEnd: 'span 2',
700+
gridColumnEnd: 3,
701+
width: 50,
702+
height: 50,
703+
})
704+
expect(result).toEqual({
705+
left: { x: 688.5, y: 315.5, width: 12, height: 1 },
706+
top: { x: 725.5, y: 285.5, width: 1, height: 5 },
707+
})
708+
})
709+
it('pinned bottom and right, grid rows and columns fully specified and not absolutely positioned, with a row end span', async () => {
710+
const result = await testGridOutlines('storyboard/scene/grid/grid-child', {
711+
bottom: 5,
712+
right: 12,
713+
gridRowStart: 2,
714+
gridColumnStart: 3,
715+
gridRowEnd: 'span 2',
716+
gridColumnEnd: 3,
717+
width: 50,
718+
height: 50,
719+
})
720+
expect(result).toEqual({})
721+
})
722+
it('pinned bottom and right, grid rows and columns fully specified and absolutely positioned, with a row end span', async () => {
723+
const result = await testGridOutlines('storyboard/scene/grid/grid-child', {
724+
position: 'absolute',
725+
bottom: 5,
726+
right: 12,
727+
gridRowStart: 2,
728+
gridColumnStart: 3,
729+
gridRowEnd: 'span 2',
730+
gridColumnEnd: 3,
731+
width: 50,
732+
height: 50,
733+
})
734+
expect(result).toEqual({
735+
right: { x: 777.5, y: 470.5, width: 12, height: 1 },
736+
bottom: { x: 751.5, y: 496.5, width: 1, height: 5 },
737+
})
738+
})
618739
})

editor/src/components/canvas/controls/grid-controls.tsx

+33-18
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import * as EP from '../../../core/shared/element-path'
1717
import type {
1818
ElementInstanceMetadataMap,
1919
GridAutoOrTemplateDimensions,
20+
GridContainerProperties,
2021
GridPositionOrSpan,
2122
} from '../../../core/shared/element-template'
2223
import {
@@ -73,6 +74,7 @@ import {
7374
getGridRelatedIndexes,
7475
getGridElementPinState,
7576
gridPositionToValue,
77+
printPin,
7678
getGridIdentifierContainerOrComponentPath,
7779
gridIdentifierToString,
7880
gridIdentifiersSimilar,
@@ -1944,6 +1946,17 @@ export interface GridElementContainingBlockProps {
19441946
gridChild: ElementPath
19451947
}
19461948

1949+
function nullHandlingPrintPin(
1950+
gridTemplate: GridContainerProperties | null | undefined,
1951+
pin: GridPositionOrSpan | null | undefined,
1952+
axis: 'row' | 'column',
1953+
): string | number | undefined {
1954+
if (gridTemplate == null || pin == null) {
1955+
return undefined
1956+
}
1957+
return printPin(gridTemplate, pin, axis)
1958+
}
1959+
19471960
const GridElementContainingBlock = React.memo<GridElementContainingBlockProps>((props) => {
19481961
const gridData = useGridMeasurementHelperData(props.gridPath, 'element')
19491962
const scale = useEditorState(
@@ -1975,24 +1988,26 @@ const GridElementContainingBlock = React.memo<GridElementContainingBlockProps>((
19751988
const gridFromProps = childMetadata.specialSizeMeasurements.elementGridPropertiesFromProps
19761989
const gridComputed = childMetadata.specialSizeMeasurements.elementGridProperties
19771990
return {
1978-
gridColumnStart:
1979-
gridPositionToValue(
1980-
gridFromProps.gridColumnStart ?? gridComputed.gridColumnStart,
1981-
null,
1982-
) ?? undefined,
1983-
gridColumnEnd:
1984-
gridPositionToValue(
1985-
gridFromProps.gridColumnEnd ?? gridComputed.gridColumnEnd,
1986-
gridFromProps.gridColumnStart ?? gridComputed.gridColumnStart,
1987-
) ?? undefined,
1988-
gridRowStart:
1989-
gridPositionToValue(gridFromProps.gridRowStart ?? gridComputed.gridRowStart, null) ??
1990-
undefined,
1991-
gridRowEnd:
1992-
gridPositionToValue(
1993-
gridFromProps.gridRowEnd ?? gridComputed.gridRowEnd,
1994-
gridFromProps.gridRowStart ?? gridComputed.gridRowStart,
1995-
) ?? undefined,
1991+
gridColumnStart: nullHandlingPrintPin(
1992+
childMetadata.specialSizeMeasurements.containerGridProperties,
1993+
gridFromProps.gridColumnStart ?? gridComputed.gridColumnStart,
1994+
'column',
1995+
),
1996+
gridColumnEnd: nullHandlingPrintPin(
1997+
childMetadata.specialSizeMeasurements.containerGridProperties,
1998+
gridFromProps.gridColumnEnd ?? gridComputed.gridColumnEnd,
1999+
'column',
2000+
),
2001+
gridRowStart: nullHandlingPrintPin(
2002+
childMetadata.specialSizeMeasurements.containerGridProperties,
2003+
gridFromProps.gridRowStart ?? gridComputed.gridRowStart,
2004+
'row',
2005+
),
2006+
gridRowEnd: nullHandlingPrintPin(
2007+
childMetadata.specialSizeMeasurements.containerGridProperties,
2008+
gridFromProps.gridRowEnd ?? gridComputed.gridRowEnd,
2009+
'row',
2010+
),
19962011
position: childMetadata.specialSizeMeasurements.position ?? undefined,
19972012
}
19982013
},

0 commit comments

Comments
 (0)