chore: add hslToHex and hexToHsl color helpers (#6629)
* chore: add more color helpers * chore: added error handling
This commit is contained in:
parent
cba27c348d
commit
3f6ef56a0f
1 changed files with 80 additions and 0 deletions
|
|
@ -7,6 +7,8 @@
|
|||
*/
|
||||
export type RGB = { r: number; g: number; b: number };
|
||||
|
||||
export type HSL = { h: number; s: number; l: number };
|
||||
|
||||
/**
|
||||
* @description Validates and clamps color values to RGB range (0-255)
|
||||
* @param {number} value - The color value to validate
|
||||
|
|
@ -62,3 +64,81 @@ export const hexToRgb = (hex: string): RGB => {
|
|||
* rgbToHex({ r: 0, g: 0, b: 255 }) // returns "#0000ff"
|
||||
*/
|
||||
export const rgbToHex = ({ r, g, b }: RGB): string => `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
||||
|
||||
/**
|
||||
* Converts Hex values to HSL values
|
||||
* @param {string} hex - The hexadecimal color code (e.g., "#ff0000" for red)
|
||||
* @returns {HSL} An object containing the HSL values
|
||||
* @example
|
||||
* hexToHsl("#ff0000") // returns { h: 0, s: 100, l: 50 }
|
||||
* hexToHsl("#00ff00") // returns { h: 120, s: 100, l: 50 }
|
||||
* hexToHsl("#0000ff") // returns { h: 240, s: 100, l: 50 }
|
||||
*/
|
||||
export const hexToHsl = (hex: string): HSL => {
|
||||
// return default value for invalid hex
|
||||
if (!/^#[0-9A-Fa-f]{6}$/.test(hex)) return { h: 0, s: 0, l: 0 };
|
||||
|
||||
const r = parseInt(hex.slice(1, 3), 16) / 255;
|
||||
const g = parseInt(hex.slice(3, 5), 16) / 255;
|
||||
const b = parseInt(hex.slice(5, 7), 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);
|
||||
break;
|
||||
case g:
|
||||
h = (b - r) / d + 2;
|
||||
break;
|
||||
case b:
|
||||
h = (r - g) / d + 4;
|
||||
break;
|
||||
}
|
||||
h /= 6;
|
||||
}
|
||||
|
||||
return {
|
||||
h: h * 360,
|
||||
s: s * 100,
|
||||
l: l * 100,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts HSL values to a hexadecimal color code
|
||||
* @param {HSL} hsl - An object containing HSL values
|
||||
* @param {number} hsl.h - Hue component (0-360)
|
||||
* @param {number} hsl.s - Saturation component (0-100)
|
||||
* @param {number} hsl.l - Lightness component (0-100)
|
||||
* @returns {string} The hexadecimal color code (e.g., "#ff0000" for red)
|
||||
* @example
|
||||
* hslToHex({ h: 0, s: 100, l: 50 }) // returns "#ff0000"
|
||||
* hslToHex({ h: 120, s: 100, l: 50 }) // returns "#00ff00"
|
||||
* hslToHex({ h: 240, s: 100, l: 50 }) // returns "#0000ff"
|
||||
*/
|
||||
export const hslToHex = ({ h, s, l }: HSL): string => {
|
||||
if (h < 0 || h > 360) return "#000000";
|
||||
if (s < 0 || s > 100) return "#000000";
|
||||
if (l < 0 || l > 100) return "#000000";
|
||||
|
||||
l /= 100;
|
||||
const a = (s * Math.min(l, 1 - l)) / 100;
|
||||
|
||||
const f = (n: number) => {
|
||||
const k = (n + h / 30) % 12;
|
||||
const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
|
||||
return Math.round(255 * color)
|
||||
.toString(16)
|
||||
.padStart(2, "0");
|
||||
};
|
||||
|
||||
return `#${f(0)}${f(8)}${f(4)}`;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue