All files / src/utils colorUtils.ts

100% Statements 66/66
100% Branches 23/23
100% Functions 7/7
100% Lines 45/45

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123                97x 97x   94x 94x 94x   94x 94x 94x 94x 94x   94x 89x 89x   89x   21x 21x   7x 7x   61x 61x       94x             271x 271x   271x 271x 271x   271x   271x 215x 203x 187x 3x 13x   813x 271x             27x   27x                                   16x 16x 142x               9x 9x     9x 9x           2x                        
/**
 * Color utility functions for generating brand color palettes
 */
 
/**
 * Convert hex color to HSL values
 */
export function hexToHSL(hex: string): { h: number; s: number; l: number } {
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  if (!result) return { h: 0, s: 0, l: 0 };
 
  const r = parseInt(result[1], 16) / 255;
  const g = parseInt(result[2], 16) / 255;
  const b = parseInt(result[3], 16) / 255;
 
  const max = Math.max(r, g, b);
  const min = Math.min(r, g, b);
  let h = 0;
  let s = 0;
  const l = (max + min) / 2;
 
  if (max !== min) {
    const d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
 
    switch (max) {
      case r:
        h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
        break;
      case g:
        h = ((b - r) / d + 2) / 6;
        break;
      case b:
        h = ((r - g) / d + 4) / 6;
        break;
    }
  }
 
  return { h: h * 360, s: s * 100, l: l * 100 };
}
 
/**
 * Convert HSL values to hex color
 */
export function hslToHex(h: number, s: number, l: number): string {
  s /= 100;
  l /= 100;
 
  const c = (1 - Math.abs(2 * l - 1)) * s;
  const x = c * (1 - Math.abs((h / 60) % 2 - 1));
  const m = l - c / 2;
 
  let r = 0, g = 0, b = 0;
 
  if (h < 60) { r = c; g = x; b = 0; }
  else if (h < 120) { r = x; g = c; b = 0; }
  else if (h < 180) { r = 0; g = c; b = x; }
  else if (h < 240) { r = 0; g = x; b = c; }
  else if (h < 300) { r = x; g = 0; b = c; }
  else { r = c; g = 0; b = x; }
 
  const toHex = (n: number) => Math.round((n + m) * 255).toString(16).padStart(2, '0');
  return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}
 
/**
 * Generate a color palette from a base color
 */
export function generateColorPalette(baseColor: string): Record<string, string> {
  const { h, s } = hexToHSL(baseColor);
 
  return {
    50: hslToHex(h, Math.min(s, 30), 97),
    100: hslToHex(h, Math.min(s, 40), 94),
    200: hslToHex(h, Math.min(s, 50), 86),
    300: hslToHex(h, Math.min(s, 60), 74),
    400: hslToHex(h, Math.min(s, 70), 60),
    500: hslToHex(h, s, 50),
    600: baseColor, // Use the exact primary color for 600
    700: hslToHex(h, s, 40),
    800: hslToHex(h, s, 32),
    900: hslToHex(h, s, 24),
  };
}
 
/**
 * Apply a color palette to CSS custom properties
 */
export function applyColorPalette(palette: Record<string, string>): void {
  const root = document.documentElement;
  Object.entries(palette).forEach(([shade, color]) => {
    root.style.setProperty(`--color-brand-${shade}`, color);
  });
}
 
/**
 * Apply primary and secondary colors including the secondary color variable
 */
export function applyBrandColors(primaryColor: string, secondaryColor?: string): void {
  const palette = generateColorPalette(primaryColor);
  applyColorPalette(palette);
 
  // Set the secondary color variable (used for gradients)
  const root = document.documentElement;
  root.style.setProperty('--color-brand-secondary', secondaryColor || primaryColor);
}
 
/**
 * Default brand color palette (blue)
 */
export const defaultColorPalette: Record<string, string> = {
  50: '#eff6ff',
  100: '#dbeafe',
  200: '#bfdbfe',
  300: '#93c5fd',
  400: '#60a5fa',
  500: '#3b82f6',
  600: '#2563eb',
  700: '#1d4ed8',
  800: '#1e40af',
  900: '#1e3a8a',
};