color-value-tools 1.2.1 → 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.
Files changed (49) hide show
  1. package/README.md +18 -0
  2. package/dist/cjs/a11y.d.ts +40 -0
  3. package/dist/cjs/a11y.js +253 -0
  4. package/dist/cjs/cache.d.ts +9 -0
  5. package/dist/cjs/cache.js +38 -0
  6. package/dist/cjs/convert/format.d.ts +3 -0
  7. package/dist/cjs/convert/format.js +42 -0
  8. package/dist/cjs/convert/index.d.ts +2 -0
  9. package/dist/cjs/convert/index.js +18 -0
  10. package/dist/cjs/convert/spaces.d.ts +189 -0
  11. package/dist/cjs/convert/spaces.js +556 -0
  12. package/dist/cjs/index.d.ts +6 -397
  13. package/dist/cjs/index.js +20 -1466
  14. package/dist/cjs/internal/named-colors.d.ts +1 -0
  15. package/dist/cjs/internal/named-colors.js +165 -0
  16. package/dist/cjs/internal/transfer.d.ts +2 -0
  17. package/dist/cjs/internal/transfer.js +12 -0
  18. package/dist/cjs/manipulate.d.ts +15 -0
  19. package/dist/cjs/manipulate.js +223 -0
  20. package/dist/cjs/palette.d.ts +40 -0
  21. package/dist/cjs/palette.js +164 -0
  22. package/dist/cjs/parse.d.ts +102 -0
  23. package/dist/cjs/parse.js +257 -0
  24. package/dist/cli/{bin/cli.js → cli.js} +28 -26
  25. package/dist/esm/a11y.d.ts +40 -0
  26. package/dist/esm/a11y.js +237 -0
  27. package/dist/esm/cache.d.ts +9 -0
  28. package/dist/esm/cache.js +31 -0
  29. package/dist/esm/convert/format.d.ts +3 -0
  30. package/dist/esm/convert/format.js +37 -0
  31. package/dist/esm/convert/index.d.ts +2 -0
  32. package/dist/esm/convert/index.js +2 -0
  33. package/dist/esm/convert/spaces.d.ts +189 -0
  34. package/dist/esm/convert/spaces.js +520 -0
  35. package/dist/esm/index.d.ts +6 -0
  36. package/dist/esm/index.js +6 -1368
  37. package/dist/esm/internal/named-colors.d.ts +1 -0
  38. package/dist/esm/internal/named-colors.js +162 -0
  39. package/dist/esm/internal/transfer.d.ts +2 -0
  40. package/dist/esm/internal/transfer.js +8 -0
  41. package/dist/esm/manipulate.d.ts +15 -0
  42. package/dist/esm/manipulate.js +210 -0
  43. package/dist/esm/package.json +3 -1
  44. package/dist/esm/palette.d.ts +40 -0
  45. package/dist/esm/palette.js +145 -0
  46. package/dist/esm/parse.d.ts +102 -0
  47. package/dist/esm/parse.js +241 -0
  48. package/package.json +100 -8
  49. package/dist/cli/src/index.js +0 -1468
package/README.md CHANGED
@@ -91,6 +91,24 @@ CommonJS:
91
91
  const { normalizeColor, mixColors } = require('color-value-tools')
