mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-10 07:11:25 +03:00
120 lines
3.9 KiB
JavaScript
120 lines
3.9 KiB
JavaScript
/**
|
|
* bindVariablesToComponent
|
|
*
|
|
* Binds design token variables to the visual properties of a component node.
|
|
* Supports fills, strokes, all padding directions, item spacing, and corner radius.
|
|
* Only binds properties for which a variable ID is provided in `bindings`.
|
|
*
|
|
* This function should be called on each variant individually within a component
|
|
* set, OR on the component set itself for properties shared by all variants.
|
|
*
|
|
* @param {ComponentNode | FrameNode | RectangleNode} component
|
|
* The Figma node to mutate. Usually a ComponentNode or one of its children.
|
|
* @param {{
|
|
* fills?: string,
|
|
* strokes?: string,
|
|
* paddingTop?: string,
|
|
* paddingBottom?: string,
|
|
* paddingLeft?: string,
|
|
* paddingRight?: string,
|
|
* itemSpacing?: string,
|
|
* cornerRadius?: string
|
|
* }} bindings
|
|
* Each key is a visual property name; each value is a Figma Variable ID
|
|
* (e.g. "VariableID:123:456"). Omit a key to skip binding that property.
|
|
* @returns {Promise<{ mutatedNodeIds: string[] }>}
|
|
* List of node IDs that were mutated (for audit/validation purposes).
|
|
*/
|
|
async function bindVariablesToComponent(component, bindings) {
|
|
const mutatedNodeIds = []
|
|
|
|
if (!component) {
|
|
return { mutatedNodeIds }
|
|
}
|
|
|
|
// Batch every getVariableByIdAsync call upfront in a single Promise.all rather
|
|
// than awaiting per-property — the lookups are independent and IPC-bound.
|
|
const floatBindings = [
|
|
['paddingTop', 'paddingTop'],
|
|
['paddingBottom', 'paddingBottom'],
|
|
['paddingLeft', 'paddingLeft'],
|
|
['paddingRight', 'paddingRight'],
|
|
['itemSpacing', 'itemSpacing'],
|
|
['cornerRadius', 'cornerRadius'],
|
|
]
|
|
|
|
const requestedIds = []
|
|
if (bindings.fills) requestedIds.push(['fills', bindings.fills])
|
|
if (bindings.strokes) requestedIds.push(['strokes', bindings.strokes])
|
|
for (const [bindingKey] of floatBindings) {
|
|
if (bindings[bindingKey]) requestedIds.push([bindingKey, bindings[bindingKey]])
|
|
}
|
|
|
|
const resolved = await Promise.all(
|
|
requestedIds.map(([, id]) => figma.variables.getVariableByIdAsync(id)),
|
|
)
|
|
const varByKey = {}
|
|
for (let i = 0; i < requestedIds.length; i++) {
|
|
varByKey[requestedIds[i][0]] = resolved[i]
|
|
}
|
|
|
|
const markMutated = () => {
|
|
if (!mutatedNodeIds.includes(component.id)) {
|
|
mutatedNodeIds.push(component.id)
|
|
}
|
|
}
|
|
|
|
// --- Fills ---
|
|
const fillVar = varByKey.fills
|
|
if (fillVar) {
|
|
const existingFills = component.fills
|
|
if (Array.isArray(existingFills) && existingFills.length > 0) {
|
|
// Bind the color of the first fill to the variable
|
|
const boundFill = figma.variables.setBoundVariableForPaint(existingFills[0], 'color', fillVar)
|
|
component.fills = [boundFill, ...existingFills.slice(1)]
|
|
} else {
|
|
// No existing fill — create a solid fill bound to the variable
|
|
const boundFill = figma.variables.setBoundVariableForPaint(
|
|
{ type: 'SOLID', color: { r: 0.5, g: 0.5, b: 0.5 } },
|
|
'color',
|
|
fillVar,
|
|
)
|
|
component.fills = [boundFill]
|
|
}
|
|
markMutated()
|
|
}
|
|
|
|
// --- Strokes ---
|
|
const strokeVar = varByKey.strokes
|
|
if (strokeVar) {
|
|
const existingStrokes = component.strokes
|
|
if (Array.isArray(existingStrokes) && existingStrokes.length > 0) {
|
|
const boundStroke = figma.variables.setBoundVariableForPaint(
|
|
existingStrokes[0],
|
|
'color',
|
|
strokeVar,
|
|
)
|
|
component.strokes = [boundStroke, ...existingStrokes.slice(1)]
|
|
} else {
|
|
const boundStroke = figma.variables.setBoundVariableForPaint(
|
|
{ type: 'SOLID', color: { r: 0.5, g: 0.5, b: 0.5 } },
|
|
'color',
|
|
strokeVar,
|
|
)
|
|
component.strokes = [boundStroke]
|
|
}
|
|
markMutated()
|
|
}
|
|
|
|
// --- Spacing properties (FLOAT variables bound via setBoundVariable) ---
|
|
for (const [bindingKey, figmaProp] of floatBindings) {
|
|
const variable = varByKey[bindingKey]
|
|
if (variable) {
|
|
component.setBoundVariable(figmaProp, variable)
|
|
markMutated()
|
|
}
|
|
}
|
|
|
|
return { mutatedNodeIds }
|
|
}
|