1
+ import { DARK_BASE , LIGHT_BASE , DEFAULT_TINT_COLOR } from './colors' ;
2
+
1
3
type ColorShades = {
2
4
[ key : string ] : string ;
3
5
} ;
@@ -6,9 +8,6 @@ type RGBColor = [number, number, number];
6
8
type OKLABColor = { L : number ; A : number ; B : number } ;
7
9
type OKLCHColor = { L : number ; C : number ; H : number } ;
8
10
9
- export const DARK_BASE = '#1d1d1d' ;
10
- export const LIGHT_BASE = '#ffffff' ;
11
- export const DEFAULT_TINT_COLOR = '#787878' ;
12
11
const D65 = [ 95.047 , 100.0 , 108.883 ] ; // Reference white (D65)
13
12
14
13
export enum ColorCategory {
@@ -226,7 +225,7 @@ export function colorScale(
226
225
/**
227
226
* Convert a hex color to an RGB color set.
228
227
*/
229
- function hexToRgbArray ( hex : string ) : RGBColor {
228
+ export function hexToRgbArray ( hex : string ) : RGBColor {
230
229
const originalHex = hex ;
231
230
232
231
let value = hex . replace ( '#' , '' ) ;
@@ -252,7 +251,7 @@ function hexToRgbArray(hex: string): RGBColor {
252
251
/**
253
252
* Convert a RGB color set to a hex color.
254
253
*/
255
- function rgbArrayToHex ( rgb : RGBColor ) : string {
254
+ export function rgbArrayToHex ( rgb : RGBColor ) : string {
256
255
return `#${ rgb
257
256
. map ( ( channel ) => {
258
257
const component = channel . toString ( 16 ) ;
@@ -262,7 +261,7 @@ function rgbArrayToHex(rgb: RGBColor): string {
262
261
. join ( '' ) } `;
263
262
}
264
263
265
- function getColor ( percentage : number , start : RGBColor , end : RGBColor ) {
264
+ export function getColor ( percentage : number , start : RGBColor , end : RGBColor ) {
266
265
const rgb = end . map ( ( channel , index ) => {
267
266
return Math . round ( channel + percentage * ( start [ index ] - channel ) ) ;
268
267
} ) ;
@@ -271,21 +270,21 @@ function getColor(percentage: number, start: RGBColor, end: RGBColor) {
271
270
}
272
271
273
272
// Utility constants and helper functions
274
- function rgbToLinear ( rgb : RGBColor ) : [ number , number , number ] {
273
+ export function rgbToLinear ( rgb : RGBColor ) : [ number , number , number ] {
275
274
return rgb . map ( ( v ) => {
276
275
const scaled = v / 255 ;
277
276
return scaled <= 0.04045 ? scaled / 12.92 : ( ( scaled + 0.055 ) / 1.055 ) ** 2.4 ;
278
277
} ) as [ number , number , number ] ;
279
278
}
280
279
281
- function linearToRgb ( linear : [ number , number , number ] ) : RGBColor {
280
+ export function linearToRgb ( linear : [ number , number , number ] ) : RGBColor {
282
281
return linear . map ( ( v ) => {
283
282
const scaled = v <= 0.0031308 ? 12.92 * v : 1.055 * v ** ( 1 / 2.4 ) - 0.055 ;
284
283
return Math . round ( Math . max ( 0 , Math . min ( 1 , scaled ) ) * 255 ) ;
285
284
} ) as RGBColor ;
286
285
}
287
286
288
- function rgbToOklab ( rgb : RGBColor ) : OKLABColor {
287
+ export function rgbToOklab ( rgb : RGBColor ) : OKLABColor {
289
288
const [ r , g , b ] = rgbToLinear ( rgb ) ;
290
289
291
290
const l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b ;
@@ -303,7 +302,7 @@ function rgbToOklab(rgb: RGBColor): OKLABColor {
303
302
} ;
304
303
}
305
304
306
- function oklabToRgb ( oklab : OKLABColor ) : RGBColor {
305
+ export function oklabToRgb ( oklab : OKLABColor ) : RGBColor {
307
306
const { L, A, B } = oklab ;
308
307
309
308
const lRoot = L + 0.3963377774 * A + 0.2158037573 * B ;
@@ -321,14 +320,14 @@ function oklabToRgb(oklab: OKLABColor): RGBColor {
321
320
return linearToRgb ( [ r , g , b ] ) ;
322
321
}
323
322
324
- function oklabToOklch ( oklab : OKLABColor ) : OKLCHColor {
323
+ export function oklabToOklch ( oklab : OKLABColor ) : OKLCHColor {
325
324
const { L, A, B } = oklab ;
326
325
const C = Math . sqrt ( A ** 2 + B ** 2 ) ;
327
326
const H = ( Math . atan2 ( B , A ) * 180 ) / Math . PI ;
328
327
return { L, C, H : H < 0 ? H + 360 : H } ;
329
328
}
330
329
331
- function oklchToOklab ( oklch : OKLCHColor ) : OKLABColor {
330
+ export function oklchToOklab ( oklch : OKLCHColor ) : OKLABColor {
332
331
const { L, C, H } = oklch ;
333
332
const rad = ( H * Math . PI ) / 180 ;
334
333
return {
@@ -338,15 +337,15 @@ function oklchToOklab(oklch: OKLCHColor): OKLABColor {
338
337
} ;
339
338
}
340
339
341
- function rgbToOklch ( rgb : RGBColor ) : OKLCHColor {
340
+ export function rgbToOklch ( rgb : RGBColor ) : OKLCHColor {
342
341
return oklabToOklch ( rgbToOklab ( rgb ) ) ;
343
342
}
344
343
345
- function oklchToRgb ( oklch : OKLCHColor ) : RGBColor {
344
+ export function oklchToRgb ( oklch : OKLCHColor ) : RGBColor {
346
345
return oklabToRgb ( oklchToOklab ( oklch ) ) ;
347
346
}
348
347
349
- function rgbToXyz ( rgb : RGBColor ) : [ number , number , number ] {
348
+ export function rgbToXyz ( rgb : RGBColor ) : [ number , number , number ] {
350
349
const [ r , g , b ] = rgbToLinear ( rgb ) ;
351
350
return [
352
351
( r * 0.4124564 + g * 0.3575761 + b * 0.1804375 ) * 100 ,
@@ -355,7 +354,11 @@ function rgbToXyz(rgb: RGBColor): [number, number, number] {
355
354
] ;
356
355
}
357
356
358
- function xyzToLab65 ( xyz : [ number , number , number ] ) : { L : number ; A : number ; B : number } {
357
+ export function xyzToLab65 ( xyz : [ number , number , number ] ) : {
358
+ L : number ;
359
+ A : number ;
360
+ B : number ;
361
+ } {
359
362
const [ x , y , z ] = xyz . map ( ( v , i ) => {
360
363
const scaled = v / D65 [ i ] ;
361
364
return scaled > 0.008856 ? Math . cbrt ( scaled ) : 7.787 * scaled + 16 / 116 ;
@@ -368,15 +371,15 @@ function xyzToLab65(xyz: [number, number, number]): { L: number; A: number; B: n
368
371
} ;
369
372
}
370
373
371
- function rgbTolab65 ( rgb : RGBColor ) : { L : number ; A : number ; B : number } {
374
+ export function rgbTolab65 ( rgb : RGBColor ) : { L : number ; A : number ; B : number } {
372
375
return xyzToLab65 ( rgbToXyz ( rgb ) ) ;
373
376
}
374
377
375
378
/*
376
379
Delta Phi Star perceptual lightness contrast by Andrew Somers:
377
380
https://github.com/Myndex/deltaphistar
378
381
*/
379
- const PHI = 0.5 + Math . sqrt ( 1.25 ) ;
382
+ export const PHI = 0.5 + Math . sqrt ( 1.25 ) ;
380
383
381
384
export function dpsContrast ( a : RGBColor , b : RGBColor ) {
382
385
const dps = Math . abs ( rgbTolab65 ( a ) . L ** PHI - rgbTolab65 ( b ) . L ** PHI ) ;
@@ -387,7 +390,10 @@ export function dpsContrast(a: RGBColor, b: RGBColor) {
387
390
export function colorContrast ( background : string , foreground : string [ ] = [ LIGHT_BASE , DARK_BASE ] ) {
388
391
const bg = hexToRgbArray ( background ) ;
389
392
390
- const best : { color ?: RGBColor ; contrast : number } = { color : undefined , contrast : 0 } ;
393
+ const best : { color ?: RGBColor ; contrast : number } = {
394
+ color : undefined ,
395
+ contrast : 0 ,
396
+ } ;
391
397
for ( const color of foreground ) {
392
398
const c = hexToRgbArray ( color ) ;
393
399
0 commit comments