diff --git a/editor/src/components/canvas/canvas-context-menu.spec.browser2.tsx b/editor/src/components/canvas/canvas-context-menu.spec.browser2.tsx index fa100a357137..72862fa9e296 100644 --- a/editor/src/components/canvas/canvas-context-menu.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-context-menu.spec.browser2.tsx @@ -33,6 +33,7 @@ import { import { MetadataUtils } from '../../core/model/element-metadata-utils' import type { ElementPath } from '../../core/shared/project-file-types' import { getDomRectCenter } from '../../core/shared/dom-utils' +import { getNavigatorTargetsFromEditorState } from '../navigator/navigator-utils' function expectAllSelectedViewsToHaveMetadata(editor: EditorRenderResult) { const selectedViews = editor.getEditorState().editor.selectedViews @@ -814,7 +815,11 @@ describe('canvas context menu', () => { 'await-first-dom-report', ) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', @@ -831,7 +836,11 @@ describe('canvas context menu', () => { await pressKey(']', { modifiers: cmdModifier }) // Bring Forward - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', @@ -843,7 +852,11 @@ describe('canvas context menu', () => { await pressKey('[', { modifiers: cmdModifier }) // Send Backward - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', @@ -855,7 +868,11 @@ describe('canvas context menu', () => { await pressKey(']', { modifiers: altCmdModifier }) // Bring To Front - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', @@ -867,7 +884,11 @@ describe('canvas context menu', () => { await pressKey('[', { modifiers: altCmdModifier }) // Send To Back - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', 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 4c8f7a1d08bd..49083754b234 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 @@ -59,6 +59,7 @@ import { wait, } from '../../../../utils/utils.test-utils' import CanvasActions from '../../canvas-actions' +import { getNavigatorTargetsFromEditorState } from '../../../navigator/navigator-utils' interface CheckCursor { cursor: CSSCursor | null @@ -905,7 +906,11 @@ export var ${BakedInStoryboardVariableName} = (props) => { await mouseDoubleClickAtPoint(canvasControlsLayer, dragHereCenter) // check that `drag-here` is expanded in the navigator - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-sb/scene1', 'regular-sb/scene1/container1', 'regular-sb/scene1/container1:container-root-div', diff --git a/editor/src/components/canvas/canvas-strategies/strategies/absolute-reparent-to-flex-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/absolute-reparent-to-flex-strategy.spec.browser2.tsx index 69411fd0d3e0..7cbebcf7de2f 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/absolute-reparent-to-flex-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/absolute-reparent-to-flex-strategy.spec.browser2.tsx @@ -28,6 +28,7 @@ import { ExtraPadding } from './reparent-helpers/reparent-strategy-sibling-posit import { navigatorEntryToKey } from '../../../../components/editor/store/editor-state' import { selectComponents } from '../../../editor/actions/action-creators' import { setFeatureForBrowserTestsUseInDescribeBlockOnly } from '../../../../utils/utils.test-utils' +import { getNavigatorTargetsFromEditorState } from '../../../navigator/navigator-utils' async function dragElement( renderResult: EditorRenderResult, @@ -651,19 +652,21 @@ describe('Absolute Reparent To Flex Strategy with more complex flex layouts', () expect(renderResult.getEditorState().editor.selectedViews.map(EP.toString)).toEqual([ 'utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/targetdiv', ]) - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-utopia-storyboard-uid/scene-aaa', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild1', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild2', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child2', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/targetdiv', - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-utopia-storyboard-uid/scene-aaa', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild1', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild2', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child2', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/targetdiv', + ]) }) it('moving the element into a flex layout to the middle of the last child reparents to the child', async () => { const renderResult = await renderTestEditorWithCode( @@ -694,19 +697,21 @@ describe('Absolute Reparent To Flex Strategy with more complex flex layouts', () expect(renderResult.getEditorState().editor.selectedViews.map(EP.toString)).toEqual([ 'utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child2/targetdiv', ]) - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-utopia-storyboard-uid/scene-aaa', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild1', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild2', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child2', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child2/targetdiv', - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-utopia-storyboard-uid/scene-aaa', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild1', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild2', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child2', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child2/targetdiv', + ]) }) it('moving the element into a flex layout to the edge of the last child reparents to the end as a sibling', async () => { const renderResult = await renderTestEditorWithCode( @@ -737,19 +742,21 @@ describe('Absolute Reparent To Flex Strategy with more complex flex layouts', () expect(renderResult.getEditorState().editor.selectedViews.map(EP.toString)).toEqual([ 'utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/targetdiv', ]) - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-utopia-storyboard-uid/scene-aaa', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild1', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild2', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child2', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/targetdiv', - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-utopia-storyboard-uid/scene-aaa', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild1', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild2', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child2', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/targetdiv', + ]) }) it('moving the element to the edge of a flex in flex layout will reparent to the outer flex container', async () => { const renderResult = await renderTestEditorWithCode( @@ -779,19 +786,21 @@ describe('Absolute Reparent To Flex Strategy with more complex flex layouts', () expect(renderResult.getEditorState().editor.selectedViews.map(EP.toString)).toEqual([ 'utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/targetdiv', ]) - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-utopia-storyboard-uid/scene-aaa', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/targetdiv', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild1', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild2', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child2', - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-utopia-storyboard-uid/scene-aaa', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/targetdiv', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild1', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild2', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child2', + ]) }) it('moving the element to the center of a flex in flex layout will reparent to flex grandchild', async () => { const renderResult = await renderTestEditorWithCode( @@ -822,19 +831,21 @@ describe('Absolute Reparent To Flex Strategy with more complex flex layouts', () expect(renderResult.getEditorState().editor.selectedViews.map(EP.toString)).toEqual([ 'utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild2/targetdiv', ]) - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-utopia-storyboard-uid/scene-aaa', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild1', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild2', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild2/targetdiv', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child2', - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-utopia-storyboard-uid/scene-aaa', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild1', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild2', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild2/targetdiv', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child2', + ]) }) it('moving one of the inner element over its parents edge while inside the parent area doesnt trigger reparent', async () => { const renderResult = await renderTestEditorWithCode( @@ -865,19 +876,21 @@ describe('Absolute Reparent To Flex Strategy with more complex flex layouts', () expect(renderResult.getEditorState().editor.selectedViews.map(EP.toString)).toEqual([ 'utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild2', ]) - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-utopia-storyboard-uid/scene-aaa', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild1', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild2', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child2', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/targetdiv', - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-utopia-storyboard-uid/scene-aaa', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild1', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild2', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child2', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/targetdiv', + ]) }) it('moving one of the inner element over its parents edge from the outside triggers reparent', async () => { const renderResult = await renderTestEditorWithCode( @@ -908,19 +921,21 @@ describe('Absolute Reparent To Flex Strategy with more complex flex layouts', () expect(renderResult.getEditorState().editor.selectedViews.map(EP.toString)).toEqual([ 'utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/innerchild2', ]) - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-utopia-storyboard-uid/scene-aaa', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild1', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/innerchild2', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child2', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/targetdiv', - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-utopia-storyboard-uid/scene-aaa', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child1flex/innerchild1', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/innerchild2', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/flexcontainer/child2', + 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/targetdiv', + ]) }) it('moving the inner child element to reparent to the parent sibling visually keeps the original layout until mouseup', async () => { const renderResult = await renderTestEditorWithCode( diff --git a/editor/src/components/canvas/canvas-strategies/strategies/flex-reparent-to-flex-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/flex-reparent-to-flex-strategy.spec.browser2.tsx index 94be253e1d43..b31be5690f9a 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/flex-reparent-to-flex-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/flex-reparent-to-flex-strategy.spec.browser2.tsx @@ -19,6 +19,7 @@ import { mouseClickAtPoint, mouseDragFromPointWithDelta } from '../../event-help import { selectComponentsForTest } from '../../../../utils/utils.test-utils' import * as EP from '../../../../core/shared/element-path' import { navigatorEntryToKey } from '../../../../components/editor/store/editor-state' +import { getNavigatorTargetsFromEditorState } from '../../../navigator/navigator-utils' async function dragElement( renderResult: EditorRenderResult, @@ -403,9 +404,9 @@ describe('Flex Reparent To Flex Strategy', () => { await renderResult.getDispatchFollowUpActionsFinished() - const navigatorTargets = renderResult - .getEditorState() - .derived.visibleNavigatorTargets.map(navigatorEntryToKey) + const navigatorTargets = getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey) expect(navigatorTargets).toEqual([ 'regular-utopia-storyboard-uid/parent2', 'regular-utopia-storyboard-uid/parent2/0b5', diff --git a/editor/src/components/canvas/canvas-strategies/strategies/flow-reorder-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/flow-reorder-strategy.spec.browser2.tsx index c97a3ce9baa7..bb856989c4e8 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/flow-reorder-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/flow-reorder-strategy.spec.browser2.tsx @@ -24,6 +24,7 @@ import * as EP from '../../../../core/shared/element-path' import { MetadataUtils } from '../../../../core/model/element-metadata-utils' import { assert } from 'chai' import { navigatorEntryToKey } from '../../../../components/editor/store/editor-state' +import { getNavigatorTargetsFromEditorState } from '../../../navigator/navigator-utils' const TestProjectBlockElements = (additionalContainerStyle: string = '') => `
@@ -316,7 +317,9 @@ async function dragElement( modifiers: modifiers, midDragCallback: async () => { expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsDuringMove) }, }) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/fragment-like-helpers.test-utils.ts b/editor/src/components/canvas/canvas-strategies/strategies/fragment-like-helpers.test-utils.ts index 4f2ad3fe0958..b5bafc0ac8d3 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/fragment-like-helpers.test-utils.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/fragment-like-helpers.test-utils.ts @@ -1,4 +1,5 @@ import * as EP from '../../../../core/shared/element-path' +import { getNavigatorTargetsFromEditorState } from '../../../navigator/navigator-utils' import type { EditorRenderResult } from '../../ui-jsx.test-utils' import type { FragmentLikeType } from './fragment-like-helpers' @@ -57,9 +58,8 @@ export function getClosingFragmentLikeTag(type: FragmentLikeType): string { } export function getRegularNavigatorTargets(renderResult: EditorRenderResult): Array { - return renderResult - .getEditorState() - .derived.navigatorTargets.filter((t) => t.type === 'REGULAR') + return getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor) + .navigatorTargets.filter((t) => t.type === 'REGULAR') .map((t) => t.elementPath) .map(EP.toString) } diff --git a/editor/src/components/canvas/canvas-strategies/strategies/keyboard-reorder-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/keyboard-reorder-strategy.spec.browser2.tsx index 1e6f0fd369f8..8a8288a6c008 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/keyboard-reorder-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/keyboard-reorder-strategy.spec.browser2.tsx @@ -11,6 +11,7 @@ import { } from './fragment-like-helpers.test-utils' import type { FragmentLikeType } from './fragment-like-helpers' import { AllFragmentLikeTypes } from './fragment-like-helpers' +import { getNavigatorTargetsFromEditorState } from '../../../navigator/navigator-utils' const TestProject = ( display: 'block' | 'inline-block', @@ -207,7 +208,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowDown) await pressKeysRepeat(renderResult, 'ArrowUp', 1) @@ -222,7 +225,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowUp) // pressing keyboard left and right reorders elements @@ -238,7 +243,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/aaa', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowRight) await pressKeysRepeat(renderResult, 'ArrowLeft', 1) @@ -253,7 +260,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowLeft) }) @@ -287,7 +296,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowDown) await pressKeysRepeat(renderResult, 'ArrowUp', 1) @@ -302,7 +313,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowUp) // pressing keyboard left and right reorders elements in the opposite direction than in the ltr case @@ -318,7 +331,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/aaa', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowRight) await pressKeysRepeat(renderResult, 'ArrowRight', 1) @@ -333,7 +348,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowLeft) }) @@ -367,7 +384,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowDown) await pressKeysRepeat(renderResult, 'ArrowUp', 1) @@ -382,7 +401,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowUp) // pressing keyboard left and right reorders elements @@ -398,7 +419,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/aaa', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowRight) await pressKeysRepeat(renderResult, 'ArrowLeft', 1) @@ -413,7 +436,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowLeft) }) @@ -447,7 +472,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowDown) await pressKeysRepeat(renderResult, 'ArrowUp', 1) @@ -462,7 +489,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowUp) // pressing keyboard left and right reorders elements in the opposite direction than in the ltr case @@ -478,7 +507,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/aaa', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowRight) await pressKeysRepeat(renderResult, 'ArrowRight', 1) @@ -493,7 +524,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowLeft) }) it('pressing the arrow keys reorders in a flex column-reverse layout', async () => { @@ -526,7 +559,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowDown) await pressKeysRepeat(renderResult, 'ArrowDown', 1) @@ -541,7 +576,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowUp) // pressing keyboard left and right reorders elements in reverse order @@ -557,7 +594,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/aaa', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowRight) await pressKeysRepeat(renderResult, 'ArrowRight', 1) @@ -572,7 +611,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowLeft) }) it('pressing the arrow keys reorders in a flex column-reverse layout with rtl text direction', async () => { @@ -605,7 +646,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowDown) await pressKeysRepeat(renderResult, 'ArrowDown', 1) @@ -620,7 +663,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowUp) // pressing keyboard left and right reorders elements in "normal order", because flex reverse and rtl together reverses the directions twice @@ -636,7 +681,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/aaa', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowRight) await pressKeysRepeat(renderResult, 'ArrowRight', 1) @@ -651,7 +698,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowLeft) }) @@ -684,7 +733,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowDown) await pressKeysRepeat(renderResult, 'ArrowUp', 1) @@ -699,7 +750,9 @@ describe('Keyboard Reorder Strategy', () => { 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container/ddd', ] expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsAfterArrowUp) }) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/reorder-slider-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/reorder-slider-strategy.spec.browser2.tsx index 1547aa0c0a0c..81f832edb3ce 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/reorder-slider-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/reorder-slider-strategy.spec.browser2.tsx @@ -23,6 +23,7 @@ import { } from '../../event-helpers.test-utils' import { CanvasControlsContainerID } from '../../controls/new-canvas-controls' import { navigatorEntryToKey } from '../../../../components/editor/store/editor-state' +import { getNavigatorTargetsFromEditorState } from '../../../navigator/navigator-utils' const TestProjectComplex = (additionalStyle: string = '') => `
@@ -273,7 +274,9 @@ async function dragControl( modifiers: modifiers, midDragCallback: async () => { expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedNavigatorTargetsDuringMove) }, }) diff --git a/editor/src/components/canvas/remix/remix-navigator.spec.browser2.tsx b/editor/src/components/canvas/remix/remix-navigator.spec.browser2.tsx index 5ca016bb7325..b56940dc5344 100644 --- a/editor/src/components/canvas/remix/remix-navigator.spec.browser2.tsx +++ b/editor/src/components/canvas/remix/remix-navigator.spec.browser2.tsx @@ -16,6 +16,7 @@ import { renderTestEditorWithModel } from '../ui-jsx.test-utils' import { dragElementWithDNDEvents } from '../event-helpers.test-utils' import { windowPoint } from '../../../core/shared/math-utils' import { RemixIndexPathLabel } from './remix-utils' +import { getNavigatorTargetsFromEditorState } from '../../navigator/navigator-utils' const DefaultRouteTextContent = 'Hello Remix!' const RootTextContent = 'This is root!' @@ -80,14 +81,16 @@ describe('Remix navigator', () => { }) const renderResult = await renderRemixProject(project) - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-storyboard/remix-scene', - 'regular-storyboard/remix-scene:rootdiv', - 'regular-storyboard/remix-scene:rootdiv/outlet', - 'regular-storyboard/remix-scene:rootdiv/outlet:remix-div', - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-storyboard/remix-scene', + 'regular-storyboard/remix-scene:rootdiv', + 'regular-storyboard/remix-scene:rootdiv/outlet', + 'regular-storyboard/remix-scene:rootdiv/outlet:remix-div', + ]) }) it('Shows navigator for remix content with two outlets', async () => { const project = createModifiedProject({ @@ -143,16 +146,18 @@ describe('Remix navigator', () => { }) const renderResult = await renderRemixProject(project) - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-storyboard/remix-scene', - 'regular-storyboard/remix-scene:rootdiv', - 'regular-storyboard/remix-scene:rootdiv/outlet', - 'regular-storyboard/remix-scene:rootdiv/outlet:remix-div', - 'regular-storyboard/remix-scene:rootdiv/outlet2', - 'regular-storyboard/remix-scene:rootdiv/outlet2:remix-div', - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-storyboard/remix-scene', + 'regular-storyboard/remix-scene:rootdiv', + 'regular-storyboard/remix-scene:rootdiv/outlet', + 'regular-storyboard/remix-scene:rootdiv/outlet:remix-div', + 'regular-storyboard/remix-scene:rootdiv/outlet2', + 'regular-storyboard/remix-scene:rootdiv/outlet2:remix-div', + ]) }) it('Navigator for remix content has default color', async () => { const project = createModifiedProject({ @@ -382,15 +387,17 @@ describe('Reparenting in Remix projects in the navigator', () => { dragDelta, ) - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-storyboard/remix-scene', - 'regular-storyboard/remix-scene:rootdiv', - 'regular-storyboard/remix-scene:rootdiv/outlet', - 'regular-storyboard/remix-scene:rootdiv/outlet:remix-div', - 'regular-storyboard/remix-scene:rootdiv/outlet:remix-div/drag-div', // <-- reparented here from storyboard - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-storyboard/remix-scene', + 'regular-storyboard/remix-scene:rootdiv', + 'regular-storyboard/remix-scene:rootdiv/outlet', + 'regular-storyboard/remix-scene:rootdiv/outlet:remix-div', + 'regular-storyboard/remix-scene:rootdiv/outlet:remix-div/drag-div', // <-- reparented here from storyboard + ]) }) it('Can not reparent into Remix Outlet', async () => { @@ -494,14 +501,16 @@ describe('Reparenting in Remix projects in the navigator', () => { dragDelta, ) - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-storyboard/remix-scene', - 'regular-storyboard/remix-scene:rootdiv', - 'regular-storyboard/remix-scene:rootdiv/outlet', - 'regular-storyboard/remix-scene:rootdiv/outlet:remix-div', - 'regular-storyboard/drag-div', // <-- not reparented - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-storyboard/remix-scene', + 'regular-storyboard/remix-scene:rootdiv', + 'regular-storyboard/remix-scene:rootdiv/outlet', + 'regular-storyboard/remix-scene:rootdiv/outlet:remix-div', + 'regular-storyboard/drag-div', // <-- not reparented + ]) }) }) diff --git a/editor/src/components/canvas/remix/remix-rendering.spec.browser2.tsx b/editor/src/components/canvas/remix/remix-rendering.spec.browser2.tsx index f2c34dcf69d0..8c7ad9535991 100644 --- a/editor/src/components/canvas/remix/remix-rendering.spec.browser2.tsx +++ b/editor/src/components/canvas/remix/remix-rendering.spec.browser2.tsx @@ -61,6 +61,7 @@ import { RegisteredCanvasStrategies, } from '../canvas-strategies/canvas-strategies' import CanvasActions from '../canvas-actions' +import { getNavigatorTargetsFromEditorState } from '../../navigator/navigator-utils' const DefaultRouteTextContent = 'Hello Remix!' const RootTextContent = 'This is root!' @@ -1766,19 +1767,21 @@ export default function Index() { await renderResult.dispatch([runDOMWalker()], true) - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-sb/remix-scene', - 'regular-sb/remix-scene:app', - 'regular-sb/remix-scene:app/outlet', - 'regular-sb/remix-scene:app/outlet:index', - 'regular-sb/remix-scene:app/outlet:index/absolute-div', - 'regular-sb/remix-scene:app/outlet:index/flex-div', - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-1', - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-2', - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-3', - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-sb/remix-scene', + 'regular-sb/remix-scene:app', + 'regular-sb/remix-scene:app/outlet', + 'regular-sb/remix-scene:app/outlet:index', + 'regular-sb/remix-scene:app/outlet:index/absolute-div', + 'regular-sb/remix-scene:app/outlet:index/flex-div', + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-1', + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-2', + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-3', + ]) const child1 = await clickElementOnCanvasControlsLayer(renderResult, Child1TestId) const child1Bounds = child1.getBoundingClientRect() @@ -1788,19 +1791,21 @@ export default function Index() { windowPoint({ x: child1Bounds.width * 1.5, y: 0 }), ) - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-sb/remix-scene', - 'regular-sb/remix-scene:app', - 'regular-sb/remix-scene:app/outlet', - 'regular-sb/remix-scene:app/outlet:index', - 'regular-sb/remix-scene:app/outlet:index/absolute-div', - 'regular-sb/remix-scene:app/outlet:index/flex-div', - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-2', - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-1', // <- child1 is the middle element after the reorder - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-3', - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-sb/remix-scene', + 'regular-sb/remix-scene:app', + 'regular-sb/remix-scene:app/outlet', + 'regular-sb/remix-scene:app/outlet:index', + 'regular-sb/remix-scene:app/outlet:index/absolute-div', + 'regular-sb/remix-scene:app/outlet:index/flex-div', + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-2', + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-1', // <- child1 is the middle element after the reorder + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-3', + ]) }) it('absolute move elements inside Remix', async () => { @@ -1881,19 +1886,21 @@ export default function Index() { await renderResult.dispatch([runDOMWalker()], true) - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-sb/remix-scene', - 'regular-sb/remix-scene:app', - 'regular-sb/remix-scene:app/outlet', - 'regular-sb/remix-scene:app/outlet:index', - 'regular-sb/remix-scene:app/outlet:index/absolute-div', - 'regular-sb/remix-scene:app/outlet:index/flex-div', - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-1', - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-2', - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-3', - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-sb/remix-scene', + 'regular-sb/remix-scene:app', + 'regular-sb/remix-scene:app/outlet', + 'regular-sb/remix-scene:app/outlet:index', + 'regular-sb/remix-scene:app/outlet:index/absolute-div', + 'regular-sb/remix-scene:app/outlet:index/flex-div', + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-1', + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-2', + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-3', + ]) await pressKey('d') // enter draw to insert mode @@ -2103,19 +2110,21 @@ export default function Index() { it('dragging elements between Remix and the storyboard', async () => { const renderResult = await renderRemixProject(remixProjectForEditingTests) - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-sb/remix-scene', - 'regular-sb/remix-scene:app', - 'regular-sb/remix-scene:app/outlet', - 'regular-sb/remix-scene:app/outlet:index', - 'regular-sb/remix-scene:app/outlet:index/absolute-div', - 'regular-sb/remix-scene:app/outlet:index/flex-div', - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-1', - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-2', - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-3', - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-sb/remix-scene', + 'regular-sb/remix-scene:app', + 'regular-sb/remix-scene:app/outlet', + 'regular-sb/remix-scene:app/outlet:index', + 'regular-sb/remix-scene:app/outlet:index/absolute-div', + 'regular-sb/remix-scene:app/outlet:index/flex-div', + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-1', + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-2', + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-3', + ]) { // Drag the element out of Remix @@ -2138,19 +2147,21 @@ export default function Index() { ) } - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-sb/remix-scene', - 'regular-sb/remix-scene:app', - 'regular-sb/remix-scene:app/outlet', - 'regular-sb/remix-scene:app/outlet:index', - 'regular-sb/remix-scene:app/outlet:index/flex-div', - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-1', - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-2', - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-3', - 'regular-sb/absolute-div', - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-sb/remix-scene', + 'regular-sb/remix-scene:app', + 'regular-sb/remix-scene:app/outlet', + 'regular-sb/remix-scene:app/outlet:index', + 'regular-sb/remix-scene:app/outlet:index/flex-div', + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-1', + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-2', + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-3', + 'regular-sb/absolute-div', + ]) { // Drag the element back into Remix @@ -2173,19 +2184,21 @@ export default function Index() { ) } - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-sb/remix-scene', - 'regular-sb/remix-scene:app', - 'regular-sb/remix-scene:app/outlet', - 'regular-sb/remix-scene:app/outlet:index', - 'regular-sb/remix-scene:app/outlet:index/flex-div', - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-1', - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-2', - 'regular-sb/remix-scene:app/outlet:index/flex-div/child-3', - 'regular-sb/remix-scene:app/outlet:index/absolute-div', - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-sb/remix-scene', + 'regular-sb/remix-scene:app', + 'regular-sb/remix-scene:app/outlet', + 'regular-sb/remix-scene:app/outlet:index', + 'regular-sb/remix-scene:app/outlet:index/flex-div', + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-1', + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-2', + 'regular-sb/remix-scene:app/outlet:index/flex-div/child-3', + 'regular-sb/remix-scene:app/outlet:index/absolute-div', + ]) }) }) diff --git a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-conditionals.spec.browser2.tsx b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-conditionals.spec.browser2.tsx index 5ff7ff145a37..77c3ef66da37 100644 --- a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-conditionals.spec.browser2.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-conditionals.spec.browser2.tsx @@ -1,5 +1,6 @@ import { createModifiedProject } from '../../../sample-projects/sample-project-utils.test-utils' import { navigatorEntryToKey, StoryboardFilePath } from '../../editor/store/editor-state' +import { getNavigatorTargetsFromEditorState } from '../../navigator/navigator-utils' import { renderTestEditorWithModel } from '../ui-jsx.test-utils' const appFilePath = '/src/app.js' @@ -64,7 +65,9 @@ async function createAndRenderProject() { describe('a project with conditionals', () => { it('fills the content of the navigator', async () => { const renderedProject = await createAndRenderProject() - const navigatorTargets = renderedProject.getEditorState().derived.visibleNavigatorTargets + const navigatorTargets = getNavigatorTargetsFromEditorState( + renderedProject.getEditorState().editor, + ).visibleNavigatorTargets const pathStrings = navigatorTargets.map(navigatorEntryToKey) expect(pathStrings).toEqual([ 'regular-storyboard/scene', diff --git a/editor/src/components/common/shared-strategies/convert-to-flex-strategy.spec.browser2.tsx b/editor/src/components/common/shared-strategies/convert-to-flex-strategy.spec.browser2.tsx index 37d67c0475ac..e05620eca08f 100644 --- a/editor/src/components/common/shared-strategies/convert-to-flex-strategy.spec.browser2.tsx +++ b/editor/src/components/common/shared-strategies/convert-to-flex-strategy.spec.browser2.tsx @@ -18,6 +18,7 @@ import { selectComponents } from '../../editor/actions/action-creators' import type { FlexDirection } from '../../inspector/common/css-utils' import type { FlexAlignment, FlexJustifyContent } from '../../inspector/inspector-common' import { MaxContent } from '../../inspector/inspector-common' +import { getNavigatorTargetsFromEditorState } from '../../navigator/navigator-utils' type LTWH = [ left: number, @@ -740,15 +741,19 @@ describe('Smart Convert to Flex Reordering Children if Needed', () => { 'regular-sb/parent/second', ] - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - originalElementOrder, - ) + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual(originalElementOrder) await expectSingleUndo2Saves(editor, () => pressShiftA(editor)) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - originalElementOrder, - ) + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual(originalElementOrder) }) }) diff --git a/editor/src/components/editor/actions/actions.spec.browser2.tsx b/editor/src/components/editor/actions/actions.spec.browser2.tsx index 96605c8da5ea..4ea691d27750 100644 --- a/editor/src/components/editor/actions/actions.spec.browser2.tsx +++ b/editor/src/components/editor/actions/actions.spec.browser2.tsx @@ -82,6 +82,7 @@ import { getDomRectCenter } from '../../../core/shared/dom-utils' import { FloatingPostActionMenuTestId } from '../../canvas/controls/select-mode/post-action-menu' import { safeIndex } from '../../../core/shared/array-utils' import { updateSelectedViews } from '../../canvas/commands/update-selected-views-command' +import { getNavigatorTargetsFromEditorState } from '../../navigator/navigator-utils' async function deleteFromScene( inputSnippet: string, @@ -604,7 +605,11 @@ describe('actions', () => { 'await-first-dom-report', ) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/map', 'regular-sb/scene/map/card~~~1', @@ -622,7 +627,11 @@ describe('actions', () => { await pressKey('Backspace') - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/map', 'regular-sb/scene/map/card~~~1', @@ -2316,7 +2325,9 @@ export var storyboard = ( y: 2, }) expect( - editor.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + editor.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/app', @@ -2361,7 +2372,9 @@ export var storyboard = ( }) expect( - editor.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + editor.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/app', @@ -2406,7 +2419,9 @@ export var storyboard = ( }) expect( - editor.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + editor.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/app', @@ -2515,7 +2530,11 @@ export var storyboard = ( await pressKey('Esc') await editor.getDispatchFollowUpActionsFinished() - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:root', @@ -2688,7 +2707,9 @@ export var storyboard = (props) => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', @@ -2863,7 +2884,9 @@ export var storyboard = (props) => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', @@ -5752,7 +5775,9 @@ export var storyboard = ( expect(renderResult.getEditorState().postActionInteractionSession).toBeNull() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', @@ -5803,7 +5828,9 @@ export var storyboard = ( expect(renderResult.getEditorState().postActionInteractionSession).not.toBeNull() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', diff --git a/editor/src/components/editor/actions/actions.tsx b/editor/src/components/editor/actions/actions.tsx index be1ab55d635d..60ed8fd4ecb2 100644 --- a/editor/src/components/editor/actions/actions.tsx +++ b/editor/src/components/editor/actions/actions.tsx @@ -619,6 +619,7 @@ import { dataCanCondenseProp, isDataCanCondenseProp, } from '../../../utils/can-condense' +import { getNavigatorTargetsFromEditorState } from '../../navigator/navigator-utils' export const MIN_CODE_PANE_REOPEN_WIDTH = 100 @@ -1052,9 +1053,6 @@ export function restoreDerivedState(history: StateHistory): DerivedState { const poppedDerived = history.current.derived return { - navigatorRows: poppedDerived.navigatorRows, - navigatorTargets: poppedDerived.navigatorTargets, - visibleNavigatorTargets: poppedDerived.visibleNavigatorTargets, autoFocusedPaths: poppedDerived.autoFocusedPaths, controls: [], elementWarnings: poppedDerived.elementWarnings, @@ -1512,7 +1510,6 @@ let checkpointTimeoutId: number | undefined = undefined let canvasScrollAnimationTimer: number | undefined = undefined function updateSelectedComponentsFromEditorPosition( - derived: DerivedState, editor: EditorState, dispatch: EditorDispatch, filePath: string, @@ -1525,12 +1522,16 @@ function updateSelectedComponentsFromEditorPosition( const highlightBoundsForUids = getHighlightBoundsForFile(editor, filePath) const allElementPathsOptic = traverseArray().compose(fromField('elementPath')) + + // TODO this is wasteful here, instead we should get the allElementPaths through a more conservative way, for example taking all the keys of JSXMetadata + const navigatorTargets = getNavigatorTargetsFromEditorState(editor) + const newlySelectedElements = getElementPathsInBounds( line, highlightBoundsForUids, toArrayOf( allElementPathsOptic, - derived.navigatorTargets.filter((t) => !isConditionalClauseNavigatorEntry(t)), + navigatorTargets.navigatorTargets.filter((t) => !isConditionalClauseNavigatorEntry(t)), ), ) @@ -2599,14 +2600,10 @@ export const UPDATE_FNS = { leftMenu: { visible: editor.leftMenu.visible, selectedTab: LeftMenuTab.Navigator }, } }, - WRAP_IN_ELEMENT: ( - action: WrapInElement, - editor: EditorModel, - derived: DerivedState, - ): EditorModel => { + WRAP_IN_ELEMENT: (action: WrapInElement, editor: EditorModel): EditorModel => { const orderedActionTargets = getZIndexOrderedViewsWithoutDirectChildren( action.targets, - derived.navigatorTargets, + getNavigatorTargetsFromEditorState(editor).navigatorTargets, ) const parentPath = commonInsertionPathFromArray( @@ -5029,11 +5026,9 @@ export const UPDATE_FNS = { SELECT_FROM_FILE_AND_POSITION: ( action: SelectFromFileAndPosition, editor: EditorModel, - derived: DerivedState, dispatch: EditorDispatch, ): EditorModel => { return updateSelectedComponentsFromEditorPosition( - derived, editor, dispatch, action.filePath, diff --git a/editor/src/components/editor/canvas-toolbar.spec.browser2.tsx b/editor/src/components/editor/canvas-toolbar.spec.browser2.tsx index d1f3e3d59af3..af8bd0de6d59 100644 --- a/editor/src/components/editor/canvas-toolbar.spec.browser2.tsx +++ b/editor/src/components/editor/canvas-toolbar.spec.browser2.tsx @@ -40,6 +40,7 @@ import { } from './canvas-toolbar' import { StoryboardFilePath, PlaygroundFilePath, navigatorEntryToKey } from './store/editor-state' import { cmdModifier } from '../../utils/modifiers' +import { getNavigatorTargetsFromEditorState } from '../navigator/navigator-utils' function slightlyOffsetWindowPointBecauseVeryWeirdIssue(point: { x: number; y: number }) { // FIXME when running in headless chrome, the result of getBoundingClientRect will be slightly @@ -418,7 +419,11 @@ describe('canvas toolbar', () => { await insertViaAddElementPopup(editor, 'div') - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:container', diff --git a/editor/src/components/editor/editor-component.tsx b/editor/src/components/editor/editor-component.tsx index 4484d9c0772d..3cb50f55cd99 100644 --- a/editor/src/components/editor/editor-component.tsx +++ b/editor/src/components/editor/editor-component.tsx @@ -93,6 +93,10 @@ import { import { useGithubPolling } from '../../core/shared/github/helpers' import { useAtom } from 'jotai' import { clearOpenMenuIds } from '../../core/shared/menu-state' +import { + navigatorTargetsSelector, + navigatorTargetsSelectorNavigatorTargets, +} from '../navigator/navigator-utils' const liveModeToastId = 'play-mode-toast' @@ -150,7 +154,7 @@ export const EditorComponentInner = React.memo((props: EditorProps) => { const dispatch = useDispatch() const editorStoreRef = useRefEditorState((store) => store) const metadataRef = useRefEditorState((store) => store.editor.jsxMetadata) - const navigatorTargetsRef = useRefEditorState((store) => store.derived.navigatorTargets) + const navigatorTargetsRef = useRefEditorState(navigatorTargetsSelectorNavigatorTargets) const colorTheme = useColorTheme() const onWindowMouseUp = React.useCallback((event: MouseEvent) => { return [EditorActions.updateMouseButtonsPressed(null, event.button)] diff --git a/editor/src/components/editor/store/editor-state.ts b/editor/src/components/editor/store/editor-state.ts index 4e2eeee82bc3..2e4d8349adb8 100644 --- a/editor/src/components/editor/store/editor-state.ts +++ b/editor/src/components/editor/store/editor-state.ts @@ -140,7 +140,6 @@ import { objectMap, pick } from '../../../core/shared/object-utils' import type { Spec } from 'immutability-helper' import { v4 as UUID } from 'uuid' -import { getNavigatorTargets } from '../../../components/navigator/navigator-utils' import type { BuiltInDependencies } from '../../../core/es-modules/package-manager/built-in-dependencies-list' import type { ConditionalCase } from '../../../core/model/conditionals' import { UTOPIA_LABEL_KEY } from '../../../core/model/utopia-constants' @@ -2422,9 +2421,6 @@ export function isSlotNavigatorEntry(entry: NavigatorEntry): entry is SlotNaviga } export interface DerivedState { - navigatorRows: Array - navigatorTargets: Array - visibleNavigatorTargets: Array autoFocusedPaths: Array controls: Array elementWarnings: { [key: string]: ElementWarnings } @@ -2436,9 +2432,6 @@ export interface DerivedState { function emptyDerivedState(editor: EditorState): DerivedState { return { - navigatorRows: [], - navigatorTargets: [], - visibleNavigatorTargets: [], autoFocusedPaths: [], controls: [], elementWarnings: {}, @@ -2795,9 +2788,6 @@ function getElementWarningsInner( const getElementWarnings = memoize(getElementWarningsInner, { maxSize: 1 }) type CacheableDerivedState = { - navigatorRows: Array - navigatorTargets: Array - visibleNavigatorTargets: Array elementWarnings: { [key: string]: ElementWarnings } autoFocusedPaths: Array } @@ -2811,15 +2801,6 @@ function deriveCacheableStateInner( hiddenInNavigator: ElementPath[], propertyControlsInfo: PropertyControlsInfo, ): CacheableDerivedState { - const { navigatorRows, navigatorTargets, visibleNavigatorTargets } = getNavigatorTargets( - jsxMetadata, - elementPathTree, - collapsedViews, - hiddenInNavigator, - propertyControlsInfo, - projectContents, - ) - const warnings = getElementWarnings( projectContents, jsxMetadata, @@ -2840,9 +2821,6 @@ function deriveCacheableStateInner( ) return { - navigatorRows: navigatorRows, - navigatorTargets: navigatorTargets, - visibleNavigatorTargets: visibleNavigatorTargets, elementWarnings: warnings, autoFocusedPaths: autoFocusedPaths, } @@ -2862,13 +2840,7 @@ export function deriveState( const deriveCacheableState = cacheKey === 'patched' ? patchedDeriveCacheableState : unpatchedDeriveCacheableState - const { - navigatorRows, - navigatorTargets, - visibleNavigatorTargets, - elementWarnings: warnings, - autoFocusedPaths, - } = deriveCacheableState( + const { elementWarnings: warnings, autoFocusedPaths } = deriveCacheableState( editor.projectContents, editor.jsxMetadata, editor.elementPathTree, @@ -2887,9 +2859,6 @@ export function deriveState( const filePathMappings = getFilePathMappings(editor.projectContents) const derived: DerivedState = { - navigatorRows: navigatorRows, - navigatorTargets: navigatorTargets, - visibleNavigatorTargets: visibleNavigatorTargets, autoFocusedPaths: autoFocusedPaths, controls: derivedState.controls, elementWarnings: warnings, diff --git a/editor/src/components/editor/store/editor-update.tsx b/editor/src/components/editor/store/editor-update.tsx index 185185010d5e..feb529936f02 100644 --- a/editor/src/components/editor/store/editor-update.tsx +++ b/editor/src/components/editor/store/editor-update.tsx @@ -343,7 +343,7 @@ export function runSimpleLocalEditorAction( case 'DELETE_SELECTED': return UPDATE_FNS.DELETE_SELECTED(state, dispatch) case 'WRAP_IN_ELEMENT': - return UPDATE_FNS.WRAP_IN_ELEMENT(action, state, derivedState) + return UPDATE_FNS.WRAP_IN_ELEMENT(action, state) case 'UNWRAP_ELEMENTS': return UPDATE_FNS.UNWRAP_ELEMENTS(action, state, builtInDependencies) case 'INSERT_IMAGE_INTO_UI': @@ -386,7 +386,7 @@ export function runSimpleLocalEditorAction( case 'UPDATE_PROPERTY_CONTROLS_INFO': return UPDATE_FNS.UPDATE_PROPERTY_CONTROLS_INFO(action, state) case 'SELECT_FROM_FILE_AND_POSITION': - return UPDATE_FNS.SELECT_FROM_FILE_AND_POSITION(action, state, derivedState, dispatch) + return UPDATE_FNS.SELECT_FROM_FILE_AND_POSITION(action, state, dispatch) case 'SEND_LINTER_REQUEST_MESSAGE': // side effect ☢️ workers.sendLinterRequestMessage(action.filePath, action.content) diff --git a/editor/src/components/editor/store/store-deep-equality-instances.spec.ts b/editor/src/components/editor/store/store-deep-equality-instances.spec.ts index f9b1156f7c84..86b5e83121b7 100644 --- a/editor/src/components/editor/store/store-deep-equality-instances.spec.ts +++ b/editor/src/components/editor/store/store-deep-equality-instances.spec.ts @@ -66,11 +66,6 @@ import { regularNavigatorRow } from '../../navigator/navigator-row' describe('DerivedStateKeepDeepEquality', () => { const oldValue: DerivedState = { - navigatorRows: [ - regularNavigatorRow(regularNavigatorEntry(EP.elementPath([['scene'], ['aaa', 'bbb']])), 1), - ], - navigatorTargets: [regularNavigatorEntry(EP.elementPath([['scene'], ['aaa', 'bbb']]))], - visibleNavigatorTargets: [regularNavigatorEntry(EP.elementPath([['scene'], ['aaa', 'bbb']]))], autoFocusedPaths: [EP.elementPath([['scene'], ['aaa']])], controls: [], elementWarnings: { @@ -102,11 +97,6 @@ describe('DerivedStateKeepDeepEquality', () => { filePathMappings: [], } const newSameValue: DerivedState = { - navigatorRows: [ - regularNavigatorRow(regularNavigatorEntry(EP.elementPath([['scene'], ['aaa', 'bbb']])), 1), - ], - navigatorTargets: [regularNavigatorEntry(EP.elementPath([['scene'], ['aaa', 'bbb']]))], - visibleNavigatorTargets: [regularNavigatorEntry(EP.elementPath([['scene'], ['aaa', 'bbb']]))], autoFocusedPaths: [EP.elementPath([['scene'], ['aaa']])], controls: [], elementWarnings: { @@ -138,12 +128,7 @@ describe('DerivedStateKeepDeepEquality', () => { filePathMappings: [], } const newDifferentValue: DerivedState = { - navigatorRows: [ - regularNavigatorRow(regularNavigatorEntry(EP.elementPath([['scene'], ['aaa', 'ddd']])), 2), - ], - navigatorTargets: [regularNavigatorEntry(EP.elementPath([['scene'], ['aaa', 'ddd']]))], - visibleNavigatorTargets: [regularNavigatorEntry(EP.elementPath([['scene'], ['aaa', 'bbb']]))], - autoFocusedPaths: [EP.elementPath([['scene'], ['aaa']])], + autoFocusedPaths: [EP.elementPath([['scene'], ['aab']])], controls: [], elementWarnings: { [EP.toString(EP.elementPath([['scene'], ['aaa', 'bbb']]))]: defaultElementWarnings, @@ -185,11 +170,7 @@ describe('DerivedStateKeepDeepEquality', () => { }) it('different but similar value handled appropriately', () => { const result = DerivedStateKeepDeepEquality()(oldValue, newDifferentValue) - expect(result.value.navigatorTargets[0].elementPath).toBe( - newDifferentValue.navigatorTargets[0].elementPath, - ) - expect(result.value.visibleNavigatorTargets).toBe(oldValue.visibleNavigatorTargets) - expect(result.value.autoFocusedPaths).toBe(oldValue.autoFocusedPaths) + expect(result.value.autoFocusedPaths).toEqual(newDifferentValue.autoFocusedPaths) expect(result.value.controls).toBe(oldValue.controls) expect(result.value.elementWarnings).toBe(oldValue.elementWarnings) expect(result.value).toEqual(newDifferentValue) diff --git a/editor/src/components/editor/store/store-deep-equality-instances.ts b/editor/src/components/editor/store/store-deep-equality-instances.ts index 687bf263487a..91d4ac3e8a1c 100644 --- a/editor/src/components/editor/store/store-deep-equality-instances.ts +++ b/editor/src/components/editor/store/store-deep-equality-instances.ts @@ -952,13 +952,7 @@ export const NavigatorStateKeepDeepEquality: KeepDeepEqualityCall { - return combine10EqualityCalls( - (state) => state.navigatorRows, - arrayDeepEquality(NavigatorRowKeepDeepEquality), - (state) => state.navigatorTargets, - arrayDeepEquality(NavigatorEntryKeepDeepEquality), - (state) => state.visibleNavigatorTargets, - arrayDeepEquality(NavigatorEntryKeepDeepEquality), + return combine7EqualityCalls( (state) => state.autoFocusedPaths, arrayDeepEquality(ElementPathKeepDeepEquality), (state) => state.controls, @@ -974,9 +968,6 @@ export function DerivedStateKeepDeepEquality(): KeepDeepEqualityCall state.filePathMappings, createCallWithShallowEquals(), ( - navigatorRows, - navigatorTargets, - visibleNavigatorTargets, autoFocusedPaths, controls, elementWarnings, @@ -986,9 +977,6 @@ export function DerivedStateKeepDeepEquality(): KeepDeepEqualityCall { return { - navigatorRows: navigatorRows, - navigatorTargets: navigatorTargets, - visibleNavigatorTargets: visibleNavigatorTargets, autoFocusedPaths: autoFocusedPaths, controls: controls, elementWarnings: elementWarnings, diff --git a/editor/src/components/editor/store/store-hook-substore-types.ts b/editor/src/components/editor/store/store-hook-substore-types.ts index 949830c50128..c6a0fd468326 100644 --- a/editor/src/components/editor/store/store-hook-substore-types.ts +++ b/editor/src/components/editor/store/store-hook-substore-types.ts @@ -18,6 +18,7 @@ export type Substates = { projectContents: ProjectContentSubstate canvas: CanvasSubstate canvasOffset: CanvasOffsetSubstate + navigatorTargetsSubstate: NavigatorTargetsSubstate derived: { derived: DerivedState } restOfEditor: RestOfEditorState restOfStore: Omit @@ -57,6 +58,19 @@ const emptyMetadataSubstate = { } as const export type MetadataSubstate = typeof emptyMetadataSubstate +// NavigatorTargetsSubstate +export const navigatorTargetsSubstateKeys = [ + 'jsxMetadata', + 'elementPathTree', + 'navigator', + 'propertyControlsInfo', + 'projectContents', +] as const +const emptyNavigatorTargetsSubstate = { + editor: pick(navigatorTargetsSubstateKeys, EmptyEditorStateForKeysOnly), +} as const +export type NavigatorTargetsSubstate = typeof emptyNavigatorTargetsSubstate + // SelectedViewsSubstate export const selectedViewsSubstateKeys = ['selectedViews'] as const const emptySelectedViewsSubstate = { diff --git a/editor/src/components/editor/store/store-hook.ts b/editor/src/components/editor/store/store-hook.ts index 34e4d6e1ea88..f1259268a604 100644 --- a/editor/src/components/editor/store/store-hook.ts +++ b/editor/src/components/editor/store/store-hook.ts @@ -29,6 +29,7 @@ import type { MetadataSubstate, MultiplayerSubstate, NavigatorSubstate, + NavigatorTargetsSubstate, OnlineStateSubstate, PostActionInteractionSessionSubstate, ProjectContentAndMetadataAndVariablesInScopeSubstate, @@ -51,6 +52,7 @@ import { githubSubstateKeys, highlightedHoveredViewsSubstateKeys, metadataSubstateKeys, + navigatorTargetsSubstateKeys, projectContentsKeys, propertyControlsInfoSubstateKeys, restOfEditorStateKeys, @@ -294,6 +296,9 @@ export const Substores = { navigator: (a: NavigatorSubstate, b: NavigatorSubstate) => { return NavigatorStateKeepDeepEquality(a.editor.navigator, b.editor.navigator).areEqual }, + navigatorTargetsSubstate: (a: NavigatorTargetsSubstate, b: NavigatorTargetsSubstate) => { + return keysEquality(navigatorTargetsSubstateKeys, a.editor, b.editor) + }, postActionInteractionSession: ( a: PostActionInteractionSessionSubstate, b: PostActionInteractionSessionSubstate, diff --git a/editor/src/components/element-context-menu.tsx b/editor/src/components/element-context-menu.tsx index a8c6bc3d71d0..5455769c58df 100644 --- a/editor/src/components/element-context-menu.tsx +++ b/editor/src/components/element-context-menu.tsx @@ -49,6 +49,7 @@ import type { WindowPoint } from '../core/shared/math-utils' import { pointsEqual } from '../core/shared/math-utils' import { useDispatch } from './editor/store/dispatch-context' import { useCreateCallbackToShowComponentPicker } from './navigator/navigator-item/component-picker-context-menu' +import { navigatorTargetsSelector, useGetNavigatorTargets } from './navigator/navigator-utils' export type ElementContextMenuInstance = | 'context-menu-navigator' @@ -199,10 +200,10 @@ function useCanvasContextMenuGetData( openFile: store.editor.canvas.openFile?.filename ?? null, internalClipboard: store.editor.internalClipboard, autoFocusedPaths: store.derived.autoFocusedPaths, - navigatorTargets: store.derived.navigatorTargets, propertyControlsInfo: store.editor.propertyControlsInfo, } }) + const navigatorTargetsRef = useRefEditorState(navigatorTargetsSelector) const showComponentPicker = useCreateCallbackToShowComponentPicker() return React.useCallback(() => { @@ -225,11 +226,11 @@ function useCanvasContextMenuGetData( internalClipboard: currentEditor.internalClipboard, contextMenuInstance: contextMenuInstance, autoFocusedPaths: currentEditor.autoFocusedPaths, - navigatorTargets: currentEditor.navigatorTargets, + navigatorTargets: navigatorTargetsRef.current.navigatorTargets, propertyControlsInfo: currentEditor.propertyControlsInfo, showComponentPicker: showComponentPicker, } - }, [editorSliceRef, contextMenuInstance, showComponentPicker]) + }, [editorSliceRef, navigatorTargetsRef, contextMenuInstance, showComponentPicker]) } export const ElementContextMenu = React.memo(({ contextMenuInstance }: ElementContextMenuProps) => { diff --git a/editor/src/components/inspector/sections/layout-section/conditional-section.tsx b/editor/src/components/inspector/sections/layout-section/conditional-section.tsx index d090d75415f2..0e5e163d6979 100644 --- a/editor/src/components/inspector/sections/layout-section/conditional-section.tsx +++ b/editor/src/components/inspector/sections/layout-section/conditional-section.tsx @@ -47,6 +47,7 @@ import type { NavigatorEntry } from '../../../editor/store/editor-state' import { Substores, useEditorState } from '../../../editor/store/store-hook' import type { MetadataSubstate, + NavigatorTargetsSubstate, ProjectContentAndMetadataSubstate, } from '../../../editor/store/store-hook-substore-types' import { LayoutIcon } from '../../../navigator/navigator-item/layout-icon' @@ -54,7 +55,7 @@ import { getNavigatorEntryLabel, labelSelector, } from '../../../navigator/navigator-item/navigator-item-wrapper' -import { getNavigatorTargets } from '../../../navigator/navigator-utils' +import { navigatorTargetsSelector } from '../../../navigator/navigator-utils' import type { ControlStatus } from '../../common/control-status' import { getControlStyles } from '../../common/control-styles' import { usePropControlledStateV2 } from '../../common/inspector-utils' @@ -77,11 +78,10 @@ type BranchNavigatorEntries = { } const branchNavigatorEntriesSelector = createCachedSelector( - (store: ProjectContentAndMetadataSubstate) => store.editor.jsxMetadata, - (store: ProjectContentAndMetadataSubstate) => store.editor.elementPathTree, - (store: ProjectContentAndMetadataSubstate) => store.editor.projectContents, - (_store: ProjectContentAndMetadataSubstate, paths: ElementPath[]) => paths, - (jsxMetadata, elementPathTree, projectContents, paths): BranchNavigatorEntries | null => { + (store: NavigatorTargetsSubstate) => store.editor.jsxMetadata, + navigatorTargetsSelector, + (_store: NavigatorTargetsSubstate, paths: ElementPath[]) => paths, + (jsxMetadata, navigatorTargets, paths): BranchNavigatorEntries | null => { if (paths.length !== 1) { return null } @@ -96,14 +96,7 @@ const branchNavigatorEntriesSelector = createCachedSelector( const conditional = elementMetadata.element.value - const navigatorEntries = getNavigatorTargets( - jsxMetadata, - elementPathTree, - [], - [], - {}, - projectContents, - ).navigatorTargets + const navigatorEntries = navigatorTargets.navigatorTargets function getNavigatorEntry(clause: JSXElementChild): NavigatorEntry | null { return ( @@ -294,7 +287,7 @@ export const ConditionalSection = React.memo(({ paths }: { paths: ElementPath[] }, [paths, conditionExpression, setConditionExpression, originalConditionExpression, dispatch]) const branchNavigatorEntries = useEditorState( - Substores.projectContentsAndMetadata, + Substores.navigatorTargetsSubstate, (store) => branchNavigatorEntriesSelector(store, paths), 'ConditionalSection branches', ) diff --git a/editor/src/components/navigator/navigator-conditionals.spec.browser2.tsx b/editor/src/components/navigator/navigator-conditionals.spec.browser2.tsx index 2df5e397af65..90524bb818b1 100644 --- a/editor/src/components/navigator/navigator-conditionals.spec.browser2.tsx +++ b/editor/src/components/navigator/navigator-conditionals.spec.browser2.tsx @@ -66,6 +66,7 @@ import { TopDropTargetLineTestId, } from './navigator-item/navigator-item-dnd-container' import { getEntriesForRow } from './navigator-row' +import { getNavigatorTargetsFromEditorState } from './navigator-utils' const ASYNC_NOOP = async () => NO_OP() @@ -520,12 +521,16 @@ export var ${BakedInStoryboardVariableName} = ( ` } -function navigatorStructure(editorState: EditorState, deriveState: DerivedState): string { - const lines = deriveState.visibleNavigatorTargets.map((target) => { +function navigatorStructure( + editorState: EditorState, + deriveState: DerivedState, // TODO delete me +): string { + const navigatorTargets = getNavigatorTargetsFromEditorState(editorState) + const lines = navigatorTargets.visibleNavigatorTargets.map((target) => { const targetAsText = navigatorEntryToKey(target) let prefix: string = '' const depth = - deriveState.navigatorRows.find((row) => + navigatorTargets.navigatorRows.find((row) => EP.pathsEqual(getEntriesForRow(row)[0].elementPath, target.elementPath), )?.indentation ?? 0 for (let index = 0; index < depth; index++) { diff --git a/editor/src/components/navigator/navigator-item/navigator-item-clickable-wrapper.tsx b/editor/src/components/navigator/navigator-item/navigator-item-clickable-wrapper.tsx index 85c2929d8cc5..a42ba01e2b34 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item-clickable-wrapper.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item-clickable-wrapper.tsx @@ -31,6 +31,7 @@ import type { ElementInstanceMetadata, ElementInstanceMetadataMap, } from '../../../core/shared/element-template' +import { navigatorTargetsSelector } from '../navigator-utils' export const NavigatorRowClickableWrapper = React.memo( (props: { row: NavigatorRow; children: React.ReactNode }) => { @@ -73,7 +74,7 @@ export function useGetNavigatorClickActions( selected: boolean, row: NavigatorRow, ) { - const navigatorTargets = useRefEditorState((store) => store.derived.navigatorTargets) + const navigatorTargets = useRefEditorState(navigatorTargetsSelector) const selectedViews = useRefEditorState((store) => store.editor.selectedViews) const collapsedViews = useRefEditorState((store) => store.editor.navigator.collapsedViews) const projectContents = useRefEditorState((store) => store.editor.projectContents) @@ -89,7 +90,7 @@ export function useGetNavigatorClickActions( } else if (e.shiftKey) { return actionsForRangeSelection( targetPath, - navigatorTargets.current, + navigatorTargets.current.navigatorTargets, selectedViews.current, collapsedViews.current, projectContents.current, diff --git a/editor/src/components/navigator/navigator-item/navigator-item-dnd-container.tsx b/editor/src/components/navigator/navigator-item/navigator-item-dnd-container.tsx index 511b64e03752..d2ce13445154 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item-dnd-container.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item-dnd-container.tsx @@ -45,7 +45,11 @@ import { MetadataUtils } from '../../../core/model/element-metadata-utils' import { getEmptyImage } from 'react-dnd-html5-backend' import { when } from '../../../utils/react-conditionals' import { metadataSelector } from '../../inspector/inpector-selectors' -import { baseNavigatorDepth } from '../navigator-utils' +import { + baseNavigatorDepth, + navigatorTargetsSelector, + useGetNavigatorTargets, +} from '../navigator-utils' import type { ElementInstanceMetadataMap, JSXElementChild, @@ -554,11 +558,7 @@ export const NavigatorItemContainer = React.memo((props: NavigatorItemDragAndDro 'NavigatorItemDndWrapper dropTargetHint', ) - const navigatorTargets = useEditorState( - Substores.derived, - (store) => store.derived.navigatorTargets, - 'NavigatorItemDndWrapper navigatorTargets', - ) + const navigatorTargets = useGetNavigatorTargets().navigatorTargets const isFirstSibling = React.useMemo(() => { const siblings = MetadataUtils.getSiblingsOrdered( @@ -793,14 +793,14 @@ export const NavigatorItemContainer = React.memo((props: NavigatorItemDragAndDro !isHintDisallowed(props.elementPath, editorStateRef.current.jsxMetadata) && isCollapsedCondtionalEntry - const navigatorRows = useRefEditorState((store) => store.derived.navigatorRows) + const navigatorRows = useRefEditorState(navigatorTargetsSelector) const margin = (() => { if (dropTargetHint == null) { return 0 } - const targetRow = navigatorRows.current.find((row) => + const targetRow = navigatorRows.current.navigatorRows.find((row) => isRegulaNavigatorRow(row) ? EP.pathsEqual(row.entry.elementPath, dropTargetHint.targetParent.elementPath) : row.entries.some((entry) => diff --git a/editor/src/components/navigator/navigator-item/navigator-item-wrapper.tsx b/editor/src/components/navigator/navigator-item/navigator-item-wrapper.tsx index ffe9becd6407..7d3ae201df8f 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item-wrapper.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item-wrapper.tsx @@ -33,6 +33,7 @@ import { Substores, useEditorState } from '../../editor/store/store-hook' import type { DerivedSubstate, MetadataSubstate, + NavigatorTargetsSubstate, ProjectContentAndMetadataSubstate, PropertyControlsInfoSubstate, } from '../../editor/store/store-hook-substore-types' @@ -56,6 +57,10 @@ import { SyntheticNavigatorItemContainer, } from './navigator-item-dnd-container' import { CondensedEntryItemWrapper } from './navigator-condensed-entry' +import { + navigatorTargetsSelector, + navigatorTargetsSelectorNavigatorTargets, +} from '../navigator-utils' interface NavigatorItemWrapperProps { index: number @@ -75,10 +80,10 @@ const targetElementMetadataSelector = createCachedSelector( )((_, navigatorEntry) => navigatorEntryToKey(navigatorEntry)) const targetInNavigatorItemsSelector = createCachedSelector( - (store: EditorStorePatched) => store.derived.navigatorTargets, + navigatorTargetsSelector, (store: EditorStorePatched, target: NavigatorEntry) => target, (navigatorTargets, target) => { - return navigatorTargets.some((navigatorTarget) => { + return navigatorTargets.navigatorTargets.some((navigatorTarget) => { return navigatorEntriesEqual(target, navigatorTarget) }) }, @@ -142,11 +147,11 @@ export const labelSelector = createCachedSelector( )((_, navigatorEntry) => navigatorEntryToKey(navigatorEntry)) const noOfChildrenSelector = createCachedSelector( - (store: DerivedSubstate) => store.derived.navigatorTargets, - (_: DerivedSubstate, navigatorEntry: NavigatorEntry) => navigatorEntry, + navigatorTargetsSelector, + (_: NavigatorTargetsSubstate, navigatorEntry: NavigatorEntry) => navigatorEntry, (navigatorTargets, navigatorEntry) => { let result = 0 - for (const nt of navigatorTargets) { + for (const nt of navigatorTargets.navigatorTargets) { if ( isRegularNavigatorEntry(navigatorEntry) && EP.isChildOf(nt.elementPath, navigatorEntry.elementPath) @@ -269,7 +274,7 @@ const SingleEntryNavigatorItemWrapper: React.FunctionComponent< ) const noOfChildren = useEditorState( - Substores.derived, + Substores.navigatorTargetsSubstate, // TODO do not use fullStore here (store) => { return noOfChildrenSelector(store, props.navigatorEntry) }, @@ -325,8 +330,8 @@ const SingleEntryNavigatorItemWrapper: React.FunctionComponent< const label = getNavigatorEntryLabel(props.navigatorEntry, labelForTheElement) const visibleNavigatorTargets = useEditorState( - Substores.derived, - (store) => store.derived.visibleNavigatorTargets, + Substores.navigatorTargetsSubstate, + navigatorTargetsSelectorNavigatorTargets, 'NavigatorItemWrapper navigatorTargets', ) const dispatch = useDispatch() diff --git a/editor/src/components/navigator/navigator-item/navigator-item.spec.browser2.tsx b/editor/src/components/navigator/navigator-item/navigator-item.spec.browser2.tsx index 4dc88f3cab92..3bccb1a7e8e4 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item.spec.browser2.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item.spec.browser2.tsx @@ -1,5 +1,6 @@ import { renderTestEditorWithCode } from '../../canvas/ui-jsx.test-utils' import type { NavigatorEntry } from '../../editor/store/editor-state' +import { getNavigatorTargetsFromEditorState } from '../navigator-utils' import { itemLabelTestIdForEntry } from './item-label' import { layoutIconTestIdForEntry } from './layout-icon' @@ -175,7 +176,9 @@ describe('Navigator item row icons', () => { // https://github.com/concrete-utopia/utopia/issues/4773 it('Should show the correct icons for each type of row', async () => { const editor = await renderTestEditorWithCode(testProjectCode, 'await-first-dom-report') - const visibleNavigatorTargets = editor.getEditorState().derived.visibleNavigatorTargets + const visibleNavigatorTargets = getNavigatorTargetsFromEditorState( + editor.getEditorState().editor, + ).visibleNavigatorTargets async function checkNavigatorIcon( description: string, @@ -313,7 +316,9 @@ describe('Navigator item row icons', () => { // https://github.com/concrete-utopia/utopia/issues/4773 it('Should show the correct labels for each type of row', async () => { const editor = await renderTestEditorWithCode(testProjectCode, 'await-first-dom-report') - const visibleNavigatorTargets = editor.getEditorState().derived.visibleNavigatorTargets + const visibleNavigatorTargets = getNavigatorTargetsFromEditorState( + editor.getEditorState().editor, + ).visibleNavigatorTargets async function checkNavigatorLabel( navigatorEntry: NavigatorEntry, diff --git a/editor/src/components/navigator/navigator-item/run-in-shard-2-component-picker-context-menu.spec.browser2.tsx b/editor/src/components/navigator/navigator-item/run-in-shard-2-component-picker-context-menu.spec.browser2.tsx index 8bc7150dc200..86d2c4ff0ce6 100644 --- a/editor/src/components/navigator/navigator-item/run-in-shard-2-component-picker-context-menu.spec.browser2.tsx +++ b/editor/src/components/navigator/navigator-item/run-in-shard-2-component-picker-context-menu.spec.browser2.tsx @@ -34,6 +34,7 @@ import { ReplaceElementButtonTestId, addChildButtonTestId } from './navigator-it import { NavigatorContainerId } from '../navigator' import { act } from 'react-dom/test-utils' import { cmdModifier } from '../../../utils/modifiers' +import { getNavigatorTargetsFromEditorState } from '../navigator-utils' describe('The navigator component picker context menu', () => { const PreferredChildComponents = [ @@ -1202,7 +1203,11 @@ describe('The navigator component picker context menu', () => { const menuButton = await waitFor(() => editor.renderedDOM.getByText('Flex Hello')) await mouseClickAtPoint(menuButton, { x: 3, y: 3 }) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', 'regular-sb/scene/pg:pg-root', @@ -1213,7 +1218,9 @@ describe('The navigator component picker context menu', () => { 'regular-sb/scene/pg:pg-root/card/contents', ]) expect( - editor.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + editor.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', @@ -1533,7 +1540,9 @@ export const Column = () => ( await trigger(renderResult) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', @@ -1652,7 +1661,9 @@ export const Column = () => ( await trigger(renderResult) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', diff --git a/editor/src/components/navigator/navigator-item/use-navigator-selection-bounds-for-entry.tsx b/editor/src/components/navigator/navigator-item/use-navigator-selection-bounds-for-entry.tsx index 43ed0956a51b..e0f4af4fe7d6 100644 --- a/editor/src/components/navigator/navigator-item/use-navigator-selection-bounds-for-entry.tsx +++ b/editor/src/components/navigator/navigator-item/use-navigator-selection-bounds-for-entry.tsx @@ -3,6 +3,14 @@ import * as EP from '../../../core/shared/element-path' import type { NavigatorEntry } from '../../editor/store/editor-state' import { Substores, useEditorState } from '../../editor/store/store-hook' import { isRegulaNavigatorRow } from '../navigator-row' +import { createSelector } from 'reselect' +import { navigatorTargetsSelector } from '../navigator-utils' + +const navigatorRowsPathsSelector = createSelector(navigatorTargetsSelector, (targets) => { + return targets.navigatorRows.map((row) => + isRegulaNavigatorRow(row) ? row.entry.elementPath : row.entries[0].elementPath, + ) +}) export function useNavigatorSelectionBoundsForEntry( navigatorEntry: NavigatorEntry, @@ -19,12 +27,8 @@ export function useNavigatorSelectionBoundsForEntry( ) const navigatorRowsPaths = useEditorState( - Substores.derived, - (store) => { - return store.derived.navigatorRows.map((row) => - isRegulaNavigatorRow(row) ? row.entry.elementPath : row.entries[0].elementPath, - ) - }, + Substores.navigatorTargetsSubstate, + navigatorRowsPathsSelector, 'useNavigatorSelectionBoundsCheck navigatorRowsPaths', ) diff --git a/editor/src/components/navigator/navigator-map.spec.browser2.tsx b/editor/src/components/navigator/navigator-map.spec.browser2.tsx index 1ed3836faa0a..dc08e64a030d 100644 --- a/editor/src/components/navigator/navigator-map.spec.browser2.tsx +++ b/editor/src/components/navigator/navigator-map.spec.browser2.tsx @@ -10,6 +10,7 @@ import * as EP from '../../core/shared/element-path' import { mouseClickAtPoint } from '../canvas/event-helpers.test-utils' import { navigatorEntryToKey } from '../editor/store/editor-state' import { getMapCounterTestId } from './navigator-item/map-counter' +import { getNavigatorTargetsFromEditorState } from './navigator-utils' function getProjectCode(arr: Array, countOverride?: number): string { return formatTestProjectCode(`import * as React from 'react' @@ -233,7 +234,9 @@ describe('maps in the navigator', () => { expectOverriddenCounterWithCount(counter, overrideCount, overrideSuccess) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual(expectedTargets) }) }) diff --git a/editor/src/components/navigator/navigator-utils.ts b/editor/src/components/navigator/navigator-utils.ts index 78f2579f4e55..5246057df69d 100644 --- a/editor/src/components/navigator/navigator-utils.ts +++ b/editor/src/components/navigator/navigator-utils.ts @@ -17,7 +17,12 @@ import { } from '../../core/shared/element-template' import { MetadataUtils } from '../../core/model/element-metadata-utils' import { isLeft } from '../../core/shared/either' -import type { ConditionalClauseNavigatorEntry, NavigatorEntry } from '../editor/store/editor-state' +import type { + ConditionalClauseNavigatorEntry, + EditorState, + EditorStorePatched, + NavigatorEntry, +} from '../editor/store/editor-state' import { conditionalClauseNavigatorEntry, dataReferenceNavigatorEntry, @@ -56,6 +61,15 @@ import { getUtopiaID } from '../../core/shared/uid-utils' import { emptySet } from '../../core/shared/set-utils' import { objectMap } from '../../core/shared/object-utils' import { dataCanCondenseFromMetadata } from '../../utils/can-condense' +import { createSelector } from 'reselect' +import { Substores, useEditorState } from '../editor/store/store-hook' +import type { + MetadataSubstate, + NavigatorSubstate, + NavigatorTargetsSubstate, + ProjectContentSubstate, + PropertyControlsInfoSubstate, +} from '../editor/store/store-hook-substore-types' export function baseNavigatorDepth(path: ElementPath): number { // The storyboard means that this starts at -1, @@ -793,7 +807,56 @@ function getNavigatorRowsForTree( return condensedTree.flatMap((t) => walkTree(t, 0)) } -export function getNavigatorTargets( +export function getNavigatorTargetsFromEditorState( + editorState: EditorState, +): GetNavigatorTargetsResults { + return navigatorTargetsSelector({ editor: editorState }) +} + +export function useGetNavigatorTargets(): GetNavigatorTargetsResults { + return useEditorState( + Substores.navigatorTargetsSubstate, + navigatorTargetsSelector, + 'useGetNavigatorTargets', + ) +} + +export const navigatorTargetsSelector = createSelector( + (state: NavigatorTargetsSubstate) => state.editor.jsxMetadata, + (state: NavigatorTargetsSubstate) => state.editor.elementPathTree, + (state: NavigatorTargetsSubstate) => state.editor.navigator.collapsedViews, + (state: NavigatorTargetsSubstate) => state.editor.navigator.hiddenInNavigator, + (state: NavigatorTargetsSubstate) => state.editor.propertyControlsInfo, + (state: NavigatorTargetsSubstate) => state.editor.projectContents, + ( + jsxMetadata, + elementPathTree, + collapsedViews, + hiddenInNavigator, + propertyControlsInfo, + projectContents, + ) => + getNavigatorTargets( + jsxMetadata, + elementPathTree, + collapsedViews, + hiddenInNavigator, + propertyControlsInfo, + projectContents, + ), +) + +export const navigatorTargetsSelectorNavigatorTargets = createSelector( + navigatorTargetsSelector, + (results) => results.navigatorTargets, +) + +export const navigatorTargetsSelectorVisibleNavigatorTargets = createSelector( + navigatorTargetsSelector, + (results) => results.visibleNavigatorTargets, +) + +function getNavigatorTargets( metadata: ElementInstanceMetadataMap, elementPathTree: ElementPathTrees, collapsedViews: Array, diff --git a/editor/src/components/navigator/navigator.spec.browser2.tsx b/editor/src/components/navigator/navigator.spec.browser2.tsx index ccb8d9444def..0eab136f609d 100644 --- a/editor/src/components/navigator/navigator.spec.browser2.tsx +++ b/editor/src/components/navigator/navigator.spec.browser2.tsx @@ -54,6 +54,7 @@ import { shiftModifier } from '../../utils/modifiers' import { back, front } from '../../utils/utils' import { createNavigatorReparentPostActionActions } from '../canvas/canvas-strategies/post-action-options/post-action-options' import { createModifiedProject } from '../../sample-projects/sample-project-utils.test-utils' +import { getNavigatorTargetsFromEditorState } from './navigator-utils' const SceneRootId = 'sceneroot' const DragMeId = 'dragme' @@ -1507,7 +1508,9 @@ describe('Navigator', () => { ) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -1581,7 +1584,9 @@ describe('Navigator', () => { ) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -1657,7 +1662,9 @@ describe('Navigator', () => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -1740,7 +1747,9 @@ describe('Navigator', () => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -1759,9 +1768,9 @@ describe('Navigator', () => { 'await-first-dom-report', ) - const originalNavigatorOrder = renderResult - .getEditorState() - .derived.navigatorTargets.map(navigatorEntryToKey) + const originalNavigatorOrder = getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey) const dragMeElement = await renderResult.renderedDOM.findByTestId( `navigator-item-regular_utopia_storyboard_uid/scene_aaa/sceneroot/dragme`, @@ -1807,7 +1816,9 @@ describe('Navigator', () => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual(originalNavigatorOrder) }) @@ -1862,7 +1873,9 @@ describe('Navigator', () => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -1939,7 +1952,9 @@ describe('Navigator', () => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -1995,7 +2010,9 @@ describe('Navigator', () => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -2060,7 +2077,9 @@ describe('Navigator', () => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -2130,7 +2149,9 @@ describe('Navigator', () => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -2183,7 +2204,9 @@ describe('Navigator', () => { ) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/parent2', 'regular-sb/parent2/aaa', @@ -2238,7 +2261,9 @@ describe('Navigator', () => { ) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/parent1', // <- cannot be reparented under its own child 'regular-sb/parent1/child1', @@ -2290,7 +2315,9 @@ describe('Navigator', () => { ) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/parent1', // <- cannot be reparented under `text` 'regular-sb/parent1/child1', @@ -2422,7 +2449,9 @@ describe('Navigator', () => { ) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/parent1', 'regular-sb/parent1/755', @@ -2456,7 +2485,9 @@ describe('Navigator', () => { ) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -2476,9 +2507,9 @@ describe('Navigator', () => { 'await-first-dom-report', ) - const initialOrder = renderResult - .getEditorState() - .derived.navigatorTargets.map(navigatorEntryToKey) + const initialOrder = getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey) const target = EP.fromString( `${BakedInStoryboardUID}/${TestSceneUID}/${SceneRootId}/firstdiv`, @@ -2504,7 +2535,9 @@ describe('Navigator', () => { }) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual(initialOrder) }) }) @@ -2515,9 +2548,9 @@ describe('Navigator', () => { 'await-first-dom-report', ) - const initialOrder = renderResult - .getEditorState() - .derived.navigatorTargets.map(navigatorEntryToKey) + const initialOrder = getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey) const target = EP.fromString( `${BakedInStoryboardUID}/${TestSceneUID}/${SceneRootId}/firstdiv`, @@ -2543,7 +2576,9 @@ describe('Navigator', () => { }) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual(initialOrder) }) @@ -2553,9 +2588,9 @@ describe('Navigator', () => { 'await-first-dom-report', ) - const initialOrder = renderResult - .getEditorState() - .derived.navigatorTargets.map(navigatorEntryToKey) + const initialOrder = getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey) const target = EP.fromString( `${BakedInStoryboardUID}/${TestSceneUID}/${SceneRootId}/seconddiv`, @@ -2586,7 +2621,9 @@ describe('Navigator', () => { }) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual(initialOrder) }) @@ -2642,9 +2679,9 @@ describe('Navigator', () => { y: 2, }) - const startingVisibleNavigatorEntries = editor - .getEditorState() - .derived.visibleNavigatorTargets.map(navigatorEntryToKey) + const startingVisibleNavigatorEntries = getNavigatorTargetsFromEditorState( + editor.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey) expect(startingVisibleNavigatorEntries).toEqual([ 'regular-sb/scene', @@ -2666,7 +2703,9 @@ describe('Navigator', () => { await editor.getDispatchFollowUpActionsFinished() expect( - editor.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + editor.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(startingVisibleNavigatorEntries) }) @@ -2737,9 +2776,9 @@ describe('Navigator', () => { y: 2, }) - const startingVisibleNavigatorEntries = editor - .getEditorState() - .derived.visibleNavigatorTargets.map(navigatorEntryToKey) + const startingVisibleNavigatorEntries = getNavigatorTargetsFromEditorState( + editor.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey) expect(startingVisibleNavigatorEntries).toEqual([ 'regular-sb/scene-1', @@ -2766,7 +2805,9 @@ describe('Navigator', () => { await editor.getDispatchFollowUpActionsFinished() expect( - editor.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + editor.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(startingVisibleNavigatorEntries) }) }) @@ -2833,7 +2874,9 @@ describe('Navigator', () => { ) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -2911,7 +2954,9 @@ describe('Navigator', () => { ) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -2991,7 +3036,9 @@ describe('Navigator', () => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -3078,7 +3125,9 @@ describe('Navigator', () => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -3143,7 +3192,9 @@ describe('Navigator', () => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -3208,7 +3259,9 @@ describe('Navigator', () => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -3288,7 +3341,9 @@ describe('Navigator', () => { ) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -3363,7 +3418,9 @@ describe('Navigator', () => { ) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -3440,7 +3497,9 @@ describe('Navigator', () => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -3524,7 +3583,9 @@ describe('Navigator', () => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -3586,7 +3647,9 @@ describe('Navigator', () => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -3648,7 +3711,9 @@ describe('Navigator', () => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/sceneroot', @@ -3680,7 +3745,11 @@ describe('Navigator', () => { targetElementPath, ) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/app', 'regular-sb/scene/app:root', @@ -3805,7 +3874,11 @@ describe('Navigator', () => { await doBasicDrag(editor, dragMeElementPath, targetElementPath) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:root', @@ -3860,7 +3933,11 @@ describe('Navigator', () => { await doBasicDrag(editor, dragMeElementPath, targetElementPath) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:root', @@ -3915,7 +3992,11 @@ describe('Navigator', () => { await doBasicDrag(editor, dragMeElementPath, targetElementPath) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:root', @@ -3953,7 +4034,11 @@ describe('Navigator', () => { targetElementPath, ) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/app', 'regular-sb/scene/app:root', @@ -3990,7 +4075,11 @@ describe('Navigator', () => { targetElementPath, ) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/app', 'regular-sb/scene/app:root', @@ -4026,7 +4115,11 @@ describe('Navigator', () => { targetElementPath, ) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/app', 'regular-sb/scene/app:root', @@ -4145,7 +4238,11 @@ describe('Navigator', () => { await doBasicDrag(editor, dragMeElementPath, targetElementPath) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:root', @@ -4213,7 +4310,11 @@ describe('Navigator', () => { await doBasicDrag(editor, dragMeElementPath, targetElementPath) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:root', @@ -4316,7 +4417,11 @@ describe('Navigator', () => { await doBasicDrag(editor, dragMeElementPath, targetElementPath, ReparentDropTargetTestId) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:root', @@ -4380,7 +4485,11 @@ describe('Navigator', () => { await doBasicDrag(editor, dragMeElementPath, targetElementPath, ReparentDropTargetTestId) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:root', @@ -4432,7 +4541,11 @@ describe('Navigator', () => { await doBasicDrag(editor, dragMeElementPath, targetElementPath, ReparentDropTargetTestId) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:root', @@ -4483,7 +4596,11 @@ describe('Navigator', () => { await doBasicDrag(editor, dragMeElementPath, targetElementPath, ReparentDropTargetTestId) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:root', @@ -4534,7 +4651,11 @@ describe('Navigator', () => { await doBasicDrag(editor, dragMeElementPath, targetElementPath, ReparentDropTargetTestId) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:root', @@ -4618,7 +4739,11 @@ describe('Navigator', () => { await doBasicDrag(editor, dragMeElementPath, targetElementPath, ReparentDropTargetTestId) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:root', @@ -4707,7 +4832,11 @@ describe('Navigator', () => { ReparentDropTargetTestId, ) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:root', @@ -4802,7 +4931,9 @@ describe('Navigator', () => { ) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', @@ -4867,7 +4998,11 @@ describe('Navigator', () => { await doBasicDrag(editor, dragMeElementPath, targetElementPath, ReparentDropTargetTestId) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', 'regular-utopia-storyboard-uid/scene-aaa/app-entity:root', @@ -4961,7 +5096,9 @@ describe('Navigator', () => { ) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/group', 'regular-sb/group/groupchild', @@ -5013,7 +5150,9 @@ describe('Navigator', () => { ) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/group', 'regular-sb/group/groupchild', @@ -5053,7 +5192,9 @@ describe('Navigator', () => { await renderResult.getDispatchFollowUpActionsFinished() expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-utopia-storyboard-uid/scene-aaa', 'regular-utopia-storyboard-uid/scene-aaa/app-entity', @@ -5092,7 +5233,9 @@ describe('Navigator', () => { await mouseClickAtPoint(renderPropOptionElement, { x: 3, y: 3 }) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', @@ -5104,7 +5247,9 @@ describe('Navigator', () => { 'regular-sb/scene/pg:dbc/78c/d93', ]) expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', @@ -5134,7 +5279,9 @@ describe('Navigator', () => { await mouseClickAtPoint(renderPropOptionElement, { x: 3, y: 3 }) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', @@ -5146,7 +5293,9 @@ describe('Navigator', () => { 'regular-sb/scene/pg:dbc/78c/d93', ]) expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', @@ -5176,7 +5325,9 @@ describe('Navigator', () => { await mouseClickAtPoint(renderPropOptionElement, { x: 3, y: 3 }) expect( - renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).navigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', @@ -5188,7 +5339,9 @@ describe('Navigator', () => { 'regular-sb/scene/pg:dbc/78c/891', ]) expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', @@ -5210,7 +5363,11 @@ describe('Navigator', () => { ) // before the render prop child is deleted - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', 'regular-sb/scene/pg:dbc', @@ -5228,7 +5385,11 @@ describe('Navigator', () => { await pressKey('Backspace') // before the render prop child is deleted - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', 'regular-sb/scene/pg:dbc', @@ -5239,7 +5400,11 @@ describe('Navigator', () => { 'regular-sb/scene/pg:dbc/78c/f59', ]) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', 'regular-sb/scene/pg:dbc', @@ -5260,7 +5425,11 @@ describe('Navigator', () => { ) // before the render prop child is deleted - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', 'regular-sb/scene/pg:dbc', @@ -5278,7 +5447,11 @@ describe('Navigator', () => { await pressKey('Backspace') // before the render prop child is deleted - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', 'regular-sb/scene/pg:dbc', @@ -5289,7 +5462,11 @@ describe('Navigator', () => { 'regular-sb/scene/pg:dbc/78c/f59', ]) - expect(editor.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual([ + expect( + getNavigatorTargetsFromEditorState(editor.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', 'regular-sb/scene/pg:dbc', @@ -5419,34 +5596,36 @@ describe('Navigator row order', () => { await renderResult.dispatch([setFocusedElement(EP.fromString('sb/sc/app:app-root/card'))], true) await renderResult.getDispatchFollowUpActionsFinished() - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-sb/1e7', - 'regular-sb/sc', - 'regular-sb/sc/app', - 'regular-sb/sc/app:app-root', - 'regular-sb/sc/app:app-root/card', - 'regular-sb/sc/app:app-root/card:card-root', - 'regular-sb/sc/app:app-root/card:card-root/30d', - 'regular-sb/sc/app:app-root/card:card-root/card-span', - 'regular-sb/sc/app:app-root/card/card-child', - 'regular-sb/sc/app:app-root/52e', - 'regular-sb/sc/app:app-root/frag', - 'regular-sb/sc/app:app-root/frag/frag-child', - 'regular-sb/sc/app:app-root/frag/cond-1', - 'conditional-clause-sb/sc/app:app-root/frag/cond-1-true-case', - 'regular-sb/sc/app:app-root/frag/cond-1/cond-1-true', - 'regular-sb/sc/app:app-root/frag/cond-1/cond-1-true/cond-1-true-child', - 'regular-sb/sc/app:app-root/frag/cond-1/cond-1-true/cond-2', - 'conditional-clause-sb/sc/app:app-root/frag/cond-1/cond-1-true/cond-2-true-case', - 'regular-sb/sc/app:app-root/frag/cond-1/cond-1-true/cond-2/cond-2-child', - 'conditional-clause-sb/sc/app:app-root/frag/cond-1/cond-1-true/cond-2-false-case', - 'synthetic-sb/sc/app:app-root/frag/cond-1/cond-1-true/cond-2/d84-attribute', - 'conditional-clause-sb/sc/app:app-root/frag/cond-1-false-case', - 'synthetic-sb/sc/app:app-root/frag/cond-1/019-attribute', - 'regular-sb/sc/app/app-child', - ], - ) + expect( + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-sb/1e7', + 'regular-sb/sc', + 'regular-sb/sc/app', + 'regular-sb/sc/app:app-root', + 'regular-sb/sc/app:app-root/card', + 'regular-sb/sc/app:app-root/card:card-root', + 'regular-sb/sc/app:app-root/card:card-root/30d', + 'regular-sb/sc/app:app-root/card:card-root/card-span', + 'regular-sb/sc/app:app-root/card/card-child', + 'regular-sb/sc/app:app-root/52e', + 'regular-sb/sc/app:app-root/frag', + 'regular-sb/sc/app:app-root/frag/frag-child', + 'regular-sb/sc/app:app-root/frag/cond-1', + 'conditional-clause-sb/sc/app:app-root/frag/cond-1-true-case', + 'regular-sb/sc/app:app-root/frag/cond-1/cond-1-true', + 'regular-sb/sc/app:app-root/frag/cond-1/cond-1-true/cond-1-true-child', + 'regular-sb/sc/app:app-root/frag/cond-1/cond-1-true/cond-2', + 'conditional-clause-sb/sc/app:app-root/frag/cond-1/cond-1-true/cond-2-true-case', + 'regular-sb/sc/app:app-root/frag/cond-1/cond-1-true/cond-2/cond-2-child', + 'conditional-clause-sb/sc/app:app-root/frag/cond-1/cond-1-true/cond-2-false-case', + 'synthetic-sb/sc/app:app-root/frag/cond-1/cond-1-true/cond-2/d84-attribute', + 'conditional-clause-sb/sc/app:app-root/frag/cond-1-false-case', + 'synthetic-sb/sc/app:app-root/frag/cond-1/019-attribute', + 'regular-sb/sc/app/app-child', + ]) }) it('is correct for js map expressions with multiple values', async () => { @@ -5457,59 +5636,63 @@ describe('Navigator row order', () => { await renderResult.getDispatchFollowUpActionsFinished() - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-sb/group', - 'regular-sb/group/70f', - 'regular-sb/group/70f/33d~~~1', - 'regular-sb/group/70f/33d~~~1/b1f', - 'regular-sb/group/70f/33d~~~2', - 'regular-sb/group/70f/33d~~~2/b1f', - 'regular-sb/group/70f/33d~~~3', - 'regular-sb/group/70f/33d~~~3/b1f', - 'regular-sb/group/foo', - 'regular-sb/group/b68', - 'regular-sb/group/b68/46a~~~1', - 'regular-sb/group/b68/46a~~~1/255', - 'regular-sb/group/b68/46a~~~2', - 'regular-sb/group/b68/46a~~~2/255', - 'regular-sb/group/b68/46a~~~3', - 'regular-sb/group/b68/46a~~~3/255', - 'regular-sb/group/b68/46a~~~4', - 'regular-sb/group/b68/46a~~~4/255', - 'regular-sb/group/b68/46a~~~5', - 'regular-sb/group/b68/46a~~~5/255', - 'regular-sb/group/b68/46a~~~6', - 'regular-sb/group/b68/46a~~~6/255', - 'regular-sb/group/cond', - 'conditional-clause-sb/group/cond-true-case', - 'regular-sb/group/cond/929', - 'regular-sb/group/cond/929/f23~~~1', - 'regular-sb/group/cond/929/f23~~~1/c6b', - 'regular-sb/group/cond/929/f23~~~2', - 'regular-sb/group/cond/929/f23~~~2/c6b', - 'regular-sb/group/cond/929/f23~~~3', - 'regular-sb/group/cond/929/f23~~~3/c6b', - 'conditional-clause-sb/group/cond-false-case', - 'synthetic-sb/group/cond/235-element-235', - 'regular-sb/group/bar', - 'regular-sb/group/651', - 'regular-sb/group/651/3bc~~~1', - 'regular-sb/group/651/3bc~~~1/7a7', - 'regular-sb/group/651/3bc~~~2', - 'regular-sb/group/651/3bc~~~2/7a7', - 'regular-sb/group/text-expr-cond-wrapper', - 'regular-sb/group/text-expr-cond-wrapper/text-expr-cond', - 'conditional-clause-sb/group/text-expr-cond-wrapper/text-expr-cond-true-case', - 'regular-sb/group/text-expr-cond-wrapper/text-expr-cond/619', - 'conditional-clause-sb/group/text-expr-cond-wrapper/text-expr-cond-false-case', - 'synthetic-sb/group/text-expr-cond-wrapper/text-expr-cond/e4a-element-e4a', - 'regular-sb/group/zero-length-map-wrapper', - 'regular-sb/group/zero-length-map-wrapper/e23', - ], - ) expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-sb/group', + 'regular-sb/group/70f', + 'regular-sb/group/70f/33d~~~1', + 'regular-sb/group/70f/33d~~~1/b1f', + 'regular-sb/group/70f/33d~~~2', + 'regular-sb/group/70f/33d~~~2/b1f', + 'regular-sb/group/70f/33d~~~3', + 'regular-sb/group/70f/33d~~~3/b1f', + 'regular-sb/group/foo', + 'regular-sb/group/b68', + 'regular-sb/group/b68/46a~~~1', + 'regular-sb/group/b68/46a~~~1/255', + 'regular-sb/group/b68/46a~~~2', + 'regular-sb/group/b68/46a~~~2/255', + 'regular-sb/group/b68/46a~~~3', + 'regular-sb/group/b68/46a~~~3/255', + 'regular-sb/group/b68/46a~~~4', + 'regular-sb/group/b68/46a~~~4/255', + 'regular-sb/group/b68/46a~~~5', + 'regular-sb/group/b68/46a~~~5/255', + 'regular-sb/group/b68/46a~~~6', + 'regular-sb/group/b68/46a~~~6/255', + 'regular-sb/group/cond', + 'conditional-clause-sb/group/cond-true-case', + 'regular-sb/group/cond/929', + 'regular-sb/group/cond/929/f23~~~1', + 'regular-sb/group/cond/929/f23~~~1/c6b', + 'regular-sb/group/cond/929/f23~~~2', + 'regular-sb/group/cond/929/f23~~~2/c6b', + 'regular-sb/group/cond/929/f23~~~3', + 'regular-sb/group/cond/929/f23~~~3/c6b', + 'conditional-clause-sb/group/cond-false-case', + 'synthetic-sb/group/cond/235-element-235', + 'regular-sb/group/bar', + 'regular-sb/group/651', + 'regular-sb/group/651/3bc~~~1', + 'regular-sb/group/651/3bc~~~1/7a7', + 'regular-sb/group/651/3bc~~~2', + 'regular-sb/group/651/3bc~~~2/7a7', + 'regular-sb/group/text-expr-cond-wrapper', + 'regular-sb/group/text-expr-cond-wrapper/text-expr-cond', + 'conditional-clause-sb/group/text-expr-cond-wrapper/text-expr-cond-true-case', + 'regular-sb/group/text-expr-cond-wrapper/text-expr-cond/619', + 'conditional-clause-sb/group/text-expr-cond-wrapper/text-expr-cond-false-case', + 'synthetic-sb/group/text-expr-cond-wrapper/text-expr-cond/e4a-element-e4a', + 'regular-sb/group/zero-length-map-wrapper', + 'regular-sb/group/zero-length-map-wrapper/e23', + ]) + expect( + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/group', 'regular-sb/group/70f', @@ -5555,28 +5738,32 @@ describe('Navigator row order', () => { await renderResult.getDispatchFollowUpActionsFinished() - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-sb/group', - 'regular-sb/group/0b5', - 'regular-sb/group/0b5/995~~~1', - 'regular-sb/group/foo', - 'regular-sb/group/809', - 'regular-sb/group/809/ea0~~~1', - 'regular-sb/group/809/ea0~~~2', - 'regular-sb/group/cond', - 'conditional-clause-sb/group/cond-true-case', - 'regular-sb/group/cond/4ce', - 'regular-sb/group/cond/4ce/27d~~~1', - 'conditional-clause-sb/group/cond-false-case', - 'synthetic-sb/group/cond/75a-element-75a', - 'regular-sb/group/bar', - 'regular-sb/group/bf0', - 'regular-sb/group/bf0/b78~~~1', - ], - ) expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-sb/group', + 'regular-sb/group/0b5', + 'regular-sb/group/0b5/995~~~1', + 'regular-sb/group/foo', + 'regular-sb/group/809', + 'regular-sb/group/809/ea0~~~1', + 'regular-sb/group/809/ea0~~~2', + 'regular-sb/group/cond', + 'conditional-clause-sb/group/cond-true-case', + 'regular-sb/group/cond/4ce', + 'regular-sb/group/cond/4ce/27d~~~1', + 'conditional-clause-sb/group/cond-false-case', + 'synthetic-sb/group/cond/75a-element-75a', + 'regular-sb/group/bar', + 'regular-sb/group/bf0', + 'regular-sb/group/bf0/b78~~~1', + ]) + expect( + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/group', 'regular-sb/group/0b5', @@ -5605,20 +5792,24 @@ describe('Navigator row order', () => { await renderResult.getDispatchFollowUpActionsFinished() - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-sb/scene', - 'regular-sb/scene/pg', - 'regular-sb/scene/pg:dbc', - 'regular-sb/scene/pg:dbc/78c', - 'render-prop-sb/scene/pg:dbc/78c/prop-label-header-header', - 'render-prop-value-sb/scene/pg:dbc/78c/298-header', - 'render-prop-sb/scene/pg:dbc/78c/prop-label-children-children', - 'regular-sb/scene/pg:dbc/78c/d93', - ], - ) expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-sb/scene', + 'regular-sb/scene/pg', + 'regular-sb/scene/pg:dbc', + 'regular-sb/scene/pg:dbc/78c', + 'render-prop-sb/scene/pg:dbc/78c/prop-label-header-header', + 'render-prop-value-sb/scene/pg:dbc/78c/298-header', + 'render-prop-sb/scene/pg:dbc/78c/prop-label-children-children', + 'regular-sb/scene/pg:dbc/78c/d93', + ]) + expect( + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', @@ -5638,20 +5829,24 @@ describe('Navigator row order', () => { await renderResult.getDispatchFollowUpActionsFinished() - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-sb/scene', - 'regular-sb/scene/pg', - 'regular-sb/scene/pg:dbc', - 'regular-sb/scene/pg:dbc/78c', - 'render-prop-sb/scene/pg:dbc/78c/prop-label-header-header', - 'synthetic-sb/scene/pg:dbc/78c/ee8-attribute', - 'render-prop-sb/scene/pg:dbc/78c/prop-label-children-children', - 'regular-sb/scene/pg:dbc/78c/d93', - ], - ) expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-sb/scene', + 'regular-sb/scene/pg', + 'regular-sb/scene/pg:dbc', + 'regular-sb/scene/pg:dbc/78c', + 'render-prop-sb/scene/pg:dbc/78c/prop-label-header-header', + 'synthetic-sb/scene/pg:dbc/78c/ee8-attribute', + 'render-prop-sb/scene/pg:dbc/78c/prop-label-children-children', + 'regular-sb/scene/pg:dbc/78c/d93', + ]) + expect( + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', @@ -5670,20 +5865,24 @@ describe('Navigator row order', () => { ) await renderResult.getDispatchFollowUpActionsFinished() - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-sb/scene', - 'regular-sb/scene/pg', - 'regular-sb/scene/pg:dbc', - 'regular-sb/scene/pg:dbc/78c', - 'render-prop-sb/scene/pg:dbc/78c/prop-label-header-header', - 'slot_sb/scene/pg:dbc/78c/prop-label-header', // <- the slot is shown - 'render-prop-sb/scene/pg:dbc/78c/prop-label-children-children', - 'regular-sb/scene/pg:dbc/78c/d93', - ], - ) expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-sb/scene', + 'regular-sb/scene/pg', + 'regular-sb/scene/pg:dbc', + 'regular-sb/scene/pg:dbc/78c', + 'render-prop-sb/scene/pg:dbc/78c/prop-label-header-header', + 'slot_sb/scene/pg:dbc/78c/prop-label-header', // <- the slot is shown + 'render-prop-sb/scene/pg:dbc/78c/prop-label-children-children', + 'regular-sb/scene/pg:dbc/78c/d93', + ]) + expect( + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', @@ -5703,20 +5902,24 @@ describe('Navigator row order', () => { await renderResult.getDispatchFollowUpActionsFinished() - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-sb/scene', - 'regular-sb/scene/pg', - 'regular-sb/scene/pg:dbc', - 'regular-sb/scene/pg:dbc/78c', - 'render-prop-sb/scene/pg:dbc/78c/prop-label-header-header', - 'slot_sb/scene/pg:dbc/78c/prop-label-header', // <- the slot is shown - 'render-prop-sb/scene/pg:dbc/78c/prop-label-children-children', - 'regular-sb/scene/pg:dbc/78c/d93', - ], - ) expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-sb/scene', + 'regular-sb/scene/pg', + 'regular-sb/scene/pg:dbc', + 'regular-sb/scene/pg:dbc/78c', + 'render-prop-sb/scene/pg:dbc/78c/prop-label-header-header', + 'slot_sb/scene/pg:dbc/78c/prop-label-header', // <- the slot is shown + 'render-prop-sb/scene/pg:dbc/78c/prop-label-children-children', + 'regular-sb/scene/pg:dbc/78c/d93', + ]) + expect( + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', @@ -5737,20 +5940,24 @@ describe('Navigator row order', () => { await renderResult.getDispatchFollowUpActionsFinished() - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-sb/scene', - 'regular-sb/scene/pg', - 'regular-sb/scene/pg:dbc', - 'regular-sb/scene/pg:dbc/78c', - 'render-prop-sb/scene/pg:dbc/78c/prop-label-header-header', // <- the name of this is coming from an import - 'slot_sb/scene/pg:dbc/78c/prop-label-header', - 'render-prop-sb/scene/pg:dbc/78c/prop-label-children-children', - 'regular-sb/scene/pg:dbc/78c/891', - ], - ) expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual([ + 'regular-sb/scene', + 'regular-sb/scene/pg', + 'regular-sb/scene/pg:dbc', + 'regular-sb/scene/pg:dbc/78c', + 'render-prop-sb/scene/pg:dbc/78c/prop-label-header-header', // <- the name of this is coming from an import + 'slot_sb/scene/pg:dbc/78c/prop-label-header', + 'render-prop-sb/scene/pg:dbc/78c/prop-label-children-children', + 'regular-sb/scene/pg:dbc/78c/891', + ]) + expect( + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual([ 'regular-sb/scene', 'regular-sb/scene/pg', @@ -5771,11 +5978,15 @@ describe('Navigator row order', () => { await renderResult.getDispatchFollowUpActionsFinished() - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - ['regular-sb/scene'], - ) expect( - renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + getNavigatorTargetsFromEditorState(renderResult.getEditorState().editor).navigatorTargets.map( + navigatorEntryToKey, + ), + ).toEqual(['regular-sb/scene']) + expect( + getNavigatorTargetsFromEditorState( + renderResult.getEditorState().editor, + ).visibleNavigatorTargets.map(navigatorEntryToKey), ).toEqual(['regular-sb/scene']) }) }) diff --git a/editor/src/components/navigator/navigator.tsx b/editor/src/components/navigator/navigator.tsx index 35b0a26cca88..a889f6c6c3e8 100644 --- a/editor/src/components/navigator/navigator.tsx +++ b/editor/src/components/navigator/navigator.tsx @@ -20,7 +20,7 @@ import { showContextMenu, } from '../editor/actions/action-creators' import { useDispatch } from '../editor/store/dispatch-context' -import type { NavigatorEntry } from '../editor/store/editor-state' +import type { EditorStorePatched, NavigatorEntry } from '../editor/store/editor-state' import { isRegularNavigatorEntry, navigatorEntryToKey, @@ -35,40 +35,63 @@ import { NavigatorItemWrapper } from './navigator-item/navigator-item-wrapper' import type { CondensedNavigatorRow, NavigatorRow, RegularNavigatorRow } from './navigator-row' import { getEntriesForRow } from './navigator-row' import { assertNever } from '../../core/shared/utils' +import { + navigatorTargetsSelector, + navigatorTargetsSelectorVisibleNavigatorTargets, +} from './navigator-utils' +import { createSelector } from 'reselect' +import createCachedSelector from 're-reselect' +import type { + NavigatorTargetsSubstate, + SelectedViewsSubstate, +} from '../editor/store/store-hook-substore-types' interface ItemProps extends ListChildComponentProps {} +const currentlySelectedNavigatorEntriesSelector = createSelector( + navigatorTargetsSelector, + (store: EditorStorePatched) => store.editor.selectedViews, + (navigatorTargets, selectedViews) => { + return getSelectedNavigatorEntries(selectedViews, navigatorTargets.navigatorTargets) + }, +) + +const targetEntrySelector = createCachedSelector( + navigatorTargetsSelector, + (_: NavigatorTargetsSubstate, index: number) => index, + (navigatorTargets, index) => navigatorTargets.navigatorRows[index], +)((_, index) => index) + const Item = React.memo(({ index, style }: ItemProps) => { - const visibleNavigatorTargets = useEditorState( - Substores.derived, - (store) => store.derived.navigatorRows, - 'Item visibleNavigatorTargets', + const targetEntry = useEditorState( + Substores.navigatorTargetsSubstate, + (store) => targetEntrySelector(store, index), + 'Item navigatorRows', ) + const editorSliceRef = useRefEditorState((store) => { - const currentlySelectedNavigatorEntries = getSelectedNavigatorEntries( - store.editor.selectedViews, - store.derived.navigatorTargets, - ) return { selectedViews: store.editor.selectedViews, - navigatorTargets: store.derived.navigatorTargets, - visibleNavigatorTargets: store.derived.visibleNavigatorTargets, - currentlySelectedNavigatorEntries: currentlySelectedNavigatorEntries, } }) + const navigatorTargetsRef = useRefEditorState(navigatorTargetsSelector) + const currentlySelectedNavigatorEntriesRef = useRefEditorState( + currentlySelectedNavigatorEntriesSelector, + ) + const getCurrentlySelectedNavigatorEntries = React.useCallback((): Array => { - return editorSliceRef.current.currentlySelectedNavigatorEntries - }, [editorSliceRef]) + return currentlySelectedNavigatorEntriesRef.current + }, [currentlySelectedNavigatorEntriesRef]) const visibleTargetIndexToRegularIndex = React.useCallback( (visibleTargetIndex: number) => { const visibleNavigatorEntry = - editorSliceRef.current.visibleNavigatorTargets[visibleTargetIndex] + navigatorTargetsRef.current.visibleNavigatorTargets[visibleTargetIndex] if (visibleNavigatorEntry == null) { return null } else { - const targetIndex = editorSliceRef.current.navigatorTargets.findIndex((target) => + const targetIndex = navigatorTargetsRef.current.navigatorTargets.findIndex((target) => navigatorEntriesEqual(target, visibleNavigatorEntry), ) if (targetIndex >= 0) { @@ -78,7 +101,7 @@ const Item = React.memo(({ index, style }: ItemProps) => { } } }, - [editorSliceRef], + [navigatorTargetsRef], ) // Used to determine the views that will be selected by starting with the last selected item @@ -87,7 +110,7 @@ const Item = React.memo(({ index, style }: ItemProps) => { (visibleTargetIndex: number): Array => { const selectedItemIndexes = editorSliceRef.current.selectedViews .map((selection) => - editorSliceRef.current.navigatorTargets.findIndex( + navigatorTargetsRef.current.navigatorTargets.findIndex( (entry) => isRegularNavigatorEntry(entry) && EP.pathsEqual(entry.elementPath, selection), ), @@ -100,7 +123,7 @@ const Item = React.memo(({ index, style }: ItemProps) => { } const lastSelectedItemIndex = last(selectedItemIndexes) if (lastSelectedItemIndex == null) { - const lastSelectedItem = editorSliceRef.current.navigatorTargets[targetIndex] + const lastSelectedItem = navigatorTargetsRef.current.navigatorTargets[targetIndex] if (isRegularNavigatorEntry(lastSelectedItem)) { return [lastSelectedItem.elementPath] } else { @@ -120,7 +143,7 @@ const Item = React.memo(({ index, style }: ItemProps) => { end = lastSelectedItemIndex } let selectedViewTargets: Array = editorSliceRef.current.selectedViews - Utils.fastForEach(editorSliceRef.current.navigatorTargets, (item, itemIndex) => { + Utils.fastForEach(navigatorTargetsRef.current.navigatorTargets, (item, itemIndex) => { if (itemIndex >= start && itemIndex <= end && isRegularNavigatorEntry(item)) { selectedViewTargets = EP.addPathIfMissing(item.elementPath, selectedViewTargets) } @@ -128,10 +151,9 @@ const Item = React.memo(({ index, style }: ItemProps) => { return selectedViewTargets } }, - [editorSliceRef, visibleTargetIndexToRegularIndex], + [editorSliceRef, navigatorTargetsRef, visibleTargetIndexToRegularIndex], ) - const targetEntry = visibleNavigatorTargets[index] const componentKey = navigatorRowToKey(targetEntry) const deepKeptStyle = useKeepReferenceEqualityIfPossible(style) @@ -150,28 +172,41 @@ const Item = React.memo(({ index, style }: ItemProps) => { export const NavigatorContainerId = 'navigator' +const selectionIndexSelector = createSelector( + navigatorTargetsSelector, + (store: SelectedViewsSubstate) => store.editor.selectedViews, + (navigatorTargets, selectedViews) => { + const selectionIndex = + selectedViews == null + ? -1 + : navigatorTargets.navigatorRows.findIndex((entry) => { + return getEntriesForRow(entry).some( + (e) => isRegularNavigatorEntry(e) && EP.pathsEqual(e.elementPath, selectedViews[0]), + ) + }) + return selectionIndex + }, +) + export const NavigatorComponent = React.memo(() => { const dispatch = useDispatch() - const { minimised, visibleNavigatorTargets, selectionIndex } = useEditorState( - Substores.fullStore, + const minimised = useEditorState( + Substores.navigator, (store) => { - const selectedViews = store.editor.selectedViews - const innerVisibleNavigatorTargets = store.derived.navigatorRows - const innerSelectionIndex = - selectedViews == null - ? -1 - : innerVisibleNavigatorTargets.findIndex((entry) => { - return getEntriesForRow(entry).some( - (e) => isRegularNavigatorEntry(e) && EP.pathsEqual(e.elementPath, selectedViews[0]), - ) - }) - return { - minimised: store.editor.navigator.minimised, - visibleNavigatorTargets: innerVisibleNavigatorTargets, - selectionIndex: innerSelectionIndex, - } + return store.editor.navigator.minimised }, - 'NavigatorComponent', + 'NavigatorComponent navigator.minimised', + ) + const selectionIndex = useEditorState( + Substores.fullStore, + selectionIndexSelector, + 'NavigatorComponent selectionIndexSelector', + ) + + const { navigatorRows } = useEditorState( + Substores.navigatorTargetsSubstate, + navigatorTargetsSelector, + 'NavigatorComponent navigatorTargetsSelector', ) const itemListRef = React.createRef() @@ -188,10 +223,10 @@ export const NavigatorComponent = React.memo(() => { * When a reorder happens, the items are offset, and the cached sizes are not applied to the right items anymore * resetAfterIndex(0, false) clears the cached size of all items, and false means it does not force a re-render * - * as a first approximation, this useEffect runs on any change to visibleNavigatorTargets + * as a first approximation, this useEffect runs on any change to navigatorRows */ itemListRef.current?.resetAfterIndex(0, false) - }, [visibleNavigatorTargets, itemListRef]) + }, [navigatorRows, itemListRef]) const onFocus = React.useCallback( (e: React.FocusEvent) => { @@ -216,7 +251,7 @@ export const NavigatorComponent = React.memo(() => { const getItemSize = React.useCallback( (entryIndex: number) => { - const navigatorRow = safeIndex(visibleNavigatorTargets, entryIndex) + const navigatorRow = safeIndex(navigatorRows, entryIndex) if (navigatorRow == null) { throw new Error(`Could not find navigator entry at index ${entryIndex}`) } @@ -228,7 +263,7 @@ export const NavigatorComponent = React.memo(() => { } assertNever(navigatorRow) }, - [visibleNavigatorTargets], + [navigatorRows], ) const ItemList = (size: Size) => { @@ -241,7 +276,7 @@ export const NavigatorComponent = React.memo(() => { width={'100%'} height={size.height} itemSize={getItemSize} - itemCount={visibleNavigatorTargets.length} + itemCount={navigatorRows.length} layout={'vertical'} style={{ overflowX: 'hidden' }} > diff --git a/editor/src/core/model/performance-scripts.tsx b/editor/src/core/model/performance-scripts.tsx index 95c7509a1711..a1abc365d53c 100644 --- a/editor/src/core/model/performance-scripts.tsx +++ b/editor/src/core/model/performance-scripts.tsx @@ -181,12 +181,6 @@ async function loadProject( return editorReady } -const storeToAllRegularPaths = fromField('derived') - .compose(fromField('navigatorTargets')) - .compose(traverseArray()) - .compose(regularNavigatorEntryOptic) - .compose(fromField('elementPath')) - export function useTriggerScrollPerformanceTest(): () => void { const dispatch = useDispatch() as DebugDispatch const builtInDependencies = useEditorState( @@ -199,7 +193,9 @@ export function useTriggerScrollPerformanceTest(): () => void { (store) => store.editor.id, 'useTriggerScrollPerformanceTest id', ) - const allPaths = useRefEditorState((store) => toArrayOf(storeToAllRegularPaths, store)) + const allPaths = useRefEditorState((store) => + MetadataUtils.getAllPaths(store.editor.jsxMetadata, store.editor.elementPathTree), + ) const trigger = React.useCallback(async () => { const editorReady = await loadProject( dispatch, @@ -243,7 +239,9 @@ export function useTriggerScrollPerformanceTest(): () => void { } function useTriggerHighlightPerformanceTest(key: 'regular' | 'all-elements'): () => void { - const allPaths = useRefEditorState((store) => toArrayOf(storeToAllRegularPaths, store)) + const allPaths = useRefEditorState((store) => + MetadataUtils.getAllPaths(store.editor.jsxMetadata, store.editor.elementPathTree), + ) const getHighlightableViews = useGetSelectableViewsForSelectMode() const calculateHighlightedViews = useCalculateHighlightedViews(true, getHighlightableViews) const dispatch = useDispatch() as DebugDispatch @@ -322,7 +320,9 @@ export const useTriggerAllElementsHighlightPerformanceTest = () => export function useTriggerSelectionPerformanceTest(): () => void { const dispatch = useDispatch() as DebugDispatch - const allPaths = useRefEditorState((store) => toArrayOf(storeToAllRegularPaths, store)) + const allPaths = useRefEditorState((store) => + MetadataUtils.getAllPaths(store.editor.jsxMetadata, store.editor.elementPathTree), + ) const selectedViews = useRefEditorState((store) => store.editor.selectedViews) const builtInDependencies = useEditorState( Substores.restOfStore, @@ -458,8 +458,8 @@ export function useTriggerAbsoluteMovePerformanceTest( projectContents: ProjectContentTreeRoot, ): () => void { const dispatch = useDispatch() as DebugDispatch - const allPaths = useRefEditorState( - React.useCallback((store) => toArrayOf(storeToAllRegularPaths, store), []), + const allPaths = useRefEditorState((store) => + MetadataUtils.getAllPaths(store.editor.jsxMetadata, store.editor.elementPathTree), ) const metadata = useRefEditorState(React.useCallback((store) => store.editor.jsxMetadata, [])) const builtInDependencies = useEditorState( @@ -651,8 +651,8 @@ export function useTriggerAbsoluteMovePerformanceTest( export function useTriggerSelectionChangePerformanceTest(): () => void { const projectContents = LargeProjectContents const dispatch = useDispatch() as DebugDispatch - const allPaths = useRefEditorState( - React.useCallback((store) => toArrayOf(storeToAllRegularPaths, store), []), + const allPaths = useRefEditorState((store) => + MetadataUtils.getAllPaths(store.editor.jsxMetadata, store.editor.elementPathTree), ) const metadata = useRefEditorState(React.useCallback((store) => store.editor.jsxMetadata, [])) const builtInDependencies = useEditorState( 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 d8bfacc44e7c..a97427908fa2 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 @@ -1315,6 +1315,17 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", + "/div/div/NavigatorComponent/Symbol(react.memo)()", + "/div/div/NavigatorComponent/Symbol(react.memo)(NavigatorDragLayer)", + "/div/div/NavigatorComponent/UtopiaSpiedClass(AutoSizer)", + "/div/div/NavigatorComponent/Symbol(react.forward_ref)(Styled(div))", + "/div/div/NavigatorComponent/Symbol(react.forward_ref)(Styled(div))", + "/div/div/NavigatorComponent/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='navigator'", + "/div/NavigatorComponent/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div)):data-testid='navigator'", + "/NavigatorComponent/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div))/div:data-testid='navigator'", + "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", + "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", + "/Symbol(react.forward_ref)(Styled(div))/div/UtopiaSpiedClass(AutoSizer)/div", "////UtopiaSpiedFunctionComponent()", "////UtopiaSpiedExoticType(Symbol(react.provider))", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/UtopiaSpiedFunctionComponent()/UtopiaSpiedExoticType(Symbol(react.provider))", @@ -1634,6 +1645,17 @@ Array [ "/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", + "/div/div/NavigatorComponent/Symbol(react.memo)()", + "/div/div/NavigatorComponent/Symbol(react.memo)(NavigatorDragLayer)", + "/div/div/NavigatorComponent/UtopiaSpiedClass(AutoSizer)", + "/div/div/NavigatorComponent/Symbol(react.forward_ref)(Styled(div))", + "/div/div/NavigatorComponent/Symbol(react.forward_ref)(Styled(div))", + "/div/div/NavigatorComponent/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='navigator'", + "/div/NavigatorComponent/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div)):data-testid='navigator'", + "/NavigatorComponent/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div))/div:data-testid='navigator'", + "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", + "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", + "/Symbol(react.forward_ref)(Styled(div))/div/UtopiaSpiedClass(AutoSizer)/div", "/Symbol(react.provider)///Symbol(react.memo)(Inspector)", "/Symbol(react.provider)///Symbol(react.memo)()", "////UtopiaSpiedFunctionComponent()", @@ -2461,6 +2483,17 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", + "/div/div/NavigatorComponent/Symbol(react.memo)()", + "/div/div/NavigatorComponent/Symbol(react.memo)(NavigatorDragLayer)", + "/div/div/NavigatorComponent/UtopiaSpiedClass(AutoSizer)", + "/div/div/NavigatorComponent/Symbol(react.forward_ref)(Styled(div))", + "/div/div/NavigatorComponent/Symbol(react.forward_ref)(Styled(div))", + "/div/div/NavigatorComponent/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='navigator'", + "/div/NavigatorComponent/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div)):data-testid='navigator'", + "/NavigatorComponent/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div))/div:data-testid='navigator'", + "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", + "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", + "/Symbol(react.forward_ref)(Styled(div))/div/UtopiaSpiedClass(AutoSizer)/div", "////UtopiaSpiedFunctionComponent()", "////UtopiaSpiedExoticType(Symbol(react.provider))", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/UtopiaSpiedFunctionComponent()/UtopiaSpiedExoticType(Symbol(react.provider))", @@ -2768,6 +2801,17 @@ Array [ "/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", + "/div/div/NavigatorComponent/Symbol(react.memo)()", + "/div/div/NavigatorComponent/Symbol(react.memo)(NavigatorDragLayer)", + "/div/div/NavigatorComponent/UtopiaSpiedClass(AutoSizer)", + "/div/div/NavigatorComponent/Symbol(react.forward_ref)(Styled(div))", + "/div/div/NavigatorComponent/Symbol(react.forward_ref)(Styled(div))", + "/div/div/NavigatorComponent/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='navigator'", + "/div/NavigatorComponent/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div)):data-testid='navigator'", + "/NavigatorComponent/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div))/div:data-testid='navigator'", + "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", + "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", + "/Symbol(react.forward_ref)(Styled(div))/div/UtopiaSpiedClass(AutoSizer)/div", "/Symbol(react.provider)///Symbol(react.memo)(Inspector)", "/Symbol(react.provider)///Symbol(react.memo)()", "////UtopiaSpiedFunctionComponent()", diff --git a/editor/src/core/performance/performance-regression-tests.spec.tsx b/editor/src/core/performance/performance-regression-tests.spec.tsx index dc9294576202..49c9be720d0e 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(`793`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`815`) 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(`1141`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`1163`) expect(renderResult.getRenderInfo()).toMatchSnapshot() })