color-contrast-js 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/API.md +183 -0
- package/CHANGELOG.md +37 -0
- package/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES.md +13 -0
- package/color-contrast.js +2125 -0
- package/color-contrast.min.js +5 -0
- package/index.d.ts +49 -0
- package/package.json +66 -0
- package/readme.md +134 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/*! colorContrast.js v2.0.0 | MIT | includes Culori (MIT) */
|
|
2
|
+
var wt=(e,t)=>{if(typeof e=="number"){if(t===3)return{mode:"rgb",r:(e>>8&15|e>>4&240)/255,g:(e>>4&15|e&240)/255,b:(e&15|e<<4&240)/255};if(t===4)return{mode:"rgb",r:(e>>12&15|e>>8&240)/255,g:(e>>8&15|e>>4&240)/255,b:(e>>4&15|e&240)/255,alpha:(e&15|e<<4&240)/255};if(t===6)return{mode:"rgb",r:(e>>16&255)/255,g:(e>>8&255)/255,b:(e&255)/255};if(t===8)return{mode:"rgb",r:(e>>24&255)/255,g:(e>>16&255)/255,b:(e>>8&255)/255,alpha:(e&255)/255}}},_=wt;var kt={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Ze=kt;var Rt=e=>_(Ze[e.toLowerCase()],6),je=Rt;var Xt=/^#?([0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{4}|[0-9a-f]{3})$/i,Ht=e=>{let t;return(t=e.match(Xt))?_(parseInt(t[1],16),t[1].length):void 0},Ue=Ht;var p="([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)",io=`(?:${p}|none)`,z=`${p}%`,lo=`(?:${p}%|none)`,S=`(?:${p}%|${p})`,St=`(?:${p}%|${p}|none)`,Ke=`(?:${p}(deg|grad|rad|turn)|${p})`,uo=`(?:${p}(deg|grad|rad|turn)|${p}|none)`,y="\\s*,\\s*";var po=new RegExp("^"+St+"$");var At=new RegExp(`^rgba?\\(\\s*${p}${y}${p}${y}${p}\\s*(?:,\\s*${S}\\s*)?\\)$`),Nt=new RegExp(`^rgba?\\(\\s*${z}${y}${z}${y}${z}\\s*(?:,\\s*${S}\\s*)?\\)$`),Pt=e=>{let t={mode:"rgb"},r;if(r=e.match(At))r[1]!==void 0&&(t.r=r[1]/255),r[2]!==void 0&&(t.g=r[2]/255),r[3]!==void 0&&(t.b=r[3]/255);else if(r=e.match(Nt))r[1]!==void 0&&(t.r=r[1]/100),r[2]!==void 0&&(t.g=r[2]/100),r[3]!==void 0&&(t.b=r[3]/100);else return;return r[4]!==void 0?t.alpha=Math.max(0,Math.min(1,r[4]/100)):r[5]!==void 0&&(t.alpha=Math.max(0,Math.min(1,+r[5]))),t},Ve=Pt;var $t=(e,t)=>e===void 0?void 0:typeof e!="object"?A(e):e.mode!==void 0?e:t?{...e,mode:t}:void 0,Qe=$t;var Ct=(e="rgb")=>t=>(t=Qe(t,e))!==void 0?t.mode===e?t:h[t.mode][e]?h[t.mode][e](t):e==="rgb"?h[t.mode].rgb(t):h.rgb[e](h[t.mode].rgb(t)):void 0,N=Ct;var h={},et={},P=[],ne={},It=e=>e,ae=e=>(h[e.mode]={...h[e.mode],...e.toMode},Object.keys(e.fromMode||{}).forEach(t=>{h[t]||(h[t]={}),h[t][e.mode]=e.fromMode[t]}),e.ranges||(e.ranges={}),e.difference||(e.difference={}),e.channels.forEach(t=>{if(e.ranges[t]===void 0&&(e.ranges[t]=[0,1]),!e.interpolate[t])throw new Error(`Missing interpolator for: ${t}`);typeof e.interpolate[t]=="function"&&(e.interpolate[t]={use:e.interpolate[t]}),e.interpolate[t].fixup||(e.interpolate[t].fixup=It)}),et[e.mode]=e,(e.parse||[]).forEach(t=>{tt(t,e.mode)}),N(e.mode)),fe=e=>et[e],tt=(e,t)=>{if(typeof e=="string"){if(!t)throw new Error("'mode' required when 'parser' is a string");ne[e]=t}else typeof e=="function"&&P.indexOf(e)<0&&P.push(e)};var ie=/[^\x00-\x7F]|[a-zA-Z_]/,Ot=/[^\x00-\x7F]|[-\w]/,f={Function:"function",Ident:"ident",Number:"number",Percentage:"percentage",ParenClose:")",None:"none",Hue:"hue",Alpha:"alpha"},l=0;function E(e){let t=e[l],r=e[l+1];return t==="-"||t==="+"?/\d/.test(r)||r==="."&&/\d/.test(e[l+2]):t==="."?/\d/.test(r):/\d/.test(t)}function le(e){if(l>=e.length)return!1;let t=e[l];if(ie.test(t))return!0;if(t==="-"){if(e.length-l<2)return!1;let r=e[l+1];return!!(r==="-"||ie.test(r))}return!1}var qt={deg:1,rad:180/Math.PI,grad:9/10,turn:360};function $(e){let t="";if((e[l]==="-"||e[l]==="+")&&(t+=e[l++]),t+=F(e),e[l]==="."&&/\d/.test(e[l+1])&&(t+=e[l++]+F(e)),(e[l]==="e"||e[l]==="E")&&((e[l+1]==="-"||e[l+1]==="+")&&/\d/.test(e[l+2])?t+=e[l++]+e[l++]+F(e):/\d/.test(e[l+1])&&(t+=e[l++]+F(e))),le(e)){let r=D(e);return r==="deg"||r==="rad"||r==="turn"||r==="grad"?{type:f.Hue,value:t*qt[r]}:void 0}return e[l]==="%"?(l++,{type:f.Percentage,value:+t}):{type:f.Number,value:+t}}function F(e){let t="";for(;/\d/.test(e[l]);)t+=e[l++];return t}function D(e){let t="";for(;l<e.length&&Ot.test(e[l]);)t+=e[l++];return t}function _t(e){let t=D(e);return e[l]==="("?(l++,{type:f.Function,value:t}):t==="none"?{type:f.None,value:void 0}:{type:f.Ident,value:t}}function Et(e=""){let t=e.trim(),r=[],o;for(l=0;l<t.length;){if(o=t[l++],o===`
|
|
3
|
+
`||o===" "||o===" "){for(;l<t.length&&(t[l]===`
|
|
4
|
+
`||t[l]===" "||t[l]===" ");)l++;continue}if(o===",")return;if(o===")"){r.push({type:f.ParenClose});continue}if(o==="+"){if(l--,E(t)){r.push($(t));continue}return}if(o==="-"){if(l--,E(t)){r.push($(t));continue}if(le(t)){r.push({type:f.Ident,value:D(t)});continue}return}if(o==="."){if(l--,E(t)){r.push($(t));continue}return}if(o==="/"){for(;l<t.length&&(t[l]===`
|
|
5
|
+
`||t[l]===" "||t[l]===" ");)l++;let n;if(E(t)&&(n=$(t),n.type!==f.Hue)){r.push({type:f.Alpha,value:n});continue}if(le(t)&&D(t)==="none"){r.push({type:f.Alpha,value:{type:f.None,value:void 0}});continue}return}if(/\d/.test(o)){l--,r.push($(t));continue}if(ie.test(o)){l--,r.push(_t(t));continue}return}return r}function Ft(e){e._i=0;let t=e[e._i++];if(!t||t.type!==f.Function||t.value!=="color"||(t=e[e._i++],t.type!==f.Ident))return;let r=ne[t.value];if(!r)return;let o={mode:r},n=rt(e,!1);if(!n)return;let a=fe(r).channels;for(let i=0,d,g;i<a.length;i++)d=n[i],g=a[i],d.type!==f.None&&(o[g]=d.type===f.Number?d.value:d.value/100,g==="alpha"&&(o[g]=Math.max(0,Math.min(1,o[g]))));return o}function rt(e,t){let r=[],o;for(;e._i<e.length;){if(o=e[e._i++],o.type===f.None||o.type===f.Number||o.type===f.Alpha||o.type===f.Percentage||t&&o.type===f.Hue){r.push(o);continue}if(o.type===f.ParenClose){if(e._i<e.length)return;continue}return}if(!(r.length<3||r.length>4)){if(r.length===4){if(r[3].type!==f.Alpha)return;r[3]=r[3].value}return r.length===3&&r.push({type:f.None,value:void 0}),r.every(n=>n.type!==f.Alpha)?r:void 0}}function Dt(e,t){e._i=0;let r=e[e._i++];if(!r||r.type!==f.Function)return;let o=rt(e,t);if(o)return o.unshift(r.value),o}var Bt=e=>{if(typeof e!="string")return;let t=Et(e),r=t?Dt(t,!0):void 0,o,n=0,a=P.length;for(;n<a;)if((o=P[n++](e,r))!==void 0)return o;return t?Ft(t):void 0},A=Bt;function Wt(e,t){if(!t||t[0]!=="rgb"&&t[0]!=="rgba")return;let r={mode:"rgb"},[,o,n,a,i]=t;if(!(o.type===f.Hue||n.type===f.Hue||a.type===f.Hue))return o.type!==f.None&&(r.r=o.type===f.Number?o.value/255:o.value/100),n.type!==f.None&&(r.g=n.type===f.Number?n.value/255:n.value/100),a.type!==f.None&&(r.b=a.type===f.Number?a.value/255:a.value/100),i.type!==f.None&&(r.alpha=Math.min(1,Math.max(0,i.type===f.Number?i.value:i.value/100))),r}var ot=Wt;var Gt=e=>e==="transparent"?{mode:"rgb",r:0,g:0,b:0,alpha:0}:void 0,nt=Gt;var at=(e,t,r)=>e+r*(t-e);var Jt=e=>{let t=[];for(let r=0;r<e.length-1;r++){let o=e[r],n=e[r+1];o===void 0&&n===void 0?t.push(void 0):o!==void 0&&n!==void 0?t.push([o,n]):t.push(o!==void 0?[o,o]:[n,n])}return t},ft=e=>t=>{let r=Jt(t);return o=>{let n=o*r.length,a=o>=1?r.length-1:Math.max(Math.floor(n),0),i=r[a];return i===void 0?void 0:e(i[0],i[1],n-a)}};var u=ft(at);var m=e=>{let t=!1,r=e.map(o=>o!==void 0?(t=!0,o):1);return t?r:e};var Yt={mode:"rgb",channels:["r","g","b","alpha"],parse:[ot,Ue,Ve,je,nt,"srgb"],serialize:"srgb",interpolate:{r:u,g:u,b:u,alpha:{use:u,fixup:m}},gamut:!0,white:{r:1,g:1,b:1},black:{r:0,g:0,b:0}},s=Yt;var ue=(e=0)=>Math.pow(Math.abs(e),2.19921875)*Math.sign(e),Zt=e=>{let t=ue(e.r),r=ue(e.g),o=ue(e.b),n={mode:"xyz65",x:.5766690429101305*t+.1855582379065463*r+.1882286462349947*o,y:.297344975250536*t+.6273635662554661*r+.0752914584939979*o,z:.0270313613864123*t+.0706888525358272*r+.9913375368376386*o};return e.alpha!==void 0&&(n.alpha=e.alpha),n},de=Zt;var pe=e=>Math.pow(Math.abs(e),.4547069271758437)*Math.sign(e),jt=({x:e,y:t,z:r,alpha:o})=>{e===void 0&&(e=0),t===void 0&&(t=0),r===void 0&&(r=0);let n={mode:"a98",r:pe(e*2.0415879038107465-t*.5650069742788597-.3447313507783297*r),g:pe(e*-.9692436362808798+t*1.8759675015077206+.0415550574071756*r),b:pe(e*.0134442806320312-t*.1183623922310184+1.0151749943912058*r)};return o!==void 0&&(n.alpha=o),n},se=jt;var me=(e=0)=>{let t=Math.abs(e);return t<=.04045?e/12.92:(Math.sign(e)||1)*Math.pow((t+.055)/1.055,2.4)},Ut=({r:e,g:t,b:r,alpha:o})=>{let n={mode:"lrgb",r:me(e),g:me(t),b:me(r)};return o!==void 0&&(n.alpha=o),n},b=Ut;var Kt=e=>{let{r:t,g:r,b:o,alpha:n}=b(e),a={mode:"xyz65",x:.4123907992659593*t+.357584339383878*r+.1804807884018343*o,y:.2126390058715102*t+.715168678767756*r+.0721923153607337*o,z:.0193308187155918*t+.119194779794626*r+.9505321522496607*o};return n!==void 0&&(a.alpha=n),a},v=Kt;var ce=(e=0)=>{let t=Math.abs(e);return t>.0031308?(Math.sign(e)||1)*(1.055*Math.pow(t,.4166666666666667)-.055):e*12.92},Vt=({r:e,g:t,b:r,alpha:o},n="rgb")=>{let a={mode:n,r:ce(e),g:ce(t),b:ce(r)};return o!==void 0&&(a.alpha=o),a},x=Vt;var Qt=({x:e,y:t,z:r,alpha:o})=>{e===void 0&&(e=0),t===void 0&&(t=0),r===void 0&&(r=0);let n=x({r:e*3.2409699419045226-t*1.537383177570094-.4986107602930034*r,g:e*-.9692436362808796+t*1.8759675015077204+.0415550574071756*r,b:e*.0556300796969936-t*.2039769588889765+1.0569715142428784*r});return o!==void 0&&(n.alpha=o),n},M=Qt;var er={...s,mode:"a98",parse:["a98-rgb"],serialize:"a98-rgb",fromMode:{rgb:e=>se(v(e)),xyz65:se},toMode:{rgb:e=>M(de(e)),xyz65:de}},he=er;var tr=e=>(e=e%360)<0?e+360:e,c=tr;var rr=(e,t)=>e.map((r,o,n)=>{if(r===void 0)return r;let a=c(r);return o===0||e[o-1]===void 0?a:t(a-c(n[o-1]))}).reduce((r,o)=>!r.length||o===void 0||r[r.length-1]===void 0?(r.push(o),r):(r.push(o+r[r.length-1]),r),[]),B=e=>rr(e,t=>Math.abs(t)<=180?t:t-360*Math.sign(t));var it=(e,t)=>{if(e.h===void 0||t.h===void 0||!e.s||!t.s)return 0;let r=c(e.h),o=c(t.h),n=Math.sin((o-r+360)/2*Math.PI/180);return 2*Math.sqrt(e.s*t.s)*n};var lt=(e,t)=>{if(e.h===void 0||t.h===void 0||!e.c||!t.c)return 0;let r=c(e.h),o=c(t.h),n=Math.sin((o-r+360)/2*Math.PI/180);return 2*Math.sqrt(e.c*t.c)*n};var W=e=>{let t=e.reduce((o,n)=>{if(n!==void 0){let a=n*Math.PI/180;o.sin+=Math.sin(a),o.cos+=Math.cos(a)}return o},{sin:0,cos:0}),r=Math.atan2(t.sin,t.cos)*180/Math.PI;return r<0?360+r:r};var or=({l:e,a:t,b:r,alpha:o},n="lch")=>{t===void 0&&(t=0),r===void 0&&(r=0);let a=Math.sqrt(t*t+r*r),i={mode:n,l:e,c:a};return a&&(i.h=c(Math.atan2(r,t)*180/Math.PI)),o!==void 0&&(i.alpha=o),i},L=or;var nr=({l:e,c:t,h:r,alpha:o},n="lab")=>{r===void 0&&(r=0);let a={mode:n,l:e,a:t?t*Math.cos(r/180*Math.PI):0,b:t?t*Math.sin(r/180*Math.PI):0};return o!==void 0&&(a.alpha=o),a},w=nr;var T={X:.9642956764295677,Y:1,Z:.8251046025104602},pn={X:.3127/.329,Y:1,Z:(1-.3127-.329)/.329},sn=Math.pow(29,3)/Math.pow(3,3),mn=Math.pow(6,3)/Math.pow(29,3);function be({h:e,s:t,l:r,alpha:o}){e=c(e!==void 0?e:0),t===void 0&&(t=0),r===void 0&&(r=0);let n=r+t*(r<.5?r:1-r),a=n-(n-r)*2*Math.abs(e/60%2-1),i;switch(Math.floor(e/60)){case 0:i={r:n,g:a,b:2*r-n};break;case 1:i={r:a,g:n,b:2*r-n};break;case 2:i={r:2*r-n,g:n,b:a};break;case 3:i={r:2*r-n,g:a,b:n};break;case 4:i={r:a,g:2*r-n,b:n};break;case 5:i={r:n,g:2*r-n,b:a};break;default:i={r:2*r-n,g:2*r-n,b:2*r-n}}return i.mode="rgb",o!==void 0&&(i.alpha=o),i}function xe({r:e,g:t,b:r,alpha:o}){e===void 0&&(e=0),t===void 0&&(t=0),r===void 0&&(r=0);let n=Math.max(e,t,r),a=Math.min(e,t,r),i={mode:"hsl",s:n===a?0:(n-a)/(1-Math.abs(n+a-1)),l:.5*(n+a)};return n-a!==0&&(i.h=(n===e?(t-r)/(n-a)+(t<r)*6:n===t?(r-e)/(n-a)+2:(e-t)/(n-a)+4)*60),o!==void 0&&(i.alpha=o),i}var ar=(e,t)=>{switch(t){case"deg":return+e;case"rad":return e/Math.PI*180;case"grad":return e/10*9;case"turn":return e*360}},ut=ar;var fr=new RegExp(`^hsla?\\(\\s*${Ke}${y}${z}${y}${z}\\s*(?:,\\s*${S}\\s*)?\\)$`),ir=e=>{let t=e.match(fr);if(!t)return;let r={mode:"hsl"};return t[3]!==void 0?r.h=+t[3]:t[1]!==void 0&&t[2]!==void 0&&(r.h=ut(t[1],t[2])),t[4]!==void 0&&(r.s=Math.min(Math.max(0,t[4]/100),1)),t[5]!==void 0&&(r.l=Math.min(Math.max(0,t[5]/100),1)),t[6]!==void 0?r.alpha=Math.max(0,Math.min(1,t[6]/100)):t[7]!==void 0&&(r.alpha=Math.max(0,Math.min(1,+t[7]))),r},dt=ir;function lr(e,t){if(!t||t[0]!=="hsl"&&t[0]!=="hsla")return;let r={mode:"hsl"},[,o,n,a,i]=t;if(o.type!==f.None){if(o.type===f.Percentage)return;r.h=o.value}if(n.type!==f.None){if(n.type===f.Hue)return;r.s=n.value/100}if(a.type!==f.None){if(a.type===f.Hue)return;r.l=a.value/100}return i.type!==f.None&&(r.alpha=Math.min(1,Math.max(0,i.type===f.Number?i.value:i.value/100))),r}var pt=lr;var ur={mode:"hsl",toMode:{rgb:be},fromMode:{rgb:xe},channels:["h","s","l","alpha"],ranges:{h:[0,360]},gamut:"rgb",parse:[pt,dt],serialize:e=>`hsl(${e.h!==void 0?e.h:"none"} ${e.s!==void 0?e.s*100+"%":"none"} ${e.l!==void 0?e.l*100+"%":"none"}${e.alpha<1?` / ${e.alpha}`:""})`,interpolate:{h:{use:u,fixup:B},s:u,l:u,alpha:{use:u,fixup:m}},difference:{h:it},average:{h:W}},ge=ur;var G=Math.pow(29,3)/Math.pow(3,3),J=Math.pow(6,3)/Math.pow(29,3);var ye=e=>Math.pow(e,3)>J?Math.pow(e,3):(116*e-16)/G,dr=({l:e,a:t,b:r,alpha:o})=>{e===void 0&&(e=0),t===void 0&&(t=0),r===void 0&&(r=0);let n=(e+16)/116,a=t/500+n,i=n-r/200,d={mode:"xyz50",x:ye(a)*T.X,y:ye(n)*T.Y,z:ye(i)*T.Z};return o!==void 0&&(d.alpha=o),d},k=dr;var pr=({x:e,y:t,z:r,alpha:o})=>{e===void 0&&(e=0),t===void 0&&(t=0),r===void 0&&(r=0);let n=x({r:e*3.1341359569958707-t*1.6173863321612538-.4906619460083532*r,g:e*-.978795502912089+t*1.916254567259524+.03344273116131949*r,b:e*.07195537988411677-t*.2289768264158322+1.405386058324125*r});return o!==void 0&&(n.alpha=o),n},R=pr;var sr=e=>R(k(e)),Y=sr;var mr=e=>{let{r:t,g:r,b:o,alpha:n}=b(e),a={mode:"xyz50",x:.436065742824811*t+.3851514688337912*r+.14307845442264197*o,y:.22249319175623702*t+.7168870538238823*r+.06061979053616537*o,z:.013923904500943465*t+.09708128566574634*r+.7140993584005155*o};return n!==void 0&&(a.alpha=n),a},X=mr;var ve=e=>e>J?Math.cbrt(e):(G*e+16)/116,cr=({x:e,y:t,z:r,alpha:o})=>{e===void 0&&(e=0),t===void 0&&(t=0),r===void 0&&(r=0);let n=ve(e/T.X),a=ve(t/T.Y),i=ve(r/T.Z),d={mode:"lab",l:116*a-16,a:500*(n-a),b:200*(a-i)};return o!==void 0&&(d.alpha=o),d},H=cr;var hr=e=>{let t=H(X(e));return e.r===e.b&&e.b===e.g&&(t.a=t.b=0),t},Z=hr;function br(e,t){if(!t||t[0]!=="lab")return;let r={mode:"lab"},[,o,n,a,i]=t;if(!(o.type===f.Hue||n.type===f.Hue||a.type===f.Hue))return o.type!==f.None&&(r.l=Math.min(Math.max(0,o.value),100)),n.type!==f.None&&(r.a=n.type===f.Number?n.value:n.value*125/100),a.type!==f.None&&(r.b=a.type===f.Number?a.value:a.value*125/100),i.type!==f.None&&(r.alpha=Math.min(1,Math.max(0,i.type===f.Number?i.value:i.value/100))),r}var st=br;var xr={mode:"lab",toMode:{xyz50:k,rgb:Y},fromMode:{xyz50:H,rgb:Z},channels:["l","a","b","alpha"],ranges:{l:[0,100],a:[-125,125],b:[-125,125]},parse:[st],serialize:e=>`lab(${e.l!==void 0?e.l:"none"} ${e.a!==void 0?e.a:"none"} ${e.b!==void 0?e.b:"none"}${e.alpha<1?` / ${e.alpha}`:""})`,interpolate:{l:u,a:u,b:u,alpha:{use:u,fixup:m}}},C=xr;function gr(e,t){if(!t||t[0]!=="lch")return;let r={mode:"lch"},[,o,n,a,i]=t;if(o.type!==f.None){if(o.type===f.Hue)return;r.l=Math.min(Math.max(0,o.value),100)}if(n.type!==f.None&&(r.c=Math.max(0,n.type===f.Number?n.value:n.value*150/100)),a.type!==f.None){if(a.type===f.Percentage)return;r.h=a.value}return i.type!==f.None&&(r.alpha=Math.min(1,Math.max(0,i.type===f.Number?i.value:i.value/100))),r}var mt=gr;var yr={mode:"lch",toMode:{lab:w,rgb:e=>Y(w(e))},fromMode:{rgb:e=>L(Z(e)),lab:L},channels:["l","c","h","alpha"],ranges:{l:[0,100],c:[0,150],h:[0,360]},parse:[mt],serialize:e=>`lch(${e.l!==void 0?e.l:"none"} ${e.c!==void 0?e.c:"none"} ${e.h!==void 0?e.h:"none"}${e.alpha<1?` / ${e.alpha}`:""})`,interpolate:{h:{use:u,fixup:B},c:u,l:u,alpha:{use:u,fixup:m}},difference:{h:lt},average:{h:W}},I=yr;var vr={...s,mode:"lrgb",toMode:{rgb:x},fromMode:{rgb:b},parse:["srgb-linear"],serialize:"srgb-linear"},Me=vr;var Mr=({r:e,g:t,b:r,alpha:o})=>{e===void 0&&(e=0),t===void 0&&(t=0),r===void 0&&(r=0);let n=Math.cbrt(.412221469470763*e+.5363325372617348*t+.0514459932675022*r),a=Math.cbrt(.2119034958178252*e+.6806995506452344*t+.1073969535369406*r),i=Math.cbrt(.0883024591900564*e+.2817188391361215*t+.6299787016738222*r),d={mode:"oklab",l:.210454268309314*n+.7936177747023054*a-.0040720430116193*i,a:1.9779985324311684*n-2.42859224204858*a+.450593709617411*i,b:.0259040424655478*n+.7827717124575296*a-.8086757549230774*i};return o!==void 0&&(d.alpha=o),d},j=Mr;var Tr=e=>{let t=j(b(e));return e.r===e.b&&e.b===e.g&&(t.a=t.b=0),t},U=Tr;var zr=({l:e,a:t,b:r,alpha:o})=>{e===void 0&&(e=0),t===void 0&&(t=0),r===void 0&&(r=0);let n=Math.pow(e+.3963377773761749*t+.2158037573099136*r,3),a=Math.pow(e-.1055613458156586*t-.0638541728258133*r,3),i=Math.pow(e-.0894841775298119*t-1.2914855480194092*r,3),d={mode:"lrgb",r:4.076741636075957*n-3.3077115392580616*a+.2309699031821044*i,g:-1.2684379732850317*n+2.6097573492876887*a-.3413193760026573*i,b:-.0041960761386756*n-.7034186179359362*a+1.7076146940746117*i};return o!==void 0&&(d.alpha=o),d},K=zr;var Lr=e=>x(K(e)),V=Lr;function wr(e,t){if(!t||t[0]!=="oklab")return;let r={mode:"oklab"},[,o,n,a,i]=t;if(!(o.type===f.Hue||n.type===f.Hue||a.type===f.Hue))return o.type!==f.None&&(r.l=Math.min(Math.max(0,o.type===f.Number?o.value:o.value/100),1)),n.type!==f.None&&(r.a=n.type===f.Number?n.value:n.value*.4/100),a.type!==f.None&&(r.b=a.type===f.Number?a.value:a.value*.4/100),i.type!==f.None&&(r.alpha=Math.min(1,Math.max(0,i.type===f.Number?i.value:i.value/100))),r}var ct=wr;var kr={...C,mode:"oklab",toMode:{lrgb:K,rgb:V},fromMode:{lrgb:j,rgb:U},ranges:{l:[0,1],a:[-.4,.4],b:[-.4,.4]},parse:[ct],serialize:e=>`oklab(${e.l!==void 0?e.l:"none"} ${e.a!==void 0?e.a:"none"} ${e.b!==void 0?e.b:"none"}${e.alpha<1?` / ${e.alpha}`:""})`},Te=kr;function Rr(e,t){if(!t||t[0]!=="oklch")return;let r={mode:"oklch"},[,o,n,a,i]=t;if(o.type!==f.None){if(o.type===f.Hue)return;r.l=Math.min(Math.max(0,o.type===f.Number?o.value:o.value/100),1)}if(n.type!==f.None&&(r.c=Math.max(0,n.type===f.Number?n.value:n.value*.4/100)),a.type!==f.None){if(a.type===f.Percentage)return;r.h=a.value}return i.type!==f.None&&(r.alpha=Math.min(1,Math.max(0,i.type===f.Number?i.value:i.value/100))),r}var ht=Rr;var Xr={...I,mode:"oklch",toMode:{oklab:e=>w(e,"oklab"),rgb:e=>V(w(e,"oklab"))},fromMode:{rgb:e=>L(U(e),"oklch"),oklab:e=>L(e,"oklch")},parse:[ht],serialize:e=>`oklch(${e.l!==void 0?e.l:"none"} ${e.c!==void 0?e.c:"none"} ${e.h!==void 0?e.h:"none"}${e.alpha<1?` / ${e.alpha}`:""})`,ranges:{l:[0,1],c:[0,.4],h:[0,360]}},ze=Xr;var Hr=e=>{let{r:t,g:r,b:o,alpha:n}=b(e),a={mode:"xyz65",x:.486570948648216*t+.265667693169093*r+.1982172852343625*o,y:.2289745640697487*t+.6917385218365062*r+.079286914093745*o,z:0*t+.0451133818589026*r+1.043944368900976*o};return n!==void 0&&(a.alpha=n),a},Le=Hr;var Sr=({x:e,y:t,z:r,alpha:o})=>{e===void 0&&(e=0),t===void 0&&(t=0),r===void 0&&(r=0);let n=x({r:e*2.4934969119414263-t*.9313836179191242-.402710784450717*r,g:e*-.8294889695615749+t*1.7626640603183465+.0236246858419436*r,b:e*.0358458302437845-t*.0761723892680418+.9568845240076871*r},"p3");return o!==void 0&&(n.alpha=o),n},we=Sr;var Ar={...s,mode:"p3",parse:["display-p3"],serialize:"display-p3",fromMode:{rgb:e=>we(v(e)),xyz65:we},toMode:{rgb:e=>M(Le(e)),xyz65:Le}},ke=Ar;var Re=e=>{let t=Math.abs(e);return t>=.001953125?Math.sign(e)*Math.pow(t,.5555555555555556):16*e},Nr=({x:e,y:t,z:r,alpha:o})=>{e===void 0&&(e=0),t===void 0&&(t=0),r===void 0&&(r=0);let n={mode:"prophoto",r:Re(e*1.3457868816471585-t*.2555720873797946-.0511018649755453*r),g:Re(e*-.5446307051249019+t*1.5082477428451466+.0205274474364214*r),b:Re(e*0+t*0+1.2119675456389452*r)};return o!==void 0&&(n.alpha=o),n},Xe=Nr;var He=(e=0)=>{let t=Math.abs(e);return t>=.03125?Math.sign(e)*Math.pow(t,1.8):e/16},Pr=e=>{let t=He(e.r),r=He(e.g),o=He(e.b),n={mode:"xyz50",x:.7977666449006423*t+.1351812974005331*r+.0313477341283922*o,y:.2880748288194013*t+.7118352342418731*r+899369387256e-16*o,z:0*t+0*r+.8251046025104602*o};return e.alpha!==void 0&&(n.alpha=e.alpha),n},Se=Pr;var $r={...s,mode:"prophoto",parse:["prophoto-rgb"],serialize:"prophoto-rgb",fromMode:{xyz50:Xe,rgb:e=>Xe(X(e))},toMode:{xyz50:Se,rgb:e=>R(Se(e))}},Ae=$r;var bt=1.09929682680944,Cr=.018053968510807,Ne=e=>{let t=Math.abs(e);return t>Cr?(Math.sign(e)||1)*(bt*Math.pow(t,.45)-(bt-1)):4.5*e},Ir=({x:e,y:t,z:r,alpha:o})=>{e===void 0&&(e=0),t===void 0&&(t=0),r===void 0&&(r=0);let n={mode:"rec2020",r:Ne(e*1.7166511879712683-t*.3556707837763925-.2533662813736599*r),g:Ne(e*-.6666843518324893+t*1.6164812366349395+.0157685458139111*r),b:Ne(e*.0176398574453108-t*.0427706132578085+.9421031212354739*r)};return o!==void 0&&(n.alpha=o),n},Pe=Ir;var xt=1.09929682680944,Or=.018053968510807,$e=(e=0)=>{let t=Math.abs(e);return t<Or*4.5?e/4.5:(Math.sign(e)||1)*Math.pow((t+xt-1)/xt,1/.45)},qr=e=>{let t=$e(e.r),r=$e(e.g),o=$e(e.b),n={mode:"xyz65",x:.6369580483012911*t+.1446169035862083*r+.1688809751641721*o,y:.262700212011267*t+.6779980715188708*r+.059301716469862*o,z:0*t+.0280726930490874*r+1.0609850577107909*o};return e.alpha!==void 0&&(n.alpha=e.alpha),n},Ce=qr;var _r={...s,mode:"rec2020",fromMode:{xyz65:Pe,rgb:e=>Pe(v(e))},toMode:{xyz65:Ce,rgb:e=>M(Ce(e))},parse:["rec2020"],serialize:"rec2020"},Ie=_r;var Er={mode:"xyz50",parse:["xyz-d50"],serialize:"xyz-d50",toMode:{rgb:R,lab:H},fromMode:{rgb:X,lab:k},channels:["x","y","z","alpha"],ranges:{x:[0,.964],y:[0,.999],z:[0,.825]},interpolate:{x:u,y:u,z:u,alpha:{use:u,fixup:m}}},Oe=Er;var Fr=e=>{let{x:t,y:r,z:o,alpha:n}=e;t===void 0&&(t=0),r===void 0&&(r=0),o===void 0&&(o=0);let a={mode:"xyz50",x:1.0479298208405488*t+.0229467933410191*r-.0501922295431356*o,y:.0296278156881593*t+.990434484573249*r-.0170738250293851*o,z:-.0092430581525912*t+.0150551448965779*r+.7518742899580008*o};return n!==void 0&&(a.alpha=n),a},gt=Fr;var Dr=e=>{let{x:t,y:r,z:o,alpha:n}=e;t===void 0&&(t=0),r===void 0&&(r=0),o===void 0&&(o=0);let a={mode:"xyz65",x:.9554734527042182*t-.0230985368742614*r+.0632593086610217*o,y:-.0283697069632081*t+1.0099954580058226*r+.021041398966943*o,z:.0123140016883199*t-.0205076964334779*r+1.3303659366080753*o};return n!==void 0&&(a.alpha=n),a},yt=Dr;var Br={mode:"xyz65",toMode:{rgb:M,xyz50:gt},fromMode:{rgb:v,xyz50:yt},ranges:{x:[0,.95],y:[0,1],z:[0,1.088]},channels:["x","y","z","alpha"],parse:["xyz","xyz-d65"],serialize:"xyz-d65",interpolate:{x:u,y:u,z:u,alpha:{use:u,fixup:m}}},qe=Br;[s,ge,C,I,Te,ze,ke,he,Ae,Ie,Me,Oe,qe].forEach(ae);var Wr=N("rgb"),Gr={r:0,g:0,b:0,a:1},Jr={r:255,g:255,b:255,a:1},Yr=18*(96/72),Zr=14*(96/72),O={AA:{normal:4.5,large:3},AAA:{normal:7,large:4.5}},Q=(e,t=0,r=1)=>Math.min(r,Math.max(t,e));function Be(e){if(typeof e!="string")return null;let t=A(e.trim());if(!t)return null;let r=Wr(t);return!r||![r.r,r.g,r.b].every(Number.isFinite)?null:{r:Q(r.r)*255,g:Q(r.g)*255,b:Q(r.b)*255,a:Q(r.alpha??1)}}function q(e,t="color"){let r=typeof e=="string"?Be(e):e;if(!(r!==null&&typeof r=="object"&&[r.r,r.g,r.b,r.a].every(Number.isFinite)&&r.r>=0&&r.r<=255&&r.g>=0&&r.g<=255&&r.b>=0&&r.b<=255&&r.a>=0&&r.a<=1))throw new TypeError(`Unsupported ${t}: ${e}`);return r}function ee(e,t){let r=e.a+t.a*(1-e.a);if(r===0)return{r:0,g:0,b:0,a:0};let o=n=>(e[n]*e.a+t[n]*t.a*(1-e.a))/r;return{r:o("r"),g:o("g"),b:o("b"),a:r}}function Mt(e){let t=q(e,"fallback color");if(t.a!==1)throw new TypeError(`Fallback color must be opaque: ${e}`);return t}function Tt(e,t="#fff"){let r=q(e);return r.a<1?ee(r,Mt(t)):r}function _e(e){let t=e/255;return t<=.04045?t/12.92:((t+.055)/1.055)**2.4}function Ee({r:e,g:t,b:r}){return .2126*_e(e)+.7152*_e(t)+.0722*_e(r)}function Fe(e,t){let r=Ee(e),o=Ee(t),n=Math.max(r,o),a=Math.min(r,o);return(n+.05)/(a+.05)}function vt(e){return{aa:e>=O.AA.normal,aaLarge:e>=O.AA.large,aaa:e>=O.AAA.normal,aaaLarge:e>=O.AAA.large}}function De(e,t){if(typeof e!="string"||typeof t!="string")throw new TypeError("Expected AA or AAA and normal or large text");let r=e.toUpperCase(),o=t.toLowerCase(),n=O[r]?.[o];if(n===void 0)throw new TypeError("Expected AA or AAA and normal or large text");return n}function We({r:e,g:t,b:r,a:o}){let n=`${Math.round(e)}, ${Math.round(t)}, ${Math.round(r)}`;return o<1?`rgba(${n}, ${Number(o.toFixed(4))})`:`rgb(${n})`}function jr(e,t){return We(ee(q(e),q(t)))}function te(e,t,{fallback:r="#fff"}={}){let o=Tt(t,r),n=q(e,"foreground color"),a=n.a<1?ee(n,o):n;return Fe(a,o)}function Ge(e,{fallback:t="#fff"}={}){let r=Tt(e,t),o=Fe(r,Gr),n=Fe(r,Jr),a=o>=n;return{color:e,resolvedColor:We(r),luminance:Ee(r),recommendedTextColor:a?"#000000":"#FFFFFF",backgroundTone:a?"light":"dark",contrastWithBlack:o,contrastWithWhite:n,blackText:vt(o),whiteText:vt(n)}}function Je(e,t){return Ge(e,t).backgroundTone}function Ur(e,t=["#000000","#FFFFFF"],r){if(!Array.isArray(t)||t.length===0)throw new TypeError("Candidates must be a non-empty array of colors");return t.reduce((o,n)=>{let a=te(n,e,r);return!o||a>o.ratio?{color:n,ratio:a}:o},null).color}function n0(e,t,{level:r="AA",textSize:o="normal",fallback:n="#fff"}={}){let a=De(r,o);return te(e,t,{fallback:n})>=a}function Kr(e,t){if(!Array.isArray(e))throw new TypeError("Palette must be an array");return e.map(r=>Ge(r,t))}function a0(e,t){if(!Array.isArray(e))throw new TypeError("Palette must be an array");return e.map(r=>e.map(o=>te(r,o,t)))}function zt(e){let t=e.ownerDocument?.defaultView,r=t?.getComputedStyle??globalThis.getComputedStyle;if(typeof r!="function")throw new TypeError("getComputedStyle is not available for this element");return r.bind(t??globalThis)}function Ye(e,{fallback:t="#fff"}={}){let r=zt(e),o=[],n=e;for(;n;){let a=Be(r(n).backgroundColor);if(a&&a.a>0&&(o.push(a),a.a===1))break;n=n.parentElement}return o.some(({a})=>a===1)||o.push(Mt(t)),We(o.reverse().reduce((a,i)=>ee(i,a)))}function Vr(e,{fallback:t="#fff"}={}){let r=zt(e)(e),o=r.color,n=Ye(e,{fallback:t}),a=Number.parseFloat(r.fontSize),i=Number.parseInt(r.fontWeight,10),d=Number.isFinite(i)?i:r.fontWeight==="bold"||r.fontWeight==="bolder"?700:400,g=a>=Yr||a>=Zr&&d>=700,re=g?"large":"normal",oe=te(o,n,{fallback:t});return{foregroundColor:o,backgroundColor:n,fontSize:a,fontWeight:d,textSize:re,isLargeText:g,contrastRatio:oe,aa:oe>=De("AA",re),aaa:oe>=De("AAA",re)}}function Qr(e,t){if(typeof e=="string")return[...t.querySelectorAll(e)];if(e?.classList)return[e];if(e?.[Symbol.iterator])return[...e];throw new TypeError("Expected an element, selector, or iterable of elements")}function Lt(e,{fallback:t="#fff",root:r=globalThis.document,lightClass:o="light",darkClass:n="dark"}={}){if(!r&&typeof e=="string")throw new TypeError("A document or root is required when using a selector");let a=Qr(e,r);for(let i of a){let d=Je(Ye(i,{fallback:t}));i.classList.remove(o,n),i.classList.add(d==="light"?o:n)}return a}var f0=Je,i0=Je,l0=Ge,u0=Be,d0=Ur,p0=jr,s0=Lt,m0=Lt,c0=Ye,h0=Vr,b0=Kr;export{l0 as analyseColour,h0 as analyseElement,b0 as analysePalette,Ge as analyzeColor,Vr as analyzeElement,Kr as analyzePalette,Lt as applyBackgroundTone,s0 as applyColorBrightness,m0 as applyColourBrightness,Je as backgroundTone,Ur as bestTextColor,d0 as bestTextColour,f0 as colorBrightness,i0 as colourBrightness,jr as compositeColors,p0 as compositeColours,a0 as contrastMatrix,te as contrastRatio,Ye as getBackgroundColor,c0 as getBackgroundColour,n0 as meetsContrast,Be as parseColor,u0 as parseColour};
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export type BackgroundTone = "light" | "dark";
|
|
2
|
+
/** @deprecated Use BackgroundTone. */
|
|
3
|
+
export type BrightnessClass = BackgroundTone;
|
|
4
|
+
export type ColorChannels = { r: number; g: number; b: number; a: number };
|
|
5
|
+
export type ContrastCompliance = {
|
|
6
|
+
aa: boolean;
|
|
7
|
+
aaLarge: boolean;
|
|
8
|
+
aaa: boolean;
|
|
9
|
+
aaaLarge: boolean;
|
|
10
|
+
};
|
|
11
|
+
export type ColorOptions = { fallback?: string };
|
|
12
|
+
export type ColorAnalysis = {
|
|
13
|
+
color: string;
|
|
14
|
+
resolvedColor: string;
|
|
15
|
+
luminance: number;
|
|
16
|
+
recommendedTextColor: "#000000" | "#FFFFFF";
|
|
17
|
+
backgroundTone: BrightnessClass;
|
|
18
|
+
contrastWithBlack: number;
|
|
19
|
+
contrastWithWhite: number;
|
|
20
|
+
blackText: ContrastCompliance;
|
|
21
|
+
whiteText: ContrastCompliance;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export function parseColor(value: string): ColorChannels | null;
|
|
25
|
+
export function backgroundTone(color: string, options?: ColorOptions): BackgroundTone;
|
|
26
|
+
export function colorBrightness(color: string, options?: ColorOptions): BackgroundTone;
|
|
27
|
+
export function analyzeColor(color: string, options?: ColorOptions): ColorAnalysis;
|
|
28
|
+
export function contrastRatio(foreground: string, background: string, options?: ColorOptions): number;
|
|
29
|
+
export function bestTextColor(background: string, candidates?: readonly string[], options?: ColorOptions): string;
|
|
30
|
+
export function meetsContrast(foreground: string, background: string, options?: ColorOptions & { level?: "AA" | "AAA"; textSize?: "normal" | "large" }): boolean;
|
|
31
|
+
export function compositeColors(foreground: string, background: string): string;
|
|
32
|
+
export function analyzePalette(colors: readonly string[], options?: ColorOptions): ColorAnalysis[];
|
|
33
|
+
export function contrastMatrix(colors: readonly string[], options?: ColorOptions): number[][];
|
|
34
|
+
export function getBackgroundColor(element: Element, options?: ColorOptions): string;
|
|
35
|
+
export function analyzeElement(element: Element, options?: ColorOptions): {
|
|
36
|
+
foregroundColor: string;
|
|
37
|
+
backgroundColor: string;
|
|
38
|
+
fontSize: number;
|
|
39
|
+
fontWeight: number;
|
|
40
|
+
textSize: "normal" | "large";
|
|
41
|
+
isLargeText: boolean;
|
|
42
|
+
contrastRatio: number;
|
|
43
|
+
aa: boolean;
|
|
44
|
+
aaa: boolean;
|
|
45
|
+
};
|
|
46
|
+
export function applyBackgroundTone(target: Element | Iterable<Element> | string, options?: ColorOptions & { root?: ParentNode; lightClass?: string; darkClass?: string }): Element[];
|
|
47
|
+
export function applyColorBrightness(target: Element | Iterable<Element> | string, options?: ColorOptions & { root?: ParentNode; lightClass?: string; darkClass?: string }): Element[];
|
|
48
|
+
|
|
49
|
+
export { backgroundTone as colourBrightness, analyzeColor as analyseColour, parseColor as parseColour, bestTextColor as bestTextColour, compositeColors as compositeColours, applyBackgroundTone as applyColourBrightness, getBackgroundColor as getBackgroundColour, analyzeElement as analyseElement, analyzePalette as analysePalette };
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "color-contrast-js",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Analyze CSS color contrast and choose accessible foreground colors.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./color-contrast.js",
|
|
7
|
+
"types": "./index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./index.d.ts",
|
|
11
|
+
"import": "./color-contrast.js",
|
|
12
|
+
"default": "./color-contrast.js"
|
|
13
|
+
},
|
|
14
|
+
"./min": {
|
|
15
|
+
"types": "./index.d.ts",
|
|
16
|
+
"import": "./color-contrast.min.js",
|
|
17
|
+
"default": "./color-contrast.min.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"files": [
|
|
22
|
+
"color-contrast.js",
|
|
23
|
+
"color-contrast.min.js",
|
|
24
|
+
"index.d.ts",
|
|
25
|
+
"API.md",
|
|
26
|
+
"CHANGELOG.md",
|
|
27
|
+
"THIRD_PARTY_NOTICES.md"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "node scripts/build.js",
|
|
31
|
+
"check": "node --check color-contrast.js && node --check color-contrast.min.js && node --check jquery.colourbrightness.js && node --check jquery.colourbrightness.min.js && npm run check:types && node --test",
|
|
32
|
+
"check:types": "tsc",
|
|
33
|
+
"test": "node --test",
|
|
34
|
+
"prepack": "npm run build && npm run check"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"colour",
|
|
38
|
+
"color",
|
|
39
|
+
"brightness",
|
|
40
|
+
"contrast",
|
|
41
|
+
"accessibility",
|
|
42
|
+
"wcag",
|
|
43
|
+
"luminance",
|
|
44
|
+
"palette",
|
|
45
|
+
"oklch"
|
|
46
|
+
],
|
|
47
|
+
"author": "Jamie Brittain",
|
|
48
|
+
"license": "MIT",
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "git+https://github.com/jamiebrittain/colorContrast.js.git"
|
|
52
|
+
},
|
|
53
|
+
"bugs": {
|
|
54
|
+
"url": "https://github.com/jamiebrittain/colorContrast.js/issues"
|
|
55
|
+
},
|
|
56
|
+
"homepage": "https://github.com/jamiebrittain/colorContrast.js#readme",
|
|
57
|
+
"engines": {
|
|
58
|
+
"node": ">=22"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"culori": "^4.0.2",
|
|
62
|
+
"esbuild": "^0.28.1",
|
|
63
|
+
"terser": "^5.49.0",
|
|
64
|
+
"typescript": "^7.0.2"
|
|
65
|
+
}
|
|
66
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# colorContrast.js
|
|
2
|
+
|
|
3
|
+
Analyze CSS color contrast, check WCAG compliance, and choose accessible foreground colors. It is a browser-ready, ESM-only module with TypeScript declarations and no runtime dependencies for consumers.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
After publication:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install color-contrast-js
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
import {
|
|
15
|
+
backgroundTone,
|
|
16
|
+
analyzeColor,
|
|
17
|
+
contrastRatio,
|
|
18
|
+
} from "color-contrast-js";
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick start
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
backgroundTone("#336699"); // "dark" — use light text
|
|
25
|
+
backgroundTone("tomato"); // "light" — use dark text
|
|
26
|
+
|
|
27
|
+
contrastRatio("#000", "#fff"); // 21
|
|
28
|
+
|
|
29
|
+
analyzeColor("oklch(65% 0.2 30)");
|
|
30
|
+
// Color, luminance, black/white contrast, recommended text,
|
|
31
|
+
// background tone, and WCAG AA/AAA results.
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The tone describes the background, so it can be used as a class name:
|
|
35
|
+
|
|
36
|
+
```css
|
|
37
|
+
.light { color: #000; }
|
|
38
|
+
.dark { color: #fff; }
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Common tasks
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
bestTextColor("#336699", ["#fff", "#000", "#ff0"]); // "#fff"
|
|
45
|
+
|
|
46
|
+
meetsContrast("#000", "#FF5733", {
|
|
47
|
+
level: "AA",
|
|
48
|
+
textSize: "normal",
|
|
49
|
+
}); // true
|
|
50
|
+
|
|
51
|
+
compositeColors("rgb(0 0 0 / 50%)", "#fff");
|
|
52
|
+
// "rgb(128, 128, 128)"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Analyze an element using its computed foreground, composited background, font size, and font weight:
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
const result = analyzeElement(document.querySelector(".sample"));
|
|
59
|
+
|
|
60
|
+
result.contrastRatio;
|
|
61
|
+
result.textSize; // "normal" or "large"
|
|
62
|
+
result.aa;
|
|
63
|
+
result.aaa;
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Or apply a background-tone class to elements:
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
applyBackgroundTone(".sample", {
|
|
70
|
+
lightClass: "on-light",
|
|
71
|
+
darkClass: "on-dark",
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## API
|
|
76
|
+
|
|
77
|
+
| API | Purpose |
|
|
78
|
+
| --- | --- |
|
|
79
|
+
| `backgroundTone(color, options)` | Classify a background as `"light"` or `"dark"` |
|
|
80
|
+
| `analyzeColor(color, options)` | Return luminance, recommendations, contrast, and compliance |
|
|
81
|
+
| `contrastRatio(first, second, options)` | Compare two colors from 1 to 21 |
|
|
82
|
+
| `bestTextColor(background, candidates, options)` | Choose the strongest supplied foreground |
|
|
83
|
+
| `meetsContrast(foreground, background, options)` | Check WCAG AA or AAA |
|
|
84
|
+
| `compositeColors(foreground, background)` | Resolve the visible result of transparency |
|
|
85
|
+
| `parseColor(color)` | Parse a CSS color into RGBA channels |
|
|
86
|
+
| `analyzePalette(colors, options)` | Analyze every color in a palette |
|
|
87
|
+
| `contrastMatrix(colors, options)` | Calculate all palette contrast pairs |
|
|
88
|
+
| `getBackgroundColor(element, options)` | Resolve a composited DOM background |
|
|
89
|
+
| `analyzeElement(element, options)` | Check computed element contrast and WCAG results |
|
|
90
|
+
| `applyBackgroundTone(target, options)` | Apply tone classes to DOM elements |
|
|
91
|
+
|
|
92
|
+
See the complete [API reference](API.md) for parameters, return values, options, examples, and TypeScript types.
|
|
93
|
+
|
|
94
|
+
The historical `colorBrightness`, `colourBrightness`, `applyColorBrightness`, and `applyColourBrightness` names remain as compatibility aliases. New code should use `backgroundTone` and `applyBackgroundTone` because their names make the result unambiguous.
|
|
95
|
+
|
|
96
|
+
## Supported colors
|
|
97
|
+
|
|
98
|
+
- HEX, RGB, RGBA, HSL, and HSLA
|
|
99
|
+
- CSS named colors such as `tomato`
|
|
100
|
+
- `lab()`, `lch()`, `oklab()`, and `oklch()`
|
|
101
|
+
- `color()` spaces including sRGB, linear sRGB, Display P3, A98 RGB, ProPhoto RGB, Rec. 2020, and XYZ
|
|
102
|
+
|
|
103
|
+
Wide-gamut colors are converted to sRGB and clipped to the sRGB gamut before the WCAG 2 contrast calculation. Alpha values and CSS percentage syntax are supported.
|
|
104
|
+
|
|
105
|
+
## Which build should I use?
|
|
106
|
+
|
|
107
|
+
Both builds expose the same API:
|
|
108
|
+
|
|
109
|
+
- `color-contrast.js` is the readable ES module and the default npm entry. Use `import ... from "color-contrast-js"` in applications and libraries. Your bundler can minify it as part of the final build.
|
|
110
|
+
- `color-contrast.min.js` is the pre-minified ES module for direct browser or CDN use. npm consumers can explicitly import `color-contrast-js/min`, although this is rarely necessary.
|
|
111
|
+
|
|
112
|
+
Keeping the readable build makes debugging, code review, source attribution, and unbundled development easier. The minified build provides the smaller delivery option; it should not be the only published file.
|
|
113
|
+
|
|
114
|
+
The package is ESM-only. Use `import` rather than CommonJS `require()`.
|
|
115
|
+
|
|
116
|
+
## Live example
|
|
117
|
+
|
|
118
|
+
[hex.madebynifty.com](https://hex.madebynifty.com/) uses colorContrast.js to keep its text readable as the background changes.
|
|
119
|
+
|
|
120
|
+
## Development
|
|
121
|
+
|
|
122
|
+
Requires Node.js 22 or newer for development:
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
npm install
|
|
126
|
+
npm run build
|
|
127
|
+
npm run check
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
See [CHANGELOG.md](CHANGELOG.md) and [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
|
131
|
+
|
|
132
|
+
## License
|
|
133
|
+
|
|
134
|
+
[MIT](LICENSE) © 2013–2026 Jamie Brittain.
|