refactor(fig): route derived data through patches

This commit is contained in:
Danila Poyarkov 2026-05-18 00:27:24 +03:00
parent 7992f8c013
commit 1fc0b62e9e
5 changed files with 81 additions and 47 deletions

View file

@ -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<string, number>,
nodeId: string,
d: DerivedSymbolOverride,
modified: Set<string>,
sizeSet: Set<string>
): 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<string>; sizeSet: Set<string> } {
const modified = new Set<string>()
const sizeSet = new Set<string>()
@ -170,25 +198,7 @@ function resolveDsdUpdates(ctx: OverrideContext): { modified: Set<string>; 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)
}
}

View file

@ -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<string, Set<ProtectedField>>
@ -25,7 +35,17 @@ const PROP_TO_PROTECTED_FIELD: Partial<Record<keyof SceneNode, ProtectedField>>
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(

View file

@ -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

View file

@ -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<string, unknown>)
if (Object.keys(props).length > 0) patch.props = props
}
return patch.swapComponentId || patch.props ? patch : null
}
/**
* Apply symbolOverrides from kiwi data.
*

View file

@ -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<string, unknown>)
if (Object.keys(props).length > 0) patch.props = props
}
return patch.swapComponentId || patch.props ? patch : null
}