@thednp/color-picker 0.0.1-alpha3 → 0.0.2-alpha2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/css/color-picker.css +3 -2
- package/dist/css/color-picker.min.css +2 -2
- package/dist/css/color-picker.rtl.css +3 -2
- package/dist/css/color-picker.rtl.min.css +2 -2
- package/dist/js/color-esm.js +1167 -0
- package/dist/js/color-esm.min.js +2 -0
- package/dist/js/color-palette-esm.js +1238 -0
- package/dist/js/color-palette-esm.min.js +2 -0
- package/dist/js/color-palette.js +1246 -0
- package/dist/js/color-palette.min.js +2 -0
- package/dist/js/color-picker-element-esm.js +567 -683
- package/dist/js/color-picker-element-esm.min.js +2 -2
- package/dist/js/color-picker-element.js +569 -685
- package/dist/js/color-picker-element.min.js +2 -2
- package/dist/js/color-picker-esm.js +782 -890
- package/dist/js/color-picker-esm.min.js +2 -2
- package/dist/js/color-picker.js +784 -892
- package/dist/js/color-picker.min.js +2 -2
- package/dist/js/color.js +1175 -0
- package/dist/js/color.min.js +2 -0
- package/package.json +22 -3
- package/src/js/color-palette.js +18 -14
- package/src/js/color-picker-element.js +47 -55
- package/src/js/color-picker.js +155 -329
- package/src/js/color.js +175 -193
- package/src/js/util/getColorMenu.js +12 -7
- package/src/js/util/setMarkup.js +122 -0
- package/src/js/util/version.js +6 -0
- package/src/scss/color-picker.scss +3 -7
- package/types/cp.d.ts +64 -32
- package/types/source/types.d.ts +1 -1
- package/src/js/util/templates.js +0 -10
package/src/js/color.js
CHANGED
@@ -1,13 +1,14 @@
|
|
1
|
-
import
|
1
|
+
import documentHead from 'shorter-js/src/blocks/documentHead';
|
2
2
|
import getElementStyle from 'shorter-js/src/get/getElementStyle';
|
3
3
|
import setElementStyle from 'shorter-js/src/misc/setElementStyle';
|
4
4
|
import ObjectAssign from 'shorter-js/src/misc/ObjectAssign';
|
5
|
+
import toLowerCase from 'shorter-js/src/misc/toLowerCase';
|
5
6
|
|
6
7
|
import nonColors from './util/nonColors';
|
7
8
|
import roundPart from './util/roundPart';
|
8
9
|
|
9
10
|
// Color supported formats
|
10
|
-
const COLOR_FORMAT = ['rgb', 'hex', 'hsl', '
|
11
|
+
const COLOR_FORMAT = ['rgb', 'hex', 'hsl', 'hsv', 'hwb'];
|
11
12
|
|
12
13
|
// Hue angles
|
13
14
|
const ANGLES = 'deg|rad|grad|turn';
|
@@ -29,10 +30,17 @@ const CSS_UNIT = `(?:${CSS_NUMBER})|(?:${CSS_INTEGER})`;
|
|
29
30
|
// Add angles to the mix
|
30
31
|
const CSS_UNIT2 = `(?:${CSS_UNIT})|(?:${CSS_ANGLE})`;
|
31
32
|
|
33
|
+
// Start & end
|
34
|
+
const START_MATCH = '(?:[\\s|\\(\\s|\\s\\(\\s]+)?';
|
35
|
+
const END_MATCH = '(?:[\\s|\\)\\s]+)?';
|
36
|
+
// Components separation
|
37
|
+
const SEP = '(?:[,|\\s]+)';
|
38
|
+
const SEP2 = '(?:[,|\\/\\s]*)?';
|
39
|
+
|
32
40
|
// Actual matching.
|
33
41
|
// Parentheses and commas are optional, but not required.
|
34
42
|
// Whitespace can take the place of commas or opening paren
|
35
|
-
const PERMISSIVE_MATCH =
|
43
|
+
const PERMISSIVE_MATCH = `${START_MATCH}(${CSS_UNIT2})${SEP}(${CSS_UNIT})${SEP}(${CSS_UNIT})${SEP2}(${CSS_UNIT})?${END_MATCH}`;
|
36
44
|
|
37
45
|
const matchers = {
|
38
46
|
CSS_UNIT: new RegExp(CSS_UNIT2),
|
@@ -65,23 +73,24 @@ function isPercentage(n) {
|
|
65
73
|
return `${n}`.includes('%');
|
66
74
|
}
|
67
75
|
|
68
|
-
/**
|
69
|
-
* Check to see if string passed in is an angle
|
70
|
-
* @param {string} n testing string
|
71
|
-
* @returns {boolean} the query result
|
72
|
-
*/
|
73
|
-
function isAngle(n) {
|
74
|
-
return ANGLES.split('|').some((a) => `${n}`.includes(a));
|
75
|
-
}
|
76
|
-
|
77
76
|
/**
|
78
77
|
* Check to see if string passed is a web safe colour.
|
78
|
+
* @see https://stackoverflow.com/a/16994164
|
79
79
|
* @param {string} color a colour name, EG: *red*
|
80
80
|
* @returns {boolean} the query result
|
81
81
|
*/
|
82
82
|
function isColorName(color) {
|
83
|
-
|
84
|
-
|
83
|
+
if (nonColors.includes(color)
|
84
|
+
|| ['#', ...COLOR_FORMAT].some((f) => color.includes(f))) return false;
|
85
|
+
|
86
|
+
if (['black', 'white'].includes(color)) return true;
|
87
|
+
|
88
|
+
return ['rgb(255, 255, 255)', 'rgb(0, 0, 0)'].every((c) => {
|
89
|
+
setElementStyle(documentHead, { color });
|
90
|
+
const computedColor = getElementStyle(documentHead, 'color');
|
91
|
+
setElementStyle(documentHead, { color: '' });
|
92
|
+
return computedColor !== c;
|
93
|
+
});
|
85
94
|
}
|
86
95
|
|
87
96
|
/**
|
@@ -102,15 +111,20 @@ function isValidCSSUnit(color) {
|
|
102
111
|
*/
|
103
112
|
function bound01(N, max) {
|
104
113
|
let n = N;
|
105
|
-
if (isOnePointZero(n)) n = '100%';
|
106
114
|
|
107
|
-
|
115
|
+
if (typeof N === 'number'
|
116
|
+
&& Math.min(N, 0) === 0 // round values to 6 decimals Math.round(N * (10 ** 6)) / 10 ** 6
|
117
|
+
&& Math.max(N, 1) === 1) return N;
|
118
|
+
|
119
|
+
if (isOnePointZero(N)) n = '100%';
|
108
120
|
|
109
|
-
|
110
|
-
|
121
|
+
const processPercent = isPercentage(n);
|
122
|
+
n = max === 360
|
123
|
+
? parseFloat(n)
|
124
|
+
: Math.min(max, Math.max(0, parseFloat(n)));
|
111
125
|
|
112
126
|
// Automatically convert percentage into number
|
113
|
-
if (
|
127
|
+
if (processPercent) n = (n * max) / 100;
|
114
128
|
|
115
129
|
// Handle floating point rounding errors
|
116
130
|
if (Math.abs(n - max) < 0.000001) {
|
@@ -121,11 +135,11 @@ function bound01(N, max) {
|
|
121
135
|
// If n is a hue given in degrees,
|
122
136
|
// wrap around out-of-range values into [0, 360] range
|
123
137
|
// then convert into [0, 1].
|
124
|
-
n = (n < 0 ? (n % max) + max : n % max) /
|
138
|
+
n = (n < 0 ? (n % max) + max : n % max) / max;
|
125
139
|
} else {
|
126
140
|
// If n not a hue given in degrees
|
127
141
|
// Convert into [0, 1] range if it isn't already.
|
128
|
-
n = (n % max) /
|
142
|
+
n = (n % max) / max;
|
129
143
|
}
|
130
144
|
return n;
|
131
145
|
}
|
@@ -160,7 +174,6 @@ function clamp01(v) {
|
|
160
174
|
* @returns {string}
|
161
175
|
*/
|
162
176
|
function getRGBFromName(name) {
|
163
|
-
const documentHead = getDocumentHead();
|
164
177
|
setElementStyle(documentHead, { color: name });
|
165
178
|
const colorName = getElementStyle(documentHead, 'color');
|
166
179
|
setElementStyle(documentHead, { color: '' });
|
@@ -206,15 +219,12 @@ function pad2(c) {
|
|
206
219
|
/**
|
207
220
|
* Converts an RGB colour value to HSL.
|
208
221
|
*
|
209
|
-
* @param {number}
|
210
|
-
* @param {number}
|
211
|
-
* @param {number}
|
222
|
+
* @param {number} r Red component [0, 1]
|
223
|
+
* @param {number} g Green component [0, 1]
|
224
|
+
* @param {number} b Blue component [0, 1]
|
212
225
|
* @returns {CP.HSL} {h,s,l} object with [0, 1] ranged values
|
213
226
|
*/
|
214
|
-
function rgbToHsl(
|
215
|
-
const r = R / 255;
|
216
|
-
const g = G / 255;
|
217
|
-
const b = B / 255;
|
227
|
+
function rgbToHsl(r, g, b) {
|
218
228
|
const max = Math.max(r, g, b);
|
219
229
|
const min = Math.min(r, g, b);
|
220
230
|
let h = 0;
|
@@ -226,18 +236,10 @@ function rgbToHsl(R, G, B) {
|
|
226
236
|
} else {
|
227
237
|
const d = max - min;
|
228
238
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
case g:
|
234
|
-
h = (b - r) / d + 2;
|
235
|
-
break;
|
236
|
-
case b:
|
237
|
-
h = (r - g) / d + 4;
|
238
|
-
break;
|
239
|
-
default:
|
240
|
-
}
|
239
|
+
if (max === r) h = (g - b) / d + (g < b ? 6 : 0);
|
240
|
+
if (max === g) h = (b - r) / d + 2;
|
241
|
+
if (max === b) h = (r - g) / d + 4;
|
242
|
+
|
241
243
|
h /= 6;
|
242
244
|
}
|
243
245
|
return { h, s, l };
|
@@ -260,21 +262,46 @@ function hueToRgb(p, q, t) {
|
|
260
262
|
return p;
|
261
263
|
}
|
262
264
|
|
265
|
+
/**
|
266
|
+
* Converts an HSL colour value to RGB.
|
267
|
+
*
|
268
|
+
* @param {number} h Hue Angle [0, 1]
|
269
|
+
* @param {number} s Saturation [0, 1]
|
270
|
+
* @param {number} l Lightness Angle [0, 1]
|
271
|
+
* @returns {CP.RGB} {r,g,b} object with [0, 1] ranged values
|
272
|
+
*/
|
273
|
+
function hslToRgb(h, s, l) {
|
274
|
+
let r = 0;
|
275
|
+
let g = 0;
|
276
|
+
let b = 0;
|
277
|
+
|
278
|
+
if (s === 0) {
|
279
|
+
// achromatic
|
280
|
+
g = l;
|
281
|
+
b = l;
|
282
|
+
r = l;
|
283
|
+
} else {
|
284
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
285
|
+
const p = 2 * l - q;
|
286
|
+
r = hueToRgb(p, q, h + 1 / 3);
|
287
|
+
g = hueToRgb(p, q, h);
|
288
|
+
b = hueToRgb(p, q, h - 1 / 3);
|
289
|
+
}
|
290
|
+
|
291
|
+
return { r, g, b };
|
292
|
+
}
|
293
|
+
|
263
294
|
/**
|
264
295
|
* Returns an HWB colour object from an RGB colour object.
|
265
296
|
* @link https://www.w3.org/TR/css-color-4/#hwb-to-rgb
|
266
297
|
* @link http://alvyray.com/Papers/CG/hwb2rgb.htm
|
267
298
|
*
|
268
|
-
* @param {number}
|
269
|
-
* @param {number}
|
270
|
-
* @param {number}
|
299
|
+
* @param {number} r Red component [0, 1]
|
300
|
+
* @param {number} g Green [0, 1]
|
301
|
+
* @param {number} b Blue [0, 1]
|
271
302
|
* @return {CP.HWB} {h,w,b} object with [0, 1] ranged values
|
272
303
|
*/
|
273
|
-
function rgbToHwb(
|
274
|
-
const r = R / 255;
|
275
|
-
const g = G / 255;
|
276
|
-
const b = B / 255;
|
277
|
-
|
304
|
+
function rgbToHwb(r, g, b) {
|
278
305
|
let f = 0;
|
279
306
|
let i = 0;
|
280
307
|
const whiteness = Math.min(r, g, b);
|
@@ -304,50 +331,18 @@ function rgbToHwb(R, G, B) {
|
|
304
331
|
* @param {number} H Hue Angle [0, 1]
|
305
332
|
* @param {number} W Whiteness [0, 1]
|
306
333
|
* @param {number} B Blackness [0, 1]
|
307
|
-
* @return {CP.RGB} {r,g,b} object with [0,
|
334
|
+
* @return {CP.RGB} {r,g,b} object with [0, 1] ranged values
|
308
335
|
*
|
309
336
|
* @link https://www.w3.org/TR/css-color-4/#hwb-to-rgb
|
310
337
|
* @link http://alvyray.com/Papers/CG/hwb2rgb.htm
|
311
338
|
*/
|
312
339
|
function hwbToRgb(H, W, B) {
|
313
340
|
if (W + B >= 1) {
|
314
|
-
const gray =
|
341
|
+
const gray = W / (W + B);
|
315
342
|
return { r: gray, g: gray, b: gray };
|
316
343
|
}
|
317
344
|
let { r, g, b } = hslToRgb(H, 1, 0.5);
|
318
|
-
[r, g, b] = [r, g, b]
|
319
|
-
.map((v) => (v / 255) * (1 - W - B) + W)
|
320
|
-
.map((v) => v * 255);
|
321
|
-
|
322
|
-
return { r, g, b };
|
323
|
-
}
|
324
|
-
|
325
|
-
/**
|
326
|
-
* Converts an HSL colour value to RGB.
|
327
|
-
*
|
328
|
-
* @param {number} h Hue Angle [0, 1]
|
329
|
-
* @param {number} s Saturation [0, 1]
|
330
|
-
* @param {number} l Lightness Angle [0, 1]
|
331
|
-
* @returns {CP.RGB} {r,g,b} object with [0, 255] ranged values
|
332
|
-
*/
|
333
|
-
function hslToRgb(h, s, l) {
|
334
|
-
let r = 0;
|
335
|
-
let g = 0;
|
336
|
-
let b = 0;
|
337
|
-
|
338
|
-
if (s === 0) {
|
339
|
-
// achromatic
|
340
|
-
g = l;
|
341
|
-
b = l;
|
342
|
-
r = l;
|
343
|
-
} else {
|
344
|
-
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
345
|
-
const p = 2 * l - q;
|
346
|
-
r = hueToRgb(p, q, h + 1 / 3);
|
347
|
-
g = hueToRgb(p, q, h);
|
348
|
-
b = hueToRgb(p, q, h - 1 / 3);
|
349
|
-
}
|
350
|
-
[r, g, b] = [r, g, b].map((x) => x * 255);
|
345
|
+
[r, g, b] = [r, g, b].map((v) => v * (1 - W - B) + W);
|
351
346
|
|
352
347
|
return { r, g, b };
|
353
348
|
}
|
@@ -355,15 +350,12 @@ function hslToRgb(h, s, l) {
|
|
355
350
|
/**
|
356
351
|
* Converts an RGB colour value to HSV.
|
357
352
|
*
|
358
|
-
* @param {number}
|
359
|
-
* @param {number}
|
360
|
-
* @param {number}
|
353
|
+
* @param {number} r Red component [0, 1]
|
354
|
+
* @param {number} g Green [0, 1]
|
355
|
+
* @param {number} b Blue [0, 1]
|
361
356
|
* @returns {CP.HSV} {h,s,v} object with [0, 1] ranged values
|
362
357
|
*/
|
363
|
-
function rgbToHsv(
|
364
|
-
const r = R / 255;
|
365
|
-
const g = G / 255;
|
366
|
-
const b = B / 255;
|
358
|
+
function rgbToHsv(r, g, b) {
|
367
359
|
const max = Math.max(r, g, b);
|
368
360
|
const min = Math.min(r, g, b);
|
369
361
|
let h = 0;
|
@@ -373,18 +365,10 @@ function rgbToHsv(R, G, B) {
|
|
373
365
|
if (max === min) {
|
374
366
|
h = 0; // achromatic
|
375
367
|
} else {
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
case g:
|
381
|
-
h = (b - r) / d + 2;
|
382
|
-
break;
|
383
|
-
case b:
|
384
|
-
h = (r - g) / d + 4;
|
385
|
-
break;
|
386
|
-
default:
|
387
|
-
}
|
368
|
+
if (r === max) h = (g - b) / d + (g < b ? 6 : 0);
|
369
|
+
if (g === max) h = (b - r) / d + 2;
|
370
|
+
if (b === max) h = (r - g) / d + 4;
|
371
|
+
|
388
372
|
h /= 6;
|
389
373
|
}
|
390
374
|
return { h, s, v };
|
@@ -411,7 +395,7 @@ function hsvToRgb(H, S, V) {
|
|
411
395
|
const r = [v, q, p, p, t, v][mod];
|
412
396
|
const g = [t, v, v, q, p, p][mod];
|
413
397
|
const b = [p, p, t, v, v, q][mod];
|
414
|
-
return { r
|
398
|
+
return { r, g, b };
|
415
399
|
}
|
416
400
|
|
417
401
|
/**
|
@@ -435,7 +419,7 @@ function rgbToHex(r, g, b, allow3Char) {
|
|
435
419
|
// Return a 3 character hex if possible
|
436
420
|
if (allow3Char && hex[0].charAt(0) === hex[0].charAt(1)
|
437
421
|
&& hex[1].charAt(0) === hex[1].charAt(1)
|
438
|
-
|
422
|
+
&& hex[2].charAt(0) === hex[2].charAt(1)) {
|
439
423
|
return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
|
440
424
|
}
|
441
425
|
|
@@ -463,51 +447,34 @@ function rgbaToHex(r, g, b, a, allow4Char) {
|
|
463
447
|
// Return a 4 character hex if possible
|
464
448
|
if (allow4Char && hex[0].charAt(0) === hex[0].charAt(1)
|
465
449
|
&& hex[1].charAt(0) === hex[1].charAt(1)
|
466
|
-
|
467
|
-
|
450
|
+
&& hex[2].charAt(0) === hex[2].charAt(1)
|
451
|
+
&& hex[3].charAt(0) === hex[3].charAt(1)) {
|
468
452
|
return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0);
|
469
453
|
}
|
470
454
|
return hex.join('');
|
471
455
|
}
|
472
456
|
|
473
|
-
/**
|
474
|
-
* Returns a colour object corresponding to a given number.
|
475
|
-
* @param {number} color input number
|
476
|
-
* @returns {CP.RGB} {r,g,b} object with [0, 255] ranged values
|
477
|
-
*/
|
478
|
-
function numberInputToObject(color) {
|
479
|
-
/* eslint-disable no-bitwise */
|
480
|
-
return {
|
481
|
-
r: color >> 16,
|
482
|
-
g: (color & 0xff00) >> 8,
|
483
|
-
b: color & 0xff,
|
484
|
-
};
|
485
|
-
/* eslint-enable no-bitwise */
|
486
|
-
}
|
487
|
-
|
488
457
|
/**
|
489
458
|
* Permissive string parsing. Take in a number of formats, and output an object
|
490
459
|
* based on detected format. Returns {r,g,b} or {h,s,l} or {h,s,v}
|
491
460
|
* @param {string} input colour value in any format
|
492
|
-
* @returns {Record<string, (number | string)> | false} an object matching the RegExp
|
461
|
+
* @returns {Record<string, (number | string | boolean)> | false} an object matching the RegExp
|
493
462
|
*/
|
494
463
|
function stringInputToObject(input) {
|
495
|
-
let color = input.trim()
|
464
|
+
let color = toLowerCase(input.trim());
|
465
|
+
|
496
466
|
if (color.length === 0) {
|
497
467
|
return {
|
498
|
-
r: 0, g: 0, b: 0, a:
|
468
|
+
r: 0, g: 0, b: 0, a: 1,
|
499
469
|
};
|
500
470
|
}
|
501
|
-
|
471
|
+
|
502
472
|
if (isColorName(color)) {
|
503
473
|
color = getRGBFromName(color);
|
504
|
-
named = true;
|
505
474
|
} else if (nonColors.includes(color)) {
|
506
|
-
const
|
507
|
-
const rgb = isTransparent ? 0 : 255;
|
508
|
-
const a = isTransparent ? 0 : 1;
|
475
|
+
const a = color === 'transparent' ? 0 : 1;
|
509
476
|
return {
|
510
|
-
r:
|
477
|
+
r: 0, g: 0, b: 0, a, format: 'rgb', ok: true,
|
511
478
|
};
|
512
479
|
}
|
513
480
|
|
@@ -522,24 +489,28 @@ function stringInputToObject(input) {
|
|
522
489
|
r: m1, g: m2, b: m3, a: m4 !== undefined ? m4 : 1, format: 'rgb',
|
523
490
|
};
|
524
491
|
}
|
492
|
+
|
525
493
|
[, m1, m2, m3, m4] = matchers.hsl.exec(color) || [];
|
526
494
|
if (m1 && m2 && m3/* && m4 */) {
|
527
495
|
return {
|
528
496
|
h: m1, s: m2, l: m3, a: m4 !== undefined ? m4 : 1, format: 'hsl',
|
529
497
|
};
|
530
498
|
}
|
499
|
+
|
531
500
|
[, m1, m2, m3, m4] = matchers.hsv.exec(color) || [];
|
532
501
|
if (m1 && m2 && m3/* && m4 */) {
|
533
502
|
return {
|
534
503
|
h: m1, s: m2, v: m3, a: m4 !== undefined ? m4 : 1, format: 'hsv',
|
535
504
|
};
|
536
505
|
}
|
506
|
+
|
537
507
|
[, m1, m2, m3, m4] = matchers.hwb.exec(color) || [];
|
538
508
|
if (m1 && m2 && m3) {
|
539
509
|
return {
|
540
510
|
h: m1, w: m2, b: m3, a: m4 !== undefined ? m4 : 1, format: 'hwb',
|
541
511
|
};
|
542
512
|
}
|
513
|
+
|
543
514
|
[, m1, m2, m3, m4] = matchers.hex8.exec(color) || [];
|
544
515
|
if (m1 && m2 && m3 && m4) {
|
545
516
|
return {
|
@@ -547,19 +518,20 @@ function stringInputToObject(input) {
|
|
547
518
|
g: parseIntFromHex(m2),
|
548
519
|
b: parseIntFromHex(m3),
|
549
520
|
a: convertHexToDecimal(m4),
|
550
|
-
|
551
|
-
format: named ? 'rgb' : 'hex',
|
521
|
+
format: 'hex',
|
552
522
|
};
|
553
523
|
}
|
524
|
+
|
554
525
|
[, m1, m2, m3] = matchers.hex6.exec(color) || [];
|
555
526
|
if (m1 && m2 && m3) {
|
556
527
|
return {
|
557
528
|
r: parseIntFromHex(m1),
|
558
529
|
g: parseIntFromHex(m2),
|
559
530
|
b: parseIntFromHex(m3),
|
560
|
-
format:
|
531
|
+
format: 'hex',
|
561
532
|
};
|
562
533
|
}
|
534
|
+
|
563
535
|
[, m1, m2, m3, m4] = matchers.hex4.exec(color) || [];
|
564
536
|
if (m1 && m2 && m3 && m4) {
|
565
537
|
return {
|
@@ -567,19 +539,20 @@ function stringInputToObject(input) {
|
|
567
539
|
g: parseIntFromHex(m2 + m2),
|
568
540
|
b: parseIntFromHex(m3 + m3),
|
569
541
|
a: convertHexToDecimal(m4 + m4),
|
570
|
-
|
571
|
-
format: named ? 'rgb' : 'hex',
|
542
|
+
format: 'hex',
|
572
543
|
};
|
573
544
|
}
|
545
|
+
|
574
546
|
[, m1, m2, m3] = matchers.hex3.exec(color) || [];
|
575
547
|
if (m1 && m2 && m3) {
|
576
548
|
return {
|
577
549
|
r: parseIntFromHex(m1 + m1),
|
578
550
|
g: parseIntFromHex(m2 + m2),
|
579
551
|
b: parseIntFromHex(m3 + m3),
|
580
|
-
format:
|
552
|
+
format: 'hex',
|
581
553
|
};
|
582
554
|
}
|
555
|
+
|
583
556
|
return false;
|
584
557
|
}
|
585
558
|
|
@@ -610,7 +583,9 @@ function stringInputToObject(input) {
|
|
610
583
|
*/
|
611
584
|
function inputToRGB(input) {
|
612
585
|
let rgb = { r: 0, g: 0, b: 0 };
|
586
|
+
/** @type {*} */
|
613
587
|
let color = input;
|
588
|
+
/** @type {string | number} */
|
614
589
|
let a = 1;
|
615
590
|
let s = null;
|
616
591
|
let v = null;
|
@@ -621,58 +596,67 @@ function inputToRGB(input) {
|
|
621
596
|
let r = null;
|
622
597
|
let g = null;
|
623
598
|
let ok = false;
|
624
|
-
|
599
|
+
const inputFormat = typeof color === 'object' && color.format;
|
600
|
+
let format = inputFormat && COLOR_FORMAT.includes(inputFormat) ? inputFormat : 'rgb';
|
625
601
|
|
626
602
|
if (typeof input === 'string') {
|
627
|
-
// @ts-ignore -- this now is converted to object
|
628
603
|
color = stringInputToObject(input);
|
629
604
|
if (color) ok = true;
|
630
605
|
}
|
631
606
|
if (typeof color === 'object') {
|
632
607
|
if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) {
|
633
608
|
({ r, g, b } = color);
|
634
|
-
|
635
|
-
|
636
|
-
rgb = { r, g, b };
|
609
|
+
// RGB values now are all in [0, 1] range
|
610
|
+
[r, g, b] = [r, g, b].map((n) => bound01(n, isPercentage(n) ? 100 : 255));
|
611
|
+
rgb = { r, g, b };
|
637
612
|
ok = true;
|
638
|
-
format = 'rgb';
|
639
|
-
}
|
613
|
+
format = color.format || 'rgb';
|
614
|
+
}
|
615
|
+
if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) {
|
640
616
|
({ h, s, v } = color);
|
641
|
-
h =
|
642
|
-
s =
|
643
|
-
v =
|
617
|
+
h = bound01(h, 360); // hue can be `5deg` or a [0, 1] value
|
618
|
+
s = bound01(s, 100); // saturation can be `5%` or a [0, 1] value
|
619
|
+
v = bound01(v, 100); // brightness can be `5%` or a [0, 1] value
|
644
620
|
rgb = hsvToRgb(h, s, v);
|
645
621
|
ok = true;
|
646
622
|
format = 'hsv';
|
647
|
-
}
|
623
|
+
}
|
624
|
+
if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) {
|
648
625
|
({ h, s, l } = color);
|
649
|
-
h =
|
650
|
-
s =
|
651
|
-
l =
|
626
|
+
h = bound01(h, 360); // hue can be `5deg` or a [0, 1] value
|
627
|
+
s = bound01(s, 100); // saturation can be `5%` or a [0, 1] value
|
628
|
+
l = bound01(l, 100); // lightness can be `5%` or a [0, 1] value
|
652
629
|
rgb = hslToRgb(h, s, l);
|
653
630
|
ok = true;
|
654
631
|
format = 'hsl';
|
655
|
-
}
|
632
|
+
}
|
633
|
+
if (isValidCSSUnit(color.h) && isValidCSSUnit(color.w) && isValidCSSUnit(color.b)) {
|
656
634
|
({ h, w, b } = color);
|
657
|
-
h =
|
658
|
-
w =
|
659
|
-
b =
|
635
|
+
h = bound01(h, 360); // hue can be `5deg` or a [0, 1] value
|
636
|
+
w = bound01(w, 100); // whiteness can be `5%` or a [0, 1] value
|
637
|
+
b = bound01(b, 100); // blackness can be `5%` or a [0, 1] value
|
660
638
|
rgb = hwbToRgb(h, w, b);
|
661
639
|
ok = true;
|
662
640
|
format = 'hwb';
|
663
641
|
}
|
664
642
|
if (isValidCSSUnit(color.a)) {
|
665
|
-
a = color.a;
|
666
|
-
a = isPercentage(`${a}`) ? bound01(a, 100) : a;
|
643
|
+
a = color.a; // @ts-ignore -- `parseFloat` works with numbers too
|
644
|
+
a = isPercentage(`${a}`) || parseFloat(a) > 1 ? bound01(a, 100) : a;
|
667
645
|
}
|
668
646
|
}
|
647
|
+
if (typeof color === 'undefined') {
|
648
|
+
ok = true;
|
649
|
+
}
|
669
650
|
|
670
651
|
return {
|
671
|
-
ok,
|
672
|
-
format
|
673
|
-
r: Math.min(255, Math.max(rgb.r, 0)),
|
674
|
-
g: Math.min(255, Math.max(rgb.g, 0)),
|
675
|
-
b: Math.min(255, Math.max(rgb.b, 0)),
|
652
|
+
ok,
|
653
|
+
format,
|
654
|
+
// r: Math.min(255, Math.max(rgb.r, 0)),
|
655
|
+
// g: Math.min(255, Math.max(rgb.g, 0)),
|
656
|
+
// b: Math.min(255, Math.max(rgb.b, 0)),
|
657
|
+
r: rgb.r,
|
658
|
+
g: rgb.g,
|
659
|
+
b: rgb.b,
|
676
660
|
a: boundAlpha(a),
|
677
661
|
};
|
678
662
|
}
|
@@ -691,15 +675,13 @@ export default class Color {
|
|
691
675
|
constructor(input, config) {
|
692
676
|
let color = input;
|
693
677
|
const configFormat = config && COLOR_FORMAT.includes(config)
|
694
|
-
? config : '
|
678
|
+
? config : '';
|
695
679
|
|
696
|
-
// If input is already a `Color`,
|
680
|
+
// If input is already a `Color`, clone its values
|
697
681
|
if (color instanceof Color) {
|
698
682
|
color = inputToRGB(color);
|
699
683
|
}
|
700
|
-
|
701
|
-
color = numberInputToObject(color);
|
702
|
-
}
|
684
|
+
|
703
685
|
const {
|
704
686
|
r, g, b, a, ok, format,
|
705
687
|
} = inputToRGB(color);
|
@@ -708,7 +690,7 @@ export default class Color {
|
|
708
690
|
const self = this;
|
709
691
|
|
710
692
|
/** @type {CP.ColorInput} */
|
711
|
-
self.originalInput =
|
693
|
+
self.originalInput = input;
|
712
694
|
/** @type {number} */
|
713
695
|
self.r = r;
|
714
696
|
/** @type {number} */
|
@@ -749,24 +731,21 @@ export default class Color {
|
|
749
731
|
let R = 0;
|
750
732
|
let G = 0;
|
751
733
|
let B = 0;
|
752
|
-
const rp = r / 255;
|
753
|
-
const rg = g / 255;
|
754
|
-
const rb = b / 255;
|
755
734
|
|
756
|
-
if (
|
757
|
-
R =
|
735
|
+
if (r <= 0.03928) {
|
736
|
+
R = r / 12.92;
|
758
737
|
} else {
|
759
|
-
R = ((
|
738
|
+
R = ((r + 0.055) / 1.055) ** 2.4;
|
760
739
|
}
|
761
|
-
if (
|
762
|
-
G =
|
740
|
+
if (g <= 0.03928) {
|
741
|
+
G = g / 12.92;
|
763
742
|
} else {
|
764
|
-
G = ((
|
743
|
+
G = ((g + 0.055) / 1.055) ** 2.4;
|
765
744
|
}
|
766
|
-
if (
|
767
|
-
B =
|
745
|
+
if (b <= 0.03928) {
|
746
|
+
B = b / 12.92;
|
768
747
|
} else {
|
769
|
-
B = ((
|
748
|
+
B = ((b + 0.055) / 1.055) ** 2.4;
|
770
749
|
}
|
771
750
|
return 0.2126 * R + 0.7152 * G + 0.0722 * B;
|
772
751
|
}
|
@@ -776,7 +755,7 @@ export default class Color {
|
|
776
755
|
* @returns {number} a number in the [0, 255] range
|
777
756
|
*/
|
778
757
|
get brightness() {
|
779
|
-
const { r, g, b } = this;
|
758
|
+
const { r, g, b } = this.toRgb();
|
780
759
|
return (r * 299 + g * 587 + b * 114) / 1000;
|
781
760
|
}
|
782
761
|
|
@@ -785,16 +764,14 @@ export default class Color {
|
|
785
764
|
* @returns {CP.RGBA} an {r,g,b,a} object with [0, 255] ranged values
|
786
765
|
*/
|
787
766
|
toRgb() {
|
788
|
-
|
767
|
+
let {
|
789
768
|
r, g, b, a,
|
790
769
|
} = this;
|
791
|
-
const [R, G, B] = [r, g, b].map((x) => roundPart(x));
|
792
770
|
|
771
|
+
[r, g, b] = [r, g, b].map((n) => roundPart(n * 255 * 100) / 100);
|
772
|
+
a = roundPart(a * 100) / 100;
|
793
773
|
return {
|
794
|
-
r
|
795
|
-
g: G,
|
796
|
-
b: B,
|
797
|
-
a: roundPart(a * 100) / 100,
|
774
|
+
r, g, b, a,
|
798
775
|
};
|
799
776
|
}
|
800
777
|
|
@@ -808,10 +785,11 @@ export default class Color {
|
|
808
785
|
const {
|
809
786
|
r, g, b, a,
|
810
787
|
} = this.toRgb();
|
788
|
+
const [R, G, B] = [r, g, b].map(roundPart);
|
811
789
|
|
812
790
|
return a === 1
|
813
|
-
? `rgb(${
|
814
|
-
: `rgba(${
|
791
|
+
? `rgb(${R}, ${G}, ${B})`
|
792
|
+
: `rgba(${R}, ${G}, ${B}, ${a})`;
|
815
793
|
}
|
816
794
|
|
817
795
|
/**
|
@@ -824,9 +802,10 @@ export default class Color {
|
|
824
802
|
const {
|
825
803
|
r, g, b, a,
|
826
804
|
} = this.toRgb();
|
805
|
+
const [R, G, B] = [r, g, b].map(roundPart);
|
827
806
|
const A = a === 1 ? '' : ` / ${roundPart(a * 100)}%`;
|
828
807
|
|
829
|
-
return `rgb(${
|
808
|
+
return `rgb(${R} ${G} ${B}${A})`;
|
830
809
|
}
|
831
810
|
|
832
811
|
/**
|
@@ -886,7 +865,7 @@ export default class Color {
|
|
886
865
|
toHsv() {
|
887
866
|
const {
|
888
867
|
r, g, b, a,
|
889
|
-
} = this
|
868
|
+
} = this;
|
890
869
|
const { h, s, v } = rgbToHsv(r, g, b);
|
891
870
|
|
892
871
|
return {
|
@@ -901,7 +880,7 @@ export default class Color {
|
|
901
880
|
toHsl() {
|
902
881
|
const {
|
903
882
|
r, g, b, a,
|
904
|
-
} = this
|
883
|
+
} = this;
|
905
884
|
const { h, s, l } = rgbToHsl(r, g, b);
|
906
885
|
|
907
886
|
return {
|
@@ -986,6 +965,7 @@ export default class Color {
|
|
986
965
|
*/
|
987
966
|
setAlpha(alpha) {
|
988
967
|
const self = this;
|
968
|
+
if (typeof alpha !== 'number') return self;
|
989
969
|
self.a = boundAlpha(alpha);
|
990
970
|
return self;
|
991
971
|
}
|
@@ -1100,6 +1080,7 @@ ObjectAssign(Color, {
|
|
1100
1080
|
isOnePointZero,
|
1101
1081
|
isPercentage,
|
1102
1082
|
isValidCSSUnit,
|
1083
|
+
isColorName,
|
1103
1084
|
pad2,
|
1104
1085
|
clamp01,
|
1105
1086
|
bound01,
|
@@ -1117,9 +1098,10 @@ ObjectAssign(Color, {
|
|
1117
1098
|
hueToRgb,
|
1118
1099
|
hwbToRgb,
|
1119
1100
|
parseIntFromHex,
|
1120
|
-
numberInputToObject,
|
1121
1101
|
stringInputToObject,
|
1122
1102
|
inputToRGB,
|
1123
1103
|
roundPart,
|
1104
|
+
getElementStyle,
|
1105
|
+
setElementStyle,
|
1124
1106
|
ObjectAssign,
|
1125
1107
|
});
|