color-value-tools 1.1.5 → 1.1.7

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Danil Lisin Vladimirovich (macrulez)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/cjs/index.js CHANGED
@@ -236,11 +236,11 @@ function displayP3ToRgb(p3) {
236
236
  const sr = 1.2247 * rl + (-0.2247) * gl + 0.0000 * bl;
237
237
  const sg = (-0.0421) * rl + 1.0432 * gl + 0.0000 * bl;
238
238
  const sb = (-0.0197) * rl + (-0.0786) * gl + 1.0983 * bl;
239
- // Apply sRGB gamma
239
+ // Apply sRGB gamma and scale to 0-255
240
240
  return {
241
- r: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sr)))),
242
- g: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sg)))),
243
- b: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sb)))),
241
+ r: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sr) * 255))),
242
+ g: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sg) * 255))),
243
+ b: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sb) * 255))),
244
244
  };
245
245
  }
246
246
  // Helpers for Display P3 (operate on 0-1 values)
@@ -254,8 +254,11 @@ function linearChanToSrgb(v) {
254
254
  function toDisplayP3Hex(color) {
255
255
  const n = normalizeColorRaw(color);
256
256
  const p3 = rgbToDisplayP3({ r: n.r, g: n.g, b: n.b });
257
- const back = displayP3ToRgb(p3);
258
- return rgbToHex(back);
257
+ return rgbToHex({
258
+ r: Math.round(Math.max(0, Math.min(255, p3.r * 255))),
259
+ g: Math.round(Math.max(0, Math.min(255, p3.g * 255))),
260
+ b: Math.round(Math.max(0, Math.min(255, p3.b * 255))),
261
+ });
259
262
  }
260
263
  // Internal raw normalizer (no cache, no circular dep issues)
261
264
  function normalizeColorRaw(color) {
@@ -660,13 +663,7 @@ function normalizeColor(input) {
660
663
  const str = input.trim();
661
664
  if (isCssVariable(str))
662
665
  return { type: 'css-var', raw: str };
663
- if (isHexColor(str)) {
664
- const hex = normalizeHex(str);
665
- const [r, g, b] = hexToRgb(hex);
666
- const [h, s, l] = hexToHsl(hex);
667
- const [hh, ss, vv] = rgbToHsv({ r, g, b });
668
- return { type: 'hex', hex, r, g, b, a: 1, h, s, l, v: vv };
669
- }
666
+ // 8-digit (#rrggbbaa) or 4-digit (#rgba) — check before isHexColor
670
667
  const hex8 = str.match(/^#([0-9a-f]{8}|[0-9a-f]{4})$/i);
671
668
  if (hex8) {
672
669
  const rgba = hex8ToRgba(str);
@@ -678,6 +675,13 @@ function normalizeColor(input) {
678
675
  return { type: 'hex', hex, r, g, b, a, h, s, l, v: vv };
679
676
  }
680
677
  }
678
+ if (isHexColor(str)) {
679
+ const hex = normalizeHex(str);
680
+ const [r, g, b] = hexToRgb(hex);
681
+ const [h, s, l] = hexToHsl(hex);
682
+ const [hh, ss, vv] = rgbToHsv({ r, g, b });
683
+ return { type: 'hex', hex, r, g, b, a: 1, h, s, l, v: vv };
684
+ }
681
685
  if (isRgbColor(str)) {
682
686
  const rgba = rgbaStringToRgba(str);
683
687
  if (rgba) {
@@ -704,17 +708,6 @@ function normalizeColor(input) {
704
708
  }
705
709
  if (str === 'transparent')
706
710
  return { type: 'named', hex: '#000000', r: 0, g: 0, b: 0, a: 0 };
707
- // 4-digit #RGBA hex
708
- if (/^#[0-9a-f]{4}$/i.test(str)) {
709
- const rgba = shortHexToRgba(str);
710
- if (rgba) {
711
- const { r, g, b, a } = rgba;
712
- const hex = rgbToHex({ r, g, b });
713
- const [h, s, l] = rgbToHsl({ r, g, b });
714
- const [, , vv] = rgbToHsv({ r, g, b });
715
- return { type: 'hex', hex, r, g, b, a, h, s, l, v: vv };
716
- }
717
- }
718
711
  // oklch / oklcha
719
712
  if (isOklchColor(str)) {
720
713
  const parsed = parseOklchString(str);
@@ -236,11 +236,11 @@ function displayP3ToRgb(p3) {
236
236
  const sr = 1.2247 * rl + (-0.2247) * gl + 0.0000 * bl;
237
237
  const sg = (-0.0421) * rl + 1.0432 * gl + 0.0000 * bl;
238
238
  const sb = (-0.0197) * rl + (-0.0786) * gl + 1.0983 * bl;
239
- // Apply sRGB gamma
239
+ // Apply sRGB gamma and scale to 0-255
240
240
  return {
241
- r: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sr)))),
242
- g: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sg)))),
243
- b: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sb)))),
241
+ r: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sr) * 255))),
242
+ g: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sg) * 255))),
243
+ b: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sb) * 255))),
244
244
  };
