chromonym 2.0.0 → 3.0.0
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/NOTICE.md +32 -0
- package/README.md +138 -72
- package/dist/identify.d.ts +36 -11
- package/dist/identify.d.ts.map +1 -1
- package/dist/identify.js +34 -19
- package/dist/identify.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/indexing.d.ts +18 -0
- package/dist/indexing.d.ts.map +1 -1
- package/dist/indexing.js +62 -0
- package/dist/indexing.js.map +1 -1
- package/dist/math/editDistance.d.ts +17 -0
- package/dist/math/editDistance.d.ts.map +1 -0
- package/dist/math/editDistance.js +48 -0
- package/dist/math/editDistance.js.map +1 -0
- package/dist/palettes/crayola.d.ts +200 -0
- package/dist/palettes/crayola.d.ts.map +1 -0
- package/dist/palettes/crayola.js +121 -0
- package/dist/palettes/crayola.js.map +1 -0
- package/dist/palettes/index.d.ts +1 -0
- package/dist/palettes/index.d.ts.map +1 -1
- package/dist/palettes/index.js +1 -0
- package/dist/palettes/index.js.map +1 -1
- package/dist/resolve.d.ts +39 -6
- package/dist/resolve.d.ts.map +1 -1
- package/dist/resolve.js +39 -12
- package/dist/resolve.js.map +1 -1
- package/package.json +8 -2
package/NOTICE.md
CHANGED
|
@@ -51,6 +51,38 @@ color-library lookup that rounds it through sRGB loses information.
|
|
|
51
51
|
If you need Pantone-certified color values, consult Pantone directly:
|
|
52
52
|
<https://www.pantone.com/>.
|
|
53
53
|
|
|
54
|
+
## Crayola®
|
|
55
|
+
|
|
56
|
+
**Crayola®** is a registered trademark of **Crayola LLC**. Chromonym is
|
|
57
|
+
**not affiliated with, endorsed by, licensed by, or certified by Crayola
|
|
58
|
+
LLC**.
|
|
59
|
+
|
|
60
|
+
The `crayola` palette in this library ships a **community-curated
|
|
61
|
+
subset** of Crayola crayon-color names with sRGB approximations of their
|
|
62
|
+
wrappers. The names are used as **nominative references** to publicly
|
|
63
|
+
identified Crayola colors — there is no trademark claim, and no
|
|
64
|
+
endorsement is implied. Hex values are derived from the widely-cited
|
|
65
|
+
Wikipedia list of Crayola crayon colors (CC BY-SA), which itself cites
|
|
66
|
+
Crayola's published approximations.
|
|
67
|
+
|
|
68
|
+
### Scope
|
|
69
|
+
|
|
70
|
+
The shipped set is ~85 entries — the current 64-standard box, the
|
|
71
|
+
iconic fluorescent "Neon" range, and widely-recognized modern
|
|
72
|
+
additions. It is not exhaustive: historical, retired, specialty-box
|
|
73
|
+
(Gem Tones, Heads 'N Tails, Multicultural, etc.), and regional-variant
|
|
74
|
+
colors are not included. If you need a specific Crayola color that
|
|
75
|
+
isn't present, open an issue or define a BYO palette.
|
|
76
|
+
|
|
77
|
+
### Accuracy
|
|
78
|
+
|
|
79
|
+
- Fluorescents and neons saturate outside sRGB by design; on-screen
|
|
80
|
+
sRGB approximations are necessarily softer than the physical crayons.
|
|
81
|
+
- Metallics (Silver, Gold, Copper) are flat sRGB approximations; the
|
|
82
|
+
physical crayons' reflective behavior is lost.
|
|
83
|
+
- Classic hues are close enough for comparative UI / identification
|
|
84
|
+
work but should not be used as a reference for print color matching.
|
|
85
|
+
|
|
54
86
|
## X11 / X.Org
|
|
55
87
|
|
|
56
88
|
The `x11` palette is derived from the X.Org `rgb.txt` file, which is in
|
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
<code>identify</code> • <code>resolve</code> • <code>convert</code>
|
|
21
21
|
</p>
|
|
22
22
|
|
|
23
|
-
**The last color-naming library you'll ever need.** One API — `identify`, `resolve`, `convert` — works against any palette you throw at it. Ships CSS, X11, and
|
|
23
|
+
**The last color-naming library you'll ever need.** One API — `identify`, `resolve`, `convert` — works against any palette you throw at it. Ships CSS, X11, Pantone, and Crayola out of the box; bring your own (brand colors, paint chips, game factions, chart themes) with full TypeScript inference and zero registration. Six distance metrics — from fast Euclidean to industry-standard CIEDE2000 and OKLAB. Tree-shakes to the bone — you only pay for palettes you import.
|
|
24
24
|
|
|
25
25
|
<p align="center">
|
|
26
26
|
<a href="https://simiancraft.github.io/chromonym/">
|
|
@@ -33,7 +33,7 @@ Because "it's sort of magenta-ish, maybe?" doesn't copy-paste into code — and
|
|
|
33
33
|
For color *manipulation* (mixing, scales, gamut mapping), reach for [`chroma-js`](https://gka.github.io/chroma.js/) or [`color.js`](https://colorjs.io/) — chromonym is the tool for *naming*.
|
|
34
34
|
|
|
35
35
|
```ts
|
|
36
|
-
import { identify, resolve, convert, pantone, type Palette } from 'chromonym';
|
|
36
|
+
import { identify, resolve, convert, pantone, crayola, web, type Palette } from 'chromonym';
|
|
37
37
|
|
|
38
38
|
// Your palette — defined inline, type-checked, no registration. Works the
|
|
39
39
|
// same as the built-in ones because that's the whole point.
|
|
@@ -47,12 +47,16 @@ const brand = {
|
|
|
47
47
|
identify('#ff2b3c', { palette: brand }) // 'acme red'
|
|
48
48
|
resolve('Acme Ink', { palette: brand }) // '#0a0f2c'
|
|
49
49
|
|
|
50
|
-
// Built-in palettes follow the identical shape — CSS, X11, Pantone out of the box.
|
|
50
|
+
// Built-in palettes follow the identical shape — CSS, X11, Pantone, Crayola out of the box.
|
|
51
51
|
identify('#ff8080') // 'lightcoral' (web is the default)
|
|
52
52
|
identify('#663399') // 'rebeccapurple'
|
|
53
53
|
identify('#E20074', { palette: pantone }) // '213 C' — T-Mobile magenta
|
|
54
|
+
identify('#E20074', { palette: crayola }) // 'Razzmatazz' — the closest Crayon
|
|
54
55
|
resolve('Pantone 185 C', { palette: pantone }) // '#e4002b'
|
|
55
56
|
|
|
57
|
+
// Cross-palette in one call: parse input as a name from `source`, return nearest in `palette`.
|
|
58
|
+
identify('rebeccapurple', { palette: pantone, source: web }) // '267 C'
|
|
59
|
+
|
|
56
60
|
// Format conversion: HEX / RGB / RGBA / HSL / HSV (palette-free, tree-shakes cleanly)
|
|
57
61
|
convert('#ff0000', { format: 'HSL' }) // 'hsl(0, 100%, 50%)'
|
|
58
62
|
convert({ h: 120, s: 100, l: 50 }, { format: 'HEX' }) // '#00ff00'
|
|
@@ -76,67 +80,127 @@ yarn add chromonym
|
|
|
76
80
|
npm install chromonym
|
|
77
81
|
```
|
|
78
82
|
|
|
83
|
+
## Migrating from 1.x
|
|
84
|
+
|
|
85
|
+
v2 collapsed the five-verb draft API (`identify`, `identifyAll`, `translate`, `resolve`, `convert`) into **three verbs** by folding the duplicates into options on existing verbs. Mechanical rewrites:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
// v1 → v2
|
|
89
|
+
identifyAll(color, { palette, k: 3 }) // → identify(color, { palette, k: 3 })
|
|
90
|
+
translate(name, { from: web, to: pantone }) // → identify(name, { palette: pantone, source: web })
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`resolve` and `convert` are unchanged. If you were only using those two, no edits are needed. See `CHANGELOG.md` for the full list of breaking changes.
|
|
94
|
+
|
|
79
95
|
## API
|
|
80
96
|
|
|
81
|
-
Three
|
|
97
|
+
Three verbs. All accept an optional `opts` object; defaults fire when omitted.
|
|
98
|
+
|
|
99
|
+
### Options × verbs, at a glance
|
|
100
|
+
|
|
101
|
+
chromonym's API is deliberately tight: **three verbs, five options, no new nouns per feature**. Options earn their seat on each verb only where the semantics fit. Same-named options mean the same thing everywhere they appear.
|
|
102
|
+
|
|
103
|
+
| | `identify` | `resolve` | `convert` |
|
|
104
|
+
|---|:---:|:---:|:---:|
|
|
105
|
+
| `palette` | ✓ target (default: `web`) | ✓ source (default: `web`) | ✓ optional — enables name I/O |
|
|
106
|
+
| `source` | ✓ when input is a name from another palette | — (the palette *is* the source) | — |
|
|
107
|
+
| `metric` | ✓ ΔE dispatch | — (no distance) | — (structural / exact-name only) |
|
|
108
|
+
| `format` | — (returns a name) | ✓ output format | ✓ output format |
|
|
109
|
+
| `k` | ✓ top-k (in the chosen metric's units) | ✓ fuzzy top-k by Levenshtein | ✗ — breaks strict-convert contract |
|
|
110
|
+
|
|
111
|
+
No aliases, no plugin hooks. Every verb defaults to single-result / strict behavior; supplying `k` opts into the ranked-array return and (for `resolve`) the fuzzy-matching path.
|
|
82
112
|
|
|
83
113
|
### `identify(input, opts?)`
|
|
84
114
|
|
|
85
|
-
**Color → name.** Finds the nearest-match name in the chosen palette using the selected perceptual distance metric.
|
|
115
|
+
**Color (or palette name) → name.** Finds the nearest-match name in the chosen palette using the selected perceptual distance metric.
|
|
86
116
|
|
|
87
117
|
```ts
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
118
|
+
// Simple case — single nearest name.
|
|
119
|
+
function identify<P extends Palette = typeof web>(
|
|
120
|
+
input: ColorInput | string,
|
|
121
|
+
opts?: { palette?: P; source?: Palette; metric?: DistanceMetric },
|
|
122
|
+
): Extract<keyof P['colors'], string> | null;
|
|
123
|
+
|
|
124
|
+
// With `k` — ranked top-k matches with distances.
|
|
125
|
+
function identify<P extends Palette = typeof web>(
|
|
126
|
+
input: ColorInput | string,
|
|
127
|
+
opts: { palette?: P; source?: Palette; metric?: DistanceMetric; k: number },
|
|
128
|
+
): Array<{ name: Extract<keyof P['colors'], string>; value: HexColor; distance: number }>;
|
|
92
129
|
```
|
|
93
130
|
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
-
|
|
97
|
-
- Return type
|
|
98
|
-
- Ties go to whichever color was defined first
|
|
131
|
+
- **`palette`** — target (default: `web`). The palette to search in.
|
|
132
|
+
- **`source`** — when `input` is a string that isn't structurally a color (hex / rgb / hsl / …), parse it as a name in this palette. Enables cross-palette lookups in one verb. Structural inputs always parse structurally even when `source` is set.
|
|
133
|
+
- **`metric`** — distance metric for the nearest-match step. Defaults to the target palette's own `defaultMetric`.
|
|
134
|
+
- **`k`** — when present, return the top-k matches sorted ascending by distance. Return type flips from `Name | null` to `Array<Match>`; each `Match` carries `{ name, value, distance }`. `value` is the palette's stored hex for rendering swatches; `distance` is in the metric's natural units (ΔE units for all `deltaE*` metrics, channel-unit Euclidean for the others).
|
|
135
|
+
- Returns `null` / `[]` when the input can't be parsed. Ties go to whichever color was defined first in the palette.
|
|
99
136
|
|
|
100
137
|
```ts
|
|
101
|
-
import { identify, pantone, x11 } from 'chromonym';
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
identify(
|
|
105
|
-
identify({ r: 250, g: 20, b: 60 })
|
|
106
|
-
identify('#
|
|
107
|
-
identify('#
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
identify('
|
|
138
|
+
import { identify, pantone, x11, web, crayola } from 'chromonym';
|
|
139
|
+
|
|
140
|
+
// Classic color → name
|
|
141
|
+
identify('#ff0000') // 'red' (web default)
|
|
142
|
+
identify({ r: 250, g: 20, b: 60 }) // 'crimson' (nearest)
|
|
143
|
+
identify('#e4002b', { palette: pantone }) // '185 C' (exact match)
|
|
144
|
+
identify('#ff0000', { palette: pantone }) // '172 C' (nearest — pure red isn't a Pantone)
|
|
145
|
+
|
|
146
|
+
// Cross-palette: parse input as a name in `source`, match in `palette`
|
|
147
|
+
identify('rebeccapurple', { palette: pantone, source: web }) // '267 C'
|
|
148
|
+
identify('Razzmatazz', { palette: pantone, source: crayola }) // '213 C' (same family as T-Mobile magenta)
|
|
149
|
+
identify('dodgerblue', { palette: x11, source: web }) // 'dodger blue' (shared hex)
|
|
150
|
+
|
|
151
|
+
// Top-k matches with ΔE distances — powers "did you mean" UIs
|
|
152
|
+
identify('#ff4488', { palette: crayola, k: 3 })
|
|
153
|
+
// [
|
|
154
|
+
// { name: 'Violet Red', value: '#f75394', distance: 0.0251 },
|
|
155
|
+
// { name: 'Wild Watermelon', value: '#fc6c85', distance: 0.0682 },
|
|
156
|
+
// { name: 'Cerise', value: '#dd4492', distance: 0.0685 },
|
|
157
|
+
// ]
|
|
111
158
|
```
|
|
112
159
|
|
|
113
160
|
### `resolve(name, opts?)`
|
|
114
161
|
|
|
115
|
-
**Name → color.** Normalizes the input
|
|
162
|
+
**Name → color.** Normalizes the input, looks up the canonical key in the chosen palette, and returns the value in the chosen format. With `k`, switches to fuzzy matching via Levenshtein edit distance — perfect for user-typed input where typos, casing, and punctuation vary.
|
|
116
163
|
|
|
117
164
|
```ts
|
|
165
|
+
// Strict — exact match via normalizer.
|
|
118
166
|
function resolve(
|
|
119
167
|
name: string,
|
|
120
168
|
opts?: { palette?: Palette; format?: ColorFormat },
|
|
121
|
-
): ColorValue | null
|
|
169
|
+
): ColorValue | null;
|
|
170
|
+
|
|
171
|
+
// Fuzzy top-k via Levenshtein edit distance.
|
|
172
|
+
function resolve<P extends Palette = typeof web>(
|
|
173
|
+
name: string,
|
|
174
|
+
opts: { palette?: P; format?: ColorFormat; k: number },
|
|
175
|
+
): Array<{ name: Extract<keyof P['colors'], string>; value: ColorValue; distance: number }>;
|
|
122
176
|
```
|
|
123
177
|
|
|
124
|
-
-
|
|
125
|
-
-
|
|
126
|
-
-
|
|
127
|
-
- Normalization is the palette's own `normalize` function
|
|
178
|
+
- **`palette`** — source (default: `web`). The palette to look the name up in.
|
|
179
|
+
- **`format`** — output format (default: `'HEX'`). Affects both the strict return and the `value` field in each fuzzy `Match`.
|
|
180
|
+
- **`k`** — when present, bypass strict lookup and do fuzzy top-k. `distance` is the Levenshtein edit count against the palette's normalized key. Strict exact matches have distance `0`.
|
|
181
|
+
- Normalization is always the palette's own `normalize` function, applied to both the input and the keys before comparison. So `'Alice Blue'`, `'alice-blue'`, `'ALICEBLUE'`, `'Pantone 185 C'` all resolve identically in their respective palettes — strict mode uses normalization to reach exact match; fuzzy mode uses it as the input to the edit-distance ranking.
|
|
128
182
|
|
|
129
183
|
```ts
|
|
130
|
-
import { resolve, pantone } from 'chromonym';
|
|
184
|
+
import { resolve, pantone, crayola } from 'chromonym';
|
|
131
185
|
|
|
186
|
+
// Strict (default) — exact match or null
|
|
132
187
|
resolve('crimson') // '#dc143c'
|
|
133
188
|
resolve('Alice Blue') // '#f0f8ff'
|
|
134
189
|
resolve('alice-blue!') // '#f0f8ff'
|
|
135
|
-
resolve('185 C', { palette: pantone })
|
|
136
|
-
resolve('Pantone 185 C', { palette: pantone })
|
|
190
|
+
resolve('185 C', { palette: pantone }) // '#e4002b'
|
|
191
|
+
resolve('Pantone 185 C', { palette: pantone }) // '#e4002b' (same, normalized)
|
|
137
192
|
resolve('crimson', { format: 'RGB' }) // 'rgb(220, 20, 60)'
|
|
138
|
-
resolve('crimson', { format: 'RGBA' }) // { r: 220, g: 20, b: 60, a: 1 }
|
|
139
193
|
resolve('not-a-color') // null
|
|
194
|
+
|
|
195
|
+
// Fuzzy — typo-tolerant user input
|
|
196
|
+
resolve('rebecapurple', { palette: web, k: 3 })
|
|
197
|
+
// [
|
|
198
|
+
// { name: 'rebeccapurple', value: '#663399', distance: 1 },
|
|
199
|
+
// { name: 'mediumpurple', value: '#9370db', distance: 5 },
|
|
200
|
+
// { name: 'purple', value: '#800080', distance: 6 },
|
|
201
|
+
// ]
|
|
202
|
+
resolve('Razmataz', { palette: crayola, k: 1 })
|
|
203
|
+
// [{ name: 'Razzmatazz', value: '#e3256b', distance: 2 }]
|
|
140
204
|
```
|
|
141
205
|
|
|
142
206
|
### `convert(input, opts?)`
|
|
@@ -233,72 +297,74 @@ resolve('Nurgle Green', { palette: warhammer })
|
|
|
233
297
|
// → '#748c3f' (your normalizer handles case + punctuation)
|
|
234
298
|
```
|
|
235
299
|
|
|
236
|
-
### The
|
|
300
|
+
### The four we ship
|
|
237
301
|
|
|
238
302
|
| Name | Entries | Source |
|
|
239
303
|
|---|---|---|
|
|
240
304
|
| `web` (default) | 148 | CSS Color Module Level 4 named colors |
|
|
241
305
|
| `x11` | 658 | X.Org `rgb.txt` (public domain) |
|
|
242
306
|
| `pantone` | 907 | Pantone Coated (C) — community approximations (not Pantone-licensed) |
|
|
307
|
+
| `crayola` | ~85 | Crayola crayon colors — community approximations (not Crayola-licensed) |
|
|
243
308
|
|
|
244
309
|
Importable directly, or via subpath exports for stricter tree-shaking:
|
|
245
310
|
|
|
246
311
|
```ts
|
|
247
|
-
import { web, x11, pantone } from 'chromonym';
|
|
312
|
+
import { web, x11, pantone, crayola } from 'chromonym';
|
|
248
313
|
// or: import { pantone } from 'chromonym/pantone';
|
|
249
314
|
|
|
250
315
|
web.colors.crimson // '#dc143c'
|
|
251
|
-
web.colors.aliceblue // '#f0f8ff'
|
|
316
|
+
web.colors.aliceblue // '#f0f8ff' (CSS keyword form — paste-compatible)
|
|
252
317
|
pantone.colors['185 C'] // '#e4002b'
|
|
318
|
+
crayola.colors.Razzmatazz // '#e3256b'
|
|
319
|
+
crayola.colors['Granny Smith Apple'] // '#a8e4a0'
|
|
253
320
|
```
|
|
254
321
|
|
|
255
|
-
Each palette's keys follow its own domain convention — so `identify`'s output pastes back into whatever ecosystem the name came from. `web` uses the CSS spec's single-word form (`rebeccapurple`), `x11` uses the X.Org docs' spaced form (`'antique white 1'`), `pantone` uses the official print notation (`'185 C'`).
|
|
322
|
+
Each palette's keys follow its own domain convention — so `identify`'s output pastes back into whatever ecosystem the name came from. `web` uses the CSS spec's single-word form (`rebeccapurple`), `x11` uses the X.Org docs' spaced form (`'antique white 1'`), `pantone` uses the official print notation (`'185 C'`), `crayola` uses the Title Case form printed on the crayon wrapper (`'Granny Smith Apple'`).
|
|
256
323
|
|
|
257
324
|
*Trivia:* `web.colors.rebeccapurple` (`#663399`) entered CSS Color 4 in 2014 in memory of [Rebecca Meyer](https://meyerweb.com/eric/thoughts/2014/06/19/rebeccapurple/). The X11 set ships every gray name twice (`gray`, `grey`) plus numbered variants up to 99, so `x11.colors['gray 73']` is a real key (`#bababa`). Yes, these are Greys. No, not the kind that visit during sleep paralysis.
|
|
258
325
|
|
|
259
326
|
### Cross-palette translation
|
|
260
327
|
|
|
261
|
-
"What's this CSS color in X11?" / "What's our brand red in Pantone?" is a *nearest-match* question — palettes almost never share exact hex values, so there's no strict round-trip.
|
|
328
|
+
"What's this CSS color in X11?" / "What's our brand red in Pantone?" is a *nearest-match* question — palettes almost never share exact hex values, so there's no strict round-trip. `identify` handles it directly via `source`: parse the input as a name from one palette, return the nearest name from another.
|
|
262
329
|
|
|
263
330
|
```ts
|
|
264
|
-
import {
|
|
265
|
-
|
|
266
|
-
//
|
|
267
|
-
identify(
|
|
268
|
-
//
|
|
269
|
-
|
|
270
|
-
identify(
|
|
271
|
-
//
|
|
272
|
-
|
|
273
|
-
//
|
|
274
|
-
identify(
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
identify(
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
//
|
|
288
|
-
//
|
|
289
|
-
|
|
290
|
-
// → '526 C' (OKLAB disagrees with ΔE2000's '267 C' in the saturated-purple region)
|
|
331
|
+
import { identify, web, x11, pantone, crayola } from 'chromonym';
|
|
332
|
+
|
|
333
|
+
// Name in one palette → nearest name in another.
|
|
334
|
+
identify('rebeccapurple', { palette: x11, source: web }) // 'dark orchid 4'
|
|
335
|
+
identify('dodgerblue', { palette: x11, source: web }) // 'dodger blue' (shared hex)
|
|
336
|
+
identify('dark slate gray 4',{ palette: pantone, source: x11 }) // '5483 C'
|
|
337
|
+
identify('hotpink', { palette: pantone, source: web }) // '812 C'
|
|
338
|
+
identify('Razzmatazz', { palette: pantone, source: crayola }) // '213 C' (same family as T-Mobile magenta)
|
|
339
|
+
identify('Razzmatazz', { palette: web, source: crayola }) // 'deeppink'
|
|
340
|
+
identify('hotpink', { palette: crayola, source: web }) // 'Violet Red'
|
|
341
|
+
identify('forestgreen', { palette: crayola, source: web }) // 'Green'
|
|
342
|
+
|
|
343
|
+
// BYO works on either side — ship your brand palette, find the closest Pantone for print.
|
|
344
|
+
identify('acme red', { palette: pantone, source: brand }) // '1788 C'
|
|
345
|
+
|
|
346
|
+
// Override the metric for the nearest-match side.
|
|
347
|
+
identify('rebeccapurple', { palette: pantone, source: web, metric: 'deltaEok' })
|
|
348
|
+
// '526 C' (OKLAB disagrees with ΔE2000's '267 C' in the saturated-purple region)
|
|
349
|
+
|
|
350
|
+
// Top-k across palettes — what are the three closest Pantones to CSS "hotpink"?
|
|
351
|
+
identify('hotpink', { palette: pantone, source: web, k: 3 })
|
|
352
|
+
// [
|
|
353
|
+
// { name: '812 C', value: '#ff5fa2', distance: 3.56 },
|
|
354
|
+
// { name: '211 C', value: '#f57eb6', distance: 3.95 },
|
|
355
|
+
// { name: '218 C', value: '#e56db1', distance: 4.30 },
|
|
356
|
+
// ]
|
|
291
357
|
```
|
|
292
358
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
If this chain shows up often in your code, wrap it in your own helper:
|
|
359
|
+
If you want the underlying chain — keeping the intermediate hex, or using `convert`'s strict throw-on-miss behavior for unknown source names — `identify(convert(…))` still works:
|
|
296
360
|
|
|
297
361
|
```ts
|
|
298
|
-
const
|
|
299
|
-
|
|
362
|
+
const hex = convert('rebeccapurple', { palette: web }); // '#663399' (throws on miss)
|
|
363
|
+
const near = identify(hex, { palette: pantone }); // '267 C'
|
|
300
364
|
```
|
|
301
365
|
|
|
366
|
+
Rule of thumb: use `source` when you want one clean call and `null` on miss; use the chain when you want to inspect the intermediate hex or trigger a loud failure on unknown source names.
|
|
367
|
+
|
|
302
368
|
## Distance metrics
|
|
303
369
|
|
|
304
370
|
*Six ways to ask "how different are two colors?"*
|
|
@@ -309,7 +375,7 @@ const translate = (name: string, from: Palette, to: Palette) =>
|
|
|
309
375
|
|---|---|---|
|
|
310
376
|
| `'euclidean-srgb'` | Raw `sqrt(Δr² + Δg² + Δb²)` in sRGB. Fastest. Not perceptually uniform — a unit of distance doesn't mean a unit of "visual difference." | Tight perf budgets; well-separated palettes where you just need the obvious answer. |
|
|
311
377
|
| `'euclidean-linear'` | Same math, but on linearized (gamma-removed) RGB. Somewhat better in dark regions. Still not perceptual. | Physical-light mixing contexts; incremental upgrade from sRGB Euclidean. |
|
|
312
|
-
| `'deltaE76'` | Euclidean in CIELAB (CIE 1976). Simple perceptual metric. 1 ΔE
|
|
378
|
+
| `'deltaE76'` | Euclidean in CIELAB (CIE 1976). Simple perceptual metric. 1 ΔE is often cited as roughly a just-noticeable difference, though uniformity breaks down in saturated blues/purples — which is the reason ΔE2000 exists. | **Default for web and x11.** Meaningful perceptual accuracy at low cost. |
|
|
313
379
|
| `'deltaE94'` | ΔE76 + chroma/hue weighting (CIE 1994). Fixes "saturated colors feel too far apart." | When ΔE76 is over-penalizing saturated matches in your use case. |
|
|
314
380
|
| `'deltaE2000'` | Full CIEDE2000 formula with blue/purple rotation correction. Industry standard for print, design tools, Pantone workflows. | **Default for pantone.** Use whenever accuracy matters, especially in the blue region where ΔE76/94 break down. |
|
|
315
381
|
| `'deltaEok'` | Euclidean distance in OKLAB (Björn Ottosson, 2020). OKLAB is perceptually uniform by construction — no weighting formula needed. Strictly more uniform than CIELAB; often a better nearest-match than ΔE2000 in saturated-blue regions, and cheaper to compute. | Use when you want perceptual accuracy without the CIEDE2000 rotation-term complexity. |
|
package/dist/identify.d.ts
CHANGED
|
@@ -1,25 +1,50 @@
|
|
|
1
1
|
import { web } from './palettes/web.js';
|
|
2
|
-
import type { ColorInput, DistanceMetric, Palette } from './types.js';
|
|
2
|
+
import type { ColorInput, DistanceMetric, HexColor, Palette } from './types.js';
|
|
3
3
|
/** Extract string keys from a Palette's `colors` map. */
|
|
4
4
|
type PaletteKey<P extends Palette> = Extract<keyof P['colors'], string>;
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* One ranked nearest-match entry when `identify` is called with `k`.
|
|
7
|
+
* `value` is the palette's stored hex for the match (useful for rendering
|
|
8
|
+
* swatches). `distance` is in the selected metric's natural units — ΔE
|
|
9
|
+
* for `deltaE*` metrics, channel-unit Euclidean for the others.
|
|
10
|
+
*/
|
|
11
|
+
export type IdentifyMatch<Name extends string> = {
|
|
12
|
+
readonly name: Name;
|
|
13
|
+
readonly value: HexColor;
|
|
14
|
+
readonly distance: number;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Identify the nearest-named color for any color input (or palette name
|
|
18
|
+
* from another palette via `source`).
|
|
19
|
+
*
|
|
20
|
+
* **Simple case — color in, name out:**
|
|
21
|
+
* identify('#ff0000') → 'red'
|
|
22
|
+
* identify('#ff0000', { palette: pantone }) → '172 C'
|
|
7
23
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* `{ metric: 'deltaE2000' }` for strictest perceptual accuracy.
|
|
24
|
+
* **Cross-palette — name from one palette, nearest in another:**
|
|
25
|
+
* identify('rebeccapurple', { palette: pantone, source: web }) → '267 C'
|
|
26
|
+
* identify('Razzmatazz', { palette: pantone, source: crayola }) → '213 C'
|
|
12
27
|
*
|
|
13
|
-
*
|
|
28
|
+
* **Top-k ranked matches with ΔE distances:**
|
|
29
|
+
* identify('#ff0000', { palette: pantone, k: 3 })
|
|
30
|
+
* // [{ name: '172 C', value: '#fa4616', distance: 3.2 }, ...]
|
|
14
31
|
*
|
|
15
|
-
*
|
|
32
|
+
* The distance metric defaults to the target palette's `defaultMetric`
|
|
33
|
+
* (web/x11: `deltaE76`, pantone: `deltaE2000`, crayola: `deltaEok`).
|
|
34
|
+
* Override with `metric`.
|
|
16
35
|
*
|
|
17
|
-
*
|
|
18
|
-
* return type is inferred from its `colors` keys — no registration needed.
|
|
36
|
+
* Returns `null` (or `[]` when `k` is set) if the input can't be parsed.
|
|
19
37
|
*/
|
|
20
|
-
export declare function identify<P extends Palette = typeof web>(input: ColorInput, opts?: {
|
|
38
|
+
export declare function identify<P extends Palette = typeof web>(input: ColorInput | string, opts?: {
|
|
21
39
|
palette?: P;
|
|
40
|
+
source?: Palette;
|
|
22
41
|
metric?: DistanceMetric;
|
|
23
42
|
}): PaletteKey<P> | null;
|
|
43
|
+
export declare function identify<P extends Palette = typeof web>(input: ColorInput | string, opts: {
|
|
44
|
+
palette?: P;
|
|
45
|
+
source?: Palette;
|
|
46
|
+
metric?: DistanceMetric;
|
|
47
|
+
k: number;
|
|
48
|
+
}): Array<IdentifyMatch<PaletteKey<P>>>;
|
|
24
49
|
export {};
|
|
25
50
|
//# sourceMappingURL=identify.d.ts.map
|
package/dist/identify.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identify.d.ts","sourceRoot":"","sources":["../src/identify.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"identify.d.ts","sourceRoot":"","sources":["../src/identify.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAQ,MAAM,YAAY,CAAC;AAEtF,yDAAyD;AACzD,KAAK,UAAU,CAAC,CAAC,SAAS,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;AAExE;;;;;GAKG;AACH,MAAM,MAAM,aAAa,CAAC,IAAI,SAAS,MAAM,IAAI;IAC/C,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC;AAmBF;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,GAAG,EACrD,KAAK,EAAE,UAAU,GAAG,MAAM,EAC1B,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,cAAc,CAAA;CAAE,GAChE,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;AAGxB,wBAAgB,QAAQ,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,GAAG,EACrD,KAAK,EAAE,UAAU,GAAG,MAAM,EAC1B,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,cAAc,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1E,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC","sourcesContent":["import { hexToRgba } from './conversions/hex.js';\nimport { toRgba } from './convert.js';\nimport { detectFormat } from './detectFormat.js';\nimport { getNameIndex, nearest, nearestAll } from './indexing.js';\nimport { web } from './palettes/web.js';\nimport type { ColorInput, DistanceMetric, HexColor, Palette, Rgba } from './types.js';\n\n/** Extract string keys from a Palette's `colors` map. */\ntype PaletteKey<P extends Palette> = Extract<keyof P['colors'], string>;\n\n/**\n * One ranked nearest-match entry when `identify` is called with `k`.\n * `value` is the palette's stored hex for the match (useful for rendering\n * swatches). `distance` is in the selected metric's natural units — ΔE\n * for `deltaE*` metrics, channel-unit Euclidean for the others.\n */\nexport type IdentifyMatch<Name extends string> = {\n readonly name: Name;\n readonly value: HexColor;\n readonly distance: number;\n};\n\n/**\n * Parse a string input that may be a color literal or a palette name.\n * Returns the canonical Rgba, or `null` if nothing matches.\n */\nfunction parseInput(input: ColorInput | string, source?: Palette): Rgba | null {\n const detected = detectFormat(input as ColorInput);\n if (detected !== 'UNKNOWN') return toRgba(input as ColorInput, detected);\n if (source !== undefined && typeof input === 'string') {\n const canonical = getNameIndex(source).get(source.normalize(input));\n if (canonical === undefined) return null;\n const hex = (source.colors as Record<string, HexColor>)[canonical];\n if (hex === undefined) return null;\n return hexToRgba(hex);\n }\n return null;\n}\n\n/**\n * Identify the nearest-named color for any color input (or palette name\n * from another palette via `source`).\n *\n * **Simple case — color in, name out:**\n * identify('#ff0000') → 'red'\n * identify('#ff0000', { palette: pantone }) → '172 C'\n *\n * **Cross-palette — name from one palette, nearest in another:**\n * identify('rebeccapurple', { palette: pantone, source: web }) → '267 C'\n * identify('Razzmatazz', { palette: pantone, source: crayola }) → '213 C'\n *\n * **Top-k ranked matches with ΔE distances:**\n * identify('#ff0000', { palette: pantone, k: 3 })\n * // [{ name: '172 C', value: '#fa4616', distance: 3.2 }, ...]\n *\n * The distance metric defaults to the target palette's `defaultMetric`\n * (web/x11: `deltaE76`, pantone: `deltaE2000`, crayola: `deltaEok`).\n * Override with `metric`.\n *\n * Returns `null` (or `[]` when `k` is set) if the input can't be parsed.\n */\n\n// Overload 1: no `k` — single name (or null). Unchanged legacy shape.\nexport function identify<P extends Palette = typeof web>(\n input: ColorInput | string,\n opts?: { palette?: P; source?: Palette; metric?: DistanceMetric },\n): PaletteKey<P> | null;\n\n// Overload 2: `k` present — ranked Match[] with distances.\nexport function identify<P extends Palette = typeof web>(\n input: ColorInput | string,\n opts: { palette?: P; source?: Palette; metric?: DistanceMetric; k: number },\n): Array<IdentifyMatch<PaletteKey<P>>>;\n\n// Implementation.\nexport function identify(\n input: ColorInput | string,\n opts: { palette?: Palette; source?: Palette; metric?: DistanceMetric; k?: number } = {},\n): string | null | Array<IdentifyMatch<string>> {\n const palette = opts.palette ?? web;\n const metric = opts.metric ?? palette.defaultMetric;\n const rgba = parseInput(input, opts.source);\n\n if (opts.k !== undefined) {\n if (rgba === null) return [];\n const raw = nearestAll(rgba, palette, metric, opts.k);\n return raw.map((m) => {\n const value = (palette.colors as Record<string, HexColor>)[m.name];\n return { name: m.name, value: value as HexColor, distance: m.distance };\n });\n }\n\n if (rgba === null) return null;\n const name = nearest(rgba, palette, metric);\n return name || null;\n}\n"]}
|
package/dist/identify.js
CHANGED
|
@@ -1,29 +1,44 @@
|
|
|
1
|
+
import { hexToRgba } from './conversions/hex.js';
|
|
1
2
|
import { toRgba } from './convert.js';
|
|
2
3
|
import { detectFormat } from './detectFormat.js';
|
|
3
|
-
import { nearest } from './indexing.js';
|
|
4
|
+
import { getNameIndex, nearest, nearestAll } from './indexing.js';
|
|
4
5
|
import { web } from './palettes/web.js';
|
|
5
6
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* The distance metric defaults to the palette's own `defaultMetric`
|
|
9
|
-
* (web/x11: `deltaE76`, pantone: `deltaE2000`). Override with the `metric`
|
|
10
|
-
* option — e.g. `{ metric: 'euclidean-srgb' }` for maximum speed, or
|
|
11
|
-
* `{ metric: 'deltaE2000' }` for strictest perceptual accuracy.
|
|
12
|
-
*
|
|
13
|
-
* Returns `null` if the input isn't a recognized color shape.
|
|
14
|
-
*
|
|
15
|
-
* Defaults: palette = `web`.
|
|
16
|
-
*
|
|
17
|
-
* BYO palettes: pass any object matching `Palette<Name>` and the
|
|
18
|
-
* return type is inferred from its `colors` keys — no registration needed.
|
|
7
|
+
* Parse a string input that may be a color literal or a palette name.
|
|
8
|
+
* Returns the canonical Rgba, or `null` if nothing matches.
|
|
19
9
|
*/
|
|
10
|
+
function parseInput(input, source) {
|
|
11
|
+
const detected = detectFormat(input);
|
|
12
|
+
if (detected !== 'UNKNOWN')
|
|
13
|
+
return toRgba(input, detected);
|
|
14
|
+
if (source !== undefined && typeof input === 'string') {
|
|
15
|
+
const canonical = getNameIndex(source).get(source.normalize(input));
|
|
16
|
+
if (canonical === undefined)
|
|
17
|
+
return null;
|
|
18
|
+
const hex = source.colors[canonical];
|
|
19
|
+
if (hex === undefined)
|
|
20
|
+
return null;
|
|
21
|
+
return hexToRgba(hex);
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
// Implementation.
|
|
20
26
|
export function identify(input, opts = {}) {
|
|
21
|
-
const
|
|
22
|
-
|
|
27
|
+
const palette = opts.palette ?? web;
|
|
28
|
+
const metric = opts.metric ?? palette.defaultMetric;
|
|
29
|
+
const rgba = parseInput(input, opts.source);
|
|
30
|
+
if (opts.k !== undefined) {
|
|
31
|
+
if (rgba === null)
|
|
32
|
+
return [];
|
|
33
|
+
const raw = nearestAll(rgba, palette, metric, opts.k);
|
|
34
|
+
return raw.map((m) => {
|
|
35
|
+
const value = palette.colors[m.name];
|
|
36
|
+
return { name: m.name, value: value, distance: m.distance };
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if (rgba === null)
|
|
23
40
|
return null;
|
|
24
|
-
const
|
|
25
|
-
const rgba = toRgba(input, format);
|
|
26
|
-
const name = nearest(rgba, palette, opts.metric ?? palette.defaultMetric);
|
|
41
|
+
const name = nearest(rgba, palette, metric);
|
|
27
42
|
return name || null;
|
|
28
43
|
}
|
|
29
44
|
//# sourceMappingURL=identify.js.map
|
package/dist/identify.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identify.js","sourceRoot":"","sources":["../src/identify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"identify.js","sourceRoot":"","sources":["../src/identify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAkBxC;;;GAGG;AACH,SAAS,UAAU,CAAC,KAA0B,EAAE,MAAgB;IAC9D,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAmB,CAAC,CAAC;IACnD,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,KAAmB,EAAE,QAAQ,CAAC,CAAC;IACzE,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACtD,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACpE,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACzC,MAAM,GAAG,GAAI,MAAM,CAAC,MAAmC,CAAC,SAAS,CAAC,CAAC;QACnE,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACnC,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAqCD,kBAAkB;AAClB,MAAM,UAAU,QAAQ,CACtB,KAA0B,EAC1B,IAAI,GAAiF,EAAE;IAEvF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,GAAG,CAAC;IACpC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC;IACpD,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAE5C,IAAI,IAAI,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QACzB,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QACtD,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACnB,MAAM,KAAK,GAAI,OAAO,CAAC,MAAmC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACnE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,KAAiB,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC1E,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5C,OAAO,IAAI,IAAI,IAAI,CAAC;AACtB,CAAC","sourcesContent":["import { hexToRgba } from './conversions/hex.js';\nimport { toRgba } from './convert.js';\nimport { detectFormat } from './detectFormat.js';\nimport { getNameIndex, nearest, nearestAll } from './indexing.js';\nimport { web } from './palettes/web.js';\nimport type { ColorInput, DistanceMetric, HexColor, Palette, Rgba } from './types.js';\n\n/** Extract string keys from a Palette's `colors` map. */\ntype PaletteKey<P extends Palette> = Extract<keyof P['colors'], string>;\n\n/**\n * One ranked nearest-match entry when `identify` is called with `k`.\n * `value` is the palette's stored hex for the match (useful for rendering\n * swatches). `distance` is in the selected metric's natural units — ΔE\n * for `deltaE*` metrics, channel-unit Euclidean for the others.\n */\nexport type IdentifyMatch<Name extends string> = {\n readonly name: Name;\n readonly value: HexColor;\n readonly distance: number;\n};\n\n/**\n * Parse a string input that may be a color literal or a palette name.\n * Returns the canonical Rgba, or `null` if nothing matches.\n */\nfunction parseInput(input: ColorInput | string, source?: Palette): Rgba | null {\n const detected = detectFormat(input as ColorInput);\n if (detected !== 'UNKNOWN') return toRgba(input as ColorInput, detected);\n if (source !== undefined && typeof input === 'string') {\n const canonical = getNameIndex(source).get(source.normalize(input));\n if (canonical === undefined) return null;\n const hex = (source.colors as Record<string, HexColor>)[canonical];\n if (hex === undefined) return null;\n return hexToRgba(hex);\n }\n return null;\n}\n\n/**\n * Identify the nearest-named color for any color input (or palette name\n * from another palette via `source`).\n *\n * **Simple case — color in, name out:**\n * identify('#ff0000') → 'red'\n * identify('#ff0000', { palette: pantone }) → '172 C'\n *\n * **Cross-palette — name from one palette, nearest in another:**\n * identify('rebeccapurple', { palette: pantone, source: web }) → '267 C'\n * identify('Razzmatazz', { palette: pantone, source: crayola }) → '213 C'\n *\n * **Top-k ranked matches with ΔE distances:**\n * identify('#ff0000', { palette: pantone, k: 3 })\n * // [{ name: '172 C', value: '#fa4616', distance: 3.2 }, ...]\n *\n * The distance metric defaults to the target palette's `defaultMetric`\n * (web/x11: `deltaE76`, pantone: `deltaE2000`, crayola: `deltaEok`).\n * Override with `metric`.\n *\n * Returns `null` (or `[]` when `k` is set) if the input can't be parsed.\n */\n\n// Overload 1: no `k` — single name (or null). Unchanged legacy shape.\nexport function identify<P extends Palette = typeof web>(\n input: ColorInput | string,\n opts?: { palette?: P; source?: Palette; metric?: DistanceMetric },\n): PaletteKey<P> | null;\n\n// Overload 2: `k` present — ranked Match[] with distances.\nexport function identify<P extends Palette = typeof web>(\n input: ColorInput | string,\n opts: { palette?: P; source?: Palette; metric?: DistanceMetric; k: number },\n): Array<IdentifyMatch<PaletteKey<P>>>;\n\n// Implementation.\nexport function identify(\n input: ColorInput | string,\n opts: { palette?: Palette; source?: Palette; metric?: DistanceMetric; k?: number } = {},\n): string | null | Array<IdentifyMatch<string>> {\n const palette = opts.palette ?? web;\n const metric = opts.metric ?? palette.defaultMetric;\n const rgba = parseInput(input, opts.source);\n\n if (opts.k !== undefined) {\n if (rgba === null) return [];\n const raw = nearestAll(rgba, palette, metric, opts.k);\n return raw.map((m) => {\n const value = (palette.colors as Record<string, HexColor>)[m.name];\n return { name: m.name, value: value as HexColor, distance: m.distance };\n });\n }\n\n if (rgba === null) return null;\n const name = nearest(rgba, palette, metric);\n return name || null;\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,11 +5,12 @@ export { pantoneToRgba, rgbaToPantone } from './conversions/pantone.js';
|
|
|
5
5
|
export { rgbaToRgb, rgbToRgba } from './conversions/rgb.js';
|
|
6
6
|
export { convert, fromRgba, toRgba } from './convert.js';
|
|
7
7
|
export { type DetectedFormat, detectFormat, isColor } from './detectFormat.js';
|
|
8
|
-
export { identify } from './identify.js';
|
|
8
|
+
export { type IdentifyMatch, identify } from './identify.js';
|
|
9
|
+
export { type CrayolaColorName, crayola } from './palettes/crayola.js';
|
|
9
10
|
export { type PantoneColorName, pantone } from './palettes/pantone.js';
|
|
10
11
|
export { type WebColorName, web } from './palettes/web.js';
|
|
11
12
|
export { type X11ColorName, x11 } from './palettes/x11.js';
|
|
12
|
-
export { resolve } from './resolve.js';
|
|
13
|
+
export { type ResolveMatch, resolve } from './resolve.js';
|
|
13
14
|
export type { ColorFormat, ColorInput, ColorValue, DistanceMetric, HexColor, HslInput, HslObject, HslString, HsvInput, HsvObject, HsvString, NormalizeFn, Palette, Rgba, RgbaInput, RgbaString, RgbaTuple, RgbInput, RgbObject, RgbString, RgbTuple, } from './types.js';
|
|
14
15
|
export { COLOR_FORMATS } from './types.js';
|
|
15
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,KAAK,cAAc,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,KAAK,cAAc,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,KAAK,aAAa,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,KAAK,gBAAgB,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,KAAK,gBAAgB,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,KAAK,YAAY,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,KAAK,YAAY,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,KAAK,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC1D,YAAY,EACV,WAAW,EACX,UAAU,EACV,UAAU,EACV,cAAc,EACd,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,SAAS,EACT,QAAQ,EACR,SAAS,EACT,SAAS,EACT,WAAW,EACX,OAAO,EACP,IAAI,EACJ,SAAS,EACT,UAAU,EACV,SAAS,EACT,QAAQ,EACR,SAAS,EACT,SAAS,EACT,QAAQ,GACT,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC","sourcesContent":["// Public API barrel — explicit named re-exports only (tree-shake friendly).\n// No default export; no side effects at module scope.\n\nexport { hexToRgba, rgbaToHex } from './conversions/hex.js';\nexport { hslToRgba, rgbaToHsl } from './conversions/hsl.js';\nexport { hsvToRgba, rgbaToHsv } from './conversions/hsv.js';\nexport { pantoneToRgba, rgbaToPantone } from './conversions/pantone.js';\nexport { rgbaToRgb, rgbToRgba } from './conversions/rgb.js';\nexport { convert, fromRgba, toRgba } from './convert.js';\nexport { type DetectedFormat, detectFormat, isColor } from './detectFormat.js';\nexport { type IdentifyMatch, identify } from './identify.js';\nexport { type CrayolaColorName, crayola } from './palettes/crayola.js';\nexport { type PantoneColorName, pantone } from './palettes/pantone.js';\nexport { type WebColorName, web } from './palettes/web.js';\nexport { type X11ColorName, x11 } from './palettes/x11.js';\nexport { type ResolveMatch, resolve } from './resolve.js';\nexport type {\n ColorFormat,\n ColorInput,\n ColorValue,\n DistanceMetric,\n HexColor,\n HslInput,\n HslObject,\n HslString,\n HsvInput,\n HsvObject,\n HsvString,\n NormalizeFn,\n Palette,\n Rgba,\n RgbaInput,\n RgbaString,\n RgbaTuple,\n RgbInput,\n RgbObject,\n RgbString,\n RgbTuple,\n} from './types.js';\nexport { COLOR_FORMATS } from './types.js';\n"]}
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export { rgbaToRgb, rgbToRgba } from './conversions/rgb.js';
|
|
|
8
8
|
export { convert, fromRgba, toRgba } from './convert.js';
|
|
9
9
|
export { detectFormat, isColor } from './detectFormat.js';
|
|
10
10
|
export { identify } from './identify.js';
|
|
11
|
+
export { crayola } from './palettes/crayola.js';
|
|
11
12
|
export { pantone } from './palettes/pantone.js';
|
|
12
13
|
export { web } from './palettes/web.js';
|
|
13
14
|
export { x11 } from './palettes/x11.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,sDAAsD;AAEtD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAuB,YAAY,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,sDAAsD;AAEtD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAuB,YAAY,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAsB,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAyB,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAyB,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAqB,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAqB,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAqB,OAAO,EAAE,MAAM,cAAc,CAAC;AAwB1D,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC","sourcesContent":["// Public API barrel — explicit named re-exports only (tree-shake friendly).\n// No default export; no side effects at module scope.\n\nexport { hexToRgba, rgbaToHex } from './conversions/hex.js';\nexport { hslToRgba, rgbaToHsl } from './conversions/hsl.js';\nexport { hsvToRgba, rgbaToHsv } from './conversions/hsv.js';\nexport { pantoneToRgba, rgbaToPantone } from './conversions/pantone.js';\nexport { rgbaToRgb, rgbToRgba } from './conversions/rgb.js';\nexport { convert, fromRgba, toRgba } from './convert.js';\nexport { type DetectedFormat, detectFormat, isColor } from './detectFormat.js';\nexport { type IdentifyMatch, identify } from './identify.js';\nexport { type CrayolaColorName, crayola } from './palettes/crayola.js';\nexport { type PantoneColorName, pantone } from './palettes/pantone.js';\nexport { type WebColorName, web } from './palettes/web.js';\nexport { type X11ColorName, x11 } from './palettes/x11.js';\nexport { type ResolveMatch, resolve } from './resolve.js';\nexport type {\n ColorFormat,\n ColorInput,\n ColorValue,\n DistanceMetric,\n HexColor,\n HslInput,\n HslObject,\n HslString,\n HsvInput,\n HsvObject,\n HsvString,\n NormalizeFn,\n Palette,\n Rgba,\n RgbaInput,\n RgbaString,\n RgbaTuple,\n RgbInput,\n RgbObject,\n RgbString,\n RgbTuple,\n} from './types.js';\nexport { COLOR_FORMATS } from './types.js';\n"]}
|