@auaust/jaune 0.0.3 → 0.0.5
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/dist/chunk-Q3GK6DZM.js +2 -0
- package/dist/chunk-Q3GK6DZM.js.map +1 -0
- package/dist/chunk-X6GMJCOG.cjs +2 -0
- package/dist/chunk-X6GMJCOG.cjs.map +1 -0
- package/dist/{index-VyiURM-J.d.cts → index-7Xs589Bo.d.cts} +37 -90
- package/dist/{index-VyiURM-J.d.ts → index-7Xs589Bo.d.ts} +37 -90
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/utils.cjs +1 -1
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +115 -26
- package/dist/utils.d.ts +115 -26
- package/dist/utils.js +1 -1
- package/dist/utils.js.map +1 -1
- package/package.json +14 -10
- package/src/classes/Color.ts +26 -14
- package/src/data/fallbackColor.ts +10 -0
- package/src/{utils → data}/namedColors.ts +5 -109
- package/src/types/index.ts +2 -0
- package/src/utils/brightness.ts +17 -0
- package/src/utils/closestNamedColor.ts +25 -0
- package/src/utils/contrast.ts +17 -0
- package/src/utils/couldBeRgb.ts +13 -0
- package/src/utils/grayscale.ts +12 -0
- package/src/utils/index.ts +45 -34
- package/src/utils/invert.ts +11 -0
- package/src/utils/isAliasToNamedColor.ts +12 -0
- package/src/utils/isAlphaChannel.ts +5 -0
- package/src/utils/isBright.ts +7 -0
- package/src/utils/isColor.ts +7 -0
- package/src/utils/isColorChannels.ts +13 -0
- package/src/utils/isDark.ts +7 -0
- package/src/utils/isHex.ts +27 -0
- package/src/utils/isNamedColor.ts +12 -0
- package/src/utils/isOpaque.ts +6 -0
- package/src/utils/isRgb.ts +15 -0
- package/src/utils/isRgbChannel.ts +5 -0
- package/src/utils/isTranslucent.ts +7 -0
- package/src/utils/isTransparent.ts +6 -0
- package/src/utils/linearTosRGB.ts +10 -0
- package/src/utils/luminance.ts +1 -77
- package/src/utils/namedColorAliases.ts +33 -0
- package/src/utils/namedColorChannels.ts +13 -0
- package/src/utils/namedColorToHex.ts +11 -0
- package/src/utils/parseColor.ts +44 -0
- package/src/utils/parseHex.ts +23 -0
- package/src/utils/parseNamedColor.ts +13 -0
- package/src/utils/parseRgb.ts +14 -0
- package/src/utils/random.ts +2 -29
- package/src/utils/randomAlphaChannel.ts +15 -0
- package/src/utils/randomRgbChannel.ts +15 -0
- package/src/utils/sRGBtoLinear.ts +12 -0
- package/src/utils/toAlphaChannel.ts +5 -0
- package/src/utils/{channels.ts → toColorChannels.ts} +4 -31
- package/src/utils/toHex.ts +29 -0
- package/src/utils/toRgb.ts +13 -0
- package/src/utils/toRgbChannel.ts +5 -0
- package/src/utils/type.ts +32 -0
- package/src/utils/colors.ts +0 -72
- package/src/utils/hex.ts +0 -75
- package/src/utils/opacity.ts +0 -16
- package/src/utils/rgb.ts +0 -51
package/src/utils/luminance.ts
CHANGED
|
@@ -1,32 +1,5 @@
|
|
|
1
|
-
import { N } from "@auaust/primitive-kit";
|
|
2
1
|
import type { ColorChannels } from "~/types";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Returns the linearized value of a sRGB channel.
|
|
7
|
-
*
|
|
8
|
-
* @see https://stackoverflow.com/a/56678483
|
|
9
|
-
*/
|
|
10
|
-
export function sRGBtoLinear(channel: number) {
|
|
11
|
-
if (channel <= 0.04045) {
|
|
12
|
-
return channel / 12.92;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return Math.pow((channel + 0.055) / 1.055, 2.4);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Returns the gamma corrected sRGB value of a linear channel.
|
|
20
|
-
*
|
|
21
|
-
* @see sRGBtoLinear
|
|
22
|
-
*/
|
|
23
|
-
export function linearTosRGB(channel: number) {
|
|
24
|
-
if (channel <= 0.04045 / 12.92) {
|
|
25
|
-
return channel * 12.92;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return 1.055 * Math.pow(channel, 1 / 2.4) - 0.055;
|
|
29
|
-
}
|
|
2
|
+
import { sRGBtoLinear } from "~/utils";
|
|
30
3
|
|
|
31
4
|
/**
|
|
32
5
|
* Returns the luminance of a color normalized to the range [0, 1].
|
|
@@ -41,52 +14,3 @@ export function luminance(channels: ColorChannels) {
|
|
|
41
14
|
|
|
42
15
|
return r * 0.2126 + g * 0.7152 + b * 0.0722;
|
|
43
16
|
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Returns the perceived brightness of a color normalized to the range [0, 1].
|
|
47
|
-
*
|
|
48
|
-
* @see https://stackoverflow.com/a/56678483
|
|
49
|
-
*/
|
|
50
|
-
export function brightness(channels: ColorChannels): number {
|
|
51
|
-
const l = luminance(channels);
|
|
52
|
-
|
|
53
|
-
if (l <= 216 / 24389) {
|
|
54
|
-
return (l * (24389 / 27)) / 100;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return (Math.pow(l, 1 / 3) * 116 - 16) / 100;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/** Returns whether the color is bright, as in its brightness is greater than 0.5 or the provided threshold. */
|
|
61
|
-
export function isBright(channels: ColorChannels, threshold = 0.5): boolean {
|
|
62
|
-
return brightness(channels) > threshold;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** Returns whether the color is dark, as in its brightness is less than or equal to 0.5 or the provided threshold. */
|
|
66
|
-
export function isDark(channels: ColorChannels, threshold = 0.5): boolean {
|
|
67
|
-
return brightness(channels) <= threshold;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Returns the contrast ratio between two colors.
|
|
72
|
-
*
|
|
73
|
-
* @see https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
|
|
74
|
-
*/
|
|
75
|
-
export function contrast(channelsA: ColorChannels, channelsB: ColorChannels) {
|
|
76
|
-
const [darkest, brightest] = N.minMax(
|
|
77
|
-
luminance(channelsA),
|
|
78
|
-
luminance(channelsB)
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
return (brightest + 0.05) / (darkest + 0.05);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Returns the grayscale equivalent of a color as a new color channels object.
|
|
86
|
-
*/
|
|
87
|
-
export function grayscale(channels: ColorChannels): ColorChannels {
|
|
88
|
-
// Reverse gamma correction from luminance
|
|
89
|
-
const gray = linearTosRGB(luminance(channels)) * 255;
|
|
90
|
-
|
|
91
|
-
return toColorChannels(gray, gray, gray, channels.a);
|
|
92
|
-
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { entries } from "@auaust/primitive-kit/objects";
|
|
2
|
+
import type { NamedColor } from "~/types";
|
|
3
|
+
import { isNamedColor, namedColorToHex, namedColorsMap } from "~/utils";
|
|
4
|
+
|
|
5
|
+
const namedColorsAliasesCache: Partial<
|
|
6
|
+
Record<NamedColor, readonly NamedColor[]>
|
|
7
|
+
> = {};
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Returns all the aliases of a named color.
|
|
11
|
+
*/
|
|
12
|
+
export function namedColorAliases(name: NamedColor): readonly NamedColor[] {
|
|
13
|
+
name = <NamedColor>name.toLowerCase();
|
|
14
|
+
|
|
15
|
+
if (!isNamedColor(name)) {
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (namedColorsAliasesCache[name]) {
|
|
20
|
+
return namedColorsAliasesCache[name]!;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const aliases: NamedColor[] = [];
|
|
24
|
+
const targetHex = namedColorToHex(name);
|
|
25
|
+
|
|
26
|
+
for (const [name, hex] of entries(namedColorsMap)) {
|
|
27
|
+
if (hex === targetHex) {
|
|
28
|
+
aliases.push(name);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return (namedColorsAliasesCache[name] = Object.freeze(aliases));
|
|
33
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ColorChannels, NamedColor } from "~/types";
|
|
2
|
+
import { namedColorToHex, parseHex } from "~/utils";
|
|
3
|
+
|
|
4
|
+
const namedColorsChannelsCache: Partial<Record<NamedColor, ColorChannels>> = {};
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Returns the color channels from a named color. Must be a valid named color, already lowercased.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export function namedColorChannels(name: NamedColor): ColorChannels {
|
|
12
|
+
return (namedColorsChannelsCache[name] ??= parseHex(namedColorToHex(name)!));
|
|
13
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { namedColorsMap } from "~/data/namedColors";
|
|
2
|
+
import type { MaybeNamedColor, NamedColor } from "~/types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns the corresponding HEX value of a named color.
|
|
6
|
+
*/
|
|
7
|
+
export function namedColorToHex(name: NamedColor): string;
|
|
8
|
+
export function namedColorToHex(name: MaybeNamedColor): string | undefined;
|
|
9
|
+
export function namedColorToHex(name: MaybeNamedColor): string | undefined {
|
|
10
|
+
return namedColorsMap[<NamedColor>name.toLowerCase()] || undefined;
|
|
11
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Color } from "~/classes/Color";
|
|
2
|
+
import type { ColorChannels } from "~/types";
|
|
3
|
+
import {
|
|
4
|
+
channels,
|
|
5
|
+
couldBeRgb,
|
|
6
|
+
fallbackColor,
|
|
7
|
+
isColorChannels,
|
|
8
|
+
isHex,
|
|
9
|
+
isNamedColor,
|
|
10
|
+
parseHex,
|
|
11
|
+
parseNamedColor,
|
|
12
|
+
parseRgb,
|
|
13
|
+
} from "~/utils";
|
|
14
|
+
|
|
15
|
+
/** Tries to parse the value as a color. If it fails, returns the fallback color. */
|
|
16
|
+
export function parseColor(value: unknown): ColorChannels {
|
|
17
|
+
if (!value) {
|
|
18
|
+
return fallbackColor;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (value instanceof Color) {
|
|
22
|
+
return value[channels];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (isColorChannels(value)) {
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (isNamedColor(value)) {
|
|
30
|
+
return parseNamedColor(value);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (isHex(value)) {
|
|
34
|
+
return parseHex(value);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (couldBeRgb(value)) {
|
|
38
|
+
// It might not be a valid RGB, in which case `parseRgb` is responsible for returning the fallback color
|
|
39
|
+
// In case more color types are added, it might be required to only return the result of `parseRgb` if `isFallback` is false
|
|
40
|
+
return parseRgb(value);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return fallbackColor;
|
|
44
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ColorChannels, Hex } from "~/types";
|
|
2
|
+
import { toColorChannels } from "~/utils";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Parses a hex string into an object of color channels.
|
|
6
|
+
*
|
|
7
|
+
* The input must already be a valid HEX color, otherwise the result will be unexpected.
|
|
8
|
+
*/
|
|
9
|
+
export function parseHex(value: Hex): ColorChannels {
|
|
10
|
+
value = value.startsWith("#") ? value.slice(1) : value;
|
|
11
|
+
|
|
12
|
+
const isShort = value.length < 6;
|
|
13
|
+
const hasAlpha = isShort ? value.length === 4 : value.length === 8;
|
|
14
|
+
|
|
15
|
+
const r = parseInt(isShort ? value[0].repeat(2) : value.slice(0, 2), 16);
|
|
16
|
+
const g = parseInt(isShort ? value[1].repeat(2) : value.slice(2, 4), 16);
|
|
17
|
+
const b = parseInt(isShort ? value[2].repeat(2) : value.slice(4, 6), 16);
|
|
18
|
+
const a = hasAlpha
|
|
19
|
+
? parseInt(isShort ? value[3].repeat(2) : value.slice(6, 8), 16) / 255
|
|
20
|
+
: 1;
|
|
21
|
+
|
|
22
|
+
return toColorChannels(r, g, b, a);
|
|
23
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ColorChannels, MaybeNamedColor, NamedColor } from "~/types";
|
|
2
|
+
import { fallbackColor, isNamedColor, namedColorChannels } from "~/utils";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns the color channels from a named color.
|
|
6
|
+
*/
|
|
7
|
+
export function parseNamedColor(name: MaybeNamedColor): ColorChannels {
|
|
8
|
+
if (!isNamedColor(name)) {
|
|
9
|
+
return fallbackColor;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return namedColorChannels(<NamedColor>name.toLowerCase());
|
|
13
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { isArray } from "@auaust/primitive-kit/arrays";
|
|
2
|
+
import type { ColorChannels, Rgb } from "~/types";
|
|
3
|
+
import { fallbackColor, toColorChannels } from "~/utils";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Parses a RGB tuple into an object of color channels.
|
|
7
|
+
*
|
|
8
|
+
* The input must already be a valid RGB tuple, otherwise the result will be unexpected.
|
|
9
|
+
*/
|
|
10
|
+
export function parseRgb(value: Rgb): ColorChannels {
|
|
11
|
+
return isArray(value)
|
|
12
|
+
? toColorChannels(value[0], value[1], value[2], value[3]) // Don't spread to avoid mistakenly forwarding `isTransformed` and `isFallback`
|
|
13
|
+
: fallbackColor;
|
|
14
|
+
}
|
package/src/utils/random.ts
CHANGED
|
@@ -1,32 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { toColorChannels } from "~/utils";
|
|
4
|
-
|
|
5
|
-
export type ChannelRange = number | [min: number, max: number];
|
|
6
|
-
|
|
7
|
-
function randomRgbChannel(range?: ChannelRange | undefined): number {
|
|
8
|
-
if (N.is(range)) {
|
|
9
|
-
return range;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
if (A.is(range)) {
|
|
13
|
-
return N.randInt(range[0], range[1]);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
return N.randInt(0, 255);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function randomAlphaChannel(range?: ChannelRange | undefined): number {
|
|
20
|
-
if (N.is(range)) {
|
|
21
|
-
return range;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (A.is(range)) {
|
|
25
|
-
return N.randFloat(range[0], range[1]);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return 1;
|
|
29
|
-
}
|
|
1
|
+
import type { ChannelRange, ColorChannels } from "~/types";
|
|
2
|
+
import { randomAlphaChannel, randomRgbChannel, toColorChannels } from "~/utils";
|
|
30
3
|
|
|
31
4
|
/**
|
|
32
5
|
* Generates a random color.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { isArray } from "@auaust/primitive-kit/arrays";
|
|
2
|
+
import { isNumber, randomFloat } from "@auaust/primitive-kit/numbers";
|
|
3
|
+
import type { ChannelRange } from "~/types";
|
|
4
|
+
|
|
5
|
+
export function randomAlphaChannel(range?: ChannelRange | undefined): number {
|
|
6
|
+
if (isNumber(range)) {
|
|
7
|
+
return range;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (isArray(range)) {
|
|
11
|
+
return randomFloat(range[0], range[1]);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return 1;
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { isArray } from "@auaust/primitive-kit/arrays";
|
|
2
|
+
import { isNumber, randomInteger } from "@auaust/primitive-kit/numbers";
|
|
3
|
+
import type { ChannelRange } from "~/types";
|
|
4
|
+
|
|
5
|
+
export function randomRgbChannel(range?: ChannelRange | undefined): number {
|
|
6
|
+
if (isNumber(range)) {
|
|
7
|
+
return range;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (isArray(range)) {
|
|
11
|
+
return randomInteger(range[0], range[1]);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return randomInteger(0, 255);
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the linearized value of a sRGB channel.
|
|
3
|
+
*
|
|
4
|
+
* @see https://stackoverflow.com/a/56678483
|
|
5
|
+
*/
|
|
6
|
+
export function sRGBtoLinear(channel: number) {
|
|
7
|
+
if (channel <= 0.04045) {
|
|
8
|
+
return channel / 12.92;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return Math.pow((channel + 0.055) / 1.055, 2.4);
|
|
12
|
+
}
|
|
@@ -1,31 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isObject } from "@auaust/primitive-kit/objects";
|
|
2
2
|
import type { ColorChannels } from "~/types";
|
|
3
|
-
|
|
4
|
-
export function isRgbChannel(value: unknown): value is number {
|
|
5
|
-
return N.is(value) && N.isBetween(value, 0, 255);
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function toRgbChannel(value: number | undefined | null): number {
|
|
9
|
-
return N.clamp(N.round(value), 0, 255);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function isAlphaChannel(value: unknown): value is number {
|
|
13
|
-
return N.is(value) && N.isBetween(value, 0, 1);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function toAlphaChannel(value: number | undefined | null): number {
|
|
17
|
-
return N.is(value) ? N.clamp(value, 0, 1) : 1;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function isColorChannels(value: unknown): value is ColorChannels {
|
|
21
|
-
return (
|
|
22
|
-
O.is(value, false) &&
|
|
23
|
-
isRgbChannel(value.r) &&
|
|
24
|
-
isRgbChannel(value.g) &&
|
|
25
|
-
isRgbChannel(value.b) &&
|
|
26
|
-
isAlphaChannel(value.a ?? 1)
|
|
27
|
-
);
|
|
28
|
-
}
|
|
3
|
+
import { fallbackColor, toAlphaChannel, toRgbChannel } from "~/utils";
|
|
29
4
|
|
|
30
5
|
/**
|
|
31
6
|
* Formats the input into a readonly object of color channels.
|
|
@@ -51,7 +26,7 @@ export function toColorChannels(
|
|
|
51
26
|
isTransformed?: boolean,
|
|
52
27
|
isFallback?: boolean
|
|
53
28
|
): Required<ColorChannels> {
|
|
54
|
-
if (
|
|
29
|
+
if (isObject(r, false)) {
|
|
55
30
|
({ r, g, b, a, isTransformed, isFallback } = r);
|
|
56
31
|
}
|
|
57
32
|
|
|
@@ -65,7 +40,7 @@ export function toColorChannels(
|
|
|
65
40
|
|
|
66
41
|
const finalA = toAlphaChannel(a);
|
|
67
42
|
|
|
68
|
-
return
|
|
43
|
+
return Object.freeze({
|
|
69
44
|
r: finalR,
|
|
70
45
|
g: finalG,
|
|
71
46
|
b: finalB,
|
|
@@ -80,5 +55,3 @@ export function toColorChannels(
|
|
|
80
55
|
isFallback: !!isFallback,
|
|
81
56
|
});
|
|
82
57
|
}
|
|
83
|
-
|
|
84
|
-
export const fallbackColor = toColorChannels(0, 0, 0, 1, false, true);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { isNumber, max, round } from "@auaust/primitive-kit/numbers";
|
|
2
|
+
import type { ColorChannels, Hex } from "~/types";
|
|
3
|
+
import { toRgbChannel } from "~/utils";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns the corresponding hex string of a color channels object.
|
|
7
|
+
*
|
|
8
|
+
* If the alpha channel is 1, it will be omitted.
|
|
9
|
+
*/
|
|
10
|
+
export function toHex(channels: ColorChannels): Hex {
|
|
11
|
+
const { r, g, b, a } = channels;
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
"#" +
|
|
15
|
+
(
|
|
16
|
+
(1 << 24) +
|
|
17
|
+
(toRgbChannel(r) << 16) +
|
|
18
|
+
(toRgbChannel(g) << 8) +
|
|
19
|
+
toRgbChannel(b)
|
|
20
|
+
)
|
|
21
|
+
.toString(16)
|
|
22
|
+
.substring(1) +
|
|
23
|
+
(isNumber(a) && a < 1
|
|
24
|
+
? round(max(0, a) * 255)
|
|
25
|
+
.toString(16)
|
|
26
|
+
.padStart(2, "0")
|
|
27
|
+
: "")
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ColorChannels, Rgb } from "~/types";
|
|
2
|
+
import { toAlphaChannel, toRgbChannel } from "~/utils";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns the corresponding RGB tuple of a color channels object.
|
|
6
|
+
*/
|
|
7
|
+
export function toRgb(channels: ColorChannels): Rgb {
|
|
8
|
+
const { r, g, b, a } = channels;
|
|
9
|
+
|
|
10
|
+
return Array.from([r, g, b, a], (value, i) =>
|
|
11
|
+
i === 3 ? toAlphaChannel(value) : toRgbChannel(value)
|
|
12
|
+
);
|
|
13
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Color } from "~/classes/Color";
|
|
2
|
+
import type { ColorType } from "~/types";
|
|
3
|
+
import { isColorChannels, isHex, isNamedColor, isRgb } from "~/utils";
|
|
4
|
+
|
|
5
|
+
/** Returns the color type of the value, or undefined if it's not a color. */
|
|
6
|
+
export function type(value: unknown): ColorType | undefined {
|
|
7
|
+
if (!value) {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (value instanceof Color) {
|
|
12
|
+
return "color";
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (isNamedColor(value)) {
|
|
16
|
+
return "named";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (isHex(value)) {
|
|
20
|
+
return "hex";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (isRgb(value)) {
|
|
24
|
+
return "rgb";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (isColorChannels(value)) {
|
|
28
|
+
return "channels";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
package/src/utils/colors.ts
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { Color } from "~/classes/Color";
|
|
2
|
-
import type { ColorChannels, ColorType, ColorValue } from "~/types";
|
|
3
|
-
import { fallbackColor, isColorChannels } from "./channels";
|
|
4
|
-
import { isHex, parseHex } from "./hex";
|
|
5
|
-
import { isNamedColor, parseNamedColor } from "./namedColors";
|
|
6
|
-
import { couldBeRgb, isRgb, parseRgb } from "./rgb";
|
|
7
|
-
import { channels } from "./symbols";
|
|
8
|
-
|
|
9
|
-
/** Returns true if the value is any format of supported color. */
|
|
10
|
-
export function isColor(value: unknown): value is ColorValue {
|
|
11
|
-
return type(value) !== undefined;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/** Returns the color type of the value, or undefined if it's not a color. */
|
|
15
|
-
export function type(value: unknown): ColorType | undefined {
|
|
16
|
-
if (!value) {
|
|
17
|
-
return undefined;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (value instanceof Color) {
|
|
21
|
-
return "color";
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (isNamedColor(value)) {
|
|
25
|
-
return "named";
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (isHex(value)) {
|
|
29
|
-
return "hex";
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (isRgb(value)) {
|
|
33
|
-
return "rgb";
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (isColorChannels(value)) {
|
|
37
|
-
return "channels";
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return undefined;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** Tries to parse the value as a color. If it fails, returns the fallback color. */
|
|
44
|
-
export function parseColor(value: unknown): ColorChannels {
|
|
45
|
-
if (!value) {
|
|
46
|
-
return fallbackColor;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (value instanceof Color) {
|
|
50
|
-
return value[channels];
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (isColorChannels(value)) {
|
|
54
|
-
return value;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (isNamedColor(value)) {
|
|
58
|
-
return parseNamedColor(value);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (isHex(value)) {
|
|
62
|
-
return parseHex(value);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (couldBeRgb(value)) {
|
|
66
|
-
// It might not be a valid RGB, in which case `parseRgb` is responsible for returning the fallback color
|
|
67
|
-
// In case more color types are added, it might be required to only return the result of `parseRgb` if `isFallback` is false
|
|
68
|
-
return parseRgb(value);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return fallbackColor;
|
|
72
|
-
}
|
package/src/utils/hex.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { N, S } from "@auaust/primitive-kit";
|
|
2
|
-
import type { ColorChannels, Hex } from "~/types";
|
|
3
|
-
import { toColorChannels, toRgbChannel } from "./channels";
|
|
4
|
-
|
|
5
|
-
const hexadecimalRegex = /^[0-9a-f]+$/i;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Whether the input is a valid HEX color. With or without the alpha channel, and with single or double digits.
|
|
9
|
-
*
|
|
10
|
-
* It may or may not start with a hash character, which will be ignored.
|
|
11
|
-
*/
|
|
12
|
-
export function isHex(value: unknown): value is Hex {
|
|
13
|
-
value = S.is(value) && (value.startsWith("#") ? value.slice(1) : value);
|
|
14
|
-
|
|
15
|
-
if (!S.isStrict(value)) {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
switch (value.length) {
|
|
20
|
-
case 3: // RGB
|
|
21
|
-
case 4: // RGBA
|
|
22
|
-
case 6: // RRGGBB
|
|
23
|
-
case 8: // RRGGBBAA
|
|
24
|
-
return hexadecimalRegex.test(value);
|
|
25
|
-
default:
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Parses a hex string into an object of color channels.
|
|
32
|
-
*
|
|
33
|
-
* The input must already be a valid HEX color, otherwise the result will be unexpected.
|
|
34
|
-
*/
|
|
35
|
-
export function parseHex(value: Hex): ColorChannels {
|
|
36
|
-
value = value.startsWith("#") ? value.slice(1) : value;
|
|
37
|
-
|
|
38
|
-
const isShort = value.length < 6;
|
|
39
|
-
const hasAlpha = isShort ? value.length === 4 : value.length === 8;
|
|
40
|
-
|
|
41
|
-
const r = parseInt(isShort ? value[0].repeat(2) : value.slice(0, 2), 16);
|
|
42
|
-
const g = parseInt(isShort ? value[1].repeat(2) : value.slice(2, 4), 16);
|
|
43
|
-
const b = parseInt(isShort ? value[2].repeat(2) : value.slice(4, 6), 16);
|
|
44
|
-
const a = hasAlpha
|
|
45
|
-
? parseInt(isShort ? value[3].repeat(2) : value.slice(6, 8), 16) / 255
|
|
46
|
-
: 1;
|
|
47
|
-
|
|
48
|
-
return toColorChannels(r, g, b, a);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Returns the corresponding hex string of a color channels object.
|
|
53
|
-
*
|
|
54
|
-
* If the alpha channel is 1, it will be omitted.
|
|
55
|
-
*/
|
|
56
|
-
export function toHex(channels: ColorChannels): Hex {
|
|
57
|
-
const { r, g, b, a } = channels;
|
|
58
|
-
|
|
59
|
-
return (
|
|
60
|
-
"#" +
|
|
61
|
-
(
|
|
62
|
-
(1 << 24) +
|
|
63
|
-
(toRgbChannel(r) << 16) +
|
|
64
|
-
(toRgbChannel(g) << 8) +
|
|
65
|
-
toRgbChannel(b)
|
|
66
|
-
)
|
|
67
|
-
.toString(16)
|
|
68
|
-
.substring(1) +
|
|
69
|
-
(N.is(a) && a < 1
|
|
70
|
-
? N.round(N.max(0, a) * 255)
|
|
71
|
-
.toString(16)
|
|
72
|
-
.padStart(2, "0")
|
|
73
|
-
: "")
|
|
74
|
-
);
|
|
75
|
-
}
|
package/src/utils/opacity.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { ColorChannels } from "~/types";
|
|
2
|
-
|
|
3
|
-
/** Checks if the color is fully opaque. */
|
|
4
|
-
export function isOpaque(channels: ColorChannels) {
|
|
5
|
-
return channels.a === 1 || channels.a == undefined;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
/** Checks if the color is fully transparent. */
|
|
9
|
-
export function isTransparent(channels: ColorChannels) {
|
|
10
|
-
return channels.a === 0;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/** Checks if the color is at least partially transparent. */
|
|
14
|
-
export function isTranslucent(channels: ColorChannels) {
|
|
15
|
-
return !isOpaque(channels);
|
|
16
|
-
}
|