@soybeanjs/colord 0.0.4 → 0.0.6
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/dist/{colord-C3iU53g-.js → colord-CLzIbIN2.js} +20 -7
- package/dist/{colord-xpgrVWRV.d.ts → colord-Dc09uNcG.d.ts} +10 -0
- package/dist/colord.d.ts +1 -1
- package/dist/colord.js +8 -8
- package/dist/{extend-DrPfn2Q1.d.ts → extend-D_jQFvDk.d.ts} +1 -1
- package/dist/{get-D0jfz1WU.js → get-SLuYLSG9.js} +1 -1
- package/dist/{hsv-BKcGyyrD.js → hsv-OOAVcaRH.js} +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +8 -8
- package/dist/lab-9NsKpGel.js +219 -0
- package/dist/{manipulate-C3CvrU4m.js → manipulate-DCHNBCkU.js} +3 -3
- package/dist/plugins/a11y.d.ts +2 -2
- package/dist/plugins/a11y.js +3 -3
- package/dist/plugins/cmyk.d.ts +2 -2
- package/dist/plugins/cmyk.js +1 -1
- package/dist/plugins/harmonies.d.ts +1 -1
- package/dist/plugins/hwb.d.ts +2 -2
- package/dist/plugins/hwb.js +2 -2
- package/dist/plugins/lab.d.ts +6 -2
- package/dist/plugins/lab.js +11 -8
- package/dist/plugins/lch.d.ts +2 -2
- package/dist/plugins/lch.js +99 -25
- package/dist/plugins/minify.d.ts +1 -1
- package/dist/plugins/minify.js +1 -1
- package/dist/plugins/mix.d.ts +2 -2
- package/dist/plugins/mix.js +6 -6
- package/dist/plugins/names.d.ts +1 -1
- package/dist/plugins/oklab.d.ts +2 -2
- package/dist/plugins/oklab.js +50 -17
- package/dist/plugins/oklch.d.ts +2 -2
- package/dist/plugins/oklch.js +93 -24
- package/dist/plugins/xyz.d.ts +2 -2
- package/dist/plugins/xyz.js +5 -5
- package/dist/{rgb-DNYno5F7.js → rgb-BVkoWOmR.js} +8 -9
- package/dist/{utils-DajWVr6Z.js → utils-CshL9w1R.js} +18 -1
- package/dist/{xyz-CXEZJhV8.js → xyz-DsYRwYO_.js} +22 -9
- package/package.json +1 -1
- package/dist/lab-B5wAd4fu.js +0 -128
package/dist/plugins/lch.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { i as isPresent, l as round, n as clampHue, o as parseAlpha, s as parseHue, t as clamp, v as ALPHA_PRECISION } from "../utils-
|
|
2
|
-
import "../rgb-
|
|
3
|
-
import "../xyz-
|
|
4
|
-
import {
|
|
1
|
+
import { i as isPresent, l as round, n as clampHue, o as parseAlpha, s as parseHue, t as clamp, v as ALPHA_PRECISION } from "../utils-CshL9w1R.js";
|
|
2
|
+
import { n as clampRgb } from "../rgb-BVkoWOmR.js";
|
|
3
|
+
import "../xyz-DsYRwYO_.js";
|
|
4
|
+
import { n as labToRgb, o as rgbToLab } from "../lab-9NsKpGel.js";
|
|
5
5
|
|
|
6
6
|
//#region src/models/lch.ts
|
|
7
7
|
/**
|
|
@@ -13,7 +13,7 @@ const clampLch = (lab) => {
|
|
|
13
13
|
const { l, c, h, alpha } = lab;
|
|
14
14
|
return {
|
|
15
15
|
l: clamp(l, 0, 100),
|
|
16
|
-
c: clamp(c),
|
|
16
|
+
c: clamp(c, 0, 150),
|
|
17
17
|
h: clampHue(h),
|
|
18
18
|
alpha: clamp(alpha)
|
|
19
19
|
};
|
|
@@ -48,10 +48,9 @@ const rgbToLch = (rgb) => {
|
|
|
48
48
|
};
|
|
49
49
|
};
|
|
50
50
|
/**
|
|
51
|
-
*
|
|
52
|
-
* https://www.w3.org/TR/css-color-4/#color-conversion-code
|
|
51
|
+
* Convert LCH to RGB without gamut checking (internal helper)
|
|
53
52
|
*/
|
|
54
|
-
const
|
|
53
|
+
const lchToRgbDirect = (lcha) => {
|
|
55
54
|
const { l, c, h, alpha } = lcha;
|
|
56
55
|
const hRad = h * Math.PI / 180;
|
|
57
56
|
return labToRgb({
|
|
@@ -61,14 +60,74 @@ const lchaToRgb = (lcha) => {
|
|
|
61
60
|
alpha
|
|
62
61
|
});
|
|
63
62
|
};
|
|
63
|
+
/**
|
|
64
|
+
* Check if RGB is within sRGB gamut
|
|
65
|
+
* Note: RGB values are in [0, 255] range (not [0, 1])
|
|
66
|
+
*/
|
|
67
|
+
const isRgbInGamut = (rgb, epsilon = .01) => {
|
|
68
|
+
return rgb.r >= -epsilon && rgb.r <= 255 + epsilon && rgb.g >= -epsilon && rgb.g <= 255 + epsilon && rgb.b >= -epsilon && rgb.b <= 255 + epsilon;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Binary search to find maximum chroma that fits in sRGB gamut for LCH
|
|
72
|
+
* Similar to OKLCH's findGamutChroma
|
|
73
|
+
* @param l - Lightness (0-100)
|
|
74
|
+
* @param h - Hue (0-360)
|
|
75
|
+
* @param alpha - Alpha (0-1)
|
|
76
|
+
* @returns Maximum chroma that fits in sRGB gamut
|
|
77
|
+
*/
|
|
78
|
+
const findGamutChromaForLch = (l, h, alpha) => {
|
|
79
|
+
let min = 0;
|
|
80
|
+
let max = 150;
|
|
81
|
+
const epsilon = .01;
|
|
82
|
+
if (isRgbInGamut(lchToRgbDirect({
|
|
83
|
+
l,
|
|
84
|
+
c: max,
|
|
85
|
+
h,
|
|
86
|
+
alpha
|
|
87
|
+
}))) return max;
|
|
88
|
+
while (max - min > epsilon) {
|
|
89
|
+
const mid = (min + max) / 2;
|
|
90
|
+
if (isRgbInGamut(lchToRgbDirect({
|
|
91
|
+
l,
|
|
92
|
+
c: mid,
|
|
93
|
+
h,
|
|
94
|
+
alpha
|
|
95
|
+
}))) min = mid;
|
|
96
|
+
else max = mid;
|
|
97
|
+
}
|
|
98
|
+
return min;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Performs CIELCH → CIELAB → CIEXYZ → RGB color conversion with gamut mapping
|
|
102
|
+
* https://www.w3.org/TR/css-color-4/#color-conversion-code
|
|
103
|
+
*
|
|
104
|
+
* Similar to OKLCH, if the color is out of sRGB gamut, reduce chroma
|
|
105
|
+
* while preserving lightness and hue
|
|
106
|
+
*/
|
|
107
|
+
const lchaToRgb = (lcha) => {
|
|
108
|
+
const { l, h, alpha } = lcha;
|
|
109
|
+
let rgb = lchToRgbDirect(lcha);
|
|
110
|
+
if (!isRgbInGamut(rgb)) rgb = lchToRgbDirect({
|
|
111
|
+
l,
|
|
112
|
+
c: findGamutChromaForLch(l, h, alpha),
|
|
113
|
+
h,
|
|
114
|
+
alpha
|
|
115
|
+
});
|
|
116
|
+
return clampRgb(rgb);
|
|
117
|
+
};
|
|
64
118
|
const parseLch = ({ l, c, h, alpha = 1 }) => {
|
|
65
119
|
if (!isPresent(l) || !isPresent(c) || !isPresent(h)) return null;
|
|
66
|
-
return
|
|
120
|
+
return clampLch({
|
|
67
121
|
l: Number(l),
|
|
68
122
|
c: Number(c),
|
|
69
123
|
h: Number(h),
|
|
70
124
|
alpha: Number(alpha)
|
|
71
|
-
})
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
const parseLchToRgb = (input) => {
|
|
128
|
+
const lch = parseLch(input);
|
|
129
|
+
if (!lch) return null;
|
|
130
|
+
return lchaToRgb(lch);
|
|
72
131
|
};
|
|
73
132
|
/**
|
|
74
133
|
* Parsing syntax: lch(L c h [/ alpha])
|
|
@@ -76,28 +135,43 @@ const parseLch = ({ l, c, h, alpha = 1 }) => {
|
|
|
76
135
|
* - c: <number> [0,150]
|
|
77
136
|
* - h: <number|angle> [0,360] (deg, rad, grad, turn)
|
|
78
137
|
* - alpha: <number|percentage> [0,1]
|
|
79
|
-
*
|
|
80
138
|
*/
|
|
81
139
|
const lchaMatcher = /^lch\(\s*([+-]?[\d.]+)%?\s+([+-]?[\d.]+)\s+([+-]?[\d.]+)(deg|grad|rad|turn)?(?:\s*\/\s*([+-]?[\d.]+%?))?\s*\)$/i;
|
|
82
|
-
/**
|
|
83
|
-
* Parses a valid LCH CSS color function/string
|
|
84
|
-
* https://www.w3.org/TR/css-color-4/#specifying-lab-lch
|
|
85
|
-
*/
|
|
86
140
|
const parseLchString = (input) => {
|
|
87
141
|
const match = lchaMatcher.exec(input);
|
|
88
142
|
if (!match) return null;
|
|
89
|
-
const [, l, c, h, unit, alpha] = match;
|
|
90
|
-
return
|
|
143
|
+
const [_, l, c, h, unit, alpha] = match;
|
|
144
|
+
return clampLch({
|
|
91
145
|
l: Number.parseFloat(l),
|
|
92
146
|
c: Number.parseFloat(c),
|
|
93
147
|
h: parseHue(h, unit),
|
|
94
148
|
alpha: parseAlpha(alpha)
|
|
95
|
-
})
|
|
149
|
+
});
|
|
96
150
|
};
|
|
97
|
-
const
|
|
98
|
-
const
|
|
151
|
+
const parseLchStringToRgb = (input) => {
|
|
152
|
+
const lch = parseLchString(input);
|
|
153
|
+
if (!lch) return null;
|
|
154
|
+
return lchaToRgb(lch);
|
|
155
|
+
};
|
|
156
|
+
const toLchString = (lch) => {
|
|
157
|
+
const { l, c, h, alpha } = roundLch(lch);
|
|
99
158
|
return alpha < 1 ? `lch(${l}% ${c} ${h} / ${alpha})` : `lch(${l}% ${c} ${h})`;
|
|
100
159
|
};
|
|
160
|
+
const rgbToLchString = (rgb) => {
|
|
161
|
+
return toLchString(rgbToLch(rgb));
|
|
162
|
+
};
|
|
163
|
+
const parseLchBySource = (source) => {
|
|
164
|
+
if (!source || source.format !== "lch") return null;
|
|
165
|
+
const { input } = source;
|
|
166
|
+
if (typeof input === "string") return parseLchString(input);
|
|
167
|
+
if (typeof input === "object") return parseLch(input);
|
|
168
|
+
return null;
|
|
169
|
+
};
|
|
170
|
+
const toLchStringBySource = (source) => {
|
|
171
|
+
const lch = parseLchBySource(source);
|
|
172
|
+
if (!lch) return null;
|
|
173
|
+
return toLchString(lch);
|
|
174
|
+
};
|
|
101
175
|
|
|
102
176
|
//#endregion
|
|
103
177
|
//#region src/plugins/lch.ts
|
|
@@ -108,13 +182,13 @@ const rgbToLchString = (rgb) => {
|
|
|
108
182
|
*/
|
|
109
183
|
const lchPlugin = (ColordClass, parsers) => {
|
|
110
184
|
ColordClass.prototype.toLch = function toLch() {
|
|
111
|
-
return roundLch(rgbToLch(this.rgb));
|
|
185
|
+
return roundLch(parseLchBySource(this.getSource()) || rgbToLch(this.rgb));
|
|
112
186
|
};
|
|
113
|
-
ColordClass.prototype.toLchString = function toLchString() {
|
|
114
|
-
return rgbToLchString(this.rgb);
|
|
187
|
+
ColordClass.prototype.toLchString = function toLchString$1() {
|
|
188
|
+
return toLchStringBySource(this.getSource()) || rgbToLchString(this.rgb);
|
|
115
189
|
};
|
|
116
|
-
parsers.string.push([
|
|
117
|
-
parsers.object.push([
|
|
190
|
+
parsers.string.push([parseLchStringToRgb, "lch"]);
|
|
191
|
+
parsers.object.push([parseLchToRgb, "lch"]);
|
|
118
192
|
};
|
|
119
193
|
var lch_default = lchPlugin;
|
|
120
194
|
|
package/dist/plugins/minify.d.ts
CHANGED
package/dist/plugins/minify.js
CHANGED
package/dist/plugins/mix.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { r as AnyColor } from "../colord-
|
|
2
|
-
import { t as Plugin } from "../extend-
|
|
1
|
+
import { r as AnyColor } from "../colord-Dc09uNcG.js";
|
|
2
|
+
import { t as Plugin } from "../extend-D_jQFvDk.js";
|
|
3
3
|
|
|
4
4
|
//#region src/plugins/mix.d.ts
|
|
5
5
|
declare module '@soybeanjs/colord' {
|
package/dist/plugins/mix.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import "../utils-
|
|
2
|
-
import "../rgb-
|
|
3
|
-
import "../hsv-
|
|
4
|
-
import { i as mix } from "../manipulate-
|
|
5
|
-
import "../xyz-
|
|
6
|
-
import "../lab-
|
|
1
|
+
import "../utils-CshL9w1R.js";
|
|
2
|
+
import "../rgb-BVkoWOmR.js";
|
|
3
|
+
import "../hsv-OOAVcaRH.js";
|
|
4
|
+
import { i as mix } from "../manipulate-DCHNBCkU.js";
|
|
5
|
+
import "../xyz-DsYRwYO_.js";
|
|
6
|
+
import "../lab-9NsKpGel.js";
|
|
7
7
|
|
|
8
8
|
//#region src/plugins/mix.ts
|
|
9
9
|
/**
|
package/dist/plugins/names.d.ts
CHANGED
package/dist/plugins/oklab.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { f as OklabColor } from "../colord-
|
|
2
|
-
import { t as Plugin } from "../extend-
|
|
1
|
+
import { f as OklabColor } from "../colord-Dc09uNcG.js";
|
|
2
|
+
import { t as Plugin } from "../extend-D_jQFvDk.js";
|
|
3
3
|
|
|
4
4
|
//#region src/plugins/oklab.d.ts
|
|
5
5
|
declare module '@soybeanjs/colord' {
|
package/dist/plugins/oklab.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { _ as OKLAB_M2_INV, a as mul3x3, c as parseValueToDecimal, g as OKLAB_M2, h as OKLAB_M1_INV, i as isPresent, l as round, m as OKLAB_M1, o as parseAlpha, t as clamp, v as ALPHA_PRECISION } from "../utils-
|
|
2
|
-
import { n as clampRgb, o as rgbToLinearRgb, r as linearRgbToRgb, t as clampLinearRgb } from "../rgb-
|
|
1
|
+
import { _ as OKLAB_M2_INV, a as mul3x3, c as parseValueToDecimal, g as OKLAB_M2, h as OKLAB_M1_INV, i as isPresent, l as round, m as OKLAB_M1, o as parseAlpha, t as clamp, v as ALPHA_PRECISION } from "../utils-CshL9w1R.js";
|
|
2
|
+
import { n as clampRgb, o as rgbToLinearRgb, r as linearRgbToRgb, t as clampLinearRgb } from "../rgb-BVkoWOmR.js";
|
|
3
3
|
|
|
4
4
|
//#region src/models/oklab.ts
|
|
5
5
|
const clampOklab = (oklab) => {
|
|
6
6
|
const { l, a, b, alpha } = oklab;
|
|
7
7
|
return {
|
|
8
|
-
l: clamp(l,
|
|
8
|
+
l: clamp(l, 0, 1),
|
|
9
9
|
a: clamp(a, -.4, .4),
|
|
10
10
|
b: clamp(b, -.4, .4),
|
|
11
11
|
alpha: clamp(alpha)
|
|
@@ -49,12 +49,17 @@ const rgbToOklab = (rgb) => {
|
|
|
49
49
|
};
|
|
50
50
|
const parseOklab = ({ l, a, b, alpha = 1 }) => {
|
|
51
51
|
if (!isPresent(l) || !isPresent(a) || !isPresent(b)) return null;
|
|
52
|
-
return
|
|
52
|
+
return clampOklab({
|
|
53
53
|
l: Number(l),
|
|
54
54
|
a: Number(a),
|
|
55
55
|
b: Number(b),
|
|
56
56
|
alpha: Number(alpha)
|
|
57
|
-
})
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
const parseOklabToRgb = (input) => {
|
|
60
|
+
const oklab = parseOklab(input);
|
|
61
|
+
if (!oklab) return null;
|
|
62
|
+
return oklabToRgb(oklab);
|
|
58
63
|
};
|
|
59
64
|
/**
|
|
60
65
|
* Parsing syntax: oklab(L a b [/ alpha])
|
|
@@ -65,26 +70,54 @@ const parseOklab = ({ l, a, b, alpha = 1 }) => {
|
|
|
65
70
|
*/
|
|
66
71
|
const oklabMatcher = /^oklab\(\s*([+-]?[\d.]+)%?\s+([+-]?[\d.]+)\s+([+-]?[\d.]+)(?:\s*\/\s*([+-]?[\d.]+%?))?\s*\)$/i;
|
|
67
72
|
/**
|
|
68
|
-
* Parses a valid OKLAB CSS color function/string
|
|
73
|
+
* Parses a valid OKLAB CSS color function/string to OKLAB object
|
|
69
74
|
* https://www.w3.org/TR/css-color-4/#specifying-oklab
|
|
70
|
-
* @param input
|
|
71
|
-
* @returns
|
|
72
75
|
*/
|
|
73
76
|
const parseOklabString = (input) => {
|
|
74
77
|
const match = oklabMatcher.exec(input);
|
|
75
78
|
if (!match) return null;
|
|
76
79
|
const [_, l, a, b, alpha] = match;
|
|
77
|
-
return
|
|
80
|
+
return clampOklab({
|
|
78
81
|
l: parseValueToDecimal(l),
|
|
79
82
|
a: Number.parseFloat(a),
|
|
80
83
|
b: Number.parseFloat(b),
|
|
81
84
|
alpha: parseAlpha(alpha)
|
|
82
|
-
})
|
|
85
|
+
});
|
|
83
86
|
};
|
|
84
|
-
|
|
85
|
-
|
|
87
|
+
/**
|
|
88
|
+
* Parses a valid OKLAB CSS color function/string to RGB
|
|
89
|
+
* https://www.w3.org/TR/css-color-4/#specifying-oklab
|
|
90
|
+
*/
|
|
91
|
+
const parseOklabStringToRgb = (input) => {
|
|
92
|
+
const oklab = parseOklabString(input);
|
|
93
|
+
if (!oklab) return null;
|
|
94
|
+
return oklabToRgb(oklab);
|
|
95
|
+
};
|
|
96
|
+
const toOklabString = (oklab) => {
|
|
97
|
+
const { l, a, b, alpha } = roundOklab(oklab);
|
|
86
98
|
return alpha < 1 ? `oklab(${l}% ${a} ${b} / ${alpha})` : `oklab(${l}% ${a} ${b})`;
|
|
87
99
|
};
|
|
100
|
+
const rgbToOklabString = (rgb) => {
|
|
101
|
+
return toOklabString(rgbToOklab(rgb));
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Parse OKLAB from cached source input to avoid conversion loss
|
|
105
|
+
*/
|
|
106
|
+
const parseOklabBySource = (source) => {
|
|
107
|
+
if (!source || source.format !== "oklab") return null;
|
|
108
|
+
const { input } = source;
|
|
109
|
+
if (typeof input === "string") return parseOklabString(input);
|
|
110
|
+
if (typeof input === "object") return parseOklab(input);
|
|
111
|
+
return null;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Convert to OKLAB string from cached source input to avoid conversion loss
|
|
115
|
+
*/
|
|
116
|
+
const toOklabStringBySource = (source) => {
|
|
117
|
+
const oklab = parseOklabBySource(source);
|
|
118
|
+
if (!oklab) return null;
|
|
119
|
+
return toOklabString(oklab);
|
|
120
|
+
};
|
|
88
121
|
|
|
89
122
|
//#endregion
|
|
90
123
|
//#region src/plugins/oklab.ts
|
|
@@ -94,13 +127,13 @@ const rgbToOklabString = (rgb) => {
|
|
|
94
127
|
*/
|
|
95
128
|
const oklabPlugin = (ColordClass, parsers) => {
|
|
96
129
|
ColordClass.prototype.toOklab = function toOklab() {
|
|
97
|
-
return roundOklab(rgbToOklab(this.rgb));
|
|
130
|
+
return roundOklab(parseOklabBySource(this.getSource()) || rgbToOklab(this.rgb));
|
|
98
131
|
};
|
|
99
|
-
ColordClass.prototype.toOklabString = function toOklabString() {
|
|
100
|
-
return rgbToOklabString(this.rgb);
|
|
132
|
+
ColordClass.prototype.toOklabString = function toOklabString$1() {
|
|
133
|
+
return toOklabStringBySource(this.getSource()) || rgbToOklabString(this.rgb);
|
|
101
134
|
};
|
|
102
|
-
parsers.string.push([
|
|
103
|
-
parsers.object.push([
|
|
135
|
+
parsers.string.push([parseOklabStringToRgb, "oklab"]);
|
|
136
|
+
parsers.object.push([parseOklabToRgb, "oklab"]);
|
|
104
137
|
};
|
|
105
138
|
var oklab_default = oklabPlugin;
|
|
106
139
|
|
package/dist/plugins/oklch.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { p as OklchColor } from "../colord-
|
|
2
|
-
import { t as Plugin } from "../extend-
|
|
1
|
+
import { p as OklchColor } from "../colord-Dc09uNcG.js";
|
|
2
|
+
import { t as Plugin } from "../extend-D_jQFvDk.js";
|
|
3
3
|
|
|
4
4
|
//#region src/plugins/oklch.d.ts
|
|
5
5
|
declare module '@soybeanjs/colord' {
|
package/dist/plugins/oklch.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { _ as OKLAB_M2_INV, a as mul3x3, c as parseValueToDecimal, g as OKLAB_M2, h as OKLAB_M1_INV, i as isPresent, l as round, m as OKLAB_M1, n as clampHue, o as parseAlpha, s as parseHue, t as clamp, v as ALPHA_PRECISION } from "../utils-
|
|
2
|
-
import { n as clampRgb, o as rgbToLinearRgb, r as linearRgbToRgb, t as clampLinearRgb } from "../rgb-
|
|
1
|
+
import { _ as OKLAB_M2_INV, a as mul3x3, c as parseValueToDecimal, g as OKLAB_M2, h as OKLAB_M1_INV, i as isPresent, l as round, m as OKLAB_M1, n as clampHue, o as parseAlpha, s as parseHue, t as clamp, v as ALPHA_PRECISION } from "../utils-CshL9w1R.js";
|
|
2
|
+
import { n as clampRgb, o as rgbToLinearRgb, r as linearRgbToRgb, t as clampLinearRgb } from "../rgb-BVkoWOmR.js";
|
|
3
3
|
|
|
4
4
|
//#region src/models/oklch.ts
|
|
5
5
|
const clampOklch = (oklch) => {
|
|
6
6
|
const { l, c, h, alpha } = oklch;
|
|
7
7
|
return {
|
|
8
|
-
l: clamp(l,
|
|
9
|
-
c: clamp(c,
|
|
8
|
+
l: clamp(l, 0, 1),
|
|
9
|
+
c: clamp(c, 0, .37),
|
|
10
10
|
h: clampHue(h),
|
|
11
11
|
alpha: clamp(alpha)
|
|
12
12
|
};
|
|
@@ -20,7 +20,10 @@ const roundOklch = (oklch) => {
|
|
|
20
20
|
alpha: round(alpha, ALPHA_PRECISION)
|
|
21
21
|
};
|
|
22
22
|
};
|
|
23
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Convert OKLCH to Linear RGB without gamut mapping
|
|
25
|
+
*/
|
|
26
|
+
const oklchToLinearRgb = (oklch) => {
|
|
24
27
|
const { l, c, h, alpha } = oklch;
|
|
25
28
|
const hRad = h * Math.PI / 180;
|
|
26
29
|
const [r, g, b] = mul3x3(OKLAB_M1_INV, mul3x3(OKLAB_M2_INV, [
|
|
@@ -28,12 +31,59 @@ const oklchToRgb = (oklch) => {
|
|
|
28
31
|
c * Math.cos(hRad),
|
|
29
32
|
c * Math.sin(hRad)
|
|
30
33
|
]).map((v) => v * v * v));
|
|
31
|
-
return
|
|
34
|
+
return {
|
|
32
35
|
r,
|
|
33
36
|
g,
|
|
34
37
|
b,
|
|
35
38
|
alpha
|
|
36
|
-
}
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Check if a linear RGB color is within sRGB gamut
|
|
43
|
+
*/
|
|
44
|
+
const isInGamut = (linearRgb, epsilon = 1e-6) => {
|
|
45
|
+
return linearRgb.r >= -epsilon && linearRgb.r <= 1 + epsilon && linearRgb.g >= -epsilon && linearRgb.g <= 1 + epsilon && linearRgb.b >= -epsilon && linearRgb.b <= 1 + epsilon;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Binary search to find maximum chroma that fits in sRGB gamut
|
|
49
|
+
* @param l - Lightness (0-1)
|
|
50
|
+
* @param h - Hue (0-360)
|
|
51
|
+
* @param alpha - Alpha (0-1)
|
|
52
|
+
* @returns Maximum chroma that fits in sRGB gamut
|
|
53
|
+
*/
|
|
54
|
+
const findGamutChroma = (l, h, alpha) => {
|
|
55
|
+
let min = 0;
|
|
56
|
+
let max = .37;
|
|
57
|
+
const epsilon = 1e-5;
|
|
58
|
+
if (isInGamut(oklchToLinearRgb({
|
|
59
|
+
l,
|
|
60
|
+
c: max,
|
|
61
|
+
h,
|
|
62
|
+
alpha
|
|
63
|
+
}), epsilon)) return max;
|
|
64
|
+
while (max - min > epsilon) {
|
|
65
|
+
const mid = (min + max) / 2;
|
|
66
|
+
if (isInGamut(oklchToLinearRgb({
|
|
67
|
+
l,
|
|
68
|
+
c: mid,
|
|
69
|
+
h,
|
|
70
|
+
alpha
|
|
71
|
+
}), epsilon)) min = mid;
|
|
72
|
+
else max = mid;
|
|
73
|
+
}
|
|
74
|
+
return min;
|
|
75
|
+
};
|
|
76
|
+
const oklchToRgb = (oklch) => {
|
|
77
|
+
const { l, h, alpha } = oklch;
|
|
78
|
+
let linearRgb = oklchToLinearRgb(oklch);
|
|
79
|
+
if (!isInGamut(linearRgb)) linearRgb = oklchToLinearRgb({
|
|
80
|
+
l,
|
|
81
|
+
c: findGamutChroma(l, h, alpha),
|
|
82
|
+
h,
|
|
83
|
+
alpha
|
|
84
|
+
});
|
|
85
|
+
linearRgb = clampLinearRgb(linearRgb);
|
|
86
|
+
return clampRgb(linearRgbToRgb(linearRgb));
|
|
37
87
|
};
|
|
38
88
|
const rgbToOklch = (rgb) => {
|
|
39
89
|
const lRgb = rgbToLinearRgb(rgb);
|
|
@@ -58,12 +108,17 @@ const rgbToOklch = (rgb) => {
|
|
|
58
108
|
};
|
|
59
109
|
const parseOklch = ({ l, c, h, alpha = 1 }) => {
|
|
60
110
|
if (!isPresent(l) || !isPresent(c) || !isPresent(h)) return null;
|
|
61
|
-
return
|
|
111
|
+
return clampOklch({
|
|
62
112
|
l: Number(l),
|
|
63
113
|
c: Number(c),
|
|
64
114
|
h: Number(h),
|
|
65
115
|
alpha: Number(alpha)
|
|
66
|
-
})
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
const parseOklchToRgb = (input) => {
|
|
119
|
+
const oklch = parseOklch(input);
|
|
120
|
+
if (!oklch) return null;
|
|
121
|
+
return oklchToRgb(oklch);
|
|
67
122
|
};
|
|
68
123
|
/**
|
|
69
124
|
* Parsing syntax: oklch(L c h [/ alpha])
|
|
@@ -73,27 +128,41 @@ const parseOklch = ({ l, c, h, alpha = 1 }) => {
|
|
|
73
128
|
* - alpha: <number|percentage>
|
|
74
129
|
*/
|
|
75
130
|
const oklchMatcher = /^oklch\(\s*([+-]?[\d.]+)%?\s+([+-]?[\d.]+)\s+([+-]?[\d.]+)(deg|grad|rad|turn)?(?:\s*\/\s*([+-]?[\d.]+%?))?\s*\)$/i;
|
|
76
|
-
/**
|
|
77
|
-
* Parses a valid OKLCH CSS color function/string
|
|
78
|
-
* https://www.w3.org/TR/css-color-4/#specifying-oklch
|
|
79
|
-
* @param input
|
|
80
|
-
* @returns
|
|
81
|
-
*/
|
|
82
131
|
const parseOklchString = (input) => {
|
|
83
132
|
const match = oklchMatcher.exec(input);
|
|
84
133
|
if (!match) return null;
|
|
85
134
|
const [_, l, c, h, unit, alpha] = match;
|
|
86
|
-
return
|
|
135
|
+
return clampOklch({
|
|
87
136
|
l: parseValueToDecimal(l),
|
|
88
137
|
c: Number.parseFloat(c),
|
|
89
138
|
h: parseHue(h, unit),
|
|
90
139
|
alpha: parseAlpha(alpha)
|
|
91
|
-
})
|
|
140
|
+
});
|
|
92
141
|
};
|
|
93
|
-
const
|
|
94
|
-
const
|
|
142
|
+
const parseOklchStringToRgb = (input) => {
|
|
143
|
+
const oklch = parseOklchString(input);
|
|
144
|
+
if (!oklch) return null;
|
|
145
|
+
return oklchToRgb(oklch);
|
|
146
|
+
};
|
|
147
|
+
const toOklchString = (oklch) => {
|
|
148
|
+
const { l, c, h, alpha } = roundOklch(oklch);
|
|
95
149
|
return alpha < 1 ? `oklch(${l} ${c} ${h} / ${alpha})` : `oklch(${l} ${c} ${h})`;
|
|
96
150
|
};
|
|
151
|
+
const rgbToOklchString = (rgb) => {
|
|
152
|
+
return toOklchString(rgbToOklch(rgb));
|
|
153
|
+
};
|
|
154
|
+
const parseOklchBySource = (source) => {
|
|
155
|
+
if (!source || source.format !== "oklch") return null;
|
|
156
|
+
const { input } = source;
|
|
157
|
+
if (typeof input === "string") return parseOklchString(input);
|
|
158
|
+
if (typeof input === "object") return parseOklch(input);
|
|
159
|
+
return null;
|
|
160
|
+
};
|
|
161
|
+
const toOklchStringBySource = (source) => {
|
|
162
|
+
const oklch = parseOklchBySource(source);
|
|
163
|
+
if (!oklch) return null;
|
|
164
|
+
return toOklchString(oklch);
|
|
165
|
+
};
|
|
97
166
|
|
|
98
167
|
//#endregion
|
|
99
168
|
//#region src/plugins/oklch.ts
|
|
@@ -103,13 +172,13 @@ const rgbToOklchString = (rgb) => {
|
|
|
103
172
|
*/
|
|
104
173
|
const oklchPlugin = (ColordClass, parsers) => {
|
|
105
174
|
ColordClass.prototype.toOklch = function toOklch() {
|
|
106
|
-
return roundOklch(rgbToOklch(this.rgb));
|
|
175
|
+
return roundOklch(parseOklchBySource(this.getSource()) || rgbToOklch(this.rgb));
|
|
107
176
|
};
|
|
108
|
-
ColordClass.prototype.toOklchString = function toOklchString() {
|
|
109
|
-
return rgbToOklchString(this.rgb);
|
|
177
|
+
ColordClass.prototype.toOklchString = function toOklchString$1() {
|
|
178
|
+
return toOklchStringBySource(this.getSource()) || rgbToOklchString(this.rgb);
|
|
110
179
|
};
|
|
111
|
-
parsers.string.push([
|
|
112
|
-
parsers.object.push([
|
|
180
|
+
parsers.string.push([parseOklchStringToRgb, "oklch"]);
|
|
181
|
+
parsers.object.push([parseOklchToRgb, "oklch"]);
|
|
113
182
|
};
|
|
114
183
|
var oklch_default = oklchPlugin;
|
|
115
184
|
|
package/dist/plugins/xyz.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { g as XyzColor } from "../colord-
|
|
2
|
-
import { t as Plugin } from "../extend-
|
|
1
|
+
import { g as XyzColor } from "../colord-Dc09uNcG.js";
|
|
2
|
+
import { t as Plugin } from "../extend-D_jQFvDk.js";
|
|
3
3
|
|
|
4
4
|
//#region src/plugins/xyz.d.ts
|
|
5
5
|
declare module '@soybeanjs/colord' {
|
package/dist/plugins/xyz.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "../utils-
|
|
2
|
-
import "../rgb-
|
|
3
|
-
import { n as
|
|
1
|
+
import "../utils-CshL9w1R.js";
|
|
2
|
+
import "../rgb-BVkoWOmR.js";
|
|
3
|
+
import { i as roundXyz, n as parseXyzToRgb, r as rgbToXyz, t as parseXyzBySource } from "../xyz-DsYRwYO_.js";
|
|
4
4
|
|
|
5
5
|
//#region src/plugins/xyz.ts
|
|
6
6
|
/**
|
|
@@ -10,9 +10,9 @@ import { n as rgbToXyz, r as roundXyz, t as parseXyz } from "../xyz-CXEZJhV8.js"
|
|
|
10
10
|
*/
|
|
11
11
|
const xyzPlugin = (ColordClass, parsers) => {
|
|
12
12
|
ColordClass.prototype.toXyz = function toXyz() {
|
|
13
|
-
return roundXyz(rgbToXyz(this.rgb));
|
|
13
|
+
return roundXyz(parseXyzBySource(this.getSource()) || rgbToXyz(this.rgb));
|
|
14
14
|
};
|
|
15
|
-
parsers.object.push([
|
|
15
|
+
parsers.object.push([parseXyzToRgb, "xyz"]);
|
|
16
16
|
};
|
|
17
17
|
var xyz_default = xyzPlugin;
|
|
18
18
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as isPresent, l as round, o as parseAlpha, t as clamp, v as ALPHA_PRECISION } from "./utils-
|
|
1
|
+
import { i as isPresent, l as round, o as parseAlpha, t as clamp, v as ALPHA_PRECISION } from "./utils-CshL9w1R.js";
|
|
2
2
|
|
|
3
3
|
//#region src/models/rgb.ts
|
|
4
4
|
const clampRgb = (rgb) => {
|
|
@@ -13,18 +13,18 @@ const clampRgb = (rgb) => {
|
|
|
13
13
|
const roundRgb = (rgb) => {
|
|
14
14
|
const { r, g, b, alpha } = rgb;
|
|
15
15
|
return {
|
|
16
|
-
r: round(r),
|
|
17
|
-
g: round(g),
|
|
18
|
-
b: round(b),
|
|
16
|
+
r: round(r, 2),
|
|
17
|
+
g: round(g, 2),
|
|
18
|
+
b: round(b, 2),
|
|
19
19
|
alpha: round(alpha, ALPHA_PRECISION)
|
|
20
20
|
};
|
|
21
21
|
};
|
|
22
22
|
const clampLinearRgb = (rgb) => {
|
|
23
23
|
const { r, g, b, alpha } = rgb;
|
|
24
24
|
return {
|
|
25
|
-
r: clamp(r
|
|
26
|
-
g: clamp(g
|
|
27
|
-
b: clamp(b
|
|
25
|
+
r: clamp(r),
|
|
26
|
+
g: clamp(g),
|
|
27
|
+
b: clamp(b),
|
|
28
28
|
alpha: clamp(alpha)
|
|
29
29
|
};
|
|
30
30
|
};
|
|
@@ -63,8 +63,7 @@ const rgbToLinear = (value) => {
|
|
|
63
63
|
* @param value - Linear light value (0-1)
|
|
64
64
|
*/
|
|
65
65
|
function linearToRgb(value) {
|
|
66
|
-
|
|
67
|
-
return Math.round(v * 255);
|
|
66
|
+
return (value <= .0031308 ? value * 12.92 : 1.055 * value ** (1 / 2.4) - .055) * 255;
|
|
68
67
|
}
|
|
69
68
|
/**
|
|
70
69
|
* Converts an RGBA color to Linear RGB color space.
|
|
@@ -13,6 +13,23 @@ const ANGLE_UNITS = {
|
|
|
13
13
|
turn: 360,
|
|
14
14
|
rad: 360 / (Math.PI * 2)
|
|
15
15
|
};
|
|
16
|
+
/**
|
|
17
|
+
* D65 Standard Illuminant white point.
|
|
18
|
+
*
|
|
19
|
+
* D65 represents average daylight (including ultraviolet)
|
|
20
|
+
* with a correlated color temperature of approximately 6500K.
|
|
21
|
+
* It is the standard white point for sRGB, Display P3, and most
|
|
22
|
+
* web-related color spaces.
|
|
23
|
+
*
|
|
24
|
+
* Values are normalized with Y = 1.0.
|
|
25
|
+
*
|
|
26
|
+
* @see https://en.wikipedia.org/wiki/Illuminant_D65
|
|
27
|
+
*/
|
|
28
|
+
const D65 = {
|
|
29
|
+
x: .95047,
|
|
30
|
+
y: 1,
|
|
31
|
+
z: 1.08883
|
|
32
|
+
};
|
|
16
33
|
const D50 = {
|
|
17
34
|
x: .96422,
|
|
18
35
|
y: 1,
|
|
@@ -236,4 +253,4 @@ function parseValueToDecimal(value) {
|
|
|
236
253
|
}
|
|
237
254
|
|
|
238
255
|
//#endregion
|
|
239
|
-
export { OKLAB_M2_INV as _, mul3x3 as a, parseValueToDecimal as c, M_D65_TO_D50 as d, M_SRGB_TO_XYZ_D65 as f, OKLAB_M2 as g, OKLAB_M1_INV as h, isPresent as i, round as l, OKLAB_M1 as m, clampHue as n, parseAlpha as o, M_XYZ_D65_TO_SRGB as p, floor as r, parseHue as s, clamp as t, M_D50_TO_D65 as u, ALPHA_PRECISION as v, D50 as y };
|
|
256
|
+
export { OKLAB_M2_INV as _, mul3x3 as a, D65 as b, parseValueToDecimal as c, M_D65_TO_D50 as d, M_SRGB_TO_XYZ_D65 as f, OKLAB_M2 as g, OKLAB_M1_INV as h, isPresent as i, round as l, OKLAB_M1 as m, clampHue as n, parseAlpha as o, M_XYZ_D65_TO_SRGB as p, floor as r, parseHue as s, clamp as t, M_D50_TO_D65 as u, ALPHA_PRECISION as v, D50 as y };
|