color-value-tools 1.1.3 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +522 -98
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,12 +4,58 @@
|
|
|
4
4
|
</h1>
|
|
5
5
|
<img
|
|
6
6
|
src="https://s3.twcstorage.ru/c9a2cc89-780f97fd-311d-4a1a-b86f-c25665c9dc46/images/npm/color-value-tools.webp"
|
|
7
|
-
alt="
|
|
7
|
+
alt="color-value-tools"
|
|
8
8
|
style="max-width:100%;width:auto;height:300px;border-radius:12px"
|
|
9
9
|
/>
|
|
10
10
|
</div>
|
|
11
11
|
|
|
12
|
-
A comprehensive utility library for parsing, converting, manipulating, and analyzing color values across all major color models — hex, RGB, HSL, HSV, HWB, Lab, LCH,
|
|
12
|
+
A comprehensive utility library for parsing, converting, manipulating, and analyzing color values across all major color models — hex, RGB, HSL, HSV, HWB, Lab, LCH, Oklab, Oklch, CMYK, Display P3 — plus CSS variables and named colors. Zero dependencies.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Contents
|
|
17
|
+
|
|
18
|
+
- [Features](#features)
|
|
19
|
+
- [Installation](#installation)
|
|
20
|
+
- [Quick start](#quick-start)
|
|
21
|
+
- [Detection](#detection)
|
|
22
|
+
- [Parsing & Normalization](#parsing--normalization)
|
|
23
|
+
- [Conversions](#conversions)
|
|
24
|
+
- [Manipulation](#manipulation)
|
|
25
|
+
- [Interpolation & Scales](#interpolation--scales)
|
|
26
|
+
- [Color Harmonies](#color-harmonies)
|
|
27
|
+
- [Palette Generation](#palette-generation)
|
|
28
|
+
- [Accessibility (WCAG)](#accessibility-wcag)
|
|
29
|
+
- [Color Blindness Simulation](#color-blindness-simulation)
|
|
30
|
+
- [Formatting](#formatting)
|
|
31
|
+
- [Cache Management](#cache-management)
|
|
32
|
+
- [Generator Functions](#generator-functions)
|
|
33
|
+
- [CLI](#cli)
|
|
34
|
+
- [Cookbook](#cookbook)
|
|
35
|
+
- [TypeScript types](#typescript-types)
|
|
36
|
+
- [Architecture](#architecture)
|
|
37
|
+
- [Bundle size & dependencies](#bundle-size--dependencies)
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Features
|
|
42
|
+
|
|
43
|
+
- **Universal parser** — `normalizeColor()` accepts hex (3/4/6/8-digit), `rgb()` / `rgba()`, `hsl()` / `hsla()`, `hwb()`, `oklch()` / `oklcha()`, `color(display-p3 ...)`, CSS named colors (all 148), and plain `{r,g,b}` / `{h,s,l}` objects
|
|
44
|
+
- **Conversions** — every path between hex, RGB, HSL, HSV, HWB, Lab, LCH, Oklab, Oklch, CMYK, Display P3; all round-trip accurate
|
|
45
|
+
- **Manipulation** — `lighten`, `darken`, `saturate`, `desaturate`, `invertColor`, `grayscale`, `setAlpha`, `rotateHue`, `adjustHexBrightness`
|
|
46
|
+
- **Mixing & Interpolation** — `mixColors` and `interpolateColors` in 6 color spaces with 4 hue interpolation modes; `createColorScale` across multiple anchor colors with custom positions; `midpointColor` for a perceptual midpoint
|
|
47
|
+
- **Color Harmonies** — `complement`, `triadic`, `analogous`, `splitComplementary`, `tetradic`
|
|
48
|
+
- **Palette Generation** — `colorShades`, `monochromatic`, `tints`, `shades`, `tones` — all Oklab-accurate where applicable
|
|
49
|
+
- **WCAG Accessibility** — `relativeLuminance`, `contrastRatio`, `wcagLevel`, `bestTextColor`, `bestContrastColor`, `bestContrastPalette`, `isReadableOnBackground` (solid, semi-transparent, and gradient backgrounds)
|
|
50
|
+
- **Color Blindness Simulation** — protanopia, deuteranopia, tritanopia using Vienot 1999 matrices on linear RGB
|
|
51
|
+
- **Perceptual color distance** — `colorDeltaE` implementing the full CIEDE2000 formula
|
|
52
|
+
- **CSS Formatting** — `toHslString`, `toHwbString`, `toOklchString`, `toColorP3String`
|
|
53
|
+
- **Cache** — LRU-style `normalizeColorCached`; `getCacheStats`, `clearColorCache`, `enableCache` / `disableCache`
|
|
54
|
+
- **Generator functions** — `generateGradientColors*`, `generateTints*`, `generateShades*` for lazy iteration without pre-allocating arrays
|
|
55
|
+
- **CLI (`cvt`)** — inspect any color from the terminal: full info, all conversions, WCAG contrast, shades, harmonies, nearest named color
|
|
56
|
+
- **Zero dependencies** — no runtime deps; ships as tree-shakeable ESM + CommonJS
|
|
57
|
+
|
|
58
|
+
---
|
|
13
59
|
|
|
14
60
|
## Installation
|
|
15
61
|
|
|
@@ -17,7 +63,11 @@ A comprehensive utility library for parsing, converting, manipulating, and analy
|
|
|
17
63
|
npm install color-value-tools
|
|
18
64
|
```
|
|
19
65
|
|
|
20
|
-
|
|
66
|
+
No peer dependencies required.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Quick start
|
|
21
71
|
|
|
22
72
|
```ts
|
|
23
73
|
import {
|
|
@@ -26,70 +76,100 @@ import {
|
|
|
26
76
|
complement, triadic,
|
|
27
77
|
wcagLevel, bestTextColor,
|
|
28
78
|
colorDeltaE, randomColor,
|
|
29
|
-
} from 'color-value-tools'
|
|
79
|
+
} from 'color-value-tools'
|
|
30
80
|
|
|
31
81
|
// Parse any color format
|
|
32
|
-
normalizeColor('#3498db')
|
|
33
|
-
// { type: 'hex', hex: '#3498db', r: 52, g: 152, b: 219, h: 204, s: 70, l: 53,
|
|
82
|
+
normalizeColor('#3498db')
|
|
83
|
+
// { type: 'hex', hex: '#3498db', r: 52, g: 152, b: 219, h: 204, s: 70, l: 53, v: 86, a: 1 }
|
|
34
84
|
|
|
35
85
|
// Manipulate
|
|
36
|
-
lighten('#3498db', 15)
|
|
37
|
-
darken('#3498db', 15)
|
|
38
|
-
saturate('#3498db', 20)
|
|
86
|
+
lighten('#3498db', 15) // '#6ab4e8'
|
|
87
|
+
darken('#3498db', 15) // '#1a6da3'
|
|
88
|
+
saturate('#3498db', 20) // '#1a8fe8'
|
|
39
89
|
|
|
40
90
|
// Harmonies
|
|
41
|
-
complement('#3498db')
|
|
42
|
-
triadic('#3498db')
|
|
91
|
+
complement('#3498db') // '#db6034'
|
|
92
|
+
triadic('#3498db') // ['#3498db', '#db3498', '#98db34']
|
|
43
93
|
|
|
44
94
|
// WCAG accessibility
|
|
45
|
-
wcagLevel('#ffffff', '#3498db')
|
|
46
|
-
bestTextColor('#3498db')
|
|
95
|
+
wcagLevel('#ffffff', '#3498db') // 'AA'
|
|
96
|
+
bestTextColor('#3498db') // '#ffffff'
|
|
47
97
|
|
|
48
98
|
// Perceptual color distance (CIEDE2000)
|
|
49
|
-
colorDeltaE('#ff0000', '#fe0000')
|
|
99
|
+
colorDeltaE('#ff0000', '#fe0000') // ~0.9
|
|
50
100
|
|
|
51
101
|
// Random color
|
|
52
|
-
randomColor({ hRange: [200, 260], sRange: [60, 80] })
|
|
102
|
+
randomColor({ hRange: [200, 260], sRange: [60, 80] })
|
|
53
103
|
```
|
|
54
104
|
|
|
55
105
|
CommonJS:
|
|
106
|
+
|
|
56
107
|
```js
|
|
57
|
-
const { normalizeColor, mixColors } = require('color-value-tools')
|
|
108
|
+
const { normalizeColor, mixColors } = require('color-value-tools')
|
|
58
109
|
```
|
|
59
110
|
|
|
60
111
|
---
|
|
61
112
|
|
|
62
|
-
##
|
|
63
|
-
|
|
64
|
-
### Detection
|
|
113
|
+
## Detection
|
|
65
114
|
|
|
66
115
|
| Function | Description |
|
|
67
116
|
|---|---|
|
|
68
117
|
| `getColorType(value)` | Returns `'hex'` \| `'css-var'` \| `'rgb'` \| `'hsl'` \| `'named'` \| `'oklch'` \| `'color'` \| `'unknown'` |
|
|
69
|
-
| `isHexColor(value)` | Detects 3-, 4-,
|
|
118
|
+
| `isHexColor(value)` | Detects 3-, 4-, or 6-digit hex strings (with or without `#`) |
|
|
70
119
|
| `isRgbColor(value)` | Detects `rgb()` / `rgba()` strings |
|
|
71
120
|
| `isHslColor(value)` | Detects `hsl()` / `hsla()` strings |
|
|
72
121
|
| `isOklchColor(value)` | Detects `oklch()` / `oklcha()` strings |
|
|
73
|
-
| `isColorFunction(value)` | Detects `color(display-p3 ...)`
|
|
122
|
+
| `isColorFunction(value)` | Detects `color(display-p3 ...)`, `color(srgb ...)`, `color(srgb-linear ...)` strings |
|
|
74
123
|
| `isCssVariable(value)` | Checks for `var(--name)` pattern |
|
|
75
124
|
| `extractCssVariableName(value)` | Extracts `--name` from `var(--name, fallback)` |
|
|
76
125
|
|
|
77
|
-
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Parsing & Normalization
|
|
78
129
|
|
|
79
130
|
| Function | Description |
|
|
80
131
|
|---|---|
|
|
81
|
-
| `normalizeColor(input)` | Universal parser. Accepts hex, `rgb()`, `hsl()`, `oklch()`, `color()`, named color, `{r,g,b}`
|
|
82
|
-
| `normalizeColorCached(input)` | Same as `normalizeColor` but uses an internal LRU-style cache |
|
|
132
|
+
| `normalizeColor(input)` | Universal parser. Accepts hex (3/4/6/8-digit), `rgb()`, `hsl()`, `hwb()`, `oklch()`, `color()`, named color, `{r,g,b}` object, `{h,s,l}` object. Returns `{ type, hex, r, g, b, a, h, s, l, v }` |
|
|
133
|
+
| `normalizeColorCached(input)` | Same as `normalizeColor` but uses an internal LRU-style cache. String input only |
|
|
83
134
|
| `normalizeHex(hex)` | Normalizes 3- or 6-digit hex to lowercase 6-digit with `#` |
|
|
84
|
-
| `rgbaStringToRgba(str)` | Parses `rgb()` / `rgba()` string to `{r, g, b, a}
|
|
85
|
-
| `hex8ToRgba(hex)` | Parses 8-digit hex (`#rrggbbaa`) to `{r, g, b, a}` |
|
|
135
|
+
| `rgbaStringToRgba(str)` | Parses `rgb()` / `rgba()` string to `{r, g, b, a}`; supports percentage channels |
|
|
136
|
+
| `hex8ToRgba(hex)` | Parses 8-digit hex (`#rrggbbaa`) or 4-digit hex (`#rgba`) to `{r, g, b, a}` |
|
|
86
137
|
| `shortHexToRgba(hex)` | Parses 4-digit hex (`#rgba`) to `{r, g, b, a}` — e.g. `#f0f0` → `{r:255,g:0,b:255,a:0}` |
|
|
87
138
|
| `parseHwbString(str)` | Parses `hwb()` string to `{H, W, B, alpha}` |
|
|
88
|
-
| `parseOklchString(str)` | Parses `oklch(L C H / alpha)` to `{L, C, H, alpha}
|
|
139
|
+
| `parseOklchString(str)` | Parses `oklch(L C H / alpha)` to `{L, C, H, alpha}`; accepts percentage L |
|
|
89
140
|
| `parseColorFn(str)` | Parses `color(display-p3 r g b / alpha)` to `{space, r, g, b, alpha}` |
|
|
90
141
|
| `parseCssVar(value)` | Parses `var(--name, fallback)` to `{variableName, fallback?}` |
|
|
91
142
|
|
|
92
|
-
###
|
|
143
|
+
### `normalizeColor` return value
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
{
|
|
147
|
+
type: 'hex' | 'rgb' | 'hsl' | 'oklch' | 'color' | 'named' | 'css-var' | 'unknown'
|
|
148
|
+
hex?: string // '#rrggbb'
|
|
149
|
+
r?: number // 0–255
|
|
150
|
+
g?: number // 0–255
|
|
151
|
+
b?: number // 0–255
|
|
152
|
+
a?: number // 0–1
|
|
153
|
+
h?: number // hue 0–360
|
|
154
|
+
s?: number // HSL saturation 0–100
|
|
155
|
+
l?: number // HSL lightness 0–100
|
|
156
|
+
v?: number // HSV value 0–100
|
|
157
|
+
raw?: string // set for css-var type
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
// Object input
|
|
163
|
+
normalizeColor({ r: 52, g: 152, b: 219 }) // → full result with hex, h, s, l, v
|
|
164
|
+
normalizeColor({ h: 204, s: 70, l: 53 }) // → full result with hex, r, g, b, v
|
|
165
|
+
|
|
166
|
+
// CSS variable — returns raw, no color channels
|
|
167
|
+
normalizeColor('var(--brand-color)') // → { type: 'css-var', raw: 'var(--brand-color)' }
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Conversions
|
|
93
173
|
|
|
94
174
|
| Function | Description |
|
|
95
175
|
|---|---|
|
|
@@ -103,6 +183,7 @@ const { normalizeColor, mixColors } = require('color-value-tools');
|
|
|
103
183
|
| `hsvToRgb(h, s, v)` | `→ {r, g, b}` |
|
|
104
184
|
| `rgbToHex({r,g,b})` | `→ #rrggbb` |
|
|
105
185
|
| `rgbaToHex({r,g,b,a})` | `→ #rrggbbaa` |
|
|
186
|
+
| `rgbaToHex8({r,g,b,a})` | Alias for `rgbaToHex` |
|
|
106
187
|
| `rgbToRgbaString({r,g,b}, a)` | `→ rgba(...)` string |
|
|
107
188
|
| `rgbToHsl({r,g,b})` | `→ [h, s, l]` |
|
|
108
189
|
| `rgbToHsv({r,g,b})` | `→ [h, s, v]` |
|
|
@@ -121,9 +202,10 @@ const { normalizeColor, mixColors } = require('color-value-tools');
|
|
|
121
202
|
| `rgbToDisplayP3({r,g,b})` | `→ {r, g, b}` in Display P3 space (0–1 per channel) |
|
|
122
203
|
| `displayP3ToRgb({r,g,b})` | `→ {r, g, b}` sRGB (0–255) |
|
|
123
204
|
| `toDisplayP3Hex(color)` | Converts any color → Display P3 → hex |
|
|
124
|
-
| `rgbaToHex8({r,g,b,a})` | Alias for `rgbaToHex` |
|
|
125
205
|
|
|
126
|
-
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Manipulation
|
|
127
209
|
|
|
128
210
|
| Function | Description |
|
|
129
211
|
|---|---|
|
|
@@ -133,21 +215,64 @@ const { normalizeColor, mixColors } = require('color-value-tools');
|
|
|
133
215
|
| `desaturate(color, amount)` | Decrease HSL saturation by `amount` (0–100) |
|
|
134
216
|
| `setAlpha(color, alpha)` | Returns `rgba(...)` with the given alpha (0–1) |
|
|
135
217
|
| `getAlpha(color)` | Returns the alpha channel value (0–1) |
|
|
136
|
-
| `invertColor(color)` | Inverts RGB channels |
|
|
137
|
-
| `grayscale(color)` | Converts to grayscale using ITU-R BT.709 weights |
|
|
138
|
-
| `rotateHue(hex, degrees)` | Rotates hue by degrees
|
|
218
|
+
| `invertColor(color)` | Inverts all three RGB channels |
|
|
219
|
+
| `grayscale(color)` | Converts to grayscale using ITU-R BT.709 perceptual weights |
|
|
220
|
+
| `rotateHue(hex, degrees)` | Rotates hue by degrees; supports negative values |
|
|
139
221
|
| `adjustHexBrightness(hex, offsetPercent)` | Lightens (positive) or darkens (negative) by percentage |
|
|
140
|
-
| `mixColors(c1, c2, t, opts?)` | Interpolates between two colors. `t` = 0–1. `mode`: `'rgb'
|
|
222
|
+
| `mixColors(c1, c2, t, opts?)` | Interpolates between two colors. `t` = 0–1. `mode`: `'rgb'` \| `'hsl'` \| `'lab'` \| `'lch'` \| `'oklab'` \| `'oklch'`. `hueInterpolation`: `'shorter'` \| `'longer'` \| `'increasing'` \| `'decreasing'` |
|
|
223
|
+
|
|
224
|
+
### `mixColors` example
|
|
141
225
|
|
|
142
|
-
|
|
226
|
+
```ts
|
|
227
|
+
import { mixColors } from 'color-value-tools'
|
|
228
|
+
|
|
229
|
+
// RGB mix at midpoint
|
|
230
|
+
mixColors('#e74c3c', '#3498db', 0.5)
|
|
231
|
+
// → '#8dc6bc'
|
|
232
|
+
|
|
233
|
+
// Perceptually even mix in Oklab
|
|
234
|
+
mixColors('#e74c3c', '#3498db', 0.5, { mode: 'oklab', format: 'hex' })
|
|
235
|
+
|
|
236
|
+
// HSL with "longer" hue path
|
|
237
|
+
mixColors('#e74c3c', '#3498db', 0.5, { mode: 'hsl', hueInterpolation: 'longer' })
|
|
238
|
+
|
|
239
|
+
// Get rgba string output
|
|
240
|
+
mixColors('#ff0000', '#0000ff', 0.25, { mode: 'lab', format: 'rgba' })
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Interpolation & Scales
|
|
143
246
|
|
|
144
247
|
| Function | Description |
|
|
145
248
|
|---|---|
|
|
146
|
-
| `interpolateColors(c1, c2, steps, opts?)` | Returns array of `steps` colors from `c1` to `c2`. Same `space
|
|
249
|
+
| `interpolateColors(c1, c2, steps, opts?)` | Returns array of `steps` colors from `c1` to `c2`. Same `space` / `format` / `hueInterpolation` options as `mixColors` |
|
|
147
250
|
| `createColorScale(anchors, steps, opts?)` | Generates a `steps`-color scale across multiple anchor colors with optional positions (0–1) |
|
|
148
251
|
| `midpointColor(c1, c2, opts?)` | Perceptual midpoint between two colors (default space: `'oklab'`) |
|
|
149
252
|
|
|
150
|
-
###
|
|
253
|
+
### `createColorScale` — multi-stop gradient
|
|
254
|
+
|
|
255
|
+
```ts
|
|
256
|
+
import { createColorScale } from 'color-value-tools'
|
|
257
|
+
|
|
258
|
+
// Evenly spaced anchors
|
|
259
|
+
createColorScale(['#ff0000', '#ffff00', '#00ff00'], 9)
|
|
260
|
+
|
|
261
|
+
// With explicit positions
|
|
262
|
+
createColorScale(
|
|
263
|
+
[
|
|
264
|
+
{ color: '#1a1a2e', position: 0 },
|
|
265
|
+
{ color: '#e94560', position: 0.4 },
|
|
266
|
+
{ color: '#f5a623', position: 1 },
|
|
267
|
+
],
|
|
268
|
+
12,
|
|
269
|
+
{ space: 'oklch' }
|
|
270
|
+
)
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Color Harmonies
|
|
151
276
|
|
|
152
277
|
| Function | Description |
|
|
153
278
|
|---|---|
|
|
@@ -157,7 +282,17 @@ const { normalizeColor, mixColors } = require('color-value-tools');
|
|
|
157
282
|
| `splitComplementary(color)` | Base + two colors at 150° and 210° |
|
|
158
283
|
| `tetradic(color)` | 4 colors evenly spaced 90° apart |
|
|
159
284
|
|
|
160
|
-
|
|
285
|
+
```ts
|
|
286
|
+
import { triadic, analogous, tetradic } from 'color-value-tools'
|
|
287
|
+
|
|
288
|
+
triadic('#6c3483') // ['#6c3483', '#34836c', '#83346c']
|
|
289
|
+
analogous('#6c3483', 45) // ['#833469', '#6c3483', '#3469…']
|
|
290
|
+
tetradic('#6c3483') // 4 colors
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Palette Generation
|
|
161
296
|
|
|
162
297
|
| Function | Description |
|
|
163
298
|
|---|---|
|
|
@@ -167,7 +302,9 @@ const { normalizeColor, mixColors } = require('color-value-tools');
|
|
|
167
302
|
| `shades(color, steps?)` | Mix toward black in Oklab (default 5 steps) |
|
|
168
303
|
| `tones(color, steps?, gray?)` | Mix toward gray in Oklab (default 5 steps, gray `#808080`) |
|
|
169
304
|
|
|
170
|
-
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Accessibility (WCAG)
|
|
171
308
|
|
|
172
309
|
| Function | Description |
|
|
173
310
|
|---|---|
|
|
@@ -176,14 +313,56 @@ const { normalizeColor, mixColors } = require('color-value-tools');
|
|
|
176
313
|
| `wcagLevel(fg, bg)` | Returns `'AAA'` \| `'AA'` \| `'AA-large'` \| `'fail'` |
|
|
177
314
|
| `bestTextColor(bg)` | Returns `'#000000'` or `'#ffffff'` for best contrast on `bg` |
|
|
178
315
|
| `bestContrastColor(bg, candidates)` | Picks the most readable color from an array of candidates |
|
|
179
|
-
| `bestContrastPalette(bg, palettes, opts?)` | Picks the palette with best overall contrast. Returns `{paletteIndex, palette, minContrastRatio, avgContrastRatio}` |
|
|
180
|
-
| `isReadableOnBackground(text, bg, opts?)` | Checks readability on solid, semi-transparent, or gradient backgrounds. Returns `{readable, minContrastRatio, wcagLevel}` |
|
|
316
|
+
| `bestContrastPalette(bg, palettes, opts?)` | Picks the palette with best overall contrast. Returns `{ paletteIndex, palette, minContrastRatio, avgContrastRatio }` |
|
|
317
|
+
| `isReadableOnBackground(text, bg, opts?)` | Checks readability on solid, semi-transparent, or gradient backgrounds. Returns `{ readable, minContrastRatio, wcagLevel }` |
|
|
181
318
|
| `isDark(color, threshold?)` | `true` if luminance is below threshold (default 0.5) |
|
|
182
319
|
| `isLight(color, threshold?)` | Inverse of `isDark` |
|
|
183
320
|
|
|
184
|
-
###
|
|
321
|
+
### `isReadableOnBackground` — complex backgrounds
|
|
322
|
+
|
|
323
|
+
`background` can be a plain color string, a semi-transparent spec, or a gradient with multiple stops:
|
|
324
|
+
|
|
325
|
+
```ts
|
|
326
|
+
import { isReadableOnBackground } from 'color-value-tools'
|
|
327
|
+
|
|
328
|
+
// Solid background
|
|
329
|
+
isReadableOnBackground('#ffffff', '#3498db')
|
|
330
|
+
// → { readable: true, minContrastRatio: 3.05, wcagLevel: 'AA-large' }
|
|
331
|
+
|
|
332
|
+
// Semi-transparent overlay composited over white
|
|
333
|
+
isReadableOnBackground('#ffffff', {
|
|
334
|
+
type: 'semi-transparent',
|
|
335
|
+
color: 'rgba(52, 152, 219, 0.5)',
|
|
336
|
+
underlay: '#f0f0f0',
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
// Gradient — worst stop is used for the result
|
|
340
|
+
isReadableOnBackground('#ffffff', {
|
|
341
|
+
type: 'gradient',
|
|
342
|
+
stops: ['#1a1a2e', '#e94560', '#f5a623'],
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
// AAA + large text
|
|
346
|
+
isReadableOnBackground('#000000', '#f0f0f0', { level: 'AAA', largeText: true })
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### `bestContrastPalette` — pick accessible palette
|
|
350
|
+
|
|
351
|
+
```ts
|
|
352
|
+
import { bestContrastPalette } from 'color-value-tools'
|
|
353
|
+
|
|
354
|
+
const result = bestContrastPalette('#1a1a2e', [
|
|
355
|
+
['#ffffff', '#f0f0f0', '#cccccc'],
|
|
356
|
+
['#ffff00', '#ffd700', '#ff8c00'],
|
|
357
|
+
])
|
|
358
|
+
// → { paletteIndex: 0, palette: [...], minContrastRatio: 12.1, avgContrastRatio: 14.3 }
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Color Blindness Simulation
|
|
185
364
|
|
|
186
|
-
Simulates perception using Vienot 1999 matrices applied to
|
|
365
|
+
Simulates perception using Vienot 1999 matrices applied to linearized RGB.
|
|
187
366
|
|
|
188
367
|
| Function | Description |
|
|
189
368
|
|---|---|
|
|
@@ -192,7 +371,16 @@ Simulates perception using Vienot 1999 matrices applied to linear RGB.
|
|
|
192
371
|
| `simulateTritanopia(color)` | No S-cones (blue-blind) |
|
|
193
372
|
| `simulateColorBlindness(color, type)` | Generic — `type`: `'protanopia'` \| `'deuteranopia'` \| `'tritanopia'` |
|
|
194
373
|
|
|
195
|
-
|
|
374
|
+
```ts
|
|
375
|
+
import { simulateColorBlindness } from 'color-value-tools'
|
|
376
|
+
|
|
377
|
+
simulateColorBlindness('#e74c3c', 'deuteranopia') // '#9a7b00'
|
|
378
|
+
simulateColorBlindness('#3498db', 'protanopia') // '#5282db'
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
## Formatting
|
|
196
384
|
|
|
197
385
|
| Function | Description |
|
|
198
386
|
|---|---|
|
|
@@ -201,48 +389,81 @@ Simulates perception using Vienot 1999 matrices applied to linear RGB.
|
|
|
201
389
|
| `toOklchString(color, alpha?)` | Converts any color to `oklch(L C H)` CSS string |
|
|
202
390
|
| `toColorP3String(color, alpha?)` | Converts any color to `color(display-p3 r g b)` CSS string |
|
|
203
391
|
|
|
204
|
-
|
|
392
|
+
```ts
|
|
393
|
+
import { toOklchString, toColorP3String, toHwbString } from 'color-value-tools'
|
|
205
394
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
| `enableCache()` / `disableCache()` | Toggle caching on/off |
|
|
395
|
+
toOklchString('#3498db') // 'oklch(0.6 0.1175 234.77)'
|
|
396
|
+
toColorP3String('#3498db') // 'color(display-p3 0.2493 0.5875 0.8479)'
|
|
397
|
+
toHwbString(204, 20, 14) // 'hwb(204 20% 14%)'
|
|
398
|
+
toHwbString(204, 20, 14, 0.8) // 'hwb(204 20% 14% / 0.8)'
|
|
399
|
+
```
|
|
212
400
|
|
|
213
|
-
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## Cache Management
|
|
214
404
|
|
|
215
|
-
Useful
|
|
405
|
+
Useful in rendering loops, color pickers, or any context with repeated `normalizeColor` calls on the same values.
|
|
216
406
|
|
|
217
407
|
| Function | Description |
|
|
218
408
|
|---|---|
|
|
219
|
-
| `
|
|
220
|
-
| `
|
|
221
|
-
| `
|
|
409
|
+
| `normalizeColorCached(input)` | Cached version of `normalizeColor` for repeated string calls |
|
|
410
|
+
| `clearColorCache()` | Clears the normalization cache and resets hit counter |
|
|
411
|
+
| `getCacheStats()` | Returns `{ size: number, hits: number }` |
|
|
412
|
+
| `enableCache()` | Re-enables the cache (on by default) |
|
|
413
|
+
| `disableCache()` | Disables caching (useful in tests) |
|
|
414
|
+
|
|
415
|
+
```ts
|
|
416
|
+
import { normalizeColorCached, getCacheStats, clearColorCache } from 'color-value-tools'
|
|
417
|
+
|
|
418
|
+
// First call — parsed and cached
|
|
419
|
+
normalizeColorCached('#3498db')
|
|
222
420
|
|
|
223
|
-
|
|
421
|
+
// Second call — instant cache hit
|
|
422
|
+
normalizeColorCached('#3498db')
|
|
423
|
+
|
|
424
|
+
getCacheStats() // { size: 1, hits: 1 }
|
|
425
|
+
clearColorCache() // { size: 0, hits: 0 } reset
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
## Generator Functions
|
|
431
|
+
|
|
432
|
+
Useful for large palettes and frame-by-frame animations without allocating full arrays upfront.
|
|
224
433
|
|
|
225
434
|
| Function | Description |
|
|
226
435
|
|---|---|
|
|
227
|
-
| `
|
|
228
|
-
| `
|
|
229
|
-
| `
|
|
436
|
+
| `generateGradientColors*(start, end, steps, opts?)` | Yields `steps` colors from `start` to `end`. Same `mode` / `format` options as `mixColors` |
|
|
437
|
+
| `generateTints*(color, steps, opts?)` | Yields tints toward white in Oklab |
|
|
438
|
+
| `generateShades*(color, steps, opts?)` | Yields shades toward black in Oklab |
|
|
439
|
+
|
|
440
|
+
```ts
|
|
441
|
+
import { generateGradientColors, generateTints } from 'color-value-tools'
|
|
442
|
+
|
|
443
|
+
// Process one color at a time — no intermediate array
|
|
444
|
+
for (const color of generateGradientColors('#ff0000', '#0000ff', 1000, { mode: 'oklch' })) {
|
|
445
|
+
renderPixel(color)
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// Collect lazily
|
|
449
|
+
const first5 = [...generateTints('#e74c3c', 100)].slice(0, 5)
|
|
450
|
+
```
|
|
230
451
|
|
|
231
452
|
---
|
|
232
453
|
|
|
233
454
|
## CLI
|
|
234
455
|
|
|
235
|
-
|
|
456
|
+
The `cvt` CLI is included in the package. Install globally or use via `npx`:
|
|
236
457
|
|
|
237
458
|
```bash
|
|
238
459
|
npm install -g color-value-tools
|
|
239
460
|
```
|
|
240
461
|
|
|
241
462
|
```bash
|
|
242
|
-
# Full info (default)
|
|
463
|
+
# Full info (default command)
|
|
243
464
|
cvt "#3498db"
|
|
244
465
|
|
|
245
|
-
# All format conversions
|
|
466
|
+
# All format conversions — hex, rgb, hsl, hsv, hwb, lab, lch, oklab, oklch, cmyk
|
|
246
467
|
cvt "#3498db" convert
|
|
247
468
|
|
|
248
469
|
# Contrast ratio and WCAG level
|
|
@@ -251,13 +472,27 @@ cvt "#3498db" contrast "#ffffff"
|
|
|
251
472
|
# Generate 7 shades
|
|
252
473
|
cvt "#3498db" shades 7
|
|
253
474
|
|
|
254
|
-
# All harmonies
|
|
475
|
+
# All harmonies — complement, triadic, analogous, split-comp, tetradic
|
|
255
476
|
cvt "#3498db" harmonies
|
|
256
477
|
|
|
257
478
|
# Nearest CSS named color
|
|
258
479
|
cvt "cornflowerblue" nearest
|
|
259
480
|
```
|
|
260
481
|
|
|
482
|
+
Accepts any valid color format: hex, `rgb()`, `hsl()`, `oklch()`, named colors.
|
|
483
|
+
|
|
484
|
+
```
|
|
485
|
+
cvt "#3498db"
|
|
486
|
+
────────────────────────────────────────
|
|
487
|
+
Type: hex
|
|
488
|
+
Hex: #3498db
|
|
489
|
+
RGB: rgb(52, 152, 219)
|
|
490
|
+
HSL: hsl(204, 70%, 53%)
|
|
491
|
+
HSV: hsv(204, 76%, 86%)
|
|
492
|
+
Nearest named: cornflowerblue
|
|
493
|
+
Best text on it: #ffffff
|
|
494
|
+
```
|
|
495
|
+
|
|
261
496
|
---
|
|
262
497
|
|
|
263
498
|
## Cookbook
|
|
@@ -265,88 +500,277 @@ cvt "cornflowerblue" nearest
|
|
|
265
500
|
### Generate an accessible button palette
|
|
266
501
|
|
|
267
502
|
```ts
|
|
268
|
-
import { colorShades, bestTextColor, wcagLevel } from 'color-value-tools'
|
|
503
|
+
import { colorShades, bestTextColor, wcagLevel } from 'color-value-tools'
|
|
269
504
|
|
|
270
505
|
function buttonPalette(base: string) {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
bg: shade,
|
|
506
|
+
return colorShades(base, 9).map(shade => ({
|
|
507
|
+
bg: shade,
|
|
274
508
|
text: bestTextColor(shade),
|
|
275
509
|
wcag: wcagLevel(bestTextColor(shade), shade),
|
|
276
|
-
}))
|
|
510
|
+
}))
|
|
277
511
|
}
|
|
278
512
|
|
|
279
|
-
buttonPalette('#3498db')
|
|
513
|
+
buttonPalette('#3498db')
|
|
280
514
|
// [{ bg: '#ffffff', text: '#000000', wcag: 'AAA' }, ...]
|
|
281
515
|
```
|
|
282
516
|
|
|
283
|
-
### Theme-aware
|
|
517
|
+
### Theme-aware color adaptation
|
|
284
518
|
|
|
285
519
|
```ts
|
|
286
|
-
import { isDark, lighten, darken } from 'color-value-tools'
|
|
520
|
+
import { isDark, lighten, darken } from 'color-value-tools'
|
|
287
521
|
|
|
288
522
|
function adaptToTheme(color: string, isDarkTheme: boolean): string {
|
|
289
|
-
return isDarkTheme ? lighten(color, 20) : darken(color, 10)
|
|
523
|
+
return isDarkTheme ? lighten(color, 20) : darken(color, 10)
|
|
290
524
|
}
|
|
291
525
|
```
|
|
292
526
|
|
|
293
|
-
### Mix two brand colors at a midpoint
|
|
527
|
+
### Mix two brand colors at a perceptual midpoint
|
|
294
528
|
|
|
295
529
|
```ts
|
|
296
|
-
import {
|
|
530
|
+
import { midpointColor } from 'color-value-tools'
|
|
297
531
|
|
|
298
|
-
const mid =
|
|
299
|
-
|
|
532
|
+
const mid = midpointColor('#e74c3c', '#3498db') // Oklab midpoint
|
|
533
|
+
const midLch = midpointColor('#e74c3c', '#3498db', { space: 'oklch' })
|
|
300
534
|
```
|
|
301
535
|
|
|
302
|
-
### Build a triadic
|
|
536
|
+
### Build a triadic scheme and check contrast
|
|
303
537
|
|
|
304
538
|
```ts
|
|
305
|
-
import { triadic, contrastRatio } from 'color-value-tools'
|
|
539
|
+
import { triadic, contrastRatio } from 'color-value-tools'
|
|
306
540
|
|
|
307
|
-
const [base, second, third] = triadic('#6c3483')
|
|
308
|
-
console.log(contrastRatio(base, '#ffffff'))
|
|
309
|
-
console.log(contrastRatio(second, '#ffffff'))
|
|
541
|
+
const [base, second, third] = triadic('#6c3483')
|
|
542
|
+
console.log(contrastRatio(base, '#ffffff')) // e.g. 8.4
|
|
543
|
+
console.log(contrastRatio(second, '#ffffff'))
|
|
310
544
|
```
|
|
311
545
|
|
|
312
|
-
### Convert
|
|
546
|
+
### Convert any color string to all formats at once
|
|
313
547
|
|
|
314
548
|
```ts
|
|
315
|
-
import { normalizeColor, rgbToOklch, rgbToCmyk } from 'color-value-tools'
|
|
549
|
+
import { normalizeColor, rgbToOklch, rgbToCmyk, toColorP3String } from 'color-value-tools'
|
|
316
550
|
|
|
317
|
-
const n = normalizeColor('hsl(204, 70%, 53%)')
|
|
318
|
-
const oklch = rgbToOklch({ r: n.r!, g: n.g!, b: n.b! })
|
|
319
|
-
const cmyk = rgbToCmyk({ r: n.r!, g: n.g!, b: n.b! })
|
|
320
|
-
|
|
551
|
+
const n = normalizeColor('hsl(204, 70%, 53%)')
|
|
552
|
+
const oklch = rgbToOklch({ r: n.r!, g: n.g!, b: n.b! })
|
|
553
|
+
const cmyk = rgbToCmyk({ r: n.r!, g: n.g!, b: n.b! })
|
|
554
|
+
const p3 = toColorP3String(n.hex!)
|
|
555
|
+
console.log(n.hex, oklch, cmyk, p3)
|
|
321
556
|
```
|
|
322
557
|
|
|
323
|
-
### Find the
|
|
558
|
+
### Find the nearest CSS named color
|
|
324
559
|
|
|
325
560
|
```ts
|
|
326
|
-
import { toNearestNamedColor } from 'color-value-tools'
|
|
561
|
+
import { toNearestNamedColor } from 'color-value-tools'
|
|
327
562
|
|
|
328
|
-
toNearestNamedColor('#1a8ccc')
|
|
563
|
+
toNearestNamedColor('#1a8ccc') // 'steelblue'
|
|
564
|
+
toNearestNamedColor('#e74c3c') // 'tomato'
|
|
329
565
|
```
|
|
330
566
|
|
|
331
567
|
### Random palette within a hue range
|
|
332
568
|
|
|
333
569
|
```ts
|
|
334
|
-
import { randomColor, colorShades } from 'color-value-tools'
|
|
570
|
+
import { randomColor, colorShades } from 'color-value-tools'
|
|
571
|
+
|
|
572
|
+
const accent = randomColor({ hRange: [200, 260], sRange: [60, 80], lRange: [40, 60] })
|
|
573
|
+
const palette = colorShades(accent, 5)
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
### Simulate color blindness for a palette
|
|
577
|
+
|
|
578
|
+
```ts
|
|
579
|
+
import { triadic, simulateColorBlindness } from 'color-value-tools'
|
|
580
|
+
|
|
581
|
+
const palette = triadic('#e74c3c')
|
|
582
|
+
const deuteranopia = palette.map(c => simulateColorBlindness(c, 'deuteranopia'))
|
|
583
|
+
// Compare palette vs deuteranopia to verify distinguishability
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
### Lazy gradient — process 10 000 colors one at a time
|
|
587
|
+
|
|
588
|
+
```ts
|
|
589
|
+
import { generateGradientColors } from 'color-value-tools'
|
|
335
590
|
|
|
336
|
-
const
|
|
337
|
-
|
|
591
|
+
for (const color of generateGradientColors('#1a1a2e', '#f5a623', 10_000, { mode: 'oklch' })) {
|
|
592
|
+
ctx.fillStyle = color
|
|
593
|
+
ctx.fillRect(x++, 0, 1, height)
|
|
594
|
+
}
|
|
338
595
|
```
|
|
339
596
|
|
|
340
597
|
---
|
|
341
598
|
|
|
342
|
-
##
|
|
599
|
+
## TypeScript types
|
|
343
600
|
|
|
344
|
-
|
|
601
|
+
All public types are exported from the package root:
|
|
602
|
+
|
|
603
|
+
```ts
|
|
604
|
+
import type {
|
|
605
|
+
ColorType, // 'hex' | 'css-var' | 'rgb' | 'hsl' | 'named' | 'oklch' | 'color' | 'unknown'
|
|
606
|
+
WcagLevel, // 'AAA' | 'AA' | 'AA-large' | 'fail'
|
|
607
|
+
ColorBlindnessType, // 'protanopia' | 'deuteranopia' | 'tritanopia'
|
|
608
|
+
BackgroundSpec, // string | { type: 'semi-transparent'; ... } | { type: 'gradient'; ... }
|
|
609
|
+
PaletteScore, // { palette, minContrastRatio, avgContrastRatio }
|
|
610
|
+
} from 'color-value-tools'
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
### `BackgroundSpec` — discriminated union
|
|
614
|
+
|
|
615
|
+
```ts
|
|
616
|
+
import type { BackgroundSpec } from 'color-value-tools'
|
|
617
|
+
|
|
618
|
+
const solid: BackgroundSpec = '#3498db'
|
|
619
|
+
|
|
620
|
+
const semiTransparent: BackgroundSpec = {
|
|
621
|
+
type: 'semi-transparent',
|
|
622
|
+
color: 'rgba(0,0,0,0.4)',
|
|
623
|
+
underlay: '#ffffff', // optional, defaults to white
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
const gradient: BackgroundSpec = {
|
|
627
|
+
type: 'gradient',
|
|
628
|
+
stops: ['#1a1a2e', '#e94560', '#f5a623'],
|
|
629
|
+
}
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
### `PaletteScore` — from `bestContrastPalette`
|
|
633
|
+
|
|
634
|
+
```ts
|
|
635
|
+
import type { PaletteScore } from 'color-value-tools'
|
|
636
|
+
|
|
637
|
+
const result: PaletteScore & { paletteIndex: number } = bestContrastPalette(bg, palettes)
|
|
638
|
+
result.paletteIndex // number
|
|
639
|
+
result.palette // string[]
|
|
640
|
+
result.minContrastRatio // number
|
|
641
|
+
result.avgContrastRatio // number
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
### Inference from `normalizeColor`
|
|
645
|
+
|
|
646
|
+
```ts
|
|
647
|
+
import { normalizeColor } from 'color-value-tools'
|
|
648
|
+
|
|
649
|
+
const n = normalizeColor('#3498db')
|
|
650
|
+
// TypeScript knows: n.hex, n.r, n.g, n.b, n.h, n.s, n.l, n.v, n.a, n.type
|
|
651
|
+
|
|
652
|
+
if (n.type !== 'unknown' && n.type !== 'css-var') {
|
|
653
|
+
const r: number = n.r! // available for all resolved color types
|
|
654
|
+
}
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
---
|
|
658
|
+
|
|
659
|
+
## Architecture
|
|
660
|
+
|
|
661
|
+
```
|
|
662
|
+
color-value-tools
|
|
663
|
+
│
|
|
664
|
+
├── Detection
|
|
665
|
+
│ getColorType, isHexColor, isRgbColor, isHslColor,
|
|
666
|
+
│ isOklchColor, isColorFunction, isCssVariable
|
|
667
|
+
│
|
|
668
|
+
├── Parsing
|
|
669
|
+
│ normalizeColor → universal entry point; handles all formats + objects
|
|
670
|
+
│ rgbaStringToRgba → rgb()/rgba() parser
|
|
671
|
+
│ hex8ToRgba → 8-digit and 4-digit hex with alpha
|
|
672
|
+
│ parseOklchString → oklch(L C H / alpha) with % L support
|
|
673
|
+
│ parseColorFn → color(display-p3 ...) / color(srgb ...)
|
|
674
|
+
│ parseHwbString → hwb() string
|
|
675
|
+
│ parseCssVar → var(--name, fallback)
|
|
676
|
+
│
|
|
677
|
+
├── Color Math — every space via RGB as the hub
|
|
678
|
+
│ sRGB ↔ Linear (srgbChanToLinear / linearChanToSrgb)
|
|
679
|
+
│ XYZ D65 intermediate for Lab/LCH
|
|
680
|
+
│ Oklab/Oklch — Björn Ottosson matrices
|
|
681
|
+
│ Display P3 — ICC sRGB→P3 and P3→sRGB matrices
|
|
682
|
+
│
|
|
683
|
+
├── Manipulation
|
|
684
|
+
│ lighten / darken / saturate / desaturate — via HSL
|
|
685
|
+
│ invertColor — RGB invert
|
|
686
|
+
│ grayscale — BT.709 perceptual weights
|
|
687
|
+
│ rotateHue — via HSL hue shift
|
|
688
|
+
│ adjustHexBrightness — linear channel blend toward 0/255
|
|
689
|
+
│ setAlpha / getAlpha — rgba string manipulation
|
|
690
|
+
│
|
|
691
|
+
├── mixColors (core of interpolation system)
|
|
692
|
+
│ 6 color space modes: rgb | hsl | lab | lch | oklab | oklch
|
|
693
|
+
│ 4 hue interpolation modes: shorter | longer | increasing | decreasing
|
|
694
|
+
│ 4 output formats: hex | rgb | rgba | hsl
|
|
695
|
+
│ Used internally by: interpolateColors, createColorScale,
|
|
696
|
+
│ midpointColor, tints, shades, tones,
|
|
697
|
+
│ generateGradientColors*, generateTints*, generateShades*
|
|
698
|
+
│
|
|
699
|
+
├── Color Harmonies
|
|
700
|
+
│ All implemented as hue rotations on normalized hex
|
|
701
|
+
│
|
|
702
|
+
├── Palette Generation
|
|
703
|
+
│ colorShades — HSL lightness sweep
|
|
704
|
+
│ monochromatic — HSL saturation sweep
|
|
705
|
+
│ tints / shades / tones — Oklab interpolation via mixColors
|
|
706
|
+
│
|
|
707
|
+
├── Accessibility
|
|
708
|
+
│ relativeLuminance — WCAG linearization formula
|
|
709
|
+
│ contrastRatio — (L1+0.05)/(L2+0.05)
|
|
710
|
+
│ wcagLevel — ratio thresholds 3 / 4.5 / 7
|
|
711
|
+
│ isReadableOnBackground — handles 3 background types;
|
|
712
|
+
│ semi-transparent: alpha-composites onto underlay before ratio check
|
|
713
|
+
│ gradient: evaluates each stop, uses minimum ratio
|
|
714
|
+
│ bestContrastPalette — score = avg×0.4 + min×0.6
|
|
715
|
+
│
|
|
716
|
+
├── Color Blindness
|
|
717
|
+
│ Vienot 1999 matrices on linear RGB
|
|
718
|
+
│ 3 types: protanopia / deuteranopia / tritanopia
|
|
719
|
+
│
|
|
720
|
+
├── Cache (Section 5.1)
|
|
721
|
+
│ Simple Map<string, NormalizeResult>
|
|
722
|
+
│ normalizeColorCached — Map lookup before calling normalizeColor
|
|
723
|
+
│ getCacheStats / clearColorCache / enableCache / disableCache
|
|
724
|
+
│
|
|
725
|
+
├── Generator functions (Section 5.2)
|
|
726
|
+
│ ES2015 generator syntax (*) — yield one color at a time
|
|
727
|
+
│ generateGradientColors* → mixColors inside the generator
|
|
728
|
+
│ generateTints* / generateShades* → Oklab mix toward white/black
|
|
729
|
+
│
|
|
730
|
+
└── CLI (dist/cli/bin/cli.js → cvt)
|
|
731
|
+
Commands: info | convert | contrast | shades | harmonies | nearest
|
|
732
|
+
Accepts any color format normalizeColor understands
|
|
733
|
+
```
|
|
345
734
|
|
|
346
|
-
|
|
735
|
+
---
|
|
736
|
+
|
|
737
|
+
## Bundle size & dependencies
|
|
738
|
+
|
|
739
|
+
| | |
|
|
740
|
+
|---|---|
|
|
741
|
+
| **Runtime dependencies** | None |
|
|
742
|
+
| **Peer dependencies** | None |
|
|
743
|
+
| **Dev dependencies** | TypeScript, Vitest |
|
|
744
|
+
| **ESM entry** | `dist/esm/index.js` (tree-shakeable) |
|
|
745
|
+
| **CJS entry** | `dist/cjs/index.js` |
|
|
746
|
+
| **CLI entry** | `dist/cli/bin/cli.js` → `cvt` |
|
|
747
|
+
|
|
748
|
+
The package ships both ESM (`type: module`) and CommonJS modules. Every function is a named export — unused functions are eliminated by bundlers that support tree-shaking.
|
|
347
749
|
|
|
348
|
-
|
|
750
|
+
---
|
|
349
751
|
|
|
350
752
|
## License
|
|
351
753
|
|
|
352
754
|
MIT
|
|
755
|
+
|
|
756
|
+
---
|
|
757
|
+
|
|
758
|
+
## Author
|
|
759
|
+
|
|
760
|
+
Danil Lisin Vladimirovich aka Macrulez
|
|
761
|
+
|
|
762
|
+
GitHub: [macrulezru](https://github.com/macrulezru) · Website: [macrulez.ru/en](https://macrulez.ru/en)
|
|
763
|
+
|
|
764
|
+
Bugs and questions — [issues](https://github.com/macrulezru/color-value-tools/issues)
|
|
765
|
+
|
|
766
|
+
---
|
|
767
|
+
|
|
768
|
+
## 💖 Support the project
|
|
769
|
+
|
|
770
|
+
Open source takes time and effort. If my work saves you time or brings value, consider supporting further development.
|
|
771
|
+
|
|
772
|
+
<a href="https://donate.cryptocloud.plus/M6O34NIN" target="_blank">
|
|
773
|
+
<img src="https://img.shields.io/badge/Donate-CryptoCloud-8A2BE2?style=for-the-badge&logo=cryptocurrency&logoColor=white" alt="Donate via CryptoCloud">
|
|
774
|
+
</a>
|
|
775
|
+
|
|
776
|
+
Thank you for being part of this journey. ❤️
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "color-value-tools",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "A comprehensive utility library for parsing, converting, manipulating, and analyzing color values across all major color models — hex, RGB, HSL, HSV, HWB, Lab, LCH, OKLAB, OKLCH, CMYK — plus CSS variables and named colors.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|