colorizr 3.0.2 → 3.0.4
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 +40 -21
- package/dist/index.d.mts +79 -14
- package/dist/index.d.ts +79 -14
- package/dist/index.js +76 -54
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +73 -51
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
- package/src/colorizr.ts +5 -3
- package/src/format-css.ts +7 -3
- package/src/index.ts +7 -0
- package/src/modules/invariant.ts +0 -1
- package/src/palette.ts +34 -18
- package/src/scheme.ts +5 -0
- package/src/swatch.ts +93 -36
- package/src/text-color.ts +15 -5
- package/src/types/index.ts +4 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "colorizr",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.4",
|
|
4
4
|
"description": "Manipulate colors like a boss",
|
|
5
5
|
"author": "Gil Barbara <gilbarbara@gmail.com>",
|
|
6
6
|
"keywords": [
|
|
@@ -32,13 +32,13 @@
|
|
|
32
32
|
"types": "dist/index.d.ts",
|
|
33
33
|
"sideEffects": false,
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@arethetypeswrong/cli": "^0.17.
|
|
35
|
+
"@arethetypeswrong/cli": "^0.17.2",
|
|
36
36
|
"@gilbarbara/eslint-config": "^0.8.2",
|
|
37
37
|
"@gilbarbara/prettier-config": "^1.0.0",
|
|
38
38
|
"@gilbarbara/tsconfig": "^0.2.3",
|
|
39
39
|
"@size-limit/preset-small-lib": "^11.1.6",
|
|
40
|
-
"@types/node": "^22.10.
|
|
41
|
-
"@vitest/coverage-v8": "^2.1.
|
|
40
|
+
"@types/node": "^22.10.2",
|
|
41
|
+
"@vitest/coverage-v8": "^2.1.8",
|
|
42
42
|
"del-cli": "^6.0.0",
|
|
43
43
|
"husky": "^9.1.7",
|
|
44
44
|
"is-ci-cli": "^2.2.0",
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
"size-limit": "^11.1.6",
|
|
47
47
|
"ts-node": "^10.9.2",
|
|
48
48
|
"tsup": "^8.3.5",
|
|
49
|
-
"typescript": "^5.
|
|
50
|
-
"vite-tsconfig-paths": "^5.1.
|
|
51
|
-
"vitest": "^2.1.
|
|
49
|
+
"typescript": "^5.6.3",
|
|
50
|
+
"vite-tsconfig-paths": "^5.1.4",
|
|
51
|
+
"vitest": "^2.1.8",
|
|
52
52
|
"watch-run": "^1.2.5"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
package/src/colorizr.ts
CHANGED
|
@@ -20,9 +20,11 @@ import textColor from '~/text-color';
|
|
|
20
20
|
import transparentize from '~/transparentize';
|
|
21
21
|
import { Alpha, Amount, Analysis, ColorType, Degrees, HEX, HSL, LAB, LCH, RGB } from '~/types';
|
|
22
22
|
|
|
23
|
-
export interface
|
|
23
|
+
export interface ColorizrOptions {
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
25
|
+
* Output color format.
|
|
26
|
+
*
|
|
27
|
+
* If not specified, the output will use the same format as the input color.
|
|
26
28
|
*/
|
|
27
29
|
format?: ColorType;
|
|
28
30
|
}
|
|
@@ -36,7 +38,7 @@ export default class Colorizr {
|
|
|
36
38
|
public rgb: RGB;
|
|
37
39
|
public type: ColorType;
|
|
38
40
|
|
|
39
|
-
constructor(color: string | HSL | LAB | LCH | RGB, options:
|
|
41
|
+
constructor(color: string | HSL | LAB | LCH | RGB, options: ColorizrOptions = {}) {
|
|
40
42
|
invariant(!!color, 'color is required');
|
|
41
43
|
|
|
42
44
|
const { alpha, hex, hsl, oklab, oklch, rgb, type } = parseColor(color);
|
package/src/format-css.ts
CHANGED
|
@@ -7,10 +7,13 @@ import { isHex, isHSL, isLAB, isLCH, isValidColorModel } from '~/modules/validat
|
|
|
7
7
|
import * as converters from '~/converters';
|
|
8
8
|
import { Alpha, ColorModel, ColorType, HEX, HSL } from '~/types';
|
|
9
9
|
|
|
10
|
-
export interface
|
|
10
|
+
export interface FormatCSSOptions {
|
|
11
|
+
/**
|
|
12
|
+
* The alpha value of the color.
|
|
13
|
+
*/
|
|
11
14
|
alpha?: Alpha;
|
|
12
15
|
/**
|
|
13
|
-
*
|
|
16
|
+
* Output color format.
|
|
14
17
|
* @default 'hex'
|
|
15
18
|
*/
|
|
16
19
|
format?: ColorType;
|
|
@@ -21,6 +24,7 @@ export interface FormatOptions {
|
|
|
21
24
|
precision?: number;
|
|
22
25
|
/**
|
|
23
26
|
* The separator between the values.
|
|
27
|
+
*
|
|
24
28
|
* oklab and oklch always use space as a separator.
|
|
25
29
|
* @default ' '
|
|
26
30
|
*/
|
|
@@ -29,7 +33,7 @@ export interface FormatOptions {
|
|
|
29
33
|
|
|
30
34
|
export default function formatCSS<T extends ColorModel | HEX>(
|
|
31
35
|
input: T,
|
|
32
|
-
options:
|
|
36
|
+
options: FormatCSSOptions = {},
|
|
33
37
|
): string {
|
|
34
38
|
invariant(isHex(input) || isValidColorModel(input), MESSAGES.invalid);
|
|
35
39
|
|
package/src/index.ts
CHANGED
|
@@ -33,5 +33,12 @@ export * from '~/types';
|
|
|
33
33
|
export * from '~/modules/hex-utils';
|
|
34
34
|
export { isHex, isHSL, isLAB, isLCH, isRGB } from '~/modules/validators';
|
|
35
35
|
|
|
36
|
+
export type { ColorizrOptions } from '~/colorizr';
|
|
37
|
+
export type { FormatCSSOptions } from '~/format-css';
|
|
38
|
+
export type { PaletteOptions } from '~/palette';
|
|
39
|
+
export type { Scheme, SchemeOptions } from '~/scheme';
|
|
40
|
+
export type { Swatch, SwatchOptions, SwatchVariant } from '~/swatch';
|
|
41
|
+
export type { TextColorOptions } from '~/text-color';
|
|
42
|
+
|
|
36
43
|
// eslint-disable-next-line unicorn/prefer-export-from
|
|
37
44
|
export default Colorizr;
|
package/src/modules/invariant.ts
CHANGED
|
@@ -3,7 +3,6 @@ export function invariant(condition: boolean, message: string): asserts conditio
|
|
|
3
3
|
return;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
/* istanbul ignore else */
|
|
7
6
|
if (process.env.NODE_ENV !== 'production') {
|
|
8
7
|
if (message === undefined) {
|
|
9
8
|
throw new Error('invariant requires an error message argument');
|
package/src/palette.ts
CHANGED
|
@@ -11,14 +11,36 @@ import rotate from '~/rotate';
|
|
|
11
11
|
import { ColorType, HEX } from '~/types';
|
|
12
12
|
|
|
13
13
|
export interface PaletteOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Output color format.
|
|
16
|
+
*
|
|
17
|
+
* If not specified, the output will use the same format as the input color.
|
|
18
|
+
*/
|
|
14
19
|
format?: ColorType;
|
|
20
|
+
/**
|
|
21
|
+
* Adjusts the lightness of the base color before generating the palette.
|
|
22
|
+
*
|
|
23
|
+
* Value should be between 0 and 100.
|
|
24
|
+
*/
|
|
15
25
|
lightness?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Adjusts the saturation of the base color before generating the palette.
|
|
28
|
+
*
|
|
29
|
+
* Value should be between 0 and 100.
|
|
30
|
+
*/
|
|
16
31
|
saturation?: number;
|
|
17
32
|
/**
|
|
18
|
-
* The number of colors to generate
|
|
33
|
+
* The number of colors to generate in the palette.
|
|
34
|
+
*
|
|
35
|
+
* Minimum value is 2.
|
|
19
36
|
* @default 6
|
|
20
37
|
*/
|
|
21
38
|
size?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Generate a monochromatic palette.
|
|
41
|
+
*
|
|
42
|
+
* For more options, use the `swatch` function.
|
|
43
|
+
*/
|
|
22
44
|
type?: 'monochromatic';
|
|
23
45
|
}
|
|
24
46
|
|
|
@@ -28,31 +50,25 @@ export default function palette(input: string, options: PaletteOptions = {}): st
|
|
|
28
50
|
|
|
29
51
|
const { format, lightness, saturation, size = 6, type } = options;
|
|
30
52
|
const hsl = parseCSS(input, 'hsl');
|
|
31
|
-
const output: string[] = [];
|
|
32
53
|
const colorFormat = isHex(input) || isNamedColor(input) ? 'hex' : extractColorParts(input).model;
|
|
33
54
|
|
|
34
|
-
|
|
35
|
-
case 'monochromatic': {
|
|
36
|
-
const step = 80 / size;
|
|
55
|
+
const output: string[] = [];
|
|
37
56
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
57
|
+
if (type === 'monochromatic') {
|
|
58
|
+
const step = 80 / size;
|
|
41
59
|
|
|
42
|
-
|
|
60
|
+
for (let index = size; index > 0; index--) {
|
|
61
|
+
output.push(hsl2hex({ ...hsl, l: step * index }));
|
|
43
62
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
output.push(hsl2hex({ ...hsl, l: lightness ?? hsl.l, s: saturation ?? hsl.s }));
|
|
63
|
+
} else {
|
|
64
|
+
const step = 360 / size;
|
|
48
65
|
|
|
49
|
-
|
|
50
|
-
const color = rotate(input, hsl.h + step * index, 'hex') as HEX;
|
|
66
|
+
output.push(hsl2hex({ ...hsl, l: lightness ?? hsl.l, s: saturation ?? hsl.s }));
|
|
51
67
|
|
|
52
|
-
|
|
53
|
-
|
|
68
|
+
for (let index = 1; index < size; index++) {
|
|
69
|
+
const color = rotate(input, hsl.h + step * index, 'hex') as HEX;
|
|
54
70
|
|
|
55
|
-
|
|
71
|
+
output.push(hsl2hex({ ...hex2hsl(color), l: lightness ?? hsl.l, s: saturation ?? hsl.s }));
|
|
56
72
|
}
|
|
57
73
|
}
|
|
58
74
|
|
package/src/scheme.ts
CHANGED
|
@@ -18,6 +18,11 @@ export type Scheme =
|
|
|
18
18
|
| 'triadic';
|
|
19
19
|
|
|
20
20
|
export interface SchemeOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Output color format.
|
|
23
|
+
*
|
|
24
|
+
* If not specified, the output will use the same format as the input color.
|
|
25
|
+
*/
|
|
21
26
|
format?: ColorType;
|
|
22
27
|
/**
|
|
23
28
|
* The type of scheme to generate.
|
package/src/swatch.ts
CHANGED
|
@@ -9,47 +9,81 @@ import oklch2rgb from '~/converters/oklch2rgb';
|
|
|
9
9
|
import rgb2hex from '~/converters/rgb2hex';
|
|
10
10
|
import extractColorParts from '~/extract-color-parts';
|
|
11
11
|
import parseCSS from '~/parse-css';
|
|
12
|
-
import { ColorType, HEX, LCH } from '~/types';
|
|
12
|
+
import { ColorTokens, ColorType, HEX, LCH } from '~/types';
|
|
13
13
|
|
|
14
|
-
type
|
|
15
|
-
|
|
16
|
-
type Swatch = {
|
|
14
|
+
export type Swatch = {
|
|
17
15
|
[key in ColorTokens]: string;
|
|
18
16
|
};
|
|
19
17
|
|
|
18
|
+
export type SwatchVariant = 'deep' | 'neutral' | 'pastel' | 'subtle' | 'vibrant';
|
|
19
|
+
|
|
20
20
|
export interface SwatchOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Output color format.
|
|
23
|
+
*
|
|
24
|
+
* If not specified, the output will use the same format as the input color.
|
|
25
|
+
*/
|
|
21
26
|
format?: ColorType;
|
|
22
27
|
/**
|
|
23
|
-
* The
|
|
24
|
-
*
|
|
28
|
+
* The mode of the swatch.
|
|
29
|
+
* - 'light': Focuses on lighter tones starting from a higher lightness.
|
|
30
|
+
* - 'dark': Focuses on darker tones starting from a lower lightness.
|
|
31
|
+
*
|
|
32
|
+
* If omitted, a balanced palette is generated.
|
|
33
|
+
*/
|
|
34
|
+
mode?: 'light' | 'dark';
|
|
35
|
+
/**
|
|
36
|
+
* Generate a monochromatic swatch.
|
|
37
|
+
*
|
|
38
|
+
* Disable chroma adjustments for all shades.
|
|
39
|
+
* @default false
|
|
40
|
+
*/
|
|
41
|
+
monochromatic?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Determines the scale type for the swatch.
|
|
44
|
+
* - 'linear': Shades are distributed with equal lightness intervals.
|
|
45
|
+
* - 'dynamic': Shades are distributed adaptively based on the input color.
|
|
25
46
|
* @default 'dynamic'
|
|
26
47
|
*/
|
|
27
48
|
scale?: 'dynamic' | 'linear';
|
|
49
|
+
/**
|
|
50
|
+
* The variant of the swatch.
|
|
51
|
+
* - 'deep': Generates rich and bold tones with significantly reduced lightness.
|
|
52
|
+
* - 'neutral': Generates muted tones by reducing chroma.
|
|
53
|
+
* - 'pastel': Produces soft and airy tones with significant chroma reduction.
|
|
54
|
+
* - 'subtle': Creates extremely desaturated tones, close to grayscale.
|
|
55
|
+
* - 'vibrant': Enhances chroma for bold and striking tones.
|
|
56
|
+
*/
|
|
57
|
+
variant?: SwatchVariant;
|
|
28
58
|
}
|
|
29
59
|
|
|
30
|
-
const MIN_LIGHTNESS =
|
|
31
|
-
const MAX_LIGHTNESS =
|
|
60
|
+
const MIN_LIGHTNESS = 5;
|
|
61
|
+
const MAX_LIGHTNESS = 95;
|
|
32
62
|
|
|
33
63
|
/**
|
|
34
64
|
* Generate a shade of a color based its lightness tuning factor
|
|
35
65
|
*/
|
|
36
|
-
function shadeColorDynamic(input: LCH, lightnessTuningFactor: number,
|
|
66
|
+
function shadeColorDynamic(input: LCH, lightnessTuningFactor: number, chromaFactor = 0): HEX {
|
|
37
67
|
if (lightnessTuningFactor === 0) {
|
|
38
|
-
|
|
68
|
+
const { l } = input;
|
|
69
|
+
|
|
70
|
+
return rgb2hex(oklch2rgb({ ...input, l: l / 100 }));
|
|
39
71
|
}
|
|
40
72
|
|
|
41
73
|
// Convert back to RGB and make sure it's within the sRGB gamut
|
|
42
|
-
return shadeColor(input, input.l + lightnessTuningFactor,
|
|
74
|
+
return shadeColor(input, input.l + lightnessTuningFactor, chromaFactor);
|
|
43
75
|
}
|
|
44
76
|
|
|
45
77
|
/**
|
|
46
78
|
* Generate a shade of a color based its lightness tuning factor
|
|
47
79
|
*/
|
|
48
|
-
function shadeColor(input: LCH, lightness: number,
|
|
80
|
+
function shadeColor(input: LCH, lightness: number, chromaFactor = 0): HEX {
|
|
49
81
|
const { c, h } = input;
|
|
50
82
|
|
|
83
|
+
const adjustedChroma = clamp(c + chromaFactor, 0, 0.4);
|
|
84
|
+
|
|
51
85
|
// Convert back to RGB and make sure it's within the sRGB gamut
|
|
52
|
-
return oklch2hex({ l: lightness / 100, c:
|
|
86
|
+
return oklch2hex({ l: lightness / 100, c: adjustedChroma, h });
|
|
53
87
|
}
|
|
54
88
|
|
|
55
89
|
/**
|
|
@@ -57,45 +91,68 @@ function shadeColor(input: LCH, lightness: number, chromaTuningFactor = 0): HEX
|
|
|
57
91
|
*/
|
|
58
92
|
export default function swatch(input: string, options: SwatchOptions = {}): Swatch {
|
|
59
93
|
invariant(isString(input), MESSAGES.inputString);
|
|
60
|
-
const { format, scale = 'dynamic' } = options;
|
|
94
|
+
const { format, monochromatic = false, scale = 'dynamic', mode, variant = 'base' } = options;
|
|
61
95
|
|
|
62
96
|
const lch = parseCSS(input, 'oklch');
|
|
97
|
+
const chromaScale = {
|
|
98
|
+
base: 1,
|
|
99
|
+
deep: 0.8,
|
|
100
|
+
neutral: 0.5,
|
|
101
|
+
pastel: 0.3,
|
|
102
|
+
subtle: 0.2,
|
|
103
|
+
vibrant: 1.25,
|
|
104
|
+
}[variant];
|
|
63
105
|
|
|
64
106
|
lch.l = 50;
|
|
107
|
+
lch.c *= chromaScale;
|
|
108
|
+
|
|
109
|
+
if (variant === 'deep') {
|
|
110
|
+
lch.l *= 0.7;
|
|
111
|
+
}
|
|
65
112
|
|
|
66
113
|
const colorFormat = isHex(input) || isNamedColor(input) ? 'hex' : extractColorParts(input).model;
|
|
67
114
|
|
|
68
115
|
const currentLightness = lch.l;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
116
|
+
let lightSteps = 5;
|
|
117
|
+
let darkSteps = 8;
|
|
118
|
+
|
|
119
|
+
if (mode) {
|
|
120
|
+
lightSteps *= mode === 'light' ? 0.75 : 1.25;
|
|
121
|
+
darkSteps *= mode === 'light' ? 1.25 : 0.75;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const lightStepSize = (MAX_LIGHTNESS - currentLightness) / lightSteps;
|
|
125
|
+
const darkStepSize = (-1 * (currentLightness - MIN_LIGHTNESS)) / darkSteps;
|
|
126
|
+
|
|
127
|
+
const getChromaFactor = (value: number): number => {
|
|
128
|
+
return monochromatic ? 0 : value; // Disable adjustments for monochromatic swatches
|
|
129
|
+
};
|
|
73
130
|
|
|
74
131
|
const output: Swatch =
|
|
75
132
|
scale === 'linear'
|
|
76
133
|
? {
|
|
77
|
-
50: shadeColor(lch, 95, -0.00375),
|
|
78
|
-
100: shadeColor(lch, 90, -0.00375),
|
|
79
|
-
200: shadeColor(lch, 80, -0.00375),
|
|
80
|
-
300: shadeColor(lch, 70, -0.00375),
|
|
81
|
-
400: shadeColor(lch, 60, -0.00375),
|
|
134
|
+
50: shadeColor(lch, 95, getChromaFactor(-0.00375)),
|
|
135
|
+
100: shadeColor(lch, 90, getChromaFactor(-0.00375)),
|
|
136
|
+
200: shadeColor(lch, 80, getChromaFactor(-0.00375)),
|
|
137
|
+
300: shadeColor(lch, 70, getChromaFactor(-0.00375)),
|
|
138
|
+
400: shadeColor(lch, 60, getChromaFactor(-0.00375)),
|
|
82
139
|
500: shadeColor(lch, 50),
|
|
83
|
-
600: shadeColor(lch, 40, 0.025),
|
|
84
|
-
700: shadeColor(lch, 30, 0.05),
|
|
85
|
-
800: shadeColor(lch, 20, 0.075),
|
|
86
|
-
900: shadeColor(lch, 10, 0.1),
|
|
140
|
+
600: shadeColor(lch, 40, getChromaFactor(0.025)),
|
|
141
|
+
700: shadeColor(lch, 30, getChromaFactor(0.05)),
|
|
142
|
+
800: shadeColor(lch, 20, getChromaFactor(0.075)),
|
|
143
|
+
900: shadeColor(lch, 10, getChromaFactor(0.1)),
|
|
87
144
|
}
|
|
88
145
|
: {
|
|
89
|
-
50: shadeColorDynamic(lch, 5 *
|
|
90
|
-
100: shadeColorDynamic(lch, 4 *
|
|
91
|
-
200: shadeColorDynamic(lch, 3 *
|
|
92
|
-
300: shadeColorDynamic(lch, 2 *
|
|
93
|
-
400: shadeColorDynamic(lch,
|
|
146
|
+
50: shadeColorDynamic(lch, 5 * lightStepSize, getChromaFactor(-0.00375)),
|
|
147
|
+
100: shadeColorDynamic(lch, 4 * lightStepSize, getChromaFactor(-0.00375)),
|
|
148
|
+
200: shadeColorDynamic(lch, 3 * lightStepSize, getChromaFactor(-0.00375)),
|
|
149
|
+
300: shadeColorDynamic(lch, 2 * lightStepSize, getChromaFactor(-0.00375)),
|
|
150
|
+
400: shadeColorDynamic(lch, lightStepSize, getChromaFactor(-0.00375)),
|
|
94
151
|
500: shadeColorDynamic(lch, 0),
|
|
95
|
-
600: shadeColorDynamic(lch, 1.6 *
|
|
96
|
-
700: shadeColorDynamic(lch,
|
|
97
|
-
800: shadeColorDynamic(lch,
|
|
98
|
-
900: shadeColorDynamic(lch, 4 *
|
|
152
|
+
600: shadeColorDynamic(lch, 1.6 * darkStepSize, getChromaFactor(0.025)),
|
|
153
|
+
700: shadeColorDynamic(lch, 3.2 * darkStepSize, getChromaFactor(0.05)),
|
|
154
|
+
800: shadeColorDynamic(lch, 4.8 * darkStepSize, getChromaFactor(0.075)),
|
|
155
|
+
900: shadeColorDynamic(lch, 6.4 * darkStepSize, getChromaFactor(0.1)),
|
|
99
156
|
};
|
|
100
157
|
|
|
101
158
|
return Object.entries(output).reduce((acc, [key, value]) => {
|
package/src/text-color.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { isString } from '~/modules/validators';
|
|
|
5
5
|
import hex2rgb from '~/converters/hex2rgb';
|
|
6
6
|
import parseCSS from '~/parse-css';
|
|
7
7
|
|
|
8
|
-
interface
|
|
8
|
+
export interface TextColorOptions {
|
|
9
9
|
/**
|
|
10
10
|
* The dark color to return if the input is light.
|
|
11
11
|
* @default '#000000'
|
|
@@ -18,6 +18,7 @@ interface Options {
|
|
|
18
18
|
lightColor?: string;
|
|
19
19
|
/**
|
|
20
20
|
* The threshold to determine if the color is light or dark.
|
|
21
|
+
*
|
|
21
22
|
* A number between 0 and 255.
|
|
22
23
|
* @default 128
|
|
23
24
|
*/
|
|
@@ -27,14 +28,23 @@ interface Options {
|
|
|
27
28
|
/**
|
|
28
29
|
* Get the contrasted color for a given hex.
|
|
29
30
|
*/
|
|
30
|
-
export default function textColor(input: string, options:
|
|
31
|
+
export default function textColor(input: string, options: TextColorOptions = {}): string {
|
|
31
32
|
const { darkColor = '#000000', lightColor = '#ffffff', threshold = 128 } = options;
|
|
32
33
|
|
|
33
34
|
invariant(isString(input), MESSAGES.inputString);
|
|
34
35
|
invariant(threshold >= 0 && threshold <= 255, MESSAGES.threshold);
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
try {
|
|
38
|
+
const { r, g, b } = hex2rgb(parseCSS(input, 'hex'));
|
|
39
|
+
const yiq = (r * 299 + g * 587 + b * 114) / 1000;
|
|
38
40
|
|
|
39
|
-
|
|
41
|
+
return yiq >= threshold ? darkColor : lightColor;
|
|
42
|
+
} catch (error) {
|
|
43
|
+
/* eslint-disable no-console */
|
|
44
|
+
console.warn(`Invalid color input: ${input}`);
|
|
45
|
+
console.warn(error);
|
|
46
|
+
/* eslint-enable no-console */
|
|
47
|
+
|
|
48
|
+
return darkColor; // Default to dark color in case of error
|
|
49
|
+
}
|
|
40
50
|
}
|
package/src/types/index.ts
CHANGED
|
@@ -14,7 +14,8 @@ export type ColorModelKeys<TModel extends ColorModelKey> = TModel extends 'hsl'
|
|
|
14
14
|
|
|
15
15
|
export type ColorKeysTuple = [string, string, string];
|
|
16
16
|
export type ColorTuple = [number, number, number];
|
|
17
|
-
export type
|
|
17
|
+
export type ColorTokens = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
|
|
18
|
+
|
|
18
19
|
export interface Colors {
|
|
19
20
|
alpha: Alpha;
|
|
20
21
|
hex: HEX;
|
|
@@ -25,6 +26,8 @@ export interface Colors {
|
|
|
25
26
|
type: ColorType;
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
export type ConverterParameters<TModel extends ColorModel> = TModel | ColorTuple;
|
|
30
|
+
|
|
28
31
|
/* A number between 0 and 1 */
|
|
29
32
|
export type Alpha = number;
|
|
30
33
|
|