diff options
Diffstat (limited to 'packages/excalidraw/colors.ts')
| -rw-r--r-- | packages/excalidraw/colors.ts | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/packages/excalidraw/colors.ts b/packages/excalidraw/colors.ts new file mode 100644 index 0000000..e4cd67a --- /dev/null +++ b/packages/excalidraw/colors.ts @@ -0,0 +1,170 @@ +import oc from "open-color"; +import type { Merge } from "./utility-types"; + +// FIXME can't put to utils.ts rn because of circular dependency +const pick = <R extends Record<string, any>, K extends readonly (keyof R)[]>( + source: R, + keys: K, +) => { + return keys.reduce((acc, key: K[number]) => { + if (key in source) { + acc[key] = source[key]; + } + return acc; + }, {} as Pick<R, K[number]>) as Pick<R, K[number]>; +}; + +export type ColorPickerColor = + | Exclude<keyof oc, "indigo" | "lime"> + | "transparent" + | "bronze"; +export type ColorTuple = readonly [string, string, string, string, string]; +export type ColorPalette = Merge< + Record<ColorPickerColor, ColorTuple>, + { black: "#1e1e1e"; white: "#ffffff"; transparent: "transparent" } +>; + +// used general type instead of specific type (ColorPalette) to support custom colors +export type ColorPaletteCustom = { [key: string]: ColorTuple | string }; +export type ColorShadesIndexes = [number, number, number, number, number]; + +export const MAX_CUSTOM_COLORS_USED_IN_CANVAS = 5; +export const COLORS_PER_ROW = 5; + +export const DEFAULT_CHART_COLOR_INDEX = 4; + +export const DEFAULT_ELEMENT_STROKE_COLOR_INDEX = 4; +export const DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX = 1; +export const ELEMENTS_PALETTE_SHADE_INDEXES = [0, 2, 4, 6, 8] as const; +export const CANVAS_PALETTE_SHADE_INDEXES = [0, 1, 2, 3, 4] as const; + +export const getSpecificColorShades = ( + color: Exclude< + ColorPickerColor, + "transparent" | "white" | "black" | "bronze" + >, + indexArr: Readonly<ColorShadesIndexes>, +) => { + return indexArr.map((index) => oc[color][index]) as any as ColorTuple; +}; + +export const COLOR_PALETTE = { + transparent: "transparent", + black: "#1e1e1e", + white: "#ffffff", + // open-colors + gray: getSpecificColorShades("gray", ELEMENTS_PALETTE_SHADE_INDEXES), + red: getSpecificColorShades("red", ELEMENTS_PALETTE_SHADE_INDEXES), + pink: getSpecificColorShades("pink", ELEMENTS_PALETTE_SHADE_INDEXES), + grape: getSpecificColorShades("grape", ELEMENTS_PALETTE_SHADE_INDEXES), + violet: getSpecificColorShades("violet", ELEMENTS_PALETTE_SHADE_INDEXES), + blue: getSpecificColorShades("blue", ELEMENTS_PALETTE_SHADE_INDEXES), + cyan: getSpecificColorShades("cyan", ELEMENTS_PALETTE_SHADE_INDEXES), + teal: getSpecificColorShades("teal", ELEMENTS_PALETTE_SHADE_INDEXES), + green: getSpecificColorShades("green", ELEMENTS_PALETTE_SHADE_INDEXES), + yellow: getSpecificColorShades("yellow", ELEMENTS_PALETTE_SHADE_INDEXES), + orange: getSpecificColorShades("orange", ELEMENTS_PALETTE_SHADE_INDEXES), + // radix bronze shades 3,5,7,9,11 + bronze: ["#f8f1ee", "#eaddd7", "#d2bab0", "#a18072", "#846358"], +} as ColorPalette; + +const COMMON_ELEMENT_SHADES = pick(COLOR_PALETTE, [ + "cyan", + "blue", + "violet", + "grape", + "pink", + "green", + "teal", + "yellow", + "orange", + "red", +]); + +// ----------------------------------------------------------------------------- +// quick picks defaults +// ----------------------------------------------------------------------------- + +// ORDER matters for positioning in quick picker +export const DEFAULT_ELEMENT_STROKE_PICKS = [ + COLOR_PALETTE.black, + COLOR_PALETTE.red[DEFAULT_ELEMENT_STROKE_COLOR_INDEX], + COLOR_PALETTE.green[DEFAULT_ELEMENT_STROKE_COLOR_INDEX], + COLOR_PALETTE.blue[DEFAULT_ELEMENT_STROKE_COLOR_INDEX], + COLOR_PALETTE.yellow[DEFAULT_ELEMENT_STROKE_COLOR_INDEX], +] as ColorTuple; + +// ORDER matters for positioning in quick picker +export const DEFAULT_ELEMENT_BACKGROUND_PICKS = [ + COLOR_PALETTE.transparent, + COLOR_PALETTE.red[DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX], + COLOR_PALETTE.green[DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX], + COLOR_PALETTE.blue[DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX], + COLOR_PALETTE.yellow[DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX], +] as ColorTuple; + +// ORDER matters for positioning in quick picker +export const DEFAULT_CANVAS_BACKGROUND_PICKS = [ + COLOR_PALETTE.white, + // radix slate2 + "#f8f9fa", + // radix blue2 + "#f5faff", + // radix yellow2 + "#fffce8", + // radix bronze2 + "#fdf8f6", +] as ColorTuple; + +// ----------------------------------------------------------------------------- +// palette defaults +// ----------------------------------------------------------------------------- + +export const DEFAULT_ELEMENT_STROKE_COLOR_PALETTE = { + // 1st row + transparent: COLOR_PALETTE.transparent, + white: COLOR_PALETTE.white, + gray: COLOR_PALETTE.gray, + black: COLOR_PALETTE.black, + bronze: COLOR_PALETTE.bronze, + // rest + ...COMMON_ELEMENT_SHADES, +} as const; + +// ORDER matters for positioning in pallete (5x3 grid)s +export const DEFAULT_ELEMENT_BACKGROUND_COLOR_PALETTE = { + transparent: COLOR_PALETTE.transparent, + white: COLOR_PALETTE.white, + gray: COLOR_PALETTE.gray, + black: COLOR_PALETTE.black, + bronze: COLOR_PALETTE.bronze, + + ...COMMON_ELEMENT_SHADES, +} as const; + +// ----------------------------------------------------------------------------- +// helpers +// ----------------------------------------------------------------------------- + +// !!!MUST BE WITHOUT GRAY, TRANSPARENT AND BLACK!!! +export const getAllColorsSpecificShade = (index: 0 | 1 | 2 | 3 | 4) => + [ + // 2nd row + COLOR_PALETTE.cyan[index], + COLOR_PALETTE.blue[index], + COLOR_PALETTE.violet[index], + COLOR_PALETTE.grape[index], + COLOR_PALETTE.pink[index], + + // 3rd row + COLOR_PALETTE.green[index], + COLOR_PALETTE.teal[index], + COLOR_PALETTE.yellow[index], + COLOR_PALETTE.orange[index], + COLOR_PALETTE.red[index], + ] as const; + +export const rgbToHex = (r: number, g: number, b: number) => + `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`; + +// ----------------------------------------------------------------------------- |
