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.
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 -1450
  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 -1352
  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 -1452
package/dist/cjs/index.js CHANGED
@@ -1,1452 +1,22 @@
1
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.rgbToDisplayP3 = rgbToDisplayP3;
15
- exports.displayP3ToRgb = displayP3ToRgb;
16
- exports.toDisplayP3Hex = toDisplayP3Hex;
17
- exports.shortHexToRgba = shortHexToRgba;
18
- exports.normalizeHex = normalizeHex;
19
- exports.hexToRgb = hexToRgb;
20
- exports.hexToRgba = hexToRgba;
21
- exports.hexToHsl = hexToHsl;
22
- exports.hslToHex = hslToHex;
23
- exports.adjustHexBrightness = adjustHexBrightness;
24
- exports.rotateHue = rotateHue;
25
- exports.lighten = lighten;
26
- exports.darken = darken;
27
- exports.saturate = saturate;
28
- exports.desaturate = desaturate;
29
- exports.setAlpha = setAlpha;
30
- exports.getAlpha = getAlpha;
31
- exports.invertColor = invertColor;
32
- exports.grayscale = grayscale;
33
- exports.rgbToHex = rgbToHex;
34
- exports.rgbaToHex = rgbaToHex;
35
- exports.rgbToRgbaString = rgbToRgbaString;
36
- exports.rgbaStringToRgba = rgbaStringToRgba;
37
- exports.rgbToHsl = rgbToHsl;
38
- exports.hslToRgb = hslToRgb;
39
- exports.rgbToHsv = rgbToHsv;
40
- exports.hsvToRgb = hsvToRgb;
41
- exports.hexToHsv = hexToHsv;
42
- exports.hsvToHex = hsvToHex;
43
- exports.hex8ToRgba = hex8ToRgba;
44
- exports.rgbaToHex8 = rgbaToHex8;
45
- exports.normalizeColor = normalizeColor;
46
- exports.complement = complement;
47
- exports.triadic = triadic;
48
- exports.analogous = analogous;
49
- exports.splitComplementary = splitComplementary;
50
- exports.tetradic = tetradic;
51
- exports.colorShades = colorShades;
52
- exports.monochromatic = monochromatic;
53
- exports.mixColors = mixColors;
54
- exports.relativeLuminance = relativeLuminance;
55
- exports.contrastRatio = contrastRatio;
56
- exports.isDark = isDark;
57
- exports.isLight = isLight;
58
- exports.rgbToCmyk = rgbToCmyk;
59
- exports.cmykToRgb = cmykToRgb;
60
- exports.rgbToLab = rgbToLab;
61
- exports.labToRgb = labToRgb;
62
- exports.rgbToLch = rgbToLch;
63
- exports.lchToRgb = lchToRgb;
64
- exports.wcagLevel = wcagLevel;
65
- exports.bestTextColor = bestTextColor;
66
- exports.bestContrastColor = bestContrastColor;
67
- exports.rgbToHwb = rgbToHwb;
68
- exports.hwbToRgb = hwbToRgb;
69
- exports.toHwbString = toHwbString;
70
- exports.parseHwbString = parseHwbString;
71
- exports.rgbToOklab = rgbToOklab;
72
- exports.oklabToRgb = oklabToRgb;
73
- exports.rgbToOklch = rgbToOklch;
74
- exports.oklchToRgb = oklchToRgb;
75
- exports.toHslString = toHslString;
76
- exports.colorDeltaE = colorDeltaE;
77
- exports.randomColor = randomColor;
78
- exports.toNearestNamedColor = toNearestNamedColor;
79
- exports.toOklchString = toOklchString;
80
- exports.toColorP3String = toColorP3String;
81
- exports.interpolateColors = interpolateColors;
82
- exports.createColorScale = createColorScale;
83
- exports.midpointColor = midpointColor;
84
- exports.tints = tints;
85
- exports.shades = shades;
86
- exports.tones = tones;
87
- exports.simulateProtanopia = simulateProtanopia;
88
- exports.simulateDeuteranopia = simulateDeuteranopia;
89
- exports.simulateTritanopia = simulateTritanopia;
90
- exports.simulateColorBlindness = simulateColorBlindness;
91
- exports.isReadableOnBackground = isReadableOnBackground;
92
- exports.bestContrastPalette = bestContrastPalette;
93
- exports.clearColorCache = clearColorCache;
94
- exports.getCacheStats = getCacheStats;
95
- exports.enableCache = enableCache;
96
- exports.disableCache = disableCache;
97
- exports.normalizeColorCached = normalizeColorCached;
98
- exports.generateGradientColors = generateGradientColors;
99
- exports.generateTints = generateTints;
100
- exports.generateShades = generateShades;
101
- const NAMED_COLORS = {
102
- aliceblue: '#f0f8ff', antiquewhite: '#faebd7', aqua: '#00ffff', aquamarine: '#7fffd4', azure: '#f0ffff',
103
- beige: '#f5f5dc', bisque: '#ffe4c4', black: '#000000', blanchedalmond: '#ffebcd', blue: '#0000ff',
104
- blueviolet: '#8a2be2', brown: '#a52a2a', burlywood: '#deb887', cadetblue: '#5f9ea0', chartreuse: '#7fff00',
105
- chocolate: '#d2691e', coral: '#ff7f50', cornflowerblue: '#6495ed', cornsilk: '#fff8dc', crimson: '#dc143c',
106
- cyan: '#00ffff', darkblue: '#00008b', darkcyan: '#008b8b', darkgoldenrod: '#b8860b', darkgray: '#a9a9a9',
107
- darkgreen: '#006400', darkgrey: '#a9a9a9', darkkhaki: '#bdb76b', darkmagenta: '#8b008b', darkolivegreen: '#556b2f',
108
- darkorange: '#ff8c00', darkorchid: '#9932cc', darkred: '#8b0000', darksalmon: '#e9967a', darkseagreen: '#8fbc8f',
109
- darkslateblue: '#483d8b', darkslategray: '#2f4f4f', darkslategrey: '#2f4f4f', darkturquoise: '#00ced1',
110
- darkviolet: '#9400d3', deeppink: '#ff1493', deepskyblue: '#00bfff', dimgray: '#696969', dimgrey: '#696969',
111
- dodgerblue: '#1e90ff', firebrick: '#b22222', floralwhite: '#fffaf0', forestgreen: '#228b22', fuchsia: '#ff00ff',
112
- gainsboro: '#dcdcdc', ghostwhite: '#f8f8ff', gold: '#ffd700', goldenrod: '#daa520', gray: '#808080',
113
- green: '#008000', greenyellow: '#adff2f', grey: '#808080', honeydew: '#f0fff0', hotpink: '#ff69b4',
114
- indianred: '#cd5c5c', indigo: '#4b0082', ivory: '#fffff0', khaki: '#f0e68c', lavender: '#e6e6fa',
115
- lavenderblush: '#fff0f5', lawngreen: '#7cfc00', lemonchiffon: '#fffacd', lightblue: '#add8e6', lightcoral: '#f08080',
116
- lightcyan: '#e0ffff', lightgoldenrodyellow: '#fafad2', lightgray: '#d3d3d3', lightgreen: '#90ee90',
117
- lightgrey: '#d3d3d3', lightpink: '#ffb6c1', lightsalmon: '#ffa07a', lightseagreen: '#20b2aa', lightskyblue: '#87cefa',
118
- lightslategray: '#778899', lightslategrey: '#778899', lightsteelblue: '#b0c4de', lightyellow: '#ffffe0',
119
- lime: '#00ff00', limegreen: '#32cd32', linen: '#faf0e6', magenta: '#ff00ff', maroon: '#800000',
120
- mediumaquamarine: '#66cdaa', mediumblue: '#0000cd', mediumorchid: '#ba55d3', mediumpurple: '#9370db',
121
- mediumseagreen: '#3cb371', mediumslateblue: '#7b68ee', mediumspringgreen: '#00fa9a', mediumturquoise: '#48d1cc',
122
- mediumvioletred: '#c71585', midnightblue: '#191970', mintcream: '#f5fffa', mistyrose: '#ffe4e1', moccasin: '#ffe4b5',
123
- navajowhite: '#ffdead', navy: '#000080', oldlace: '#fdf5e6', olive: '#808000', olivedrab: '#6b8e23',
124
- orange: '#ffa500', orangered: '#ff4500', orchid: '#da70d6', palegoldenrod: '#eee8aa', palegreen: '#98fb98',
125
- paleturquoise: '#afeeee', palevioletred: '#db7093', papayawhip: '#ffefd5', peachpuff: '#ffdab9', peru: '#cd853f',
126
- pink: '#ffc0cb', plum: '#dda0dd', powderblue: '#b0e0e6', purple: '#800080', rebeccapurple: '#663399',
127
- red: '#ff0000', rosybrown: '#bc8f8f', royalblue: '#4169e1', saddlebrown: '#8b4513', salmon: '#fa8072',
128
- sandybrown: '#f4a460', seagreen: '#2e8b57', seashell: '#fff5ee', sienna: '#a0522d', silver: '#c0c0c0',
129
- skyblue: '#87ceeb', slateblue: '#6a5acd', slategray: '#708090', slategrey: '#708090', snow: '#fffafa',
130
- springgreen: '#00ff7f', steelblue: '#4682b4', tan: '#d2b48c', teal: '#008080', thistle: '#d8bfd8',
131
- tomato: '#ff6347', turquoise: '#40e0d0', violet: '#ee82ee', wheat: '#f5deb3', white: '#ffffff',
132
- whitesmoke: '#f5f5f5', yellow: '#ffff00', yellowgreen: '#9acd32',
133
- // 'transparent' is the only CSS-wide keyword with an actual fixed color (fully
134
- // transparent black) — normalizeColor() special-cases it before ever reaching
135
- // this table (see the `str === 'transparent'` check), so this entry only
136
- // matters for getColorType()/toNearestNamedColor(), which read the table
137
- // directly. 'currentcolor'/'inherit'/'initial'/'unset' are deliberately NOT
138
- // listed here: none of them has a color value of their own (they only resolve
139
- // to one given surrounding DOM/CSSOM context this library never has access
140
- // to), so treating them as resolvable named colors would mean fabricating an
141
- // arbitrary RGB value with no way for a caller to tell it apart from a real
142
- // one — see normalizeColor()'s `type: 'unknown'` fallback for these instead.
143
- transparent: 'transparent',
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);
144
15
  };
