diff --git a/packages/core/src/kiwi/fig/import.ts b/packages/core/src/kiwi/fig/import.ts index dee60e635..ed767b2f7 100644 --- a/packages/core/src/kiwi/fig/import.ts +++ b/packages/core/src/kiwi/fig/import.ts @@ -9,6 +9,7 @@ import { setVariableColorResolver, VARIABLE_BINDING_FIELDS_INVERSE } from '#core/kiwi/node-change/convert' +import { applyStyleRefsToFields } from '#core/kiwi/node-change/style-refs' import { SceneGraph } from '#core/scene-graph' import type { VariableType, VariableValue } from '#core/scene-graph' @@ -350,35 +351,7 @@ function parseDocumentColorSpace(nodeChanges: NodeChange[]): 'srgb' | 'display-p } function applyStyleRefs(changeMap: Map): void { - const textStyleFields = [ - 'fontSize', - 'fontName', - 'lineHeight', - 'letterSpacing', - 'textDecoration', - 'textCase' - ] as const - - for (const nc of changeMap.values()) { - const fillStyleGuid = nc.styleIdForFill?.guid - if (fillStyleGuid) { - const style = changeMap.get(guidToString(fillStyleGuid)) - if (style?.styleType === 'FILL' && style.fillPaints) nc.fillPaints = style.fillPaints - } - - if (nc.type !== 'TEXT') continue - const textStyleGuid = nc.styleIdForText?.guid - if (!textStyleGuid) continue - const style = changeMap.get(guidToString(textStyleGuid)) - if (style?.type !== 'TEXT' || style.styleType !== 'TEXT') continue - for (const field of textStyleFields) { - if (field === 'textDecoration') { - nc.textDecoration = style.textDecoration - } else if (style[field] !== undefined) { - nc[field] = style[field] as never - } - } - } + for (const nc of changeMap.values()) applyStyleRefsToFields(changeMap, nc) } export interface FigImportOptions { diff --git a/packages/core/src/kiwi/instance-overrides/symbol/overrides.ts b/packages/core/src/kiwi/instance-overrides/symbol/overrides.ts index 733aa435c..1db60c68b 100644 --- a/packages/core/src/kiwi/instance-overrides/symbol/overrides.ts +++ b/packages/core/src/kiwi/instance-overrides/symbol/overrides.ts @@ -1,7 +1,7 @@ import { resolveOverrideTarget, repopulateInstance } from '#core/kiwi/instance-overrides/resolve' import type { OverrideContext } from '#core/kiwi/instance-overrides/types' -import type { GUID } from '#core/kiwi/binary/codec' import { guidToString } from '#core/kiwi/node-change/convert' +import { applyStyleRefsToFields } from '#core/kiwi/node-change/style-refs' import type { SceneNode } from '#core/scene-graph' import { convertOverrideToProps } from './props' @@ -10,13 +10,6 @@ function isActiveInstance(ctx: OverrideContext, nodeId: string | undefined): nod return nodeId !== undefined && (!ctx.activeNodeIds || ctx.activeNodeIds.has(nodeId)) } -function resolveStrokeFillStyle(ctx: OverrideContext, fields: Record): void { - const guid = (fields.styleIdForStrokeFill as { guid?: GUID } | undefined)?.guid - if (!guid || fields.strokePaints !== undefined) return - const style = ctx.changeMap.get(guidToString(guid)) - if (style?.styleType === 'FILL' && style.fillPaints) fields.strokePaints = style.fillPaints -} - function preserveStrokeShapeProps(target: SceneNode, updates: Partial): void { if (!updates.strokes) return updates.strokes = updates.strokes.map((stroke, index) => { @@ -80,7 +73,7 @@ export function applySymbolOverrides(ctx: OverrideContext): Set { const { guidPath: _, overriddenSymbolID: _s, componentPropAssignments: _c, ...fields } = ov if (Object.keys(fields).length === 0) continue - resolveStrokeFillStyle(ctx, fields) + applyStyleRefsToFields(ctx.changeMap, fields) const updates = convertOverrideToProps(fields as Record) if (Object.keys(updates).length > 0) { const target = ctx.graph.getNode(targetId) diff --git a/packages/core/src/kiwi/node-change/style-refs.ts b/packages/core/src/kiwi/node-change/style-refs.ts new file mode 100644 index 000000000..b5f0b3173 --- /dev/null +++ b/packages/core/src/kiwi/node-change/style-refs.ts @@ -0,0 +1,61 @@ +import type { GUID, NodeChange } from '#core/kiwi/binary/codec' +import { guidToString } from '#core/kiwi/node-change/guid' + +const TEXT_STYLE_FIELDS = [ + 'fontSize', + 'fontName', + 'lineHeight', + 'letterSpacing', + 'textDecoration', + 'textCase' +] as const + +type StyleRefFields = Record & { + styleIdForFill?: { guid?: GUID } + styleIdForStrokeFill?: { guid?: GUID } + styleIdForText?: { guid?: GUID } +} + +type StyleSource = Pick< + NodeChange, + | 'type' + | 'styleType' + | 'fillPaints' + | 'fontSize' + | 'fontName' + | 'lineHeight' + | 'letterSpacing' + | 'textDecoration' + | 'textCase' +> + +export function applyStyleRefsToFields( + changeMap: ReadonlyMap>, + fields: StyleRefFields +): void { + const fillStyleGuid = fields.styleIdForFill?.guid + if (fillStyleGuid) { + const style = changeMap.get(guidToString(fillStyleGuid)) + if (style?.styleType === 'FILL' && style.fillPaints) fields.fillPaints = style.fillPaints + } + + const strokeFillStyleGuid = fields.styleIdForStrokeFill?.guid + if (strokeFillStyleGuid && fields.strokePaints === undefined) { + const style = changeMap.get(guidToString(strokeFillStyleGuid)) + if (style?.styleType === 'FILL' && style.fillPaints) fields.strokePaints = style.fillPaints + } + + const textStyleGuid = fields.styleIdForText?.guid + if (!textStyleGuid) return + + const style = changeMap.get(guidToString(textStyleGuid)) + if (style?.type !== 'TEXT' || style.styleType !== 'TEXT') return + + for (const field of TEXT_STYLE_FIELDS) { + if (field === 'textDecoration') { + fields.textDecoration = style.textDecoration + } else if (style[field] !== undefined) { + fields[field] = style[field] + } + } +}