diff --git a/packages/scene-graph/src/index.ts b/packages/scene-graph/src/index.ts index e2c18371a..32d5b1b79 100644 --- a/packages/scene-graph/src/index.ts +++ b/packages/scene-graph/src/index.ts @@ -523,16 +523,16 @@ export class SceneGraph { insertChildAt(childId: string, parentId: string, index: number): void { const node = this.getNode(childId) - const previousParentId = node?.parentId ?? null + const newParent = this.getNode(parentId) + if (!node || !newParent) return + const previousParentId = node.parentId const oldParent = previousParentId ? this.getNode(previousParentId) : undefined if (oldParent) { oldParent.childIds = oldParent.childIds.filter((id) => id !== childId) } - const newParent = this.getNode(parentId) - if (!newParent) return newParent.childIds = newParent.childIds.filter((id) => id !== childId) newParent.childIds.splice(index, 0, childId) - if (node) node.parentId = parentId + node.parentId = parentId this.clearAbsPosCache() this.emitter.emit('node:reordered', childId, parentId, index, previousParentId) } diff --git a/packages/scene-graph/src/mutation-impact.test.ts b/packages/scene-graph/src/mutation-impact.test.ts index 3181b4bad..a8639858d 100644 --- a/packages/scene-graph/src/mutation-impact.test.ts +++ b/packages/scene-graph/src/mutation-impact.test.ts @@ -54,6 +54,29 @@ describe('scene mutation impact', () => { expect(impact.currentParentIds).toContain(right.id) }) + test('retains old and new parents when reorderChild transfers a node', async () => { + const { graph, left, right, child } = transferSetup() + + const { impact } = await collectSceneMutation(graph, () => + graph.reorderChild(child.id, right.id, 0) + ) + + expect(child.parentId).toBe(right.id) + expect(left.childIds).not.toContain(child.id) + expect(right.childIds).toContain(child.id) + expect(impact.previousParentIds).toContain(left.id) + expect(impact.currentParentIds).toContain(right.id) + }) + + test('does not detach insertChildAt targets when the destination is missing', () => { + const { graph, left, child } = transferSetup() + + graph.insertChildAt(child.id, 'missing', 0) + + expect(child.parentId).toBe(left.id) + expect(left.childIds).toContain(child.id) + }) + test('retains old and new parents when insertChildAt transfers a node', async () => { const { graph, left, right, child } = transferSetup()