diff --git a/packages/tldraw/src/lib/shapes/line/LineShapeTool.test.ts b/packages/tldraw/src/lib/shapes/line/LineShapeTool.test.ts index c39b3f794..55ac42122 100644 --- a/packages/tldraw/src/lib/shapes/line/LineShapeTool.test.ts +++ b/packages/tldraw/src/lib/shapes/line/LineShapeTool.test.ts @@ -146,7 +146,7 @@ describe('When extending the line with the shift-key in tool-lock mode', () => { const line = editor.currentPageShapes[editor.currentPageShapes.length - 1] assert(editor.isShapeOfType(line, 'line')) const handles = Object.values(line.props.handles) - expect(handles.length).toBe(3) + expect(handles.length).toBe(2) }) it('extends a line by shift-click dragging', () => { diff --git a/packages/tldraw/src/lib/shapes/line/LineShapeUtil.tsx b/packages/tldraw/src/lib/shapes/line/LineShapeUtil.tsx index 01a394d23..fb667a897 100644 --- a/packages/tldraw/src/lib/shapes/line/LineShapeUtil.tsx +++ b/packages/tldraw/src/lib/shapes/line/LineShapeUtil.tsx @@ -65,8 +65,8 @@ export class LineShapeUtil extends ShapeUtil { canBind: false, canSnap: true, index: 'a2', - x: 0, - y: 0, + x: 0.1, + y: 0.1, }, }, } @@ -243,11 +243,9 @@ export class LineShapeUtil extends ShapeUtil { ) } } - // Cubic style spline if (shape.props.spline === 'cubic') { const splinePath = getSvgPathForLineGeometry(spline) - if (dash === 'solid') { return ( diff --git a/packages/tldraw/src/lib/shapes/line/toolStates/Pointing.ts b/packages/tldraw/src/lib/shapes/line/toolStates/Pointing.ts index cc5c3949c..c5257ec3e 100644 --- a/packages/tldraw/src/lib/shapes/line/toolStates/Pointing.ts +++ b/packages/tldraw/src/lib/shapes/line/toolStates/Pointing.ts @@ -14,6 +14,8 @@ import { structuredClone, } from '@tldraw/editor' +const MINIMUM_DISTANCE_BETWEEN_SHIFT_CLICKED_HANDLES = 2 + export class Pointing extends StateNode { static override id = 'pointing' @@ -27,9 +29,11 @@ export class Pointing extends StateNode { this.markId = undefined + // Previously created line shape that we might be extending const shape = info.shapeId && this.editor.getShape(info.shapeId) if (shape && inputs.shiftKey) { + // Extending a previous shape this.markId = `creating:${shape.id}` this.editor.mark(this.markId) this.shape = shape @@ -39,6 +43,7 @@ export class Pointing extends StateNode { const vertexHandles = handles.filter((h) => h.type === 'vertex').sort(sortByIndex) const endHandle = vertexHandles[vertexHandles.length - 1] + const prevEndHandle = vertexHandles[vertexHandles.length - 2] const shapePagePoint = Matrix2d.applyToPoint( this.editor.getShapeParentTransform(this.shape)!, @@ -47,24 +52,31 @@ export class Pointing extends StateNode { let nextEndHandleIndex: string, nextEndHandleId: string, nextEndHandle: TLHandle - if (vertexHandles.length === 2 && vertexHandles[1].x === 1 && vertexHandles[1].y === 1) { - nextEndHandleIndex = vertexHandles[1].index - nextEndHandleId = vertexHandles[1].id + const nextPoint = Vec2d.Sub(currentPagePoint, shapePagePoint) + + if ( + Vec2d.Dist(endHandle, prevEndHandle) < MINIMUM_DISTANCE_BETWEEN_SHIFT_CLICKED_HANDLES || + Vec2d.Dist(nextPoint, endHandle) < MINIMUM_DISTANCE_BETWEEN_SHIFT_CLICKED_HANDLES + ) { + // If the end handle is too close to the previous end handle, we'll just extend the previous end handle + nextEndHandleIndex = endHandle.index + nextEndHandleId = endHandle.id nextEndHandle = { - ...vertexHandles[1], - x: currentPagePoint.x - shapePagePoint.x, - y: currentPagePoint.y - shapePagePoint.y, + ...endHandle, + x: nextPoint.x + 0.1, + y: nextPoint.y + 0.1, } } else { + // Otherwise, we'll create a new end handle nextEndHandleIndex = getIndexAbove(endHandle.index) nextEndHandleId = 'handle:' + nextEndHandleIndex nextEndHandle = { - x: currentPagePoint.x - shapePagePoint.x, - y: currentPagePoint.y - shapePagePoint.y, - index: nextEndHandleIndex, - canBind: false, - type: 'vertex', id: nextEndHandleId, + type: 'vertex', + index: nextEndHandleIndex, + x: nextPoint.x + 0.1, + y: nextPoint.y + 0.1, + canBind: false, } } @@ -106,15 +118,17 @@ export class Pointing extends StateNode { if (this.editor.inputs.isDragging) { const handles = this.editor.getShapeHandles(this.shape) + console if (!handles) { if (this.markId) this.editor.bailToMark(this.markId) throw Error('No handles found') } - + const lastHandle = last(handles)! this.editor.setCurrentTool('select.dragging_handle', { shape: this.shape, isCreating: true, - handle: last(handles)!, + // remove the offset that we added to the handle when we created it + handle: { ...lastHandle, x: lastHandle.x - 0.1, y: lastHandle.y - 0.1 }, onInteractionEnd: 'line', }) } diff --git a/packages/tldraw/src/lib/ui/components/Toolbar/Toolbar.tsx b/packages/tldraw/src/lib/ui/components/Toolbar/Toolbar.tsx index 2a4eb281a..72a00ec76 100644 --- a/packages/tldraw/src/lib/ui/components/Toolbar/Toolbar.tsx +++ b/packages/tldraw/src/lib/ui/components/Toolbar/Toolbar.tsx @@ -110,19 +110,21 @@ export const Toolbar = memo(function Toolbar() {
- {!isReadonly && breakpoint < 6 && !editor.isInAny('hand', 'zoom') && ( + {!isReadonly && (
-
- - - - - -
+ {breakpoint < 6 && !editor.isInAny('hand', 'zoom') && ( +
+ + + + + +
+ )}
)}