azure-devops-ui
Version:
React components for building web UI in Azure DevOps
115 lines (114 loc) • 4.59 kB
JavaScript
export function darken(color, darkenFactor) {
const darkenMultiplier = 1 - darkenFactor;
return {
red: color.red * darkenMultiplier,
green: color.green * darkenMultiplier,
blue: color.blue * darkenMultiplier
};
}
export function getColorString(color) {
return `rgb(${color.red}, ${color.green}, ${color.blue})`;
}
export function isDark(color) {
const luminance = color.red * 0.299 + color.green * 0.587 + color.blue * 0.114;
return luminance <= 128;
}
export function rgbToHex(color) {
return `#${rgbValueToString(color.red)}${rgbValueToString(color.green)}${rgbValueToString(color.blue)}`.toUpperCase();
}
/**
* Convert a hex color to numeric r g b value
* @param color Color in format #aabbcc
*/
export function hexToRgb(color) {
if (color.length !== 7 || color[0] !== "#") {
throw new Error("Expected color in format #AABBCC");
}
return {
red: parseInt(color.substr(1, 2), 16),
green: parseInt(color.substr(3, 2), 16),
blue: parseInt(color.substr(5, 2), 16)
};
}
export function generateRandomColor() {
const blue = Math.floor(Math.random() * 256);
const green = Math.floor(Math.random() * 256);
const red = Math.floor(Math.random() * 256);
return { red, blue, green };
}
export function generateRandomColorHex() {
return rgbToHex(generateRandomColor());
}
export function parseColor(hexString) {
if (!hexString) {
return undefined;
}
let color = undefined;
if (hexString.length === 7) {
try {
color = hexToRgb(hexString);
}
catch (ex) {
console.log(ex);
// swallow the exception
}
}
return color;
}
export function adjustHighlightedTextColors(elements, lightTextColor, darkTextColor) {
var _a, _b;
const corrections = [];
// Check the contrast of lightTextColor and darkTextColor. If they are not good, fallback to white and black.
const parsedLightTextColor = parseCssColor(lightTextColor !== null && lightTextColor !== void 0 ? lightTextColor : "");
const parsedDarkTextColor = parseCssColor(darkTextColor !== null && darkTextColor !== void 0 ? darkTextColor : "");
const lightColor = lightTextColor && parsedLightTextColor && !isDark(parsedLightTextColor) ? lightTextColor : "#ffffff";
const darkColor = darkTextColor && parsedDarkTextColor && isDark(parsedDarkTextColor) ? darkTextColor : "#000000";
for (const element of elements) {
const backgroundColor = element.style.backgroundColor;
if (!backgroundColor) {
continue;
}
const parsedBackgroundColor = parseCssColor(backgroundColor);
if (!parsedBackgroundColor) {
continue;
}
const optimalTextColor = isDark(parsedBackgroundColor) ? lightColor : darkColor;
const actualTextColor = (_b = (_a = element.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView) === null || _b === void 0 ? void 0 : _b.getComputedStyle(element).color;
if (actualTextColor) {
const parsedTextColor = parseCssColor(actualTextColor);
if (parsedTextColor && isDark(parsedBackgroundColor) !== isDark(parsedTextColor)) {
// Check if contrast is good: dark text on light background or light text on dark background.
// If not, adjust text color. If yes, keep the original one.
continue;
}
}
corrections.push({ element, color: optimalTextColor });
}
for (const { element, color } of corrections) {
element.style.color = color;
}
}
const hexRegex = new RegExp("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$");
const rgbRegex = new RegExp("^rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)(?:\\s*,\\s*[\\d.]+)?\\s*\\)");
export function testForHexString(hexString) {
return hexString.match(hexRegex);
}
function rgbValueToString(colorCoord) {
let hexColor = colorCoord.toString(16);
if (hexColor.length === 1) {
hexColor = "0" + hexColor;
}
return hexColor;
}
function parseCssColor(color) {
const rgbMatch = color.trim().match(rgbRegex);
if ((rgbMatch === null || rgbMatch === void 0 ? void 0 : rgbMatch.length) === 4) {
return {
red: parseInt(rgbMatch[1]),
green: parseInt(rgbMatch[2]),
blue: parseInt(rgbMatch[3])
};
}
// Fallback to hex parsing.
return parseColor(color);
}