From d6da1ce5bfd5af0e4b0bcf7b115ffe24f3bc4ef4 Mon Sep 17 00:00:00 2001
From: Federico Ruggi <1081051+ruggi@users.noreply.github.com>
Date: Fri, 29 Sep 2023 09:30:50 +0200
Subject: [PATCH] Group size label (#4257)
* use "group" for group size label
* type
---
...ze-bounding-box-strategy.spec.browser2.tsx | 26 ++++++++
.../select-mode/absolute-resize-control.tsx | 60 ++++++++++++++++---
2 files changed, 78 insertions(+), 8 deletions(-)
diff --git a/editor/src/components/canvas/canvas-strategies/strategies/absolute-resize-bounding-box-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/absolute-resize-bounding-box-strategy.spec.browser2.tsx
index c046cd7e65b3..6b3bec6bfe8f 100644
--- a/editor/src/components/canvas/canvas-strategies/strategies/absolute-resize-bounding-box-strategy.spec.browser2.tsx
+++ b/editor/src/components/canvas/canvas-strategies/strategies/absolute-resize-bounding-box-strategy.spec.browser2.tsx
@@ -1497,6 +1497,32 @@ export var storyboard = (
})
})
describe('groups', () => {
+ it('has a "Group" size label', async () => {
+ const renderResult = await renderTestEditorWithCode(
+ formatTestProjectCode(`
+ import * as React from 'react'
+ import { Storyboard, Group } from 'utopia-api'
+
+ export var storyboard = (
+
+
+
+
+
+
+ )
+ `),
+ 'await-first-dom-report',
+ )
+
+ await renderResult.dispatch(
+ [selectComponents([EP.fromString('storyboard/group')], false)],
+ true,
+ )
+
+ const label = await renderResult.renderedDOM.findByTestId(SizeLabelTestId)
+ expect(label.textContent).toEqual('Group')
+ })
it('resizes groups correctly when dragging from top/left without existing left/top props (left)', async () => {
const renderResult = await renderTestEditorWithCode(
formatTestProjectCode(`
diff --git a/editor/src/components/canvas/controls/select-mode/absolute-resize-control.tsx b/editor/src/components/canvas/controls/select-mode/absolute-resize-control.tsx
index 6f2cc0cdfde3..10c7e4b2929e 100644
--- a/editor/src/components/canvas/controls/select-mode/absolute-resize-control.tsx
+++ b/editor/src/components/canvas/controls/select-mode/absolute-resize-control.tsx
@@ -38,6 +38,7 @@ import { CanvasOffsetWrapper } from '../canvas-offset-wrapper'
import { isZeroSizedElement } from '../outline-utils'
import { useMaybeHighlightElement } from './select-mode-hooks'
import { isEdgePositionEqualTo } from '../../canvas-utils'
+import { treatElementAsGroupLike } from '../../canvas-strategies/strategies/group-helpers'
export const AbsoluteResizeControlTestId = (targets: Array): string =>
`${targets.map(EP.toString).sort()}-absolute-resize-control`
@@ -399,15 +400,45 @@ const sizeLabel = (state: FixedHugFill['type'], actualSize: number): string => {
}
}
+export type SizeLabelSize = {
+ type: 'SIZE_LABEL_WITH_DIMENSIONS'
+ h: string
+ v: string
+}
+
+function sizeLabelWithDimensions(h: string, v: string): SizeLabelSize {
+ return {
+ type: 'SIZE_LABEL_WITH_DIMENSIONS',
+ h: h,
+ v: v,
+ }
+}
+
+export type SizeLabelGroup = {
+ type: 'SIZE_LABEL_GROUP'
+}
+
+function sizeLabelGroup(): SizeLabelGroup {
+ return {
+ type: 'SIZE_LABEL_GROUP',
+ }
+}
+
+export type SizeLabelContents = SizeLabelSize | SizeLabelGroup
+
function sizeLabelContents(
metadata: ElementInstanceMetadataMap,
selectedElements: Array,
-): { h: string; v: string } | null {
+): SizeLabelContents | null {
if (selectedElements.length === 0) {
return null
}
if (selectedElements.length === 1) {
+ if (treatElementAsGroupLike(metadata, selectedElements[0])) {
+ return sizeLabelGroup()
+ }
+
const globalFrame = MetadataUtils.findElementByElementPath(
metadata,
selectedElements[0],
@@ -422,17 +453,17 @@ function sizeLabelContents(
const vertical =
detectFillHugFixedState('vertical', metadata, selectedElements[0]).fixedHugFill?.type ??
'fixed'
- return {
- h: sizeLabel(horizontal, globalFrame.width),
- v: sizeLabel(vertical, globalFrame.height),
- }
+ return sizeLabelWithDimensions(
+ sizeLabel(horizontal, globalFrame.width),
+ sizeLabel(vertical, globalFrame.height),
+ )
}
const boundingBox = boundingRectangleArray(
selectedElements.map((t) => nullIfInfinity(MetadataUtils.getFrameInCanvasCoords(t, metadata))),
)
if (boundingBox != null) {
- return { h: `${boundingBox.width}`, v: `${boundingBox.height}` }
+ return sizeLabelWithDimensions(`${boundingBox.width}`, `${boundingBox.height}`)
}
return null
@@ -449,6 +480,20 @@ const ExplicitHeightHacked = 20
const BorderRadius = 2
const SizeLabelMarginTop = 8
+function getLabelText(label: SizeLabelContents | null): string | null {
+ if (label == null) {
+ return null
+ }
+ switch (label.type) {
+ case 'SIZE_LABEL_GROUP':
+ return 'Group'
+ case 'SIZE_LABEL_WITH_DIMENSIONS':
+ return `${label.h} x ${label.v}`
+ default:
+ assertNever(label)
+ }
+}
+
const SizeLabel = React.memo(
React.forwardRef(({ targets }, ref) => {
const scale = useEditorState(
@@ -464,8 +509,7 @@ const SizeLabel = React.memo(
)
const label = sizeLabelContents(metadata, targets)
-
- const labelText = label == null ? null : `${label.h} x ${label.v}`
+ const labelText = getLabelText(label)
return (