chromametry 0.3.1 → 0.3.3

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 CHANGED
@@ -23,17 +23,17 @@
23
23
  Comparison of popular design systems based on Chromametry metrics.
24
24
  | Design System | Steps | Span (K) | Contrast Efficiency | Lightness Linearity | Chroma Smoothness | Hue Stability | Spacing Uniformity | **SCORE** |
25
25
  | :--------------------- | :---: | :------: | :-----------------: | :-----------------: | :---------------: | :-----------: | :----------------: | :-------: |
26
- | Adobe Spectrum | 18 | 9 | 0.947 | 0.9333 | 0.8786 | 0.9138 | 0.7722 | **88.67** |
27
- | IBM Carbon | 12 | 6 | 0.923 | 0.9303 | 0.8688 | 0.9252 | 0.7919 | **88.62** |
28
- | U.S. Web Design System | 12 | 6 | 0.923 | 0.9359 | 0.8096 | 0.9380 | 0.7997 | **87.90** |
29
- | Salesforce Lightning 2 | 14 | 7 | 0.933 | 0.9187 | 0.8464 | 0.9372 | 0.7107 | **86.47** |
30
- | GitHub Primer Brand | 12 | 6 | 0.923 | 0.9243 | 0.8405 | 0.9408 | 0.6841 | **85.67** |
31
- | Atlassian | 14 | 8 | 0.800 | 0.8964 | 0.9094 | 0.9465 | 0.7129 | **84.86** |
32
- | Tailwind CSS | 13 | 8 | 0.789 | 0.8705 | 0.8565 | 0.9147 | 0.6780 | **81.74** |
33
- | Ant Design | 12 | 9 | 0.711 | 0.8586 | 0.8734 | 0.9276 | 0.6550 | **79.81** |
34
- | Material UI | 12 | 11 | 0.565 | 0.7967 | 0.7861 | 0.9239 | 0.5500 | **70.95** |
35
- | Radix UI | 13 | 10 | 0.543 | 0.7979 | 0.7679 | 0.9481 | 0.5207 | **69.67** |
36
- | Shopify Polaris | 17 | 15 | 0.356 | 0.7281 | 0.6892 | 0.9223 | 0.4667 | **59.86** |
26
+ | Adobe Spectrum | 18 | 9 | 0.9431 | 0.9333 | 0.8786 | 0.9138 | 0.7722 | **88.59** |
27
+ | IBM Carbon | 12 | 6 | 0.9109 | 0.9303 | 0.8688 | 0.9288 | 0.7919 | **88.46** |
28
+ | U.S. Web Design System | 12 | 6 | 0.9109 | 0.9359 | 0.8096 | 0.9380 | 0.7997 | **87.67** |
29
+ | Salesforce Lightning 2 | 14 | 7 | 0.9249 | 0.9187 | 0.8464 | 0.9372 | 0.7107 | **86.31** |
30
+ | GitHub Primer Brand | 12 | 6 | 0.9109 | 0.9243 | 0.8405 | 0.9408 | 0.6841 | **85.45** |
31
+ | Atlassian | 14 | 8 | 0.7708 | 0.8964 | 0.9094 | 0.9465 | 0.7129 | **84.23** |
32
+ | Tailwind CSS | 13 | 8 | 0.7561 | 0.8705 | 0.8565 | 0.9147 | 0.6780 | **81.04** |
33
+ | Ant Design | 12 | 9 | 0.6652 | 0.8586 | 0.8734 | 0.9276 | 0.6550 | **78.76** |
34
+ | Material UI | 12 | 11 | 0.5067 | 0.7967 | 0.7861 | 0.9239 | 0.5500 | **69.43** |
35
+ | Radix UI | 13 | 10 | 0.4742 | 0.7979 | 0.7679 | 0.9468 | 0.5207 | **67.80** |
36
+ | Shopify Polaris | 17 | 15 | 0.2824 | 0.7281 | 0.6892 | 0.9223 | 0.4667 | **57.16** |
37
37
 
38
38
 
39
39
 
@@ -42,7 +42,7 @@ Comparison of popular design systems based on Chromametry metrics.
42
42
 
43
43
  > **Note:** Design systems like Bootstrap,Google Material 3, Apple Human Interface or Fluent UI are excluded as they define discrete semantic tokens rather than algorithmic sequential ramps.
44
44
 
45
- > **Overall Score** is computed as the weighted mean of the five normalized metrics, using equal weights by default.
45
+ > **Overall Score** is computed as the geometric mean of the five normalized metrics.
46
46
 
47
47
  ### Example: A Typical Report
48
48
 
@@ -57,169 +57,160 @@ Comparison of popular design systems based on Chromametry metrics.
57
57
 
58
58
  ## Benchmark result page
59
59
 
