@fluixi/utils 1.0.0-alpha.53
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/LICENSE +21 -0
- package/README.md +73 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- package/dist/lib/array/advanced.cjs +1 -0
- package/dist/lib/array/advanced.d.ts +1116 -0
- package/dist/lib/array/advanced.d.ts.map +1 -0
- package/dist/lib/array/advanced.js +2429 -0
- package/dist/lib/array/advanced.mjs +1 -0
- package/dist/lib/array/array.cjs +1 -0
- package/dist/lib/array/array.d.ts +6 -0
- package/dist/lib/array/array.d.ts.map +1 -0
- package/dist/lib/array/array.js +31 -0
- package/dist/lib/array/array.mjs +1 -0
- package/dist/lib/array/index.cjs +1 -0
- package/dist/lib/array/index.d.ts +4 -0
- package/dist/lib/array/index.d.ts.map +1 -0
- package/dist/lib/array/index.js +3 -0
- package/dist/lib/array/index.mjs +1 -0
- package/dist/lib/array/utils.cjs +1 -0
- package/dist/lib/array/utils.d.ts +100 -0
- package/dist/lib/array/utils.d.ts.map +1 -0
- package/dist/lib/array/utils.js +165 -0
- package/dist/lib/array/utils.mjs +1 -0
- package/dist/lib/color/color.cjs +1 -0
- package/dist/lib/color/color.d.ts +366 -0
- package/dist/lib/color/color.d.ts.map +1 -0
- package/dist/lib/color/color.js +722 -0
- package/dist/lib/color/color.mjs +1 -0
- package/dist/lib/color/constants.cjs +1 -0
- package/dist/lib/color/constants.d.ts +361 -0
- package/dist/lib/color/constants.d.ts.map +1 -0
- package/dist/lib/color/constants.js +358 -0
- package/dist/lib/color/constants.mjs +1 -0
- package/dist/lib/color/conversions.cjs +1 -0
- package/dist/lib/color/conversions.d.ts +166 -0
- package/dist/lib/color/conversions.d.ts.map +1 -0
- package/dist/lib/color/conversions.js +766 -0
- package/dist/lib/color/conversions.mjs +1 -0
- package/dist/lib/color/helpers.cjs +1 -0
- package/dist/lib/color/helpers.d.ts +75 -0
- package/dist/lib/color/helpers.d.ts.map +1 -0
- package/dist/lib/color/helpers.js +419 -0
- package/dist/lib/color/helpers.mjs +1 -0
- package/dist/lib/color/index.cjs +1 -0
- package/dist/lib/color/index.d.ts +12 -0
- package/dist/lib/color/index.d.ts.map +1 -0
- package/dist/lib/color/index.js +15 -0
- package/dist/lib/color/index.mjs +1 -0
- package/dist/lib/color/types.cjs +1 -0
- package/dist/lib/color/types.d.ts +179 -0
- package/dist/lib/color/types.d.ts.map +1 -0
- package/dist/lib/color/types.js +1 -0
- package/dist/lib/color/types.mjs +0 -0
- package/dist/lib/color/utils.cjs +1 -0
- package/dist/lib/color/utils.d.ts +199 -0
- package/dist/lib/color/utils.d.ts.map +1 -0
- package/dist/lib/color/utils.js +858 -0
- package/dist/lib/color/utils.mjs +1 -0
- package/dist/lib/compare/comparators.cjs +1 -0
- package/dist/lib/compare/comparators.d.ts +65 -0
- package/dist/lib/compare/comparators.d.ts.map +1 -0
- package/dist/lib/compare/comparators.js +210 -0
- package/dist/lib/compare/comparators.mjs +1 -0
- package/dist/lib/compare/index.cjs +1 -0
- package/dist/lib/compare/index.d.ts +2 -0
- package/dist/lib/compare/index.d.ts.map +1 -0
- package/dist/lib/compare/index.js +1 -0
- package/dist/lib/compare/index.mjs +1 -0
- package/dist/lib/crypto/hash.cjs +1 -0
- package/dist/lib/crypto/hash.d.ts +6 -0
- package/dist/lib/crypto/hash.d.ts.map +1 -0
- package/dist/lib/crypto/hash.js +53 -0
- package/dist/lib/crypto/hash.mjs +1 -0
- package/dist/lib/crypto/index.cjs +1 -0
- package/dist/lib/crypto/index.d.ts +2 -0
- package/dist/lib/crypto/index.d.ts.map +1 -0
- package/dist/lib/crypto/index.js +1 -0
- package/dist/lib/crypto/index.mjs +1 -0
- package/dist/lib/dom/events.cjs +1 -0
- package/dist/lib/dom/events.d.ts +159 -0
- package/dist/lib/dom/events.d.ts.map +1 -0
- package/dist/lib/dom/events.js +50 -0
- package/dist/lib/dom/events.mjs +1 -0
- package/dist/lib/dom/index.cjs +1 -0
- package/dist/lib/dom/index.d.ts +3 -0
- package/dist/lib/dom/index.d.ts.map +1 -0
- package/dist/lib/dom/index.js +2 -0
- package/dist/lib/dom/index.mjs +1 -0
- package/dist/lib/dom/utils.cjs +1 -0
- package/dist/lib/dom/utils.d.ts +6 -0
- package/dist/lib/dom/utils.d.ts.map +1 -0
- package/dist/lib/dom/utils.js +37 -0
- package/dist/lib/dom/utils.mjs +1 -0
- package/dist/lib/functions/functions.cjs +1 -0
- package/dist/lib/functions/functions.d.ts +329 -0
- package/dist/lib/functions/functions.d.ts.map +1 -0
- package/dist/lib/functions/functions.js +585 -0
- package/dist/lib/functions/functions.mjs +1 -0
- package/dist/lib/functions/index.cjs +1 -0
- package/dist/lib/functions/index.d.ts +3 -0
- package/dist/lib/functions/index.d.ts.map +1 -0
- package/dist/lib/functions/index.js +1 -0
- package/dist/lib/functions/index.mjs +1 -0
- package/dist/lib/functions/types.cjs +1 -0
- package/dist/lib/functions/types.d.ts +2 -0
- package/dist/lib/functions/types.d.ts.map +1 -0
- package/dist/lib/functions/types.js +1 -0
- package/dist/lib/functions/types.mjs +0 -0
- package/dist/lib/helpers.cjs +1 -0
- package/dist/lib/helpers.d.ts +13 -0
- package/dist/lib/helpers.d.ts.map +1 -0
- package/dist/lib/helpers.js +66 -0
- package/dist/lib/helpers.mjs +1 -0
- package/dist/lib/index.cjs +1 -0
- package/dist/lib/index.d.ts +6 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +8 -0
- package/dist/lib/index.mjs +1 -0
- package/dist/lib/maths/constants.cjs +1 -0
- package/dist/lib/maths/constants.d.ts +84 -0
- package/dist/lib/maths/constants.d.ts.map +1 -0
- package/dist/lib/maths/constants.js +79 -0
- package/dist/lib/maths/constants.mjs +1 -0
- package/dist/lib/maths/fn/advanced.cjs +1 -0
- package/dist/lib/maths/fn/advanced.d.ts +149 -0
- package/dist/lib/maths/fn/advanced.d.ts.map +1 -0
- package/dist/lib/maths/fn/advanced.js +264 -0
- package/dist/lib/maths/fn/advanced.mjs +1 -0
- package/dist/lib/maths/fn/basic.cjs +1 -0
- package/dist/lib/maths/fn/basic.d.ts +182 -0
- package/dist/lib/maths/fn/basic.d.ts.map +1 -0
- package/dist/lib/maths/fn/basic.js +343 -0
- package/dist/lib/maths/fn/basic.mjs +1 -0
- package/dist/lib/maths/fn/complex.cjs +1 -0
- package/dist/lib/maths/fn/complex.d.ts +153 -0
- package/dist/lib/maths/fn/complex.d.ts.map +1 -0
- package/dist/lib/maths/fn/complex.js +383 -0
- package/dist/lib/maths/fn/complex.mjs +1 -0
- package/dist/lib/maths/fn/index.cjs +1 -0
- package/dist/lib/maths/fn/index.d.ts +10 -0
- package/dist/lib/maths/fn/index.d.ts.map +1 -0
- package/dist/lib/maths/fn/index.js +9 -0
- package/dist/lib/maths/fn/index.mjs +1 -0
- package/dist/lib/maths/fn/trigo.cjs +1 -0
- package/dist/lib/maths/fn/trigo.d.ts +147 -0
- package/dist/lib/maths/fn/trigo.d.ts.map +1 -0
- package/dist/lib/maths/fn/trigo.js +227 -0
- package/dist/lib/maths/fn/trigo.mjs +1 -0
- package/dist/lib/maths/fn/vector.cjs +1 -0
- package/dist/lib/maths/fn/vector.d.ts +512 -0
- package/dist/lib/maths/fn/vector.d.ts.map +1 -0
- package/dist/lib/maths/fn/vector.js +1136 -0
- package/dist/lib/maths/fn/vector.mjs +1 -0
- package/dist/lib/maths/formatter.cjs +1 -0
- package/dist/lib/maths/formatter.d.ts +35 -0
- package/dist/lib/maths/formatter.d.ts.map +1 -0
- package/dist/lib/maths/formatter.js +56 -0
- package/dist/lib/maths/formatter.mjs +1 -0
- package/dist/lib/maths/guards.cjs +1 -0
- package/dist/lib/maths/guards.d.ts +166 -0
- package/dist/lib/maths/guards.d.ts.map +1 -0
- package/dist/lib/maths/guards.js +315 -0
- package/dist/lib/maths/guards.mjs +1 -0
- package/dist/lib/maths/index.cjs +1 -0
- package/dist/lib/maths/index.d.ts +24 -0
- package/dist/lib/maths/index.d.ts.map +1 -0
- package/dist/lib/maths/index.js +29 -0
- package/dist/lib/maths/index.mjs +1 -0
- package/dist/lib/maths/parser.cjs +1 -0
- package/dist/lib/maths/parser.d.ts +20 -0
- package/dist/lib/maths/parser.d.ts.map +1 -0
- package/dist/lib/maths/parser.js +78 -0
- package/dist/lib/maths/parser.mjs +1 -0
- package/dist/lib/maths/random.cjs +1 -0
- package/dist/lib/maths/random.d.ts +27 -0
- package/dist/lib/maths/random.d.ts.map +1 -0
- package/dist/lib/maths/random.js +49 -0
- package/dist/lib/maths/random.mjs +1 -0
- package/dist/lib/maths/types/advanced.cjs +1 -0
- package/dist/lib/maths/types/advanced.d.ts +357 -0
- package/dist/lib/maths/types/advanced.d.ts.map +1 -0
- package/dist/lib/maths/types/advanced.js +5 -0
- package/dist/lib/maths/types/advanced.mjs +0 -0
- package/dist/lib/maths/types/basic.cjs +1 -0
- package/dist/lib/maths/types/basic.d.ts +95 -0
- package/dist/lib/maths/types/basic.d.ts.map +1 -0
- package/dist/lib/maths/types/basic.js +5 -0
- package/dist/lib/maths/types/basic.mjs +0 -0
- package/dist/lib/maths/types/index.cjs +1 -0
- package/dist/lib/maths/types/index.d.ts +4 -0
- package/dist/lib/maths/types/index.d.ts.map +1 -0
- package/dist/lib/maths/types/index.js +3 -0
- package/dist/lib/maths/types/index.mjs +0 -0
- package/dist/lib/maths/types/negative.cjs +1 -0
- package/dist/lib/maths/types/negative.d.ts +51 -0
- package/dist/lib/maths/types/negative.d.ts.map +1 -0
- package/dist/lib/maths/types/negative.js +5 -0
- package/dist/lib/maths/types/negative.mjs +0 -0
- package/dist/lib/maths/types/operations.cjs +1 -0
- package/dist/lib/maths/types/operations.d.ts +188 -0
- package/dist/lib/maths/types/operations.d.ts.map +1 -0
- package/dist/lib/maths/types/operations.js +6 -0
- package/dist/lib/maths/types/operations.mjs +0 -0
- package/dist/lib/object/clone.cjs +1 -0
- package/dist/lib/object/clone.d.ts +46 -0
- package/dist/lib/object/clone.d.ts.map +1 -0
- package/dist/lib/object/clone.js +104 -0
- package/dist/lib/object/clone.mjs +1 -0
- package/dist/lib/object/diff.cjs +1 -0
- package/dist/lib/object/diff.d.ts +203 -0
- package/dist/lib/object/diff.d.ts.map +1 -0
- package/dist/lib/object/diff.js +805 -0
- package/dist/lib/object/diff.mjs +1 -0
- package/dist/lib/object/getter-setter.cjs +1 -0
- package/dist/lib/object/getter-setter.d.ts +361 -0
- package/dist/lib/object/getter-setter.d.ts.map +1 -0
- package/dist/lib/object/getter-setter.js +1771 -0
- package/dist/lib/object/getter-setter.mjs +1 -0
- package/dist/lib/object/index.cjs +6 -0
- package/dist/lib/object/index.d.ts +13 -0
- package/dist/lib/object/index.d.ts.map +1 -0
- package/dist/lib/object/index.js +12 -0
- package/dist/lib/object/index.mjs +6 -0
- package/dist/lib/object/merge.cjs +1 -0
- package/dist/lib/object/merge.d.ts +93 -0
- package/dist/lib/object/merge.d.ts.map +1 -0
- package/dist/lib/object/merge.js +474 -0
- package/dist/lib/object/merge.mjs +1 -0
- package/dist/lib/object/object.cjs +1 -0
- package/dist/lib/object/object.d.ts +128 -0
- package/dist/lib/object/object.d.ts.map +1 -0
- package/dist/lib/object/object.js +432 -0
- package/dist/lib/object/object.mjs +1 -0
- package/dist/lib/object/omit.cjs +1 -0
- package/dist/lib/object/omit.d.ts +351 -0
- package/dist/lib/object/omit.d.ts.map +1 -0
- package/dist/lib/object/omit.js +656 -0
- package/dist/lib/object/omit.mjs +1 -0
- package/dist/lib/object/reconcile.cjs +1 -0
- package/dist/lib/object/reconcile.d.ts +7 -0
- package/dist/lib/object/reconcile.d.ts.map +1 -0
- package/dist/lib/object/reconcile.js +122 -0
- package/dist/lib/object/reconcile.mjs +1 -0
- package/dist/lib/object/selector.cjs +1 -0
- package/dist/lib/object/selector.d.ts +50 -0
- package/dist/lib/object/selector.d.ts.map +1 -0
- package/dist/lib/object/selector.js +371 -0
- package/dist/lib/object/selector.mjs +1 -0
- package/dist/lib/object/sort.cjs +1 -0
- package/dist/lib/object/sort.d.ts +149 -0
- package/dist/lib/object/sort.d.ts.map +1 -0
- package/dist/lib/object/sort.js +298 -0
- package/dist/lib/object/sort.mjs +1 -0
- package/dist/lib/object/transform.cjs +1 -0
- package/dist/lib/object/transform.d.ts +620 -0
- package/dist/lib/object/transform.d.ts.map +1 -0
- package/dist/lib/object/transform.js +1058 -0
- package/dist/lib/object/transform.mjs +1 -0
- package/dist/lib/object/types.cjs +1 -0
- package/dist/lib/object/types.d.ts +250 -0
- package/dist/lib/object/types.d.ts.map +1 -0
- package/dist/lib/object/types.js +1 -0
- package/dist/lib/object/types.mjs +0 -0
- package/dist/lib/object/utils.cjs +6 -0
- package/dist/lib/object/utils.d.ts +165 -0
- package/dist/lib/object/utils.d.ts.map +1 -0
- package/dist/lib/object/utils.js +444 -0
- package/dist/lib/object/utils.mjs +6 -0
- package/dist/lib/primitive/boolean/boolean.cjs +1 -0
- package/dist/lib/primitive/boolean/boolean.d.ts +276 -0
- package/dist/lib/primitive/boolean/boolean.d.ts.map +1 -0
- package/dist/lib/primitive/boolean/boolean.js +615 -0
- package/dist/lib/primitive/boolean/boolean.mjs +1 -0
- package/dist/lib/primitive/boolean/index.cjs +1 -0
- package/dist/lib/primitive/boolean/index.d.ts +3 -0
- package/dist/lib/primitive/boolean/index.d.ts.map +1 -0
- package/dist/lib/primitive/boolean/index.js +2 -0
- package/dist/lib/primitive/boolean/index.mjs +1 -0
- package/dist/lib/primitive/boolean/types.cjs +1 -0
- package/dist/lib/primitive/boolean/types.d.ts +14 -0
- package/dist/lib/primitive/boolean/types.d.ts.map +1 -0
- package/dist/lib/primitive/boolean/types.js +1 -0
- package/dist/lib/primitive/boolean/types.mjs +0 -0
- package/dist/lib/primitive/date/date.cjs +1 -0
- package/dist/lib/primitive/date/date.d.ts +641 -0
- package/dist/lib/primitive/date/date.d.ts.map +1 -0
- package/dist/lib/primitive/date/date.js +1998 -0
- package/dist/lib/primitive/date/date.mjs +1 -0
- package/dist/lib/primitive/date/index.cjs +1 -0
- package/dist/lib/primitive/date/index.d.ts +3 -0
- package/dist/lib/primitive/date/index.d.ts.map +1 -0
- package/dist/lib/primitive/date/index.js +2 -0
- package/dist/lib/primitive/date/index.mjs +1 -0
- package/dist/lib/primitive/date/types.cjs +1 -0
- package/dist/lib/primitive/date/types.d.ts +205 -0
- package/dist/lib/primitive/date/types.d.ts.map +1 -0
- package/dist/lib/primitive/date/types.js +7 -0
- package/dist/lib/primitive/date/types.mjs +0 -0
- package/dist/lib/primitive/index.cjs +5 -0
- package/dist/lib/primitive/index.d.ts +5 -0
- package/dist/lib/primitive/index.d.ts.map +1 -0
- package/dist/lib/primitive/index.js +4 -0
- package/dist/lib/primitive/index.mjs +5 -0
- package/dist/lib/primitive/string/index.cjs +5 -0
- package/dist/lib/primitive/string/index.d.ts +3 -0
- package/dist/lib/primitive/string/index.d.ts.map +1 -0
- package/dist/lib/primitive/string/index.js +2 -0
- package/dist/lib/primitive/string/index.mjs +5 -0
- package/dist/lib/primitive/string/parser-2.cjs +8 -0
- package/dist/lib/primitive/string/parser-2.d.ts +17 -0
- package/dist/lib/primitive/string/parser-2.d.ts.map +1 -0
- package/dist/lib/primitive/string/parser-2.js +656 -0
- package/dist/lib/primitive/string/parser-2.mjs +8 -0
- package/dist/lib/primitive/string/parser.cjs +3 -0
- package/dist/lib/primitive/string/parser.d.ts +9 -0
- package/dist/lib/primitive/string/parser.d.ts.map +1 -0
- package/dist/lib/primitive/string/parser.js +775 -0
- package/dist/lib/primitive/string/parser.mjs +3 -0
- package/dist/lib/primitive/string/string.cjs +5 -0
- package/dist/lib/primitive/string/string.d.ts +535 -0
- package/dist/lib/primitive/string/string.d.ts.map +1 -0
- package/dist/lib/primitive/string/string.js +1301 -0
- package/dist/lib/primitive/string/string.mjs +5 -0
- package/dist/lib/primitive/string/types.cjs +1 -0
- package/dist/lib/primitive/string/types.d.ts +318 -0
- package/dist/lib/primitive/string/types.d.ts.map +1 -0
- package/dist/lib/primitive/string/types.js +5 -0
- package/dist/lib/primitive/string/types.mjs +0 -0
- package/dist/lib/primitive/types.cjs +1 -0
- package/dist/lib/primitive/types.d.ts +27 -0
- package/dist/lib/primitive/types.d.ts.map +1 -0
- package/dist/lib/primitive/types.js +1 -0
- package/dist/lib/primitive/types.mjs +0 -0
- package/dist/lib/url/index.cjs +1 -0
- package/dist/lib/url/index.d.ts +3 -0
- package/dist/lib/url/index.d.ts.map +1 -0
- package/dist/lib/url/index.js +2 -0
- package/dist/lib/url/index.mjs +1 -0
- package/dist/lib/url/parser.cjs +1 -0
- package/dist/lib/url/parser.d.ts +216 -0
- package/dist/lib/url/parser.d.ts.map +1 -0
- package/dist/lib/url/parser.js +488 -0
- package/dist/lib/url/parser.mjs +1 -0
- package/dist/lib/url/types.cjs +1 -0
- package/dist/lib/url/types.d.ts +18 -0
- package/dist/lib/url/types.d.ts.map +1 -0
- package/dist/lib/url/types.js +1 -0
- package/dist/lib/url/types.mjs +0 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -0
- package/package.json +150 -0
|
@@ -0,0 +1,766 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Comprehensive color conversion utilities
|
|
3
|
+
* Supports conversions between: RGB, HSL, HSV, HWB, CMYK, LAB, LCH, OKLAB, OKLCH, XYZ
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Constants for color conversions
|
|
7
|
+
*/
|
|
8
|
+
const D65_WHITE = { x: 0.95047, y: 1.0, z: 1.08883 };
|
|
9
|
+
const EPSILON = 0.008856;
|
|
10
|
+
const KAPPA = 903.3;
|
|
11
|
+
/**
|
|
12
|
+
* Utility function to clamp values
|
|
13
|
+
*/
|
|
14
|
+
function clamp(value, min, max) {
|
|
15
|
+
return Math.max(min, Math.min(max, value));
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Round to specified precision
|
|
19
|
+
*/
|
|
20
|
+
function roundToPrecision(value, precision = 2) {
|
|
21
|
+
const multiplier = Math.pow(10, precision);
|
|
22
|
+
return Math.round(value * multiplier) / multiplier;
|
|
23
|
+
}
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// RGB CONVERSIONS
|
|
26
|
+
// ============================================================================
|
|
27
|
+
/**
|
|
28
|
+
* Convert RGB to HSL
|
|
29
|
+
*/
|
|
30
|
+
export function rgbToHsl(rgb) {
|
|
31
|
+
const r = rgb.r / 255;
|
|
32
|
+
const g = rgb.g / 255;
|
|
33
|
+
const b = rgb.b / 255;
|
|
34
|
+
const max = Math.max(r, g, b);
|
|
35
|
+
const min = Math.min(r, g, b);
|
|
36
|
+
const delta = max - min;
|
|
37
|
+
let h = 0;
|
|
38
|
+
let s = 0;
|
|
39
|
+
const l = (max + min) / 2;
|
|
40
|
+
if (delta !== 0) {
|
|
41
|
+
s = l > 0.5 ? delta / (2 - max - min) : delta / (max + min);
|
|
42
|
+
switch (max) {
|
|
43
|
+
case r:
|
|
44
|
+
h = ((g - b) / delta + (g < b ? 6 : 0)) / 6;
|
|
45
|
+
break;
|
|
46
|
+
case g:
|
|
47
|
+
h = ((b - r) / delta + 2) / 6;
|
|
48
|
+
break;
|
|
49
|
+
case b:
|
|
50
|
+
h = ((r - g) / delta + 4) / 6;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
h: h * 360,
|
|
56
|
+
s: s * 100,
|
|
57
|
+
l: l * 100,
|
|
58
|
+
a: rgb.a,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Convert RGB to HSV
|
|
63
|
+
*/
|
|
64
|
+
export function rgbToHsv(rgb) {
|
|
65
|
+
const r = rgb.r / 255;
|
|
66
|
+
const g = rgb.g / 255;
|
|
67
|
+
const b = rgb.b / 255;
|
|
68
|
+
const max = Math.max(r, g, b);
|
|
69
|
+
const min = Math.min(r, g, b);
|
|
70
|
+
const delta = max - min;
|
|
71
|
+
let h = 0;
|
|
72
|
+
const s = max === 0 ? 0 : delta / max;
|
|
73
|
+
const v = max;
|
|
74
|
+
if (delta !== 0) {
|
|
75
|
+
switch (max) {
|
|
76
|
+
case r:
|
|
77
|
+
h = ((g - b) / delta + (g < b ? 6 : 0)) / 6;
|
|
78
|
+
break;
|
|
79
|
+
case g:
|
|
80
|
+
h = ((b - r) / delta + 2) / 6;
|
|
81
|
+
break;
|
|
82
|
+
case b:
|
|
83
|
+
h = ((r - g) / delta + 4) / 6;
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
h: h * 360,
|
|
89
|
+
s: s * 100,
|
|
90
|
+
v: v * 100,
|
|
91
|
+
a: rgb.a,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Convert RGB to HWB
|
|
96
|
+
*/
|
|
97
|
+
export function rgbToHwb(rgb) {
|
|
98
|
+
const hsv = rgbToHsv(rgb);
|
|
99
|
+
const w = ((100 - hsv.s) * hsv.v) / 100;
|
|
100
|
+
const b = 100 - hsv.v;
|
|
101
|
+
return {
|
|
102
|
+
h: hsv.h,
|
|
103
|
+
w,
|
|
104
|
+
b,
|
|
105
|
+
a: rgb.a,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Convert RGB to CMYK
|
|
110
|
+
*/
|
|
111
|
+
export function rgbToCmyk(rgb) {
|
|
112
|
+
const r = rgb.r / 255;
|
|
113
|
+
const g = rgb.g / 255;
|
|
114
|
+
const b = rgb.b / 255;
|
|
115
|
+
const k = 1 - Math.max(r, g, b);
|
|
116
|
+
const c = k === 1 ? 0 : (1 - r - k) / (1 - k);
|
|
117
|
+
const m = k === 1 ? 0 : (1 - g - k) / (1 - k);
|
|
118
|
+
const y = k === 1 ? 0 : (1 - b - k) / (1 - k);
|
|
119
|
+
return {
|
|
120
|
+
c: c * 100,
|
|
121
|
+
m: m * 100,
|
|
122
|
+
y: y * 100,
|
|
123
|
+
k: k * 100,
|
|
124
|
+
a: rgb.a,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Convert RGB to XYZ
|
|
129
|
+
*/
|
|
130
|
+
export function rgbToXyz(rgb) {
|
|
131
|
+
let r = rgb.r / 255;
|
|
132
|
+
let g = rgb.g / 255;
|
|
133
|
+
let b = rgb.b / 255;
|
|
134
|
+
// Apply gamma correction
|
|
135
|
+
r = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
|
|
136
|
+
g = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
|
|
137
|
+
b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
|
|
138
|
+
// Convert to XYZ using sRGB matrix
|
|
139
|
+
const x = r * 0.4124564 + g * 0.3575761 + b * 0.1804375;
|
|
140
|
+
const y = r * 0.2126729 + g * 0.7151522 + b * 0.072175;
|
|
141
|
+
const z = r * 0.0193339 + g * 0.119192 + b * 0.9503041;
|
|
142
|
+
return {
|
|
143
|
+
x: x * 100,
|
|
144
|
+
y: y * 100,
|
|
145
|
+
z: z * 100,
|
|
146
|
+
alpha: rgb.a,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Convert RGB to LAB
|
|
151
|
+
*/
|
|
152
|
+
export function rgbToLab(rgb) {
|
|
153
|
+
const xyz = rgbToXyz(rgb);
|
|
154
|
+
return xyzToLab(xyz);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Convert RGB to LCH
|
|
158
|
+
*/
|
|
159
|
+
export function rgbToLch(rgb) {
|
|
160
|
+
const lab = rgbToLab(rgb);
|
|
161
|
+
return labToLch(lab);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Convert RGB to OKLAB
|
|
165
|
+
*/
|
|
166
|
+
export function rgbToOklab(rgb) {
|
|
167
|
+
const r = rgb.r / 255;
|
|
168
|
+
const g = rgb.g / 255;
|
|
169
|
+
const b = rgb.b / 255;
|
|
170
|
+
// Linear RGB
|
|
171
|
+
const lr = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
|
|
172
|
+
const lg = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
|
|
173
|
+
const lb = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
|
|
174
|
+
// Convert to LMS cone space
|
|
175
|
+
const l = 0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb;
|
|
176
|
+
const m = 0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb;
|
|
177
|
+
const s = 0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb;
|
|
178
|
+
const l_ = Math.cbrt(l);
|
|
179
|
+
const m_ = Math.cbrt(m);
|
|
180
|
+
const s_ = Math.cbrt(s);
|
|
181
|
+
return {
|
|
182
|
+
l: 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_,
|
|
183
|
+
a: 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_,
|
|
184
|
+
b: 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_,
|
|
185
|
+
alpha: rgb.a,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Convert RGB to OKLCH
|
|
190
|
+
*/
|
|
191
|
+
export function rgbToOklch(rgb) {
|
|
192
|
+
const oklab = rgbToOklab(rgb);
|
|
193
|
+
return oklabToOklch(oklab);
|
|
194
|
+
}
|
|
195
|
+
// ============================================================================
|
|
196
|
+
// HSL CONVERSIONS
|
|
197
|
+
// ============================================================================
|
|
198
|
+
/**
|
|
199
|
+
* Convert HSL to RGB
|
|
200
|
+
*/
|
|
201
|
+
export function hslToRgb(hsl) {
|
|
202
|
+
const h = hsl.h / 360;
|
|
203
|
+
const s = hsl.s / 100;
|
|
204
|
+
const l = hsl.l / 100;
|
|
205
|
+
let r, g, b;
|
|
206
|
+
if (s === 0) {
|
|
207
|
+
r = g = b = l;
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
const hue2rgb = (p, q, t) => {
|
|
211
|
+
if (t < 0)
|
|
212
|
+
t += 1;
|
|
213
|
+
if (t > 1)
|
|
214
|
+
t -= 1;
|
|
215
|
+
if (t < 1 / 6)
|
|
216
|
+
return p + (q - p) * 6 * t;
|
|
217
|
+
if (t < 1 / 2)
|
|
218
|
+
return q;
|
|
219
|
+
if (t < 2 / 3)
|
|
220
|
+
return p + (q - p) * (2 / 3 - t) * 6;
|
|
221
|
+
return p;
|
|
222
|
+
};
|
|
223
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
224
|
+
const p = 2 * l - q;
|
|
225
|
+
r = hue2rgb(p, q, h + 1 / 3);
|
|
226
|
+
g = hue2rgb(p, q, h);
|
|
227
|
+
b = hue2rgb(p, q, h - 1 / 3);
|
|
228
|
+
}
|
|
229
|
+
return {
|
|
230
|
+
r: Math.round(r * 255),
|
|
231
|
+
g: Math.round(g * 255),
|
|
232
|
+
b: Math.round(b * 255),
|
|
233
|
+
a: hsl.a,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Convert HSL to HSV
|
|
238
|
+
*/
|
|
239
|
+
export function hslToHsv(hsl) {
|
|
240
|
+
const rgb = hslToRgb(hsl);
|
|
241
|
+
return rgbToHsv(rgb);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Convert HSL to HWB
|
|
245
|
+
*/
|
|
246
|
+
export function hslToHwb(hsl) {
|
|
247
|
+
const rgb = hslToRgb(hsl);
|
|
248
|
+
return rgbToHwb(rgb);
|
|
249
|
+
}
|
|
250
|
+
// ============================================================================
|
|
251
|
+
// HSV CONVERSIONS
|
|
252
|
+
// ============================================================================
|
|
253
|
+
/**
|
|
254
|
+
* Convert HSV to RGB
|
|
255
|
+
*/
|
|
256
|
+
export function hsvToRgb(hsv) {
|
|
257
|
+
const h = hsv.h / 360;
|
|
258
|
+
const s = hsv.s / 100;
|
|
259
|
+
const v = hsv.v / 100;
|
|
260
|
+
const i = Math.floor(h * 6);
|
|
261
|
+
const f = h * 6 - i;
|
|
262
|
+
const p = v * (1 - s);
|
|
263
|
+
const q = v * (1 - f * s);
|
|
264
|
+
const t = v * (1 - (1 - f) * s);
|
|
265
|
+
let r, g, b;
|
|
266
|
+
switch (i % 6) {
|
|
267
|
+
case 0:
|
|
268
|
+
r = v;
|
|
269
|
+
g = t;
|
|
270
|
+
b = p;
|
|
271
|
+
break;
|
|
272
|
+
case 1:
|
|
273
|
+
r = q;
|
|
274
|
+
g = v;
|
|
275
|
+
b = p;
|
|
276
|
+
break;
|
|
277
|
+
case 2:
|
|
278
|
+
r = p;
|
|
279
|
+
g = v;
|
|
280
|
+
b = t;
|
|
281
|
+
break;
|
|
282
|
+
case 3:
|
|
283
|
+
r = p;
|
|
284
|
+
g = q;
|
|
285
|
+
b = v;
|
|
286
|
+
break;
|
|
287
|
+
case 4:
|
|
288
|
+
r = t;
|
|
289
|
+
g = p;
|
|
290
|
+
b = v;
|
|
291
|
+
break;
|
|
292
|
+
case 5:
|
|
293
|
+
default:
|
|
294
|
+
r = v;
|
|
295
|
+
g = p;
|
|
296
|
+
b = q;
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
return {
|
|
300
|
+
r: Math.round(r * 255),
|
|
301
|
+
g: Math.round(g * 255),
|
|
302
|
+
b: Math.round(b * 255),
|
|
303
|
+
a: hsv.a,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Convert HSV to HSL
|
|
308
|
+
*/
|
|
309
|
+
export function hsvToHsl(hsv) {
|
|
310
|
+
const rgb = hsvToRgb(hsv);
|
|
311
|
+
return rgbToHsl(rgb);
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Convert HSV to HWB
|
|
315
|
+
*/
|
|
316
|
+
export function hsvToHwb(hsv) {
|
|
317
|
+
const w = ((100 - hsv.s) * hsv.v) / 100;
|
|
318
|
+
const b = 100 - hsv.v;
|
|
319
|
+
return {
|
|
320
|
+
h: hsv.h,
|
|
321
|
+
w,
|
|
322
|
+
b,
|
|
323
|
+
a: hsv.a,
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
// ============================================================================
|
|
327
|
+
// HWB CONVERSIONS
|
|
328
|
+
// ============================================================================
|
|
329
|
+
/**
|
|
330
|
+
* Convert HWB to RGB
|
|
331
|
+
*/
|
|
332
|
+
export function hwbToRgb(hwb) {
|
|
333
|
+
const h = hwb.h;
|
|
334
|
+
let w = hwb.w / 100;
|
|
335
|
+
let b = hwb.b / 100;
|
|
336
|
+
const sum = w + b;
|
|
337
|
+
if (sum > 1) {
|
|
338
|
+
w /= sum;
|
|
339
|
+
b /= sum;
|
|
340
|
+
}
|
|
341
|
+
const v = 1 - b;
|
|
342
|
+
const s = v === 0 ? 0 : 1 - w / v;
|
|
343
|
+
return hsvToRgb({ h, s: s * 100, v: v * 100, a: hwb.a });
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Convert HWB to HSL
|
|
347
|
+
*/
|
|
348
|
+
export function hwbToHsl(hwb) {
|
|
349
|
+
const rgb = hwbToRgb(hwb);
|
|
350
|
+
return rgbToHsl(rgb);
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Convert HWB to HSV
|
|
354
|
+
*/
|
|
355
|
+
export function hwbToHsv(hwb) {
|
|
356
|
+
const rgb = hwbToRgb(hwb);
|
|
357
|
+
return rgbToHsv(rgb);
|
|
358
|
+
}
|
|
359
|
+
// ============================================================================
|
|
360
|
+
// CMYK CONVERSIONS
|
|
361
|
+
// ============================================================================
|
|
362
|
+
/**
|
|
363
|
+
* Convert CMYK to RGB
|
|
364
|
+
*/
|
|
365
|
+
export function cmykToRgb(cmyk) {
|
|
366
|
+
const c = cmyk.c / 100;
|
|
367
|
+
const m = cmyk.m / 100;
|
|
368
|
+
const y = cmyk.y / 100;
|
|
369
|
+
const k = cmyk.k / 100;
|
|
370
|
+
const r = 255 * (1 - c) * (1 - k);
|
|
371
|
+
const g = 255 * (1 - m) * (1 - k);
|
|
372
|
+
const b = 255 * (1 - y) * (1 - k);
|
|
373
|
+
return {
|
|
374
|
+
r: Math.round(r),
|
|
375
|
+
g: Math.round(g),
|
|
376
|
+
b: Math.round(b),
|
|
377
|
+
a: cmyk.a,
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Convert CMYK to HSL
|
|
382
|
+
*/
|
|
383
|
+
export function cmykToHsl(cmyk) {
|
|
384
|
+
const rgb = cmykToRgb(cmyk);
|
|
385
|
+
return rgbToHsl(rgb);
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Convert CMYK to HSV
|
|
389
|
+
*/
|
|
390
|
+
export function cmykToHsv(cmyk) {
|
|
391
|
+
const rgb = cmykToRgb(cmyk);
|
|
392
|
+
return rgbToHsv(rgb);
|
|
393
|
+
}
|
|
394
|
+
// ============================================================================
|
|
395
|
+
// XYZ CONVERSIONS
|
|
396
|
+
// ============================================================================
|
|
397
|
+
/**
|
|
398
|
+
* Convert XYZ to RGB
|
|
399
|
+
*/
|
|
400
|
+
export function xyzToRgb(xyz) {
|
|
401
|
+
const x = xyz.x / 100;
|
|
402
|
+
const y = xyz.y / 100;
|
|
403
|
+
const z = xyz.z / 100;
|
|
404
|
+
// Convert XYZ to linear RGB using sRGB matrix
|
|
405
|
+
let r = x * 3.2404542 + y * -1.5371385 + z * -0.4985314;
|
|
406
|
+
let g = x * -0.969266 + y * 1.8760108 + z * 0.041556;
|
|
407
|
+
let b = x * 0.0556434 + y * -0.2040259 + z * 1.0572252;
|
|
408
|
+
// Apply gamma correction
|
|
409
|
+
r = r > 0.0031308 ? 1.055 * Math.pow(r, 1 / 2.4) - 0.055 : 12.92 * r;
|
|
410
|
+
g = g > 0.0031308 ? 1.055 * Math.pow(g, 1 / 2.4) - 0.055 : 12.92 * g;
|
|
411
|
+
b = b > 0.0031308 ? 1.055 * Math.pow(b, 1 / 2.4) - 0.055 : 12.92 * b;
|
|
412
|
+
return {
|
|
413
|
+
r: Math.round(clamp(r * 255, 0, 255)),
|
|
414
|
+
g: Math.round(clamp(g * 255, 0, 255)),
|
|
415
|
+
b: Math.round(clamp(b * 255, 0, 255)),
|
|
416
|
+
a: xyz.alpha || 1,
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Convert XYZ to LAB
|
|
421
|
+
*/
|
|
422
|
+
export function xyzToLab(xyz) {
|
|
423
|
+
const xr = xyz.x / D65_WHITE.x / 100;
|
|
424
|
+
const yr = xyz.y / D65_WHITE.y / 100;
|
|
425
|
+
const zr = xyz.z / D65_WHITE.z / 100;
|
|
426
|
+
const fx = xr > EPSILON ? Math.cbrt(xr) : (KAPPA * xr + 16) / 116;
|
|
427
|
+
const fy = yr > EPSILON ? Math.cbrt(yr) : (KAPPA * yr + 16) / 116;
|
|
428
|
+
const fz = zr > EPSILON ? Math.cbrt(zr) : (KAPPA * zr + 16) / 116;
|
|
429
|
+
const l = 116 * fy - 16;
|
|
430
|
+
const a = 500 * (fx - fy);
|
|
431
|
+
const b = 200 * (fy - fz);
|
|
432
|
+
return {
|
|
433
|
+
l: clamp(l, 0, 100),
|
|
434
|
+
a,
|
|
435
|
+
b,
|
|
436
|
+
alpha: xyz.alpha,
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
// ============================================================================
|
|
440
|
+
// LAB CONVERSIONS
|
|
441
|
+
// ============================================================================
|
|
442
|
+
/**
|
|
443
|
+
* Convert LAB to XYZ
|
|
444
|
+
*/
|
|
445
|
+
export function labToXyz(lab) {
|
|
446
|
+
const fy = (lab.l + 16) / 116;
|
|
447
|
+
const fx = lab.a / 500 + fy;
|
|
448
|
+
const fz = fy - lab.b / 200;
|
|
449
|
+
const xr = fx * fx * fx > EPSILON ? fx * fx * fx : (116 * fx - 16) / KAPPA;
|
|
450
|
+
const yr = lab.l > KAPPA * EPSILON ? Math.pow((lab.l + 16) / 116, 3) : lab.l / KAPPA;
|
|
451
|
+
const zr = fz * fz * fz > EPSILON ? fz * fz * fz : (116 * fz - 16) / KAPPA;
|
|
452
|
+
return {
|
|
453
|
+
x: xr * D65_WHITE.x * 100,
|
|
454
|
+
y: yr * D65_WHITE.y * 100,
|
|
455
|
+
z: zr * D65_WHITE.z * 100,
|
|
456
|
+
alpha: lab.alpha,
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Convert LAB to RGB
|
|
461
|
+
*/
|
|
462
|
+
export function labToRgb(lab) {
|
|
463
|
+
const xyz = labToXyz(lab);
|
|
464
|
+
return xyzToRgb(xyz);
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Convert LAB to LCH
|
|
468
|
+
*/
|
|
469
|
+
export function labToLch(lab) {
|
|
470
|
+
const c = Math.sqrt(lab.a * lab.a + lab.b * lab.b);
|
|
471
|
+
let h = (Math.atan2(lab.b, lab.a) * 180) / Math.PI;
|
|
472
|
+
if (h < 0) {
|
|
473
|
+
h += 360;
|
|
474
|
+
}
|
|
475
|
+
return {
|
|
476
|
+
l: lab.l,
|
|
477
|
+
c,
|
|
478
|
+
h,
|
|
479
|
+
alpha: lab.alpha,
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
// ============================================================================
|
|
483
|
+
// LCH CONVERSIONS
|
|
484
|
+
// ============================================================================
|
|
485
|
+
/**
|
|
486
|
+
* Convert LCH to LAB
|
|
487
|
+
*/
|
|
488
|
+
export function lchToLab(lch) {
|
|
489
|
+
const h = (lch.h * Math.PI) / 180;
|
|
490
|
+
const a = lch.c * Math.cos(h);
|
|
491
|
+
const b = lch.c * Math.sin(h);
|
|
492
|
+
return {
|
|
493
|
+
l: lch.l,
|
|
494
|
+
a,
|
|
495
|
+
b,
|
|
496
|
+
alpha: lch.alpha,
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Convert LCH to RGB
|
|
501
|
+
*/
|
|
502
|
+
export function lchToRgb(lch) {
|
|
503
|
+
const lab = lchToLab(lch);
|
|
504
|
+
return labToRgb(lab);
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Convert LCH to XYZ
|
|
508
|
+
*/
|
|
509
|
+
export function lchToXyz(lch) {
|
|
510
|
+
const lab = lchToLab(lch);
|
|
511
|
+
return labToXyz(lab);
|
|
512
|
+
}
|
|
513
|
+
// ============================================================================
|
|
514
|
+
// OKLAB CONVERSIONS
|
|
515
|
+
// ============================================================================
|
|
516
|
+
/**
|
|
517
|
+
* Convert OKLAB to RGB
|
|
518
|
+
*/
|
|
519
|
+
export function oklabToRgb(oklab) {
|
|
520
|
+
const l_ = oklab.l + 0.3963377774 * oklab.a + 0.2158037573 * oklab.b;
|
|
521
|
+
const m_ = oklab.l - 0.1055613458 * oklab.a - 0.0638541728 * oklab.b;
|
|
522
|
+
const s_ = oklab.l - 0.0894841775 * oklab.a - 1.291485548 * oklab.b;
|
|
523
|
+
const l = l_ * l_ * l_;
|
|
524
|
+
const m = m_ * m_ * m_;
|
|
525
|
+
const s = s_ * s_ * s_;
|
|
526
|
+
let lr = +4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s;
|
|
527
|
+
let lg = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s;
|
|
528
|
+
let lb = -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s;
|
|
529
|
+
// Apply gamma correction
|
|
530
|
+
lr = lr > 0.0031308 ? 1.055 * Math.pow(lr, 1 / 2.4) - 0.055 : 12.92 * lr;
|
|
531
|
+
lg = lg > 0.0031308 ? 1.055 * Math.pow(lg, 1 / 2.4) - 0.055 : 12.92 * lg;
|
|
532
|
+
lb = lb > 0.0031308 ? 1.055 * Math.pow(lb, 1 / 2.4) - 0.055 : 12.92 * lb;
|
|
533
|
+
return {
|
|
534
|
+
r: Math.round(clamp(lr * 255, 0, 255)),
|
|
535
|
+
g: Math.round(clamp(lg * 255, 0, 255)),
|
|
536
|
+
b: Math.round(clamp(lb * 255, 0, 255)),
|
|
537
|
+
a: oklab.alpha,
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Convert OKLAB to OKLCH
|
|
542
|
+
*/
|
|
543
|
+
export function oklabToOklch(oklab) {
|
|
544
|
+
const c = Math.sqrt(oklab.a * oklab.a + oklab.b * oklab.b);
|
|
545
|
+
let h = (Math.atan2(oklab.b, oklab.a) * 180) / Math.PI;
|
|
546
|
+
if (h < 0) {
|
|
547
|
+
h += 360;
|
|
548
|
+
}
|
|
549
|
+
return {
|
|
550
|
+
l: oklab.l,
|
|
551
|
+
c,
|
|
552
|
+
h,
|
|
553
|
+
alpha: oklab.alpha,
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
// ============================================================================
|
|
557
|
+
// OKLCH CONVERSIONS
|
|
558
|
+
// ============================================================================
|
|
559
|
+
/**
|
|
560
|
+
* Convert OKLCH to OKLAB
|
|
561
|
+
*/
|
|
562
|
+
export function oklchToOklab(oklch) {
|
|
563
|
+
const h = (oklch.h * Math.PI) / 180;
|
|
564
|
+
const a = oklch.c * Math.cos(h);
|
|
565
|
+
const b = oklch.c * Math.sin(h);
|
|
566
|
+
return {
|
|
567
|
+
l: oklch.l,
|
|
568
|
+
a,
|
|
569
|
+
b,
|
|
570
|
+
alpha: oklch.alpha,
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Convert OKLCH to RGB
|
|
575
|
+
*/
|
|
576
|
+
export function oklchToRgb(oklch) {
|
|
577
|
+
const oklab = oklchToOklab(oklch);
|
|
578
|
+
return oklabToRgb(oklab);
|
|
579
|
+
}
|
|
580
|
+
// ============================================================================
|
|
581
|
+
// UNIVERSAL CONVERTER
|
|
582
|
+
// ============================================================================
|
|
583
|
+
/**
|
|
584
|
+
* Convert any color to RGB
|
|
585
|
+
*/
|
|
586
|
+
export function anyToRgb(color) {
|
|
587
|
+
// Check which color space we have based on properties
|
|
588
|
+
if ('r' in color && 'g' in color && 'b' in color) {
|
|
589
|
+
return color;
|
|
590
|
+
}
|
|
591
|
+
if ('h' in color && 's' in color && 'l' in color) {
|
|
592
|
+
return hslToRgb(color);
|
|
593
|
+
}
|
|
594
|
+
if ('h' in color && 's' in color && 'v' in color) {
|
|
595
|
+
return hsvToRgb(color);
|
|
596
|
+
}
|
|
597
|
+
if ('h' in color && 'w' in color && 'b' in color) {
|
|
598
|
+
return hwbToRgb(color);
|
|
599
|
+
}
|
|
600
|
+
if ('c' in color && 'm' in color && 'y' in color && 'k' in color) {
|
|
601
|
+
return cmykToRgb(color);
|
|
602
|
+
}
|
|
603
|
+
if ('x' in color && 'y' in color && 'z' in color) {
|
|
604
|
+
return xyzToRgb(color);
|
|
605
|
+
}
|
|
606
|
+
if ('l' in color &&
|
|
607
|
+
'a' in color &&
|
|
608
|
+
'b' in color &&
|
|
609
|
+
!('c' in color) &&
|
|
610
|
+
!('h' in color)) {
|
|
611
|
+
return labToRgb(color);
|
|
612
|
+
}
|
|
613
|
+
if ('l' in color && 'c' in color && 'h' in color) {
|
|
614
|
+
// Could be LCH or OKLCH - we'll treat as LCH by default
|
|
615
|
+
// For better detection, check if values are in OKLCH range
|
|
616
|
+
const lchColor = color;
|
|
617
|
+
if (lchColor.l <= 1) {
|
|
618
|
+
// Likely OKLCH (0-1 range)
|
|
619
|
+
return oklchToRgb(color);
|
|
620
|
+
}
|
|
621
|
+
return lchToRgb(lchColor);
|
|
622
|
+
}
|
|
623
|
+
throw new Error('Unknown color format');
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Generic conversion function
|
|
627
|
+
*/
|
|
628
|
+
export function convertColor(color, targetFormat, options = {}) {
|
|
629
|
+
const { round = true, precision = 2, preserveAlpha = true } = options;
|
|
630
|
+
// First convert to RGB as intermediate format
|
|
631
|
+
const rgb = anyToRgb(color);
|
|
632
|
+
let result;
|
|
633
|
+
switch (targetFormat.toLowerCase()) {
|
|
634
|
+
case 'rgb':
|
|
635
|
+
result = rgb;
|
|
636
|
+
break;
|
|
637
|
+
case 'hsl':
|
|
638
|
+
result = rgbToHsl(rgb);
|
|
639
|
+
break;
|
|
640
|
+
case 'hsv':
|
|
641
|
+
result = rgbToHsv(rgb);
|
|
642
|
+
break;
|
|
643
|
+
case 'hwb':
|
|
644
|
+
result = rgbToHwb(rgb);
|
|
645
|
+
break;
|
|
646
|
+
case 'cmyk':
|
|
647
|
+
result = rgbToCmyk(rgb);
|
|
648
|
+
break;
|
|
649
|
+
case 'xyz':
|
|
650
|
+
result = rgbToXyz(rgb);
|
|
651
|
+
break;
|
|
652
|
+
case 'lab':
|
|
653
|
+
result = rgbToLab(rgb);
|
|
654
|
+
break;
|
|
655
|
+
case 'lch':
|
|
656
|
+
result = rgbToLch(rgb);
|
|
657
|
+
break;
|
|
658
|
+
case 'oklab':
|
|
659
|
+
result = rgbToOklab(rgb);
|
|
660
|
+
break;
|
|
661
|
+
case 'oklch':
|
|
662
|
+
result = rgbToOklch(rgb);
|
|
663
|
+
break;
|
|
664
|
+
default:
|
|
665
|
+
result = rgb;
|
|
666
|
+
}
|
|
667
|
+
// Apply rounding if requested
|
|
668
|
+
if (round && result) {
|
|
669
|
+
Object.keys(result).forEach((key) => {
|
|
670
|
+
if (typeof result[key] === 'number' && key !== 'a' && key !== 'alpha') {
|
|
671
|
+
result[key] = roundToPrecision(result[key], precision);
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
// Handle alpha channel
|
|
676
|
+
if (!preserveAlpha) {
|
|
677
|
+
delete result.a;
|
|
678
|
+
delete result.alpha;
|
|
679
|
+
}
|
|
680
|
+
return result;
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Batch convert multiple colors
|
|
684
|
+
*/
|
|
685
|
+
export function batchConvert(colors, targetFormat, options = {}) {
|
|
686
|
+
return colors.map((color) => convertColor(color, targetFormat, options));
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Get conversion path between two formats
|
|
690
|
+
*/
|
|
691
|
+
export function getConversionPath(from, to) {
|
|
692
|
+
// Direct conversions
|
|
693
|
+
const directConversions = {
|
|
694
|
+
rgb: ['hsl', 'hsv', 'hwb', 'cmyk', 'xyz', 'lab', 'lch', 'oklab', 'oklch'],
|
|
695
|
+
hsl: ['rgb', 'hsv', 'hwb'],
|
|
696
|
+
hsv: ['rgb', 'hsl', 'hwb'],
|
|
697
|
+
hwb: ['rgb', 'hsl', 'hsv'],
|
|
698
|
+
cmyk: ['rgb', 'hsl', 'hsv'],
|
|
699
|
+
xyz: ['rgb', 'lab'],
|
|
700
|
+
lab: ['rgb', 'xyz', 'lch'],
|
|
701
|
+
lch: ['rgb', 'lab', 'xyz'],
|
|
702
|
+
oklab: ['rgb', 'oklch'],
|
|
703
|
+
oklch: ['rgb', 'oklab'],
|
|
704
|
+
};
|
|
705
|
+
from = from.toLowerCase();
|
|
706
|
+
to = to.toLowerCase();
|
|
707
|
+
if (from === to) {
|
|
708
|
+
return [from];
|
|
709
|
+
}
|
|
710
|
+
// Check for direct conversion
|
|
711
|
+
if (directConversions[from]?.includes(to)) {
|
|
712
|
+
return [from, to];
|
|
713
|
+
}
|
|
714
|
+
// Use RGB as intermediate (most common case)
|
|
715
|
+
if (directConversions[from]?.includes('rgb') &&
|
|
716
|
+
directConversions['rgb']?.includes(to)) {
|
|
717
|
+
return [from, 'rgb', to];
|
|
718
|
+
}
|
|
719
|
+
// Use XYZ as intermediate for LAB/LCH conversions
|
|
720
|
+
if (['lab', 'lch'].includes(from) &&
|
|
721
|
+
['lab', 'lch'].includes(to) &&
|
|
722
|
+
from !== to) {
|
|
723
|
+
return [from, 'xyz', to];
|
|
724
|
+
}
|
|
725
|
+
// Use OKLAB as intermediate for OKLCH
|
|
726
|
+
if (['oklab', 'oklch'].includes(from) &&
|
|
727
|
+
['oklab', 'oklch'].includes(to) &&
|
|
728
|
+
from !== to) {
|
|
729
|
+
return [from, 'oklab', to];
|
|
730
|
+
}
|
|
731
|
+
// Complex path through RGB
|
|
732
|
+
if (directConversions[from] && directConversions['rgb']?.includes(to)) {
|
|
733
|
+
return [from, 'rgb', to];
|
|
734
|
+
}
|
|
735
|
+
return null;
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* Check if direct conversion exists between two formats
|
|
739
|
+
*/
|
|
740
|
+
export function hasDirectConversion(from, to) {
|
|
741
|
+
const path = getConversionPath(from, to);
|
|
742
|
+
return path !== null && path.length <= 2;
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* Get all supported color formats
|
|
746
|
+
*/
|
|
747
|
+
export function getSupportedFormats() {
|
|
748
|
+
return [
|
|
749
|
+
'rgb',
|
|
750
|
+
'hsl',
|
|
751
|
+
'hsv',
|
|
752
|
+
'hwb',
|
|
753
|
+
'cmyk',
|
|
754
|
+
'xyz',
|
|
755
|
+
'lab',
|
|
756
|
+
'lch',
|
|
757
|
+
'oklab',
|
|
758
|
+
'oklch',
|
|
759
|
+
];
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Validate color format
|
|
763
|
+
*/
|
|
764
|
+
export function isValidFormat(format) {
|
|
765
|
+
return getSupportedFormats().includes(format.toLowerCase());
|
|
766
|
+
}
|