diff --git a/packages/core/src/kiwi/instance-overrides/derived-symbol-data/propagate.ts b/packages/core/src/kiwi/instance-overrides/derived-symbol-data/propagate.ts index 5e44ea94a..ea43da554 100644 --- a/packages/core/src/kiwi/instance-overrides/derived-symbol-data/propagate.ts +++ b/packages/core/src/kiwi/instance-overrides/derived-symbol-data/propagate.ts @@ -3,6 +3,32 @@ import type { OverrideContext } from '#core/kiwi/instance-overrides/types' import type { SceneNode } from '#core/scene-graph' import { copyGeometryPaths } from '#core/scene-graph/copy' +function buildCloneUpdates( + ctx: OverrideContext, + source: SceneNode, + clone: SceneNode, + cloneId: string, + sizeSet: Set +): Partial { + const updates: Partial = {} + if (sizeSet.has(cloneId)) return updates + if (source.width !== clone.width) updates.width = source.width + if (source.height !== clone.height) updates.height = source.height + if (source.x !== clone.x) updates.x = source.x + if (source.y !== clone.y) updates.y = source.y + if (!ctx.geometryOverrideNodes.has(cloneId)) { + if (source.fillGeometry !== clone.fillGeometry) updates.fillGeometry = copyGeometryPaths(source.fillGeometry) + if (source.strokeGeometry !== clone.strokeGeometry) updates.strokeGeometry = copyGeometryPaths(source.strokeGeometry) + } + if (source.text === clone.text && source.figmaDerivedTextGlyphs) { + updates.figmaDerivedTextGlyphs = structuredClone(source.figmaDerivedTextGlyphs) + } + if (source.text === clone.text && source.figmaDerivedLayout) { + updates.figmaDerivedLayout = { ...source.figmaDerivedLayout } + } + return updates +} + export function propagateDsdChanges( ctx: OverrideContext, modified: Set, @@ -27,18 +53,8 @@ export function propagateDsdChanges( visited.add(cloneId) const clone = ctx.graph.getNode(cloneId) if (!clone) continue - if (!sizeSet.has(cloneId)) { - const cu: Partial = {} - if (source.width !== clone.width) cu.width = source.width - if (source.height !== clone.height) cu.height = source.height - if (source.x !== clone.x) cu.x = source.x - if (source.y !== clone.y) cu.y = source.y - if (!ctx.geometryOverrideNodes.has(cloneId)) { - if (source.fillGeometry !== clone.fillGeometry) cu.fillGeometry = copyGeometryPaths(source.fillGeometry) - if (source.strokeGeometry !== clone.strokeGeometry) cu.strokeGeometry = copyGeometryPaths(source.strokeGeometry) - } - if (Object.keys(cu).length > 0) ctx.graph.updateNode(cloneId, cu) - } + const updates = buildCloneUpdates(ctx, source, clone, cloneId, sizeSet) + if (Object.keys(updates).length > 0) ctx.graph.updateNode(cloneId, updates) queue.push(cloneId) } } diff --git a/tests/engine/io/fig/import/derived-symbol-data.test.ts b/tests/engine/io/fig/import/derived-symbol-data.test.ts index 55eb0a67f..5e092015f 100644 --- a/tests/engine/io/fig/import/derived-symbol-data.test.ts +++ b/tests/engine/io/fig/import/derived-symbol-data.test.ts @@ -1,6 +1,7 @@ import { describe, expect, test } from 'bun:test' import { buildDsdLayoutUpdates } from '#core/kiwi/instance-overrides/derived-symbol-data/layout' +import { propagateDsdChanges } from '#core/kiwi/instance-overrides/derived-symbol-data/propagate' import type { OverrideContext } from '#core/kiwi/instance-overrides' import { SceneGraph } from '#core/scene-graph' @@ -9,6 +10,26 @@ function pageId(graph: SceneGraph): string { } describe('fig import derived symbol data', () => { + test('propagates derived glyphs through clone chains', () => { + const graph = new SceneGraph() + const source = graph.createNode('TEXT', pageId(graph), { + text: 'Account', + figmaDerivedTextGlyphs: [{ commandsBlob: new Uint8Array([0]), x: 0, y: 10, fontSize: 14 }], + figmaDerivedLayout: { width: 56, height: 20 } + }) + const clone = graph.createNode('TEXT', pageId(graph), { text: 'Account', componentId: source.id }) + const ctx = { + graph, + activeNodeIds: new Set([source.id, clone.id]), + geometryOverrideNodes: new Set() + } as OverrideContext + + propagateDsdChanges(ctx, new Set([source.id]), new Set()) + + expect(clone.figmaDerivedTextGlyphs).toEqual(source.figmaDerivedTextGlyphs) + expect(clone.figmaDerivedLayout).toEqual(source.figmaDerivedLayout) + }) + test('routes derived text glyphs through layout patch updates', () => { const graph = new SceneGraph() const target = graph.createNode('TEXT', pageId(graph), { text: 'Menu Item' })