@sardine/colour 2.2.0 → 2.3.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/dist/convertHextoCSSRGB.d.ts +12 -0
- package/dist/convertHextoRGB.d.ts +1 -1
- package/dist/getContrastRatio.d.ts +9 -0
- package/dist/getContrastRatioFromCSSRGB.d.ts +9 -0
- package/dist/getContrastRatioFromNamedCSSColour.d.ts +11 -0
- package/dist/index.cjs +82 -23
- package/dist/index.d.ts +4 -0
- package/dist/index.min.js +7 -1
- package/dist/index.mjs +82 -23
- package/dist/util/calculateContrastRatio.d.ts +7 -0
- package/package.json +2 -2
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts an hexadecimal colour into CSS RGB/A colour.
|
|
3
|
+
* @param {string} hex - An hexadecimal colour in the format:
|
|
4
|
+
*
|
|
5
|
+
* - `#000`
|
|
6
|
+
* - `#102030`
|
|
7
|
+
* - `#ffff`
|
|
8
|
+
* - `#102030ff`
|
|
9
|
+
*
|
|
10
|
+
* @returns {string} either a CSS RGB or CSS RGBA string.
|
|
11
|
+
*/
|
|
12
|
+
export declare function convertHextoCSSRGB(hex: string): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NamedCSSColour, WCAG } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Calculates the contrast ratio between two colours.
|
|
4
|
+
* @param colour1 The first colour
|
|
5
|
+
* @param colour2 The second colour
|
|
6
|
+
* @param standard The standard to evaluate the contrast ratio against, defaults to WCAG2.1
|
|
7
|
+
* @returns The contrast ratio between the two colours truncated to 3 decimal places
|
|
8
|
+
*/
|
|
9
|
+
export declare function getContrastRatio(colour1: string | NamedCSSColour, colour2: string | NamedCSSColour, standard: WCAG): number;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { WCAG } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Calculates the contrast ratio between two colours in CSSRGB format.
|
|
4
|
+
* @param colour1 The first colour in CSSRGB format
|
|
5
|
+
* @param colour2 The second colour in CSSRGB format
|
|
6
|
+
* @param standard The standard to evaluate the contrast ratio against, defaults to WCAG2.1
|
|
7
|
+
* @returns The contrast ratio between the two colours truncated to 3 decimal places
|
|
8
|
+
*/
|
|
9
|
+
export declare function getContrastRatioFromCSSRGB(colour1: string, colour2: string, standard: WCAG): number;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { NamedCSSColour, WCAG } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Calculates the contrast ratio between two named CSS colours in.
|
|
4
|
+
*
|
|
5
|
+
* See list here https://developer.mozilla.org/en-US/docs/Web/CSS/named-color
|
|
6
|
+
* @param colour1 The first named CSS colour
|
|
7
|
+
* @param colour2 The second named CSS colour
|
|
8
|
+
* @param standard The standard to evaluate the contrast ratio against, defaults to WCAG2.1
|
|
9
|
+
* @returns The contrast ratio between the two colours truncated to 3 decimal places
|
|
10
|
+
*/
|
|
11
|
+
export declare function getContrastRatioFromNamedCSSColour(colour1: NamedCSSColour, colour2: NamedCSSColour, standard: WCAG): number;
|
package/dist/index.cjs
CHANGED
|
@@ -14,31 +14,27 @@ function deltaHue_d({ C1, C2, h1_d, h2_d }) {
|
|
|
14
14
|
if (C1 * C2 === 0) {
|
|
15
15
|
return 0;
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
const delta = h2_d - h1_d;
|
|
18
|
+
if (Math.abs(delta) <= 180) {
|
|
19
|
+
return delta;
|
|
19
20
|
}
|
|
20
|
-
if (
|
|
21
|
-
return
|
|
21
|
+
if (delta > 180) {
|
|
22
|
+
return delta - 360;
|
|
22
23
|
}
|
|
23
|
-
|
|
24
|
-
return h2_d - h1_d + 360;
|
|
25
|
-
}
|
|
26
|
-
return 0;
|
|
24
|
+
return delta + 360;
|
|
27
25
|
}
|
|
28
26
|
function meanHue_d({ C1, C2, h1_d, h2_d }) {
|
|
29
27
|
if (C1 * C2 === 0) {
|
|
30
28
|
return h2_d + h1_d;
|
|
31
29
|
}
|
|
32
|
-
|
|
30
|
+
const delta = Math.abs(h1_d - h2_d);
|
|
31
|
+
if (delta <= 180) {
|
|
33
32
|
return (h2_d + h1_d) / 2;
|
|
34
33
|
}
|
|
35
|
-
if (
|
|
34
|
+
if (delta > 180 && h1_d + h2_d < 360) {
|
|
36
35
|
return (h2_d + h1_d + 360) / 2;
|
|
37
36
|
}
|
|
38
|
-
|
|
39
|
-
return (h2_d + h1_d - 360) / 2;
|
|
40
|
-
}
|
|
41
|
-
return 0;
|
|
37
|
+
return (h2_d + h1_d - 360) / 2;
|
|
42
38
|
}
|
|
43
39
|
const toRadians = (n) => n * (Math.PI / 180);
|
|
44
40
|
const bigSquare = (n) => Math.sqrt(n ** 7 / (n ** 7 + 25 ** 7));
|
|
@@ -358,7 +354,7 @@ function convertHextoRGB(hex) {
|
|
|
358
354
|
R: Number.parseInt(`${hex[1]}${hex[2]}`, 16),
|
|
359
355
|
G: Number.parseInt(`${hex[3]}${hex[4]}`, 16),
|
|
360
356
|
B: Number.parseInt(`${hex[5]}${hex[6]}`, 16),
|
|
361
|
-
A: Number.parseInt(`${hex[7]}${hex[8]}`, 16) / 255
|
|
357
|
+
A: Math.round(Number.parseInt(`${hex[7]}${hex[8]}`, 16) / 255 * 100) / 100
|
|
362
358
|
};
|
|
363
359
|
}
|
|
364
360
|
if (hex.match(shortAlphaHexRegex)) {
|
|
@@ -366,13 +362,20 @@ function convertHextoRGB(hex) {
|
|
|
366
362
|
R: Number.parseInt(`${hex[1]}${hex[1]}`, 16),
|
|
367
363
|
G: Number.parseInt(`${hex[2]}${hex[2]}`, 16),
|
|
368
364
|
B: Number.parseInt(`${hex[3]}${hex[3]}`, 16),
|
|
369
|
-
A: Number.parseInt(`${hex[4]}${hex[4]}`, 16) / 255
|
|
365
|
+
A: Math.round(Number.parseInt(`${hex[4]}${hex[4]}`, 16) / 255 * 100) / 100
|
|
370
366
|
};
|
|
371
367
|
}
|
|
372
368
|
throw new Error(
|
|
373
369
|
`convertHextoRGB expects an valid hexadecimal colour value but got ${hex}`
|
|
374
370
|
);
|
|
375
371
|
}
|
|
372
|
+
function convertHextoCSSRGB(hex) {
|
|
373
|
+
const rgb = convertHextoRGB(hex);
|
|
374
|
+
if (rgb.A) {
|
|
375
|
+
return `rgba(${rgb.R},${rgb.G},${rgb.B},${rgb.A})`;
|
|
376
|
+
}
|
|
377
|
+
return `rgb(${rgb.R},${rgb.G},${rgb.B})`;
|
|
378
|
+
}
|
|
376
379
|
function convertNamedCSSColourtoHex(name) {
|
|
377
380
|
return namedCSSColours.get(name);
|
|
378
381
|
}
|
|
@@ -468,10 +471,7 @@ function findNearestColour(colour, palette) {
|
|
|
468
471
|
if (colourType === "cssRGB") {
|
|
469
472
|
return convertRGBtoCSSRGB(nearest);
|
|
470
473
|
}
|
|
471
|
-
|
|
472
|
-
return convertRGBtoNamedCSSColour(nearest);
|
|
473
|
-
}
|
|
474
|
-
return;
|
|
474
|
+
return convertRGBtoNamedCSSColour(nearest);
|
|
475
475
|
}
|
|
476
476
|
function findNearestHexColour(colour, palette) {
|
|
477
477
|
if (!palette || palette.length < 2) {
|
|
@@ -518,14 +518,69 @@ function getSRGBLuminanceFromHex(colour, standard) {
|
|
|
518
518
|
const rgbColor = convertHextoRGB(colour);
|
|
519
519
|
return getSRGBLuminanceFromRGB(rgbColor, standard);
|
|
520
520
|
}
|
|
521
|
-
function
|
|
522
|
-
const luminance1 = getSRGBLuminanceFromHex(colour1, standard);
|
|
523
|
-
const luminance2 = getSRGBLuminanceFromHex(colour2, standard);
|
|
521
|
+
function calculateContrastRatio(luminance1, luminance2) {
|
|
524
522
|
const lighter = Math.max(luminance1, luminance2);
|
|
525
523
|
const darker = Math.min(luminance1, luminance2);
|
|
526
524
|
const ratio = (lighter + 0.05) / (darker + 0.05);
|
|
527
525
|
return Math.floor(ratio * 1e3) / 1e3;
|
|
528
526
|
}
|
|
527
|
+
function getContrastRatioFromHex(colour1, colour2, standard) {
|
|
528
|
+
const luminance1 = getSRGBLuminanceFromHex(colour1, standard);
|
|
529
|
+
const luminance2 = getSRGBLuminanceFromHex(colour2, standard);
|
|
530
|
+
return calculateContrastRatio(luminance1, luminance2);
|
|
531
|
+
}
|
|
532
|
+
function getContrastRatio(colour1, colour2, standard) {
|
|
533
|
+
let hexColour1;
|
|
534
|
+
let hexColour2;
|
|
535
|
+
if (colour1.startsWith("#")) {
|
|
536
|
+
hexColour1 = colour1;
|
|
537
|
+
} else if (colour1.startsWith("rgb")) {
|
|
538
|
+
hexColour1 = convertCSSRGBtoHex(colour1);
|
|
539
|
+
} else {
|
|
540
|
+
const _hexColour1 = convertNamedCSSColourtoHex(colour1);
|
|
541
|
+
if (_hexColour1 === void 0) {
|
|
542
|
+
throw new Error(
|
|
543
|
+
`getContrastRatio expects valid CSS named colours.
|
|
544
|
+
${colour1} is not a valid CSS named colour.
|
|
545
|
+
See https://developer.mozilla.org/en-US/docs/Web/CSS/named-color`
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
hexColour1 = _hexColour1;
|
|
549
|
+
}
|
|
550
|
+
if (colour2.startsWith("#")) {
|
|
551
|
+
hexColour2 = colour2;
|
|
552
|
+
} else if (colour2.startsWith("rgb")) {
|
|
553
|
+
hexColour2 = convertCSSRGBtoHex(colour2);
|
|
554
|
+
} else {
|
|
555
|
+
const _hexColour2 = convertNamedCSSColourtoHex(colour2);
|
|
556
|
+
if (_hexColour2 === void 0) {
|
|
557
|
+
throw new Error(`getContrastRatio expects valid CSS named colours.
|
|
558
|
+
${colour2} is not a valid CSS named colour.
|
|
559
|
+
See https://developer.mozilla.org/en-US/docs/Web/CSS/named-color`);
|
|
560
|
+
}
|
|
561
|
+
hexColour2 = _hexColour2;
|
|
562
|
+
}
|
|
563
|
+
return getContrastRatioFromHex(hexColour1, hexColour2, standard);
|
|
564
|
+
}
|
|
565
|
+
function getContrastRatioFromCSSRGB(colour1, colour2, standard) {
|
|
566
|
+
const rgbColour1 = convertCSSRGBtoRGB(colour1);
|
|
567
|
+
const rgbColour2 = convertCSSRGBtoRGB(colour2);
|
|
568
|
+
const luminance1 = getSRGBLuminanceFromRGB(rgbColour1, standard);
|
|
569
|
+
const luminance2 = getSRGBLuminanceFromRGB(rgbColour2, standard);
|
|
570
|
+
return calculateContrastRatio(luminance1, luminance2);
|
|
571
|
+
}
|
|
572
|
+
function getContrastRatioFromNamedCSSColour(colour1, colour2, standard) {
|
|
573
|
+
const hexColour1 = convertNamedCSSColourtoHex(colour1);
|
|
574
|
+
const hexColour2 = convertNamedCSSColourtoHex(colour2);
|
|
575
|
+
if (hexColour1 === void 0 || hexColour2 === void 0) {
|
|
576
|
+
throw new Error(
|
|
577
|
+
`getContrastRatioFromNamedCSSColour expects valid CSS named colours.
|
|
578
|
+
${colour1} or ${colour2} are not valid CSS named colours.
|
|
579
|
+
See https://developer.mozilla.org/en-US/docs/Web/CSS/named-color`
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
return getContrastRatioFromHex(hexColour1, hexColour2, standard);
|
|
583
|
+
}
|
|
529
584
|
function isHexDarkColour(colour, standard) {
|
|
530
585
|
const colourLuminance = getSRGBLuminanceFromHex(colour, standard) + 0.05;
|
|
531
586
|
const whiteContrast = 1.05 / colourLuminance;
|
|
@@ -590,6 +645,7 @@ exports.RGBdistance = RGBdistance;
|
|
|
590
645
|
exports.ciede2000 = ciede2000;
|
|
591
646
|
exports.convertCSSRGBtoHex = convertCSSRGBtoHex;
|
|
592
647
|
exports.convertCSSRGBtoRGB = convertCSSRGBtoRGB;
|
|
648
|
+
exports.convertHextoCSSRGB = convertHextoCSSRGB;
|
|
593
649
|
exports.convertHextoNamedCSSColour = convertHextoNamedCSSColour;
|
|
594
650
|
exports.convertHextoRGB = convertHextoRGB;
|
|
595
651
|
exports.convertNamedCSSColourtoHex = convertNamedCSSColourtoHex;
|
|
@@ -605,7 +661,10 @@ exports.findNearestColour = findNearestColour;
|
|
|
605
661
|
exports.findNearestHexColour = findNearestHexColour;
|
|
606
662
|
exports.findNearestNamedCSSColour = findNearestNamedCSSColour;
|
|
607
663
|
exports.findNearestRGBColour = findNearestRGBColour;
|
|
664
|
+
exports.getContrastRatio = getContrastRatio;
|
|
665
|
+
exports.getContrastRatioFromCSSRGB = getContrastRatioFromCSSRGB;
|
|
608
666
|
exports.getContrastRatioFromHex = getContrastRatioFromHex;
|
|
667
|
+
exports.getContrastRatioFromNamedCSSColour = getContrastRatioFromNamedCSSColour;
|
|
609
668
|
exports.getSRGBLuminanceFromHex = getSRGBLuminanceFromHex;
|
|
610
669
|
exports.getSRGBLuminanceFromRGB = getSRGBLuminanceFromRGB;
|
|
611
670
|
exports.isCSSNamedDarkColour = isCSSNamedDarkColour;
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export { convertCSSRGBtoHex } from "./convertCSSRGBtoHex";
|
|
|
4
4
|
export { convertCSSRGBtoRGB } from "./convertCSSRGBtoRGB";
|
|
5
5
|
export { convertHextoNamedCSSColour } from "./convertHextoNamedCSSColour";
|
|
6
6
|
export { convertHextoRGB } from "./convertHextoRGB";
|
|
7
|
+
export { convertHextoCSSRGB } from "./convertHextoCSSRGB";
|
|
7
8
|
export { convertNamedCSSColourtoHex } from "./convertNamedCSSColourtoHex";
|
|
8
9
|
export { convertNamedCSSColourtoRGB } from "./convertNamedCSSColourtoRGB";
|
|
9
10
|
export { convertRGBtoCSSRGB } from "./convertRGBtoCSSRGB";
|
|
@@ -17,7 +18,10 @@ export { findNearestColour } from "./findNearestColour";
|
|
|
17
18
|
export { findNearestHexColour } from "./findNearestHexColour";
|
|
18
19
|
export { findNearestNamedCSSColour } from "./findNearestNamedCSSColour";
|
|
19
20
|
export { findNearestRGBColour } from "./findNearestRGBColour";
|
|
21
|
+
export { getContrastRatio } from "./getContrastRatio";
|
|
22
|
+
export { getContrastRatioFromCSSRGB } from "./getContrastRatioFromCSSRGB";
|
|
20
23
|
export { getContrastRatioFromHex } from "./getContrastRatioFromHex";
|
|
24
|
+
export { getContrastRatioFromNamedCSSColour } from "./getContrastRatioFromNamedCSSColour";
|
|
21
25
|
export { getSRGBLuminanceFromHex } from "./getSRGBLuminanceFromHex";
|
|
22
26
|
export { getSRGBLuminanceFromRGB } from "./getSRGBLuminanceFromRGB";
|
|
23
27
|
export { isCSSNamedDarkColour } from "./isCSSNameDarkColour";
|
package/dist/index.min.js
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
"use strict";function T(e,t){if(e===0&&t===0)return 0;const n=Math.atan2(e,t)*(180/Math.PI);return n>=0?n:n+360}function
|
|
1
|
+
"use strict";function T(e,t){if(e===0&&t===0)return 0;const n=Math.atan2(e,t)*(180/Math.PI);return n>=0?n:n+360}function Ce({C1:e,C2:t,h1_d:n,h2_d:o}){if(e*t===0)return 0;const r=o-n;return Math.abs(r)<=180?r:r>180?r-360:r+360}function Se({C1:e,C2:t,h1_d:n,h2_d:o}){if(e*t===0)return o+n;const r=Math.abs(n-o);return r<=180?(o+n)/2:r>180&&n+o<360?(o+n+360)/2:(o+n-360)/2}const b=e=>e*(Math.PI/180),U=e=>Math.sqrt(e**7/(e**7+25**7));function g(e,t){const n=e/255,o=t?.03928:.04045;let r;return n>o?r=((n+.055)/1.055)**2.4:r=n/12.92,r}function y(e){const t=.20689655172413793,n=t**3;let o;return e>n?o=Math.cbrt(e):o=e/(3*t**2)+4/29,o}function pe(e,t,n){return Math.min(Math.max(e,t),n)}function j(e,t){const n=e.L,o=e.a,r=e.b,a=t.L,s=t.a,c=t.b,f=1,m=1,G=1,h=Math.sqrt(o**2+r**2),C=Math.sqrt(s**2+c**2),ue=a-n,le=(h+C)/2,P=.5*(1-U(le)),A=o*(1+P),F=s*(1+P),B=Math.sqrt(A**2+r**2),k=Math.sqrt(F**2+c**2),w=(B+k)/2,E=k-B,Y=T(r,A),X=T(c,F),de=Ce({C1:h,C2:C,h1_d:Y,h2_d:X}),Z=2*Math.sqrt(B*k)*Math.sin(b(de)/2),S=Se({C1:h,C2:C,h1_d:Y,h2_d:X}),D=(n+a)/2,me=1-.17*Math.cos(b(S-30))+.24*Math.cos(b(2*S))+.32*Math.cos(b(3*S+6))-.2*Math.cos(b(4*S-63)),be=1+.015*(D-50)**2/Math.sqrt(20+(D-50)**2),z=.045*w+1,_=1+.015*w*me,ge=30*Math.exp(-(((S-275)/25)**2)),he=-2*U(w)*Math.sin(b(ge*2));return Math.sqrt((ue/(f*be))**2+(E/(m*z))**2+(Z/(G*_))**2+he*(E/(m*z))*(Z/(G*_)))}function O(e){const{R:t,G:n,B:o}=e,r=g(t)*100,a=g(n)*100,s=g(o)*100,c=r*.4124+a*.3576+s*.1805,f=r*.2126+a*.7152+s*.0722,m=r*.0193+a*.1192+s*.9505;return{X:c,Y:f,Z:m}}function V(e){const{X:t,Y:n,Z:o}=e,r=t/95.047,a=n/100,s=o/108.883,c=y(r),f=y(a),m=y(s),G=116*f-16,h=500*(c-f),C=200*(f-m);return{L:G,a:h,b:C}}function N(e){const t=O(e);return V(t)}const J=(e,t)=>{const n=N(e),o=N(t);return j(n,o)},K=/^#[a-fA-F0-9]{6}$/,Q=/^#[a-fA-F0-9]{8}$/,ee=/^#[a-fA-F0-9]{3}$/,te=/^#[a-fA-F0-9]{4}$/,ne=/^rgba*\(\s*([-+]?\d+)\s*(?:,)?\s*([-+]?\d+)\s*(?:,)?\s*([-+]?\d+)\s*(?:,*|\/*)\s*([-+]?\d*[.]?\d+[%]?)*\)$/i;function i(e){const t=e.match(ne);if(!t)throw new Error(`convertCSSRGBtoHex expects a valid CSS RGB string but got ${e}`);const n=o=>o?Number.parseFloat(o):void 0;return{R:n(t[1]),G:n(t[2]),B:n(t[3]),A:n(t[4])}}function p({R:e,G:t,B:n,A:o}){const r=a=>pe(a,0,255).toString(16).padStart(2,"0");return`#${r(e)}${r(t)}${r(n)}${o?r(Math.round(o*255)):""}`}function M(e){const t=i(e);return p(t)}const H=new Map([["aliceblue","#f0f8ff"],["antiquewhite","#faebd7"],["aqua","#00ffff"],["aquamarine","#7fffd4"],["azure","#f0ffff"],["beige","#f5f5dc"],["bisque","#ffe4c4"],["black","#000000"],["blanchedalmond","#ffebcd"],["blue","#0000ff"],["blueviolet","#8a2be2"],["brown","#a52a2a"],["burlywood","#deb887"],["cadetblue","#5f9ea0"],["chartreuse","#7fff00"],["chocolate","#d2691e"],["coral","#ff7f50"],["cornflowerblue","#6495ed"],["cornsilk","#fff8dc"],["crimson","#dc143c"],["cyan","#00ffff"],["darkblue","#00008b"],["darkcyan","#008b8b"],["darkgoldenrod","#b8860b"],["darkgray","#a9a9a9"],["darkgreen","#006400"],["darkgrey","#a9a9a9"],["darkkhaki","#bdb76b"],["darkmagenta","#8b008b"],["darkolivegreen","#556b2f"],["darkorange","#ff8c00"],["darkorchid","#9932cc"],["darkred","#8b0000"],["darksalmon","#e9967a"],["darkseagreen","#8fbc8f"],["darkslateblue","#483d8b"],["darkslategray","#2f4f4f"],["darkslategrey","#2f4f4f"],["darkturquoise","#00ced1"],["darkviolet","#9400d3"],["deeppink","#ff1493"],["deepskyblue","#00bfff"],["dimgray","#696969"],["dimgrey","#696969"],["dodgerblue","#1e90ff"],["firebrick","#b22222"],["floralwhite","#fffaf0"],["forestgreen","#228b22"],["fuchsia","#ff00ff"],["gainsboro","#dcdcdc"],["ghostwhite","#f8f8ff"],["gold","#ffd700"],["goldenrod","#daa520"],["gray","#808080"],["green","#008000"],["greenyellow","#adff2f"],["grey","#808080"],["honeydew","#f0fff0"],["hotpink","#ff69b4"],["indianred","#cd5c5c"],["indigo","#4b0082"],["ivory","#fffff0"],["khaki","#f0e68c"],["lavender","#e6e6fa"],["lavenderblush","#fff0f5"],["lawngreen","#7cfc00"],["lemonchiffon","#fffacd"],["lightblue","#add8e6"],["lightcoral","#f08080"],["lightcyan","#e0ffff"],["lightgoldenrodyellow","#fafad2"],["lightgray","#d3d3d3"],["lightgreen","#90ee90"],["lightgrey","#d3d3d3"],["lightpink","#ffb6c1"],["lightsalmon","#ffa07a"],["lightseagreen","#20b2aa"],["lightskyblue","#87cefa"],["lightslategray","#778899"],["lightslategrey","#778899"],["lightsteelblue","#b0c4de"],["lightyellow","#ffffe0"],["lime","#00ff00"],["limegreen","#32cd32"],["linen","#faf0e6"],["magenta","#ff00ff"],["maroon","#800000"],["mediumaquamarine","#66cdaa"],["mediumblue","#0000cd"],["mediumorchid","#ba55d3"],["mediumpurple","#9370db"],["mediumseagreen","#3cb371"],["mediumslateblue","#7b68ee"],["mediumspringgreen","#00fa9a"],["mediumturquoise","#48d1cc"],["mediumvioletred","#c71585"],["midnightblue","#191970"],["mintcream","#f5fffa"],["mistyrose","#ffe4e1"],["moccasin","#ffe4b5"],["navajowhite","#ffdead"],["navy","#000080"],["oldlace","#fdf5e6"],["olive","#808000"],["olivedrab","#6b8e23"],["orangered","#ff4500"],["orchid","#da70d6"],["palegoldenrod","#eee8aa"],["palegreen","#98fb98"],["paleturquoise","#afeeee"],["palevioletred","#db7093"],["papayawhip","#ffefd5"],["peachpuff","#ffdab9"],["peru","#cd853f"],["pink","#ffc0cb"],["plum","#dda0dd"],["powderblue","#b0e0e6"],["purple","#800080"],["red","#ff0000"],["rosybrown","#bc8f8f"],["royalblue","#4169e1"],["saddlebrown","#8b4513"],["salmon","#fa8072"],["sandybrown","#f4a460"],["seagreen","#2e8b57"],["seashell","#fff5ee"],["sienna","#a0522d"],["silver","#c0c0c0"],["skyblue","#87ceeb"],["slateblue","#6a5acd"],["slategray","#708090"],["slategrey","#708090"],["snow","#fffafa"],["springgreen","#00ff7f"],["steelblue","#4682b4"],["tan","#d2b48c"],["teal","#008080"],["thistle","#d8bfd8"],["tomato","#ff6347"],["transparent","#00000000"],["turquoise","#40e0d0"],["violet","#ee82ee"],["wheat","#f5deb3"],["white","#ffffff"],["whitesmoke","#f5f5f5"],["yellow","#ffff00"],["yellowgreen","#9acd32"]]);function re(e){for(const[t,n]of H.entries())if(n===e)return t}function u(e){if(typeof e!="string")throw new Error(`convertHextoRGB expects a string but got a ${typeof e}`);if(e.match(K))return{R:Number.parseInt(`${e[1]}${e[2]}`,16),G:Number.parseInt(`${e[3]}${e[4]}`,16),B:Number.parseInt(`${e[5]}${e[6]}`,16)};if(e.match(ee))return{R:Number.parseInt(`${e[1]}${e[1]}`,16),G:Number.parseInt(`${e[2]}${e[2]}`,16),B:Number.parseInt(`${e[3]}${e[3]}`,16)};if(e.match(Q))return{R:Number.parseInt(`${e[1]}${e[2]}`,16),G:Number.parseInt(`${e[3]}${e[4]}`,16),B:Number.parseInt(`${e[5]}${e[6]}`,16),A:Math.round(Number.parseInt(`${e[7]}${e[8]}`,16)/255*100)/100};if(e.match(te))return{R:Number.parseInt(`${e[1]}${e[1]}`,16),G:Number.parseInt(`${e[2]}${e[2]}`,16),B:Number.parseInt(`${e[3]}${e[3]}`,16),A:Math.round(Number.parseInt(`${e[4]}${e[4]}`,16)/255*100)/100};throw new Error(`convertHextoRGB expects an valid hexadecimal colour value but got ${e}`)}function Re(e){const t=u(e);return t.A?`rgba(${t.R},${t.G},${t.B},${t.A})`:`rgb(${t.R},${t.G},${t.B})`}function l(e){return H.get(e)}function R(e){const t=l(e);if(t)return u(t)}function q({R:e,G:t,B:n,A:o}){return`rgb(${e} ${t} ${n}${o?` / ${o}`:""})`}function I(e){const t=p(e);return re(t)}function $(e,t){if(!t||t.length<2)return e;const n=[];for(const r of t){const a=J(e,r);n.push([r,a])}return n.sort((r,a)=>r[1]-a[1])[0][0]}function $e(e,t){if(!t||t.length<2)return e;const n=i(e),o=t.map(a=>i(a)),r=$(n,o);return q(r)}function L(e){return!!e.match(ne)}function oe(e){return!!e.match(K)||!!e.match(Q)||!!e.match(te)||!!e.match(ee)}function ae(e){return H.has(e)}function ve(e,t){if(!t||t.length<2)return e;let n,o;const r=[];if(oe(e)&&(n=u(e),o="hex"),L(e)&&(n=i(e),o="cssRGB"),ae(e)&&(n=R(e),o="namedCSS"),!n)return;for(const s of t)oe(s)&&r.push(u(s)),L(s)&&r.push(i(s)),ae(s)&&r.push(R(s));if(r.length<2)return e;const a=$(n,r);return o==="hex"?p(a):o==="cssRGB"?q(a):I(a)}function Ge(e,t){if(!t||t.length<2)return e;const n=u(e),o=t.map(a=>u(a)),r=$(n,o);return p(r)}function Be(e,t){if(!t||t.length<2)return e;const n=R(e),r=t.map(s=>R(s)).filter(s=>s!==void 0);if(!n||r.length<2)return e;const a=$(n,r);return I(a)}function v({R:e,G:t,B:n},o){const r=o==="WCAG2.1",a=g(e,r),s=g(t,r),c=g(n,r);return .2126*a+.7152*s+.0722*c}function d(e,t){const n=u(e);return v(n,t)}function se(e,t){const n=Math.max(e,t),o=Math.min(e,t),r=(n+.05)/(o+.05);return Math.floor(r*1e3)/1e3}function W(e,t,n){const o=d(e,n),r=d(t,n);return se(o,r)}function ke(e,t,n){let o,r;if(e.startsWith("#"))o=e;else if(e.startsWith("rgb"))o=M(e);else{const a=l(e);if(a===void 0)throw new Error(`getContrastRatio expects valid CSS named colours.
|
|
2
|
+
${e} is not a valid CSS named colour.
|
|
3
|
+
See https://developer.mozilla.org/en-US/docs/Web/CSS/named-color`);o=a}if(t.startsWith("#"))r=t;else if(t.startsWith("rgb"))r=M(t);else{const a=l(t);if(a===void 0)throw new Error(`getContrastRatio expects valid CSS named colours.
|
|
4
|
+
${t} is not a valid CSS named colour.
|
|
5
|
+
See https://developer.mozilla.org/en-US/docs/Web/CSS/named-color`);r=a}return W(o,r,n)}function we(e,t,n){const o=i(e),r=i(t),a=v(o,n),s=v(r,n);return se(a,s)}function ye(e,t,n){const o=l(e),r=l(t);if(o===void 0||r===void 0)throw new Error(`getContrastRatioFromNamedCSSColour expects valid CSS named colours.
|
|
6
|
+
${e} or ${t} are not valid CSS named colours.
|
|
7
|
+
See https://developer.mozilla.org/en-US/docs/Web/CSS/named-color`);return W(o,r,n)}function x(e,t){const n=d(e,t)+.05,o=1.05/n,r=n/.05;return o>r}function ce(e,t){const n=l(e);if(n)return x(n,t);throw new Error(`${e} is not a valid colour format. isCSSNamedDarkColour only accepts CSS named colours. Check more details here https://developer.mozilla.org/en-US/docs/Web/CSS/named-color`)}function fe(e,t){const n=i(e),o=v(n,t),r=1.05/o,a=o/.05;return r>a}function Ne(e,t){try{return e.startsWith("#")?x(e,t):e.startsWith("rgb")?fe(e,t):ce(e,t)}catch{throw new Error(`${e} is not a valid colour format. isDarkColour accepts CSS RGB formats, ie rgb(0,0,0) and rgba(255, 255, 255, 0.4), hexadecimal and CSS named colours.`)}}const ie=(e,t)=>e>t?e/t:t/e,Me=({backgroundColour:e,optionOneColour:t,optionTwoColour:n},o)=>{const r=d(e,o)+.05,a=d(t,o)+.05,s=d(n,o)+.05,c=ie(a,r),f=ie(s,r);return c>f?t:n};export{J as RGBdistance,j as ciede2000,M as convertCSSRGBtoHex,i as convertCSSRGBtoRGB,Re as convertHextoCSSRGB,re as convertHextoNamedCSSColour,u as convertHextoRGB,l as convertNamedCSSColourtoHex,R as convertNamedCSSColourtoRGB,q as convertRGBtoCSSRGB,p as convertRGBtoHex,N as convertRGBtoLab,I as convertRGBtoNamedCSSColour,O as convertRGBtoXYZ,V as convertXYZtoLab,$e as findNearestCSSRGBColour,ve as findNearestColour,Ge as findNearestHexColour,Be as findNearestNamedCSSColour,$ as findNearestRGBColour,ke as getContrastRatio,we as getContrastRatioFromCSSRGB,W as getContrastRatioFromHex,ye as getContrastRatioFromNamedCSSColour,d as getSRGBLuminanceFromHex,v as getSRGBLuminanceFromRGB,ce as isCSSNamedDarkColour,L as isCSSRGBColour,fe as isCSSRGBDarkColour,Ne as isDarkColour,x as isHexDarkColour,Me as pickHexColourContrast};
|
package/dist/index.mjs
CHANGED
|
@@ -12,31 +12,27 @@ function deltaHue_d({ C1, C2, h1_d, h2_d }) {
|
|
|
12
12
|
if (C1 * C2 === 0) {
|
|
13
13
|
return 0;
|
|
14
14
|
}
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const delta = h2_d - h1_d;
|
|
16
|
+
if (Math.abs(delta) <= 180) {
|
|
17
|
+
return delta;
|
|
17
18
|
}
|
|
18
|
-
if (
|
|
19
|
-
return
|
|
19
|
+
if (delta > 180) {
|
|
20
|
+
return delta - 360;
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
-
return h2_d - h1_d + 360;
|
|
23
|
-
}
|
|
24
|
-
return 0;
|
|
22
|
+
return delta + 360;
|
|
25
23
|
}
|
|
26
24
|
function meanHue_d({ C1, C2, h1_d, h2_d }) {
|
|
27
25
|
if (C1 * C2 === 0) {
|
|
28
26
|
return h2_d + h1_d;
|
|
29
27
|
}
|
|
30
|
-
|
|
28
|
+
const delta = Math.abs(h1_d - h2_d);
|
|
29
|
+
if (delta <= 180) {
|
|
31
30
|
return (h2_d + h1_d) / 2;
|
|
32
31
|
}
|
|
33
|
-
if (
|
|
32
|
+
if (delta > 180 && h1_d + h2_d < 360) {
|
|
34
33
|
return (h2_d + h1_d + 360) / 2;
|
|
35
34
|
}
|
|
36
|
-
|
|
37
|
-
return (h2_d + h1_d - 360) / 2;
|
|
38
|
-
}
|
|
39
|
-
return 0;
|
|
35
|
+
return (h2_d + h1_d - 360) / 2;
|
|
40
36
|
}
|
|
41
37
|
const toRadians = (n) => n * (Math.PI / 180);
|
|
42
38
|
const bigSquare = (n) => Math.sqrt(n ** 7 / (n ** 7 + 25 ** 7));
|
|
@@ -356,7 +352,7 @@ function convertHextoRGB(hex) {
|
|
|
356
352
|
R: Number.parseInt(`${hex[1]}${hex[2]}`, 16),
|
|
357
353
|
G: Number.parseInt(`${hex[3]}${hex[4]}`, 16),
|
|
358
354
|
B: Number.parseInt(`${hex[5]}${hex[6]}`, 16),
|
|
359
|
-
A: Number.parseInt(`${hex[7]}${hex[8]}`, 16) / 255
|
|
355
|
+
A: Math.round(Number.parseInt(`${hex[7]}${hex[8]}`, 16) / 255 * 100) / 100
|
|
360
356
|
};
|
|
361
357
|
}
|
|
362
358
|
if (hex.match(shortAlphaHexRegex)) {
|
|
@@ -364,13 +360,20 @@ function convertHextoRGB(hex) {
|
|
|
364
360
|
R: Number.parseInt(`${hex[1]}${hex[1]}`, 16),
|
|
365
361
|
G: Number.parseInt(`${hex[2]}${hex[2]}`, 16),
|
|
366
362
|
B: Number.parseInt(`${hex[3]}${hex[3]}`, 16),
|
|
367
|
-
A: Number.parseInt(`${hex[4]}${hex[4]}`, 16) / 255
|
|
363
|
+
A: Math.round(Number.parseInt(`${hex[4]}${hex[4]}`, 16) / 255 * 100) / 100
|
|
368
364
|
};
|
|
369
365
|
}
|
|
370
366
|
throw new Error(
|
|
371
367
|
`convertHextoRGB expects an valid hexadecimal colour value but got ${hex}`
|
|
372
368
|
);
|
|
373
369
|
}
|
|
370
|
+
function convertHextoCSSRGB(hex) {
|
|
371
|
+
const rgb = convertHextoRGB(hex);
|
|
372
|
+
if (rgb.A) {
|
|
373
|
+
return `rgba(${rgb.R},${rgb.G},${rgb.B},${rgb.A})`;
|
|
374
|
+
}
|
|
375
|
+
return `rgb(${rgb.R},${rgb.G},${rgb.B})`;
|
|
376
|
+
}
|
|
374
377
|
function convertNamedCSSColourtoHex(name) {
|
|
375
378
|
return namedCSSColours.get(name);
|
|
376
379
|
}
|
|
@@ -466,10 +469,7 @@ function findNearestColour(colour, palette) {
|
|
|
466
469
|
if (colourType === "cssRGB") {
|
|
467
470
|
return convertRGBtoCSSRGB(nearest);
|
|
468
471
|
}
|
|
469
|
-
|
|
470
|
-
return convertRGBtoNamedCSSColour(nearest);
|
|
471
|
-
}
|
|
472
|
-
return;
|
|
472
|
+
return convertRGBtoNamedCSSColour(nearest);
|
|
473
473
|
}
|
|
474
474
|
function findNearestHexColour(colour, palette) {
|
|
475
475
|
if (!palette || palette.length < 2) {
|
|
@@ -516,14 +516,69 @@ function getSRGBLuminanceFromHex(colour, standard) {
|
|
|
516
516
|
const rgbColor = convertHextoRGB(colour);
|
|
517
517
|
return getSRGBLuminanceFromRGB(rgbColor, standard);
|
|
518
518
|
}
|
|
519
|
-
function
|
|
520
|
-
const luminance1 = getSRGBLuminanceFromHex(colour1, standard);
|
|
521
|
-
const luminance2 = getSRGBLuminanceFromHex(colour2, standard);
|
|
519
|
+
function calculateContrastRatio(luminance1, luminance2) {
|
|
522
520
|
const lighter = Math.max(luminance1, luminance2);
|
|
523
521
|
const darker = Math.min(luminance1, luminance2);
|
|
524
522
|
const ratio = (lighter + 0.05) / (darker + 0.05);
|
|
525
523
|
return Math.floor(ratio * 1e3) / 1e3;
|
|
526
524
|
}
|
|
525
|
+
function getContrastRatioFromHex(colour1, colour2, standard) {
|
|
526
|
+
const luminance1 = getSRGBLuminanceFromHex(colour1, standard);
|
|
527
|
+
const luminance2 = getSRGBLuminanceFromHex(colour2, standard);
|
|
528
|
+
return calculateContrastRatio(luminance1, luminance2);
|
|
529
|
+
}
|
|
530
|
+
function getContrastRatio(colour1, colour2, standard) {
|
|
531
|
+
let hexColour1;
|
|
532
|
+
let hexColour2;
|
|
533
|
+
if (colour1.startsWith("#")) {
|
|
534
|
+
hexColour1 = colour1;
|
|
535
|
+
} else if (colour1.startsWith("rgb")) {
|
|
536
|
+
hexColour1 = convertCSSRGBtoHex(colour1);
|
|
537
|
+
} else {
|
|
538
|
+
const _hexColour1 = convertNamedCSSColourtoHex(colour1);
|
|
539
|
+
if (_hexColour1 === void 0) {
|
|
540
|
+
throw new Error(
|
|
541
|
+
`getContrastRatio expects valid CSS named colours.
|
|
542
|
+
${colour1} is not a valid CSS named colour.
|
|
543
|
+
See https://developer.mozilla.org/en-US/docs/Web/CSS/named-color`
|
|
544
|
+
);
|
|
545
|
+
}
|
|
546
|
+
hexColour1 = _hexColour1;
|
|
547
|
+
}
|
|
548
|
+
if (colour2.startsWith("#")) {
|
|
549
|
+
hexColour2 = colour2;
|
|
550
|
+
} else if (colour2.startsWith("rgb")) {
|
|
551
|
+
hexColour2 = convertCSSRGBtoHex(colour2);
|
|
552
|
+
} else {
|
|
553
|
+
const _hexColour2 = convertNamedCSSColourtoHex(colour2);
|
|
554
|
+
if (_hexColour2 === void 0) {
|
|
555
|
+
throw new Error(`getContrastRatio expects valid CSS named colours.
|
|
556
|
+
${colour2} is not a valid CSS named colour.
|
|
557
|
+
See https://developer.mozilla.org/en-US/docs/Web/CSS/named-color`);
|
|
558
|
+
}
|
|
559
|
+
hexColour2 = _hexColour2;
|
|
560
|
+
}
|
|
561
|
+
return getContrastRatioFromHex(hexColour1, hexColour2, standard);
|
|
562
|
+
}
|
|
563
|
+
function getContrastRatioFromCSSRGB(colour1, colour2, standard) {
|
|
564
|
+
const rgbColour1 = convertCSSRGBtoRGB(colour1);
|
|
565
|
+
const rgbColour2 = convertCSSRGBtoRGB(colour2);
|
|
566
|
+
const luminance1 = getSRGBLuminanceFromRGB(rgbColour1, standard);
|
|
567
|
+
const luminance2 = getSRGBLuminanceFromRGB(rgbColour2, standard);
|
|
568
|
+
return calculateContrastRatio(luminance1, luminance2);
|
|
569
|
+
}
|
|
570
|
+
function getContrastRatioFromNamedCSSColour(colour1, colour2, standard) {
|
|
571
|
+
const hexColour1 = convertNamedCSSColourtoHex(colour1);
|
|
572
|
+
const hexColour2 = convertNamedCSSColourtoHex(colour2);
|
|
573
|
+
if (hexColour1 === void 0 || hexColour2 === void 0) {
|
|
574
|
+
throw new Error(
|
|
575
|
+
`getContrastRatioFromNamedCSSColour expects valid CSS named colours.
|
|
576
|
+
${colour1} or ${colour2} are not valid CSS named colours.
|
|
577
|
+
See https://developer.mozilla.org/en-US/docs/Web/CSS/named-color`
|
|
578
|
+
);
|
|
579
|
+
}
|
|
580
|
+
return getContrastRatioFromHex(hexColour1, hexColour2, standard);
|
|
581
|
+
}
|
|
527
582
|
function isHexDarkColour(colour, standard) {
|
|
528
583
|
const colourLuminance = getSRGBLuminanceFromHex(colour, standard) + 0.05;
|
|
529
584
|
const whiteContrast = 1.05 / colourLuminance;
|
|
@@ -589,6 +644,7 @@ export {
|
|
|
589
644
|
ciede2000,
|
|
590
645
|
convertCSSRGBtoHex,
|
|
591
646
|
convertCSSRGBtoRGB,
|
|
647
|
+
convertHextoCSSRGB,
|
|
592
648
|
convertHextoNamedCSSColour,
|
|
593
649
|
convertHextoRGB,
|
|
594
650
|
convertNamedCSSColourtoHex,
|
|
@@ -604,7 +660,10 @@ export {
|
|
|
604
660
|
findNearestHexColour,
|
|
605
661
|
findNearestNamedCSSColour,
|
|
606
662
|
findNearestRGBColour,
|
|
663
|
+
getContrastRatio,
|
|
664
|
+
getContrastRatioFromCSSRGB,
|
|
607
665
|
getContrastRatioFromHex,
|
|
666
|
+
getContrastRatioFromNamedCSSColour,
|
|
608
667
|
getSRGBLuminanceFromHex,
|
|
609
668
|
getSRGBLuminanceFromRGB,
|
|
610
669
|
isCSSNamedDarkColour,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculate the contrast ratio between two colours
|
|
3
|
+
* @param luminance1 The luminance of the first colour
|
|
4
|
+
* @param luminance2 The luminance of the second colour
|
|
5
|
+
* @returns The contrast ratio between the two colours truncated to 3 decimal places
|
|
6
|
+
*/
|
|
7
|
+
export declare function calculateContrastRatio(luminance1: number, luminance2: number): number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sardine/colour",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "It does things to colours",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"@vitest/coverage-v8": "^2.0.0",
|
|
54
54
|
"lefthook": "^1.8.1",
|
|
55
55
|
"typescript": "^5.4.5",
|
|
56
|
-
"vite": "^
|
|
56
|
+
"vite": "^6.0.0",
|
|
57
57
|
"vitest": "^2.0.0"
|
|
58
58
|
}
|
|
59
59
|
}
|