From d1f7ae8369a13fbf9cc0967f14fa22ef0d887118 Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Thu, 10 Oct 2024 17:49:46 +0200 Subject: [PATCH 01/24] Show invisible grid controls on all grids during interactions --- .../strategies/grid-helpers.ts | 9 +++ .../canvas/controls/grid-controls.tsx | 67 +++++++++++-------- .../canvas/controls/new-canvas-controls.tsx | 12 ++++ 3 files changed, 59 insertions(+), 29 deletions(-) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts index bf51b4149b2c..17b08a8ec464 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts @@ -45,6 +45,7 @@ import { import { mapDropNulls } from '../../../../core/shared/array-utils' import { assertNever } from '../../../../core/shared/utils' import { showGridControls } from '../../commands/show-grid-controls-command' +import { memoize } from '../../../../core/shared/memoize' export function runGridRearrangeMove( targetElement: ElementPath, @@ -813,3 +814,11 @@ function getOriginalElementGridConfiguration( mouseCellPosInOriginalElement, } } + +export const getAllGrids = memoize(getAllGridsInner, { maxSize: 1 }) + +function getAllGridsInner(jsxMetadata: ElementInstanceMetadataMap): Array { + return Object.keys(jsxMetadata) + .filter((key) => MetadataUtils.isGridLayoutedContainer(jsxMetadata[key])) + .map(EP.fromString) +} diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index 0ab0b0c43535..2e1282bee7c0 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -40,7 +40,6 @@ import { pointsEqual, scaleRect, windowPoint, - zeroRectangle, zeroRectIfNullOrInfinity, } from '../../../core/shared/math-utils' import { @@ -89,7 +88,6 @@ import { windowToCanvasCoordinates } from '../dom-lookup' import type { Axis } from '../gap-utils' import { useCanvasAnimation } from '../ui-jsx-canvas-renderer/animation-context' import { CanvasOffsetWrapper } from './canvas-offset-wrapper' -import { CanvasLabel } from './select-mode/controls-common' import { useMaybeHighlightElement } from './select-mode/select-mode-hooks' import type { GridCellCoordinates } from '../canvas-strategies/strategies/grid-cell-bounds' import { gridCellTargetId } from '../canvas-strategies/strategies/grid-cell-bounds' @@ -662,9 +660,10 @@ export const GridControlsKey = (gridPath: ElementPath) => `grid-controls-${EP.to export interface GridControlProps { grid: GridData + visible: 'visible' | 'hidden' } -export const GridControl = React.memo(({ grid }) => { +export const GridControl = React.memo(({ grid, visible }) => { const dispatch = useDispatch() const controls = useAnimationControls() const colorTheme = useColorTheme() @@ -916,6 +915,7 @@ export const GridControl = React.memo(({ grid }) => { grid.padding == null ? 0 : `${grid.padding.top}px ${grid.padding.right}px ${grid.padding.bottom}px ${grid.padding.left}px`, + opacity: visible === 'visible' ? 1 : 0, } // Gap needs to be set only if the other two are not present or we'll have rendering issues @@ -1126,38 +1126,47 @@ GridControl.displayName = 'GridControl' export interface GridControlsProps { targets: ElementPath[] + visible: 'visible' | 'hidden' } -export const GridControls = controlForStrategyMemoized(({ targets }) => { - const targetRootCell = useEditorState( - Substores.canvas, - (store) => store.editor.canvas.controls.gridControlData?.rootCell ?? null, - 'GridControls targetRootCell', - ) +export const GridControls = controlForStrategyMemoized( + ({ targets, visible }) => { + const targetRootCell = useEditorState( + Substores.canvas, + (store) => store.editor.canvas.controls.gridControlData?.rootCell ?? null, + 'GridControls targetRootCell', + ) - const hoveredGrids = useEditorState( - Substores.canvas, - (store) => stripNulls([store.editor.canvas.controls.gridControlData?.grid]), - 'GridControls hoveredGrids', - ) + const hoveredGrids = useEditorState( + Substores.canvas, + (store) => stripNulls([store.editor.canvas.controls.gridControlData?.grid]), + 'GridControls hoveredGrids', + ) - const grids = useGridData(uniqBy([...targets, ...hoveredGrids], (a, b) => EP.pathsEqual(a, b))) + const grids = useGridData(uniqBy([...targets, ...hoveredGrids], (a, b) => EP.pathsEqual(a, b))) - if (grids.length === 0) { - return null - } + if (grids.length === 0) { + return null + } - return ( -
- - {grids.map((grid) => { - return - })} - - -
- ) -}) + return ( +
+ + {grids.map((grid) => { + return ( + + ) + })} + + +
+ ) + }, +) const MIN_INDICATORS_DISTANCE = 32 // px diff --git a/editor/src/components/canvas/controls/new-canvas-controls.tsx b/editor/src/components/canvas/controls/new-canvas-controls.tsx index be85b3261131..d30f250812cf 100644 --- a/editor/src/components/canvas/controls/new-canvas-controls.tsx +++ b/editor/src/components/canvas/controls/new-canvas-controls.tsx @@ -74,6 +74,8 @@ import { NO_OP } from '../../../core/shared/utils' import { useIsMyProject } from '../../editor/store/collaborative-editing' import { MultiplayerWrapper } from '../../../utils/multiplayer-wrapper' import { MultiplayerPresence } from '../multiplayer-presence' +import { GridControls } from './grid-controls' +import { getAllGrids } from '../canvas-strategies/strategies/grid-helpers' export const CanvasControlsContainerID = 'new-canvas-controls-container' @@ -313,6 +315,7 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => { autoFocusedPaths, filePathMappings, propertyControlsInfo, + grids, } = useEditorState( Substores.fullStore, (store) => { @@ -333,6 +336,7 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => { autoFocusedPaths: store.derived.autoFocusedPaths, filePathMappings: store.derived.filePathMappings, propertyControlsInfo: store.editor.propertyControlsInfo, + grids: isDragInteractionActive(store.editor) ? getAllGrids(store.editor.jsxMetadata) : [], } }, 'NewCanvasControlsInner', @@ -596,6 +600,14 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => { isSelectOrInsertMode(editorMode) && !EP.multiplePathsAllWithTheSameUID(localSelectedViews), <> + {when( + dragInteractionActive, + } + propsForControl={{ targets: grids, visible: 'hidden' }} + />, + )} {strategyControls.map((c) => ( Date: Thu, 10 Oct 2024 18:17:37 +0200 Subject: [PATCH 02/24] Update snapshot --- .../performance-regression-tests.spec.tsx.snap | 18 ++++++++++++++---- .../performance-regression-tests.spec.tsx | 8 ++++---- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap index 4635c7a78aab..1983b6c03e94 100644 --- a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap +++ b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap @@ -34,6 +34,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", @@ -53,7 +54,7 @@ Array [ "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)()//Symbol(react.memo)()", + "/null/Symbol(react.memo)()//Symbol(react.memo)()", "/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)())", "/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)())", "/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)())", @@ -84,7 +85,7 @@ Array [ "/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div", "/div/Symbol(react.memo)(Symbol(react.forward_ref)(SizeLabel))/Symbol(react.forward_ref)(SizeLabel)/div:data-testid='SizeLabelTestId'", "/div/Symbol(react.memo)(Symbol(react.forward_ref)(SizeLabel))/Symbol(react.forward_ref)(SizeLabel)/div:data-testid='parent-resize-label'", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)()//Symbol(react.memo)()", + "/null/Symbol(react.memo)()//Symbol(react.memo)()", "/Symbol(react.memo)()///UtopiaSpiedExoticType(Symbol(react.fragment))", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", "/UtopiaSpiedFunctionComponent(SimpleFlexColumn)/div/ElementsOutsideVisibleAreaIndicator/Symbol(react.memo)(IndicatorArrow)", @@ -814,6 +815,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", @@ -833,7 +835,7 @@ Array [ "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)()//Symbol(react.memo)()", + "/null/Symbol(react.memo)()//Symbol(react.memo)()", "/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)())", "/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)())", "/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)())", @@ -864,7 +866,7 @@ Array [ "/div/Symbol(react.memo)(Symbol(react.forward_ref)(ResizePoint))/Symbol(react.forward_ref)(ResizePoint)/div", "/div/Symbol(react.memo)(Symbol(react.forward_ref)(SizeLabel))/Symbol(react.forward_ref)(SizeLabel)/div:data-testid='SizeLabelTestId'", "/div/Symbol(react.memo)(Symbol(react.forward_ref)(SizeLabel))/Symbol(react.forward_ref)(SizeLabel)/div:data-testid='parent-resize-label'", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)()//Symbol(react.memo)()", + "/null/Symbol(react.memo)()//Symbol(react.memo)()", "/Symbol(react.memo)()///UtopiaSpiedExoticType(Symbol(react.fragment))", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", "/UtopiaSpiedFunctionComponent(SimpleFlexColumn)/div/ElementsOutsideVisibleAreaIndicator/Symbol(react.memo)(IndicatorArrow)", @@ -1483,6 +1485,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", @@ -1772,6 +1775,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", @@ -2373,6 +2377,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", @@ -2480,6 +2485,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", @@ -2598,6 +2604,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", @@ -2875,6 +2882,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", @@ -3352,6 +3360,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", @@ -3401,6 +3410,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", diff --git a/editor/src/core/performance/performance-regression-tests.spec.tsx b/editor/src/core/performance/performance-regression-tests.spec.tsx index 7f53a8cd0879..1cc6f4f93750 100644 --- a/editor/src/core/performance/performance-regression-tests.spec.tsx +++ b/editor/src/core/performance/performance-regression-tests.spec.tsx @@ -65,7 +65,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`858`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`862`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -127,7 +127,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`1110`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`1114`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -183,7 +183,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`650`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`651`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -249,7 +249,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`775`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`776`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) }) From 15097475a58b976c7a000fc2ee5f73aa675cf154 Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Thu, 10 Oct 2024 18:22:03 +0200 Subject: [PATCH 03/24] remove unnecessary nullish coalescing --- editor/src/components/canvas/controls/grid-controls.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index 2e1282bee7c0..32cd6fc580c5 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -1157,7 +1157,7 @@ export const GridControls = controlForStrategyMemoized( ) })} From 145fe5a3f438eea4ab8a044a2e8913bff0ad3fc3 Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Thu, 10 Oct 2024 18:41:42 +0200 Subject: [PATCH 04/24] Add missing visible prop --- editor/src/components/canvas/controls/grid-controls.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index 32cd6fc580c5..b3d894ecbaf2 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -1854,10 +1854,10 @@ function gridPlaceholderWidthOrHeight(scale: number): string { export function controlsForGridPlaceholders( gridPath: ElementPath, whenToShow: WhenToShowControl = 'always-visible', -): ControlWithProps { +): ControlWithProps { return { control: GridControls, - props: { targets: [gridPath] }, + props: { targets: [gridPath], visible: 'visible' }, key: GridControlsKey(gridPath), show: whenToShow, priority: 'bottom', From ed1a2619fde23a8632021487dfe1d97557845259 Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Fri, 11 Oct 2024 10:44:58 +0200 Subject: [PATCH 05/24] Deduplicate grid controls --- .../strategies/grid-reparent-strategy.tsx | 1 - .../canvas/controls/grid-controls.tsx | 4 ++- .../canvas/controls/new-canvas-controls.tsx | 32 ++++++++++++++++--- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategy.tsx b/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategy.tsx index 419b1633ca7a..902769b4546d 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategy.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategy.tsx @@ -17,7 +17,6 @@ import type { InsertionPath } from '../../../editor/store/insertion-path' import { CSSCursor } from '../../canvas-types' import { setCursorCommand } from '../../commands/set-cursor-command' import { propertyToSet, updateBulkProperties } from '../../commands/set-property-command' -import { showGridControls } from '../../commands/show-grid-controls-command' import { updateSelectedViews } from '../../commands/update-selected-views-command' import { controlsForGridPlaceholders } from '../../controls/grid-controls' import { ParentBounds } from '../../controls/parent-bounds' diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index b3d894ecbaf2..6a35cac6b768 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -656,7 +656,9 @@ export const GridRowColumnResizingControls = ) }) -export const GridControlsKey = (gridPath: ElementPath) => `grid-controls-${EP.toString(gridPath)}` +export const GridControlsKeyPrefix = 'grid-controls-' +export const GridControlsKey = (gridPath: ElementPath) => + `${GridControlsKeyPrefix}${EP.toString(gridPath)}` export interface GridControlProps { grid: GridData diff --git a/editor/src/components/canvas/controls/new-canvas-controls.tsx b/editor/src/components/canvas/controls/new-canvas-controls.tsx index d30f250812cf..784c6227b998 100644 --- a/editor/src/components/canvas/controls/new-canvas-controls.tsx +++ b/editor/src/components/canvas/controls/new-canvas-controls.tsx @@ -74,8 +74,9 @@ import { NO_OP } from '../../../core/shared/utils' import { useIsMyProject } from '../../editor/store/collaborative-editing' import { MultiplayerWrapper } from '../../../utils/multiplayer-wrapper' import { MultiplayerPresence } from '../multiplayer-presence' -import { GridControls } from './grid-controls' +import { GridControls, GridControlsKeyPrefix, type GridControlsProps } from './grid-controls' import { getAllGrids } from '../canvas-strategies/strategies/grid-helpers' +import type { ControlWithProps } from '../canvas-strategies/canvas-strategy-types' export const CanvasControlsContainerID = 'new-canvas-controls-container' @@ -315,7 +316,6 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => { autoFocusedPaths, filePathMappings, propertyControlsInfo, - grids, } = useEditorState( Substores.fullStore, (store) => { @@ -336,12 +336,17 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => { autoFocusedPaths: store.derived.autoFocusedPaths, filePathMappings: store.derived.filePathMappings, propertyControlsInfo: store.editor.propertyControlsInfo, - grids: isDragInteractionActive(store.editor) ? getAllGrids(store.editor.jsxMetadata) : [], } }, 'NewCanvasControlsInner', ) + const gridsWithoutControl = useGridsWithoutControl( + strategyControls, + dragInteractionActive, + componentMetadata, + ) + const cmdKeyPressed = keysPressed['cmd'] ?? false const contextMenuEnabled = !isLiveMode(editorMode) @@ -605,7 +610,7 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => { } - propsForControl={{ targets: grids, visible: 'hidden' }} + propsForControl={{ targets: gridsWithoutControl, visible: 'hidden' }} />, )} {strategyControls.map((c) => ( @@ -685,4 +690,23 @@ const SelectionAreaRectangle = React.memo( }, ) +function useGridsWithoutControl( + strategyControls: Array>, + dragInteractionActive: boolean, + metadata: ElementInstanceMetadataMap, +) { + return React.useMemo(() => { + if (!dragInteractionActive) { + return [] + } + return getAllGrids(metadata).filter((grid) => { + return !strategyControls.some( + (control) => + control.key.startsWith(GridControlsKeyPrefix) && + (control.props as GridControlsProps).targets.some((t) => EP.pathsEqual(t, grid)), + ) + }) + }, [metadata, strategyControls, dragInteractionActive]) +} + SelectionAreaRectangle.displayName = 'SelectionAreaRectangle' From e995db362a3bc24dbddeb4aa64d87536ae9e6c4e Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Fri, 11 Oct 2024 11:15:37 +0200 Subject: [PATCH 06/24] Better deduplication --- .../components/canvas/controls/new-canvas-controls.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/editor/src/components/canvas/controls/new-canvas-controls.tsx b/editor/src/components/canvas/controls/new-canvas-controls.tsx index 784c6227b998..2e5f2cae6ec5 100644 --- a/editor/src/components/canvas/controls/new-canvas-controls.tsx +++ b/editor/src/components/canvas/controls/new-canvas-controls.tsx @@ -74,7 +74,7 @@ import { NO_OP } from '../../../core/shared/utils' import { useIsMyProject } from '../../editor/store/collaborative-editing' import { MultiplayerWrapper } from '../../../utils/multiplayer-wrapper' import { MultiplayerPresence } from '../multiplayer-presence' -import { GridControls, GridControlsKeyPrefix, type GridControlsProps } from './grid-controls' +import { GridControls, GridControlsKey } from './grid-controls' import { getAllGrids } from '../canvas-strategies/strategies/grid-helpers' import type { ControlWithProps } from '../canvas-strategies/canvas-strategy-types' @@ -700,11 +700,7 @@ function useGridsWithoutControl( return [] } return getAllGrids(metadata).filter((grid) => { - return !strategyControls.some( - (control) => - control.key.startsWith(GridControlsKeyPrefix) && - (control.props as GridControlsProps).targets.some((t) => EP.pathsEqual(t, grid)), - ) + return strategyControls.every((control) => control.key !== GridControlsKey(grid)) }) }, [metadata, strategyControls, dragInteractionActive]) } From 46e414a948ac670a48596b08b90ccafd40455d02 Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Fri, 11 Oct 2024 11:16:54 +0200 Subject: [PATCH 07/24] Remove unnecessary change --- editor/src/components/canvas/controls/grid-controls.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index 6a35cac6b768..b3d894ecbaf2 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -656,9 +656,7 @@ export const GridRowColumnResizingControls = ) }) -export const GridControlsKeyPrefix = 'grid-controls-' -export const GridControlsKey = (gridPath: ElementPath) => - `${GridControlsKeyPrefix}${EP.toString(gridPath)}` +export const GridControlsKey = (gridPath: ElementPath) => `grid-controls-${EP.toString(gridPath)}` export interface GridControlProps { grid: GridData From a81df07cb4ed1c26c12ed2c66e7a53c9c7d49902 Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Fri, 11 Oct 2024 11:35:04 +0200 Subject: [PATCH 08/24] Use GridControl directly in canvas controls --- .../canvas/controls/grid-controls.tsx | 7 ++----- .../canvas/controls/new-canvas-controls.tsx | 21 +++++++++++++------ 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index b3d894ecbaf2..dd410ad18853 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -657,6 +657,7 @@ export const GridRowColumnResizingControls = }) export const GridControlsKey = (gridPath: ElementPath) => `grid-controls-${EP.toString(gridPath)}` +export const GridControlKey = (gridPath: ElementPath) => `grid-control-${EP.toString(gridPath)}` export interface GridControlProps { grid: GridData @@ -1154,11 +1155,7 @@ export const GridControls = controlForStrategyMemoized( {grids.map((grid) => { return ( - + ) })} diff --git a/editor/src/components/canvas/controls/new-canvas-controls.tsx b/editor/src/components/canvas/controls/new-canvas-controls.tsx index 2e5f2cae6ec5..ebb218d82c38 100644 --- a/editor/src/components/canvas/controls/new-canvas-controls.tsx +++ b/editor/src/components/canvas/controls/new-canvas-controls.tsx @@ -74,9 +74,10 @@ import { NO_OP } from '../../../core/shared/utils' import { useIsMyProject } from '../../editor/store/collaborative-editing' import { MultiplayerWrapper } from '../../../utils/multiplayer-wrapper' import { MultiplayerPresence } from '../multiplayer-presence' -import { GridControls, GridControlsKey } from './grid-controls' +import { GridControl, GridControlKey, GridControlsKey, useGridData } from './grid-controls' import { getAllGrids } from '../canvas-strategies/strategies/grid-helpers' import type { ControlWithProps } from '../canvas-strategies/canvas-strategy-types' +import { CanvasOffsetWrapper } from './canvas-offset-wrapper' export const CanvasControlsContainerID = 'new-canvas-controls-container' @@ -347,6 +348,8 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => { componentMetadata, ) + const gridsWithoutControlData = useGridData(gridsWithoutControl) + const cmdKeyPressed = keysPressed['cmd'] ?? false const contextMenuEnabled = !isLiveMode(editorMode) @@ -607,11 +610,17 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => { <> {when( dragInteractionActive, - } - propsForControl={{ targets: gridsWithoutControl, visible: 'hidden' }} - />, + + {gridsWithoutControlData.map((grid) => { + return ( + + ) + })} + , )} {strategyControls.map((c) => ( Date: Fri, 11 Oct 2024 11:38:11 +0200 Subject: [PATCH 09/24] Even better --- .../components/canvas/controls/new-canvas-controls.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/editor/src/components/canvas/controls/new-canvas-controls.tsx b/editor/src/components/canvas/controls/new-canvas-controls.tsx index ebb218d82c38..dd46c87902d8 100644 --- a/editor/src/components/canvas/controls/new-canvas-controls.tsx +++ b/editor/src/components/canvas/controls/new-canvas-controls.tsx @@ -348,8 +348,6 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => { componentMetadata, ) - const gridsWithoutControlData = useGridData(gridsWithoutControl) - const cmdKeyPressed = keysPressed['cmd'] ?? false const contextMenuEnabled = !isLiveMode(editorMode) @@ -611,7 +609,7 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => { {when( dragInteractionActive, - {gridsWithoutControlData.map((grid) => { + {gridsWithoutControl.map((grid) => { return ( { + const grids = React.useMemo(() => { if (!dragInteractionActive) { return [] } @@ -712,6 +710,8 @@ function useGridsWithoutControl( return strategyControls.every((control) => control.key !== GridControlsKey(grid)) }) }, [metadata, strategyControls, dragInteractionActive]) + + return useGridData(grids) } SelectionAreaRectangle.displayName = 'SelectionAreaRectangle' From d4814cfe3feb2c11dd6e9919e22a3c380d5e8a28 Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:53:50 +0200 Subject: [PATCH 10/24] Separate measurement grid helper --- .../strategies/grid-helpers.ts | 8 -- .../canvas/controls/grid-controls.tsx | 131 +++++++++++++----- .../canvas/controls/new-canvas-controls.tsx | 35 ++--- editor/src/components/canvas/dom-walker.ts | 2 +- .../src/core/model/element-metadata-utils.ts | 5 + 5 files changed, 111 insertions(+), 70 deletions(-) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts index 17b08a8ec464..d41fb8acdd53 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts @@ -814,11 +814,3 @@ function getOriginalElementGridConfiguration( mouseCellPosInOriginalElement, } } - -export const getAllGrids = memoize(getAllGridsInner, { maxSize: 1 }) - -function getAllGridsInner(jsxMetadata: ElementInstanceMetadataMap): Array { - return Object.keys(jsxMetadata) - .filter((key) => MetadataUtils.isGridLayoutedContainer(jsxMetadata[key])) - .map(EP.fromString) -} diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index dd410ad18853..d9980b5db121 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -661,10 +661,9 @@ export const GridControlKey = (gridPath: ElementPath) => `grid-control-${EP.toSt export interface GridControlProps { grid: GridData - visible: 'visible' | 'hidden' } -export const GridControl = React.memo(({ grid, visible }) => { +export const GridControl = React.memo(({ grid }) => { const dispatch = useDispatch() const controls = useAnimationControls() const colorTheme = useColorTheme() @@ -916,7 +915,6 @@ export const GridControl = React.memo(({ grid, visible }) => { grid.padding == null ? 0 : `${grid.padding.top}px ${grid.padding.right}px ${grid.padding.bottom}px ${grid.padding.left}px`, - opacity: visible === 'visible' ? 1 : 0, } // Gap needs to be set only if the other two are not present or we'll have rendering issues @@ -1125,45 +1123,108 @@ export const GridControl = React.memo(({ grid, visible }) => { }) GridControl.displayName = 'GridControl' +export const GridMeasurementHelper = React.memo(({ grid }) => { + const placeholders = range(0, grid.cells) + + let style: CSSProperties = { + position: 'absolute', + top: grid.frame.y, + left: grid.frame.x, + width: grid.frame.width, + height: grid.frame.height, + display: 'grid', + gridTemplateColumns: getNullableAutoOrTemplateBaseString(grid.gridTemplateColumns), + gridTemplateRows: getNullableAutoOrTemplateBaseString(grid.gridTemplateRows), + justifyContent: grid.justifyContent ?? 'initial', + alignContent: grid.alignContent ?? 'initial', + pointerEvents: 'none', + padding: + grid.padding == null + ? 0 + : `${grid.padding.top}px ${grid.padding.right}px ${grid.padding.bottom}px ${grid.padding.left}px`, + opacity: 1, + } + + // Gap needs to be set only if the other two are not present or we'll have rendering issues + // due to how measurements are calculated. + if (grid.rowGap != null && grid.columnGap != null) { + style.rowGap = grid.rowGap + style.columnGap = grid.columnGap + } else { + if (grid.gap != null) { + style.gap = grid.gap + } + if (grid.rowGap != null) { + style.rowGap = grid.rowGap + } + if (grid.columnGap != null) { + style.columnGap = grid.columnGap + } + } + + return ( + +
+ {placeholders.map((cell) => { + const countedRow = Math.floor(cell / grid.columns) + 1 + const countedColumn = Math.floor(cell % grid.columns) + 1 + const id = gridCellTargetId(grid.elementPath, countedRow, countedColumn) + return ( +
+ ) + })} +
+ + ) +}) +GridMeasurementHelper.displayName = 'GridControl' + export interface GridControlsProps { targets: ElementPath[] - visible: 'visible' | 'hidden' } -export const GridControls = controlForStrategyMemoized( - ({ targets, visible }) => { - const targetRootCell = useEditorState( - Substores.canvas, - (store) => store.editor.canvas.controls.gridControlData?.rootCell ?? null, - 'GridControls targetRootCell', - ) +export const GridControls = controlForStrategyMemoized(({ targets }) => { + const targetRootCell = useEditorState( + Substores.canvas, + (store) => store.editor.canvas.controls.gridControlData?.rootCell ?? null, + 'GridControls targetRootCell', + ) - const hoveredGrids = useEditorState( - Substores.canvas, - (store) => stripNulls([store.editor.canvas.controls.gridControlData?.grid]), - 'GridControls hoveredGrids', - ) + const hoveredGrids = useEditorState( + Substores.canvas, + (store) => stripNulls([store.editor.canvas.controls.gridControlData?.grid]), + 'GridControls hoveredGrids', + ) - const grids = useGridData(uniqBy([...targets, ...hoveredGrids], (a, b) => EP.pathsEqual(a, b))) + const grids = useGridData(uniqBy([...targets, ...hoveredGrids], (a, b) => EP.pathsEqual(a, b))) - if (grids.length === 0) { - return null - } + if (grids.length === 0) { + return null + } - return ( -
- - {grids.map((grid) => { - return ( - - ) - })} - - -
- ) - }, -) + return ( +
+ + {grids.map((grid) => { + return + })} + + +
+ ) +}) const MIN_INDICATORS_DISTANCE = 32 // px @@ -1854,7 +1915,7 @@ export function controlsForGridPlaceholders( ): ControlWithProps { return { control: GridControls, - props: { targets: [gridPath], visible: 'visible' }, + props: { targets: [gridPath] }, key: GridControlsKey(gridPath), show: whenToShow, priority: 'bottom', diff --git a/editor/src/components/canvas/controls/new-canvas-controls.tsx b/editor/src/components/canvas/controls/new-canvas-controls.tsx index dd46c87902d8..ce18e34f500e 100644 --- a/editor/src/components/canvas/controls/new-canvas-controls.tsx +++ b/editor/src/components/canvas/controls/new-canvas-controls.tsx @@ -74,10 +74,7 @@ import { NO_OP } from '../../../core/shared/utils' import { useIsMyProject } from '../../editor/store/collaborative-editing' import { MultiplayerWrapper } from '../../../utils/multiplayer-wrapper' import { MultiplayerPresence } from '../multiplayer-presence' -import { GridControl, GridControlKey, GridControlsKey, useGridData } from './grid-controls' -import { getAllGrids } from '../canvas-strategies/strategies/grid-helpers' -import type { ControlWithProps } from '../canvas-strategies/canvas-strategy-types' -import { CanvasOffsetWrapper } from './canvas-offset-wrapper' +import { GridMeasurementHelper, GridControlKey, useGridData } from './grid-controls' export const CanvasControlsContainerID = 'new-canvas-controls-container' @@ -342,11 +339,7 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => { 'NewCanvasControlsInner', ) - const gridsWithoutControl = useGridsWithoutControl( - strategyControls, - dragInteractionActive, - componentMetadata, - ) + const grids = useAllGrids(componentMetadata) const cmdKeyPressed = keysPressed['cmd'] ?? false @@ -608,17 +601,16 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => { <> {when( dragInteractionActive, - - {gridsWithoutControl.map((grid) => { + + {grids.map((grid) => { return ( - ) })} - , + , )} {strategyControls.map((c) => ( >, - dragInteractionActive: boolean, - metadata: ElementInstanceMetadataMap, -) { +function useAllGrids(metadata: ElementInstanceMetadataMap) { const grids = React.useMemo(() => { - if (!dragInteractionActive) { - return [] - } - return getAllGrids(metadata).filter((grid) => { - return strategyControls.every((control) => control.key !== GridControlsKey(grid)) - }) - }, [metadata, strategyControls, dragInteractionActive]) + return MetadataUtils.getAllGrids(metadata) + }, [metadata]) return useGridData(grids) } diff --git a/editor/src/components/canvas/dom-walker.ts b/editor/src/components/canvas/dom-walker.ts index 2dfe03416b5a..085b22e1e1d9 100644 --- a/editor/src/components/canvas/dom-walker.ts +++ b/editor/src/components/canvas/dom-walker.ts @@ -1069,7 +1069,7 @@ function measureGlobalFramesOfGridCellsFromControl( const path = grid.getAttribute(UTOPIA_PATH_KEY) let gridCellGlobalFrames: Array> | null = null if (path != null) { - const gridControlElement = document.getElementById(`grid-${path}`) + const gridControlElement = document.getElementById(`grid-measurement-helper-${path}`) if (gridControlElement != null) { gridCellGlobalFrames = [] for (const cell of gridControlElement.children) { diff --git a/editor/src/core/model/element-metadata-utils.ts b/editor/src/core/model/element-metadata-utils.ts index e9c448db5d3e..ac005c2026ac 100644 --- a/editor/src/core/model/element-metadata-utils.ts +++ b/editor/src/core/model/element-metadata-utils.ts @@ -408,6 +408,11 @@ export const MetadataUtils = { specialSizeMeasurements.elementGridPropertiesFromProps.gridRowEnd == null ) }, + getAllGrids(metadata: ElementInstanceMetadataMap): Array { + return Object.values(metadata) + .filter((m) => MetadataUtils.isGridLayoutedContainer(m)) + .map((m) => m.elementPath) + }, isComponentInstanceFromMetadata( metadata: ElementInstanceMetadataMap, path: ElementPath, From a92c086e252fa169dd0c402a68fe6026ba04f205 Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Mon, 14 Oct 2024 15:54:51 +0200 Subject: [PATCH 11/24] Remove latestMetadata hack from interactions --- .../grid-draw-to-insert-strategy.tsx | 14 ++--- .../strategies/grid-helpers.ts | 56 ------------------- .../strategies/grid-reparent-strategy.tsx | 23 +++----- .../grid-resize-element-strategy.ts | 17 ++---- .../canvas/controls/new-canvas-controls.tsx | 3 +- 5 files changed, 20 insertions(+), 93 deletions(-) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-draw-to-insert-strategy.tsx b/editor/src/components/canvas/canvas-strategies/strategies/grid-draw-to-insert-strategy.tsx index 894570a5266e..9756bb49ddfe 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-draw-to-insert-strategy.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-draw-to-insert-strategy.tsx @@ -43,7 +43,7 @@ import { getStyleAttributesForFrameInAbsolutePosition, updateInsertionSubjectWithAttributes, } from './draw-to-insert-metastrategy' -import { getMetadataWithGridCellBounds, setGridPropsCommands } from './grid-helpers' +import { setGridPropsCommands } from './grid-helpers' import { newReparentSubjects } from './reparent-helpers/reparent-strategy-helpers' import { getReparentTargetUnified } from './reparent-helpers/reparent-strategy-parent-lookup' import { getGridCellUnderMouseFromMetadata } from './grid-cell-bounds' @@ -132,13 +132,10 @@ const gridDrawToInsertStrategyInner = canvasState.propertyControlsInfo, )?.newParent.intendedParentPath - const { metadata: parent, customStrategyState: updatedCustomState } = - getMetadataWithGridCellBounds( - targetParent, - canvasState.startingMetadata, - interactionSession.latestMetadata, - customStrategyState, - ) + const parent = MetadataUtils.findElementByElementPath( + canvasState.startingMetadata, + targetParent, + ) if (targetParent == null || parent == null || !MetadataUtils.isGridLayoutedContainer(parent)) { return null @@ -175,7 +172,6 @@ const gridDrawToInsertStrategyInner = updateHighlightedViews('mid-interaction', [targetParent]), ], [targetParent], - updatedCustomState ?? undefined, ) } diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts index d41fb8acdd53..ca02b58e1ab5 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts @@ -711,62 +711,6 @@ export function getGridRelatedIndexes(params: { return expandedRelatedIndexes[params.index] ?? [] } -export function getMetadataWithGridCellBounds( - path: ElementPath | null | undefined, - startingMetadata: ElementInstanceMetadataMap, - latestMetadata: ElementInstanceMetadataMap, - customStrategyState: CustomStrategyState, -): { - metadata: ElementInstanceMetadata | null - customStrategyState: CustomStrategyState | null -} { - if (path == null) { - return { - metadata: null, - customStrategyState: null, - } - } - - const fromStartingMetadata = MetadataUtils.findElementByElementPath(startingMetadata, path) - - if (fromStartingMetadata?.specialSizeMeasurements.gridCellGlobalFrames != null) { - return { - metadata: fromStartingMetadata, - customStrategyState: null, - } - } - - const fromStrategyState = customStrategyState.grid.metadataCacheForGrids[EP.toString(path)] - if (fromStrategyState != null) { - return { - metadata: fromStrategyState, - customStrategyState: null, - } - } - - const fromLatestMetadata = MetadataUtils.findElementByElementPath(latestMetadata, path) - if (fromLatestMetadata?.specialSizeMeasurements.gridCellGlobalFrames != null) { - return { - metadata: fromLatestMetadata, - customStrategyState: { - ...customStrategyState, - grid: { - ...customStrategyState.grid, - metadataCacheForGrids: { - ...customStrategyState.grid.metadataCacheForGrids, - [EP.toString(path)]: fromLatestMetadata, - }, - }, - }, - } - } - - return { - metadata: fromStartingMetadata, - customStrategyState: null, - } -} - function getOriginalElementGridConfiguration( gridCellGlobalFrames: GridCellGlobalFrames, interactionData: DragInteractionData, diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategy.tsx b/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategy.tsx index 902769b4546d..eb144e0ba877 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategy.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-reparent-strategy.tsx @@ -38,7 +38,7 @@ import { import type { DragInteractionData, InteractionSession, UpdatedPathMap } from '../interaction-state' import { honoursPropsPosition, shouldKeepMovingDraggedGroupChildren } from './absolute-utils' import { replaceFragmentLikePathsWithTheirChildrenRecursive } from './fragment-like-helpers' -import { getMetadataWithGridCellBounds, runGridRearrangeMove } from './grid-helpers' +import { runGridRearrangeMove } from './grid-helpers' import { ifAllowedToReparent, isAllowedToReparent } from './reparent-helpers/reparent-helpers' import { removeAbsolutePositioningProps } from './reparent-helpers/reparent-property-changes' import type { ReparentTarget } from './reparent-helpers/reparent-strategy-helpers' @@ -163,13 +163,10 @@ export function applyGridReparent( return emptyStrategyApplicationResult } - const { metadata: grid, customStrategyState: updatedCustomState } = - getMetadataWithGridCellBounds( - newParent.intendedParentPath, - canvasState.startingMetadata, - interactionSession.latestMetadata, - customStrategyState, - ) + const grid = MetadataUtils.findElementByElementPath( + canvasState.startingMetadata, + newParent.intendedParentPath, + ) if (grid == null) { return strategyApplicationResult([], [newParent.intendedParentPath]) @@ -230,12 +227,6 @@ export function applyGridReparent( newParent.intendedParentPath, ]) - const baseCustomState = updatedCustomState ?? customStrategyState - const customStrategyStatePatch = { - ...baseCustomState, - elementsToRerender: elementsToRerender, - } - return strategyApplicationResult( [ ...outcomes.flatMap((c) => c.commands), @@ -244,7 +235,9 @@ export function applyGridReparent( setCursorCommand(CSSCursor.Reparent), ], elementsToRerender, - customStrategyStatePatch, + { + elementsToRerender: elementsToRerender, + }, ) }, ) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-strategy.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-strategy.ts index 91ff1f35c18e..d1ae3e360525 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-strategy.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-resize-element-strategy.ts @@ -1,12 +1,10 @@ import { MetadataUtils } from '../../../../core/model/element-metadata-utils' import * as EP from '../../../../core/shared/element-path' -import type { GridElementProperties, GridPosition } from '../../../../core/shared/element-template' import { type CanvasRectangle, isInfinityRectangle, rectangleIntersection, } from '../../../../core/shared/math-utils' -import { isCSSKeyword } from '../../../inspector/common/css-utils' import { isFixedHugFillModeApplied } from '../../../inspector/inspector-common' import { controlsForGridPlaceholders, @@ -22,13 +20,12 @@ import { strategyApplicationResult, } from '../canvas-strategy-types' import type { InteractionSession } from '../interaction-state' -import { getMetadataWithGridCellBounds, setGridPropsCommands } from './grid-helpers' +import { setGridPropsCommands } from './grid-helpers' import { resizeBoundingBoxFromSide } from './resize-helpers' export const gridResizeElementStrategy: CanvasStrategyFactory = ( canvasState: InteractionCanvasState, interactionSession: InteractionSession | null, - customState, ) => { const selectedElements = getTargetPathsFromInteractionTarget(canvasState.interactionTarget) if (selectedElements.length !== 1) { @@ -89,13 +86,10 @@ export const gridResizeElementStrategy: CanvasStrategyFactory = ( return emptyStrategyApplicationResult } - const { metadata: container, customStrategyState: updatedCustomState } = - getMetadataWithGridCellBounds( - EP.parentPath(selectedElement), - canvasState.startingMetadata, - interactionSession.latestMetadata, - customState, - ) + const container = MetadataUtils.findElementByElementPath( + canvasState.startingMetadata, + EP.parentPath(selectedElement), + ) if (container == null) { return emptyStrategyApplicationResult @@ -126,7 +120,6 @@ export const gridResizeElementStrategy: CanvasStrategyFactory = ( return strategyApplicationResult( setGridPropsCommands(selectedElement, gridTemplate, gridProps), [parentGridPath], - updatedCustomState ?? undefined, ) }, } diff --git a/editor/src/components/canvas/controls/new-canvas-controls.tsx b/editor/src/components/canvas/controls/new-canvas-controls.tsx index ce18e34f500e..81ee44b2829e 100644 --- a/editor/src/components/canvas/controls/new-canvas-controls.tsx +++ b/editor/src/components/canvas/controls/new-canvas-controls.tsx @@ -24,6 +24,7 @@ import { ElementContextMenu } from '../../element-context-menu' import type { Mode } from '../../editor/editor-modes' import { isCommentMode, + isInsertMode, isLiveMode, isSelectMode, isSelectModeWithArea, @@ -600,7 +601,7 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => { !EP.multiplePathsAllWithTheSameUID(localSelectedViews), <> {when( - dragInteractionActive, + isSelectMode(editorMode) || isInsertMode(editorMode), {grids.map((grid) => { return ( From bf86fa4c95e4b877930c871c91777557480b7515 Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Mon, 14 Oct 2024 16:08:16 +0200 Subject: [PATCH 12/24] Remove unused import --- .../canvas/canvas-strategies/strategies/grid-helpers.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts b/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts index ca02b58e1ab5..8f871138c922 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts @@ -45,7 +45,6 @@ import { import { mapDropNulls } from '../../../../core/shared/array-utils' import { assertNever } from '../../../../core/shared/utils' import { showGridControls } from '../../commands/show-grid-controls-command' -import { memoize } from '../../../../core/shared/memoize' export function runGridRearrangeMove( targetElement: ElementPath, From 4310311f3117b94fbc2d1dee22b619cddabccae8 Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Mon, 14 Oct 2024 17:34:17 +0200 Subject: [PATCH 13/24] Fix build and refactor --- .../canvas/controls/grid-controls.tsx | 122 +++++++----------- editor/src/uuiui/styles/theme/dark.ts | 1 + editor/src/uuiui/styles/theme/light.ts | 1 + 3 files changed, 51 insertions(+), 73 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index 19ad2335c8cf..f81a7d814530 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -764,45 +764,14 @@ const GridControl = React.memo(({ grid }) => { }) const placeholders = range(0, grid.cells) - let style: CSSProperties = { - position: 'absolute', - top: grid.frame.y, - left: grid.frame.x, - width: grid.frame.width, - height: grid.frame.height, - display: 'grid', - gridTemplateColumns: getNullableAutoOrTemplateBaseString(grid.gridTemplateColumns), - gridTemplateRows: getNullableAutoOrTemplateBaseString(grid.gridTemplateRows), - backgroundColor: - activelyDraggingOrResizingCell != null ? colorTheme.primary10.value : 'transparent', - outline: `1px solid ${ - activelyDraggingOrResizingCell != null ? colorTheme.primary.value : 'transparent' - }`, - justifyContent: grid.justifyContent ?? 'initial', - alignContent: grid.alignContent ?? 'initial', - pointerEvents: 'none', - padding: - grid.padding == null - ? 0 - : `${grid.padding.top}px ${grid.padding.right}px ${grid.padding.bottom}px ${grid.padding.left}px`, - } - // Gap needs to be set only if the other two are not present or we'll have rendering issues - // due to how measurements are calculated. - if (grid.rowGap != null && grid.columnGap != null) { - style.rowGap = grid.rowGap - style.columnGap = grid.columnGap - } else { - if (grid.gap != null) { - style.gap = grid.gap - } - if (grid.rowGap != null) { - style.rowGap = grid.rowGap - } - if (grid.columnGap != null) { - style.columnGap = grid.columnGap - } - } + let style = useGridControlBaseStyle(grid) + + style.backgroundColor = + activelyDraggingOrResizingCell != null ? colorTheme.primary10.value : 'transparent' + style.outline = `1px solid ${ + activelyDraggingOrResizingCell != null ? colorTheme.primary.value : 'transparent' + }` return ( @@ -930,41 +899,8 @@ GridControl.displayName = 'GridControl' export const GridMeasurementHelper = React.memo(({ grid }) => { const placeholders = range(0, grid.cells) - let style: CSSProperties = { - position: 'absolute', - top: grid.frame.y, - left: grid.frame.x, - width: grid.frame.width, - height: grid.frame.height, - display: 'grid', - gridTemplateColumns: getNullableAutoOrTemplateBaseString(grid.gridTemplateColumns), - gridTemplateRows: getNullableAutoOrTemplateBaseString(grid.gridTemplateRows), - justifyContent: grid.justifyContent ?? 'initial', - alignContent: grid.alignContent ?? 'initial', - pointerEvents: 'none', - padding: - grid.padding == null - ? 0 - : `${grid.padding.top}px ${grid.padding.right}px ${grid.padding.bottom}px ${grid.padding.left}px`, - opacity: 1, - } - - // Gap needs to be set only if the other two are not present or we'll have rendering issues - // due to how measurements are calculated. - if (grid.rowGap != null && grid.columnGap != null) { - style.rowGap = grid.rowGap - style.columnGap = grid.columnGap - } else { - if (grid.gap != null) { - style.gap = grid.gap - } - if (grid.rowGap != null) { - style.rowGap = grid.rowGap - } - if (grid.columnGap != null) { - style.columnGap = grid.columnGap - } - } + const style = useGridControlBaseStyle(grid) + style.opacity = 1 return ( @@ -1026,6 +962,46 @@ export const GridControlsComponent = ({ targets }: GridControlsProps) => { ) } +function useGridControlBaseStyle(grid: GridData) { + return React.useMemo(() => { + let style: CSSProperties = { + position: 'absolute', + top: grid.frame.y, + left: grid.frame.x, + width: grid.frame.width, + height: grid.frame.height, + display: 'grid', + gridTemplateColumns: getNullableAutoOrTemplateBaseString(grid.gridTemplateColumns), + gridTemplateRows: getNullableAutoOrTemplateBaseString(grid.gridTemplateRows), + justifyContent: grid.justifyContent ?? 'initial', + alignContent: grid.alignContent ?? 'initial', + pointerEvents: 'none', + padding: + grid.padding == null + ? 0 + : `${grid.padding.top}px ${grid.padding.right}px ${grid.padding.bottom}px ${grid.padding.left}px`, + } + + // Gap needs to be set only if the other two are not present or we'll have rendering issues + // due to how measurements are calculated. + if (grid.rowGap != null && grid.columnGap != null) { + style.rowGap = grid.rowGap + style.columnGap = grid.columnGap + } else { + if (grid.gap != null) { + style.gap = grid.gap + } + if (grid.rowGap != null) { + style.rowGap = grid.rowGap + } + if (grid.columnGap != null) { + style.columnGap = grid.columnGap + } + } + return style + }, [grid]) +} + const MIN_INDICATORS_DISTANCE = 32 // px const AbsoluteDistanceIndicators = React.memo( diff --git a/editor/src/uuiui/styles/theme/dark.ts b/editor/src/uuiui/styles/theme/dark.ts index 63c1564223f5..7e76faef77b3 100644 --- a/editor/src/uuiui/styles/theme/dark.ts +++ b/editor/src/uuiui/styles/theme/dark.ts @@ -134,6 +134,7 @@ const colorsWithOpacity = { whiteOpacity20: createUtopiColor('oklch(100% 0 0 /20%)'), whiteOpacity30: createUtopiColor('oklch(100% 0 0 /30%)'), whiteOpacity35: createUtopiColor('oklch(100% 0 0 /35%)'), + grey65: createUtopiColor('oklch(65% 0 0)'), blackOpacity35: createUtopiColor('oklch(0% 0 0 / 35%)'), canvasControlsSizeBoxShadowColor20: createUtopiColor('rgba(255,255,255,0.20)'), canvasControlsSizeBoxShadowColor50: createUtopiColor('rgba(255,255,255,0.5)'), diff --git a/editor/src/uuiui/styles/theme/light.ts b/editor/src/uuiui/styles/theme/light.ts index 0063da12508d..ad00d11d5e84 100644 --- a/editor/src/uuiui/styles/theme/light.ts +++ b/editor/src/uuiui/styles/theme/light.ts @@ -136,6 +136,7 @@ const colorsWithOpacity = { whiteOpacity30: createUtopiColor('oklch(100% 0 0 /30%)'), whiteOpacity35: createUtopiColor('oklch(100% 0 0 /35%)'), blackOpacity35: createUtopiColor('oklch(0% 0 0 / 35%)'), + grey65: createUtopiColor('oklch(65% 0 0)'), canvasControlsSizeBoxShadowColor20: createUtopiColor('rgba(0,0,0,0.20)'), canvasControlsSizeBoxShadowColor50: createUtopiColor('rgba(0,0,0,0.5)'), neutralInvertedBackground10: createUtopiColor('hsla(0,0%,0%,0.1)'), From 0df12580bc8e131a75d21b392e798ac30c9149eb Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Mon, 14 Oct 2024 17:57:06 +0200 Subject: [PATCH 14/24] fix --- .../canvas/controls/grid-controls.tsx | 122 +++++++++++------- 1 file changed, 73 insertions(+), 49 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index f81a7d814530..19ad2335c8cf 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -764,14 +764,45 @@ const GridControl = React.memo(({ grid }) => { }) const placeholders = range(0, grid.cells) + let style: CSSProperties = { + position: 'absolute', + top: grid.frame.y, + left: grid.frame.x, + width: grid.frame.width, + height: grid.frame.height, + display: 'grid', + gridTemplateColumns: getNullableAutoOrTemplateBaseString(grid.gridTemplateColumns), + gridTemplateRows: getNullableAutoOrTemplateBaseString(grid.gridTemplateRows), + backgroundColor: + activelyDraggingOrResizingCell != null ? colorTheme.primary10.value : 'transparent', + outline: `1px solid ${ + activelyDraggingOrResizingCell != null ? colorTheme.primary.value : 'transparent' + }`, + justifyContent: grid.justifyContent ?? 'initial', + alignContent: grid.alignContent ?? 'initial', + pointerEvents: 'none', + padding: + grid.padding == null + ? 0 + : `${grid.padding.top}px ${grid.padding.right}px ${grid.padding.bottom}px ${grid.padding.left}px`, + } - let style = useGridControlBaseStyle(grid) - - style.backgroundColor = - activelyDraggingOrResizingCell != null ? colorTheme.primary10.value : 'transparent' - style.outline = `1px solid ${ - activelyDraggingOrResizingCell != null ? colorTheme.primary.value : 'transparent' - }` + // Gap needs to be set only if the other two are not present or we'll have rendering issues + // due to how measurements are calculated. + if (grid.rowGap != null && grid.columnGap != null) { + style.rowGap = grid.rowGap + style.columnGap = grid.columnGap + } else { + if (grid.gap != null) { + style.gap = grid.gap + } + if (grid.rowGap != null) { + style.rowGap = grid.rowGap + } + if (grid.columnGap != null) { + style.columnGap = grid.columnGap + } + } return ( @@ -899,8 +930,41 @@ GridControl.displayName = 'GridControl' export const GridMeasurementHelper = React.memo(({ grid }) => { const placeholders = range(0, grid.cells) - const style = useGridControlBaseStyle(grid) - style.opacity = 1 + let style: CSSProperties = { + position: 'absolute', + top: grid.frame.y, + left: grid.frame.x, + width: grid.frame.width, + height: grid.frame.height, + display: 'grid', + gridTemplateColumns: getNullableAutoOrTemplateBaseString(grid.gridTemplateColumns), + gridTemplateRows: getNullableAutoOrTemplateBaseString(grid.gridTemplateRows), + justifyContent: grid.justifyContent ?? 'initial', + alignContent: grid.alignContent ?? 'initial', + pointerEvents: 'none', + padding: + grid.padding == null + ? 0 + : `${grid.padding.top}px ${grid.padding.right}px ${grid.padding.bottom}px ${grid.padding.left}px`, + opacity: 1, + } + + // Gap needs to be set only if the other two are not present or we'll have rendering issues + // due to how measurements are calculated. + if (grid.rowGap != null && grid.columnGap != null) { + style.rowGap = grid.rowGap + style.columnGap = grid.columnGap + } else { + if (grid.gap != null) { + style.gap = grid.gap + } + if (grid.rowGap != null) { + style.rowGap = grid.rowGap + } + if (grid.columnGap != null) { + style.columnGap = grid.columnGap + } + } return ( @@ -962,46 +1026,6 @@ export const GridControlsComponent = ({ targets }: GridControlsProps) => { ) } -function useGridControlBaseStyle(grid: GridData) { - return React.useMemo(() => { - let style: CSSProperties = { - position: 'absolute', - top: grid.frame.y, - left: grid.frame.x, - width: grid.frame.width, - height: grid.frame.height, - display: 'grid', - gridTemplateColumns: getNullableAutoOrTemplateBaseString(grid.gridTemplateColumns), - gridTemplateRows: getNullableAutoOrTemplateBaseString(grid.gridTemplateRows), - justifyContent: grid.justifyContent ?? 'initial', - alignContent: grid.alignContent ?? 'initial', - pointerEvents: 'none', - padding: - grid.padding == null - ? 0 - : `${grid.padding.top}px ${grid.padding.right}px ${grid.padding.bottom}px ${grid.padding.left}px`, - } - - // Gap needs to be set only if the other two are not present or we'll have rendering issues - // due to how measurements are calculated. - if (grid.rowGap != null && grid.columnGap != null) { - style.rowGap = grid.rowGap - style.columnGap = grid.columnGap - } else { - if (grid.gap != null) { - style.gap = grid.gap - } - if (grid.rowGap != null) { - style.rowGap = grid.rowGap - } - if (grid.columnGap != null) { - style.columnGap = grid.columnGap - } - } - return style - }, [grid]) -} - const MIN_INDICATORS_DISTANCE = 32 // px const AbsoluteDistanceIndicators = React.memo( From 1696fd1b3aeb4a4aa82469cb871fd4ec84981851 Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Mon, 14 Oct 2024 18:03:51 +0200 Subject: [PATCH 15/24] Update keys and types --- editor/src/components/canvas/controls/grid-controls.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index 19ad2335c8cf..b96faef88e1c 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -927,7 +927,9 @@ const GridControl = React.memo(({ grid }) => { }) GridControl.displayName = 'GridControl' -export const GridMeasurementHelper = React.memo(({ grid }) => { +type GridMeasurementHelperProps = GridControlProps + +export const GridMeasurementHelper = React.memo(({ grid }) => { const placeholders = range(0, grid.cells) let style: CSSProperties = { @@ -976,7 +978,9 @@ export const GridMeasurementHelper = React.memo(({ grid }) => {placeholders.map((cell) => { const countedRow = Math.floor(cell / grid.columns) + 1 const countedColumn = Math.floor(cell % grid.columns) + 1 - const id = gridCellTargetId(grid.elementPath, countedRow, countedColumn) + const id = `grid-measurement-helper-${EP.toString( + grid.elementPath, + )}-${countedRow}-${countedColumn}` return (
Date: Mon, 14 Oct 2024 20:49:13 +0200 Subject: [PATCH 16/24] Flatten props --- .../canvas/controls/grid-controls.tsx | 54 +++++++++---------- .../canvas/controls/new-canvas-controls.tsx | 2 +- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index b96faef88e1c..e7fba4c0d0b3 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -927,59 +927,57 @@ const GridControl = React.memo(({ grid }) => { }) GridControl.displayName = 'GridControl' -type GridMeasurementHelperProps = GridControlProps - -export const GridMeasurementHelper = React.memo(({ grid }) => { - const placeholders = range(0, grid.cells) +export const GridMeasurementHelper = React.memo((props) => { + const placeholders = range(0, props.cells) let style: CSSProperties = { position: 'absolute', - top: grid.frame.y, - left: grid.frame.x, - width: grid.frame.width, - height: grid.frame.height, + top: props.frame.y, + left: props.frame.x, + width: props.frame.width, + height: props.frame.height, display: 'grid', - gridTemplateColumns: getNullableAutoOrTemplateBaseString(grid.gridTemplateColumns), - gridTemplateRows: getNullableAutoOrTemplateBaseString(grid.gridTemplateRows), - justifyContent: grid.justifyContent ?? 'initial', - alignContent: grid.alignContent ?? 'initial', + gridTemplateColumns: getNullableAutoOrTemplateBaseString(props.gridTemplateColumns), + gridTemplateRows: getNullableAutoOrTemplateBaseString(props.gridTemplateRows), + justifyContent: props.justifyContent ?? 'initial', + alignContent: props.alignContent ?? 'initial', pointerEvents: 'none', padding: - grid.padding == null + props.padding == null ? 0 - : `${grid.padding.top}px ${grid.padding.right}px ${grid.padding.bottom}px ${grid.padding.left}px`, + : `${props.padding.top}px ${props.padding.right}px ${props.padding.bottom}px ${props.padding.left}px`, opacity: 1, } // Gap needs to be set only if the other two are not present or we'll have rendering issues // due to how measurements are calculated. - if (grid.rowGap != null && grid.columnGap != null) { - style.rowGap = grid.rowGap - style.columnGap = grid.columnGap + if (props.rowGap != null && props.columnGap != null) { + style.rowGap = props.rowGap + style.columnGap = props.columnGap } else { - if (grid.gap != null) { - style.gap = grid.gap + if (props.gap != null) { + style.gap = props.gap } - if (grid.rowGap != null) { - style.rowGap = grid.rowGap + if (props.rowGap != null) { + style.rowGap = props.rowGap } - if (grid.columnGap != null) { - style.columnGap = grid.columnGap + if (props.columnGap != null) { + style.columnGap = props.columnGap } } return (
{placeholders.map((cell) => { - const countedRow = Math.floor(cell / grid.columns) + 1 - const countedColumn = Math.floor(cell % grid.columns) + 1 + const countedRow = Math.floor(cell / props.columns) + 1 + const countedColumn = Math.floor(cell % props.columns) + 1 const id = `grid-measurement-helper-${EP.toString( - grid.elementPath, + props.elementPath, )}-${countedRow}-${countedColumn}` return (
{ return ( ) })} From 3d8be9f200ab489a01cc6cb998e788875f8bd56a Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Tue, 15 Oct 2024 09:00:34 +0200 Subject: [PATCH 17/24] Move grid measurement helpers together into component --- .../canvas/controls/grid-controls.tsx | 83 ++++++++++++------- .../canvas/controls/new-canvas-controls.tsx | 25 +----- 2 files changed, 57 insertions(+), 51 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index e7fba4c0d0b3..ddd923db8cbd 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -11,7 +11,10 @@ import { MetadataUtils } from '../../../core/model/element-metadata-utils' import { mapDropNulls, range, stripNulls, uniqBy } from '../../../core/shared/array-utils' import { defaultEither } from '../../../core/shared/either' import * as EP from '../../../core/shared/element-path' -import type { GridAutoOrTemplateDimensions } from '../../../core/shared/element-template' +import type { + ElementInstanceMetadataMap, + GridAutoOrTemplateDimensions, +} from '../../../core/shared/element-template' import { isGridAutoOrTemplateDimensions, type GridAutoOrTemplateBase, @@ -927,7 +930,25 @@ const GridControl = React.memo(({ grid }) => { }) GridControl.displayName = 'GridControl' -export const GridMeasurementHelper = React.memo((props) => { +export const GridMeasurementHelpers = React.memo(() => { + const metadata = useEditorState( + Substores.metadata, + (store) => store.editor.jsxMetadata, + 'GridMeasurementHelpers metadata', + ) + + const grids = useAllGrids(metadata) + + return ( + + {grids.map((grid) => { + return + })} + + ) +}) + +const GridMeasurementHelper = React.memo((props) => { const placeholders = range(0, props.cells) let style: CSSProperties = { @@ -967,32 +988,30 @@ export const GridMeasurementHelper = React.memo((props) => { } return ( - -
- {placeholders.map((cell) => { - const countedRow = Math.floor(cell / props.columns) + 1 - const countedColumn = Math.floor(cell % props.columns) + 1 - const id = `grid-measurement-helper-${EP.toString( - props.elementPath, - )}-${countedRow}-${countedColumn}` - return ( -
- ) - })} -
- +
+ {placeholders.map((cell) => { + const countedRow = Math.floor(cell / props.columns) + 1 + const countedColumn = Math.floor(cell % props.columns) + 1 + const id = `grid-measurement-helper-${EP.toString( + props.elementPath, + )}-${countedRow}-${countedColumn}` + return ( +
+ ) + })} +
) }) GridMeasurementHelper.displayName = 'GridMeasurementHelper' @@ -1663,3 +1682,11 @@ function gridPlaceholderTopOrLeftPosition(scale: number): string { function gridPlaceholderWidthOrHeight(scale: number): string { return `calc(100% + ${(borderExtension * 2) / scale}px)` } + +function useAllGrids(metadata: ElementInstanceMetadataMap) { + const grids = React.useMemo(() => { + return MetadataUtils.getAllGrids(metadata) + }, [metadata]) + + return useGridData(grids) +} diff --git a/editor/src/components/canvas/controls/new-canvas-controls.tsx b/editor/src/components/canvas/controls/new-canvas-controls.tsx index ae24b7bd7c00..344d57ed840d 100644 --- a/editor/src/components/canvas/controls/new-canvas-controls.tsx +++ b/editor/src/components/canvas/controls/new-canvas-controls.tsx @@ -75,8 +75,7 @@ import { NO_OP } from '../../../core/shared/utils' import { useIsMyProject } from '../../editor/store/collaborative-editing' import { MultiplayerWrapper } from '../../../utils/multiplayer-wrapper' import { MultiplayerPresence } from '../multiplayer-presence' -import { GridMeasurementHelper } from './grid-controls' -import { GridControlKey, useGridData } from './grid-controls-for-strategies' +import { GridMeasurementHelpers } from './grid-controls' export const CanvasControlsContainerID = 'new-canvas-controls-container' @@ -341,8 +340,6 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => { 'NewCanvasControlsInner', ) - const grids = useAllGrids(componentMetadata) - const cmdKeyPressed = keysPressed['cmd'] ?? false const contextMenuEnabled = !isLiveMode(editorMode) @@ -603,16 +600,7 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => { <> {when( isSelectMode(editorMode) || isInsertMode(editorMode), - - {grids.map((grid) => { - return ( - - ) - })} - , + , )} {strategyControls.map((c) => ( { - return MetadataUtils.getAllGrids(metadata) - }, [metadata]) - - return useGridData(grids) -} - SelectionAreaRectangle.displayName = 'SelectionAreaRectangle' From 586676549402eb763ac73ea90c346d28a4ec5452 Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Tue, 15 Oct 2024 09:10:38 +0200 Subject: [PATCH 18/24] Added missing displayName --- editor/src/components/canvas/controls/grid-controls.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index ddd923db8cbd..c703259ab76b 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -947,6 +947,7 @@ export const GridMeasurementHelpers = React.memo(() => { ) }) +GridMeasurementHelpers.displayName = 'GridMeasurementHelpers' const GridMeasurementHelper = React.memo((props) => { const placeholders = range(0, props.cells) From d14e7df163488b50f75f5d7da364761470f878ae Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Tue, 15 Oct 2024 15:33:37 +0200 Subject: [PATCH 19/24] Restrict GridMeasurmentHelper prop type --- .../controls/grid-controls-for-strategies.tsx | 49 ++++++++++++ .../canvas/controls/grid-controls.tsx | 80 ++++++++++++------- ...performance-regression-tests.spec.tsx.snap | 28 ++++--- .../performance-regression-tests.spec.tsx | 8 +- 4 files changed, 121 insertions(+), 44 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx b/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx index e93dc309cd2c..9993782443a1 100644 --- a/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx +++ b/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx @@ -27,6 +27,7 @@ import { } from '../canvas-types' import { GridControlsComponent, + type GridMeasurementHelperProps, GridResizeControlsComponent, GridRowColumnResizingControlsComponent, } from './grid-controls' @@ -80,6 +81,54 @@ export type GridData = { metadata: ElementInstanceMetadata } +export function useGridMeasurentHelperData( + elementPath: ElementPath, +): GridMeasurementHelperProps | null { + const grid = useEditorState( + Substores.metadata, + (store) => { + const element = MetadataUtils.findElementByElementPath(store.editor.jsxMetadata, elementPath) + + const targetGridContainer = MetadataUtils.isGridLayoutedContainer(element) ? element : null + + if ( + targetGridContainer == null || + targetGridContainer.globalFrame == null || + !isFiniteRectangle(targetGridContainer.globalFrame) + ) { + return null + } + + const columns = getCellsCount( + targetGridContainer.specialSizeMeasurements.containerGridProperties.gridTemplateColumns, + ) + const rows = getCellsCount( + targetGridContainer.specialSizeMeasurements.containerGridProperties.gridTemplateRows, + ) + + return { + elementPath: targetGridContainer.elementPath, + frame: targetGridContainer.globalFrame, + gridTemplateColumns: + targetGridContainer.specialSizeMeasurements.containerGridProperties.gridTemplateColumns, + gridTemplateRows: + targetGridContainer.specialSizeMeasurements.containerGridProperties.gridTemplateRows, + gap: targetGridContainer.specialSizeMeasurements.gap, + rowGap: targetGridContainer.specialSizeMeasurements.rowGap, + columnGap: targetGridContainer.specialSizeMeasurements.columnGap, + justifyContent: targetGridContainer.specialSizeMeasurements.justifyContent, + alignContent: targetGridContainer.specialSizeMeasurements.alignContent, + padding: targetGridContainer.specialSizeMeasurements.padding, + columns: columns, + cells: rows * columns, + } + }, + 'useGridMeasurentHelperData', + ) + + return grid +} + export function useGridData(elementPaths: ElementPath[]): GridData[] { const grids = useEditorState( Substores.metadata, diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index c703259ab76b..4383067fa4c8 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -82,6 +82,7 @@ import { GridControlKey, gridEdgeToEdgePosition, useGridData, + useGridMeasurentHelperData, } from './grid-controls-for-strategies' import { useMaybeHighlightElement } from './select-mode/select-mode-hooks' import { useResizeEdges } from './select-mode/use-resize-edges' @@ -942,63 +943,84 @@ export const GridMeasurementHelpers = React.memo(() => { return ( {grids.map((grid) => { - return + return })} ) }) GridMeasurementHelpers.displayName = 'GridMeasurementHelpers' -const GridMeasurementHelper = React.memo((props) => { - const placeholders = range(0, props.cells) +export interface GridMeasurementHelperProps { + elementPath: ElementPath + frame: CanvasRectangle + gridTemplateColumns: GridAutoOrTemplateBase | null + gridTemplateRows: GridAutoOrTemplateBase | null + gap: number | null + justifyContent: string | null + alignContent: string | null + rowGap: number | null + columnGap: number | null + padding: Sides + columns: number + cells: number +} + +const GridMeasurementHelper = React.memo<{ elementPath: ElementPath }>(({ elementPath }) => { + const grid = useGridMeasurentHelperData(elementPath) + + if (grid == null) { + return null + } + + const placeholders = range(0, grid.cells) let style: CSSProperties = { position: 'absolute', - top: props.frame.y, - left: props.frame.x, - width: props.frame.width, - height: props.frame.height, + top: grid.frame.y, + left: grid.frame.x, + width: grid.frame.width, + height: grid.frame.height, display: 'grid', - gridTemplateColumns: getNullableAutoOrTemplateBaseString(props.gridTemplateColumns), - gridTemplateRows: getNullableAutoOrTemplateBaseString(props.gridTemplateRows), - justifyContent: props.justifyContent ?? 'initial', - alignContent: props.alignContent ?? 'initial', + gridTemplateColumns: getNullableAutoOrTemplateBaseString(grid.gridTemplateColumns), + gridTemplateRows: getNullableAutoOrTemplateBaseString(grid.gridTemplateRows), + justifyContent: grid.justifyContent ?? 'initial', + alignContent: grid.alignContent ?? 'initial', pointerEvents: 'none', padding: - props.padding == null + grid.padding == null ? 0 - : `${props.padding.top}px ${props.padding.right}px ${props.padding.bottom}px ${props.padding.left}px`, + : `${grid.padding.top}px ${grid.padding.right}px ${grid.padding.bottom}px ${grid.padding.left}px`, opacity: 1, } // Gap needs to be set only if the other two are not present or we'll have rendering issues // due to how measurements are calculated. - if (props.rowGap != null && props.columnGap != null) { - style.rowGap = props.rowGap - style.columnGap = props.columnGap + if (grid.rowGap != null && grid.columnGap != null) { + style.rowGap = grid.rowGap + style.columnGap = grid.columnGap } else { - if (props.gap != null) { - style.gap = props.gap + if (grid.gap != null) { + style.gap = grid.gap } - if (props.rowGap != null) { - style.rowGap = props.rowGap + if (grid.rowGap != null) { + style.rowGap = grid.rowGap } - if (props.columnGap != null) { - style.columnGap = props.columnGap + if (grid.columnGap != null) { + style.columnGap = grid.columnGap } } return (
{placeholders.map((cell) => { - const countedRow = Math.floor(cell / props.columns) + 1 - const countedColumn = Math.floor(cell % props.columns) + 1 + const countedRow = Math.floor(cell / grid.columns) + 1 + const countedColumn = Math.floor(cell % grid.columns) + 1 const id = `grid-measurement-helper-${EP.toString( - props.elementPath, + grid.elementPath, )}-${countedRow}-${countedColumn}` return (
{ + return React.useMemo(() => { return MetadataUtils.getAllGrids(metadata) }, [metadata]) - - return useGridData(grids) } diff --git a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap index 89a3488776c2..61e602e6e233 100644 --- a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap +++ b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap @@ -32,7 +32,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", - "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(GridMeasurementHelpers)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", @@ -54,6 +54,8 @@ Array [ "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/GridMeasurementHelpers/Symbol(react.memo)()", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/GridMeasurementHelpers//div", "/null/Symbol(react.memo)()//Symbol(react.memo)()", "/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))", "/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))", @@ -813,7 +815,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", - "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(GridMeasurementHelpers)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", @@ -835,6 +837,8 @@ Array [ "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/GridMeasurementHelpers/Symbol(react.memo)()", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/GridMeasurementHelpers//div", "/null/Symbol(react.memo)()//Symbol(react.memo)()", "/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))", "/Symbol(react.memo)()///Symbol(react.memo)(Symbol(react.forward_ref)(ResizeEdge))", @@ -1483,7 +1487,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", - "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(GridMeasurementHelpers)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", @@ -1773,7 +1777,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", - "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(GridMeasurementHelpers)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", @@ -1785,6 +1789,8 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(SelectionAreaRectangle)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/GridMeasurementHelpers/Symbol(react.memo)()", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/GridMeasurementHelpers//div", "/div/Symbol(react.memo)(Symbol(react.forward_ref)(SizeLabel))/Symbol(react.forward_ref)(SizeLabel)/div:data-testid='SizeLabelTestId'", "/div/Symbol(react.memo)(Symbol(react.forward_ref)(SizeLabel))/Symbol(react.forward_ref)(SizeLabel)/div:data-testid='parent-resize-label'", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", @@ -2375,7 +2381,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", - "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(GridMeasurementHelpers)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", @@ -2483,7 +2489,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", - "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(GridMeasurementHelpers)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", @@ -2602,7 +2608,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", - "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(GridMeasurementHelpers)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", @@ -2880,7 +2886,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", - "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(GridMeasurementHelpers)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", @@ -2892,6 +2898,8 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(SelectionAreaRectangle)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/GridMeasurementHelpers/Symbol(react.memo)()", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/GridMeasurementHelpers//div", "/div/Symbol(react.memo)(Symbol(react.forward_ref)(SizeLabel))/Symbol(react.forward_ref)(SizeLabel)/div:data-testid='SizeLabelTestId'", "/div/Symbol(react.memo)(Symbol(react.forward_ref)(SizeLabel))/Symbol(react.forward_ref)(SizeLabel)/div:data-testid='parent-resize-label'", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", @@ -3358,7 +3366,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", - "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(GridMeasurementHelpers)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", @@ -3408,7 +3416,7 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", - "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(GridMeasurementHelpers)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", diff --git a/editor/src/core/performance/performance-regression-tests.spec.tsx b/editor/src/core/performance/performance-regression-tests.spec.tsx index 1cc6f4f93750..435dc603ed7f 100644 --- a/editor/src/core/performance/performance-regression-tests.spec.tsx +++ b/editor/src/core/performance/performance-regression-tests.spec.tsx @@ -65,7 +65,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`862`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`864`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -127,7 +127,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`1114`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`1116`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -183,7 +183,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`651`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`653`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -249,7 +249,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`776`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`778`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) }) From 06aff88313989f6aeb27ed29d03a1b101964cf0d Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:06:47 +0200 Subject: [PATCH 20/24] fastDeepEqual hack --- .../controls/grid-controls-for-strategies.tsx | 12 ++-- .../canvas/controls/grid-controls.tsx | 65 ++++++++----------- 2 files changed, 31 insertions(+), 46 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx b/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx index 9993782443a1..d554c34d3bac 100644 --- a/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx +++ b/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx @@ -1,5 +1,6 @@ /** @jsxRuntime classic */ /** @jsx jsx */ +import fastDeepEqual from 'fast-deep-equal' import type { Sides } from 'utopia-api/core' import type { ElementPath } from 'utopia-shared/src/types' import { isStaticGridRepeat, printGridAutoOrTemplateBase } from '../../inspector/common/css-utils' @@ -27,7 +28,6 @@ import { } from '../canvas-types' import { GridControlsComponent, - type GridMeasurementHelperProps, GridResizeControlsComponent, GridRowColumnResizingControlsComponent, } from './grid-controls' @@ -81,10 +81,8 @@ export type GridData = { metadata: ElementInstanceMetadata } -export function useGridMeasurentHelperData( - elementPath: ElementPath, -): GridMeasurementHelperProps | null { - const grid = useEditorState( +export function useGridMeasurentHelperData(elementPath: ElementPath) { + return useEditorState( Substores.metadata, (store) => { const element = MetadataUtils.findElementByElementPath(store.editor.jsxMetadata, elementPath) @@ -107,7 +105,6 @@ export function useGridMeasurentHelperData( ) return { - elementPath: targetGridContainer.elementPath, frame: targetGridContainer.globalFrame, gridTemplateColumns: targetGridContainer.specialSizeMeasurements.containerGridProperties.gridTemplateColumns, @@ -124,9 +121,8 @@ export function useGridMeasurentHelperData( } }, 'useGridMeasurentHelperData', + fastDeepEqual, ) - - return grid } export function useGridData(elementPaths: ElementPath[]): GridData[] { diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index 4383067fa4c8..5df7424b2d46 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -952,75 +952,64 @@ GridMeasurementHelpers.displayName = 'GridMeasurementHelpers' export interface GridMeasurementHelperProps { elementPath: ElementPath - frame: CanvasRectangle - gridTemplateColumns: GridAutoOrTemplateBase | null - gridTemplateRows: GridAutoOrTemplateBase | null - gap: number | null - justifyContent: string | null - alignContent: string | null - rowGap: number | null - columnGap: number | null - padding: Sides - columns: number - cells: number } const GridMeasurementHelper = React.memo<{ elementPath: ElementPath }>(({ elementPath }) => { - const grid = useGridMeasurentHelperData(elementPath) + const gridData = useGridMeasurentHelperData(elementPath) - if (grid == null) { + if (gridData == null) { return null } - const placeholders = range(0, grid.cells) + const placeholders = range(0, gridData.cells) let style: CSSProperties = { position: 'absolute', - top: grid.frame.y, - left: grid.frame.x, - width: grid.frame.width, - height: grid.frame.height, + top: gridData.frame.y, + left: gridData.frame.x, + width: gridData.frame.width, + height: gridData.frame.height, display: 'grid', - gridTemplateColumns: getNullableAutoOrTemplateBaseString(grid.gridTemplateColumns), - gridTemplateRows: getNullableAutoOrTemplateBaseString(grid.gridTemplateRows), - justifyContent: grid.justifyContent ?? 'initial', - alignContent: grid.alignContent ?? 'initial', + gridTemplateColumns: getNullableAutoOrTemplateBaseString(gridData.gridTemplateColumns), + gridTemplateRows: getNullableAutoOrTemplateBaseString(gridData.gridTemplateRows), + justifyContent: gridData.justifyContent ?? 'initial', + alignContent: gridData.alignContent ?? 'initial', pointerEvents: 'none', padding: - grid.padding == null + gridData.padding == null ? 0 - : `${grid.padding.top}px ${grid.padding.right}px ${grid.padding.bottom}px ${grid.padding.left}px`, + : `${gridData.padding.top}px ${gridData.padding.right}px ${gridData.padding.bottom}px ${gridData.padding.left}px`, opacity: 1, } // Gap needs to be set only if the other two are not present or we'll have rendering issues // due to how measurements are calculated. - if (grid.rowGap != null && grid.columnGap != null) { - style.rowGap = grid.rowGap - style.columnGap = grid.columnGap + if (gridData.rowGap != null && gridData.columnGap != null) { + style.rowGap = gridData.rowGap + style.columnGap = gridData.columnGap } else { - if (grid.gap != null) { - style.gap = grid.gap + if (gridData.gap != null) { + style.gap = gridData.gap } - if (grid.rowGap != null) { - style.rowGap = grid.rowGap + if (gridData.rowGap != null) { + style.rowGap = gridData.rowGap } - if (grid.columnGap != null) { - style.columnGap = grid.columnGap + if (gridData.columnGap != null) { + style.columnGap = gridData.columnGap } } return (
{placeholders.map((cell) => { - const countedRow = Math.floor(cell / grid.columns) + 1 - const countedColumn = Math.floor(cell % grid.columns) + 1 + const countedRow = Math.floor(cell / gridData.columns) + 1 + const countedColumn = Math.floor(cell % gridData.columns) + 1 const id = `grid-measurement-helper-${EP.toString( - grid.elementPath, + elementPath, )}-${countedRow}-${countedColumn}` return (
Date: Tue, 15 Oct 2024 16:08:11 +0200 Subject: [PATCH 21/24] Added comment --- .../components/canvas/controls/grid-controls-for-strategies.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx b/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx index d554c34d3bac..72e1813dea3a 100644 --- a/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx +++ b/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx @@ -121,7 +121,7 @@ export function useGridMeasurentHelperData(elementPath: ElementPath) { } }, 'useGridMeasurentHelperData', - fastDeepEqual, + fastDeepEqual, //TODO: this should not be needed, but it seems EditorStateKeepDeepEquality is not running, and metadata reference is always updated ) } From d6530e5752cfa81ca2e1324a5a97a362cd8496ef Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:24:07 +0200 Subject: [PATCH 22/24] Remove magic constant --- .../canvas/controls/grid-controls-for-strategies.tsx | 5 +++++ .../src/components/canvas/controls/grid-controls.tsx | 10 +++++----- editor/src/components/canvas/dom-walker.ts | 5 ++++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx b/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx index 72e1813dea3a..3a18c35cc2c1 100644 --- a/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx +++ b/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx @@ -203,6 +203,11 @@ export const GridRowColumnResizingControls = export const GridControlsKey = (gridPath: ElementPath) => `grid-controls-${EP.toString(gridPath)}` export const GridControlKey = (gridPath: ElementPath) => `grid-control-${EP.toString(gridPath)}` +export const GridMeasurementHelpersKey = (gridPath: ElementPath) => + `grid-measurement-helpers-${EP.toString(gridPath)}` +export const GridMeasurementHelperKey = (gridPath: ElementPath) => + `grid-measurement-helper-${EP.toString(gridPath)}` + export interface GridControlProps { grid: GridData } diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index 5df7424b2d46..c2010e74ec36 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -81,6 +81,8 @@ import { GridCellTestId, GridControlKey, gridEdgeToEdgePosition, + GridMeasurementHelperKey, + GridMeasurementHelpersKey, useGridData, useGridMeasurentHelperData, } from './grid-controls-for-strategies' @@ -943,7 +945,7 @@ export const GridMeasurementHelpers = React.memo(() => { return ( {grids.map((grid) => { - return + return })} ) @@ -1001,16 +1003,14 @@ const GridMeasurementHelper = React.memo<{ elementPath: ElementPath }>(({ elemen return (
{placeholders.map((cell) => { const countedRow = Math.floor(cell / gridData.columns) + 1 const countedColumn = Math.floor(cell % gridData.columns) + 1 - const id = `grid-measurement-helper-${EP.toString( - elementPath, - )}-${countedRow}-${countedColumn}` + const id = `${GridMeasurementHelperKey(elementPath)}-${countedRow}-${countedColumn}` return (
> | null = null if (path != null) { - const gridControlElement = document.getElementById(`grid-measurement-helper-${path}`) + const gridControlElement = document.getElementById( + GridMeasurementHelperKey(EP.fromString(path)), + ) if (gridControlElement != null) { gridCellGlobalFrames = [] for (const cell of gridControlElement.children) { From 5e69431527a66521a56cce0847b25b65aa6b96b3 Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:43:59 +0200 Subject: [PATCH 23/24] Small refactor to remove duplicated code --- .../controls/grid-controls-for-strategies.tsx | 24 ++-- .../canvas/controls/grid-controls.tsx | 110 +++++++----------- 2 files changed, 59 insertions(+), 75 deletions(-) diff --git a/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx b/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx index 3a18c35cc2c1..5d6fd793dfe5 100644 --- a/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx +++ b/editor/src/components/canvas/controls/grid-controls-for-strategies.tsx @@ -62,26 +62,23 @@ export function getNullableAutoOrTemplateBaseString( } } -export type GridData = { - elementPath: ElementPath +export type GridMeasurementHelperData = { frame: CanvasRectangle gridTemplateColumns: GridAutoOrTemplateBase | null gridTemplateRows: GridAutoOrTemplateBase | null - gridTemplateColumnsFromProps: GridAutoOrTemplateBase | null - gridTemplateRowsFromProps: GridAutoOrTemplateBase | null gap: number | null - justifyContent: string | null - alignContent: string | null rowGap: number | null columnGap: number | null + justifyContent: string | null + alignContent: string | null padding: Sides - rows: number columns: number cells: number - metadata: ElementInstanceMetadata } -export function useGridMeasurentHelperData(elementPath: ElementPath) { +export function useGridMeasurentHelperData( + elementPath: ElementPath, +): GridMeasurementHelperData | null { return useEditorState( Substores.metadata, (store) => { @@ -125,6 +122,15 @@ export function useGridMeasurentHelperData(elementPath: ElementPath) { ) } +export type GridData = GridMeasurementHelperData & { + elementPath: ElementPath + gridTemplateColumnsFromProps: GridAutoOrTemplateBase | null + gridTemplateRowsFromProps: GridAutoOrTemplateBase | null + rows: number + cells: number + metadata: ElementInstanceMetadata +} + export function useGridData(elementPaths: ElementPath[]): GridData[] { const grids = useEditorState( Substores.metadata, diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index c2010e74ec36..80f85c6ccf4d 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -770,44 +770,14 @@ const GridControl = React.memo(({ grid }) => { }) const placeholders = range(0, grid.cells) - let style: CSSProperties = { - position: 'absolute', - top: grid.frame.y, - left: grid.frame.x, - width: grid.frame.width, - height: grid.frame.height, - display: 'grid', - gridTemplateColumns: getNullableAutoOrTemplateBaseString(grid.gridTemplateColumns), - gridTemplateRows: getNullableAutoOrTemplateBaseString(grid.gridTemplateRows), + + const style: CSSProperties = { + ...getGridControlBaseStyle(grid), backgroundColor: activelyDraggingOrResizingCell != null ? colorTheme.primary10.value : 'transparent', outline: `1px solid ${ activelyDraggingOrResizingCell != null ? colorTheme.primary.value : 'transparent' }`, - justifyContent: grid.justifyContent ?? 'initial', - alignContent: grid.alignContent ?? 'initial', - pointerEvents: 'none', - padding: - grid.padding == null - ? 0 - : `${grid.padding.top}px ${grid.padding.right}px ${grid.padding.bottom}px ${grid.padding.left}px`, - } - - // Gap needs to be set only if the other two are not present or we'll have rendering issues - // due to how measurements are calculated. - if (grid.rowGap != null && grid.columnGap != null) { - style.rowGap = grid.rowGap - style.columnGap = grid.columnGap - } else { - if (grid.gap != null) { - style.gap = grid.gap - } - if (grid.rowGap != null) { - style.rowGap = grid.rowGap - } - if (grid.columnGap != null) { - style.columnGap = grid.columnGap - } } return ( @@ -965,42 +935,11 @@ const GridMeasurementHelper = React.memo<{ elementPath: ElementPath }>(({ elemen const placeholders = range(0, gridData.cells) - let style: CSSProperties = { - position: 'absolute', - top: gridData.frame.y, - left: gridData.frame.x, - width: gridData.frame.width, - height: gridData.frame.height, - display: 'grid', - gridTemplateColumns: getNullableAutoOrTemplateBaseString(gridData.gridTemplateColumns), - gridTemplateRows: getNullableAutoOrTemplateBaseString(gridData.gridTemplateRows), - justifyContent: gridData.justifyContent ?? 'initial', - alignContent: gridData.alignContent ?? 'initial', - pointerEvents: 'none', - padding: - gridData.padding == null - ? 0 - : `${gridData.padding.top}px ${gridData.padding.right}px ${gridData.padding.bottom}px ${gridData.padding.left}px`, + const style: CSSProperties = { + ...getGridControlBaseStyle(gridData), opacity: 1, } - // Gap needs to be set only if the other two are not present or we'll have rendering issues - // due to how measurements are calculated. - if (gridData.rowGap != null && gridData.columnGap != null) { - style.rowGap = gridData.rowGap - style.columnGap = gridData.columnGap - } else { - if (gridData.gap != null) { - style.gap = gridData.gap - } - if (gridData.rowGap != null) { - style.rowGap = gridData.rowGap - } - if (gridData.columnGap != null) { - style.columnGap = gridData.columnGap - } - } - return (
Date: Tue, 15 Oct 2024 17:13:30 +0200 Subject: [PATCH 24/24] Fix compile error --- editor/src/components/canvas/controls/grid-controls.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index 80f85c6ccf4d..9393c96963bb 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -74,7 +74,11 @@ import { windowToCanvasCoordinates } from '../dom-lookup' import type { Axis } from '../gap-utils' import { useCanvasAnimation } from '../ui-jsx-canvas-renderer/animation-context' import { CanvasOffsetWrapper } from './canvas-offset-wrapper' -import type { GridControlsProps, GridData } from './grid-controls-for-strategies' +import type { + GridControlsProps, + GridData, + GridMeasurementHelperData, +} from './grid-controls-for-strategies' import { edgePositionToGridResizeEdge, getNullableAutoOrTemplateBaseString,