60
- - Online Report : [Benchmark page](https://chromametry.github.io/chromametry/benchmark/)
61
- - Local `/benchmark/index.html` (double click)
62
-
63
- ## API
64
- ### Installation
65
- ```bash
66
- npm install chromametry
67
- ```
68
-
69
- ### Usage
70
- ```ts
71
- import { Palette, Ramp, Shade } from "chromametry";
72
-
73
- const blue = new Ramp([
74
- "#ffffff",
75
- "#eff6fb",
76
- "#d9e8f6",
77
- "#aacdec",
78
- "#73b3e7",
79
- "#4f97d1",
80
- "#2378c3",
81
- "#2c608a",
82
- "#274863",
83
- "#1f303e",
84
- "#11181d",
85
- "#000000",
86
- ], "blue");
87
-
88
- console.log(blue.baseColor);
89
- console.log(blue.wcag[45].span);
90
- console.log(blue.metrics);
91
- console.log(blue.score);
92
-
93
- const brand = new Palette({
94
- blue: blue.colors,
95
- orange: [
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);
118
- ```
119
-
120
- ### Browser
121
- **ESM**
122
- ```html
123
- <script type="module">
124
- import { Palette, Ramp } from "https://esm.sh/chromametry";
125
-
126
- const ramp = new Ramp(["#ffffff", "#2378c3", "#000000"], "blue");
127
- console.log(ramp.score);
128
- </script>
129
- ```
130
-
131
- **Global**
132
- ```html
133
- <script src="https://unpkg.com/chromametry/dist/index.global.js"></script>
134
- <script>
135
- const ramp = new Chromametry.Ramp(["#ffffff", "#2378c3", "#000000"], "blue");
136
- console.log(ramp.score);
137
- </script>
138
- ```
139
-
140
- ### Class Reference
141
- #### Shade
142
- | Property | Description |
143
- | :--- | :--- |
144
- | `constructor(hex)` | Create a shade from a hex color string. |
145
- | `hex` | Original hex color. |
146
- | `rgb` | Linear RGB values. |
147
- | `lab` | CIELAB coordinates. |
148
- | `lch` | LCH coordinates derived from LAB. |
149
- | `lightness` | Perceptual lightness with Helmholtz-Kohlrausch correction. |
150
- | `chroma` | Chroma of the shade. |
151
- | `hue` | Hue angle in degrees. |
152
- | `luminance` | Relative luminance used for contrast. |
153
- | `wcag` | WCAG contrast ratio against white. |
154
- | `apca` | APCA contrast value against white. |
155
-
156
- #### Ramp
157
- | Property | Description |
158
- | :--- | :--- |
159
- | `constructor(colors, name?)` | Create a sequential ramp from hex colors. |
160
- | `name` | Ramp name. |
161
- | `shades` | `Shade[]` built from the input colors. |
162
- | `colors` | Original ramp colors as hex strings. |
163
- | `steps` | Number of steps in the ramp. |
164
- | `peakChroma` | Hex color with the highest chroma in the inner ramp. |
165
- | `baseColor` | Base color used as the ramp anchor. |
166
- | `baseIndex` | Index of the base color. |
167
- | `wcag` | WCAG contrast spans for levels `30`, `45`, and `70`. |
168
- | `apca` | APCA contrast spans for levels `45`, `60`, and `75`. |
169
- | `contrasts` | Combined contrast object with `wcag` and `apca`. |
170
- | `deltaECurve` | Cumulative DeltaE curve across ramp steps. |
171
- | `unwrapHues` | Hue sequence with wrap-around discontinuities removed. |
172
- | `lightnessLinearity` | Linearity score of the lightness curve. |
173
- | `chromaSmoothness` | Smoothness score of the chroma curve. |
174
- | `spacingUniformity` | Uniformity score of DeltaE spacing. |
175
- | `hueStability` | Stability score of hue drift across the ramp. |
176
- | `contrastEfficiency` | Efficiency score of using contrast span for WCAG 4.5. |
177
- | `metrics` | Object containing the five ramp metrics. |
178
- | `score` | Composite ramp score. |
179
-
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
- ## Reproducing Benchmarks
196
- To run the benchmark generator locally:
197
- ```bash
198
- git clone https://github.com/chromametry/chromametry.git
60
+ - Online Report : [Benchmark page](https://chromametry.github.io/chromametry/benchmark/)
61
+ - Local `/benchmark/index.html` (double click)
62
+
63
+ ## API
64
+ ### Installation
65
+ ```bash
66
+ npm install chromametry
67
+ ```
68
+
69
+ ### Usage
70
+ ```ts
71
+ import { Palette, Ramp, Swatch } from "chromametry";
72
+
73
+ const blue = new Ramp([
74
+ "#ffffff",
75
+ "#eff6fb",
76
+ "#d9e8f6",
77
+ "#aacdec",
78
+ "#73b3e7",
79
+ "#4f97d1",
80
+ "#2378c3",
81
+ "#2c608a",
82
+ "#274863",
83
+ "#1f303e",
84
+ "#11181d",
85
+ "#000000",
86
+ ], "blue");
87
+
88
+ console.log(blue.baseColor);
89
+ console.log(blue.wcag[45].span);
90
+ console.log(blue.metrics);
91
+ console.log(blue.score);
92
+ console.log(blue.direction);
93
+
94
+ const palette = new Palette({
95
+ blue: blue.colors,
96
+ gray: ["#ffffff", "#dfe1e2", "#71767a", "#000000"],
97
+ }, "example");
98
+
99
+ console.log(palette.contrastEfficiency);
100
+ console.log(palette.lightnessLinearity);
101
+ console.log(palette.score);
102
+
103
+ const swatch = new Swatch("#2378c3");
104
+ console.log(swatch.lab);
105
+ console.log(swatch.chroma);
106
+ ```
107
+
108
+ ### Browser
109
+ **ESM**
110
+ ```html
111
+ <script type="module">
112
+ import { Ramp } from "https://esm.sh/chromametry";
113
+
114
+ const ramp = new Ramp(["#ffffff", "#2378c3", "#000000"], "blue");
115
+ console.log(ramp.score);
116
+ </script>
117
+ ```
118
+
119
+ **Global**
120
+ ```html
121
+ <script src="https://unpkg.com/chromametry/dist/index.global.js"></script>
122
+ <script>
123
+ const ramp = new Chromametry.Ramp(["#ffffff", "#2378c3", "#000000"], "blue");
124
+ console.log(ramp.score);
125
+ </script>
126
+ ```
127
+
128
+ ### Class Reference
129
+ #### Swatch
130
+ | Property | Description |
131
+ | :--- | :--- |
132
+ | `constructor(hex)` | Create a swatch from a hex color string. |
133
+ | `hex` | Original hex color. |
134
+ | `rgb` | Linear RGB values. |
135
+ | `lab` | CIELAB coordinates. |
136
+ | `lch` | LCH coordinates derived from LAB. |
137
+ | `lightness` | Perceptual lightness with Helmholtz-Kohlrausch correction. |
138
+ | `chroma` | Chroma of the swatch. |
139
+ | `hue` | Hue angle in degrees. |
140
+ | `luminance` | Relative luminance used for contrast. |
141
+ | `wcag` | WCAG contrast ratio against white. |
142
+ | `apca` | APCA contrast value against white. |
143
+
144
+ #### Ramp
145
+ | Property | Description |
146
+ | :--- | :--- |
147
+ | `constructor(colors, name?)` | Create a sequential ramp from hex colors. |
148
+ | `name` | Ramp name. |
149
+ | `swatches` | `Swatch[]` built from the input colors. |
150
+ | `colors` | Original ramp colors as hex strings. |
151
+ | `steps` | Number of steps in the ramp. |
152
+ | `direction` | Whether the ramp trends from light to dark or dark to light. |
153
+ | `peakChroma` | Hex color with the highest chroma in the inner ramp. |
154
+ | `baseColor` | Base color used as the ramp anchor. |
155
+ | `baseIndex` | Index of the base color. |
156
+ | `wcag` | WCAG contrast spans for levels `30`, `45`, and `70`. |
157
+ | `apca` | APCA contrast spans for levels `45`, `60`, and `75`. |
158
+ | `contrasts` | Combined contrast object with `wcag` and `apca`. |
159
+ | `deltaECurve` | Cumulative DeltaE curve across ramp steps. |
160
+ | `unwrapHues` | Hue sequence with wrap-around discontinuities removed. |
161
+ | `lightnessLinearity` | Linearity score of the lightness curve. |
162
+ | `chromaSmoothness` | Smoothness score of the chroma curve. |
163
+ | `spacingUniformity` | Uniformity score of DeltaE spacing. |
164
+ | `hueStability` | Stability score of hue drift across the ramp. |
165
+ | `contrastEfficiency` | Efficiency score of using contrast span for WCAG 4.5. |
166
+ | `metrics` | Object containing the five ramp metrics. |
167
+ | `score` | Composite ramp score. |
168
+
169
+ #### Palette
170
+ | Property | Description |
171
+ | :--- | :--- |
172
+ | `constructor(colors, name?)` | Create a named palette from multiple ramps. |
173
+ | `name` | Palette name. |
174
+ | `ramps` | `Ramp[]` built from the input color map. |
175
+ | `colors` | Original colors as `Record<string, string[]>`. |
176
+ | `steps` | Number of steps in each ramp. |
177
+ | `wcag` | Aggregated WCAG contrast spans across ramps. |
178
+ | `apca` | Aggregated APCA contrast spans across ramps. |
179
+ | `contrastEfficiency` | RMS aggregate of ramp contrast-efficiency scores. |
180
+ | `lightnessLinearity` | RMS aggregate of ramp lightness-linearity scores. |
181
+ | `chromaSmoothness` | RMS aggregate of ramp chroma-smoothness scores. |
182
+ | `hueStability` | RMS aggregate of ramp hue-stability scores. |
183
+ | `spacingUniformity` | RMS aggregate of ramp spacing-uniformity scores. |
184
+ | `score` | Composite palette score. |
185
+
186
+ ## Reproducing Benchmarks
187
+ To run the benchmark generator locally:
188
+ ```bash
189
+ git clone https://github.com/chromametry/chromametry.git
199
190
  cd chromametry
200
191
  npm install
201
192
  npm run generate
202
193
  ```
203
194
 
204
195
  ## Adding Custom Palettes to Benchmark
205
- Create a new .ts file in benchmark/input/ (e.g., my-palette.ts).
196
+ Create a new .ts file in benchmark/input/ (e.g., my-palette.ts).
197
+
198
+ ```ts
199
+ import { red, volcano, gold } from '@ant-design/colors';
206
200
 
207
- ```ts
208
- import { red, volcano, gold } from '@ant-design/colors';
209
-
210
- // Define colors (imported or inline object)
211
- let colors: Record<string, string[]> = { red, volcano, gold };
201
+ // Define colors (imported or inline object)
202
+ let colors: Record<string, string[]> = { red, volcano, gold };
212
203
 
213
204
  // Ensure white/black anchors exist if your ramp misses them
214
205
  for (let name in colors) {
215
206
  if (colors[name][0] !== "#ffffff") colors[name].unshift("#ffffff");
216
207
  if (colors[name][colors[name].length - 1] !== "#000000") colors[name].push("#000000");
217
208
  }
218
- export default {
219
- name: "Ant Design",
220
- colors,
221
- };
222
- ```
209
+ export default {
210
+ name: "Ant Design",
211
+ colors,
212
+ };
213
+ ```
223
214
  Then regenerate the report:
224
215
  ```bash
225
216
  npm run generate
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var S=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var V=(u,n)=>{for(var t in n)S(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&&S(u,e,{get:()=>n[e],enumerable:!(s=G(n,e))||s.enumerable});return u};var $=u=>W(S({},"__esModule",{value:!0}),u);var st={};V(st,{Ramp:()=>y,Shade:()=>w,calcDeltaE2000:()=>v,calcScore:()=>P,calcStatistics:()=>nt,createMonotone:()=>k,cssRgbToRgb:()=>Q,fromLightnessEAL:()=>j,hexToRgb:()=>q,labToLch:()=>R,labToRgb:()=>J,lchToLab:()=>O,rgbToHex:()=>Z,rgbToLab:()=>L,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}`},q=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),o=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,m=.0603,r=.1307,i=.006,l=c*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+m,a=0;return(o<=90||o>=270)&&(a=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),n+(l+a)*e},j=(u,n)=>{let[,t,s]=n,e=Math.sqrt(t*t+s*s),o=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,m=.0603,r=.1307,i=.006,l=c*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+m,a=0;return(o<=90||o>=270)&&(a=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),Math.max(0,u-(l+a)*e)},O=u=>{let[n,t,s]=u,e=s*Math.PI/180;return[n,t*Math.cos(e),t*Math.sin(e)]},L=u=>{let[n,t,s]=u,e=.4124564*n+.3575761*t+.1804375*s,h=.2126729*n+.7151522*t+.072175*s,o=.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),a=i(h/m),M=i(o/r);return[116*a-16,500*(l-a),200*(a-M)]},J=u=>{let[n,t,s]=u,e=(n+16)/116,h=t/500+e,o=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,a=c(e)*r,M=c(o)*i;return[3.2404542*l-1.5371385*a-.4985314*M,-.969266*l+1.8760108*a+.041556*M,.0556434*l-.2040259*a+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 o=(Math.atan2(s,t)*180/Math.PI+360)%360;return o>=359.9999&&(o=0),[n,e,o]},v=(u,n)=>{let[t,s,e]=u,[h,o,c]=n,m=(t+h)/2,r=Math.sqrt(s*s+e*e),i=Math.sqrt(o*o+c*c),l=(r+i)/2,a=.5*(1-Math.sqrt(Math.pow(l,7)/(Math.pow(l,7)+Math.pow(25,7)))),M=s*(1+a),b=o*(1+a),f=Math.sqrt(M*M+e*e),g=Math.sqrt(b*b+c*c),x=(f+g)/2,d=Math.atan2(e,M)*180/Math.PI+(Math.atan2(e,M)<0?360:0),p=Math.atan2(c,b)*180/Math.PI+(Math.atan2(c,b)<0?360:0),I=p-d;Math.abs(I)>180&&(I+=p<=d?360:-360);let C=Math.abs(d-p)>180?(d+p+360)/2:(d+p)/2,H=1-.17*Math.cos((C-30)*Math.PI/180)+.24*Math.cos(2*C*Math.PI/180)+.32*Math.cos((3*C+6)*Math.PI/180)-.2*Math.cos((4*C-63)*Math.PI/180),Y=h-t,E=g-f,T=2*Math.sqrt(f*g)*Math.sin(I/2*Math.PI/180),A=1+.015*Math.pow(m-50,2)/Math.sqrt(20+Math.pow(m-50,2)),B=1+.045*x,D=1+.015*x*H,X=30*Math.exp(-Math.pow((C-275)/25,2)),z=-(2*Math.sqrt(Math.pow(x,7)/(Math.pow(x,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]),o=[],c=[];for(let r=0;r<s-1;r++)o[r]=e[r+1]-e[r],c[r]=(h[r+1]-h[r])/o[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 a=(1+o[r]/(o[r-1]+o[r]))/3;m[r]=i*l/((1-a)*i+a*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,a=0;for(;i<=l;){let p=Math.floor((i+l)/2);if(r>=e[p]&&r<=e[p+1]){a=p;break}r<e[p]?l=p-1:i=p+1}let M=o[a],b=(r-e[a])/M,f=b*b,g=f*b,x=m[a]*M,d=m[a+1]*M;return(2*g-3*f+1)*h[a]+(g-2*f+b)*x+(-2*g+3*f)*h[a+1]+(g-f)*d}};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 o=u[h];o<t&&(t=o),o>s&&(s=o),e+=o}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((o,c)=>o*(c+t),1),e=Math.pow(s,1/n),h=Math.max(0,Math.min(1,e));return parseFloat((h*100).toFixed(2))};var w=class{constructor(n){this.hex=n}get rgb(){return q(this.hex)}get lab(){return L(this.rgb)}get lch(){return R(this.lab)}get lightness(){let[n,t,s]=this.lab,e=Math.sqrt(t*t+s*s),o=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,m=.0603,r=.1307,i=.006,l=c*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+m,a=0;return(o<=90||o>=270)&&(a=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),n+(l+a)*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.shades=n.map(s=>new w(s)),this.name=t}get colors(){return this.shades.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 w(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 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.shades,t=n.length,s=t-1,e={};for(let h of[30,45,70]){let o=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 a=n[l].luminance,M=n[l+r].luminance,b=(Math.max(a,M)+.05)/(Math.min(a,M)+.05);b<i&&(i=b)}if(i>=o){c=r,m=i;break}r===s&&(m=i)}e[h]={efficiency:c/s,target:o,span:c,value:m}}return e}get apca(){let n=this.shades,t=n.length,s=t-1,e={},h=(o,c)=>{let i=o<.022?o+Math.pow(.022-o,1.414):o,l=c<.022?c+Math.pow(.022-c,1.414):c,a=l>=i?(Math.pow(l,.56)-Math.pow(i,.57))*114:(Math.pow(l,.65)-Math.pow(i,.62))*114;return Math.abs(a)<10?0:(a=a>0?a-2.7:a+2.7,Math.round(a))};for(let o of[45,60,75]){let c=o,m=s,r=0;for(let i=1;i<t;i++){let l=1/0;for(let a=0;a<t-i;a++){let M=n[a].luminance>n[a+i].luminance?n[a].luminance:n[a+i].luminance,b=n[a].luminance>n[a+i].luminance?n[a+i].luminance:n[a].luminance,f=Math.abs(h(b,M));f<l&&(l=f)}if(l>=c){m=i,r=l;break}i===s&&(r=l)}e[o]={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.shades.length;t++){let s=v(this.shades[t-1].lab,this.shades[t].lab);n.push(n[t-1]+s)}return n}get unwrapHues(){let n=this.shades.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.shades.map(M=>M.lightness),t=n.length;if(t<2)return 1;let s=0,e=0,h=0,o=0;for(let M=0;M<t;M++)s+=M,e+=n[M],h+=M*n[M],o+=M*M;let c=t*o-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,a=0;for(let M=0;M<t;M++){let b=m*M+r,f=n[M]-b;l+=f*f;let g=Math.max(b-Math.min(r,m*(t-1)+r),Math.max(r,m*(t-1)+r)-b);a+=g*g}return Math.max(0,Math.min(1,1-Math.sqrt(l/t)/Math.sqrt(a/t)))}get chromaSmoothness(){let n=this.shades.map(a=>a.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(a=>a/e*s),o=Math.min(...h),c=Math.max(...h),m=h.findIndex(a=>a===c),r=k([[0,h[0]],[m,c],[t-1,h[t-1]]]),i=0,l=0;for(let a=0;a<t;a++){let M=r(a),b=h[a]-M;i+=b*b,l+=Math.pow(Math.max(M-o,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 o=Math.sqrt(h/s.length)/e;return Math.max(0,Math.min(1,1/(1+o)))}get hueStability(){var o,c,m;let n=this.unwrapHues,t=n.length;if(t<2)return 1;let s=(m=(c=n[this.baseIndex-1])!=null?c:(o=this.shades[this.baseIndex])==null?void 0:o.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,Shade,calcDeltaE2000,calcScore,calcStatistics,createMonotone,cssRgbToRgb,fromLightnessEAL,hexToRgb,labToLch,labToRgb,lchToLab,rgbToHex,rgbToLab,rootMeanSquare,toLightnessEAL});
1
+ "use strict";var v=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var O=(l,t)=>{for(var s in t)v(l,s,{get:t[s],enumerable:!0})},V=(l,t,s,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of j(t))!N.call(l,e)&&e!==s&&v(l,e,{get:()=>t[e],enumerable:!(n=G(t,e))||n.enumerable});return l};var $=l=>V(v({},"__esModule",{value:!0}),l);var et={};O(et,{Palette:()=>T,Ramp:()=>q,Swatch:()=>y,calcDeltaE2000:()=>k,calcScore:()=>L,calcStatistics:()=>nt,createMonotone:()=>E,cssRgbToRgb:()=>st,fromLightnessEAL:()=>J,hexToRgb:()=>C,labToLch:()=>P,labToRgb:()=>tt,lchToLab:()=>Q,rgbToHex:()=>Z,rgbToLab:()=>S,rootMeanSquare:()=>d,toLightnessEAL:()=>_});module.exports=$(et);var F=l=>{let t=s=>{let n=Math.max(0,Math.min(1,s)),e=n<=.0031308?12.92*n:1.055*Math.pow(n,1/2.4)-.055;return Math.max(0,Math.min(255,Math.round(e*255)))};return l.map(t)},K=l=>{let t=s=>s>.04045?Math.pow((s+.055)/1.055,2.4):s/12.92;return l.map(t)},Z=l=>{let[t,s,n]=F(l);return t=t.toString(16).padStart(2,"0"),s=s.toString(16).padStart(2,"0"),n=n.toString(16).padStart(2,"0"),`#${t}${s}${n}`},C=l=>{let t=parseInt(l.slice(1,3),16)/255,s=parseInt(l.slice(3,5),16)/255,n=parseInt(l.slice(5,7),16)/255;return K([t,s,n])},_=l=>{let[t,s,n]=l,e=Math.sqrt(s*s+n*n),o=(Math.atan2(n,s)*180/Math.PI+360)%360,a=.1644,u=.0603,r=.1307,i=.006,m=a*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+u,c=0;return(o<=90||o>=270)&&(c=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),t+(m+c)*e},J=(l,t)=>{let[,s,n]=t,e=Math.sqrt(s*s+n*n),o=(Math.atan2(n,s)*180/Math.PI+360)%360,a=.1644,u=.0603,r=.1307,i=.006,m=a*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+u,c=0;return(o<=90||o>=270)&&(c=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),Math.max(0,l-(m+c)*e)},Q=l=>{let[t,s,n]=l,e=n*Math.PI/180;return[t,s*Math.cos(e),s*Math.sin(e)]},S=l=>{let[t,s,n]=l,e=.4124564*t+.3575761*s+.1804375*n,h=.2126729*t+.7151522*s+.072175*n,o=.0193339*t+.119192*s+.9503041*n,a=.95047,u=1,r=1.08883,i=g=>g>.008856?Math.cbrt(g):7.787*g+16/116,m=i(e/a),c=i(h/u),p=i(o/r);return[116*c-16,500*(m-c),200*(c-p)]},tt=l=>{let[t,s,n]=l,e=(t+16)/116,h=s/500+e,o=e-n/200,a=g=>g**3>.008856?g**3:(g-16/116)/7.787,u=.95047,r=1,i=1.08883,m=a(h)*u,c=a(e)*r,p=a(o)*i;return[3.2404542*m-1.5371385*c-.4985314*p,-.969266*m+1.8760108*c+.041556*p,.0556434*m-.2040259*c+1.0572252*p]},P=l=>{let[t,s,n]=l,e=Math.sqrt(s*s+n*n);if(e<1e-4)return[t,0,0];let o=(Math.atan2(n,s)*180/Math.PI+360)%360;return o>=359.9999&&(o=0),[t,e,o]},k=(l,t)=>{let[s,n,e]=l,[h,o,a]=t,u=(s+h)/2,r=Math.sqrt(n*n+e*e),i=Math.sqrt(o*o+a*a),m=(r+i)/2,c=.5*(1-Math.sqrt(Math.pow(m,7)/(Math.pow(m,7)+Math.pow(25,7)))),p=n*(1+c),g=o*(1+c),M=Math.sqrt(p*p+e*e),b=Math.sqrt(g*g+a*a),w=(M+b)/2,x=Math.atan2(e,p)*180/Math.PI+(Math.atan2(e,p)<0?360:0),f=Math.atan2(a,g)*180/Math.PI+(Math.atan2(a,g)<0?360:0),R=f-x;Math.abs(R)>180&&(R+=f<=x?360:-360);let I=Math.abs(x-f)>180?(x+f+360)/2:(x+f)/2,Y=1-.17*Math.cos((I-30)*Math.PI/180)+.24*Math.cos(2*I*Math.PI/180)+.32*Math.cos((3*I+6)*Math.PI/180)-.2*Math.cos((4*I-63)*Math.PI/180),U=h-s,B=b-M,A=2*Math.sqrt(M*b)*Math.sin(R/2*Math.PI/180),W=1+.015*Math.pow(u-50,2)/Math.sqrt(20+Math.pow(u-50,2)),D=1+.045*w,H=1+.015*w*Y,X=30*Math.exp(-Math.pow((I-275)/25,2)),z=-(2*Math.sqrt(Math.pow(w,7)/(Math.pow(w,7)+Math.pow(25,7))))*Math.sin(2*X*Math.PI/180);return Math.sqrt(Math.pow(U/W,2)+Math.pow(B/D,2)+Math.pow(A/H,2)+z*(B/D)*(A/H))},st=l=>{let t=l.match(/\d+(\.\d+)?/g);if(!t||t.length<3)throw new Error("Invalid CSS rgb()");let s=n=>{let e=n/255;return e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4)};return[s(Number(t[0])),s(Number(t[1])),s(Number(t[2]))]},E=l=>{if(l.length<1)return r=>0;let t=[...l].sort((r,i)=>r[0]-i[0]),s=[];for(let r=0;r<t.length;r++)(r===0||t[r][0]!==t[r-1][0])&&s.push(t[r]);let n=s.length;if(n===1)return r=>s[0][1];let e=s.map(r=>r[0]),h=s.map(r=>r[1]),o=[],a=[];for(let r=0;r<n-1;r++)o[r]=e[r+1]-e[r],a[r]=(h[r+1]-h[r])/o[r];let u=new Array(n);u[0]=a[0],u[n-1]=a[n-2];for(let r=1;r<n-1;r++){let i=a[r-1],m=a[r];if(i*m<=0)u[r]=0;else{let c=(1+o[r]/(o[r-1]+o[r]))/3;u[r]=i*m/((1-c)*i+c*m)}}return r=>{if(r<=e[0])return h[0];if(r>=e[n-1])return h[n-1];let i=0,m=n-2,c=0;for(;i<=m;){let f=Math.floor((i+m)/2);if(r>=e[f]&&r<=e[f+1]){c=f;break}r<e[f]?m=f-1:i=f+1}let p=o[c],g=(r-e[c])/p,M=g*g,b=M*g,w=u[c]*p,x=u[c+1]*p;return(2*b-3*M+1)*h[c]+(b-2*M+g)*w+(-2*b+3*M)*h[c+1]+(b-M)*x}};function d(l){let t=l.length;if(t===0)return 0;let s=0;for(let n=0;n<t;n++)s+=l[n]*l[n];return Math.sqrt(s/t)}var nt=l=>{let t=l.length;if(t===0)return{min:0,max:0,avg:0};let s=l[0],n=l[0],e=0;for(let h=0;h<t;h++){let o=l[h];o<s&&(s=o),o>n&&(n=o),e+=o}return{min:s,max:n,avg:e/t}},L=l=>{let t=l.length;if(t===0)return 0;let s=1e-6,n=l.reduce((o,a)=>o*(a+s),1),e=Math.pow(n,1/t),h=Math.max(0,Math.min(1,e));return parseFloat((h*100).toFixed(2))};var y=class{constructor(t){this.hex=t}get rgb(){return C(this.hex)}get lab(){return S(this.rgb)}get lch(){return P(this.lab)}get lightness(){let[t,s,n]=this.lab,e=Math.sqrt(s*s+n*n),o=(Math.atan2(n,s)*180/Math.PI+360)%360,a=.1644,u=.0603,r=.1307,i=.006,m=a*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+u,c=0;return(o<=90||o>=270)&&(c=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),t+(m+c)*e}get chroma(){return this.lch[1]}get hue(){return this.lch[2]}get luminance(){let[t,s,n]=this.rgb;return .2126*t+.7152*s+.0722*n}get wcag(){return(Math.max(this.luminance,1)+.05)/(Math.min(this.luminance,1)+.05)}get apca(){let t=h=>h>5e-4?h:h+Math.pow(5e-4-h,.8),s=t(this.luminance),n=t(1),e=(Math.pow(s,.56)-Math.pow(n,.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 q=class{constructor(t=[],s="brand"){this.swatches=t.map(n=>new y(n)),this.name=s}get colors(){return this.swatches.map(t=>t.hex)}get peakChroma(){let t=this.colors.slice(2,-2),s="",n=-1/0;for(let e of t){let h=new y(e);h.chroma>n&&(n=h.chroma,s=e)}return n<6?this.colors[Math.ceil(this.steps/2)]:s}get steps(){return this.colors.length}get direction(){if(this.colors.length===0)return"lighten";let t=S(C(this.colors[0])),s=S(C(this.colors[this.colors.length-1]));return t[0]>s[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(t=>t.toLowerCase()===this.baseColor.toLowerCase())}get wcag(){let t=this.swatches,s=t.length,n=s-1,e={};for(let h of[30,45,70]){let o=h/10,a=n,u=0;for(let r=1;r<s;r++){let i=1/0;for(let m=0;m<s-r;m++){let c=t[m].luminance,p=t[m+r].luminance,g=(Math.max(c,p)+.05)/(Math.min(c,p)+.05);g<i&&(i=g)}if(i>=o){a=r,u=i;break}r===n&&(u=i)}e[h]={efficiency:a/n,target:o,span:a,value:u}}return e}get apca(){let t=this.swatches,s=t.length,n=s-1,e={},h=(o,a)=>{let i=o<.022?o+Math.pow(.022-o,1.414):o,m=a<.022?a+Math.pow(.022-a,1.414):a,c=m>=i?(Math.pow(m,.56)-Math.pow(i,.57))*114:(Math.pow(m,.65)-Math.pow(i,.62))*114;return Math.abs(c)<10?0:(c=c>0?c-2.7:c+2.7,Math.round(c))};for(let o of[45,60,75]){let a=o,u=n,r=0;for(let i=1;i<s;i++){let m=1/0;for(let c=0;c<s-i;c++){let p=t[c].luminance>t[c+i].luminance?t[c].luminance:t[c+i].luminance,g=t[c].luminance>t[c+i].luminance?t[c+i].luminance:t[c].luminance,M=Math.abs(h(g,p));M<m&&(m=M)}if(m>=a){u=i,r=m;break}i===n&&(r=m)}e[o]={efficiency:u/n,target:a,span:u,value:r}}return e}get contrasts(){return{wcag:this.wcag,apca:this.apca}}get deltaECurve(){let t=[0];for(let s=1;s<this.swatches.length;s++){let n=k(this.swatches[s-1].lab,this.swatches[s].lab);t.push(t[s-1]+n)}return t}get unwrapHues(){let t=this.swatches.map(n=>n.hue).slice(1,-1);if(t.length===0)return[];let s=[t[0]];for(let n=1;n<t.length;n++){let e=t[n]-t[n-1];e>180?e-=360:e<-180&&(e+=360),s.push(s[n-1]+e)}return s}get lightnessLinearity(){let t=this.swatches.map(p=>p.lightness),s=t.length;if(s<2)return 1;let n=0,e=0,h=0,o=0;for(let p=0;p<s;p++)n+=p,e+=t[p],h+=p*t[p],o+=p*p;let a=s*o-n*n;if(Math.abs(a)<1e-10)return 1;let u=(s*h-n*e)/a,r=(e-u*n)/s;if(Math.abs(u*(s-1))<.001)return 1;let m=0,c=0;for(let p=0;p<s;p++){let g=u*p+r,M=t[p]-g;m+=M*M;let b=Math.max(g-Math.min(r,u*(s-1)+r),Math.max(r,u*(s-1)+r)-g);c+=b*b}return Math.max(0,Math.min(1,1-Math.sqrt(m/s)/Math.sqrt(c/s)))}get chromaSmoothness(){let t=this.swatches.map(c=>c.chroma),s=t.length;if(s<3)return 1;let n=133.8,e=Math.max(...t);if(e<=.01)return 1;let h=t.map(c=>c/e*n),o=Math.min(...h),a=Math.max(...h),u=h.findIndex(c=>c===a),r=E([[0,h[0]],[u,a],[s-1,h[s-1]]]),i=0,m=0;for(let c=0;c<s;c++){let p=r(c),g=h[c]-p;i+=g*g,m+=Math.pow(Math.max(p-o,a-p),2)}return Math.max(0,Math.min(1,1-Math.sqrt(i/s)/Math.sqrt(m/s)))}get spacingUniformity(){let t=this.deltaECurve,s=t.length;if(s<2)return 1;let n=[];for(let a=1;a<s;a++){let u=t[a]-t[a-1];if(u<0)return 0;n.push(u)}let e=n.reduce((a,u)=>a+u,0)/n.length;if(e<=1e-6)return 0;let h=0;for(let a of n)h+=Math.pow(a-e,2);let o=Math.sqrt(h/n.length)/e;return Math.max(0,Math.min(1,1/(1+o)))}get hueStability(){var o,a,u;let t=this.unwrapHues,s=t.length;if(s<2)return 1;let n=(u=(a=t[this.baseIndex-1])!=null?a:(o=this.swatches[this.baseIndex])==null?void 0:o.hue)!=null?u:0,e=0,h=0;for(let r=0;r<s;r++){let i=Math.abs(t[r]-n)%360;i>180&&(i=360-i),e+=i*i;let m=r/(s-1)*180;h+=m*m}return Math.max(0,Math.min(1,1-Math.sqrt(e/s)/(Math.sqrt(h/s)||1)))}get contrastEfficiency(){let t=this.wcag[45].span,s=this.steps;if(s<=1)return 1;let n=.501,e=t/(s-1);return e<=n?1:e>=1?0:1-(e-n)/(1-n)}get metrics(){return{lightnessLinearity:this.lightnessLinearity,chromaSmoothness:this.chromaSmoothness,spacingUniformity:this.spacingUniformity,hueStability:this.hueStability,contrastEfficiency:this.contrastEfficiency}}get score(){return L(Object.values(this.metrics))}};var T=class{constructor(t={},s="Collection 1"){this.ramps=Object.entries(t).map(([n,e])=>new q(e,n)),this.name=s}get colors(){return Object.fromEntries(this.ramps.map(t=>[t.name,t.colors]))}get steps(){var t;return((t=this.ramps[0])==null?void 0:t.steps)||0}get wcag(){let t={},s=this.steps;for(let n of[30,45,70]){let e=this.ramps.map(a=>a.wcag[n]),h=Math.max(0,...e.map(a=>(a==null?void 0:a.span)||0)),o=e.reduce((a,u)=>a+((u==null?void 0:u.value)||0),0);t[n]={target:n/10,span:h,value:o/(this.ramps.length||1),efficiency:s>1?h/(s-1):0}}return t}get apca(){let t={},s=this.steps;for(let n of[45,60,75]){let e=this.ramps.map(a=>a.apca[n]),h=Math.max(0,...e.map(a=>(a==null?void 0:a.span)||0)),o=e.reduce((a,u)=>a+((u==null?void 0:u.value)||0),0);t[n]={target:n,span:h,value:o/(this.ramps.length||1),efficiency:s>1?h/(s-1):0}}return t}get contrastEfficiency(){return d(this.ramps.map(t=>t.contrastEfficiency))}get lightnessLinearity(){return d(this.ramps.map(t=>t.lightnessLinearity))}get chromaSmoothness(){return d(this.ramps.map(t=>t.chromaSmoothness))}get hueStability(){return d(this.ramps.map(t=>t.hueStability))}get spacingUniformity(){return d(this.ramps.map(t=>t.spacingUniformity))}get score(){return L([this.contrastEfficiency,this.lightnessLinearity,this.chromaSmoothness,this.hueStability,this.spacingUniformity])}};0&&(module.exports={Palette,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 Shade {
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
- shades: Shade[];
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,21 @@ declare class Ramp {
89
90
  get score(): number;
90
91
  }
91
92
 
92
- export { type ApcaContrasts, type ContrastValue, Ramp, Shade, type WcagContrasts, calcDeltaE2000, calcScore, calcStatistics, createMonotone, cssRgbToRgb, fromLightnessEAL, hexToRgb, labToLch, labToRgb, lchToLab, rgbToHex, rgbToLab, rootMeanSquare, toLightnessEAL };
93
+ type PaletteColors = Record<string, string[]>;
94
+ declare class Palette {
95
+ ramps: Ramp[];
96
+ name: string;
97
+ constructor(colors?: PaletteColors, name?: string);
98
+ get colors(): PaletteColors;
99
+ get steps(): number;
100
+ get wcag(): WcagContrasts;
101
+ get apca(): ApcaContrasts;
102
+ get contrastEfficiency(): number;
103
+ get lightnessLinearity(): number;
104
+ get chromaSmoothness(): number;
105
+ get hueStability(): number;
106
+ get spacingUniformity(): number;
107
+ get score(): number;
108
+ }
109
+
110
+ export { type ApcaContrasts, type ContrastValue, Palette, type PaletteColors, 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 Shade {
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
- shades: Shade[];
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,21 @@ declare class Ramp {
89
90
  get score(): number;
90
91
  }
91
92
 
92
- export { type ApcaContrasts, type ContrastValue, Ramp, Shade, type WcagContrasts, calcDeltaE2000, calcScore, calcStatistics, createMonotone, cssRgbToRgb, fromLightnessEAL, hexToRgb, labToLch, labToRgb, lchToLab, rgbToHex, rgbToLab, rootMeanSquare, toLightnessEAL };
93
+ type PaletteColors = Record<string, string[]>;
94
+ declare class Palette {
95
+ ramps: Ramp[];
96
+ name: string;
97
+ constructor(colors?: PaletteColors, name?: string);
98
+ get colors(): PaletteColors;
99
+ get steps(): number;
100
+ get wcag(): WcagContrasts;
101
+ get apca(): ApcaContrasts;
102
+ get contrastEfficiency(): number;
103
+ get lightnessLinearity(): number;
104
+ get chromaSmoothness(): number;
105
+ get hueStability(): number;
106
+ get spacingUniformity(): number;
107
+ get score(): number;
108
+ }
109
+
110
+ export { type ApcaContrasts, type ContrastValue, Palette, type PaletteColors, Ramp, Swatch, type WcagContrasts, calcDeltaE2000, calcScore, calcStatistics, createMonotone, cssRgbToRgb, fromLightnessEAL, hexToRgb, labToLch, labToRgb, lchToLab, rgbToHex, rgbToLab, rootMeanSquare, toLightnessEAL };
@@ -1 +1 @@
1
- "use strict";var Chromametry=(()=>{var S=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var V=(u,n)=>{for(var t in n)S(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&&S(u,e,{get:()=>n[e],enumerable:!(s=G(n,e))||s.enumerable});return u};var $=u=>W(S({},"__esModule",{value:!0}),u);var st={};V(st,{Ramp:()=>y,Shade:()=>w,calcDeltaE2000:()=>v,calcScore:()=>P,calcStatistics:()=>nt,createMonotone:()=>k,cssRgbToRgb:()=>Q,fromLightnessEAL:()=>j,hexToRgb:()=>q,labToLch:()=>R,labToRgb:()=>J,lchToLab:()=>O,rgbToHex:()=>Z,rgbToLab:()=>L,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}`},q=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),o=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,m=.0603,r=.1307,i=.006,l=c*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+m,a=0;return(o<=90||o>=270)&&(a=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),n+(l+a)*e},j=(u,n)=>{let[,t,s]=n,e=Math.sqrt(t*t+s*s),o=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,m=.0603,r=.1307,i=.006,l=c*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+m,a=0;return(o<=90||o>=270)&&(a=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),Math.max(0,u-(l+a)*e)},O=u=>{let[n,t,s]=u,e=s*Math.PI/180;return[n,t*Math.cos(e),t*Math.sin(e)]},L=u=>{let[n,t,s]=u,e=.4124564*n+.3575761*t+.1804375*s,h=.2126729*n+.7151522*t+.072175*s,o=.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),a=i(h/m),M=i(o/r);return[116*a-16,500*(l-a),200*(a-M)]},J=u=>{let[n,t,s]=u,e=(n+16)/116,h=t/500+e,o=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,a=c(e)*r,M=c(o)*i;return[3.2404542*l-1.5371385*a-.4985314*M,-.969266*l+1.8760108*a+.041556*M,.0556434*l-.2040259*a+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 o=(Math.atan2(s,t)*180/Math.PI+360)%360;return o>=359.9999&&(o=0),[n,e,o]},v=(u,n)=>{let[t,s,e]=u,[h,o,c]=n,m=(t+h)/2,r=Math.sqrt(s*s+e*e),i=Math.sqrt(o*o+c*c),l=(r+i)/2,a=.5*(1-Math.sqrt(Math.pow(l,7)/(Math.pow(l,7)+Math.pow(25,7)))),M=s*(1+a),b=o*(1+a),f=Math.sqrt(M*M+e*e),g=Math.sqrt(b*b+c*c),x=(f+g)/2,d=Math.atan2(e,M)*180/Math.PI+(Math.atan2(e,M)<0?360:0),p=Math.atan2(c,b)*180/Math.PI+(Math.atan2(c,b)<0?360:0),I=p-d;Math.abs(I)>180&&(I+=p<=d?360:-360);let C=Math.abs(d-p)>180?(d+p+360)/2:(d+p)/2,H=1-.17*Math.cos((C-30)*Math.PI/180)+.24*Math.cos(2*C*Math.PI/180)+.32*Math.cos((3*C+6)*Math.PI/180)-.2*Math.cos((4*C-63)*Math.PI/180),Y=h-t,E=g-f,T=2*Math.sqrt(f*g)*Math.sin(I/2*Math.PI/180),A=1+.015*Math.pow(m-50,2)/Math.sqrt(20+Math.pow(m-50,2)),B=1+.045*x,D=1+.015*x*H,X=30*Math.exp(-Math.pow((C-275)/25,2)),z=-(2*Math.sqrt(Math.pow(x,7)/(Math.pow(x,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]),o=[],c=[];for(let r=0;r<s-1;r++)o[r]=e[r+1]-e[r],c[r]=(h[r+1]-h[r])/o[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 a=(1+o[r]/(o[r-1]+o[r]))/3;m[r]=i*l/((1-a)*i+a*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,a=0;for(;i<=l;){let p=Math.floor((i+l)/2);if(r>=e[p]&&r<=e[p+1]){a=p;break}r<e[p]?l=p-1:i=p+1}let M=o[a],b=(r-e[a])/M,f=b*b,g=f*b,x=m[a]*M,d=m[a+1]*M;return(2*g-3*f+1)*h[a]+(g-2*f+b)*x+(-2*g+3*f)*h[a+1]+(g-f)*d}};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 o=u[h];o<t&&(t=o),o>s&&(s=o),e+=o}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((o,c)=>o*(c+t),1),e=Math.pow(s,1/n),h=Math.max(0,Math.min(1,e));return parseFloat((h*100).toFixed(2))};var w=class{constructor(n){this.hex=n}get rgb(){return q(this.hex)}get lab(){return L(this.rgb)}get lch(){return R(this.lab)}get lightness(){let[n,t,s]=this.lab,e=Math.sqrt(t*t+s*s),o=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,m=.0603,r=.1307,i=.006,l=c*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+m,a=0;return(o<=90||o>=270)&&(a=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),n+(l+a)*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.shades=n.map(s=>new w(s)),this.name=t}get colors(){return this.shades.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 w(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 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.shades,t=n.length,s=t-1,e={};for(let h of[30,45,70]){let o=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 a=n[l].luminance,M=n[l+r].luminance,b=(Math.max(a,M)+.05)/(Math.min(a,M)+.05);b<i&&(i=b)}if(i>=o){c=r,m=i;break}r===s&&(m=i)}e[h]={efficiency:c/s,target:o,span:c,value:m}}return e}get apca(){let n=this.shades,t=n.length,s=t-1,e={},h=(o,c)=>{let i=o<.022?o+Math.pow(.022-o,1.414):o,l=c<.022?c+Math.pow(.022-c,1.414):c,a=l>=i?(Math.pow(l,.56)-Math.pow(i,.57))*114:(Math.pow(l,.65)-Math.pow(i,.62))*114;return Math.abs(a)<10?0:(a=a>0?a-2.7:a+2.7,Math.round(a))};for(let o of[45,60,75]){let c=o,m=s,r=0;for(let i=1;i<t;i++){let l=1/0;for(let a=0;a<t-i;a++){let M=n[a].luminance>n[a+i].luminance?n[a].luminance:n[a+i].luminance,b=n[a].luminance>n[a+i].luminance?n[a+i].luminance:n[a].luminance,f=Math.abs(h(b,M));f<l&&(l=f)}if(l>=c){m=i,r=l;break}i===s&&(r=l)}e[o]={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.shades.length;t++){let s=v(this.shades[t-1].lab,this.shades[t].lab);n.push(n[t-1]+s)}return n}get unwrapHues(){let n=this.shades.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.shades.map(M=>M.lightness),t=n.length;if(t<2)return 1;let s=0,e=0,h=0,o=0;for(let M=0;M<t;M++)s+=M,e+=n[M],h+=M*n[M],o+=M*M;let c=t*o-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,a=0;for(let M=0;M<t;M++){let b=m*M+r,f=n[M]-b;l+=f*f;let g=Math.max(b-Math.min(r,m*(t-1)+r),Math.max(r,m*(t-1)+r)-b);a+=g*g}return Math.max(0,Math.min(1,1-Math.sqrt(l/t)/Math.sqrt(a/t)))}get chromaSmoothness(){let n=this.shades.map(a=>a.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(a=>a/e*s),o=Math.min(...h),c=Math.max(...h),m=h.findIndex(a=>a===c),r=k([[0,h[0]],[m,c],[t-1,h[t-1]]]),i=0,l=0;for(let a=0;a<t;a++){let M=r(a),b=h[a]-M;i+=b*b,l+=Math.pow(Math.max(M-o,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 o=Math.sqrt(h/s.length)/e;return Math.max(0,Math.min(1,1/(1+o)))}get hueStability(){var o,c,m;let n=this.unwrapHues,t=n.length;if(t<2)return 1;let s=(m=(c=n[this.baseIndex-1])!=null?c:(o=this.shades[this.baseIndex])==null?void 0:o.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);})();
1
+ "use strict";var Chromametry=(()=>{var v=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var O=(l,t)=>{for(var s in t)v(l,s,{get:t[s],enumerable:!0})},V=(l,t,s,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of j(t))!N.call(l,e)&&e!==s&&v(l,e,{get:()=>t[e],enumerable:!(n=G(t,e))||n.enumerable});return l};var $=l=>V(v({},"__esModule",{value:!0}),l);var et={};O(et,{Palette:()=>T,Ramp:()=>q,Swatch:()=>y,calcDeltaE2000:()=>k,calcScore:()=>L,calcStatistics:()=>nt,createMonotone:()=>E,cssRgbToRgb:()=>st,fromLightnessEAL:()=>J,hexToRgb:()=>C,labToLch:()=>P,labToRgb:()=>tt,lchToLab:()=>Q,rgbToHex:()=>Z,rgbToLab:()=>S,rootMeanSquare:()=>d,toLightnessEAL:()=>_});var F=l=>{let t=s=>{let n=Math.max(0,Math.min(1,s)),e=n<=.0031308?12.92*n:1.055*Math.pow(n,1/2.4)-.055;return Math.max(0,Math.min(255,Math.round(e*255)))};return l.map(t)},K=l=>{let t=s=>s>.04045?Math.pow((s+.055)/1.055,2.4):s/12.92;return l.map(t)},Z=l=>{let[t,s,n]=F(l);return t=t.toString(16).padStart(2,"0"),s=s.toString(16).padStart(2,"0"),n=n.toString(16).padStart(2,"0"),`#${t}${s}${n}`},C=l=>{let t=parseInt(l.slice(1,3),16)/255,s=parseInt(l.slice(3,5),16)/255,n=parseInt(l.slice(5,7),16)/255;return K([t,s,n])},_=l=>{let[t,s,n]=l,e=Math.sqrt(s*s+n*n),o=(Math.atan2(n,s)*180/Math.PI+360)%360,a=.1644,u=.0603,r=.1307,i=.006,m=a*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+u,c=0;return(o<=90||o>=270)&&(c=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),t+(m+c)*e},J=(l,t)=>{let[,s,n]=t,e=Math.sqrt(s*s+n*n),o=(Math.atan2(n,s)*180/Math.PI+360)%360,a=.1644,u=.0603,r=.1307,i=.006,m=a*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+u,c=0;return(o<=90||o>=270)&&(c=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),Math.max(0,l-(m+c)*e)},Q=l=>{let[t,s,n]=l,e=n*Math.PI/180;return[t,s*Math.cos(e),s*Math.sin(e)]},S=l=>{let[t,s,n]=l,e=.4124564*t+.3575761*s+.1804375*n,h=.2126729*t+.7151522*s+.072175*n,o=.0193339*t+.119192*s+.9503041*n,a=.95047,u=1,r=1.08883,i=g=>g>.008856?Math.cbrt(g):7.787*g+16/116,m=i(e/a),c=i(h/u),p=i(o/r);return[116*c-16,500*(m-c),200*(c-p)]},tt=l=>{let[t,s,n]=l,e=(t+16)/116,h=s/500+e,o=e-n/200,a=g=>g**3>.008856?g**3:(g-16/116)/7.787,u=.95047,r=1,i=1.08883,m=a(h)*u,c=a(e)*r,p=a(o)*i;return[3.2404542*m-1.5371385*c-.4985314*p,-.969266*m+1.8760108*c+.041556*p,.0556434*m-.2040259*c+1.0572252*p]},P=l=>{let[t,s,n]=l,e=Math.sqrt(s*s+n*n);if(e<1e-4)return[t,0,0];let o=(Math.atan2(n,s)*180/Math.PI+360)%360;return o>=359.9999&&(o=0),[t,e,o]},k=(l,t)=>{let[s,n,e]=l,[h,o,a]=t,u=(s+h)/2,r=Math.sqrt(n*n+e*e),i=Math.sqrt(o*o+a*a),m=(r+i)/2,c=.5*(1-Math.sqrt(Math.pow(m,7)/(Math.pow(m,7)+Math.pow(25,7)))),p=n*(1+c),g=o*(1+c),M=Math.sqrt(p*p+e*e),b=Math.sqrt(g*g+a*a),w=(M+b)/2,x=Math.atan2(e,p)*180/Math.PI+(Math.atan2(e,p)<0?360:0),f=Math.atan2(a,g)*180/Math.PI+(Math.atan2(a,g)<0?360:0),R=f-x;Math.abs(R)>180&&(R+=f<=x?360:-360);let I=Math.abs(x-f)>180?(x+f+360)/2:(x+f)/2,Y=1-.17*Math.cos((I-30)*Math.PI/180)+.24*Math.cos(2*I*Math.PI/180)+.32*Math.cos((3*I+6)*Math.PI/180)-.2*Math.cos((4*I-63)*Math.PI/180),U=h-s,B=b-M,A=2*Math.sqrt(M*b)*Math.sin(R/2*Math.PI/180),W=1+.015*Math.pow(u-50,2)/Math.sqrt(20+Math.pow(u-50,2)),D=1+.045*w,H=1+.015*w*Y,X=30*Math.exp(-Math.pow((I-275)/25,2)),z=-(2*Math.sqrt(Math.pow(w,7)/(Math.pow(w,7)+Math.pow(25,7))))*Math.sin(2*X*Math.PI/180);return Math.sqrt(Math.pow(U/W,2)+Math.pow(B/D,2)+Math.pow(A/H,2)+z*(B/D)*(A/H))},st=l=>{let t=l.match(/\d+(\.\d+)?/g);if(!t||t.length<3)throw new Error("Invalid CSS rgb()");let s=n=>{let e=n/255;return e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4)};return[s(Number(t[0])),s(Number(t[1])),s(Number(t[2]))]},E=l=>{if(l.length<1)return r=>0;let t=[...l].sort((r,i)=>r[0]-i[0]),s=[];for(let r=0;r<t.length;r++)(r===0||t[r][0]!==t[r-1][0])&&s.push(t[r]);let n=s.length;if(n===1)return r=>s[0][1];let e=s.map(r=>r[0]),h=s.map(r=>r[1]),o=[],a=[];for(let r=0;r<n-1;r++)o[r]=e[r+1]-e[r],a[r]=(h[r+1]-h[r])/o[r];let u=new Array(n);u[0]=a[0],u[n-1]=a[n-2];for(let r=1;r<n-1;r++){let i=a[r-1],m=a[r];if(i*m<=0)u[r]=0;else{let c=(1+o[r]/(o[r-1]+o[r]))/3;u[r]=i*m/((1-c)*i+c*m)}}return r=>{if(r<=e[0])return h[0];if(r>=e[n-1])return h[n-1];let i=0,m=n-2,c=0;for(;i<=m;){let f=Math.floor((i+m)/2);if(r>=e[f]&&r<=e[f+1]){c=f;break}r<e[f]?m=f-1:i=f+1}let p=o[c],g=(r-e[c])/p,M=g*g,b=M*g,w=u[c]*p,x=u[c+1]*p;return(2*b-3*M+1)*h[c]+(b-2*M+g)*w+(-2*b+3*M)*h[c+1]+(b-M)*x}};function d(l){let t=l.length;if(t===0)return 0;let s=0;for(let n=0;n<t;n++)s+=l[n]*l[n];return Math.sqrt(s/t)}var nt=l=>{let t=l.length;if(t===0)return{min:0,max:0,avg:0};let s=l[0],n=l[0],e=0;for(let h=0;h<t;h++){let o=l[h];o<s&&(s=o),o>n&&(n=o),e+=o}return{min:s,max:n,avg:e/t}},L=l=>{let t=l.length;if(t===0)return 0;let s=1e-6,n=l.reduce((o,a)=>o*(a+s),1),e=Math.pow(n,1/t),h=Math.max(0,Math.min(1,e));return parseFloat((h*100).toFixed(2))};var y=class{constructor(t){this.hex=t}get rgb(){return C(this.hex)}get lab(){return S(this.rgb)}get lch(){return P(this.lab)}get lightness(){let[t,s,n]=this.lab,e=Math.sqrt(s*s+n*n),o=(Math.atan2(n,s)*180/Math.PI+360)%360,a=.1644,u=.0603,r=.1307,i=.006,m=a*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+u,c=0;return(o<=90||o>=270)&&(c=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),t+(m+c)*e}get chroma(){return this.lch[1]}get hue(){return this.lch[2]}get luminance(){let[t,s,n]=this.rgb;return .2126*t+.7152*s+.0722*n}get wcag(){return(Math.max(this.luminance,1)+.05)/(Math.min(this.luminance,1)+.05)}get apca(){let t=h=>h>5e-4?h:h+Math.pow(5e-4-h,.8),s=t(this.luminance),n=t(1),e=(Math.pow(s,.56)-Math.pow(n,.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 q=class{constructor(t=[],s="brand"){this.swatches=t.map(n=>new y(n)),this.name=s}get colors(){return this.swatches.map(t=>t.hex)}get peakChroma(){let t=this.colors.slice(2,-2),s="",n=-1/0;for(let e of t){let h=new y(e);h.chroma>n&&(n=h.chroma,s=e)}return n<6?this.colors[Math.ceil(this.steps/2)]:s}get steps(){return this.colors.length}get direction(){if(this.colors.length===0)return"lighten";let t=S(C(this.colors[0])),s=S(C(this.colors[this.colors.length-1]));return t[0]>s[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(t=>t.toLowerCase()===this.baseColor.toLowerCase())}get wcag(){let t=this.swatches,s=t.length,n=s-1,e={};for(let h of[30,45,70]){let o=h/10,a=n,u=0;for(let r=1;r<s;r++){let i=1/0;for(let m=0;m<s-r;m++){let c=t[m].luminance,p=t[m+r].luminance,g=(Math.max(c,p)+.05)/(Math.min(c,p)+.05);g<i&&(i=g)}if(i>=o){a=r,u=i;break}r===n&&(u=i)}e[h]={efficiency:a/n,target:o,span:a,value:u}}return e}get apca(){let t=this.swatches,s=t.length,n=s-1,e={},h=(o,a)=>{let i=o<.022?o+Math.pow(.022-o,1.414):o,m=a<.022?a+Math.pow(.022-a,1.414):a,c=m>=i?(Math.pow(m,.56)-Math.pow(i,.57))*114:(Math.pow(m,.65)-Math.pow(i,.62))*114;return Math.abs(c)<10?0:(c=c>0?c-2.7:c+2.7,Math.round(c))};for(let o of[45,60,75]){let a=o,u=n,r=0;for(let i=1;i<s;i++){let m=1/0;for(let c=0;c<s-i;c++){let p=t[c].luminance>t[c+i].luminance?t[c].luminance:t[c+i].luminance,g=t[c].luminance>t[c+i].luminance?t[c+i].luminance:t[c].luminance,M=Math.abs(h(g,p));M<m&&(m=M)}if(m>=a){u=i,r=m;break}i===n&&(r=m)}e[o]={efficiency:u/n,target:a,span:u,value:r}}return e}get contrasts(){return{wcag:this.wcag,apca:this.apca}}get deltaECurve(){let t=[0];for(let s=1;s<this.swatches.length;s++){let n=k(this.swatches[s-1].lab,this.swatches[s].lab);t.push(t[s-1]+n)}return t}get unwrapHues(){let t=this.swatches.map(n=>n.hue).slice(1,-1);if(t.length===0)return[];let s=[t[0]];for(let n=1;n<t.length;n++){let e=t[n]-t[n-1];e>180?e-=360:e<-180&&(e+=360),s.push(s[n-1]+e)}return s}get lightnessLinearity(){let t=this.swatches.map(p=>p.lightness),s=t.length;if(s<2)return 1;let n=0,e=0,h=0,o=0;for(let p=0;p<s;p++)n+=p,e+=t[p],h+=p*t[p],o+=p*p;let a=s*o-n*n;if(Math.abs(a)<1e-10)return 1;let u=(s*h-n*e)/a,r=(e-u*n)/s;if(Math.abs(u*(s-1))<.001)return 1;let m=0,c=0;for(let p=0;p<s;p++){let g=u*p+r,M=t[p]-g;m+=M*M;let b=Math.max(g-Math.min(r,u*(s-1)+r),Math.max(r,u*(s-1)+r)-g);c+=b*b}return Math.max(0,Math.min(1,1-Math.sqrt(m/s)/Math.sqrt(c/s)))}get chromaSmoothness(){let t=this.swatches.map(c=>c.chroma),s=t.length;if(s<3)return 1;let n=133.8,e=Math.max(...t);if(e<=.01)return 1;let h=t.map(c=>c/e*n),o=Math.min(...h),a=Math.max(...h),u=h.findIndex(c=>c===a),r=E([[0,h[0]],[u,a],[s-1,h[s-1]]]),i=0,m=0;for(let c=0;c<s;c++){let p=r(c),g=h[c]-p;i+=g*g,m+=Math.pow(Math.max(p-o,a-p),2)}return Math.max(0,Math.min(1,1-Math.sqrt(i/s)/Math.sqrt(m/s)))}get spacingUniformity(){let t=this.deltaECurve,s=t.length;if(s<2)return 1;let n=[];for(let a=1;a<s;a++){let u=t[a]-t[a-1];if(u<0)return 0;n.push(u)}let e=n.reduce((a,u)=>a+u,0)/n.length;if(e<=1e-6)return 0;let h=0;for(let a of n)h+=Math.pow(a-e,2);let o=Math.sqrt(h/n.length)/e;return Math.max(0,Math.min(1,1/(1+o)))}get hueStability(){var o,a,u;let t=this.unwrapHues,s=t.length;if(s<2)return 1;let n=(u=(a=t[this.baseIndex-1])!=null?a:(o=this.swatches[this.baseIndex])==null?void 0:o.hue)!=null?u:0,e=0,h=0;for(let r=0;r<s;r++){let i=Math.abs(t[r]-n)%360;i>180&&(i=360-i),e+=i*i;let m=r/(s-1)*180;h+=m*m}return Math.max(0,Math.min(1,1-Math.sqrt(e/s)/(Math.sqrt(h/s)||1)))}get contrastEfficiency(){let t=this.wcag[45].span,s=this.steps;if(s<=1)return 1;let n=.501,e=t/(s-1);return e<=n?1:e>=1?0:1-(e-n)/(1-n)}get metrics(){return{lightnessLinearity:this.lightnessLinearity,chromaSmoothness:this.chromaSmoothness,spacingUniformity:this.spacingUniformity,hueStability:this.hueStability,contrastEfficiency:this.contrastEfficiency}}get score(){return L(Object.values(this.metrics))}};var T=class{constructor(t={},s="Collection 1"){this.ramps=Object.entries(t).map(([n,e])=>new q(e,n)),this.name=s}get colors(){return Object.fromEntries(this.ramps.map(t=>[t.name,t.colors]))}get steps(){var t;return((t=this.ramps[0])==null?void 0:t.steps)||0}get wcag(){let t={},s=this.steps;for(let n of[30,45,70]){let e=this.ramps.map(a=>a.wcag[n]),h=Math.max(0,...e.map(a=>(a==null?void 0:a.span)||0)),o=e.reduce((a,u)=>a+((u==null?void 0:u.value)||0),0);t[n]={target:n/10,span:h,value:o/(this.ramps.length||1),efficiency:s>1?h/(s-1):0}}return t}get apca(){let t={},s=this.steps;for(let n of[45,60,75]){let e=this.ramps.map(a=>a.apca[n]),h=Math.max(0,...e.map(a=>(a==null?void 0:a.span)||0)),o=e.reduce((a,u)=>a+((u==null?void 0:u.value)||0),0);t[n]={target:n,span:h,value:o/(this.ramps.length||1),efficiency:s>1?h/(s-1):0}}return t}get contrastEfficiency(){return d(this.ramps.map(t=>t.contrastEfficiency))}get lightnessLinearity(){return d(this.ramps.map(t=>t.lightnessLinearity))}get chromaSmoothness(){return d(this.ramps.map(t=>t.chromaSmoothness))}get hueStability(){return d(this.ramps.map(t=>t.hueStability))}get spacingUniformity(){return d(this.ramps.map(t=>t.spacingUniformity))}get score(){return L([this.contrastEfficiency,this.lightnessLinearity,this.chromaSmoothness,this.hueStability,this.spacingUniformity])}};return $(et);})();
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}`},v=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),o=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,l=.0603,r=.1307,i=.006,u=c*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+l,a=0;return(o<=90||o>=270)&&(a=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),n+(u+a)*e},W=(m,n)=>{let[,t,s]=n,e=Math.sqrt(t*t+s*s),o=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,l=.0603,r=.1307,i=.006,u=c*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+l,a=0;return(o<=90||o>=270)&&(a=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),Math.max(0,m-(u+a)*e)},$=m=>{let[n,t,s]=m,e=s*Math.PI/180;return[n,t*Math.cos(e),t*Math.sin(e)]},k=m=>{let[n,t,s]=m,e=.4124564*n+.3575761*t+.1804375*s,h=.2126729*n+.7151522*t+.072175*s,o=.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),a=i(h/l),M=i(o/r);return[116*a-16,500*(u-a),200*(a-M)]},F=m=>{let[n,t,s]=m,e=(n+16)/116,h=t/500+e,o=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,a=c(e)*r,M=c(o)*i;return[3.2404542*u-1.5371385*a-.4985314*M,-.969266*u+1.8760108*a+.041556*M,.0556434*u-.2040259*a+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 o=(Math.atan2(s,t)*180/Math.PI+360)%360;return o>=359.9999&&(o=0),[n,e,o]},y=(m,n)=>{let[t,s,e]=m,[h,o,c]=n,l=(t+h)/2,r=Math.sqrt(s*s+e*e),i=Math.sqrt(o*o+c*c),u=(r+i)/2,a=.5*(1-Math.sqrt(Math.pow(u,7)/(Math.pow(u,7)+Math.pow(25,7)))),M=s*(1+a),b=o*(1+a),f=Math.sqrt(M*M+e*e),g=Math.sqrt(b*b+c*c),x=(f+g)/2,d=Math.atan2(e,M)*180/Math.PI+(Math.atan2(e,M)<0?360:0),p=Math.atan2(c,b)*180/Math.PI+(Math.atan2(c,b)<0?360:0),I=p-d;Math.abs(I)>180&&(I+=p<=d?360:-360);let w=Math.abs(d-p)>180?(d+p+360)/2:(d+p)/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,S=g-f,q=2*Math.sqrt(f*g)*Math.sin(I/2*Math.PI/180),Y=1+.015*Math.pow(l-50,2)/Math.sqrt(20+Math.pow(l-50,2)),L=1+.045*x,R=1+.015*x*D,A=30*Math.exp(-Math.pow((w-275)/25,2)),X=-(2*Math.sqrt(Math.pow(x,7)/(Math.pow(x,7)+Math.pow(25,7))))*Math.sin(2*A*Math.PI/180);return Math.sqrt(Math.pow(H/Y,2)+Math.pow(S/L,2)+Math.pow(q/R,2)+X*(S/L)*(q/R))},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]),o=[],c=[];for(let r=0;r<s-1;r++)o[r]=e[r+1]-e[r],c[r]=(h[r+1]-h[r])/o[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 a=(1+o[r]/(o[r-1]+o[r]))/3;l[r]=i*u/((1-a)*i+a*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,a=0;for(;i<=u;){let p=Math.floor((i+u)/2);if(r>=e[p]&&r<=e[p+1]){a=p;break}r<e[p]?u=p-1:i=p+1}let M=o[a],b=(r-e[a])/M,f=b*b,g=f*b,x=l[a]*M,d=l[a+1]*M;return(2*g-3*f+1)*h[a]+(g-2*f+b)*x+(-2*g+3*f)*h[a+1]+(g-f)*d}};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 o=m[h];o<t&&(t=o),o>s&&(s=o),e+=o}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((o,c)=>o*(c+t),1),e=Math.pow(s,1/n),h=Math.max(0,Math.min(1,e));return parseFloat((h*100).toFixed(2))};var C=class{constructor(n){this.hex=n}get rgb(){return v(this.hex)}get lab(){return k(this.rgb)}get lch(){return P(this.lab)}get lightness(){let[n,t,s]=this.lab,e=Math.sqrt(t*t+s*s),o=(Math.atan2(s,t)*180/Math.PI+360)%360,c=.1644,l=.0603,r=.1307,i=.006,u=c*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+l,a=0;return(o<=90||o>=270)&&(a=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),n+(u+a)*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.shades=n.map(s=>new C(s)),this.name=t}get colors(){return this.shades.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 C(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 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.shades,t=n.length,s=t-1,e={};for(let h of[30,45,70]){let o=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 a=n[u].luminance,M=n[u+r].luminance,b=(Math.max(a,M)+.05)/(Math.min(a,M)+.05);b<i&&(i=b)}if(i>=o){c=r,l=i;break}r===s&&(l=i)}e[h]={efficiency:c/s,target:o,span:c,value:l}}return e}get apca(){let n=this.shades,t=n.length,s=t-1,e={},h=(o,c)=>{let i=o<.022?o+Math.pow(.022-o,1.414):o,u=c<.022?c+Math.pow(.022-c,1.414):c,a=u>=i?(Math.pow(u,.56)-Math.pow(i,.57))*114:(Math.pow(u,.65)-Math.pow(i,.62))*114;return Math.abs(a)<10?0:(a=a>0?a-2.7:a+2.7,Math.round(a))};for(let o of[45,60,75]){let c=o,l=s,r=0;for(let i=1;i<t;i++){let u=1/0;for(let a=0;a<t-i;a++){let M=n[a].luminance>n[a+i].luminance?n[a].luminance:n[a+i].luminance,b=n[a].luminance>n[a+i].luminance?n[a+i].luminance:n[a].luminance,f=Math.abs(h(b,M));f<u&&(u=f)}if(u>=c){l=i,r=u;break}i===s&&(r=u)}e[o]={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.shades.length;t++){let s=y(this.shades[t-1].lab,this.shades[t].lab);n.push(n[t-1]+s)}return n}get unwrapHues(){let n=this.shades.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.shades.map(M=>M.lightness),t=n.length;if(t<2)return 1;let s=0,e=0,h=0,o=0;for(let M=0;M<t;M++)s+=M,e+=n[M],h+=M*n[M],o+=M*M;let c=t*o-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,a=0;for(let M=0;M<t;M++){let b=l*M+r,f=n[M]-b;u+=f*f;let g=Math.max(b-Math.min(r,l*(t-1)+r),Math.max(r,l*(t-1)+r)-b);a+=g*g}return Math.max(0,Math.min(1,1-Math.sqrt(u/t)/Math.sqrt(a/t)))}get chromaSmoothness(){let n=this.shades.map(a=>a.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(a=>a/e*s),o=Math.min(...h),c=Math.max(...h),l=h.findIndex(a=>a===c),r=E([[0,h[0]],[l,c],[t-1,h[t-1]]]),i=0,u=0;for(let a=0;a<t;a++){let M=r(a),b=h[a]-M;i+=b*b,u+=Math.pow(Math.max(M-o,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 o=Math.sqrt(h/s.length)/e;return Math.max(0,Math.min(1,1/(1+o)))}get hueStability(){var o,c,l;let n=this.unwrapHues,t=n.length;if(t<2)return 1;let s=(l=(c=n[this.baseIndex-1])!=null?c:(o=this.shades[this.baseIndex])==null?void 0:o.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,C as Shade,y as calcDeltaE2000,T as calcScore,_ as calcStatistics,E as createMonotone,K as cssRgbToRgb,W as fromLightnessEAL,v as hexToRgb,P as labToLch,F as labToRgb,$ as lchToLab,U as rgbToHex,k as rgbToLab,Z as rootMeanSquare,V as toLightnessEAL};
1
+ var z=m=>{let t=s=>{let n=Math.max(0,Math.min(1,s)),e=n<=.0031308?12.92*n:1.055*Math.pow(n,1/2.4)-.055;return Math.max(0,Math.min(255,Math.round(e*255)))};return m.map(t)},G=m=>{let t=s=>s>.04045?Math.pow((s+.055)/1.055,2.4):s/12.92;return m.map(t)},N=m=>{let[t,s,n]=z(m);return t=t.toString(16).padStart(2,"0"),s=s.toString(16).padStart(2,"0"),n=n.toString(16).padStart(2,"0"),`#${t}${s}${n}`},S=m=>{let t=parseInt(m.slice(1,3),16)/255,s=parseInt(m.slice(3,5),16)/255,n=parseInt(m.slice(5,7),16)/255;return G([t,s,n])},O=m=>{let[t,s,n]=m,e=Math.sqrt(s*s+n*n),o=(Math.atan2(n,s)*180/Math.PI+360)%360,a=.1644,u=.0603,r=.1307,i=.006,l=a*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+u,c=0;return(o<=90||o>=270)&&(c=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),t+(l+c)*e},V=(m,t)=>{let[,s,n]=t,e=Math.sqrt(s*s+n*n),o=(Math.atan2(n,s)*180/Math.PI+360)%360,a=.1644,u=.0603,r=.1307,i=.006,l=a*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+u,c=0;return(o<=90||o>=270)&&(c=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),Math.max(0,m-(l+c)*e)},$=m=>{let[t,s,n]=m,e=n*Math.PI/180;return[t,s*Math.cos(e),s*Math.sin(e)]},y=m=>{let[t,s,n]=m,e=.4124564*t+.3575761*s+.1804375*n,h=.2126729*t+.7151522*s+.072175*n,o=.0193339*t+.119192*s+.9503041*n,a=.95047,u=1,r=1.08883,i=g=>g>.008856?Math.cbrt(g):7.787*g+16/116,l=i(e/a),c=i(h/u),p=i(o/r);return[116*c-16,500*(l-c),200*(c-p)]},F=m=>{let[t,s,n]=m,e=(t+16)/116,h=s/500+e,o=e-n/200,a=g=>g**3>.008856?g**3:(g-16/116)/7.787,u=.95047,r=1,i=1.08883,l=a(h)*u,c=a(e)*r,p=a(o)*i;return[3.2404542*l-1.5371385*c-.4985314*p,-.969266*l+1.8760108*c+.041556*p,.0556434*l-.2040259*c+1.0572252*p]},T=m=>{let[t,s,n]=m,e=Math.sqrt(s*s+n*n);if(e<1e-4)return[t,0,0];let o=(Math.atan2(n,s)*180/Math.PI+360)%360;return o>=359.9999&&(o=0),[t,e,o]},B=(m,t)=>{let[s,n,e]=m,[h,o,a]=t,u=(s+h)/2,r=Math.sqrt(n*n+e*e),i=Math.sqrt(o*o+a*a),l=(r+i)/2,c=.5*(1-Math.sqrt(Math.pow(l,7)/(Math.pow(l,7)+Math.pow(25,7)))),p=n*(1+c),g=o*(1+c),M=Math.sqrt(p*p+e*e),b=Math.sqrt(g*g+a*a),d=(M+b)/2,x=Math.atan2(e,p)*180/Math.PI+(Math.atan2(e,p)<0?360:0),f=Math.atan2(a,g)*180/Math.PI+(Math.atan2(a,g)<0?360:0),R=f-x;Math.abs(R)>180&&(R+=f<=x?360:-360);let C=Math.abs(x-f)>180?(x+f+360)/2:(x+f)/2,H=1-.17*Math.cos((C-30)*Math.PI/180)+.24*Math.cos(2*C*Math.PI/180)+.32*Math.cos((3*C+6)*Math.PI/180)-.2*Math.cos((4*C-63)*Math.PI/180),Y=h-s,v=b-M,P=2*Math.sqrt(M*b)*Math.sin(R/2*Math.PI/180),U=1+.015*Math.pow(u-50,2)/Math.sqrt(20+Math.pow(u-50,2)),k=1+.045*d,E=1+.015*d*H,W=30*Math.exp(-Math.pow((C-275)/25,2)),X=-(2*Math.sqrt(Math.pow(d,7)/(Math.pow(d,7)+Math.pow(25,7))))*Math.sin(2*W*Math.PI/180);return Math.sqrt(Math.pow(Y/U,2)+Math.pow(v/k,2)+Math.pow(P/E,2)+X*(v/k)*(P/E))},K=m=>{let t=m.match(/\d+(\.\d+)?/g);if(!t||t.length<3)throw new Error("Invalid CSS rgb()");let s=n=>{let e=n/255;return e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4)};return[s(Number(t[0])),s(Number(t[1])),s(Number(t[2]))]},A=m=>{if(m.length<1)return r=>0;let t=[...m].sort((r,i)=>r[0]-i[0]),s=[];for(let r=0;r<t.length;r++)(r===0||t[r][0]!==t[r-1][0])&&s.push(t[r]);let n=s.length;if(n===1)return r=>s[0][1];let e=s.map(r=>r[0]),h=s.map(r=>r[1]),o=[],a=[];for(let r=0;r<n-1;r++)o[r]=e[r+1]-e[r],a[r]=(h[r+1]-h[r])/o[r];let u=new Array(n);u[0]=a[0],u[n-1]=a[n-2];for(let r=1;r<n-1;r++){let i=a[r-1],l=a[r];if(i*l<=0)u[r]=0;else{let c=(1+o[r]/(o[r-1]+o[r]))/3;u[r]=i*l/((1-c)*i+c*l)}}return r=>{if(r<=e[0])return h[0];if(r>=e[n-1])return h[n-1];let i=0,l=n-2,c=0;for(;i<=l;){let f=Math.floor((i+l)/2);if(r>=e[f]&&r<=e[f+1]){c=f;break}r<e[f]?l=f-1:i=f+1}let p=o[c],g=(r-e[c])/p,M=g*g,b=M*g,d=u[c]*p,x=u[c+1]*p;return(2*b-3*M+1)*h[c]+(b-2*M+g)*d+(-2*b+3*M)*h[c+1]+(b-M)*x}};function w(m){let t=m.length;if(t===0)return 0;let s=0;for(let n=0;n<t;n++)s+=m[n]*m[n];return Math.sqrt(s/t)}var Z=m=>{let t=m.length;if(t===0)return{min:0,max:0,avg:0};let s=m[0],n=m[0],e=0;for(let h=0;h<t;h++){let o=m[h];o<s&&(s=o),o>n&&(n=o),e+=o}return{min:s,max:n,avg:e/t}},L=m=>{let t=m.length;if(t===0)return 0;let s=1e-6,n=m.reduce((o,a)=>o*(a+s),1),e=Math.pow(n,1/t),h=Math.max(0,Math.min(1,e));return parseFloat((h*100).toFixed(2))};var I=class{constructor(t){this.hex=t}get rgb(){return S(this.hex)}get lab(){return y(this.rgb)}get lch(){return T(this.lab)}get lightness(){let[t,s,n]=this.lab,e=Math.sqrt(s*s+n*n),o=(Math.atan2(n,s)*180/Math.PI+360)%360,a=.1644,u=.0603,r=.1307,i=.006,l=a*Math.abs(Math.sin((o-90)/2*(Math.PI/180)))+u,c=0;return(o<=90||o>=270)&&(c=r*Math.abs(Math.cos(o*(Math.PI/180)))+i),t+(l+c)*e}get chroma(){return this.lch[1]}get hue(){return this.lch[2]}get luminance(){let[t,s,n]=this.rgb;return .2126*t+.7152*s+.0722*n}get wcag(){return(Math.max(this.luminance,1)+.05)/(Math.min(this.luminance,1)+.05)}get apca(){let t=h=>h>5e-4?h:h+Math.pow(5e-4-h,.8),s=t(this.luminance),n=t(1),e=(Math.pow(s,.56)-Math.pow(n,.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 q=class{constructor(t=[],s="brand"){this.swatches=t.map(n=>new I(n)),this.name=s}get colors(){return this.swatches.map(t=>t.hex)}get peakChroma(){let t=this.colors.slice(2,-2),s="",n=-1/0;for(let e of t){let h=new I(e);h.chroma>n&&(n=h.chroma,s=e)}return n<6?this.colors[Math.ceil(this.steps/2)]:s}get steps(){return this.colors.length}get direction(){if(this.colors.length===0)return"lighten";let t=y(S(this.colors[0])),s=y(S(this.colors[this.colors.length-1]));return t[0]>s[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(t=>t.toLowerCase()===this.baseColor.toLowerCase())}get wcag(){let t=this.swatches,s=t.length,n=s-1,e={};for(let h of[30,45,70]){let o=h/10,a=n,u=0;for(let r=1;r<s;r++){let i=1/0;for(let l=0;l<s-r;l++){let c=t[l].luminance,p=t[l+r].luminance,g=(Math.max(c,p)+.05)/(Math.min(c,p)+.05);g<i&&(i=g)}if(i>=o){a=r,u=i;break}r===n&&(u=i)}e[h]={efficiency:a/n,target:o,span:a,value:u}}return e}get apca(){let t=this.swatches,s=t.length,n=s-1,e={},h=(o,a)=>{let i=o<.022?o+Math.pow(.022-o,1.414):o,l=a<.022?a+Math.pow(.022-a,1.414):a,c=l>=i?(Math.pow(l,.56)-Math.pow(i,.57))*114:(Math.pow(l,.65)-Math.pow(i,.62))*114;return Math.abs(c)<10?0:(c=c>0?c-2.7:c+2.7,Math.round(c))};for(let o of[45,60,75]){let a=o,u=n,r=0;for(let i=1;i<s;i++){let l=1/0;for(let c=0;c<s-i;c++){let p=t[c].luminance>t[c+i].luminance?t[c].luminance:t[c+i].luminance,g=t[c].luminance>t[c+i].luminance?t[c+i].luminance:t[c].luminance,M=Math.abs(h(g,p));M<l&&(l=M)}if(l>=a){u=i,r=l;break}i===n&&(r=l)}e[o]={efficiency:u/n,target:a,span:u,value:r}}return e}get contrasts(){return{wcag:this.wcag,apca:this.apca}}get deltaECurve(){let t=[0];for(let s=1;s<this.swatches.length;s++){let n=B(this.swatches[s-1].lab,this.swatches[s].lab);t.push(t[s-1]+n)}return t}get unwrapHues(){let t=this.swatches.map(n=>n.hue).slice(1,-1);if(t.length===0)return[];let s=[t[0]];for(let n=1;n<t.length;n++){let e=t[n]-t[n-1];e>180?e-=360:e<-180&&(e+=360),s.push(s[n-1]+e)}return s}get lightnessLinearity(){let t=this.swatches.map(p=>p.lightness),s=t.length;if(s<2)return 1;let n=0,e=0,h=0,o=0;for(let p=0;p<s;p++)n+=p,e+=t[p],h+=p*t[p],o+=p*p;let a=s*o-n*n;if(Math.abs(a)<1e-10)return 1;let u=(s*h-n*e)/a,r=(e-u*n)/s;if(Math.abs(u*(s-1))<.001)return 1;let l=0,c=0;for(let p=0;p<s;p++){let g=u*p+r,M=t[p]-g;l+=M*M;let b=Math.max(g-Math.min(r,u*(s-1)+r),Math.max(r,u*(s-1)+r)-g);c+=b*b}return Math.max(0,Math.min(1,1-Math.sqrt(l/s)/Math.sqrt(c/s)))}get chromaSmoothness(){let t=this.swatches.map(c=>c.chroma),s=t.length;if(s<3)return 1;let n=133.8,e=Math.max(...t);if(e<=.01)return 1;let h=t.map(c=>c/e*n),o=Math.min(...h),a=Math.max(...h),u=h.findIndex(c=>c===a),r=A([[0,h[0]],[u,a],[s-1,h[s-1]]]),i=0,l=0;for(let c=0;c<s;c++){let p=r(c),g=h[c]-p;i+=g*g,l+=Math.pow(Math.max(p-o,a-p),2)}return Math.max(0,Math.min(1,1-Math.sqrt(i/s)/Math.sqrt(l/s)))}get spacingUniformity(){let t=this.deltaECurve,s=t.length;if(s<2)return 1;let n=[];for(let a=1;a<s;a++){let u=t[a]-t[a-1];if(u<0)return 0;n.push(u)}let e=n.reduce((a,u)=>a+u,0)/n.length;if(e<=1e-6)return 0;let h=0;for(let a of n)h+=Math.pow(a-e,2);let o=Math.sqrt(h/n.length)/e;return Math.max(0,Math.min(1,1/(1+o)))}get hueStability(){var o,a,u;let t=this.unwrapHues,s=t.length;if(s<2)return 1;let n=(u=(a=t[this.baseIndex-1])!=null?a:(o=this.swatches[this.baseIndex])==null?void 0:o.hue)!=null?u:0,e=0,h=0;for(let r=0;r<s;r++){let i=Math.abs(t[r]-n)%360;i>180&&(i=360-i),e+=i*i;let l=r/(s-1)*180;h+=l*l}return Math.max(0,Math.min(1,1-Math.sqrt(e/s)/(Math.sqrt(h/s)||1)))}get contrastEfficiency(){let t=this.wcag[45].span,s=this.steps;if(s<=1)return 1;let n=.501,e=t/(s-1);return e<=n?1:e>=1?0:1-(e-n)/(1-n)}get metrics(){return{lightnessLinearity:this.lightnessLinearity,chromaSmoothness:this.chromaSmoothness,spacingUniformity:this.spacingUniformity,hueStability:this.hueStability,contrastEfficiency:this.contrastEfficiency}}get score(){return L(Object.values(this.metrics))}};var D=class{constructor(t={},s="Collection 1"){this.ramps=Object.entries(t).map(([n,e])=>new q(e,n)),this.name=s}get colors(){return Object.fromEntries(this.ramps.map(t=>[t.name,t.colors]))}get steps(){var t;return((t=this.ramps[0])==null?void 0:t.steps)||0}get wcag(){let t={},s=this.steps;for(let n of[30,45,70]){let e=this.ramps.map(a=>a.wcag[n]),h=Math.max(0,...e.map(a=>(a==null?void 0:a.span)||0)),o=e.reduce((a,u)=>a+((u==null?void 0:u.value)||0),0);t[n]={target:n/10,span:h,value:o/(this.ramps.length||1),efficiency:s>1?h/(s-1):0}}return t}get apca(){let t={},s=this.steps;for(let n of[45,60,75]){let e=this.ramps.map(a=>a.apca[n]),h=Math.max(0,...e.map(a=>(a==null?void 0:a.span)||0)),o=e.reduce((a,u)=>a+((u==null?void 0:u.value)||0),0);t[n]={target:n,span:h,value:o/(this.ramps.length||1),efficiency:s>1?h/(s-1):0}}return t}get contrastEfficiency(){return w(this.ramps.map(t=>t.contrastEfficiency))}get lightnessLinearity(){return w(this.ramps.map(t=>t.lightnessLinearity))}get chromaSmoothness(){return w(this.ramps.map(t=>t.chromaSmoothness))}get hueStability(){return w(this.ramps.map(t=>t.hueStability))}get spacingUniformity(){return w(this.ramps.map(t=>t.spacingUniformity))}get score(){return L([this.contrastEfficiency,this.lightnessLinearity,this.chromaSmoothness,this.hueStability,this.spacingUniformity])}};export{D as Palette,q as Ramp,I as Swatch,B as calcDeltaE2000,L as calcScore,Z as calcStatistics,A as createMonotone,K as cssRgbToRgb,V as fromLightnessEAL,S as hexToRgb,T as labToLch,F as labToRgb,$ as lchToLab,N as rgbToHex,y as rgbToLab,w as rootMeanSquare,O as toLightnessEAL};
package/package.json CHANGED
@@ -1,16 +1,24 @@
1
1
  {
2
2
  "name": "chromametry",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Web-accessible Color Palette Metrics",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
8
8
  "type": "module",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ },
15
+ "./palettes": "./dist/palettes.js"
16
+ },
9
17
  "scripts": {
10
18
  "test": "vitest",
11
19
  "generate": "tsx scripts/generate.ts",
12
20
  "build": "tsup",
13
- "prepublishOnly": "npm run test &&npm run build"
21
+ "prepublishOnly": "npm run build"
14
22
  },
15
23
  "keywords": [
16
24
  "color",