UNPKG

15.3 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var _a;
4var formatting_1 = require("./utils/formatting");
5var math_1 = require("./utils/math");
6var RGB = 'rgb', HSL = 'hsl';
7var converters = (_a = {},
8 _a[RGB + HSL] = RGBtoHSL,
9 _a[HSL + RGB] = HSLtoRGB,
10 _a);
11/**
12 * Describe the ceiling for each color channel for each format
13 */
14var maxChannelValues = {
15 r: 255,
16 g: 255,
17 b: 255,
18 h: 360,
19 s: 1,
20 l: 1,
21 a: 1
22};
23/**
24 * Creates a color from a hex color code or named color.
25 * e.g. color('red') or color('#FF0000') or color('#F00'))
26 */
27function color(value) {
28 return parseHexCode(value) || parseColorFunction(value) || rgb(255, 0, 0);
29}
30exports.color = color;
31/**
32 * Creates a color from hue, saturation, and lightness. Alpha is automatically set to 100%
33 * @param hue The hue of the color. This should be a number between 0-360.
34 * @param saturation The saturation of the color. This should be a number between 0-1 or a percentage string between 0%-100%.
35 * @param lightness The lightness of the color. This should be a number between 0-1 or a percentage string between 0%-100%.
36 * @param alpha The alpha of the color. This should be a number between 0-1 or a percentage string between 0%-100%. If not specified, this defaults to 1.
37 */
38function hsl(hue, saturation, lightness, alpha) {
39 return new ColorHelper(HSL, modDegrees(hue), formatting_1.ensurePercent(saturation), formatting_1.ensurePercent(lightness), (alpha === undefined ? 1 : formatting_1.ensurePercent(alpha)), alpha !== undefined /* hasAlpha*/);
40}
41exports.hsl = hsl;
42/**
43 * Creates a color from hue, saturation, lightness, and alpha
44 * @param hue The hue of the color. This should be a number between 0-360.
45 * @param saturation The saturation of the color. This should be a number between 0-1 or a percentage string between 0%-100%.
46 * @param lightness The lightness of the color. This should be a number between 0-1 or a percentage string between 0%-100%.
47 * @param alpha The alpha of the color. This should be a number between 0-1 or a percentage string between 0%-100%.
48 */
49function hsla(hue, saturation, lightness, alpha) {
50 return new ColorHelper(HSL, modDegrees(hue), formatting_1.ensurePercent(saturation), formatting_1.ensurePercent(lightness), formatting_1.ensurePercent(alpha), true);
51}
52exports.hsla = hsla;
53/**
54 * Creates a color form the red, blue, and green color space. Alpha is automatically set to 100%
55 * @param red The red channel of the color. This should be a number between 0-255.
56 * @param blue The blue channel of the color. This should be a number between 0-255.
57 * @param green The green channel of the color. This should be a number between 0-255.
58 * @param alpha The alpha of the color. This should be a number between 0-1 or a percentage string between 0%-100%. If not specified, this defaults to 1.
59 */
60function rgb(red, blue, green, alpha) {
61 return new ColorHelper(RGB, red, blue, green, (alpha === undefined ? 1 : formatting_1.ensurePercent(alpha)), alpha !== undefined /* hasAlpha*/);
62}
63exports.rgb = rgb;
64/**
65 * Creates a color form the red, blue, green, and alpha in the color space
66 * @param red The red channel of the color. This should be a number between 0-255.
67 * @param blue The blue channel of the color. This should be a number between 0-255.
68 * @param green The green channel of the color. This should be a number between 0-255.
69 * @param alpha The alpha of the color. This should be a number between 0-1 or a percentage string between 0%-100%.
70 */
71function rgba(red, blue, green, alpha) {
72 return new ColorHelper(RGB, red, blue, green, formatting_1.ensurePercent(alpha), true);
73}
74exports.rgba = rgba;
75function convertHelper(toFormat, helper, forceAlpha) {
76 var fromFormat = helper.f, r = helper.r, g = helper.g, b = helper.b, a = helper.a;
77 var newAlpha = forceAlpha === undefined ? helper.o : forceAlpha;
78 if (fromFormat !== toFormat) {
79 return converters[fromFormat + toFormat](r, g, b, a, newAlpha);
80 }
81 return forceAlpha === undefined ? helper : new ColorHelper(fromFormat, r, g, b, a, newAlpha);
82}
83/**
84 * A CSS Color. Includes utilities for converting between color types
85 */
86var ColorHelper = /** @class */ (function () {
87 function ColorHelper(format, r, g, b, a, hasAlpha) {
88 var self = this;
89 self.f = format;
90 self.o = hasAlpha;
91 var isHSL = format === HSL;
92 self.r = clampColor(isHSL ? 'h' : 'r', r);
93 self.g = clampColor(isHSL ? 's' : 'g', g);
94 self.b = clampColor(isHSL ? 'l' : 'b', b);
95 self.a = clampColor('a', a);
96 }
97 /**
98 * Converts the stored color into string form (which is used by Free Style)
99 */
100 ColorHelper.prototype.toString = function () {
101 var _a = this, hasAlpha = _a.o, format = _a.f, r = _a.r, g = _a.g, b = _a.b, a = _a.a;
102 var fnName;
103 var params;
104 // find function name and resolve first three channels
105 if (format === RGB) {
106 fnName = hasAlpha ? 'rgba' : RGB;
107 params = [math_1.round(r), math_1.round(g), math_1.round(b)];
108 }
109 else if (format === HSL) {
110 fnName = hasAlpha ? 'hsla' : HSL;
111 params = [math_1.round(r), formatting_1.formatPercent(math_1.roundFloat(g, 100)), formatting_1.formatPercent(math_1.roundFloat(b, 100))];
112 }
113 else {
114 throw new Error('Invalid color format');
115 }
116 // add alpha channel if needed
117 if (hasAlpha) {
118 params.push(formatting_1.formatFloat(math_1.roundFloat(a, 100000)));
119 }
120 // return as a string
121 return formatting_1.cssFunction(fnName, params);
122 };
123 /**
124 * Converts to hex rgb(255, 255, 255) to #FFFFFF
125 */
126 ColorHelper.prototype.toHexString = function () {
127 var color = convertHelper(RGB, this);
128 return '#' + (toHex(color.r) + toHex(color.g) + toHex(color.b)).toUpperCase();
129 };
130 /**
131 * Converts to the Hue, Saturation, Lightness color space
132 */
133 ColorHelper.prototype.toHSL = function () {
134 return convertHelper(HSL, this, false);
135 };
136 /**
137 * Converts to the Hue, Saturation, Lightness color space and adds an alpha channel
138 */
139 ColorHelper.prototype.toHSLA = function () {
140 return convertHelper(HSL, this, true);
141 };
142 /**
143 * Converts to the Red, Green, Blue color space
144 */
145 ColorHelper.prototype.toRGB = function () {
146 return convertHelper(RGB, this, false);
147 };
148 /**
149 * Converts to the Red, Green, Blue color space and adds an alpha channel
150 */
151 ColorHelper.prototype.toRGBA = function () {
152 return convertHelper(RGB, this, true);
153 };
154 ColorHelper.prototype.red = function () {
155 var _ = this;
156 return (_.f === RGB ? _ : _.toRGB()).r;
157 };
158 ColorHelper.prototype.green = function () {
159 var _ = this;
160 return (_.f === RGB ? _ : _.toRGB()).g;
161 };
162 ColorHelper.prototype.blue = function () {
163 var _ = this;
164 return (_.f === RGB ? _ : _.toRGB()).b;
165 };
166 ColorHelper.prototype.hue = function () {
167 var _ = this;
168 return (_.f === HSL ? _ : _.toHSL()).r;
169 };
170 ColorHelper.prototype.saturation = function () {
171 var _ = this;
172 return (_.f === HSL ? _ : _.toHSL()).g;
173 };
174 ColorHelper.prototype.lightness = function () {
175 var _ = this;
176 return (_.f === HSL ? _ : _.toHSL()).b;
177 };
178 ColorHelper.prototype.alpha = function () {
179 return this.a;
180 };
181 ColorHelper.prototype.opacity = function () {
182 return this.a;
183 };
184 ColorHelper.prototype.invert = function () {
185 var _ = this;
186 var color2 = convertHelper(RGB, _);
187 return convertHelper(_.f, new ColorHelper(RGB, 255 - color2.r, 255 - color2.g, 255 - color2.b, _.a, _.o));
188 };
189 ColorHelper.prototype.lighten = function (percent, relative) {
190 var _ = this;
191 var color2 = convertHelper(HSL, _);
192 var max = maxChannelValues.l;
193 var l = color2.b + (relative ? max - color2.b : max) * formatting_1.ensurePercent(percent);
194 return convertHelper(_.f, new ColorHelper(HSL, color2.r, color2.g, l, _.a, _.o));
195 };
196 ColorHelper.prototype.darken = function (percent, relative) {
197 var _ = this;
198 var color2 = convertHelper(HSL, _);
199 var l = color2.b - (relative ? color2.b : maxChannelValues.l) * formatting_1.ensurePercent(percent);
200 return convertHelper(_.f, new ColorHelper(HSL, color2.r, color2.g, l, _.a, _.o));
201 };
202 ColorHelper.prototype.saturate = function (percent, relative) {
203 var _ = this;
204 var color2 = convertHelper(HSL, _);
205 var max = maxChannelValues.s;
206 var s = color2.g + (relative ? max - color2.g : max) * formatting_1.ensurePercent(percent);
207 return convertHelper(_.f, new ColorHelper(HSL, color2.r, s, color2.b, _.a, _.o));
208 };
209 ColorHelper.prototype.desaturate = function (percent, relative) {
210 var _ = this;
211 var color2 = convertHelper(HSL, _);
212 var max = maxChannelValues.s;
213 var s = color2.g - (relative ? color2.g : max) * formatting_1.ensurePercent(percent);
214 return convertHelper(_.f, new ColorHelper(HSL, color2.r, s, color2.b, _.a, _.o));
215 };
216 ColorHelper.prototype.grayscale = function () {
217 return this.desaturate(1);
218 };
219 ColorHelper.prototype.fade = function (percent) {
220 var _ = this;
221 var a = clampColor('a', formatting_1.ensurePercent(percent));
222 return convertHelper(_.f, new ColorHelper(_.f, _.r, _.g, _.b, a, true));
223 };
224 ColorHelper.prototype.fadeOut = function (percent, relative) {
225 var _ = this;
226 var max = 1;
227 var a = clampColor('a', _.a - (relative ? _.a : max) * formatting_1.ensurePercent(percent));
228 return convertHelper(_.f, new ColorHelper(_.f, _.r, _.g, _.b, a, true));
229 };
230 ColorHelper.prototype.fadeIn = function (percent, relative) {
231 var _ = this;
232 var max = 1;
233 var a = clampColor('a', _.a + (relative ? _.a : max) * formatting_1.ensurePercent(percent));
234 return convertHelper(_.f, new ColorHelper(_.f, _.r, _.g, _.b, a, true));
235 };
236 ColorHelper.prototype.mix = function (mixin, weight) {
237 var _ = this;
238 var color2 = ensureColor(mixin);
239 var g = convertHelper(RGB, _);
240 var b = convertHelper(RGB, color2);
241 var p = weight === undefined ? 0.5 : weight;
242 var w = 2 * p - 1;
243 var a = Math.abs(g.a - b.a);
244 var w1 = ((w * a === -1 ? w : (w + a) / (1 + w * a)) + 1) / 2.0;
245 var w2 = 1 - w1;
246 var helper = new ColorHelper(RGB, math_1.round(g.r * w1 + b.r * w2), math_1.round(g.g * w1 + b.g * w2), math_1.round(g.b * w1 + b.b * w2), g.a * p + b.a * (1 - p), _.o || color2.o);
247 return convertHelper(this.f, helper);
248 };
249 ColorHelper.prototype.tint = function (weight) {
250 return rgb(255, 255, 255).mix(this, weight);
251 };
252 ColorHelper.prototype.shade = function (weight) {
253 return rgb(0, 0, 0).mix(this, weight);
254 };
255 ColorHelper.prototype.spin = function (degrees) {
256 var _ = this;
257 var color2 = convertHelper(HSL, _);
258 return convertHelper(_.f, new ColorHelper(HSL, modDegrees(color2.r + degrees), color2.g, color2.b, _.a, _.o));
259 };
260 return ColorHelper;
261}());
262exports.ColorHelper = ColorHelper;
263function toHex(n) {
264 var i = math_1.round(n);
265 return (i < 16 ? '0' : '') + i.toString(16);
266}
267function modDegrees(n) {
268 // note: maybe there is a way to simplify this
269 return ((n < 0 ? 360 : 0) + n % 360) % 360;
270}
271function RGBtoHSL(r, g, b, a, hasAlpha) {
272 var newR = r / 255;
273 var newG = g / 255;
274 var newB = b / 255;
275 var min = Math.min(newR, newG, newB);
276 var max = Math.max(newR, newG, newB);
277 var l = (min + max) / 2;
278 var delta = max - min;
279 var h;
280 if (max === min) {
281 h = 0;
282 }
283 else if (newR === max) {
284 h = (newG - newB) / delta;
285 }
286 else if (newG === max) {
287 h = 2 + (newB - newR) / delta;
288 }
289 else if (newB === max) {
290 h = 4 + (newR - newG) / delta;
291 }
292 else {
293 h = 0;
294 }
295 h = Math.min(h * 60, 360);
296 if (h < 0) {
297 h += 360;
298 }
299 var s;
300 if (max === min) {
301 s = 0;
302 }
303 else if (l <= 0.5) {
304 s = delta / (max + min);
305 }
306 else {
307 s = delta / (2 - max - min);
308 }
309 return new ColorHelper(HSL, h, s, l, a, hasAlpha);
310}
311function HSLtoRGB(r, g, b, a, hasAlpha) {
312 var newH = r / 360;
313 var newS = g;
314 var newL = b;
315 if (newS === 0) {
316 var val = newL * 255;
317 return new ColorHelper(RGB, val, val, val, a, hasAlpha);
318 }
319 var t2 = newL < 0.5 ? newL * (1 + newS) : newL + newS - newL * newS;
320 var t1 = 2 * newL - t2;
321 var newR = 0, newG = 0, newB = 0;
322 for (var i = 0; i < 3; i++) {
323 var t3 = newH + 1 / 3 * -(i - 1);
324 if (t3 < 0) {
325 t3++;
326 }
327 if (t3 > 1) {
328 t3--;
329 }
330 var val = void 0;
331 if (6 * t3 < 1) {
332 val = t1 + (t2 - t1) * 6 * t3;
333 }
334 else if (2 * t3 < 1) {
335 val = t2;
336 }
337 else if (3 * t3 < 2) {
338 val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
339 }
340 else {
341 val = t1;
342 }
343 val *= 255;
344 // manually set variables instead of using an array
345 if (i === 0) {
346 newR = val;
347 }
348 else if (i === 1) {
349 newG = val;
350 }
351 else {
352 newB = val;
353 }
354 }
355 return new ColorHelper(RGB, newR, newG, newB, a, hasAlpha);
356}
357function clampColor(channel, value) {
358 var min = 0;
359 var max = maxChannelValues[channel];
360 return value < min ? min : value > max ? max : value;
361}
362function ensureColor(c) {
363 return c instanceof ColorHelper ? c : color(c);
364}
365function parseHexCode(stringValue) {
366 var match = stringValue.match(/#(([a-f0-9]{6})|([a-f0-9]{3}))$/i);
367 if (!match) {
368 return undefined;
369 }
370 var hex = match[1];
371 var hexColor = parseInt(hex.length === 3 ? hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2] : hex, 16);
372 var r = (hexColor >> 16) & 0xff;
373 var b = (hexColor >> 8) & 0xff;
374 var g = hexColor & 0xff;
375 return new ColorHelper(RGB, r, b, g, 1, false);
376}
377function parseColorFunction(colorString) {
378 var cssParts = formatting_1.parseCSSFunction(colorString);
379 if (!cssParts || !(cssParts.length === 4 || cssParts.length === 5)) {
380 return undefined;
381 }
382 var fn = cssParts[0];
383 var isRGBA = fn === 'rgba';
384 var isHSLA = fn === 'hsla';
385 var isRGB = fn === RGB;
386 var isHSL = fn === HSL;
387 var hasAlpha = isHSLA || isRGBA;
388 var type;
389 if (isRGB || isRGBA) {
390 type = RGB;
391 }
392 else if (isHSL || isHSLA) {
393 type = HSL;
394 }
395 else {
396 throw new Error('unsupported color string');
397 }
398 var r = formatting_1.toFloat(cssParts[1]);
399 var g = isRGB || isRGBA ? formatting_1.toFloat(cssParts[2]) : formatting_1.ensurePercent(cssParts[2]);
400 var b = isRGB || isRGBA ? formatting_1.toFloat(cssParts[3]) : formatting_1.ensurePercent(cssParts[3]);
401 var a = hasAlpha ? formatting_1.toFloat(cssParts[4]) : 1;
402 return new ColorHelper(type, r, g, b, a, hasAlpha);
403}