Initial public release of Warp.
Repo-Sync-Origin: warpdotdev/warp-internal@12af1d983b
This commit is contained in:
+108
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* createSemanticTokens
|
||||
*
|
||||
* Creates a batch of Figma variables in the given collection, one per entry in
|
||||
* `tokenMap`. Supports raw values, variable alias references, code syntax, and
|
||||
* scopes. Returns a map of token name → Variable for use in subsequent steps.
|
||||
*
|
||||
* @param {VariableCollection} collection - The target variable collection.
|
||||
* @param {Record<string, string>} modeIds - Map of {modeName: modeId} from createVariableCollection.
|
||||
* @param {Array<{
|
||||
* name: string,
|
||||
* type: 'COLOR' | 'FLOAT' | 'STRING' | 'BOOLEAN',
|
||||
* values: Record<string, string | number | boolean | {type: 'VARIABLE_ALIAS', id: string}>,
|
||||
* scopes?: VariableScope[],
|
||||
* codeSyntax?: {WEB?: string, ANDROID?: string, iOS?: string}
|
||||
* }>} tokenMap - Ordered list of token definitions.
|
||||
* - `name`: Variable name using slash hierarchy (e.g. "color/bg/primary").
|
||||
* - `type`: Figma variable type.
|
||||
* - `values`: Map of {modeName: value}. Values can be raw (hex string for COLOR,
|
||||
* number for FLOAT) or alias objects {type: 'VARIABLE_ALIAS', id: variableId}.
|
||||
* For COLOR, raw values are accepted as hex strings ("#rrggbb" or "#rrggbbaa")
|
||||
* and converted to {r, g, b, a} automatically.
|
||||
* - `scopes`: Array of VariableScope strings. Omit to use [] (hidden/primitive).
|
||||
* - `codeSyntax`: Platform code syntax strings. Omit to skip.
|
||||
* @param {string} [runId] - Optional dsb_run_id to tag every variable.
|
||||
* @returns {Promise<{variables: Record<string, Variable>}>}
|
||||
* `variables` maps each token name to its created Variable object.
|
||||
*/
|
||||
async function createSemanticTokens(collection, modeIds, tokenMap, runId) {
|
||||
const variables = {}
|
||||
|
||||
for (const token of tokenMap) {
|
||||
// Create the variable
|
||||
const variable = figma.variables.createVariable(token.name, collection, token.type)
|
||||
|
||||
// Tag for cleanup
|
||||
variable.setPluginData('dsb_key', `variable/${token.name}`)
|
||||
if (runId) {
|
||||
variable.setPluginData('dsb_run_id', runId)
|
||||
}
|
||||
|
||||
// Set values for each mode
|
||||
for (const [modeName, rawValue] of Object.entries(token.values)) {
|
||||
const modeId = modeIds[modeName]
|
||||
if (!modeId) {
|
||||
throw new Error(
|
||||
`createSemanticTokens: mode "${modeName}" not found in modeIds for token "${token.name}". ` +
|
||||
`Available modes: ${Object.keys(modeIds).join(', ')}`,
|
||||
)
|
||||
}
|
||||
|
||||
let value = rawValue
|
||||
|
||||
// Convert hex strings to Figma RGBA for COLOR type
|
||||
if (token.type === 'COLOR' && typeof rawValue === 'string' && rawValue.startsWith('#')) {
|
||||
value = hexToFigmaColor(rawValue)
|
||||
}
|
||||
|
||||
variable.setValueForMode(modeId, value)
|
||||
}
|
||||
|
||||
// Set scopes (default: empty array = hidden from property pickers / primitives)
|
||||
variable.scopes = token.scopes || []
|
||||
|
||||
// Set code syntax per platform
|
||||
if (token.codeSyntax) {
|
||||
if (token.codeSyntax.WEB) {
|
||||
variable.setVariableCodeSyntax('WEB', token.codeSyntax.WEB)
|
||||
}
|
||||
if (token.codeSyntax.ANDROID) {
|
||||
variable.setVariableCodeSyntax('ANDROID', token.codeSyntax.ANDROID)
|
||||
}
|
||||
if (token.codeSyntax.iOS) {
|
||||
variable.setVariableCodeSyntax('iOS', token.codeSyntax.iOS)
|
||||
}
|
||||
}
|
||||
|
||||
variables[token.name] = variable
|
||||
}
|
||||
|
||||
return { variables }
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a hex color string to a Figma RGBA object.
|
||||
* Supports "#rgb", "#rrggbb", and "#rrggbbaa".
|
||||
*
|
||||
* @param {string} hex
|
||||
* @returns {{ r: number, g: number, b: number, a: number }}
|
||||
*/
|
||||
function hexToFigmaColor(hex) {
|
||||
let h = hex.replace('#', '')
|
||||
|
||||
// Expand shorthand #rgb → #rrggbb
|
||||
if (h.length === 3) {
|
||||
h = h
|
||||
.split('')
|
||||
.map((c) => c + c)
|
||||
.join('')
|
||||
}
|
||||
|
||||
const r = parseInt(h.substring(0, 2), 16) / 255
|
||||
const g = parseInt(h.substring(2, 4), 16) / 255
|
||||
const b = parseInt(h.substring(4, 6), 16) / 255
|
||||
const a = h.length === 8 ? parseInt(h.substring(6, 8), 16) / 255 : 1
|
||||
|
||||
return { r, g, b, a }
|
||||
}
|
||||
Reference in New Issue
Block a user