color.ts

 1import chroma, { Scale } from "chroma-js";
 2import { ColorToken } from "../tokens";
 3
 4export type Color = string;
 5export type ColorRampStep = { value: Color; type: "color"; step: number };
 6export type ColorRamp = {
 7    [index: number]: ColorRampStep;
 8};
 9
10export function colorRamp(
11    color: Color | [Color, Color],
12    options?: { steps?: number; increment?: number; }
13): ColorRamp {
14    let scale: Scale;
15    if (Array.isArray(color)) {
16        const [startColor, endColor] = color;
17        scale = chroma.scale([startColor, endColor]);
18    } else {
19        let hue = Math.round(chroma(color).hsl()[0]);
20        let startColor = chroma.hsl(hue, 0.88, 0.96);
21        let endColor = chroma.hsl(hue, 0.68, 0.12);
22        scale = chroma
23            .scale([startColor, color, endColor])
24            .domain([0, 0.5, 1])
25            .mode("hsl")
26            .gamma(1)
27            // .correctLightness(true)
28            .padding([0, 0]);
29    }
30
31    const ramp: ColorRamp = {};
32    const steps = options?.steps || 10;
33    const increment = options?.increment || 100;
34
35    scale.colors(steps, "hex").forEach((color, ix) => {
36        const step = ix * increment;
37        ramp[step] = {
38            value: color,
39            step,
40            type: "color",
41        };
42    });
43
44    return ramp;
45}
46
47export function withOpacity(color: ColorToken, opacity: number): ColorToken {
48    return {
49        ...color,
50        value: chroma(color.value).alpha(opacity).hex()
51    };
52}