@sardine/colour 2.2.0 → 2.2.1

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.
@@ -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
@@ -518,14 +518,69 @@ function getSRGBLuminanceFromHex(colour, standard) {
518
518
  const rgbColor = convertHextoRGB(colour);
519
519
  return getSRGBLuminanceFromRGB(rgbColor, standard);
520
520
  }
521
- function getContrastRatioFromHex(colour1, colour2, standard) {
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;
@@ -605,7 +660,10 @@ exports.findNearestColour = findNearestColour;
605
660
  exports.findNearestHexColour = findNearestHexColour;
606
661
  exports.findNearestNamedCSSColour = findNearestNamedCSSColour;
607
662
  exports.findNearestRGBColour = findNearestRGBColour;
663
+ exports.getContrastRatio = getContrastRatio;
664
+ exports.getContrastRatioFromCSSRGB = getContrastRatioFromCSSRGB;
608
665
  exports.getContrastRatioFromHex = getContrastRatioFromHex;
666
+ exports.getContrastRatioFromNamedCSSColour = getContrastRatioFromNamedCSSColour;
609
667
  exports.getSRGBLuminanceFromHex = getSRGBLuminanceFromHex;
610
668
  exports.getSRGBLuminanceFromRGB = getSRGBLuminanceFromRGB;
611
669
  exports.isCSSNamedDarkColour = isCSSNamedDarkColour;
package/dist/index.d.ts CHANGED
@@ -17,7 +17,10 @@ export { findNearestColour } from "./findNearestColour";
17
17
  export { findNearestHexColour } from "./findNearestHexColour";
18
18
  export { findNearestNamedCSSColour } from "./findNearestNamedCSSColour";
19
19
  export { findNearestRGBColour } from "./findNearestRGBColour";
20
+ export { getContrastRatio } from "./getContrastRatio";
21
+ export { getContrastRatioFromCSSRGB } from "./getContrastRatioFromCSSRGB";
20
22
  export { getContrastRatioFromHex } from "./getContrastRatioFromHex";
23
+ export { getContrastRatioFromNamedCSSColour } from "./getContrastRatioFromNamedCSSColour";
21
24
  export { getSRGBLuminanceFromHex } from "./getSRGBLuminanceFromHex";
22
25
  export { getSRGBLuminanceFromRGB } from "./getSRGBLuminanceFromRGB";
23
26
  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 be({C1:e,C2:t,h1_d:n,h2_d:r}){return e*t===0?0:Math.abs(r-n)<=180?r-n:r-n>180?r-n-360:r-n<-180?r-n+360:0}function ge({C1:e,C2:t,h1_d:n,h2_d:r}){return e*t===0?r+n:Math.abs(n-r)<=180?(r+n)/2:Math.abs(n-r)>180&&n+r<360?(r+n+360)/2:Math.abs(n-r)>180&&n+r>=360?(r+n-360)/2:0}const m=e=>e*(Math.PI/180),z=e=>Math.sqrt(e**7/(e**7+25**7));function b(e,t){const n=e/255,r=t?.03928:.04045;let o;return n>r?o=((n+.055)/1.055)**2.4:o=n/12.92,o}function v(e){const t=.20689655172413793,n=t**3;let r;return e>n?r=Math.cbrt(e):r=e/(3*t**2)+4/29,r}function he(e,t,n){return Math.min(Math.max(e,t),n)}function j(e,t){const n=e.L,r=e.a,o=e.b,a=t.L,s=t.a,f=t.b,c=1,d=1,G=1,g=Math.sqrt(r**2+o**2),h=Math.sqrt(s**2+f**2),fe=a-n,ce=(g+h)/2,P=.5*(1-z(ce)),A=r*(1+P),Y=s*(1+P),B=Math.sqrt(A**2+o**2),$=Math.sqrt(Y**2+f**2),k=(B+$)/2,F=$-B,W=T(o,A),E=T(f,Y),ie=be({C1:g,C2:h,h1_d:W,h2_d:E}),X=2*Math.sqrt(B*$)*Math.sin(m(ie)/2),C=ge({C1:g,C2:h,h1_d:W,h2_d:E}),Z=(n+a)/2,ue=1-.17*Math.cos(m(C-30))+.24*Math.cos(m(2*C))+.32*Math.cos(m(3*C+6))-.2*Math.cos(m(4*C-63)),le=1+.015*(Z-50)**2/Math.sqrt(20+(Z-50)**2),D=.045*k+1,x=1+.015*k*ue,de=30*Math.exp(-(((C-275)/25)**2)),me=-2*z(k)*Math.sin(m(de*2));return Math.sqrt((fe/(c*le))**2+(F/(d*D))**2+(X/(G*x))**2+me*(F/(d*D))*(X/(G*x)))}function O(e){const{R:t,G:n,B:r}=e,o=b(t)*100,a=b(n)*100,s=b(r)*100,f=o*.4124+a*.3576+s*.1805,c=o*.2126+a*.7152+s*.0722,d=o*.0193+a*.1192+s*.9505;return{X:f,Y:c,Z:d}}function U(e){const{X:t,Y:n,Z:r}=e,o=t/95.047,a=n/100,s=r/108.883,f=v(o),c=v(a),d=v(s),G=116*c-16,g=500*(f-c),h=200*(c-d);return{L:G,a:g,b:h}}function w(e){const t=O(e);return U(t)}const V=(e,t)=>{const n=w(e),r=w(t);return j(n,r)},J=/^#[a-fA-F0-9]{6}$/,K=/^#[a-fA-F0-9]{8}$/,Q=/^#[a-fA-F0-9]{3}$/,_=/^#[a-fA-F0-9]{4}$/,ee=/^rgba*\(\s*([-+]?\d+)\s*(?:,)?\s*([-+]?\d+)\s*(?:,)?\s*([-+]?\d+)\s*(?:,*|\/*)\s*([-+]?\d*[.]?\d+[%]?)*\)$/i;function i(e){const t=e.match(ee);if(!t)throw new Error(`convertCSSRGBtoHex expects a valid CSS RGB string but got ${e}`);const n=r=>r?Number.parseFloat(r):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:r}){const o=a=>he(a,0,255).toString(16).padStart(2,"0");return`#${o(e)}${o(t)}${o(n)}${r?o(Math.round(r*255)):""}`}function Ce(e){const t=i(e);return p(t)}const y=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 te(e){for(const[t,n]of y.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(J))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(Q))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(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),A:Number.parseInt(`${e[7]}${e[8]}`,16)/255};if(e.match(_))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:Number.parseInt(`${e[4]}${e[4]}`,16)/255};throw new Error(`convertHextoRGB expects an valid hexadecimal colour value but got ${e}`)}function M(e){return y.get(e)}function R(e){const t=M(e);if(t)return u(t)}function N({R:e,G:t,B:n,A:r}){return`rgb(${e} ${t} ${n}${r?` / ${r}`:""})`}function H(e){const t=p(e);return te(t)}function S(e,t){if(!t||t.length<2)return e;const n=[];for(const o of t){const a=V(e,o);n.push([o,a])}return n.sort((o,a)=>o[1]-a[1])[0][0]}function pe(e,t){if(!t||t.length<2)return e;const n=i(e),r=t.map(a=>i(a)),o=S(n,r);return N(o)}function q(e){return!!e.match(ee)}function ne(e){return!!e.match(J)||!!e.match(K)||!!e.match(_)||!!e.match(Q)}function re(e){return y.has(e)}function Re(e,t){if(!t||t.length<2)return e;let n,r;const o=[];if(ne(e)&&(n=u(e),r="hex"),q(e)&&(n=i(e),r="cssRGB"),re(e)&&(n=R(e),r="namedCSS"),!n)return;for(const s of t)ne(s)&&o.push(u(s)),q(s)&&o.push(i(s)),re(s)&&o.push(R(s));if(o.length<2)return e;const a=S(n,o);if(r==="hex")return p(a);if(r==="cssRGB")return N(a);if(r==="namedCSS")return H(a)}function Se(e,t){if(!t||t.length<2)return e;const n=u(e),r=t.map(a=>u(a)),o=S(n,r);return p(o)}function Ge(e,t){if(!t||t.length<2)return e;const n=R(e),o=t.map(s=>R(s)).filter(s=>s!==void 0);if(!n||o.length<2)return e;const a=S(n,o);return H(a)}function I({R:e,G:t,B:n},r){const o=r==="WCAG2.1",a=b(e,o),s=b(t,o),f=b(n,o);return .2126*a+.7152*s+.0722*f}function l(e,t){const n=u(e);return I(n,t)}function Be(e,t,n){const r=l(e,n),o=l(t,n),a=Math.max(r,o),s=Math.min(r,o),f=(a+.05)/(s+.05);return Math.floor(f*1e3)/1e3}function L(e,t){const n=l(e,t)+.05,r=1.05/n,o=n/.05;return r>o}function oe(e,t){const n=M(e);if(n)return L(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 ae(e,t){const n=i(e),r=I(n,t),o=1.05/r,a=r/.05;return o>a}function $e(e,t){try{return e.startsWith("#")?L(e,t):e.startsWith("rgb")?ae(e,t):oe(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 se=(e,t)=>e>t?e/t:t/e,ke=({backgroundColour:e,optionOneColour:t,optionTwoColour:n},r)=>{const o=l(e,r)+.05,a=l(t,r)+.05,s=l(n,r)+.05,f=se(a,o),c=se(s,o);return f>c?t:n};export{V as RGBdistance,j as ciede2000,Ce as convertCSSRGBtoHex,i as convertCSSRGBtoRGB,te as convertHextoNamedCSSColour,u as convertHextoRGB,M as convertNamedCSSColourtoHex,R as convertNamedCSSColourtoRGB,N as convertRGBtoCSSRGB,p as convertRGBtoHex,w as convertRGBtoLab,H as convertRGBtoNamedCSSColour,O as convertRGBtoXYZ,U as convertXYZtoLab,pe as findNearestCSSRGBColour,Re as findNearestColour,Se as findNearestHexColour,Ge as findNearestNamedCSSColour,S as findNearestRGBColour,Be as getContrastRatioFromHex,l as getSRGBLuminanceFromHex,I as getSRGBLuminanceFromRGB,oe as isCSSNamedDarkColour,q as isCSSRGBColour,ae as isCSSRGBDarkColour,$e as isDarkColour,L as isHexDarkColour,ke as pickHexColourContrast};
1
+ "use strict";function U(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 he({C1:e,C2:t,h1_d:n,h2_d:r}){return e*t===0?0:Math.abs(r-n)<=180?r-n:r-n>180?r-n-360:r-n<-180?r-n+360:0}function Se({C1:e,C2:t,h1_d:n,h2_d:r}){return e*t===0?r+n:Math.abs(n-r)<=180?(r+n)/2:Math.abs(n-r)>180&&n+r<360?(r+n+360)/2:Math.abs(n-r)>180&&n+r>=360?(r+n-360)/2:0}const b=e=>e*(Math.PI/180),j=e=>Math.sqrt(e**7/(e**7+25**7));function g(e,t){const n=e/255,r=t?.03928:.04045;let o;return n>r?o=((n+.055)/1.055)**2.4:o=n/12.92,o}function y(e){const t=.20689655172413793,n=t**3;let r;return e>n?r=Math.cbrt(e):r=e/(3*t**2)+4/29,r}function pe(e,t,n){return Math.min(Math.max(e,t),n)}function O(e,t){const n=e.L,r=e.a,o=e.b,a=t.L,s=t.a,f=t.b,c=1,m=1,$=1,C=Math.sqrt(r**2+o**2),h=Math.sqrt(s**2+f**2),ue=a-n,le=(C+h)/2,P=.5*(1-j(le)),F=r*(1+P),A=s*(1+P),B=Math.sqrt(F**2+o**2),k=Math.sqrt(A**2+f**2),w=(B+k)/2,E=k-B,Y=U(o,F),X=U(f,A),de=he({C1:C,C2:h,h1_d:Y,h2_d:X}),Z=2*Math.sqrt(B*k)*Math.sin(b(de)/2),S=Se({C1:C,C2:h,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,T=1+.015*w*me,ge=30*Math.exp(-(((S-275)/25)**2)),Ce=-2*j(w)*Math.sin(b(ge*2));return Math.sqrt((ue/(c*be))**2+(E/(m*z))**2+(Z/($*T))**2+Ce*(E/(m*z))*(Z/($*T)))}function V(e){const{R:t,G:n,B:r}=e,o=g(t)*100,a=g(n)*100,s=g(r)*100,f=o*.4124+a*.3576+s*.1805,c=o*.2126+a*.7152+s*.0722,m=o*.0193+a*.1192+s*.9505;return{X:f,Y:c,Z:m}}function J(e){const{X:t,Y:n,Z:r}=e,o=t/95.047,a=n/100,s=r/108.883,f=y(o),c=y(a),m=y(s),$=116*c-16,C=500*(f-c),h=200*(c-m);return{L:$,a:C,b:h}}function N(e){const t=V(e);return J(t)}const K=(e,t)=>{const n=N(e),r=N(t);return O(n,r)},Q=/^#[a-fA-F0-9]{6}$/,_=/^#[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=r=>r?Number.parseFloat(r):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:r}){const o=a=>pe(a,0,255).toString(16).padStart(2,"0");return`#${o(e)}${o(t)}${o(n)}${r?o(Math.round(r*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(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)};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(_))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:Number.parseInt(`${e[7]}${e[8]}`,16)/255};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:Number.parseInt(`${e[4]}${e[4]}`,16)/255};throw new Error(`convertHextoRGB expects an valid hexadecimal colour value but got ${e}`)}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:r}){return`rgb(${e} ${t} ${n}${r?` / ${r}`:""})`}function I(e){const t=p(e);return re(t)}function v(e,t){if(!t||t.length<2)return e;const n=[];for(const o of t){const a=K(e,o);n.push([o,a])}return n.sort((o,a)=>o[1]-a[1])[0][0]}function Re(e,t){if(!t||t.length<2)return e;const n=i(e),r=t.map(a=>i(a)),o=v(n,r);return q(o)}function L(e){return!!e.match(ne)}function oe(e){return!!e.match(Q)||!!e.match(_)||!!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,r;const o=[];if(oe(e)&&(n=u(e),r="hex"),L(e)&&(n=i(e),r="cssRGB"),ae(e)&&(n=R(e),r="namedCSS"),!n)return;for(const s of t)oe(s)&&o.push(u(s)),L(s)&&o.push(i(s)),ae(s)&&o.push(R(s));if(o.length<2)return e;const a=v(n,o);if(r==="hex")return p(a);if(r==="cssRGB")return q(a);if(r==="namedCSS")return I(a)}function Ge(e,t){if(!t||t.length<2)return e;const n=u(e),r=t.map(a=>u(a)),o=v(n,r);return p(o)}function $e(e,t){if(!t||t.length<2)return e;const n=R(e),o=t.map(s=>R(s)).filter(s=>s!==void 0);if(!n||o.length<2)return e;const a=v(n,o);return I(a)}function G({R:e,G:t,B:n},r){const o=r==="WCAG2.1",a=g(e,o),s=g(t,o),f=g(n,o);return .2126*a+.7152*s+.0722*f}function d(e,t){const n=u(e);return G(n,t)}function se(e,t){const n=Math.max(e,t),r=Math.min(e,t),o=(n+.05)/(r+.05);return Math.floor(o*1e3)/1e3}function W(e,t,n){const r=d(e,n),o=d(t,n);return se(r,o)}function Be(e,t,n){let r,o;if(e.startsWith("#"))r=e;else if(e.startsWith("rgb"))r=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`);r=a}if(t.startsWith("#"))o=t;else if(t.startsWith("rgb"))o=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`);o=a}return W(r,o,n)}function ke(e,t,n){const r=i(e),o=i(t),a=G(r,n),s=G(o,n);return se(a,s)}function we(e,t,n){const r=l(e),o=l(t);if(r===void 0||o===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(r,o,n)}function x(e,t){const n=d(e,t)+.05,r=1.05/n,o=n/.05;return r>o}function fe(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 ce(e,t){const n=i(e),r=G(n,t),o=1.05/r,a=r/.05;return o>a}function ye(e,t){try{return e.startsWith("#")?x(e,t):e.startsWith("rgb")?ce(e,t):fe(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,Ne=({backgroundColour:e,optionOneColour:t,optionTwoColour:n},r)=>{const o=d(e,r)+.05,a=d(t,r)+.05,s=d(n,r)+.05,f=ie(a,o),c=ie(s,o);return f>c?t:n};export{K as RGBdistance,O as ciede2000,M as convertCSSRGBtoHex,i as convertCSSRGBtoRGB,re as convertHextoNamedCSSColour,u as convertHextoRGB,l as convertNamedCSSColourtoHex,R as convertNamedCSSColourtoRGB,q as convertRGBtoCSSRGB,p as convertRGBtoHex,N as convertRGBtoLab,I as convertRGBtoNamedCSSColour,V as convertRGBtoXYZ,J as convertXYZtoLab,Re as findNearestCSSRGBColour,ve as findNearestColour,Ge as findNearestHexColour,$e as findNearestNamedCSSColour,v as findNearestRGBColour,Be as getContrastRatio,ke as getContrastRatioFromCSSRGB,W as getContrastRatioFromHex,we as getContrastRatioFromNamedCSSColour,d as getSRGBLuminanceFromHex,G as getSRGBLuminanceFromRGB,fe as isCSSNamedDarkColour,L as isCSSRGBColour,ce as isCSSRGBDarkColour,ye as isDarkColour,x as isHexDarkColour,Ne as pickHexColourContrast};
package/dist/index.mjs CHANGED
@@ -516,14 +516,69 @@ function getSRGBLuminanceFromHex(colour, standard) {
516
516
  const rgbColor = convertHextoRGB(colour);
517
517
  return getSRGBLuminanceFromRGB(rgbColor, standard);
518
518
  }
519
- function getContrastRatioFromHex(colour1, colour2, standard) {
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;
@@ -604,7 +659,10 @@ export {
604
659
  findNearestHexColour,
605
660
  findNearestNamedCSSColour,
606
661
  findNearestRGBColour,
662
+ getContrastRatio,
663
+ getContrastRatioFromCSSRGB,
607
664
  getContrastRatioFromHex,
665
+ getContrastRatioFromNamedCSSColour,
608
666
  getSRGBLuminanceFromHex,
609
667
  getSRGBLuminanceFromRGB,
610
668
  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.2.0",
3
+ "version": "2.2.1",
4
4
  "description": "It does things to colours",
5
5
  "type": "module",
6
6
  "module": "./dist/index.mjs",