color-value-tools 1.1.0 → 1.1.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.
@@ -0,0 +1,1410 @@
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
+ // Special CSS keywords
134
+ transparent: 'transparent', currentcolor: 'currentcolor', inherit: 'inherit', initial: 'initial', unset: 'unset',
135
+ };
136
+ function isCssVariable(value) {
137
+ return value.trim().startsWith('var(--');
138
+ }
139
+ function isHexColor(value) {
140
+ const trimmed = value.trim();
141
+ return /^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6})$/.test(trimmed);
142
+ }
143
+ function isOklchColor(value) {
144
+ return /^\s*oklcha?\s*\(/i.test(value.trim());
145
+ }
146
+ function isColorFunction(value) {
147
+ return /^\s*color\s*\(\s*(display-p3|srgb|srgb-linear)\s/i.test(value.trim());
148
+ }
149
+ function isRgbColor(value) {
150
+ const trimmed = value.trim().toLowerCase();
151
+ return trimmed.startsWith('rgb(') || trimmed.startsWith('rgba(');
152
+ }
153
+ function isHslColor(value) {
154
+ const trimmed = value.trim().toLowerCase();
155
+ return trimmed.startsWith('hsl(') || trimmed.startsWith('hsla(');
156
+ }
157
+ function getColorType(value) {
158
+ const trimmed = value.trim();
159
+ const lower = trimmed.toLowerCase();
160
+ if (isCssVariable(trimmed))
161
+ return 'css-var';
162
+ if (isHexColor(trimmed))
163
+ return 'hex';
164
+ if (isRgbColor(trimmed))
165
+ return 'rgb';
166
+ if (isHslColor(trimmed))
167
+ return 'hsl';
168
+ if (isOklchColor(trimmed))
169
+ return 'oklch';
170
+ if (isColorFunction(trimmed))
171
+ return 'color';
172
+ if (lower in NAMED_COLORS)
173
+ return 'named';
174
+ return 'unknown';
175
+ }
176
+ function extractCssVariableName(value) {
177
+ var _a;
178
+ const match = value.match(/var\(\s*(--[^,)]+)/);
179
+ return ((_a = match === null || match === void 0 ? void 0 : match[1]) === null || _a === void 0 ? void 0 : _a.trim()) || value;
180
+ }
181
+ function parseCssVar(value) {
182
+ var _a;
183
+ const m = value.trim().match(/^var\(\s*(--[^,)]+)(?:,\s*([\s\S]+?))?\s*\)$/);
184
+ if (!m)
185
+ return null;
186
+ return { variableName: m[1].trim(), fallback: (_a = m[2]) === null || _a === void 0 ? void 0 : _a.trim() };
187
+ }
188
+ // ─── Section 1.1 — OKLCH / color() CSS string parsing ────────────────────────
189
+ function parseOklchString(str) {
190
+ const m = str.trim().match(/oklcha?\(\s*([\d.]+%?)\s+([\d.]+)\s+([\d.]+)(?:\s*\/\s*([\d.]+))?\s*\)/i);
191
+ if (!m)
192
+ return null;
193
+ let L = parseFloat(m[1]);
194
+ if (m[1].endsWith('%'))
195
+ L = L / 100;
196
+ const C = parseFloat(m[2]);
197
+ const H = parseFloat(m[3]);
198
+ const alpha = m[4] !== undefined ? parseFloat(m[4]) : 1;
199
+ return { L, C, H, alpha };
200
+ }
201
+ function parseColorFn(str) {
202
+ const m = str.trim().match(/color\(\s*([\w-]+)\s+([\d.]+%?)\s+([\d.]+%?)\s+([\d.]+%?)(?:\s*\/\s*([\d.]+))?\s*\)/i);
203
+ if (!m)
204
+ return null;
205
+ const space = m[1].toLowerCase();
206
+ const parseVal = (v) => v.endsWith('%') ? parseFloat(v) / 100 : parseFloat(v);
207
+ const r = parseVal(m[2]);
208
+ const g = parseVal(m[3]);
209
+ const b = parseVal(m[4]);
210
+ const alpha = m[5] !== undefined ? parseFloat(m[5]) : 1;
211
+ return { space, r, g, b, alpha };
212
+ }
213
+ // ─── Section 1.2 — Display P3 ────────────────────────────────────────────────
214
+ function rgbToDisplayP3(rgb) {
215
+ // Remove sRGB gamma (linearize)
216
+ const rl = srgbChanToLinear(rgb.r / 255);
217
+ const gl = srgbChanToLinear(rgb.g / 255);
218
+ const bl = srgbChanToLinear(rgb.b / 255);
219
+ // sRGB-linear → P3-linear matrix
220
+ const pr = 0.8226 * rl + 0.1774 * gl + 0.0000 * bl;
221
+ const pg = 0.0332 * rl + 0.9669 * gl + 0.0000 * bl;
222
+ const pb = 0.0171 * rl + 0.0724 * gl + 0.9103 * bl;
223
+ // Apply P3 gamma (same as sRGB)
224
+ return {
225
+ r: linearChanToSrgb(pr),
226
+ g: linearChanToSrgb(pg),
227
+ b: linearChanToSrgb(pb),
228
+ };
229
+ }
230
+ function displayP3ToRgb(p3) {
231
+ // Remove P3 gamma
232
+ const rl = srgbChanToLinear(p3.r);
233
+ const gl = srgbChanToLinear(p3.g);
234
+ const bl = srgbChanToLinear(p3.b);
235
+ // P3-linear → sRGB-linear inverse matrix
236
+ const sr = 1.2247 * rl + (-0.2247) * gl + 0.0000 * bl;
237
+ const sg = (-0.0421) * rl + 1.0432 * gl + 0.0000 * bl;
238
+ const sb = (-0.0197) * rl + (-0.0786) * gl + 1.0983 * bl;
239
+ // Apply sRGB gamma
240
+ return {
241
+ r: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sr)))),
242
+ g: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sg)))),
243
+ b: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sb)))),
244
+ };
245
+ }
246
+ // Helpers for Display P3 (operate on 0-1 values)
247
+ function srgbChanToLinear(v) {
248
+ return v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
249
+ }
250
+ function linearChanToSrgb(v) {
251
+ const t = v <= 0.0031308 ? 12.92 * v : 1.055 * Math.pow(v, 1 / 2.4) - 0.055;
252
+ return Math.max(0, Math.min(1, t));
253
+ }
254
+ function toDisplayP3Hex(color) {
255
+ const n = normalizeColorRaw(color);
256
+ const p3 = rgbToDisplayP3({ r: n.r, g: n.g, b: n.b });
257
+ const back = displayP3ToRgb(p3);
258
+ return rgbToHex(back);
259
+ }
260
+ // Internal raw normalizer (no cache, no circular dep issues)
261
+ function normalizeColorRaw(color) {
262
+ var _a, _b, _c, _d;
263
+ const n = normalizeColor(color);
264
+ 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 };
265
+ }
266
+ // ─── Section 1.3 — Short RGBA hex #RGBA ──────────────────────────────────────
267
+ function shortHexToRgba(hex) {
268
+ let h = hex.trim();
269
+ if (!h.startsWith('#'))
270
+ h = `#${h}`;
271
+ if (!/^#[0-9a-f]{4}$/i.test(h))
272
+ return null;
273
+ const r = parseInt(h[1] + h[1], 16);
274
+ const g = parseInt(h[2] + h[2], 16);
275
+ const b = parseInt(h[3] + h[3], 16);
276
+ const a = parseInt(h[4] + h[4], 16) / 255;
277
+ return { r, g, b, a };
278
+ }
279
+ function normalizeHex(hex) {
280
+ let cleanHex = hex.trim();
281
+ if (!cleanHex.startsWith('#'))
282
+ cleanHex = `#${cleanHex}`;
283
+ if (cleanHex.length === 4) {
284
+ cleanHex = `#${cleanHex.slice(1).split('').map(c => c + c).join('')}`;
285
+ }
286
+ if (!/^#[0-9A-Fa-f]{6}$/.test(cleanHex)) {
287
+ return '#f5e477';
288
+ }
289
+ return cleanHex.toLowerCase();
290
+ }
291
+ function hexToRgb(hex) {
292
+ const normalizedHex = normalizeHex(hex);
293
+ const r = parseInt(normalizedHex.slice(1, 3), 16);
294
+ const g = parseInt(normalizedHex.slice(3, 5), 16);
295
+ const b = parseInt(normalizedHex.slice(5, 7), 16);
296
+ return [r, g, b];
297
+ }
298
+ function hexToRgba(hex, opacity = 1) {
299
+ const [r, g, b] = hexToRgb(hex);
300
+ return `rgba(${r}, ${g}, ${b}, ${opacity})`;
301
+ }
302
+ function hexToHsl(hex) {
303
+ const [r, g, b] = hexToRgb(hex);
304
+ const red = r / 255;
305
+ const green = g / 255;
306
+ const blue = b / 255;
307
+ const max = Math.max(red, green, blue);
308
+ const min = Math.min(red, green, blue);
309
+ let h = 0, s = 0;
310
+ const l = (max + min) / 2;
311
+ if (max !== min) {
312
+ const d = max - min;
313
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
314
+ switch (max) {
315
+ case red:
316
+ h = (green - blue) / d + (green < blue ? 6 : 0);
317
+ break;
318
+ case green:
319
+ h = (blue - red) / d + 2;
320
+ break;
321
+ case blue:
322
+ h = (red - green) / d + 4;
323
+ break;
324
+ }
325
+ h /= 6;
326
+ }
327
+ return [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100)];
328
+ }
329
+ function hslToHex(h, s, l) {
330
+ h = ((h % 360) + 360) % 360;
331
+ s = Math.max(0, Math.min(100, s)) / 100;
332
+ l = Math.max(0, Math.min(100, l)) / 100;
333
+ const c = (1 - Math.abs(2 * l - 1)) * s;
334
+ const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
335
+ const m = l - c / 2;
336
+ let r = 0, g = 0, b = 0;
337
+ if (h >= 0 && h < 60) {
338
+ r = c;
339
+ g = x;
340
+ b = 0;
341
+ }
342
+ else if (h >= 60 && h < 120) {
343
+ r = x;
344
+ g = c;
345
+ b = 0;
346
+ }
347
+ else if (h >= 120 && h < 180) {
348
+ r = 0;
349
+ g = c;
350
+ b = x;
351
+ }
352
+ else if (h >= 180 && h < 240) {
353
+ r = 0;
354
+ g = x;
355
+ b = c;
356
+ }
357
+ else if (h >= 240 && h < 300) {
358
+ r = x;
359
+ g = 0;
360
+ b = c;
361
+ }
362
+ else {
363
+ r = c;
364
+ g = 0;
365
+ b = x;
366
+ }
367
+ r = Math.round((r + m) * 255);
368
+ g = Math.round((g + m) * 255);
369
+ b = Math.round((b + m) * 255);
370
+ return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
371
+ }
372
+ function adjustHexBrightness(hex, offsetPercent) {
373
+ const normalizedHex = normalizeHex(hex);
374
+ const p = Math.max(-100, Math.min(100, offsetPercent)) / 100;
375
+ const r = parseInt(normalizedHex.slice(1, 3), 16);
376
+ const g = parseInt(normalizedHex.slice(3, 5), 16);
377
+ const b = parseInt(normalizedHex.slice(5, 7), 16);
378
+ const adjustChannel = (channel) => {
379
+ if (p > 0)
380
+ return Math.min(255, Math.floor(channel + (255 - channel) * p));
381
+ else if (p < 0)
382
+ return Math.max(0, Math.floor(channel * (1 + p)));
383
+ return channel;
384
+ };
385
+ const newR = adjustChannel(r);
386
+ const newG = adjustChannel(g);
387
+ const newB = adjustChannel(b);
388
+ return `#${newR.toString(16).padStart(2, '0')}${newG.toString(16).padStart(2, '0')}${newB.toString(16).padStart(2, '0')}`;
389
+ }
390
+ function rotateHue(hex, degrees) {
391
+ const [h, s, l] = hexToHsl(hex);
392
+ const newH = ((h + degrees) % 360 + 360) % 360;
393
+ return hslToHex(newH, s, l);
394
+ }
395
+ function lighten(color, amount) {
396
+ var _a, _b, _c;
397
+ const n = normalizeColor(color);
398
+ const h = (_a = n.h) !== null && _a !== void 0 ? _a : 0;
399
+ const s = (_b = n.s) !== null && _b !== void 0 ? _b : 0;
400
+ const l = Math.min(100, ((_c = n.l) !== null && _c !== void 0 ? _c : 0) + amount);
401
+ return hslToHex(h, s, l);
402
+ }
403
+ function darken(color, amount) {
404
+ var _a, _b, _c;
405
+ const n = normalizeColor(color);
406
+ const h = (_a = n.h) !== null && _a !== void 0 ? _a : 0;
407
+ const s = (_b = n.s) !== null && _b !== void 0 ? _b : 0;
408
+ const l = Math.max(0, ((_c = n.l) !== null && _c !== void 0 ? _c : 0) - amount);
409
+ return hslToHex(h, s, l);
410
+ }
411
+ function saturate(color, amount) {
412
+ var _a, _b, _c;
413
+ const n = normalizeColor(color);
414
+ const h = (_a = n.h) !== null && _a !== void 0 ? _a : 0;
415
+ const s = Math.min(100, ((_b = n.s) !== null && _b !== void 0 ? _b : 0) + amount);
416
+ const l = (_c = n.l) !== null && _c !== void 0 ? _c : 0;
417
+ return hslToHex(h, s, l);
418
+ }
419
+ function desaturate(color, amount) {
420
+ var _a, _b, _c;
421
+ const n = normalizeColor(color);
422
+ const h = (_a = n.h) !== null && _a !== void 0 ? _a : 0;
423
+ const s = Math.max(0, ((_b = n.s) !== null && _b !== void 0 ? _b : 0) - amount);
424
+ const l = (_c = n.l) !== null && _c !== void 0 ? _c : 0;
425
+ return hslToHex(h, s, l);
426
+ }
427
+ function setAlpha(color, alpha) {
428
+ var _a, _b, _c;
429
+ const n = normalizeColor(color);
430
+ const r = (_a = n.r) !== null && _a !== void 0 ? _a : 0;
431
+ const g = (_b = n.g) !== null && _b !== void 0 ? _b : 0;
432
+ const b = (_c = n.b) !== null && _c !== void 0 ? _c : 0;
433
+ const a = Math.max(0, Math.min(1, alpha));
434
+ return `rgba(${r}, ${g}, ${b}, ${+a.toFixed(3)})`;
435
+ }
436
+ function getAlpha(color) {
437
+ var _a;
438
+ const n = normalizeColor(color);
439
+ return (_a = n.a) !== null && _a !== void 0 ? _a : 1;
440
+ }
441
+ function invertColor(color) {
442
+ var _a, _b, _c;
443
+ const n = normalizeColor(color);
444
+ const r = 255 - ((_a = n.r) !== null && _a !== void 0 ? _a : 0);
445
+ const g = 255 - ((_b = n.g) !== null && _b !== void 0 ? _b : 0);
446
+ const b = 255 - ((_c = n.b) !== null && _c !== void 0 ? _c : 0);
447
+ return rgbToHex({ r, g, b });
448
+ }
449
+ function grayscale(color) {
450
+ var _a, _b, _c;
451
+ const n = normalizeColor(color);
452
+ const r = (_a = n.r) !== null && _a !== void 0 ? _a : 0;
453
+ const g = (_b = n.g) !== null && _b !== void 0 ? _b : 0;
454
+ const b = (_c = n.b) !== null && _c !== void 0 ? _c : 0;
455
+ // Perceptual luminance weights (ITU-R BT.709)
456
+ const gray = Math.round(0.2126 * r + 0.7152 * g + 0.0722 * b);
457
+ return rgbToHex({ r: gray, g: gray, b: gray });
458
+ }
459
+ function clamp01(v) { return Math.max(0, Math.min(1, v)); }
460
+ function toHex2(n) { return Math.round(n).toString(16).padStart(2, '0'); }
461
+ function rgbToHex({ r, g, b }) {
462
+ return `#${toHex2(r)}${toHex2(g)}${toHex2(b)}`.toLowerCase();
463
+ }
464
+ function rgbaToHex({ r, g, b, a }) {
465
+ const aa = Math.round(clamp01(a) * 255);
466
+ return `#${toHex2(r)}${toHex2(g)}${toHex2(b)}${toHex2(aa)}`.toLowerCase();
467
+ }
468
+ function rgbToRgbaString({ r, g, b }, a) {
469
+ return `rgba(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)}, ${+a.toFixed(3)})`;
470
+ }
471
+ function rgbaStringToRgba(str) {
472
+ const s = str.trim().toLowerCase();
473
+ const m = s.match(/rgba?\(([^)]+)\)/);
474
+ if (!m)
475
+ return null;
476
+ const parts = m[1].split(/,\s*/).map(p => p.trim());
477
+ if (parts.length < 3)
478
+ return null;
479
+ const parseChannel = (v) => v.endsWith('%') ? Math.round(parseFloat(v) * 2.55) : Math.round(parseFloat(v));
480
+ const r = parseChannel(parts[0]);
481
+ const g = parseChannel(parts[1]);
482
+ const b = parseChannel(parts[2]);
483
+ const a = parts[3] !== undefined ? parseFloat(parts[3]) : 1;
484
+ return { r, g, b, a };
485
+ }
486
+ function rgbToHsl({ r, g, b }) {
487
+ const rd = r / 255, gd = g / 255, bd = b / 255;
488
+ const max = Math.max(rd, gd, bd), min = Math.min(rd, gd, bd);
489
+ let h = 0, s = 0;
490
+ const l = (max + min) / 2;
491
+ if (max !== min) {
492
+ const d = max - min;
493
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
494
+ switch (max) {
495
+ case rd:
496
+ h = (gd - bd) / d + (gd < bd ? 6 : 0);
497
+ break;
498
+ case gd:
499
+ h = (bd - rd) / d + 2;
500
+ break;
501
+ case bd:
502
+ h = (rd - gd) / d + 4;
503
+ break;
504
+ }
505
+ h /= 6;
506
+ }
507
+ return [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100)];
508
+ }
509
+ function hslToRgb(h, s, l) {
510
+ h = ((h % 360) + 360) % 360;
511
+ s = Math.max(0, Math.min(100, s)) / 100;
512
+ l = Math.max(0, Math.min(100, l)) / 100;
513
+ const c = (1 - Math.abs(2 * l - 1)) * s;
514
+ const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
515
+ const m = l - c / 2;
516
+ let rd = 0, gd = 0, bd = 0;
517
+ if (h >= 0 && h < 60) {
518
+ rd = c;
519
+ gd = x;
520
+ bd = 0;
521
+ }
522
+ else if (h >= 60 && h < 120) {
523
+ rd = x;
524
+ gd = c;
525
+ bd = 0;
526
+ }
527
+ else if (h >= 120 && h < 180) {
528
+ rd = 0;
529
+ gd = c;
530
+ bd = x;
531
+ }
532
+ else if (h >= 180 && h < 240) {
533
+ rd = 0;
534
+ gd = x;
535
+ bd = c;
536
+ }
537
+ else if (h >= 240 && h < 300) {
538
+ rd = x;
539
+ gd = 0;
540
+ bd = c;
541
+ }
542
+ else {
543
+ rd = c;
544
+ gd = 0;
545
+ bd = x;
546
+ }
547
+ return { r: Math.round((rd + m) * 255), g: Math.round((gd + m) * 255), b: Math.round((bd + m) * 255) };
548
+ }
549
+ function rgbToHsv({ r, g, b }) {
550
+ const rd = r / 255, gd = g / 255, bd = b / 255;
551
+ const max = Math.max(rd, gd, bd), min = Math.min(rd, gd, bd);
552
+ const v = max;
553
+ const d = max - min;
554
+ const s = max === 0 ? 0 : d / max;
555
+ let h = 0;
556
+ if (d !== 0) {
557
+ switch (max) {
558
+ case rd:
559
+ h = (gd - bd) / d + (gd < bd ? 6 : 0);
560
+ break;
561
+ case gd:
562
+ h = (bd - rd) / d + 2;
563
+ break;
564
+ case bd:
565
+ h = (rd - gd) / d + 4;
566
+ break;
567
+ }
568
+ h /= 6;
569
+ }
570
+ return [Math.round(h * 360), Math.round(s * 100), Math.round(v * 100)];
571
+ }
572
+ function hsvToRgb(h, s, v) {
573
+ h = ((h % 360) + 360) % 360;
574
+ s = Math.max(0, Math.min(100, s)) / 100;
575
+ v = Math.max(0, Math.min(100, v)) / 100;
576
+ const i = Math.floor(h / 60);
577
+ const f = h / 60 - i;
578
+ const p = v * (1 - s);
579
+ const q = v * (1 - f * s);
580
+ const t = v * (1 - (1 - f) * s);
581
+ let rd = 0, gd = 0, bd = 0;
582
+ switch (i) {
583
+ case 0:
584
+ rd = v;
585
+ gd = t;
586
+ bd = p;
587
+ break;
588
+ case 1:
589
+ rd = q;
590
+ gd = v;
591
+ bd = p;
592
+ break;
593
+ case 2:
594
+ rd = p;
595
+ gd = v;
596
+ bd = t;
597
+ break;
598
+ case 3:
599
+ rd = p;
600
+ gd = q;
601
+ bd = v;
602
+ break;
603
+ case 4:
604
+ rd = t;
605
+ gd = p;
606
+ bd = v;
607
+ break;
608
+ default:
609
+ rd = v;
610
+ gd = p;
611
+ bd = q;
612
+ break;
613
+ }
614
+ return { r: Math.round(rd * 255), g: Math.round(gd * 255), b: Math.round(bd * 255) };
615
+ }
616
+ function hexToHsv(hex) {
617
+ const [r, g, b] = hexToRgb(hex);
618
+ return rgbToHsv({ r, g, b });
619
+ }
620
+ function hsvToHex(h, s, v) {
621
+ const { r, g, b } = hsvToRgb(h, s, v);
622
+ return rgbToHex({ r, g, b });
623
+ }
624
+ function hex8ToRgba(hex) {
625
+ let h = hex.trim();
626
+ if (!h.startsWith('#'))
627
+ h = `#${h}`;
628
+ if (h.length === 5) { // #rgba shorthand
629
+ h = `#${h[1]}${h[1]}${h[2]}${h[2]}${h[3]}${h[3]}${h[4]}${h[4]}`;
630
+ }
631
+ if (h.length !== 9)
632
+ return null;
633
+ const r = parseInt(h.slice(1, 3), 16);
634
+ const g = parseInt(h.slice(3, 5), 16);
635
+ const b = parseInt(h.slice(5, 7), 16);
636
+ const a = parseInt(h.slice(7, 9), 16) / 255;
637
+ return { r, g, b, a };
638
+ }
639
+ function rgbaToHex8({ r, g, b, a }) {
640
+ return rgbaToHex({ r, g, b, a });
641
+ }
642
+ function normalizeColor(input) {
643
+ if (typeof input !== 'string') {
644
+ if ('r' in input && 'g' in input && 'b' in input) {
645
+ const { r, g, b } = input;
646
+ const hex = rgbToHex({ r, g, b });
647
+ const [h, s, l] = rgbToHsl({ r, g, b });
648
+ const [hh, ss, vv] = rgbToHsv({ r, g, b });
649
+ return { type: 'rgb', hex, r, g, b, a: 1, h, s, l, v: vv };
650
+ }
651
+ if ('h' in input && 's' in input && 'l' in input) {
652
+ const { h, s, l } = input;
653
+ const { r, g, b } = hslToRgb(h, s, l);
654
+ const hex = rgbToHex({ r, g, b });
655
+ const [hh, ss, vv] = rgbToHsv({ r, g, b });
656
+ return { type: 'hsl', hex, r, g, b, a: 1, h, s, l, v: vv };
657
+ }
658
+ return { type: 'unknown' };
659
+ }
660
+ const str = input.trim();
661
+ if (isCssVariable(str))
662
+ return { type: 'css-var', raw: str };
663
+ if (isHexColor(str)) {
664
+ const hex = normalizeHex(str);
665
+ const [r, g, b] = hexToRgb(hex);
666
+ const [h, s, l] = hexToHsl(hex);
667
+ const [hh, ss, vv] = rgbToHsv({ r, g, b });
668
+ return { type: 'hex', hex, r, g, b, a: 1, h, s, l, v: vv };
669
+ }
670
+ const hex8 = str.match(/^#([0-9a-f]{8}|[0-9a-f]{4})$/i);
671
+ if (hex8) {
672
+ const rgba = hex8ToRgba(str);
673
+ if (rgba) {
674
+ const { r, g, b, a } = rgba;
675
+ const hex = rgbToHex({ r, g, b });
676
+ const [h, s, l] = rgbToHsl({ r, g, b });
677
+ const [hh, ss, vv] = rgbToHsv({ r, g, b });
678
+ return { type: 'hex', hex, r, g, b, a, h, s, l, v: vv };
679
+ }
680
+ }
681
+ if (isRgbColor(str)) {
682
+ const rgba = rgbaStringToRgba(str);
683
+ if (rgba) {
684
+ const { r, g, b, a } = rgba;
685
+ const hex = rgbToHex({ r, g, b });
686
+ const [h, s, l] = rgbToHsl({ r, g, b });
687
+ const [hh, ss, vv] = rgbToHsv({ r, g, b });
688
+ return { type: 'rgb', hex, r, g, b, a, h, s, l, v: vv };
689
+ }
690
+ }
691
+ if (isHslColor(str)) {
692
+ const m = str.match(/hsla?\(([^)]+)\)/i);
693
+ if (m) {
694
+ const parts = m[1].split(/,\s*/);
695
+ const h = parseFloat(parts[0]);
696
+ const s = parseFloat(parts[1]);
697
+ const l = parseFloat(parts[2]);
698
+ const a = parts[3] ? parseFloat(parts[3]) : 1;
699
+ const { r, g, b } = hslToRgb(h, s, l);
700
+ const hex = rgbToHex({ r, g, b });
701
+ const [hh, ss, vv] = rgbToHsv({ r, g, b });
702
+ return { type: 'hsl', hex, r, g, b, a, h, s, l, v: vv };
703
+ }
704
+ }
705
+ if (str === 'transparent')
706
+ return { type: 'named', hex: '#000000', r: 0, g: 0, b: 0, a: 0 };
707
+ // 4-digit #RGBA hex
708
+ if (/^#[0-9a-f]{4}$/i.test(str)) {
709
+ const rgba = shortHexToRgba(str);
710
+ if (rgba) {
711
+ const { r, g, b, a } = rgba;
712
+ const hex = rgbToHex({ r, g, b });
713
+ const [h, s, l] = rgbToHsl({ r, g, b });
714
+ const [, , vv] = rgbToHsv({ r, g, b });
715
+ return { type: 'hex', hex, r, g, b, a, h, s, l, v: vv };
716
+ }
717
+ }
718
+ // oklch / oklcha
719
+ if (isOklchColor(str)) {
720
+ const parsed = parseOklchString(str);
721
+ if (parsed) {
722
+ const { r, g, b } = oklchToRgb({ L: parsed.L, C: parsed.C, H: parsed.H });
723
+ const hex = rgbToHex({ r, g, b });
724
+ const [h, s, l] = rgbToHsl({ r, g, b });
725
+ const [, , vv] = rgbToHsv({ r, g, b });
726
+ return { type: 'oklch', hex, r, g, b, a: parsed.alpha, h, s, l, v: vv };
727
+ }
728
+ }
729
+ // color(display-p3 ...) / color(srgb ...)
730
+ if (isColorFunction(str)) {
731
+ const parsed = parseColorFn(str);
732
+ if (parsed) {
733
+ const { r: p3r, g: p3g, b: p3b, alpha } = parsed;
734
+ // Convert from p3/srgb (0-1) to sRGB 0-255
735
+ let r, g, b;
736
+ if (parsed.space === 'display-p3') {
737
+ const srgb = displayP3ToRgb({ r: p3r, g: p3g, b: p3b });
738
+ r = srgb.r;
739
+ g = srgb.g;
740
+ b = srgb.b;
741
+ }
742
+ else {
743
+ r = Math.round(Math.max(0, Math.min(255, p3r * 255)));
744
+ g = Math.round(Math.max(0, Math.min(255, p3g * 255)));
745
+ b = Math.round(Math.max(0, Math.min(255, p3b * 255)));
746
+ }
747
+ const hex = rgbToHex({ r, g, b });
748
+ const [h, s, l] = rgbToHsl({ r, g, b });
749
+ const [, , vv] = rgbToHsv({ r, g, b });
750
+ return { type: 'color', hex, r, g, b, a: alpha, h, s, l, v: vv };
751
+ }
752
+ }
753
+ return { type: 'unknown' };
754
+ }
755
+ function complement(color) {
756
+ var _a;
757
+ return rotateHue((_a = normalizeColor(color).hex) !== null && _a !== void 0 ? _a : '#000000', 180);
758
+ }
759
+ function triadic(color) {
760
+ var _a;
761
+ const hex = (_a = normalizeColor(color).hex) !== null && _a !== void 0 ? _a : '#000000';
762
+ return [hex, rotateHue(hex, 120), rotateHue(hex, 240)];
763
+ }
764
+ function analogous(color, angle = 30) {
765
+ var _a;
766
+ const hex = (_a = normalizeColor(color).hex) !== null && _a !== void 0 ? _a : '#000000';
767
+ return [rotateHue(hex, -angle), hex, rotateHue(hex, angle)];
768
+ }
769
+ function splitComplementary(color) {
770
+ var _a;
771
+ const hex = (_a = normalizeColor(color).hex) !== null && _a !== void 0 ? _a : '#000000';
772
+ return [hex, rotateHue(hex, 150), rotateHue(hex, 210)];
773
+ }
774
+ function tetradic(color) {
775
+ var _a;
776
+ const hex = (_a = normalizeColor(color).hex) !== null && _a !== void 0 ? _a : '#000000';
777
+ return [hex, rotateHue(hex, 90), rotateHue(hex, 180), rotateHue(hex, 270)];
778
+ }
779
+ function colorShades(color, steps = 9) {
780
+ var _a, _b;
781
+ const n = normalizeColor(color);
782
+ const h = (_a = n.h) !== null && _a !== void 0 ? _a : 0;
783
+ const s = (_b = n.s) !== null && _b !== void 0 ? _b : 0;
784
+ const result = [];
785
+ for (let i = 0; i < steps; i++) {
786
+ const l = Math.round(100 - (i / (steps - 1)) * 100);
787
+ result.push(hslToHex(h, s, l));
788
+ }
789
+ return result;
790
+ }
791
+ function monochromatic(color, steps = 5) {
792
+ var _a, _b;
793
+ const n = normalizeColor(color);
794
+ const h = (_a = n.h) !== null && _a !== void 0 ? _a : 0;
795
+ const l = (_b = n.l) !== null && _b !== void 0 ? _b : 50;
796
+ const result = [];
797
+ for (let i = 0; i < steps; i++) {
798
+ const s = Math.round((i / (steps - 1)) * 100);
799
+ result.push(hslToHex(h, s, l));
800
+ }
801
+ return result;
802
+ }
803
+ function _lerpHue(h1, h2, t, mode = 'shorter') {
804
+ let d = h2 - h1;
805
+ if (mode === 'shorter') {
806
+ if (d > 180)
807
+ d -= 360;
808
+ else if (d < -180)
809
+ d += 360;
810
+ }
811
+ else if (mode === 'longer') {
812
+ if (d > 0 && d < 180)
813
+ d -= 360;
814
+ else if (d < 0 && d > -180)
815
+ d += 360;
816
+ }
817
+ else if (mode === 'increasing') {
818
+ if (d < 0)
819
+ d += 360;
820
+ }
821
+ else if (mode === 'decreasing') {
822
+ if (d > 0)
823
+ d -= 360;
824
+ }
825
+ return h1 + d * t;
826
+ }
827
+ function _formatMixResult(r, g, b, a, out) {
828
+ if (out === 'hex')
829
+ return rgbToHex({ r: Math.round(r), g: Math.round(g), b: Math.round(b) });
830
+ if (out === 'rgba')
831
+ return rgbToRgbaString({ r: Math.round(r), g: Math.round(g), b: Math.round(b) }, a);
832
+ if (out === 'rgb')
833
+ return `rgb(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)})`;
834
+ if (out === 'hsl') {
835
+ const [hh, ss, ll] = rgbToHsl({ r: Math.round(r), g: Math.round(g), b: Math.round(b) });
836
+ return `hsl(${hh}, ${ss}%, ${ll}%)`;
837
+ }
838
+ return rgbToHex({ r: Math.round(r), g: Math.round(g), b: Math.round(b) });
839
+ }
840
+ function mixColors(c1, c2, t, opts) {
841
+ 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;
842
+ const o1 = normalizeColor(c1);
843
+ const o2 = normalizeColor(c2);
844
+ t = Math.max(0, Math.min(1, t));
845
+ const mode = (opts === null || opts === void 0 ? void 0 : opts.mode) || 'rgb';
846
+ const out = (opts === null || opts === void 0 ? void 0 : opts.format) || 'hex';
847
+ const hueMode = (_a = opts === null || opts === void 0 ? void 0 : opts.hueInterpolation) !== null && _a !== void 0 ? _a : 'shorter';
848
+ let r = 0, g = 0, b = 0, a = 1;
849
+ if (mode === 'hsl') {
850
+ 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];
851
+ const s1 = (_f = o1.s) !== null && _f !== void 0 ? _f : 0;
852
+ const l1 = (_g = o1.l) !== null && _g !== void 0 ? _g : 0;
853
+ 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];
854
+ const s2 = (_m = o2.s) !== null && _m !== void 0 ? _m : 0;
855
+ const l2 = (_o = o2.l) !== null && _o !== void 0 ? _o : 0;
856
+ const ih = _lerpHue(h1, h2, t, hueMode);
857
+ const rgb = hslToRgb(ih, s1 + (s2 - s1) * t, l1 + (l2 - l1) * t);
858
+ r = rgb.r;
859
+ g = rgb.g;
860
+ b = rgb.b;
861
+ 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;
862
+ }
863
+ else if (mode === 'lab') {
864
+ 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 });
865
+ 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 });
866
+ 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 });
867
+ r = mixed.r;
868
+ g = mixed.g;
869
+ b = mixed.b;
870
+ 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;
871
+ }
872
+ else if (mode === 'lch') {
873
+ 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 });
874
+ 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 });
875
+ 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) });
876
+ r = mixed.r;
877
+ g = mixed.g;
878
+ b = mixed.b;
879
+ 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;
880
+ }
881
+ else if (mode === 'oklab') {
882
+ 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 });
883
+ 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 });
884
+ 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 });
885
+ r = mixed.r;
886
+ g = mixed.g;
887
+ b = mixed.b;
888
+ 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;
889
+ }
890
+ else if (mode === 'oklch') {
891
+ 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 });
892
+ 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 });
893
+ 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) });
894
+ r = mixed.r;
895
+ g = mixed.g;
896
+ b = mixed.b;
897
+ 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;
898
+ }
899
+ else {
900
+ r = ((_28 = o1.r) !== null && _28 !== void 0 ? _28 : 0) * (1 - t) + ((_29 = o2.r) !== null && _29 !== void 0 ? _29 : 0) * t;
901
+ g = ((_30 = o1.g) !== null && _30 !== void 0 ? _30 : 0) * (1 - t) + ((_31 = o2.g) !== null && _31 !== void 0 ? _31 : 0) * t;
902
+ b = ((_32 = o1.b) !== null && _32 !== void 0 ? _32 : 0) * (1 - t) + ((_33 = o2.b) !== null && _33 !== void 0 ? _33 : 0) * t;
903
+ a = ((_34 = o1.a) !== null && _34 !== void 0 ? _34 : 1) * (1 - t) + ((_35 = o2.a) !== null && _35 !== void 0 ? _35 : 1) * t;
904
+ }
905
+ return _formatMixResult(r, g, b, a, out);
906
+ }
907
+ function relativeLuminance(color) {
908
+ var _a, _b, _c;
909
+ const n = normalizeColor(color);
910
+ const r = ((_a = n.r) !== null && _a !== void 0 ? _a : 0) / 255;
911
+ const g = ((_b = n.g) !== null && _b !== void 0 ? _b : 0) / 255;
912
+ const b = ((_c = n.b) !== null && _c !== void 0 ? _c : 0) / 255;
913
+ const srgbToLin = (c) => c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
914
+ const R = srgbToLin(r), G = srgbToLin(g), B = srgbToLin(b);
915
+ return 0.2126 * R + 0.7152 * G + 0.0722 * B;
916
+ }
917
+ function contrastRatio(a, b) {
918
+ const L1 = relativeLuminance(a);
919
+ const L2 = relativeLuminance(b);
920
+ const light = Math.max(L1, L2);
921
+ const dark = Math.min(L1, L2);
922
+ return +((light + 0.05) / (dark + 0.05)).toFixed(2);
923
+ }
924
+ function isDark(color, threshold = 0.5) {
925
+ return relativeLuminance(color) < threshold;
926
+ }
927
+ function isLight(color, threshold = 0.5) {
928
+ return !isDark(color, threshold);
929
+ }
930
+ function rgbToCmyk({ r, g, b }) {
931
+ const rd = r / 255, gd = g / 255, bd = b / 255;
932
+ const k = 1 - Math.max(rd, gd, bd);
933
+ if (k === 1)
934
+ return { c: 0, m: 0, y: 0, k: 1 };
935
+ const c = (1 - rd - k) / (1 - k);
936
+ const m = (1 - gd - k) / (1 - k);
937
+ const y = (1 - bd - k) / (1 - k);
938
+ return { c, m, y, k };
939
+ }
940
+ function cmykToRgb({ c, m, y, k }) {
941
+ const r = 255 * (1 - c) * (1 - k);
942
+ const g = 255 * (1 - m) * (1 - k);
943
+ const b = 255 * (1 - y) * (1 - k);
944
+ return { r: Math.round(r), g: Math.round(g), b: Math.round(b) };
945
+ }
946
+ function srgbToLinear(v) {
947
+ v = v / 255;
948
+ return v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
949
+ }
950
+ function linearToSrgb(v) {
951
+ const t = v <= 0.0031308 ? 12.92 * v : 1.055 * Math.pow(v, 1 / 2.4) - 0.055;
952
+ return Math.round(Math.max(0, Math.min(1, t)) * 255);
953
+ }
954
+ function rgbToXyz({ r, g, b }) {
955
+ const R = srgbToLinear(r);
956
+ const G = srgbToLinear(g);
957
+ const B = srgbToLinear(b);
958
+ const X = R * 0.4124564 + G * 0.3575761 + B * 0.1804375;
959
+ const Y = R * 0.2126729 + G * 0.7151522 + B * 0.0721750;
960
+ const Z = R * 0.0193339 + G * 0.1191920 + B * 0.9503041;
961
+ return { X: X * 100, Y: Y * 100, Z: Z * 100 };
962
+ }
963
+ function xyzToRgb({ X, Y, Z }) {
964
+ X = X / 100;
965
+ Y = Y / 100;
966
+ Z = Z / 100;
967
+ let R = X * 3.2404542 + Y * -1.5371385 + Z * -0.4985314;
968
+ let G = X * -0.9692660 + Y * 1.8760108 + Z * 0.0415560;
969
+ let B = X * 0.0556434 + Y * -0.2040259 + Z * 1.0572252;
970
+ R = linearToSrgb(R);
971
+ G = linearToSrgb(G);
972
+ B = linearToSrgb(B);
973
+ return { r: R, g: G, b: B };
974
+ }
975
+ function rgbToLab({ r, g, b }) {
976
+ const { X, Y, Z } = rgbToXyz({ r, g, b });
977
+ const refX = 95.047, refY = 100.0, refZ = 108.883;
978
+ const x = X / refX, y = Y / refY, z = Z / refZ;
979
+ const fx = x > 0.008856 ? Math.cbrt(x) : (7.787 * x) + 16 / 116;
980
+ const fy = y > 0.008856 ? Math.cbrt(y) : (7.787 * y) + 16 / 116;
981
+ const fz = z > 0.008856 ? Math.cbrt(z) : (7.787 * z) + 16 / 116;
982
+ const L = (116 * fy) - 16;
983
+ const a = 500 * (fx - fy);
984
+ const b2 = 200 * (fy - fz);
985
+ return { L, a, b: b2 };
986
+ }
987
+ function labToRgb({ L, a, b }) {
988
+ const refX = 95.047, refY = 100.0, refZ = 108.883;
989
+ let fy = (L + 16) / 116;
990
+ let fx = a / 500 + fy;
991
+ let fz = fy - b / 200;
992
+ const fx3 = Math.pow(fx, 3);
993
+ const fz3 = Math.pow(fz, 3);
994
+ const fy3 = Math.pow(fy, 3);
995
+ const xr = fx3 > 0.008856 ? fx3 : (fx - 16 / 116) / 7.787;
996
+ const yr = L > (903.3 * 0.008856) ? fy3 : L / 903.3;
997
+ const zr = fz3 > 0.008856 ? fz3 : (fz - 16 / 116) / 7.787;
998
+ const X = xr * refX, Y = yr * refY, Z = zr * refZ;
999
+ return xyzToRgb({ X, Y, Z });
1000
+ }
1001
+ function rgbToLch({ r, g, b }) {
1002
+ const { L, a, b: bb } = rgbToLab({ r, g, b });
1003
+ const C = Math.sqrt(a * a + bb * bb);
1004
+ let H = Math.atan2(bb, a) * (180 / Math.PI);
1005
+ if (H < 0)
1006
+ H += 360;
1007
+ return { L, C, H };
1008
+ }
1009
+ function lchToRgb({ L, C, H }) {
1010
+ const a = Math.cos(H * Math.PI / 180) * C;
1011
+ const b = Math.sin(H * Math.PI / 180) * C;
1012
+ return labToRgb({ L, a, b });
1013
+ }
1014
+ function wcagLevel(foreground, background) {
1015
+ const ratio = contrastRatio(foreground, background);
1016
+ if (ratio >= 7)
1017
+ return 'AAA';
1018
+ if (ratio >= 4.5)
1019
+ return 'AA';
1020
+ if (ratio >= 3)
1021
+ return 'AA-large';
1022
+ return 'fail';
1023
+ }
1024
+ function bestTextColor(background) {
1025
+ const onBlack = contrastRatio(background, '#000000');
1026
+ const onWhite = contrastRatio(background, '#ffffff');
1027
+ return onBlack >= onWhite ? '#000000' : '#ffffff';
1028
+ }
1029
+ function bestContrastColor(background, candidates) {
1030
+ let best = candidates[0];
1031
+ let bestRatio = -1;
1032
+ for (const c of candidates) {
1033
+ const ratio = contrastRatio(background, c);
1034
+ if (ratio > bestRatio) {
1035
+ bestRatio = ratio;
1036
+ best = c;
1037
+ }
1038
+ }
1039
+ return best;
1040
+ }
1041
+ // ─── HWB ─────────────────────────────────────────────────────────────────────
1042
+ function rgbToHwb({ r, g, b }) {
1043
+ const rd = r / 255, gd = g / 255, bd = b / 255;
1044
+ const max = Math.max(rd, gd, bd), min = Math.min(rd, gd, bd);
1045
+ const w = min;
1046
+ const bl = 1 - max;
1047
+ let h = 0;
1048
+ if (max !== min) {
1049
+ const d = max - min;
1050
+ switch (max) {
1051
+ case rd:
1052
+ h = (gd - bd) / d + (gd < bd ? 6 : 0);
1053
+ break;
1054
+ case gd:
1055
+ h = (bd - rd) / d + 2;
1056
+ break;
1057
+ case bd:
1058
+ h = (rd - gd) / d + 4;
1059
+ break;
1060
+ }
1061
+ h /= 6;
1062
+ }
1063
+ return [Math.round(h * 360), Math.round(w * 100), Math.round(bl * 100)];
1064
+ }
1065
+ function hwbToRgb(H, W, B) {
1066
+ H = ((H % 360) + 360) % 360;
1067
+ const w = W / 100, b = B / 100;
1068
+ if (w + b >= 1) {
1069
+ const gray = Math.round((w / (w + b)) * 255);
1070
+ return { r: gray, g: gray, b: gray };
1071
+ }
1072
+ const { r, g, b: rb } = hslToRgb(H, 100, 50);
1073
+ const factor = 1 - w - b;
1074
+ return {
1075
+ r: Math.round(r / 255 * factor * 255 + w * 255),
1076
+ g: Math.round(g / 255 * factor * 255 + w * 255),
1077
+ b: Math.round(rb / 255 * factor * 255 + w * 255),
1078
+ };
1079
+ }
1080
+ function toHwbString(H, W, B, alpha) {
1081
+ if (alpha !== undefined)
1082
+ return `hwb(${H} ${W}% ${B}% / ${+alpha.toFixed(3)})`;
1083
+ return `hwb(${H} ${W}% ${B}%)`;
1084
+ }
1085
+ function parseHwbString(str) {
1086
+ const m = str.trim().match(/hwb\(\s*([\d.+-]+)\s+([\d.]+)%\s+([\d.]+)%(?:\s*\/\s*([\d.]+))?\s*\)/i);
1087
+ if (!m)
1088
+ return null;
1089
+ return { H: parseFloat(m[1]), W: parseFloat(m[2]), B: parseFloat(m[3]), alpha: m[4] !== undefined ? parseFloat(m[4]) : 1 };
1090
+ }
1091
+ // ─── OKLCH / OKLAB ───────────────────────────────────────────────────────────
1092
+ function srgbToOkLinear(v) {
1093
+ v = v / 255;
1094
+ return v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
1095
+ }
1096
+ function okLinearToSrgb(v) {
1097
+ const t = v <= 0.0031308 ? 12.92 * v : 1.055 * Math.pow(v, 1 / 2.4) - 0.055;
1098
+ return Math.round(Math.max(0, Math.min(1, t)) * 255);
1099
+ }
1100
+ function rgbToOklab({ r, g, b }) {
1101
+ const R = srgbToOkLinear(r), G = srgbToOkLinear(g), B = srgbToOkLinear(b);
1102
+ const l = Math.cbrt(0.4122214708 * R + 0.5363325363 * G + 0.0514459929 * B);
1103
+ const m = Math.cbrt(0.2119034982 * R + 0.6806995451 * G + 0.1073969566 * B);
1104
+ const s = Math.cbrt(0.0883024619 * R + 0.2817188376 * G + 0.6299787005 * B);
1105
+ return {
1106
+ L: 0.2104542553 * l + 0.7936177850 * m - 0.0040720468 * s,
1107
+ a: 1.9779984951 * l - 2.4285922050 * m + 0.4505937099 * s,
1108
+ b: 0.0259040371 * l + 0.7827717662 * m - 0.8086757660 * s,
1109
+ };
1110
+ }
1111
+ function oklabToRgb({ L, a, b }) {
1112
+ const l = Math.pow(L + 0.3963377774 * a + 0.2158037573 * b, 3);
1113
+ const m = Math.pow(L - 0.1055613458 * a - 0.0638541728 * b, 3);
1114
+ const s = Math.pow(L - 0.0894841775 * a - 1.2914855480 * b, 3);
1115
+ const R = okLinearToSrgb(+4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s);
1116
+ const G = okLinearToSrgb(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s);
1117
+ const B = okLinearToSrgb(-0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s);
1118
+ return { r: R, g: G, b: B };
1119
+ }
1120
+ function rgbToOklch({ r, g, b }) {
1121
+ const { L, a, b: bb } = rgbToOklab({ r, g, b });
1122
+ const C = Math.sqrt(a * a + bb * bb);
1123
+ let H = Math.atan2(bb, a) * (180 / Math.PI);
1124
+ if (H < 0)
1125
+ H += 360;
1126
+ return { L, C, H };
1127
+ }
1128
+ function oklchToRgb({ L, C, H }) {
1129
+ const a = Math.cos(H * Math.PI / 180) * C;
1130
+ const b = Math.sin(H * Math.PI / 180) * C;
1131
+ return oklabToRgb({ L, a, b });
1132
+ }
1133
+ // ─── Utilities ───────────────────────────────────────────────────────────────
1134
+ function toHslString(h, s, l, alpha) {
1135
+ if (alpha !== undefined)
1136
+ return `hsla(${h}, ${s}%, ${l}%, ${+alpha.toFixed(3)})`;
1137
+ return `hsl(${h}, ${s}%, ${l}%)`;
1138
+ }
1139
+ function colorDeltaE(c1, c2) {
1140
+ var _a, _b, _c, _d, _e, _f;
1141
+ const n1 = normalizeColor(c1);
1142
+ const n2 = normalizeColor(c2);
1143
+ 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 });
1144
+ 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 });
1145
+ // CIEDE2000
1146
+ const deg = (rad) => rad * (180 / Math.PI);
1147
+ const rad = (d) => d * (Math.PI / 180);
1148
+ const { L: L1, a: a1, b: b1 } = lab1;
1149
+ const { L: L2, a: a2, b: b2 } = lab2;
1150
+ const dL = L2 - L1;
1151
+ const Lm = (L1 + L2) / 2;
1152
+ const C1 = Math.sqrt(a1 * a1 + b1 * b1);
1153
+ const C2 = Math.sqrt(a2 * a2 + b2 * b2);
1154
+ const Cm = (C1 + C2) / 2;
1155
+ const Cm7 = Math.pow(Cm, 7);
1156
+ const G = 0.5 * (1 - Math.sqrt(Cm7 / (Cm7 + Math.pow(25, 7))));
1157
+ const a1p = a1 * (1 + G), a2p = a2 * (1 + G);
1158
+ const C1p = Math.sqrt(a1p * a1p + b1 * b1);
1159
+ const C2p = Math.sqrt(a2p * a2p + b2 * b2);
1160
+ const dCp = C2p - C1p;
1161
+ const Cmp = (C1p + C2p) / 2;
1162
+ let h1p = deg(Math.atan2(b1, a1p));
1163
+ if (h1p < 0)
1164
+ h1p += 360;
1165
+ let h2p = deg(Math.atan2(b2, a2p));
1166
+ if (h2p < 0)
1167
+ h2p += 360;
1168
+ let dhp;
1169
+ if (Math.abs(h1p - h2p) <= 180)
1170
+ dhp = h2p - h1p;
1171
+ else if (h2p <= h1p)
1172
+ dhp = h2p - h1p + 360;
1173
+ else
1174
+ dhp = h2p - h1p - 360;
1175
+ const dHp = 2 * Math.sqrt(C1p * C2p) * Math.sin(rad(dhp / 2));
1176
+ let Hmp;
1177
+ if (Math.abs(h1p - h2p) <= 180)
1178
+ Hmp = (h1p + h2p) / 2;
1179
+ else if (h1p + h2p < 360)
1180
+ Hmp = (h1p + h2p + 360) / 2;
1181
+ else
1182
+ Hmp = (h1p + h2p - 360) / 2;
1183
+ const T = 1
1184
+ - 0.17 * Math.cos(rad(Hmp - 30))
1185
+ + 0.24 * Math.cos(rad(2 * Hmp))
1186
+ + 0.32 * Math.cos(rad(3 * Hmp + 6))
1187
+ - 0.20 * Math.cos(rad(4 * Hmp - 63));
1188
+ const SL = 1 + 0.015 * Math.pow(Lm - 50, 2) / Math.sqrt(20 + Math.pow(Lm - 50, 2));
1189
+ const SC = 1 + 0.045 * Cmp;
1190
+ const SH = 1 + 0.015 * Cmp * T;
1191
+ const Cmp7 = Math.pow(Cmp, 7);
1192
+ const RC = 2 * Math.sqrt(Cmp7 / (Cmp7 + Math.pow(25, 7)));
1193
+ const dTheta = 30 * Math.exp(-Math.pow((Hmp - 275) / 25, 2));
1194
+ const RT = -Math.sin(rad(2 * dTheta)) * RC;
1195
+ return +Math.sqrt(Math.pow(dL / SL, 2) +
1196
+ Math.pow(dCp / SC, 2) +
1197
+ Math.pow(dHp / SH, 2) +
1198
+ RT * (dCp / SC) * (dHp / SH)).toFixed(4);
1199
+ }
1200
+ function randomColor(options) {
1201
+ var _a, _b, _c;
1202
+ const [hMin, hMax] = (_a = options === null || options === void 0 ? void 0 : options.hRange) !== null && _a !== void 0 ? _a : [0, 360];
1203
+ const [sMin, sMax] = (_b = options === null || options === void 0 ? void 0 : options.sRange) !== null && _b !== void 0 ? _b : [40, 90];
1204
+ const [lMin, lMax] = (_c = options === null || options === void 0 ? void 0 : options.lRange) !== null && _c !== void 0 ? _c : [30, 70];
1205
+ const h = Math.floor(Math.random() * (hMax - hMin)) + hMin;
1206
+ const s = Math.floor(Math.random() * (sMax - sMin)) + sMin;
1207
+ const l = Math.floor(Math.random() * (lMax - lMin)) + lMin;
1208
+ return hslToHex(h, s, l);
1209
+ }
1210
+ function toNearestNamedColor(color) {
1211
+ var _a, _b, _c;
1212
+ const n = normalizeColor(color);
1213
+ 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;
1214
+ let bestName = 'black';
1215
+ let bestDist = Infinity;
1216
+ for (const [name, hex] of Object.entries(NAMED_COLORS)) {
1217
+ const [nr, ng, nb] = hexToRgb(hex);
1218
+ const dist = Math.sqrt(Math.pow(r - nr, 2) + Math.pow(g - ng, 2) + Math.pow(b - nb, 2));
1219
+ if (dist < bestDist) {
1220
+ bestDist = dist;
1221
+ bestName = name;
1222
+ }
1223
+ }
1224
+ return bestName;
1225
+ }
1226
+ // ─── Formatting ───────────────────────────────────────────────────────────────
1227
+ function toOklchString(color, alpha) {
1228
+ var _a, _b, _c;
1229
+ const n = normalizeColor(color);
1230
+ 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 });
1231
+ const Lr = +L.toFixed(4), Cr = +C.toFixed(4), Hr = +H.toFixed(2);
1232
+ if (alpha !== undefined)
1233
+ return `oklch(${Lr} ${Cr} ${Hr} / ${+alpha.toFixed(3)})`;
1234
+ return `oklch(${Lr} ${Cr} ${Hr})`;
1235
+ }
1236
+ function toColorP3String(color, alpha) {
1237
+ var _a, _b, _c;
1238
+ const n = normalizeColor(color);
1239
+ 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 });
1240
+ const r = +p3.r.toFixed(4), g = +p3.g.toFixed(4), b = +p3.b.toFixed(4);
1241
+ if (alpha !== undefined)
1242
+ return `color(display-p3 ${r} ${g} ${b} / ${+alpha.toFixed(3)})`;
1243
+ return `color(display-p3 ${r} ${g} ${b})`;
1244
+ }
1245
+ // ─── Section 2: Interpolation ─────────────────────────────────────────────────
1246
+ function interpolateColors(color1, color2, steps, options) {
1247
+ if (steps < 2)
1248
+ return steps === 1 ? [mixColors(color1, color2, 0.5, options)] : [];
1249
+ const result = [];
1250
+ for (let i = 0; i < steps; i++) {
1251
+ result.push(mixColors(color1, color2, i / (steps - 1), options));
1252
+ }
1253
+ return result;
1254
+ }
1255
+ function createColorScale(anchors, steps, options) {
1256
+ const normalized = anchors.map((a, i, arr) => {
1257
+ var _a;
1258
+ return ({
1259
+ color: typeof a === 'string' ? a : a.color,
1260
+ 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)),
1261
+ });
1262
+ });
1263
+ normalized.sort((a, b) => a.position - b.position);
1264
+ const result = [];
1265
+ for (let i = 0; i < steps; i++) {
1266
+ const t = steps === 1 ? 0 : i / (steps - 1);
1267
+ let lo = normalized[0], hi = normalized[normalized.length - 1];
1268
+ for (let j = 0; j < normalized.length - 1; j++) {
1269
+ if (t >= normalized[j].position && t <= normalized[j + 1].position) {
1270
+ lo = normalized[j];
1271
+ hi = normalized[j + 1];
1272
+ break;
1273
+ }
1274
+ }
1275
+ const span = hi.position - lo.position;
1276
+ const localT = span === 0 ? 0 : (t - lo.position) / span;
1277
+ result.push(mixColors(lo.color, hi.color, localT, options));
1278
+ }
1279
+ return result;
1280
+ }
1281
+ function midpointColor(color1, color2, options) {
1282
+ var _a;
1283
+ return mixColors(color1, color2, 0.5, { mode: (_a = options === null || options === void 0 ? void 0 : options.space) !== null && _a !== void 0 ? _a : 'oklab' });
1284
+ }
1285
+ // ─── Section 3: Tints / Shades / Tones ───────────────────────────────────────
1286
+ function tints(color, steps = 5) {
1287
+ return interpolateColors(color, '#ffffff', steps, { space: 'oklab' });
1288
+ }
1289
+ function shades(color, steps = 5) {
1290
+ return interpolateColors(color, '#000000', steps, { space: 'oklab' });
1291
+ }
1292
+ function tones(color, steps = 5, gray = '#808080') {
1293
+ return interpolateColors(color, gray, steps, { space: 'oklab' });
1294
+ }
1295
+ // ─── Section 4: Color blindness simulation ────────────────────────────────────
1296
+ function _simulateCB(color, matrix) {
1297
+ var _a, _b, _c;
1298
+ const n = normalizeColor(color);
1299
+ // linearize
1300
+ const lin = (v) => { const c = v / 255; return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4); };
1301
+ 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); };
1302
+ 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);
1303
+ const nr = enc(matrix[0][0] * r + matrix[0][1] * g + matrix[0][2] * b);
1304
+ const ng = enc(matrix[1][0] * r + matrix[1][1] * g + matrix[1][2] * b);
1305
+ const nb = enc(matrix[2][0] * r + matrix[2][1] * g + matrix[2][2] * b);
1306
+ return rgbToHex({ r: nr, g: ng, b: nb });
1307
+ }
1308
+ const _PROTANOPIA_M = [[0.56667, 0.43333, 0.00000], [0.55833, 0.44167, 0.00000], [0.00000, 0.24167, 0.75833]];
1309
+ const _DEUTERANOPIA_M = [[0.62500, 0.37500, 0.00000], [0.70000, 0.30000, 0.00000], [0.00000, 0.30000, 0.70000]];
1310
+ const _TRITANOPIA_M = [[0.95000, 0.05000, 0.00000], [0.00000, 0.43333, 0.56667], [0.00000, 0.47500, 0.52500]];
1311
+ function simulateProtanopia(color) { return _simulateCB(color, _PROTANOPIA_M); }
1312
+ function simulateDeuteranopia(color) { return _simulateCB(color, _DEUTERANOPIA_M); }
1313
+ function simulateTritanopia(color) { return _simulateCB(color, _TRITANOPIA_M); }
1314
+ function simulateColorBlindness(color, type) {
1315
+ if (type === 'protanopia')
1316
+ return simulateProtanopia(color);
1317
+ if (type === 'deuteranopia')
1318
+ return simulateDeuteranopia(color);
1319
+ return simulateTritanopia(color);
1320
+ }
1321
+ function isReadableOnBackground(textColor, background, options) {
1322
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
1323
+ const level = (_a = options === null || options === void 0 ? void 0 : options.level) !== null && _a !== void 0 ? _a : 'AA';
1324
+ const large = (_b = options === null || options === void 0 ? void 0 : options.largeText) !== null && _b !== void 0 ? _b : false;
1325
+ const minRequired = level === 'AAA' ? (large ? 4.5 : 7) : (large ? 3 : 4.5);
1326
+ let minRatio;
1327
+ if (typeof background === 'string') {
1328
+ minRatio = contrastRatio(textColor, background);
1329
+ }
1330
+ else if (background.type === 'semi-transparent') {
1331
+ const underlay = (_c = background.underlay) !== null && _c !== void 0 ? _c : '#ffffff';
1332
+ const fg = normalizeColor(background.color);
1333
+ const bg = normalizeColor(underlay);
1334
+ const alpha = (_d = fg.a) !== null && _d !== void 0 ? _d : 1;
1335
+ 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));
1336
+ 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));
1337
+ 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));
1338
+ minRatio = contrastRatio(textColor, rgbToHex({ r: cr, g: cg, b: cb }));
1339
+ }
1340
+ else {
1341
+ const ratios = background.stops.map(stop => contrastRatio(textColor, stop));
1342
+ minRatio = Math.min(...ratios);
1343
+ }
1344
+ const wLevel = wcagLevel(textColor, typeof background === 'string' ? background : '#ffffff');
1345
+ return { readable: minRatio >= minRequired, minContrastRatio: +minRatio.toFixed(2), wcagLevel: wLevel };
1346
+ }
1347
+ function bestContrastPalette(background, palettes, options) {
1348
+ let bestIdx = 0;
1349
+ let bestScore = -1;
1350
+ let bestMin = 0, bestAvg = 0;
1351
+ palettes.forEach((palette, idx) => {
1352
+ var _a;
1353
+ const ratios = palette.map(c => contrastRatio(background, c));
1354
+ const weights = (_a = options === null || options === void 0 ? void 0 : options.weights) !== null && _a !== void 0 ? _a : ratios.map(() => 1);
1355
+ const totalW = weights.reduce((s, w) => s + w, 0);
1356
+ const avg = ratios.reduce((s, r, i) => { var _a; return s + r * ((_a = weights[i]) !== null && _a !== void 0 ? _a : 1); }, 0) / totalW;
1357
+ const min = Math.min(...ratios);
1358
+ // Score: weighted avg with heavy penalty on minimum
1359
+ const score = avg * 0.4 + min * 0.6;
1360
+ if (score > bestScore) {
1361
+ bestScore = score;
1362
+ bestIdx = idx;
1363
+ bestMin = min;
1364
+ bestAvg = avg;
1365
+ }
1366
+ });
1367
+ return {
1368
+ paletteIndex: bestIdx,
1369
+ palette: palettes[bestIdx],
1370
+ minContrastRatio: +bestMin.toFixed(2),
1371
+ avgContrastRatio: +bestAvg.toFixed(2),
1372
+ };
1373
+ }
1374
+ // ─── Section 5.1: Caching ────────────────────────────────────────────────────
1375
+ let _cacheEnabled = true;
1376
+ const _normalizeCache = new Map();
1377
+ let _cacheHits = 0;
1378
+ function clearColorCache() { _normalizeCache.clear(); _cacheHits = 0; }
1379
+ function getCacheStats() { return { size: _normalizeCache.size, hits: _cacheHits }; }
1380
+ function enableCache() { _cacheEnabled = true; }
1381
+ function disableCache() { _cacheEnabled = false; }
1382
+ // Cached normalizer wrapper — use this in performance-sensitive contexts
1383
+ function normalizeColorCached(input) {
1384
+ if (!_cacheEnabled)
1385
+ return normalizeColor(input);
1386
+ const cached = _normalizeCache.get(input);
1387
+ if (cached) {
1388
+ _cacheHits++;
1389
+ return cached;
1390
+ }
1391
+ const result = normalizeColor(input);
1392
+ _normalizeCache.set(input, result);
1393
+ return result;
1394
+ }
1395
+ // ─── Section 5.2: Generator functions ────────────────────────────────────────
1396
+ function* generateGradientColors(start, end, steps, options) {
1397
+ for (let i = 0; i < steps; i++) {
1398
+ yield mixColors(start, end, steps === 1 ? 0 : i / (steps - 1), options);
1399
+ }
1400
+ }
1401
+ function* generateTints(color, steps, options) {
1402
+ for (let i = 0; i < steps; i++) {
1403
+ yield mixColors(color, '#ffffff', steps === 1 ? 0 : i / (steps - 1), { mode: 'oklab', ...options });
1404
+ }
1405
+ }
1406
+ function* generateShades(color, steps, options) {
1407
+ for (let i = 0; i < steps; i++) {
1408
+ yield mixColors(color, '#000000', steps === 1 ? 0 : i / (steps - 1), { mode: 'oklab', ...options });
1409
+ }
1410
+ }