UNPKG

@tokens-studio/graph-engine

Version:

An execution engine to handle Token Studios generators and resolvers

84 lines 3.29 kB
import { BooleanSchema, ColorSchema, NumberSchema, StringSchema } from '../../schemas/index.js'; import { ContrastAlgorithm } from '../../types/index.js'; import { Node } from '../../programmatic/node.js'; import { White, toColor } from './lib/utils.js'; import { arrayOf } from '../../schemas/utils.js'; /** * Evaluates an array of colors against a background color and returns the first one that meets the contrast threshold */ export default class NodeDefinition extends Node { static title = 'Contrasting from Array'; static type = 'studio.tokens.color.contrastingFromArray'; static description = 'Takes an array of colors and returns the first one that meets the contrast threshold against the background color. If no color meets the threshold, returns the color with the highest contrast.'; constructor(props) { super(props); this.addInput('colors', { type: arrayOf(ColorSchema) }); this.addInput('background', { type: { ...ColorSchema, default: White } }); this.addInput('algorithm', { type: { ...StringSchema, enum: Object.values(ContrastAlgorithm), default: ContrastAlgorithm.APCA } }); this.addInput('threshold', { type: { ...NumberSchema, default: 60 } }); this.addOutput('sufficient', { type: BooleanSchema }); this.addOutput('color', { type: ColorSchema }); this.addOutput('contrast', { type: NumberSchema }); this.addOutput('index', { type: NumberSchema }); } execute() { const { algorithm, colors, background, threshold } = this.getAllInputs(); if (!colors || colors.length === 0) { throw new Error('No colors provided'); } const backgroundCol = toColor(background); let maxContrast = -Infinity; let maxContrastColor = colors[0]; let maxContrastIndex = 0; // Find the first color that meets the threshold, or the one with highest contrast for (let i = 0; i < colors.length; i++) { const color = colors[i]; const contrast = Math.abs(backgroundCol.contrast(toColor(color), algorithm)); if (contrast >= threshold) { // Found a color that meets the threshold, return it immediately this.outputs.color.set(color); this.outputs.sufficient.set(true); this.outputs.contrast.set(contrast); this.outputs.index.set(i); return; } if (contrast > maxContrast) { maxContrast = contrast; maxContrastColor = color; maxContrastIndex = i; } } // If we get here, no color met the threshold, return the one with highest contrast this.outputs.color.set(maxContrastColor); this.outputs.sufficient.set(false); this.outputs.contrast.set(maxContrast); this.outputs.index.set(maxContrastIndex); } } //# sourceMappingURL=contrastingFromArray.js.map