245
245
  }
246
246
  // Helpers for Display P3 (operate on 0-1 values)
@@ -254,8 +254,11 @@ function linearChanToSrgb(v) {
254
254
  function toDisplayP3Hex(color) {
255
255
  const n = normalizeColorRaw(color);
256
256
  const p3 = rgbToDisplayP3({ r: n.r, g: n.g, b: n.b });
257
- const back = displayP3ToRgb(p3);
258
- return rgbToHex(back);
257
+ return rgbToHex({
258
+ r: Math.round(Math.max(0, Math.min(255, p3.r * 255))),
259
+ g: Math.round(Math.max(0, Math.min(255, p3.g * 255))),
260
+ b: Math.round(Math.max(0, Math.min(255, p3.b * 255))),
261
+ });
259
262
  }
260
263
  // Internal raw normalizer (no cache, no circular dep issues)
261
264
  function normalizeColorRaw(color) {
@@ -660,13 +663,7 @@ function normalizeColor(input) {
660
663
  const str = input.trim();
661
664
  if (isCssVariable(str))
662
665
  return { type: 'css-var', raw: str };
663
- if (isHexColor(str)) {
664
- const hex = normalizeHex(str);
665
- const [r, g, b] = hexToRgb(hex);
666
- const [h, s, l] = hexToHsl(hex);
667
- const [hh, ss, vv] = rgbToHsv({ r, g, b });
668
- return { type: 'hex', hex, r, g, b, a: 1, h, s, l, v: vv };
669
- }
666
+ // 8-digit (#rrggbbaa) or 4-digit (#rgba) — check before isHexColor
670
667
  const hex8 = str.match(/^#([0-9a-f]{8}|[0-9a-f]{4})$/i);
671
668
  if (hex8) {
672
669
  const rgba = hex8ToRgba(str);
@@ -678,6 +675,13 @@ function normalizeColor(input) {
678
675
  return { type: 'hex', hex, r, g, b, a, h, s, l, v: vv };
679
676
  }
680
677
  }
678
+ if (isHexColor(str)) {
679
+ const hex = normalizeHex(str);
680
+ const [r, g, b] = hexToRgb(hex);
681
+ const [h, s, l] = hexToHsl(hex);
682
+ const [hh, ss, vv] = rgbToHsv({ r, g, b });
683
+ return { type: 'hex', hex, r, g, b, a: 1, h, s, l, v: vv };
684
+ }
681
685
  if (isRgbColor(str)) {
682
686
  const rgba = rgbaStringToRgba(str);
683
687
  if (rgba) {
@@ -704,17 +708,6 @@ function normalizeColor(input) {
704
708
  }
705
709
  if (str === 'transparent')
706
710
  return { type: 'named', hex: '#000000', r: 0, g: 0, b: 0, a: 0 };
707
- // 4-digit #RGBA hex
708
- if (/^#[0-9a-f]{4}$/i.test(str)) {
709
- const rgba = shortHexToRgba(str);
710
- if (rgba) {
711
- const { r, g, b, a } = rgba;
712
- const hex = rgbToHex({ r, g, b });
713
- const [h, s, l] = rgbToHsl({ r, g, b });
714
- const [, , vv] = rgbToHsv({ r, g, b });
715
- return { type: 'hex', hex, r, g, b, a, h, s, l, v: vv };
716
- }
717
- }
718
711
  // oklch / oklcha
719
712
  if (isOklchColor(str)) {
720
713
  const parsed = parseOklchString(str);
package/dist/esm/index.js CHANGED
@@ -136,11 +136,11 @@ export function displayP3ToRgb(p3) {
136
136
  const sr = 1.2247 * rl + (-0.2247) * gl + 0.0000 * bl;
137
137
  const sg = (-0.0421) * rl + 1.0432 * gl + 0.0000 * bl;
138
138
  const sb = (-0.0197) * rl + (-0.0786) * gl + 1.0983 * bl;
139
- // Apply sRGB gamma
139
+ // Apply sRGB gamma and scale to 0-255
140
140
  return {
141
- r: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sr)))),
142
- g: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sg)))),
143
- b: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sb)))),
141
+ r: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sr) * 255))),
142
+ g: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sg) * 255))),
143
+ b: Math.round(Math.max(0, Math.min(255, linearChanToSrgb(sb) * 255))),
144
144
  };
