@oscarpalmer/atoms 0.188.0 → 0.189.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.
Files changed (130) hide show
  1. package/dist/array/difference.d.mts +0 -1
  2. package/dist/array/exists.d.mts +0 -1
  3. package/dist/array/filter.d.mts +0 -1
  4. package/dist/array/find.d.mts +0 -1
  5. package/dist/array/first.d.mts +0 -1
  6. package/dist/array/flatten.d.mts +0 -1
  7. package/dist/array/get.d.mts +0 -1
  8. package/dist/array/group-by.d.mts +0 -1
  9. package/dist/array/last.d.mts +0 -1
  10. package/dist/array/match.d.mts +0 -1
  11. package/dist/array/match.mjs +3 -3
  12. package/dist/array/move.d.mts +0 -1
  13. package/dist/array/partition.d.mts +0 -1
  14. package/dist/array/select.d.mts +0 -1
  15. package/dist/array/select.mjs +2 -1
  16. package/dist/array/single.d.mts +0 -1
  17. package/dist/array/slice.d.mts +0 -1
  18. package/dist/array/sort.d.mts +1 -2
  19. package/dist/array/sort.mjs +0 -1
  20. package/dist/array/swap.d.mts +0 -1
  21. package/dist/array/to-map.d.mts +0 -1
  22. package/dist/array/to-record.d.mts +0 -1
  23. package/dist/array/to-set.d.mts +0 -1
  24. package/dist/array/toggle.d.mts +0 -1
  25. package/dist/array/unique.d.mts +0 -1
  26. package/dist/array/update.d.mts +0 -1
  27. package/dist/color/constants.d.mts +9 -10
  28. package/dist/color/constants.mjs +15 -7
  29. package/dist/color/index.d.mts +9 -9
  30. package/dist/color/index.mjs +8 -7
  31. package/dist/color/instance.d.mts +35 -8
  32. package/dist/color/instance.mjs +53 -13
  33. package/dist/color/misc/alpha.d.mts +0 -1
  34. package/dist/color/misc/alpha.mjs +5 -5
  35. package/dist/color/misc/get.d.mts +42 -13
  36. package/dist/color/misc/get.mjs +45 -24
  37. package/dist/color/misc/index.d.mts +4 -4
  38. package/dist/color/misc/index.mjs +12 -12
  39. package/dist/color/misc/is.d.mts +56 -3
  40. package/dist/color/misc/is.mjs +72 -4
  41. package/dist/color/misc/state.d.mts +2 -2
  42. package/dist/color/misc/state.mjs +79 -43
  43. package/dist/color/models.d.mts +18 -2
  44. package/dist/color/space/hex.d.mts +38 -5
  45. package/dist/color/space/hex.mjs +57 -9
  46. package/dist/color/space/hsl.d.mts +33 -7
  47. package/dist/color/space/hsl.mjs +65 -14
  48. package/dist/color/space/hwb.d.mts +52 -0
  49. package/dist/color/space/hwb.mjs +99 -0
  50. package/dist/color/space/rgb.d.mts +26 -5
  51. package/dist/color/space/rgb.mjs +82 -28
  52. package/dist/function/assert.d.mts +1 -2
  53. package/dist/function/limit.d.mts +0 -1
  54. package/dist/function/memoize.d.mts +0 -1
  55. package/dist/function/once.d.mts +0 -1
  56. package/dist/function/retry.d.mts +0 -1
  57. package/dist/function/work.d.mts +0 -1
  58. package/dist/herald.d.mts +0 -1
  59. package/dist/index.d.mts +296 -51
  60. package/dist/index.mjs +664 -265
  61. package/dist/internal/array/callbacks.d.mts +0 -1
  62. package/dist/internal/array/callbacks.mjs +0 -1
  63. package/dist/internal/array/group.d.mts +0 -1
  64. package/dist/internal/array/index-of.d.mts +0 -1
  65. package/dist/internal/function/timer.d.mts +0 -1
  66. package/dist/internal/is.d.mts +0 -1
  67. package/dist/internal/is.mjs +1 -1
  68. package/dist/internal/math/aggregate.d.mts +0 -1
  69. package/dist/internal/math/misc.d.mts +12 -0
  70. package/dist/internal/math/misc.mjs +19 -0
  71. package/dist/internal/result.d.mts +0 -1
  72. package/dist/internal/value/compare.d.mts +0 -1
  73. package/dist/internal/value/equal.d.mts +0 -1
  74. package/dist/internal/value/get.d.mts +0 -1
  75. package/dist/internal/value/handlers.d.mts +0 -1
  76. package/dist/internal/value/has.d.mts +0 -1
  77. package/dist/internal/value/misc.d.mts +0 -1
  78. package/dist/internal/value/set.d.mts +0 -1
  79. package/dist/is.d.mts +0 -1
  80. package/dist/math.d.mts +1 -9
  81. package/dist/math.mjs +1 -16
  82. package/dist/models.d.mts +6 -6
  83. package/dist/promise/delay.d.mts +0 -1
  84. package/dist/promise/helpers.d.mts +0 -1
  85. package/dist/promise/index.d.mts +0 -1
  86. package/dist/promise/misc.d.mts +0 -1
  87. package/dist/promise/models.d.mts +4 -5
  88. package/dist/promise/models.mjs +1 -1
  89. package/dist/promise/timed.d.mts +0 -1
  90. package/dist/query.d.mts +0 -1
  91. package/dist/query.mjs +1 -1
  92. package/dist/queue.d.mts +0 -1
  93. package/dist/random.d.mts +0 -1
  94. package/dist/result/index.d.mts +0 -1
  95. package/dist/result/index.mjs +2 -1
  96. package/dist/result/match.d.mts +0 -1
  97. package/dist/result/misc.d.mts +0 -1
  98. package/dist/result/models.d.mts +0 -1
  99. package/dist/result/work/flow.d.mts +0 -1
  100. package/dist/result/work/pipe.d.mts +0 -1
  101. package/dist/string/fuzzy.d.mts +0 -1
  102. package/dist/string/index.d.mts +0 -1
  103. package/dist/string/index.mjs +8 -7
  104. package/dist/string/template.d.mts +0 -1
  105. package/dist/value/clone.d.mts +0 -1
  106. package/dist/value/freeze.d.mts +1 -2
  107. package/dist/value/merge.d.mts +0 -1
  108. package/dist/value/omit.d.mts +0 -1
  109. package/dist/value/pick.d.mts +0 -1
  110. package/dist/value/shake.d.mts +1 -2
  111. package/dist/value/smush.d.mts +1 -2
  112. package/dist/value/transform.d.mts +1 -2
  113. package/dist/value/unsmush.d.mts +1 -2
  114. package/package.json +5 -5
  115. package/src/color/constants.ts +17 -13
  116. package/src/color/index.ts +21 -6
  117. package/src/color/instance.ts +67 -14
  118. package/src/color/misc/alpha.ts +6 -10
  119. package/src/color/misc/get.ts +70 -16
  120. package/src/color/misc/index.ts +18 -17
  121. package/src/color/misc/is.ts +86 -3
  122. package/src/color/misc/state.ts +126 -40
  123. package/src/color/models.ts +19 -1
  124. package/src/color/space/hex.ts +55 -8
  125. package/src/color/space/hsl.ts +80 -14
  126. package/src/color/space/hwb.ts +123 -0
  127. package/src/color/space/rgb.ts +108 -27
  128. package/src/internal/math/misc.ts +28 -0
  129. package/src/math.ts +2 -29
  130. package/src/string/index.ts +13 -11
