CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-tinycolor2

Fast color parsing and manipulation library with comprehensive conversion and accessibility features

Pending
Overview
Eval results
Files

utilities.mddocs/

Utility Functions

Additional utility functions for color comparison, mixing, random color generation, and working with ratio-based values. These static methods provide essential tools for advanced color operations and programmatic color generation.

Capabilities

Color Comparison

Compare Colors for Equality

Compares two colors to determine if they represent the same color value.

/**
 * Compares two colors for equality
 * @param color1 - First color (any valid tinycolor input)
 * @param color2 - Second color (any valid tinycolor input)
 * @returns boolean indicating if colors are equal
 */
tinycolor.equals(color1: any, color2: any): boolean;

Usage Examples:

import tinycolor from "tinycolor2";

// Compare different representations of the same color
const red1 = "#ff0000";
const red2 = "rgb(255, 0, 0)";
const red3 = "red";
const red4 = {r: 255, g: 0, b: 0};

console.log(tinycolor.equals(red1, red2)); // true
console.log(tinycolor.equals(red2, red3)); // true
console.log(tinycolor.equals(red3, red4)); // true

// Compare different colors
console.log(tinycolor.equals("red", "blue")); // false

// Compare with slight variations
const almostRed = "#ff0001";
console.log(tinycolor.equals("red", almostRed)); // false

// Useful for color validation in arrays
const palette = ["#ff0000", "#00ff00", "#0000ff"];
const targetColor = "rgb(255, 0, 0)";

const exists = palette.some(color => tinycolor.equals(color, targetColor));
console.log("Color exists in palette:", exists); // true

// Remove duplicates from color array
function removeDuplicateColors(colors) {
  const unique = [];
  colors.forEach(color => {
    const isDuplicate = unique.some(existing => tinycolor.equals(existing, color));
    if (!isDuplicate) {
      unique.push(color);
    }
  });
  return unique;
}

const colorsWithDupes = ["red", "#ff0000", "rgb(255,0,0)", "blue", "#0000ff"];
const uniqueColors = removeDuplicateColors(colorsWithDupes);

Color Mixing

Mix Two Colors

Blends two colors together by a specified percentage.

/**
 * Mixes two colors together
 * @param color1 - First color (any valid tinycolor input)
 * @param color2 - Second color (any valid tinycolor input)
 * @param amount - Mixing percentage (0-100), where 0 returns color1, 100 returns color2
 * @returns new tinycolor instance representing the mixed color
 */
tinycolor.mix(color1: any, color2: any, amount?: number): tinycolor;

Usage Examples:

// Basic color mixing
const red = "red";
const blue = "blue";

const purple25 = tinycolor.mix(red, blue, 25);  // 25% blue, 75% red
const purple50 = tinycolor.mix(red, blue, 50);  // Equal mix
const purple75 = tinycolor.mix(red, blue, 75);  // 75% blue, 25% red

console.log("25% blue:", purple25.toHexString()); // More red
console.log("50% mix:", purple50.toHexString());  // Equal purple
console.log("75% blue:", purple75.toHexString()); // More blue

// Create gradients
function createGradient(startColor, endColor, steps = 10) {
  const gradient = [];
  for (let i = 0; i <= steps; i++) {
    const amount = (i / steps) * 100;
    const mixed = tinycolor.mix(startColor, endColor, amount);
    gradient.push(mixed.toHexString());
  }
  return gradient;
}

const redToBlue = createGradient("#ff0000", "#0000ff", 5);
console.log("Gradient:", redToBlue);

// Mix with transparency
const opaqueRed = "rgba(255, 0, 0, 1)";
const transparentBlue = "rgba(0, 0, 255, 0.3)";
const mixed = tinycolor.mix(opaqueRed, transparentBlue, 50);

console.log("Mixed with alpha:", mixed.toRgbString());

// Color blending for design
function blendColors(baseColor, overlayColor, opacity) {
  return tinycolor.mix(baseColor, overlayColor, opacity * 100);
}

const background = "#ffffff";
const overlay = "#ff0000";
const blended = blendColors(background, overlay, 0.3);

Random Color Generation

Generate Random Color

Creates a completely random color.

/**
 * Generates a random color
 * @returns new tinycolor instance with random RGB values
 */
tinycolor.random(): tinycolor;

Usage Examples:

// Generate single random color
const randomColor = tinycolor.random();
console.log("Random color:", randomColor.toHexString());

