vinh-colors-utils 3.1.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 +83 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/lib/colors.d.ts +56 -0
- package/dist/lib/colors.d.ts.map +1 -0
- package/dist/lib/colors.js +154 -0
- package/package.json +29 -0
package/README.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# @org/colors
|
|
2
|
+
|
|
3
|
+
Color conversion and manipulation utilities for TypeScript applications.
|
|
4
|
+
|
|
5
|
+
## ๐ฆ Package Information
|
|
6
|
+
|
|
7
|
+
- **Version**: 0.0.1
|
|
8
|
+
- **Publishable**: โ
Yes
|
|
9
|
+
- **Tag**: `scope:colors`
|
|
10
|
+
- **Module Boundaries**: Can only import from `scope:shared` packages
|
|
11
|
+
|
|
12
|
+
## ๐ Features
|
|
13
|
+
|
|
14
|
+
This package provides comprehensive color utilities:
|
|
15
|
+
|
|
16
|
+
- **hexToRgb** - Convert hex color codes to RGB values
|
|
17
|
+
- **rgbToHex** - Convert RGB values to hex color codes
|
|
18
|
+
- **lighten** - Make colors lighter by a percentage
|
|
19
|
+
- **darken** - Make colors darker by a percentage
|
|
20
|
+
|
|
21
|
+
## ๐ Usage Examples
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { hexToRgb, rgbToHex, lighten, darken } from '@org/colors';
|
|
25
|
+
|
|
26
|
+
// Convert hex to RGB
|
|
27
|
+
hexToRgb('#FF5733'); // { r: 255, g: 87, b: 51 }
|
|
28
|
+
hexToRgb('#000'); // { r: 0, g: 0, b: 0 }
|
|
29
|
+
|
|
30
|
+
// Convert RGB to hex
|
|
31
|
+
rgbToHex(255, 87, 51); // '#FF5733'
|
|
32
|
+
rgbToHex(0, 0, 0); // '#000000'
|
|
33
|
+
|
|
34
|
+
// Lighten colors
|
|
35
|
+
lighten('#FF5733', 20); // Returns a 20% lighter shade
|
|
36
|
+
lighten('#000000', 50); // Returns a 50% lighter shade (gray)
|
|
37
|
+
|
|
38
|
+
// Darken colors
|
|
39
|
+
darken('#FF5733', 20); // Returns a 20% darker shade
|
|
40
|
+
darken('#FFFFFF', 30); // Returns a 30% darker shade
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## ๐งช Testing
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Run tests for this package
|
|
47
|
+
nx test colors
|
|
48
|
+
|
|
49
|
+
# Run tests in watch mode
|
|
50
|
+
nx test colors --watch
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## ๐๏ธ Building
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Build the package
|
|
57
|
+
nx build colors
|
|
58
|
+
|
|
59
|
+
# The build output will be in dist/packages/colors
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## ๐ Available Commands
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
nx build colors # Build the package
|
|
66
|
+
nx test colors # Run tests
|
|
67
|
+
nx lint colors # Lint the package
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## ๐ Module Boundaries
|
|
71
|
+
|
|
72
|
+
This package has the tag `scope:colors` and can only import from:
|
|
73
|
+
- `@org/utils` (tagged with `scope:shared`)
|
|
74
|
+
|
|
75
|
+
Attempting to import from `@org/strings` or `@org/async` will result in a linting error due to module boundary constraints.
|
|
76
|
+
|
|
77
|
+
## ๐จ Color Format Support
|
|
78
|
+
|
|
79
|
+
The utilities support various color formats:
|
|
80
|
+
- **Hex**: `#RGB`, `#RRGGBB`
|
|
81
|
+
- **RGB**: Object with `r`, `g`, `b` properties (0-255)
|
|
82
|
+
|
|
83
|
+
All functions include proper validation and error handling for invalid color formats.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lib/colors.js';
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RGB color representation
|
|
3
|
+
*/
|
|
4
|
+
export interface RgbColor {
|
|
5
|
+
r: number;
|
|
6
|
+
g: number;
|
|
7
|
+
b: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* HSL color representation
|
|
11
|
+
*/
|
|
12
|
+
export interface HslColor {
|
|
13
|
+
h: number;
|
|
14
|
+
s: number;
|
|
15
|
+
l: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Convert hex color to RGB
|
|
19
|
+
*/
|
|
20
|
+
export declare function hexToRgb(hex: string): RgbColor;
|
|
21
|
+
/**
|
|
22
|
+
* Convert RGB to hex color
|
|
23
|
+
*/
|
|
24
|
+
export declare function rgbToHex(r: number, g: number, b: number): string;
|
|
25
|
+
export declare function rgbToHex(rgb: RgbColor): string;
|
|
26
|
+
/**
|
|
27
|
+
* Darken a color by percentage
|
|
28
|
+
*/
|
|
29
|
+
export declare function darken(color: string, percent: number): string;
|
|
30
|
+
/**
|
|
31
|
+
* Lighten a color by percentage
|
|
32
|
+
*/
|
|
33
|
+
export declare function lighten(color: string, percent: number): string;
|
|
34
|
+
/**
|
|
35
|
+
* Validate hex color code
|
|
36
|
+
*/
|
|
37
|
+
export declare function isValidHex(color: unknown): color is string;
|
|
38
|
+
/**
|
|
39
|
+
* Validate RGB values
|
|
40
|
+
*/
|
|
41
|
+
export declare function isValidRgb(r: number, g: number, b: number): boolean;
|
|
42
|
+
export declare function isValidRgb(rgb: Partial<RgbColor>): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Get contrast ratio between two colors
|
|
45
|
+
*/
|
|
46
|
+
export declare function getContrastRatio(color1: string, color2: string): number;
|
|
47
|
+
/**
|
|
48
|
+
* Generate a random hex color
|
|
49
|
+
*/
|
|
50
|
+
export declare function randomHex(): string;
|
|
51
|
+
/**
|
|
52
|
+
* Convert RGB to HSL
|
|
53
|
+
*/
|
|
54
|
+
export declare function rgbToHsl(r: number, g: number, b: number): HslColor;
|
|
55
|
+
export declare function rgbToHsl(rgb: RgbColor): HslColor;
|
|
56
|
+
//# sourceMappingURL=colors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../src/lib/colors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,QAAQ;IACrB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACrB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAoB9C;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;AAClE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAAC;AA4BhD;;GAEG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAgB7D;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAgB9D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAG1D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;AACrE,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC;AAoB5D;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAuBvE;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAGlC;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;AACpE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,QAAQ,GAAG,QAAQ,CAAC"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert hex color to RGB
|
|
3
|
+
*/
|
|
4
|
+
export function hexToRgb(hex) {
|
|
5
|
+
if (!isValidHex(hex)) {
|
|
6
|
+
throw new Error('Invalid hex color');
|
|
7
|
+
}
|
|
8
|
+
// Remove # if present
|
|
9
|
+
const cleanHex = hex.replace('#', '');
|
|
10
|
+
// Handle 3-digit hex
|
|
11
|
+
const fullHex = cleanHex.length === 3
|
|
12
|
+
? cleanHex.split('').map(char => char + char).join('')
|
|
13
|
+
: cleanHex;
|
|
14
|
+
const bigint = parseInt(fullHex, 16);
|
|
15
|
+
return {
|
|
16
|
+
r: (bigint >> 16) & 255,
|
|
17
|
+
g: (bigint >> 8) & 255,
|
|
18
|
+
b: bigint & 255
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function rgbToHex(rOrRgb, g, b) {
|
|
22
|
+
let r;
|
|
23
|
+
if (typeof rOrRgb === 'object') {
|
|
24
|
+
({ r, g, b } = rOrRgb);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
r = rOrRgb;
|
|
28
|
+
g = g;
|
|
29
|
+
b = b;
|
|
30
|
+
}
|
|
31
|
+
if (!isValidRgb(r, g, b)) {
|
|
32
|
+
throw new Error('Invalid RGB values. Must be between 0-255');
|
|
33
|
+
}
|
|
34
|
+
const toHex = (n) => {
|
|
35
|
+
const hex = n.toString(16);
|
|
36
|
+
return hex.length === 1 ? '0' + hex : hex;
|
|
37
|
+
};
|
|
38
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Darken a color by percentage
|
|
42
|
+
*/
|
|
43
|
+
export function darken(color, percent) {
|
|
44
|
+
if (!isValidHex(color)) {
|
|
45
|
+
throw new Error('Invalid hex color');
|
|
46
|
+
}
|
|
47
|
+
if (percent < 0 || percent > 100) {
|
|
48
|
+
throw new Error('Percent must be between 0 and 100');
|
|
49
|
+
}
|
|
50
|
+
const rgb = hexToRgb(color);
|
|
51
|
+
const factor = 1 - (percent / 100);
|
|
52
|
+
return rgbToHex(Math.round(rgb.r * factor), Math.round(rgb.g * factor), Math.round(rgb.b * factor));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Lighten a color by percentage
|
|
56
|
+
*/
|
|
57
|
+
export function lighten(color, percent) {
|
|
58
|
+
if (!isValidHex(color)) {
|
|
59
|
+
throw new Error('Invalid hex color');
|
|
60
|
+
}
|
|
61
|
+
if (percent < 0 || percent > 100) {
|
|
62
|
+
throw new Error('Percent must be between 0 and 100');
|
|
63
|
+
}
|
|
64
|
+
const rgb = hexToRgb(color);
|
|
65
|
+
const factor = percent / 100;
|
|
66
|
+
return rgbToHex(Math.round(rgb.r + (255 - rgb.r) * factor), Math.round(rgb.g + (255 - rgb.g) * factor), Math.round(rgb.b + (255 - rgb.b) * factor));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Validate hex color code
|
|
70
|
+
*/
|
|
71
|
+
export function isValidHex(color) {
|
|
72
|
+
if (typeof color !== 'string')
|
|
73
|
+
return false;
|
|
74
|
+
return /^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(color);
|
|
75
|
+
}
|
|
76
|
+
export function isValidRgb(rOrRgb, g, b) {
|
|
77
|
+
let r;
|
|
78
|
+
if (typeof rOrRgb === 'object') {
|
|
79
|
+
({ r, g, b } = rOrRgb);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
r = rOrRgb;
|
|
83
|
+
}
|
|
84
|
+
const isValid = (n) => n !== undefined && Number.isInteger(n) && n >= 0 && n <= 255;
|
|
85
|
+
return isValid(r) && isValid(g) && isValid(b);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Get contrast ratio between two colors
|
|
89
|
+
*/
|
|
90
|
+
export function getContrastRatio(color1, color2) {
|
|
91
|
+
const getLuminance = (rgb) => {
|
|
92
|
+
const toLinear = (val) => {
|
|
93
|
+
const normalized = val / 255;
|
|
94
|
+
return normalized <= 0.03928
|
|
95
|
+
? normalized / 12.92
|
|
96
|
+
: Math.pow((normalized + 0.055) / 1.055, 2.4);
|
|
97
|
+
};
|
|
98
|
+
const r = toLinear(rgb.r);
|
|
99
|
+
const g = toLinear(rgb.g);
|
|
100
|
+
const b = toLinear(rgb.b);
|
|
101
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
102
|
+
};
|
|
103
|
+
const lum1 = getLuminance(hexToRgb(color1));
|
|
104
|
+
const lum2 = getLuminance(hexToRgb(color2));
|
|
105
|
+
const lighter = Math.max(lum1, lum2);
|
|
106
|
+
const darker = Math.min(lum1, lum2);
|
|
107
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Generate a random hex color
|
|
111
|
+
*/
|
|
112
|
+
export function randomHex() {
|
|
113
|
+
const random = () => Math.floor(Math.random() * 256);
|
|
114
|
+
return rgbToHex(random(), random(), random());
|
|
115
|
+
}
|
|
116
|
+
export function rgbToHsl(rOrRgb, g, b) {
|
|
117
|
+
let r;
|
|
118
|
+
if (typeof rOrRgb === 'object') {
|
|
119
|
+
({ r, g, b } = rOrRgb);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
r = rOrRgb;
|
|
123
|
+
g = g;
|
|
124
|
+
b = b;
|
|
125
|
+
}
|
|
126
|
+
r /= 255;
|
|
127
|
+
g /= 255;
|
|
128
|
+
b /= 255;
|
|
129
|
+
const max = Math.max(r, g, b);
|
|
130
|
+
const min = Math.min(r, g, b);
|
|
131
|
+
let h = 0;
|
|
132
|
+
let s = 0;
|
|
133
|
+
const l = (max + min) / 2;
|
|
134
|
+
if (max !== min) {
|
|
135
|
+
const d = max - min;
|
|
136
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
137
|
+
switch (max) {
|
|
138
|
+
case r:
|
|
139
|
+
h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
|
|
140
|
+
break;
|
|
141
|
+
case g:
|
|
142
|
+
h = ((b - r) / d + 2) / 6;
|
|
143
|
+
break;
|
|
144
|
+
case b:
|
|
145
|
+
h = ((r - g) / d + 4) / 6;
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
h: Math.round(h * 360),
|
|
151
|
+
s: Math.round(s * 100),
|
|
152
|
+
l: Math.round(l * 100)
|
|
153
|
+
};
|
|
154
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vinh-colors-utils",
|
|
3
|
+
"version": "3.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
"./package.json": "./package.json",
|
|
10
|
+
".": {
|
|
11
|
+
"@org/source": "./src/index.ts",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"!**/*.tsbuildinfo"
|
|
20
|
+
],
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"tslib": "^2.3.0"
|
|
23
|
+
},
|
|
24
|
+
"nx": {
|
|
25
|
+
"tags": [
|
|
26
|
+
"scope:colors"
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
}
|