From a42da8ab1628eba009d42fadedb6d2e485ea46cd Mon Sep 17 00:00:00 2001 From: Danila Poyarkov Date: Sat, 25 Apr 2026 22:08:45 +0300 Subject: [PATCH] fix(kiwi): preserve input badge avatar swaps --- packages/core/src/canvas/scene.ts | 2 +- .../core/src/kiwi/instance-overrides/dsd.ts | 14 +++++++-- .../core/src/kiwi/instance-overrides/props.ts | 31 ++++++++++++------- .../core/src/kiwi/instance-overrides/types.ts | 12 ++++++- 4 files changed, 44 insertions(+), 15 deletions(-) diff --git a/packages/core/src/canvas/scene.ts b/packages/core/src/canvas/scene.ts index 791b79b6d..38c68a1fa 100644 --- a/packages/core/src/canvas/scene.ts +++ b/packages/core/src/canvas/scene.ts @@ -650,7 +650,7 @@ export function renderText(r: SkiaRenderer, canvas: Canvas, node: SceneNode): vo } if (r.fontsLoaded && r.fontProvider) { const paragraph = r.buildParagraph(node, r.fillPaint.getColor()) - const paragraphY = node.fontSize < 13 ? 0 : -1 + const paragraphY = -1 canvas.drawParagraph(paragraph, 0, paragraphY) paragraph.delete() } else if (r.textFont) { diff --git a/packages/core/src/kiwi/instance-overrides/dsd.ts b/packages/core/src/kiwi/instance-overrides/dsd.ts index 9685cd57f..f50c332a3 100644 --- a/packages/core/src/kiwi/instance-overrides/dsd.ts +++ b/packages/core/src/kiwi/instance-overrides/dsd.ts @@ -1,5 +1,5 @@ import { copyGeometryPaths } from '../../scene-graph/copy' -import { resolveGeometryPaths } from '../convert' +import { convertLetterSpacing, convertLineHeight, resolveGeometryPaths } from '../convert' import { resolveOverrideTarget } from './resolve' import { buildClonesMap } from './sync' @@ -105,13 +105,23 @@ function resolveSizeOnlyPosition( return withinParent ? { x: source.x, y: source.y } : { x: 0, y: 0 } } +function buildDsdTextUpdates(d: DerivedSymbolOverride): Partial { + const updates: Partial = {} + if (d.fontSize !== undefined) updates.fontSize = d.fontSize + if (d.lineHeight !== undefined) updates.lineHeight = convertLineHeight(d.lineHeight, d.fontSize) + if (d.letterSpacing !== undefined) { + updates.letterSpacing = convertLetterSpacing(d.letterSpacing, d.fontSize) + } + return updates +} + function buildDsdLayoutUpdates( ctx: OverrideContext, visibleSiblingCount: Map, d: DerivedSymbolOverride, target: SceneNode ): { updates: Partial; hasSize: boolean } { - const updates: Partial = {} + const updates: Partial = buildDsdTextUpdates(d) const figmaDerivedLayout: NonNullable = {} if (d.size) { diff --git a/packages/core/src/kiwi/instance-overrides/props.ts b/packages/core/src/kiwi/instance-overrides/props.ts index 78e3d55bd..a565c3504 100644 --- a/packages/core/src/kiwi/instance-overrides/props.ts +++ b/packages/core/src/kiwi/instance-overrides/props.ts @@ -48,23 +48,32 @@ function findPropRefs( * means "reset to the component's initialValue default". This is distinct * from `{boolValue: false}` which is an explicit false. */ +function resolveAssignmentValue( + ctx: OverrideContext, + assignment: ComponentPropAssignment, + key: string, + resolveDefaults: boolean +): ComponentPropValue { + if (!isEmptyPropValue(assignment.value)) return assignment.value + + const variableValue = assignment.varValue?.value + if (variableValue?.symbolIdValue?.guid) return { guidValue: variableValue.symbolIdValue.guid } + if (variableValue?.boolValue !== undefined) return { boolValue: variableValue.boolValue } + if (variableValue?.textValue !== undefined) return { textValue: variableValue.textValue } + + return resolveDefaults ? (ctx.propDefaults.get(key) ?? assignment.value) : assignment.value +} + function assignmentsToValueMap( ctx: OverrideContext, assignments: ComponentPropAssignment[], resolveDefaults = false ): Map { const valueByDef = new Map() - for (const a of assignments) { - if (!a.defID) continue - const key = guidToString(a.defID) - if (resolveDefaults && isEmptyPropValue(a.value)) { - const def = ctx.propDefaults.get(key) - if (def) { - valueByDef.set(key, def) - continue - } - } - valueByDef.set(key, a.value) + for (const assignment of assignments) { + if (!assignment.defID) continue + const key = guidToString(assignment.defID) + valueByDef.set(key, resolveAssignmentValue(ctx, assignment, key, resolveDefaults)) } return valueByDef } diff --git a/packages/core/src/kiwi/instance-overrides/types.ts b/packages/core/src/kiwi/instance-overrides/types.ts index 47f3df601..f4d752331 100644 --- a/packages/core/src/kiwi/instance-overrides/types.ts +++ b/packages/core/src/kiwi/instance-overrides/types.ts @@ -1,6 +1,6 @@ import type { SceneGraph } from '../../scene-graph' import type { Matrix, Vector } from '../../types' -import type { GUID } from '../codec' +import type { GUID, NodeChange } from '../codec' export interface SymbolOverride { guidPath?: { guids?: GUID[] } @@ -28,12 +28,22 @@ export type ComponentPropValue = { export interface ComponentPropAssignment { defID?: GUID value: ComponentPropValue + varValue?: { + value?: { + boolValue?: boolean + textValue?: string + symbolIdValue?: { guid?: GUID } + } + } } export interface DerivedSymbolOverride { guidPath?: { guids?: GUID[] } size?: Vector transform?: Matrix + fontSize?: number + lineHeight?: NodeChange['lineHeight'] + letterSpacing?: NodeChange['letterSpacing'] fillGeometry?: Array<{ windingRule?: string; commandsBlob?: number }> strokeGeometry?: Array<{ windingRule?: string; commandsBlob?: number }> }