@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.
@@ -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 };