WIP: Use algorithm to generate reference color palette

Adapted from @k-vyn/coloralgorithm
Generate colors for our reference palette.
This commit is contained in:
Nate Butler
2023-02-09 12:37:05 -05:00
parent f787f6054b
commit 42b5fa1fa3
9 changed files with 474 additions and 62 deletions
+103
View File
@@ -0,0 +1,103 @@
// Adapted from @k-vyn/coloralgorithm
import chroma, { Scale } from "chroma-js";
export type Color = {
step: number;
hex: string;
lch: number[];
rgbaArray: number[];
};
export type ColorSet = Color[];
export type ColorFamily = {
name: string;
colors: string[];
invertedColors: string[];
colorsMeta: ColorSet;
invertedMeta: ColorSet;
};
export interface ColorProps {
name: string;
color: {
start: string;
middle: string;
end: string;
};
}
function validColor(color: string) {
if (chroma.valid(color)) {
return color;
} else {
throw new Error(`Invalid color: ${color}`);
}
}
function assignColor(scale: Scale, steps: number, step: number) {
const color = scale(step / steps);
const lch = color.lch();
const rgbaArray = color.rgba();
const hex = color.hex();
const result = {
step,
hex,
lch,
rgbaArray,
};
return result;
}
/** Outputs 101 colors (0-100) */
export function generateColors(props: ColorProps, inverted: boolean) {
const steps = 101;
const colors: ColorSet = [];
const { start, middle, end } = props.color;
const startColor = validColor(start);
const middleColor = validColor(middle);
const endColor = validColor(end);
// TODO: Use curve when generating colors
let scale: Scale;
if (inverted) {
scale = chroma.scale([endColor, middleColor, startColor]).mode("lch");
} else {
scale = chroma.scale([startColor, middleColor, endColor]).mode("lch");
}
for (let i = 0; i < steps; i++) {
const color = assignColor(scale, steps, i);
colors.push(color);
}
return colors;
}
/** Generates two color ramps:
* One for for light, and one for dark.
* By generating two ramps, rather than two default themes, we can use the same reference palette values for tokens in components.
*
* Each ramp has 101 colors (0-100)
*/
export function generateColorSet(props: ColorProps) {
const generatedColors = generateColors(props, false);
const generatedInvertedColors = generateColors(props, true);
const colors = generatedColors.map((color) => color.hex);
const invertedColors = generatedInvertedColors.map((color) => color.hex);
const result: ColorFamily = {
name: props.name,
colors: colors,
invertedColors: invertedColors,
colorsMeta: generatedColors,
invertedMeta: generatedInvertedColors,
};
return result;
}