export function hexToRGB(H: string) { let r = '0', g = '0', b = '0'; switch (H.length) { case 4: r = '0x' + H[1] + H[1]; g = '0x' + H[2] + H[2]; b = '0x' + H[3] + H[3]; break; case 7: r = '0x' + H[1] + H[2]; g = '0x' + H[3] + H[4]; b = '0x' + H[5] + H[6]; break; default: r = '0x' + '0' + '0'; g = '0x' + '0' + '0'; b = '0x' + '0' + '0'; break; } return { r: parseInt(r), g: parseInt(g), b: parseInt(b) }; } export function hexToHSL(H: string) { // Convert hex to RGB first const { r, g, b } = hexToRGB(H); // Then to HSL const intR = r / 255; const intG = g / 255; const intB = b / 255; let cmin = Math.min(intR, intG, intB), cmax = Math.max(intR, intG, intB), delta = cmax - cmin, h = 0, s = 0, l = 0; if (delta === 0) h = 0; else if (cmax === intR) h = ((intG - intB) / delta) % 6; else if (cmax === intG) h = (intB - intR) / delta + 2; else h = (intR - intG) / delta + 4; h = Math.round(h * 60); if (h < 0) h += 360; l = (cmax + cmin) / 2; s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1)); s = +(s * 100).toFixed(1); l = +(l * 100).toFixed(1); return { h, s, l }; // return 'hsl(' + h + ',' + s + '%,' + l + '%)'; } export function convertChannels(r: number, g: number, b: number, m: number) { // Having obtained RGB, convert channels to hex let stringR = Math.round((r + m) * 255).toString(16); let stringG = Math.round((g + m) * 255).toString(16); let stringB = Math.round((b + m) * 255).toString(16); // Prepend 0s, if necessary if (stringR.length == 1) stringR = '0' + stringR; if (stringG.length == 1) stringG = '0' + stringG; if (stringB.length == 1) stringB = '0' + stringB; return '#' + stringR + stringG + stringB; } export function gteAndLt(x: number, y: number, z: number) { return x <= y && y < z; } export function HSLToHex(h: number, s: number, l: number) { const newH = gteAndLt(0, h, 360) ? h : 360; const newS = s / 100; const newL = l / 100; // chroma - color intensity const c = (1 - Math.abs(2 * newL - 1)) * newS; const x = c * (1 - Math.abs(((newH / 60) % 2) - 1)); // lightness to match when converting channels const m = newL - c / 2; switch (true) { case gteAndLt(0, newH, 60): return convertChannels(c, x, 0, m); case gteAndLt(60, newH, 120): return convertChannels(x, c, 0, m); case gteAndLt(120, newH, 180): return convertChannels(0, c, x, m); case gteAndLt(180, newH, 240): return convertChannels(0, x, c, m); case gteAndLt(240, newH, 300): return convertChannels(x, 0, c, m); case gteAndLt(300, newH, 360): default: return convertChannels(c, 0, x, m); } } export function lightOrDark(H: string) { const { r, g, b } = hexToRGB(H); const hsp = Math.sqrt(0.299 * (r * r) + 0.587 * (g * g) + 0.114 * (b * b)); // Using the HSP value, determine whether the color is light or dark if (hsp > 127.5) { return 'light'; } else { return 'dark'; } }