diff --git a/editor/karma-base.conf.js b/editor/karma-base.conf.js index b7ae2e81309b..95410c01b8d4 100644 --- a/editor/karma-base.conf.js +++ b/editor/karma-base.conf.js @@ -54,7 +54,8 @@ module.exports = function (config) { // list of files / patterns to load in the browser files: [ './mocha-setup-beforeall.js', - './karma-setup.js', + './karma-setup.js', // this must run before importing the editor-entry-point-imports module + './src/templates/editor-entry-point-imports.tsx', // we load the real editor entry point first, to make sure the environment matches the real environment, and also to avoid diverging circular dependencies { pattern: './resources/editor/**/*.png', watched: false, @@ -62,8 +63,16 @@ module.exports = function (config) { included: false, nocache: false, }, + { + pattern: './resources/editor/**/*.css', + watched: false, + served: true, + included: false, + nocache: false, + }, ], proxies: { + '/editor/css/': '/base/resources/editor/css', '/editor/icons': '/base/resources/editor/icons', '/editor/cursors': '/base/resources/editor/cursors', '/editor/fills': '/base/resources/editor/fills', diff --git a/editor/karma-setup.js b/editor/karma-setup.js index e81eb48d4303..7aac2f522b49 100644 --- a/editor/karma-setup.js +++ b/editor/karma-setup.js @@ -18,6 +18,7 @@ ReactTestingLibrary.configure({ }, }) +// this must run before importing the editor-entry-point-imports module window.expect = expect window.jest = null window.KarmaTestEnvironment = true diff --git a/editor/package.json b/editor/package.json index ef1ed9c69c99..9a1a7dd2e06b 100644 --- a/editor/package.json +++ b/editor/package.json @@ -50,7 +50,7 @@ "lint-editor": "lint-staged", "dev-fast": "APP_ENV=development REACT_APP_ENVIRONMENT_CONFIG=development REACT_APP_AUTH0_CLIENT_ID=$AUTH0_CLIENT_ID REACT_APP_AUTH0_ENDPOINT=$AUTH0_ENDPOINT REACT_APP_AUTH0_REDIRECT_URI=$AUTH0_REDIRECT_URI REACT_APP_COMMIT_HASH=`git rev-parse HEAD` vite --force", "vite-build": "node --max_old_space_size=16384 ./node_modules/vite/bin/vite build -- -DEBUG", - "watch-tsc": "tsc --watch && NODE_OPTIONS=\"--max_old_space_size=4096 $NODE_OPENSSL_OPTION\"", + "watch-tsc": "tsc --watch --noEmit && NODE_OPTIONS=\"--max_old_space_size=4096 $NODE_OPENSSL_OPTION\"", "unused-exports": "ts-unused-exports ./tsconfig.json --ignoreLocallyUsed" }, "lint-staged": { diff --git a/editor/src/components/canvas/__snapshots__/ui-jsx-canvas-bugs.spec.tsx.snap b/editor/src/components/canvas/__snapshots__/ui-jsx-canvas-bugs.spec.tsx.snap index e82c1b649993..47314c6b6785 100644 --- a/editor/src/components/canvas/__snapshots__/ui-jsx-canvas-bugs.spec.tsx.snap +++ b/editor/src/components/canvas/__snapshots__/ui-jsx-canvas-bugs.spec.tsx.snap @@ -4,6 +4,7 @@ exports[`UiJsxCanvas #747 - DOM object constructor cannot be called as a functio "
{ const element = await renderResult.renderedDOM.findByTestId('flex-reparent-indicator-0') const bounds = element.getBoundingClientRect() - expect(bounds.left).toEqual(expectedLeft) - expect(bounds.top).toEqual(expectedTop) - expect(bounds.width).toEqual(expectedWidth) - expect(bounds.height).toEqual(expectedHeight) + const canvasBounds = boundingClientRectToCanvasRectangle(renderResult, bounds) + expect( + canvasBounds.x + (horizontal === 'horizontal' ? FlexReparentIndicatorSize / 2 : 0), + ).toEqual(expectedLeft) + expect(canvasBounds.y + (horizontal === 'vertical' ? FlexReparentIndicatorSize / 2 : 0)).toEqual( + expectedTop, + ) + expect(canvasBounds.width).toEqual(expectedWidth) + expect(canvasBounds.height).toEqual(expectedHeight) } describe('Reparent indicators', () => { @@ -2271,7 +2279,7 @@ describe('Reparent indicators', () => { await renderResult.getDispatchFollowUpActionsFinished() // Check the indicator presence and position. - await checkReparentIndicator(renderResult, 388, 610, 2, 123) + await checkReparentIndicator(renderResult, 0, 500, 2, 123, 'horizontal') expect(renderResult.getEditorState().editor.displayNoneInstances).toEqual([ EP.fromString('storyboard/scene/parentsibling/seconddiv'), ]) @@ -2317,7 +2325,7 @@ describe('Reparent indicators', () => { await renderResult.getDispatchFollowUpActionsFinished() // Check the indicator presence and position. - await checkReparentIndicator(renderResult, 788, 610, 2, 123) + await checkReparentIndicator(renderResult, 400, 500, 2, 123, 'horizontal') }) it(`shows the reparent indicator between two elements in a 'row' container`, async () => { @@ -2360,7 +2368,7 @@ describe('Reparent indicators', () => { await renderResult.getDispatchFollowUpActionsFinished() // Check the indicator presence and position. - await checkReparentIndicator(renderResult, 522, 610, 2, 123) + await checkReparentIndicator(renderResult, 134, 500, 2, 123, 'horizontal') }) it(`shows the reparent indicator between two elements in a 'row-reverse' container`, async () => { @@ -2403,7 +2411,7 @@ describe('Reparent indicators', () => { await renderResult.getDispatchFollowUpActionsFinished() // Check the indicator presence and position. - await checkReparentIndicator(renderResult, 654, 610, 2, 123) + await checkReparentIndicator(renderResult, 266, 500, 2, 123, 'horizontal') }) it(`shows the reparent indicator between the parent and the first element in a 'row' container with absolute siblings`, async () => { const renderResult = await renderTestEditorWithCode( @@ -2447,7 +2455,7 @@ describe('Reparent indicators', () => { await renderResult.getDispatchFollowUpActionsFinished() // Check the indicator presence and position. - await checkReparentIndicator(renderResult, 388, 110, 2, 40) + await checkReparentIndicator(renderResult, 0, 0, 2, 40, 'horizontal') }) it(`shows the reparent indicator between the parent and the last element in a 'row' container with absolute siblings`, async () => { const renderResult = await renderTestEditorWithCode( @@ -2491,7 +2499,7 @@ describe('Reparent indicators', () => { await renderResult.getDispatchFollowUpActionsFinished() // Check the indicator presence and position. - await checkReparentIndicator(renderResult, 438, 110, 2, 40) + await checkReparentIndicator(renderResult, 50, 0, 2, 40, 'horizontal') }) it(`shows the reparent indicator between the parent and the first element in a 'row-reverse' container with absolute siblings`, async () => { const renderResult = await renderTestEditorWithCode( @@ -2535,7 +2543,7 @@ describe('Reparent indicators', () => { await renderResult.getDispatchFollowUpActionsFinished() // Check the indicator presence and position. - await checkReparentIndicator(renderResult, 788, 110, 2, 40) + await checkReparentIndicator(renderResult, 400, 0, 2, 40, 'horizontal') }) it(`doesn't show the reparent indicator when there are no siblings`, async () => { const renderResult = await renderTestEditorWithCode( @@ -2764,6 +2772,6 @@ describe('Reparent indicators', () => { ), ]) expect(renderResult.getEditorState().editor.canvas.controls.parentOutlineHighlight).toBeNull() - await checkReparentIndicator(renderResult, 389, 227, 75, 2) + await checkReparentIndicator(renderResult, 0, 118, 75, 2, 'vertical') }) }) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/absolute-reparent-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/absolute-reparent-strategy.spec.browser2.tsx index bb41de686317..e0b6f200de40 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/absolute-reparent-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/absolute-reparent-strategy.spec.browser2.tsx @@ -50,6 +50,7 @@ import { import { queryHelpers } from '@testing-library/react' import { forceNotNull } from '../../../../core/shared/optional-utils' import { getDomRectCenter } from '../../../../core/shared/dom-utils' +import { boundingClientRectToCanvasRectangle } from '../../../../utils/utils.test-utils' interface CheckCursor { cursor: CSSCursor | null @@ -1040,10 +1041,14 @@ export var ${BakedInStoryboardVariableName} = (props) => { await dragElement(renderResult, 'ccc', dragDelta, emptyModifiers, null, async () => { const draggedElement = await renderResult.renderedDOM.findByTestId('ccc') const draggedElementBounds = draggedElement.getBoundingClientRect() - expect(draggedElementBounds.x).toEqual(1014) - expect(draggedElementBounds.y).toEqual(535) - expect(draggedElementBounds.width).toEqual(50) - expect(draggedElementBounds.height).toEqual(50) + const draggedElementCanvasBounds = boundingClientRectToCanvasRectangle( + renderResult, + draggedElementBounds, + ) + expect(draggedElementCanvasBounds.x).toEqual(625) + expect(draggedElementCanvasBounds.y).toEqual(425) + expect(draggedElementCanvasBounds.width).toEqual(50) + expect(draggedElementCanvasBounds.height).toEqual(50) }) await renderResult.getDispatchFollowUpActionsFinished() @@ -1157,10 +1162,14 @@ export var ${BakedInStoryboardVariableName} = (props) => { await dragElement(renderResult, 'ccc', dragDelta, emptyModifiers, null, async () => { const draggedElement = await renderResult.renderedDOM.findByTestId('ccc') const draggedElementBounds = draggedElement.getBoundingClientRect() - expect(draggedElementBounds.x).toEqual(1014) - expect(draggedElementBounds.y).toEqual(535) - expect(draggedElementBounds.width).toEqual(50) - expect(draggedElementBounds.height).toEqual(50) + const draggedElementCanvasBounds = boundingClientRectToCanvasRectangle( + renderResult, + draggedElementBounds, + ) + expect(draggedElementCanvasBounds.x).toEqual(625) + expect(draggedElementCanvasBounds.y).toEqual(425) + expect(draggedElementCanvasBounds.width).toEqual(50) + expect(draggedElementCanvasBounds.height).toEqual(50) }) await renderResult.getDispatchFollowUpActionsFinished() diff --git a/editor/src/components/canvas/canvas-strategies/strategies/draw-to-insert-text-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/draw-to-insert-text-strategy.spec.browser2.tsx index 846c9de4415c..2d0ebb1e7670 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/draw-to-insert-text-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/draw-to-insert-text-strategy.spec.browser2.tsx @@ -11,6 +11,7 @@ import { getPrintedUiJsCode, renderTestEditorWithCode, } from '../../../canvas/ui-jsx.test-utils' +import { CanvasContainerID } from '../../canvas-types' describe('draw-to-insert text', () => { describe('draw', () => { @@ -288,9 +289,13 @@ describe('draw-to-insert text', () => { await pressKey('t') await editor.getDispatchFollowUpActionsFinished() + const canvasRootElement = editor.renderedDOM + .getByTestId(CanvasContainerID) + .getBoundingClientRect() + const insideDiv = { - x: 500, - y: 500, + x: canvasRootElement.x + 120, + y: canvasRootElement.y + 400, } await mouseDragFromPointToPoint(canvasControlsLayer, insideDiv, { @@ -314,13 +319,13 @@ describe('draw-to-insert text', () => { import { Storyboard } from 'utopia-api' export var storyboard = ( - + { + async function checkInsertButtonPosition( + renderResult: EditorRenderResult, + buttonTestId: string, + expectedLeft: number, + expectedTop: number, + ): Promise { + const element = await renderResult.renderedDOM.findByTestId(buttonTestId) + const bounds = element.getBoundingClientRect() + + const canvasBounds = boundingClientRectToCanvasRectangle(renderResult, bounds) + + expect(canvasBounds.x + BlueDotSize / 2).toEqual(expectedLeft) + expect(canvasBounds.y + BlueDotSize / 2).toEqual(expectedTop) + } + it(`shows the buttons in the correct places for a flex container with a direction of 'row' that already has children`, async () => { const renderResult = await renderTestEditorWithCode( getProjectCode('row'), @@ -268,20 +295,24 @@ describe('Insertion Plus Button', () => { await act(() => renderResult.dispatch([selectComponents([targetPath], false)], false)) await renderResult.getDispatchFollowUpActionsFinished() - async function checkInsertButtonPosition( - buttonTestId: string, - expectedLeft: number, - expectedTop: number, - ): Promise { - const element = await renderResult.renderedDOM.findByTestId(buttonTestId) - const bounds = element.getBoundingClientRect() - expect(bounds.left).toEqual(expectedLeft) - expect(bounds.top).toEqual(expectedTop) - } - - await checkInsertButtonPosition('blue-dot-control-0', 385.5, 596.5) - await checkInsertButtonPosition('blue-dot-control-1', 519.5, 596.5) - await checkInsertButtonPosition('blue-dot-control-2', 712.5, 596.5) + await checkInsertButtonPosition( + renderResult, + 'blue-dot-control-0', + 0, + 500 - InsertionButtonOffset, + ) + await checkInsertButtonPosition( + renderResult, + 'blue-dot-control-1', + 134, + 500 - InsertionButtonOffset, + ) + await checkInsertButtonPosition( + renderResult, + 'blue-dot-control-2', + 327, + 500 - InsertionButtonOffset, + ) }) it(`shows the buttons in the correct places for a flex container with a direction of 'row-reverse' that already has children`, async () => { @@ -294,20 +325,24 @@ describe('Insertion Plus Button', () => { await act(() => renderResult.dispatch([selectComponents([targetPath], false)], false)) await renderResult.getDispatchFollowUpActionsFinished() - async function checkInsertButtonPosition( - buttonTestId: string, - expectedLeft: number, - expectedTop: number, - ): Promise { - const element = await renderResult.renderedDOM.findByTestId(buttonTestId) - const bounds = element.getBoundingClientRect() - expect(bounds.left).toEqual(expectedLeft) - expect(bounds.top).toEqual(expectedTop) - } - - await checkInsertButtonPosition('blue-dot-control-0', 785.5, 596.5) - await checkInsertButtonPosition('blue-dot-control-1', 651.5, 596.5) - await checkInsertButtonPosition('blue-dot-control-2', 458.5, 596.5) + await checkInsertButtonPosition( + renderResult, + 'blue-dot-control-0', + 400, + 500 - InsertionButtonOffset, + ) + await checkInsertButtonPosition( + renderResult, + 'blue-dot-control-1', + 266, + 500 - InsertionButtonOffset, + ) + await checkInsertButtonPosition( + renderResult, + 'blue-dot-control-2', + 73, + 500 - InsertionButtonOffset, + ) }) it(`shows the buttons in the correct places for a flex container with a direction of 'column' that already has children`, async () => { @@ -320,20 +355,24 @@ describe('Insertion Plus Button', () => { await act(() => renderResult.dispatch([selectComponents([targetPath], false)], false)) await renderResult.getDispatchFollowUpActionsFinished() - async function checkInsertButtonPosition( - buttonTestId: string, - expectedLeft: number, - expectedTop: number, - ): Promise { - const element = await renderResult.renderedDOM.findByTestId(buttonTestId) - const bounds = element.getBoundingClientRect() - expect(bounds.left).toEqual(expectedLeft) - expect(bounds.top).toEqual(expectedTop) - } - - await checkInsertButtonPosition('blue-dot-control-0', 375.5, 606.5) - await checkInsertButtonPosition('blue-dot-control-1', 375.5, 706.5) - await checkInsertButtonPosition('blue-dot-control-2', 375.5, 806.5) + await checkInsertButtonPosition( + renderResult, + 'blue-dot-control-0', + 0 - InsertionButtonOffset, + 500, + ) + await checkInsertButtonPosition( + renderResult, + 'blue-dot-control-1', + 0 - InsertionButtonOffset, + 600, + ) + await checkInsertButtonPosition( + renderResult, + 'blue-dot-control-2', + 0 - InsertionButtonOffset, + 700, + ) }) it(`shows the buttons in the correct places for a flex container with a direction of 'column-reverse' that already has children`, async () => { @@ -346,20 +385,24 @@ describe('Insertion Plus Button', () => { await act(() => renderResult.dispatch([selectComponents([targetPath], false)], false)) await renderResult.getDispatchFollowUpActionsFinished() - async function checkInsertButtonPosition( - buttonTestId: string, - expectedLeft: number, - expectedTop: number, - ): Promise { - const element = await renderResult.renderedDOM.findByTestId(buttonTestId) - const bounds = element.getBoundingClientRect() - expect(bounds.left).toEqual(expectedLeft) - expect(bounds.top).toEqual(expectedTop) - } - - await checkInsertButtonPosition('blue-dot-control-0', 375.5, 806.5) - await checkInsertButtonPosition('blue-dot-control-1', 375.5, 706.5) - await checkInsertButtonPosition('blue-dot-control-2', 375.5, 606.5) + await checkInsertButtonPosition( + renderResult, + 'blue-dot-control-0', + 0 - InsertionButtonOffset, + 700, + ) + await checkInsertButtonPosition( + renderResult, + 'blue-dot-control-1', + 0 - InsertionButtonOffset, + 600, + ) + await checkInsertButtonPosition( + renderResult, + 'blue-dot-control-2', + 0 - InsertionButtonOffset, + 500, + ) }) it('shows the buttons in the correct places for a flex container that has no children', async () => { @@ -372,17 +415,11 @@ describe('Insertion Plus Button', () => { await act(() => renderResult.dispatch([selectComponents([targetPath], false)], false)) await renderResult.getDispatchFollowUpActionsFinished() - async function checkInsertButtonPosition( - buttonTestId: string, - expectedLeft: number, - expectedTop: number, - ): Promise { - const element = await renderResult.renderedDOM.findByTestId(buttonTestId) - const bounds = element.getBoundingClientRect() - expect(bounds.left).toEqual(expectedLeft) - expect(bounds.top).toEqual(expectedTop) - } - - await checkInsertButtonPosition('blue-dot-control-0', 385.5, 596.5) + await checkInsertButtonPosition( + renderResult, + 'blue-dot-control-0', + 0, + 500 - InsertionButtonOffset, + ) }) }) diff --git a/editor/src/components/canvas/controls/insertion-plus-button.tsx b/editor/src/components/canvas/controls/insertion-plus-button.tsx index 896a1ef8423d..6552da2b1d34 100644 --- a/editor/src/components/canvas/controls/insertion-plus-button.tsx +++ b/editor/src/components/canvas/controls/insertion-plus-button.tsx @@ -15,7 +15,7 @@ import { } from '../canvas-strategies/strategies/reparent-helpers/reparent-strategy-sibling-position-helpers' import { CanvasOffsetWrapper } from './canvas-offset-wrapper' -const InsertionButtonOffset = 10 +export const InsertionButtonOffset = 10 interface ButtonControlProps { identifier: string @@ -203,9 +203,9 @@ const InsertionButtonContainer = React.memo((props: ButtonControlProps) => { ) }) +export const BlueDotSize = 7 const BlueDot = React.memo((props: ButtonControlProps) => { const colorTheme = useColorTheme() - const BlueDotSize = 7 return (
{ const scale = useEditorState( Substores.canvas, (store) => store.editor.canvas.scale, 'FlexReparentTargetIndicator scale', ) - const FlexReparentIndicatorSize = React.useMemo(() => 2 / scale, [scale]) + const flexReparentIndicatorScaledSize = React.useMemo( + () => FlexReparentIndicatorSize / scale, + [scale], + ) const reparentTargetLines = useEditorState( Substores.canvas, (store) => store.editor.canvas.controls.flexReparentTargetLines, @@ -19,8 +24,8 @@ export const FlexReparentTargetIndicator = controlForStrategyMemoized(() => { () => reparentTargetLines.every((line) => line.height === 0), [reparentTargetLines], ) - const positionOffsetX = isHorizontal ? 0 : -FlexReparentIndicatorSize / 2 - const positionOffsetY = isHorizontal ? -FlexReparentIndicatorSize / 2 : 0 + const positionOffsetX = isHorizontal ? 0 : -flexReparentIndicatorScaledSize / 2 + const positionOffsetY = isHorizontal ? -flexReparentIndicatorScaledSize / 2 : 0 return ( @@ -33,8 +38,8 @@ export const FlexReparentTargetIndicator = controlForStrategyMemoized(() => { position: 'absolute', left: line.x + positionOffsetX, top: line.y + positionOffsetY, - width: isHorizontal ? line.width : FlexReparentIndicatorSize, - height: !isHorizontal ? line.height : FlexReparentIndicatorSize, + width: isHorizontal ? line.width : flexReparentIndicatorScaledSize, + height: !isHorizontal ? line.height : flexReparentIndicatorScaledSize, backgroundColor: 'blue', }} >
diff --git a/editor/src/components/canvas/ui-jsx-canvas-bugs.spec.tsx b/editor/src/components/canvas/ui-jsx-canvas-bugs.spec.tsx index bf5d7f0e2680..6020e37ff142 100644 --- a/editor/src/components/canvas/ui-jsx-canvas-bugs.spec.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas-bugs.spec.tsx @@ -74,6 +74,7 @@ export var storyboard = ( "
{ "
{ "
{ "
{ "
{ "
{ "
{ "
{ "
{ shortcut?: string isSeparator?: boolean isHidden?: (data: T) => boolean - action: (data: T, dispatch?: EditorDispatch, event?: MouseEvent) => void + action: ( + data: T, + dispatch: EditorDispatch | undefined, + rightClickCoordinate: WindowPoint | null, + ) => void } export interface CanvasData { @@ -170,14 +173,14 @@ export const pasteHere: ContextMenuItem = { isHidden: (data: CanvasData) => { return data.contextMenuInstance === 'context-menu-navigator' }, - action: (data, dispatch?: EditorDispatch) => { - if (WindowMousePositionRaw == null) { + action: (data, dispatch: EditorDispatch | undefined, mouseWindowPosition: WindowPoint | null) => { + if (mouseWindowPosition == null) { return } const pointOnCanvas = windowToCanvasCoordinates( data.scale, data.canvasOffset, - WindowMousePositionRaw, + mouseWindowPosition, ).canvasPositionRaw const pasteHerePostActionData = { type: 'PASTE_HERE', diff --git a/editor/src/components/context-menu-wrapper.tsx b/editor/src/components/context-menu-wrapper.tsx index 8bc5a58c9f73..ca50fb765334 100644 --- a/editor/src/components/context-menu-wrapper.tsx +++ b/editor/src/components/context-menu-wrapper.tsx @@ -14,6 +14,8 @@ import { colorTheme, Icons } from '../uuiui' import { getControlStyles } from '../uuiui-deps' import type { ContextMenuItem } from './context-menu-items' import type { EditorDispatch } from './editor/action-types' +import type { WindowPoint } from '../core/shared/math-utils' +import { windowPoint } from '../core/shared/math-utils' export interface ContextMenuWrapperProps { id: string @@ -107,9 +109,15 @@ export class MomentumContextMenu extends ReactComponent> key={`context-menu-${index}-item`} disabled={this.isDisabled(item)} // eslint-disable-next-line react/jsx-no-bind - onClick={({ event }) => { + onClick={({ event, triggerEvent }) => { event.stopPropagation() - item.action(this.props.getData(), this.props.dispatch, (event as any)?.nativeEvent) + const rightClickCoordinate: WindowPoint | null = (() => { + if (!(triggerEvent instanceof MouseEvent)) { + return null + } + return windowPoint({ x: triggerEvent.clientX, y: triggerEvent.clientY }) + })() + item.action(this.props.getData(), this.props.dispatch, rightClickCoordinate) contextMenu.hideAll() }} hidden={this.isHidden(item)} diff --git a/editor/src/components/editor/actions/actions.spec.browser2.tsx b/editor/src/components/editor/actions/actions.spec.browser2.tsx index e64ca064b8c8..4950df6346d3 100644 --- a/editor/src/components/editor/actions/actions.spec.browser2.tsx +++ b/editor/src/components/editor/actions/actions.spec.browser2.tsx @@ -5374,7 +5374,7 @@ export var storyboard = ( style={{ position: 'absolute', bottom: 0, left: 0, right: 0, top: 0 }} /> -
+
) } @@ -5391,7 +5391,7 @@ export var storyboard = (
` const expectedDiv = ` -
+
` const renderResult = await renderTestEditorWithCode( makeTestProjectCodeWithSnippet(testCode('')), @@ -5526,7 +5526,7 @@ export var storyboard = (
-
+
) @@ -5666,7 +5666,7 @@ export var storyboard = (
preloadPrioritizedAssets()) + +import { addStyleSheetToPage } from '../core/shared/dom-utils' +import { STATIC_BASE_URL } from '../common/env-vars' + +const editorCSS = [ + `${STATIC_BASE_URL}editor/css/initial-load.css`, + `${STATIC_BASE_URL}editor/css/canvas.css`, + `${STATIC_BASE_URL}editor/css/slider.css`, + `${STATIC_BASE_URL}editor/css/ReactContexify.css`, + `${STATIC_BASE_URL}editor/css/codicons.css`, +] + +// Queue up further CSS downloads before going any further +editorCSS.forEach((url) => addStyleSheetToPage(url, true)) + +export { Editor } from './editor' +import { applyUIDMonkeyPatch } from '../utils/canvas-react-utils' + +applyUIDMonkeyPatch() diff --git a/editor/src/templates/editor-entry-point.tsx b/editor/src/templates/editor-entry-point.tsx index a851d8d972f5..aae2c55f19c9 100644 --- a/editor/src/templates/editor-entry-point.tsx +++ b/editor/src/templates/editor-entry-point.tsx @@ -1,41 +1,5 @@ -// import * as React from 'react' -// const whyDidYouRender = require('@welldone-software/why-did-you-render') -// whyDidYouRender(React, { -// trackAllPureComponents: true, -// }) - -import '../vite-shims' - -// import feature switches so they are loaded before anything else can read them -import { loadFeatureSwitches } from '../utils/feature-switches' -await loadFeatureSwitches() - -// Fire off server requests that later block, to improve initial load on slower connections. These will still block, -// but this gives us a chance to cache the result first -import { getLoginState } from '../common/server' -import { triggerHashedAssetsUpdate, preloadPrioritizedAssets } from '../utils/hashed-assets' - -void getLoginState('no-cache') -void triggerHashedAssetsUpdate().then(() => preloadPrioritizedAssets()) - -import { addStyleSheetToPage } from '../core/shared/dom-utils' -import { STATIC_BASE_URL } from '../common/env-vars' - -const editorCSS = [ - `${STATIC_BASE_URL}editor/css/initial-load.css`, - `${STATIC_BASE_URL}editor/css/canvas.css`, - `${STATIC_BASE_URL}editor/css/slider.css`, - `${STATIC_BASE_URL}editor/css/ReactContexify.css`, - `${STATIC_BASE_URL}editor/css/codicons.css`, -] - -// Queue up further CSS downloads before going any further -editorCSS.forEach((url) => addStyleSheetToPage(url, true)) - -import { Editor } from './editor' -import { applyUIDMonkeyPatch } from '../utils/canvas-react-utils' - -applyUIDMonkeyPatch() +import { Editor } from './editor-entry-point-imports' +// the constructor of the Editor class initializes all of Utopia // eslint-disable-next-line const EditorRunner = new Editor() diff --git a/editor/src/utils/utils.test-utils.tsx b/editor/src/utils/utils.test-utils.tsx index 2155ebf91a6e..1288978f3bba 100644 --- a/editor/src/utils/utils.test-utils.tsx +++ b/editor/src/utils/utils.test-utils.tsx @@ -55,8 +55,8 @@ import { } from '../core/shared/project-file-types' import { foldEither, right } from '../core/shared/either' import Utils from './utils' -import type { SimpleRectangle } from '../core/shared/math-utils' -import { canvasRectangle, localRectangle } from '../core/shared/math-utils' +import type { SimpleRectangle, WindowRectangle } from '../core/shared/math-utils' +import { canvasRectangle, localRectangle, negate, offsetRect } from '../core/shared/math-utils' import { createSceneUidFromIndex, BakedInStoryboardUID, @@ -78,6 +78,8 @@ import type { FeatureName } from './feature-switches' import { isFeatureEnabled, setFeatureEnabled } from './feature-switches' import { getUtopiaID } from '../core/shared/uid-utils' import { unpatchedCreateRemixDerivedDataMemo } from '../components/editor/store/remix-derived-data' +import { getCanvasRectangleFromElement } from '../core/shared/dom-utils' +import { CanvasContainerID } from '../components/canvas/canvas-types' export function delay(time: number): Promise { return new Promise((resolve) => setTimeout(resolve, time)) @@ -553,3 +555,19 @@ export const expectElementWithTestIdNotToBeRendered = ( editor: EditorRenderResult, testId: string, ): void => expect(getElementsWithTestId(editor, testId).length).toEqual(0) + +export function boundingClientRectToCanvasRectangle( + result: EditorRenderResult, + elementBounds: DOMRect, +) { + const canvasRootContainer = result.renderedDOM.getByTestId(CanvasContainerID) + const canvasScale = result.getEditorState().editor.canvas.scale + const canvasRootRectangle = getCanvasRectangleFromElement( + canvasRootContainer, + canvasScale, + 'without-content', + ) + const canvasBounds = offsetRect(canvasRectangle(elementBounds), negate(canvasRootRectangle)) + + return canvasBounds +}