From 9044b1b18365cc8d49e73fd3c531a84d7c8c1244 Mon Sep 17 00:00:00 2001 From: Danila Poyarkov Date: Tue, 3 Mar 2026 23:31:23 +0300 Subject: [PATCH] Sort auto-layout children by geometric position on import Figma's parentIndex.position strings represent z-order, not visual layout order. In auto-layout frames, children must be sorted by their x (horizontal) or y (vertical) coordinate to match the visual order. Fixes scrambled calendar dates and other auto-layout child ordering. --- packages/core/src/clipboard.ts | 21 ++++++++++++++++----- packages/core/src/kiwi/fig-import.ts | 23 +++++++++++++++++------ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/packages/core/src/clipboard.ts b/packages/core/src/clipboard.ts index 3d609ed54..78fe4d52e 100644 --- a/packages/core/src/clipboard.ts +++ b/packages/core/src/clipboard.ts @@ -209,11 +209,22 @@ export function importClipboardNodes( children.push(childId) } } - children.sort((a, b) => { - const aPos = guidMap.get(a)?.parentIndex?.position ?? '' - const bPos = guidMap.get(b)?.parentIndex?.position ?? '' - return aPos.localeCompare(bPos) - }) + const parentNc = guidMap.get(figmaId) + const stackMode = (parentNc as unknown as Record)?.stackMode as string | undefined + if (stackMode === 'HORIZONTAL' || stackMode === 'VERTICAL') { + const axis = stackMode === 'HORIZONTAL' ? 'm02' : 'm12' + children.sort((a, b) => { + const aT = guidMap.get(a)?.transform?.[axis] ?? 0 + const bT = guidMap.get(b)?.transform?.[axis] ?? 0 + return aT - bT + }) + } else { + children.sort((a, b) => { + const aPos = guidMap.get(a)?.parentIndex?.position ?? '' + const bPos = guidMap.get(b)?.parentIndex?.position ?? '' + return aPos.localeCompare(bPos) + }) + } for (const childId of children) { createNode(childId, node.id) } diff --git a/packages/core/src/kiwi/fig-import.ts b/packages/core/src/kiwi/fig-import.ts index 3dc9d2a07..16293b5b8 100644 --- a/packages/core/src/kiwi/fig-import.ts +++ b/packages/core/src/kiwi/fig-import.ts @@ -44,12 +44,23 @@ export function importNodeChanges( } } - for (const [, children] of childrenMap) { - children.sort((a, b) => { - const aPos = changeMap.get(a)?.parentIndex?.position ?? '' - const bPos = changeMap.get(b)?.parentIndex?.position ?? '' - return aPos.localeCompare(bPos) - }) + for (const [parentId, children] of childrenMap) { + const parentNc = changeMap.get(parentId) + const stackMode = (parentNc as unknown as Record)?.stackMode as string | undefined + if (stackMode === 'HORIZONTAL' || stackMode === 'VERTICAL') { + const axis = stackMode === 'HORIZONTAL' ? 'm02' : 'm12' + children.sort((a, b) => { + const aT = changeMap.get(a)?.transform?.[axis] ?? 0 + const bT = changeMap.get(b)?.transform?.[axis] ?? 0 + return aT - bT + }) + } else { + children.sort((a, b) => { + const aPos = changeMap.get(a)?.parentIndex?.position ?? '' + const bPos = changeMap.get(b)?.parentIndex?.position ?? '' + return aPos.localeCompare(bPos) + }) + } } function getChildren(ncId: string): string[] {