diff --git a/editor/src/components/canvas/canvas-strategies/strategies/absolute-flex-reparent-strategy-helpers.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/absolute-flex-reparent-strategy-helpers.spec.browser2.tsx index 2878285b03f9..ec806d991cf4 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/absolute-flex-reparent-strategy-helpers.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/absolute-flex-reparent-strategy-helpers.spec.browser2.tsx @@ -37,6 +37,7 @@ async function dragElement( modifiers: Modifiers, includeMouseUp: boolean, midDragCallback?: () => Promise, + mouseDownModifiers?: Modifiers, ): Promise { const targetElement = renderResult.renderedDOM.getByTestId(targetTestId) const targetElementBounds = targetElement.getBoundingClientRect() @@ -51,10 +52,11 @@ async function dragElement( if (includeMouseUp) { await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint, { modifiers: modifiers, + mouseDownModifiers: mouseDownModifiers, midDragCallback: midDragCallback, }) } else { - await mouseDownAtPoint(canvasControlsLayer, startPoint, { modifiers: modifiers }) + await mouseDownAtPoint(canvasControlsLayer, startPoint) await mouseMoveToPoint(canvasControlsLayer, endPoint, { modifiers: modifiers, eventOptions: { buttons: 1 }, diff --git a/editor/src/components/canvas/canvas-strategies/strategies/absolute-move-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/absolute-move-strategy.spec.browser2.tsx index 6c18d89c5a5f..537d4d8ca82c 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/absolute-move-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/absolute-move-strategy.spec.browser2.tsx @@ -52,6 +52,7 @@ async function dragByPixels( delta: WindowPoint, testid: string, modifiers: Modifiers = emptyModifiers, + mouseDownModifiers?: Modifiers, ) { const targetElement = editor.renderedDOM.getByTestId(testid) const targetElementBounds = targetElement.getBoundingClientRect() @@ -60,6 +61,7 @@ async function dragByPixels( await mouseDragFromPointWithDelta(canvasControlsLayer, targetElementCenter, delta, { modifiers, + mouseDownModifiers, midDragCallback: async () => { NO_OP() }, @@ -72,8 +74,9 @@ async function dragElement( dragDelta: WindowPoint, modifiers: Modifiers, midDragCallback?: () => Promise, + mouseDownModifiers?: Modifiers, ): Promise { - await mouseDownAtPoint(canvasControlsLayer, startPoint, { modifiers: cmdModifier }) + await mouseDownAtPoint(canvasControlsLayer, startPoint, { modifiers: mouseDownModifiers }) await mouseDragFromPointWithDelta(canvasControlsLayer, startPoint, dragDelta, { modifiers, midDragCallback, @@ -316,7 +319,7 @@ describe('Absolute Move Strategy', () => { await selectComponentsForTest(editor, [targetElement]) - await dragByPixels(editor, windowPoint({ x: 15, y: 15 }), 'bbb', cmdModifier) + await dragByPixels(editor, windowPoint({ x: 15, y: 15 }), 'bbb') expect(getPrintedUiJsCode(editor.getEditorState())).toEqual( makeTestProjectCodeWithSnippet( @@ -947,8 +950,6 @@ describe('Absolute Move Strategy', () => { EP.fromString(`${BakedInStoryboardUID}/${TestSceneUID}/${TestAppUID}:aaa/bbb/ccc`), ]) - // await wait(10000) - await dragByPixels(editor, windowPoint({ x: 15, y: 15 }), 'bbb') expect(getPrintedUiJsCode(editor.getEditorState())).toEqual( @@ -1215,7 +1216,14 @@ describe('Absolute Move Strategy', () => { const startPoint = windowPoint({ x: targetElementBounds.x + 5, y: targetElementBounds.y + 5 }) const dragDelta = windowPoint({ x: 40, y: 25 }) - await dragElement(canvasControlsLayer, startPoint, dragDelta, emptyModifiers) + await dragElement( + canvasControlsLayer, + startPoint, + dragDelta, + cmdModifier, + undefined, + cmdModifier, + ) await renderResult.getDispatchFollowUpActionsFinished() expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( 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 49083754b234..20884f475651 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 @@ -72,6 +72,7 @@ async function dragElement( modifiers: Modifiers, checkCursor: CheckCursor | null, midDragCallback: (() => Promise) | null, + mouseDownModifiers?: Modifiers, ) { const targetElement = renderResult.renderedDOM.getByTestId(targetTestId) const targetElementBounds = targetElement.getBoundingClientRect() @@ -90,6 +91,7 @@ async function dragElement( await mouseClickAtPoint(canvasControlsLayer, startPoint, { modifiers: cmdModifier }) await mouseDragFromPointWithDelta(canvasControlsLayer, startPoint, dragDelta, { modifiers: modifiers, + mouseDownModifiers: mouseDownModifiers, midDragCallback: combinedMidDragCallback, }) } @@ -1325,7 +1327,15 @@ export var ${BakedInStoryboardVariableName} = (props) => { ) const dragDelta = windowPoint({ x: 50, y: 0 }) - await dragElement(renderResult, 'child-1', dragDelta, cmdModifier, null, null) + await dragElement( + renderResult, + 'child-1', + dragDelta, + cmdModifier, + null, + null, + cmdModifier, + ) await renderResult.getDispatchFollowUpActionsFinished() diff --git a/editor/src/components/canvas/canvas-strategies/strategies/convert-to-absolute-and-move-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/convert-to-absolute-and-move-strategy.spec.browser2.tsx index e711710d7e34..014c148bdef7 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/convert-to-absolute-and-move-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/convert-to-absolute-and-move-strategy.spec.browser2.tsx @@ -55,6 +55,7 @@ import { import { selectComponentsForTest } from '../../../../utils/utils.test-utils' import { ConvertToAbsoluteAndMoveStrategyID } from './convert-to-absolute-and-move-strategy' import CanvasActions from '../../canvas-actions' +import { ctrlModifier } from '../../../../utils/modifiers' const complexProject = () => { const code = ` @@ -1140,12 +1141,7 @@ describe('Convert to absolute/escape hatch', () => { y: elementBounds.y + 10, }, { - modifiers: { - alt: false, - cmd: true, - ctrl: true, - shift: false, - }, + modifiers: ctrlModifier, }, ) @@ -1805,12 +1801,7 @@ describe('Escape hatch strategy on awkward project', () => { y: 15, }, { - modifiers: { - alt: false, - cmd: true, - ctrl: true, - shift: false, - }, + modifiers: ctrlModifier, }, ) diff --git a/editor/src/components/canvas/controls/select-mode/select-mode-hooks.tsx b/editor/src/components/canvas/controls/select-mode/select-mode-hooks.tsx index 33dabf21c3f4..2703490e0f4b 100644 --- a/editor/src/components/canvas/controls/select-mode/select-mode-hooks.tsx +++ b/editor/src/components/canvas/controls/select-mode/select-mode-hooks.tsx @@ -303,7 +303,7 @@ function getCandidateSelectableViews( export function useFindValidTarget(): ( selectableViews: Array, mousePoint: WindowPoint | null, - preferAlreadySelected: 'prefer-selected' | 'dont-prefer-selected', + preferAlreadySelected: 'prefer-selected' | 'prefer-more-specific-selection', ) => { elementPath: ElementPath isSelected: boolean @@ -325,7 +325,7 @@ export function useFindValidTarget(): ( ( selectableViews: Array, mousePoint: WindowPoint | null, - preferAlreadySelected: 'prefer-selected' | 'dont-prefer-selected', + preferAlreadySelected: 'prefer-selected' | 'prefer-more-specific-selection', ) => { const { selectedViews, @@ -336,26 +336,43 @@ export function useFindValidTarget(): ( elementPathTree, allElementProps, } = storeRef.current - const validElementMouseOver: ElementPath | null = - preferAlreadySelected === 'prefer-selected' - ? getSelectionOrValidTargetAtPoint( - componentMetadata, - selectedViews, - hiddenInstances, - selectableViews, - mousePoint, - canvasScale, - canvasOffset, - elementPathTree, - allElementProps, - ) - : getValidTargetAtPoint( - selectableViews, - mousePoint, - canvasScale, - canvasOffset, - componentMetadata, - ) + const validElementMouseOver: ElementPath | null = (() => { + if (preferAlreadySelected === 'prefer-selected') { + return getSelectionOrValidTargetAtPoint( + componentMetadata, + selectedViews, + hiddenInstances, + selectableViews, + mousePoint, + canvasScale, + canvasOffset, + elementPathTree, + allElementProps, + ) + } + const newSelection = getValidTargetAtPoint( + selectableViews, + mousePoint, + canvasScale, + canvasOffset, + componentMetadata, + ) + if (newSelection != null) { + return newSelection + } + return getSelectionOrValidTargetAtPoint( + componentMetadata, + selectedViews, + hiddenInstances, + selectableViews, + mousePoint, + canvasScale, + canvasOffset, + elementPathTree, + allElementProps, + ) + })() + const validElementPath: ElementPath | null = validElementMouseOver != null ? validElementMouseOver : null if (validElementPath != null) { @@ -452,7 +469,11 @@ export function useCalculateHighlightedViews( return React.useCallback( (targetPoint: WindowPoint, eventCmdPressed: boolean) => { const selectableViews: Array = getHighlightableViews(eventCmdPressed, false) - const validElementPath = findValidTarget(selectableViews, targetPoint, 'dont-prefer-selected') + const validElementPath = findValidTarget( + selectableViews, + targetPoint, + 'prefer-more-specific-selection', + ) const validElementPathForHover = findValidTarget( selectableViews, targetPoint, @@ -528,14 +549,15 @@ export function useHighlightCallbacks( function getPreferredSelectionForEvent( eventType: 'mousedown' | 'mouseup' | string, isDoubleClick: boolean, -): 'prefer-selected' | 'dont-prefer-selected' { + cmdModifier: boolean, +): 'prefer-selected' | 'prefer-more-specific-selection' { // mousedown keeps selection on a single click to allow dragging overlapping elements and selection happens on mouseup // with continuous clicking mousedown should select switch (eventType) { case 'mousedown': - return isDoubleClick ? 'dont-prefer-selected' : 'prefer-selected' + return isDoubleClick || cmdModifier ? 'prefer-more-specific-selection' : 'prefer-selected' case 'mouseup': - return isDoubleClick ? 'prefer-selected' : 'dont-prefer-selected' + return isDoubleClick ? 'prefer-selected' : 'prefer-more-specific-selection' default: return 'prefer-selected' } @@ -561,6 +583,7 @@ function useSelectOrLiveModeSelectAndHover( ) const windowToCanvasCoordinates = useWindowToCanvasCoordinates() const interactionSessionHappened = React.useRef(false) + const draggedOverThreshold = React.useRef(false) const didWeHandleMouseDown = React.useRef(false) // this is here to avoid selecting when closing text editing const { onMouseMove: innerOnMouseMove } = useHighlightCallbacks( @@ -582,6 +605,14 @@ function useSelectOrLiveModeSelectAndHover( editorStoreRef.current.editor.canvas.interactionSession, editorStoreRef.current.editor.keysPressed['space'], ) || event.buttons === 4 + + const draggingOverThreshold = + editorStoreRef.current.editor.canvas.interactionSession?.interactionData?.type === 'DRAG' + ? editorStoreRef.current.editor.canvas.interactionSession?.interactionData?.drag != null + : false + + draggedOverThreshold.current = draggedOverThreshold.current || draggingOverThreshold + if (isDragIntention) { return } @@ -601,20 +632,23 @@ function useSelectOrLiveModeSelectAndHover( (event: React.MouseEvent) => { const isLeftClick = event.button === 0 const isRightClick = event.type === 'contextmenu' && event.detail === 0 - const isDragIntention = + const isCanvasPanIntention = editorStoreRef.current.editor.keysPressed['space'] || event.button === 1 - const hasInteractionSessionWithMouseMoved = + + const draggingOverThreshold = editorStoreRef.current.editor.canvas.interactionSession?.interactionData?.type === 'DRAG' ? editorStoreRef.current.editor.canvas.interactionSession?.interactionData?.drag != null : false + const hasInteractionSession = editorStoreRef.current.editor.canvas.interactionSession != null const hadInteractionSessionThatWasCancelled = interactionSessionHappened.current && !hasInteractionSession const activeControl = editorStoreRef.current.editor.canvas.interactionSession?.activeControl + const mouseUpSelectionAllowed = didWeHandleMouseDown.current && - !hadInteractionSessionThatWasCancelled && + (!hadInteractionSessionThatWasCancelled || !draggedOverThreshold.current) && (activeControl == null || activeControl.type === 'BOUNDING_AREA') if (event.type === 'mousedown') { @@ -625,6 +659,7 @@ function useSelectOrLiveModeSelectAndHover( interactionSessionHappened.current = false // didWeHandleMouseDown is used to avoid selecting when closing text editing didWeHandleMouseDown.current = false + draggedOverThreshold.current = false if (!mouseUpSelectionAllowed) { // We should skip this mouseup @@ -633,8 +668,8 @@ function useSelectOrLiveModeSelectAndHover( } if ( - isDragIntention || - hasInteractionSessionWithMouseMoved || + isCanvasPanIntention || + draggingOverThreshold || !active || !(isLeftClick || isRightClick) ) { @@ -643,8 +678,13 @@ function useSelectOrLiveModeSelectAndHover( } const doubleClick = event.type === 'mousedown' && event.detail > 0 && event.detail % 2 === 0 + const cmdMouseDown = event.type === 'mousedown' && event.metaKey const selectableViews = getSelectableViewsForSelectMode(event.metaKey, doubleClick) - const preferAlreadySelected = getPreferredSelectionForEvent(event.type, doubleClick) + const preferAlreadySelected = getPreferredSelectionForEvent( + event.type, + doubleClick, + event.metaKey, + ) const foundTarget = findValidTarget( selectableViews, windowPoint(point(event.clientX, event.clientY)), @@ -658,7 +698,7 @@ function useSelectOrLiveModeSelectAndHover( if (foundTarget != null || isDeselect) { if ( event.button !== 2 && - event.type !== 'mouseup' && + (event.type !== 'mouseup' || cmdMouseDown) && foundTarget != null && draggingAllowed && // grid has its own drag handling diff --git a/editor/src/components/canvas/controls/select-mode/select-mode.spec.browser2.tsx b/editor/src/components/canvas/controls/select-mode/select-mode.spec.browser2.tsx index d13d6108bffa..42b2fd55f15c 100644 --- a/editor/src/components/canvas/controls/select-mode/select-mode.spec.browser2.tsx +++ b/editor/src/components/canvas/controls/select-mode/select-mode.spec.browser2.tsx @@ -33,7 +33,6 @@ import type { Modifiers } from '../../../../utils/modifiers' import { cmdModifier, emptyModifiers, shiftCmdModifier } from '../../../../utils/modifiers' import { FOR_TESTS_setNextGeneratedUids } from '../../../../core/model/element-template-utils.test-utils' import type { ElementPath } from '../../../../core/shared/project-file-types' -import { setFeatureForBrowserTestsUseInDescribeBlockOnly } from '../../../../utils/utils.test-utils' async function fireSingleClickEvents( target: HTMLElement, @@ -1532,6 +1531,7 @@ describe('mouseup selection', () => { `) + const ScenePath = EP.elementPath([[BakedInStoryboardUID, TestSceneUID]]) const RedPath = EP.elementPath([ [BakedInStoryboardUID, TestSceneUID, TestAppUID], ['app-root', 'red'], @@ -1562,7 +1562,171 @@ describe('mouseup selection', () => { return getDOMRectCentre(elementRect) } - it('mouseup in the gap between a multi-selection will select the element behind if no drag happens', async () => { + describe('Interactions in selected scene', () => { + it('Can select element in selected scene by clicking on it', async () => { + const renderResult = await renderTestEditorWithCode( + MouseupTestProject, + 'await-first-dom-report', + ) + + await renderResult.dispatch([selectComponents([ScenePath], false)], true) + + const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) + + const redCentre = await getElementCentre('red', renderResult) + await mouseDownAtPoint(canvasControlsLayer, redCentre) + + // selection should not change on mouse down + expect(renderResult.getEditorState().editor.selectedViews).toEqual([ScenePath]) + await mouseUpAtPoint(canvasControlsLayer, redCentre) + + // selection should change on mouse up + expect(renderResult.getEditorState().editor.selectedViews).toEqual([RedPath]) + + // Check nothing has changed in the project + expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual(MouseupTestProject) + }) + + it('Can select element in selected scene by dragging it under the drag threshold', async () => { + const renderResult = await renderTestEditorWithCode( + MouseupTestProject, + 'await-first-dom-report', + ) + + await renderResult.dispatch([selectComponents([ScenePath], false)], true) + + const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) + + const redCentre = await getElementCentre('red', renderResult) + await mouseMoveToPoint(canvasControlsLayer, redCentre) + + await mouseDownAtPoint(canvasControlsLayer, redCentre) + // selection should not change on mouse down + expect(renderResult.getEditorState().editor.selectedViews).toEqual([ScenePath]) + + await mouseMoveToPoint(canvasControlsLayer, { x: redCentre.x + 1, y: redCentre.y + 1 }) + + await mouseUpAtPoint(canvasControlsLayer, { x: redCentre.x + 1, y: redCentre.y + 1 }) + + // selection should change on mouse up because dragging was below threshold, so this interaction was something like a click + expect(renderResult.getEditorState().editor.selectedViews).toEqual([RedPath]) + + // Check nothing has changed in the project + expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual(MouseupTestProject) + }) + + it('When the scene is selected, dragging an element inside it drags the scene and the selection doesnt change', async () => { + const renderResult = await renderTestEditorWithCode( + MouseupTestProject, + 'await-first-dom-report', + ) + + await renderResult.dispatch([selectComponents([ScenePath], false)], true) + + const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) + + const redCentre = await getElementCentre('red', renderResult) + await mouseMoveToPoint(canvasControlsLayer, redCentre) + await mouseDownAtPoint(canvasControlsLayer, redCentre) + + // selection should not change on mouse down + expect(renderResult.getEditorState().editor.selectedViews).toEqual([ScenePath]) + + await mouseMoveToPoint(canvasControlsLayer, { x: redCentre.x + 100, y: redCentre.y + 100 }) + await mouseUpAtPoint(canvasControlsLayer, { x: redCentre.x + 100, y: redCentre.y + 100 }) + + // selection should not change on mouse up because dragging of the scene was successful + expect(renderResult.getEditorState().editor.selectedViews).toEqual([ScenePath]) + + // Dragging was successful so the project has changed + expect(getPrintedUiJsCode(renderResult.getEditorState())).not.toEqual(MouseupTestProject) + }) + + it('When the scene is selected, cmd-mousedown selects the element inside it', async () => { + const renderResult = await renderTestEditorWithCode( + MouseupTestProject, + 'await-first-dom-report', + ) + + await renderResult.dispatch([selectComponents([ScenePath], false)], true) + + const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) + + const redCentre = await getElementCentre('red', renderResult) + await mouseMoveToPoint(canvasControlsLayer, redCentre) + + await mouseDownAtPoint(canvasControlsLayer, redCentre, { modifiers: cmdModifier }) + + // selection should change on mouse down because cmd was down + expect(renderResult.getEditorState().editor.selectedViews).toEqual([RedPath]) + }) + + it('When the scene is selected, cmd-drag drags the element inside it', async () => { + const renderResult = await renderTestEditorWithCode( + MouseupTestProject, + 'await-first-dom-report', + ) + + await renderResult.dispatch([selectComponents([ScenePath], false)], true) + + const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) + + const redCentre = await getElementCentre('red', renderResult) + await mouseMoveToPoint(canvasControlsLayer, redCentre) + + await mouseDownAtPoint(canvasControlsLayer, redCentre, { modifiers: cmdModifier }) + + // selection should change on mouse down because cmd was down. This is necessary, the following drag will move the element inside + expect(renderResult.getEditorState().editor.selectedViews).toEqual([RedPath]) + + await mouseMoveToPoint( + canvasControlsLayer, + { x: redCentre.x + 100, y: redCentre.y + 100 }, + { modifiers: cmdModifier }, + ) + await mouseUpAtPoint(canvasControlsLayer, { x: redCentre.x + 100, y: redCentre.y + 100 }) + + // selection is still on dragged the element + expect(renderResult.getEditorState().editor.selectedViews).toEqual([RedPath]) + + // Dragging was successful so the project has changed + expect(getPrintedUiJsCode(renderResult.getEditorState())).not.toEqual(MouseupTestProject) + }) + + it('When the scene is selected, cmd-dragging it below the drag threshold selects the element inside it', async () => { + const renderResult = await renderTestEditorWithCode( + MouseupTestProject, + 'await-first-dom-report', + ) + + await renderResult.dispatch([selectComponents([ScenePath], false)], true) + + const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) + + const redCentre = await getElementCentre('red', renderResult) + await mouseMoveToPoint(canvasControlsLayer, redCentre) + + await mouseDownAtPoint(canvasControlsLayer, redCentre, { modifiers: cmdModifier }) + + // selection should change on mouse down because cmd was down + expect(renderResult.getEditorState().editor.selectedViews).toEqual([RedPath]) + + await mouseMoveToPoint( + canvasControlsLayer, + { x: redCentre.x + 100, y: redCentre.y + 100 }, + { modifiers: cmdModifier }, + ) + await mouseUpAtPoint(canvasControlsLayer, { x: redCentre.x + 1, y: redCentre.y + 1 }) + + // selection is still on the element which was already selected on mousedown + expect(renderResult.getEditorState().editor.selectedViews).toEqual([RedPath]) + + // Dragging was not successful so the project hasn't changed + expect(getPrintedUiJsCode(renderResult.getEditorState())).not.toEqual(MouseupTestProject) + }) + }) + + it('mouseup in the gap between a multi-selection will not select the element behind if no drag happens', async () => { const renderResult = await renderTestEditorWithCode( MouseupTestProject, 'await-first-dom-report', diff --git a/editor/src/components/canvas/controls/selection-area.spec.browser2.tsx b/editor/src/components/canvas/controls/selection-area.spec.browser2.tsx index ba2520178615..c7133afb532a 100644 --- a/editor/src/components/canvas/controls/selection-area.spec.browser2.tsx +++ b/editor/src/components/canvas/controls/selection-area.spec.browser2.tsx @@ -739,6 +739,7 @@ export var ${BakedInStoryboardVariableName} = (props) => { moveBeforeMouseDown: true, staggerMoveEvents: true, modifiers: shiftModifier, + mouseDownModifiers: shiftModifier, }, ) @@ -759,6 +760,7 @@ export var ${BakedInStoryboardVariableName} = (props) => { moveBeforeMouseDown: true, staggerMoveEvents: true, modifiers: shiftModifier, + mouseDownModifiers: shiftModifier, }, ) @@ -813,7 +815,12 @@ export var ${BakedInStoryboardVariableName} = (props) => { container, { x: rect.x + 620, y: rect.y + 100 }, { x: rect.x + 670, y: rect.y + 310 }, - { moveBeforeMouseDown: true, staggerMoveEvents: true, modifiers: shiftModifier }, + { + moveBeforeMouseDown: true, + staggerMoveEvents: true, + modifiers: shiftModifier, + mouseDownModifiers: shiftModifier, + }, ) expect(renderResult.getEditorState().editor.selectedViews.map(EP.toString)).toEqual([ diff --git a/editor/src/components/canvas/controls/text-edit-mode/text-edit-mode-hooks.tsx b/editor/src/components/canvas/controls/text-edit-mode/text-edit-mode-hooks.tsx index bb735835fff2..9cf14a4857c9 100644 --- a/editor/src/components/canvas/controls/text-edit-mode/text-edit-mode-hooks.tsx +++ b/editor/src/components/canvas/controls/text-edit-mode/text-edit-mode-hooks.tsx @@ -50,7 +50,7 @@ export function useTextEditModeSelectAndHover(active: boolean): MouseCallbacks { const foundTarget = findValidTarget( textEditableViews, windowPoint(point(event.clientX, event.clientY)), - 'dont-prefer-selected', + 'prefer-more-specific-selection', ) if (foundTarget == null) { return diff --git a/editor/src/components/canvas/event-helpers.test-utils.tsx b/editor/src/components/canvas/event-helpers.test-utils.tsx index d05cdd786d87..66073a73ad42 100644 --- a/editor/src/components/canvas/event-helpers.test-utils.tsx +++ b/editor/src/components/canvas/event-helpers.test-utils.tsx @@ -178,6 +178,7 @@ export async function mouseDragFromPointWithDelta( dragDelta: Point, options: { modifiers?: Modifiers + mouseDownModifiers?: Modifiers eventOptions?: MouseEventInit staggerMoveEvents?: boolean midDragCallback?: () => Promise @@ -197,6 +198,7 @@ export async function mouseDragFromPointToPoint( endPoint: Point, options: { modifiers?: Modifiers + mouseDownModifiers?: Modifiers eventOptions?: MouseEventInit staggerMoveEvents?: boolean midDragCallback?: () => Promise @@ -216,10 +218,13 @@ export async function mouseDragFromPointToPoint( if (options.moveBeforeMouseDown) { await mouseMoveToPoint(eventSourceElement, startPoint, options) } + + const mouseDownOptions = { ...options, modifiers: options.mouseDownModifiers } + if (options.realMouseDown) { - dispatchMouseDownEventAtPoint(startPoint, options) + dispatchMouseDownEventAtPoint(startPoint, mouseDownOptions) } else { - await mouseDownAtPoint(eventSourceElement, startPoint, options) + await mouseDownAtPoint(eventSourceElement, startPoint, mouseDownOptions) } if (staggerMoveEvents) {