dashboard/shell/utils/color.js

138 lines
3.7 KiB
JavaScript

/*
Primary color classes from _light.scss
--primary : #{$primary};
--primary-text : #{contrast-color($primary)};
--primary-hover-bg : #{darken($primary, 10%)};
--primary-hover-text : #{saturate($lightest, 20%)};
--primary-active-bg : #{darken($primary, 25%)};
--primary-active-text : #{contrast-color(darken($primary, 25%))};
--primary-border : #($primary);
--primary-banner-bg : #{rgba($primary, 0.15)};
--primary-light-bg : #{rgba($primary, 0.05)};
*/
const Color = require('color');
export function createCssVars(color, theme = 'light', name = 'primary') {
const contrastOpts = theme === 'light' ? LIGHT_CONTRAST_COLORS : DARK_CONTRAST_COLORS;
return {
[`--${ name }`]: color,
[`--${ name }-text `]: contrastColor(color, contrastOpts),
[`--${ name }-hover-bg`]: lighten(color, -10),
[`--${ name }-active-bg`]: lighten(color, -25),
[`--${ name }-active-text`]: contrastColor(lighten(color, -25), contrastOpts),
[`--${ name }-border`]: color,
[`--${ name }-banner-bg`]: opacity(color, 0.15),
[`--${ name }-light-bg`]: opacity(color, 0.05),
};
}
// scss 'lighten(color, percent)' increases color's hsl lightness by percent amount, not scaled
function lighten(color, amount) {
const inHSL = Color(color)?.hsl()?.color;
inHSL[2] -= amount;
return Color.hsl(inHSL).rgb().string();
}
function opacity(color, val) {
return Color(color).alpha(val).string();
}
/*
light theme
$contrasted-dark: $darkest !default; #141419;
$contrasted-light: $lightest !default; #FFFFFF
dark theme
$contrasted-dark: $lightest !default; #ffffff;
$contrasted-light: $darkest !default; #141419
*/
const LIGHT_CONTRAST_COLORS = {
dark: 'rgb(20, 20, 25)',
light: 'rgb(255, 255, 255)'
};
const DARK_CONTRAST_COLORS = {
dark: 'rgb(255, 255, 255)',
light: 'rgb(20, 20, 25)',
};
const STANDARD_COLORS = {
black: '#000000',
white: '#ffffff',
};
// contrastColor(color, {light, dark}) returns which of 2 options is higher contrast with color
export function contrastColor(color, contrastOptions = LIGHT_CONTRAST_COLORS) {
let out = contrastOptions.light;
const contrastDark = Color(color).contrast(Color(contrastOptions.dark));
const contrastLight = Color(color).contrast(Color(contrastOptions.light));
if (contrastDark > contrastLight) {
out = contrastOptions.dark;
}
return out;
}
export function parseColor(str) {
return Color(str);
}
export function textColor(color) {
const rgb = color.rgb().array();
// http://www.w3.org/TR/AERT#color-contrast
const brightness = Math.round(((parseInt(rgb[0]) * 299) +
(parseInt(rgb[1]) * 587) +
(parseInt(rgb[2]) * 114)) / 1000);
return (brightness > 125) ? 'black' : 'white';
}
export function hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
export function mapStandardColors(color) {
return STANDARD_COLORS[color] || color;
}
export function rgbToRgb(rgb) {
const result = /^rgb\(([0-9]{1,3}),\s*([0-9]{1,3}),\s*([0-9]{1,3})\)$/i.exec(rgb);
return result ? {
r: parseInt(result[1], 10),
g: parseInt(result[2], 10),
b: parseInt(result[3], 10)
} : null;
}
export function colorToRgb(color) {
let value;
if (color.startsWith('rgb(')) {
value = rgbToRgb(color);
} else if (color.startsWith('#')) {
value = hexToRgb(color);
} else {
console.warn(`Unable to parse color: ${ color }`); // eslint-disable-line no-console
}
return value || {
r: 0, g: 0, b: 0
};
}