chromametry 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +211 -130
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +81 -108
- package/dist/index.d.ts +81 -108
- package/dist/index.global.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +44 -44
package/README.md
CHANGED
|
@@ -1,155 +1,236 @@
|
|
|
1
|
-
# Chromametry
|
|
2
|
-
> A metrics framework for evaluating web-accessible sequential color palettes.
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-

|
|
6
|
-
*Figure 1. Web-accessible Palette Ranking*
|
|
7
|
-
|
|
8
|
-
## Metric Definitions
|
|
9
|
-
|
|
10
|
-
1. **Contrast Efficiency:** Measures how efficiently contrast space is used to achieve WCAG 4.5:1 contrast.
|
|
11
|
-
2. **Lightness Linearity:** Evaluates the linearity of lightness (with Helmholtz–Kohlrausch correction).
|
|
12
|
-
3. **Chroma Smoothness:** Checks for artifacts and kinks in the saturation curve using Monotone Cubic Splines.
|
|
13
|
-
4. **Hue Stability:** Quantifies hue shift/drift across the lightness ramp.
|
|
14
|
-
5. **Spacing Uniformity:** Measures the consistency of color spacing (DeltaE 2000).
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
|
25
|
-
|
|
|
26
|
-
|
|
|
27
|
-
|
|
|
28
|
-
|
|
|
29
|
-
|
|
|
30
|
-
|
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
1
|
+
# Chromametry
|
|
2
|
+
> A metrics framework for evaluating web-accessible sequential color palettes.
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
*Figure 1. Web-accessible Palette Ranking*
|
|
7
|
+
|
|
8
|
+
## Metric Definitions
|
|
9
|
+
|
|
10
|
+
1. **Contrast Efficiency:** Measures how efficiently contrast space is used to achieve WCAG 4.5:1 contrast.
|
|
11
|
+
2. **Lightness Linearity:** Evaluates the linearity of lightness (with Helmholtz–Kohlrausch correction).
|
|
12
|
+
3. **Chroma Smoothness:** Checks for artifacts and kinks in the saturation curve using Monotone Cubic Splines.
|
|
13
|
+
4. **Hue Stability:** Quantifies hue shift/drift across the lightness ramp.
|
|
14
|
+
5. **Spacing Uniformity:** Measures the consistency of color spacing (DeltaE 2000).
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
>[Read full paper](paper/paper.pdf)
|
|
18
|
+
|
|
19
|
+
> All lightness, chroma, hue, and DeltaE2000 computations are performed in the CIELAB color space.
|
|
20
|
+
|
|
21
|
+
## Benchmark Rankings
|
|
22
|
+
|
|
23
|
+
Comparison of popular design systems based on Chromametry metrics.
|
|
24
|
+
| Design System | Steps | Span (K) | Contrast Efficiency | Lightness Linearity | Chroma Smoothness | Hue Stability | Spacing Uniformity | **SCORE** |
|
|
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** |
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
*Table 1. Benchmark ranking of design systems evaluated using Chromametry metrics.*
|
|
42
|
+
|
|
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
|
+
|
|
45
|
+
> **Overall Score** is computed as the weighted mean of the five normalized metrics, using equal weights by default.
|
|
46
|
+
|
|
47
|
+
### Example: A Typical Report
|
|
48
|
+
|
|
49
|
+

|
|
50
|
+
*Figure 2. Adobe Spectrum Color Palette.*
|
|
51
|
+
|
|
52
|
+

|
|
53
|
+
*Figure 3. Adobe Spectrum Palette Metrics.*
|
|
54
|
+
|
|
55
|
+