92
92
  ```
93
93
 
94
+ ### Subpath imports
95
+
96
+ Everything is available from the package root, but you can also import a single group by meaning. Both ESM and CommonJS are supported, with full TypeScript types.
97
+
98
+ ```ts
99
+ import { hexToRgb, rgbToOklch, toOklchString } from 'color-value-tools/convert'
100
+ import { wcagLevel, simulateColorBlindness } from 'color-value-tools/a11y'
101
+ ```
102
+
103
+ | Subpath | Contents |
104
+ | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
105
+ | `color-value-tools/parse` | Type detection (`isHexColor`, `getColorType`, …), CSS string parsers, `normalizeColor`, `toNearestNamedColor` |
106
+ | `color-value-tools/convert` | Conversions between hex, RGB, HSL, HSV, HWB, CMYK, Lab, LCH, Oklab, Oklch, Display P3; CSS string formatters |
107
+ | `color-value-tools/manipulate` | `lighten`, `darken`, `saturate`, `desaturate`, `setAlpha`, `invertColor`, `grayscale`, `rotateHue`, `mixColors` |
108
+ | `color-value-tools/palette` | Harmonies, `colorShades`, `monochromatic`, `tints` / `shades` / `tones`, `interpolateColors`, `createColorScale`, `randomColor`, generators |
109
+ | `color-value-tools/a11y` | Luminance, contrast, WCAG checks, `colorDeltaE`, color blindness simulation |
110
+ | `color-value-tools/cache` | `normalizeColorCached` and cache controls |
111
+
94
112
  ### More examples
95
113
 
96
114
  #### What your palette looks like to a colorblind user
@@ -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
+ };
@@ -0,0 +1,253 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.relativeLuminance = relativeLuminance;
4
+ exports.contrastRatio = contrastRatio;
5
+ exports.isDark = isDark;
6
+ exports.isLight = isLight;
7
+ exports.wcagLevel = wcagLevel;
8
+ exports.bestTextColor = bestTextColor;
9
+ exports.bestContrastColor = bestContrastColor;
10
+ exports.colorDeltaE = colorDeltaE;
11
+ exports.simulateProtanopia = simulateProtanopia;
12
+ exports.simulateDeuteranopia = simulateDeuteranopia;
13
+ exports.simulateTritanopia = simulateTritanopia;
14
+ exports.simulateColorBlindness = simulateColorBlindness;
15
+ exports.isReadableOnBackground = isReadableOnBackground;
16
+ exports.bestContrastPalette = bestContrastPalette;
17
+ // Luminance, WCAG contrast, perceptual difference and color-blindness simulation.
18
+ const parse_js_1 = require("./parse.js");
19
+ const spaces_js_1 = require("./convert/spaces.js");
20
+ function relativeLuminance(color) {
21
+ var _a, _b, _c;
22
+ const n = (0, parse_js_1.normalizeColor)(color);
23
+ const r = ((_a = n.r) !== null && _a !== void 0 ? _a : 0) / 255;
24
+ const g = ((_b = n.g) !== null && _b !== void 0 ? _b : 0) / 255;
25
+ const b = ((_c = n.b) !== null && _c !== void 0 ? _c : 0) / 255;
26
+ const srgbToLin = (c) => (c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));
27
+ const R = srgbToLin(r), G = srgbToLin(g), B = srgbToLin(b);
28
+ return 0.2126 * R + 0.7152 * G + 0.0722 * B;
29
+ }
30
+ function contrastRatio(a, b) {
31
+ const L1 = relativeLuminance(a);
32
+ const L2 = relativeLuminance(b);
33
+ const light = Math.max(L1, L2);
34
+ const dark = Math.min(L1, L2);
35
+ return +((light + 0.05) / (dark + 0.05)).toFixed(2);
36
+ }
37
+ function isDark(color, threshold = 0.5) {
38
+ return relativeLuminance(color) < threshold;
39
+ }
40
+ function isLight(color, threshold = 0.5) {
41
+ return !isDark(color, threshold);
42
+ }
43
+ function wcagLevel(foreground, background) {
44
+ const ratio = contrastRatio(foreground, background);
45
+ if (ratio >= 7)
46
+ return 'AAA';
47
+ if (ratio >= 4.5)
48
+ return 'AA';
49
+ if (ratio >= 3)
50
+ return 'AA-large';
51
+ return 'fail';
52
+ }
53
+ function bestTextColor(background) {
54
+ const onBlack = contrastRatio(background, '#000000');
55
+ const onWhite = contrastRatio(background, '#ffffff');
56
+ return onBlack >= onWhite ? '#000000' : '#ffffff';
57
+ }
58
+ function bestContrastColor(background, candidates) {
59
+ let best = candidates[0];
60
+ let bestRatio = -1;
61
+ for (const c of candidates) {
62
+ const ratio = contrastRatio(background, c);
63
+ if (ratio > bestRatio) {
64
+ bestRatio = ratio;
65
+ best = c;
66
+ }
67
+ }
68
+ return best;
69
+ }
70
+ function colorDeltaE(c1, c2) {
71
+ var _a, _b, _c, _d, _e, _f;
72
+ const n1 = (0, parse_js_1.normalizeColor)(c1);
73
+ const n2 = (0, parse_js_1.normalizeColor)(c2);
74
+ const lab1 = (0, spaces_js_1.rgbToLab)({ r: (_a = n1.r) !== null && _a !== void 0 ? _a : 0, g: (_b = n1.g) !== null && _b !== void 0 ? _b : 0, b: (_c = n1.b) !== null && _c !== void 0 ? _c : 0 });
75
+ const lab2 = (0, spaces_js_1.rgbToLab)({ r: (_d = n2.r) !== null && _d !== void 0 ? _d : 0, g: (_e = n2.g) !== null && _e !== void 0 ? _e : 0, b: (_f = n2.b) !== null && _f !== void 0 ? _f : 0 });
76
+ // CIEDE2000
77
+ const deg = (rad) => rad * (180 / Math.PI);
78
+ const rad = (d) => d * (Math.PI / 180);
79
+ const { L: L1, a: a1, b: b1 } = lab1;
80
+ const { L: L2, a: a2, b: b2 } = lab2;
81
+ const dL = L2 - L1;
82
+ const Lm = (L1 + L2) / 2;
83
+ const C1 = Math.sqrt(a1 * a1 + b1 * b1);
84
+ const C2 = Math.sqrt(a2 * a2 + b2 * b2);
85
+ const Cm = (C1 + C2) / 2;
86
+ const Cm7 = Math.pow(Cm, 7);
87
+ const G = 0.5 * (1 - Math.sqrt(Cm7 / (Cm7 + Math.pow(25, 7))));
88
+ const a1p = a1 * (1 + G), a2p = a2 * (1 + G);
89
+ const C1p = Math.sqrt(a1p * a1p + b1 * b1);
90
+ const C2p = Math.sqrt(a2p * a2p + b2 * b2);
91
+ const dCp = C2p - C1p;
92
+ const Cmp = (C1p + C2p) / 2;
93
+ let h1p = deg(Math.atan2(b1, a1p));
94
+ if (h1p < 0)
95
+ h1p += 360;
96
+ let h2p = deg(Math.atan2(b2, a2p));
97
+ if (h2p < 0)
98
+ h2p += 360;
99
+ let dhp;
100
+ if (Math.abs(h1p - h2p) <= 180)
101
+ dhp = h2p - h1p;
102
+ else if (h2p <= h1p)
103
+ dhp = h2p - h1p + 360;
104
+ else
105
+ dhp = h2p - h1p - 360;
106
+ const dHp = 2 * Math.sqrt(C1p * C2p) * Math.sin(rad(dhp / 2));
107
+ let Hmp;
108
+ if (Math.abs(h1p - h2p) <= 180)
109
+ Hmp = (h1p + h2p) / 2;
110
+ else if (h1p + h2p < 360)
111
+ Hmp = (h1p + h2p + 360) / 2;
112
+ else
113
+ Hmp = (h1p + h2p - 360) / 2;
114
+ const T = 1 -
115
+ 0.17 * Math.cos(rad(Hmp - 30)) +
116
+ 0.24 * Math.cos(rad(2 * Hmp)) +
117
+ 0.32 * Math.cos(rad(3 * Hmp + 6)) -
118
+ 0.2 * Math.cos(rad(4 * Hmp - 63));
119
+ const SL = 1 + (0.015 * Math.pow(Lm - 50, 2)) / Math.sqrt(20 + Math.pow(Lm - 50, 2));
120
+ const SC = 1 + 0.045 * Cmp;
121
+ const SH = 1 + 0.015 * Cmp * T;
122
+ const Cmp7 = Math.pow(Cmp, 7);
123
+ const RC = 2 * Math.sqrt(Cmp7 / (Cmp7 + Math.pow(25, 7)));
124
+ const dTheta = 30 * Math.exp(-Math.pow((Hmp - 275) / 25, 2));
125
+ const RT = -Math.sin(rad(2 * dTheta)) * RC;
126
+ return +Math.sqrt(Math.pow(dL / SL, 2) +
127
+ Math.pow(dCp / SC, 2) +
128
+ Math.pow(dHp / SH, 2) +
129
+ RT * (dCp / SC) * (dHp / SH)).toFixed(4);
130
+ }
131
+ // ─── Color blindness simulation ────────────────────────────────────
132
+ function _simulateCB(color, matrix) {
133
+ var _a, _b, _c;
134
+ const n = (0, parse_js_1.normalizeColor)(color);
135
+ // linearize
136
+ const lin = (v) => {
137
+ const c = v / 255;
138
+ return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
139
+ };
140
+ const enc = (v) => {
141
+ const c = v <= 0.0031308 ? 12.92 * v : 1.055 * Math.pow(v, 1 / 2.4) - 0.055;
142
+ return Math.round(Math.max(0, Math.min(1, c)) * 255);
143
+ };
144
+ const r = lin((_a = n.r) !== null && _a !== void 0 ? _a : 0), g = lin((_b = n.g) !== null && _b !== void 0 ? _b : 0), b = lin((_c = n.b) !== null && _c !== void 0 ? _c : 0);
145
+ const nr = enc(matrix[0][0] * r + matrix[0][1] * g + matrix[0][2] * b);
146
+ const ng = enc(matrix[1][0] * r + matrix[1][1] * g + matrix[1][2] * b);
147
+ const nb = enc(matrix[2][0] * r + matrix[2][1] * g + matrix[2][2] * b);
148
+ return (0, spaces_js_1.rgbToHex)({ r: nr, g: ng, b: nb });
149
+ }
150
+ const _PROTANOPIA_M = [
151
+ [0.56667, 0.43333, 0.0],
152
+ [0.55833, 0.44167, 0.0],
153
+ [0.0, 0.24167, 0.75833],
154
+ ];
155
+ const _DEUTERANOPIA_M = [
156
+ [0.625, 0.375, 0.0],
157
+ [0.7, 0.3, 0.0],
158
+ [0.0, 0.3, 0.7],
159
+ ];
160
+ const _TRITANOPIA_M = [
161
+ [0.95, 0.05, 0.0],
162
+ [0.0, 0.43333, 0.56667],
163
+ [0.0, 0.475, 0.525],
164
+ ];
165
+ function simulateProtanopia(color) {
166
+ return _simulateCB(color, _PROTANOPIA_M);
167
+ }
168
+ function simulateDeuteranopia(color) {
169
+ return _simulateCB(color, _DEUTERANOPIA_M);
170
+ }
171
+ function simulateTritanopia(color) {
172
+ return _simulateCB(color, _TRITANOPIA_M);
173
+ }
174
+ function simulateColorBlindness(color, type) {
175
+ if (type === 'protanopia')
176
+ return simulateProtanopia(color);
177
+ if (type === 'deuteranopia')
178
+ return simulateDeuteranopia(color);
179
+ return simulateTritanopia(color);
180
+ }
181
+ function isReadableOnBackground(textColor, background, options) {
182
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
183
+ const level = (_a = options === null || options === void 0 ? void 0 : options.level) !== null && _a !== void 0 ? _a : 'AA';
184
+ const large = (_b = options === null || options === void 0 ? void 0 : options.largeText) !== null && _b !== void 0 ? _b : false;
185
+ const minRequired = level === 'AAA' ? (large ? 4.5 : 7) : large ? 3 : 4.5;
186
+ // The specific effective background color that minRatio was actually
187
+ // computed against — wcagLevel below is derived from this same color
188
+ // (never a hardcoded '#ffffff') so it can't disagree with minRatio/readable.
189
+ let minRatio;
190
+ let effectiveBackground;
191
+ if (typeof background === 'string') {
192
+ effectiveBackground = background;
193
+ minRatio = contrastRatio(textColor, background);
194
+ }
195
+ else if (background.type === 'semi-transparent') {
196
+ const underlay = (_c = background.underlay) !== null && _c !== void 0 ? _c : '#ffffff';
197
+ const fg = (0, parse_js_1.normalizeColor)(background.color);
198
+ const bg = (0, parse_js_1.normalizeColor)(underlay);
199
+ const alpha = (_d = fg.a) !== null && _d !== void 0 ? _d : 1;
200
+ const cr = Math.round(((_e = fg.r) !== null && _e !== void 0 ? _e : 0) * alpha + ((_f = bg.r) !== null && _f !== void 0 ? _f : 255) * (1 - alpha));
201
+ const cg = Math.round(((_g = fg.g) !== null && _g !== void 0 ? _g : 0) * alpha + ((_h = bg.g) !== null && _h !== void 0 ? _h : 255) * (1 - alpha));
202
+ const cb = Math.round(((_j = fg.b) !== null && _j !== void 0 ? _j : 0) * alpha + ((_k = bg.b) !== null && _k !== void 0 ? _k : 255) * (1 - alpha));
203
+ effectiveBackground = (0, spaces_js_1.rgbToHex)({ r: cr, g: cg, b: cb });
204
+ minRatio = contrastRatio(textColor, effectiveBackground);
205
+ }
206
+ else {
207
+ // The worst-case stop (lowest ratio) drives both minRatio and wcagLevel.
208
+ let worstStop = background.stops[0];
209
+ let worstRatio = Infinity;
210
+ for (const stop of background.stops) {
211
+ const ratio = contrastRatio(textColor, stop);
212
+ if (ratio < worstRatio) {
213
+ worstRatio = ratio;
214
+ worstStop = stop;
215
+ }
216
+ }
217
+ effectiveBackground = worstStop;
218
+ minRatio = worstRatio;
219
+ }
220
+ const wLevel = wcagLevel(textColor, effectiveBackground);
221
+ return {
222
+ readable: minRatio >= minRequired,
223
+ minContrastRatio: +minRatio.toFixed(2),
224
+ wcagLevel: wLevel,
225
+ };
226
+ }
227
+ function bestContrastPalette(background, palettes, options) {
228
+ let bestIdx = 0;
229
+ let bestScore = -1;
230
+ let bestMin = 0, bestAvg = 0;
231
+ palettes.forEach((palette, idx) => {
232
+ var _a;
233
+ const ratios = palette.map((c) => contrastRatio(background, c));
234
+ const weights = (_a = options === null || options === void 0 ? void 0 : options.weights) !== null && _a !== void 0 ? _a : ratios.map(() => 1);
235
+ const totalW = weights.reduce((s, w) => s + w, 0);
236
+ const avg = ratios.reduce((s, r, i) => { var _a; return s + r * ((_a = weights[i]) !== null && _a !== void 0 ? _a : 1); }, 0) / totalW;
237
+ const min = Math.min(...ratios);
238
+ // Score: weighted avg with heavy penalty on minimum
239
+ const score = avg * 0.4 + min * 0.6;
240
+ if (score > bestScore) {
241
+ bestScore = score;
242
+ bestIdx = idx;
243
+ bestMin = min;
244
+ bestAvg = avg;
245
+ }
246
+ });
247
+ return {
248
+ paletteIndex: bestIdx,
249
+ palette: palettes[bestIdx],
250
+ minContrastRatio: +bestMin.toFixed(2),
251
+ avgContrastRatio: +bestAvg.toFixed(2),
252
+ };
253
+ }
@@ -0,0 +1,9 @@
1
+ import { normalizeColor } from './parse.js';
2
+ export declare function clearColorCache(): void;
3
+ export declare function getCacheStats(): {
4
+ size: number;
5
+ hits: number;
6
+ };
7
+ export declare function enableCache(): void;
8
+ export declare function disableCache(): void;
9
+ export declare function normalizeColorCached(input: string): ReturnType<typeof normalizeColor>;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.clearColorCache = clearColorCache;
4
+ exports.getCacheStats = getCacheStats;
5
+ exports.enableCache = enableCache;
6
+ exports.disableCache = disableCache;
7
+ exports.normalizeColorCached = normalizeColorCached;
8
+ // Memoized normalizeColor() for performance-sensitive code.
9
+ const parse_js_1 = require("./parse.js");
10
+ let _cacheEnabled = true;
11
+ const _normalizeCache = new Map();
12
+ let _cacheHits = 0;
13
+ function clearColorCache() {
14
+ _normalizeCache.clear();
15
+ _cacheHits = 0;
16
+ }
17
+ function getCacheStats() {
18
+ return { size: _normalizeCache.size, hits: _cacheHits };
19
+ }
20
+ function enableCache() {
21
+ _cacheEnabled = true;
22
+ }
23
+ function disableCache() {
24
+ _cacheEnabled = false;
25
+ }
26
+ // Cached normalizer wrapper — use this in performance-sensitive contexts
27
+ function normalizeColorCached(input) {
28
+ if (!_cacheEnabled)
29
+ return (0, parse_js_1.normalizeColor)(input);
30
+ const cached = _normalizeCache.get(input);
31
+ if (cached) {
32
+ _cacheHits++;
33
+ return cached;
34
+ }
35
+ const result = (0, parse_js_1.normalizeColor)(input);
36
+ _normalizeCache.set(input, result);
37
+ return result;
38
+ }
@@ -0,0 +1,3 @@
1
+ export declare function toDisplayP3Hex(color: string): string;
2
+ export declare function toOklchString(color: string, alpha?: number): string;
3
+ export declare function toColorP3String(color: string, alpha?: number): string;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toDisplayP3Hex = toDisplayP3Hex;
4
+ exports.toOklchString = toOklchString;
5
+ exports.toColorP3String = toColorP3String;
6
+ // Formatters that accept any supported CSS color string.
7
+ const parse_js_1 = require("../parse.js");
8
+ const spaces_js_1 = require("./spaces.js");
9
+ function toDisplayP3Hex(color) {
10
+ const n = normalizeColorRaw(color);
11
+ const p3 = (0, spaces_js_1.rgbToDisplayP3)({ r: n.r, g: n.g, b: n.b });
12
+ return (0, spaces_js_1.rgbToHex)({
13
+ r: Math.round(Math.max(0, Math.min(255, p3.r * 255))),
14
+ g: Math.round(Math.max(0, Math.min(255, p3.g * 255))),
15
+ b: Math.round(Math.max(0, Math.min(255, p3.b * 255))),
16
+ });
17
+ }
18
+ // Internal raw normalizer (no cache, no circular dep issues)
19
+ function normalizeColorRaw(color) {
20
+ var _a, _b, _c, _d;
21
+ const n = (0, parse_js_1.normalizeColor)(color);
22
+ return { 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, a: (_d = n.a) !== null && _d !== void 0 ? _d : 1 };
23
+ }
24
+ // ─── Formatting ───────────────────────────────────────────────────────────────
25
+ function toOklchString(color, alpha) {
26
+ var _a, _b, _c;
27
+ const n = (0, parse_js_1.normalizeColor)(color);
28
+ const { L, C, H } = (0, spaces_js_1.rgbToOklch)({ 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 });
29
+ const Lr = +L.toFixed(4), Cr = +C.toFixed(4), Hr = +H.toFixed(2);
30
+ if (alpha !== undefined)
31
+ return `oklch(${Lr} ${Cr} ${Hr} / ${+alpha.toFixed(3)})`;
32
+ return `oklch(${Lr} ${Cr} ${Hr})`;
33
+ }
34
+ function toColorP3String(color, alpha) {
35
+ var _a, _b, _c;
36
+ const n = (0, parse_js_1.normalizeColor)(color);
37
+ const p3 = (0, spaces_js_1.rgbToDisplayP3)({ 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 });
38
+ const r = +p3.r.toFixed(4), g = +p3.g.toFixed(4), b = +p3.b.toFixed(4);
39
+ if (alpha !== undefined)
40
+ return `color(display-p3 ${r} ${g} ${b} / ${+alpha.toFixed(3)})`;
41
+ return `color(display-p3 ${r} ${g} ${b})`;
42
+ }
@@ -0,0 +1,2 @@
1
+ export * from './spaces.js';
2
+ export * from './format.js';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./spaces.js"), exports);
18
+ __exportStar(require("./format.js"), exports);
@@ -0,0 +1,189 @@
1
+ export declare function rgbToDisplayP3(rgb: {
2
+ r: number;
3
+ g: number;
4
+ b: number;
5
+ }): {
6
+ r: number;
7
+ g: number;
8
+ b: number;
9
+ };
10
+ export declare function displayP3ToRgb(p3: {
11
+ r: number;
12
+ g: number;
13
+ b: number;
14
+ }): {
15
+ r: number;
16
+ g: number;
17
+ b: number;
18
+ };
19
+ export declare function shortHexToRgba(hex: string): {
20
+ r: number;
21
+ g: number;
22
+ b: number;
23
+ a: number;
24
+ } | null;
25
+ export declare function normalizeHex(hex: string): string;
26
+ export declare function hexToRgb(hex: string): [number, number, number];
27
+ export declare function hexToRgba(hex: string, opacity?: number): string;
28
+ export declare function hexToHsl(hex: string): [number, number, number];
29
+ export declare function hslToHex(h: number, s: number, l: number): string;
30
+ export declare function rgbToHex({ r, g, b }: {
31
+ r: number;
32
+ g: number;
33
+ b: number;
34
+ }): string;
35
+ export declare function rgbaToHex({ r, g, b, a }: {
36
+ r: number;
37
+ g: number;
38
+ b: number;
39
+ a: number;
40
+ }): string;
41
+ export declare function rgbToRgbaString({ r, g, b }: {
42
+ r: number;
43
+ g: number;
44
+ b: number;
45
+ }, a: number): string;
46
+ export declare function rgbaStringToRgba(str: string): {
47
+ r: number;
48
+ g: number;
49
+ b: number;
50
+ a: number;
51
+ } | null;
52
+ export declare function rgbToHsl({ r, g, b, }: {
53
+ r: number;
54
+ g: number;
55
+ b: number;
56
+ }): [number, number, number];
57
+ export declare function hslToRgb(h: number, s: number, l: number): {
58
+ r: number;
59
+ g: number;
60
+ b: number;
61
+ };
62
+ export declare function rgbToHsv({ r, g, b, }: {
63
+ r: number;
64
+ g: number;
65
+ b: number;
66
+ }): [number, number, number];
67
+ export declare function hsvToRgb(h: number, s: number, v: number): {
68
+ r: number;
69
+ g: number;
70
+ b: number;
71
+ };
72
+ export declare function hexToHsv(hex: string): [number, number, number];
73
+ export declare function hsvToHex(h: number, s: number, v: number): string;
74
+ export declare function hex8ToRgba(hex: string): {
75
+ r: number;
76
+ g: number;
77
+ b: number;
78
+ a: number;
79
+ } | null;
80
+ export declare function rgbaToHex8({ r, g, b, a }: {
81
+ r: number;
82
+ g: number;
83
+ b: number;
84
+ a: number;
85
+ }): string;
86
+ export declare function rgbToCmyk({ r, g, b }: {
87
+ r: number;
88
+ g: number;
89
+ b: number;
90
+ }): {
91
+ c: number;
92
+ m: number;
93
+ y: number;
94
+ k: number;
95
+ };
96
+ export declare function cmykToRgb({ c, m, y, k }: {
97
+ c: number;
98
+ m: number;
99
+ y: number;
100
+ k: number;
101
+ }): {
102
+ r: number;
103
+ g: number;
104
+ b: number;
105
+ };
106
+ export declare function rgbToLab({ r, g, b }: {
107
+ r: number;
108
+ g: number;
109
+ b: number;
110
+ }): {
111
+ L: number;
112
+ a: number;
113
+ b: number;
114
+ };
115
+ export declare function labToRgb({ L, a, b }: {
116
+ L: number;
117
+ a: number;
118
+ b: number;
119
+ }): {
120
+ r: number;
121
+ g: number;
122
+ b: number;
123
+ };
124
+ export declare function rgbToLch({ r, g, b }: {
125
+ r: number;
126
+ g: number;
127
+ b: number;
128
+ }): {
129
+ L: number;
130
+ C: number;
131
+ H: number;
132
+ };
133
+ export declare function lchToRgb({ L, C, H }: {
134
+ L: number;
135
+ C: number;
136
+ H: number;
137
+ }): {
138
+ r: number;
139
+ g: number;
140
+ b: number;
141
+ };
142
+ export declare function rgbToHwb({ r, g, b, }: {
143
+ r: number;
144
+ g: number;
145
+ b: number;
146
+ }): [number, number, number];
147
+ export declare function hwbToRgb(H: number, W: number, B: number): {
148
+ r: number;
149
+ g: number;
150
+ b: number;
151
+ };
152
+ export declare function toHwbString(H: number, W: number, B: number, alpha?: number): string;
153
+ export declare function rgbToOklab({ r, g, b }: {
154
+ r: number;
155
+ g: number;
156
+ b: number;
157
+ }): {
158
+ L: number;
159
+ a: number;
160
+ b: number;
161
+ };
162
+ export declare function oklabToRgb({ L, a, b }: {
163
+ L: number;
164
+ a: number;
165
+ b: number;
166
+ }): {
167
+ r: number;
168
+ g: number;
169
+ b: number;
170
+ };
171
+ export declare function rgbToOklch({ r, g, b }: {
172
+ r: number;
173
+ g: number;
174
+ b: number;
175
+ }): {
176
+ L: number;
177
+ C: number;
178
+ H: number;
179
+ };
180
+ export declare function oklchToRgb({ L, C, H }: {
181
+ L: number;
182
+ C: number;
183
+ H: number;
184
+ }): {
185
+ r: number;
186
+ g: number;
187
+ b: number;
188
+ };
189
+ export declare function toHslString(h: number, s: number, l: number, alpha?: number): string;