@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,40 +1,43 @@
1
1
  import {
2
- ALPHA_FULL_VALUE,
3
2
  DEFAULT_HSL,
3
+ DEFAULT_HWB,
4
4
  DEFAULT_RGB,
5
5
  HEX_BLACK,
6
6
  KEYS_HSL,
7
+ KEYS_HWB,
7
8
  KEYS_RGB,
8
9
  LENGTH_LONG,
10
+ MAX_PERCENT,
9
11
  } from '../constants';
10
- import type {ColorState, HSLAColor, HSLColor, RGBAColor, RGBColor} from '../models';
11
- import {getNormalizedHex, hexToRgb} from '../space/hex';
12
- import {getHslValue, hslToRgb} from '../space/hsl';
13
- import {getRgbValue, rgbToHex, rgbToHsl} from '../space/rgb';
12
+ import type {
13
+ ColorState,
14
+ HSLAColor,
15
+ HSLColor,
16
+ HWBAColor,
17
+ HWBColor,
18
+ RGBAColor,
19
+ RGBColor,
20
+ } from '../models';
21
+ import {getNormalizedHex, hexToHsl, hexToRgb} from '../space/hex';
22
+ import {getHslValue, hslToHex, hslToHwb, hslToRgb} from '../space/hsl';
23
+ import {getHwbValue, hwbToHex, hwbToHsl, hwbToRgb} from '../space/hwb';
24
+ import {getRgbValue, rgbToHex, rgbToHsl, rgbToHwb} from '../space/rgb';
14
25
  import {getAlpha} from './alpha';
15
- import {getHexValue, getDegrees, getPercentage} from './get';
16
- import {isColor, isHexColor, isHslLike, isRgbLike} from './is';
26
+ import {getDegrees, getHexValue, getPercentage} from './get';
27
+ import {isColor, isHexColor, isHslLike, isHwbLike, isRgbLike} from './is';
17
28
 
18
29
  // #region Functions
19
30
 
