@soybeanjs/colord 0.0.1
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 +58 -0
- package/dist/colord-BV1k1-gC.js +239 -0
- package/dist/colord-xpgrVWRV.d.ts +167 -0
- package/dist/colord.d.ts +2 -0
- package/dist/colord.js +10 -0
- package/dist/extend-DrPfn2Q1.d.ts +7 -0
- package/dist/get-BFaklfVd.js +92 -0
- package/dist/hsv-UWMaaOSN.js +78 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +22 -0
- package/dist/lab-CJHLdqfe.js +128 -0
- package/dist/manipulate-CeAgrUd6.js +119 -0
- package/dist/plugins/a11y.d.ts +41 -0
- package/dist/plugins/a11y.js +35 -0
- package/dist/plugins/cmyk.d.ts +27 -0
- package/dist/plugins/cmyk.js +121 -0
- package/dist/plugins/harmonies.d.ts +19 -0
- package/dist/plugins/harmonies.js +54 -0
- package/dist/plugins/hwb.d.ts +26 -0
- package/dist/plugins/hwb.js +92 -0
- package/dist/plugins/lab.d.ts +26 -0
- package/dist/plugins/lab.js +26 -0
- package/dist/plugins/lch.d.ts +27 -0
- package/dist/plugins/lch.js +122 -0
- package/dist/plugins/minify.d.ts +23 -0
- package/dist/plugins/minify.js +61 -0
- package/dist/plugins/mix.d.ts +30 -0
- package/dist/plugins/mix.js +39 -0
- package/dist/plugins/names.d.ts +22 -0
- package/dist/plugins/names.js +201 -0
- package/dist/plugins/oklab.d.ts +16 -0
- package/dist/plugins/oklab.js +103 -0
- package/dist/plugins/oklch.d.ts +16 -0
- package/dist/plugins/oklch.js +112 -0
- package/dist/plugins/xyz.d.ts +17 -0
- package/dist/plugins/xyz.js +20 -0
- package/dist/rgb-CfVJB1Bj.js +148 -0
- package/dist/utils-BgIyY6bK.js +229 -0
- package/dist/xyz-MII3ndWO.js +73 -0
- package/package.json +81 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { _ as ALPHA_PRECISION, a as mul3x3, c as round, i as isPresent, l as M_D50_TO_D65, o as parseAlpha, t as clamp, u as M_D65_TO_D50, v as D50 } from "./utils-BgIyY6bK.js";
|
|
2
|
+
import { i as xyzToRgb, n as rgbToXyz } from "./xyz-MII3ndWO.js";
|
|
3
|
+
|
|
4
|
+
//#region src/models/lab.ts
|
|
5
|
+
const EPSILON = 216 / 24389;
|
|
6
|
+
const KAPPA = 24389 / 27;
|
|
7
|
+
/**
|
|
8
|
+
* Clamps LAB axis values as defined in CSS Color Level 4 specs.
|
|
9
|
+
* https://www.w3.org/TR/css-color-4/#specifying-lab-lch
|
|
10
|
+
*/
|
|
11
|
+
const clampLab = (lab) => {
|
|
12
|
+
const { l, a, b, alpha } = lab;
|
|
13
|
+
return {
|
|
14
|
+
l: clamp(l, 0, 100),
|
|
15
|
+
a: clamp(a, -128, 127),
|
|
16
|
+
b: clamp(b, -128, 127),
|
|
17
|
+
alpha: clamp(alpha)
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
const roundLab = (lab) => {
|
|
21
|
+
const { l, a, b, alpha } = lab;
|
|
22
|
+
return {
|
|
23
|
+
l: round(l, 3),
|
|
24
|
+
a: round(a, 3),
|
|
25
|
+
b: round(b, 3),
|
|
26
|
+
alpha: round(alpha, ALPHA_PRECISION)
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Performs RGB → CIEXYZ → LAB color conversion
|
|
31
|
+
* https://www.w3.org/TR/css-color-4/#color-conversion-code
|
|
32
|
+
*/
|
|
33
|
+
const rgbToLab = (rgb) => {
|
|
34
|
+
const xyzD65 = rgbToXyz(rgb);
|
|
35
|
+
const { alpha } = xyzD65;
|
|
36
|
+
const [x, y, z] = mul3x3(M_D65_TO_D50, [
|
|
37
|
+
xyzD65.x,
|
|
38
|
+
xyzD65.y,
|
|
39
|
+
xyzD65.z
|
|
40
|
+
]);
|
|
41
|
+
return xyzToLabRaw({
|
|
42
|
+
x,
|
|
43
|
+
y,
|
|
44
|
+
z,
|
|
45
|
+
alpha
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Performs LAB → CIEXYZ → RGB color conversion
|
|
50
|
+
* https://www.w3.org/TR/css-color-4/#color-conversion-code
|
|
51
|
+
*/
|
|
52
|
+
const labToRgb = (lab) => {
|
|
53
|
+
const xyzD50 = labToXyzRaw(lab);
|
|
54
|
+
const [x, y, z] = mul3x3(M_D50_TO_D65, [
|
|
55
|
+
xyzD50.x,
|
|
56
|
+
xyzD50.y,
|
|
57
|
+
xyzD50.z
|
|
58
|
+
]);
|
|
59
|
+
return xyzToRgb({
|
|
60
|
+
x,
|
|
61
|
+
y,
|
|
62
|
+
z,
|
|
63
|
+
alpha: lab.alpha
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
function xyzToLabRaw(xyz) {
|
|
67
|
+
const { x, y, z, alpha } = xyz;
|
|
68
|
+
const xr = x / D50.x;
|
|
69
|
+
const yr = y / D50.y;
|
|
70
|
+
const zr = z / D50.z;
|
|
71
|
+
const f = (t) => t > EPSILON ? Math.cbrt(t) : (KAPPA * t + 16) / 116;
|
|
72
|
+
const fx = f(xr);
|
|
73
|
+
const fy = f(yr);
|
|
74
|
+
const fz = f(zr);
|
|
75
|
+
return {
|
|
76
|
+
l: 116 * fy - 16,
|
|
77
|
+
a: 500 * (fx - fy),
|
|
78
|
+
b: 200 * (fy - fz),
|
|
79
|
+
alpha
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function labToXyzRaw(lab) {
|
|
83
|
+
const { l, a, b, alpha } = lab;
|
|
84
|
+
const fy = (l + 16) / 116;
|
|
85
|
+
const fx = a / 500 + fy;
|
|
86
|
+
const fz = fy - b / 200;
|
|
87
|
+
const f3 = (t) => t * t * t > EPSILON ? t * t * t : (116 * t - 16) / KAPPA;
|
|
88
|
+
const xr = f3(fx);
|
|
89
|
+
const yr = l > KAPPA * EPSILON ? ((l + 16) / 116) ** 3 : l / KAPPA;
|
|
90
|
+
const zr = f3(fz);
|
|
91
|
+
return {
|
|
92
|
+
x: xr * D50.x,
|
|
93
|
+
y: yr * D50.y,
|
|
94
|
+
z: zr * D50.z,
|
|
95
|
+
alpha
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const parseLab = ({ l, a, b, alpha = 1 }) => {
|
|
99
|
+
if (!isPresent(l) || !isPresent(a) || !isPresent(b)) return null;
|
|
100
|
+
return labToRgb(clampLab({
|
|
101
|
+
l: Number(l),
|
|
102
|
+
a: Number(a),
|
|
103
|
+
b: Number(b),
|
|
104
|
+
alpha: Number(alpha)
|
|
105
|
+
}));
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* Parsing syntax: oklab(L a b [/ alpha])
|
|
109
|
+
* - L: <number|percentage> [0,100]
|
|
110
|
+
* - a: <number> [-125,125]
|
|
111
|
+
* - b: <number> [-125,125]
|
|
112
|
+
* - alpha: <number|percentage> [0,1]
|
|
113
|
+
*/
|
|
114
|
+
const labMatcher = /^lab\(\s*([+-]?[\d.]+)%?\s+([+-]?[\d.]+)\s+([+-]?[\d.]+)(?:\s*\/\s*([+-]?[\d.]+%?))?\s*\)$/i;
|
|
115
|
+
const parseLabString = (input) => {
|
|
116
|
+
const match = labMatcher.exec(input);
|
|
117
|
+
if (!match) return null;
|
|
118
|
+
const [_, l, a, b, alpha] = match;
|
|
119
|
+
return labToRgb(clampLab({
|
|
120
|
+
l: Number.parseFloat(l),
|
|
121
|
+
a: Number.parseFloat(a),
|
|
122
|
+
b: Number.parseFloat(b),
|
|
123
|
+
alpha: parseAlpha(alpha)
|
|
124
|
+
}));
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
//#endregion
|
|
128
|
+
export { rgbToLab as a, parseLabString as i, labToRgb as n, roundLab as o, parseLab as r, clampLab as t };
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { _ as ALPHA_PRECISION, c as round, i as isPresent, n as clampHue, o as parseAlpha, s as parseHue, t as clamp } from "./utils-BgIyY6bK.js";
|
|
2
|
+
import { r as rgbToHsv, t as hsvToRgb } from "./hsv-UWMaaOSN.js";
|
|
3
|
+
import { a as rgbToLab, n as labToRgb, t as clampLab } from "./lab-CJHLdqfe.js";
|
|
4
|
+
|
|
5
|
+
//#region src/models/hsl.ts
|
|
6
|
+
const clampHsl = (hsl) => {
|
|
7
|
+
const { h, s, l, alpha } = hsl;
|
|
8
|
+
return {
|
|
9
|
+
h: clampHue(h),
|
|
10
|
+
s: clamp(s, 0, 100),
|
|
11
|
+
l: clamp(l, 0, 100),
|
|
12
|
+
alpha: clamp(alpha)
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
const roundHsl = (hsl) => {
|
|
16
|
+
const { h, s, l, alpha } = hsl;
|
|
17
|
+
return {
|
|
18
|
+
h: round(h, 3),
|
|
19
|
+
s: round(s, 3),
|
|
20
|
+
l: round(l, 3),
|
|
21
|
+
alpha: round(alpha, ALPHA_PRECISION)
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
const hslToHsv = (hsl) => {
|
|
25
|
+
const { h, l, alpha } = hsl;
|
|
26
|
+
const s = hsl.s * (l < 50 ? l : 100 - l) / 100;
|
|
27
|
+
return {
|
|
28
|
+
h,
|
|
29
|
+
s: s > 0 ? 2 * s / (l + s) * 100 : 0,
|
|
30
|
+
v: l + s,
|
|
31
|
+
alpha
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
const hsvToHsl = ({ h, s, v, alpha }) => {
|
|
35
|
+
const hh = (200 - s) * v / 100;
|
|
36
|
+
return {
|
|
37
|
+
h,
|
|
38
|
+
s: hh > 0 && hh < 200 ? s * v / 100 / (hh <= 100 ? hh : 200 - hh) * 100 : 0,
|
|
39
|
+
l: hh / 2,
|
|
40
|
+
alpha
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
const hslToRgb = (hsl) => {
|
|
44
|
+
return hsvToRgb(hslToHsv(hsl));
|
|
45
|
+
};
|
|
46
|
+
const rgbToHsl = (rgb) => {
|
|
47
|
+
return hsvToHsl(rgbToHsv(rgb));
|
|
48
|
+
};
|
|
49
|
+
const parseHsl = ({ h, s, l, alpha = 1 }) => {
|
|
50
|
+
if (!isPresent(h) || !isPresent(s) || !isPresent(l)) return null;
|
|
51
|
+
return hslToRgb(clampHsl({
|
|
52
|
+
h: Number(h),
|
|
53
|
+
s: Number(s),
|
|
54
|
+
l: Number(l),
|
|
55
|
+
alpha: Number(alpha)
|
|
56
|
+
}));
|
|
57
|
+
};
|
|
58
|
+
const rgbToHslString = (rgb) => {
|
|
59
|
+
const { h, s, l, alpha } = roundHsl(rgbToHsl(rgb));
|
|
60
|
+
return alpha < 1 ? `hsl(${h}, ${s}%, ${l}%, ${alpha})` : `hsl(${h}, ${s}%, ${l}%)`;
|
|
61
|
+
};
|
|
62
|
+
const hslMatcher = /^hsl?\(\s*([+-]?[\d.]+)(deg|grad|rad|turn)?\s*[, ]\s*([+-]?[\d.]+)%\s*[, ]\s*([+-]?[\d.]+)%(?:\s*\/\s*([+-]?[\d.]+%?))?\s*\)$/i;
|
|
63
|
+
const parseHslString = (input) => {
|
|
64
|
+
const match = hslMatcher.exec(input);
|
|
65
|
+
if (!match) return null;
|
|
66
|
+
const [, h, unit, s, l, alpha] = match;
|
|
67
|
+
return hslToRgb(clampHsl({
|
|
68
|
+
h: parseHue(h, unit),
|
|
69
|
+
s: Number.parseFloat(s),
|
|
70
|
+
l: Number.parseFloat(l),
|
|
71
|
+
alpha: parseAlpha(alpha)
|
|
72
|
+
}));
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
//#endregion
|
|
76
|
+
//#region src/shared/manipulate.ts
|
|
77
|
+
const changeAlpha = (rgb, alpha) => ({
|
|
78
|
+
r: rgb.r,
|
|
79
|
+
g: rgb.g,
|
|
80
|
+
b: rgb.b,
|
|
81
|
+
alpha
|
|
82
|
+
});
|
|
83
|
+
const invert = (rgb) => ({
|
|
84
|
+
r: 255 - rgb.r,
|
|
85
|
+
g: 255 - rgb.g,
|
|
86
|
+
b: 255 - rgb.b,
|
|
87
|
+
alpha: rgb.alpha
|
|
88
|
+
});
|
|
89
|
+
const lighten = (rgb, amount) => {
|
|
90
|
+
const hsl = rgbToHsl(rgb);
|
|
91
|
+
return {
|
|
92
|
+
h: hsl.h,
|
|
93
|
+
s: hsl.s,
|
|
94
|
+
l: clamp(hsl.l + amount * 100, 0, 100),
|
|
95
|
+
alpha: hsl.alpha
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
const mix = (rgb1, rgb2, ratio) => {
|
|
99
|
+
const lab1 = rgbToLab(rgb1);
|
|
100
|
+
const lab2 = rgbToLab(rgb2);
|
|
101
|
+
return labToRgb(clampLab({
|
|
102
|
+
l: lab1.l * (1 - ratio) + lab2.l * ratio,
|
|
103
|
+
a: lab1.a * (1 - ratio) + lab2.a * ratio,
|
|
104
|
+
b: lab1.b * (1 - ratio) + lab2.b * ratio,
|
|
105
|
+
alpha: lab1.alpha * (1 - ratio) + lab2.alpha * ratio
|
|
106
|
+
}));
|
|
107
|
+
};
|
|
108
|
+
const saturate = (rgb, amount) => {
|
|
109
|
+
const { h, s, l, alpha } = rgbToHsl(rgb);
|
|
110
|
+
return {
|
|
111
|
+
h,
|
|
112
|
+
s: clamp(s + amount * 100, 0, 100),
|
|
113
|
+
l,
|
|
114
|
+
alpha
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
//#endregion
|
|
119
|
+
export { saturate as a, rgbToHsl as c, mix as i, rgbToHslString as l, invert as n, parseHsl as o, lighten as r, parseHslString as s, changeAlpha as t, roundHsl as u };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { r as AnyColor } from "../colord-xpgrVWRV.js";
|
|
2
|
+
import { t as Plugin } from "../extend-DrPfn2Q1.js";
|
|
3
|
+
|
|
4
|
+
//#region src/plugins/a11y.d.ts
|
|
5
|
+
interface ReadabilityOptions {
|
|
6
|
+
level?: 'AA' | 'AAA';
|
|
7
|
+
size?: 'normal' | 'large';
|
|
8
|
+
}
|
|
9
|
+
declare module '../colord' {
|
|
10
|
+
interface Colord {
|
|
11
|
+
/**
|
|
12
|
+
* Returns the relative luminance of a color,
|
|
13
|
+
* normalized to 0 for darkest black and 1 for lightest white.
|
|
14
|
+
* https://www.w3.org/TR/WCAG20/#relativeluminancedef
|
|
15
|
+
* https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_Colors_and_Luminance
|
|
16
|
+
*/
|
|
17
|
+
luminance(): number;
|
|
18
|
+
/**
|
|
19
|
+
* Calculates a contrast ratio for a color pair.
|
|
20
|
+
* This luminance difference is expressed as a ratio ranging
|
|
21
|
+
* from 1 (e.g. white on white) to 21 (e.g., black on a white).
|
|
22
|
+
* WCAG requires a ratio of at least 4.5 for normal text and 3 for large text.
|
|
23
|
+
* https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html
|
|
24
|
+
* https://webaim.org/articles/contrast/
|
|
25
|
+
*/
|
|
26
|
+
contrast(color2?: AnyColor | Colord): number;
|
|
27
|
+
/**
|
|
28
|
+
* Checks that a background and text color pair conforms to WCAG 2.0 requirements.
|
|
29
|
+
* https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html
|
|
30
|
+
*/
|
|
31
|
+
isReadable(color2?: AnyColor | Colord, options?: ReadabilityOptions): boolean;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A plugin adding accessibility and color contrast utilities.
|
|
36
|
+
* Follows Web Content Accessibility Guidelines 2.0.
|
|
37
|
+
* https://www.w3.org/TR/WCAG20/
|
|
38
|
+
*/
|
|
39
|
+
declare const a11yPlugin: Plugin;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { a11yPlugin, a11yPlugin as default };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { c as round, r as floor } from "../utils-BgIyY6bK.js";
|
|
2
|
+
import "../rgb-CfVJB1Bj.js";
|
|
3
|
+
import { i as getLuminance, n as getContrast } from "../get-BFaklfVd.js";
|
|
4
|
+
|
|
5
|
+
//#region src/plugins/a11y.ts
|
|
6
|
+
/**
|
|
7
|
+
* A plugin adding accessibility and color contrast utilities.
|
|
8
|
+
* Follows Web Content Accessibility Guidelines 2.0.
|
|
9
|
+
* https://www.w3.org/TR/WCAG20/
|
|
10
|
+
*/
|
|
11
|
+
const a11yPlugin = (ColordClass) => {
|
|
12
|
+
/**
|
|
13
|
+
* Returns WCAG text color contrast requirement.
|
|
14
|
+
* Read explanation here https://webaim.org/resources/contrastchecker/
|
|
15
|
+
*/
|
|
16
|
+
const getMinimalContrast = ({ level = "AA", size = "normal" }) => {
|
|
17
|
+
if (level === "AAA" && size === "normal") return 7;
|
|
18
|
+
if (level === "AA" && size === "large") return 3;
|
|
19
|
+
return 4.5;
|
|
20
|
+
};
|
|
21
|
+
ColordClass.prototype.luminance = function luminance() {
|
|
22
|
+
return round(getLuminance(this.rgb), 2);
|
|
23
|
+
};
|
|
24
|
+
ColordClass.prototype.contrast = function contrast(color2 = "#FFF") {
|
|
25
|
+
const instance2 = color2 instanceof ColordClass ? color2 : new ColordClass(color2);
|
|
26
|
+
return floor(getContrast(this.rgb, instance2.toRgb()), 2);
|
|
27
|
+
};
|
|
28
|
+
ColordClass.prototype.isReadable = function isReadable(color2 = "#FFF", options = {}) {
|
|
29
|
+
return this.contrast(color2) >= getMinimalContrast(options);
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
var a11y_default = a11yPlugin;
|
|
33
|
+
|
|
34
|
+
//#endregion
|
|
35
|
+
export { a11yPlugin, a11y_default as default };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { i as CmykColor } from "../colord-xpgrVWRV.js";
|
|
2
|
+
import { t as Plugin } from "../extend-DrPfn2Q1.js";
|
|
3
|
+
|
|
4
|
+
//#region src/plugins/cmyk.d.ts
|
|
5
|
+
declare module '../colord' {
|
|
6
|
+
interface Colord {
|
|
7
|
+
/**
|
|
8
|
+
* Converts a color to CMYK color space and returns an object.
|
|
9
|
+
* https://drafts.csswg.org/css-color/#cmyk-colors
|
|
10
|
+
* https://lea.verou.me/2009/03/cmyk-colors-in-css-useful-or-useless/
|
|
11
|
+
*/
|
|
12
|
+
toCmyk(): CmykColor;
|
|
13
|
+
/**
|
|
14
|
+
* Converts a color to CMYK color space and returns a string.
|
|
15
|
+
* https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/device-cmyk()
|
|
16
|
+
*/
|
|
17
|
+
toCmykString(): string;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A plugin adding support for CMYK color space.
|
|
22
|
+
* https://lea.verou.me/2009/03/cmyk-colors-in-css-useful-or-useless/
|
|
23
|
+
* https://en.wikipedia.org/wiki/CMYK_color_model
|
|
24
|
+
*/
|
|
25
|
+
declare const cmykPlugin: Plugin;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { cmykPlugin, cmykPlugin as default };
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { _ as ALPHA_PRECISION, c as round, i as isPresent, o as parseAlpha, t as clamp } from "../utils-BgIyY6bK.js";
|
|
2
|
+
|
|
3
|
+
//#region src/models/cmyk.ts
|
|
4
|
+
/**
|
|
5
|
+
* Clamps the CMYK color object values.
|
|
6
|
+
*/
|
|
7
|
+
const clampCmyk = (cmyk) => {
|
|
8
|
+
const { c, m, y, k, alpha } = cmyk;
|
|
9
|
+
return {
|
|
10
|
+
c: clamp(c, 0, 100),
|
|
11
|
+
m: clamp(m, 0, 100),
|
|
12
|
+
y: clamp(y, 0, 100),
|
|
13
|
+
k: clamp(k, 0, 100),
|
|
14
|
+
alpha: clamp(alpha)
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Rounds the CMYK color object values.
|
|
19
|
+
*/
|
|
20
|
+
const roundCmyk = (cmyk) => {
|
|
21
|
+
const { c, m, y, k, alpha } = cmyk;
|
|
22
|
+
return {
|
|
23
|
+
c: round(c, 2),
|
|
24
|
+
m: round(m, 2),
|
|
25
|
+
y: round(y, 2),
|
|
26
|
+
k: round(k, 2),
|
|
27
|
+
alpha: round(alpha, ALPHA_PRECISION)
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Transforms the CMYK color object to RGB.
|
|
32
|
+
* https://www.rapidtables.com/convert/color/cmyk-to-rgb.html
|
|
33
|
+
*/
|
|
34
|
+
function cmykToRgb(cmyk) {
|
|
35
|
+
const { c, m, y, k, alpha } = cmyk;
|
|
36
|
+
return {
|
|
37
|
+
r: round(255 * (1 - c / 100) * (1 - k / 100)),
|
|
38
|
+
g: round(255 * (1 - m / 100) * (1 - k / 100)),
|
|
39
|
+
b: round(255 * (1 - y / 100) * (1 - k / 100)),
|
|
40
|
+
alpha
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Convert RGB Color Model object to CMYK.
|
|
45
|
+
* https://www.rapidtables.com/convert/color/rgb-to-cmyk.html
|
|
46
|
+
*/
|
|
47
|
+
function rgbToCmyk(rgb) {
|
|
48
|
+
const { r, g, b, alpha } = rgb;
|
|
49
|
+
const k = 1 - Math.max(r / 255, g / 255, b / 255);
|
|
50
|
+
const c = (1 - r / 255 - k) / (1 - k);
|
|
51
|
+
const m = (1 - g / 255 - k) / (1 - k);
|
|
52
|
+
const y = (1 - b / 255 - k) / (1 - k);
|
|
53
|
+
return {
|
|
54
|
+
c: Number.isNaN(c) ? 0 : round(c * 100),
|
|
55
|
+
m: Number.isNaN(m) ? 0 : round(m * 100),
|
|
56
|
+
y: Number.isNaN(y) ? 0 : round(y * 100),
|
|
57
|
+
k: round(k * 100),
|
|
58
|
+
alpha
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Parses the CMYK color object into RGB.
|
|
63
|
+
*/
|
|
64
|
+
function parseCmyk({ c, m, y, k, alpha = 1 }) {
|
|
65
|
+
if (!isPresent(c) || !isPresent(m) || !isPresent(y) || !isPresent(k)) return null;
|
|
66
|
+
return cmykToRgb(clampCmyk({
|
|
67
|
+
c: Number(c),
|
|
68
|
+
m: Number(m),
|
|
69
|
+
y: Number(y),
|
|
70
|
+
k: Number(k),
|
|
71
|
+
alpha: Number(alpha)
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
const cmykMatcher = /^device-cmyk\(\s*([\d.]+%?)\s*[, ]\s*([\d.]+%?)\s*[, ]\s*([\d.]+%?)\s*[, ]\s*([\d.]+%?)(?:\s*\/\s*([\d.]+%?))?\s*\)$/i;
|
|
75
|
+
/**
|
|
76
|
+
* Parses a valid CMYK CSS color function/string
|
|
77
|
+
* https://www.w3.org/TR/css-color-4/#device-cmyk
|
|
78
|
+
*/
|
|
79
|
+
const parseCmykString = (input) => {
|
|
80
|
+
const match = cmykMatcher.exec(input);
|
|
81
|
+
if (!match) return null;
|
|
82
|
+
const [, c, m, y, k, al] = match;
|
|
83
|
+
return cmykToRgb(clampCmyk({
|
|
84
|
+
c: parseValue(c),
|
|
85
|
+
m: parseValue(m),
|
|
86
|
+
y: parseValue(y),
|
|
87
|
+
k: parseValue(k),
|
|
88
|
+
alpha: al ? parseAlpha(al) : 1
|
|
89
|
+
}));
|
|
90
|
+
};
|
|
91
|
+
function parseValue(str) {
|
|
92
|
+
const isPercent = str.endsWith("%");
|
|
93
|
+
const num = Number.parseFloat(isPercent ? str.slice(0, -1) : str);
|
|
94
|
+
return isPercent ? num : num * 100;
|
|
95
|
+
}
|
|
96
|
+
function rgbToCmykString(rgb) {
|
|
97
|
+
const { c, m, y, k, alpha } = roundCmyk(rgbToCmyk(rgb));
|
|
98
|
+
return alpha < 1 ? `device-cmyk(${c}% ${m}% ${y}% ${k}% / ${alpha})` : `device-cmyk(${c}% ${m}% ${y}% ${k}%)`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
//#endregion
|
|
102
|
+
//#region src/plugins/cmyk.ts
|
|
103
|
+
/**
|
|
104
|
+
* A plugin adding support for CMYK color space.
|
|
105
|
+
* https://lea.verou.me/2009/03/cmyk-colors-in-css-useful-or-useless/
|
|
106
|
+
* https://en.wikipedia.org/wiki/CMYK_color_model
|
|
107
|
+
*/
|
|
108
|
+
const cmykPlugin = (ColordClass, parsers) => {
|
|
109
|
+
ColordClass.prototype.toCmyk = function toCmyk() {
|
|
110
|
+
return roundCmyk(rgbToCmyk(this.rgb));
|
|
111
|
+
};
|
|
112
|
+
ColordClass.prototype.toCmykString = function toCmykString() {
|
|
113
|
+
return rgbToCmykString(this.rgb);
|
|
114
|
+
};
|
|
115
|
+
parsers.object.push([parseCmyk, "cmyk"]);
|
|
116
|
+
parsers.string.push([parseCmykString, "cmyk"]);
|
|
117
|
+
};
|
|
118
|
+
var cmyk_default = cmykPlugin;
|
|
119
|
+
|
|
120
|
+
//#endregion
|
|
121
|
+
export { cmykPlugin, cmyk_default as default };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { t as Plugin } from "../extend-DrPfn2Q1.js";
|
|
2
|
+
|
|
3
|
+
//#region src/plugins/harmonies.d.ts
|
|
4
|
+
type HarmonyType = 'analogous' | 'complementary' | 'double-split-complementary' | 'rectangle' | 'split-complementary' | 'tetradic' | 'triadic';
|
|
5
|
+
declare module '../colord' {
|
|
6
|
+
interface Colord {
|
|
7
|
+
/**
|
|
8
|
+
* Returns an array of harmony colors as `Colord` instances.
|
|
9
|
+
*/
|
|
10
|
+
harmonies(type?: HarmonyType): Colord[];
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A plugin adding functionality to generate harmony colors.
|
|
15
|
+
* https://en.wikipedia.org/wiki/Harmony_(color)
|
|
16
|
+
*/
|
|
17
|
+
declare const harmoniesPlugin: Plugin;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { HarmonyType, harmoniesPlugin as default, harmoniesPlugin };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
//#region src/plugins/harmonies.ts
|
|
2
|
+
/**
|
|
3
|
+
* A plugin adding functionality to generate harmony colors.
|
|
4
|
+
* https://en.wikipedia.org/wiki/Harmony_(color)
|
|
5
|
+
*/
|
|
6
|
+
const harmoniesPlugin = (ColordClass) => {
|
|
7
|
+
/**
|
|
8
|
+
* Harmony colors are colors with particular hue shift of the original color.
|
|
9
|
+
*/
|
|
10
|
+
const hueShifts = {
|
|
11
|
+
analogous: [
|
|
12
|
+
-30,
|
|
13
|
+
0,
|
|
14
|
+
30
|
|
15
|
+
],
|
|
16
|
+
complementary: [0, 180],
|
|
17
|
+
"double-split-complementary": [
|
|
18
|
+
-30,
|
|
19
|
+
0,
|
|
20
|
+
30,
|
|
21
|
+
150,
|
|
22
|
+
210
|
|
23
|
+
],
|
|
24
|
+
rectangle: [
|
|
25
|
+
0,
|
|
26
|
+
60,
|
|
27
|
+
180,
|
|
28
|
+
240
|
|
29
|
+
],
|
|
30
|
+
tetradic: [
|
|
31
|
+
0,
|
|
32
|
+
90,
|
|
33
|
+
180,
|
|
34
|
+
270
|
|
35
|
+
],
|
|
36
|
+
triadic: [
|
|
37
|
+
0,
|
|
38
|
+
120,
|
|
39
|
+
240
|
|
40
|
+
],
|
|
41
|
+
"split-complementary": [
|
|
42
|
+
0,
|
|
43
|
+
150,
|
|
44
|
+
210
|
|
45
|
+
]
|
|
46
|
+
};
|
|
47
|
+
ColordClass.prototype.harmonies = function harmonies(type = "complementary") {
|
|
48
|
+
return hueShifts[type].map((shift) => this.rotate(shift));
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
var harmonies_default = harmoniesPlugin;
|
|
52
|
+
|
|
53
|
+
//#endregion
|
|
54
|
+
export { harmonies_default as default, harmoniesPlugin };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { c as HwbColor } from "../colord-xpgrVWRV.js";
|
|
2
|
+
import { t as Plugin } from "../extend-DrPfn2Q1.js";
|
|
3
|
+
|
|
4
|
+
//#region src/plugins/hwb.d.ts
|
|
5
|
+
declare module '../colord' {
|
|
6
|
+
interface Colord {
|
|
7
|
+
/**
|
|
8
|
+
* Converts a color to HWB (Hue-Whiteness-Blackness) color space and returns an object.
|
|
9
|
+
* https://en.wikipedia.org/wiki/HWB_color_model
|
|
10
|
+
*/
|
|
11
|
+
toHwb(): HwbColor;
|
|
12
|
+
/**
|
|
13
|
+
* Converts a color to HWB (Hue-Whiteness-Blackness) color space and returns a string.
|
|
14
|
+
* https://www.w3.org/TR/css-color-4/#the-hwb-notation
|
|
15
|
+
*/
|
|
16
|
+
toHwbString(): string;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A plugin adding support for HWB (Hue-Whiteness-Blackness) color model.
|
|
21
|
+
* https://en.wikipedia.org/wiki/HWB_color_model
|
|
22
|
+
* https://www.w3.org/TR/css-color-4/#the-hwb-notation
|
|
23
|
+
*/
|
|
24
|
+
declare const hwbPlugin: Plugin;
|
|
25
|
+
//#endregion
|
|
26
|
+
export { hwbPlugin as default, hwbPlugin };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { _ as ALPHA_PRECISION, c as round, i as isPresent, n as clampHue, o as parseAlpha, s as parseHue, t as clamp } from "../utils-BgIyY6bK.js";
|
|
2
|
+
import { r as rgbToHsv, t as hsvToRgb } from "../hsv-UWMaaOSN.js";
|
|
3
|
+
|
|
4
|
+
//#region src/models/hwb.ts
|
|
5
|
+
const clampHwb = (hwb) => {
|
|
6
|
+
const { h, w, b, alpha } = hwb;
|
|
7
|
+
return {
|
|
8
|
+
h: clampHue(h),
|
|
9
|
+
w: clamp(w, 0, 100),
|
|
10
|
+
b: clamp(b, 0, 100),
|
|
11
|
+
alpha: clamp(alpha)
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
const roundHwb = (hwb) => {
|
|
15
|
+
const { h, w, b, alpha } = hwb;
|
|
16
|
+
return {
|
|
17
|
+
h: round(h, 3),
|
|
18
|
+
w: round(w, 3),
|
|
19
|
+
b: round(b, 3),
|
|
20
|
+
alpha: round(alpha, ALPHA_PRECISION)
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
const rgbToHwb = (rgb) => {
|
|
24
|
+
const { r, g, b: rb, alpha } = rgb;
|
|
25
|
+
const { h } = rgbToHsv(rgb);
|
|
26
|
+
return {
|
|
27
|
+
h,
|
|
28
|
+
w: Math.min(r, g, rb) / 255 * 100,
|
|
29
|
+
b: 100 - Math.max(r, g, rb) / 255 * 100,
|
|
30
|
+
alpha
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
const hwbToRgb = (hwb) => {
|
|
34
|
+
const { h, w, b, alpha } = hwb;
|
|
35
|
+
return hsvToRgb({
|
|
36
|
+
h,
|
|
37
|
+
s: b === 100 ? 0 : 100 - w / (100 - b) * 100,
|
|
38
|
+
v: 100 - b,
|
|
39
|
+
alpha
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
const parseHwb = ({ h, w, b, alpha = 1 }) => {
|
|
43
|
+
if (!isPresent(h) || !isPresent(w) || !isPresent(b)) return null;
|
|
44
|
+
return hwbToRgb(clampHwb({
|
|
45
|
+
h: Number(h),
|
|
46
|
+
w: Number(w),
|
|
47
|
+
b: Number(b),
|
|
48
|
+
alpha: Number(alpha)
|
|
49
|
+
}));
|
|
50
|
+
};
|
|
51
|
+
const hwbaMatcher = /^hwb\(\s*([+-]?[\d.]+)(deg|grad|rad|turn)?\s*[, ]\s*([+-]?[\d.]+)%\s*[, ]\s*([+-]?[\d.]+)%(?:\s*\/\s*([+-]?[\d.]+%?))?\s*\)$/i;
|
|
52
|
+
/**
|
|
53
|
+
* Parses a valid HWB[A] CSS color function/string
|
|
54
|
+
* https://www.w3.org/TR/css-color-4/#the-hwb-notation
|
|
55
|
+
*/
|
|
56
|
+
const parseHwbString = (input) => {
|
|
57
|
+
const match = hwbaMatcher.exec(input);
|
|
58
|
+
if (!match) return null;
|
|
59
|
+
const [, h, unit, w, b, alpha] = match;
|
|
60
|
+
return hwbToRgb(clampHwb({
|
|
61
|
+
h: parseHue(h, unit),
|
|
62
|
+
w: Number.parseFloat(w),
|
|
63
|
+
b: Number.parseFloat(b),
|
|
64
|
+
alpha: parseAlpha(alpha)
|
|
65
|
+
}));
|
|
66
|
+
};
|
|
67
|
+
const rgbToHwbString = (rgb) => {
|
|
68
|
+
const { h, w, b, alpha } = roundHwb(rgbToHwb(rgb));
|
|
69
|
+
return alpha < 1 ? `hwb(${h} ${w}% ${b}% / ${alpha})` : `hwb(${h} ${w}% ${b}%)`;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region src/plugins/hwb.ts
|
|
74
|
+
/**
|
|
75
|
+
* A plugin adding support for HWB (Hue-Whiteness-Blackness) color model.
|
|
76
|
+
* https://en.wikipedia.org/wiki/HWB_color_model
|
|
77
|
+
* https://www.w3.org/TR/css-color-4/#the-hwb-notation
|
|
78
|
+
*/
|
|
79
|
+
const hwbPlugin = (ColordClass, parsers) => {
|
|
80
|
+
ColordClass.prototype.toHwb = function toHwb() {
|
|
81
|
+
return roundHwb(rgbToHwb(this.rgb));
|
|
82
|
+
};
|
|
83
|
+
ColordClass.prototype.toHwbString = function toHwbString() {
|
|
84
|
+
return rgbToHwbString(this.rgb);
|
|
85
|
+
};
|
|
86
|
+
parsers.string.push([parseHwbString, "hwb"]);
|
|
87
|
+
parsers.object.push([parseHwb, "hwb"]);
|
|
88
|
+
};
|
|
89
|
+
var hwb_default = hwbPlugin;
|
|
90
|
+
|
|
91
|
+
//#endregion
|
|
92
|
+
export { hwb_default as default, hwbPlugin };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { r as AnyColor, u as LabColor } from "../colord-xpgrVWRV.js";
|
|
2
|
+
import { t as Plugin } from "../extend-DrPfn2Q1.js";
|
|
3
|
+
|
|
4
|
+
//#region src/plugins/lab.d.ts
|
|
5
|
+
declare module '../colord' {
|
|
6
|
+
interface Colord {
|
|
7
|
+
/**
|
|
8
|
+
* Converts a color to CIELAB color space and returns an object.
|
|
9
|
+
* The object always includes `alpha` value [0, 1].
|
|
10
|
+
*/
|
|
11
|
+
toLab(): LabColor;
|
|
12
|
+
/**
|
|
13
|
+
* Calculates the perceived color difference for two colors according to
|
|
14
|
+
* [Delta E2000](https://en.wikipedia.org/wiki/Color_difference#CIEDE2000).
|
|
15
|
+
* Returns a value in [0, 1] range.
|
|
16
|
+
*/
|
|
17
|
+
delta(color?: AnyColor | Colord): number;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A plugin adding support for CIELAB color space.
|
|
22
|
+
* https://en.wikipedia.org/wiki/CIELAB_color_space
|
|
23
|
+
*/
|
|
24
|
+
declare const labPlugin: Plugin;
|
|
25
|
+
//#endregion
|
|
26
|
+
export { labPlugin as default, labPlugin };
|