diff --git a/packages/editor/src/lib/editor/Editor.ts b/packages/editor/src/lib/editor/Editor.ts index 39070882c..93e2b9368 100644 --- a/packages/editor/src/lib/editor/Editor.ts +++ b/packages/editor/src/lib/editor/Editor.ts @@ -290,8 +290,14 @@ export class Editor extends EventEmitter { // if arrow has two bindings, always parent arrow to closest common ancestor of the bindings nextParentId = this.findCommonAncestor([startShape, endShape]) ?? parentPageId } else if (startShape || endShape) { - // if arrow has one binding, keep arrow on its own page - nextParentId = parentPageId + const bindingParentId = (startShape || endShape)?.parentId + // If the arrow and the shape that it is bound to have the same parent, then keep that parent + if (bindingParentId && bindingParentId === arrow.parentId) { + nextParentId = arrow.parentId + } else { + // if arrow has one binding, keep arrow on its own page + nextParentId = parentPageId + } } else { return } diff --git a/packages/tldraw/src/lib/ui/hooks/menuHelpers.ts b/packages/tldraw/src/lib/ui/hooks/menuHelpers.ts index 50c046749..3ef6b04f0 100644 --- a/packages/tldraw/src/lib/ui/hooks/menuHelpers.ts +++ b/packages/tldraw/src/lib/ui/hooks/menuHelpers.ts @@ -1,6 +1,8 @@ import { Editor, TLArrowShape, + TLShape, + TLShapeId, assert, exhaustiveSwitchError, useEditor, @@ -163,10 +165,38 @@ export const useThreeStackableItems = () => { return useValue('threeStackableItems', () => shapesWithUnboundArrows(editor).length > 2, [editor]) } +function shapesWithArrowsBoundToThem(editor: Editor) { + const selectedShapes = editor.getSelectedShapes() + const arrows: TLArrowShape[] = [] + const otherShapesMap = new Map() + selectedShapes.forEach((shape) => { + if (shape.type === 'arrow') { + arrows.push(shape as TLArrowShape) + } else { + otherShapesMap.set(shape.id, shape) + } + }) + // We want to get all the arrows that are either unbound or bound to one of the selected shapes + const groupableArrows = arrows.filter((arrow) => { + if (arrow.props.start.type === 'binding') { + if (!otherShapesMap.has(arrow.props.start.boundShapeId)) { + return false + } + } + if (arrow.props.end.type === 'binding') { + if (!otherShapesMap.has(arrow.props.end.boundShapeId)) { + return false + } + } + return true + }) + return Array.from(otherShapesMap.values()).concat(groupableArrows) +} + /** @internal */ export const useAllowGroup = () => { const editor = useEditor() - return useValue('allowGroup', () => shapesWithUnboundArrows(editor).length > 1, [editor]) + return useValue('allowGroup', () => shapesWithArrowsBoundToThem(editor).length > 1, [editor]) } /** @internal */