@etsoo/shared 1.1.13 → 1.1.16
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 +17 -0
- package/__tests__/EColor.ts +18 -0
- package/lib/cjs/ExtendUtils.js +3 -2
- package/lib/cjs/index.d.ts +2 -1
- package/lib/cjs/index.js +7 -2
- package/lib/cjs/types/DelayedExecutorType.d.ts +2 -1
- package/lib/cjs/types/EColor.d.ts +105 -0
- package/lib/cjs/types/EColor.js +265 -0
- package/lib/mjs/ExtendUtils.js +3 -2
- package/lib/mjs/index.d.ts +2 -1
- package/lib/mjs/index.js +2 -1
- package/lib/mjs/types/DelayedExecutorType.d.ts +2 -1
- package/lib/mjs/types/EColor.d.ts +105 -0
- package/lib/mjs/types/EColor.js +261 -0
- package/package.json +4 -4
- package/src/ExtendUtils.ts +3 -2
- package/src/index.ts +2 -1
- package/src/types/DelayedExecutorType.ts +2 -1
- package/src/types/EColor.ts +324 -0
package/README.md
CHANGED
|
@@ -18,6 +18,22 @@ $ yarn add @etsoo/shared
|
|
|
18
18
|
## storage
|
|
19
19
|
Storage interface and browser storage implementation
|
|
20
20
|
|
|
21
|
+
## EColor
|
|
22
|
+
Etsoo implmented Color
|
|
23
|
+
|
|
24
|
+
|Name|Description|
|
|
25
|
+
|---:|---|
|
|
26
|
+
|static getColors|Get HEX or RGB colors|
|
|
27
|
+
|static getEColors|Get EColors|
|
|
28
|
+
|static parse|Parse HTML color to EColor|
|
|
29
|
+
|clone|Clone color with adjustments|
|
|
30
|
+
|getContrastRatio|Get contrast ratio, a value between 0 and 1|
|
|
31
|
+
|getDeltaValue|Get Delta value (perceptible by human eyes)|
|
|
32
|
+
|getLuminance|Get luminance|
|
|
33
|
+
|toHEXColor|To HEX color string|
|
|
34
|
+
|toLabValue|To Lab value|
|
|
35
|
+
|toRGBColor|To RGB color string|
|
|
36
|
+
|
|
21
37
|
## Keyboard
|
|
22
38
|
Keyboard keys and codes
|
|
23
39
|
|
|
@@ -122,6 +138,7 @@ Extend current class/object functioning
|
|
|
122
138
|
|Name|Description|
|
|
123
139
|
|---:|---|
|
|
124
140
|
|applyMixins|Apply mixins to current class|
|
|
141
|
+
|delayedExecutor|Create delayed executor|
|
|
125
142
|
|promiseHandler|Promise handler to catch error|
|
|
126
143
|
|sleep|Delay promise|
|
|
127
144
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { EColor } from '../src/types/EColor';
|
|
2
|
+
|
|
3
|
+
test('Tests for parse', () => {
|
|
4
|
+
// Arrange & act
|
|
5
|
+
const colorShort = EColor.parse('#000');
|
|
6
|
+
const color = EColor.parse('#e21821');
|
|
7
|
+
const colorRgb = EColor.parse('RGB(226, 24, 33)');
|
|
8
|
+
|
|
9
|
+
// Assert
|
|
10
|
+
expect(colorShort?.toRGBColor()).toBe('RGB(0, 0, 0)');
|
|
11
|
+
expect(color?.toRGBColor()).toBe('RGB(226, 24, 33)');
|
|
12
|
+
expect(colorRgb?.toHEXColor()).toBe('#e21821');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('Tests for getColors', () => {
|
|
16
|
+
const colors = EColor.getColors(undefined, 128);
|
|
17
|
+
expect(colors.length).toBe(8);
|
|
18
|
+
});
|
package/lib/cjs/ExtendUtils.js
CHANGED
|
@@ -34,14 +34,15 @@ var ExtendUtils;
|
|
|
34
34
|
return {
|
|
35
35
|
/**
|
|
36
36
|
* Call the function
|
|
37
|
+
* @param miliseconds Delayed miliseconds for this call
|
|
37
38
|
* @param args Args
|
|
38
39
|
*/
|
|
39
|
-
call(...args) {
|
|
40
|
+
call(miliseconds, ...args) {
|
|
40
41
|
this.clear();
|
|
41
42
|
seed = window.setTimeout((...args) => {
|
|
42
43
|
func(...args);
|
|
43
44
|
seed = 0;
|
|
44
|
-
}, delayMiliseconds, ...args);
|
|
45
|
+
}, miliseconds !== null && miliseconds !== void 0 ? miliseconds : delayMiliseconds, ...args);
|
|
45
46
|
},
|
|
46
47
|
/**
|
|
47
48
|
* Clear
|
package/lib/cjs/index.d.ts
CHANGED
package/lib/cjs/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -10,8 +14,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
10
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
15
|
};
|
|
12
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
__exportStar(require("./types/FormData"), exports);
|
|
14
17
|
__exportStar(require("./types/DelayedExecutorType"), exports);
|
|
18
|
+
__exportStar(require("./types/EColor"), exports);
|
|
19
|
+
__exportStar(require("./types/FormData"), exports);
|
|
15
20
|
__exportStar(require("./storage/IStorage"), exports);
|
|
16
21
|
__exportStar(require("./storage/WindowStorage"), exports);
|
|
17
22
|
__exportStar(require("./DataTypes"), exports);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
export declare type DelayedExecutorType<P extends any[]> = {
|
|
2
2
|
/**
|
|
3
3
|
* Call the function
|
|
4
|
+
* @param miliseconds Delayed miliseconds for this call
|
|
4
5
|
* @param args Args
|
|
5
6
|
*/
|
|
6
|
-
call(...args: P): void;
|
|
7
|
+
call(miliseconds?: number, ...args: P): void;
|
|
7
8
|
/**
|
|
8
9
|
* Clear
|
|
9
10
|
*/
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Etsoo implmented Color
|
|
3
|
+
*/
|
|
4
|
+
export declare class EColor {
|
|
5
|
+
readonly r: number;
|
|
6
|
+
readonly g: number;
|
|
7
|
+
readonly b: number;
|
|
8
|
+
readonly alpha?: number | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Adjust value
|
|
11
|
+
* @param value Current value
|
|
12
|
+
* @param adjust Adjust value
|
|
13
|
+
* @returns Adjusted value
|
|
14
|
+
*/
|
|
15
|
+
static adjust(value: number, adjust?: number): number;
|
|
16
|
+
/**
|
|
17
|
+
* Get HEX or RGB colors
|
|
18
|
+
* @param init Initial color
|
|
19
|
+
* @param factor Increase factor
|
|
20
|
+
* @param adjustOrder Adjust order to increase difference
|
|
21
|
+
* @param hex to HEX or not
|
|
22
|
+
* @returns Result
|
|
23
|
+
*/
|
|
24
|
+
static getColors(init?: string, factor?: number, adjustOrder?: boolean, hex?: boolean): string[];
|
|
25
|
+
/**
|
|
26
|
+
* Get EColors
|
|
27
|
+
* @param init Initial color
|
|
28
|
+
* @param factor Increase factor
|
|
29
|
+
* @param adjustOrder Adjust order to increase difference
|
|
30
|
+
* @returns Result
|
|
31
|
+
*/
|
|
32
|
+
static getEColors(init?: string, factor?: number, adjustOrder?: boolean): EColor[];
|
|
33
|
+
/**
|
|
34
|
+
* HEX string to integer value
|
|
35
|
+
* @param hex HEX string
|
|
36
|
+
* @returns Integer value
|
|
37
|
+
*/
|
|
38
|
+
static hexTo(hex: string): number;
|
|
39
|
+
/**
|
|
40
|
+
* Format value to 16 radix string
|
|
41
|
+
* @param num Int value
|
|
42
|
+
* @returns Result
|
|
43
|
+
*/
|
|
44
|
+
static toHex(num: number): string;
|
|
45
|
+
/**
|
|
46
|
+
* Parse HTML color to EColor
|
|
47
|
+
* @param htmlColor HTML color
|
|
48
|
+
* @returns EColor
|
|
49
|
+
*/
|
|
50
|
+
static parse(htmlColor?: string | null): EColor | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Constructor
|
|
53
|
+
* @param r Reg
|
|
54
|
+
* @param g Green
|
|
55
|
+
* @param b Blue
|
|
56
|
+
* @param alpha Alpha
|
|
57
|
+
*/
|
|
58
|
+
constructor(r: number, g: number, b: number, alpha?: number | undefined);
|
|
59
|
+
/**
|
|
60
|
+
* Clone color with adjustments
|
|
61
|
+
* @param adjustR Adjust R value
|
|
62
|
+
* @param adjustG Adjust G value
|
|
63
|
+
* @param adjustB Adjust B value
|
|
64
|
+
* @param alpha New alpha value
|
|
65
|
+
*/
|
|
66
|
+
clone(adjustR?: number, adjustG?: number, adjustB?: number, alpha?: number): EColor | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Get contrast ratio, a value between 0 and 1
|
|
69
|
+
* @param color Contrast color
|
|
70
|
+
*/
|
|
71
|
+
getContrastRatio(color: EColor): number;
|
|
72
|
+
/**
|
|
73
|
+
* Get Delta value (perceptible by human eyes)
|
|
74
|
+
* <= 1, Not perceptible by human eyes
|
|
75
|
+
* 1 - 2, Perceptible through close observation
|
|
76
|
+
* 2 - 10, Perceptible at a glance
|
|
77
|
+
* 11 - 49, Colors are more similar than opposite
|
|
78
|
+
* 100+, Colors are exact opposite
|
|
79
|
+
* @param color Contrast color
|
|
80
|
+
* @returns Value
|
|
81
|
+
*/
|
|
82
|
+
getDeltaValue(color: EColor): number;
|
|
83
|
+
/**
|
|
84
|
+
* Get luminance
|
|
85
|
+
* Darker one has higher luminance
|
|
86
|
+
* https://dev.to/alvaromontoro/building-your-own-color-contrast-checker-4j7o
|
|
87
|
+
*/
|
|
88
|
+
getLuminance(): number;
|
|
89
|
+
/**
|
|
90
|
+
* To HEX color string
|
|
91
|
+
* @returns HEX color string
|
|
92
|
+
*/
|
|
93
|
+
toHEXColor(): string;
|
|
94
|
+
/**
|
|
95
|
+
* To Lab value
|
|
96
|
+
* @returns Lab value
|
|
97
|
+
*/
|
|
98
|
+
toLabValue(): [number, number, number];
|
|
99
|
+
/**
|
|
100
|
+
* To RGB color string
|
|
101
|
+
* @param includeAlpha Include alpha or not
|
|
102
|
+
* @returns RGB color string
|
|
103
|
+
*/
|
|
104
|
+
toRGBColor(includeAlpha?: boolean): string;
|
|
105
|
+
}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EColor = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Etsoo implmented Color
|
|
6
|
+
*/
|
|
7
|
+
class EColor {
|
|
8
|
+
/**
|
|
9
|
+
* Constructor
|
|
10
|
+
* @param r Reg
|
|
11
|
+
* @param g Green
|
|
12
|
+
* @param b Blue
|
|
13
|
+
* @param alpha Alpha
|
|
14
|
+
*/
|
|
15
|
+
constructor(r, g, b, alpha) {
|
|
16
|
+
this.r = r;
|
|
17
|
+
this.g = g;
|
|
18
|
+
this.b = b;
|
|
19
|
+
this.alpha = alpha;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Adjust value
|
|
23
|
+
* @param value Current value
|
|
24
|
+
* @param adjust Adjust value
|
|
25
|
+
* @returns Adjusted value
|
|
26
|
+
*/
|
|
27
|
+
static adjust(value, adjust) {
|
|
28
|
+
if (adjust == null)
|
|
29
|
+
return value;
|
|
30
|
+
value = Math.abs(value + adjust);
|
|
31
|
+
if (value > 255)
|
|
32
|
+
return value % 255;
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get HEX or RGB colors
|
|
37
|
+
* @param init Initial color
|
|
38
|
+
* @param factor Increase factor
|
|
39
|
+
* @param adjustOrder Adjust order to increase difference
|
|
40
|
+
* @param hex to HEX or not
|
|
41
|
+
* @returns Result
|
|
42
|
+
*/
|
|
43
|
+
static getColors(init = '#000', factor = 51, adjustOrder = true, hex = true) {
|
|
44
|
+
return EColor.getEColors(init, factor, adjustOrder).map((c) => hex ? c.toHEXColor() : c.toRGBColor());
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get EColors
|
|
48
|
+
* @param init Initial color
|
|
49
|
+
* @param factor Increase factor
|
|
50
|
+
* @param adjustOrder Adjust order to increase difference
|
|
51
|
+
* @returns Result
|
|
52
|
+
*/
|
|
53
|
+
static getEColors(init = '#000', factor = 51, adjustOrder = true) {
|
|
54
|
+
var _a;
|
|
55
|
+
// Init color
|
|
56
|
+
const initColor = (_a = EColor.parse(init)) !== null && _a !== void 0 ? _a : new EColor(0, 0, 0);
|
|
57
|
+
// Factors elements
|
|
58
|
+
// 51 = '00', '33', '66', '99', 'cc', 'ff'
|
|
59
|
+
const factors = [];
|
|
60
|
+
let f = 0;
|
|
61
|
+
while (f <= 255) {
|
|
62
|
+
factors.push(f);
|
|
63
|
+
f += factor;
|
|
64
|
+
}
|
|
65
|
+
// RGB loop
|
|
66
|
+
const colors = [initColor];
|
|
67
|
+
for (const r of factors) {
|
|
68
|
+
for (const g of factors) {
|
|
69
|
+
for (const b of factors) {
|
|
70
|
+
colors.push(initColor.clone(r, g, b));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Non-nullable colors
|
|
75
|
+
const nColors = colors.filter((color) => color != null);
|
|
76
|
+
// Adjust order
|
|
77
|
+
if (adjustOrder) {
|
|
78
|
+
const firstColor = nColors.shift();
|
|
79
|
+
if (firstColor) {
|
|
80
|
+
let color = firstColor;
|
|
81
|
+
const newColors = [color];
|
|
82
|
+
while (nColors.length > 0) {
|
|
83
|
+
const result = nColors.reduce((p, c, index) => {
|
|
84
|
+
const delta = color.getDeltaValue(c);
|
|
85
|
+
if (delta != null && delta > p.delta) {
|
|
86
|
+
p.delta = delta;
|
|
87
|
+
p.color = c;
|
|
88
|
+
p.index = index;
|
|
89
|
+
}
|
|
90
|
+
return p;
|
|
91
|
+
}, { delta: 0, color, index: -1 });
|
|
92
|
+
if (result.delta > 0) {
|
|
93
|
+
color = result.color;
|
|
94
|
+
newColors.push(color);
|
|
95
|
+
nColors.splice(result.index, 1);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return newColors;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return nColors;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* HEX string to integer value
|
|
105
|
+
* @param hex HEX string
|
|
106
|
+
* @returns Integer value
|
|
107
|
+
*/
|
|
108
|
+
static hexTo(hex) {
|
|
109
|
+
return parseInt(hex, 16);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Format value to 16 radix string
|
|
113
|
+
* @param num Int value
|
|
114
|
+
* @returns Result
|
|
115
|
+
*/
|
|
116
|
+
static toHex(num) {
|
|
117
|
+
return num.toString(16).padStart(2, '0');
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Parse HTML color to EColor
|
|
121
|
+
* @param htmlColor HTML color
|
|
122
|
+
* @returns EColor
|
|
123
|
+
*/
|
|
124
|
+
static parse(htmlColor) {
|
|
125
|
+
// Null
|
|
126
|
+
if (htmlColor == null)
|
|
127
|
+
return undefined;
|
|
128
|
+
htmlColor = htmlColor.toUpperCase();
|
|
129
|
+
// HEX color
|
|
130
|
+
if (htmlColor.startsWith('#')) {
|
|
131
|
+
htmlColor = htmlColor.substring(1);
|
|
132
|
+
if (htmlColor.length === 3)
|
|
133
|
+
htmlColor = Array.from(htmlColor)
|
|
134
|
+
.map((c) => c + c)
|
|
135
|
+
.join('');
|
|
136
|
+
if (htmlColor.length === 6) {
|
|
137
|
+
return new EColor(EColor.hexTo(htmlColor.substring(0, 2)), EColor.hexTo(htmlColor.substring(2, 4)), EColor.hexTo(htmlColor.substring(4, 6)));
|
|
138
|
+
}
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
// For RGB and RGBA
|
|
142
|
+
const reg = /^RGBA?\(([0-9,\s\.]+)\)$/;
|
|
143
|
+
const result = htmlColor.match(reg);
|
|
144
|
+
if (result != null && result.length == 2) {
|
|
145
|
+
const parts = result[1].split(/\s*,\s*/);
|
|
146
|
+
if (parts.length === 3 || parts.length === 4) {
|
|
147
|
+
const alpha = parts[3];
|
|
148
|
+
return new EColor(parseInt(parts[0]), parseInt(parts[1]), parseInt(parts[2]), alpha == null ? undefined : parseFloat(alpha));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Clone color with adjustments
|
|
155
|
+
* @param adjustR Adjust R value
|
|
156
|
+
* @param adjustG Adjust G value
|
|
157
|
+
* @param adjustB Adjust B value
|
|
158
|
+
* @param alpha New alpha value
|
|
159
|
+
*/
|
|
160
|
+
clone(adjustR, adjustG, adjustB, alpha) {
|
|
161
|
+
const r = EColor.adjust(this.r, adjustR);
|
|
162
|
+
const g = EColor.adjust(this.g, adjustG);
|
|
163
|
+
const b = EColor.adjust(this.b, adjustB);
|
|
164
|
+
if (r === this.r &&
|
|
165
|
+
g === this.g &&
|
|
166
|
+
b === this.b &&
|
|
167
|
+
(alpha == null || alpha === this.alpha))
|
|
168
|
+
return undefined;
|
|
169
|
+
return new EColor(r, g, b, alpha);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Get contrast ratio, a value between 0 and 1
|
|
173
|
+
* @param color Contrast color
|
|
174
|
+
*/
|
|
175
|
+
getContrastRatio(color) {
|
|
176
|
+
const lum1 = this.getLuminance();
|
|
177
|
+
const lum2 = color.getLuminance();
|
|
178
|
+
const brightest = Math.max(lum1, lum2);
|
|
179
|
+
const darkest = Math.min(lum1, lum2);
|
|
180
|
+
return (brightest + 0.05) / (darkest + 0.05);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get Delta value (perceptible by human eyes)
|
|
184
|
+
* <= 1, Not perceptible by human eyes
|
|
185
|
+
* 1 - 2, Perceptible through close observation
|
|
186
|
+
* 2 - 10, Perceptible at a glance
|
|
187
|
+
* 11 - 49, Colors are more similar than opposite
|
|
188
|
+
* 100+, Colors are exact opposite
|
|
189
|
+
* @param color Contrast color
|
|
190
|
+
* @returns Value
|
|
191
|
+
*/
|
|
192
|
+
getDeltaValue(color) {
|
|
193
|
+
const labA = this.toLabValue();
|
|
194
|
+
const labB = color.toLabValue();
|
|
195
|
+
const deltaL = labA[0] - labB[0];
|
|
196
|
+
const deltaA = labA[1] - labB[1];
|
|
197
|
+
const deltaB = labA[2] - labB[2];
|
|
198
|
+
const c1 = Math.sqrt(labA[1] * labA[1] + labA[2] * labA[2]);
|
|
199
|
+
const c2 = Math.sqrt(labB[1] * labB[1] + labB[2] * labB[2]);
|
|
200
|
+
const deltaC = c1 - c2;
|
|
201
|
+
let deltaH = deltaA * deltaA + deltaB * deltaB - deltaC * deltaC;
|
|
202
|
+
deltaH = deltaH < 0 ? 0 : Math.sqrt(deltaH);
|
|
203
|
+
const sc = 1.0 + 0.045 * c1;
|
|
204
|
+
const sh = 1.0 + 0.015 * c1;
|
|
205
|
+
const deltaLKlsl = deltaL / 1.0;
|
|
206
|
+
const deltaCkcsc = deltaC / sc;
|
|
207
|
+
const deltaHkhsh = deltaH / sh;
|
|
208
|
+
const i = deltaLKlsl * deltaLKlsl +
|
|
209
|
+
deltaCkcsc * deltaCkcsc +
|
|
210
|
+
deltaHkhsh * deltaHkhsh;
|
|
211
|
+
return i < 0 ? 0 : Math.sqrt(i);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Get luminance
|
|
215
|
+
* Darker one has higher luminance
|
|
216
|
+
* https://dev.to/alvaromontoro/building-your-own-color-contrast-checker-4j7o
|
|
217
|
+
*/
|
|
218
|
+
getLuminance() {
|
|
219
|
+
const a = [this.r, this.g, this.b].map((v) => {
|
|
220
|
+
v /= 255;
|
|
221
|
+
return v <= 0.03928
|
|
222
|
+
? v / 12.92
|
|
223
|
+
: Math.pow((v + 0.055) / 1.055, 2.4);
|
|
224
|
+
});
|
|
225
|
+
return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* To HEX color string
|
|
229
|
+
* @returns HEX color string
|
|
230
|
+
*/
|
|
231
|
+
toHEXColor() {
|
|
232
|
+
return `#${EColor.toHex(this.r)}${EColor.toHex(this.g)}${EColor.toHex(this.b)}`;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* To Lab value
|
|
236
|
+
* @returns Lab value
|
|
237
|
+
*/
|
|
238
|
+
toLabValue() {
|
|
239
|
+
let r = this.r / 255, g = this.g / 255, b = this.b / 255, x, y, z;
|
|
240
|
+
r = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
|
|
241
|
+
g = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
|
|
242
|
+
b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
|
|
243
|
+
x = (r * 0.4124 + g * 0.3576 + b * 0.1805) / 0.95047;
|
|
244
|
+
y = (r * 0.2126 + g * 0.7152 + b * 0.0722) / 1.0;
|
|
245
|
+
z = (r * 0.0193 + g * 0.1192 + b * 0.9505) / 1.08883;
|
|
246
|
+
x = x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787 * x + 16 / 116;
|
|
247
|
+
y = y > 0.008856 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116;
|
|
248
|
+
z = z > 0.008856 ? Math.pow(z, 1 / 3) : 7.787 * z + 16 / 116;
|
|
249
|
+
return [116 * y - 16, 500 * (x - y), 200 * (y - z)];
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* To RGB color string
|
|
253
|
+
* @param includeAlpha Include alpha or not
|
|
254
|
+
* @returns RGB color string
|
|
255
|
+
*/
|
|
256
|
+
toRGBColor(includeAlpha) {
|
|
257
|
+
var _a;
|
|
258
|
+
// Default case
|
|
259
|
+
includeAlpha !== null && includeAlpha !== void 0 ? includeAlpha : (includeAlpha = this.alpha != null);
|
|
260
|
+
if (includeAlpha)
|
|
261
|
+
return `RGBA(${this.r}, ${this.g}, ${this.b}, ${(_a = this.alpha) !== null && _a !== void 0 ? _a : 1})`;
|
|
262
|
+
return `RGB(${this.r}, ${this.g}, ${this.b})`;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
exports.EColor = EColor;
|
package/lib/mjs/ExtendUtils.js
CHANGED
|
@@ -31,14 +31,15 @@ export var ExtendUtils;
|
|
|
31
31
|
return {
|
|
32
32
|
/**
|
|
33
33
|
* Call the function
|
|
34
|
+
* @param miliseconds Delayed miliseconds for this call
|
|
34
35
|
* @param args Args
|
|
35
36
|
*/
|
|
36
|
-
call(...args) {
|
|
37
|
+
call(miliseconds, ...args) {
|
|
37
38
|
this.clear();
|
|
38
39
|
seed = window.setTimeout((...args) => {
|
|
39
40
|
func(...args);
|
|
40
41
|
seed = 0;
|
|
41
|
-
}, delayMiliseconds, ...args);
|
|
42
|
+
}, miliseconds !== null && miliseconds !== void 0 ? miliseconds : delayMiliseconds, ...args);
|
|
42
43
|
},
|
|
43
44
|
/**
|
|
44
45
|
* Clear
|
package/lib/mjs/index.d.ts
CHANGED
package/lib/mjs/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
export declare type DelayedExecutorType<P extends any[]> = {
|
|
2
2
|
/**
|
|
3
3
|
* Call the function
|
|
4
|
+
* @param miliseconds Delayed miliseconds for this call
|
|
4
5
|
* @param args Args
|
|
5
6
|
*/
|
|
6
|
-
call(...args: P): void;
|
|
7
|
+
call(miliseconds?: number, ...args: P): void;
|
|
7
8
|
/**
|
|
8
9
|
* Clear
|
|
9
10
|
*/
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Etsoo implmented Color
|
|
3
|
+
*/
|
|
4
|
+
export declare class EColor {
|
|
5
|
+
readonly r: number;
|
|
6
|
+
readonly g: number;
|
|
7
|
+
readonly b: number;
|
|
8
|
+
readonly alpha?: number | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Adjust value
|
|
11
|
+
* @param value Current value
|
|
12
|
+
* @param adjust Adjust value
|
|
13
|
+
* @returns Adjusted value
|
|
14
|
+
*/
|
|
15
|
+
static adjust(value: number, adjust?: number): number;
|
|
16
|
+
/**
|
|
17
|
+
* Get HEX or RGB colors
|
|
18
|
+
* @param init Initial color
|
|
19
|
+
* @param factor Increase factor
|
|
20
|
+
* @param adjustOrder Adjust order to increase difference
|
|
21
|
+
* @param hex to HEX or not
|
|
22
|
+
* @returns Result
|
|
23
|
+
*/
|
|
24
|
+
static getColors(init?: string, factor?: number, adjustOrder?: boolean, hex?: boolean): string[];
|
|
25
|
+
/**
|
|
26
|
+
* Get EColors
|
|
27
|
+
* @param init Initial color
|
|
28
|
+
* @param factor Increase factor
|
|
29
|
+
* @param adjustOrder Adjust order to increase difference
|
|
30
|
+
* @returns Result
|
|
31
|
+
*/
|
|
32
|
+
static getEColors(init?: string, factor?: number, adjustOrder?: boolean): EColor[];
|
|
33
|
+
/**
|
|
34
|
+
* HEX string to integer value
|
|
35
|
+
* @param hex HEX string
|
|
36
|
+
* @returns Integer value
|
|
37
|
+
*/
|
|
38
|
+
static hexTo(hex: string): number;
|
|
39
|
+
/**
|
|
40
|
+
* Format value to 16 radix string
|
|
41
|
+
* @param num Int value
|
|
42
|
+
* @returns Result
|
|
43
|
+
*/
|
|
44
|
+
static toHex(num: number): string;
|
|
45
|
+
/**
|
|
46
|
+
* Parse HTML color to EColor
|
|
47
|
+
* @param htmlColor HTML color
|
|
48
|
+
* @returns EColor
|
|
49
|
+
*/
|
|
50
|
+
static parse(htmlColor?: string | null): EColor | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Constructor
|
|
53
|
+
* @param r Reg
|
|
54
|
+
* @param g Green
|
|
55
|
+
* @param b Blue
|
|
56
|
+
* @param alpha Alpha
|
|
57
|
+
*/
|
|
58
|
+
constructor(r: number, g: number, b: number, alpha?: number | undefined);
|
|
59
|
+
/**
|
|
60
|
+
* Clone color with adjustments
|
|
61
|
+
* @param adjustR Adjust R value
|
|
62
|
+
* @param adjustG Adjust G value
|
|
63
|
+
* @param adjustB Adjust B value
|
|
64
|
+
* @param alpha New alpha value
|
|
65
|
+
*/
|
|
66
|
+
clone(adjustR?: number, adjustG?: number, adjustB?: number, alpha?: number): EColor | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Get contrast ratio, a value between 0 and 1
|
|
69
|
+
* @param color Contrast color
|
|
70
|
+
*/
|
|
71
|
+
getContrastRatio(color: EColor): number;
|
|
72
|
+
/**
|
|
73
|
+
* Get Delta value (perceptible by human eyes)
|
|
74
|
+
* <= 1, Not perceptible by human eyes
|
|
75
|
+
* 1 - 2, Perceptible through close observation
|
|
76
|
+
* 2 - 10, Perceptible at a glance
|
|
77
|
+
* 11 - 49, Colors are more similar than opposite
|
|
78
|
+
* 100+, Colors are exact opposite
|
|
79
|
+
* @param color Contrast color
|
|
80
|
+
* @returns Value
|
|
81
|
+
*/
|
|
82
|
+
getDeltaValue(color: EColor): number;
|
|
83
|
+
/**
|
|
84
|
+
* Get luminance
|
|
85
|
+
* Darker one has higher luminance
|
|
86
|
+
* https://dev.to/alvaromontoro/building-your-own-color-contrast-checker-4j7o
|
|
87
|
+
*/
|
|
88
|
+
getLuminance(): number;
|
|
89
|
+
/**
|
|
90
|
+
* To HEX color string
|
|
91
|
+
* @returns HEX color string
|
|
92
|
+
*/
|
|
93
|
+
toHEXColor(): string;
|
|
94
|
+
/**
|
|
95
|
+
* To Lab value
|
|
96
|
+
* @returns Lab value
|
|
97
|
+
*/
|
|
98
|
+
toLabValue(): [number, number, number];
|
|
99
|
+
/**
|
|
100
|
+
* To RGB color string
|
|
101
|
+
* @param includeAlpha Include alpha or not
|
|
102
|
+
* @returns RGB color string
|
|
103
|
+
*/
|
|
104
|
+
toRGBColor(includeAlpha?: boolean): string;
|
|
105
|
+
}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Etsoo implmented Color
|
|
3
|
+
*/
|
|
4
|
+
export class EColor {
|
|
5
|
+
/**
|
|
6
|
+
* Constructor
|
|
7
|
+
* @param r Reg
|
|
8
|
+
* @param g Green
|
|
9
|
+
* @param b Blue
|
|
10
|
+
* @param alpha Alpha
|
|
11
|
+
*/
|
|
12
|
+
constructor(r, g, b, alpha) {
|
|
13
|
+
this.r = r;
|
|
14
|
+
this.g = g;
|
|
15
|
+
this.b = b;
|
|
16
|
+
this.alpha = alpha;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Adjust value
|
|
20
|
+
* @param value Current value
|
|
21
|
+
* @param adjust Adjust value
|
|
22
|
+
* @returns Adjusted value
|
|
23
|
+
*/
|
|
24
|
+
static adjust(value, adjust) {
|
|
25
|
+
if (adjust == null)
|
|
26
|
+
return value;
|
|
27
|
+
value = Math.abs(value + adjust);
|
|
28
|
+
if (value > 255)
|
|
29
|
+
return value % 255;
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get HEX or RGB colors
|
|
34
|
+
* @param init Initial color
|
|
35
|
+
* @param factor Increase factor
|
|
36
|
+
* @param adjustOrder Adjust order to increase difference
|
|
37
|
+
* @param hex to HEX or not
|
|
38
|
+
* @returns Result
|
|
39
|
+
*/
|
|
40
|
+
static getColors(init = '#000', factor = 51, adjustOrder = true, hex = true) {
|
|
41
|
+
return EColor.getEColors(init, factor, adjustOrder).map((c) => hex ? c.toHEXColor() : c.toRGBColor());
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get EColors
|
|
45
|
+
* @param init Initial color
|
|
46
|
+
* @param factor Increase factor
|
|
47
|
+
* @param adjustOrder Adjust order to increase difference
|
|
48
|
+
* @returns Result
|
|
49
|
+
*/
|
|
50
|
+
static getEColors(init = '#000', factor = 51, adjustOrder = true) {
|
|
51
|
+
var _a;
|
|
52
|
+
// Init color
|
|
53
|
+
const initColor = (_a = EColor.parse(init)) !== null && _a !== void 0 ? _a : new EColor(0, 0, 0);
|
|
54
|
+
// Factors elements
|
|
55
|
+
// 51 = '00', '33', '66', '99', 'cc', 'ff'
|
|
56
|
+
const factors = [];
|
|
57
|
+
let f = 0;
|
|
58
|
+
while (f <= 255) {
|
|
59
|
+
factors.push(f);
|
|
60
|
+
f += factor;
|
|
61
|
+
}
|
|
62
|
+
// RGB loop
|
|
63
|
+
const colors = [initColor];
|
|
64
|
+
for (const r of factors) {
|
|
65
|
+
for (const g of factors) {
|
|
66
|
+
for (const b of factors) {
|
|
67
|
+
colors.push(initColor.clone(r, g, b));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Non-nullable colors
|
|
72
|
+
const nColors = colors.filter((color) => color != null);
|
|
73
|
+
// Adjust order
|
|
74
|
+
if (adjustOrder) {
|
|
75
|
+
const firstColor = nColors.shift();
|
|
76
|
+
if (firstColor) {
|
|
77
|
+
let color = firstColor;
|
|
78
|
+
const newColors = [color];
|
|
79
|
+
while (nColors.length > 0) {
|
|
80
|
+
const result = nColors.reduce((p, c, index) => {
|
|
81
|
+
const delta = color.getDeltaValue(c);
|
|
82
|
+
if (delta != null && delta > p.delta) {
|
|
83
|
+
p.delta = delta;
|
|
84
|
+
p.color = c;
|
|
85
|
+
p.index = index;
|
|
86
|
+
}
|
|
87
|
+
return p;
|
|
88
|
+
}, { delta: 0, color, index: -1 });
|
|
89
|
+
if (result.delta > 0) {
|
|
90
|
+
color = result.color;
|
|
91
|
+
newColors.push(color);
|
|
92
|
+
nColors.splice(result.index, 1);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return newColors;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return nColors;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* HEX string to integer value
|
|
102
|
+
* @param hex HEX string
|
|
103
|
+
* @returns Integer value
|
|
104
|
+
*/
|
|
105
|
+
static hexTo(hex) {
|
|
106
|
+
return parseInt(hex, 16);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Format value to 16 radix string
|
|
110
|
+
* @param num Int value
|
|
111
|
+
* @returns Result
|
|
112
|
+
*/
|
|
113
|
+
static toHex(num) {
|
|
114
|
+
return num.toString(16).padStart(2, '0');
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Parse HTML color to EColor
|
|
118
|
+
* @param htmlColor HTML color
|
|
119
|
+
* @returns EColor
|
|
120
|
+
*/
|
|
121
|
+
static parse(htmlColor) {
|
|
122
|
+
// Null
|
|
123
|
+
if (htmlColor == null)
|
|
124
|
+
return undefined;
|
|
125
|
+
htmlColor = htmlColor.toUpperCase();
|
|
126
|
+
// HEX color
|
|
127
|
+
if (htmlColor.startsWith('#')) {
|
|
128
|
+
htmlColor = htmlColor.substring(1);
|
|
129
|
+
if (htmlColor.length === 3)
|
|
130
|
+
htmlColor = Array.from(htmlColor)
|
|
131
|
+
.map((c) => c + c)
|
|
132
|
+
.join('');
|
|
133
|
+
if (htmlColor.length === 6) {
|
|
134
|
+
return new EColor(EColor.hexTo(htmlColor.substring(0, 2)), EColor.hexTo(htmlColor.substring(2, 4)), EColor.hexTo(htmlColor.substring(4, 6)));
|
|
135
|
+
}
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
// For RGB and RGBA
|
|
139
|
+
const reg = /^RGBA?\(([0-9,\s\.]+)\)$/;
|
|
140
|
+
const result = htmlColor.match(reg);
|
|
141
|
+
if (result != null && result.length == 2) {
|
|
142
|
+
const parts = result[1].split(/\s*,\s*/);
|
|
143
|
+
if (parts.length === 3 || parts.length === 4) {
|
|
144
|
+
const alpha = parts[3];
|
|
145
|
+
return new EColor(parseInt(parts[0]), parseInt(parts[1]), parseInt(parts[2]), alpha == null ? undefined : parseFloat(alpha));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Clone color with adjustments
|
|
152
|
+
* @param adjustR Adjust R value
|
|
153
|
+
* @param adjustG Adjust G value
|
|
154
|
+
* @param adjustB Adjust B value
|
|
155
|
+
* @param alpha New alpha value
|
|
156
|
+
*/
|
|
157
|
+
clone(adjustR, adjustG, adjustB, alpha) {
|
|
158
|
+
const r = EColor.adjust(this.r, adjustR);
|
|
159
|
+
const g = EColor.adjust(this.g, adjustG);
|
|
160
|
+
const b = EColor.adjust(this.b, adjustB);
|
|
161
|
+
if (r === this.r &&
|
|
162
|
+
g === this.g &&
|
|
163
|
+
b === this.b &&
|
|
164
|
+
(alpha == null || alpha === this.alpha))
|
|
165
|
+
return undefined;
|
|
166
|
+
return new EColor(r, g, b, alpha);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Get contrast ratio, a value between 0 and 1
|
|
170
|
+
* @param color Contrast color
|
|
171
|
+
*/
|
|
172
|
+
getContrastRatio(color) {
|
|
173
|
+
const lum1 = this.getLuminance();
|
|
174
|
+
const lum2 = color.getLuminance();
|
|
175
|
+
const brightest = Math.max(lum1, lum2);
|
|
176
|
+
const darkest = Math.min(lum1, lum2);
|
|
177
|
+
return (brightest + 0.05) / (darkest + 0.05);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Get Delta value (perceptible by human eyes)
|
|
181
|
+
* <= 1, Not perceptible by human eyes
|
|
182
|
+
* 1 - 2, Perceptible through close observation
|
|
183
|
+
* 2 - 10, Perceptible at a glance
|
|
184
|
+
* 11 - 49, Colors are more similar than opposite
|
|
185
|
+
* 100+, Colors are exact opposite
|
|
186
|
+
* @param color Contrast color
|
|
187
|
+
* @returns Value
|
|
188
|
+
*/
|
|
189
|
+
getDeltaValue(color) {
|
|
190
|
+
const labA = this.toLabValue();
|
|
191
|
+
const labB = color.toLabValue();
|
|
192
|
+
const deltaL = labA[0] - labB[0];
|
|
193
|
+
const deltaA = labA[1] - labB[1];
|
|
194
|
+
const deltaB = labA[2] - labB[2];
|
|
195
|
+
const c1 = Math.sqrt(labA[1] * labA[1] + labA[2] * labA[2]);
|
|
196
|
+
const c2 = Math.sqrt(labB[1] * labB[1] + labB[2] * labB[2]);
|
|
197
|
+
const deltaC = c1 - c2;
|
|
198
|
+
let deltaH = deltaA * deltaA + deltaB * deltaB - deltaC * deltaC;
|
|
199
|
+
deltaH = deltaH < 0 ? 0 : Math.sqrt(deltaH);
|
|
200
|
+
const sc = 1.0 + 0.045 * c1;
|
|
201
|
+
const sh = 1.0 + 0.015 * c1;
|
|
202
|
+
const deltaLKlsl = deltaL / 1.0;
|
|
203
|
+
const deltaCkcsc = deltaC / sc;
|
|
204
|
+
const deltaHkhsh = deltaH / sh;
|
|
205
|
+
const i = deltaLKlsl * deltaLKlsl +
|
|
206
|
+
deltaCkcsc * deltaCkcsc +
|
|
207
|
+
deltaHkhsh * deltaHkhsh;
|
|
208
|
+
return i < 0 ? 0 : Math.sqrt(i);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Get luminance
|
|
212
|
+
* Darker one has higher luminance
|
|
213
|
+
* https://dev.to/alvaromontoro/building-your-own-color-contrast-checker-4j7o
|
|
214
|
+
*/
|
|
215
|
+
getLuminance() {
|
|
216
|
+
const a = [this.r, this.g, this.b].map((v) => {
|
|
217
|
+
v /= 255;
|
|
218
|
+
return v <= 0.03928
|
|
219
|
+
? v / 12.92
|
|
220
|
+
: Math.pow((v + 0.055) / 1.055, 2.4);
|
|
221
|
+
});
|
|
222
|
+
return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* To HEX color string
|
|
226
|
+
* @returns HEX color string
|
|
227
|
+
*/
|
|
228
|
+
toHEXColor() {
|
|
229
|
+
return `#${EColor.toHex(this.r)}${EColor.toHex(this.g)}${EColor.toHex(this.b)}`;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* To Lab value
|
|
233
|
+
* @returns Lab value
|
|
234
|
+
*/
|
|
235
|
+
toLabValue() {
|
|
236
|
+
let r = this.r / 255, g = this.g / 255, b = this.b / 255, x, y, z;
|
|
237
|
+
r = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
|
|
238
|
+
g = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
|
|
239
|
+
b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
|
|
240
|
+
x = (r * 0.4124 + g * 0.3576 + b * 0.1805) / 0.95047;
|
|
241
|
+
y = (r * 0.2126 + g * 0.7152 + b * 0.0722) / 1.0;
|
|
242
|
+
z = (r * 0.0193 + g * 0.1192 + b * 0.9505) / 1.08883;
|
|
243
|
+
x = x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787 * x + 16 / 116;
|
|
244
|
+
y = y > 0.008856 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116;
|
|
245
|
+
z = z > 0.008856 ? Math.pow(z, 1 / 3) : 7.787 * z + 16 / 116;
|
|
246
|
+
return [116 * y - 16, 500 * (x - y), 200 * (y - z)];
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* To RGB color string
|
|
250
|
+
* @param includeAlpha Include alpha or not
|
|
251
|
+
* @returns RGB color string
|
|
252
|
+
*/
|
|
253
|
+
toRGBColor(includeAlpha) {
|
|
254
|
+
var _a;
|
|
255
|
+
// Default case
|
|
256
|
+
includeAlpha !== null && includeAlpha !== void 0 ? includeAlpha : (includeAlpha = this.alpha != null);
|
|
257
|
+
if (includeAlpha)
|
|
258
|
+
return `RGBA(${this.r}, ${this.g}, ${this.b}, ${(_a = this.alpha) !== null && _a !== void 0 ? _a : 1})`;
|
|
259
|
+
return `RGB(${this.r}, ${this.g}, ${this.b})`;
|
|
260
|
+
}
|
|
261
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/shared",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.16",
|
|
4
4
|
"description": "TypeScript shared utilities and functions",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"module": "lib/mjs/index.js",
|
|
@@ -55,13 +55,13 @@
|
|
|
55
55
|
"dependencies": {},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/jest": "^27.4.1",
|
|
58
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
59
|
-
"@typescript-eslint/parser": "^5.
|
|
58
|
+
"@typescript-eslint/eslint-plugin": "^5.13.0",
|
|
59
|
+
"@typescript-eslint/parser": "^5.13.0",
|
|
60
60
|
"eslint": "^8.10.0",
|
|
61
61
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
62
62
|
"eslint-plugin-import": "^2.25.4",
|
|
63
63
|
"jest": "^27.5.1",
|
|
64
64
|
"ts-jest": "^27.1.3",
|
|
65
|
-
"typescript": "^4.
|
|
65
|
+
"typescript": "^4.6.2"
|
|
66
66
|
}
|
|
67
67
|
}
|
package/src/ExtendUtils.ts
CHANGED
|
@@ -35,16 +35,17 @@ export namespace ExtendUtils {
|
|
|
35
35
|
return {
|
|
36
36
|
/**
|
|
37
37
|
* Call the function
|
|
38
|
+
* @param miliseconds Delayed miliseconds for this call
|
|
38
39
|
* @param args Args
|
|
39
40
|
*/
|
|
40
|
-
call(...args: P) {
|
|
41
|
+
call(miliseconds?: number, ...args: P) {
|
|
41
42
|
this.clear();
|
|
42
43
|
seed = window.setTimeout(
|
|
43
44
|
(...args: P) => {
|
|
44
45
|
func(...args);
|
|
45
46
|
seed = 0;
|
|
46
47
|
},
|
|
47
|
-
delayMiliseconds,
|
|
48
|
+
miliseconds ?? delayMiliseconds,
|
|
48
49
|
...args
|
|
49
50
|
);
|
|
50
51
|
},
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Etsoo implmented Color
|
|
3
|
+
*/
|
|
4
|
+
export class EColor {
|
|
5
|
+
/**
|
|
6
|
+
* Adjust value
|
|
7
|
+
* @param value Current value
|
|
8
|
+
* @param adjust Adjust value
|
|
9
|
+
* @returns Adjusted value
|
|
10
|
+
*/
|
|
11
|
+
static adjust(value: number, adjust?: number) {
|
|
12
|
+
if (adjust == null) return value;
|
|
13
|
+
value = Math.abs(value + adjust);
|
|
14
|
+
if (value > 255) return value % 255;
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Get HEX or RGB colors
|
|
20
|
+
* @param init Initial color
|
|
21
|
+
* @param factor Increase factor
|
|
22
|
+
* @param adjustOrder Adjust order to increase difference
|
|
23
|
+
* @param hex to HEX or not
|
|
24
|
+
* @returns Result
|
|
25
|
+
*/
|
|
26
|
+
static getColors(
|
|
27
|
+
init: string = '#000',
|
|
28
|
+
factor: number = 51,
|
|
29
|
+
adjustOrder: boolean = true,
|
|
30
|
+
hex: boolean = true
|
|
31
|
+
) {
|
|
32
|
+
return EColor.getEColors(init, factor, adjustOrder).map((c) =>
|
|
33
|
+
hex ? c.toHEXColor() : c.toRGBColor()
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get EColors
|
|
39
|
+
* @param init Initial color
|
|
40
|
+
* @param factor Increase factor
|
|
41
|
+
* @param adjustOrder Adjust order to increase difference
|
|
42
|
+
* @returns Result
|
|
43
|
+
*/
|
|
44
|
+
static getEColors(
|
|
45
|
+
init: string = '#000',
|
|
46
|
+
factor: number = 51,
|
|
47
|
+
adjustOrder: boolean = true
|
|
48
|
+
): EColor[] {
|
|
49
|
+
// Init color
|
|
50
|
+
const initColor = EColor.parse(init) ?? new EColor(0, 0, 0);
|
|
51
|
+
|
|
52
|
+
// Factors elements
|
|
53
|
+
// 51 = '00', '33', '66', '99', 'cc', 'ff'
|
|
54
|
+
const factors: number[] = [];
|
|
55
|
+
let f = 0;
|
|
56
|
+
while (f <= 255) {
|
|
57
|
+
factors.push(f);
|
|
58
|
+
f += factor;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// RGB loop
|
|
62
|
+
const colors: (EColor | undefined)[] = [initColor];
|
|
63
|
+
for (const r of factors) {
|
|
64
|
+
for (const g of factors) {
|
|
65
|
+
for (const b of factors) {
|
|
66
|
+
colors.push(initColor.clone(r, g, b));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Non-nullable colors
|
|
72
|
+
const nColors = colors.filter(
|
|
73
|
+
(color): color is EColor => color != null
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
// Adjust order
|
|
77
|
+
if (adjustOrder) {
|
|
78
|
+
const firstColor = nColors.shift();
|
|
79
|
+
if (firstColor) {
|
|
80
|
+
let color = firstColor;
|
|
81
|
+
const newColors: EColor[] = [color];
|
|
82
|
+
|
|
83
|
+
while (nColors.length > 0) {
|
|
84
|
+
const result = nColors.reduce(
|
|
85
|
+
(p, c, index) => {
|
|
86
|
+
const delta = color.getDeltaValue(c);
|
|
87
|
+
if (delta != null && delta > p.delta) {
|
|
88
|
+
p.delta = delta;
|
|
89
|
+
p.color = c;
|
|
90
|
+
p.index = index;
|
|
91
|
+
}
|
|
92
|
+
return p;
|
|
93
|
+
},
|
|
94
|
+
{ delta: 0, color, index: -1 }
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
if (result.delta > 0) {
|
|
98
|
+
color = result.color;
|
|
99
|
+
newColors.push(color);
|
|
100
|
+
nColors.splice(result.index, 1);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return newColors;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return nColors;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* HEX string to integer value
|
|
113
|
+
* @param hex HEX string
|
|
114
|
+
* @returns Integer value
|
|
115
|
+
*/
|
|
116
|
+
static hexTo(hex: string) {
|
|
117
|
+
return parseInt(hex, 16);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Format value to 16 radix string
|
|
122
|
+
* @param num Int value
|
|
123
|
+
* @returns Result
|
|
124
|
+
*/
|
|
125
|
+
static toHex(num: number) {
|
|
126
|
+
return num.toString(16).padStart(2, '0');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Parse HTML color to EColor
|
|
131
|
+
* @param htmlColor HTML color
|
|
132
|
+
* @returns EColor
|
|
133
|
+
*/
|
|
134
|
+
static parse(htmlColor?: string | null): EColor | undefined {
|
|
135
|
+
// Null
|
|
136
|
+
if (htmlColor == null) return undefined;
|
|
137
|
+
htmlColor = htmlColor.toUpperCase();
|
|
138
|
+
|
|
139
|
+
// HEX color
|
|
140
|
+
if (htmlColor.startsWith('#')) {
|
|
141
|
+
htmlColor = htmlColor.substring(1);
|
|
142
|
+
if (htmlColor.length === 3)
|
|
143
|
+
htmlColor = Array.from(htmlColor)
|
|
144
|
+
.map((c) => c + c)
|
|
145
|
+
.join('');
|
|
146
|
+
|
|
147
|
+
if (htmlColor.length === 6) {
|
|
148
|
+
return new EColor(
|
|
149
|
+
EColor.hexTo(htmlColor.substring(0, 2)),
|
|
150
|
+
EColor.hexTo(htmlColor.substring(2, 4)),
|
|
151
|
+
EColor.hexTo(htmlColor.substring(4, 6))
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return undefined;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// For RGB and RGBA
|
|
159
|
+
const reg = /^RGBA?\(([0-9,\s\.]+)\)$/;
|
|
160
|
+
const result = htmlColor.match(reg);
|
|
161
|
+
if (result != null && result.length == 2) {
|
|
162
|
+
const parts = result[1].split(/\s*,\s*/);
|
|
163
|
+
if (parts.length === 3 || parts.length === 4) {
|
|
164
|
+
const alpha = parts[3];
|
|
165
|
+
return new EColor(
|
|
166
|
+
parseInt(parts[0]),
|
|
167
|
+
parseInt(parts[1]),
|
|
168
|
+
parseInt(parts[2]),
|
|
169
|
+
alpha == null ? undefined : parseFloat(alpha)
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Constructor
|
|
179
|
+
* @param r Reg
|
|
180
|
+
* @param g Green
|
|
181
|
+
* @param b Blue
|
|
182
|
+
* @param alpha Alpha
|
|
183
|
+
*/
|
|
184
|
+
constructor(
|
|
185
|
+
public readonly r: number,
|
|
186
|
+
public readonly g: number,
|
|
187
|
+
public readonly b: number,
|
|
188
|
+
public readonly alpha?: number
|
|
189
|
+
) {}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Clone color with adjustments
|
|
193
|
+
* @param adjustR Adjust R value
|
|
194
|
+
* @param adjustG Adjust G value
|
|
195
|
+
* @param adjustB Adjust B value
|
|
196
|
+
* @param alpha New alpha value
|
|
197
|
+
*/
|
|
198
|
+
clone(
|
|
199
|
+
adjustR?: number,
|
|
200
|
+
adjustG?: number,
|
|
201
|
+
adjustB?: number,
|
|
202
|
+
alpha?: number
|
|
203
|
+
) {
|
|
204
|
+
const r = EColor.adjust(this.r, adjustR);
|
|
205
|
+
const g = EColor.adjust(this.g, adjustG);
|
|
206
|
+
const b = EColor.adjust(this.b, adjustB);
|
|
207
|
+
if (
|
|
208
|
+
r === this.r &&
|
|
209
|
+
g === this.g &&
|
|
210
|
+
b === this.b &&
|
|
211
|
+
(alpha == null || alpha === this.alpha)
|
|
212
|
+
)
|
|
213
|
+
return undefined;
|
|
214
|
+
return new EColor(r, g, b, alpha);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Get contrast ratio, a value between 0 and 1
|
|
219
|
+
* @param color Contrast color
|
|
220
|
+
*/
|
|
221
|
+
getContrastRatio(color: EColor) {
|
|
222
|
+
const lum1 = this.getLuminance();
|
|
223
|
+
const lum2 = color.getLuminance();
|
|
224
|
+
const brightest = Math.max(lum1, lum2);
|
|
225
|
+
const darkest = Math.min(lum1, lum2);
|
|
226
|
+
return (brightest + 0.05) / (darkest + 0.05);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Get Delta value (perceptible by human eyes)
|
|
231
|
+
* <= 1, Not perceptible by human eyes
|
|
232
|
+
* 1 - 2, Perceptible through close observation
|
|
233
|
+
* 2 - 10, Perceptible at a glance
|
|
234
|
+
* 11 - 49, Colors are more similar than opposite
|
|
235
|
+
* 100+, Colors are exact opposite
|
|
236
|
+
* @param color Contrast color
|
|
237
|
+
* @returns Value
|
|
238
|
+
*/
|
|
239
|
+
getDeltaValue(color: EColor) {
|
|
240
|
+
const labA = this.toLabValue();
|
|
241
|
+
const labB = color.toLabValue();
|
|
242
|
+
const deltaL = labA[0] - labB[0];
|
|
243
|
+
const deltaA = labA[1] - labB[1];
|
|
244
|
+
const deltaB = labA[2] - labB[2];
|
|
245
|
+
const c1 = Math.sqrt(labA[1] * labA[1] + labA[2] * labA[2]);
|
|
246
|
+
const c2 = Math.sqrt(labB[1] * labB[1] + labB[2] * labB[2]);
|
|
247
|
+
const deltaC = c1 - c2;
|
|
248
|
+
let deltaH = deltaA * deltaA + deltaB * deltaB - deltaC * deltaC;
|
|
249
|
+
deltaH = deltaH < 0 ? 0 : Math.sqrt(deltaH);
|
|
250
|
+
const sc = 1.0 + 0.045 * c1;
|
|
251
|
+
const sh = 1.0 + 0.015 * c1;
|
|
252
|
+
const deltaLKlsl = deltaL / 1.0;
|
|
253
|
+
const deltaCkcsc = deltaC / sc;
|
|
254
|
+
const deltaHkhsh = deltaH / sh;
|
|
255
|
+
const i =
|
|
256
|
+
deltaLKlsl * deltaLKlsl +
|
|
257
|
+
deltaCkcsc * deltaCkcsc +
|
|
258
|
+
deltaHkhsh * deltaHkhsh;
|
|
259
|
+
return i < 0 ? 0 : Math.sqrt(i);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Get luminance
|
|
264
|
+
* Darker one has higher luminance
|
|
265
|
+
* https://dev.to/alvaromontoro/building-your-own-color-contrast-checker-4j7o
|
|
266
|
+
*/
|
|
267
|
+
getLuminance() {
|
|
268
|
+
const a = [this.r, this.g, this.b].map((v) => {
|
|
269
|
+
v /= 255;
|
|
270
|
+
return v <= 0.03928
|
|
271
|
+
? v / 12.92
|
|
272
|
+
: Math.pow((v + 0.055) / 1.055, 2.4);
|
|
273
|
+
});
|
|
274
|
+
return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* To HEX color string
|
|
279
|
+
* @returns HEX color string
|
|
280
|
+
*/
|
|
281
|
+
toHEXColor() {
|
|
282
|
+
return `#${EColor.toHex(this.r)}${EColor.toHex(this.g)}${EColor.toHex(
|
|
283
|
+
this.b
|
|
284
|
+
)}`;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* To Lab value
|
|
289
|
+
* @returns Lab value
|
|
290
|
+
*/
|
|
291
|
+
toLabValue(): [number, number, number] {
|
|
292
|
+
let r = this.r / 255,
|
|
293
|
+
g = this.g / 255,
|
|
294
|
+
b = this.b / 255,
|
|
295
|
+
x,
|
|
296
|
+
y,
|
|
297
|
+
z;
|
|
298
|
+
r = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
|
|
299
|
+
g = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
|
|
300
|
+
b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
|
|
301
|
+
x = (r * 0.4124 + g * 0.3576 + b * 0.1805) / 0.95047;
|
|
302
|
+
y = (r * 0.2126 + g * 0.7152 + b * 0.0722) / 1.0;
|
|
303
|
+
z = (r * 0.0193 + g * 0.1192 + b * 0.9505) / 1.08883;
|
|
304
|
+
x = x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787 * x + 16 / 116;
|
|
305
|
+
y = y > 0.008856 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116;
|
|
306
|
+
z = z > 0.008856 ? Math.pow(z, 1 / 3) : 7.787 * z + 16 / 116;
|
|
307
|
+
return [116 * y - 16, 500 * (x - y), 200 * (y - z)];
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* To RGB color string
|
|
312
|
+
* @param includeAlpha Include alpha or not
|
|
313
|
+
* @returns RGB color string
|
|
314
|
+
*/
|
|
315
|
+
toRGBColor(includeAlpha?: boolean) {
|
|
316
|
+
// Default case
|
|
317
|
+
includeAlpha ??= this.alpha != null;
|
|
318
|
+
|
|
319
|
+
if (includeAlpha)
|
|
320
|
+
return `RGBA(${this.r}, ${this.g}, ${this.b}, ${this.alpha ?? 1})`;
|
|
321
|
+
|
|
322
|
+
return `RGB(${this.r}, ${this.g}, ${this.b})`;
|
|
323
|
+
}
|
|
324
|
+
}
|