color-value-tools 1.2.0 → 1.2.2
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 +18 -0
- package/dist/cjs/a11y.d.ts +40 -0
- package/dist/cjs/a11y.js +253 -0
- package/dist/cjs/cache.d.ts +9 -0
- package/dist/cjs/cache.js +38 -0
- package/dist/cjs/convert/format.d.ts +3 -0
- package/dist/cjs/convert/format.js +42 -0
- package/dist/cjs/convert/index.d.ts +2 -0
- package/dist/cjs/convert/index.js +18 -0
- package/dist/cjs/convert/spaces.d.ts +189 -0
- package/dist/cjs/convert/spaces.js +556 -0
- package/dist/cjs/index.d.ts +6 -397
- package/dist/cjs/index.js +20 -1450
- package/dist/cjs/internal/named-colors.d.ts +1 -0
- package/dist/cjs/internal/named-colors.js +165 -0
- package/dist/cjs/internal/transfer.d.ts +2 -0
- package/dist/cjs/internal/transfer.js +12 -0
- package/dist/cjs/manipulate.d.ts +15 -0
- package/dist/cjs/manipulate.js +223 -0
- package/dist/cjs/palette.d.ts +40 -0
- package/dist/cjs/palette.js +164 -0
- package/dist/cjs/parse.d.ts +102 -0
- package/dist/cjs/parse.js +257 -0
- package/dist/cli/{bin/cli.js → cli.js} +28 -26
- package/dist/esm/a11y.d.ts +40 -0
- package/dist/esm/a11y.js +237 -0
- package/dist/esm/cache.d.ts +9 -0
- package/dist/esm/cache.js +31 -0
- package/dist/esm/convert/format.d.ts +3 -0
- package/dist/esm/convert/format.js +37 -0
- package/dist/esm/convert/index.d.ts +2 -0
- package/dist/esm/convert/index.js +2 -0
- package/dist/esm/convert/spaces.d.ts +189 -0
- package/dist/esm/convert/spaces.js +520 -0
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.js +6 -1352
- package/dist/esm/internal/named-colors.d.ts +1 -0
- package/dist/esm/internal/named-colors.js +162 -0
- package/dist/esm/internal/transfer.d.ts +2 -0
- package/dist/esm/internal/transfer.js +8 -0
- package/dist/esm/manipulate.d.ts +15 -0
- package/dist/esm/manipulate.js +210 -0
- package/dist/esm/package.json +3 -1
- package/dist/esm/palette.d.ts +40 -0
- package/dist/esm/palette.js +145 -0
- package/dist/esm/parse.d.ts +102 -0
- package/dist/esm/parse.js +241 -0
- package/package.json +100 -8
- package/dist/cli/src/index.js +0 -1452
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
export type ColorType = 'hex' | 'css-var' | 'rgb' | 'hsl' | 'named' | 'oklch' | 'color' | 'unknown';
|
|
2
|
+
export declare function isCssVariable(value: string): boolean;
|
|
3
|
+
export declare function isHexColor(value: string): boolean;
|
|
4
|
+
export declare function isOklchColor(value: string): boolean;
|
|
5
|
+
export declare function isColorFunction(value: string): boolean;
|
|
6
|
+
export declare function isRgbColor(value: string): boolean;
|
|
7
|
+
export declare function isHslColor(value: string): boolean;
|
|
8
|
+
export declare function getColorType(value: string): ColorType;
|
|
9
|
+
export declare function extractCssVariableName(value: string): string;
|
|
10
|
+
export declare function parseCssVar(value: string): {
|
|
11
|
+
variableName: string;
|
|
12
|
+
fallback?: string;
|
|
13
|
+
} | null;
|
|
14
|
+
export declare function parseOklchString(str: string): {
|
|
15
|
+
L: number;
|
|
16
|
+
C: number;
|
|
17
|
+
H: number;
|
|
18
|
+
alpha: number;
|
|
19
|
+
} | null;
|
|
20
|
+
export declare function parseColorFn(str: string): {
|
|
21
|
+
space: string;
|
|
22
|
+
r: number;
|
|
23
|
+
g: number;
|
|
24
|
+
b: number;
|
|
25
|
+
alpha: number;
|
|
26
|
+
} | null;
|
|
27
|
+
export declare function normalizeColor(input: string | {
|
|
28
|
+
r: number;
|
|
29
|
+
g: number;
|
|
30
|
+
b: number;
|
|
31
|
+
} | {
|
|
32
|
+
h: number;
|
|
33
|
+
s: number;
|
|
34
|
+
l: number;
|
|
35
|
+
}): {
|
|
36
|
+
type: string;
|
|
37
|
+
hex: string;
|
|
38
|
+
r: any;
|
|
39
|
+
g: any;
|
|
40
|
+
b: any;
|
|
41
|
+
a: number;
|
|
42
|
+
h: number;
|
|
43
|
+
s: number;
|
|
44
|
+
l: number;
|
|
45
|
+
v: number;
|
|
46
|
+
raw?: undefined;
|
|
47
|
+
} | {
|
|
48
|
+
type: string;
|
|
49
|
+
hex: string;
|
|
50
|
+
r: number;
|
|
51
|
+
g: number;
|
|
52
|
+
b: number;
|
|
53
|
+
a: number;
|
|
54
|
+
h: any;
|
|
55
|
+
s: any;
|
|
56
|
+
l: any;
|
|
57
|
+
v: number;
|
|
58
|
+
raw?: undefined;
|
|
59
|
+
} | {
|
|
60
|
+
type: string;
|
|
61
|
+
hex?: undefined;
|
|
62
|
+
r?: undefined;
|
|
63
|
+
g?: undefined;
|
|
64
|
+
b?: undefined;
|
|
65
|
+
a?: undefined;
|
|
66
|
+
h?: undefined;
|
|
67
|
+
s?: undefined;
|
|
68
|
+
l?: undefined;
|
|
69
|
+
v?: undefined;
|
|
70
|
+
raw?: undefined;
|
|
71
|
+
} | {
|
|
72
|
+
type: string;
|
|
73
|
+
raw: string;
|
|
74
|
+
hex?: undefined;
|
|
75
|
+
r?: undefined;
|
|
76
|
+
g?: undefined;
|
|
77
|
+
b?: undefined;
|
|
78
|
+
a?: undefined;
|
|
79
|
+
h?: undefined;
|
|
80
|
+
s?: undefined;
|
|
81
|
+
l?: undefined;
|
|
82
|
+
v?: undefined;
|
|
83
|
+
} | {
|
|
84
|
+
type: string;
|
|
85
|
+
hex: string;
|
|
86
|
+
r: number;
|
|
87
|
+
g: number;
|
|
88
|
+
b: number;
|
|
89
|
+
a: number;
|
|
90
|
+
h?: undefined;
|
|
91
|
+
s?: undefined;
|
|
92
|
+
l?: undefined;
|
|
93
|
+
v?: undefined;
|
|
94
|
+
raw?: undefined;
|
|
95
|
+
};
|
|
96
|
+
export declare function parseHwbString(str: string): {
|
|
97
|
+
H: number;
|
|
98
|
+
W: number;
|
|
99
|
+
B: number;
|
|
100
|
+
alpha: number;
|
|
101
|
+
} | null;
|
|
102
|
+
export declare function toNearestNamedColor(color: string): string;
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isCssVariable = isCssVariable;
|
|
4
|
+
exports.isHexColor = isHexColor;
|
|
5
|
+
exports.isOklchColor = isOklchColor;
|
|
6
|
+
exports.isColorFunction = isColorFunction;
|
|
7
|
+
exports.isRgbColor = isRgbColor;
|
|
8
|
+
exports.isHslColor = isHslColor;
|
|
9
|
+
exports.getColorType = getColorType;
|
|
10
|
+
exports.extractCssVariableName = extractCssVariableName;
|
|
11
|
+
exports.parseCssVar = parseCssVar;
|
|
12
|
+
exports.parseOklchString = parseOklchString;
|
|
13
|
+
exports.parseColorFn = parseColorFn;
|
|
14
|
+
exports.normalizeColor = normalizeColor;
|
|
15
|
+
exports.parseHwbString = parseHwbString;
|
|
16
|
+
exports.toNearestNamedColor = toNearestNamedColor;
|
|
17
|
+
// Detecting, parsing and normalizing CSS color strings.
|
|
18
|
+
const named_colors_js_1 = require("./internal/named-colors.js");
|
|
19
|
+
const transfer_js_1 = require("./internal/transfer.js");
|
|
20
|
+
const spaces_js_1 = require("./convert/spaces.js");
|
|
21
|
+
function isCssVariable(value) {
|
|
22
|
+
return value.trim().startsWith('var(--');
|
|
23
|
+
}
|
|
24
|
+
function isHexColor(value) {
|
|
25
|
+
const trimmed = value.trim();
|
|
26
|
+
return /^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(trimmed);
|
|
27
|
+
}
|
|
28
|
+
function isOklchColor(value) {
|
|
29
|
+
return /^\s*oklcha?\s*\(/i.test(value.trim());
|
|
30
|
+
}
|
|
31
|
+
function isColorFunction(value) {
|
|
32
|
+
return /^\s*color\s*\(\s*(display-p3|srgb|srgb-linear)\s/i.test(value.trim());
|
|
33
|
+
}
|
|
34
|
+
function isRgbColor(value) {
|
|
35
|
+
const trimmed = value.trim().toLowerCase();
|
|
36
|
+
return trimmed.startsWith('rgb(') || trimmed.startsWith('rgba(');
|
|
37
|
+
}
|
|
38
|
+
function isHslColor(value) {
|
|
39
|
+
const trimmed = value.trim().toLowerCase();
|
|
40
|
+
return trimmed.startsWith('hsl(') || trimmed.startsWith('hsla(');
|
|
41
|
+
}
|
|
42
|
+
function getColorType(value) {
|
|
43
|
+
const trimmed = value.trim();
|
|
44
|
+
const lower = trimmed.toLowerCase();
|
|
45
|
+
if (isCssVariable(trimmed))
|
|
46
|
+
return 'css-var';
|
|
47
|
+
if (isHexColor(trimmed))
|
|
48
|
+
return 'hex';
|
|
49
|
+
if (isRgbColor(trimmed))
|
|
50
|
+
return 'rgb';
|
|
51
|
+
if (isHslColor(trimmed))
|
|
52
|
+
return 'hsl';
|
|
53
|
+
if (isOklchColor(trimmed))
|
|
54
|
+
return 'oklch';
|
|
55
|
+
if (isColorFunction(trimmed))
|
|
56
|
+
return 'color';
|
|
57
|
+
if (lower in named_colors_js_1.NAMED_COLORS)
|
|
58
|
+
return 'named';
|
|
59
|
+
return 'unknown';
|
|
60
|
+
}
|
|
61
|
+
function extractCssVariableName(value) {
|
|
62
|
+
var _a;
|
|
63
|
+
const match = value.match(/var\(\s*(--[^,)]+)/);
|
|
64
|
+
return ((_a = match === null || match === void 0 ? void 0 : match[1]) === null || _a === void 0 ? void 0 : _a.trim()) || value;
|
|
65
|
+
}
|
|
66
|
+
function parseCssVar(value) {
|
|
67
|
+
var _a;
|
|
68
|
+
const m = value.trim().match(/^var\(\s*(--[^,)]+)(?:,\s*([\s\S]+?))?\s*\)$/);
|
|
69
|
+
if (!m)
|
|
70
|
+
return null;
|
|
71
|
+
return { variableName: m[1].trim(), fallback: (_a = m[2]) === null || _a === void 0 ? void 0 : _a.trim() };
|
|
72
|
+
}
|
|
73
|
+
// ─── OKLCH / color() CSS string parsing ────────────────────────
|
|
74
|
+
function parseOklchString(str) {
|
|
75
|
+
const m = str
|
|
76
|
+
.trim()
|
|
77
|
+
.match(/oklcha?\(\s*([\d.]+%?)\s+([\d.]+)\s+([\d.]+)(?:\s*\/\s*([\d.]+))?\s*\)/i);
|
|
78
|
+
if (!m)
|
|
79
|
+
return null;
|
|
80
|
+
let L = parseFloat(m[1]);
|
|
81
|
+
if (m[1].endsWith('%'))
|
|
82
|
+
L = L / 100;
|
|
83
|
+
const C = parseFloat(m[2]);
|
|
84
|
+
const H = parseFloat(m[3]);
|
|
85
|
+
const alpha = m[4] !== undefined ? parseFloat(m[4]) : 1;
|
|
86
|
+
return { L, C, H, alpha };
|
|
87
|
+
}
|
|
88
|
+
function parseColorFn(str) {
|
|
89
|
+
const m = str
|
|
90
|
+
.trim()
|
|
91
|
+
.match(/color\(\s*([\w-]+)\s+([\d.]+%?)\s+([\d.]+%?)\s+([\d.]+%?)(?:\s*\/\s*([\d.]+))?\s*\)/i);
|
|
92
|
+
if (!m)
|
|
93
|
+
return null;
|
|
94
|
+
const space = m[1].toLowerCase();
|
|
95
|
+
const parseVal = (v) => (v.endsWith('%') ? parseFloat(v) / 100 : parseFloat(v));
|
|
96
|
+
const r = parseVal(m[2]);
|
|
97
|
+
const g = parseVal(m[3]);
|
|
98
|
+
const b = parseVal(m[4]);
|
|
99
|
+
const alpha = m[5] !== undefined ? parseFloat(m[5]) : 1;
|
|
100
|
+
return { space, r, g, b, alpha };
|
|
101
|
+
}
|
|
102
|
+
function normalizeColor(input) {
|
|
103
|
+
if (typeof input !== 'string') {
|
|
104
|
+
if ('r' in input && 'g' in input && 'b' in input) {
|
|
105
|
+
const { r, g, b } = input;
|
|
106
|
+
const hex = (0, spaces_js_1.rgbToHex)({ r, g, b });
|
|
107
|
+
const [h, s, l] = (0, spaces_js_1.rgbToHsl)({ r, g, b });
|
|
108
|
+
const [hh, ss, vv] = (0, spaces_js_1.rgbToHsv)({ r, g, b });
|
|
109
|
+
return { type: 'rgb', hex, r, g, b, a: 1, h, s, l, v: vv };
|
|
110
|
+
}
|
|
111
|
+
if ('h' in input && 's' in input && 'l' in input) {
|
|
112
|
+
const { h, s, l } = input;
|
|
113
|
+
const { r, g, b } = (0, spaces_js_1.hslToRgb)(h, s, l);
|
|
114
|
+
const hex = (0, spaces_js_1.rgbToHex)({ r, g, b });
|
|
115
|
+
const [hh, ss, vv] = (0, spaces_js_1.rgbToHsv)({ r, g, b });
|
|
116
|
+
return { type: 'hsl', hex, r, g, b, a: 1, h, s, l, v: vv };
|
|
117
|
+
}
|
|
118
|
+
return { type: 'unknown' };
|
|
119
|
+
}
|
|
120
|
+
const str = input.trim();
|
|
121
|
+
if (isCssVariable(str))
|
|
122
|
+
return { type: 'css-var', raw: str };
|
|
123
|
+
// 8-digit (#rrggbbaa) or 4-digit (#rgba) — check before isHexColor
|
|
124
|
+
const hex8 = str.match(/^#([0-9a-f]{8}|[0-9a-f]{4})$/i);
|
|
125
|
+
if (hex8) {
|
|
126
|
+
const rgba = (0, spaces_js_1.hex8ToRgba)(str);
|
|
127
|
+
if (rgba) {
|
|
128
|
+
const { r, g, b, a } = rgba;
|
|
129
|
+
const hex = (0, spaces_js_1.rgbToHex)({ r, g, b });
|
|
130
|
+
const [h, s, l] = (0, spaces_js_1.rgbToHsl)({ r, g, b });
|
|
131
|
+
const [hh, ss, vv] = (0, spaces_js_1.rgbToHsv)({ r, g, b });
|
|
132
|
+
return { type: 'hex', hex, r, g, b, a, h, s, l, v: vv };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (isHexColor(str)) {
|
|
136
|
+
const hex = (0, spaces_js_1.normalizeHex)(str);
|
|
137
|
+
const [r, g, b] = (0, spaces_js_1.hexToRgb)(hex);
|
|
138
|
+
const [h, s, l] = (0, spaces_js_1.hexToHsl)(hex);
|
|
139
|
+
const [hh, ss, vv] = (0, spaces_js_1.rgbToHsv)({ r, g, b });
|
|
140
|
+
return { type: 'hex', hex, r, g, b, a: 1, h, s, l, v: vv };
|
|
141
|
+
}
|
|
142
|
+
if (isRgbColor(str)) {
|
|
143
|
+
const rgba = (0, spaces_js_1.rgbaStringToRgba)(str);
|
|
144
|
+
if (rgba) {
|
|
145
|
+
const { r, g, b, a } = rgba;
|
|
146
|
+
const hex = (0, spaces_js_1.rgbToHex)({ r, g, b });
|
|
147
|
+
const [h, s, l] = (0, spaces_js_1.rgbToHsl)({ r, g, b });
|
|
148
|
+
const [hh, ss, vv] = (0, spaces_js_1.rgbToHsv)({ r, g, b });
|
|
149
|
+
return { type: 'rgb', hex, r, g, b, a, h, s, l, v: vv };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (isHslColor(str)) {
|
|
153
|
+
const m = str.match(/hsla?\(([^)]+)\)/i);
|
|
154
|
+
if (m) {
|
|
155
|
+
const parts = m[1].split(/,\s*/);
|
|
156
|
+
const h = parseFloat(parts[0]);
|
|
157
|
+
const s = parseFloat(parts[1]);
|
|
158
|
+
const l = parseFloat(parts[2]);
|
|
159
|
+
const a = parts[3] ? parseFloat(parts[3]) : 1;
|
|
160
|
+
const { r, g, b } = (0, spaces_js_1.hslToRgb)(h, s, l);
|
|
161
|
+
const hex = (0, spaces_js_1.rgbToHex)({ r, g, b });
|
|
162
|
+
const [hh, ss, vv] = (0, spaces_js_1.rgbToHsv)({ r, g, b });
|
|
163
|
+
return { type: 'hsl', hex, r, g, b, a, h, s, l, v: vv };
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (str === 'transparent')
|
|
167
|
+
return { type: 'named', hex: '#000000', r: 0, g: 0, b: 0, a: 0 };
|
|
168
|
+
const lowerStr = str.toLowerCase();
|
|
169
|
+
if (lowerStr in named_colors_js_1.NAMED_COLORS) {
|
|
170
|
+
const hex = named_colors_js_1.NAMED_COLORS[lowerStr];
|
|
171
|
+
const [r, g, b] = (0, spaces_js_1.hexToRgb)(hex);
|
|
172
|
+
const [h, s, l] = (0, spaces_js_1.hexToHsl)(hex);
|
|
173
|
+
const [, , vv] = (0, spaces_js_1.rgbToHsv)({ r, g, b });
|
|
174
|
+
return { type: 'named', hex, r, g, b, a: 1, h, s, l, v: vv };
|
|
175
|
+
}
|
|
176
|
+
// oklch / oklcha
|
|
177
|
+
if (isOklchColor(str)) {
|
|
178
|
+
const parsed = parseOklchString(str);
|
|
179
|
+
if (parsed) {
|
|
180
|
+
const { r, g, b } = (0, spaces_js_1.oklchToRgb)({ L: parsed.L, C: parsed.C, H: parsed.H });
|
|
181
|
+
const hex = (0, spaces_js_1.rgbToHex)({ r, g, b });
|
|
182
|
+
const [h, s, l] = (0, spaces_js_1.rgbToHsl)({ r, g, b });
|
|
183
|
+
const [, , vv] = (0, spaces_js_1.rgbToHsv)({ r, g, b });
|
|
184
|
+
return { type: 'oklch', hex, r, g, b, a: parsed.alpha, h, s, l, v: vv };
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// color(display-p3 ...) / color(srgb ...)
|
|
188
|
+
if (isColorFunction(str)) {
|
|
189
|
+
const parsed = parseColorFn(str);
|
|
190
|
+
if (parsed) {
|
|
191
|
+
const { r: p3r, g: p3g, b: p3b, alpha } = parsed;
|
|
192
|
+
// Convert from p3/srgb (0-1) to sRGB 0-255
|
|
193
|
+
let r, g, b;
|
|
194
|
+
if (parsed.space === 'display-p3') {
|
|
195
|
+
const srgb = (0, spaces_js_1.displayP3ToRgb)({ r: p3r, g: p3g, b: p3b });
|
|
196
|
+
r = srgb.r;
|
|
197
|
+
g = srgb.g;
|
|
198
|
+
b = srgb.b;
|
|
199
|
+
}
|
|
200
|
+
else if (parsed.space === 'srgb-linear') {
|
|
201
|
+
// srgb-linear components are linear-light, not gamma-encoded — unlike
|
|
202
|
+
// plain srgb below, they need the linear-to-sRGB transfer function
|
|
203
|
+
// applied before scaling to a 0-255 byte. Without this, only the 0/1
|
|
204
|
+
// extremes happened to come out correct; any mid-range value (e.g. 0.5)
|
|
205
|
+
// converted as if it were already gamma-encoded, which is wrong.
|
|
206
|
+
r = Math.round((0, transfer_js_1.linearChanToSrgb)(p3r) * 255);
|
|
207
|
+
g = Math.round((0, transfer_js_1.linearChanToSrgb)(p3g) * 255);
|
|
208
|
+
b = Math.round((0, transfer_js_1.linearChanToSrgb)(p3b) * 255);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
r = Math.round(Math.max(0, Math.min(255, p3r * 255)));
|
|
212
|
+
g = Math.round(Math.max(0, Math.min(255, p3g * 255)));
|
|
213
|
+
b = Math.round(Math.max(0, Math.min(255, p3b * 255)));
|
|
214
|
+
}
|
|
215
|
+
const hex = (0, spaces_js_1.rgbToHex)({ r, g, b });
|
|
216
|
+
const [h, s, l] = (0, spaces_js_1.rgbToHsl)({ r, g, b });
|
|
217
|
+
const [, , vv] = (0, spaces_js_1.rgbToHsv)({ r, g, b });
|
|
218
|
+
return { type: 'color', hex, r, g, b, a: alpha, h, s, l, v: vv };
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return { type: 'unknown' };
|
|
222
|
+
}
|
|
223
|
+
function parseHwbString(str) {
|
|
224
|
+
const m = str
|
|
225
|
+
.trim()
|
|
226
|
+
.match(/hwb\(\s*([\d.+-]+)\s+([\d.]+)%\s+([\d.]+)%(?:\s*\/\s*([\d.]+))?\s*\)/i);
|
|
227
|
+
if (!m)
|
|
228
|
+
return null;
|
|
229
|
+
return {
|
|
230
|
+
H: parseFloat(m[1]),
|
|
231
|
+
W: parseFloat(m[2]),
|
|
232
|
+
B: parseFloat(m[3]),
|
|
233
|
+
alpha: m[4] !== undefined ? parseFloat(m[4]) : 1,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
function toNearestNamedColor(color) {
|
|
237
|
+
var _a, _b, _c;
|
|
238
|
+
const n = normalizeColor(color);
|
|
239
|
+
const r = (_a = n.r) !== null && _a !== void 0 ? _a : 0, g = (_b = n.g) !== null && _b !== void 0 ? _b : 0, b = (_c = n.b) !== null && _c !== void 0 ? _c : 0;
|
|
240
|
+
let bestName = 'black';
|
|
241
|
+
let bestDist = Infinity;
|
|
242
|
+
for (const [name, hex] of Object.entries(named_colors_js_1.NAMED_COLORS)) {
|
|
243
|
+
// Skip any non-hex entry (currently just a defensive guard — 'transparent'
|
|
244
|
+
// is the only such value left in the table, and it has no real RGB to
|
|
245
|
+
// compare against; hexToRgb() would otherwise silently fall back to
|
|
246
|
+
// normalizeHex()'s placeholder color for it).
|
|
247
|
+
if (hex[0] !== '#')
|
|
248
|
+
continue;
|
|
249
|
+
const [nr, ng, nb] = (0, spaces_js_1.hexToRgb)(hex);
|
|
250
|
+
const dist = Math.sqrt(Math.pow(r - nr, 2) + Math.pow(g - ng, 2) + Math.pow(b - nb, 2));
|
|
251
|
+
if (dist < bestDist) {
|
|
252
|
+
bestDist = dist;
|
|
253
|
+
bestName = name;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return bestName;
|
|
257
|
+
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
const
|
|
17
|
+
const color_value_tools_1 = require("color-value-tools");
|
|
18
18
|
const args = process.argv.slice(2);
|
|
19
19
|
function printUsage() {
|
|
20
20
|
console.log(`
|
|
@@ -42,7 +42,7 @@ if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
|
|
|
42
42
|
}
|
|
43
43
|
const colorInput = args[0];
|
|
44
44
|
const command = (_a = args[1]) !== null && _a !== void 0 ? _a : 'info';
|
|
45
|
-
const normalized = (0,
|
|
45
|
+
const normalized = (0, color_value_tools_1.normalizeColor)(colorInput);
|
|
46
46
|
if (normalized.type === 'unknown' || normalized.type === 'css-var') {
|
|
47
47
|
console.error(`Error: Cannot resolve color "${colorInput}"`);
|
|
48
48
|
if (normalized.type === 'css-var') {
|
|
@@ -64,11 +64,11 @@ function line(label, value) {
|
|
|
64
64
|
}
|
|
65
65
|
switch (command) {
|
|
66
66
|
case 'info': {
|
|
67
|
-
const type = (0,
|
|
68
|
-
const [h, s, l] = (0,
|
|
69
|
-
const [hv, sv, v] = (0,
|
|
70
|
-
const nearest = (0,
|
|
71
|
-
const textColor = (0,
|
|
67
|
+
const type = (0, color_value_tools_1.getColorType)(colorInput);
|
|
68
|
+
const [h, s, l] = (0, color_value_tools_1.rgbToHsl)({ r, g, b });
|
|
69
|
+
const [hv, sv, v] = (0, color_value_tools_1.rgbToHsv)({ r, g, b });
|
|
70
|
+
const nearest = (0, color_value_tools_1.toNearestNamedColor)(hex);
|
|
71
|
+
const textColor = (0, color_value_tools_1.bestTextColor)(hex);
|
|
72
72
|
console.log(`\nColor: ${colorInput}`);
|
|
73
73
|
console.log('─'.repeat(40));
|
|
74
74
|
line('Type:', type);
|
|
@@ -84,18 +84,20 @@ switch (command) {
|
|
|
84
84
|
break;
|
|
85
85
|
}
|
|
86
86
|
case 'convert': {
|
|
87
|
-
const [h, s, l] = (0,
|
|
88
|
-
const [hv, sv, v] = (0,
|
|
89
|
-
const [hw, w, bw] = (0,
|
|
90
|
-
const lab = (0,
|
|
91
|
-
const lch = (0,
|
|
92
|
-
const oklab = (0,
|
|
93
|
-
const oklch = (0,
|
|
94
|
-
const cmyk = (0,
|
|
87
|
+
const [h, s, l] = (0, color_value_tools_1.rgbToHsl)({ r, g, b });
|
|
88
|
+
const [hv, sv, v] = (0, color_value_tools_1.rgbToHsv)({ r, g, b });
|
|
89
|
+
const [hw, w, bw] = (0, color_value_tools_1.rgbToHwb)({ r, g, b });
|
|
90
|
+
const lab = (0, color_value_tools_1.rgbToLab)({ r, g, b });
|
|
91
|
+
const lch = (0, color_value_tools_1.rgbToLch)({ r, g, b });
|
|
92
|
+
const oklab = (0, color_value_tools_1.rgbToOklab)({ r, g, b });
|
|
93
|
+
const oklch = (0, color_value_tools_1.rgbToOklch)({ r, g, b });
|
|
94
|
+
const cmyk = (0, color_value_tools_1.rgbToCmyk)({ r, g, b });
|
|
95
95
|
console.log(`\nConversions for: ${colorInput}`);
|
|
96
96
|
console.log('─'.repeat(40));
|
|
97
97
|
line('Hex:', hex);
|
|
98
|
-
line('Hex8:', `${hex}${Math.round(a * 255)
|
|
98
|
+
line('Hex8:', `${hex}${Math.round(a * 255)
|
|
99
|
+
.toString(16)
|
|
100
|
+
.padStart(2, '0')}`);
|
|
99
101
|
line('RGB:', `rgb(${r}, ${g}, ${b})`);
|
|
100
102
|
line('RGBA:', `rgba(${r}, ${g}, ${b}, ${fmt2(a)})`);
|
|
101
103
|
line('HSL:', `hsl(${h}, ${s}%, ${l}%)`);
|
|
@@ -115,14 +117,14 @@ switch (command) {
|
|
|
115
117
|
console.error('Error: Please provide a background color. Usage: cvt <color> contrast <bg>');
|
|
116
118
|
process.exit(1);
|
|
117
119
|
}
|
|
118
|
-
const bg = (0,
|
|
120
|
+
const bg = (0, color_value_tools_1.normalizeColor)(bgInput);
|
|
119
121
|
if (bg.type === 'unknown' || bg.type === 'css-var') {
|
|
120
122
|
console.error(`Error: Cannot resolve background color "${bgInput}"`);
|
|
121
123
|
process.exit(1);
|
|
122
124
|
}
|
|
123
125
|
const bgHex = (_g = bg.hex) !== null && _g !== void 0 ? _g : '#000000';
|
|
124
|
-
const ratio = (0,
|
|
125
|
-
const level = (0,
|
|
126
|
+
const ratio = (0, color_value_tools_1.contrastRatio)(hex, bgHex);
|
|
127
|
+
const level = (0, color_value_tools_1.wcagLevel)(hex, bgHex);
|
|
126
128
|
console.log(`\nContrast: ${colorInput} on ${bgInput}`);
|
|
127
129
|
console.log('─'.repeat(40));
|
|
128
130
|
line('Ratio:', `${fmt2(ratio)}:1`);
|
|
@@ -139,7 +141,7 @@ switch (command) {
|
|
|
139
141
|
console.error('Error: steps must be a number >= 2');
|
|
140
142
|
process.exit(1);
|
|
141
143
|
}
|
|
142
|
-
const shades = (0,
|
|
144
|
+
const shades = (0, color_value_tools_1.colorShades)(hex, steps);
|
|
143
145
|
console.log(`\nShades of ${colorInput} (${steps} steps):`);
|
|
144
146
|
console.log('─'.repeat(40));
|
|
145
147
|
shades.forEach((shade, i) => {
|
|
@@ -149,11 +151,11 @@ switch (command) {
|
|
|
149
151
|
break;
|
|
150
152
|
}
|
|
151
153
|
case 'harmonies': {
|
|
152
|
-
const comp = (0,
|
|
153
|
-
const tri = (0,
|
|
154
|
-
const ana = (0,
|
|
155
|
-
const split = (0,
|
|
156
|
-
const tet = (0,
|
|
154
|
+
const comp = (0, color_value_tools_1.complement)(hex);
|
|
155
|
+
const tri = (0, color_value_tools_1.triadic)(hex);
|
|
156
|
+
const ana = (0, color_value_tools_1.analogous)(hex);
|
|
157
|
+
const split = (0, color_value_tools_1.splitComplementary)(hex);
|
|
158
|
+
const tet = (0, color_value_tools_1.tetradic)(hex);
|
|
157
159
|
console.log(`\nHarmonies for: ${colorInput}`);
|
|
158
160
|
console.log('─'.repeat(40));
|
|
159
161
|
line('Complement:', comp);
|
|
@@ -165,7 +167,7 @@ switch (command) {
|
|
|
165
167
|
break;
|
|
166
168
|
}
|
|
167
169
|
case 'nearest': {
|
|
168
|
-
const name = (0,
|
|
170
|
+
const name = (0, color_value_tools_1.toNearestNamedColor)(hex);
|
|
169
171
|
console.log(`\nNearest CSS named color for ${colorInput}:`);
|
|
170
172
|
console.log('─'.repeat(40));
|
|
171
173
|
line('Name:', name);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export declare function relativeLuminance(color: string): number;
|
|
2
|
+
export declare function contrastRatio(a: string, b: string): number;
|
|
3
|
+
export declare function isDark(color: string, threshold?: number): boolean;
|
|
4
|
+
export declare function isLight(color: string, threshold?: number): boolean;
|
|
5
|
+
export type WcagLevel = 'AAA' | 'AA' | 'AA-large' | 'fail';
|
|
6
|
+
export declare function wcagLevel(foreground: string, background: string): WcagLevel;
|
|
7
|
+
export declare function bestTextColor(background: string): '#000000' | '#ffffff';
|
|
8
|
+
export declare function bestContrastColor(background: string, candidates: string[]): string;
|
|
9
|
+
export declare function colorDeltaE(c1: string, c2: string): number;
|
|
10
|
+
export type ColorBlindnessType = 'protanopia' | 'deuteranopia' | 'tritanopia';
|
|
11
|
+
export declare function simulateProtanopia(color: string): string;
|
|
12
|
+
export declare function simulateDeuteranopia(color: string): string;
|
|
13
|
+
export declare function simulateTritanopia(color: string): string;
|
|
14
|
+
export declare function simulateColorBlindness(color: string, type: ColorBlindnessType): string;
|
|
15
|
+
export type BackgroundSpec = string | {
|
|
16
|
+
type: 'semi-transparent';
|
|
17
|
+
color: string;
|
|
18
|
+
underlay?: string;
|
|
19
|
+
} | {
|
|
20
|
+
type: 'gradient';
|
|
21
|
+
stops: string[];
|
|
22
|
+
};
|
|
23
|
+
export declare function isReadableOnBackground(textColor: string, background: BackgroundSpec, options?: {
|
|
24
|
+
level?: 'AA' | 'AAA';
|
|
25
|
+
largeText?: boolean;
|
|
26
|
+
}): {
|
|
27
|
+
readable: boolean;
|
|
28
|
+
minContrastRatio: number;
|
|
29
|
+
wcagLevel: WcagLevel;
|
|
30
|
+
};
|
|
31
|
+
export interface PaletteScore {
|
|
32
|
+
palette: string[];
|
|
33
|
+
minContrastRatio: number;
|
|
34
|
+
avgContrastRatio: number;
|
|
35
|
+
}
|
|
36
|
+
export declare function bestContrastPalette(background: string, palettes: string[][], options?: {
|
|
37
|
+
weights?: number[];
|
|
38
|
+
}): PaletteScore & {
|
|
39
|
+
paletteIndex: number;
|
|
40
|
+
};
|