@thednp/color-picker 0.0.1-alpha3 → 0.0.2-alpha2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
});
|