From 1fc0b62e9e649d2a5b2b61e9cbf8eb05d003a9c5 Mon Sep 17 00:00:00 2001 From: Danila Poyarkov Date: Mon, 18 May 2026 00:27:24 +0300 Subject: [PATCH] refactor(fig): route derived data through patches --- .../core/src/kiwi/instance-overrides/dsd.ts | 48 +++++++++++-------- .../instance-overrides/patches/protection.ts | 22 ++++++++- .../kiwi/instance-overrides/patches/types.ts | 2 +- .../instance-overrides/symbol/overrides.ts | 29 ++--------- .../kiwi/instance-overrides/symbol/patches.ts | 27 +++++++++++ 5 files changed, 81 insertions(+), 47 deletions(-) create mode 100644 packages/core/src/kiwi/instance-overrides/symbol/patches.ts diff --git a/packages/core/src/kiwi/instance-overrides/dsd.ts b/packages/core/src/kiwi/instance-overrides/dsd.ts index cf001fe03..44d7efecd 100644 --- a/packages/core/src/kiwi/instance-overrides/dsd.ts +++ b/packages/core/src/kiwi/instance-overrides/dsd.ts @@ -3,6 +3,7 @@ import { convertLineHeight, resolveGeometryPaths } from '#core/kiwi/node-change/convert' +import { applyOverridePatch } from '#core/kiwi/instance-overrides/patches' import type { SceneNode, GeometryPath } from '#core/scene-graph' import { copyGeometryPaths } from '#core/scene-graph/copy' @@ -156,6 +157,33 @@ function buildDsdLayoutUpdates( return { updates, hasSize: d.size !== undefined } } +function applyDsdOverride( + ctx: OverrideContext, + visibleSiblingCount: Map, + nodeId: string, + d: DerivedSymbolOverride, + modified: Set, + sizeSet: Set +): void { + const guids = d.guidPath?.guids + if (!guids?.length) return + + const targetId = resolveOverrideTarget(ctx, nodeId, guids) + if (!targetId) return + + const target = ctx.graph.getNode(targetId) + if (!target) return + + const { updates, hasSize } = buildDsdLayoutUpdates(ctx, visibleSiblingCount, d, target) + if (d.fillGeometry?.length || d.strokeGeometry?.length) ctx.geometryOverrideNodes.add(targetId) + if (Object.keys(updates).length === 0) return + + if (applyOverridePatch(ctx, { targetId, source: 'derived-symbol-data', props: updates })) { + modified.add(targetId) + } + if (hasSize) sizeSet.add(targetId) +} + function resolveDsdUpdates(ctx: OverrideContext): { modified: Set; sizeSet: Set } { const modified = new Set() const sizeSet = new Set() @@ -170,25 +198,7 @@ function resolveDsdUpdates(ctx: OverrideContext): { modified: Set; sizeS if (!nodeId || (ctx.activeNodeIds && !ctx.activeNodeIds.has(nodeId))) continue for (const d of derived) { - const guids = d.guidPath?.guids - if (!guids?.length) continue - - const targetId = resolveOverrideTarget(ctx, nodeId, guids) - if (!targetId) continue - - const target = ctx.graph.getNode(targetId) - if (!target) continue - - const { updates, hasSize } = buildDsdLayoutUpdates(ctx, visibleSiblingCount, d, target) - if (d.fillGeometry?.length || d.strokeGeometry?.length) { - ctx.geometryOverrideNodes.add(targetId) - } - - if (Object.keys(updates).length > 0) { - ctx.graph.updateNode(targetId, updates) - modified.add(targetId) - if (hasSize) sizeSet.add(targetId) - } + applyDsdOverride(ctx, visibleSiblingCount, nodeId, d, modified, sizeSet) } } diff --git a/packages/core/src/kiwi/instance-overrides/patches/protection.ts b/packages/core/src/kiwi/instance-overrides/patches/protection.ts index d6d4cc142..808c8ba39 100644 --- a/packages/core/src/kiwi/instance-overrides/patches/protection.ts +++ b/packages/core/src/kiwi/instance-overrides/patches/protection.ts @@ -11,6 +11,16 @@ export type ProtectedField = | 'layoutGrow' | 'textAutoResize' | 'locked' + | 'x' + | 'y' + | 'width' + | 'height' + | 'figmaDerivedLayout' + | 'fontSize' + | 'lineHeight' + | 'letterSpacing' + | 'fillGeometry' + | 'strokeGeometry' | 'structure' export type ProtectionMap = Map> @@ -25,7 +35,17 @@ const PROP_TO_PROTECTED_FIELD: Partial> styleRuns: 'styleRuns', layoutGrow: 'layoutGrow', textAutoResize: 'textAutoResize', - locked: 'locked' + locked: 'locked', + x: 'x', + y: 'y', + width: 'width', + height: 'height', + figmaDerivedLayout: 'figmaDerivedLayout', + fontSize: 'fontSize', + lineHeight: 'lineHeight', + letterSpacing: 'letterSpacing', + fillGeometry: 'fillGeometry', + strokeGeometry: 'strokeGeometry' } export function protectField( diff --git a/packages/core/src/kiwi/instance-overrides/patches/types.ts b/packages/core/src/kiwi/instance-overrides/patches/types.ts index 2e5c53924..56eb37915 100644 --- a/packages/core/src/kiwi/instance-overrides/patches/types.ts +++ b/packages/core/src/kiwi/instance-overrides/patches/types.ts @@ -1,6 +1,6 @@ import type { SceneNode } from '#core/scene-graph' -export type OverridePatchSource = 'symbol-override' | 'component-prop' +export type OverridePatchSource = 'symbol-override' | 'component-prop' | 'derived-symbol-data' export interface OverridePatch { targetId: string diff --git a/packages/core/src/kiwi/instance-overrides/symbol/overrides.ts b/packages/core/src/kiwi/instance-overrides/symbol/overrides.ts index 25d99bdc5..6785342b9 100644 --- a/packages/core/src/kiwi/instance-overrides/symbol/overrides.ts +++ b/packages/core/src/kiwi/instance-overrides/symbol/overrides.ts @@ -1,36 +1,13 @@ -import { applyOverridePatch, type OverridePatch } from '#core/kiwi/instance-overrides/patches' +import { applyOverridePatch } from '#core/kiwi/instance-overrides/patches' import { resolveOverrideTarget } from '#core/kiwi/instance-overrides/resolve' -import type { OverrideContext, SymbolOverride } from '#core/kiwi/instance-overrides/types' -import { guidToString } from '#core/kiwi/node-change/convert' -import { applyStyleRefsToFields } from '#core/kiwi/node-change/style-refs' +import type { OverrideContext } from '#core/kiwi/instance-overrides/types' -import { convertOverrideToProps } from './props' +import { patchFromSymbolOverride } from './patches' function isActiveInstance(ctx: OverrideContext, nodeId: string | undefined): nodeId is string { return nodeId !== undefined && (!ctx.activeNodeIds || ctx.activeNodeIds.has(nodeId)) } -function patchFromSymbolOverride( - ctx: OverrideContext, - targetId: string, - ov: SymbolOverride -): OverridePatch | null { - const patch: OverridePatch = { targetId, source: 'symbol-override' } - if (ov.overriddenSymbolID) { - const swapGuid = guidToString(ov.overriddenSymbolID) - patch.swapComponentId = ctx.guidToNodeId.get(swapGuid) - } - - const { guidPath: _, overriddenSymbolID: _s, componentPropAssignments: _c, ...fields } = ov - if (Object.keys(fields).length > 0) { - applyStyleRefsToFields(ctx.changeMap, fields) - const props = convertOverrideToProps(fields as Record) - if (Object.keys(props).length > 0) patch.props = props - } - - return patch.swapComponentId || patch.props ? patch : null -} - /** * Apply symbolOverrides from kiwi data. * diff --git a/packages/core/src/kiwi/instance-overrides/symbol/patches.ts b/packages/core/src/kiwi/instance-overrides/symbol/patches.ts new file mode 100644 index 000000000..d5461079b --- /dev/null +++ b/packages/core/src/kiwi/instance-overrides/symbol/patches.ts @@ -0,0 +1,27 @@ +import type { OverridePatch } from '#core/kiwi/instance-overrides/patches' +import type { OverrideContext, SymbolOverride } from '#core/kiwi/instance-overrides/types' +import { guidToString } from '#core/kiwi/node-change/convert' +import { applyStyleRefsToFields } from '#core/kiwi/node-change/style-refs' + +import { convertOverrideToProps } from './props' + +export function patchFromSymbolOverride( + ctx: OverrideContext, + targetId: string, + ov: SymbolOverride +): OverridePatch | null { + const patch: OverridePatch = { targetId, source: 'symbol-override' } + if (ov.overriddenSymbolID) { + const swapGuid = guidToString(ov.overriddenSymbolID) + patch.swapComponentId = ctx.guidToNodeId.get(swapGuid) + } + + const { guidPath: _, overriddenSymbolID: _s, componentPropAssignments: _c, ...fields } = ov + if (Object.keys(fields).length > 0) { + applyStyleRefsToFields(ctx.changeMap, fields) + const props = convertOverrideToProps(fields as Record) + if (Object.keys(props).length > 0) patch.props = props + } + + return patch.swapComponentId || patch.props ? patch : null +}