20
31
  export function getColorState(value: unknown): ColorState {
21
32
  if (typeof value === 'string') {
22
- const normalized = getNormalizedHex(value, true);
23
- const hex = normalized.slice(0, LENGTH_LONG);
24
- const rgb = hexToRgb(hex);
25
-
26
- return {
27
- hex,
28
- rgb,
29
- alpha: getAlpha(normalized.slice(LENGTH_LONG)),
30
- hsl: rgbToHsl(rgb),
31
- };
33
+ return getColorStateForHex(value);
32
34
  }
33
35
 
34
36
  if (isColor(value)) {
35
37
  return {
36
38
  hex: value.hex,
37
39
  hsl: value.hsl,
40
+ hwb: value.hwb,
38
41
  rgb: value.rgb,
39
42
  alpha: getAlpha(value.alpha),
40
43
  };
@@ -46,26 +49,81 @@ export function getColorState(value: unknown): ColorState {
46
49
  state.alpha = getAlpha((value as HSLAColor).alpha);
47
50
 
48
51
  if (KEYS_HSL.every(key => key in value)) {
49
- state.hsl = getHslValue(value as Record<keyof HSLColor, unknown>);
50
- state.rgb = hslToRgb(state.hsl as HSLColor);
51
- state.hex = rgbToHex(state.rgb as RGBColor);
52
+ return getColorStateForHsl(state, value as Record<keyof HSLColor, unknown>);
53
+ }
52
54
 
53
- return state as ColorState;
55
+ if (KEYS_HWB.every(key => key in value)) {
56
+ return getColorStateForHwb(state, value as Record<keyof HWBColor, unknown>);
54
57
  }
55
58
 
56
59
  if (KEYS_RGB.every(key => key in value)) {
57
- state.rgb = getRgbValue(value as Record<keyof RGBColor, unknown>);
58
- state.hex = rgbToHex(state.rgb as RGBColor);
59
- state.hsl = rgbToHsl(state.rgb as RGBColor);
60
-
61
- return state as ColorState;
60
+ return getColorStateForRgb(state, value as Record<keyof RGBColor, unknown>);
62
61
  }
63
62
  }
64
63
 
65
- state.alpha ??= getAlpha(ALPHA_FULL_VALUE);
66
- state.hex ??= HEX_BLACK;
67
- state.hsl ??= {...DEFAULT_HSL};
68
- state.rgb ??= {...DEFAULT_RGB};
64
+ return getDefaultColorState(state);
65
+ }
66
+
67
+ function getColorStateForHex(value: string): ColorState {
68
+ const normalized = getNormalizedHex(value, true);
69
+ const hex = normalized.slice(0, LENGTH_LONG);
70
+
71
+ const hsl = hexToHsl(hex);
72
+
73
+ return {
74
+ hex,
75
+ hsl,
76
+ alpha: getAlpha(normalized.slice(LENGTH_LONG)),
77
+ hwb: hslToHwb(hsl),
78
+ rgb: hslToRgb(hsl),
79
+ };
80
+ }
81
+
82
+ function getColorStateForHsl(
83
+ state: Partial<ColorState>,
84
+ value: Record<keyof HSLColor, unknown>,
85
+ ): ColorState {
86
+ state.hsl = getHslValue(value);
87
+
88
+ state.rgb = hslToRgb(state.hsl);
89
+ state.hex = hslToHex(state.hsl);
90
+ state.hwb = hslToHwb(state.hsl);
91
+
92
+ return state as ColorState;
93
+ }
94
+
95
+ function getColorStateForHwb(
96
+ state: Partial<ColorState>,
97
+ value: Record<keyof HWBColor, unknown>,
98
+ ): ColorState {
99
+ state.hwb = getHwbValue(value);
100
+
101
+ state.hsl = hwbToHsl(state.hwb);
102
+ state.rgb = hwbToRgb(state.hwb);
103
+ state.hex = hwbToHex(state.hwb);
104
+
105
+ return state as ColorState;
106
+ }
107
+
108
+ function getColorStateForRgb(
109
+ state: Partial<ColorState>,
110
+ value: Record<keyof RGBColor, unknown>,
111
+ ): ColorState {
112
+ state.rgb = getRgbValue(value);
113
+
114
+ state.hex = rgbToHex(state.rgb);
115
+ state.hsl = rgbToHsl(state.rgb);
116
+ state.hwb = rgbToHwb(state.rgb);
117
+
118
+ return state as ColorState;
119
+ }
120
+
121
+ function getDefaultColorState(state: Partial<ColorState>): ColorState {
122
+ state.alpha = getAlpha(MAX_PERCENT);
123
+ state.hex = HEX_BLACK;
124
+ state.hsl = {...DEFAULT_HSL};
125
+ state.hwb = {...DEFAULT_HWB};
126
+ state.rgb = {...DEFAULT_RGB};
69
127
 
70
128
  return state as ColorState;
71
129
  }
@@ -77,11 +135,13 @@ export function setHexColor(state: ColorState, value: string, alpha: boolean): v
77
135
 
78
136
  const normalized = getNormalizedHex(value, true);
79
137
  const hex = normalized.slice(0, LENGTH_LONG);
80
- const rgb = hexToRgb(hex);
138
+ const hsl = hexToHsl(hex);
81
139
 
82
140
  state.hex = hex;
83
- state.hsl = rgbToHsl(rgb);
84
- state.rgb = rgb;
141
+ state.hsl = hsl;
142
+
143
+ state.rgb = hslToRgb(hsl);
144
+ state.hwb = hslToHwb(hsl);
85
145
 
86
146
  if (alpha) {
87
147
  state.alpha = getAlpha(normalized.slice(LENGTH_LONG));
@@ -95,21 +155,43 @@ export function setHSLColor(state: ColorState, value: unknown, alpha: boolean):
95
155
 
96
156
  const hsl = {
97
157
  hue: getDegrees((value as HSLColor).hue),
98
- lightness: getPercentage((value as HSLColor).lightness),
99
158
  saturation: getPercentage((value as HSLColor).saturation),
159
+ lightness: getPercentage((value as HSLColor).lightness),
100
160
  };
101
161
 
102
- const rgb = hslToRgb(hsl);
103
-
104
- state.hex = rgbToHex(rgb);
105
162
  state.hsl = hsl;
106
- state.rgb = rgb;
163
+
164
+ state.hex = hslToHex(hsl);
165
+ state.hwb = hslToHwb(hsl);
166
+ state.rgb = hslToRgb(hsl);
107
167
 
108
168
  if (alpha) {
109
169
  state.alpha = getAlpha((value as HSLAColor).alpha);
110
170
  }
111
171
  }
112
172
 
173
+ export function setHWBColor(state: ColorState, value: unknown, alpha: boolean): void {
174
+ if (!isHwbLike(value)) {
175
+ return;
176
+ }
177
+
178
+ const hwb = {
179
+ hue: getDegrees((value as HWBColor).hue),
180
+ whiteness: getPercentage((value as HWBColor).whiteness),
181
+ blackness: getPercentage((value as HWBColor).blackness),
182
+ };
183
+
184
+ state.hwb = hwb;
185
+
186
+ state.hex = hwbToHex(hwb);
187
+ state.hsl = hwbToHsl(hwb);
188
+ state.rgb = hwbToRgb(hwb);
189
+
190
+ if (alpha) {
191
+ state.alpha = getAlpha((value as HWBAColor).alpha);
192
+ }
193
+ }
194
+
113
195
  export function setRGBColor(state: ColorState, value: unknown, alpha: boolean): void {
114
196
  if (!isRgbLike(value)) {
115
197
  return;
@@ -121,10 +203,14 @@ export function setRGBColor(state: ColorState, value: unknown, alpha: boolean):
121
203
  red: getHexValue((value as RGBColor).red),
122
204
  };
123
205
 
124
- state.hex = rgbToHex(rgb);
125
- state.hsl = rgbToHsl(rgb);
206
+ const hsl = rgbToHsl(rgb);
207
+
208
+ state.hsl = hsl;
126
209
  state.rgb = rgb;
127
210
 
211
+ state.hex = hslToHex(hsl);
212
+ state.hwb = hslToHwb(hsl);
213
+
128
214
  if (alpha) {
129
215
  state.alpha = getAlpha((value as RGBAColor).alpha);
130
216
  }
@@ -35,6 +35,23 @@ export type HSLColor = {
35
35
  saturation: number;
36
36
  };
37
37
 
38
+ export type HWBColor = {
39
+ /**
40
+ * Blackness of the color _(in percentage; 0-100)_
41
+ */
42
+ blackness: number;
43
+ /**
44
+ * Hue of the color _(in degrees; 0-360)_
45
+ */
46
+ hue: number;
47
+ /**
48
+ * Whiteness of the color _(in percentage; 0-100)_
49
+ */
50
+ whiteness: number;
51
+ };
52
+
53
+ export type HWBAColor = HWBColor & ColorWithAlpha;
54
+
38
55
  /**
39
56
  * An _RGB_ color with an alpha channel _(opacity)_
40
57
  */
@@ -58,7 +75,7 @@ export type RGBColor = {
58
75
  red: number;
59
76
  };
60
77
 
61
- export type ColorProperty = 'alpha' | 'blue' | 'green' | 'hue' | 'lightness' | 'red' | 'saturation';
78
+ export type ColorProperty = 'alpha' | keyof HSLColor | keyof HWBColor | keyof RGBColor;
62
79
 
63
80
  export type ColorSpace = 'hsl' | 'rgb';
64
81
 
@@ -66,6 +83,7 @@ export type ColorState = {
66
83
  alpha: Alpha;
67
84
  hex: string;
68
85
  hsl: HSLColor;
86
+ hwb: HWBColor;
69
87
  rgb: RGBColor;
70
88
  };
71
89
 
@@ -9,9 +9,10 @@ import {
9
9
  LENGTH_SHORT,
10
10
  MAX_HEX,
11
11
  } from '../constants';
12
+ import {getHexValue, getPercentage} from '../misc/get';
12
13
  import {isHexColor} from '../misc/is';
13
- import type {HSLAColor, HSLColor, RGBAColor, RGBColor} from '../models';
14
- import {convertRgbToHsla} from './rgb';
14
+ import type {HSLAColor, HSLColor, HWBAColor, HWBColor, RGBAColor, RGBColor} from '../models';
15
+ import {convertRgbToHsla, convertRgbToHwba} from './rgb';
15
16
 
16
17
  // #region Functions
17
18
 
@@ -27,10 +28,10 @@ function convertHexToRgba(value: string): RGBAColor {
27
28
  }
28
29
 
29
30
  return {
30
- alpha: values[3] / MAX_HEX,
31
- blue: values[2],
32
- green: values[1],
33
- red: values[0],
31
+ alpha: getPercentage((values[3] / MAX_HEX) * 100),
32
+ blue: getHexValue(values[2]),
33
+ green: getHexValue(values[1]),
34
+ red: getHexValue(values[0]),
34
35
  };
35
36
  }
36
37
 
@@ -66,6 +67,14 @@ export function getNormalizedHex(value: unknown, alpha?: boolean): string {
66
67
  return `${hex}${a}`;
67
68
  }
68
69
 
70
+ /**
71
+ * Convert a hex color string to a _HSL_ color
72
+ *
73
+ * _If the value is unable to be converted, a black _HSL_ color will be returned_
74
+ *
75
+ * @param value Hex color string
76
+ * @returns _HSL_ color
77
+ */
69
78
  export function hexToHsl(value: string): HSLColor {
70
79
  const {hue, lightness, saturation} = hexToHsla(value);
71
80
 
@@ -76,14 +85,52 @@ export function hexToHsl(value: string): HSLColor {
76
85
  };
77
86
  }
78
87
 
88
+ /**
89
+ * Convert a hex color string to a _HSLA_ color
90
+ *
91
+ * _If the value is unable to be converted, a black _HSLA_ color will be returned_
92
+ *
93
+ * @param value Hex color string
94
+ * @returns _HSLA_ color
95
+ */
79
96
  export function hexToHsla(value: string): HSLAColor {
80
97
  return convertRgbToHsla(convertHexToRgba(value));
81
98
  }
82
99
 
100
+ /**
101
+ * Convert a hex color string to a _HWB_ color
102
+ *
103
+ * _If the value is unable to be converted, a black _HWB_ color will be returned_
104
+ *
105
+ * @param value Hex color string
106
+ * @returns _HWB_ color
107
+ */
108
+ export function hexToHwb(value: string): HWBColor {
109
+ const {blackness, hue, whiteness} = hexToHwba(value);
110
+
111
+ return {
112
+ hue,
113
+ whiteness,
114
+ blackness,
115
+ };
116
+ }
117
+
118
+ /**
119
+ * Convert a hex color string to a _HWBA_ color
120
+ *
121
+ * _If the value is unable to be converted, a black _HWBA_ color will be returned_
122
+ *
123
+ * @param value Hex color string
124
+ * @returns _HWBA_ color
125
+ */
126
+ export function hexToHwba(value: string): HWBAColor {
127
+ return convertRgbToHwba(convertHexToRgba(value));
128
+ }
129
+
83
130
  /**
84
131
  * Convert a hex color to an _RGB_ color
85
132
  *
86
- * _If the value is unable to be converted, a black RGB color will be returned_
133
+ * _If the value is unable to be converted, a black _RGB_ color will be returned_
87
134
  *
88
135
  * @param value Original value
89
136
  * @returns _RGB_ color
@@ -97,7 +144,7 @@ export function hexToRgb(value: string): RGBColor {
97
144
  /**
98
145
  * Convert a hex color to an _RGBA_ color
99
146
  *
100
- * _If the value is unable to be converted, a black RGBA color with an alpha channel (opacity) of `0` will be returned_
147
+ * _If the value is unable to be converted, a black _RGBA_ color will be returned_
101
148
  *
102
149
  * @param value Original value
103
150
  * @returns _RGBA_ color
@@ -1,24 +1,51 @@
1
- import {ALPHA_FULL_VALUE, DEFAULT_HSL, MAX_DEGREE, MAX_HEX, MAX_PERCENT} from '../constants';
1
+ import {DEFAULT_HSL, MAX_DEGREE, MAX_HEX, MAX_PERCENT} from '../constants';
2
2
  import {getAlphaValue} from '../misc/alpha';
3
- import {getHexValue, getDegrees, getPercentage} from '../misc/get';
3
+ import {getDegrees, getHexValue, getPercentage} from '../misc/get';
4
4
  import {isHslLike} from '../misc/is';
5
- import type {HSLAColor, HSLColor, RGBAColor, RGBColor} from '../models';
5
+ import type {HSLAColor, HSLColor, HWBAColor, HWBColor, RGBAColor, RGBColor} from '../models';
6
6
  import {convertRgbToHex} from './rgb';
7
7
 
8
8
  // #region Functions
9
9
 
10
- function convertHslToRgba(value: unknown): RGBAColor {
11
- const hsl = isHslLike(value) ? getHslValue(value) : {...DEFAULT_HSL};
10
+ function convertHslToHwba(input: unknown): HWBAColor {
11
+ const hsl = isHslLike(input) ? getHslValue(input) : {...DEFAULT_HSL};
12
+
13
+ let {hue, lightness, saturation} = hsl;
14
+
15
+ lightness /= MAX_PERCENT;
16
+ saturation /= MAX_PERCENT;
17
+
18
+ const value = lightness + saturation * Math.min(lightness, 1 - lightness);
19
+
20
+ if (value === 0) {
21
+ saturation = 0;
22
+ } else {
23
+ saturation = 2 * (1 - lightness / value);
24
+ }
25
+
26
+ const blackness = 1 - value;
27
+ const whiteness = (1 - saturation) * value;
28
+
29
+ return {
30
+ hue,
31
+ whiteness: whiteness * MAX_PERCENT,
32
+ blackness: blackness * MAX_PERCENT,
33
+ alpha: getAlphaValue((input as HSLAColor)?.alpha ?? MAX_PERCENT),
34
+ };
35
+ }
36
+
37
+ function convertHslToRgba(input: unknown): RGBAColor {
38
+ const hsl = isHslLike(input) ? getHslValue(input) : {...DEFAULT_HSL};
12
39
 
13
40
  const hue = hsl.hue % MAX_DEGREE;
14
41
  const saturation = hsl.saturation / MAX_PERCENT;
15
42
  const lightness = hsl.lightness / MAX_PERCENT;
16
43
 
17
44
  return {
18
- alpha: getAlphaValue((value as HSLAColor).alpha ?? ALPHA_FULL_VALUE),
19
- blue: getHexValue(Math.round(getHexyValue(hue, lightness, saturation, 4))),
20
- green: getHexValue(Math.round(getHexyValue(hue, lightness, saturation, 8))),
21
- red: getHexValue(Math.round(getHexyValue(hue, lightness, saturation, 0))),
45
+ alpha: getAlphaValue((input as HSLAColor)?.alpha ?? MAX_PERCENT),
46
+ blue: getHexValue(getHexyValue(hue, lightness, saturation, 4)),
47
+ green: getHexValue(getHexyValue(hue, lightness, saturation, 8)),
48
+ red: getHexValue(getHexyValue(hue, lightness, saturation, 0)),
22
49
  };
23
50
  }
24
51
 
@@ -32,24 +59,63 @@ function getHexyValue(hue: number, lightness: number, saturation: number, value:
32
59
  export function getHslValue(value: Record<keyof HSLColor, unknown>): HSLColor {
33
60
  return {
34
61
  hue: getDegrees(value.hue),
35
- lightness: getPercentage(value.lightness),
36
62
  saturation: getPercentage(value.saturation),
63
+ lightness: getPercentage(value.lightness),
37
64
  };
38
65
  }
39
66
 
67
+ /**
68
+ * Convert an _HSL(A)_ color to a hex color _(with optional alpha channel, i.e., opacity)_
69
+ *
70
+ * _If the value is unable to be converted, a black hex color will be returned_
71
+ *
72
+ * @param hsl _HSL(A)_ color
73
+ * @param alpha Include alpha channel _(opacity)_? _(defaults to `false`)_
74
+ * @returns Hex color string
75
+ */
40
76
  export function hslToHex(hsl: HSLAColor | HSLColor, alpha?: boolean): string {
41
77
  return convertRgbToHex(convertHslToRgba(hsl), alpha ?? false);
42
78
  }
43
79
 
80
+ /**
81
+ * Convert an _HSL(A)_ color to an _HWB_ color
82
+ *
83
+ * _If the value is unable to be converted, a black _HWB_ color will be returned_
84
+ *
85
+ * @param hsl HSL(A) color
86
+ * @returns _HWB_ color
87
+ */
88
+ export function hslToHwb(hsl: HSLAColor | HSLColor): HWBColor {
89
+ const {blackness, hue, whiteness} = convertHslToHwba(hsl);
90
+
91
+ return {
92
+ hue,
93
+ whiteness,
94
+ blackness,
95
+ };
96
+ }
97
+
98
+ /**
99
+ * Convert an _HSL(A)_ color to an _HWBA_ color
100
+ *
101
+ * _If the value is unable to be converted, a black _HWBA_ color will be returned_
102
+ *
103
+ * @param hsl HSL(A) color
104
+ * @returns _HWBA_ color
105
+ */
106
+ export function hslToHwba(hsl: HSLAColor | HSLColor): HWBAColor {
107
+ return convertHslToHwba(hsl);
108
+ }
109
+
44
110
  /**
45
111
  * Convert an _HSL(A)_ color to an _RGB_ color
46
112
  *
47
- * _If the value is unable to be converted, a black RGB color will be returned_
113
+ * _If the value is unable to be converted, a black _RGB_ color will be returned_
48
114
  *
49
115
  * _Thanks, https://github.com/color-js/color.js/blob/main/src/spaces/hsl.js#L61_
50
116
  *
51
117
  * @param hsl HSL(A) color
52
- * @returns RGB color
118
+ * @returns _RGB_ color
53
119
  */
54
120
  export function hslToRgb(hsl: HSLAColor | HSLColor): RGBColor {
55
121
  const {blue, green, red} = convertHslToRgba(hsl);
@@ -64,12 +130,12 @@ export function hslToRgb(hsl: HSLAColor | HSLColor): RGBColor {
64
130
  /**
65
131
  * Convert an _HSL(A)_ color to an _RGBA_ color
66
132
  *
67
- * _If the value is unable to be converted, a black RGBA color with an alpha channel (opactiy) of `0` will be returned_
133
+ * _If the value is unable to be converted, a black _RGBA_ color will be returned_
68
134
  *
69
135
  * _Thanks, https://github.com/color-js/color.js/blob/main/src/spaces/hsl.js#L61_
70
136
  *
71
137
  * @param hsl HSL(A) color
72
- * @returns RGBA color
138
+ * @returns _RGBA_ color
73
139
  */
74
140
  export function hslToRgba(hsl: HSLAColor | HSLColor): RGBAColor {
75
141
  return convertHslToRgba(hsl);
@@ -0,0 +1,123 @@
1
+ import {DEFAULT_HWB, MAX_PERCENT} from '../constants';
2
+ import {getAlphaValue} from '../misc/alpha';
3
+ import {getDegrees, getPercentage} from '../misc/get';
4
+ import {isHwbLike} from '../misc/is';
5
+ import type {HSLAColor, HSLColor, HWBAColor, HWBColor, RGBAColor, RGBColor} from '../models';
6
+ import {hslToRgb, hslToRgba} from './hsl';
7
+ import {rgbToHex} from './rgb';
8
+
9
+ // #region Functions
10
+
11
+ export function convertHwbToHsl(input: HWBAColor | HWBColor): HSLAColor {
12
+ let {blackness, hue, whiteness} = isHwbLike(input) ? getHwbValue(input) : DEFAULT_HWB;
13
+
14
+ blackness /= MAX_PERCENT;
15
+ whiteness /= MAX_PERCENT;
16
+
17
+ if (blackness + whiteness > 1) {
18
+ const total = blackness + whiteness;
19
+
20
+ blackness /= total;
21
+ whiteness /= total;
22
+ }
23
+
24
+ const lightness = (1 - blackness + whiteness) / 2;
25
+
26
+ const saturation = getHwbSaturation(blackness, whiteness, lightness);
27
+
28
+ return {
29
+ hue,
30
+ saturation: saturation * MAX_PERCENT,
31
+ lightness: lightness * MAX_PERCENT,
32
+ alpha: getAlphaValue((input as HWBAColor)?.alpha ?? MAX_PERCENT),
33
+ };
34
+ }
35
+
36
+ function getHwbSaturation(blackness: number, whiteness: number, lightness: number): number {
37
+ const value = 1 - blackness;
38
+
39
+ const hue = value - whiteness;
40
+
41
+ if (hue <= 0) {
42
+ return 0;
43
+ }
44
+
45
+ return hue / Math.min(2 * lightness, 2 - 2 * lightness);
46
+ }
47
+
48
+ export function getHwbValue(value: Record<keyof HWBColor, unknown>): HWBColor {
49
+ return {
50
+ hue: getDegrees(value.hue),
51
+ whiteness: getPercentage(value.whiteness),
52
+ blackness: getPercentage(value.blackness),
53
+ };
54
+ }
55
+
56
+ /**
57
+ * Convert an _HWB(A)_ color to a hex color _(with optional alpha channel, i.e., opacity)_
58
+ *
59
+ * _If the value is unable to be converted, a black hex color will be returned_
60
+ *
61
+ * @param hwb _HWB(A)_ color
62
+ * @param alpha Include alpha channel _(opacity)_? _(defaults to `false`)_
63
+ * @returns Hex color string
64
+ */
65
+ export function hwbToHex(hwb: HWBAColor | HWBColor, alpha?: boolean): string {
66
+ return rgbToHex(hwbToRgb(hwb), alpha);
67
+ }
68
+
69
+ /**
70
+ * Convert an _HWB(A)_ color to an _RGB_ color
71
+ *
72
+ * _If the value is unable to be converted, a black _RGB_ color will be returned_
73
+ *
74
+ * @param hwb _HWB(A)_ color
75
+ * @returns _RGB_ color
76
+ */
77
+ export function hwbToHsl(hwb: HWBAColor | HWBColor): HSLColor {
78
+ const {hue, lightness, saturation} = convertHwbToHsl(hwb);
79
+
80
+ return {
81
+ hue,
82
+ lightness,
83
+ saturation,
84
+ };
85
+ }
86
+
87
+ /**
88
+ * Convert an _HWB(A)_ color to an _HSLA_ color
89
+ *
90
+ * _If the value is unable to be converted, a black _HSLA_ color will be returned_
91
+ *
92
+ * @param hwb _HWB(A)_ color
93
+ * @returns _HSLA_ color
94
+ */
95
+ export function hwbToHsla(hwb: HWBAColor | HWBColor): HSLAColor {
96
+ return convertHwbToHsl(hwb);
97
+ }
98
+
99
+ /**
100
+ * Convert an _HWB(A)_ color to an _RGB_ color
101
+ *
102
+ * _If the value is unable to be converted, a black _RGB_ color will be returned_
103
+ *
104
+ * @param hwb _HWB(A)_ color
105
+ * @returns _RGB_ color
106
+ */
107
+ export function hwbToRgb(hwb: HWBAColor | HWBColor): RGBColor {
108
+ return hslToRgb(hwbToHsl(hwb));
109
+ }
110
+
111
+ /**
112
+ * Convert an _HWB(A)_ color to an _RGBA_ color
113
+ *
114
+ * _If the value is unable to be converted, a black _RGBA_ color will be returned_
115
+ *
116
+ * @param hwb _HWB(A)_ color
117
+ * @returns _RGBA_ color
118
+ */
119
+ export function hwbToRgba(hwb: HWBAColor | HWBColor): RGBAColor {
120
+ return hslToRgba(hwbToHsla(hwb));
121
+ }
122
+
123
+ // #endregion