aboutsummaryrefslogtreecommitdiffstats
path: root/code/app/src/utilities/colors.ts
blob: 34c7992d188805235b8fc6a1d61b68449d6c2354 (plain) (blame)
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
export function generate_random_hex_color(skip_contrast_check = false) {
    let hex = __generate_random_hex_color();
    if (skip_contrast_check) return hex;
    while ((__calculate_contrast_ratio("#ffffff", hex) < 4.5) || (__calculate_contrast_ratio("#000000", hex) < 4.5)) {
        hex = __generate_random_hex_color();
    }

    return hex;
}

// Largely copied from chroma js api
function __generate_random_hex_color(): string {
    let code = "#";
    for (let i = 0; i < 6; i++) {
        code += "0123456789abcdef".charAt(Math.floor(Math.random() * 16));
    }
    return code;
}

function __calculate_contrast_ratio(hex1: string, hex2: string): number {
    const rgb1 = __hex_to_rgb(hex1);
    const rgb2 = __hex_to_rgb(hex2);
    const l1 = __get_luminance(rgb1[0], rgb1[1], rgb1[2]);
    const l2 = __get_luminance(rgb2[0], rgb2[1], rgb2[2]);
    const result = l1 > l2 ? (l1 + 0.05) / (l2 + 0.05) : (l2 + 0.05) / (l1 + 0.05);
    return result;
}

function __hex_to_rgb(hex: string): number[] {
    if (!hex.match(/^#([A-Fa-f0-9]{6})$/)) return [];
    if (hex[0] === "#") hex = hex.substring(1, hex.length);
    return [parseInt(hex.substring(0, 2), 16), parseInt(hex.substring(2, 4), 16), parseInt(hex.substring(4, 6), 16)];
}

function __get_luminance(r: any, g: any, b: any) {
    // relative luminance
    // see http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
    r = __luminance_x(r);
    g = __luminance_x(g);
    b = __luminance_x(b);
    return 0.2126 * r + 0.7152 * g + 0.0722 * b;
}

function __luminance_x(x: any) {
    x /= 255;
    return x <= 0.03928 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
}