>(
+ ({ axis, gridRect, rulerVisible, cellFrames, children }) => {
+ const colorTheme = useColorTheme()
+ const scale = useEditorState(
+ Substores.canvas,
+ (store) => store.editor.canvas.scale,
+ 'GridRuler scale',
+ )
+
+ // Make sure the ruler extends to cover all the cells and not just the grid dimensions.
+ const cellMaxRect = React.useMemo(() => {
+ return boundingRectangleArray([gridRect, ...(cellFrames?.flat() ?? [])]) ?? gridRect
+ }, [cellFrames, gridRect])
+
+ const columnLeft = gridRect.x
+ const rowLeft = gridRect.x - RulerMarkerIconSize / scale
+ const left = axis === 'row' ? rowLeft : columnLeft
+
+ const columnTop = gridRect.y - RulerMarkerIconSize / scale
+ const rowTop = gridRect.y
+ const top = axis === 'row' ? rowTop : columnTop
+
+ const width = axis === 'row' ? RulerMarkerIconSize / scale : cellMaxRect.width
+ const height = axis === 'row' ? cellMaxRect.height : RulerMarkerIconSize / scale
+
+ return (
+
+ {children}
+
+ )
+ },
+)
+GridRuler.displayName = 'GridRuler'
+
const RulerMarkerIndicator = React.memo(
(props: {
+ gridRect: CanvasRectangle
parentGrid: GridContainerProperties
marker: RulerMarkerPositionData
axis: 'row' | 'column'
+ testID: string
+ visible: 'visible' | 'not-visible'
+ onMouseDown?: (event: React.MouseEvent) => void
}) => {
const colorTheme = useColorTheme()
- const markerType = getRulerMarkerType({
- position: props.marker.position,
- bound: props.marker.bound,
- })
- const markerIcon = rulerMarkerIcons[markerType][props.axis]
-
const canvasScale = useEditorState(
Substores.canvasOffset,
(store) => store.editor.canvas.scale,
'RulerMarkerIndicator canvasScale',
)
- const scaledTop = props.marker.top * canvasScale
- const top =
- scaledTop -
- skewMarkerPosition(props.axis === 'column', props.axis, props.marker.bound, markerType)
+ const markerType = getRulerMarkerType(props.marker)
+ const markerColor = getRulerMarkerColor(colorTheme, props.marker)
+ const markerIcon = rulerMarkerIcons[markerType][props.axis](markerColor, canvasScale)
+
+ const scaledTop =
+ props.axis === 'row'
+ ? props.marker.top - props.gridRect.y - RulerMarkerIconSize / canvasScale / 2 + 0.5
+ : 0
- const scaledLeft = props.marker.left * canvasScale
- const left =
- scaledLeft -
- skewMarkerPosition(props.axis === 'row', props.axis, props.marker.bound, markerType)
+ const scaledLeft =
+ props.axis === 'column'
+ ? props.marker.left - props.gridRect.x - RulerMarkerIconSize / canvasScale / 2 + 0.5
+ : 0
const labelText = React.useMemo(() => {
if (props.marker.position == null) {
@@ -2388,16 +2649,17 @@ const RulerMarkerIndicator = React.memo(
return (
.${labelClass}`]: {
visibility: 'hidden',
@@ -2417,16 +2679,17 @@ const RulerMarkerIndicator = React.memo(
style={{
position: 'absolute',
background: colorTheme.primary.value,
- borderRadius: 2,
- padding: '3px 6px',
+ borderRadius: 2 / canvasScale,
+ padding: `${3 / canvasScale}px ${6 / canvasScale}px`,
color: colorTheme.white.value,
- height: 20,
+ height: 20 / canvasScale,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
- top: props.axis === 'column' ? -23 : 0,
+ top: props.axis === 'column' ? -23 / canvasScale : 0,
left: props.axis === 'column' ? 0 : undefined,
- right: props.axis === 'row' ? rulerMarkerIconSize + 1 : undefined,
+ right: props.axis === 'row' ? (RulerMarkerIconSize + 1) / canvasScale : undefined,
+ fontSize: 11 / canvasScale,
}}
>
{labelText}
@@ -2438,15 +2701,14 @@ const RulerMarkerIndicator = React.memo(
)
RulerMarkerIndicator.displayName = 'RulerMarkerIndicator'
-function getRulerMarkerType(props: {
- position: GridPositionOrSpan | null
- bound: 'start' | 'end'
-}): RulerMarkerType {
- const isAuto = isAutoGridPin(props.position)
- const isSpanStart = props.bound === 'start' && isGridSpan(props.position)
- const isSpanEnd = props.bound === 'end' && isGridSpan(props.position)
+function getRulerMarkerType(marker: RulerMarkerPositionData): RulerMarkerType {
+ const isAuto = isAutoGridPin(marker.position)
+ const isSpanStart = marker.bound === 'start' && isGridSpan(marker.position)
+ const isSpanEnd = marker.bound === 'end' && isGridSpan(marker.position)
- if (isSpanStart) {
+ if (marker.markerType === 'other' || marker.markerType === 'target') {
+ return 'auto-short'
+ } else if (isSpanStart) {
return 'span-start'
} else if (isSpanEnd) {
return 'span-end'
@@ -2457,6 +2719,19 @@ function getRulerMarkerType(props: {
}
}
+function getRulerMarkerColor(colorTheme: ThemeObject, marker: RulerMarkerPositionData): UtopiColor {
+ switch (marker.markerType) {
+ case 'selected':
+ return colorTheme.primary
+ case 'target':
+ return colorTheme.brandPurple
+ case 'other':
+ return colorTheme.grey65
+ default:
+ assertNever(marker.markerType)
+ }
+}
+
function getCellCanvasWidthFromBounds(
grid: CanvasRectangle[][],
index: number,
@@ -2527,74 +2802,6 @@ export const GridHelperControls = () => {
}
GridHelperControls.displayName = 'GridHelperControls'
-// This function returns the amount of pixels used to adjust the position of
-// individual ruler markers, which need specific skews based on their shape.
-function skewMarkerPosition(
- isOnTheSameAxis: boolean,
- axis: 'column' | 'row',
- bound: 'start' | 'end',
- markerType: RulerMarkerType,
-): number {
- if (isOnTheSameAxis) {
- return rulerMarkerIconSize
- }
-
- // span-end triangle, on the column
- const spanEndColumn = axis === 'column' && markerType === 'span-end'
- if (spanEndColumn) {
- return 9
- }
- // pinned triangle, on the column
- const pinnedEndColumn = axis === 'column' && markerType === 'pinned' && bound === 'end'
- if (pinnedEndColumn) {
- return 5
- }
- // any other ending marker, on the column
- const endColumn = bound === 'end' && axis === 'column'
- if (endColumn) {
- return 1
- }
-
- // span-end triangle, on the row
- const spanEndRow = axis === 'row' && markerType === 'span-end'
- if (spanEndRow) {
- return 9
- }
- // any other ending marker, on the row
- const endRow = bound === 'end' && axis === 'row'
- if (endRow) {
- return 4
- }
-
- // span-start triangle, on the column
- const spanStartColumn = axis === 'column' && markerType === 'span-start'
- if (spanStartColumn) {
- return 0
- }
- const pinnedStartColumn = axis === 'column' && markerType === 'pinned' && bound === 'start'
- if (pinnedStartColumn) {
- return 5
- }
- // any starting marker, on the column
- const startColumn = bound === 'start' && axis === 'column'
- if (startColumn) {
- return 1
- }
-
- // span-start starting triangle, on the row
- const spanStartRow = axis === 'row' && markerType === 'span-start'
- if (spanStartRow) {
- return 0
- }
- // any other starting marker, on the row
- const startRow = bound === 'start' && axis === 'row'
- if (startRow) {
- return 4
- }
-
- return 0
-}
-
const GridCellOffsetLine = React.memo(
(props: { top: number; left: number; size: number; orientation: 'vertical' | 'horizontal' }) => {
const colorTheme = useColorTheme()