From 05a36e96722806f713c7e211ede2435b4b757935 Mon Sep 17 00:00:00 2001 From: Danila Poyarkov Date: Tue, 11 Aug 2026 18:54:29 +0300 Subject: [PATCH] fix(fig): preserve imported instance links - Remap component IDs through SceneGraph updates so the instance index stays consistent - Cover imported instances resolving through the remapped source ID - Restore source component synchronization for the reporter's .fig file --- CHANGELOG.md | 4 ++++ packages/core/src/kiwi/fig/import.ts | 12 +++++++----- tests/engine/io/fig/import/component-props.test.ts | 3 +++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5e6032fc..b66b7338a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Fixed + +- Keep imported Figma instances linked to their remapped source components so later component edits update existing instances. (#385) + ## 0.14.0 - 2026-08-10 ### Breaking changes diff --git a/packages/core/src/kiwi/fig/import.ts b/packages/core/src/kiwi/fig/import.ts index d510f20c9..8e6780def 100644 --- a/packages/core/src/kiwi/fig/import.ts +++ b/packages/core/src/kiwi/fig/import.ts @@ -358,11 +358,13 @@ function importVariableBindings( } function remapComponentIds(graph: SceneGraph, guidToNodeId: Map): void { - for (const node of graph.getAllNodes()) { - if (node.type !== 'INSTANCE' || !node.componentId) continue - const remapped = guidToNodeId.get(node.componentId) - if (remapped) node.componentId = remapped - } + graph.preserveSourceMetadataDuring(() => { + for (const node of graph.getAllNodes()) { + if (node.type !== 'INSTANCE' || !node.componentId) continue + const remapped = guidToNodeId.get(node.componentId) + if (remapped) graph.updateNode(node.id, { componentId: remapped }) + } + }) } function applyVariantPropSpecs(graph: SceneGraph): void { diff --git a/tests/engine/io/fig/import/component-props.test.ts b/tests/engine/io/fig/import/component-props.test.ts index 21c5a8a83..7069132e3 100644 --- a/tests/engine/io/fig/import/component-props.test.ts +++ b/tests/engine/io/fig/import/component-props.test.ts @@ -97,6 +97,9 @@ describe('Figma component property import', () => { (node) => node.name === 'Menu item instance' ) expect(instance?.componentPropertyAssignments).toEqual({ '3:1': 'Profile Item' }) + if (!component || !instance) throw new Error('Expected imported component and instance') + expect(graph.getInstances(component.id).map((node) => node.id)).toContain(instance.id) + expect(graph.instanceIndex.get('1:1')?.has(instance.id)).toBeFalsy() const unpopulated = importNodeChanges(nodeChanges, [], undefined, { populate: 'none' }) const unpopulatedInstance = Array.from(unpopulated.getAllNodes()).find(