145
145
  }
146
146
  // Helpers for Display P3 (operate on 0-1 values)
@@ -154,8 +154,11 @@ function linearChanToSrgb(v) {
154
154
  export function toDisplayP3Hex(color) {
155
155
  const n = normalizeColorRaw(color);
156
156
  const p3 = rgbToDisplayP3({ r: n.r, g: n.g, b: n.b });
157
- const back = displayP3ToRgb(p3);
158
- return rgbToHex(back);
157
+ return rgbToHex({
158
+ r: Math.round(Math.max(0, Math.min(255, p3.r * 255))),
159
+ g: Math.round(Math.max(0, Math.min(255, p3.g * 255))),
160
+ b: Math.round(Math.max(0, Math.min(255, p3.b * 255))),
161
+ });
159
162
  }
160
163
  // Internal raw normalizer (no cache, no circular dep issues)
161
164
  function normalizeColorRaw(color) {
@@ -560,13 +563,7 @@ export function normalizeColor(input) {
560
563
  const str = input.trim();
561
564
  if (isCssVariable(str))
562
565
  return { type: 'css-var', raw: str };
563
- if (isHexColor(str)) {
564
- const hex = normalizeHex(str);
565
- const [r, g, b] = hexToRgb(hex);
566
- const [h, s, l] = hexToHsl(hex);
567
- const [hh, ss, vv] = rgbToHsv({ r, g, b });
568
- return { type: 'hex', hex, r, g, b, a: 1, h, s, l, v: vv };
569
- }
566
+ // 8-digit (#rrggbbaa) or 4-digit (#rgba) — check before isHexColor
570
567
  const hex8 = str.match(/^#([0-9a-f]{8}|[0-9a-f]{4})$/i);
571
568
  if (hex8) {
572
569
  const rgba = hex8ToRgba(str);
@@ -578,6 +575,13 @@ export function normalizeColor(input) {
578
575
  return { type: 'hex', hex, r, g, b, a, h, s, l, v: vv };
579
576
  }
580
577
  }
578
+ if (isHexColor(str)) {
579
+ const hex = normalizeHex(str);
580
+ const [r, g, b] = hexToRgb(hex);
581
+ const [h, s, l] = hexToHsl(hex);
582
+ const [hh, ss, vv] = rgbToHsv({ r, g, b });
583
+ return { type: 'hex', hex, r, g, b, a: 1, h, s, l, v: vv };
584
+ }
581
585
  if (isRgbColor(str)) {
582
586
  const rgba = rgbaStringToRgba(str);
583
587
  if (rgba) {
@@ -604,17 +608,6 @@ export function normalizeColor(input) {
604
608
  }
605
609
  if (str === 'transparent')
606
610
  return { type: 'named', hex: '#000000', r: 0, g: 0, b: 0, a: 0 };
607
- // 4-digit #RGBA hex
608
- if (/^#[0-9a-f]{4}$/i.test(str)) {
609
- const rgba = shortHexToRgba(str);
610
- if (rgba) {
611
- const { r, g, b, a } = rgba;
612
- const hex = rgbToHex({ r, g, b });
613
- const [h, s, l] = rgbToHsl({ r, g, b });
614
- const [, , vv] = rgbToHsv({ r, g, b });
615
- return { type: 'hex', hex, r, g, b, a, h, s, l, v: vv };
616
- }
617
- }
618
611
  // oklch / oklcha
619
612
  if (isOklchColor(str)) {
620
613
  const parsed = parseOklchString(str);
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "color-value-tools",
3
- "version": "1.1.5",
4
- "description": "A comprehensive utility library for parsing, converting, manipulating, and analyzing color values across all major color models — hex, RGB, HSL, HSV, HWB, Lab, LCH, OKLAB, OKLCH, CMYK plus CSS variables and named colors.",
3
+ "version": "1.1.7",
4
+ "description": "Parse, convert and manipulate colors across hex, RGB, HSL, Lab, LCH, OKLCH and CMYK, with WCAG contrast checks and CSS variables. Zero dependencies.",
5
+ "author": "macrulez <macrulezru@gmail.com> (https://macrulez.ru/en)",
6
+ "license": "MIT",
7
+ "homepage": "https://github.com/macrulezru/color-value-tools#readme",
5
8
  "repository": {
6
9
  "type": "git",
7
10
  "url": "git+https://github.com/macrulezru/color-value-tools.git"
8
11
  },
9
- "homepage": "https://macrulez.ru/#/en",
10
12
  "bugs": {
11
13
  "url": "https://github.com/macrulezru/color-value-tools/issues"
12
14
  },
@@ -15,18 +17,24 @@
15
17
  "types": "dist/cjs/index.d.ts",
16
18
  "exports": {
17
19
  ".": {
20
+ "types": "./dist/cjs/index.d.ts",
18
21
  "import": "./dist/esm/index.js",
19
- "require": "./dist/cjs/index.js",
20
- "types": "./dist/cjs/index.d.ts"
22
+ "require": "./dist/cjs/index.js"
21
23
  }
22
24
  },
23
25
  "bin": {
24
26
  "cvt": "./dist/cli/bin/cli.js"
25
27
  },
26
28
  "files": [
27
- "dist"
29
+ "dist",
30
+ "README.md",
31
+ "LICENSE"
28
32
  ],
33
+ "engines": {
34
+ "node": ">=18"
35
+ },
29
36
  "scripts": {
37
+ "prepublishOnly": "npm run build",
30
38
  "build": "tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json && tsc -p tsconfig.cli.json && node -e \"require('fs').writeFileSync('dist/esm/package.json', JSON.stringify({type:'module'}))\"",
31
39
  "test": "vitest run"
32
40
  },
@@ -36,19 +44,13 @@
36
44
  "hex",
37
45
  "rgb",
38
46
  "hsl",
39
- "hsv",
40
- "hwb",
41
- "oklab",
42
47
  "oklch",
43
48
  "cmyk",
44
- "lab",
45
- "lch",
49
+ "color-conversion",
46
50
  "wcag",
47
51
  "accessibility",
48
52
  "typescript"
49
53
  ],
50
- "author": "",
51
- "license": "MIT",
52
54
  "devDependencies": {
53
55
  "@types/node": "^25.5.0",
54
56
  "typescript": "^5.0.0",