2022-03-22 10:37:57 -07:00
|
|
|
import tintify, { hexToRgb } from './colors';
|
2020-06-02 13:48:27 -07:00
|
|
|
|
2022-03-22 10:37:57 -07:00
|
|
|
import type { Rgb, Hsl, TailwindColorPalette } from 'soapbox/types/colors';
|
2020-09-27 19:25:48 -07:00
|
|
|
|
|
|
|
// Taken from chromatism.js
|
|
|
|
// https://github.com/graypegg/chromatism/blob/master/src/conversions/rgb.js
|
2022-03-22 10:37:57 -07:00
|
|
|
const rgbToHsl = (value: Rgb): Hsl => {
|
2021-08-03 10:10:42 -07:00
|
|
|
const r = value.r / 255;
|
|
|
|
const g = value.g / 255;
|
|
|
|
const b = value.b / 255;
|
|
|
|
const rgbOrdered = [ r, g, b ].sort();
|
|
|
|
const l = ((rgbOrdered[0] + rgbOrdered[2]) / 2) * 100;
|
|
|
|
let s, h;
|
2020-09-27 19:25:48 -07:00
|
|
|
if (rgbOrdered[0] === rgbOrdered[2]) {
|
|
|
|
s = 0;
|
|
|
|
h = 0;
|
|
|
|
} else {
|
|
|
|
if (l >= 50) {
|
|
|
|
s = ((rgbOrdered[2] - rgbOrdered[0]) / ((2.0 - rgbOrdered[2]) - rgbOrdered[0])) * 100;
|
|
|
|
} else {
|
|
|
|
s = ((rgbOrdered[2] - rgbOrdered[0]) / (rgbOrdered[2] + rgbOrdered[0])) * 100;
|
|
|
|
}
|
|
|
|
if (rgbOrdered[2] === r) {
|
|
|
|
h = ((g - b) / (rgbOrdered[2] - rgbOrdered[0])) * 60;
|
|
|
|
} else if (rgbOrdered[2] === g) {
|
|
|
|
h = (2 + ((b - r) / (rgbOrdered[2] - rgbOrdered[0]))) * 60;
|
|
|
|
} else {
|
|
|
|
h = (4 + ((r - g) / (rgbOrdered[2] - rgbOrdered[0]))) * 60;
|
|
|
|
}
|
|
|
|
if (h < 0) {
|
|
|
|
h += 360;
|
|
|
|
} else if (h > 360) {
|
|
|
|
h = h % 360;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
h: h,
|
|
|
|
s: s,
|
|
|
|
l: l,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2022-03-22 10:37:57 -07:00
|
|
|
// https://stackoverflow.com/a/44134328
|
|
|
|
function hslToHex(color: Hsl): string {
|
|
|
|
const { h, s } = color;
|
|
|
|
let { l } = color;
|
|
|
|
|
|
|
|
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'); // convert to Hex and prefix "0" if needed
|
|
|
|
};
|
|
|
|
|
|
|
|
return `#${f(0)}${f(8)}${f(4)}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate accent color from brand color
|
|
|
|
const generateAccent = (brandColor: string): string => {
|
|
|
|
console.log(brandColor);
|
|
|
|
console.log(hexToRgb(brandColor));
|
|
|
|
const { h } = rgbToHsl(hexToRgb(brandColor));
|
|
|
|
return hslToHex({ h: h - 15, s: 86, l: 44 });
|
|
|
|
};
|
|
|
|
|
2022-03-21 16:57:23 -07:00
|
|
|
const parseShades = (obj: Record<string, any>, color: string, shades: Record<string, any>) => {
|
2022-03-07 15:19:54 -08:00
|
|
|
if (typeof shades === 'string') {
|
|
|
|
const { r, g, b } = hexToRgb(shades);
|
|
|
|
return obj[`--color-${color}`] = `${r} ${g} ${b}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Object.keys(shades).forEach(shade => {
|
|
|
|
const { r, g, b } = hexToRgb(shades[shade]);
|
|
|
|
obj[`--color-${color}-${shade}`] = `${r} ${g} ${b}`;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2022-03-22 10:37:57 -07:00
|
|
|
// Convert colors as CSS variables
|
|
|
|
const parseColors = (colors: TailwindColorPalette): TailwindColorPalette => {
|
2022-03-07 15:19:54 -08:00
|
|
|
return Object.keys(colors).reduce((obj, color) => {
|
|
|
|
parseShades(obj, color, colors[color]);
|
|
|
|
return obj;
|
|
|
|
}, {});
|
|
|
|
};
|
|
|
|
|
2022-03-22 10:37:57 -07:00
|
|
|
export const colorsToCss = (colors: TailwindColorPalette): string => {
|
2022-03-07 15:19:54 -08:00
|
|
|
const parsed = parseColors(colors);
|
|
|
|
return Object.keys(parsed).reduce((css, variable) => {
|
|
|
|
return css + `${variable}:${parsed[variable]};`;
|
|
|
|
}, '');
|
|
|
|
};
|
|
|
|
|
2022-03-22 10:37:57 -07:00
|
|
|
const legacyColorsToTailwind = (brandColor: string, accentColor: string): TailwindColorPalette => {
|
|
|
|
return {
|
|
|
|
primary: tintify(brandColor),
|
|
|
|
accent: tintify(accentColor ? accentColor : generateAccent(brandColor)),
|
2022-03-22 14:25:52 -07:00
|
|
|
gray: {
|
|
|
|
50: '#f9fafb',
|
|
|
|
100: '#f3f4f6',
|
|
|
|
200: '#e5e7eb',
|
|
|
|
300: '#d1d5db',
|
|
|
|
400: '#9ca3af',
|
|
|
|
500: '#6b7280',
|
|
|
|
600: '#4b5563',
|
|
|
|
700: '#374151',
|
|
|
|
800: '#1f2937',
|
|
|
|
900: '#111827',
|
|
|
|
},
|
|
|
|
'sea-blue': '#2feecc',
|
2022-03-22 10:37:57 -07:00
|
|
|
};
|
2020-06-02 13:48:27 -07:00
|
|
|
};
|
|
|
|
|
2022-03-22 10:37:57 -07:00
|
|
|
export const themeColorsToCSS = (brandColor: string, accentColor: string): string => {
|
|
|
|
const colors = legacyColorsToTailwind(brandColor, accentColor);
|
|
|
|
return colorsToCss(colors);
|
2022-02-24 09:28:52 -08:00
|
|
|
};
|