// Generate multiple random colors
const randomPalette = Array.from({length: 5}, () => tinycolor.random());
console.log("Random palette:", randomPalette.map(c => c.toHexString()));

// Generate random colors with constraints
function randomColorWithConstraints(options = {}) {
  const {
    minBrightness = 0,
    maxBrightness = 255,
    minSaturation = 0,
    maxSaturation = 1,
    hueRange = null
  } = options;
  
  let color;
  let attempts = 0;
  const maxAttempts = 100;
  
  do {
    color = tinycolor.random();
    const hsl = color.toHsl();
    const brightness = color.getBrightness();
    
    const brightnessOk = brightness >= minBrightness && brightness <= maxBrightness;
    const saturationOk = hsl.s >= minSaturation && hsl.s <= maxSaturation;
    const hueOk = !hueRange || (hsl.h >= hueRange[0] && hsl.h <= hueRange[1]);
    
    if (brightnessOk && saturationOk && hueOk) {
      return color;
    }
    
    attempts++;
  } while (attempts < maxAttempts);
  
  return color; // Return last attempt if no perfect match
}

// Generate bright colors only
const brightColors = Array.from({length: 3}, () => 
  randomColorWithConstraints({ minBrightness: 150 })
);

// Generate colors in blue range
const blueishColors = Array.from({length: 3}, () =>
  randomColorWithConstraints({ hueRange: [200, 260] })
);

// Generate pastel colors
const pastelColors = Array.from({length: 3}, () =>
  randomColorWithConstraints({ 
    minBrightness: 180, 
    maxSaturation: 0.6 
  })
);

Ratio-Based Color Creation

Create from Ratio Values

Creates colors using ratio values (0-1) instead of standard ranges.

/**
 * Creates a tinycolor from ratio values (0-1 range instead of 0-255 for RGB)
 * @param color - Color object with ratio values
 * @param opts - Optional configuration object
 * @returns new tinycolor instance
 */
tinycolor.fromRatio(color: {r?: number, g?: number, b?: number, h?: number, s?: number, l?: number, v?: number, a?: number}, opts?: object): tinycolor;

Usage Examples:

// RGB ratios (0-1 instead of 0-255)
const redRatio = tinycolor.fromRatio({r: 1, g: 0, b: 0});
const grayRatio = tinycolor.fromRatio({r: 0.5, g: 0.5, b: 0.5});
const customRatio = tinycolor.fromRatio({r: 0.8, g: 0.2, b: 0.6});

console.log("Red from ratio:", redRatio.toHexString());    // "#ff0000"
console.log("Gray from ratio:", grayRatio.toHexString());  // "#808080"
console.log("Custom from ratio:", customRatio.toHexString());

// HSL ratios
const blueHslRatio = tinycolor.fromRatio({h: 0.67, s: 1, l: 0.5}); // Blue
const orangeHslRatio = tinycolor.fromRatio({h: 0.083, s: 1, l: 0.5}); // Orange

// HSV ratios
const yellowHsvRatio = tinycolor.fromRatio({h: 0.167, s: 1, v: 1}); // Yellow

// With alpha ratios
const transparentRedRatio = tinycolor.fromRatio({r: 1, g: 0, b: 0, a: 0.5});
console.log("Transparent red:", transparentRedRatio.toRgbString());

// Useful for mathematical color generation
function generateColorFromData(value, min, max) {
  // Normalize value to 0-1 range
  const ratio = (value - min) / (max - min);
  
  // Create color based on ratio (red to green gradient)
  return tinycolor.fromRatio({
    r: 1 - ratio,  // Red decreases as value increases
    g: ratio,      // Green increases as value increases  
    b: 0,
    a: 1
  });
}

// Data visualization colors
const dataPoints = [10, 25, 50, 75, 90];
const minValue = Math.min(...dataPoints);
const maxValue = Math.max(...dataPoints);

const colors = dataPoints.map(value => 
  generateColorFromData(value, minValue, maxValue)
);

console.log("Data colors:", colors.map(c => c.toHexString()));

Advanced Utility Examples

Color Space Utilities

// Convert between different ratio representations
function convertRatios(color, fromSpace, toSpace) {
  const tc = tinycolor(color);
  
  switch (toSpace) {
    case 'rgb-ratio':
      const rgb = tc.toRgb();
      return {r: rgb.r/255, g: rgb.g/255, b: rgb.b/255, a: rgb.a};
      
    case 'hsl-ratio': 
      const hsl = tc.toHsl();
      return {h: hsl.h/360, s: hsl.s, l: hsl.l, a: hsl.a};
      
    case 'hsv-ratio':
      const hsv = tc.toHsv();
      return {h: hsv.h/360, s: hsv.s, v: hsv.v, a: hsv.a};
      
    default:
      return tc.toRgb();
  }
}

