chromametry 0.3.1 → 0.3.2
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/README.md +11 -46
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.global.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -68,7 +68,7 @@ npm install chromametry
|
|
|
68
68
|
|
|
69
69
|
### Usage
|
|
70
70
|
```ts
|
|
71
|
-
import {
|
|
71
|
+
import { Ramp, Swatch } from "chromametry";
|
|
72
72
|
|
|
73
73
|
const blue = new Ramp([
|
|
74
74
|
"#ffffff",
|
|
@@ -89,39 +89,18 @@ console.log(blue.baseColor);
|
|
|
89
89
|
console.log(blue.wcag[45].span);
|
|
90
90
|
console.log(blue.metrics);
|
|
91
91
|
console.log(blue.score);
|
|
92
|
+
console.log(blue.direction);
|
|
92
93
|
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
"#ffffff",
|
|
97
|
-
"#fff2e8",
|
|
98
|
-
"#ffd9be",
|
|
99
|
-
"#ffb784",
|
|
100
|
-
"#ff832b",
|
|
101
|
-
"#eb6200",
|
|
102
|
-
"#ba4e00",
|
|
103
|
-
"#8a3800",
|
|
104
|
-
"#5e2900",
|
|
105
|
-
"#3e1a00",
|
|
106
|
-
"#231000",
|
|
107
|
-
"#000000",
|
|
108
|
-
],
|
|
109
|
-
}, "My Brand");
|
|
110
|
-
|
|
111
|
-
console.log(brand.metrics);
|
|
112
|
-
console.log(brand.wcag[45]);
|
|
113
|
-
console.log(brand.score);
|
|
114
|
-
|
|
115
|
-
const shade = new Shade("#2378c3");
|
|
116
|
-
console.log(shade.lab);
|
|
117
|
-
console.log(shade.chroma);
|
|
94
|
+
const swatch = new Swatch("#2378c3");
|
|
95
|
+
console.log(swatch.lab);
|
|
96
|
+
console.log(swatch.chroma);
|
|
118
97
|
```
|
|
119
98
|
|
|
120
99
|
### Browser
|
|
121
100
|
**ESM**
|
|
122
101
|
```html
|
|
123
102
|
<script type="module">
|
|
124
|
-
import {
|
|
103
|
+
import { Ramp } from "https://esm.sh/chromametry";
|
|
125
104
|
|
|
126
105
|
const ramp = new Ramp(["#ffffff", "#2378c3", "#000000"], "blue");
|
|
127
106
|
console.log(ramp.score);
|
|
@@ -138,16 +117,16 @@ console.log(shade.chroma);
|
|
|
138
117
|
```
|
|
139
118
|
|
|
140
119
|
### Class Reference
|
|
141
|
-
####
|
|
120
|
+
#### Swatch
|
|
142
121
|
| Property | Description |
|
|
143
122
|
| :--- | :--- |
|
|
144
|
-
| `constructor(hex)` | Create a
|
|
123
|
+
| `constructor(hex)` | Create a swatch from a hex color string. |
|
|
145
124
|
| `hex` | Original hex color. |
|
|
146
125
|
| `rgb` | Linear RGB values. |
|
|
147
126
|
| `lab` | CIELAB coordinates. |
|
|
148
127
|
| `lch` | LCH coordinates derived from LAB. |
|
|
149
128
|
| `lightness` | Perceptual lightness with Helmholtz-Kohlrausch correction. |
|
|
150
|
-
| `chroma` | Chroma of the
|
|
129
|
+
| `chroma` | Chroma of the swatch. |
|
|
151
130
|
| `hue` | Hue angle in degrees. |
|
|
152
131
|
| `luminance` | Relative luminance used for contrast. |
|
|
153
132
|
| `wcag` | WCAG contrast ratio against white. |
|
|
@@ -158,9 +137,10 @@ console.log(shade.chroma);
|
|
|
158
137
|
| :--- | :--- |
|
|
159
138
|
| `constructor(colors, name?)` | Create a sequential ramp from hex colors. |
|
|
160
139
|
| `name` | Ramp name. |
|
|
161
|
-
| `
|
|
140
|
+
| `swatches` | `Swatch[]` built from the input colors. |
|
|
162
141
|
| `colors` | Original ramp colors as hex strings. |
|
|
163
142
|
| `steps` | Number of steps in the ramp. |
|
|
143
|
+
| `direction` | Whether the ramp trends from light to dark or dark to light. |
|
|
164
144
|
| `peakChroma` | Hex color with the highest chroma in the inner ramp. |
|
|
165
145
|
| `baseColor` | Base color used as the ramp anchor. |
|
|
166
146
|
| `baseIndex` | Index of the base color. |
|
|
@@ -177,21 +157,6 @@ console.log(shade.chroma);
|
|
|
177
157
|
| `metrics` | Object containing the five ramp metrics. |
|
|
178
158
|
| `score` | Composite ramp score. |
|
|
179
159
|
|
|
180
|
-
#### Palette
|
|
181
|
-
| Property | Description |
|
|
182
|
-
| :--- | :--- |
|
|
183
|
-
| `constructor(colors, name?)` | Create a palette from named ramps. |
|
|
184
|
-
| `name` | Palette name. |
|
|
185
|
-
| `ramps` | `Ramp[]` built from the input record. |
|
|
186
|
-
| `colors` | Original palette colors as `Record<string, string[]>`. |
|
|
187
|
-
| `steps` | Number of steps shared by the ramps. |
|
|
188
|
-
| `direction` | Ramp direction inferred from the first ramp. |
|
|
189
|
-
| `wcag` | Palette-level WCAG contrast spans aggregated across ramps. |
|
|
190
|
-
| `apca` | Palette-level APCA contrast spans aggregated across ramps. |
|
|
191
|
-
| `contrasts` | Combined contrast object with `wcag` and `apca`. |
|
|
192
|
-
| `metrics` | Object containing the five palette metrics aggregated from ramps. |
|
|
193
|
-
| `score` | Composite palette score. |
|
|
194
|
-
|
|
195
160
|
## Reproducing Benchmarks
|
|
196
161
|
To run the benchmark generator locally:
|
|
197
162
|
```bash
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var L=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var V=(u,n)=>{for(var t in n)L(u,t,{get:n[t],enumerable:!0})},W=(u,n,t,s)=>{if(n&&typeof n=="object"||typeof n=="function")for(let e of N(n))!U.call(u,e)&&e!==t&&L(u,e,{get:()=>n[e],enumerable:!(s=G(n,e))||s.enumerable});return u};var $=u=>W(L({},"__esModule",{value:!0}),u);var st={};V(st,{Ramp:()=>y,Swatch:()=>I,calcDeltaE2000:()=>v,calcScore:()=>P,calcStatistics:()=>nt,createMonotone:()=>k,cssRgbToRgb:()=>Q,fromLightnessEAL:()=>j,hexToRgb:()=>w,labToLch:()=>R,labToRgb:()=>J,lchToLab:()=>O,rgbToHex:()=>Z,rgbToLab:()=>C,rootMeanSquare:()=>tt,toLightnessEAL:()=>_});module.exports=$(st);var F=u=>{let n=t=>{let s=Math.max(0,Math.min(1,t)),e=s<=.0031308?12.92*s:1.055*Math.pow(s,1/2.4)-.055;return Math.max(0,Math.min(255,Math.round(e*255)))};return u.map(n)},K=u=>{let n=t=>t>.04045?Math.pow((t+.055)/1.055,2.4):t/12.92;return u.map(n)},Z=u=>{let[n,t,s]=F(u);return n=n.toString(16).padStart(2,"0"),t=t.toString(16).padStart(2,"0"),s=s.toString(16).padStart(2,"0"),`#${n}${t}${s}`},w=u=>{let n=parseInt(u.slice(1,3),16)/255,t=parseInt(u.slice(3,5),16)/255,s=parseInt(u.slice(5,7),16)/255;return K([n,t,s])},_=u=>{let[n,t,s]=u,e=Math.sqrt(t*t+s*s),a=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,m=.0603,r=.1307,i=.006,l=c*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+m,o=0;return(a<=90||a>=270)&&(o=r*Math.abs(Math.cos(a*(Math.PI/180)))+i),n+(l+o)*e},j=(u,n)=>{let[,t,s]=n,e=Math.sqrt(t*t+s*s),a=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,m=.0603,r=.1307,i=.006,l=c*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+m,o=0;return(a<=90||a>=270)&&(o=r*Math.abs(Math.cos(a*(Math.PI/180)))+i),Math.max(0,u-(l+o)*e)},O=u=>{let[n,t,s]=u,e=s*Math.PI/180;return[n,t*Math.cos(e),t*Math.sin(e)]},C=u=>{let[n,t,s]=u,e=.4124564*n+.3575761*t+.1804375*s,h=.2126729*n+.7151522*t+.072175*s,a=.0193339*n+.119192*t+.9503041*s,c=.95047,m=1,r=1.08883,i=b=>b>.008856?Math.cbrt(b):7.787*b+16/116,l=i(e/c),o=i(h/m),M=i(a/r);return[116*o-16,500*(l-o),200*(o-M)]},J=u=>{let[n,t,s]=u,e=(n+16)/116,h=t/500+e,a=e-s/200,c=b=>b**3>.008856?b**3:(b-16/116)/7.787,m=.95047,r=1,i=1.08883,l=c(h)*m,o=c(e)*r,M=c(a)*i;return[3.2404542*l-1.5371385*o-.4985314*M,-.969266*l+1.8760108*o+.041556*M,.0556434*l-.2040259*o+1.0572252*M]},R=u=>{let[n,t,s]=u,e=Math.sqrt(t*t+s*s);if(e<1e-4)return[n,0,0];let a=(Math.atan2(s,t)*180/Math.PI+360)%360;return a>=359.9999&&(a=0),[n,e,a]},v=(u,n)=>{let[t,s,e]=u,[h,a,c]=n,m=(t+h)/2,r=Math.sqrt(s*s+e*e),i=Math.sqrt(a*a+c*c),l=(r+i)/2,o=.5*(1-Math.sqrt(Math.pow(l,7)/(Math.pow(l,7)+Math.pow(25,7)))),M=s*(1+o),b=a*(1+o),f=Math.sqrt(M*M+e*e),p=Math.sqrt(b*b+c*c),d=(f+p)/2,x=Math.atan2(e,M)*180/Math.PI+(Math.atan2(e,M)<0?360:0),g=Math.atan2(c,b)*180/Math.PI+(Math.atan2(c,b)<0?360:0),q=g-x;Math.abs(q)>180&&(q+=g<=x?360:-360);let S=Math.abs(x-g)>180?(x+g+360)/2:(x+g)/2,H=1-.17*Math.cos((S-30)*Math.PI/180)+.24*Math.cos(2*S*Math.PI/180)+.32*Math.cos((3*S+6)*Math.PI/180)-.2*Math.cos((4*S-63)*Math.PI/180),Y=h-t,E=p-f,T=2*Math.sqrt(f*p)*Math.sin(q/2*Math.PI/180),A=1+.015*Math.pow(m-50,2)/Math.sqrt(20+Math.pow(m-50,2)),B=1+.045*d,D=1+.015*d*H,X=30*Math.exp(-Math.pow((S-275)/25,2)),z=-(2*Math.sqrt(Math.pow(d,7)/(Math.pow(d,7)+Math.pow(25,7))))*Math.sin(2*X*Math.PI/180);return Math.sqrt(Math.pow(Y/A,2)+Math.pow(E/B,2)+Math.pow(T/D,2)+z*(E/B)*(T/D))},Q=u=>{let n=u.match(/\d+(\.\d+)?/g);if(!n||n.length<3)throw new Error("Invalid CSS rgb()");let t=s=>{let e=s/255;return e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4)};return[t(Number(n[0])),t(Number(n[1])),t(Number(n[2]))]},k=u=>{if(u.length<1)return r=>0;let n=[...u].sort((r,i)=>r[0]-i[0]),t=[];for(let r=0;r<n.length;r++)(r===0||n[r][0]!==n[r-1][0])&&t.push(n[r]);let s=t.length;if(s===1)return r=>t[0][1];let e=t.map(r=>r[0]),h=t.map(r=>r[1]),a=[],c=[];for(let r=0;r<s-1;r++)a[r]=e[r+1]-e[r],c[r]=(h[r+1]-h[r])/a[r];let m=new Array(s);m[0]=c[0],m[s-1]=c[s-2];for(let r=1;r<s-1;r++){let i=c[r-1],l=c[r];if(i*l<=0)m[r]=0;else{let o=(1+a[r]/(a[r-1]+a[r]))/3;m[r]=i*l/((1-o)*i+o*l)}}return r=>{if(r<=e[0])return h[0];if(r>=e[s-1])return h[s-1];let i=0,l=s-2,o=0;for(;i<=l;){let g=Math.floor((i+l)/2);if(r>=e[g]&&r<=e[g+1]){o=g;break}r<e[g]?l=g-1:i=g+1}let M=a[o],b=(r-e[o])/M,f=b*b,p=f*b,d=m[o]*M,x=m[o+1]*M;return(2*p-3*f+1)*h[o]+(p-2*f+b)*d+(-2*p+3*f)*h[o+1]+(p-f)*x}};function tt(u){let n=u.length;if(n===0)return 0;let t=0;for(let s=0;s<n;s++)t+=u[s]*u[s];return Math.sqrt(t/n)}var nt=u=>{let n=u.length;if(n===0)return{min:0,max:0,avg:0};let t=u[0],s=u[0],e=0;for(let h=0;h<n;h++){let a=u[h];a<t&&(t=a),a>s&&(s=a),e+=a}return{min:t,max:s,avg:e/n}},P=u=>{let n=u.length;if(n===0)return 0;let t=1e-6,s=u.reduce((a,c)=>a*(c+t),1),e=Math.pow(s,1/n),h=Math.max(0,Math.min(1,e));return parseFloat((h*100).toFixed(2))};var I=class{constructor(n){this.hex=n}get rgb(){return w(this.hex)}get lab(){return C(this.rgb)}get lch(){return R(this.lab)}get lightness(){let[n,t,s]=this.lab,e=Math.sqrt(t*t+s*s),a=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,m=.0603,r=.1307,i=.006,l=c*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+m,o=0;return(a<=90||a>=270)&&(o=r*Math.abs(Math.cos(a*(Math.PI/180)))+i),n+(l+o)*e}get chroma(){return this.lch[1]}get hue(){return this.lch[2]}get luminance(){let[n,t,s]=this.rgb;return .2126*n+.7152*t+.0722*s}get wcag(){return(Math.max(this.luminance,1)+.05)/(Math.min(this.luminance,1)+.05)}get apca(){let n=h=>h>5e-4?h:h+Math.pow(5e-4-h,.8),t=n(this.luminance),s=n(1),e=(Math.pow(t,.56)-Math.pow(s,.56))*100;return Math.abs(e)<.1?0:(e=e>0?e<1?0:e-.25:e>-1?0:e+.25,Math.round(e))}};var y=class{constructor(n=[],t="brand"){this.swatches=n.map(s=>new I(s)),this.name=t}get colors(){return this.swatches.map(n=>n.hex)}get peakChroma(){let n=this.colors.slice(2,-2),t="",s=-1/0;for(let e of n){let h=new I(e);h.chroma>s&&(s=h.chroma,t=e)}return s<6?this.colors[Math.ceil(this.steps/2)]:t}get steps(){return this.colors.length}get direction(){if(this.colors.length===0)return"lighten";let n=C(w(this.colors[0])),t=C(w(this.colors[this.colors.length-1]));return n[0]>t[0]?"darken":"lighten"}get baseColor(){return this.colors.length===0?"":this.peakChroma||this.colors[Math.floor(this.colors.length/2)]}get baseIndex(){return this.colors.length===0?-1:this.colors.findIndex(n=>n.toLowerCase()===this.baseColor.toLowerCase())}get wcag(){let n=this.swatches,t=n.length,s=t-1,e={};for(let h of[30,45,70]){let a=h/10,c=s,m=0;for(let r=1;r<t;r++){let i=1/0;for(let l=0;l<t-r;l++){let o=n[l].luminance,M=n[l+r].luminance,b=(Math.max(o,M)+.05)/(Math.min(o,M)+.05);b<i&&(i=b)}if(i>=a){c=r,m=i;break}r===s&&(m=i)}e[h]={efficiency:c/s,target:a,span:c,value:m}}return e}get apca(){let n=this.swatches,t=n.length,s=t-1,e={},h=(a,c)=>{let i=a<.022?a+Math.pow(.022-a,1.414):a,l=c<.022?c+Math.pow(.022-c,1.414):c,o=l>=i?(Math.pow(l,.56)-Math.pow(i,.57))*114:(Math.pow(l,.65)-Math.pow(i,.62))*114;return Math.abs(o)<10?0:(o=o>0?o-2.7:o+2.7,Math.round(o))};for(let a of[45,60,75]){let c=a,m=s,r=0;for(let i=1;i<t;i++){let l=1/0;for(let o=0;o<t-i;o++){let M=n[o].luminance>n[o+i].luminance?n[o].luminance:n[o+i].luminance,b=n[o].luminance>n[o+i].luminance?n[o+i].luminance:n[o].luminance,f=Math.abs(h(b,M));f<l&&(l=f)}if(l>=c){m=i,r=l;break}i===s&&(r=l)}e[a]={efficiency:m/s,target:c,span:m,value:r}}return e}get contrasts(){return{wcag:this.wcag,apca:this.apca}}get deltaECurve(){let n=[0];for(let t=1;t<this.swatches.length;t++){let s=v(this.swatches[t-1].lab,this.swatches[t].lab);n.push(n[t-1]+s)}return n}get unwrapHues(){let n=this.swatches.map(s=>s.hue).slice(1,-1);if(n.length===0)return[];let t=[n[0]];for(let s=1;s<n.length;s++){let e=n[s]-n[s-1];e>180?e-=360:e<-180&&(e+=360),t.push(t[s-1]+e)}return t}get lightnessLinearity(){let n=this.swatches.map(M=>M.lightness),t=n.length;if(t<2)return 1;let s=0,e=0,h=0,a=0;for(let M=0;M<t;M++)s+=M,e+=n[M],h+=M*n[M],a+=M*M;let c=t*a-s*s;if(Math.abs(c)<1e-10)return 1;let m=(t*h-s*e)/c,r=(e-m*s)/t;if(Math.abs(m*(t-1))<.001)return 1;let l=0,o=0;for(let M=0;M<t;M++){let b=m*M+r,f=n[M]-b;l+=f*f;let p=Math.max(b-Math.min(r,m*(t-1)+r),Math.max(r,m*(t-1)+r)-b);o+=p*p}return Math.max(0,Math.min(1,1-Math.sqrt(l/t)/Math.sqrt(o/t)))}get chromaSmoothness(){let n=this.swatches.map(o=>o.chroma),t=n.length;if(t<3)return 1;let s=133.8,e=Math.max(...n);if(e<=.01)return 1;let h=n.map(o=>o/e*s),a=Math.min(...h),c=Math.max(...h),m=h.findIndex(o=>o===c),r=k([[0,h[0]],[m,c],[t-1,h[t-1]]]),i=0,l=0;for(let o=0;o<t;o++){let M=r(o),b=h[o]-M;i+=b*b,l+=Math.pow(Math.max(M-a,c-M),2)}return Math.max(0,Math.min(1,1-Math.sqrt(i/t)/Math.sqrt(l/t)))}get spacingUniformity(){let n=this.deltaECurve,t=n.length;if(t<2)return 1;let s=[];for(let c=1;c<t;c++){let m=n[c]-n[c-1];if(m<0)return 0;s.push(m)}let e=s.reduce((c,m)=>c+m,0)/s.length;if(e<=1e-6)return 0;let h=0;for(let c of s)h+=Math.pow(c-e,2);let a=Math.sqrt(h/s.length)/e;return Math.max(0,Math.min(1,1/(1+a)))}get hueStability(){var a,c,m;let n=this.unwrapHues,t=n.length;if(t<2)return 1;let s=(m=(c=n[this.baseIndex-1])!=null?c:(a=this.swatches[this.baseIndex])==null?void 0:a.hue)!=null?m:0,e=0,h=0;for(let r=0;r<t;r++){let i=Math.abs(n[r]-s)%360;i>180&&(i=360-i),e+=i*i;let l=r/(t-1)*180;h+=l*l}return Math.max(0,Math.min(1,1-Math.sqrt(e/t)/(Math.sqrt(h/t)||1)))}get contrastEfficiency(){let n=this.wcag[45].span,t=this.steps;if(t<=1)return 1;let s=.5,e=n/t,h=s*((t-1)/t);return e<=h?1:e>=1?0:(1-e)/(1-h)}get metrics(){return{lightnessLinearity:this.lightnessLinearity,chromaSmoothness:this.chromaSmoothness,spacingUniformity:this.spacingUniformity,hueStability:this.hueStability,contrastEfficiency:this.contrastEfficiency}}get score(){return P(Object.values(this.metrics))}};0&&(module.exports={Ramp,Swatch,calcDeltaE2000,calcScore,calcStatistics,createMonotone,cssRgbToRgb,fromLightnessEAL,hexToRgb,labToLch,labToRgb,lchToLab,rgbToHex,rgbToLab,rootMeanSquare,toLightnessEAL});
|
package/dist/index.d.cts
CHANGED
|
@@ -35,7 +35,7 @@ declare const calcStatistics: (array: number[]) => {
|
|
|
35
35
|
/** Calculate geometric mean score (0-100) from metrics. */
|
|
36
36
|
declare const calcScore: (metrics: number[]) => number;
|
|
37
37
|
|
|
38
|
-
declare class
|
|
38
|
+
declare class Swatch {
|
|
39
39
|
readonly hex: string;
|
|
40
40
|
constructor(hex: string);
|
|
41
41
|
get rgb(): number[];
|
|
@@ -58,12 +58,13 @@ type ContrastValue = {
|
|
|
58
58
|
type WcagContrasts = Record<30 | 45 | 70, ContrastValue>;
|
|
59
59
|
type ApcaContrasts = Record<45 | 60 | 75, ContrastValue>;
|
|
60
60
|
declare class Ramp {
|
|
61
|
-
|
|
61
|
+
swatches: Swatch[];
|
|
62
62
|
name: string;
|
|
63
63
|
constructor(colors?: string[], name?: string);
|
|
64
64
|
get colors(): string[];
|
|
65
65
|
get peakChroma(): string;
|
|
66
66
|
get steps(): number;
|
|
67
|
+
get direction(): "lighten" | "darken";
|
|
67
68
|
get baseColor(): string;
|
|
68
69
|
get baseIndex(): number;
|
|
69
70
|
get wcag(): WcagContrasts;
|
|
@@ -89,4 +90,4 @@ declare class Ramp {
|
|
|
89
90
|
get score(): number;
|
|
90
91
|
}
|
|
91
92
|
|
|
92
|
-
export { type ApcaContrasts, type ContrastValue, Ramp,
|
|
93
|
+
export { type ApcaContrasts, type ContrastValue, Ramp, Swatch, type WcagContrasts, calcDeltaE2000, calcScore, calcStatistics, createMonotone, cssRgbToRgb, fromLightnessEAL, hexToRgb, labToLch, labToRgb, lchToLab, rgbToHex, rgbToLab, rootMeanSquare, toLightnessEAL };
|
package/dist/index.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ declare const calcStatistics: (array: number[]) => {
|
|
|
35
35
|
/** Calculate geometric mean score (0-100) from metrics. */
|
|
36
36
|
declare const calcScore: (metrics: number[]) => number;
|
|
37
37
|
|
|
38
|
-
declare class
|
|
38
|
+
declare class Swatch {
|
|
39
39
|
readonly hex: string;
|
|
40
40
|
constructor(hex: string);
|
|
41
41
|
get rgb(): number[];
|
|
@@ -58,12 +58,13 @@ type ContrastValue = {
|
|
|
58
58
|
type WcagContrasts = Record<30 | 45 | 70, ContrastValue>;
|
|
59
59
|
type ApcaContrasts = Record<45 | 60 | 75, ContrastValue>;
|
|
60
60
|
declare class Ramp {
|
|
61
|
-
|
|
61
|
+
swatches: Swatch[];
|
|
62
62
|
name: string;
|
|
63
63
|
constructor(colors?: string[], name?: string);
|
|
64
64
|
get colors(): string[];
|
|
65
65
|
get peakChroma(): string;
|
|
66
66
|
get steps(): number;
|
|
67
|
+
get direction(): "lighten" | "darken";
|
|
67
68
|
get baseColor(): string;
|
|
68
69
|
get baseIndex(): number;
|
|
69
70
|
get wcag(): WcagContrasts;
|
|
@@ -89,4 +90,4 @@ declare class Ramp {
|
|
|
89
90
|
get score(): number;
|
|
90
91
|
}
|
|
91
92
|
|
|
92
|
-
export { type ApcaContrasts, type ContrastValue, Ramp,
|
|
93
|
+
export { type ApcaContrasts, type ContrastValue, Ramp, Swatch, type WcagContrasts, calcDeltaE2000, calcScore, calcStatistics, createMonotone, cssRgbToRgb, fromLightnessEAL, hexToRgb, labToLch, labToRgb, lchToLab, rgbToHex, rgbToLab, rootMeanSquare, toLightnessEAL };
|
package/dist/index.global.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var Chromametry=(()=>{var
|
|
1
|
+
"use strict";var Chromametry=(()=>{var L=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var V=(u,n)=>{for(var t in n)L(u,t,{get:n[t],enumerable:!0})},W=(u,n,t,s)=>{if(n&&typeof n=="object"||typeof n=="function")for(let e of N(n))!U.call(u,e)&&e!==t&&L(u,e,{get:()=>n[e],enumerable:!(s=G(n,e))||s.enumerable});return u};var $=u=>W(L({},"__esModule",{value:!0}),u);var st={};V(st,{Ramp:()=>y,Swatch:()=>I,calcDeltaE2000:()=>v,calcScore:()=>P,calcStatistics:()=>nt,createMonotone:()=>k,cssRgbToRgb:()=>Q,fromLightnessEAL:()=>j,hexToRgb:()=>w,labToLch:()=>R,labToRgb:()=>J,lchToLab:()=>O,rgbToHex:()=>Z,rgbToLab:()=>C,rootMeanSquare:()=>tt,toLightnessEAL:()=>_});var F=u=>{let n=t=>{let s=Math.max(0,Math.min(1,t)),e=s<=.0031308?12.92*s:1.055*Math.pow(s,1/2.4)-.055;return Math.max(0,Math.min(255,Math.round(e*255)))};return u.map(n)},K=u=>{let n=t=>t>.04045?Math.pow((t+.055)/1.055,2.4):t/12.92;return u.map(n)},Z=u=>{let[n,t,s]=F(u);return n=n.toString(16).padStart(2,"0"),t=t.toString(16).padStart(2,"0"),s=s.toString(16).padStart(2,"0"),`#${n}${t}${s}`},w=u=>{let n=parseInt(u.slice(1,3),16)/255,t=parseInt(u.slice(3,5),16)/255,s=parseInt(u.slice(5,7),16)/255;return K([n,t,s])},_=u=>{let[n,t,s]=u,e=Math.sqrt(t*t+s*s),a=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,m=.0603,r=.1307,i=.006,l=c*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+m,o=0;return(a<=90||a>=270)&&(o=r*Math.abs(Math.cos(a*(Math.PI/180)))+i),n+(l+o)*e},j=(u,n)=>{let[,t,s]=n,e=Math.sqrt(t*t+s*s),a=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,m=.0603,r=.1307,i=.006,l=c*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+m,o=0;return(a<=90||a>=270)&&(o=r*Math.abs(Math.cos(a*(Math.PI/180)))+i),Math.max(0,u-(l+o)*e)},O=u=>{let[n,t,s]=u,e=s*Math.PI/180;return[n,t*Math.cos(e),t*Math.sin(e)]},C=u=>{let[n,t,s]=u,e=.4124564*n+.3575761*t+.1804375*s,h=.2126729*n+.7151522*t+.072175*s,a=.0193339*n+.119192*t+.9503041*s,c=.95047,m=1,r=1.08883,i=b=>b>.008856?Math.cbrt(b):7.787*b+16/116,l=i(e/c),o=i(h/m),M=i(a/r);return[116*o-16,500*(l-o),200*(o-M)]},J=u=>{let[n,t,s]=u,e=(n+16)/116,h=t/500+e,a=e-s/200,c=b=>b**3>.008856?b**3:(b-16/116)/7.787,m=.95047,r=1,i=1.08883,l=c(h)*m,o=c(e)*r,M=c(a)*i;return[3.2404542*l-1.5371385*o-.4985314*M,-.969266*l+1.8760108*o+.041556*M,.0556434*l-.2040259*o+1.0572252*M]},R=u=>{let[n,t,s]=u,e=Math.sqrt(t*t+s*s);if(e<1e-4)return[n,0,0];let a=(Math.atan2(s,t)*180/Math.PI+360)%360;return a>=359.9999&&(a=0),[n,e,a]},v=(u,n)=>{let[t,s,e]=u,[h,a,c]=n,m=(t+h)/2,r=Math.sqrt(s*s+e*e),i=Math.sqrt(a*a+c*c),l=(r+i)/2,o=.5*(1-Math.sqrt(Math.pow(l,7)/(Math.pow(l,7)+Math.pow(25,7)))),M=s*(1+o),b=a*(1+o),f=Math.sqrt(M*M+e*e),p=Math.sqrt(b*b+c*c),d=(f+p)/2,x=Math.atan2(e,M)*180/Math.PI+(Math.atan2(e,M)<0?360:0),g=Math.atan2(c,b)*180/Math.PI+(Math.atan2(c,b)<0?360:0),q=g-x;Math.abs(q)>180&&(q+=g<=x?360:-360);let S=Math.abs(x-g)>180?(x+g+360)/2:(x+g)/2,H=1-.17*Math.cos((S-30)*Math.PI/180)+.24*Math.cos(2*S*Math.PI/180)+.32*Math.cos((3*S+6)*Math.PI/180)-.2*Math.cos((4*S-63)*Math.PI/180),Y=h-t,E=p-f,T=2*Math.sqrt(f*p)*Math.sin(q/2*Math.PI/180),A=1+.015*Math.pow(m-50,2)/Math.sqrt(20+Math.pow(m-50,2)),B=1+.045*d,D=1+.015*d*H,X=30*Math.exp(-Math.pow((S-275)/25,2)),z=-(2*Math.sqrt(Math.pow(d,7)/(Math.pow(d,7)+Math.pow(25,7))))*Math.sin(2*X*Math.PI/180);return Math.sqrt(Math.pow(Y/A,2)+Math.pow(E/B,2)+Math.pow(T/D,2)+z*(E/B)*(T/D))},Q=u=>{let n=u.match(/\d+(\.\d+)?/g);if(!n||n.length<3)throw new Error("Invalid CSS rgb()");let t=s=>{let e=s/255;return e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4)};return[t(Number(n[0])),t(Number(n[1])),t(Number(n[2]))]},k=u=>{if(u.length<1)return r=>0;let n=[...u].sort((r,i)=>r[0]-i[0]),t=[];for(let r=0;r<n.length;r++)(r===0||n[r][0]!==n[r-1][0])&&t.push(n[r]);let s=t.length;if(s===1)return r=>t[0][1];let e=t.map(r=>r[0]),h=t.map(r=>r[1]),a=[],c=[];for(let r=0;r<s-1;r++)a[r]=e[r+1]-e[r],c[r]=(h[r+1]-h[r])/a[r];let m=new Array(s);m[0]=c[0],m[s-1]=c[s-2];for(let r=1;r<s-1;r++){let i=c[r-1],l=c[r];if(i*l<=0)m[r]=0;else{let o=(1+a[r]/(a[r-1]+a[r]))/3;m[r]=i*l/((1-o)*i+o*l)}}return r=>{if(r<=e[0])return h[0];if(r>=e[s-1])return h[s-1];let i=0,l=s-2,o=0;for(;i<=l;){let g=Math.floor((i+l)/2);if(r>=e[g]&&r<=e[g+1]){o=g;break}r<e[g]?l=g-1:i=g+1}let M=a[o],b=(r-e[o])/M,f=b*b,p=f*b,d=m[o]*M,x=m[o+1]*M;return(2*p-3*f+1)*h[o]+(p-2*f+b)*d+(-2*p+3*f)*h[o+1]+(p-f)*x}};function tt(u){let n=u.length;if(n===0)return 0;let t=0;for(let s=0;s<n;s++)t+=u[s]*u[s];return Math.sqrt(t/n)}var nt=u=>{let n=u.length;if(n===0)return{min:0,max:0,avg:0};let t=u[0],s=u[0],e=0;for(let h=0;h<n;h++){let a=u[h];a<t&&(t=a),a>s&&(s=a),e+=a}return{min:t,max:s,avg:e/n}},P=u=>{let n=u.length;if(n===0)return 0;let t=1e-6,s=u.reduce((a,c)=>a*(c+t),1),e=Math.pow(s,1/n),h=Math.max(0,Math.min(1,e));return parseFloat((h*100).toFixed(2))};var I=class{constructor(n){this.hex=n}get rgb(){return w(this.hex)}get lab(){return C(this.rgb)}get lch(){return R(this.lab)}get lightness(){let[n,t,s]=this.lab,e=Math.sqrt(t*t+s*s),a=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,m=.0603,r=.1307,i=.006,l=c*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+m,o=0;return(a<=90||a>=270)&&(o=r*Math.abs(Math.cos(a*(Math.PI/180)))+i),n+(l+o)*e}get chroma(){return this.lch[1]}get hue(){return this.lch[2]}get luminance(){let[n,t,s]=this.rgb;return .2126*n+.7152*t+.0722*s}get wcag(){return(Math.max(this.luminance,1)+.05)/(Math.min(this.luminance,1)+.05)}get apca(){let n=h=>h>5e-4?h:h+Math.pow(5e-4-h,.8),t=n(this.luminance),s=n(1),e=(Math.pow(t,.56)-Math.pow(s,.56))*100;return Math.abs(e)<.1?0:(e=e>0?e<1?0:e-.25:e>-1?0:e+.25,Math.round(e))}};var y=class{constructor(n=[],t="brand"){this.swatches=n.map(s=>new I(s)),this.name=t}get colors(){return this.swatches.map(n=>n.hex)}get peakChroma(){let n=this.colors.slice(2,-2),t="",s=-1/0;for(let e of n){let h=new I(e);h.chroma>s&&(s=h.chroma,t=e)}return s<6?this.colors[Math.ceil(this.steps/2)]:t}get steps(){return this.colors.length}get direction(){if(this.colors.length===0)return"lighten";let n=C(w(this.colors[0])),t=C(w(this.colors[this.colors.length-1]));return n[0]>t[0]?"darken":"lighten"}get baseColor(){return this.colors.length===0?"":this.peakChroma||this.colors[Math.floor(this.colors.length/2)]}get baseIndex(){return this.colors.length===0?-1:this.colors.findIndex(n=>n.toLowerCase()===this.baseColor.toLowerCase())}get wcag(){let n=this.swatches,t=n.length,s=t-1,e={};for(let h of[30,45,70]){let a=h/10,c=s,m=0;for(let r=1;r<t;r++){let i=1/0;for(let l=0;l<t-r;l++){let o=n[l].luminance,M=n[l+r].luminance,b=(Math.max(o,M)+.05)/(Math.min(o,M)+.05);b<i&&(i=b)}if(i>=a){c=r,m=i;break}r===s&&(m=i)}e[h]={efficiency:c/s,target:a,span:c,value:m}}return e}get apca(){let n=this.swatches,t=n.length,s=t-1,e={},h=(a,c)=>{let i=a<.022?a+Math.pow(.022-a,1.414):a,l=c<.022?c+Math.pow(.022-c,1.414):c,o=l>=i?(Math.pow(l,.56)-Math.pow(i,.57))*114:(Math.pow(l,.65)-Math.pow(i,.62))*114;return Math.abs(o)<10?0:(o=o>0?o-2.7:o+2.7,Math.round(o))};for(let a of[45,60,75]){let c=a,m=s,r=0;for(let i=1;i<t;i++){let l=1/0;for(let o=0;o<t-i;o++){let M=n[o].luminance>n[o+i].luminance?n[o].luminance:n[o+i].luminance,b=n[o].luminance>n[o+i].luminance?n[o+i].luminance:n[o].luminance,f=Math.abs(h(b,M));f<l&&(l=f)}if(l>=c){m=i,r=l;break}i===s&&(r=l)}e[a]={efficiency:m/s,target:c,span:m,value:r}}return e}get contrasts(){return{wcag:this.wcag,apca:this.apca}}get deltaECurve(){let n=[0];for(let t=1;t<this.swatches.length;t++){let s=v(this.swatches[t-1].lab,this.swatches[t].lab);n.push(n[t-1]+s)}return n}get unwrapHues(){let n=this.swatches.map(s=>s.hue).slice(1,-1);if(n.length===0)return[];let t=[n[0]];for(let s=1;s<n.length;s++){let e=n[s]-n[s-1];e>180?e-=360:e<-180&&(e+=360),t.push(t[s-1]+e)}return t}get lightnessLinearity(){let n=this.swatches.map(M=>M.lightness),t=n.length;if(t<2)return 1;let s=0,e=0,h=0,a=0;for(let M=0;M<t;M++)s+=M,e+=n[M],h+=M*n[M],a+=M*M;let c=t*a-s*s;if(Math.abs(c)<1e-10)return 1;let m=(t*h-s*e)/c,r=(e-m*s)/t;if(Math.abs(m*(t-1))<.001)return 1;let l=0,o=0;for(let M=0;M<t;M++){let b=m*M+r,f=n[M]-b;l+=f*f;let p=Math.max(b-Math.min(r,m*(t-1)+r),Math.max(r,m*(t-1)+r)-b);o+=p*p}return Math.max(0,Math.min(1,1-Math.sqrt(l/t)/Math.sqrt(o/t)))}get chromaSmoothness(){let n=this.swatches.map(o=>o.chroma),t=n.length;if(t<3)return 1;let s=133.8,e=Math.max(...n);if(e<=.01)return 1;let h=n.map(o=>o/e*s),a=Math.min(...h),c=Math.max(...h),m=h.findIndex(o=>o===c),r=k([[0,h[0]],[m,c],[t-1,h[t-1]]]),i=0,l=0;for(let o=0;o<t;o++){let M=r(o),b=h[o]-M;i+=b*b,l+=Math.pow(Math.max(M-a,c-M),2)}return Math.max(0,Math.min(1,1-Math.sqrt(i/t)/Math.sqrt(l/t)))}get spacingUniformity(){let n=this.deltaECurve,t=n.length;if(t<2)return 1;let s=[];for(let c=1;c<t;c++){let m=n[c]-n[c-1];if(m<0)return 0;s.push(m)}let e=s.reduce((c,m)=>c+m,0)/s.length;if(e<=1e-6)return 0;let h=0;for(let c of s)h+=Math.pow(c-e,2);let a=Math.sqrt(h/s.length)/e;return Math.max(0,Math.min(1,1/(1+a)))}get hueStability(){var a,c,m;let n=this.unwrapHues,t=n.length;if(t<2)return 1;let s=(m=(c=n[this.baseIndex-1])!=null?c:(a=this.swatches[this.baseIndex])==null?void 0:a.hue)!=null?m:0,e=0,h=0;for(let r=0;r<t;r++){let i=Math.abs(n[r]-s)%360;i>180&&(i=360-i),e+=i*i;let l=r/(t-1)*180;h+=l*l}return Math.max(0,Math.min(1,1-Math.sqrt(e/t)/(Math.sqrt(h/t)||1)))}get contrastEfficiency(){let n=this.wcag[45].span,t=this.steps;if(t<=1)return 1;let s=.5,e=n/t,h=s*((t-1)/t);return e<=h?1:e>=1?0:(1-e)/(1-h)}get metrics(){return{lightnessLinearity:this.lightnessLinearity,chromaSmoothness:this.chromaSmoothness,spacingUniformity:this.spacingUniformity,hueStability:this.hueStability,contrastEfficiency:this.contrastEfficiency}}get score(){return P(Object.values(this.metrics))}};return $(st);})();
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var z=m=>{let n=t=>{let s=Math.max(0,Math.min(1,t)),e=s<=.0031308?12.92*s:1.055*Math.pow(s,1/2.4)-.055;return Math.max(0,Math.min(255,Math.round(e*255)))};return m.map(n)},G=m=>{let n=t=>t>.04045?Math.pow((t+.055)/1.055,2.4):t/12.92;return m.map(n)},U=m=>{let[n,t,s]=z(m);return n=n.toString(16).padStart(2,"0"),t=t.toString(16).padStart(2,"0"),s=s.toString(16).padStart(2,"0"),`#${n}${t}${s}`},
|
|
1
|
+
var z=m=>{let n=t=>{let s=Math.max(0,Math.min(1,t)),e=s<=.0031308?12.92*s:1.055*Math.pow(s,1/2.4)-.055;return Math.max(0,Math.min(255,Math.round(e*255)))};return m.map(n)},G=m=>{let n=t=>t>.04045?Math.pow((t+.055)/1.055,2.4):t/12.92;return m.map(n)},U=m=>{let[n,t,s]=z(m);return n=n.toString(16).padStart(2,"0"),t=t.toString(16).padStart(2,"0"),s=s.toString(16).padStart(2,"0"),`#${n}${t}${s}`},C=m=>{let n=parseInt(m.slice(1,3),16)/255,t=parseInt(m.slice(3,5),16)/255,s=parseInt(m.slice(5,7),16)/255;return G([n,t,s])},V=m=>{let[n,t,s]=m,e=Math.sqrt(t*t+s*s),a=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,l=.0603,r=.1307,i=.006,u=c*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+l,o=0;return(a<=90||a>=270)&&(o=r*Math.abs(Math.cos(a*(Math.PI/180)))+i),n+(u+o)*e},W=(m,n)=>{let[,t,s]=n,e=Math.sqrt(t*t+s*s),a=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,l=.0603,r=.1307,i=.006,u=c*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+l,o=0;return(a<=90||a>=270)&&(o=r*Math.abs(Math.cos(a*(Math.PI/180)))+i),Math.max(0,m-(u+o)*e)},$=m=>{let[n,t,s]=m,e=s*Math.PI/180;return[n,t*Math.cos(e),t*Math.sin(e)]},I=m=>{let[n,t,s]=m,e=.4124564*n+.3575761*t+.1804375*s,h=.2126729*n+.7151522*t+.072175*s,a=.0193339*n+.119192*t+.9503041*s,c=.95047,l=1,r=1.08883,i=b=>b>.008856?Math.cbrt(b):7.787*b+16/116,u=i(e/c),o=i(h/l),M=i(a/r);return[116*o-16,500*(u-o),200*(o-M)]},F=m=>{let[n,t,s]=m,e=(n+16)/116,h=t/500+e,a=e-s/200,c=b=>b**3>.008856?b**3:(b-16/116)/7.787,l=.95047,r=1,i=1.08883,u=c(h)*l,o=c(e)*r,M=c(a)*i;return[3.2404542*u-1.5371385*o-.4985314*M,-.969266*u+1.8760108*o+.041556*M,.0556434*u-.2040259*o+1.0572252*M]},P=m=>{let[n,t,s]=m,e=Math.sqrt(t*t+s*s);if(e<1e-4)return[n,0,0];let a=(Math.atan2(s,t)*180/Math.PI+360)%360;return a>=359.9999&&(a=0),[n,e,a]},y=(m,n)=>{let[t,s,e]=m,[h,a,c]=n,l=(t+h)/2,r=Math.sqrt(s*s+e*e),i=Math.sqrt(a*a+c*c),u=(r+i)/2,o=.5*(1-Math.sqrt(Math.pow(u,7)/(Math.pow(u,7)+Math.pow(25,7)))),M=s*(1+o),b=a*(1+o),f=Math.sqrt(M*M+e*e),p=Math.sqrt(b*b+c*c),d=(f+p)/2,x=Math.atan2(e,M)*180/Math.PI+(Math.atan2(e,M)<0?360:0),g=Math.atan2(c,b)*180/Math.PI+(Math.atan2(c,b)<0?360:0),q=g-x;Math.abs(q)>180&&(q+=g<=x?360:-360);let w=Math.abs(x-g)>180?(x+g+360)/2:(x+g)/2,D=1-.17*Math.cos((w-30)*Math.PI/180)+.24*Math.cos(2*w*Math.PI/180)+.32*Math.cos((3*w+6)*Math.PI/180)-.2*Math.cos((4*w-63)*Math.PI/180),H=h-t,L=p-f,R=2*Math.sqrt(f*p)*Math.sin(q/2*Math.PI/180),Y=1+.015*Math.pow(l-50,2)/Math.sqrt(20+Math.pow(l-50,2)),v=1+.045*d,k=1+.015*d*D,A=30*Math.exp(-Math.pow((w-275)/25,2)),X=-(2*Math.sqrt(Math.pow(d,7)/(Math.pow(d,7)+Math.pow(25,7))))*Math.sin(2*A*Math.PI/180);return Math.sqrt(Math.pow(H/Y,2)+Math.pow(L/v,2)+Math.pow(R/k,2)+X*(L/v)*(R/k))},K=m=>{let n=m.match(/\d+(\.\d+)?/g);if(!n||n.length<3)throw new Error("Invalid CSS rgb()");let t=s=>{let e=s/255;return e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4)};return[t(Number(n[0])),t(Number(n[1])),t(Number(n[2]))]},E=m=>{if(m.length<1)return r=>0;let n=[...m].sort((r,i)=>r[0]-i[0]),t=[];for(let r=0;r<n.length;r++)(r===0||n[r][0]!==n[r-1][0])&&t.push(n[r]);let s=t.length;if(s===1)return r=>t[0][1];let e=t.map(r=>r[0]),h=t.map(r=>r[1]),a=[],c=[];for(let r=0;r<s-1;r++)a[r]=e[r+1]-e[r],c[r]=(h[r+1]-h[r])/a[r];let l=new Array(s);l[0]=c[0],l[s-1]=c[s-2];for(let r=1;r<s-1;r++){let i=c[r-1],u=c[r];if(i*u<=0)l[r]=0;else{let o=(1+a[r]/(a[r-1]+a[r]))/3;l[r]=i*u/((1-o)*i+o*u)}}return r=>{if(r<=e[0])return h[0];if(r>=e[s-1])return h[s-1];let i=0,u=s-2,o=0;for(;i<=u;){let g=Math.floor((i+u)/2);if(r>=e[g]&&r<=e[g+1]){o=g;break}r<e[g]?u=g-1:i=g+1}let M=a[o],b=(r-e[o])/M,f=b*b,p=f*b,d=l[o]*M,x=l[o+1]*M;return(2*p-3*f+1)*h[o]+(p-2*f+b)*d+(-2*p+3*f)*h[o+1]+(p-f)*x}};function Z(m){let n=m.length;if(n===0)return 0;let t=0;for(let s=0;s<n;s++)t+=m[s]*m[s];return Math.sqrt(t/n)}var _=m=>{let n=m.length;if(n===0)return{min:0,max:0,avg:0};let t=m[0],s=m[0],e=0;for(let h=0;h<n;h++){let a=m[h];a<t&&(t=a),a>s&&(s=a),e+=a}return{min:t,max:s,avg:e/n}},T=m=>{let n=m.length;if(n===0)return 0;let t=1e-6,s=m.reduce((a,c)=>a*(c+t),1),e=Math.pow(s,1/n),h=Math.max(0,Math.min(1,e));return parseFloat((h*100).toFixed(2))};var S=class{constructor(n){this.hex=n}get rgb(){return C(this.hex)}get lab(){return I(this.rgb)}get lch(){return P(this.lab)}get lightness(){let[n,t,s]=this.lab,e=Math.sqrt(t*t+s*s),a=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,l=.0603,r=.1307,i=.006,u=c*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+l,o=0;return(a<=90||a>=270)&&(o=r*Math.abs(Math.cos(a*(Math.PI/180)))+i),n+(u+o)*e}get chroma(){return this.lch[1]}get hue(){return this.lch[2]}get luminance(){let[n,t,s]=this.rgb;return .2126*n+.7152*t+.0722*s}get wcag(){return(Math.max(this.luminance,1)+.05)/(Math.min(this.luminance,1)+.05)}get apca(){let n=h=>h>5e-4?h:h+Math.pow(5e-4-h,.8),t=n(this.luminance),s=n(1),e=(Math.pow(t,.56)-Math.pow(s,.56))*100;return Math.abs(e)<.1?0:(e=e>0?e<1?0:e-.25:e>-1?0:e+.25,Math.round(e))}};var B=class{constructor(n=[],t="brand"){this.swatches=n.map(s=>new S(s)),this.name=t}get colors(){return this.swatches.map(n=>n.hex)}get peakChroma(){let n=this.colors.slice(2,-2),t="",s=-1/0;for(let e of n){let h=new S(e);h.chroma>s&&(s=h.chroma,t=e)}return s<6?this.colors[Math.ceil(this.steps/2)]:t}get steps(){return this.colors.length}get direction(){if(this.colors.length===0)return"lighten";let n=I(C(this.colors[0])),t=I(C(this.colors[this.colors.length-1]));return n[0]>t[0]?"darken":"lighten"}get baseColor(){return this.colors.length===0?"":this.peakChroma||this.colors[Math.floor(this.colors.length/2)]}get baseIndex(){return this.colors.length===0?-1:this.colors.findIndex(n=>n.toLowerCase()===this.baseColor.toLowerCase())}get wcag(){let n=this.swatches,t=n.length,s=t-1,e={};for(let h of[30,45,70]){let a=h/10,c=s,l=0;for(let r=1;r<t;r++){let i=1/0;for(let u=0;u<t-r;u++){let o=n[u].luminance,M=n[u+r].luminance,b=(Math.max(o,M)+.05)/(Math.min(o,M)+.05);b<i&&(i=b)}if(i>=a){c=r,l=i;break}r===s&&(l=i)}e[h]={efficiency:c/s,target:a,span:c,value:l}}return e}get apca(){let n=this.swatches,t=n.length,s=t-1,e={},h=(a,c)=>{let i=a<.022?a+Math.pow(.022-a,1.414):a,u=c<.022?c+Math.pow(.022-c,1.414):c,o=u>=i?(Math.pow(u,.56)-Math.pow(i,.57))*114:(Math.pow(u,.65)-Math.pow(i,.62))*114;return Math.abs(o)<10?0:(o=o>0?o-2.7:o+2.7,Math.round(o))};for(let a of[45,60,75]){let c=a,l=s,r=0;for(let i=1;i<t;i++){let u=1/0;for(let o=0;o<t-i;o++){let M=n[o].luminance>n[o+i].luminance?n[o].luminance:n[o+i].luminance,b=n[o].luminance>n[o+i].luminance?n[o+i].luminance:n[o].luminance,f=Math.abs(h(b,M));f<u&&(u=f)}if(u>=c){l=i,r=u;break}i===s&&(r=u)}e[a]={efficiency:l/s,target:c,span:l,value:r}}return e}get contrasts(){return{wcag:this.wcag,apca:this.apca}}get deltaECurve(){let n=[0];for(let t=1;t<this.swatches.length;t++){let s=y(this.swatches[t-1].lab,this.swatches[t].lab);n.push(n[t-1]+s)}return n}get unwrapHues(){let n=this.swatches.map(s=>s.hue).slice(1,-1);if(n.length===0)return[];let t=[n[0]];for(let s=1;s<n.length;s++){let e=n[s]-n[s-1];e>180?e-=360:e<-180&&(e+=360),t.push(t[s-1]+e)}return t}get lightnessLinearity(){let n=this.swatches.map(M=>M.lightness),t=n.length;if(t<2)return 1;let s=0,e=0,h=0,a=0;for(let M=0;M<t;M++)s+=M,e+=n[M],h+=M*n[M],a+=M*M;let c=t*a-s*s;if(Math.abs(c)<1e-10)return 1;let l=(t*h-s*e)/c,r=(e-l*s)/t;if(Math.abs(l*(t-1))<.001)return 1;let u=0,o=0;for(let M=0;M<t;M++){let b=l*M+r,f=n[M]-b;u+=f*f;let p=Math.max(b-Math.min(r,l*(t-1)+r),Math.max(r,l*(t-1)+r)-b);o+=p*p}return Math.max(0,Math.min(1,1-Math.sqrt(u/t)/Math.sqrt(o/t)))}get chromaSmoothness(){let n=this.swatches.map(o=>o.chroma),t=n.length;if(t<3)return 1;let s=133.8,e=Math.max(...n);if(e<=.01)return 1;let h=n.map(o=>o/e*s),a=Math.min(...h),c=Math.max(...h),l=h.findIndex(o=>o===c),r=E([[0,h[0]],[l,c],[t-1,h[t-1]]]),i=0,u=0;for(let o=0;o<t;o++){let M=r(o),b=h[o]-M;i+=b*b,u+=Math.pow(Math.max(M-a,c-M),2)}return Math.max(0,Math.min(1,1-Math.sqrt(i/t)/Math.sqrt(u/t)))}get spacingUniformity(){let n=this.deltaECurve,t=n.length;if(t<2)return 1;let s=[];for(let c=1;c<t;c++){let l=n[c]-n[c-1];if(l<0)return 0;s.push(l)}let e=s.reduce((c,l)=>c+l,0)/s.length;if(e<=1e-6)return 0;let h=0;for(let c of s)h+=Math.pow(c-e,2);let a=Math.sqrt(h/s.length)/e;return Math.max(0,Math.min(1,1/(1+a)))}get hueStability(){var a,c,l;let n=this.unwrapHues,t=n.length;if(t<2)return 1;let s=(l=(c=n[this.baseIndex-1])!=null?c:(a=this.swatches[this.baseIndex])==null?void 0:a.hue)!=null?l:0,e=0,h=0;for(let r=0;r<t;r++){let i=Math.abs(n[r]-s)%360;i>180&&(i=360-i),e+=i*i;let u=r/(t-1)*180;h+=u*u}return Math.max(0,Math.min(1,1-Math.sqrt(e/t)/(Math.sqrt(h/t)||1)))}get contrastEfficiency(){let n=this.wcag[45].span,t=this.steps;if(t<=1)return 1;let s=.5,e=n/t,h=s*((t-1)/t);return e<=h?1:e>=1?0:(1-e)/(1-h)}get metrics(){return{lightnessLinearity:this.lightnessLinearity,chromaSmoothness:this.chromaSmoothness,spacingUniformity:this.spacingUniformity,hueStability:this.hueStability,contrastEfficiency:this.contrastEfficiency}}get score(){return T(Object.values(this.metrics))}};export{B as Ramp,S as Swatch,y as calcDeltaE2000,T as calcScore,_ as calcStatistics,E as createMonotone,K as cssRgbToRgb,W as fromLightnessEAL,C as hexToRgb,P as labToLch,F as labToRgb,$ as lchToLab,U as rgbToHex,I as rgbToLab,Z as rootMeanSquare,V as toLightnessEAL};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chromametry",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Web-accessible Color Palette Metrics",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"test": "vitest",
|
|
11
11
|
"generate": "tsx scripts/generate.ts",
|
|
12
12
|
"build": "tsup",
|
|
13
|
-
"prepublishOnly": "npm run
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
14
|
},
|
|
15
15
|
"keywords": [
|
|
16
16
|
"color",
|