@thi.ng/color 5.3.3 → 5.4.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/CHANGELOG.md +39 -1
- package/README.md +22 -19
- package/alpha.d.ts +8 -0
- package/alpha.js +8 -0
- package/analog.d.ts +4 -0
- package/analog.js +5 -1
- package/api.d.ts +13 -2
- package/clamp.d.ts +13 -3
- package/clamp.js +13 -3
- package/color.d.ts +23 -0
- package/color.js +6 -1
- package/convert.d.ts +9 -0
- package/convert.js +9 -0
- package/css/css.d.ts +22 -4
- package/css/css.js +33 -12
- package/css/parse-css.d.ts +25 -0
- package/css/parse-css.js +83 -33
- package/defcolor.js +2 -2
- package/distance.d.ts +8 -3
- package/distance.js +12 -8
- package/hcy/hcy.d.ts +5 -0
- package/hcy/hcy.js +5 -0
- package/hsi/hsi.d.ts +5 -0
- package/hsi/hsi.js +5 -0
- package/hsl/hsl.d.ts +5 -0
- package/hsl/hsl.js +5 -0
- package/hsv/hsv.d.ts +5 -0
- package/hsv/hsv.js +5 -0
- package/index.d.ts +5 -0
- package/index.js +5 -0
- package/internal/css.d.ts +4 -0
- package/internal/css.js +18 -0
- package/invert.d.ts +9 -0
- package/invert.js +9 -0
- package/lab/lab-css.js +2 -10
- package/lch/lch-css.js +2 -11
- package/lch/lch.d.ts +5 -1
- package/lch/lch.js +5 -1
- package/lighten.d.ts +3 -0
- package/lighten.js +3 -0
- package/mix.d.ts +3 -1
- package/mix.js +3 -1
- package/oklab/oklab-css.d.ts +11 -0
- package/oklab/oklab-css.js +10 -0
- package/oklab/oklab-rgb.js +11 -2
- package/oklab/oklab.js +2 -2
- package/oklch/oklab-oklch.d.ts +3 -0
- package/oklch/oklab-oklch.js +15 -0
- package/oklch/oklch-css.d.ts +11 -0
- package/oklch/oklch-css.js +10 -0
- package/oklch/oklch-oklab.d.ts +11 -0
- package/oklch/oklch-oklab.js +13 -0
- package/oklch/oklch.d.ts +37 -0
- package/oklch/oklch.js +26 -0
- package/package.json +32 -14
- package/rgb/rgb-oklab.js +11 -2
- package/rotate.d.ts +33 -0
- package/rotate.js +34 -1
- package/tint.d.ts +47 -0
- package/tint.js +48 -1
package/css/parse-css.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { rotateRight } from "@thi.ng/binary/rotate";
|
|
1
2
|
import { interleave4_12_24, interleave4_16_32 } from "@thi.ng/binary/splat";
|
|
2
3
|
import { isString } from "@thi.ng/checks/is-string";
|
|
3
4
|
import { assert } from "@thi.ng/errors/assert";
|
|
@@ -7,6 +8,7 @@ import { TAU } from "@thi.ng/math/api";
|
|
|
7
8
|
import { clamp01 } from "@thi.ng/math/interval";
|
|
8
9
|
import { fract } from "@thi.ng/math/prec";
|
|
9
10
|
import { ParsedColor } from "../api.js";
|
|
11
|
+
import { INV8BIT } from "../api/constants.js";
|
|
10
12
|
import { CSS_NAMES } from "../api/names.js";
|
|
11
13
|
import { CSS_SYSTEM_COLORS } from "../api/system.js";
|
|
12
14
|
import { intArgb32Srgb } from "../int/int-srgb.js";
|
|
@@ -29,11 +31,21 @@ import { intArgb32Srgb } from "../int/int-srgb.js";
|
|
|
29
31
|
* - `hsl(h,s%,l%)`
|
|
30
32
|
* - `hsla(h,s%,l%,a)`
|
|
31
33
|
* - `lab(l a b / alpha?)`
|
|
34
|
+
* - `lab(l% a% b% / alpha?)`
|
|
32
35
|
* - `lch(l c h / alpha?)`
|
|
36
|
+
* - `lch(l% c% h / alpha?)`
|
|
37
|
+
* - `oklab(l a b / alpha?)`
|
|
38
|
+
* - `oklab(l% a% b% / alpha?)`
|
|
39
|
+
* - `oklch(l c h / alpha?)`
|
|
40
|
+
* - `oklch(l% c% h / alpha?)`
|
|
33
41
|
*
|
|
34
42
|
* Hue values can be given according to CSS Color L4 spec (raw, deg, rad, grad,
|
|
35
43
|
* turn): https://www.w3.org/TR/css-color-4/#typedef-hue
|
|
36
44
|
*
|
|
45
|
+
* For (ok)lab/(ok)lch color channel values given as percentages, the scale
|
|
46
|
+
* ranges defined in the spec are used:
|
|
47
|
+
* https://www.w3.org/TR/css-color-4/#specifying-lab-lch
|
|
48
|
+
*
|
|
37
49
|
* If no alpha channel is given, it will default to 1.0 (fully opaque).
|
|
38
50
|
*
|
|
39
51
|
* Note that any named or system CSS colors, hex colors and any RGB colors will
|
|
@@ -52,82 +64,120 @@ export const parseCss = (src) => {
|
|
|
52
64
|
return new ParsedColor("srgb", intArgb32Srgb([], parseHex(named || src)));
|
|
53
65
|
const parts = src.split(/[(),/ ]+/);
|
|
54
66
|
const [mode, a, b, c, d] = parts;
|
|
55
|
-
assert(parts.length === 5 || parts.length === 6, `invalid
|
|
67
|
+
assert(parts.length === 5 || parts.length === 6, `invalid color: ${src}`);
|
|
56
68
|
switch (mode) {
|
|
57
69
|
case "rgb":
|
|
58
70
|
case "rgba":
|
|
59
71
|
return new ParsedColor("srgb", [
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
72
|
+
__numOrPercent(a, 1, INV8BIT, true),
|
|
73
|
+
__numOrPercent(b, 1, INV8BIT, true),
|
|
74
|
+
__numOrPercent(c, 1, INV8BIT, true),
|
|
75
|
+
__alpha(d),
|
|
64
76
|
]);
|
|
65
77
|
case "hsl":
|
|
66
78
|
case "hsla":
|
|
67
79
|
return new ParsedColor("hsl", [
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
80
|
+
__hue(a),
|
|
81
|
+
__percent(b),
|
|
82
|
+
__percent(c),
|
|
83
|
+
__alpha(d),
|
|
72
84
|
]);
|
|
73
85
|
case "lab":
|
|
74
86
|
return new ParsedColor("lab50", [
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
87
|
+
__numOrPercent(a),
|
|
88
|
+
__numOrPercent(b, 1.25),
|
|
89
|
+
__numOrPercent(c, 1.25),
|
|
90
|
+
__alpha(d),
|
|
79
91
|
]);
|
|
80
92
|
case "lch":
|
|
81
|
-
return new ParsedColor(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
93
|
+
return new ParsedColor(mode, [
|
|
94
|
+
__numOrPercent(a),
|
|
95
|
+
__numOrPercent(b, 1.5),
|
|
96
|
+
__hue(c),
|
|
97
|
+
__alpha(d),
|
|
98
|
+
]);
|
|
99
|
+
case "oklab":
|
|
100
|
+
return new ParsedColor(mode, [
|
|
101
|
+
__numOrPercent(a, 1, 1),
|
|
102
|
+
__numOrPercent(b, 0.4, 1),
|
|
103
|
+
__numOrPercent(c, 0.4, 1),
|
|
104
|
+
__alpha(d),
|
|
105
|
+
]);
|
|
106
|
+
case "oklch":
|
|
107
|
+
return new ParsedColor(mode, [
|
|
108
|
+
__numOrPercent(a, 1, 1),
|
|
109
|
+
__numOrPercent(b, 0.4, 1),
|
|
110
|
+
__hue(c),
|
|
111
|
+
__alpha(d),
|
|
86
112
|
]);
|
|
87
113
|
default:
|
|
88
114
|
unsupported(`color mode: ${mode}`);
|
|
89
115
|
}
|
|
90
116
|
};
|
|
117
|
+
/**
|
|
118
|
+
* Scale factors for various CSS angle units
|
|
119
|
+
*
|
|
120
|
+
* @remarks
|
|
121
|
+
* Reference:
|
|
122
|
+
* - https://www.w3.org/TR/css-values-4/#angle-value
|
|
123
|
+
*
|
|
124
|
+
* @internal
|
|
125
|
+
*/
|
|
91
126
|
const HUE_NORMS = {
|
|
92
127
|
rad: TAU,
|
|
93
128
|
grad: 400,
|
|
94
129
|
turn: 1,
|
|
95
130
|
deg: 360,
|
|
96
|
-
undefined: 360,
|
|
97
131
|
};
|
|
98
|
-
|
|
132
|
+
/** @internal */
|
|
133
|
+
const __hue = (x) => {
|
|
99
134
|
const match = /^(-?[0-9.]+)(deg|rad|grad|turn)?$/.exec(x);
|
|
100
135
|
assert(!!match, `expected hue, got: ${x}`);
|
|
101
|
-
return fract(parseFloat(match[1]) / HUE_NORMS[match[2]]);
|
|
136
|
+
return fract(parseFloat(match[1]) / (HUE_NORMS[match[2]] || 360));
|
|
102
137
|
};
|
|
103
|
-
|
|
104
|
-
const
|
|
138
|
+
/** @internal */
|
|
139
|
+
const __alpha = (x) => (x ? __numOrPercent(x, 1, 1, true) : 1);
|
|
140
|
+
/** @internal */
|
|
141
|
+
const __percent = (x, clamp = true) => {
|
|
105
142
|
assert(/^([0-9.]+)%$/.test(x), `expected percentage, got: ${x}`);
|
|
106
143
|
const res = parseFloat(x) / 100;
|
|
107
144
|
return clamp ? clamp01(res) : res;
|
|
108
145
|
};
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return parseFloat(x);
|
|
112
|
-
};
|
|
113
|
-
const parseNumOrPercent = (x, norm = 255, clamp = true) => {
|
|
146
|
+
/** @internal */
|
|
147
|
+
const __numOrPercent = (x, scalePerc = 1, scale = 0.01, clamp = false) => {
|
|
114
148
|
assert(/^-?[0-9.]+%?$/.test(x), `expected number or percentage, got: ${x}`);
|
|
115
|
-
const res = parseFloat(x)
|
|
149
|
+
const res = parseFloat(x) * (x.endsWith("%") ? 0.01 * scalePerc : scale);
|
|
116
150
|
return clamp ? clamp01(res) : res;
|
|
117
151
|
};
|
|
152
|
+
/**
|
|
153
|
+
* Parses a CSS hex color string into an uint32. Throws an error if given string
|
|
154
|
+
* doesn't conform to any of the supported formats.
|
|
155
|
+
*
|
|
156
|
+
* @remarks
|
|
157
|
+
* Supports the following input formats (`#` always optional and each letter a
|
|
158
|
+
* hex digit):
|
|
159
|
+
*
|
|
160
|
+
* - `#rgb`
|
|
161
|
+
* - `#rgba`
|
|
162
|
+
* - `#rrggbb`
|
|
163
|
+
* - `#rrggbbaa`
|
|
164
|
+
*
|
|
165
|
+
* @param src
|
|
166
|
+
*/
|
|
118
167
|
export const parseHex = (src) => {
|
|
119
168
|
const match = /^#?([0-9a-f]{3,8})$/i.exec(src);
|
|
120
169
|
if (match) {
|
|
121
170
|
const hex = match[1];
|
|
171
|
+
const val = parseInt(hex, 16);
|
|
122
172
|
switch (hex.length) {
|
|
123
173
|
case 3:
|
|
124
|
-
return (
|
|
174
|
+
return (interleave4_12_24(val) | 0xff000000) >>> 0;
|
|
125
175
|
case 4:
|
|
126
|
-
return interleave4_16_32(
|
|
176
|
+
return rotateRight(interleave4_16_32(val), 8);
|
|
127
177
|
case 6:
|
|
128
|
-
return (
|
|
178
|
+
return (val | 0xff000000) >>> 0;
|
|
129
179
|
case 8:
|
|
130
|
-
return
|
|
180
|
+
return rotateRight(val, 8);
|
|
131
181
|
default:
|
|
132
182
|
}
|
|
133
183
|
}
|
package/defcolor.js
CHANGED
|
@@ -28,8 +28,8 @@ export const defColor = (spec) => {
|
|
|
28
28
|
};
|
|
29
29
|
return acc;
|
|
30
30
|
}, channels);
|
|
31
|
-
const min = order.map((id) => channels[id].range[0]);
|
|
32
|
-
const max = order.map((id) => channels[id].range[1]);
|
|
31
|
+
const min = Object.freeze(order.map((id) => channels[id].range[0]));
|
|
32
|
+
const max = Object.freeze(order.map((id) => channels[id].range[1]));
|
|
33
33
|
// fix alpha channel for randomize()
|
|
34
34
|
const minR = set4([], min);
|
|
35
35
|
const maxR = set4([], max);
|
package/distance.d.ts
CHANGED
|
@@ -18,10 +18,15 @@ export declare const distHsv: ColorDistance;
|
|
|
18
18
|
/**
|
|
19
19
|
* Similar to {@link distHsv}, but computes distance between two LCH colors
|
|
20
20
|
* (with different channel order), i.e. the eucledian distance between points in
|
|
21
|
-
* a cyclinder.
|
|
21
|
+
* a cyclinder (using Law of Cosines).
|
|
22
22
|
*
|
|
23
|
-
* @
|
|
24
|
-
*
|
|
23
|
+
* @remarks
|
|
24
|
+
* Reference:
|
|
25
|
+
* - https://math.stackexchange.com/a/3612602
|
|
26
|
+
* - https://en.wikipedia.org/wiki/Law_of_cosines
|
|
27
|
+
*
|
|
28
|
+
* @param a
|
|
29
|
+
* @param b
|
|
25
30
|
*/
|
|
26
31
|
export declare const distLch: ColorDistance;
|
|
27
32
|
/**
|
package/distance.js
CHANGED
|
@@ -28,16 +28,20 @@ export const distHsv = (a, b) => {
|
|
|
28
28
|
/**
|
|
29
29
|
* Similar to {@link distHsv}, but computes distance between two LCH colors
|
|
30
30
|
* (with different channel order), i.e. the eucledian distance between points in
|
|
31
|
-
* a cyclinder.
|
|
31
|
+
* a cyclinder (using Law of Cosines).
|
|
32
32
|
*
|
|
33
|
-
* @
|
|
34
|
-
*
|
|
33
|
+
* @remarks
|
|
34
|
+
* Reference:
|
|
35
|
+
* - https://math.stackexchange.com/a/3612602
|
|
36
|
+
* - https://en.wikipedia.org/wiki/Law_of_cosines
|
|
37
|
+
*
|
|
38
|
+
* @param a
|
|
39
|
+
* @param b
|
|
35
40
|
*/
|
|
36
|
-
export const distLch = (
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
};
|
|
41
|
+
export const distLch = ({ 0: la, 1: ca, 2: ha }, { 0: lb, 1: cb, 2: hb }) => Math.sqrt(ca * ca +
|
|
42
|
+
cb * cb -
|
|
43
|
+
2 * ca * cb * Math.cos((ha - hb) * TAU) +
|
|
44
|
+
(la - lb) ** 2);
|
|
41
45
|
/**
|
|
42
46
|
* Computes difference in saturation between two HSV colors.
|
|
43
47
|
*
|
package/hcy/hcy.d.ts
CHANGED
|
@@ -24,5 +24,10 @@ export declare class HCY implements TypedColor<HCY> {
|
|
|
24
24
|
set(src: ReadonlyColor): this;
|
|
25
25
|
toJSON(): number[];
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* @remarks
|
|
29
|
+
* Note: As with other hue-based color modes in this package, the hue is stored
|
|
30
|
+
* normalized (in [0..1] interval) and NOT as degrees.
|
|
31
|
+
*/
|
|
27
32
|
export declare const hcy: ColorFactory<HCY>;
|
|
28
33
|
//# sourceMappingURL=hcy.d.ts.map
|
package/hcy/hcy.js
CHANGED
|
@@ -4,6 +4,11 @@ import { labRgb } from "../lab/lab-rgb.js";
|
|
|
4
4
|
import { rgbHcy } from "../rgb/rgb-hcy.js";
|
|
5
5
|
import { rgbSrgb } from "../rgb/rgb-srgb.js";
|
|
6
6
|
import { hcyRgb } from "./hcy-rgb.js";
|
|
7
|
+
/**
|
|
8
|
+
* @remarks
|
|
9
|
+
* Note: As with other hue-based color modes in this package, the hue is stored
|
|
10
|
+
* normalized (in [0..1] interval) and NOT as degrees.
|
|
11
|
+
*/
|
|
7
12
|
export const hcy = defColor({
|
|
8
13
|
mode: "hcy",
|
|
9
14
|
channels: { h: { hue: true } },
|
package/hsi/hsi.d.ts
CHANGED
|
@@ -24,5 +24,10 @@ export declare class HSI implements TypedColor<HSI> {
|
|
|
24
24
|
set(src: ReadonlyColor): this;
|
|
25
25
|
toJSON(): number[];
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* @remarks
|
|
29
|
+
* Note: As with other hue-based color modes in this package, the hue is stored
|
|
30
|
+
* normalized (in [0..1] interval) and NOT as degrees.
|
|
31
|
+
*/
|
|
27
32
|
export declare const hsi: ColorFactory<HSI>;
|
|
28
33
|
//# sourceMappingURL=hsi.d.ts.map
|
package/hsi/hsi.js
CHANGED
|
@@ -4,6 +4,11 @@ import { labRgb } from "../lab/lab-rgb.js";
|
|
|
4
4
|
import { rgbHsi } from "../rgb/rgb-hsi.js";
|
|
5
5
|
import { rgbSrgb } from "../rgb/rgb-srgb.js";
|
|
6
6
|
import { hsiRgb } from "./hsi-rgb.js";
|
|
7
|
+
/**
|
|
8
|
+
* @remarks
|
|
9
|
+
* Note: As with other hue-based color modes in this package, the hue is stored
|
|
10
|
+
* normalized (in [0..1] interval) and NOT as degrees.
|
|
11
|
+
*/
|
|
7
12
|
export const hsi = defColor({
|
|
8
13
|
mode: "hsi",
|
|
9
14
|
channels: { h: { hue: true } },
|
package/hsl/hsl.d.ts
CHANGED
|
@@ -24,5 +24,10 @@ export declare class HSL implements TypedColor<HSL> {
|
|
|
24
24
|
set(src: ReadonlyColor): this;
|
|
25
25
|
toJSON(): number[];
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* @remarks
|
|
29
|
+
* Note: As with other hue-based color modes in this package, the hue is stored
|
|
30
|
+
* normalized (in [0..1] interval) and NOT as degrees.
|
|
31
|
+
*/
|
|
27
32
|
export declare const hsl: ColorFactory<HSL>;
|
|
28
33
|
//# sourceMappingURL=hsl.d.ts.map
|
package/hsl/hsl.js
CHANGED
|
@@ -5,6 +5,11 @@ import { labRgb } from "../lab/lab-rgb.js";
|
|
|
5
5
|
import { rgbHsl } from "../rgb/rgb-hsl.js";
|
|
6
6
|
import { rgbSrgb } from "../rgb/rgb-srgb.js";
|
|
7
7
|
import { hslRgb } from "./hsl-rgb.js";
|
|
8
|
+
/**
|
|
9
|
+
* @remarks
|
|
10
|
+
* Note: As with other hue-based color modes in this package, the hue is stored
|
|
11
|
+
* normalized (in [0..1] interval) and NOT as degrees.
|
|
12
|
+
*/
|
|
8
13
|
export const hsl = defColor({
|
|
9
14
|
mode: "hsl",
|
|
10
15
|
channels: { h: { hue: true } },
|
package/hsv/hsv.d.ts
CHANGED
|
@@ -24,5 +24,10 @@ export declare class HSV implements TypedColor<HSV> {
|
|
|
24
24
|
set(src: ReadonlyColor): this;
|
|
25
25
|
toJSON(): number[];
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* @remarks
|
|
29
|
+
* Note: As with other hue-based color modes in this package, the hue is stored
|
|
30
|
+
* normalized (in [0..1] interval) and NOT as degrees.
|
|
31
|
+
*/
|
|
27
32
|
export declare const hsv: ColorFactory<HSV>;
|
|
28
33
|
//# sourceMappingURL=hsv.d.ts.map
|
package/hsv/hsv.js
CHANGED
|
@@ -5,6 +5,11 @@ import { labRgb } from "../lab/lab-rgb.js";
|
|
|
5
5
|
import { rgbHsv } from "../rgb/rgb-hsv.js";
|
|
6
6
|
import { rgbSrgb } from "../rgb/rgb-srgb.js";
|
|
7
7
|
import { hsvRgb } from "./hsv-rgb.js";
|
|
8
|
+
/**
|
|
9
|
+
* @remarks
|
|
10
|
+
* Note: As with other hue-based color modes in this package, the hue is stored
|
|
11
|
+
* normalized (in [0..1] interval) and NOT as degrees.
|
|
12
|
+
*/
|
|
8
13
|
export const hsv = defColor({
|
|
9
14
|
mode: "hsv",
|
|
10
15
|
channels: { h: { hue: true } },
|
package/index.d.ts
CHANGED
|
@@ -36,9 +36,14 @@ export * from "./lab/lab50.js";
|
|
|
36
36
|
export * from "./lab/lab65.js";
|
|
37
37
|
export * from "./lch/lch-css.js";
|
|
38
38
|
export * from "./lch/lch.js";
|
|
39
|
+
export * from "./oklab/oklab-css.js";
|
|
39
40
|
export * from "./oklab/oklab-rgb.js";
|
|
40
41
|
export * from "./oklab/oklab-xyz.js";
|
|
41
42
|
export * from "./oklab/oklab.js";
|
|
43
|
+
export * from "./oklch/oklch-css.js";
|
|
44
|
+
export * from "./oklch/oklch-oklab.js";
|
|
45
|
+
export * from "./oklch/oklab-oklch.js";
|
|
46
|
+
export * from "./oklch/oklch.js";
|
|
42
47
|
export * from "./alpha.js";
|
|
43
48
|
export * from "./analog.js";
|
|
44
49
|
export * from "./clamp.js";
|
package/index.js
CHANGED
|
@@ -36,9 +36,14 @@ export * from "./lab/lab50.js";
|
|
|
36
36
|
export * from "./lab/lab65.js";
|
|
37
37
|
export * from "./lch/lch-css.js";
|
|
38
38
|
export * from "./lch/lch.js";
|
|
39
|
+
export * from "./oklab/oklab-css.js";
|
|
39
40
|
export * from "./oklab/oklab-rgb.js";
|
|
40
41
|
export * from "./oklab/oklab-xyz.js";
|
|
41
42
|
export * from "./oklab/oklab.js";
|
|
43
|
+
export * from "./oklch/oklch-css.js";
|
|
44
|
+
export * from "./oklch/oklch-oklab.js";
|
|
45
|
+
export * from "./oklch/oklab-oklch.js";
|
|
46
|
+
export * from "./oklch/oklch.js";
|
|
42
47
|
export * from "./alpha.js";
|
|
43
48
|
export * from "./analog.js";
|
|
44
49
|
export * from "./clamp.js";
|
package/internal/css.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { clamp0 } from "@thi.ng/math/interval";
|
|
2
|
+
import { fract } from "@thi.ng/math/prec";
|
|
3
|
+
import { FF, PC } from "../api/constants.js";
|
|
4
|
+
import { __ensureAlpha } from "./ensure.js";
|
|
5
|
+
export const __labCss = (mode, src, scale) => {
|
|
6
|
+
const l = PC(clamp0(src[0]));
|
|
7
|
+
const a = FF(src[1] * scale);
|
|
8
|
+
const b = FF(src[2] * scale);
|
|
9
|
+
const alpha = __ensureAlpha(src[3]);
|
|
10
|
+
return `${mode}(${l} ${a} ${b}` + (alpha < 1 ? `/${FF(alpha)})` : ")");
|
|
11
|
+
};
|
|
12
|
+
export const __lchCss = (mode, src, scaleC) => {
|
|
13
|
+
const l = PC(clamp0(src[0]));
|
|
14
|
+
const c = FF(clamp0(src[1]) * scaleC);
|
|
15
|
+
const h = FF(fract(src[2]) * 360);
|
|
16
|
+
const a = __ensureAlpha(src[3]);
|
|
17
|
+
return `${mode}(${l} ${c} ${h}` + (a < 1 ? `/${FF(a)})` : ")");
|
|
18
|
+
};
|
package/invert.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ import type { ColorOp, TypedColor } from "./api.js";
|
|
|
3
3
|
* Inverts the RGB channels of an RGBA color.
|
|
4
4
|
*
|
|
5
5
|
* @remarks
|
|
6
|
+
* If `out` is null, the resulting color will be written back into `src`.
|
|
7
|
+
*
|
|
6
8
|
* Also see {@link TypedColor.invert}.
|
|
7
9
|
*
|
|
8
10
|
* @param out - result
|
|
@@ -18,5 +20,12 @@ export declare const invertRgb: ColorOp;
|
|
|
18
20
|
* @param src - packed RGB int
|
|
19
21
|
*/
|
|
20
22
|
export declare const invertInt: (src: number) => number;
|
|
23
|
+
/**
|
|
24
|
+
* Inverts given color and writes result into `out` (or if null, mutates `src`
|
|
25
|
+
* in place).
|
|
26
|
+
*
|
|
27
|
+
* @param out
|
|
28
|
+
* @param src
|
|
29
|
+
*/
|
|
21
30
|
export declare const invert: import("@thi.ng/defmulti").MultiFn2<import("@thi.ng/vectors/api").Vec | null, TypedColor<any>, import("@thi.ng/vectors/api").Vec>;
|
|
22
31
|
//# sourceMappingURL=invert.d.ts.map
|
package/invert.js
CHANGED
|
@@ -11,6 +11,8 @@ import { __ensureAlpha } from "./internal/ensure.js";
|
|
|
11
11
|
* Inverts the RGB channels of an RGBA color.
|
|
12
12
|
*
|
|
13
13
|
* @remarks
|
|
14
|
+
* If `out` is null, the resulting color will be written back into `src`.
|
|
15
|
+
*
|
|
14
16
|
* Also see {@link TypedColor.invert}.
|
|
15
17
|
*
|
|
16
18
|
* @param out - result
|
|
@@ -29,6 +31,13 @@ export const invertRgb = (out, src) => {
|
|
|
29
31
|
* @param src - packed RGB int
|
|
30
32
|
*/
|
|
31
33
|
export const invertInt = (src) => src ^ 0xffffff;
|
|
34
|
+
/**
|
|
35
|
+
* Inverts given color and writes result into `out` (or if null, mutates `src`
|
|
36
|
+
* in place).
|
|
37
|
+
*
|
|
38
|
+
* @param out
|
|
39
|
+
* @param src
|
|
40
|
+
*/
|
|
32
41
|
export const invert = defmulti(__dispatch1, {
|
|
33
42
|
hcy: "hsv",
|
|
34
43
|
hsi: "hsv",
|
package/lab/lab-css.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { FF, PC } from "../api/constants.js";
|
|
3
|
-
import { __ensureAlpha } from "../internal/ensure.js";
|
|
1
|
+
import { __labCss } from "../internal/css.js";
|
|
4
2
|
/**
|
|
5
3
|
* @remarks
|
|
6
4
|
* Only supported in CSS Color Level 4 onwards
|
|
@@ -9,10 +7,4 @@ import { __ensureAlpha } from "../internal/ensure.js";
|
|
|
9
7
|
*
|
|
10
8
|
* @param src -
|
|
11
9
|
*/
|
|
12
|
-
export const labCss = (src) =>
|
|
13
|
-
const l = PC(clamp0(src[0]));
|
|
14
|
-
const a = FF(src[1] * 100);
|
|
15
|
-
const b = FF(src[2] * 100);
|
|
16
|
-
const alpha = __ensureAlpha(src[3]);
|
|
17
|
-
return `lab(${l} ${a} ${b}` + (alpha < 1 ? `/${FF(alpha)})` : ")");
|
|
18
|
-
};
|
|
10
|
+
export const labCss = (src) => __labCss("lab", src, 100);
|
package/lch/lch-css.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { fract } from "@thi.ng/math/prec";
|
|
3
|
-
import { FF, PC } from "../api/constants.js";
|
|
4
|
-
import { __ensureAlpha } from "../internal/ensure.js";
|
|
1
|
+
import { __lchCss } from "../internal/css.js";
|
|
5
2
|
/**
|
|
6
3
|
* @remarks
|
|
7
4
|
* Only supported in CSS Color Level 4 onwards
|
|
@@ -10,10 +7,4 @@ import { __ensureAlpha } from "../internal/ensure.js";
|
|
|
10
7
|
*
|
|
11
8
|
* @param src -
|
|
12
9
|
*/
|
|
13
|
-
export const lchCss = (src) =>
|
|
14
|
-
const l = PC(clamp0(src[0]));
|
|
15
|
-
const c = FF(clamp0(src[1]) * 100);
|
|
16
|
-
const h = FF(fract(src[2]) * 360);
|
|
17
|
-
const a = __ensureAlpha(src[3]);
|
|
18
|
-
return `lch(${l} ${c} ${h}` + (a < 1 ? `/${FF(a)})` : ")");
|
|
19
|
-
};
|
|
10
|
+
export const lchCss = (src) => __lchCss("lch", src, 100);
|
package/lch/lch.d.ts
CHANGED
|
@@ -26,7 +26,11 @@ export declare class LCH implements TypedColor<LCH> {
|
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
28
|
* Luminance Chroma Hue (conversions assume {@link D50} white point, as per CSS
|
|
29
|
-
* spec).
|
|
29
|
+
* spec). Polar version of {@link labD50}.
|
|
30
|
+
*
|
|
31
|
+
* @remarks
|
|
32
|
+
* Note: As with other hue-based color modes in this package, the hue is stored
|
|
33
|
+
* normalized (in [0..1] interval) and NOT as degrees.
|
|
30
34
|
*/
|
|
31
35
|
export declare const lch: ColorFactory<LCH>;
|
|
32
36
|
//# sourceMappingURL=lch.d.ts.map
|
package/lch/lch.js
CHANGED
|
@@ -7,7 +7,11 @@ import { xyzLab } from "../xyz/xyz-lab.js";
|
|
|
7
7
|
import { xyzXyzD65_50 } from "../xyz/xyz-xyz.js";
|
|
8
8
|
/**
|
|
9
9
|
* Luminance Chroma Hue (conversions assume {@link D50} white point, as per CSS
|
|
10
|
-
* spec).
|
|
10
|
+
* spec). Polar version of {@link labD50}.
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* Note: As with other hue-based color modes in this package, the hue is stored
|
|
14
|
+
* normalized (in [0..1] interval) and NOT as degrees.
|
|
11
15
|
*/
|
|
12
16
|
export const lch = defColor({
|
|
13
17
|
mode: "lch",
|
package/lighten.d.ts
CHANGED
|
@@ -3,6 +3,9 @@ import type { TypedColor } from "./api.js";
|
|
|
3
3
|
* Adjust the "lightness" (luma, brightness etc.) channel of given `src` color
|
|
4
4
|
* and `delta` offset. Writes result into `out` (or if null, back into `src`).
|
|
5
5
|
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* If `offset` is negative, then color will be darkened.
|
|
8
|
+
*
|
|
6
9
|
* @param out -
|
|
7
10
|
* @param src -
|
|
8
11
|
* @param delta -
|
package/lighten.js
CHANGED
|
@@ -11,6 +11,9 @@ const $ = (id) => (out, src, n) => {
|
|
|
11
11
|
* Adjust the "lightness" (luma, brightness etc.) channel of given `src` color
|
|
12
12
|
* and `delta` offset. Writes result into `out` (or if null, back into `src`).
|
|
13
13
|
*
|
|
14
|
+
* @remarks
|
|
15
|
+
* If `offset` is negative, then color will be darkened.
|
|
16
|
+
*
|
|
14
17
|
* @param out -
|
|
15
18
|
* @param src -
|
|
16
19
|
* @param delta -
|
package/mix.d.ts
CHANGED
|
@@ -41,10 +41,12 @@ export declare const mixNNHN: ColorMixFn<import("@thi.ng/vectors").ReadonlyVec>;
|
|
|
41
41
|
export declare const mixNNNN: ColorMixFn;
|
|
42
42
|
/**
|
|
43
43
|
* Channelwise and {@link ColorMode}-aware interpolation between colors `a` and
|
|
44
|
-
* `b` using `t` [0..1] as blend factor. `a` and `b`
|
|
44
|
+
* `b` using `t` [0..1] as blend factor. `a` and `b` MUST be of same color
|
|
45
45
|
* type.
|
|
46
46
|
*
|
|
47
47
|
* @remarks
|
|
48
|
+
* If `out` is null, the resulting color will be written back into `a`.
|
|
49
|
+
*
|
|
48
50
|
* Any hue channel will always be interpolated using the smallest angle
|
|
49
51
|
* difference (using {@link mixH}).
|
|
50
52
|
*
|
package/mix.js
CHANGED
|
@@ -56,10 +56,12 @@ export const mixNNHN = defMix(mixN, mixN, mixH, mixN);
|
|
|
56
56
|
export const mixNNNN = mixN4;
|
|
57
57
|
/**
|
|
58
58
|
* Channelwise and {@link ColorMode}-aware interpolation between colors `a` and
|
|
59
|
-
* `b` using `t` [0..1] as blend factor. `a` and `b`
|
|
59
|
+
* `b` using `t` [0..1] as blend factor. `a` and `b` MUST be of same color
|
|
60
60
|
* type.
|
|
61
61
|
*
|
|
62
62
|
* @remarks
|
|
63
|
+
* If `out` is null, the resulting color will be written back into `a`.
|
|
64
|
+
*
|
|
63
65
|
* Any hue channel will always be interpolated using the smallest angle
|
|
64
66
|
* difference (using {@link mixH}).
|
|
65
67
|
*
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ReadonlyColor } from "../api.js";
|
|
2
|
+
/**
|
|
3
|
+
* @remarks
|
|
4
|
+
* Only supported in CSS Color Level 4 onwards
|
|
5
|
+
* https://www.w3.org/TR/css-color-4/#specifying-lab-lch
|
|
6
|
+
* https://test.csswg.org/harness/results/css-color-4_dev/grouped/ (test reports)
|
|
7
|
+
*
|
|
8
|
+
* @param src -
|
|
9
|
+
*/
|
|
10
|
+
export declare const oklabCss: (src: ReadonlyColor) => string;
|
|
11
|
+
//# sourceMappingURL=oklab-css.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { __labCss } from "../internal/css.js";
|
|
2
|
+
/**
|
|
3
|
+
* @remarks
|
|
4
|
+
* Only supported in CSS Color Level 4 onwards
|
|
5
|
+
* https://www.w3.org/TR/css-color-4/#specifying-lab-lch
|
|
6
|
+
* https://test.csswg.org/harness/results/css-color-4_dev/grouped/ (test reports)
|
|
7
|
+
*
|
|
8
|
+
* @param src -
|
|
9
|
+
*/
|
|
10
|
+
export const oklabCss = (src) => __labCss("oklab", src, 1);
|
package/oklab/oklab-rgb.js
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import { __mulV33 } from "../internal/matrix-ops.js";
|
|
2
|
+
/**
|
|
3
|
+
* @remarks
|
|
4
|
+
* Reference:
|
|
5
|
+
* - https://bottosson.github.io/posts/oklab/#converting-from-linear-srgb-to-oklab
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
// prettier-ignore
|
|
2
10
|
const LMS_CONE = [
|
|
3
|
-
4.
|
|
4
|
-
-
|
|
11
|
+
4.0767416621, -1.2684380046, -0.0041960863,
|
|
12
|
+
-3.307711591, 2.6097574011, -0.7034186147,
|
|
13
|
+
0.2309699292, -0.3413193965, 1.707614701,
|
|
5
14
|
];
|
|
6
15
|
/**
|
|
7
16
|
* @remarks
|
package/oklab/oklab.js
CHANGED
|
@@ -14,8 +14,8 @@ import { oklabRgb } from "./oklab-rgb.js";
|
|
|
14
14
|
export const oklab = defColor({
|
|
15
15
|
mode: "oklab",
|
|
16
16
|
channels: {
|
|
17
|
-
a: { range: [-0.2339, 0.
|
|
18
|
-
b: { range: [-0.
|
|
17
|
+
a: { range: [-0.2339, 0.2762] },
|
|
18
|
+
b: { range: [-0.3115, 0.1986] },
|
|
19
19
|
},
|
|
20
20
|
order: ["l", "a", "b", "alpha"],
|
|
21
21
|
from: {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { atan2Abs } from "@thi.ng/math/angle";
|
|
2
|
+
import { INV_TAU } from "@thi.ng/math/api";
|
|
3
|
+
import { setC4 } from "@thi.ng/vectors/setc";
|
|
4
|
+
import { __ensureAlpha } from "../internal/ensure.js";
|
|
5
|
+
export const oklabOklch = (out, src) => setC4(out || src, src[0], Math.hypot(src[1], src[2]), atan2Abs(src[2], src[1]) * INV_TAU, __ensureAlpha(src[3]));
|
|
6
|
+
/*
|
|
7
|
+
export function OKLab_to_OKLCH(OKLab: Color): Color {
|
|
8
|
+
const hue = Math.atan2(OKLab[2], OKLab[1]) * 180 / Math.PI;
|
|
9
|
+
return [
|
|
10
|
+
OKLab[0], // L is still L
|
|
11
|
+
Math.sqrt(OKLab[1] ** 2 + OKLab[2] ** 2), // Chroma
|
|
12
|
+
hue >= 0 ? hue : hue + 360, // Hue, in degrees [0 to 360)
|
|
13
|
+
];
|
|
14
|
+
}
|
|
15
|
+
*/
|