@publidata/utils-colors
Version:
Collection of methods to handle colors
203 lines (175 loc) • 5.91 kB
JavaScript
/**
* Will check if the given element is a valid CSS variable
* @param {String} str String to be parsed
* @return {Boolean} Return a boolean representing if the given string is a valid CSS variable
*/
export const isCssVariable = str => {
if (!str) return false;
if (str.startsWith("var(") && str.endsWith(")")) return true;
if (str.startsWith("--")) return true;
return false;
};
/**
* Removes "var(" and ")" from a given string
* @param {String} str String representing the CSS variable
* @return {String} Return the string without "var(" and ")"
*/
export const getSearchableCssVariable = str => {
if (!str) return "";
if (str.startsWith("var(") && str.endsWith(")")) return str.slice(4, -1);
return str;
};
/**
* Will fetch the value of the given CSS variable
* @param {String} variable String representing the CSS variable
* @return {String} Return the value of the given CSS variable if it exists, else return null
*/
export const getCssVariableValue = variable => {
if (typeof window === "undefined") return;
if (!variable) return null;
if (!isCssVariable(variable)) {
return variable;
}
const hexaColor = window
.getComputedStyle(document.documentElement)
.getPropertyValue(getSearchableCssVariable(variable))
.trim();
return hexaColor.length ? hexaColor : null;
};
/** Return an hexadecimal color as RGB valid color
* @Param: String, an hexadecimal valid color
* @Param: [String], the format with wich the color should be returned string by default
* @Return: String or Array, as a valid CSS color
*/
export const hexaToRgb = (hexa, format = "string") => {
if (!hexa) return null;
const shades = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hexa);
const asArray = shades
? shades.slice(1, 4).map(shade => parseInt(shade, 16))
: null;
return asArray && format === "string" ? asArray.join(", ") : asArray;
};
/** Return an hexadecimal color as RGBA valid color
* @Param String, could be an hexa or an array of 3 RGB colors
* @Param Number, between 0 and 1
* @Return String, of RGBA color
*/
export const hexaToRgba = (hexa, alpha = 1) => {
if (!hexa) return null;
const rgb = hexaToRgb(hexa);
if (!rgb) return null;
let parsedAlpha = alpha > 1 ? 1 : alpha < 0 ? 0 : alpha;
return `${rgb}, ${parsedAlpha}`;
};
/** Return an hexadecimal color
* @Param String, could be an hexa or an array of 3 RGB colors
* @Return String, value for css color properties
*/
export const hexify = color => {
if (!color || typeof color !== "string") return null;
const values = color
.replace(/rgba?/, "")
.replace(/[(|)]/, "")
.replace(/[\s+]/g, "")
.split(",");
const a = parseFloat(values[3] || 1);
const hexArray = values
.slice(0, 3)
.map(value => Math.floor(a * parseInt(value) + (1 - a) * 255));
hexArray.forEach(
(hex, index) => (hexArray[index] = ("0" + hex.toString(16)).slice(-2))
);
return `#${hexArray.join("")}`;
};
/** Return an hexadecimal color with a darker or lighter shade
* @credits https://css-tricks.com/snippets/javascript/lighten-darken-color
* @Param String, color as hexadecimal
* @Param Number, negative for lighter color and positive for darker
* @Return String, Hexa color with different shade
*/
export const getShade = (color, shade) => {
if (!color || typeof color !== "string") return null;
let usePound = false;
let output = color;
if (color[0] === "#") {
output = color.slice(1);
usePound = true;
}
const num = parseInt(output, 16);
let r = (num >> 16) + shade;
if (r > 255) r = 255;
else if (r < 0) r = 0;
let g = (num & 0x0000ff) + shade;
if (g > 255) g = 255;
else if (g < 0) g = 0;
let b = ((num >> 8) & 0x00ff) + shade;
if (b > 255) b = 255;
else if (b < 0) b = 0;
return `${usePound ? "#" : ""} ${(g | (b << 8) | (r << 16)).toString(
16
)}`.replaceAll(" ", "");
};
/** Return css valid value from a color and an opacity
* @Param: String, could be an hexa or an array of 3 RGB colors
* @Return: String, value for css color properties
*/
export const getCSSColor = (color, alpha = 1) => {
if (!color) return color;
const isArray = Array.isArray(color) && color.length === 3;
const isHexa = typeof color === "string";
if (isHexa || isArray) {
let r, g, b;
if (isHexa) {
const rgb = hexaToRgb(color, "array");
if (!rgb) return color;
[r, g, b] = rgb;
} else [r, g, b] = color;
return alpha === 1
? `rgba(${r}, ${g}, ${b})`
: `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
return color;
};
/*
Shade and Tint generators
@credits: https://github.com/edelstone/tints-and-shades/blob/main/scripts/tints-and-shades.js
*/
const pad = (number, length) => {
var str = "" + number;
while (str.length < length) {
str = "0" + str;
}
return str;
};
const intToHex = rgbint => {
return pad(Math.min(Math.max(Math.round(rgbint), 0), 255).toString(16), 2);
};
const calculate = (colorValue, shadeOrTint) => {
const color = {
red: parseInt(colorValue.substr(0, 2), 16),
green: parseInt(colorValue.substr(2, 2), 16),
blue: parseInt(colorValue.substr(4, 2), 16)
};
var shadeValues = [];
function rgbObjToHex(rgb) {
return intToHex(rgb.red) + intToHex(rgb.green) + intToHex(rgb.blue);
}
for (var i = 0; i < 10; i++) {
shadeValues[i] = rgbObjToHex(shadeOrTint(color, i));
}
return shadeValues;
};
const rgbTint = (rgb, i) => ({
red: rgb.red + (255 - rgb.red) * i * 0.1,
green: rgb.green + (255 - rgb.green) * i * 0.1,
blue: rgb.blue + (255 - rgb.blue) * i * 0.1
});
export const getTints = colorValue =>
calculate(colorValue, rgbTint).concat("ffffff");
const rgbShade = (rgb, i) => ({
red: rgb.red * (1 - 0.1 * i),
green: rgb.green * (1 - 0.1 * i),
blue: rgb.blue * (1 - 0.1 * i)
});
export const getShades = colorValue =>
calculate(colorValue, rgbShade).concat("000000");