-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
121 lines (102 loc) · 3.83 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { validate as isValidUuid } from "uuid";
import * as UuidEncoder from "uuid-encoder";
import * as convert from "color-convert";
const DEFAULT_COLOR_FORMAT = "hex";
const DEFAULT_IS_RAW = false;
const encoder = new UuidEncoder("base10");
type SupportedColorNotations = "hex" | "rgb" | "hsl";
type Receivers = {
hex?: (hexString: string) => void;
rgb?: (red: number, green: number, blue: number) => void;
hsl?: (hue: number, saturation: number, lightness: number) => void;
}
export interface Options {
/**
* Determines whether to skip rounding the generated color components.
*
* @remarks
* Only applies when the specified format is `"hsl"`, as this is the only output format that involves a lossy conversion (from RGB model components).
*
* @defaultValue `false`
*/
raw?: boolean;
/**
* Determines the output format of the generated color.
*
* @remarks
* Colors are returned as strings in the CSS <color> data type hexadecimal or functional notation corresponding to the specified format.
*
* @defaultValue `"hex"`
*/
format?: SupportedColorNotations;
/**
* Attach callbacks to {@link SupportedColorNotations | supported color notations} as keys that will be called with the corresponding generated color components or code. Eliminates the need to parse the returned string if further manipulation is desired.
*
* @remarks
* Does not affect the return value of {@link colorFromUuid | the `colorFromUuid` function}.
* See {@link Receivers | the Receivers type} for more details.
*/
receivers?: Receivers;
}
/**
* Returns the generated color associated with the given uuid.
*
* @param uuid - The uuid for which to generate a color
* @param options - An optional object to configure the color generation, and attach callbacks that directly receive the generated color code or components in various formats
* @returns The generated color as a CSS `<color>` notation string
*
* @throws {@link Error}
* This exception is thrown if the input uuid string is not a valid UUID.
*
* @public
*/
export function colorFromUuid(uuid: string, options: Options = {}): string {
if (!isValidUuid(uuid)) {
throw new Error("Given string is not a valid UUID.");
}
const encodedUuid = BigInt(encoder.encode(uuid));
const colorCode = Number(encodedUuid % BigInt(0x1000000));
const red = colorCode >> 16;
const green = (colorCode >> 8) & 0xff;
const blue = colorCode & 0xff;
const receivers = {} as Receivers;
if (options.hasOwnProperty("receivers")) {
["rgb", "hsl", "hex"].forEach(format => {
if (options.receivers.hasOwnProperty(format)) {
receivers[format] = options.receivers[format]; // link to callbacks
}
});
}
/*
By default, return values are rounded. To get the unrounded (raw) results, use the raw: true option
*/
let isRaw = DEFAULT_IS_RAW;
if (options.hasOwnProperty("raw")) {
isRaw = options.raw;
}
if (!isRaw) {
// TODO round RGB if needed
}
if ("rgb" in receivers) {
receivers.rgb(red, green, blue);
}
if ("hsl" in receivers) {
receivers.hsl(...convert.rgb.hsl(red, green, blue) as [number, number, number]);
}
if ("hex" in receivers) {
receivers.hex(convert.rgb.hex(red, green, blue).toLowerCase());
}
let format = DEFAULT_COLOR_FORMAT;
if (options.hasOwnProperty("format")) {
format = options.format;
}
switch (format) {
case "rgb":
return `rgb(${red}, ${green}, ${blue})`;
case "hsl":
return `hsl(${convert.rgb.hsl(red, green, blue).join(", ")})`;
default: // don't error
case "hex":
return `#${convert.rgb.hex(red, green, blue).toLowerCase()}`;
}
}