// Interpolation utilities
function interpolateColors(color1, color2, steps, space = 'rgb') {
  const colors = [];
  
  for (let i = 0; i <= steps; i++) {
    const ratio = i / steps;
    
    switch (space) {
      case 'hsl':
        const hsl1 = tinycolor(color1).toHsl();
        const hsl2 = tinycolor(color2).toHsl();
        
        colors.push(tinycolor.fromRatio({
          h: (hsl1.h + (hsl2.h - hsl1.h) * ratio) / 360,
          s: hsl1.s + (hsl2.s - hsl1.s) * ratio,
          l: hsl1.l + (hsl2.l - hsl1.l) * ratio,
          a: hsl1.a + (hsl2.a - hsl1.a) * ratio
        }));
        break;
        
      default:
        colors.push(tinycolor.mix(color1, color2, ratio * 100));
    }
  }
  
  return colors;
}

Color Validation and Correction

function validateAndCorrectColor(input, fallback = '#000000') {
  const color = tinycolor(input);
  
  if (!color.isValid()) {
    console.warn(`Invalid color "${input}", using fallback "${fallback}"`);
    return tinycolor(fallback);
  }
  
  return color;
}

function ensureContrast(backgroundColor, textColor, minRatio = 4.5) {
  const bgColor = validateAndCorrectColor(backgroundColor);
  let txtColor = validateAndCorrectColor(textColor);
  
  const currentRatio = tinycolor.readability(bgColor, txtColor);
  
  if (currentRatio >= minRatio) {
    return txtColor;
  }
  
  // Try to adjust text color
  const bgLuminance = bgColor.getLuminance();
  const preferDark = bgLuminance > 0.5;
  
  const options = preferDark 
    ? ['#000000', '#333333', '#666666']
    : ['#ffffff', '#cccccc', '#999999'];
    
  return tinycolor.mostReadable(bgColor, options);
}

Color Math Operations

// Weighted color mixing
function weightedMix(colors, weights) {
  if (colors.length !== weights.length) {
    throw new Error('Colors and weights arrays must have the same length');
  }
  
  const totalWeight = weights.reduce((sum, weight) => sum + weight, 0);
  
  // Convert all colors to RGB ratios
  const rgbColors = colors.map(color => {
    const rgb = tinycolor(color).toRgb();
    return {
      r: rgb.r / 255,
      g: rgb.g / 255,
      b: rgb.b / 255,
      a: rgb.a
    };
  });
  
  // Calculate weighted average
  const result = rgbColors.reduce((acc, color, index) => {
    const weight = weights[index] / totalWeight;
    return {
      r: acc.r + color.r * weight,
      g: acc.g + color.g * weight,
      b: acc.b + color.b * weight,
      a: acc.a + color.a * weight
    };
  }, {r: 0, g: 0, b: 0, a: 0});
  
  return tinycolor.fromRatio(result);
}

// Usage
const mixed = weightedMix(
  ['red', 'blue', 'green'], 
  [0.5, 0.3, 0.2]
);

// Color distance calculation
function colorDistance(color1, color2) {
  const rgb1 = tinycolor(color1).toRgb();
  const rgb2 = tinycolor(color2).toRgb();
  
  // Euclidean distance in RGB space
  const dr = rgb1.r - rgb2.r;
  const dg = rgb1.g - rgb2.g;
  const db = rgb1.b - rgb2.b;
  
  return Math.sqrt(dr * dr + dg * dg + db * db);
}

// Find closest color in palette
function findClosestColor(targetColor, palette) {
  let closest = palette[0];
  let minDistance = colorDistance(targetColor, closest);
  
  palette.forEach(color => {
    const distance = colorDistance(targetColor, color);
    if (distance < minDistance) {
      minDistance = distance;
      closest = color;
    }
  });
  
  return {
    color: closest,
    distance: minDistance
  };
}

Install with Tessl CLI

npx tessl i tessl/npm-tinycolor2

docs

accessibility.md

color-analysis.md

color-conversion.md

color-creation.md

color-modification.md

color-schemes.md

index.md

utilities.md

tile.json