diff --git a/packages/tldraw/src/lib/tools/selection-logic/selectOnCanvasPointerUp.ts b/packages/tldraw/src/lib/tools/selection-logic/selectOnCanvasPointerUp.ts index eaa9fe0ed..bc4d6751a 100644 --- a/packages/tldraw/src/lib/tools/selection-logic/selectOnCanvasPointerUp.ts +++ b/packages/tldraw/src/lib/tools/selection-logic/selectOnCanvasPointerUp.ts @@ -9,6 +9,7 @@ export function selectOnCanvasPointerUp(editor: Editor) { margin: HIT_TEST_MARGIN / editor.zoomLevel, hitLabels: true, renderingOnly: true, + filter: (shape) => !shape.isLocked, }) // Note at the start: if we select a shape that is inside of a group, diff --git a/packages/tldraw/src/test/selection-omnibus.test.ts b/packages/tldraw/src/test/selection-omnibus.test.ts index dd5b75c0c..8c4390d4b 100644 --- a/packages/tldraw/src/test/selection-omnibus.test.ts +++ b/packages/tldraw/src/test/selection-omnibus.test.ts @@ -208,6 +208,25 @@ describe('when shape is hollow', () => { expect(editor.selectedShapeIds).toEqual([ids.box1]) }) + it('missed on the label when the shape is locked', () => { + editor.updateShape({ id: ids.box1, type: 'geo', isLocked: true }) + editor.pointerMove(-100, -100) + expect(editor.hoveredShapeId).toBe(null) + expect(editor.selectedShapeIds).toEqual([]) + editor.pointerMove(50, 50) + // no hover over label... + expect(editor.hoveredShapeId).toBe(null) + expect(editor.selectedShapeIds).toEqual([]) + editor.pointerDown() + // will select on pointer up + expect(editor.hoveredShapeId).toBe(null) + expect(editor.selectedShapeIds).toEqual([]) + // selects on pointer up + editor.pointerUp() + expect(editor.hoveredShapeId).toBe(null) + expect(editor.selectedShapeIds).toEqual([]) + }) + it('hits on pointer down over shape margin (inside)', () => { editor.pointerMove(96, 50) expect(editor.hoveredShapeId).toBe(box1.id) @@ -460,9 +479,44 @@ describe('when shape is inside of a frame', () => { it('misses on pointer down over shape, misses on pointer up', () => { editor.pointerMove(50, 50) expect(editor.hoveredShapeId).toBe(null) - editor.pointerDown() // inside of box1 + editor.pointerDown() // inside of box1 (which is empty) expect(editor.selectedShapeIds).toEqual([]) - editor.pointerUp() + editor.pointerUp() // does not select because inside of hollow shape + expect(editor.selectedShapeIds).toEqual([]) + }) + + it('misses on pointer down over shape, hit on pointer up on the edge', () => { + editor.pointerMove(25, 25) + editor.pointerDown() // on the edge of box1 (which is empty) + expect(editor.selectedShapeIds).toEqual([ids.box1]) + editor.pointerUp() // does not select because inside of hollow shape + expect(editor.selectedShapeIds).toEqual([ids.box1]) + }) + + it('misses on pointer down over shape, misses on pointer up on the edge when locked', () => { + editor.updateShape({ id: ids.box1, type: 'geo', isLocked: true }) + editor.pointerMove(25, 25) + editor.pointerDown() // on the edge of box1 (which is empty) + expect(editor.selectedShapeIds).toEqual([]) + editor.pointerUp() // does not select because inside of hollow shape + expect(editor.selectedShapeIds).toEqual([]) + }) + + it('misses on pointer down over shape, misses on pointer up when locked', () => { + editor.updateShape({ id: ids.box1, type: 'geo', isLocked: true }) + editor.pointerMove(50, 50) + editor.pointerDown() // on the edge of box1 (which is empty) + expect(editor.selectedShapeIds).toEqual([]) + editor.pointerUp() // does not select because inside of hollow shape + expect(editor.selectedShapeIds).toEqual([]) + }) + + it('misses on pointer down over shape label, misses on pointer up when locked', () => { + editor.updateShape({ id: ids.box1, type: 'geo', isLocked: true }) + editor.pointerMove(75, 75) + editor.pointerDown() // on the edge of box1 (which is empty) + expect(editor.selectedShapeIds).toEqual([]) + editor.pointerUp() // does not select because inside of hollow shape expect(editor.selectedShapeIds).toEqual([]) })