145
- function isCssVariable(value) {
146
- return value.trim().startsWith('var(--');
147
- }
148
- function isHexColor(value) {
149
- const trimmed = value.trim();
150
- return /^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(trimmed);
151
- }
152
- function isOklchColor(value) {
153
- return /^\s*oklcha?\s*\(/i.test(value.trim());
154
- }
155
- function isColorFunction(value) {
156
- return /^\s*color\s*\(\s*(display-p3|srgb|srgb-linear)\s/i.test(value.trim());
157
- }
158
- function isRgbColor(value) {
159
- const trimmed = value.trim().toLowerCase();
160
- return trimmed.startsWith('rgb(') || trimmed.startsWith('rgba(');
161
- }
162
- function isHslColor(value) {
163
- const trimmed = value.trim().toLowerCase();
164
- return trimmed.startsWith('hsl(') || trimmed.startsWith('hsla(');
165
- }
166
- function getColorType(value) {
167
- const trimmed = value.trim();
168
- const lower = trimmed.toLowerCase();
169
- if (isCssVariable(trimmed))
170
- return 'css-var';
171
- if (isHexColor(trimmed))
172
- return 'hex';
173
- if (isRgbColor(trimmed))
174
- return 'rgb';
175
- if (isHslColor(trimmed))
176
- return 'hsl';
177
- if (isOklchColor(trimmed))
178
- return 'oklch';
179
- if (isColorFunction(trimmed))
180
- return 'color';
181
- if (lower in NAMED_COLORS)
182
- return 'named';
183
- return 'unknown';
184
- }
185
- function extractCssVariableName(value) {
186
- var _a;
187
- const match = value.match(/var\(\s*(--[^,)]+)/);
188
- return ((_a = match === null || match === void 0 ? void 0 : match[1]) === null || _a === void 0 ? void 0 : _a.trim()) || value;
189
- }
190
- function parseCssVar(value) {
191
- var _a;
192
- const m = value.trim().match(/^var\(\s*(--[^,)]+)(?:,\s*([\s\S]+?))?\s*\)$/);
193
- if (!m)
194
- return null;
195
- return { variableName: m[1].trim(), fallback: (_a = m[2]) === null || _a === void 0 ? void 0 : _a.trim() };
196
- }
197
- // ─── Section 1.1 — OKLCH / color() CSS string parsing ────────────────────────
198
- function parseOklchString(str) {
199
- const m = str.trim().match(/oklcha?\(\s*([\d.]+%?)\s+([\d.]+)\s+([\d.]+)(?:\s*\/\s*([\d.]+))?\s*\)/i);
200
- if (!m)
201
- return null;
202
- let L = parseFloat(m[1]);
203
- if (m[1].endsWith('%'))
204
- L = L / 100;
205
- const C = parseFloat(m[2]);
206
- const H = parseFloat(m[3]);
207
- const alpha = m[4] !== undefined ? parseFloat(m[4]) : 1;
208
- return { L, C, H, alpha };
209
- }
210
- function parseColorFn(str) {
211
- const m = str.trim().match(/color\(\s*([\w-]+)\s+([\d.]+%?)\s+([\d.]+%?)\s+([\d.]+%?)(?:\s*\/\s*([\d.]+))?\s*\)/i);
212
- if (!m)
213
- return null;
214
- const space = m[1].toLowerCase();
215
- const parseVal = (v) => v.endsWith('%') ? parseFloat(v) / 100 : parseFloat(v);
216
- const r = parseVal(m[2]);
217
- const g = parseVal(m[3]);
218
- const b = parseVal(m[4]);
219
- const alpha = m[5] !== undefined ? parseFloat(m[5]) : 1;
220
- return { space, r, g, b, alpha };
221
- }
222
- // ─── Section 1.2 — Display P3 ────────────────────────────────────────────────
223
- function rgbToDisplayP3(rgb) {
224
- // Remove sRGB gamma (linearize)
225
- const rl = srgbChanToLinear(rgb.r / 255);
226
- const gl = srgbChanToLinear(rgb.g / 255);
227
- const bl = srgbChanToLinear(rgb.b / 255);
228
- // sRGB-linear → P3-linear matrix
229
- const pr = 0.8226 * rl + 0.1774 * gl + 0.0000 * bl;
230
- const pg = 0.0332 * rl + 0.9669 * gl + 0.0000 * bl;
231
- const pb = 0.0171 * rl + 0.0724 * gl + 0.9103 * bl;
232
- // Apply P3 gamma (same as sRGB)
233
- return {
234
- r: linearChanToSrgb(pr),
235
- g: linearChanToSrgb(pg),
236
- b: linearChanToSrgb(pb),
237
- };
238
- }
239
- function displayP3ToRgb(p3) {
240
- // Remove P3 gamma
241
- const rl = srgbChanToLinear(p3.r);
242
- const gl = srgbChanToLinear(p3.g);
243
- const bl = srgbChanToLinear(p3.b);
244
- // P3-linear → sRGB-linear inverse matrix
245
- const sr = 1.2247 * rl + (-0.2247) * gl + 0.0000 * bl;
246
- const sg = (-0.0421) * rl + 1.0432 * gl + 0.0000 * bl;
247
- const sb = (-0.0197) * rl + (-0.0786) * gl + 1.0983 * bl;
248
- // Apply sRGB gamma and scale to 0-255
249
- return {
250
- r: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sr) * 255))),
251
- g: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sg) * 255))),
252
- b: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sb) * 255))),
253
- };
254
- }
255
- // Helpers for Display P3 (operate on 0-1 values)
256
- function srgbChanToLinear(v) {
257
- return v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
258
- }
259
- function linearChanToSrgb(v) {
260
- const t = v <= 0.0031308 ? 12.92 * v : 1.055 * Math.pow(v, 1 / 2.4) - 0.055;
261
- return Math.max(0, Math.min(1, t));
262
- }
263
- function toDisplayP3Hex(color) {
264
- const n = normalizeColorRaw(color);
265
- const p3 = rgbToDisplayP3({ r: n.r, g: n.g, b: n.b });
266
- return rgbToHex({
267
- r: Math.round(Math.max(0, Math.min(255, p3.r * 255))),
268
- g: Math.round(Math.max(0, Math.min(255, p3.g * 255))),
269
- b: Math.round(Math.max(0, Math.min(255, p3.b * 255))),
270
- });
271
- }
272
- // Internal raw normalizer (no cache, no circular dep issues)
273
- function normalizeColorRaw(color) {
274
- var _a, _b, _c, _d;
275
- const n = normalizeColor(color);
276
- 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 };
277
- }
278
- // ─── Section 1.3 — Short RGBA hex #RGBA ──────────────────────────────────────
279
- function shortHexToRgba(hex) {
280
- let h = hex.trim();
281
- if (!h.startsWith('#'))
282
- h = `#${h}`;
283
- if (!/^#[0-9a-f]{4}$/i.test(h))
284
- return null;
285
- const r = parseInt(h[1] + h[1], 16);
286
- const g = parseInt(h[2] + h[2], 16);
287
- const b = parseInt(h[3] + h[3], 16);
288
- const a = parseInt(h[4] + h[4], 16) / 255;
289
- return { r, g, b, a };
290
- }
291
- function normalizeHex(hex) {
292
- let cleanHex = hex.trim();
293
- if (!cleanHex.startsWith('#'))
294
- cleanHex = `#${cleanHex}`;
295
- if (cleanHex.length === 4) {
296
- cleanHex = `#${cleanHex.slice(1).split('').map(c => c + c).join('')}`;
297
- }
298
- if (!/^#[0-9A-Fa-f]{6}$/.test(cleanHex)) {
299
- return '#f5e477';
300
- }
301
- return cleanHex.toLowerCase();
302
- }
303
- function hexToRgb(hex) {
304
- const normalizedHex = normalizeHex(hex);
305
- const r = parseInt(normalizedHex.slice(1, 3), 16);
306
- const g = parseInt(normalizedHex.slice(3, 5), 16);
307
- const b = parseInt(normalizedHex.slice(5, 7), 16);
308
- return [r, g, b];
309
- }
310
- function hexToRgba(hex, opacity = 1) {
311
- const [r, g, b] = hexToRgb(hex);
312
- return `rgba(${r}, ${g}, ${b}, ${opacity})`;
313
- }
314
- function hexToHsl(hex) {
315
- const [r, g, b] = hexToRgb(hex);
316
- const red = r / 255;
317
- const green = g / 255;
318
- const blue = b / 255;
319
- const max = Math.max(red, green, blue);
320
- const min = Math.min(red, green, blue);
321
- let h = 0, s = 0;
322
- const l = (max + min) / 2;
323
- if (max !== min) {
324
- const d = max - min;
325
- s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
326
- switch (max) {
327
- case red:
328
- h = (green - blue) / d + (green < blue ? 6 : 0);
329
- break;
330
- case green:
331
- h = (blue - red) / d + 2;
332
- break;
333
- case blue:
334
- h = (red - green) / d + 4;
335
- break;
336
- }
337
- h /= 6;
338
- }
339
- return [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100)];
340
- }
341
- function hslToHex(h, s, l) {
342
- h = ((h % 360) + 360) % 360;
343
- s = Math.max(0, Math.min(100, s)) / 100;
344
- l = Math.max(0, Math.min(100, l)) / 100;
345
- const c = (1 - Math.abs(2 * l - 1)) * s;
346
- const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
347
- const m = l - c / 2;
348
- let r = 0, g = 0, b = 0;
349
- if (h >= 0 && h < 60) {
350
- r = c;
351
- g = x;
352
- b = 0;
353
- }
354
- else if (h >= 60 && h < 120) {
355
- r = x;
356
- g = c;
357
- b = 0;
358
- }
359
- else if (h >= 120 && h < 180) {
360
- r = 0;
361
- g = c;
362
- b = x;
363
- }
364
- else if (h >= 180 && h < 240) {
365
- r = 0;
366
- g = x;
367
- b = c;
368
- }
369
- else if (h >= 240 && h < 300) {
370
- r = x;
371
- g = 0;
372
- b = c;
373
- }
374
- else {
375
- r = c;
376
- g = 0;
377
- b = x;
378
- }
379
- r = Math.round((r + m) * 255);
380
- g = Math.round((g + m) * 255);
381
- b = Math.round((b + m) * 255);
382
- return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
383
- }
384
- function adjustHexBrightness(hex, offsetPercent) {
385
- const normalizedHex = normalizeHex(hex);
386
- const p = Math.max(-100, Math.min(100, offsetPercent)) / 100;
387
- const r = parseInt(normalizedHex.slice(1, 3), 16);
388
- const g = parseInt(normalizedHex.slice(3, 5), 16);
389
- const b = parseInt(normalizedHex.slice(5, 7), 16);
390
- const adjustChannel = (channel) => {
391
- if (p > 0)
392
- return Math.min(255, Math.floor(channel + (255 - channel) * p));
393
- else if (p < 0)
394
- return Math.max(0, Math.floor(channel * (1 + p)));
395
- return channel;
396
- };
397
- const newR = adjustChannel(r);
398
- const newG = adjustChannel(g);
399
- const newB = adjustChannel(b);
400
- return `#${newR.toString(16).padStart(2, '0')}${newG.toString(16).padStart(2, '0')}${newB.toString(16).padStart(2, '0')}`;
401
- }
402
- function rotateHue(hex, degrees) {
403
- const [h, s, l] = hexToHsl(hex);
404
- const newH = ((h + degrees) % 360 + 360) % 360;
405
- return hslToHex(newH, s, l);
406
- }
407
- function lighten(color, amount) {
408
- var _a, _b, _c;
409
- const n = normalizeColor(color);
410
- const h = (_a = n.h) !== null && _a !== void 0 ? _a : 0;
411
- const s = (_b = n.s) !== null && _b !== void 0 ? _b : 0;
412
- const l = Math.min(100, ((_c = n.l) !== null && _c !== void 0 ? _c : 0) + amount);
413
- return hslToHex(h, s, l);
414
- }
415
- function darken(color, amount) {
416
- var _a, _b, _c;
417
- const n = normalizeColor(color);
418
- const h = (_a = n.h) !== null && _a !== void 0 ? _a : 0;
419
- const s = (_b = n.s) !== null && _b !== void 0 ? _b : 0;
420
- const l = Math.max(0, ((_c = n.l) !== null && _c !== void 0 ? _c : 0) - amount);
421
- return hslToHex(h, s, l);
422
- }
423
- function saturate(color, amount) {
424
- var _a, _b, _c;
425
- const n = normalizeColor(color);
426
- const h = (_a = n.h) !== null && _a !== void 0 ? _a : 0;
427
- const s = Math.min(100, ((_b = n.s) !== null && _b !== void 0 ? _b : 0) + amount);
428
- const l = (_c = n.l) !== null && _c !== void 0 ? _c : 0;
429
- return hslToHex(h, s, l);
430
- }
431
- function desaturate(color, amount) {
432
- var _a, _b, _c;
433
- const n = normalizeColor(color);
434
- const h = (_a = n.h) !== null && _a !== void 0 ? _a : 0;
435
- const s = Math.max(0, ((_b = n.s) !== null && _b !== void 0 ? _b : 0) - amount);
436
- const l = (_c = n.l) !== null && _c !== void 0 ? _c : 0;
437
- return hslToHex(h, s, l);
438
- }
439
- function setAlpha(color, alpha) {
440
- var _a, _b, _c;
441
- const n = normalizeColor(color);
442
- const r = (_a = n.r) !== null && _a !== void 0 ? _a : 0;
443
- const g = (_b = n.g) !== null && _b !== void 0 ? _b : 0;
444
- const b = (_c = n.b) !== null && _c !== void 0 ? _c : 0;
445
- const a = Math.max(0, Math.min(1, alpha));
446
- return `rgba(${r}, ${g}, ${b}, ${+a.toFixed(3)})`;
447
- }
448
- function getAlpha(color) {
449
- var _a;
450
- const n = normalizeColor(color);
451
- return (_a = n.a) !== null && _a !== void 0 ? _a : 1;
452
- }
453
- function invertColor(color) {
454
- var _a, _b, _c;
455
- const n = normalizeColor(color);
456
- const r = 255 - ((_a = n.r) !== null && _a !== void 0 ? _a : 0);
457
- const g = 255 - ((_b = n.g) !== null && _b !== void 0 ? _b : 0);
458
- const b = 255 - ((_c = n.b) !== null && _c !== void 0 ? _c : 0);
459
- return rgbToHex({ r, g, b });
460
- }
461
- function grayscale(color) {
462
- var _a, _b, _c;
463
- const n = normalizeColor(color);
464
- const r = (_a = n.r) !== null && _a !== void 0 ? _a : 0;
465
- const g = (_b = n.g) !== null && _b !== void 0 ? _b : 0;
466
- const b = (_c = n.b) !== null && _c !== void 0 ? _c : 0;
467
- // Perceptual luminance weights (ITU-R BT.709)
468
- const gray = Math.round(0.2126 * r + 0.7152 * g + 0.0722 * b);
469
- return rgbToHex({ r: gray, g: gray, b: gray });
470
- }
471
- function clamp01(v) { return Math.max(0, Math.min(1, v)); }
472
- function toHex2(n) { return Math.round(n).toString(16).padStart(2, '0'); }
473
- function rgbToHex({ r, g, b }) {
474
- return `#${toHex2(r)}${toHex2(g)}${toHex2(b)}`.toLowerCase();
475
- }
476
- function rgbaToHex({ r, g, b, a }) {
477
- const aa = Math.round(clamp01(a) * 255);
478
- return `#${toHex2(r)}${toHex2(g)}${toHex2(b)}${toHex2(aa)}`.toLowerCase();
479
- }
480
- function rgbToRgbaString({ r, g, b }, a) {
481
- return `rgba(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)}, ${+a.toFixed(3)})`;
482
- }
483
- function rgbaStringToRgba(str) {
484
- const s = str.trim().toLowerCase();
485
- const m = s.match(/rgba?\(([^)]+)\)/);
486
- if (!m)
487
- return null;
488
- const parts = m[1].split(/,\s*/).map(p => p.trim());
489
- if (parts.length < 3)
490
- return null;
491
- // Clamp channels to a valid byte and alpha to [0,1] — an out-of-range input
492
- // like "rgb(300, -20, 0)" or "rgba(0,0,0,2)" is invalid CSS, but previously
493
- // passed straight through unclamped, which could even corrupt downstream hex
494
- // output (a negative channel stringifies with a leading "-" via toString(16)).
495
- const parseChannel = (v) => {
496
- const n = v.endsWith('%') ? parseFloat(v) * 2.55 : parseFloat(v);
497
- return Math.round(Math.max(0, Math.min(255, n)));
498
- };
499
- const r = parseChannel(parts[0]);
500
- const g = parseChannel(parts[1]);
501
- const b = parseChannel(parts[2]);
502
- const a = parts[3] !== undefined ? Math.max(0, Math.min(1, parseFloat(parts[3]))) : 1;
503
- return { r, g, b, a };
504
- }
505
- function rgbToHsl({ r, g, b }) {
506
- const rd = r / 255, gd = g / 255, bd = b / 255;
507
- const max = Math.max(rd, gd, bd), min = Math.min(rd, gd, bd);
508
- let h = 0, s = 0;
509
- const l = (max + min) / 2;
510
- if (max !== min) {
511
- const d = max - min;
512
- s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
513
- switch (max) {
514
- case rd:
515
- h = (gd - bd) / d + (gd < bd ? 6 : 0);
516
- break;
517
- case gd:
518
- h = (bd - rd) / d + 2;
519
- break;
520
- case bd:
521
- h = (rd - gd) / d + 4;
522
- break;
523
- }
524
- h /= 6;
525
- }
526
- return [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100)];
527
- }
528
- function hslToRgb(h, s, l) {
529
- h = ((h % 360) + 360) % 360;
530
- s = Math.max(0, Math.min(100, s)) / 100;
531
- l = Math.max(0, Math.min(100, l)) / 100;
532
- const c = (1 - Math.abs(2 * l - 1)) * s;
533
- const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
534
- const m = l - c / 2;
535
- let rd = 0, gd = 0, bd = 0;
536
- if (h >= 0 && h < 60) {
537
- rd = c;
538
- gd = x;
539
- bd = 0;
540
- }
541
- else if (h >= 60 && h < 120) {
542
- rd = x;
543
- gd = c;
544
- bd = 0;
545
- }
546
- else if (h >= 120 && h < 180) {
547
- rd = 0;
548
- gd = c;
549
- bd = x;
550
- }
551
- else if (h >= 180 && h < 240) {
552
- rd = 0;
553
- gd = x;
554
- bd = c;
555
- }
556
- else if (h >= 240 && h < 300) {
557
- rd = x;
558
- gd = 0;
559
- bd = c;
560
- }
561
- else {
562
- rd = c;
563
- gd = 0;
564
- bd = x;
565
- }
566
- return { r: Math.round((rd + m) * 255), g: Math.round((gd + m) * 255), b: Math.round((bd + m) * 255) };
567
- }
568
- function rgbToHsv({ r, g, b }) {
569
- const rd = r / 255, gd = g / 255, bd = b / 255;
570
- const max = Math.max(rd, gd, bd), min = Math.min(rd, gd, bd);
571
- const v = max;
572
- const d = max - min;
573
- const s = max === 0 ? 0 : d / max;
574
- let h = 0;
575
- if (d !== 0) {
576
- switch (max) {
577
- case rd:
578
- h = (gd - bd) / d + (gd < bd ? 6 : 0);
579
- break;
580
- case gd:
581
- h = (bd - rd) / d + 2;
582
- break;
583
- case bd:
584
- h = (rd - gd) / d + 4;
585
- break;
586
- }
587
- h /= 6;
588
- }
589
- return [Math.round(h * 360), Math.round(s * 100), Math.round(v * 100)];
590
- }
591
- function hsvToRgb(h, s, v) {
592
- h = ((h % 360) + 360) % 360;
593
- s = Math.max(0, Math.min(100, s)) / 100;
594
- v = Math.max(0, Math.min(100, v)) / 100;
595
- const i = Math.floor(h / 60);
596
- const f = h / 60 - i;
597
- const p = v * (1 - s);
598
- const q = v * (1 - f * s);
599
- const t = v * (1 - (1 - f) * s);
600
- let rd = 0, gd = 0, bd = 0;
601
- switch (i) {
602
- case 0:
603
- rd = v;
604
- gd = t;
605
- bd = p;
606
- break;
607
- case 1:
608
- rd = q;
609
- gd = v;
610
- bd = p;
611
- break;
612
- case 2:
613
- rd = p;
614
- gd = v;
615
- bd = t;
616
- break;
617
- case 3:
618
- rd = p;
619
- gd = q;
620
- bd = v;
621
- break;
622
- case 4:
623
- rd = t;
624
- gd = p;
625
- bd = v;
626
- break;
627
- default:
628
- rd = v;
629
- gd = p;
630
- bd = q;
631
- break;
632
- }
633
- return { r: Math.round(rd * 255), g: Math.round(gd * 255), b: Math.round(bd * 255) };
634
- }
635
- function hexToHsv(hex) {
636
- const [r, g, b] = hexToRgb(hex);
637
- return rgbToHsv({ r, g, b });
638
- }
639
- function hsvToHex(h, s, v) {
640
- const { r, g, b } = hsvToRgb(h, s, v);
641
- return rgbToHex({ r, g, b });
642
- }
643
- function hex8ToRgba(hex) {
644
- let h = hex.trim();
645
- if (!h.startsWith('#'))
646
- h = `#${h}`;
647
- if (h.length === 5) { // #rgba shorthand
648
- h = `#${h[1]}${h[1]}${h[2]}${h[2]}${h[3]}${h[3]}${h[4]}${h[4]}`;
649
- }
650
- if (h.length !== 9)
651
- return null;
652
- const r = parseInt(h.slice(1, 3), 16);
653
- const g = parseInt(h.slice(3, 5), 16);
654
- const b = parseInt(h.slice(5, 7), 16);
655
- const a = parseInt(h.slice(7, 9), 16) / 255;
656
- return { r, g, b, a };
657
- }
658
- function rgbaToHex8({ r, g, b, a }) {
659
- return rgbaToHex({ r, g, b, a });
660
- }
661
- function normalizeColor(input) {
662
- if (typeof input !== 'string') {
663
- if ('r' in input && 'g' in input && 'b' in input) {
664
- const { r, g, b } = input;
665
- const hex = rgbToHex({ r, g, b });
666
- const [h, s, l] = rgbToHsl({ r, g, b });
667
- const [hh, ss, vv] = rgbToHsv({ r, g, b });
668
- return { type: 'rgb', hex, r, g, b, a: 1, h, s, l, v: vv };
669
- }
670
- if ('h' in input && 's' in input && 'l' in input) {
671
- const { h, s, l } = input;
672
- const { r, g, b } = hslToRgb(h, s, l);
673
- const hex = rgbToHex({ r, g, b });
674
- const [hh, ss, vv] = rgbToHsv({ r, g, b });
675
- return { type: 'hsl', hex, r, g, b, a: 1, h, s, l, v: vv };
676
- }
677
- return { type: 'unknown' };
678
- }
679
- const str = input.trim();
680
- if (isCssVariable(str))
681
- return { type: 'css-var', raw: str };
682
- // 8-digit (#rrggbbaa) or 4-digit (#rgba) — check before isHexColor
683
- const hex8 = str.match(/^#([0-9a-f]{8}|[0-9a-f]{4})$/i);
684
- if (hex8) {
685
- const rgba = hex8ToRgba(str);
686
- if (rgba) {
687
- const { r, g, b, a } = rgba;
688
- const hex = rgbToHex({ r, g, b });
689
- const [h, s, l] = rgbToHsl({ r, g, b });
690
- const [hh, ss, vv] = rgbToHsv({ r, g, b });
691
- return { type: 'hex', hex, r, g, b, a, h, s, l, v: vv };
692
- }
693
- }
694
- if (isHexColor(str)) {
695
- const hex = normalizeHex(str);
696
- const [r, g, b] = hexToRgb(hex);
697
- const [h, s, l] = hexToHsl(hex);
698
- const [hh, ss, vv] = rgbToHsv({ r, g, b });
699
- return { type: 'hex', hex, r, g, b, a: 1, h, s, l, v: vv };
700
- }
701
- if (isRgbColor(str)) {
702
- const rgba = rgbaStringToRgba(str);
703
- if (rgba) {
704
- const { r, g, b, a } = rgba;
705
- const hex = rgbToHex({ r, g, b });
706
- const [h, s, l] = rgbToHsl({ r, g, b });
707
- const [hh, ss, vv] = rgbToHsv({ r, g, b });
708
- return { type: 'rgb', hex, r, g, b, a, h, s, l, v: vv };
709
- }
710
- }
711
- if (isHslColor(str)) {
712
- const m = str.match(/hsla?\(([^)]+)\)/i);
713
- if (m) {
714
- const parts = m[1].split(/,\s*/);
715
- const h = parseFloat(parts[0]);
716
- const s = parseFloat(parts[1]);
717
- const l = parseFloat(parts[2]);
718
- const a = parts[3] ? parseFloat(parts[3]) : 1;
719
- const { r, g, b } = hslToRgb(h, s, l);
720
- const hex = rgbToHex({ r, g, b });
721
- const [hh, ss, vv] = rgbToHsv({ r, g, b });
722
- return { type: 'hsl', hex, r, g, b, a, h, s, l, v: vv };
723
- }
724
- }
725
- if (str === 'transparent')
726
- return { type: 'named', hex: '#000000', r: 0, g: 0, b: 0, a: 0 };
727
- const lowerStr = str.toLowerCase();
728
- if (lowerStr in NAMED_COLORS) {
729
- const hex = NAMED_COLORS[lowerStr];
730
- const [r, g, b] = hexToRgb(hex);
731
- const [h, s, l] = hexToHsl(hex);
732
- const [, , vv] = rgbToHsv({ r, g, b });
733
- return { type: 'named', hex, r, g, b, a: 1, h, s, l, v: vv };
734
- }
735
- // oklch / oklcha
736
- if (isOklchColor(str)) {
737
- const parsed = parseOklchString(str);
738
- if (parsed) {
739
- const { r, g, b } = oklchToRgb({ L: parsed.L, C: parsed.C, H: parsed.H });
740
- const hex = rgbToHex({ r, g, b });
741
- const [h, s, l] = rgbToHsl({ r, g, b });
742
- const [, , vv] = rgbToHsv({ r, g, b });
743
- return { type: 'oklch', hex, r, g, b, a: parsed.alpha, h, s, l, v: vv };
744
- }
745
- }
746
- // color(display-p3 ...) / color(srgb ...)
747
- if (isColorFunction(str)) {
748
- const parsed = parseColorFn(str);
749
- if (parsed) {
750
- const { r: p3r, g: p3g, b: p3b, alpha } = parsed;
751
- // Convert from p3/srgb (0-1) to sRGB 0-255
752
- let r, g, b;
753
- if (parsed.space === 'display-p3') {
754
- const srgb = displayP3ToRgb({ r: p3r, g: p3g, b: p3b });
755
- r = srgb.r;
756
- g = srgb.g;
757
- b = srgb.b;
758
- }
759
- else if (parsed.space === 'srgb-linear') {
760
- // srgb-linear components are linear-light, not gamma-encoded — unlike
761
- // plain srgb below, they need the linear-to-sRGB transfer function
762
- // applied before scaling to a 0-255 byte. Without this, only the 0/1
763
- // extremes happened to come out correct; any mid-range value (e.g. 0.5)
764
- // converted as if it were already gamma-encoded, which is wrong.
765
- r = Math.round(linearChanToSrgb(p3r) * 255);
766
- g = Math.round(linearChanToSrgb(p3g) * 255);
767
- b = Math.round(linearChanToSrgb(p3b) * 255);
768
- }
769
- else {
770
- r = Math.round(Math.max(0, Math.min(255, p3r * 255)));
771
- g = Math.round(Math.max(0, Math.min(255, p3g * 255)));
772
- b = Math.round(Math.max(0, Math.min(255, p3b * 255)));
773
- }
774
- const hex = rgbToHex({ r, g, b });
775
- const [h, s, l] = rgbToHsl({ r, g, b });
776
- const [, , vv] = rgbToHsv({ r, g, b });
777
- return { type: 'color', hex, r, g, b, a: alpha, h, s, l, v: vv };
778
- }
779
- }
780
- return { type: 'unknown' };
781
- }
782
- function complement(color) {
783
- var _a;
784
- return rotateHue((_a = normalizeColor(color).hex) !== null && _a !== void 0 ? _a : '#000000', 180);
785
- }
786
- function triadic(color) {
787
- var _a;
788
- const hex = (_a = normalizeColor(color).hex) !== null && _a !== void 0 ? _a : '#000000';
789
- return [hex, rotateHue(hex, 120), rotateHue(hex, 240)];
790
- }
791
- function analogous(color, angle = 30) {
792
- var _a;
793
- const hex = (_a = normalizeColor(color).hex) !== null && _a !== void 0 ? _a : '#000000';
794
- return [rotateHue(hex, -angle), hex, rotateHue(hex, angle)];
795
- }
796
- function splitComplementary(color) {
797
- var _a;
798
- const hex = (_a = normalizeColor(color).hex) !== null && _a !== void 0 ? _a : '#000000';
799
- return [hex, rotateHue(hex, 150), rotateHue(hex, 210)];
800
- }
801
- function tetradic(color) {
802
- var _a;
803
- const hex = (_a = normalizeColor(color).hex) !== null && _a !== void 0 ? _a : '#000000';
804
- return [hex, rotateHue(hex, 90), rotateHue(hex, 180), rotateHue(hex, 270)];
805
- }
806
- function colorShades(color, steps = 9) {
807
- var _a, _b, _c;
808
- const n = normalizeColor(color);
809
- const h = (_a = n.h) !== null && _a !== void 0 ? _a : 0;
810
- const s = (_b = n.s) !== null && _b !== void 0 ? _b : 0;
811
- // steps - 1 === 0 below would otherwise divide by zero (NaN lightness, then
812
- // a literal "#NaNNaNNaN" hex string) — a single shade is just the color's
813
- // own lightness, same idea as interpolateColors() returning the midpoint
814
- // for a 2-color, 1-step request.
815
- if (steps <= 1)
816
- return steps === 1 ? [hslToHex(h, s, (_c = n.l) !== null && _c !== void 0 ? _c : 50)] : [];
817
- const result = [];
818
- for (let i = 0; i < steps; i++) {
819
- const l = Math.round(100 - (i / (steps - 1)) * 100);
820
- result.push(hslToHex(h, s, l));
821
- }
822
- return result;
823
- }
824
- function monochromatic(color, steps = 5) {
825
- var _a, _b, _c;
826
- const n = normalizeColor(color);
827
- const h = (_a = n.h) !== null && _a !== void 0 ? _a : 0;
828
- const l = (_b = n.l) !== null && _b !== void 0 ? _b : 50;
829
- // Same steps === 1 divide-by-zero guard as colorShades() above.
830
- if (steps <= 1)
831
- return steps === 1 ? [hslToHex(h, (_c = n.s) !== null && _c !== void 0 ? _c : 0, l)] : [];
832
- const result = [];
833
- for (let i = 0; i < steps; i++) {
834
- const s = Math.round((i / (steps - 1)) * 100);
835
- result.push(hslToHex(h, s, l));
836
- }
837
- return result;
838
- }
839
- function _lerpHue(h1, h2, t, mode = 'shorter') {
840
- let d = h2 - h1;
841
- if (mode === 'shorter') {
842
- if (d > 180)
843
- d -= 360;
844
- else if (d < -180)
845
- d += 360;
846
- }
847
- else if (mode === 'longer') {
848
- if (d > 0 && d < 180)
849
- d -= 360;
850
- else if (d < 0 && d > -180)
851
- d += 360;
852
- }
853
- else if (mode === 'increasing') {
854
- if (d < 0)
855
- d += 360;
856
- }
857
- else if (mode === 'decreasing') {
858
- if (d > 0)
859
- d -= 360;
860
- }
861
- return h1 + d * t;
862
- }
863
- function _formatMixResult(r, g, b, a, out) {
864
- if (out === 'hex')
865
- return rgbToHex({ r: Math.round(r), g: Math.round(g), b: Math.round(b) });
866
- if (out === 'rgba')
867
- return rgbToRgbaString({ r: Math.round(r), g: Math.round(g), b: Math.round(b) }, a);
868
- if (out === 'rgb')
869
- return `rgb(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)})`;
870
- if (out === 'hsl') {
871
- const [hh, ss, ll] = rgbToHsl({ r: Math.round(r), g: Math.round(g), b: Math.round(b) });
872
- return `hsl(${hh}, ${ss}%, ${ll}%)`;
873
- }
874
- return rgbToHex({ r: Math.round(r), g: Math.round(g), b: Math.round(b) });
875
- }
876
- function mixColors(c1, c2, t, opts) {
877
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35;
878
- const o1 = normalizeColor(c1);
879
- const o2 = normalizeColor(c2);
880
- t = Math.max(0, Math.min(1, t));
881
- const mode = (opts === null || opts === void 0 ? void 0 : opts.mode) || 'rgb';
882
- const out = (opts === null || opts === void 0 ? void 0 : opts.format) || 'hex';
883
- const hueMode = (_a = opts === null || opts === void 0 ? void 0 : opts.hueInterpolation) !== null && _a !== void 0 ? _a : 'shorter';
884
- let r = 0, g = 0, b = 0, a = 1;
885
- if (mode === 'hsl') {
886
- const h1 = (_b = o1.h) !== null && _b !== void 0 ? _b : rgbToHsl({ r: (_c = o1.r) !== null && _c !== void 0 ? _c : 0, g: (_d = o1.g) !== null && _d !== void 0 ? _d : 0, b: (_e = o1.b) !== null && _e !== void 0 ? _e : 0 })[0];
887
- const s1 = (_f = o1.s) !== null && _f !== void 0 ? _f : 0;
888
- const l1 = (_g = o1.l) !== null && _g !== void 0 ? _g : 0;
889
- const h2 = (_h = o2.h) !== null && _h !== void 0 ? _h : rgbToHsl({ r: (_j = o2.r) !== null && _j !== void 0 ? _j : 0, g: (_k = o2.g) !== null && _k !== void 0 ? _k : 0, b: (_l = o2.b) !== null && _l !== void 0 ? _l : 0 })[0];
890
- const s2 = (_m = o2.s) !== null && _m !== void 0 ? _m : 0;
891
- const l2 = (_o = o2.l) !== null && _o !== void 0 ? _o : 0;
892
- const ih = _lerpHue(h1, h2, t, hueMode);
893
- const rgb = hslToRgb(ih, s1 + (s2 - s1) * t, l1 + (l2 - l1) * t);
894
- r = rgb.r;
895
- g = rgb.g;
896
- b = rgb.b;
897
- a = ((_p = o1.a) !== null && _p !== void 0 ? _p : 1) + (((_q = o2.a) !== null && _q !== void 0 ? _q : 1) - ((_r = o1.a) !== null && _r !== void 0 ? _r : 1)) * t;
898
- }
899
- else if (mode === 'lab') {
900
- const lab1 = rgbToLab({ r: (_s = o1.r) !== null && _s !== void 0 ? _s : 0, g: (_t = o1.g) !== null && _t !== void 0 ? _t : 0, b: (_u = o1.b) !== null && _u !== void 0 ? _u : 0 });
901
- const lab2 = rgbToLab({ r: (_v = o2.r) !== null && _v !== void 0 ? _v : 0, g: (_w = o2.g) !== null && _w !== void 0 ? _w : 0, b: (_x = o2.b) !== null && _x !== void 0 ? _x : 0 });
902
- const mixed = labToRgb({ L: lab1.L + (lab2.L - lab1.L) * t, a: lab1.a + (lab2.a - lab1.a) * t, b: lab1.b + (lab2.b - lab1.b) * t });
903
- r = mixed.r;
904
- g = mixed.g;
905
- b = mixed.b;
906
- a = ((_y = o1.a) !== null && _y !== void 0 ? _y : 1) + (((_z = o2.a) !== null && _z !== void 0 ? _z : 1) - ((_0 = o1.a) !== null && _0 !== void 0 ? _0 : 1)) * t;
907
- }
908
- else if (mode === 'lch') {
909
- const lch1 = rgbToLch({ r: (_1 = o1.r) !== null && _1 !== void 0 ? _1 : 0, g: (_2 = o1.g) !== null && _2 !== void 0 ? _2 : 0, b: (_3 = o1.b) !== null && _3 !== void 0 ? _3 : 0 });
910
- const lch2 = rgbToLch({ r: (_4 = o2.r) !== null && _4 !== void 0 ? _4 : 0, g: (_5 = o2.g) !== null && _5 !== void 0 ? _5 : 0, b: (_6 = o2.b) !== null && _6 !== void 0 ? _6 : 0 });
911
- const mixed = lchToRgb({ L: lch1.L + (lch2.L - lch1.L) * t, C: lch1.C + (lch2.C - lch1.C) * t, H: _lerpHue(lch1.H, lch2.H, t, hueMode) });
912
- r = mixed.r;
913
- g = mixed.g;
914
- b = mixed.b;
915
- a = ((_7 = o1.a) !== null && _7 !== void 0 ? _7 : 1) + (((_8 = o2.a) !== null && _8 !== void 0 ? _8 : 1) - ((_9 = o1.a) !== null && _9 !== void 0 ? _9 : 1)) * t;
916
- }
917
- else if (mode === 'oklab') {
918
- const ok1 = rgbToOklab({ r: (_10 = o1.r) !== null && _10 !== void 0 ? _10 : 0, g: (_11 = o1.g) !== null && _11 !== void 0 ? _11 : 0, b: (_12 = o1.b) !== null && _12 !== void 0 ? _12 : 0 });
919
- const ok2 = rgbToOklab({ r: (_13 = o2.r) !== null && _13 !== void 0 ? _13 : 0, g: (_14 = o2.g) !== null && _14 !== void 0 ? _14 : 0, b: (_15 = o2.b) !== null && _15 !== void 0 ? _15 : 0 });
920
- const mixed = oklabToRgb({ L: ok1.L + (ok2.L - ok1.L) * t, a: ok1.a + (ok2.a - ok1.a) * t, b: ok1.b + (ok2.b - ok1.b) * t });
921
- r = mixed.r;
922
- g = mixed.g;
923
- b = mixed.b;
924
- a = ((_16 = o1.a) !== null && _16 !== void 0 ? _16 : 1) + (((_17 = o2.a) !== null && _17 !== void 0 ? _17 : 1) - ((_18 = o1.a) !== null && _18 !== void 0 ? _18 : 1)) * t;
925
- }
926
- else if (mode === 'oklch') {
927
- const ok1 = rgbToOklch({ r: (_19 = o1.r) !== null && _19 !== void 0 ? _19 : 0, g: (_20 = o1.g) !== null && _20 !== void 0 ? _20 : 0, b: (_21 = o1.b) !== null && _21 !== void 0 ? _21 : 0 });
928
- const ok2 = rgbToOklch({ r: (_22 = o2.r) !== null && _22 !== void 0 ? _22 : 0, g: (_23 = o2.g) !== null && _23 !== void 0 ? _23 : 0, b: (_24 = o2.b) !== null && _24 !== void 0 ? _24 : 0 });
929
- const mixed = oklchToRgb({ L: ok1.L + (ok2.L - ok1.L) * t, C: ok1.C + (ok2.C - ok1.C) * t, H: _lerpHue(ok1.H, ok2.H, t, hueMode) });
930
- r = mixed.r;
931
- g = mixed.g;
932
- b = mixed.b;
933
- a = ((_25 = o1.a) !== null && _25 !== void 0 ? _25 : 1) + (((_26 = o2.a) !== null && _26 !== void 0 ? _26 : 1) - ((_27 = o1.a) !== null && _27 !== void 0 ? _27 : 1)) * t;
934
- }
935
- else {
936
- r = ((_28 = o1.r) !== null && _28 !== void 0 ? _28 : 0) * (1 - t) + ((_29 = o2.r) !== null && _29 !== void 0 ? _29 : 0) * t;
937
- g = ((_30 = o1.g) !== null && _30 !== void 0 ? _30 : 0) * (1 - t) + ((_31 = o2.g) !== null && _31 !== void 0 ? _31 : 0) * t;
938
- b = ((_32 = o1.b) !== null && _32 !== void 0 ? _32 : 0) * (1 - t) + ((_33 = o2.b) !== null && _33 !== void 0 ? _33 : 0) * t;
939
- a = ((_34 = o1.a) !== null && _34 !== void 0 ? _34 : 1) * (1 - t) + ((_35 = o2.a) !== null && _35 !== void 0 ? _35 : 1) * t;
940
- }
941
- return _formatMixResult(r, g, b, a, out);
942
- }
943
- function relativeLuminance(color) {
944
- var _a, _b, _c;
945
- const n = normalizeColor(color);
946
- const r = ((_a = n.r) !== null && _a !== void 0 ? _a : 0) / 255;
947
- const g = ((_b = n.g) !== null && _b !== void 0 ? _b : 0) / 255;
948
- const b = ((_c = n.b) !== null && _c !== void 0 ? _c : 0) / 255;
949
- const srgbToLin = (c) => c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
950
- const R = srgbToLin(r), G = srgbToLin(g), B = srgbToLin(b);
951
- return 0.2126 * R + 0.7152 * G + 0.0722 * B;
952
- }
953
- function contrastRatio(a, b) {
954
- const L1 = relativeLuminance(a);
955
- const L2 = relativeLuminance(b);
956
- const light = Math.max(L1, L2);
957
- const dark = Math.min(L1, L2);
958
- return +((light + 0.05) / (dark + 0.05)).toFixed(2);
959
- }
960
- function isDark(color, threshold = 0.5) {
961
- return relativeLuminance(color) < threshold;
962
- }
963
- function isLight(color, threshold = 0.5) {
964
- return !isDark(color, threshold);
965
- }
966
- function rgbToCmyk({ r, g, b }) {
967
- const rd = r / 255, gd = g / 255, bd = b / 255;
968
- const k = 1 - Math.max(rd, gd, bd);
969
- if (k === 1)
970
- return { c: 0, m: 0, y: 0, k: 1 };
971
- const c = (1 - rd - k) / (1 - k);
972
- const m = (1 - gd - k) / (1 - k);
973
- const y = (1 - bd - k) / (1 - k);
974
- return { c, m, y, k };
975
- }
976
- function cmykToRgb({ c, m, y, k }) {
977
- const r = 255 * (1 - c) * (1 - k);
978
- const g = 255 * (1 - m) * (1 - k);
979
- const b = 255 * (1 - y) * (1 - k);
980
- return { r: Math.round(r), g: Math.round(g), b: Math.round(b) };
981
- }
982
- function srgbToLinear(v) {
983
- v = v / 255;
984
- return v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
985
- }
986
- function linearToSrgb(v) {
987
- const t = v <= 0.0031308 ? 12.92 * v : 1.055 * Math.pow(v, 1 / 2.4) - 0.055;
988
- return Math.round(Math.max(0, Math.min(1, t)) * 255);
989
- }
990
- function rgbToXyz({ r, g, b }) {
991
- const R = srgbToLinear(r);
992
- const G = srgbToLinear(g);
993
- const B = srgbToLinear(b);
994
- const X = R * 0.4124564 + G * 0.3575761 + B * 0.1804375;
995
- const Y = R * 0.2126729 + G * 0.7151522 + B * 0.0721750;
996
- const Z = R * 0.0193339 + G * 0.1191920 + B * 0.9503041;
997
- return { X: X * 100, Y: Y * 100, Z: Z * 100 };
998
- }
999
- function xyzToRgb({ X, Y, Z }) {
1000
- X = X / 100;
1001
- Y = Y / 100;
1002
- Z = Z / 100;
1003
- let R = X * 3.2404542 + Y * -1.5371385 + Z * -0.4985314;
1004
- let G = X * -0.9692660 + Y * 1.8760108 + Z * 0.0415560;
1005
- let B = X * 0.0556434 + Y * -0.2040259 + Z * 1.0572252;
1006
- R = linearToSrgb(R);
1007
- G = linearToSrgb(G);
1008
- B = linearToSrgb(B);
1009
- return { r: R, g: G, b: B };
1010
- }
1011
- function rgbToLab({ r, g, b }) {
1012
- const { X, Y, Z } = rgbToXyz({ r, g, b });
1013
- const refX = 95.047, refY = 100.0, refZ = 108.883;
1014
- const x = X / refX, y = Y / refY, z = Z / refZ;
1015
- const fx = x > 0.008856 ? Math.cbrt(x) : (7.787 * x) + 16 / 116;
1016
- const fy = y > 0.008856 ? Math.cbrt(y) : (7.787 * y) + 16 / 116;
1017
- const fz = z > 0.008856 ? Math.cbrt(z) : (7.787 * z) + 16 / 116;
1018
- const L = (116 * fy) - 16;
1019
- const a = 500 * (fx - fy);
1020
- const b2 = 200 * (fy - fz);
1021
- return { L, a, b: b2 };
1022
- }
1023
- function labToRgb({ L, a, b }) {
1024
- const refX = 95.047, refY = 100.0, refZ = 108.883;
1025
- let fy = (L + 16) / 116;
1026
- let fx = a / 500 + fy;
1027
- let fz = fy - b / 200;
1028
- const fx3 = Math.pow(fx, 3);
1029
- const fz3 = Math.pow(fz, 3);
1030
- const fy3 = Math.pow(fy, 3);
1031
- const xr = fx3 > 0.008856 ? fx3 : (fx - 16 / 116) / 7.787;
1032
- const yr = L > (903.3 * 0.008856) ? fy3 : L / 903.3;
1033
- const zr = fz3 > 0.008856 ? fz3 : (fz - 16 / 116) / 7.787;
1034
- const X = xr * refX, Y = yr * refY, Z = zr * refZ;
1035
- return xyzToRgb({ X, Y, Z });
1036
- }
1037
- function rgbToLch({ r, g, b }) {
1038
- const { L, a, b: bb } = rgbToLab({ r, g, b });
1039
- const C = Math.sqrt(a * a + bb * bb);
1040
- let H = Math.atan2(bb, a) * (180 / Math.PI);
1041
- if (H < 0)
1042
- H += 360;
1043
- return { L, C, H };
1044
- }
1045
- function lchToRgb({ L, C, H }) {
1046
- const a = Math.cos(H * Math.PI / 180) * C;
1047
- const b = Math.sin(H * Math.PI / 180) * C;
1048
- return labToRgb({ L, a, b });
1049
- }
1050
- function wcagLevel(foreground, background) {
1051
- const ratio = contrastRatio(foreground, background);
1052
- if (ratio >= 7)
1053
- return 'AAA';
1054
- if (ratio >= 4.5)
1055
- return 'AA';
1056
- if (ratio >= 3)
1057
- return 'AA-large';
1058
- return 'fail';
1059
- }
1060
- function bestTextColor(background) {
1061
- const onBlack = contrastRatio(background, '#000000');
1062
- const onWhite = contrastRatio(background, '#ffffff');
1063
- return onBlack >= onWhite ? '#000000' : '#ffffff';
1064
- }
1065
- function bestContrastColor(background, candidates) {
1066
- let best = candidates[0];
1067
- let bestRatio = -1;
1068
- for (const c of candidates) {
1069
- const ratio = contrastRatio(background, c);
1070
- if (ratio > bestRatio) {
1071
- bestRatio = ratio;
1072
- best = c;
1073
- }
1074
- }
1075
- return best;
1076
- }
1077
- // ─── HWB ─────────────────────────────────────────────────────────────────────
1078
- function rgbToHwb({ r, g, b }) {
1079
- const rd = r / 255, gd = g / 255, bd = b / 255;
1080
- const max = Math.max(rd, gd, bd), min = Math.min(rd, gd, bd);
1081
- const w = min;
1082
- const bl = 1 - max;
1083
- let h = 0;
1084
- if (max !== min) {
1085
- const d = max - min;
1086
- switch (max) {
1087
- case rd:
1088
- h = (gd - bd) / d + (gd < bd ? 6 : 0);
1089
- break;
1090
- case gd:
1091
- h = (bd - rd) / d + 2;
1092
- break;
1093
- case bd:
1094
- h = (rd - gd) / d + 4;
1095
- break;
1096
- }
1097
- h /= 6;
1098
- }
1099
- return [Math.round(h * 360), Math.round(w * 100), Math.round(bl * 100)];
1100
- }
1101
- function hwbToRgb(H, W, B) {
1102
- H = ((H % 360) + 360) % 360;
1103
- const w = W / 100, b = B / 100;
1104
- if (w + b >= 1) {
1105
- const gray = Math.round((w / (w + b)) * 255);
1106
- return { r: gray, g: gray, b: gray };
1107
- }
1108
- const { r, g, b: rb } = hslToRgb(H, 100, 50);
1109
- const factor = 1 - w - b;
1110
- return {
1111
- r: Math.round(r / 255 * factor * 255 + w * 255),
1112
- g: Math.round(g / 255 * factor * 255 + w * 255),
1113
- b: Math.round(rb / 255 * factor * 255 + w * 255),
1114
- };
1115
- }
1116
- function toHwbString(H, W, B, alpha) {
1117
- if (alpha !== undefined)
1118
- return `hwb(${H} ${W}% ${B}% / ${+alpha.toFixed(3)})`;
1119
- return `hwb(${H} ${W}% ${B}%)`;
1120
- }
1121
- function parseHwbString(str) {
1122
- const m = str.trim().match(/hwb\(\s*([\d.+-]+)\s+([\d.]+)%\s+([\d.]+)%(?:\s*\/\s*([\d.]+))?\s*\)/i);
1123
- if (!m)
1124
- return null;
1125
- return { H: parseFloat(m[1]), W: parseFloat(m[2]), B: parseFloat(m[3]), alpha: m[4] !== undefined ? parseFloat(m[4]) : 1 };
1126
- }
1127
- // ─── OKLCH / OKLAB ───────────────────────────────────────────────────────────
1128
- function srgbToOkLinear(v) {
1129
- v = v / 255;
1130
- return v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
1131
- }
1132
- function okLinearToSrgb(v) {
1133
- const t = v <= 0.0031308 ? 12.92 * v : 1.055 * Math.pow(v, 1 / 2.4) - 0.055;
1134
- return Math.round(Math.max(0, Math.min(1, t)) * 255);
1135
- }
1136
- function rgbToOklab({ r, g, b }) {
1137
- const R = srgbToOkLinear(r), G = srgbToOkLinear(g), B = srgbToOkLinear(b);
1138
- const l = Math.cbrt(0.4122214708 * R + 0.5363325363 * G + 0.0514459929 * B);
1139
- const m = Math.cbrt(0.2119034982 * R + 0.6806995451 * G + 0.1073969566 * B);
1140
- const s = Math.cbrt(0.0883024619 * R + 0.2817188376 * G + 0.6299787005 * B);
1141
- return {
1142
- L: 0.2104542553 * l + 0.7936177850 * m - 0.0040720468 * s,
1143
- a: 1.9779984951 * l - 2.4285922050 * m + 0.4505937099 * s,
1144
- b: 0.0259040371 * l + 0.7827717662 * m - 0.8086757660 * s,
1145
- };
1146
- }
1147
- function oklabToRgb({ L, a, b }) {
1148
- const l = Math.pow(L + 0.3963377774 * a + 0.2158037573 * b, 3);
1149
- const m = Math.pow(L - 0.1055613458 * a - 0.0638541728 * b, 3);
1150
- const s = Math.pow(L - 0.0894841775 * a - 1.2914855480 * b, 3);
1151
- const R = okLinearToSrgb(+4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s);
1152
- const G = okLinearToSrgb(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s);
1153
- const B = okLinearToSrgb(-0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s);
1154
- return { r: R, g: G, b: B };
1155
- }
1156
- function rgbToOklch({ r, g, b }) {
1157
- const { L, a, b: bb } = rgbToOklab({ r, g, b });
1158
- const C = Math.sqrt(a * a + bb * bb);
1159
- let H = Math.atan2(bb, a) * (180 / Math.PI);
1160
- if (H < 0)
1161
- H += 360;
1162
- return { L, C, H };
1163
- }
1164
- function oklchToRgb({ L, C, H }) {
1165
- const a = Math.cos(H * Math.PI / 180) * C;
1166
- const b = Math.sin(H * Math.PI / 180) * C;
1167
- return oklabToRgb({ L, a, b });
1168
- }
1169
- // ─── Utilities ───────────────────────────────────────────────────────────────
1170
- function toHslString(h, s, l, alpha) {
1171
- if (alpha !== undefined)
1172
- return `hsla(${h}, ${s}%, ${l}%, ${+alpha.toFixed(3)})`;
1173
- return `hsl(${h}, ${s}%, ${l}%)`;
1174
- }
1175
- function colorDeltaE(c1, c2) {
1176
- var _a, _b, _c, _d, _e, _f;
1177
- const n1 = normalizeColor(c1);
1178
- const n2 = normalizeColor(c2);
1179
- const lab1 = 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 });
1180
- const lab2 = 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 });
1181
- // CIEDE2000
1182
- const deg = (rad) => rad * (180 / Math.PI);
1183
- const rad = (d) => d * (Math.PI / 180);
1184
- const { L: L1, a: a1, b: b1 } = lab1;
1185
- const { L: L2, a: a2, b: b2 } = lab2;
1186
- const dL = L2 - L1;
1187
- const Lm = (L1 + L2) / 2;
1188
- const C1 = Math.sqrt(a1 * a1 + b1 * b1);
1189
- const C2 = Math.sqrt(a2 * a2 + b2 * b2);
1190
- const Cm = (C1 + C2) / 2;
1191
- const Cm7 = Math.pow(Cm, 7);
1192
- const G = 0.5 * (1 - Math.sqrt(Cm7 / (Cm7 + Math.pow(25, 7))));
1193
- const a1p = a1 * (1 + G), a2p = a2 * (1 + G);
1194
- const C1p = Math.sqrt(a1p * a1p + b1 * b1);
1195
- const C2p = Math.sqrt(a2p * a2p + b2 * b2);
1196
- const dCp = C2p - C1p;
1197
- const Cmp = (C1p + C2p) / 2;
1198
- let h1p = deg(Math.atan2(b1, a1p));
1199
- if (h1p < 0)
1200
- h1p += 360;
1201
- let h2p = deg(Math.atan2(b2, a2p));
1202
- if (h2p < 0)
1203
- h2p += 360;
1204
- let dhp;
1205
- if (Math.abs(h1p - h2p) <= 180)
1206
- dhp = h2p - h1p;
1207
- else if (h2p <= h1p)
1208
- dhp = h2p - h1p + 360;
1209
- else
1210
- dhp = h2p - h1p - 360;
1211
- const dHp = 2 * Math.sqrt(C1p * C2p) * Math.sin(rad(dhp / 2));
1212
- let Hmp;
1213
- if (Math.abs(h1p - h2p) <= 180)
1214
- Hmp = (h1p + h2p) / 2;
1215
- else if (h1p + h2p < 360)
1216
- Hmp = (h1p + h2p + 360) / 2;
1217
- else
1218
- Hmp = (h1p + h2p - 360) / 2;
1219
- const T = 1
1220
- - 0.17 * Math.cos(rad(Hmp - 30))
1221
- + 0.24 * Math.cos(rad(2 * Hmp))
1222
- + 0.32 * Math.cos(rad(3 * Hmp + 6))
1223
- - 0.20 * Math.cos(rad(4 * Hmp - 63));
1224
- const SL = 1 + 0.015 * Math.pow(Lm - 50, 2) / Math.sqrt(20 + Math.pow(Lm - 50, 2));
1225
- const SC = 1 + 0.045 * Cmp;
1226
- const SH = 1 + 0.015 * Cmp * T;
1227
- const Cmp7 = Math.pow(Cmp, 7);
1228
- const RC = 2 * Math.sqrt(Cmp7 / (Cmp7 + Math.pow(25, 7)));
1229
- const dTheta = 30 * Math.exp(-Math.pow((Hmp - 275) / 25, 2));
1230
- const RT = -Math.sin(rad(2 * dTheta)) * RC;
1231
- return +Math.sqrt(Math.pow(dL / SL, 2) +
1232
- Math.pow(dCp / SC, 2) +
1233
- Math.pow(dHp / SH, 2) +
1234
- RT * (dCp / SC) * (dHp / SH)).toFixed(4);
1235
- }
1236
- function randomColor(options) {
1237
- var _a, _b, _c;
1238
- const [hMin, hMax] = (_a = options === null || options === void 0 ? void 0 : options.hRange) !== null && _a !== void 0 ? _a : [0, 360];
1239
- const [sMin, sMax] = (_b = options === null || options === void 0 ? void 0 : options.sRange) !== null && _b !== void 0 ? _b : [40, 90];
1240
- const [lMin, lMax] = (_c = options === null || options === void 0 ? void 0 : options.lRange) !== null && _c !== void 0 ? _c : [30, 70];
1241
- const h = Math.floor(Math.random() * (hMax - hMin)) + hMin;
1242
- const s = Math.floor(Math.random() * (sMax - sMin)) + sMin;
1243
- const l = Math.floor(Math.random() * (lMax - lMin)) + lMin;
1244
- return hslToHex(h, s, l);
1245
- }
1246
- function toNearestNamedColor(color) {
1247
- var _a, _b, _c;
1248
- const n = normalizeColor(color);
1249
- 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;
1250
- let bestName = 'black';
1251
- let bestDist = Infinity;
1252
- for (const [name, hex] of Object.entries(NAMED_COLORS)) {
1253
- // Skip any non-hex entry (currently just a defensive guard — 'transparent'
1254
- // is the only such value left in the table, and it has no real RGB to
1255
- // compare against; hexToRgb() would otherwise silently fall back to
1256
- // normalizeHex()'s placeholder color for it).
1257
- if (hex[0] !== '#')
1258
- continue;
1259
- const [nr, ng, nb] = hexToRgb(hex);
1260
- const dist = Math.sqrt(Math.pow(r - nr, 2) + Math.pow(g - ng, 2) + Math.pow(b - nb, 2));
1261
- if (dist < bestDist) {
1262
- bestDist = dist;
1263
- bestName = name;
1264
- }
1265
- }
1266
- return bestName;
1267
- }
1268
- // ─── Formatting ───────────────────────────────────────────────────────────────
1269
- function toOklchString(color, alpha) {
1270
- var _a, _b, _c;
1271
- const n = normalizeColor(color);
1272
- const { L, C, H } = 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 });
1273
- const Lr = +L.toFixed(4), Cr = +C.toFixed(4), Hr = +H.toFixed(2);
1274
- if (alpha !== undefined)
1275
- return `oklch(${Lr} ${Cr} ${Hr} / ${+alpha.toFixed(3)})`;
1276
- return `oklch(${Lr} ${Cr} ${Hr})`;
1277
- }
1278
- function toColorP3String(color, alpha) {
1279
- var _a, _b, _c;
1280
- const n = normalizeColor(color);
1281
- const p3 = 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 });
1282
- const r = +p3.r.toFixed(4), g = +p3.g.toFixed(4), b = +p3.b.toFixed(4);
1283
- if (alpha !== undefined)
1284
- return `color(display-p3 ${r} ${g} ${b} / ${+alpha.toFixed(3)})`;
1285
- return `color(display-p3 ${r} ${g} ${b})`;
1286
- }
1287
- // ─── Section 2: Interpolation ─────────────────────────────────────────────────
1288
- function interpolateColors(color1, color2, steps, options) {
1289
- if (steps < 2)
1290
- return steps === 1 ? [mixColors(color1, color2, 0.5, options)] : [];
1291
- const result = [];
1292
- for (let i = 0; i < steps; i++) {
1293
- result.push(mixColors(color1, color2, i / (steps - 1), options));
1294
- }
1295
- return result;
1296
- }
1297
- function createColorScale(anchors, steps, options) {
1298
- const normalized = anchors.map((a, i, arr) => {
1299
- var _a;
1300
- return ({
1301
- color: typeof a === 'string' ? a : a.color,
1302
- position: typeof a === 'string' ? i / Math.max(arr.length - 1, 1) : ((_a = a.position) !== null && _a !== void 0 ? _a : i / Math.max(arr.length - 1, 1)),
1303
- });
1304
- });
1305
- normalized.sort((a, b) => a.position - b.position);
1306
- const result = [];
1307
- for (let i = 0; i < steps; i++) {
1308
- const t = steps === 1 ? 0 : i / (steps - 1);
1309
- let lo = normalized[0], hi = normalized[normalized.length - 1];
1310
- for (let j = 0; j < normalized.length - 1; j++) {
1311
- if (t >= normalized[j].position && t <= normalized[j + 1].position) {
1312
- lo = normalized[j];
1313
- hi = normalized[j + 1];
1314
- break;
1315
- }
1316
- }
1317
- const span = hi.position - lo.position;
1318
- const localT = span === 0 ? 0 : (t - lo.position) / span;
1319
- result.push(mixColors(lo.color, hi.color, localT, options));
1320
- }
1321
- return result;
1322
- }
1323
- function midpointColor(color1, color2, options) {
1324
- var _a;
1325
- return mixColors(color1, color2, 0.5, { mode: (_a = options === null || options === void 0 ? void 0 : options.space) !== null && _a !== void 0 ? _a : 'oklab' });
1326
- }
1327
- // ─── Section 3: Tints / Shades / Tones ───────────────────────────────────────
1328
- function tints(color, steps = 5) {
1329
- return interpolateColors(color, '#ffffff', steps, { space: 'oklab' });
1330
- }
1331
- function shades(color, steps = 5) {
1332
- return interpolateColors(color, '#000000', steps, { space: 'oklab' });
1333
- }
1334
- function tones(color, steps = 5, gray = '#808080') {
1335
- return interpolateColors(color, gray, steps, { space: 'oklab' });
1336
- }
1337
- // ─── Section 4: Color blindness simulation ────────────────────────────────────
1338
- function _simulateCB(color, matrix) {
1339
- var _a, _b, _c;
1340
- const n = normalizeColor(color);
1341
- // linearize
1342
- const lin = (v) => { const c = v / 255; return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4); };
1343
- const enc = (v) => { const c = v <= 0.0031308 ? 12.92 * v : 1.055 * Math.pow(v, 1 / 2.4) - 0.055; return Math.round(Math.max(0, Math.min(1, c)) * 255); };
1344
- 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);
1345
- const nr = enc(matrix[0][0] * r + matrix[0][1] * g + matrix[0][2] * b);
1346
- const ng = enc(matrix[1][0] * r + matrix[1][1] * g + matrix[1][2] * b);
1347
- const nb = enc(matrix[2][0] * r + matrix[2][1] * g + matrix[2][2] * b);
1348
- return rgbToHex({ r: nr, g: ng, b: nb });
1349
- }
1350
- const _PROTANOPIA_M = [[0.56667, 0.43333, 0.00000], [0.55833, 0.44167, 0.00000], [0.00000, 0.24167, 0.75833]];
1351
- const _DEUTERANOPIA_M = [[0.62500, 0.37500, 0.00000], [0.70000, 0.30000, 0.00000], [0.00000, 0.30000, 0.70000]];
1352
- const _TRITANOPIA_M = [[0.95000, 0.05000, 0.00000], [0.00000, 0.43333, 0.56667], [0.00000, 0.47500, 0.52500]];
1353
- function simulateProtanopia(color) { return _simulateCB(color, _PROTANOPIA_M); }
1354
- function simulateDeuteranopia(color) { return _simulateCB(color, _DEUTERANOPIA_M); }
1355
- function simulateTritanopia(color) { return _simulateCB(color, _TRITANOPIA_M); }
1356
- function simulateColorBlindness(color, type) {
1357
- if (type === 'protanopia')
1358
- return simulateProtanopia(color);
1359
- if (type === 'deuteranopia')
1360
- return simulateDeuteranopia(color);
1361
- return simulateTritanopia(color);
1362
- }
1363
- function isReadableOnBackground(textColor, background, options) {
1364
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
1365
- const level = (_a = options === null || options === void 0 ? void 0 : options.level) !== null && _a !== void 0 ? _a : 'AA';
1366
- const large = (_b = options === null || options === void 0 ? void 0 : options.largeText) !== null && _b !== void 0 ? _b : false;
1367
- const minRequired = level === 'AAA' ? (large ? 4.5 : 7) : (large ? 3 : 4.5);
1368
- let minRatio;
1369
- if (typeof background === 'string') {
1370
- minRatio = contrastRatio(textColor, background);
1371
- }
1372
- else if (background.type === 'semi-transparent') {
1373
- const underlay = (_c = background.underlay) !== null && _c !== void 0 ? _c : '#ffffff';
1374
- const fg = normalizeColor(background.color);
1375
- const bg = normalizeColor(underlay);
1376
- const alpha = (_d = fg.a) !== null && _d !== void 0 ? _d : 1;
1377
- 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));
1378
- 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));
1379
- 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));
1380
- minRatio = contrastRatio(textColor, rgbToHex({ r: cr, g: cg, b: cb }));
1381
- }
1382
- else {
1383
- const ratios = background.stops.map(stop => contrastRatio(textColor, stop));
1384
- minRatio = Math.min(...ratios);
1385
- }
1386
- const wLevel = wcagLevel(textColor, typeof background === 'string' ? background : '#ffffff');
1387
- return { readable: minRatio >= minRequired, minContrastRatio: +minRatio.toFixed(2), wcagLevel: wLevel };
1388
- }
1389
- function bestContrastPalette(background, palettes, options) {
1390
- let bestIdx = 0;
1391
- let bestScore = -1;
1392
- let bestMin = 0, bestAvg = 0;
1393
- palettes.forEach((palette, idx) => {
1394
- var _a;
1395
- const ratios = palette.map(c => contrastRatio(background, c));
1396
- const weights = (_a = options === null || options === void 0 ? void 0 : options.weights) !== null && _a !== void 0 ? _a : ratios.map(() => 1);
1397
- const totalW = weights.reduce((s, w) => s + w, 0);
1398
- const avg = ratios.reduce((s, r, i) => { var _a; return s + r * ((_a = weights[i]) !== null && _a !== void 0 ? _a : 1); }, 0) / totalW;
1399
- const min = Math.min(...ratios);
1400
- // Score: weighted avg with heavy penalty on minimum
1401
- const score = avg * 0.4 + min * 0.6;
1402
- if (score > bestScore) {
1403
- bestScore = score;
1404
- bestIdx = idx;
1405
- bestMin = min;
1406
- bestAvg = avg;
1407
- }
1408
- });
1409
- return {
1410
- paletteIndex: bestIdx,
1411
- palette: palettes[bestIdx],
1412
- minContrastRatio: +bestMin.toFixed(2),
1413
- avgContrastRatio: +bestAvg.toFixed(2),
1414
- };
1415
- }
1416
- // ─── Section 5.1: Caching ────────────────────────────────────────────────────
1417
- let _cacheEnabled = true;
1418
- const _normalizeCache = new Map();
1419
- let _cacheHits = 0;
1420
- function clearColorCache() { _normalizeCache.clear(); _cacheHits = 0; }
1421
- function getCacheStats() { return { size: _normalizeCache.size, hits: _cacheHits }; }
1422
- function enableCache() { _cacheEnabled = true; }
1423
- function disableCache() { _cacheEnabled = false; }
1424
- // Cached normalizer wrapper — use this in performance-sensitive contexts
1425
- function normalizeColorCached(input) {
1426
- if (!_cacheEnabled)
1427
- return normalizeColor(input);
1428
- const cached = _normalizeCache.get(input);
1429
- if (cached) {
1430
- _cacheHits++;
1431
- return cached;
1432
- }
1433
- const result = normalizeColor(input);
1434
- _normalizeCache.set(input, result);
1435
- return result;
1436
- }
1437
- // ─── Section 5.2: Generator functions ────────────────────────────────────────
1438
- function* generateGradientColors(start, end, steps, options) {
1439
- for (let i = 0; i < steps; i++) {
1440
- yield mixColors(start, end, steps === 1 ? 0 : i / (steps - 1), options);
1441
- }
1442
- }
1443
- function* generateTints(color, steps, options) {
1444
- for (let i = 0; i < steps; i++) {
1445
- yield mixColors(color, '#ffffff', steps === 1 ? 0 : i / (steps - 1), { mode: 'oklab', ...options });
1446
- }
1447
- }
1448
- function* generateShades(color, steps, options) {
1449
- for (let i = 0; i < steps; i++) {
1450
- yield mixColors(color, '#000000', steps === 1 ? 0 : i / (steps - 1), { mode: 'oklab', ...options });
1451
- }
1452
- }
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./parse.js"), exports);
18
+ __exportStar(require("./convert/index.js"), exports);
19
+ __exportStar(require("./manipulate.js"), exports);
20
+ __exportStar(require("./palette.js"), exports);
21
+ __exportStar(require("./a11y.js"), exports);
22
+ __exportStar(require("./cache.js"), exports);