chromonym 1.4.1 → 2.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 -4
- package/README.md +216 -75
- package/dist/conversions/hex.d.ts +1 -1
- package/dist/conversions/hex.d.ts.map +1 -1
- package/dist/conversions/hex.js +2 -2
- package/dist/conversions/hex.js.map +1 -1
- package/dist/conversions/hsl.d.ts +1 -1
- package/dist/conversions/hsl.d.ts.map +1 -1
- package/dist/conversions/hsl.js +2 -2
- package/dist/conversions/hsl.js.map +1 -1
- package/dist/conversions/hsv.d.ts +1 -1
- package/dist/conversions/hsv.d.ts.map +1 -1
- package/dist/conversions/hsv.js +2 -2
- package/dist/conversions/hsv.js.map +1 -1
- package/dist/conversions/index.d.ts +5 -5
- package/dist/conversions/index.d.ts.map +1 -1
- package/dist/conversions/index.js +5 -5
- package/dist/conversions/index.js.map +1 -1
- package/dist/conversions/pantone.d.ts +9 -7
- package/dist/conversions/pantone.d.ts.map +1 -1
- package/dist/conversions/pantone.js +11 -10
- package/dist/conversions/pantone.js.map +1 -1
- package/dist/conversions/rgb.d.ts +1 -1
- package/dist/conversions/rgb.d.ts.map +1 -1
- package/dist/conversions/rgb.js +1 -1
- package/dist/conversions/rgb.js.map +1 -1
- package/dist/convert.d.ts +45 -5
- package/dist/convert.d.ts.map +1 -1
- package/dist/convert.js +68 -17
- package/dist/convert.js.map +1 -1
- package/dist/detectFormat.d.ts +1 -1
- package/dist/detectFormat.d.ts.map +1 -1
- package/dist/detectFormat.js +2 -6
- package/dist/detectFormat.js.map +1 -1
- package/dist/identify.d.ts +13 -16
- package/dist/identify.d.ts.map +1 -1
- package/dist/identify.js +12 -12
- package/dist/identify.js.map +1 -1
- package/dist/index.d.ts +14 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -13
- package/dist/index.js.map +1 -1
- package/dist/indexing.d.ts +30 -24
- package/dist/indexing.d.ts.map +1 -1
- package/dist/indexing.js +49 -22
- package/dist/indexing.js.map +1 -1
- package/dist/math/clamp.d.ts.map +1 -1
- package/dist/math/clamp.js.map +1 -1
- package/dist/math/colorSpace.d.ts +1 -1
- package/dist/math/colorSpace.d.ts.map +1 -1
- package/dist/math/colorSpace.js.map +1 -1
- package/dist/math/deltaE.d.ts.map +1 -1
- package/dist/math/deltaE.js.map +1 -1
- package/dist/math/euclideanDistance.d.ts +1 -1
- package/dist/math/euclideanDistance.d.ts.map +1 -1
- package/dist/math/euclideanDistance.js.map +1 -1
- package/dist/math/hueSector.d.ts.map +1 -1
- package/dist/math/hueSector.js.map +1 -1
- package/dist/palettes/index.d.ts +4 -0
- package/dist/palettes/index.d.ts.map +1 -0
- package/dist/palettes/index.js +4 -0
- package/dist/palettes/index.js.map +1 -0
- package/dist/palettes/normalize.d.ts +17 -0
- package/dist/palettes/normalize.d.ts.map +1 -0
- package/dist/palettes/normalize.js +19 -0
- package/dist/palettes/normalize.js.map +1 -0
- package/dist/palettes/pantone.d.ts +1834 -0
- package/dist/palettes/pantone.d.ts.map +1 -0
- package/dist/palettes/pantone.js +925 -0
- package/dist/palettes/pantone.js.map +1 -0
- package/dist/palettes/web.d.ts +320 -0
- package/dist/palettes/web.d.ts.map +1 -0
- package/dist/{colorspaces → palettes}/web.js +18 -3
- package/dist/palettes/web.js.map +1 -0
- package/dist/palettes/x11.d.ts +1346 -0
- package/dist/palettes/x11.d.ts.map +1 -0
- package/dist/palettes/x11.js +686 -0
- package/dist/palettes/x11.js.map +1 -0
- package/dist/resolve.d.ts +9 -7
- package/dist/resolve.d.ts.map +1 -1
- package/dist/resolve.js +18 -17
- package/dist/resolve.js.map +1 -1
- package/dist/types.d.ts +10 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -1
- package/dist/types.js.map +1 -1
- package/package.json +32 -18
- package/dist/colorspaces/index.d.ts +0 -4
- package/dist/colorspaces/index.d.ts.map +0 -1
- package/dist/colorspaces/index.js +0 -4
- package/dist/colorspaces/index.js.map +0 -1
- package/dist/colorspaces/pantone.d.ts +0 -919
- package/dist/colorspaces/pantone.d.ts.map +0 -1
- package/dist/colorspaces/pantone.js +0 -918
- package/dist/colorspaces/pantone.js.map +0 -1
- package/dist/colorspaces/registry.d.ts +0 -26
- package/dist/colorspaces/registry.d.ts.map +0 -1
- package/dist/colorspaces/registry.js +0 -36
- package/dist/colorspaces/registry.js.map +0 -1
- package/dist/colorspaces/web.d.ts +0 -156
- package/dist/colorspaces/web.d.ts.map +0 -1
- package/dist/colorspaces/web.js.map +0 -1
- package/dist/colorspaces/x11.d.ts +0 -667
- package/dist/colorspaces/x11.d.ts.map +0 -1
- package/dist/colorspaces/x11.js +0 -666
- package/dist/colorspaces/x11.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hsv.d.ts","sourceRoot":"","sources":["../../src/conversions/hsv.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"hsv.d.ts","sourceRoot":"","sources":["../../src/conversions/hsv.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAK7D;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CA+B/C;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,CAuB/C","sourcesContent":["import { requireFinite } from '../math/clamp.js';\nimport { hueSectorToPrime } from '../math/hueSector.js';\nimport type { HsvInput, HsvString, Rgba } from '../types.js';\n\nconst HSV_RE =\n /^hsv\\s*\\(\\s*(-?\\d+(?:\\.\\d+)?)\\s*,\\s*(-?\\d+(?:\\.\\d+)?)%?\\s*,\\s*(-?\\d+(?:\\.\\d+)?)%?\\s*\\)$/i;\n\n/**\n * Parse HSV input (string or object) into canonical Rgba.\n * Hue wraps modulo 360; saturation and value are 0..100 percent.\n */\nexport function hsvToRgba(input: HsvInput): Rgba {\n let h: number;\n let s: number;\n let v: number;\n\n if (typeof input === 'string') {\n const match = HSV_RE.exec(input);\n if (!match) throw new Error(`Invalid hsv string: ${input}`);\n h = Number(match[1]);\n s = Number(match[2]);\n v = Number(match[3]);\n } else {\n h = requireFinite(input.h, 'h');\n s = requireFinite(input.s, 's');\n v = requireFinite(input.v, 'v');\n }\n\n const saturation = s / 100;\n const value = v / 100;\n const chroma = value * saturation;\n const hueSector = (((h % 360) + 360) % 360) / 60;\n const secondary = chroma * (1 - Math.abs((hueSector % 2) - 1));\n const valueOffset = value - chroma;\n\n const [rPrime, gPrime, bPrime] = hueSectorToPrime(hueSector, chroma, secondary);\n return {\n r: Math.round((rPrime + valueOffset) * 255),\n g: Math.round((gPrime + valueOffset) * 255),\n b: Math.round((bPrime + valueOffset) * 255),\n a: 1,\n };\n}\n\n/**\n * Emit an `hsv(h, s%, v%)` string from Rgba. Alpha is dropped; all\n * three components are rounded to whole numbers.\n */\nexport function rgbaToHsv(rgba: Rgba): HsvString {\n const rNorm = rgba.r / 255;\n const gNorm = rgba.g / 255;\n const bNorm = rgba.b / 255;\n const max = Math.max(rNorm, gNorm, bNorm);\n const min = Math.min(rNorm, gNorm, bNorm);\n const delta = max - min;\n const value = max;\n const saturation = max === 0 ? 0 : delta / max;\n\n let hue = 0;\n if (delta !== 0) {\n if (max === rNorm) {\n hue = (gNorm - bNorm) / delta + (gNorm < bNorm ? 6 : 0);\n } else if (max === gNorm) {\n hue = (bNorm - rNorm) / delta + 2;\n } else {\n hue = (rNorm - gNorm) / delta + 4;\n }\n hue *= 60;\n }\n\n return `hsv(${Math.round(hue)}, ${Math.round(saturation * 100)}%, ${Math.round(value * 100)}%)` as HsvString;\n}\n"]}
|
package/dist/conversions/hsv.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { requireFinite } from '../math/clamp';
|
|
2
|
-
import { hueSectorToPrime } from '../math/hueSector';
|
|
1
|
+
import { requireFinite } from '../math/clamp.js';
|
|
2
|
+
import { hueSectorToPrime } from '../math/hueSector.js';
|
|
3
3
|
const HSV_RE = /^hsv\s*\(\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)%?\s*,\s*(-?\d+(?:\.\d+)?)%?\s*\)$/i;
|
|
4
4
|
/**
|
|
5
5
|
* Parse HSV input (string or object) into canonical Rgba.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hsv.js","sourceRoot":"","sources":["../../src/conversions/hsv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"hsv.js","sourceRoot":"","sources":["../../src/conversions/hsv.ts"],"names":[],"mappings":"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","sourcesContent":["import { requireFinite } from '../math/clamp.js';\nimport { hueSectorToPrime } from '../math/hueSector.js';\nimport type { HsvInput, HsvString, Rgba } from '../types.js';\n\nconst HSV_RE =\n /^hsv\\s*\\(\\s*(-?\\d+(?:\\.\\d+)?)\\s*,\\s*(-?\\d+(?:\\.\\d+)?)%?\\s*,\\s*(-?\\d+(?:\\.\\d+)?)%?\\s*\\)$/i;\n\n/**\n * Parse HSV input (string or object) into canonical Rgba.\n * Hue wraps modulo 360; saturation and value are 0..100 percent.\n */\nexport function hsvToRgba(input: HsvInput): Rgba {\n let h: number;\n let s: number;\n let v: number;\n\n if (typeof input === 'string') {\n const match = HSV_RE.exec(input);\n if (!match) throw new Error(`Invalid hsv string: ${input}`);\n h = Number(match[1]);\n s = Number(match[2]);\n v = Number(match[3]);\n } else {\n h = requireFinite(input.h, 'h');\n s = requireFinite(input.s, 's');\n v = requireFinite(input.v, 'v');\n }\n\n const saturation = s / 100;\n const value = v / 100;\n const chroma = value * saturation;\n const hueSector = (((h % 360) + 360) % 360) / 60;\n const secondary = chroma * (1 - Math.abs((hueSector % 2) - 1));\n const valueOffset = value - chroma;\n\n const [rPrime, gPrime, bPrime] = hueSectorToPrime(hueSector, chroma, secondary);\n return {\n r: Math.round((rPrime + valueOffset) * 255),\n g: Math.round((gPrime + valueOffset) * 255),\n b: Math.round((bPrime + valueOffset) * 255),\n a: 1,\n };\n}\n\n/**\n * Emit an `hsv(h, s%, v%)` string from Rgba. Alpha is dropped; all\n * three components are rounded to whole numbers.\n */\nexport function rgbaToHsv(rgba: Rgba): HsvString {\n const rNorm = rgba.r / 255;\n const gNorm = rgba.g / 255;\n const bNorm = rgba.b / 255;\n const max = Math.max(rNorm, gNorm, bNorm);\n const min = Math.min(rNorm, gNorm, bNorm);\n const delta = max - min;\n const value = max;\n const saturation = max === 0 ? 0 : delta / max;\n\n let hue = 0;\n if (delta !== 0) {\n if (max === rNorm) {\n hue = (gNorm - bNorm) / delta + (gNorm < bNorm ? 6 : 0);\n } else if (max === gNorm) {\n hue = (bNorm - rNorm) / delta + 2;\n } else {\n hue = (rNorm - gNorm) / delta + 4;\n }\n hue *= 60;\n }\n\n return `hsv(${Math.round(hue)}, ${Math.round(saturation * 100)}%, ${Math.round(value * 100)}%)` as HsvString;\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { hexToRgba, rgbaToHex } from './hex';
|
|
2
|
-
export { hslToRgba, rgbaToHsl } from './hsl';
|
|
3
|
-
export { hsvToRgba, rgbaToHsv } from './hsv';
|
|
4
|
-
export { pantoneToRgba, rgbaToPantone } from './pantone';
|
|
5
|
-
export { rgbaToRgb, rgbToRgba } from './rgb';
|
|
1
|
+
export { hexToRgba, rgbaToHex } from './hex.js';
|
|
2
|
+
export { hslToRgba, rgbaToHsl } from './hsl.js';
|
|
3
|
+
export { hsvToRgba, rgbaToHsv } from './hsv.js';
|
|
4
|
+
export { pantoneToRgba, rgbaToPantone } from './pantone.js';
|
|
5
|
+
export { rgbaToRgb, rgbToRgba } from './rgb.js';
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/conversions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/conversions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC","sourcesContent":["export { hexToRgba, rgbaToHex } from './hex.js';\nexport { hslToRgba, rgbaToHsl } from './hsl.js';\nexport { hsvToRgba, rgbaToHsv } from './hsv.js';\nexport { pantoneToRgba, rgbaToPantone } from './pantone.js';\nexport { rgbaToRgb, rgbToRgba } from './rgb.js';\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { hexToRgba, rgbaToHex } from './hex';
|
|
2
|
-
export { hslToRgba, rgbaToHsl } from './hsl';
|
|
3
|
-
export { hsvToRgba, rgbaToHsv } from './hsv';
|
|
4
|
-
export { pantoneToRgba, rgbaToPantone } from './pantone';
|
|
5
|
-
export { rgbaToRgb, rgbToRgba } from './rgb';
|
|
1
|
+
export { hexToRgba, rgbaToHex } from './hex.js';
|
|
2
|
+
export { hslToRgba, rgbaToHsl } from './hsl.js';
|
|
3
|
+
export { hsvToRgba, rgbaToHsv } from './hsv.js';
|
|
4
|
+
export { pantoneToRgba, rgbaToPantone } from './pantone.js';
|
|
5
|
+
export { rgbaToRgb, rgbToRgba } from './rgb.js';
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/conversions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/conversions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC","sourcesContent":["export { hexToRgba, rgbaToHex } from './hex.js';\nexport { hslToRgba, rgbaToHsl } from './hsl.js';\nexport { hsvToRgba, rgbaToHsv } from './hsv.js';\nexport { pantoneToRgba, rgbaToPantone } from './pantone.js';\nexport { rgbaToRgb, rgbToRgba } from './rgb.js';\n"]}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type PantoneColorName } from '../palettes/pantone.js';
|
|
2
|
+
import type { Rgba } from '../types.js';
|
|
2
3
|
/**
|
|
3
4
|
* Resolve a Pantone code to Rgba.
|
|
4
5
|
* Accepts any casing, spacing, and common prefixes ("PMS", "Pantone")
|
|
5
6
|
* since non-alphanumeric characters are stripped before lookup.
|
|
6
7
|
* Throws on unknown codes.
|
|
7
8
|
*/
|
|
8
|
-
export declare function pantoneToRgba(code:
|
|
9
|
+
export declare function pantoneToRgba(code: string): Rgba;
|
|
9
10
|
/**
|
|
10
|
-
* Find the nearest Pantone Coated code to the given Rgba. Uses
|
|
11
|
-
*
|
|
12
|
-
* Pantone values cluster densely
|
|
13
|
-
* sRGB Euclidean distance gives
|
|
11
|
+
* Find the nearest Pantone Coated code to the given Rgba. Uses the
|
|
12
|
+
* `pantone` palette's own `defaultMetric` (ΔE*00 / CIEDE2000) — the
|
|
13
|
+
* industry-standard perceptual metric, since Pantone values cluster densely
|
|
14
|
+
* in the saturated blue/purple region where sRGB Euclidean distance gives
|
|
15
|
+
* visually wrong answers.
|
|
14
16
|
* Alpha is ignored. Always returns a code.
|
|
15
17
|
*/
|
|
16
|
-
export declare function rgbaToPantone(rgba: Rgba):
|
|
18
|
+
export declare function rgbaToPantone(rgba: Rgba): PantoneColorName;
|
|
17
19
|
//# sourceMappingURL=pantone.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pantone.d.ts","sourceRoot":"","sources":["../../src/conversions/pantone.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pantone.d.ts","sourceRoot":"","sources":["../../src/conversions/pantone.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,gBAAgB,EAAW,MAAM,wBAAwB,CAAC;AACxE,OAAO,KAAK,EAAY,IAAI,EAAE,MAAM,aAAa,CAAC;AAGlD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAKhD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,gBAAgB,CAE1D","sourcesContent":["import { getNameIndex, nearest } from '../indexing.js';\nimport { type PantoneColorName, pantone } from '../palettes/pantone.js';\nimport type { HexColor, Rgba } from '../types.js';\nimport { hexToRgba } from './hex.js';\n\n/**\n * Resolve a Pantone code to Rgba.\n * Accepts any casing, spacing, and common prefixes (\"PMS\", \"Pantone\")\n * since non-alphanumeric characters are stripped before lookup.\n * Throws on unknown codes.\n */\nexport function pantoneToRgba(code: string): Rgba {\n const canonical = getNameIndex(pantone).get(pantone.normalize(code));\n if (canonical === undefined) throw new Error(`Unknown Pantone code: ${code}`);\n const hex = pantone.colors[canonical as keyof typeof pantone.colors];\n return hexToRgba(hex as HexColor);\n}\n\n/**\n * Find the nearest Pantone Coated code to the given Rgba. Uses the\n * `pantone` palette's own `defaultMetric` (ΔE*00 / CIEDE2000) — the\n * industry-standard perceptual metric, since Pantone values cluster densely\n * in the saturated blue/purple region where sRGB Euclidean distance gives\n * visually wrong answers.\n * Alpha is ignored. Always returns a code.\n */\nexport function rgbaToPantone(rgba: Rgba): PantoneColorName {\n return nearest(rgba, pantone, pantone.defaultMetric) as PantoneColorName;\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { hexToRgba } from './hex';
|
|
1
|
+
import { getNameIndex, nearest } from '../indexing.js';
|
|
2
|
+
import { pantone } from '../palettes/pantone.js';
|
|
3
|
+
import { hexToRgba } from './hex.js';
|
|
4
4
|
/**
|
|
5
5
|
* Resolve a Pantone code to Rgba.
|
|
6
6
|
* Accepts any casing, spacing, and common prefixes ("PMS", "Pantone")
|
|
@@ -8,20 +8,21 @@ import { hexToRgba } from './hex';
|
|
|
8
8
|
* Throws on unknown codes.
|
|
9
9
|
*/
|
|
10
10
|
export function pantoneToRgba(code) {
|
|
11
|
-
const canonical = getNameIndex(pantone
|
|
11
|
+
const canonical = getNameIndex(pantone).get(pantone.normalize(code));
|
|
12
12
|
if (canonical === undefined)
|
|
13
13
|
throw new Error(`Unknown Pantone code: ${code}`);
|
|
14
|
-
const hex = pantone[canonical];
|
|
14
|
+
const hex = pantone.colors[canonical];
|
|
15
15
|
return hexToRgba(hex);
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
* Find the nearest Pantone Coated code to the given Rgba. Uses
|
|
19
|
-
*
|
|
20
|
-
* Pantone values cluster densely
|
|
21
|
-
* sRGB Euclidean distance gives
|
|
18
|
+
* Find the nearest Pantone Coated code to the given Rgba. Uses the
|
|
19
|
+
* `pantone` palette's own `defaultMetric` (ΔE*00 / CIEDE2000) — the
|
|
20
|
+
* industry-standard perceptual metric, since Pantone values cluster densely
|
|
21
|
+
* in the saturated blue/purple region where sRGB Euclidean distance gives
|
|
22
|
+
* visually wrong answers.
|
|
22
23
|
* Alpha is ignored. Always returns a code.
|
|
23
24
|
*/
|
|
24
25
|
export function rgbaToPantone(rgba) {
|
|
25
|
-
return nearest(rgba, pantone,
|
|
26
|
+
return nearest(rgba, pantone, pantone.defaultMetric);
|
|
26
27
|
}
|
|
27
28
|
//# sourceMappingURL=pantone.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pantone.js","sourceRoot":"","sources":["../../src/conversions/pantone.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"pantone.js","sourceRoot":"","sources":["../../src/conversions/pantone.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAyB,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAExE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IACrE,IAAI,SAAS,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;IAC9E,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,SAAwC,CAAC,CAAC;IACrE,OAAO,SAAS,CAAC,GAAe,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,IAAU;IACtC,OAAO,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAqB,CAAC;AAC3E,CAAC","sourcesContent":["import { getNameIndex, nearest } from '../indexing.js';\nimport { type PantoneColorName, pantone } from '../palettes/pantone.js';\nimport type { HexColor, Rgba } from '../types.js';\nimport { hexToRgba } from './hex.js';\n\n/**\n * Resolve a Pantone code to Rgba.\n * Accepts any casing, spacing, and common prefixes (\"PMS\", \"Pantone\")\n * since non-alphanumeric characters are stripped before lookup.\n * Throws on unknown codes.\n */\nexport function pantoneToRgba(code: string): Rgba {\n const canonical = getNameIndex(pantone).get(pantone.normalize(code));\n if (canonical === undefined) throw new Error(`Unknown Pantone code: ${code}`);\n const hex = pantone.colors[canonical as keyof typeof pantone.colors];\n return hexToRgba(hex as HexColor);\n}\n\n/**\n * Find the nearest Pantone Coated code to the given Rgba. Uses the\n * `pantone` palette's own `defaultMetric` (ΔE*00 / CIEDE2000) — the\n * industry-standard perceptual metric, since Pantone values cluster densely\n * in the saturated blue/purple region where sRGB Euclidean distance gives\n * visually wrong answers.\n * Alpha is ignored. Always returns a code.\n */\nexport function rgbaToPantone(rgba: Rgba): PantoneColorName {\n return nearest(rgba, pantone, pantone.defaultMetric) as PantoneColorName;\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Rgba, RgbaInput, RgbInput, RgbString } from '../types';
|
|
1
|
+
import type { Rgba, RgbaInput, RgbInput, RgbString } from '../types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Normalize any RGB/RGBA input shape (string, tuple, or object) into
|
|
4
4
|
* the canonical Rgba representation. Alpha defaults to 1 when absent.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rgb.d.ts","sourceRoot":"","sources":["../../src/conversions/rgb.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAa,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"rgb.d.ts","sourceRoot":"","sources":["../../src/conversions/rgb.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAa,SAAS,EAAE,MAAM,aAAa,CAAC;AAanF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,IAAI,CA+B3D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,CAK/C","sourcesContent":["import { clamp, requireFinite } from '../math/clamp.js';\nimport type { Rgba, RgbaInput, RgbInput, RgbObject, RgbString } from '../types.js';\n\nconst RGB_RE =\n /^rgba?\\s*\\(\\s*(-?\\d+(?:\\.\\d+)?)\\s*,\\s*(-?\\d+(?:\\.\\d+)?)\\s*,\\s*(-?\\d+(?:\\.\\d+)?)\\s*(?:,\\s*(\\d*\\.?\\d+)\\s*)?\\)$/i;\n\nfunction sanitizeChannel(n: unknown, label: string): number {\n return clamp(requireFinite(n, label), 0, 255);\n}\n\nfunction sanitizeAlpha(n: unknown): number {\n return clamp(requireFinite(n, 'alpha'), 0, 1);\n}\n\n/**\n * Normalize any RGB/RGBA input shape (string, tuple, or object) into\n * the canonical Rgba representation. Alpha defaults to 1 when absent.\n * Rejects non-finite numeric inputs; clamps r/g/b to [0,255] and a to [0,1].\n * Throws on malformed strings.\n */\nexport function rgbToRgba(input: RgbInput | RgbaInput): Rgba {\n if (Array.isArray(input)) {\n const rawA = input.length === 4 ? input[3] : 1;\n return {\n r: sanitizeChannel(input[0], 'r'),\n g: sanitizeChannel(input[1], 'g'),\n b: sanitizeChannel(input[2], 'b'),\n a: sanitizeAlpha(rawA),\n };\n }\n\n if (typeof input === 'string') {\n const match = RGB_RE.exec(input);\n if (!match) throw new Error(`Invalid rgb(a) string: ${input}`);\n return {\n r: sanitizeChannel(Number(match[1]), 'r'),\n g: sanitizeChannel(Number(match[2]), 'g'),\n b: sanitizeChannel(Number(match[3]), 'b'),\n a: sanitizeAlpha(match[4] !== undefined ? Number(match[4]) : 1),\n };\n }\n\n // Object form — TypeScript's Array.isArray narrowing doesn't exclude\n // readonly tuple types from the union, so cast after the guards.\n const obj = input as RgbObject | Rgba;\n return {\n r: sanitizeChannel(obj.r, 'r'),\n g: sanitizeChannel(obj.g, 'g'),\n b: sanitizeChannel(obj.b, 'b'),\n a: sanitizeAlpha('a' in obj ? obj.a : 1),\n };\n}\n\n/**\n * Emit an `rgb(r, g, b)` string. Alpha is dropped; values are\n * already-clamped by rgbToRgba, but we re-clamp defensively for direct\n * Rgba-object callers who bypass the input normalizer.\n */\nexport function rgbaToRgb(rgba: Rgba): RgbString {\n const r = clamp(Math.round(rgba.r), 0, 255);\n const g = clamp(Math.round(rgba.g), 0, 255);\n const b = clamp(Math.round(rgba.b), 0, 255);\n return `rgb(${r}, ${g}, ${b})` as RgbString;\n}\n"]}
|
package/dist/conversions/rgb.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { clamp, requireFinite } from '../math/clamp';
|
|
1
|
+
import { clamp, requireFinite } from '../math/clamp.js';
|
|
2
2
|
const RGB_RE = /^rgba?\s*\(\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*(?:,\s*(\d*\.?\d+)\s*)?\)$/i;
|
|
3
3
|
function sanitizeChannel(n, label) {
|
|
4
4
|
return clamp(requireFinite(n, label), 0, 255);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rgb.js","sourceRoot":"","sources":["../../src/conversions/rgb.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"rgb.js","sourceRoot":"","sources":["../../src/conversions/rgb.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGxD,MAAM,MAAM,GACV,+GAA+G,CAAC;AAElH,SAAS,eAAe,CAAC,CAAU,EAAE,KAAa;IAChD,OAAO,KAAK,CAAC,aAAa,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,aAAa,CAAC,CAAU;IAC/B,OAAO,KAAK,CAAC,aAAa,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAChD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,KAA2B;IACnD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/C,OAAO;YACL,CAAC,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;YACjC,CAAC,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;YACjC,CAAC,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;YACjC,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC;SACvB,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,KAAK,EAAE,CAAC,CAAC;QAC/D,OAAO;YACL,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;YACzC,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;YACzC,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;YACzC,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAChE,CAAC;IACJ,CAAC;IAED,qEAAqE;IACrE,iEAAiE;IACjE,MAAM,GAAG,GAAG,KAAyB,CAAC;IACtC,OAAO;QACL,CAAC,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC;QAC9B,CAAC,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC;QAC9B,CAAC,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC;QAC9B,CAAC,EAAE,aAAa,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACzC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,IAAU;IAClC,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5C,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5C,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5C,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAgB,CAAC;AAC9C,CAAC","sourcesContent":["import { clamp, requireFinite } from '../math/clamp.js';\nimport type { Rgba, RgbaInput, RgbInput, RgbObject, RgbString } from '../types.js';\n\nconst RGB_RE =\n /^rgba?\\s*\\(\\s*(-?\\d+(?:\\.\\d+)?)\\s*,\\s*(-?\\d+(?:\\.\\d+)?)\\s*,\\s*(-?\\d+(?:\\.\\d+)?)\\s*(?:,\\s*(\\d*\\.?\\d+)\\s*)?\\)$/i;\n\nfunction sanitizeChannel(n: unknown, label: string): number {\n return clamp(requireFinite(n, label), 0, 255);\n}\n\nfunction sanitizeAlpha(n: unknown): number {\n return clamp(requireFinite(n, 'alpha'), 0, 1);\n}\n\n/**\n * Normalize any RGB/RGBA input shape (string, tuple, or object) into\n * the canonical Rgba representation. Alpha defaults to 1 when absent.\n * Rejects non-finite numeric inputs; clamps r/g/b to [0,255] and a to [0,1].\n * Throws on malformed strings.\n */\nexport function rgbToRgba(input: RgbInput | RgbaInput): Rgba {\n if (Array.isArray(input)) {\n const rawA = input.length === 4 ? input[3] : 1;\n return {\n r: sanitizeChannel(input[0], 'r'),\n g: sanitizeChannel(input[1], 'g'),\n b: sanitizeChannel(input[2], 'b'),\n a: sanitizeAlpha(rawA),\n };\n }\n\n if (typeof input === 'string') {\n const match = RGB_RE.exec(input);\n if (!match) throw new Error(`Invalid rgb(a) string: ${input}`);\n return {\n r: sanitizeChannel(Number(match[1]), 'r'),\n g: sanitizeChannel(Number(match[2]), 'g'),\n b: sanitizeChannel(Number(match[3]), 'b'),\n a: sanitizeAlpha(match[4] !== undefined ? Number(match[4]) : 1),\n };\n }\n\n // Object form — TypeScript's Array.isArray narrowing doesn't exclude\n // readonly tuple types from the union, so cast after the guards.\n const obj = input as RgbObject | Rgba;\n return {\n r: sanitizeChannel(obj.r, 'r'),\n g: sanitizeChannel(obj.g, 'g'),\n b: sanitizeChannel(obj.b, 'b'),\n a: sanitizeAlpha('a' in obj ? obj.a : 1),\n };\n}\n\n/**\n * Emit an `rgb(r, g, b)` string. Alpha is dropped; values are\n * already-clamped by rgbToRgba, but we re-clamp defensively for direct\n * Rgba-object callers who bypass the input normalizer.\n */\nexport function rgbaToRgb(rgba: Rgba): RgbString {\n const r = clamp(Math.round(rgba.r), 0, 255);\n const g = clamp(Math.round(rgba.g), 0, 255);\n const b = clamp(Math.round(rgba.b), 0, 255);\n return `rgb(${r}, ${g}, ${b})` as RgbString;\n}\n"]}
|
package/dist/convert.d.ts
CHANGED
|
@@ -1,21 +1,61 @@
|
|
|
1
|
-
import { type DetectedFormat } from './detectFormat';
|
|
2
|
-
import type { ColorFormat, ColorInput, ColorValue, Rgba } from './types';
|
|
1
|
+
import { type DetectedFormat } from './detectFormat.js';
|
|
2
|
+
import type { ColorFormat, ColorInput, ColorValue, Palette, Rgba } from './types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Normalize any recognized color input to canonical `Rgba`.
|
|
5
5
|
* Pass `knownFormat` when the caller has already run `detectFormat` to skip
|
|
6
6
|
* the redundant detection. Throws on `UNKNOWN` input.
|
|
7
|
+
*
|
|
8
|
+
* Palette names (Pantone codes, BYO keys) are not accepted here — they
|
|
9
|
+
* require palette data to parse. Use `convert(name, { palette })` or
|
|
10
|
+
* `resolve(name, { palette })` at the higher level.
|
|
7
11
|
*/
|
|
8
12
|
export declare function toRgba(input: ColorInput, knownFormat?: DetectedFormat): Rgba;
|
|
9
13
|
/**
|
|
10
|
-
* Emit a canonical `Rgba` in the target format.
|
|
14
|
+
* Emit a canonical `Rgba` in the target structural format. Palette-independent.
|
|
15
|
+
*
|
|
16
|
+
* For palette-key output (e.g. nearest Pantone code, brand name), use
|
|
17
|
+
* `convert(rgba, { format: 'NAME', palette })` — or `identify` for fuzzy,
|
|
18
|
+
* `rgbaToPantone` for the low-level Pantone-only path.
|
|
11
19
|
*/
|
|
12
20
|
export declare function fromRgba(rgba: Rgba, format?: ColorFormat): ColorValue;
|
|
21
|
+
/**
|
|
22
|
+
* Extract string keys from a Palette's `colors` map.
|
|
23
|
+
* Matches the `PaletteKey<P>` helper in `identify.ts` — kept local so
|
|
24
|
+
* `convert` doesn't depend on `identify`.
|
|
25
|
+
*/
|
|
26
|
+
type PaletteKey<P extends Palette> = Extract<keyof P['colors'], string>;
|
|
13
27
|
/**
|
|
14
28
|
* Detect the input color format, normalize to Rgba, and emit the result
|
|
15
|
-
* in the requested output format.
|
|
16
|
-
*
|
|
29
|
+
* in the requested output format.
|
|
30
|
+
*
|
|
31
|
+
* Without a `palette` option, `convert` is strictly structural —
|
|
32
|
+
* HEX ↔ RGB ↔ RGBA ↔ HSL ↔ HSV, no palette data ever touched, tree-shakes
|
|
33
|
+
* to the bone.
|
|
34
|
+
*
|
|
35
|
+
* With a `palette` option, `convert` understands the palette's naming
|
|
36
|
+
* scheme both ways:
|
|
37
|
+
* - Input can be a palette name (`'185 C'`, `'Acme Red'`) — parsed via
|
|
38
|
+
* `palette.normalize` and looked up in `palette.colors`.
|
|
39
|
+
* - Output can be `format: 'NAME'` — the exact canonical key from
|
|
40
|
+
* `palette.colors`, throws if the color isn't a pixel-exact match (use
|
|
41
|
+
* `identify` for nearest-match).
|
|
42
|
+
*
|
|
43
|
+
* The palette data comes from the caller's own import, so tree-shaking
|
|
44
|
+
* is preserved: callers who don't pass `palette` never pull a palette.
|
|
45
|
+
*
|
|
46
|
+
* Throws on unrecognized input (parser-flavored — `identify`/`resolve`
|
|
47
|
+
* are the `null`-returning alternatives).
|
|
17
48
|
*/
|
|
18
49
|
export declare function convert(input: ColorInput, opts?: {
|
|
19
50
|
format?: ColorFormat;
|
|
20
51
|
}): ColorValue;
|
|
52
|
+
export declare function convert<P extends Palette>(input: ColorInput | string, opts: {
|
|
53
|
+
palette: P;
|
|
54
|
+
format: 'NAME';
|
|
55
|
+
}): PaletteKey<P>;
|
|
56
|
+
export declare function convert<P extends Palette>(input: ColorInput | string, opts: {
|
|
57
|
+
palette: P;
|
|
58
|
+
format?: ColorFormat;
|
|
59
|
+
}): ColorValue;
|
|
60
|
+
export {};
|
|
21
61
|
//# sourceMappingURL=convert.d.ts.map
|
package/dist/convert.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,cAAc,EAAgB,MAAM,mBAAmB,CAAC;AAEtE,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,UAAU,EAIV,OAAO,EACP,IAAI,EAGL,MAAM,YAAY,CAAC;AAYpB;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,cAAc,GAAG,IAAI,CAgB5E;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,GAAE,WAAmB,GAAG,UAAU,CAqB5E;AAED;;;;GAIG;AACH,KAAK,UAAU,CAAC,CAAC,SAAS,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,wBAAgB,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,GAAG,UAAU,CAAC;AAGxF,wBAAgB,OAAO,CAAC,CAAC,SAAS,OAAO,EACvC,KAAK,EAAE,UAAU,GAAG,MAAM,EAC1B,IAAI,EAAE;IAAE,OAAO,EAAE,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnC,UAAU,CAAC,CAAC,CAAC,CAAC;AAGjB,wBAAgB,OAAO,CAAC,CAAC,SAAS,OAAO,EACvC,KAAK,EAAE,UAAU,GAAG,MAAM,EAC1B,IAAI,EAAE;IAAE,OAAO,EAAE,CAAC,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,GACzC,UAAU,CAAC","sourcesContent":["import { hexToRgba, rgbaToHex } from './conversions/hex.js';\nimport { hslToRgba, rgbaToHsl } from './conversions/hsl.js';\nimport { hsvToRgba, rgbaToHsv } from './conversions/hsv.js';\nimport { rgbaToRgb, rgbToRgba } from './conversions/rgb.js';\nimport { type DetectedFormat, detectFormat } from './detectFormat.js';\nimport { getNameIndex, getReverseNameIndex } from './indexing.js';\nimport type {\n ColorFormat,\n ColorInput,\n ColorValue,\n HexColor,\n HslInput,\n HsvInput,\n Palette,\n Rgba,\n RgbaInput,\n RgbInput,\n} from './types.js';\n\nfunction safeStringify(x: unknown): string {\n if (x === undefined) return 'undefined';\n try {\n const s = JSON.stringify(x);\n return s === undefined ? String(x) : s;\n } catch {\n return Object.prototype.toString.call(x);\n }\n}\n\n/**\n * Normalize any recognized color input to canonical `Rgba`.\n * Pass `knownFormat` when the caller has already run `detectFormat` to skip\n * the redundant detection. Throws on `UNKNOWN` input.\n *\n * Palette names (Pantone codes, BYO keys) are not accepted here — they\n * require palette data to parse. Use `convert(name, { palette })` or\n * `resolve(name, { palette })` at the higher level.\n */\nexport function toRgba(input: ColorInput, knownFormat?: DetectedFormat): Rgba {\n const format = knownFormat ?? detectFormat(input);\n switch (format) {\n case 'HEX':\n return hexToRgba(input as HexColor);\n case 'RGB':\n return rgbToRgba(input as RgbInput);\n case 'RGBA':\n return rgbToRgba(input as RgbaInput);\n case 'HSL':\n return hslToRgba(input as HslInput);\n case 'HSV':\n return hsvToRgba(input as HsvInput);\n default:\n throw new Error(`Unrecognized color input: ${safeStringify(input)}`);\n }\n}\n\n/**\n * Emit a canonical `Rgba` in the target structural format. Palette-independent.\n *\n * For palette-key output (e.g. nearest Pantone code, brand name), use\n * `convert(rgba, { format: 'NAME', palette })` — or `identify` for fuzzy,\n * `rgbaToPantone` for the low-level Pantone-only path.\n */\nexport function fromRgba(rgba: Rgba, format: ColorFormat = 'HEX'): ColorValue {\n switch (format) {\n case 'HEX':\n return rgbaToHex(rgba);\n case 'RGB':\n return rgbaToRgb(rgba);\n case 'RGBA':\n return rgba;\n case 'HSL':\n return rgbaToHsl(rgba);\n case 'HSV':\n return rgbaToHsv(rgba);\n default: {\n // Runtime safety for JS callers bypassing the ColorFormat union.\n const hint =\n format === ('PANTONE' as unknown)\n ? ` — use convert(rgba, { palette: pantone, format: 'NAME' }) or rgbaToPantone from 'chromonym/conversions/pantone'`\n : '';\n throw new Error(`Unsupported format: ${safeStringify(format)}${hint}`);\n }\n }\n}\n\n/**\n * Extract string keys from a Palette's `colors` map.\n * Matches the `PaletteKey<P>` helper in `identify.ts` — kept local so\n * `convert` doesn't depend on `identify`.\n */\ntype PaletteKey<P extends Palette> = Extract<keyof P['colors'], string>;\n\n/**\n * Detect the input color format, normalize to Rgba, and emit the result\n * in the requested output format.\n *\n * Without a `palette` option, `convert` is strictly structural —\n * HEX ↔ RGB ↔ RGBA ↔ HSL ↔ HSV, no palette data ever touched, tree-shakes\n * to the bone.\n *\n * With a `palette` option, `convert` understands the palette's naming\n * scheme both ways:\n * - Input can be a palette name (`'185 C'`, `'Acme Red'`) — parsed via\n * `palette.normalize` and looked up in `palette.colors`.\n * - Output can be `format: 'NAME'` — the exact canonical key from\n * `palette.colors`, throws if the color isn't a pixel-exact match (use\n * `identify` for nearest-match).\n *\n * The palette data comes from the caller's own import, so tree-shaking\n * is preserved: callers who don't pass `palette` never pull a palette.\n *\n * Throws on unrecognized input (parser-flavored — `identify`/`resolve`\n * are the `null`-returning alternatives).\n */\n\n// Overload 1: no palette — structural only. Input is strictly ColorInput.\nexport function convert(input: ColorInput, opts?: { format?: ColorFormat }): ColorValue;\n\n// Overload 2: palette present, format 'NAME' — returns a palette key.\nexport function convert<P extends Palette>(\n input: ColorInput | string,\n opts: { palette: P; format: 'NAME' },\n): PaletteKey<P>;\n\n// Overload 3: palette present, structural format — returns ColorValue.\nexport function convert<P extends Palette>(\n input: ColorInput | string,\n opts: { palette: P; format?: ColorFormat },\n): ColorValue;\n\n// Implementation\nexport function convert(\n input: ColorInput | string,\n opts: { format?: ColorFormat | 'NAME'; palette?: Palette } = {},\n): ColorValue | string {\n const { format = 'HEX', palette } = opts;\n\n // --- Parse input → Rgba ---\n // Structural detection first; palette lookup only as a fallback. This\n // way `convert('#ff0000', { palette: brand })` always means \"parse hex,\"\n // even if the brand palette happens to have a key that normalizes to\n // \"ff0000\".\n const detected = detectFormat(input as ColorInput);\n let rgba: Rgba;\n if (detected !== 'UNKNOWN') {\n rgba = toRgba(input as ColorInput, detected);\n } else if (palette !== undefined && typeof input === 'string') {\n const canonical = getNameIndex(palette).get(palette.normalize(input));\n if (canonical === undefined) {\n throw new Error(\n `Unrecognized color input: ${safeStringify(input)} (not structural, and not found in palette '${palette.name}')`,\n );\n }\n const hex = (palette.colors as Record<string, HexColor>)[canonical];\n if (hex === undefined) {\n throw new Error(`Unrecognized color input: ${safeStringify(input)}`);\n }\n rgba = hexToRgba(hex);\n } else {\n throw new Error(`Unrecognized color input: ${safeStringify(input)}`);\n }\n\n // --- Emit ---\n if (format === 'NAME') {\n if (palette === undefined) {\n throw new Error(`convert(_, { format: 'NAME' }) requires a 'palette' option`);\n }\n // Palette colors are alpha = 1 by construction; a partially-transparent\n // input isn't \"that named color\" in the strict-convert sense. Reject\n // here rather than silently drop alpha during the reverse lookup.\n if (rgba.a !== 1) {\n throw new Error(\n `format: 'NAME' requires fully-opaque input (a === 1). Got a=${rgba.a}. ` +\n `Strip alpha first or use identify() for fuzzy matching.`,\n );\n }\n const hex = rgbaToHex(rgba).toLowerCase();\n const name = getReverseNameIndex(palette).get(hex);\n if (name === undefined) {\n throw new Error(\n `No exact match for ${hex} in palette '${palette.name}'. Use identify() for nearest-match semantics.`,\n );\n }\n return name;\n }\n return fromRgba(rgba, format);\n}\n"]}
|
package/dist/convert.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { hexToRgba, rgbaToHex } from './conversions/hex';
|
|
2
|
-
import { hslToRgba, rgbaToHsl } from './conversions/hsl';
|
|
3
|
-
import { hsvToRgba, rgbaToHsv } from './conversions/hsv';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { hexToRgba, rgbaToHex } from './conversions/hex.js';
|
|
2
|
+
import { hslToRgba, rgbaToHsl } from './conversions/hsl.js';
|
|
3
|
+
import { hsvToRgba, rgbaToHsv } from './conversions/hsv.js';
|
|
4
|
+
import { rgbaToRgb, rgbToRgba } from './conversions/rgb.js';
|
|
5
|
+
import { detectFormat } from './detectFormat.js';
|
|
6
|
+
import { getNameIndex, getReverseNameIndex } from './indexing.js';
|
|
7
7
|
function safeStringify(x) {
|
|
8
8
|
if (x === undefined)
|
|
9
9
|
return 'undefined';
|
|
@@ -19,6 +19,10 @@ function safeStringify(x) {
|
|
|
19
19
|
* Normalize any recognized color input to canonical `Rgba`.
|
|
20
20
|
* Pass `knownFormat` when the caller has already run `detectFormat` to skip
|
|
21
21
|
* the redundant detection. Throws on `UNKNOWN` input.
|
|
22
|
+
*
|
|
23
|
+
* Palette names (Pantone codes, BYO keys) are not accepted here — they
|
|
24
|
+
* require palette data to parse. Use `convert(name, { palette })` or
|
|
25
|
+
* `resolve(name, { palette })` at the higher level.
|
|
22
26
|
*/
|
|
23
27
|
export function toRgba(input, knownFormat) {
|
|
24
28
|
const format = knownFormat ?? detectFormat(input);
|
|
@@ -33,14 +37,16 @@ export function toRgba(input, knownFormat) {
|
|
|
33
37
|
return hslToRgba(input);
|
|
34
38
|
case 'HSV':
|
|
35
39
|
return hsvToRgba(input);
|
|
36
|
-
case 'PANTONE':
|
|
37
|
-
return pantoneToRgba(input);
|
|
38
40
|
default:
|
|
39
41
|
throw new Error(`Unrecognized color input: ${safeStringify(input)}`);
|
|
40
42
|
}
|
|
41
43
|
}
|
|
42
44
|
/**
|
|
43
|
-
* Emit a canonical `Rgba` in the target format.
|
|
45
|
+
* Emit a canonical `Rgba` in the target structural format. Palette-independent.
|
|
46
|
+
*
|
|
47
|
+
* For palette-key output (e.g. nearest Pantone code, brand name), use
|
|
48
|
+
* `convert(rgba, { format: 'NAME', palette })` — or `identify` for fuzzy,
|
|
49
|
+
* `rgbaToPantone` for the low-level Pantone-only path.
|
|
44
50
|
*/
|
|
45
51
|
export function fromRgba(rgba, format = 'HEX') {
|
|
46
52
|
switch (format) {
|
|
@@ -54,16 +60,61 @@ export function fromRgba(rgba, format = 'HEX') {
|
|
|
54
60
|
return rgbaToHsl(rgba);
|
|
55
61
|
case 'HSV':
|
|
56
62
|
return rgbaToHsv(rgba);
|
|
57
|
-
|
|
58
|
-
|
|
63
|
+
default: {
|
|
64
|
+
// Runtime safety for JS callers bypassing the ColorFormat union.
|
|
65
|
+
const hint = format === 'PANTONE'
|
|
66
|
+
? ` — use convert(rgba, { palette: pantone, format: 'NAME' }) or rgbaToPantone from 'chromonym/conversions/pantone'`
|
|
67
|
+
: '';
|
|
68
|
+
throw new Error(`Unsupported format: ${safeStringify(format)}${hint}`);
|
|
69
|
+
}
|
|
59
70
|
}
|
|
60
71
|
}
|
|
61
|
-
|
|
62
|
-
* Detect the input color format, normalize to Rgba, and emit the result
|
|
63
|
-
* in the requested output format. Colorspace-independent.
|
|
64
|
-
* Throws if the input isn't a recognized color shape.
|
|
65
|
-
*/
|
|
72
|
+
// Implementation
|
|
66
73
|
export function convert(input, opts = {}) {
|
|
67
|
-
|
|
74
|
+
const { format = 'HEX', palette } = opts;
|
|
75
|
+
// --- Parse input → Rgba ---
|
|
76
|
+
// Structural detection first; palette lookup only as a fallback. This
|
|
77
|
+
// way `convert('#ff0000', { palette: brand })` always means "parse hex,"
|
|
78
|
+
// even if the brand palette happens to have a key that normalizes to
|
|
79
|
+
// "ff0000".
|
|
80
|
+
const detected = detectFormat(input);
|
|
81
|
+
let rgba;
|
|
82
|
+
if (detected !== 'UNKNOWN') {
|
|
83
|
+
rgba = toRgba(input, detected);
|
|
84
|
+
}
|
|
85
|
+
else if (palette !== undefined && typeof input === 'string') {
|
|
86
|
+
const canonical = getNameIndex(palette).get(palette.normalize(input));
|
|
87
|
+
if (canonical === undefined) {
|
|
88
|
+
throw new Error(`Unrecognized color input: ${safeStringify(input)} (not structural, and not found in palette '${palette.name}')`);
|
|
89
|
+
}
|
|
90
|
+
const hex = palette.colors[canonical];
|
|
91
|
+
if (hex === undefined) {
|
|
92
|
+
throw new Error(`Unrecognized color input: ${safeStringify(input)}`);
|
|
93
|
+
}
|
|
94
|
+
rgba = hexToRgba(hex);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
throw new Error(`Unrecognized color input: ${safeStringify(input)}`);
|
|
98
|
+
}
|
|
99
|
+
// --- Emit ---
|
|
100
|
+
if (format === 'NAME') {
|
|
101
|
+
if (palette === undefined) {
|
|
102
|
+
throw new Error(`convert(_, { format: 'NAME' }) requires a 'palette' option`);
|
|
103
|
+
}
|
|
104
|
+
// Palette colors are alpha = 1 by construction; a partially-transparent
|
|
105
|
+
// input isn't "that named color" in the strict-convert sense. Reject
|
|
106
|
+
// here rather than silently drop alpha during the reverse lookup.
|
|
107
|
+
if (rgba.a !== 1) {
|
|
108
|
+
throw new Error(`format: 'NAME' requires fully-opaque input (a === 1). Got a=${rgba.a}. ` +
|
|
109
|
+
`Strip alpha first or use identify() for fuzzy matching.`);
|
|
110
|
+
}
|
|
111
|
+
const hex = rgbaToHex(rgba).toLowerCase();
|
|
112
|
+
const name = getReverseNameIndex(palette).get(hex);
|
|
113
|
+
if (name === undefined) {
|
|
114
|
+
throw new Error(`No exact match for ${hex} in palette '${palette.name}'. Use identify() for nearest-match semantics.`);
|
|
115
|
+
}
|
|
116
|
+
return name;
|
|
117
|
+
}
|
|
118
|
+
return fromRgba(rgba, format);
|
|
68
119
|
}
|
|
69
120
|
//# sourceMappingURL=convert.js.map
|
package/dist/convert.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert.js","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAuB,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAcnE,SAAS,aAAa,CAAC,CAAU;IAC/B,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,WAAW,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAC5B,OAAO,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,KAAiB,EAAE,WAA4B;IACpE,MAAM,MAAM,GAAG,WAAW,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC;IAClD,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,KAAK;YACR,OAAO,SAAS,CAAC,KAAiB,CAAC,CAAC;QACtC,KAAK,KAAK;YACR,OAAO,SAAS,CAAC,KAAiB,CAAC,CAAC;QACtC,KAAK,MAAM;YACT,OAAO,SAAS,CAAC,KAAkB,CAAC,CAAC;QACvC,KAAK,KAAK;YACR,OAAO,SAAS,CAAC,KAAiB,CAAC,CAAC;QACtC,KAAK,KAAK;YACR,OAAO,SAAS,CAAC,KAAiB,CAAC,CAAC;QACtC,KAAK,SAAS;YACZ,OAAO,aAAa,CAAC,KAAoB,CAAC,CAAC;QAC7C;YACE,MAAM,IAAI,KAAK,CAAC,6BAA6B,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACzE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAU,EAAE,MAAM,GAAgB,KAAK;IAC9D,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,KAAK;YACR,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;QACzB,KAAK,KAAK;YACR,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;QACzB,KAAK,MAAM;YACT,OAAO,IAAI,CAAC;QACd,KAAK,KAAK;YACR,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;QACzB,KAAK,KAAK;YACR,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;QACzB,KAAK,SAAS;YACZ,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,KAAiB,EAAE,IAAI,GAA6B,EAAE;IAC5E,OAAO,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC;AACvD,CAAC"}
|
|
1
|
+
{"version":3,"file":"convert.js","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"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","sourcesContent":["import { hexToRgba, rgbaToHex } from './conversions/hex.js';\nimport { hslToRgba, rgbaToHsl } from './conversions/hsl.js';\nimport { hsvToRgba, rgbaToHsv } from './conversions/hsv.js';\nimport { rgbaToRgb, rgbToRgba } from './conversions/rgb.js';\nimport { type DetectedFormat, detectFormat } from './detectFormat.js';\nimport { getNameIndex, getReverseNameIndex } from './indexing.js';\nimport type {\n ColorFormat,\n ColorInput,\n ColorValue,\n HexColor,\n HslInput,\n HsvInput,\n Palette,\n Rgba,\n RgbaInput,\n RgbInput,\n} from './types.js';\n\nfunction safeStringify(x: unknown): string {\n if (x === undefined) return 'undefined';\n try {\n const s = JSON.stringify(x);\n return s === undefined ? String(x) : s;\n } catch {\n return Object.prototype.toString.call(x);\n }\n}\n\n/**\n * Normalize any recognized color input to canonical `Rgba`.\n * Pass `knownFormat` when the caller has already run `detectFormat` to skip\n * the redundant detection. Throws on `UNKNOWN` input.\n *\n * Palette names (Pantone codes, BYO keys) are not accepted here — they\n * require palette data to parse. Use `convert(name, { palette })` or\n * `resolve(name, { palette })` at the higher level.\n */\nexport function toRgba(input: ColorInput, knownFormat?: DetectedFormat): Rgba {\n const format = knownFormat ?? detectFormat(input);\n switch (format) {\n case 'HEX':\n return hexToRgba(input as HexColor);\n case 'RGB':\n return rgbToRgba(input as RgbInput);\n case 'RGBA':\n return rgbToRgba(input as RgbaInput);\n case 'HSL':\n return hslToRgba(input as HslInput);\n case 'HSV':\n return hsvToRgba(input as HsvInput);\n default:\n throw new Error(`Unrecognized color input: ${safeStringify(input)}`);\n }\n}\n\n/**\n * Emit a canonical `Rgba` in the target structural format. Palette-independent.\n *\n * For palette-key output (e.g. nearest Pantone code, brand name), use\n * `convert(rgba, { format: 'NAME', palette })` — or `identify` for fuzzy,\n * `rgbaToPantone` for the low-level Pantone-only path.\n */\nexport function fromRgba(rgba: Rgba, format: ColorFormat = 'HEX'): ColorValue {\n switch (format) {\n case 'HEX':\n return rgbaToHex(rgba);\n case 'RGB':\n return rgbaToRgb(rgba);\n case 'RGBA':\n return rgba;\n case 'HSL':\n return rgbaToHsl(rgba);\n case 'HSV':\n return rgbaToHsv(rgba);\n default: {\n // Runtime safety for JS callers bypassing the ColorFormat union.\n const hint =\n format === ('PANTONE' as unknown)\n ? ` — use convert(rgba, { palette: pantone, format: 'NAME' }) or rgbaToPantone from 'chromonym/conversions/pantone'`\n : '';\n throw new Error(`Unsupported format: ${safeStringify(format)}${hint}`);\n }\n }\n}\n\n/**\n * Extract string keys from a Palette's `colors` map.\n * Matches the `PaletteKey<P>` helper in `identify.ts` — kept local so\n * `convert` doesn't depend on `identify`.\n */\ntype PaletteKey<P extends Palette> = Extract<keyof P['colors'], string>;\n\n/**\n * Detect the input color format, normalize to Rgba, and emit the result\n * in the requested output format.\n *\n * Without a `palette` option, `convert` is strictly structural —\n * HEX ↔ RGB ↔ RGBA ↔ HSL ↔ HSV, no palette data ever touched, tree-shakes\n * to the bone.\n *\n * With a `palette` option, `convert` understands the palette's naming\n * scheme both ways:\n * - Input can be a palette name (`'185 C'`, `'Acme Red'`) — parsed via\n * `palette.normalize` and looked up in `palette.colors`.\n * - Output can be `format: 'NAME'` — the exact canonical key from\n * `palette.colors`, throws if the color isn't a pixel-exact match (use\n * `identify` for nearest-match).\n *\n * The palette data comes from the caller's own import, so tree-shaking\n * is preserved: callers who don't pass `palette` never pull a palette.\n *\n * Throws on unrecognized input (parser-flavored — `identify`/`resolve`\n * are the `null`-returning alternatives).\n */\n\n// Overload 1: no palette — structural only. Input is strictly ColorInput.\nexport function convert(input: ColorInput, opts?: { format?: ColorFormat }): ColorValue;\n\n// Overload 2: palette present, format 'NAME' — returns a palette key.\nexport function convert<P extends Palette>(\n input: ColorInput | string,\n opts: { palette: P; format: 'NAME' },\n): PaletteKey<P>;\n\n// Overload 3: palette present, structural format — returns ColorValue.\nexport function convert<P extends Palette>(\n input: ColorInput | string,\n opts: { palette: P; format?: ColorFormat },\n): ColorValue;\n\n// Implementation\nexport function convert(\n input: ColorInput | string,\n opts: { format?: ColorFormat | 'NAME'; palette?: Palette } = {},\n): ColorValue | string {\n const { format = 'HEX', palette } = opts;\n\n // --- Parse input → Rgba ---\n // Structural detection first; palette lookup only as a fallback. This\n // way `convert('#ff0000', { palette: brand })` always means \"parse hex,\"\n // even if the brand palette happens to have a key that normalizes to\n // \"ff0000\".\n const detected = detectFormat(input as ColorInput);\n let rgba: Rgba;\n if (detected !== 'UNKNOWN') {\n rgba = toRgba(input as ColorInput, detected);\n } else if (palette !== undefined && typeof input === 'string') {\n const canonical = getNameIndex(palette).get(palette.normalize(input));\n if (canonical === undefined) {\n throw new Error(\n `Unrecognized color input: ${safeStringify(input)} (not structural, and not found in palette '${palette.name}')`,\n );\n }\n const hex = (palette.colors as Record<string, HexColor>)[canonical];\n if (hex === undefined) {\n throw new Error(`Unrecognized color input: ${safeStringify(input)}`);\n }\n rgba = hexToRgba(hex);\n } else {\n throw new Error(`Unrecognized color input: ${safeStringify(input)}`);\n }\n\n // --- Emit ---\n if (format === 'NAME') {\n if (palette === undefined) {\n throw new Error(`convert(_, { format: 'NAME' }) requires a 'palette' option`);\n }\n // Palette colors are alpha = 1 by construction; a partially-transparent\n // input isn't \"that named color\" in the strict-convert sense. Reject\n // here rather than silently drop alpha during the reverse lookup.\n if (rgba.a !== 1) {\n throw new Error(\n `format: 'NAME' requires fully-opaque input (a === 1). Got a=${rgba.a}. ` +\n `Strip alpha first or use identify() for fuzzy matching.`,\n );\n }\n const hex = rgbaToHex(rgba).toLowerCase();\n const name = getReverseNameIndex(palette).get(hex);\n if (name === undefined) {\n throw new Error(\n `No exact match for ${hex} in palette '${palette.name}'. Use identify() for nearest-match semantics.`,\n );\n }\n return name;\n }\n return fromRgba(rgba, format);\n}\n"]}
|
package/dist/detectFormat.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detectFormat.d.ts","sourceRoot":"","sources":["../src/detectFormat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"detectFormat.d.ts","sourceRoot":"","sources":["../src/detectFormat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE1D;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,SAAS,CAAC;AAErD,kGAAkG;AAClG,eAAO,MAAM,MAAM,QAA8C,CAAC;AAMlE;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAE3D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,cAAc,CA8B9D","sourcesContent":["import type { ColorFormat, ColorInput } from './types.js';\n\n/**\n * A color comes in, a format key comes out.\n * 'UNKNOWN' signals the caller that the input isn't a recognized color shape.\n * Used as the dispatch key for format-specific converters.\n */\nexport type DetectedFormat = ColorFormat | 'UNKNOWN';\n\n/** Shared with `src/conversions/hex.ts`. Capture group is used there; .test() ignores it here. */\nexport const HEX_RE = /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i;\nconst RGBA_STR_RE = /^rgba\\s*\\(/i;\nconst RGB_STR_RE = /^rgb\\s*\\(/i;\nconst HSL_STR_RE = /^hsl\\s*\\(/i;\nconst HSV_STR_RE = /^hsv\\s*\\(/i;\n\n/**\n * Runtime type-guard — returns `true` if `input` looks like something any of\n * chromonym's converters can parse. Cheaper than catching a `convert` throw\n * and more ergonomic than hand-rolling `detectFormat(x) !== 'UNKNOWN'`.\n */\nexport function isColor(input: unknown): input is ColorInput {\n return detectFormat(input as ColorInput) !== 'UNKNOWN';\n}\n\nexport function detectFormat(input: ColorInput): DetectedFormat {\n if (typeof input === 'string') {\n // Runtime guard against JS callers that bypass the string template union.\n if ((input as string).length === 0) return 'UNKNOWN';\n if (HEX_RE.test(input)) return 'HEX';\n if (RGBA_STR_RE.test(input)) return 'RGBA';\n if (RGB_STR_RE.test(input)) return 'RGB';\n if (HSL_STR_RE.test(input)) return 'HSL';\n if (HSV_STR_RE.test(input)) return 'HSV';\n return 'UNKNOWN';\n }\n\n if (Array.isArray(input)) {\n if (input.length === 4) return 'RGBA';\n if (input.length === 3) return 'RGB';\n return 'UNKNOWN';\n }\n\n if (input !== null && typeof input === 'object') {\n // Use Object.hasOwn — `in` walks the prototype chain and can be\n // abused by attacker-controlled prototypes to misclassify inputs.\n const has = Object.hasOwn;\n if (has(input, 'h') && has(input, 'v')) return 'HSV';\n if (has(input, 'h') && has(input, 'l')) return 'HSL';\n if (has(input, 'r') && has(input, 'a')) return 'RGBA';\n if (has(input, 'r')) return 'RGB';\n return 'UNKNOWN';\n }\n\n return 'UNKNOWN';\n}\n"]}
|
package/dist/detectFormat.js
CHANGED
|
@@ -4,9 +4,6 @@ const RGBA_STR_RE = /^rgba\s*\(/i;
|
|
|
4
4
|
const RGB_STR_RE = /^rgb\s*\(/i;
|
|
5
5
|
const HSL_STR_RE = /^hsl\s*\(/i;
|
|
6
6
|
const HSV_STR_RE = /^hsv\s*\(/i;
|
|
7
|
-
// Conservative: matches "<digits> C|U|M" with optional "Pantone" prefix.
|
|
8
|
-
// Refine once the real Pantone code list lands.
|
|
9
|
-
const PANTONE_RE = /^(?:pantone\s+)?\d+\s*[CUM]$/i;
|
|
10
7
|
/**
|
|
11
8
|
* Runtime type-guard — returns `true` if `input` looks like something any of
|
|
12
9
|
* chromonym's converters can parse. Cheaper than catching a `convert` throw
|
|
@@ -17,7 +14,8 @@ export function isColor(input) {
|
|
|
17
14
|
}
|
|
18
15
|
export function detectFormat(input) {
|
|
19
16
|
if (typeof input === 'string') {
|
|
20
|
-
|
|
17
|
+
// Runtime guard against JS callers that bypass the string template union.
|
|
18
|
+
if (input.length === 0)
|
|
21
19
|
return 'UNKNOWN';
|
|
22
20
|
if (HEX_RE.test(input))
|
|
23
21
|
return 'HEX';
|
|
@@ -29,8 +27,6 @@ export function detectFormat(input) {
|
|
|
29
27
|
return 'HSL';
|
|
30
28
|
if (HSV_STR_RE.test(input))
|
|
31
29
|
return 'HSV';
|
|
32
|
-
if (PANTONE_RE.test(input))
|
|
33
|
-
return 'PANTONE';
|
|
34
30
|
return 'UNKNOWN';
|
|
35
31
|
}
|
|
36
32
|
if (Array.isArray(input)) {
|
package/dist/detectFormat.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detectFormat.js","sourceRoot":"","sources":["../src/detectFormat.ts"],"names":[],"mappings":"AASA,kGAAkG;AAClG,MAAM,CAAC,MAAM,MAAM,GAAG,2CAA2C,CAAC;AAClE,MAAM,WAAW,GAAG,aAAa,CAAC;AAClC,MAAM,UAAU,GAAG,YAAY,CAAC;AAChC,MAAM,UAAU,GAAG,YAAY,CAAC;AAChC,MAAM,UAAU,GAAG,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"detectFormat.js","sourceRoot":"","sources":["../src/detectFormat.ts"],"names":[],"mappings":"AASA,kGAAkG;AAClG,MAAM,CAAC,MAAM,MAAM,GAAG,2CAA2C,CAAC;AAClE,MAAM,WAAW,GAAG,aAAa,CAAC;AAClC,MAAM,UAAU,GAAG,YAAY,CAAC;AAChC,MAAM,UAAU,GAAG,YAAY,CAAC;AAChC,MAAM,UAAU,GAAG,YAAY,CAAC;AAEhC;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,OAAO,YAAY,CAAC,KAAmB,CAAC,KAAK,SAAS,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAiB;IAC5C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,0EAA0E;QAC1E,IAAK,KAAgB,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QACrD,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACrC,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,MAAM,CAAC;QAC3C,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACzC,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACzC,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACzC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,MAAM,CAAC;QACtC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACrC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,gEAAgE;QAChE,kEAAkE;QAClE,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;QAC1B,IAAI,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QACrD,IAAI,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QACrD,IAAI,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC;YAAE,OAAO,MAAM,CAAC;QACtD,IAAI,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QAClC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["import type { ColorFormat, ColorInput } from './types.js';\n\n/**\n * A color comes in, a format key comes out.\n * 'UNKNOWN' signals the caller that the input isn't a recognized color shape.\n * Used as the dispatch key for format-specific converters.\n */\nexport type DetectedFormat = ColorFormat | 'UNKNOWN';\n\n/** Shared with `src/conversions/hex.ts`. Capture group is used there; .test() ignores it here. */\nexport const HEX_RE = /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i;\nconst RGBA_STR_RE = /^rgba\\s*\\(/i;\nconst RGB_STR_RE = /^rgb\\s*\\(/i;\nconst HSL_STR_RE = /^hsl\\s*\\(/i;\nconst HSV_STR_RE = /^hsv\\s*\\(/i;\n\n/**\n * Runtime type-guard — returns `true` if `input` looks like something any of\n * chromonym's converters can parse. Cheaper than catching a `convert` throw\n * and more ergonomic than hand-rolling `detectFormat(x) !== 'UNKNOWN'`.\n */\nexport function isColor(input: unknown): input is ColorInput {\n return detectFormat(input as ColorInput) !== 'UNKNOWN';\n}\n\nexport function detectFormat(input: ColorInput): DetectedFormat {\n if (typeof input === 'string') {\n // Runtime guard against JS callers that bypass the string template union.\n if ((input as string).length === 0) return 'UNKNOWN';\n if (HEX_RE.test(input)) return 'HEX';\n if (RGBA_STR_RE.test(input)) return 'RGBA';\n if (RGB_STR_RE.test(input)) return 'RGB';\n if (HSL_STR_RE.test(input)) return 'HSL';\n if (HSV_STR_RE.test(input)) return 'HSV';\n return 'UNKNOWN';\n }\n\n if (Array.isArray(input)) {\n if (input.length === 4) return 'RGBA';\n if (input.length === 3) return 'RGB';\n return 'UNKNOWN';\n }\n\n if (input !== null && typeof input === 'object') {\n // Use Object.hasOwn — `in` walks the prototype chain and can be\n // abused by attacker-controlled prototypes to misclassify inputs.\n const has = Object.hasOwn;\n if (has(input, 'h') && has(input, 'v')) return 'HSV';\n if (has(input, 'h') && has(input, 'l')) return 'HSL';\n if (has(input, 'r') && has(input, 'a')) return 'RGBA';\n if (has(input, 'r')) return 'RGB';\n return 'UNKNOWN';\n }\n\n return 'UNKNOWN';\n}\n"]}
|
package/dist/identify.d.ts
CHANGED
|
@@ -1,28 +1,25 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
type ColorNameByColorspace = {
|
|
6
|
-
web: WebColorName;
|
|
7
|
-
x11: X11ColorName;
|
|
8
|
-
pantone: PantoneColorName;
|
|
9
|
-
};
|
|
1
|
+
import { web } from './palettes/web.js';
|
|
2
|
+
import type { ColorInput, DistanceMetric, Palette } from './types.js';
|
|
3
|
+
/** Extract string keys from a Palette's `colors` map. */
|
|
4
|
+
type PaletteKey<P extends Palette> = Extract<keyof P['colors'], string>;
|
|
10
5
|
/**
|
|
11
6
|
* Identify the nearest-named color for any color input.
|
|
12
7
|
*
|
|
13
|
-
* The distance metric defaults to the
|
|
8
|
+
* The distance metric defaults to the palette's own `defaultMetric`
|
|
14
9
|
* (web/x11: `deltaE76`, pantone: `deltaE2000`). Override with the `metric`
|
|
15
10
|
* option — e.g. `{ metric: 'euclidean-srgb' }` for maximum speed, or
|
|
16
11
|
* `{ metric: 'deltaE2000' }` for strictest perceptual accuracy.
|
|
17
12
|
*
|
|
18
|
-
* Returns `null` if the input isn't a recognized color shape
|
|
19
|
-
* colorspace name isn't one of `web` / `x11` / `pantone`.
|
|
13
|
+
* Returns `null` if the input isn't a recognized color shape.
|
|
20
14
|
*
|
|
21
|
-
* Defaults:
|
|
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.
|
|
22
19
|
*/
|
|
23
|
-
export declare function identify<
|
|
24
|
-
|
|
20
|
+
export declare function identify<P extends Palette = typeof web>(input: ColorInput, opts?: {
|
|
21
|
+
palette?: P;
|
|
25
22
|
metric?: DistanceMetric;
|
|
26
|
-
}):
|
|
23
|
+
}): PaletteKey<P> | null;
|
|
27
24
|
export {};
|
|
28
25
|
//# 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":"AAGA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEtE,yDAAyD;AACzD,KAAK,UAAU,CAAC,CAAC,SAAS,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;AAExE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,GAAG,EACrD,KAAK,EAAE,UAAU,EACjB,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IAAC,MAAM,CAAC,EAAE,cAAc,CAAA;CAAO,GAClD,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAQtB","sourcesContent":["import { toRgba } from './convert.js';\nimport { detectFormat } from './detectFormat.js';\nimport { nearest } from './indexing.js';\nimport { web } from './palettes/web.js';\nimport type { ColorInput, DistanceMetric, Palette } 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 * Identify the nearest-named color for any color input.\n *\n * The distance metric defaults to the palette's own `defaultMetric`\n * (web/x11: `deltaE76`, pantone: `deltaE2000`). Override with the `metric`\n * option — e.g. `{ metric: 'euclidean-srgb' }` for maximum speed, or\n * `{ metric: 'deltaE2000' }` for strictest perceptual accuracy.\n *\n * Returns `null` if the input isn't a recognized color shape.\n *\n * Defaults: palette = `web`.\n *\n * BYO palettes: pass any object matching `Palette<Name>` and the\n * return type is inferred from its `colors` keys — no registration needed.\n */\nexport function identify<P extends Palette = typeof web>(\n input: ColorInput,\n opts: { palette?: P; metric?: DistanceMetric } = {},\n): PaletteKey<P> | null {\n const format = detectFormat(input);\n if (format === 'UNKNOWN') return null;\n\n const palette = (opts.palette ?? web) as P;\n const rgba = toRgba(input, format);\n const name = nearest(rgba, palette, opts.metric ?? palette.defaultMetric);\n return (name as PaletteKey<P>) || null;\n}\n"]}
|