@@ -1,4 +1,4 @@
1
- import type {Alpha, ColorProperty, ColorSpace, HSLColor, RGBColor} from './models';
1
+ import type {Alpha, HSLAColor, HSLColor, HWBAColor, HWBColor, RGBAColor, RGBColor} from './models';
2
2
 
3
3
  // #region Variables
4
4
 
@@ -6,21 +6,25 @@ export const ALPHA_FULL_HEX_SHORT = 'f';
6
6
 
7
7
  export const ALPHA_FULL_HEX_LONG = `${ALPHA_FULL_HEX_SHORT}${ALPHA_FULL_HEX_SHORT}`;
8
8
 
9
- export const ALPHA_FULL_VALUE = 1;
10
-
11
9
  export const ALPHA_NONE_HEX = '00';
12
10
 
13
11
  export const ALPHA_NONE_VALUE = 0;
14
12
 
15
13
  export const DEFAULT_ALPHA: Alpha = {
16
14
  hex: ALPHA_FULL_HEX_LONG,
17
- value: ALPHA_FULL_VALUE,
15
+ value: 100,
18
16
  };
19
17
 
20
18
  export const DEFAULT_HSL: HSLColor = {
21
19
  hue: 0,
22
- lightness: 0,
23
20
  saturation: 0,
21
+ lightness: 0,
22
+ };
23
+
24
+ export const DEFAULT_HWB: HWBColor = {
25
+ hue: 0,
26
+ whiteness: 0,
27
+ blackness: 100,
24
28
  };
25
29
 
