diff --git a/src/common/color/hex.ts b/src/common/color/hex.ts index af394ed85f..ad5e6e64ae 100644 --- a/src/common/color/hex.ts +++ b/src/common/color/hex.ts @@ -1,23 +1,40 @@ +import { formatHex, parse } from "culori"; + +/** + * Expands a 3-digit hex color to a 6-digit hex color. + * @param hex - The hex color to expand. + * @returns The expanded hex color. + * @throws If the hex color is invalid. + */ export const expandHex = (hex: string): string => { - hex = hex.replace("#", ""); - if (hex.length === 6) return hex; - let result = ""; - for (const val of hex) { - result += val + val; + const color = parse(hex); + if (!color) { + throw new Error(`Invalid hex color: ${hex}`); } - return result; + const formattedColor = formatHex(color); + if (!formattedColor) { + throw new Error(`Could not format hex color: ${hex}`); + } + return formattedColor.replace("#", ""); }; -// Blend 2 hex colors: c1 is placed over c2, blend is c1's opacity. +/** + * Blends two hex colors. c1 is placed over c2, blend is c1's opacity. + * @param c1 - The first hex color. + * @param c2 - The second hex color. + * @param blend - The blend percentage (0-100). + * @returns The blended hex color. + */ export const hexBlend = (c1: string, c2: string, blend = 50): string => { - let color = ""; c1 = expandHex(c1); c2 = expandHex(c2); + let color = ""; for (let i = 0; i <= 5; i += 2) { const h1 = parseInt(c1.substring(i, i + 2), 16); const h2 = parseInt(c2.substring(i, i + 2), 16); - let hex = Math.floor(h2 + (h1 - h2) * (blend / 100)).toString(16); - while (hex.length < 2) hex = "0" + hex; + const hex = Math.floor(h2 + (h1 - h2) * (blend / 100)) + .toString(16) + .padStart(2, "0"); color += hex; } return `#${color}`;