|
|
56
|
+
*Figure 4. Adobe Spectrum Palette Charts.*
|
|
57
|
+
|
|
58
|
+
## Benchmark result page
|
|
59
|
+
|
|
60
|
+
- Online Report : [Benchmark page](https://chromametry.github.io/chromametry/benchmark/)
|
|
61
|
+
- Local `/benchmark/index.html` (double click)
|
|
62
|
+
|
|
63
|
+
## API
|
|
60
64
|
### Installation
|
|
61
|
-
**NPM Package:**
|
|
62
65
|
```bash
|
|
63
66
|
npm install chromametry
|
|
64
67
|
```
|
|
65
|
-
|
|
66
|
-
|
|
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
|
|
67
123
|
<script type="module">
|
|
68
|
-
import {
|
|
69
|
-
</script>
|
|
70
|
-
const result = Chromametry.analyzeMonochromaticPalette({ ... });
|
|
71
|
-
</script>
|
|
124
|
+
import { Palette, Ramp } from "https://esm.sh/chromametry";
|
|
72
125
|
|
|
126
|
+
const ramp = new Ramp(["#ffffff", "#2378c3", "#000000"], "blue");
|
|
127
|
+
console.log(ramp.score);
|
|
128
|
+
</script>
|
|
73
129
|
```
|
|
74
130
|
|
|
75
|
-
**
|
|
76
|
-
```
|
|
131
|
+
**Global**
|
|
132
|
+
```html
|
|
77
133
|
<script src="https://unpkg.com/chromametry/dist/index.global.js"></script>
|
|
78
134
|
<script>
|
|
79
|
-
const
|
|
135
|
+
const ramp = new Chromametry.Ramp(["#ffffff", "#2378c3", "#000000"], "blue");
|
|
136
|
+
console.log(ramp.score);
|
|
80
137
|
</script>
|
|
81
138
|
```
|
|
82
139
|
|
|
83
|
-
###
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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. |
|
|
106
194
|
|
|
107
195
|
## Reproducing Benchmarks
|
|
108
196
|
To run the benchmark generator locally:
|
|
109
197
|
```bash
|
|
110
198
|
git clone https://github.com/chromametry/chromametry.git
|
|
111
|
-
cd chromametry
|
|
112
|
-
npm install
|
|
113
|
-
npm run generate
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
## Adding Custom Palettes to Benchmark
|
|
117
|
-
Create a new .ts file in
|
|
118
|
-
|
|
199
|
+
cd chromametry
|
|
200
|
+
npm install
|
|
201
|
+
npm run generate
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Adding Custom Palettes to Benchmark
|
|
205
|
+
Create a new .ts file in benchmark/input/ (e.g., my-palette.ts).
|
|
206
|
+
|
|
119
207
|
```ts
|
|
120
|
-
import { MonochromaticPaletteData } from "../../../src/index.js";
|
|
121
208
|
import { red, volcano, gold } from '@ant-design/colors';
|
|
122
209
|
|
|
123
210
|
// Define colors (imported or inline object)
|
|
124
211
|
let colors: Record<string, string[]> = { red, volcano, gold };
|
|
125
|
-
|
|
126
|
-
// Ensure white/black anchors exist if your ramp misses them
|
|
127
|
-
for (let name in colors) {
|
|
128
|
-
if (colors[name][0] !== "#ffffff") colors[name].unshift("#ffffff");
|
|
129
|
-
if (colors[name][colors[name].length - 1] !== "#000000") colors[name].push("#000000");
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const palette: MonochromaticPaletteData = {
|
|
135
|
-
name: "Ant Design",
|
|
136
|
-
stepNames, // string[]
|
|
137
|
-
colors // Record<string, string[]>
|
|
212
|
+
|
|
213
|
+
// Ensure white/black anchors exist if your ramp misses them
|
|
214
|
+
for (let name in colors) {
|
|
215
|
+
if (colors[name][0] !== "#ffffff") colors[name].unshift("#ffffff");
|
|
216
|
+
if (colors[name][colors[name].length - 1] !== "#000000") colors[name].push("#000000");
|
|
217
|
+
}
|
|
218
|
+
export default {
|
|
219
|
+
name: "Ant Design",
|
|
220
|
+
colors,
|
|
138
221
|
};
|
|
139
|
-
|
|
140
|
-
export default palette;
|
|
141
|
-
```
|
|
142
|
-
Then regenerate the report:
|
|
143
|
-
```bash
|
|
144
|
-
npm run generate
|
|
145
222
|
```
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
-
|
|
153
|
-
|
|
154
|
-
-
|
|
155
|
-
|
|
223
|
+
Then regenerate the report:
|
|
224
|
+
```bash
|
|
225
|
+
npm run generate
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Input Requirements
|
|
229
|
+
- Equal Steps: All color ramps must have the same number of steps.
|
|
230
|
+
|
|
231
|
+
- Format: Colors must be Hex strings.
|
|
232
|
+
|
|
233
|
+
- Monotonicity: Lightness must strictly increase or decrease (sorted).
|
|
234
|
+
|
|
235
|
+
- Anchors: Start/End colors should ideally be Black and White.
|
|
236
|
+
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var P=Object.defineProperty;var ot=Object.getOwnPropertyDescriptor;var at=Object.getOwnPropertyNames;var st=Object.prototype.hasOwnProperty;var ct=(r,t)=>{for(var n in t)P(r,n,{get:t[n],enumerable:!0})},mt=(r,t,n,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of at(t))!st.call(r,o)&&o!==n&&P(r,o,{get:()=>t[o],enumerable:!(e=ot(t,o))||e.enumerable});return r};var ht=r=>mt(P({},"__esModule",{value:!0}),r);var dt={};ct(dt,{analyzeMonochromatic:()=>O,analyzeMonochromaticPalette:()=>xt,calcChromaSmoothness:()=>K,calcContrastEfficiency:()=>Q,calcDeltaE2000:()=>A,calcHueStability:()=>Z,calcLightnessLinearity:()=>W,calcScore:()=>I,calcSpacingUniformity:()=>J,calcStatistics:()=>ft,contrastList:()=>H,createMonotone:()=>z,cssRgbToRgb:()=>gt,findMaxChromaHex:()=>k,fromLightnessEAL:()=>ut,getApcaContrast:()=>L,getMonochromaticContrasts:()=>N,getPaletteContrasts:()=>X,getRelativeLuminance:()=>D,getWcagContrast:()=>R,hexToRgb:()=>f,labToLch:()=>q,labToRgb:()=>lt,lchToLab:()=>bt,lrgbToSrgb:()=>G,rgbToHex:()=>it,rgbToLab:()=>x,rootMeanSquare:()=>y,simulateDeuteranopia:()=>Mt,simulateProtanopia:()=>pt,srgbToLrgb:()=>_,toLightnessEAL:()=>T,unwrapHue:()=>v});module.exports=ht(dt);var D=r=>{let[t,n,e]=r;return .2126*t+.7152*n+.0722*e},G=r=>{let t=n=>{let e=Math.max(0,Math.min(1,n)),o=e<=.0031308?12.92*e:1.055*Math.pow(e,1/2.4)-.055;return Math.max(0,Math.min(255,Math.round(o*255)))};return r.map(t)},_=r=>{let t=n=>n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92;return r.map(t)},it=r=>{let[t,n,e]=G(r);return t=t.toString(16).padStart(2,"0"),n=n.toString(16).padStart(2,"0"),e=e.toString(16).padStart(2,"0"),`#${t}${n}${e}`},f=r=>{let t=parseInt(r.slice(1,3),16)/255,n=parseInt(r.slice(3,5),16)/255,e=parseInt(r.slice(5,7),16)/255;return _([t,n,e])},T=r=>{let[t,n,e]=r,o=Math.sqrt(n*n+e*e),s=(Math.atan2(e,n)*180/Math.PI+360)%360,i=.1644,b=.0603,m=.1307,u=.006,h=i*Math.abs(Math.sin((s-90)/2*(Math.PI/180)))+b,a=0;return(s<=90||s>=270)&&(a=m*Math.abs(Math.cos(s*(Math.PI/180)))+u),t+(h+a)*o},ut=(r,t)=>{let[,n,e]=t,o=Math.sqrt(n*n+e*e),s=(Math.atan2(e,n)*180/Math.PI+360)%360,i=.1644,b=.0603,m=.1307,u=.006,h=i*Math.abs(Math.sin((s-90)/2*(Math.PI/180)))+b,a=0;return(s<=90||s>=270)&&(a=m*Math.abs(Math.cos(s*(Math.PI/180)))+u),Math.max(0,r-(h+a)*o)},bt=r=>{let[t,n,e]=r,o=e*Math.PI/180;return[t,n*Math.cos(o),n*Math.sin(o)]},x=r=>{let[t,n,e]=r,o=.4124564*t+.3575761*n+.1804375*e,c=.2126729*t+.7151522*n+.072175*e,s=.0193339*t+.119192*n+.9503041*e,i=.95047,b=1,m=1.08883,u=p=>p>.008856?Math.cbrt(p):7.787*p+16/116,h=u(o/i),a=u(c/b),l=u(s/m);return[116*a-16,500*(h-a),200*(a-l)]},lt=r=>{let[t,n,e]=r,o=(t+16)/116,c=n/500+o,s=o-e/200,i=p=>p**3>.008856?p**3:(p-16/116)/7.787,b=.95047,m=1,u=1.08883,h=i(c)*b,a=i(o)*m,l=i(s)*u;return[3.2404542*h-1.5371385*a-.4985314*l,-.969266*h+1.8760108*a+.041556*l,.0556434*h-.2040259*a+1.0572252*l]},q=r=>{let[t,n,e]=r,o=Math.sqrt(n*n+e*e);if(o<1e-4)return[t,0,0];let s=(Math.atan2(e,n)*180/Math.PI+360)%360;return s>=359.9999&&(s=0),[t,o,s]},A=(r,t)=>{let[n,e,o]=r,[c,s,i]=t,b=(n+c)/2,m=Math.sqrt(e*e+o*o),u=Math.sqrt(s*s+i*i),h=(m+u)/2,a=.5*(1-Math.sqrt(Math.pow(h,7)/(Math.pow(h,7)+Math.pow(25,7)))),l=e*(1+a),p=s*(1+a),M=Math.sqrt(l*l+o*o),d=Math.sqrt(p*p+i*i),S=(M+d)/2,C=Math.atan2(o,l)*180/Math.PI+(Math.atan2(o,l)<0?360:0),g=Math.atan2(i,p)*180/Math.PI+(Math.atan2(i,p)<0?360:0),E=g-C;Math.abs(E)>180&&(E+=g<=C?360:-360);let w=Math.abs(C-g)>180?(C+g+360)/2:(C+g)/2,V=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),tt=c-n,Y=d-M,B=2*Math.sqrt(M*d)*Math.sin(E/2*Math.PI/180),nt=1+.015*Math.pow(b-50,2)/Math.sqrt(20+Math.pow(b-50,2)),U=1+.045*S,$=1+.015*S*V,rt=30*Math.exp(-Math.pow((w-275)/25,2)),et=-(2*Math.sqrt(Math.pow(S,7)/(Math.pow(S,7)+Math.pow(25,7))))*Math.sin(2*rt*Math.PI/180);return Math.sqrt(Math.pow(tt/nt,2)+Math.pow(Y/U,2)+Math.pow(B/$,2)+et*(Y/U)*(B/$))},k=r=>{let t="",n=-1/0;for(let e of r){let o=x(f(e)),[,c]=q(o);c>n&&(n=c,t=e)}return t};function v(r){let t=[r[0]];for(let n=1;n<r.length;n++){let e=r[n]-r[n-1];e>180?e-=360:e<-180&&(e+=360),t.push(t[n-1]+e)}return t}function pt(r){let[t,n,e]=r;return[.152286*t+1.052583*n-.204868*e,.114503*t+.786281*n+.099216*e,-.003882*t-.048116*n+1.051998*e]}function Mt(r){let[t,n,e]=r;return[.367322*t+.860646*n-.227968*e,.280085*t+.672501*n+.047413*e,-.01182*t+.04294*n+.968881*e]}var gt=r=>{let t=r.match(/\d+(\.\d+)?/g);if(!t||t.length<3)throw new Error("Invalid CSS rgb()");let n=e=>{let o=e/255;return o<=.04045?o/12.92:Math.pow((o+.055)/1.055,2.4)};return[n(Number(t[0])),n(Number(t[1])),n(Number(t[2]))]};var R=(r,t)=>(Math.max(r,t)+.05)/(Math.min(r,t)+.05),L=(r,t)=>{let n=s=>s>5e-4?s:s+Math.pow(5e-4-s,.8),e=n(r),o=n(t),c=(Math.pow(e,.56)-Math.pow(o,.56))*100;return Math.abs(c)<.1?0:(c=c>0?c<1?0:c-.25:c>-1?0:c+.25,Math.round(c))};function j(r){let t=r.match(/^(wcag|apca)(\d+)$/);if(!t)throw new Error(`Invalid contrast: ${r}`);let n=t[1]==="wcag"?Number(t[2])/10:Number(t[2]);return{system:t[1],target:n}}var N=r=>{let t={},n=r.length,e=n-1;return H.forEach(o=>{let{system:c,target:s}=j(o),i=e,b=0;for(let m=1;m<n;m++){let u=1/0;for(let h=0;h<n-m;h++){let a=c==="wcag"?R(r[h].luminance,r[h+m].luminance):Math.max(Math.abs(L(r[h+m].luminance,r[h].luminance)),Math.abs(L(r[h].luminance,r[h+m].luminance)));a<u&&(u=a)}if(u>=s){i=m,b=u;break}m===e&&(b=u)}t[o]={system:c,efficiency:i/e,target:s,span:i,value:b,name:o}}),t},H=["wcag30","wcag45","wcag70","apca45","apca60","apca75"],X=r=>{let t={};return H.forEach(n=>{var m;let{target:e,system:o}=j(n),c=r.map(u=>u.contrasts[n]),s=((m=r[0])==null?void 0:m.shades.length)||0,i=Math.max(...c.map(u=>(u==null?void 0:u.span)||0)),b=c.reduce((u,h)=>u+((h==null?void 0:h.value)||0),0);t[n]={system:o,target:e,span:i,value:b/(r.length||1),name:n,efficiency:i/(s-1||1)}}),t};var F=r=>{let t=f(r),n=x(t),e=D(t),o=T(n),c=q(n);return{hex:r,rgb:t,lab:n,lch:c,lightness:o,chroma:c[1],hue:c[2],luminance:e,parameter:0,cumDeltaE00:0,cumProtDeltaE00:0,cumDeutDeltaE00:0,wcag:R(e,1),apca:L(e,1)}};var z=r=>{if(r.length<1)return m=>0;let t=[...r].sort((m,u)=>m[0]-u[0]),n=[];for(let m=0;m<t.length;m++)(m===0||t[m][0]!==t[m-1][0])&&n.push(t[m]);let e=n.length;if(e===1)return m=>n[0][1];let o=n.map(m=>m[0]),c=n.map(m=>m[1]),s=[],i=[];for(let m=0;m<e-1;m++)s[m]=o[m+1]-o[m],i[m]=(c[m+1]-c[m])/s[m];let b=new Array(e);b[0]=i[0],b[e-1]=i[e-2];for(let m=1;m<e-1;m++){let u=i[m-1],h=i[m];if(u*h<=0)b[m]=0;else{let a=(1+s[m]/(s[m-1]+s[m]))/3;b[m]=u*h/((1-a)*u+a*h)}}return m=>{if(m<=o[0])return c[0];if(m>=o[e-1])return c[e-1];let u=0,h=e-2,a=0;for(;u<=h;){let g=Math.floor((u+h)/2);if(m>=o[g]&&m<=o[g+1]){a=g;break}m<o[g]?h=g-1:u=g+1}let l=s[a],p=(m-o[a])/l,M=p*p,d=M*p,S=b[a]*l,C=b[a+1]*l;return(2*d-3*M+1)*c[a]+(d-2*M+p)*S+(-2*d+3*M)*c[a+1]+(d-M)*C}};function y(r){let t=r.length;if(t===0)return 0;let n=0;for(let e=0;e<t;e++)n+=r[e]*r[e];return Math.sqrt(n/t)}var ft=r=>{let t=r.length;if(t===0)return{min:0,max:0,avg:0};let n=r[0],e=r[0],o=0;for(let c=0;c<t;c++){let s=r[c];s<n&&(n=s),s>e&&(e=s),o+=s}return{min:n,max:e,avg:o/t}},I=r=>{let t=r.length;if(t===0)return 0;let n=1e-6,e=r.reduce((s,i)=>s*(i+n),1),o=Math.pow(e,1/t),c=Math.max(0,Math.min(1,o));return parseFloat((c*100).toFixed(2))};var O=(r,t,n)=>{t||(t="brand"),n||(n=[...Array(r.length).keys()]);let e=x(f(r[0]))[0],o=x(f(r[r.length-1]))[0];e>o&&r.reverse();let c=r.map(a=>F(a));for(let a=1;a<c.length;a++){let l=A(c[a-1].lab,c[a].lab);c[a].cumDeltaE00=c[a-1].cumDeltaE00+l}let s=k(r.slice(2,-2))||r[Math.floor(r.length/2)],i=r.findIndex(a=>a.toLowerCase()===(s==null?void 0:s.toLowerCase())),b=v(c.map(a=>a.hue).slice(1,-1));for(let a=1;a<c.length-1;a++)c[a].hue=b[a-1];let m=Z(c.map(a=>a.hue).slice(1,-1),c[i].hue),u=N(c),h={lightnessLinearity:W(c.map(a=>a.lightness)),chromaSmoothness:K(c.map(a=>a.chroma)),spacingUniformity:J(c.map(a=>a.cumDeltaE00)),contrastEfficiency:Q(u.wcag45.span,n.length),hueStability:m};return{name:t,colors:r,baseIndex:i,baseColor:s,shades:c,contrasts:u,metrics:h,score:I(Object.values(h))}},xt=r=>{let{stepNames:t,name:n,colors:e}=r,o=Object.values(e)[0],c=x(f(o[0]))[0],s=x(f(o[o.length-1]))[0],i=c>s?"darken":"lighten",b=[],m={};for(let h in e){let a=O(e[h],h,t);b.push(a),m[h]=a.baseColor}let u={contrastEfficiency:y(b.map(h=>h.metrics.contrastEfficiency)),lightnessLinearity:y(b.map(h=>h.metrics.lightnessLinearity)),chromaSmoothness:y(b.map(h=>h.metrics.chromaSmoothness)),hueStability:y(b.map(h=>h.metrics.hueStability)),spacingUniformity:y(b.map(h=>h.metrics.spacingUniformity))};return{name:n,baseColors:m,stepNames:t,direction:i,steps:t.length,colors:e,contrasts:X(b),scales:b,metrics:u,score:I(Object.values(u))}};function W(r){let t=r.length;if(t<2)return 1;let n=0,e=0,o=0,c=0;for(let a=0;a<t;a++)n+=a,e+=r[a],o+=a*r[a],c+=a*a;let s=t*c-n*n;if(Math.abs(s)<1e-10)return 1;let i=(t*o-n*e)/s,b=(e-i*n)/t;if(Math.abs(i*(t-1))<.001)return 1;let u=0,h=0;for(let a=0;a<t;a++){let l=i*a+b,p=r[a]-l;u+=p*p;let M=Math.max(l-Math.min(b,i*(t-1)+b),Math.max(b,i*(t-1)+b)-l);h+=M*M}return Math.max(0,Math.min(1,1-Math.sqrt(u/t)/Math.sqrt(h/t)))}function Z(r,t){let n=r.length;if(n<2)return 1;let e=0,o=0;for(let c=0;c<n;c++){let s=Math.abs(r[c]-t)%360;s>180&&(s=360-s),e+=s*s;let i=c/(n-1)*180;o+=i*i}return Math.max(0,Math.min(1,1-Math.sqrt(e/n)/(Math.sqrt(o/n)||1)))}var K=r=>{let t=r.length;if(t<3)return 1;let n=133.8,e=Math.max(...r);if(e<=.01)return 1;let o=r.map(h=>h/e*n),c=Math.min(...o),s=Math.max(...o),i=o.findIndex(h=>h===s),b=z([[0,o[0]],[i,s],[t-1,o[t-1]]]),m=0,u=0;for(let h=0;h<t;h++){let a=b(h),l=o[h]-a;m+=l*l,u+=Math.pow(Math.max(a-c,s-a),2)}return Math.max(0,Math.min(1,1-Math.sqrt(m/t)/Math.sqrt(u/t)))},J=r=>{let t=r.length;if(t<2)return 1;let n=[];for(let s=1;s<t;s++){let i=r[s]-r[s-1];if(i<0)return 0;n.push(i)}let e=n.reduce((s,i)=>s+i,0)/n.length;if(e<=1e-6)return 0;let o=0;for(let s of n)o+=Math.pow(s-e,2);let c=Math.sqrt(o/n.length)/e;return Math.max(0,Math.min(1,1/(1+c)))},Q=(r,t)=>{if(t<=1)return 1;let n=.5,e=r/t,o=n*((t-1)/t);return e<=o?1:e>=1?0:(1-e)/(1-o)};0&&(module.exports={analyzeMonochromatic,analyzeMonochromaticPalette,calcChromaSmoothness,calcContrastEfficiency,calcDeltaE2000,calcHueStability,calcLightnessLinearity,calcScore,calcSpacingUniformity,calcStatistics,contrastList,createMonotone,cssRgbToRgb,findMaxChromaHex,fromLightnessEAL,getApcaContrast,getMonochromaticContrasts,getPaletteContrasts,getRelativeLuminance,getWcagContrast,hexToRgb,labToLch,labToRgb,lchToLab,lrgbToSrgb,rgbToHex,rgbToLab,rootMeanSquare,simulateDeuteranopia,simulateProtanopia,srgbToLrgb,toLightnessEAL,unwrapHue});
|
|
1
|
+
"use strict";var v=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var O=Object.prototype.hasOwnProperty;var N=(m,t)=>{for(var s in t)v(m,s,{get:t[s],enumerable:!0})},V=(m,t,s,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of j(t))!O.call(m,e)&&e!==s&&v(m,e,{get:()=>t[e],enumerable:!(n=G(t,e))||n.enumerable});return m};var $=m=>V(v({},"__esModule",{value:!0}),m);var et={};N(et,{Palette:()=>T,Ramp:()=>q,Shade:()=>y,calcDeltaE2000:()=>P,calcScore:()=>L,calcStatistics:()=>nt,createMonotone:()=>E,cssRgbToRgb:()=>st,fromLightnessEAL:()=>J,hexToRgb:()=>C,labToLch:()=>k,labToRgb:()=>tt,lchToLab:()=>Q,rgbToHex:()=>Z,rgbToLab:()=>S,rootMeanSquare:()=>x,toLightnessEAL:()=>_});module.exports=$(et);var F=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)},K=m=>{let t=s=>s>.04045?Math.pow((s+.055)/1.055,2.4):s/12.92;return m.map(t)},Z=m=>{let[t,s,n]=F(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}`},C=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 K([t,s,n])},_=m=>{let[t,s,n]=m,e=Math.sqrt(s*s+n*n),a=(Math.atan2(n,s)*180/Math.PI+360)%360,h=.1644,u=.0603,r=.1307,i=.006,l=h*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+u,c=0;return(a<=90||a>=270)&&(c=r*Math.abs(Math.cos(a*(Math.PI/180)))+i),t+(l+c)*e},J=(m,t)=>{let[,s,n]=t,e=Math.sqrt(s*s+n*n),a=(Math.atan2(n,s)*180/Math.PI+360)%360,h=.1644,u=.0603,r=.1307,i=.006,l=h*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+u,c=0;return(a<=90||a>=270)&&(c=r*Math.abs(Math.cos(a*(Math.PI/180)))+i),Math.max(0,m-(l+c)*e)},Q=m=>{let[t,s,n]=m,e=n*Math.PI/180;return[t,s*Math.cos(e),s*Math.sin(e)]},S=m=>{let[t,s,n]=m,e=.4124564*t+.3575761*s+.1804375*n,o=.2126729*t+.7151522*s+.072175*n,a=.0193339*t+.119192*s+.9503041*n,h=.95047,u=1,r=1.08883,i=g=>g>.008856?Math.cbrt(g):7.787*g+16/116,l=i(e/h),c=i(o/u),p=i(a/r);return[116*c-16,500*(l-c),200*(c-p)]},tt=m=>{let[t,s,n]=m,e=(t+16)/116,o=s/500+e,a=e-n/200,h=g=>g**3>.008856?g**3:(g-16/116)/7.787,u=.95047,r=1,i=1.08883,l=h(o)*u,c=h(e)*r,p=h(a)*i;return[3.2404542*l-1.5371385*c-.4985314*p,-.969266*l+1.8760108*c+.041556*p,.0556434*l-.2040259*c+1.0572252*p]},k=m=>{let[t,s,n]=m,e=Math.sqrt(s*s+n*n);if(e<1e-4)return[t,0,0];let a=(Math.atan2(n,s)*180/Math.PI+360)%360;return a>=359.9999&&(a=0),[t,e,a]},P=(m,t)=>{let[s,n,e]=m,[o,a,h]=t,u=(s+o)/2,r=Math.sqrt(n*n+e*e),i=Math.sqrt(a*a+h*h),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=a*(1+c),M=Math.sqrt(p*p+e*e),b=Math.sqrt(g*g+h*h),w=(M+b)/2,d=Math.atan2(e,p)*180/Math.PI+(Math.atan2(e,p)<0?360:0),f=Math.atan2(h,g)*180/Math.PI+(Math.atan2(h,g)<0?360:0),R=f-d;Math.abs(R)>180&&(R+=f<=d?360:-360);let I=Math.abs(d-f)>180?(d+f+360)/2:(d+f)/2,U=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),W=o-s,A=b-M,D=2*Math.sqrt(M*b)*Math.sin(R/2*Math.PI/180),X=1+.015*Math.pow(u-50,2)/Math.sqrt(20+Math.pow(u-50,2)),H=1+.045*w,Y=1+.015*w*U,z=30*Math.exp(-Math.pow((I-275)/25,2)),B=-(2*Math.sqrt(Math.pow(w,7)/(Math.pow(w,7)+Math.pow(25,7))))*Math.sin(2*z*Math.PI/180);return Math.sqrt(Math.pow(W/X,2)+Math.pow(A/H,2)+Math.pow(D/Y,2)+B*(A/H)*(D/Y))},st=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]))]},E=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]),o=s.map(r=>r[1]),a=[],h=[];for(let r=0;r<n-1;r++)a[r]=e[r+1]-e[r],h[r]=(o[r+1]-o[r])/a[r];let u=new Array(n);u[0]=h[0],u[n-1]=h[n-2];for(let r=1;r<n-1;r++){let i=h[r-1],l=h[r];if(i*l<=0)u[r]=0;else{let c=(1+a[r]/(a[r-1]+a[r]))/3;u[r]=i*l/((1-c)*i+c*l)}}return r=>{if(r<=e[0])return o[0];if(r>=e[n-1])return o[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=a[c],g=(r-e[c])/p,M=g*g,b=M*g,w=u[c]*p,d=u[c+1]*p;return(2*b-3*M+1)*o[c]+(b-2*M+g)*w+(-2*b+3*M)*o[c+1]+(b-M)*d}};function x(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 nt=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 o=0;o<t;o++){let a=m[o];a<s&&(s=a),a>n&&(n=a),e+=a}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((a,h)=>a*(h+s),1),e=Math.pow(n,1/t),o=Math.max(0,Math.min(1,e));return parseFloat((o*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 k(this.lab)}get lightness(){let[t,s,n]=this.lab,e=Math.sqrt(s*s+n*n),a=(Math.atan2(n,s)*180/Math.PI+360)%360,h=.1644,u=.0603,r=.1307,i=.006,l=h*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+u,c=0;return(a<=90||a>=270)&&(c=r*Math.abs(Math.cos(a*(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=o=>o>5e-4?o:o+Math.pow(5e-4-o,.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.shades=t.map(n=>new y(n)),this.name=s}get colors(){return this.shades.map(t=>t.hex)}get peakChroma(){let t=this.colors.slice(2,-2),s="",n=-1/0;for(let e of t){let o=new y(e);o.chroma>n&&(n=o.chroma,s=e)}return s}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(t=>t.toLowerCase()===this.baseColor.toLowerCase())}get wcag(){let t=this.shades,s=t.length,n=s-1,e={};for(let o of[30,45,70]){let a=o/10,h=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>=a){h=r,u=i;break}r===n&&(u=i)}e[o]={efficiency:h/n,target:a,span:h,value:u}}return e}get apca(){let t=this.shades,s=t.length,n=s-1,e={},o=(a,h)=>{let u=c=>c>5e-4?c:c+Math.pow(5e-4-c,.8),r=u(a),i=u(h),l=(Math.pow(r,.56)-Math.pow(i,.56))*100;return Math.abs(l)<.1?0:(l=l>0?l<1?0:l-.25:l>-1?0:l+.25,Math.round(l))};for(let a of[45,60,75]){let h=a,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=Math.max(Math.abs(o(t[c+i].luminance,t[c].luminance)),Math.abs(o(t[c].luminance,t[c+i].luminance)));p<l&&(l=p)}if(l>=h){u=i,r=l;break}i===n&&(r=l)}e[a]={efficiency:u/n,target:h,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.shades.length;s++){let n=P(this.shades[s-1].lab,this.shades[s].lab);t.push(t[s-1]+n)}return t}get unwrapHues(){let t=this.shades.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.shades.map(p=>p.lightness),s=t.length;if(s<2)return 1;let n=0,e=0,o=0,a=0;for(let p=0;p<s;p++)n+=p,e+=t[p],o+=p*t[p],a+=p*p;let h=s*a-n*n;if(Math.abs(h)<1e-10)return 1;let u=(s*o-n*e)/h,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.shades.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 o=t.map(c=>c/e*n),a=Math.min(...o),h=Math.max(...o),u=o.findIndex(c=>c===h),r=E([[0,o[0]],[u,h],[s-1,o[s-1]]]),i=0,l=0;for(let c=0;c<s;c++){let p=r(c),g=o[c]-p;i+=g*g,l+=Math.pow(Math.max(p-a,h-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 h=1;h<s;h++){let u=t[h]-t[h-1];if(u<0)return 0;n.push(u)}let e=n.reduce((h,u)=>h+u,0)/n.length;if(e<=1e-6)return 0;let o=0;for(let h of n)o+=Math.pow(h-e,2);let a=Math.sqrt(o/n.length)/e;return Math.max(0,Math.min(1,1/(1+a)))}get hueStability(){var a,h,u;let t=this.unwrapHues,s=t.length;if(s<2)return 1;let n=(u=(h=t[this.baseIndex-1])!=null?h:(a=this.shades[this.baseIndex])==null?void 0:a.hue)!=null?u:0,e=0,o=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;o+=l*l}return Math.max(0,Math.min(1,1-Math.sqrt(e/s)/(Math.sqrt(o/s)||1)))}get contrastEfficiency(){let t=this.wcag[45].span,s=this.steps;if(s<=1)return 1;let n=.5,e=t/s,o=n*((s-1)/s);return e<=o?1:e>=1?0:(1-e)/(1-o)}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="palette"){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 direction(){var e;let t=(e=this.ramps[0])==null?void 0:e.colors;if(!(t!=null&&t.length))return"lighten";let s=S(C(t[0])),n=S(C(t[t.length-1]));return s[0]>n[0]?"darken":"lighten"}get wcag(){var s;let t={};for(let n of[30,45,70]){let e=this.ramps.map(r=>r.wcag[n]),o=((s=this.ramps[0])==null?void 0:s.steps)||0,a=Math.max(...e.map(r=>(r==null?void 0:r.span)||0)),h=e.reduce((r,i)=>r+((i==null?void 0:i.value)||0),0),u=e[0];t[n]={target:(u==null?void 0:u.target)||0,span:a,value:h/(this.ramps.length||1),efficiency:a/(o-1||1)}}return t}get apca(){var s;let t={};for(let n of[45,60,75]){let e=this.ramps.map(r=>r.apca[n]),o=((s=this.ramps[0])==null?void 0:s.steps)||0,a=Math.max(...e.map(r=>(r==null?void 0:r.span)||0)),h=e.reduce((r,i)=>r+((i==null?void 0:i.value)||0),0),u=e[0];t[n]={target:(u==null?void 0:u.target)||0,span:a,value:h/(this.ramps.length||1),efficiency:a/(o-1||1)}}return t}get contrasts(){return{wcag:this.wcag,apca:this.apca}}get metrics(){return{contrastEfficiency:x(this.ramps.map(t=>t.contrastEfficiency)),lightnessLinearity:x(this.ramps.map(t=>t.lightnessLinearity)),chromaSmoothness:x(this.ramps.map(t=>t.chromaSmoothness)),hueStability:x(this.ramps.map(t=>t.hueStability)),spacingUniformity:x(this.ramps.map(t=>t.spacingUniformity))}}get score(){return L(Object.values(this.metrics))}};0&&(module.exports={Palette,Ramp,Shade,calcDeltaE2000,calcScore,calcStatistics,createMonotone,cssRgbToRgb,fromLightnessEAL,hexToRgb,labToLch,labToRgb,lchToLab,rgbToHex,rgbToLab,rootMeanSquare,toLightnessEAL});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/** Calculate relative luminance from linear RGB (0-1). */
|
|
2
|
-
declare const getRelativeLuminance: (rgb: number[]) => number;
|
|
3
|
-
declare const lrgbToSrgb: (rgb: number[]) => number[];
|
|
4
|
-
declare const srgbToLrgb: (rgb: number[]) => number[];
|
|
5
1
|
/** Convert linear RGB to sRGB Hex string. */
|
|
6
2
|
declare const rgbToHex: (rgb: number[]) => string;
|
|
7
3
|
/** Convert sRGB Hex string to linear RGB. */
|
|
@@ -20,111 +16,8 @@ declare const labToRgb: (lab: number[]) => number[];
|
|
|
20
16
|
declare const labToLch: (lab: number[]) => number[];
|
|
21
17
|
/** Calculate color difference using CIEDE2000 formula. */
|
|
22
18
|
declare const calcDeltaE2000: (lab1: number[], lab2: number[]) => number;
|
|
23
|
-
/** Find the Hex color with the highest Chroma in a list. */
|
|
24
|
-
declare const findMaxChromaHex: (scale: string[]) => string;
|
|
25
|
-
/** Normalize hue values to prevent large jumps during interpolation. */
|
|
26
|
-
declare function unwrapHue(hues: number[]): number[];
|
|
27
|
-
/** Simulate Protanopia (red-blindness) on linear RGB. */
|
|
28
|
-
declare function simulateProtanopia(rgb: number[]): number[];
|
|
29
|
-
/** Simulate Deuteranopia (green-blindness) on linear RGB. */
|
|
30
|
-
declare function simulateDeuteranopia(rgb: number[]): number[];
|
|
31
19
|
/** Convert CSS rgb() string to linear RGB. */
|
|
32
20
|
declare const cssRgbToRgb: (css: string) => number[];
|
|
33
|
-
|
|
34
|
-
type ColorShade = {
|
|
35
|
-
hex: string;
|
|
36
|
-
rgb: number[];
|
|
37
|
-
lab: number[];
|
|
38
|
-
lch: number[];
|
|
39
|
-
parameter: number;
|
|
40
|
-
lightness: number;
|
|
41
|
-
chroma: number;
|
|
42
|
-
hue: number;
|
|
43
|
-
luminance: number;
|
|
44
|
-
wcag: number;
|
|
45
|
-
apca: number;
|
|
46
|
-
cumDeltaE00: number;
|
|
47
|
-
cumProtDeltaE00: number;
|
|
48
|
-
cumDeutDeltaE00: number;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
type ContrastName = 'wcag20' | 'wcag30' | 'wcag45' | 'wcag70' | 'apca45' | 'apca60' | 'apca75' | 'apca90';
|
|
52
|
-
type Contrast = {
|
|
53
|
-
system: string;
|
|
54
|
-
target: number;
|
|
55
|
-
span: number;
|
|
56
|
-
value: number;
|
|
57
|
-
efficiency: number;
|
|
58
|
-
name: ContrastName;
|
|
59
|
-
};
|
|
60
|
-
/** Calculate WCAG 2.x contrast ratio. */
|
|
61
|
-
declare const getWcagContrast: (l1: number, l2: number) => number;
|
|
62
|
-
/** Calculate APCA Lc (Lightness Contrast) value. */
|
|
63
|
-
declare const getApcaContrast: (yText: number, yBg: number) => number;
|
|
64
|
-
/** Analyze contrast metrics for a single Monochromatic scale. */
|
|
65
|
-
declare const getMonochromaticContrasts: (metrics: ColorShade[]) => Record<string, Contrast>;
|
|
66
|
-
declare const contrastList: ContrastName[];
|
|
67
|
-
/** Aggregate contrast metrics across multiple color scales. */
|
|
68
|
-
declare const getPaletteContrasts: (colorScales: any[]) => Record<ContrastName, Contrast>;
|
|
69
|
-
|
|
70
|
-
type MonochromaticAnalysis = {
|
|
71
|
-
name: string;
|
|
72
|
-
colors: string[];
|
|
73
|
-
baseIndex: number;
|
|
74
|
-
baseColor: string;
|
|
75
|
-
shades: ColorShade[];
|
|
76
|
-
metrics: MonochromaticMetrics;
|
|
77
|
-
contrasts: Record<ContrastName, Contrast>;
|
|
78
|
-
score: number;
|
|
79
|
-
};
|
|
80
|
-
type MonochromaticMetrics = {
|
|
81
|
-
lightnessLinearity: number;
|
|
82
|
-
chromaSmoothness: number;
|
|
83
|
-
spacingUniformity: number;
|
|
84
|
-
hueStability: number;
|
|
85
|
-
contrastEfficiency: number;
|
|
86
|
-
};
|
|
87
|
-
/** Analyze a single monochromatic color scale. */
|
|
88
|
-
declare const analyzeMonochromatic: (colors: string[], name?: string, stepNames?: Array<number | string>) => MonochromaticAnalysis;
|
|
89
|
-
type MonochromaticPaletteData = {
|
|
90
|
-
name: string;
|
|
91
|
-
stepNames: Array<number | string>;
|
|
92
|
-
colors: Record<string, string[]>;
|
|
93
|
-
};
|
|
94
|
-
/** Analyze a full palette containing multiple monochromatic scales. */
|
|
95
|
-
declare const analyzeMonochromaticPalette: (paletteData: MonochromaticPaletteData) => {
|
|
96
|
-
name: string;
|
|
97
|
-
baseColors: Record<string, string>;
|
|
98
|
-
stepNames: (string | number)[];
|
|
99
|
-
direction: string;
|
|
100
|
-
steps: number;
|
|
101
|
-
colors: Record<string, string[]>;
|
|
102
|
-
contrasts: Record<ContrastName, Contrast>;
|
|
103
|
-
scales: MonochromaticAnalysis[];
|
|
104
|
-
metrics: {
|
|
105
|
-
contrastEfficiency: number;
|
|
106
|
-
lightnessLinearity: number;
|
|
107
|
-
chromaSmoothness: number;
|
|
108
|
-
hueStability: number;
|
|
109
|
-
spacingUniformity: number;
|
|
110
|
-
};
|
|
111
|
-
score: number;
|
|
112
|
-
};
|
|
113
|
-
/** Measure how close lightness values follow a linear trend. */
|
|
114
|
-
declare function calcLightnessLinearity(values: number[]): number;
|
|
115
|
-
/** Measure hue deviation from a reference color. */
|
|
116
|
-
declare function calcHueStability(values: number[], ref: number): number;
|
|
117
|
-
/** Measure the smoothness of chroma transitions using a spline peak. */
|
|
118
|
-
declare const calcChromaSmoothness: (C: number[]) => number;
|
|
119
|
-
/** Measure visual spacing uniformity using DeltaE2000. */
|
|
120
|
-
declare const calcSpacingUniformity: (cumulativeDeltaE00: number[]) => number;
|
|
121
|
-
/**
|
|
122
|
-
* Evaluate Contrast Span Efficiency (η) using Continuous Linear Scaling.
|
|
123
|
-
* This scientific approach removes quantization bias (no ceil/floor),
|
|
124
|
-
* ensuring fairness across both odd and even step counts.
|
|
125
|
-
*/
|
|
126
|
-
declare const calcContrastEfficiency: (span: number, steps: number) => number;
|
|
127
|
-
|
|
128
21
|
/**
|
|
129
22
|
* Create a Monotone Cubic Hermite Interpolator.
|
|
130
23
|
* Ensures monotonicity is preserved between points.
|
|
@@ -142,4 +35,84 @@ declare const calcStatistics: (array: number[]) => {
|
|
|
142
35
|
/** Calculate geometric mean score (0-100) from metrics. */
|
|
143
36
|
declare const calcScore: (metrics: number[]) => number;
|
|
144
37
|
|
|
145
|
-
|
|
38
|
+
declare class Shade {
|
|
39
|
+
readonly hex: string;
|
|
40
|
+
constructor(hex: string);
|
|
41
|
+
get rgb(): number[];
|
|
42
|
+
get lab(): number[];
|
|
43
|
+
get lch(): number[];
|
|
44
|
+
get lightness(): number;
|
|
45
|
+
get chroma(): number;
|
|
46
|
+
get hue(): number;
|
|
47
|
+
get luminance(): number;
|
|
48
|
+
get wcag(): number;
|
|
49
|
+
get apca(): number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
type ContrastValue = {
|
|
53
|
+
efficiency: number;
|
|
54
|
+
target: number;
|
|
55
|
+
span: number;
|
|
56
|
+
value: number;
|
|
57
|
+
};
|
|
58
|
+
type WcagContrasts = Record<30 | 45 | 70, ContrastValue>;
|
|
59
|
+
type ApcaContrasts = Record<45 | 60 | 75, ContrastValue>;
|
|
60
|
+
declare class Ramp {
|
|
61
|
+
shades: Shade[];
|
|
62
|
+
name: string;
|
|
63
|
+
constructor(colors?: string[], name?: string);
|
|
64
|
+
get colors(): string[];
|
|
65
|
+
get peakChroma(): string;
|
|
66
|
+
get steps(): number;
|
|
67
|
+
get baseColor(): string;
|
|
68
|
+
get baseIndex(): number;
|
|
69
|
+
get wcag(): WcagContrasts;
|
|
70
|
+
get apca(): ApcaContrasts;
|
|
71
|
+
get contrasts(): {
|
|
72
|
+
wcag: WcagContrasts;
|
|
73
|
+
apca: ApcaContrasts;
|
|
74
|
+
};
|
|
75
|
+
get deltaECurve(): number[];
|
|
76
|
+
get unwrapHues(): number[];
|
|
77
|
+
get lightnessLinearity(): number;
|
|
78
|
+
get chromaSmoothness(): number;
|
|
79
|
+
get spacingUniformity(): number;
|
|
80
|
+
get hueStability(): number;
|
|
81
|
+
get contrastEfficiency(): number;
|
|
82
|
+
get metrics(): {
|
|
83
|
+
lightnessLinearity: number;
|
|
84
|
+
chromaSmoothness: number;
|
|
85
|
+
spacingUniformity: number;
|
|
86
|
+
hueStability: number;
|
|
87
|
+
contrastEfficiency: number;
|
|
88
|
+
};
|
|
89
|
+
get score(): number;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
type PaletteMetrics = {
|
|
93
|
+
contrastEfficiency: number;
|
|
94
|
+
lightnessLinearity: number;
|
|
95
|
+
chromaSmoothness: number;
|
|
96
|
+
hueStability: number;
|
|
97
|
+
spacingUniformity: number;
|
|
98
|
+
};
|
|
99
|
+
declare class Palette {
|
|
100
|
+
ramps: Ramp[];
|
|
101
|
+
name: string;
|
|
102
|
+
constructor(colors?: Record<string, string[]>, name?: string);
|
|
103
|
+
get colors(): {
|
|
104
|
+
[k: string]: string[];
|
|
105
|
+
};
|
|
106
|
+
get steps(): number;
|
|
107
|
+
get direction(): "lighten" | "darken";
|
|
108
|
+
get wcag(): WcagContrasts;
|
|
109
|
+
get apca(): ApcaContrasts;
|
|
110
|
+
get contrasts(): {
|
|
111
|
+
wcag: WcagContrasts;
|
|
112
|
+
apca: ApcaContrasts;
|
|
113
|
+
};
|
|
114
|
+
get metrics(): PaletteMetrics;
|
|
115
|
+
get score(): number;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export { type ApcaContrasts, type ContrastValue, Palette, type PaletteMetrics, Ramp, Shade, type WcagContrasts, calcDeltaE2000, calcScore, calcStatistics, createMonotone, cssRgbToRgb, fromLightnessEAL, hexToRgb, labToLch, labToRgb, lchToLab, rgbToHex, rgbToLab, rootMeanSquare, toLightnessEAL };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/** Calculate relative luminance from linear RGB (0-1). */
|
|
2
|
-
declare const getRelativeLuminance: (rgb: number[]) => number;
|
|
3
|
-
declare const lrgbToSrgb: (rgb: number[]) => number[];
|
|
4
|
-
declare const srgbToLrgb: (rgb: number[]) => number[];
|
|
5
1
|
/** Convert linear RGB to sRGB Hex string. */
|
|
6
2
|
declare const rgbToHex: (rgb: number[]) => string;
|
|
7
3
|
/** Convert sRGB Hex string to linear RGB. */
|
|
@@ -20,111 +16,8 @@ declare const labToRgb: (lab: number[]) => number[];
|
|
|
20
16
|
declare const labToLch: (lab: number[]) => number[];
|
|
21
17
|
/** Calculate color difference using CIEDE2000 formula. */
|
|
22
18
|
declare const calcDeltaE2000: (lab1: number[], lab2: number[]) => number;
|
|
23
|
-
/** Find the Hex color with the highest Chroma in a list. */
|
|
24
|
-
declare const findMaxChromaHex: (scale: string[]) => string;
|
|
25
|
-
/** Normalize hue values to prevent large jumps during interpolation. */
|
|
26
|
-
declare function unwrapHue(hues: number[]): number[];
|
|
27
|
-
/** Simulate Protanopia (red-blindness) on linear RGB. */
|
|
28
|
-
declare function simulateProtanopia(rgb: number[]): number[];
|
|
29
|
-
/** Simulate Deuteranopia (green-blindness) on linear RGB. */
|
|
30
|
-
declare function simulateDeuteranopia(rgb: number[]): number[];
|
|
31
19
|
/** Convert CSS rgb() string to linear RGB. */
|
|
32
20
|
declare const cssRgbToRgb: (css: string) => number[];
|
|
33
|
-
|
|
34
|
-
type ColorShade = {
|
|
35
|
-
hex: string;
|
|
36
|
-
rgb: number[];
|
|
37
|
-
lab: number[];
|
|
38
|
-
lch: number[];
|
|
39
|
-
parameter: number;
|
|
40
|
-
lightness: number;
|
|
41
|
-
chroma: number;
|
|
42
|
-
hue: number;
|
|
43
|
-
luminance: number;
|
|
44
|
-
wcag: number;
|
|
45
|
-
apca: number;
|
|
46
|
-
cumDeltaE00: number;
|
|
47
|
-
cumProtDeltaE00: number;
|
|
48
|
-
cumDeutDeltaE00: number;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
type ContrastName = 'wcag20' | 'wcag30' | 'wcag45' | 'wcag70' | 'apca45' | 'apca60' | 'apca75' | 'apca90';
|
|
52
|
-
type Contrast = {
|
|
53
|
-
system: string;
|
|
54
|
-
target: number;
|
|
55
|
-
span: number;
|
|
56
|
-
value: number;
|
|
57
|
-
efficiency: number;
|
|
58
|
-
name: ContrastName;
|
|
59
|
-
};
|
|
60
|
-
/** Calculate WCAG 2.x contrast ratio. */
|
|
61
|
-
declare const getWcagContrast: (l1: number, l2: number) => number;
|
|
62
|
-
/** Calculate APCA Lc (Lightness Contrast) value. */
|
|
63
|
-
declare const getApcaContrast: (yText: number, yBg: number) => number;
|
|
64
|
-
/** Analyze contrast metrics for a single Monochromatic scale. */
|
|
65
|
-
declare const getMonochromaticContrasts: (metrics: ColorShade[]) => Record<string, Contrast>;
|
|
66
|
-
declare const contrastList: ContrastName[];
|
|
67
|
-
/** Aggregate contrast metrics across multiple color scales. */
|
|
68
|
-
declare const getPaletteContrasts: (colorScales: any[]) => Record<ContrastName, Contrast>;
|
|
69
|
-
|
|
70
|
-
type MonochromaticAnalysis = {
|
|
71
|
-
name: string;
|
|
72
|
-
colors: string[];
|
|
73
|
-
baseIndex: number;
|
|
74
|
-
baseColor: string;
|
|
75
|
-
shades: ColorShade[];
|
|
76
|
-
metrics: MonochromaticMetrics;
|
|
77
|
-
contrasts: Record<ContrastName, Contrast>;
|
|
78
|
-
score: number;
|
|
79
|
-
};
|
|
80
|
-
type MonochromaticMetrics = {
|
|
81
|
-
lightnessLinearity: number;
|
|
82
|
-
chromaSmoothness: number;
|
|
83
|
-
spacingUniformity: number;
|
|
84
|
-
hueStability: number;
|
|
85
|
-
contrastEfficiency: number;
|
|
86
|
-
};
|
|
87
|
-
/** Analyze a single monochromatic color scale. */
|
|
88
|
-
declare const analyzeMonochromatic: (colors: string[], name?: string, stepNames?: Array<number | string>) => MonochromaticAnalysis;
|
|
89
|
-
type MonochromaticPaletteData = {
|
|
90
|
-
name: string;
|
|
91
|
-
stepNames: Array<number | string>;
|
|
92
|
-
colors: Record<string, string[]>;
|
|
93
|
-
};
|
|
94
|
-
/** Analyze a full palette containing multiple monochromatic scales. */
|
|
95
|
-
declare const analyzeMonochromaticPalette: (paletteData: MonochromaticPaletteData) => {
|
|
96
|
-
name: string;
|
|
97
|
-
baseColors: Record<string, string>;
|
|
98
|
-
stepNames: (string | number)[];
|
|
99
|
-
direction: string;
|
|
100
|
-
steps: number;
|
|
101
|
-
colors: Record<string, string[]>;
|
|
102
|
-
contrasts: Record<ContrastName, Contrast>;
|
|
103
|
-
scales: MonochromaticAnalysis[];
|
|
104
|
-
metrics: {
|
|
105
|
-
contrastEfficiency: number;
|
|
106
|
-
lightnessLinearity: number;
|
|
107
|
-
chromaSmoothness: number;
|
|
108
|
-
hueStability: number;
|
|
109
|
-
spacingUniformity: number;
|
|
110
|
-
};
|
|
111
|
-
score: number;
|
|
112
|
-
};
|
|
113
|
-
/** Measure how close lightness values follow a linear trend. */
|
|
114
|
-
declare function calcLightnessLinearity(values: number[]): number;
|
|
115
|
-
/** Measure hue deviation from a reference color. */
|
|
116
|
-
declare function calcHueStability(values: number[], ref: number): number;
|
|
117
|
-
/** Measure the smoothness of chroma transitions using a spline peak. */
|
|
118
|
-
declare const calcChromaSmoothness: (C: number[]) => number;
|
|
119
|
-
/** Measure visual spacing uniformity using DeltaE2000. */
|
|
120
|
-
declare const calcSpacingUniformity: (cumulativeDeltaE00: number[]) => number;
|
|
121
|
-
/**
|
|
122
|
-
* Evaluate Contrast Span Efficiency (η) using Continuous Linear Scaling.
|
|
123
|
-
* This scientific approach removes quantization bias (no ceil/floor),
|
|
124
|
-
* ensuring fairness across both odd and even step counts.
|
|
125
|
-
*/
|
|
126
|
-
declare const calcContrastEfficiency: (span: number, steps: number) => number;
|
|
127
|
-
|
|
128
21
|
/**
|
|
129
22
|
* Create a Monotone Cubic Hermite Interpolator.
|
|
130
23
|
* Ensures monotonicity is preserved between points.
|
|
@@ -142,4 +35,84 @@ declare const calcStatistics: (array: number[]) => {
|
|
|
142
35
|
/** Calculate geometric mean score (0-100) from metrics. */
|
|
143
36
|
declare const calcScore: (metrics: number[]) => number;
|
|
144
37
|
|
|
145
|
-
|
|
38
|
+
declare class Shade {
|
|
39
|
+
readonly hex: string;
|
|
40
|
+
constructor(hex: string);
|
|
41
|
+
get rgb(): number[];
|
|
42
|
+
get lab(): number[];
|
|
43
|
+
get lch(): number[];
|
|
44
|
+
get lightness(): number;
|
|
45
|
+
get chroma(): number;
|
|
46
|
+
get hue(): number;
|
|
47
|
+
get luminance(): number;
|
|
48
|
+
get wcag(): number;
|
|
49
|
+
get apca(): number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
type ContrastValue = {
|
|
53
|
+
efficiency: number;
|
|
54
|
+
target: number;
|
|
55
|
+
span: number;
|
|
56
|
+
value: number;
|
|
57
|
+
};
|
|
58
|
+
type WcagContrasts = Record<30 | 45 | 70, ContrastValue>;
|
|
59
|
+
type ApcaContrasts = Record<45 | 60 | 75, ContrastValue>;
|
|
60
|
+
declare class Ramp {
|
|
61
|
+
shades: Shade[];
|
|
62
|
+
name: string;
|
|
63
|
+
constructor(colors?: string[], name?: string);
|
|
64
|
+
get colors(): string[];
|
|
65
|
+
get peakChroma(): string;
|
|
66
|
+
get steps(): number;
|
|
67
|
+
get baseColor(): string;
|
|
68
|
+
get baseIndex(): number;
|
|
69
|
+
get wcag(): WcagContrasts;
|
|
70
|
+
get apca(): ApcaContrasts;
|
|
71
|
+
get contrasts(): {
|
|
72
|
+
wcag: WcagContrasts;
|
|
73
|
+
apca: ApcaContrasts;
|
|
74
|
+
};
|
|
75
|
+
get deltaECurve(): number[];
|
|
76
|
+
get unwrapHues(): number[];
|
|
77
|
+
get lightnessLinearity(): number;
|
|
78
|
+
get chromaSmoothness(): number;
|
|
79
|
+
get spacingUniformity(): number;
|
|
80
|
+
get hueStability(): number;
|
|
81
|
+
get contrastEfficiency(): number;
|
|
82
|
+
get metrics(): {
|
|
83
|
+
lightnessLinearity: number;
|
|
84
|
+
chromaSmoothness: number;
|
|
85
|
+
spacingUniformity: number;
|
|
86
|
+
hueStability: number;
|
|
87
|
+
contrastEfficiency: number;
|
|
88
|
+
};
|
|
89
|
+
get score(): number;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
type PaletteMetrics = {
|
|
93
|
+
contrastEfficiency: number;
|
|
94
|
+
lightnessLinearity: number;
|
|
95
|
+
chromaSmoothness: number;
|
|
96
|
+
hueStability: number;
|
|
97
|
+
spacingUniformity: number;
|
|
98
|
+
};
|
|
99
|
+
declare class Palette {
|
|
100
|
+
ramps: Ramp[];
|
|
101
|
+
name: string;
|
|
102
|
+
constructor(colors?: Record<string, string[]>, name?: string);
|
|
103
|
+
get colors(): {
|
|
104
|
+
[k: string]: string[];
|
|
105
|
+
};
|
|
106
|
+
get steps(): number;
|
|
107
|
+
get direction(): "lighten" | "darken";
|
|
108
|
+
get wcag(): WcagContrasts;
|
|
109
|
+
get apca(): ApcaContrasts;
|
|
110
|
+
get contrasts(): {
|
|
111
|
+
wcag: WcagContrasts;
|
|
112
|
+
apca: ApcaContrasts;
|
|
113
|
+
};
|
|
114
|
+
get metrics(): PaletteMetrics;
|
|
115
|
+
get score(): number;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export { type ApcaContrasts, type ContrastValue, Palette, type PaletteMetrics, Ramp, Shade, 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 P=Object.defineProperty;var ot=Object.getOwnPropertyDescriptor;var at=Object.getOwnPropertyNames;var st=Object.prototype.hasOwnProperty;var ct=(r,t)=>{for(var n in t)P(r,n,{get:t[n],enumerable:!0})},mt=(r,t,n,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of at(t))!st.call(r,o)&&o!==n&&P(r,o,{get:()=>t[o],enumerable:!(e=ot(t,o))||e.enumerable});return r};var ht=r=>mt(P({},"__esModule",{value:!0}),r);var dt={};ct(dt,{analyzeMonochromatic:()=>O,analyzeMonochromaticPalette:()=>xt,calcChromaSmoothness:()=>K,calcContrastEfficiency:()=>Q,calcDeltaE2000:()=>A,calcHueStability:()=>Z,calcLightnessLinearity:()=>W,calcScore:()=>I,calcSpacingUniformity:()=>J,calcStatistics:()=>ft,contrastList:()=>H,createMonotone:()=>z,cssRgbToRgb:()=>gt,findMaxChromaHex:()=>k,fromLightnessEAL:()=>ut,getApcaContrast:()=>L,getMonochromaticContrasts:()=>N,getPaletteContrasts:()=>X,getRelativeLuminance:()=>D,getWcagContrast:()=>R,hexToRgb:()=>f,labToLch:()=>q,labToRgb:()=>lt,lchToLab:()=>bt,lrgbToSrgb:()=>G,rgbToHex:()=>it,rgbToLab:()=>x,rootMeanSquare:()=>y,simulateDeuteranopia:()=>Mt,simulateProtanopia:()=>pt,srgbToLrgb:()=>_,toLightnessEAL:()=>T,unwrapHue:()=>v});var D=r=>{let[t,n,e]=r;return .2126*t+.7152*n+.0722*e},G=r=>{let t=n=>{let e=Math.max(0,Math.min(1,n)),o=e<=.0031308?12.92*e:1.055*Math.pow(e,1/2.4)-.055;return Math.max(0,Math.min(255,Math.round(o*255)))};return r.map(t)},_=r=>{let t=n=>n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92;return r.map(t)},it=r=>{let[t,n,e]=G(r);return t=t.toString(16).padStart(2,"0"),n=n.toString(16).padStart(2,"0"),e=e.toString(16).padStart(2,"0"),`#${t}${n}${e}`},f=r=>{let t=parseInt(r.slice(1,3),16)/255,n=parseInt(r.slice(3,5),16)/255,e=parseInt(r.slice(5,7),16)/255;return _([t,n,e])},T=r=>{let[t,n,e]=r,o=Math.sqrt(n*n+e*e),s=(Math.atan2(e,n)*180/Math.PI+360)%360,i=.1644,b=.0603,m=.1307,u=.006,h=i*Math.abs(Math.sin((s-90)/2*(Math.PI/180)))+b,a=0;return(s<=90||s>=270)&&(a=m*Math.abs(Math.cos(s*(Math.PI/180)))+u),t+(h+a)*o},ut=(r,t)=>{let[,n,e]=t,o=Math.sqrt(n*n+e*e),s=(Math.atan2(e,n)*180/Math.PI+360)%360,i=.1644,b=.0603,m=.1307,u=.006,h=i*Math.abs(Math.sin((s-90)/2*(Math.PI/180)))+b,a=0;return(s<=90||s>=270)&&(a=m*Math.abs(Math.cos(s*(Math.PI/180)))+u),Math.max(0,r-(h+a)*o)},bt=r=>{let[t,n,e]=r,o=e*Math.PI/180;return[t,n*Math.cos(o),n*Math.sin(o)]},x=r=>{let[t,n,e]=r,o=.4124564*t+.3575761*n+.1804375*e,c=.2126729*t+.7151522*n+.072175*e,s=.0193339*t+.119192*n+.9503041*e,i=.95047,b=1,m=1.08883,u=p=>p>.008856?Math.cbrt(p):7.787*p+16/116,h=u(o/i),a=u(c/b),l=u(s/m);return[116*a-16,500*(h-a),200*(a-l)]},lt=r=>{let[t,n,e]=r,o=(t+16)/116,c=n/500+o,s=o-e/200,i=p=>p**3>.008856?p**3:(p-16/116)/7.787,b=.95047,m=1,u=1.08883,h=i(c)*b,a=i(o)*m,l=i(s)*u;return[3.2404542*h-1.5371385*a-.4985314*l,-.969266*h+1.8760108*a+.041556*l,.0556434*h-.2040259*a+1.0572252*l]},q=r=>{let[t,n,e]=r,o=Math.sqrt(n*n+e*e);if(o<1e-4)return[t,0,0];let s=(Math.atan2(e,n)*180/Math.PI+360)%360;return s>=359.9999&&(s=0),[t,o,s]},A=(r,t)=>{let[n,e,o]=r,[c,s,i]=t,b=(n+c)/2,m=Math.sqrt(e*e+o*o),u=Math.sqrt(s*s+i*i),h=(m+u)/2,a=.5*(1-Math.sqrt(Math.pow(h,7)/(Math.pow(h,7)+Math.pow(25,7)))),l=e*(1+a),p=s*(1+a),M=Math.sqrt(l*l+o*o),d=Math.sqrt(p*p+i*i),S=(M+d)/2,C=Math.atan2(o,l)*180/Math.PI+(Math.atan2(o,l)<0?360:0),g=Math.atan2(i,p)*180/Math.PI+(Math.atan2(i,p)<0?360:0),E=g-C;Math.abs(E)>180&&(E+=g<=C?360:-360);let w=Math.abs(C-g)>180?(C+g+360)/2:(C+g)/2,V=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),tt=c-n,Y=d-M,B=2*Math.sqrt(M*d)*Math.sin(E/2*Math.PI/180),nt=1+.015*Math.pow(b-50,2)/Math.sqrt(20+Math.pow(b-50,2)),U=1+.045*S,$=1+.015*S*V,rt=30*Math.exp(-Math.pow((w-275)/25,2)),et=-(2*Math.sqrt(Math.pow(S,7)/(Math.pow(S,7)+Math.pow(25,7))))*Math.sin(2*rt*Math.PI/180);return Math.sqrt(Math.pow(tt/nt,2)+Math.pow(Y/U,2)+Math.pow(B/$,2)+et*(Y/U)*(B/$))},k=r=>{let t="",n=-1/0;for(let e of r){let o=x(f(e)),[,c]=q(o);c>n&&(n=c,t=e)}return t};function v(r){let t=[r[0]];for(let n=1;n<r.length;n++){let e=r[n]-r[n-1];e>180?e-=360:e<-180&&(e+=360),t.push(t[n-1]+e)}return t}function pt(r){let[t,n,e]=r;return[.152286*t+1.052583*n-.204868*e,.114503*t+.786281*n+.099216*e,-.003882*t-.048116*n+1.051998*e]}function Mt(r){let[t,n,e]=r;return[.367322*t+.860646*n-.227968*e,.280085*t+.672501*n+.047413*e,-.01182*t+.04294*n+.968881*e]}var gt=r=>{let t=r.match(/\d+(\.\d+)?/g);if(!t||t.length<3)throw new Error("Invalid CSS rgb()");let n=e=>{let o=e/255;return o<=.04045?o/12.92:Math.pow((o+.055)/1.055,2.4)};return[n(Number(t[0])),n(Number(t[1])),n(Number(t[2]))]};var R=(r,t)=>(Math.max(r,t)+.05)/(Math.min(r,t)+.05),L=(r,t)=>{let n=s=>s>5e-4?s:s+Math.pow(5e-4-s,.8),e=n(r),o=n(t),c=(Math.pow(e,.56)-Math.pow(o,.56))*100;return Math.abs(c)<.1?0:(c=c>0?c<1?0:c-.25:c>-1?0:c+.25,Math.round(c))};function j(r){let t=r.match(/^(wcag|apca)(\d+)$/);if(!t)throw new Error(`Invalid contrast: ${r}`);let n=t[1]==="wcag"?Number(t[2])/10:Number(t[2]);return{system:t[1],target:n}}var N=r=>{let t={},n=r.length,e=n-1;return H.forEach(o=>{let{system:c,target:s}=j(o),i=e,b=0;for(let m=1;m<n;m++){let u=1/0;for(let h=0;h<n-m;h++){let a=c==="wcag"?R(r[h].luminance,r[h+m].luminance):Math.max(Math.abs(L(r[h+m].luminance,r[h].luminance)),Math.abs(L(r[h].luminance,r[h+m].luminance)));a<u&&(u=a)}if(u>=s){i=m,b=u;break}m===e&&(b=u)}t[o]={system:c,efficiency:i/e,target:s,span:i,value:b,name:o}}),t},H=["wcag30","wcag45","wcag70","apca45","apca60","apca75"],X=r=>{let t={};return H.forEach(n=>{var m;let{target:e,system:o}=j(n),c=r.map(u=>u.contrasts[n]),s=((m=r[0])==null?void 0:m.shades.length)||0,i=Math.max(...c.map(u=>(u==null?void 0:u.span)||0)),b=c.reduce((u,h)=>u+((h==null?void 0:h.value)||0),0);t[n]={system:o,target:e,span:i,value:b/(r.length||1),name:n,efficiency:i/(s-1||1)}}),t};var F=r=>{let t=f(r),n=x(t),e=D(t),o=T(n),c=q(n);return{hex:r,rgb:t,lab:n,lch:c,lightness:o,chroma:c[1],hue:c[2],luminance:e,parameter:0,cumDeltaE00:0,cumProtDeltaE00:0,cumDeutDeltaE00:0,wcag:R(e,1),apca:L(e,1)}};var z=r=>{if(r.length<1)return m=>0;let t=[...r].sort((m,u)=>m[0]-u[0]),n=[];for(let m=0;m<t.length;m++)(m===0||t[m][0]!==t[m-1][0])&&n.push(t[m]);let e=n.length;if(e===1)return m=>n[0][1];let o=n.map(m=>m[0]),c=n.map(m=>m[1]),s=[],i=[];for(let m=0;m<e-1;m++)s[m]=o[m+1]-o[m],i[m]=(c[m+1]-c[m])/s[m];let b=new Array(e);b[0]=i[0],b[e-1]=i[e-2];for(let m=1;m<e-1;m++){let u=i[m-1],h=i[m];if(u*h<=0)b[m]=0;else{let a=(1+s[m]/(s[m-1]+s[m]))/3;b[m]=u*h/((1-a)*u+a*h)}}return m=>{if(m<=o[0])return c[0];if(m>=o[e-1])return c[e-1];let u=0,h=e-2,a=0;for(;u<=h;){let g=Math.floor((u+h)/2);if(m>=o[g]&&m<=o[g+1]){a=g;break}m<o[g]?h=g-1:u=g+1}let l=s[a],p=(m-o[a])/l,M=p*p,d=M*p,S=b[a]*l,C=b[a+1]*l;return(2*d-3*M+1)*c[a]+(d-2*M+p)*S+(-2*d+3*M)*c[a+1]+(d-M)*C}};function y(r){let t=r.length;if(t===0)return 0;let n=0;for(let e=0;e<t;e++)n+=r[e]*r[e];return Math.sqrt(n/t)}var ft=r=>{let t=r.length;if(t===0)return{min:0,max:0,avg:0};let n=r[0],e=r[0],o=0;for(let c=0;c<t;c++){let s=r[c];s<n&&(n=s),s>e&&(e=s),o+=s}return{min:n,max:e,avg:o/t}},I=r=>{let t=r.length;if(t===0)return 0;let n=1e-6,e=r.reduce((s,i)=>s*(i+n),1),o=Math.pow(e,1/t),c=Math.max(0,Math.min(1,o));return parseFloat((c*100).toFixed(2))};var O=(r,t,n)=>{t||(t="brand"),n||(n=[...Array(r.length).keys()]);let e=x(f(r[0]))[0],o=x(f(r[r.length-1]))[0];e>o&&r.reverse();let c=r.map(a=>F(a));for(let a=1;a<c.length;a++){let l=A(c[a-1].lab,c[a].lab);c[a].cumDeltaE00=c[a-1].cumDeltaE00+l}let s=k(r.slice(2,-2))||r[Math.floor(r.length/2)],i=r.findIndex(a=>a.toLowerCase()===(s==null?void 0:s.toLowerCase())),b=v(c.map(a=>a.hue).slice(1,-1));for(let a=1;a<c.length-1;a++)c[a].hue=b[a-1];let m=Z(c.map(a=>a.hue).slice(1,-1),c[i].hue),u=N(c),h={lightnessLinearity:W(c.map(a=>a.lightness)),chromaSmoothness:K(c.map(a=>a.chroma)),spacingUniformity:J(c.map(a=>a.cumDeltaE00)),contrastEfficiency:Q(u.wcag45.span,n.length),hueStability:m};return{name:t,colors:r,baseIndex:i,baseColor:s,shades:c,contrasts:u,metrics:h,score:I(Object.values(h))}},xt=r=>{let{stepNames:t,name:n,colors:e}=r,o=Object.values(e)[0],c=x(f(o[0]))[0],s=x(f(o[o.length-1]))[0],i=c>s?"darken":"lighten",b=[],m={};for(let h in e){let a=O(e[h],h,t);b.push(a),m[h]=a.baseColor}let u={contrastEfficiency:y(b.map(h=>h.metrics.contrastEfficiency)),lightnessLinearity:y(b.map(h=>h.metrics.lightnessLinearity)),chromaSmoothness:y(b.map(h=>h.metrics.chromaSmoothness)),hueStability:y(b.map(h=>h.metrics.hueStability)),spacingUniformity:y(b.map(h=>h.metrics.spacingUniformity))};return{name:n,baseColors:m,stepNames:t,direction:i,steps:t.length,colors:e,contrasts:X(b),scales:b,metrics:u,score:I(Object.values(u))}};function W(r){let t=r.length;if(t<2)return 1;let n=0,e=0,o=0,c=0;for(let a=0;a<t;a++)n+=a,e+=r[a],o+=a*r[a],c+=a*a;let s=t*c-n*n;if(Math.abs(s)<1e-10)return 1;let i=(t*o-n*e)/s,b=(e-i*n)/t;if(Math.abs(i*(t-1))<.001)return 1;let u=0,h=0;for(let a=0;a<t;a++){let l=i*a+b,p=r[a]-l;u+=p*p;let M=Math.max(l-Math.min(b,i*(t-1)+b),Math.max(b,i*(t-1)+b)-l);h+=M*M}return Math.max(0,Math.min(1,1-Math.sqrt(u/t)/Math.sqrt(h/t)))}function Z(r,t){let n=r.length;if(n<2)return 1;let e=0,o=0;for(let c=0;c<n;c++){let s=Math.abs(r[c]-t)%360;s>180&&(s=360-s),e+=s*s;let i=c/(n-1)*180;o+=i*i}return Math.max(0,Math.min(1,1-Math.sqrt(e/n)/(Math.sqrt(o/n)||1)))}var K=r=>{let t=r.length;if(t<3)return 1;let n=133.8,e=Math.max(...r);if(e<=.01)return 1;let o=r.map(h=>h/e*n),c=Math.min(...o),s=Math.max(...o),i=o.findIndex(h=>h===s),b=z([[0,o[0]],[i,s],[t-1,o[t-1]]]),m=0,u=0;for(let h=0;h<t;h++){let a=b(h),l=o[h]-a;m+=l*l,u+=Math.pow(Math.max(a-c,s-a),2)}return Math.max(0,Math.min(1,1-Math.sqrt(m/t)/Math.sqrt(u/t)))},J=r=>{let t=r.length;if(t<2)return 1;let n=[];for(let s=1;s<t;s++){let i=r[s]-r[s-1];if(i<0)return 0;n.push(i)}let e=n.reduce((s,i)=>s+i,0)/n.length;if(e<=1e-6)return 0;let o=0;for(let s of n)o+=Math.pow(s-e,2);let c=Math.sqrt(o/n.length)/e;return Math.max(0,Math.min(1,1/(1+c)))},Q=(r,t)=>{if(t<=1)return 1;let n=.5,e=r/t,o=n*((t-1)/t);return e<=o?1:e>=1?0:(1-e)/(1-o)};return ht(dt);})();
|
|
1
|
+
"use strict";var Chromametry=(()=>{var v=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var O=Object.prototype.hasOwnProperty;var N=(m,t)=>{for(var s in t)v(m,s,{get:t[s],enumerable:!0})},V=(m,t,s,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of j(t))!O.call(m,e)&&e!==s&&v(m,e,{get:()=>t[e],enumerable:!(n=G(t,e))||n.enumerable});return m};var $=m=>V(v({},"__esModule",{value:!0}),m);var et={};N(et,{Palette:()=>T,Ramp:()=>q,Shade:()=>y,calcDeltaE2000:()=>P,calcScore:()=>L,calcStatistics:()=>nt,createMonotone:()=>E,cssRgbToRgb:()=>st,fromLightnessEAL:()=>J,hexToRgb:()=>C,labToLch:()=>k,labToRgb:()=>tt,lchToLab:()=>Q,rgbToHex:()=>Z,rgbToLab:()=>S,rootMeanSquare:()=>x,toLightnessEAL:()=>_});var F=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)},K=m=>{let t=s=>s>.04045?Math.pow((s+.055)/1.055,2.4):s/12.92;return m.map(t)},Z=m=>{let[t,s,n]=F(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}`},C=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 K([t,s,n])},_=m=>{let[t,s,n]=m,e=Math.sqrt(s*s+n*n),a=(Math.atan2(n,s)*180/Math.PI+360)%360,h=.1644,u=.0603,r=.1307,i=.006,l=h*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+u,c=0;return(a<=90||a>=270)&&(c=r*Math.abs(Math.cos(a*(Math.PI/180)))+i),t+(l+c)*e},J=(m,t)=>{let[,s,n]=t,e=Math.sqrt(s*s+n*n),a=(Math.atan2(n,s)*180/Math.PI+360)%360,h=.1644,u=.0603,r=.1307,i=.006,l=h*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+u,c=0;return(a<=90||a>=270)&&(c=r*Math.abs(Math.cos(a*(Math.PI/180)))+i),Math.max(0,m-(l+c)*e)},Q=m=>{let[t,s,n]=m,e=n*Math.PI/180;return[t,s*Math.cos(e),s*Math.sin(e)]},S=m=>{let[t,s,n]=m,e=.4124564*t+.3575761*s+.1804375*n,o=.2126729*t+.7151522*s+.072175*n,a=.0193339*t+.119192*s+.9503041*n,h=.95047,u=1,r=1.08883,i=g=>g>.008856?Math.cbrt(g):7.787*g+16/116,l=i(e/h),c=i(o/u),p=i(a/r);return[116*c-16,500*(l-c),200*(c-p)]},tt=m=>{let[t,s,n]=m,e=(t+16)/116,o=s/500+e,a=e-n/200,h=g=>g**3>.008856?g**3:(g-16/116)/7.787,u=.95047,r=1,i=1.08883,l=h(o)*u,c=h(e)*r,p=h(a)*i;return[3.2404542*l-1.5371385*c-.4985314*p,-.969266*l+1.8760108*c+.041556*p,.0556434*l-.2040259*c+1.0572252*p]},k=m=>{let[t,s,n]=m,e=Math.sqrt(s*s+n*n);if(e<1e-4)return[t,0,0];let a=(Math.atan2(n,s)*180/Math.PI+360)%360;return a>=359.9999&&(a=0),[t,e,a]},P=(m,t)=>{let[s,n,e]=m,[o,a,h]=t,u=(s+o)/2,r=Math.sqrt(n*n+e*e),i=Math.sqrt(a*a+h*h),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=a*(1+c),M=Math.sqrt(p*p+e*e),b=Math.sqrt(g*g+h*h),w=(M+b)/2,d=Math.atan2(e,p)*180/Math.PI+(Math.atan2(e,p)<0?360:0),f=Math.atan2(h,g)*180/Math.PI+(Math.atan2(h,g)<0?360:0),R=f-d;Math.abs(R)>180&&(R+=f<=d?360:-360);let I=Math.abs(d-f)>180?(d+f+360)/2:(d+f)/2,U=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),W=o-s,A=b-M,D=2*Math.sqrt(M*b)*Math.sin(R/2*Math.PI/180),X=1+.015*Math.pow(u-50,2)/Math.sqrt(20+Math.pow(u-50,2)),H=1+.045*w,Y=1+.015*w*U,z=30*Math.exp(-Math.pow((I-275)/25,2)),B=-(2*Math.sqrt(Math.pow(w,7)/(Math.pow(w,7)+Math.pow(25,7))))*Math.sin(2*z*Math.PI/180);return Math.sqrt(Math.pow(W/X,2)+Math.pow(A/H,2)+Math.pow(D/Y,2)+B*(A/H)*(D/Y))},st=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]))]},E=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]),o=s.map(r=>r[1]),a=[],h=[];for(let r=0;r<n-1;r++)a[r]=e[r+1]-e[r],h[r]=(o[r+1]-o[r])/a[r];let u=new Array(n);u[0]=h[0],u[n-1]=h[n-2];for(let r=1;r<n-1;r++){let i=h[r-1],l=h[r];if(i*l<=0)u[r]=0;else{let c=(1+a[r]/(a[r-1]+a[r]))/3;u[r]=i*l/((1-c)*i+c*l)}}return r=>{if(r<=e[0])return o[0];if(r>=e[n-1])return o[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=a[c],g=(r-e[c])/p,M=g*g,b=M*g,w=u[c]*p,d=u[c+1]*p;return(2*b-3*M+1)*o[c]+(b-2*M+g)*w+(-2*b+3*M)*o[c+1]+(b-M)*d}};function x(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 nt=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 o=0;o<t;o++){let a=m[o];a<s&&(s=a),a>n&&(n=a),e+=a}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((a,h)=>a*(h+s),1),e=Math.pow(n,1/t),o=Math.max(0,Math.min(1,e));return parseFloat((o*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 k(this.lab)}get lightness(){let[t,s,n]=this.lab,e=Math.sqrt(s*s+n*n),a=(Math.atan2(n,s)*180/Math.PI+360)%360,h=.1644,u=.0603,r=.1307,i=.006,l=h*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+u,c=0;return(a<=90||a>=270)&&(c=r*Math.abs(Math.cos(a*(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=o=>o>5e-4?o:o+Math.pow(5e-4-o,.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.shades=t.map(n=>new y(n)),this.name=s}get colors(){return this.shades.map(t=>t.hex)}get peakChroma(){let t=this.colors.slice(2,-2),s="",n=-1/0;for(let e of t){let o=new y(e);o.chroma>n&&(n=o.chroma,s=e)}return s}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(t=>t.toLowerCase()===this.baseColor.toLowerCase())}get wcag(){let t=this.shades,s=t.length,n=s-1,e={};for(let o of[30,45,70]){let a=o/10,h=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>=a){h=r,u=i;break}r===n&&(u=i)}e[o]={efficiency:h/n,target:a,span:h,value:u}}return e}get apca(){let t=this.shades,s=t.length,n=s-1,e={},o=(a,h)=>{let u=c=>c>5e-4?c:c+Math.pow(5e-4-c,.8),r=u(a),i=u(h),l=(Math.pow(r,.56)-Math.pow(i,.56))*100;return Math.abs(l)<.1?0:(l=l>0?l<1?0:l-.25:l>-1?0:l+.25,Math.round(l))};for(let a of[45,60,75]){let h=a,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=Math.max(Math.abs(o(t[c+i].luminance,t[c].luminance)),Math.abs(o(t[c].luminance,t[c+i].luminance)));p<l&&(l=p)}if(l>=h){u=i,r=l;break}i===n&&(r=l)}e[a]={efficiency:u/n,target:h,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.shades.length;s++){let n=P(this.shades[s-1].lab,this.shades[s].lab);t.push(t[s-1]+n)}return t}get unwrapHues(){let t=this.shades.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.shades.map(p=>p.lightness),s=t.length;if(s<2)return 1;let n=0,e=0,o=0,a=0;for(let p=0;p<s;p++)n+=p,e+=t[p],o+=p*t[p],a+=p*p;let h=s*a-n*n;if(Math.abs(h)<1e-10)return 1;let u=(s*o-n*e)/h,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.shades.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 o=t.map(c=>c/e*n),a=Math.min(...o),h=Math.max(...o),u=o.findIndex(c=>c===h),r=E([[0,o[0]],[u,h],[s-1,o[s-1]]]),i=0,l=0;for(let c=0;c<s;c++){let p=r(c),g=o[c]-p;i+=g*g,l+=Math.pow(Math.max(p-a,h-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 h=1;h<s;h++){let u=t[h]-t[h-1];if(u<0)return 0;n.push(u)}let e=n.reduce((h,u)=>h+u,0)/n.length;if(e<=1e-6)return 0;let o=0;for(let h of n)o+=Math.pow(h-e,2);let a=Math.sqrt(o/n.length)/e;return Math.max(0,Math.min(1,1/(1+a)))}get hueStability(){var a,h,u;let t=this.unwrapHues,s=t.length;if(s<2)return 1;let n=(u=(h=t[this.baseIndex-1])!=null?h:(a=this.shades[this.baseIndex])==null?void 0:a.hue)!=null?u:0,e=0,o=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;o+=l*l}return Math.max(0,Math.min(1,1-Math.sqrt(e/s)/(Math.sqrt(o/s)||1)))}get contrastEfficiency(){let t=this.wcag[45].span,s=this.steps;if(s<=1)return 1;let n=.5,e=t/s,o=n*((s-1)/s);return e<=o?1:e>=1?0:(1-e)/(1-o)}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="palette"){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 direction(){var e;let t=(e=this.ramps[0])==null?void 0:e.colors;if(!(t!=null&&t.length))return"lighten";let s=S(C(t[0])),n=S(C(t[t.length-1]));return s[0]>n[0]?"darken":"lighten"}get wcag(){var s;let t={};for(let n of[30,45,70]){let e=this.ramps.map(r=>r.wcag[n]),o=((s=this.ramps[0])==null?void 0:s.steps)||0,a=Math.max(...e.map(r=>(r==null?void 0:r.span)||0)),h=e.reduce((r,i)=>r+((i==null?void 0:i.value)||0),0),u=e[0];t[n]={target:(u==null?void 0:u.target)||0,span:a,value:h/(this.ramps.length||1),efficiency:a/(o-1||1)}}return t}get apca(){var s;let t={};for(let n of[45,60,75]){let e=this.ramps.map(r=>r.apca[n]),o=((s=this.ramps[0])==null?void 0:s.steps)||0,a=Math.max(...e.map(r=>(r==null?void 0:r.span)||0)),h=e.reduce((r,i)=>r+((i==null?void 0:i.value)||0),0),u=e[0];t[n]={target:(u==null?void 0:u.target)||0,span:a,value:h/(this.ramps.length||1),efficiency:a/(o-1||1)}}return t}get contrasts(){return{wcag:this.wcag,apca:this.apca}}get metrics(){return{contrastEfficiency:x(this.ramps.map(t=>t.contrastEfficiency)),lightnessLinearity:x(this.ramps.map(t=>t.lightnessLinearity)),chromaSmoothness:x(this.ramps.map(t=>t.chromaSmoothness)),hueStability:x(this.ramps.map(t=>t.hueStability)),spacingUniformity:x(this.ramps.map(t=>t.spacingUniformity))}}get score(){return L(Object.values(this.metrics))}};return $(et);})();
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var k=e=>{let[t,n,r]=e;return .2126*t+.7152*n+.0722*r},Z=e=>{let t=n=>{let r=Math.max(0,Math.min(1,n)),o=r<=.0031308?12.92*r:1.055*Math.pow(r,1/2.4)-.055;return Math.max(0,Math.min(255,Math.round(o*255)))};return e.map(t)},K=e=>{let t=n=>n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92;return e.map(t)},ot=e=>{let[t,n,r]=Z(e);return t=t.toString(16).padStart(2,"0"),n=n.toString(16).padStart(2,"0"),r=r.toString(16).padStart(2,"0"),`#${t}${n}${r}`},x=e=>{let t=parseInt(e.slice(1,3),16)/255,n=parseInt(e.slice(3,5),16)/255,r=parseInt(e.slice(5,7),16)/255;return K([t,n,r])},v=e=>{let[t,n,r]=e,o=Math.sqrt(n*n+r*r),s=(Math.atan2(r,n)*180/Math.PI+360)%360,i=.1644,b=.0603,m=.1307,u=.006,h=i*Math.abs(Math.sin((s-90)/2*(Math.PI/180)))+b,a=0;return(s<=90||s>=270)&&(a=m*Math.abs(Math.cos(s*(Math.PI/180)))+u),t+(h+a)*o},at=(e,t)=>{let[,n,r]=t,o=Math.sqrt(n*n+r*r),s=(Math.atan2(r,n)*180/Math.PI+360)%360,i=.1644,b=.0603,m=.1307,u=.006,h=i*Math.abs(Math.sin((s-90)/2*(Math.PI/180)))+b,a=0;return(s<=90||s>=270)&&(a=m*Math.abs(Math.cos(s*(Math.PI/180)))+u),Math.max(0,e-(h+a)*o)},st=e=>{let[t,n,r]=e,o=r*Math.PI/180;return[t,n*Math.cos(o),n*Math.sin(o)]},d=e=>{let[t,n,r]=e,o=.4124564*t+.3575761*n+.1804375*r,c=.2126729*t+.7151522*n+.072175*r,s=.0193339*t+.119192*n+.9503041*r,i=.95047,b=1,m=1.08883,u=p=>p>.008856?Math.cbrt(p):7.787*p+16/116,h=u(o/i),a=u(c/b),l=u(s/m);return[116*a-16,500*(h-a),200*(a-l)]},ct=e=>{let[t,n,r]=e,o=(t+16)/116,c=n/500+o,s=o-r/200,i=p=>p**3>.008856?p**3:(p-16/116)/7.787,b=.95047,m=1,u=1.08883,h=i(c)*b,a=i(o)*m,l=i(s)*u;return[3.2404542*h-1.5371385*a-.4985314*l,-.969266*h+1.8760108*a+.041556*l,.0556434*h-.2040259*a+1.0572252*l]},R=e=>{let[t,n,r]=e,o=Math.sqrt(n*n+r*r);if(o<1e-4)return[t,0,0];let s=(Math.atan2(r,n)*180/Math.PI+360)%360;return s>=359.9999&&(s=0),[t,o,s]},N=(e,t)=>{let[n,r,o]=e,[c,s,i]=t,b=(n+c)/2,m=Math.sqrt(r*r+o*o),u=Math.sqrt(s*s+i*i),h=(m+u)/2,a=.5*(1-Math.sqrt(Math.pow(h,7)/(Math.pow(h,7)+Math.pow(25,7)))),l=r*(1+a),p=s*(1+a),M=Math.sqrt(l*l+o*o),f=Math.sqrt(p*p+i*i),y=(M+f)/2,C=Math.atan2(o,l)*180/Math.PI+(Math.atan2(o,l)<0?360:0),g=Math.atan2(i,p)*180/Math.PI+(Math.atan2(i,p)<0?360:0),q=g-C;Math.abs(q)>180&&(q+=g<=C?360:-360);let w=Math.abs(C-g)>180?(C+g+360)/2:(C+g)/2,_=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),j=c-n,P=f-M,D=2*Math.sqrt(M*f)*Math.sin(q/2*Math.PI/180),F=1+.015*Math.pow(b-50,2)/Math.sqrt(20+Math.pow(b-50,2)),T=1+.045*y,A=1+.015*y*_,O=30*Math.exp(-Math.pow((w-275)/25,2)),W=-(2*Math.sqrt(Math.pow(y,7)/(Math.pow(y,7)+Math.pow(25,7))))*Math.sin(2*O*Math.PI/180);return Math.sqrt(Math.pow(j/F,2)+Math.pow(P/T,2)+Math.pow(D/A,2)+W*(P/T)*(D/A))},H=e=>{let t="",n=-1/0;for(let r of e){let o=d(x(r)),[,c]=R(o);c>n&&(n=c,t=r)}return t};function X(e){let t=[e[0]];for(let n=1;n<e.length;n++){let r=e[n]-e[n-1];r>180?r-=360:r<-180&&(r+=360),t.push(t[n-1]+r)}return t}function mt(e){let[t,n,r]=e;return[.152286*t+1.052583*n-.204868*r,.114503*t+.786281*n+.099216*r,-.003882*t-.048116*n+1.051998*r]}function ht(e){let[t,n,r]=e;return[.367322*t+.860646*n-.227968*r,.280085*t+.672501*n+.047413*r,-.01182*t+.04294*n+.968881*r]}var it=e=>{let t=e.match(/\d+(\.\d+)?/g);if(!t||t.length<3)throw new Error("Invalid CSS rgb()");let n=r=>{let o=r/255;return o<=.04045?o/12.92:Math.pow((o+.055)/1.055,2.4)};return[n(Number(t[0])),n(Number(t[1])),n(Number(t[2]))]};var I=(e,t)=>(Math.max(e,t)+.05)/(Math.min(e,t)+.05),L=(e,t)=>{let n=s=>s>5e-4?s:s+Math.pow(5e-4-s,.8),r=n(e),o=n(t),c=(Math.pow(r,.56)-Math.pow(o,.56))*100;return Math.abs(c)<.1?0:(c=c>0?c<1?0:c-.25:c>-1?0:c+.25,Math.round(c))};function z(e){let t=e.match(/^(wcag|apca)(\d+)$/);if(!t)throw new Error(`Invalid contrast: ${e}`);let n=t[1]==="wcag"?Number(t[2])/10:Number(t[2]);return{system:t[1],target:n}}var Y=e=>{let t={},n=e.length,r=n-1;return B.forEach(o=>{let{system:c,target:s}=z(o),i=r,b=0;for(let m=1;m<n;m++){let u=1/0;for(let h=0;h<n-m;h++){let a=c==="wcag"?I(e[h].luminance,e[h+m].luminance):Math.max(Math.abs(L(e[h+m].luminance,e[h].luminance)),Math.abs(L(e[h].luminance,e[h+m].luminance)));a<u&&(u=a)}if(u>=s){i=m,b=u;break}m===r&&(b=u)}t[o]={system:c,efficiency:i/r,target:s,span:i,value:b,name:o}}),t},B=["wcag30","wcag45","wcag70","apca45","apca60","apca75"],U=e=>{let t={};return B.forEach(n=>{var m;let{target:r,system:o}=z(n),c=e.map(u=>u.contrasts[n]),s=((m=e[0])==null?void 0:m.shades.length)||0,i=Math.max(...c.map(u=>(u==null?void 0:u.span)||0)),b=c.reduce((u,h)=>u+((h==null?void 0:h.value)||0),0);t[n]={system:o,target:r,span:i,value:b/(e.length||1),name:n,efficiency:i/(s-1||1)}}),t};var $=e=>{let t=x(e),n=d(t),r=k(t),o=v(n),c=R(n);return{hex:e,rgb:t,lab:n,lch:c,lightness:o,chroma:c[1],hue:c[2],luminance:r,parameter:0,cumDeltaE00:0,cumProtDeltaE00:0,cumDeutDeltaE00:0,wcag:I(r,1),apca:L(r,1)}};var G=e=>{if(e.length<1)return m=>0;let t=[...e].sort((m,u)=>m[0]-u[0]),n=[];for(let m=0;m<t.length;m++)(m===0||t[m][0]!==t[m-1][0])&&n.push(t[m]);let r=n.length;if(r===1)return m=>n[0][1];let o=n.map(m=>m[0]),c=n.map(m=>m[1]),s=[],i=[];for(let m=0;m<r-1;m++)s[m]=o[m+1]-o[m],i[m]=(c[m+1]-c[m])/s[m];let b=new Array(r);b[0]=i[0],b[r-1]=i[r-2];for(let m=1;m<r-1;m++){let u=i[m-1],h=i[m];if(u*h<=0)b[m]=0;else{let a=(1+s[m]/(s[m-1]+s[m]))/3;b[m]=u*h/((1-a)*u+a*h)}}return m=>{if(m<=o[0])return c[0];if(m>=o[r-1])return c[r-1];let u=0,h=r-2,a=0;for(;u<=h;){let g=Math.floor((u+h)/2);if(m>=o[g]&&m<=o[g+1]){a=g;break}m<o[g]?h=g-1:u=g+1}let l=s[a],p=(m-o[a])/l,M=p*p,f=M*p,y=b[a]*l,C=b[a+1]*l;return(2*f-3*M+1)*c[a]+(f-2*M+p)*y+(-2*f+3*M)*c[a+1]+(f-M)*C}};function S(e){let t=e.length;if(t===0)return 0;let n=0;for(let r=0;r<t;r++)n+=e[r]*e[r];return Math.sqrt(n/t)}var gt=e=>{let t=e.length;if(t===0)return{min:0,max:0,avg:0};let n=e[0],r=e[0],o=0;for(let c=0;c<t;c++){let s=e[c];s<n&&(n=s),s>r&&(r=s),o+=s}return{min:n,max:r,avg:o/t}},E=e=>{let t=e.length;if(t===0)return 0;let n=1e-6,r=e.reduce((s,i)=>s*(i+n),1),o=Math.pow(r,1/t),c=Math.max(0,Math.min(1,o));return parseFloat((c*100).toFixed(2))};var J=(e,t,n)=>{t||(t="brand"),n||(n=[...Array(e.length).keys()]);let r=d(x(e[0]))[0],o=d(x(e[e.length-1]))[0];r>o&&e.reverse();let c=e.map(a=>$(a));for(let a=1;a<c.length;a++){let l=N(c[a-1].lab,c[a].lab);c[a].cumDeltaE00=c[a-1].cumDeltaE00+l}let s=H(e.slice(2,-2))||e[Math.floor(e.length/2)],i=e.findIndex(a=>a.toLowerCase()===(s==null?void 0:s.toLowerCase())),b=X(c.map(a=>a.hue).slice(1,-1));for(let a=1;a<c.length-1;a++)c[a].hue=b[a-1];let m=V(c.map(a=>a.hue).slice(1,-1),c[i].hue),u=Y(c),h={lightnessLinearity:Q(c.map(a=>a.lightness)),chromaSmoothness:tt(c.map(a=>a.chroma)),spacingUniformity:nt(c.map(a=>a.cumDeltaE00)),contrastEfficiency:rt(u.wcag45.span,n.length),hueStability:m};return{name:t,colors:e,baseIndex:i,baseColor:s,shades:c,contrasts:u,metrics:h,score:E(Object.values(h))}},Et=e=>{let{stepNames:t,name:n,colors:r}=e,o=Object.values(r)[0],c=d(x(o[0]))[0],s=d(x(o[o.length-1]))[0],i=c>s?"darken":"lighten",b=[],m={};for(let h in r){let a=J(r[h],h,t);b.push(a),m[h]=a.baseColor}let u={contrastEfficiency:S(b.map(h=>h.metrics.contrastEfficiency)),lightnessLinearity:S(b.map(h=>h.metrics.lightnessLinearity)),chromaSmoothness:S(b.map(h=>h.metrics.chromaSmoothness)),hueStability:S(b.map(h=>h.metrics.hueStability)),spacingUniformity:S(b.map(h=>h.metrics.spacingUniformity))};return{name:n,baseColors:m,stepNames:t,direction:i,steps:t.length,colors:r,contrasts:U(b),scales:b,metrics:u,score:E(Object.values(u))}};function Q(e){let t=e.length;if(t<2)return 1;let n=0,r=0,o=0,c=0;for(let a=0;a<t;a++)n+=a,r+=e[a],o+=a*e[a],c+=a*a;let s=t*c-n*n;if(Math.abs(s)<1e-10)return 1;let i=(t*o-n*r)/s,b=(r-i*n)/t;if(Math.abs(i*(t-1))<.001)return 1;let u=0,h=0;for(let a=0;a<t;a++){let l=i*a+b,p=e[a]-l;u+=p*p;let M=Math.max(l-Math.min(b,i*(t-1)+b),Math.max(b,i*(t-1)+b)-l);h+=M*M}return Math.max(0,Math.min(1,1-Math.sqrt(u/t)/Math.sqrt(h/t)))}function V(e,t){let n=e.length;if(n<2)return 1;let r=0,o=0;for(let c=0;c<n;c++){let s=Math.abs(e[c]-t)%360;s>180&&(s=360-s),r+=s*s;let i=c/(n-1)*180;o+=i*i}return Math.max(0,Math.min(1,1-Math.sqrt(r/n)/(Math.sqrt(o/n)||1)))}var tt=e=>{let t=e.length;if(t<3)return 1;let n=133.8,r=Math.max(...e);if(r<=.01)return 1;let o=e.map(h=>h/r*n),c=Math.min(...o),s=Math.max(...o),i=o.findIndex(h=>h===s),b=G([[0,o[0]],[i,s],[t-1,o[t-1]]]),m=0,u=0;for(let h=0;h<t;h++){let a=b(h),l=o[h]-a;m+=l*l,u+=Math.pow(Math.max(a-c,s-a),2)}return Math.max(0,Math.min(1,1-Math.sqrt(m/t)/Math.sqrt(u/t)))},nt=e=>{let t=e.length;if(t<2)return 1;let n=[];for(let s=1;s<t;s++){let i=e[s]-e[s-1];if(i<0)return 0;n.push(i)}let r=n.reduce((s,i)=>s+i,0)/n.length;if(r<=1e-6)return 0;let o=0;for(let s of n)o+=Math.pow(s-r,2);let c=Math.sqrt(o/n.length)/r;return Math.max(0,Math.min(1,1/(1+c)))},rt=(e,t)=>{if(t<=1)return 1;let n=.5,r=e/t,o=n*((t-1)/t);return r<=o?1:r>=1?0:(1-r)/(1-o)};export{J as analyzeMonochromatic,Et as analyzeMonochromaticPalette,tt as calcChromaSmoothness,rt as calcContrastEfficiency,N as calcDeltaE2000,V as calcHueStability,Q as calcLightnessLinearity,E as calcScore,nt as calcSpacingUniformity,gt as calcStatistics,B as contrastList,G as createMonotone,it as cssRgbToRgb,H as findMaxChromaHex,at as fromLightnessEAL,L as getApcaContrast,Y as getMonochromaticContrasts,U as getPaletteContrasts,k as getRelativeLuminance,I as getWcagContrast,x as hexToRgb,R as labToLch,ct as labToRgb,st as lchToLab,Z as lrgbToSrgb,ot as rgbToHex,d as rgbToLab,S as rootMeanSquare,ht as simulateDeuteranopia,mt as simulateProtanopia,K as srgbToLrgb,v as toLightnessEAL,X as unwrapHue};
|
|
1
|
+
var B=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)},G=l=>{let t=s=>s>.04045?Math.pow((s+.055)/1.055,2.4):s/12.92;return l.map(t)},O=l=>{let[t,s,n]=B(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}`},S=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 G([t,s,n])},N=l=>{let[t,s,n]=l,e=Math.sqrt(s*s+n*n),a=(Math.atan2(n,s)*180/Math.PI+360)%360,h=.1644,u=.0603,r=.1307,i=.006,m=h*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+u,c=0;return(a<=90||a>=270)&&(c=r*Math.abs(Math.cos(a*(Math.PI/180)))+i),t+(m+c)*e},V=(l,t)=>{let[,s,n]=t,e=Math.sqrt(s*s+n*n),a=(Math.atan2(n,s)*180/Math.PI+360)%360,h=.1644,u=.0603,r=.1307,i=.006,m=h*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+u,c=0;return(a<=90||a>=270)&&(c=r*Math.abs(Math.cos(a*(Math.PI/180)))+i),Math.max(0,l-(m+c)*e)},$=l=>{let[t,s,n]=l,e=n*Math.PI/180;return[t,s*Math.cos(e),s*Math.sin(e)]},y=l=>{let[t,s,n]=l,e=.4124564*t+.3575761*s+.1804375*n,o=.2126729*t+.7151522*s+.072175*n,a=.0193339*t+.119192*s+.9503041*n,h=.95047,u=1,r=1.08883,i=g=>g>.008856?Math.cbrt(g):7.787*g+16/116,m=i(e/h),c=i(o/u),p=i(a/r);return[116*c-16,500*(m-c),200*(c-p)]},F=l=>{let[t,s,n]=l,e=(t+16)/116,o=s/500+e,a=e-n/200,h=g=>g**3>.008856?g**3:(g-16/116)/7.787,u=.95047,r=1,i=1.08883,m=h(o)*u,c=h(e)*r,p=h(a)*i;return[3.2404542*m-1.5371385*c-.4985314*p,-.969266*m+1.8760108*c+.041556*p,.0556434*m-.2040259*c+1.0572252*p]},T=l=>{let[t,s,n]=l,e=Math.sqrt(s*s+n*n);if(e<1e-4)return[t,0,0];let a=(Math.atan2(n,s)*180/Math.PI+360)%360;return a>=359.9999&&(a=0),[t,e,a]},A=(l,t)=>{let[s,n,e]=l,[o,a,h]=t,u=(s+o)/2,r=Math.sqrt(n*n+e*e),i=Math.sqrt(a*a+h*h),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=a*(1+c),M=Math.sqrt(p*p+e*e),b=Math.sqrt(g*g+h*h),x=(M+b)/2,d=Math.atan2(e,p)*180/Math.PI+(Math.atan2(e,p)<0?360:0),f=Math.atan2(h,g)*180/Math.PI+(Math.atan2(h,g)<0?360:0),R=f-d;Math.abs(R)>180&&(R+=f<=d?360:-360);let C=Math.abs(d-f)>180?(d+f+360)/2:(d+f)/2,Y=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),U=o-s,v=b-M,k=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)),P=1+.045*x,E=1+.015*x*Y,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(U/W,2)+Math.pow(v/P,2)+Math.pow(k/E,2)+z*(v/P)*(k/E))},K=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]))]},D=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]),o=s.map(r=>r[1]),a=[],h=[];for(let r=0;r<n-1;r++)a[r]=e[r+1]-e[r],h[r]=(o[r+1]-o[r])/a[r];let u=new Array(n);u[0]=h[0],u[n-1]=h[n-2];for(let r=1;r<n-1;r++){let i=h[r-1],m=h[r];if(i*m<=0)u[r]=0;else{let c=(1+a[r]/(a[r-1]+a[r]))/3;u[r]=i*m/((1-c)*i+c*m)}}return r=>{if(r<=e[0])return o[0];if(r>=e[n-1])return o[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=a[c],g=(r-e[c])/p,M=g*g,b=M*g,x=u[c]*p,d=u[c+1]*p;return(2*b-3*M+1)*o[c]+(b-2*M+g)*x+(-2*b+3*M)*o[c+1]+(b-M)*d}};function w(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 Z=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 o=0;o<t;o++){let a=l[o];a<s&&(s=a),a>n&&(n=a),e+=a}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((a,h)=>a*(h+s),1),e=Math.pow(n,1/t),o=Math.max(0,Math.min(1,e));return parseFloat((o*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),a=(Math.atan2(n,s)*180/Math.PI+360)%360,h=.1644,u=.0603,r=.1307,i=.006,m=h*Math.abs(Math.sin((a-90)/2*(Math.PI/180)))+u,c=0;return(a<=90||a>=270)&&(c=r*Math.abs(Math.cos(a*(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=o=>o>5e-4?o:o+Math.pow(5e-4-o,.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.shades=t.map(n=>new I(n)),this.name=s}get colors(){return this.shades.map(t=>t.hex)}get peakChroma(){let t=this.colors.slice(2,-2),s="",n=-1/0;for(let e of t){let o=new I(e);o.chroma>n&&(n=o.chroma,s=e)}return s}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(t=>t.toLowerCase()===this.baseColor.toLowerCase())}get wcag(){let t=this.shades,s=t.length,n=s-1,e={};for(let o of[30,45,70]){let a=o/10,h=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>=a){h=r,u=i;break}r===n&&(u=i)}e[o]={efficiency:h/n,target:a,span:h,value:u}}return e}get apca(){let t=this.shades,s=t.length,n=s-1,e={},o=(a,h)=>{let u=c=>c>5e-4?c:c+Math.pow(5e-4-c,.8),r=u(a),i=u(h),m=(Math.pow(r,.56)-Math.pow(i,.56))*100;return Math.abs(m)<.1?0:(m=m>0?m<1?0:m-.25:m>-1?0:m+.25,Math.round(m))};for(let a of[45,60,75]){let h=a,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=Math.max(Math.abs(o(t[c+i].luminance,t[c].luminance)),Math.abs(o(t[c].luminance,t[c+i].luminance)));p<m&&(m=p)}if(m>=h){u=i,r=m;break}i===n&&(r=m)}e[a]={efficiency:u/n,target:h,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.shades.length;s++){let n=A(this.shades[s-1].lab,this.shades[s].lab);t.push(t[s-1]+n)}return t}get unwrapHues(){let t=this.shades.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.shades.map(p=>p.lightness),s=t.length;if(s<2)return 1;let n=0,e=0,o=0,a=0;for(let p=0;p<s;p++)n+=p,e+=t[p],o+=p*t[p],a+=p*p;let h=s*a-n*n;if(Math.abs(h)<1e-10)return 1;let u=(s*o-n*e)/h,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.shades.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 o=t.map(c=>c/e*n),a=Math.min(...o),h=Math.max(...o),u=o.findIndex(c=>c===h),r=D([[0,o[0]],[u,h],[s-1,o[s-1]]]),i=0,m=0;for(let c=0;c<s;c++){let p=r(c),g=o[c]-p;i+=g*g,m+=Math.pow(Math.max(p-a,h-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 h=1;h<s;h++){let u=t[h]-t[h-1];if(u<0)return 0;n.push(u)}let e=n.reduce((h,u)=>h+u,0)/n.length;if(e<=1e-6)return 0;let o=0;for(let h of n)o+=Math.pow(h-e,2);let a=Math.sqrt(o/n.length)/e;return Math.max(0,Math.min(1,1/(1+a)))}get hueStability(){var a,h,u;let t=this.unwrapHues,s=t.length;if(s<2)return 1;let n=(u=(h=t[this.baseIndex-1])!=null?h:(a=this.shades[this.baseIndex])==null?void 0:a.hue)!=null?u:0,e=0,o=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;o+=m*m}return Math.max(0,Math.min(1,1-Math.sqrt(e/s)/(Math.sqrt(o/s)||1)))}get contrastEfficiency(){let t=this.wcag[45].span,s=this.steps;if(s<=1)return 1;let n=.5,e=t/s,o=n*((s-1)/s);return e<=o?1:e>=1?0:(1-e)/(1-o)}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 H=class{constructor(t={},s="palette"){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 direction(){var e;let t=(e=this.ramps[0])==null?void 0:e.colors;if(!(t!=null&&t.length))return"lighten";let s=y(S(t[0])),n=y(S(t[t.length-1]));return s[0]>n[0]?"darken":"lighten"}get wcag(){var s;let t={};for(let n of[30,45,70]){let e=this.ramps.map(r=>r.wcag[n]),o=((s=this.ramps[0])==null?void 0:s.steps)||0,a=Math.max(...e.map(r=>(r==null?void 0:r.span)||0)),h=e.reduce((r,i)=>r+((i==null?void 0:i.value)||0),0),u=e[0];t[n]={target:(u==null?void 0:u.target)||0,span:a,value:h/(this.ramps.length||1),efficiency:a/(o-1||1)}}return t}get apca(){var s;let t={};for(let n of[45,60,75]){let e=this.ramps.map(r=>r.apca[n]),o=((s=this.ramps[0])==null?void 0:s.steps)||0,a=Math.max(...e.map(r=>(r==null?void 0:r.span)||0)),h=e.reduce((r,i)=>r+((i==null?void 0:i.value)||0),0),u=e[0];t[n]={target:(u==null?void 0:u.target)||0,span:a,value:h/(this.ramps.length||1),efficiency:a/(o-1||1)}}return t}get contrasts(){return{wcag:this.wcag,apca:this.apca}}get metrics(){return{contrastEfficiency:w(this.ramps.map(t=>t.contrastEfficiency)),lightnessLinearity:w(this.ramps.map(t=>t.lightnessLinearity)),chromaSmoothness:w(this.ramps.map(t=>t.chromaSmoothness)),hueStability:w(this.ramps.map(t=>t.hueStability)),spacingUniformity:w(this.ramps.map(t=>t.spacingUniformity))}}get score(){return L(Object.values(this.metrics))}};export{H as Palette,q as Ramp,I as Shade,A as calcDeltaE2000,L as calcScore,Z as calcStatistics,D as createMonotone,K as cssRgbToRgb,V as fromLightnessEAL,S as hexToRgb,T as labToLch,F as labToRgb,$ as lchToLab,O as rgbToHex,y as rgbToLab,w as rootMeanSquare,N as toLightnessEAL};
|
package/package.json
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "chromametry",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Web-accessible Color Palette Metrics",
|
|
5
|
-
"main": "./dist/index.cjs",
|
|
6
|
-
"module": "./dist/index.js",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"type": "module",
|
|
9
|
-
"scripts": {
|
|
10
|
-
"test": "vitest",
|
|
11
|
-
"generate": "tsx
|
|
12
|
-
"build": "tsup",
|
|
13
|
-
"prepublishOnly": "npm run
|
|
14
|
-
},
|
|
15
|
-
"keywords": [
|
|
16
|
-
"color",
|
|
17
|
-
"color-palette",
|
|
18
|
-
"color-metrics",
|
|
19
|
-
"palette",
|
|
20
|
-
"monochromatic",
|
|
21
|
-
"accessibility",
|
|
22
|
-
"wcag",
|
|
23
|
-
"design-system"
|
|
24
|
-
],
|
|
25
|
-
"author": "Huu Khanh Nguyen",
|
|
26
|
-
"license": "MIT",
|
|
27
|
-
"devDependencies": {
|
|
28
|
-
"@ant-design/colors": "^8.0.1",
|
|
29
|
-
"@atlaskit/tokens": "^10.0.1",
|
|
30
|
-
"@material/material-color-utilities": "^0.3.0",
|
|
31
|
-
"@types/node": "^25.2.0",
|
|
32
|
-
"chartjs-node-canvas": "^5.0.0",
|
|
33
|
-
"tsup": "^8.5.0",
|
|
34
|
-
"tsx": "^4.21.0",
|
|
35
|
-
"typescript": "^5.8.3",
|
|
36
|
-
"vitest": "^4.0.18"
|
|
37
|
-
},
|
|
38
|
-
"unpkg": "dist/index.global.js",
|
|
39
|
-
"jsdelivr": "dist/index.global.js",
|
|
40
|
-
"files": [
|
|
41
|
-
"dist",
|
|
42
|
-
"README.md"
|
|
43
|
-
]
|
|
44
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "chromametry",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Web-accessible Color Palette Metrics",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "vitest",
|
|
11
|
+
"generate": "tsx scripts/generate.ts",
|
|
12
|
+
"build": "tsup",
|
|
13
|
+
"prepublishOnly": "npm run test &&npm run build"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"color",
|
|
17
|
+
"color-palette",
|
|
18
|
+
"color-metrics",
|
|
19
|
+
"palette",
|
|
20
|
+
"monochromatic",
|
|
21
|
+
"accessibility",
|
|
22
|
+
"wcag",
|
|
23
|
+
"design-system"
|
|
24
|
+
],
|
|
25
|
+
"author": "Huu Khanh Nguyen",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@ant-design/colors": "^8.0.1",
|
|
29
|
+
"@atlaskit/tokens": "^10.0.1",
|
|
30
|
+
"@material/material-color-utilities": "^0.3.0",
|
|
31
|
+
"@types/node": "^25.2.0",
|
|
32
|
+
"chartjs-node-canvas": "^5.0.0",
|
|
33
|
+
"tsup": "^8.5.0",
|
|
34
|
+
"tsx": "^4.21.0",
|
|
35
|
+
"typescript": "^5.8.3",
|
|
36
|
+
"vitest": "^4.0.18"
|
|
37
|
+
},
|
|
38
|
+
"unpkg": "dist/index.global.js",
|
|
39
|
+
"jsdelivr": "dist/index.global.js",
|
|
40
|
+
"files": [
|
|
41
|
+
"dist",
|
|
42
|
+
"README.md"
|
|
43
|
+
]
|
|
44
|
+
}
|