26
30
  export const DEFAULT_RGB: RGBColor = {
@@ -43,13 +47,17 @@ export const LENGTH_LONG = 6;
43
47
 
44
48
  export const LENGTH_SHORT = 3;
45
49
 
46
- export const KEYS_HSL: ColorProperty[] = ['hue', 'saturation', 'lightness'];
50
+ export const KEYS_HSL: Array<keyof HSLColor> = ['hue', 'saturation', 'lightness'];
51
+
52
+ export const KEYS_HSLA: Array<keyof HSLAColor> = [...KEYS_HSL, 'alpha'];
53
+
54
+ export const KEYS_HWB: Array<keyof HWBColor> = ['hue', 'whiteness', 'blackness'];
47
55
 
48
- export const KEYS_HSLA: ColorProperty[] = [...KEYS_HSL, 'alpha'];
56
+ export const KEYS_HWBA: Array<keyof HWBAColor> = [...KEYS_HWB, 'alpha'];
49
57
 
50
- export const KEYS_RGB: ColorProperty[] = ['red', 'green', 'blue'];
58
+ export const KEYS_RGB: Array<keyof RGBColor> = ['red', 'green', 'blue'];
51
59
 
52
- export const KEYS_RGBA: ColorProperty[] = [...KEYS_RGB, 'alpha'];
60
+ export const KEYS_RGBA: Array<keyof RGBAColor> = [...KEYS_RGB, 'alpha'];
53
61
 
54
62
  export const MAX_DEGREE = 360;
55
63
 
@@ -57,10 +65,6 @@ export const MAX_HEX = 255;
57
65
 
58
66
  export const MAX_PERCENT = 100;
59
67
 
60
- export const SPACE_HSL: ColorSpace = 'hsl';
61
-
62
- export const SPACE_RGB: ColorSpace = 'rgb';
63
-
64
68
  // https://www.w3.org/TR/WCAG20/#relativeluminancedef
65
69
 
66
70
  export const SRGB_LUMINANCE_BLUE = 0.0722;
@@ -1,13 +1,13 @@
1
1
  import {Color} from './instance';
2
2
  import {isColor} from './misc/is';
3
- import type {HSLAColor, HSLColor, RGBAColor, RGBColor} from './models';
3
+ import type {HSLAColor, HSLColor, HWBColor, HWBAColor, RGBAColor, RGBColor} from './models';
4
4
 
5
5
  // #region Functions
6
6
 
7
7
  /**
8
8
  * Get a _Color_ from any kind of value
9
9
  *
10
- * - Values that can be parsed are: hex(a) color strings, _HSL(A)_ color objects, and _RGB(A)_ color objects
10
+ * - Values that can be parsed are: hex(a) color strings, as well as _HSL(A)_, _HWB(A)_, and _RGB(A)_ color objects
11
11
  * - If the value is unable to be parsed, a black _Color_ will be returned
12
12
  *
13
13
  * @param value Original value
@@ -27,6 +27,8 @@ export {
27
27
  getHexColor,
28
28
  getHslaColor,
29
29
  getHslColor,
30
+ getHwbColor,
31
+ getHwbaColor,
30
32
  getRgbaColor,
31
33
  getRgbColor,
32
34
  } from './misc/get';
@@ -37,14 +39,27 @@ export {
37
39
  isHslColor,
38
40
  isHslLike,
39
41
  isHslaColor,
42
+ isHwbColor,
43
+ isHwbLike,
44
+ isHwbaColor,
45
+ isHwbaLike,
40
46
  isRgbColor,
41
47
  isRgbLike,
42
48
  isRgbaColor,
43
49
  } from './misc/is';
44
50
 
45
- export {getNormalizedHex, hexToHsl, hexToHsla, hexToRgb, hexToRgba} from './space/hex';
46
- export {hslToHex, hslToRgb, hslToRgba} from './space/hsl';
47
- export {rgbToHex, rgbToHsl, rgbToHsla} from './space/rgb';
48
- export type {Color, HSLAColor, HSLColor, RGBAColor, RGBColor};
51
+ export {
52
+ getNormalizedHex,
53
+ hexToHsl,
54
+ hexToHsla,
55
+ hexToHwb,
56
+ hexToHwba,
57
+ hexToRgb,
58
+ hexToRgba,
59
+ } from './space/hex';
60
+ export {hslToHex, hslToHwb, hslToHwba, hslToRgb, hslToRgba} from './space/hsl';
61
+ export {hwbToHex, hwbToHsl, hwbToHsla, hwbToRgb, hwbToRgba} from './space/hwb';
62
+ export {rgbToHex, rgbToHsl, rgbToHsla, rgbToHwb, rgbToHwba} from './space/rgb';
63
+ export type {Color, HSLAColor, HSLColor, HWBAColor, HWBColor, RGBAColor, RGBColor};
49
64
 
50
65
  // #endregion
@@ -1,8 +1,15 @@
1
- import {SPACE_HSL, SPACE_RGB} from './constants';
2
- import {formatColor} from './misc';
1
+ import {formatHslColor, formatHwbColor, formatRgbColor} from './misc';
3
2
  import {getAlpha} from './misc/alpha';
4
- import {getColorState, setHexColor, setHSLColor, setRGBColor} from './misc/state';
5
- import type {ColorState, HSLAColor, HSLColor, RGBAColor, RGBColor} from './models';
3
+ import {getColorState, setHexColor, setHSLColor, setHWBColor, setRGBColor} from './misc/state';
4
+ import type {
5
+ ColorState,
6
+ HSLAColor,
7
+ HSLColor,
8
+ HWBAColor,
9
+ HWBColor,
10
+ RGBAColor,
11
+ RGBColor,
12
+ } from './models';
6
13
 
7
14
  // #region Types
8
15
 
@@ -20,19 +27,16 @@ export class Color {
20
27
  readonly #state: ColorState;
21
28
 
22
29
  /**
23
- * Get the alpha channel _(opacity)_ of the color
30
+ * Get the alpha channel _(opacity)_ of the color as a percentage between `0` and `100`
24
31
  *
25
- * @returns Current alpha channel value between `0` and `1`
32
+ * @returns Current alpha channel value
26
33
  */
27
34
  get alpha(): number {
28
35
  return this.#state.alpha.value;
29
36
  }
30
37
 
31
38
  /**
32
- * Set the alpha channel _(opacity)_ of the color, as:
33
- *
34
- * - A number between `0` and `1`, where `0` is fully transparent and `1` is fully opaque
35
- * - A number between `0` and `100`, where `0` is fully transparent and `100` is fully opaque
39
+ * Set the alpha channel _(opacity)_ of the color as a percentage between `0` and `100`
36
40
  *
37
41
  * @param value New alpha channel value
38
42
  */
@@ -94,7 +98,7 @@ export class Color {
94
98
  * @returns Current color as an _HSL_ color
95
99
  */
96
100
  get hsl(): HSLColor {
97
- return this.#state.hsl;
101
+ return {...this.#state.hsl};
98
102
  }
99
103
 
100
104
  /**
@@ -127,13 +131,52 @@ export class Color {
127
131
  setHSLColor(this.#state, value, true);
128
132
  }
129
133
 
134
+ /**
135
+ * Get the color as an _HWB_ color
136
+ *
137
+ * @returns Current color as an _HWB_ color
138
+ */
139
+ get hwb(): HWBColor {
140
+ return {...this.#state.hwb};
141
+ }
142
+
143
+ /**
144
+ * Set colors from an _HWB_ color
145
+ *
146
+ * @param value New _HWB_ color
147
+ */
148
+ set hwb(value: HWBColor) {
149
+ setHWBColor(this.#state, value, false);
150
+ }
151
+
152
+ /**
153
+ * Get the color as an _HWBA_ color
154
+ *
155
+ * @returns Current color as an _HWBA_ color
156
+ */
157
+ get hwba(): HWBAColor {
158
+ return {
159
+ ...this.#state.hwb,
160
+ alpha: this.#state.alpha.value,
161
+ };
162
+ }
163
+
164
+ /**
165
+ * Set colors and alpha from an _HWBA_ color
166
+ *
167
+ * @param value New _HWBA_ color
168
+ */
169
+ set hwba(value: HWBAColor) {
170
+ setHWBColor(this.#state, value, true);
171
+ }
172
+
130
173
  /**
131
174
  * Get the color as an _RGB_ color
132
175
  *
133
176
  * @returns Current color as an _RGB_ color
134
177
  */
135
178
  get rgb(): RGBColor {
136
- return this.#state.rgb;
179
+ return {...this.#state.rgb};
137
180
  }
138
181
 
139
182
  /**
@@ -191,7 +234,17 @@ export class Color {
191
234
  * @returns _HSL(A)_ color string
192
235
  */
193
236
  toHslString(alpha?: boolean): string {
194
- return formatColor(SPACE_HSL, this, alpha === true);
237
+ return formatHslColor(this, alpha === true);
238
+ }
239
+
240
+ /**
241
+ * Get the color as an _HWB(A)_ string
242
+ *
243
+ * @param alpha Include alpha channel _(opacity)_? _(defaults to `false`)_
244
+ * @returns _HWB(A)_ color string
245
+ */
246
+ toHwbString(alpha?: boolean): string {
247
+ return formatHwbColor(this, alpha === true);
195
248
  }
196
249
 
197
250
  /**
@@ -201,7 +254,7 @@ export class Color {
201
254
  * @returns _RGB(A)_ color string
202
255
  */
203
256
  toRgbString(alpha?: boolean): string {
204
- return formatColor(SPACE_RGB, this, alpha === true);
257
+ return formatRgbColor(this, alpha === true);
205
258
  }
206
259
 
207
260
  /**
@@ -1,6 +1,6 @@
1
+ import {round} from '../../internal/math/misc';
1
2
  import {
2
3
  ALPHA_FULL_HEX_LONG,
3
- ALPHA_FULL_VALUE,
4
4
  ALPHA_NONE_HEX,
5
5
  ALPHA_NONE_VALUE,
6
6
  DEFAULT_ALPHA,
@@ -31,11 +31,11 @@ export function getAlphaHexadecimal(value: number): string {
31
31
  return ALPHA_NONE_HEX;
32
32
  }
33
33
 
34
- if (value === ALPHA_FULL_VALUE) {
34
+ if (value === MAX_PERCENT) {
35
35
  return ALPHA_FULL_HEX_LONG;
36
36
  }
37
37
 
38
- return Math.round(value * MAX_HEX).toString(16);
38
+ return round(value * MAX_HEX).toString(16);
39
39
  }
40
40
 
41
41
  function getAlphaFromValue(value: number): Alpha {
@@ -48,15 +48,11 @@ function getAlphaFromValue(value: number): Alpha {
48
48
  }
49
49
 
50
50
  export function getAlphaValue(original: number): number {
51
- if (Number.isNaN(original) || original >= MAX_PERCENT || original === ALPHA_FULL_VALUE) {
52
- return ALPHA_FULL_VALUE;
51
+ if (Number.isNaN(original) || original >= MAX_PERCENT) {
52
+ return MAX_PERCENT;
53
53
  }
54
54
 
55
- if (original < ALPHA_NONE_VALUE) {
56
- return ALPHA_NONE_VALUE;
57
- }
58
-
59
- return original <= ALPHA_FULL_VALUE ? original : original / MAX_PERCENT;
55
+ return original <= ALPHA_NONE_VALUE ? ALPHA_NONE_VALUE : original;
60
56
  }
61
57
 
62
58
  // #endregion
@@ -1,3 +1,4 @@
1
+ import {round} from '../../internal/math/misc';
1
2
  import {clamp} from '../../number';
2
3
  import {
3
4
  HEX_BLACK,
@@ -16,25 +17,45 @@ import {
16
17
  SRGB_LUMINANCE_THRESHOLD,
17
18
  } from '../constants';
18
19
  import {Color} from '../instance';
19
- import type {HSLAColor, HSLColor, RGBAColor, RGBColor} from '../models';
20
+ import type {HSLAColor, HSLColor, HWBAColor, HWBColor, RGBAColor, RGBColor} from '../models';
20
21
  import {getColorState} from './state';
21
22
 
22
23
  // #region Functions
23
24
 
24
- function getClampedValue(value: unknown, minimum: number, maximum: number): number {
25
- return typeof value === 'number' ? clamp(value, minimum, maximum) : minimum;
25
+ function getClampedValue(
26
+ value: unknown,
27
+ minimum: number,
28
+ maximum: number,
29
+ rounding?: boolean,
30
+ ): number {
31
+ return typeof value === 'number' && !Number.isNaN(value)
32
+ ? clamp((rounding ?? false) ? round(value) : value, minimum, maximum)
33
+ : minimum;
26
34
  }
27
35
 
36
+ /**
37
+ * Get a foreground color _(usually text)_ based on a background color's luminance as an unprefixed hex color string
38
+ *
39
+ * - Values that can be parsed are: hex(a) color strings, as well as _HSL(A)_, _HWB(A)_, and _RGB(A)_ color objects
40
+ * - If the value cannot be parsed, a white foreground color will be returned
41
+ *
42
+ * @param value Original value
43
+ * @returns Foreground color
44
+ */
45
+ export function getForegroundColor(value: unknown, hex: true): string;
46
+
28
47
  /**
29
48
  * Get a foreground color _(usually text)_ based on a background color's luminance
30
49
  *
31
- * - Values that can be parsed are: hex(a) color strings, _HSL(A)_ color objects, and _RGB(A)_ color objects
50
+ * - Values that can be parsed are: hex(a) color strings, as well as _HSL(A)_, _HWB(A)_, and _RGB(A)_ color objects
32
51
  * - If the value cannot be parsed, a white foreground color will be returned
33
52
  *
34
53
  * @param value Original value
35
54
  * @returns Foreground color
36
55
  */
37
- export function getForegroundColor(value: unknown): Color {
56
+ export function getForegroundColor(value: unknown): Color;
57
+
58
+ export function getForegroundColor(value: unknown, hex?: unknown): string | Color {
38
59
  const state = getColorState(value);
39
60
  const {blue, green, red} = state.rgb;
40
61
 
@@ -58,14 +79,16 @@ export function getForegroundColor(value: unknown): Color {
58
79
  SRGB_LUMINANCE_BLUE * values[0];
59
80
 
60
81
  // Rudimentary and ureliable?; implement APCA for more reliable results?
61
- return new Color(luminance > SRGB_LUMINANCE_THRESHOLD ? HEX_BLACK : HEX_WHITE);
82
+ const color = luminance > SRGB_LUMINANCE_THRESHOLD ? HEX_BLACK : HEX_WHITE;
83
+
84
+ return hex === true ? color : new Color(color);
62
85
  }
63
86
 
64
87
  /**
65
88
  * Get the hex color _(with alpha channel, i.e., opacity)_ from any kind of value
66
89
  *
67
- * - Values that can be parsed are: hex(a) color strings, _HSL(A)_ color objects, and _RGB(A)_ color objects
68
- * - If the value cannot be parsed, a black hex color with an alpha channel of `0` will be returned
90
+ * - Values that can be parsed are: hex(a) color strings, as well as _HSL(A)_, _HWB(A)_, and _RGB(A)_ color objects
91
+ * - If the value cannot be parsed, a black hex color will be returned
69
92
  *
70
93
  * @param value Original value
71
94
  * @returns Hex color string
@@ -79,7 +102,7 @@ export function getHexaColor(value: unknown): string {
79
102
  /**
80
103
  * Get the hex color from any kind of value
81
104
  *
82
- * - Values that can be parsed are: hex(a) color strings, _HSL(A)_ color objects, and _RGB(A)_ color objects
105
+ * - Values that can be parsed are: hex(a) color strings, as well as _HSL(A)_, _HWB(A)_, and _RGB(A)_ color objects
83
106
  * - If the value cannot be parsed, a black hex color will be returned
84
107
  *
85
108
  * @param value Original value
@@ -90,7 +113,7 @@ export function getHexColor(value: unknown): string {
90
113
  }
91
114
 
92
115
  export function getHexValue(value: unknown): number {
93
- return getClampedValue(value, 0, MAX_HEX);
116
+ return getClampedValue(value, 0, MAX_HEX, true);
94
117
  }
95
118
 
96
119
  export function getDegrees(value: unknown): number {
@@ -100,8 +123,8 @@ export function getDegrees(value: unknown): number {
100
123
  /**
101
124
  * Get the _HSLA_ color from any kind of value
102
125
  *
103
- * - Values that can be parsed are: hex(a) color strings, _HSL(A)_ color objects, and _RGB(A)_ color objects
104
- * - If the value cannot be parsed, a black _HSLA_ color with an alpha channel _(opacity)_ of `0` will be returned
126
+ * - Values that can be parsed are: hex(a) color strings, as well as _HSL(A)_, _HWB(A)_, and _RGB(A)_ color objects
127
+ * - If the value cannot be parsed, a black _HSLA_ color will be returned
105
128
  *
106
129
  * @param value Original value
107
130
  * @returns _HSLA_ color
@@ -115,10 +138,41 @@ export function getHslaColor(value: unknown): HSLAColor {
115
138
  };
116
139
  }
117
140
 
141
+ /**
142
+ * Get the _HWB_ color from any kind of value
143
+ *
144
+ * - Values that can be parsed are: hex(a) color strings, as well as _HSL(A)_, _HWB(A)_, and _RGB(A)_ color objects
145
+ * - If the value cannot be parsed, a black _HWB_ color will be returned
146
+ *
147
+ * @param value Original value
148
+ * @returns _HWB_ color
149
+ */
150
+ export function getHwbColor(value: unknown): HWBColor {
151
+ return getColorState(value).hwb;
152
+ }
153
+
154
+ /**
155
+ * Get the _HWBA_ color from any kind of value
156
+ *
157
+ * - Values that can be parsed are: hex(a) color strings, as well as _HSL(A)_, _HWB(A)_, and _RGB(A)_ color objects
158
+ * - If the value cannot be parsed, a black _HWBA_ color will be returned
159
+ *
160
+ * @param value Original value
161
+ * @returns _HWBA_ color
162
+ */
163
+ export function getHwbaColor(value: unknown): HWBAColor {
164
+ const {alpha, hwb} = getColorState(value);
165
+
166
+ return {
167
+ ...hwb,
168
+ alpha: alpha.value,
169
+ };
170
+ }
171
+
118
172
  /**
119
173
  * Get the _HSL_ color from any kind of value
120
174
  *
121
- * - Values that can be parsed are: hex(a) color strings, _HSL(A)_ color objects, and _RGB(A)_ color objects
175
+ * - Values that can be parsed are: hex(a) color strings, as well as _HSL(A)_, _HWB(A)_, and _RGB(A)_ color objects
122
176
  * - If the value cannot be parsed, a black _HSL_ color will be returned
123
177
  *
124
178
  * @param value Original value
@@ -135,8 +189,8 @@ export function getPercentage(value: unknown): number {
135
189
  /**
136
190
  * Get the _RGBA_ color from any kind of value
137
191
  *
138
- * - Values that can be parsed are: hex(a) color strings, _HSL(A)_ color objects, and _RGB(A)_ color objects
139
- * - If the value cannot be parsed, a black _RGBA_ color with an alpha channel _(opacity)_ of `0` will be returned
192
+ * - Values that can be parsed are: hex(a) color strings, as well as _HSL(A)_, _HWB(A)_, and _RGB(A)_ color objects
193
+ * - If the value cannot be parsed, a black _RGBA_ color will be returned
140
194
  *
141
195
  * @param value Original value
142
196
  * @returns _RGBA_ color
@@ -153,7 +207,7 @@ export function getRgbaColor(value: unknown): RGBAColor {
153
207
  /**
154
208
  * Get the _RGB_ color from any kind of value
155
209
  *
156
- * - Values that can be parsed are: hex(a) color strings, _HSL(A)_ color objects, and _RGB(A)_ color objects
210
+ * - Values that can be parsed are: hex(a) color strings, as well as _HSL(A)_, _HWB(A)_, and _RGB(A)_ color objects
157
211
  * - If the value cannot be parsed, a black _RGB_ color will be returned
158
212
  *
159
213
  * @param value Original value
@@ -1,29 +1,30 @@
1
- import {join} from '../../internal/string';
2
- import {KEYS_HSL, KEYS_RGB} from '../constants';
1
+ import {round} from '../../internal/math/misc';
3
2
  import type {Color} from '../instance';
4
- import type {ColorProperty, ColorSpace} from '../models';
5
3
 
6
4
  // #region Functions
7
5
 
8
- export function formatColor(space: ColorSpace, color: Color, alpha: boolean): string {
9
- const suffix = alpha ? ` / ${color.alpha}` : '';
10
- const value = color[space];
6
+ export function formatHslColor(color: Color, alpha: boolean): string {
7
+ const {hue, lightness, saturation} = color.hsl;
11
8
 
12
- return `${space}(${join(
13
- keys[space].map(key => value[key as never]),
14
- SPACE,
15
- )}${suffix})`;
9
+ const suffix = alpha ? ` / ${color.alpha}%` : '';
10
+
11
+ return `hsl(${hue}deg ${saturation}% ${lightness}%${suffix})`;
16
12
  }
17
13
 
18
- // #endregion
14
+ export function formatHwbColor(color: Color, alpha: boolean): string {
15
+ const {blackness, hue, whiteness} = color.hwb;
16
+
17
+ const suffix = alpha ? ` / ${color.alpha}%` : '';
19
18
 
20
- // #region Variables
19
+ return `hwb(${hue}deg ${whiteness}% ${blackness}%${suffix})`;
20
+ }
21
+
22
+ export function formatRgbColor(color: Color, alpha: boolean): string {
23
+ const {blue, green, red} = color.rgb;
21
24
 
22
- const SPACE = ' ';
25
+ const suffix = alpha ? ` / ${color.alpha}%` : '';
23
26
 
24
- const keys: Record<ColorSpace, ColorProperty[]> = {
25
- hsl: KEYS_HSL,
26
- rgb: KEYS_RGB,
27
- };
27
+ return `rgb(${red} ${green} ${blue}${suffix})`;
28
+ }
28
29
 
29
30
  // #endregion
@@ -1,12 +1,13 @@
1
1
  import {between} from '../../internal/number';
2
2
  import type {PlainObject} from '../../models';
3
3
  import {
4
- ALPHA_FULL_VALUE,
5
4
  ALPHA_NONE_VALUE,
6
5
  EXPRESSION_HEX_LONG,
7
6
  EXPRESSION_HEX_SHORT,
8
7
  KEYS_HSL,
9
8
  KEYS_HSLA,
9
+ KEYS_HWB,
10
+ KEYS_HWBA,
10
11
  KEYS_RGB,
11
12
  KEYS_RGBA,
12
13
  LENGTH_LONG,
@@ -16,7 +17,15 @@ import {
16
17
  MAX_PERCENT,
17
18
  } from '../constants';
18
19
  import type {Color} from '../index';
19
- import type {ColorProperty, HSLAColor, HSLColor, RGBAColor, RGBColor} from '../models';
20
+ import type {
21
+ ColorProperty,
22
+ HSLAColor,
23
+ HSLColor,
24
+ HWBAColor,
25
+ HWBColor,
26
+ RGBAColor,
27
+ RGBColor,
28
+ } from '../models';
20
29
 
21
30
  // ##region Functions
22
31
 
@@ -25,7 +34,7 @@ function hasKeys(value: unknown, keys: ColorProperty[]): boolean {
25
34
  }
26
35
 
27
36
  function isAlpha(value: unknown): value is number {
28
- return typeof value === 'number' && between(value, ALPHA_NONE_VALUE, ALPHA_FULL_VALUE);
37
+ return typeof value === 'number' && between(value, ALPHA_NONE_VALUE, MAX_PERCENT);
29
38
  }
30
39
 
31
40
  function isBytey(value: unknown): value is number {
@@ -116,6 +125,16 @@ export function isHslaColor(value: unknown): value is HSLAColor {
116
125
  return isColorValue(value, KEYS_HSLA);
117
126
  }
118
127
 
128
+ /**
129
+ * Is the value like an _HSLA_ color?
130
+ *
131
+ * @param value Value to check
132
+ * @returns `true` if the value is like an _HSLA_ color, otherwise `false`
133
+ */
134
+ export function isHslaLike(value: unknown): value is Record<keyof HSLAColor, unknown> {
135
+ return hasKeys(value, KEYS_HSLA);
136
+ }
137
+
119
138
  /**
120
139
  * Is the value an _HSL_ color?
121
140
  *
@@ -126,10 +145,56 @@ export function isHslColor(value: unknown): value is HSLColor {
126
145
  return isColorValue(value, KEYS_HSLA) || isColorValue(value, KEYS_HSL);
127
146
  }
128
147
 
148
+ /**
149
+ * Is the value like an _HSL_ color?
150
+ *
151
+ * @param value Value to check
152
+ * @returns `true` if the value is like an _HSL_ color, otherwise `false`
153
+ */
129
154
  export function isHslLike(value: unknown): value is Record<keyof HSLColor, unknown> {
130
155
  return hasKeys(value, KEYS_HSL);
131
156
  }
132
157
 
158
+ /**
159
+ * Is the value an _HWBA_ color?
160
+ *
161
+ * @param value Value to check
162
+ * @returns `true` if the value is an _HWBA_ color, otherwise `false`
163
+ */
164
+ export function isHwbaColor(value: unknown): value is HWBAColor {
165
+ return isColorValue(value, KEYS_HWBA);
166
+ }
167
+
168
+ /**
169
+ * Is the value like an _HWBA_ color?
170
+ *
171
+ * @param value Value to check
172
+ * @returns `true` if the value is like an _HWBA_ color, otherwise `false`
173
+ */
174
+ export function isHwbaLike(value: unknown): value is Record<keyof HWBAColor, unknown> {
175
+ return hasKeys(value, KEYS_HWBA);
176
+ }
177
+
178
+ /**
179
+ * Is the value an _HWB_ color?
180
+ *
181
+ * @param value Value to check
182
+ * @returns `true` if the value is an _HWB_ color, otherwise `false`
183
+ */
184
+ export function isHwbColor(value: unknown): value is HWBColor {
185
+ return isColorValue(value, KEYS_HWB) || isColorValue(value, KEYS_HWBA);
186
+ }
187
+
188
+ /**
189
+ * Is the value like an _HWB_ color?
190
+ *
191
+ * @param value Value to check
192
+ * @returns `true` if the value is like an _HWB_ color, otherwise `false`
193
+ */
194
+ export function isHwbLike(value: unknown): value is Record<keyof HWBColor, unknown> {
195
+ return hasKeys(value, KEYS_HWB);
196
+ }
197
+
133
198
  /**
134
199
  * Is the value an _RGBA_ color?
135
200
  *
@@ -140,6 +205,16 @@ export function isRgbaColor(value: unknown): value is RGBAColor {
140
205
  return isColorValue(value, KEYS_RGBA);
141
206
  }
142
207
 
208
+ /**
209
+ * Is the value like an _RGBA_ color?
210
+ *
211
+ * @param value Value to check
212
+ * @returns `true` if the value is like an _RGBA_ color, otherwise `false`
213
+ */
214
+ export function isRgbaLike(value: unknown): value is Record<keyof RGBAColor, unknown> {
215
+ return hasKeys(value, KEYS_RGBA);
216
+ }
217
+
143
218
  /**
144
219
  * Is the value an _RGB_ color?
145
220
  *
@@ -150,6 +225,12 @@ export function isRgbColor(value: unknown): value is RGBColor {
150
225
  return isColorValue(value, KEYS_RGBA) || isColorValue(value, KEYS_RGB);
151
226
  }
152
227
 
228
+ /**
229
+ * Is the value like an _RGB_ color?
230
+ *
231
+ * @param value Value to check
232
+ * @returns `true` if the value is like an _RGB_ color, otherwise `false`
233
+ */
153
234
  export function isRgbLike(value: unknown): value is Record<keyof RGBColor, unknown> {
154
235
  return hasKeys(value, KEYS_RGB);
155
236
  }
@@ -164,12 +245,14 @@ function isPercentage(value: unknown): value is number {
164
245
 
165
246
  const validators: Record<ColorProperty, (value: unknown) => value is number> = {
166
247
  alpha: isAlpha,
248
+ blackness: isPercentage,
167
249
  blue: isBytey,
168
250
  green: isBytey,
169
251
  hue: isDegree,
170
252
  lightness: isPercentage,
171
253
  saturation: isPercentage,
172
254
  red: isBytey,
255
+ whiteness: isPercentage,
173
256
  };
174
257
 
175
258
  // #endregion