@oscarpalmer/atoms 0.191.0 → 0.193.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 (47) hide show
  1. package/dist/beacon.d.mts +6 -44
  2. package/dist/beacon.mjs +20 -67
  3. package/dist/color/constants.d.mts +82 -41
  4. package/dist/color/constants.mjs +102 -63
  5. package/dist/color/instance.mjs +36 -13
  6. package/dist/color/misc/alpha.mjs +9 -10
  7. package/dist/color/misc/format.mjs +4 -4
  8. package/dist/color/misc/get.mjs +18 -18
  9. package/dist/color/misc/is.mjs +22 -21
  10. package/dist/color/misc/state.d.mts +6 -5
  11. package/dist/color/misc/state.mjs +31 -26
  12. package/dist/color/models.d.mts +78 -1
  13. package/dist/color/space/hex.mjs +12 -12
  14. package/dist/color/space/hsl.mjs +16 -16
  15. package/dist/color/space/hwb.mjs +10 -10
  16. package/dist/color/space/rgb.mjs +16 -16
  17. package/dist/herald.d.mts +2 -3
  18. package/dist/index.d.mts +141 -67
  19. package/dist/index.mjs +552 -391
  20. package/dist/internal/subscription.d.mts +52 -0
  21. package/dist/internal/subscription.mjs +127 -0
  22. package/dist/models.d.mts +5 -1
  23. package/dist/queue.d.mts +25 -23
  24. package/dist/queue.mjs +27 -28
  25. package/package.json +1 -1
  26. package/src/beacon.ts +32 -117
  27. package/src/color/constants.ts +115 -78
  28. package/src/color/instance.ts +65 -12
  29. package/src/color/misc/alpha.ts +13 -21
  30. package/src/color/misc/format.ts +4 -4
  31. package/src/color/misc/get.ts +23 -40
  32. package/src/color/misc/is.ts +29 -39
  33. package/src/color/misc/state.ts +77 -41
  34. package/src/color/models.ts +94 -1
  35. package/src/color/space/hex.ts +18 -23
  36. package/src/color/space/hsl.ts +16 -24
  37. package/src/color/space/hwb.ts +10 -10
  38. package/src/color/space/rgb.ts +19 -16
  39. package/src/herald.ts +1 -3
  40. package/src/index.ts +1 -0
  41. package/src/internal/subscription.ts +264 -0
  42. package/src/models.ts +5 -0
  43. package/src/queue.ts +92 -92
  44. package/src/string/fuzzy.ts +1 -1
  45. package/src/value/freeze.ts +2 -2
  46. package/src/value/shake.ts +1 -1
  47. package/src/value/transform.ts +1 -1
@@ -1,23 +1,23 @@
1
- import {TYPE_HSL, TYPE_HWB, TYPE_RGB} from '../constants';
1
+ import {COLOR_TYPE} from '../constants';
2
2
  import type {ColorState} from '../models';
3
3
  import {getColorFromState} from './state';
4
4
 
5
5
  // #region Functions
6
6
 
7
7
  export function formatHslColor(state: ColorState, alpha?: boolean): string {
8
- const {hue, lightness, saturation} = getColorFromState(state, TYPE_HSL);
8
+ const {hue, lightness, saturation} = getColorFromState(state, COLOR_TYPE.hsl);
9
9
 
10
10
  return `hsl(${hue}deg ${saturation}% ${lightness}%${getSuffix(state, alpha)})`;
11
11
  }
12
12
 
13
13
  export function formatHwbColor(state: ColorState, alpha?: boolean): string {
14
- const {blackness, hue, whiteness} = getColorFromState(state, TYPE_HWB);
14
+ const {blackness, hue, whiteness} = getColorFromState(state, COLOR_TYPE.hwb);
15
15
 
16
16
  return `hwb(${hue}deg ${whiteness}% ${blackness}%${getSuffix(state, alpha)})`;
17
17
  }
18
18
 
19
19
  export function formatRgbColor(state: ColorState, alpha?: boolean): string {
20
- const {blue, green, red} = getColorFromState(state, TYPE_RGB);
20
+ const {blue, green, red} = getColorFromState(state, COLOR_TYPE.rgb);
21
21
 
22
22
  return `rgb(${red} ${green} ${blue}${getSuffix(state, alpha)})`;
23
23
  }
@@ -1,25 +1,6 @@
1
1
  import {round} from '../../internal/math/misc';
2
- import {clamp} from '../../number';
3
- import {
4
- HEX_BLACK,
5
- HEX_WHITE,
6
- MAX_DEGREE,
7
- MAX_HEX,
8
- MAX_PERCENT,
9
- SRGB_LUMINANCE_BLUE,
10
- SRGB_LUMINANCE_EXPONENT,
11
- SRGB_LUMINANCE_GREEN,
12
- SRGB_LUMINANCE_MINIMUM,
13
- SRGB_LUMINANCE_MODIFIER,
14
- SRGB_LUMINANCE_MULTIPLIER,
15
- SRGB_LUMINANCE_OFFSET,
16
- SRGB_LUMINANCE_RED,
17
- SRGB_LUMINANCE_THRESHOLD,
18
- TYPE_HEX,
19
- TYPE_HSL,
20
- TYPE_HWB,
21
- TYPE_RGB,
22
- } from '../constants';
2
+ import {clamp} from '../../internal/number';
3
+ import {COLOR_DEFAULTS, COLOR_MAX, COLOR_SRGB, COLOR_TYPE} from '../constants';
23
4
  import {color} from '../instance';
24
5
  import type {Color, HSLAColor, HSLColor, HWBAColor, HWBColor, RGBAColor, RGBColor} from '../models';
25
6
  import {getColorFromState, getColorState} from './state';
@@ -60,30 +41,32 @@ export function getForegroundColor(value: unknown, hex: true): string;
60
41
  export function getForegroundColor(value: unknown): Color;
61
42
 
62
43
  export function getForegroundColor(value: unknown, hex?: unknown): string | Color {
63
- const rgb = getColorFromState(getColorState(value), TYPE_RGB);
44
+ const rgb = getColorFromState(getColorState(value), COLOR_TYPE.rgb);
64
45
  const {blue, green, red} = rgb;
65
46
 
66
- const values = [blue / MAX_HEX, green / MAX_HEX, red / MAX_HEX];
47
+ const values = [blue / COLOR_MAX.hex, green / COLOR_MAX.hex, red / COLOR_MAX.hex];
67
48
  const {length} = values;
68
49
 
69
50
  for (let index = 0; index < length; index += 1) {
70
51
  const color = values[index];
71
52
 
72
- if (color <= SRGB_LUMINANCE_MINIMUM) {
73
- values[index] /= SRGB_LUMINANCE_MULTIPLIER;
53
+ if (color <= COLOR_SRGB.luminanceMinimum) {
54
+ values[index] /= COLOR_SRGB.luminanceMultiplier;
74
55
  } else {
75
56
  values[index] =
76
- ((color + SRGB_LUMINANCE_OFFSET) / SRGB_LUMINANCE_MODIFIER) ** SRGB_LUMINANCE_EXPONENT;
57
+ ((color + COLOR_SRGB.luminanceOffset) / COLOR_SRGB.luminanceModifier) **
58
+ COLOR_SRGB.luminanceExponent;
77
59
  }
78
60
  }
79
61
 
80
62
  const luminance =
81
- SRGB_LUMINANCE_RED * values[2] +
82
- SRGB_LUMINANCE_GREEN * values[1] +
83
- SRGB_LUMINANCE_BLUE * values[0];
63
+ COLOR_SRGB.luminanceRed * values[2] +
64
+ COLOR_SRGB.luminanceGreen * values[1] +
65
+ COLOR_SRGB.luminanceBlue * values[0];
84
66
 
85
67
  // Rudimentary and ureliable?; implement APCA for more reliable results?
86
- const foreground = luminance > SRGB_LUMINANCE_THRESHOLD ? HEX_BLACK : HEX_WHITE;
68
+ const foreground =
69
+ luminance > COLOR_SRGB.luminanceThreshold ? COLOR_DEFAULTS.hexBlack : COLOR_DEFAULTS.hexWhite;
87
70
 
88
71
  return hex === true ? foreground : color(foreground);
89
72
  }
@@ -113,15 +96,15 @@ export function getHexaColor(value: unknown): string {
113
96
  * @returns Hex color string
114
97
  */
115
98
  export function getHexColor(value: unknown): string {
116
- return getColorFromState(getColorState(value), TYPE_HEX);
99
+ return getColorFromState(getColorState(value), COLOR_TYPE.hex);
117
100
  }
118
101
 
119
102
  export function getHexValue(value: unknown): number {
120
- return getClampedValue(value, 0, MAX_HEX, true);
103
+ return getClampedValue(value, 0, COLOR_MAX.hex, true);
121
104
  }
122
105
 
123
106
  export function getDegrees(value: unknown): number {
124
- return getClampedValue(value, 0, MAX_DEGREE);
107
+ return getClampedValue(value, 0, COLOR_MAX.degree);
125
108
  }
126
109
 
127
110
  /**
@@ -135,7 +118,7 @@ export function getDegrees(value: unknown): number {
135
118
  */
136
119
  export function getHslaColor(value: unknown): HSLAColor {
137
120
  const state = getColorState(value);
138
- const hsl = getColorFromState(state, TYPE_HSL);
121
+ const hsl = getColorFromState(state, COLOR_TYPE.hsl);
139
122
 
140
123
  return {
141
124
  ...hsl,
@@ -153,7 +136,7 @@ export function getHslaColor(value: unknown): HSLAColor {
153
136
  * @returns _HWB_ color
154
137
  */
155
138
  export function getHwbColor(value: unknown): HWBColor {
156
- return getColorFromState(getColorState(value), TYPE_HWB);
139
+ return getColorFromState(getColorState(value), COLOR_TYPE.hwb);
157
140
  }
158
141
 
159
142
  /**
@@ -167,7 +150,7 @@ export function getHwbColor(value: unknown): HWBColor {
167
150
  */
168
151
  export function getHwbaColor(value: unknown): HWBAColor {
169
152
  const state = getColorState(value);
170
- const hwb = getColorFromState(state, TYPE_HWB);
153
+ const hwb = getColorFromState(state, COLOR_TYPE.hwb);
171
154
 
172
155
  return {
173
156
  ...hwb,
@@ -185,11 +168,11 @@ export function getHwbaColor(value: unknown): HWBAColor {
185
168
  * @returns _HSL_ color
186
169
  */
187
170
  export function getHslColor(value: unknown): HSLColor {
188
- return getColorFromState(getColorState(value), TYPE_HSL);
171
+ return getColorFromState(getColorState(value), COLOR_TYPE.hsl);
189
172
  }
190
173
 
191
174
  export function getPercentage(value: unknown): number {
192
- return getClampedValue(value, 0, MAX_PERCENT);
175
+ return getClampedValue(value, 0, COLOR_MAX.percent);
193
176
  }
194
177
 
195
178
  /**
@@ -203,7 +186,7 @@ export function getPercentage(value: unknown): number {
203
186
  */
204
187
  export function getRgbaColor(value: unknown): RGBAColor {
205
188
  const state = getColorState(value);
206
- const rgb = getColorFromState(state, TYPE_RGB);
189
+ const rgb = getColorFromState(state, COLOR_TYPE.rgb);
207
190
 
208
191
  return {
209
192
  ...rgb,
@@ -221,7 +204,7 @@ export function getRgbaColor(value: unknown): RGBAColor {
221
204
  * @returns _RGB_ color
222
205
  */
223
206
  export function getRgbColor(value: unknown): RGBColor {
224
- return getColorFromState(getColorState(value), TYPE_RGB);
207
+ return getColorFromState(getColorState(value), COLOR_TYPE.rgb);
225
208
  }
226
209
 
227
210
  // #endregion
@@ -1,22 +1,13 @@
1
+ import {isPlainObject} from '../../internal/is';
1
2
  import {between} from '../../internal/number';
2
3
  import type {PlainObject} from '../../models';
3
4
  import {
4
- ALPHA_NONE_VALUE,
5
- EXPRESSION_HEX_LONG,
6
- EXPRESSION_HEX_SHORT,
7
- EXPRESSION_PREFIX,
8
- KEYS_HSL,
9
- KEYS_HSLA,
10
- KEYS_HWB,
11
- KEYS_HWBA,
12
- KEYS_RGB,
13
- KEYS_RGBA,
14
- LENGTH_LONG,
15
- LENGTH_SHORT,
16
- MAX_DEGREE,
17
- MAX_HEX,
18
- MAX_PERCENT,
19
- PROPERTY_COLOR,
5
+ COLOR_ALPHA,
6
+ COLOR_EXPRESSION,
7
+ COLOR_KEYS,
8
+ COLOR_LENGTHS,
9
+ COLOR_MAX,
10
+ COLOR_PROPERTY,
20
11
  } from '../constants';
21
12
  import type {Color} from '../index';
22
13
  import type {
@@ -36,11 +27,11 @@ function hasKeys(value: unknown, keys: ColorProperty[]): boolean {
36
27
  }
37
28
 
38
29
  function isAlpha(value: unknown): value is number {
39
- return typeof value === 'number' && between(value, ALPHA_NONE_VALUE, MAX_PERCENT);
30
+ return typeof value === 'number' && between(value, COLOR_ALPHA.noneValue, COLOR_MAX.percent);
40
31
  }
41
32
 
42
33
  function isBytey(value: unknown): value is number {
43
- return typeof value === 'number' && between(value, 0, MAX_HEX);
34
+ return typeof value === 'number' && between(value, 0, COLOR_MAX.hex);
44
35
  }
45
36
 
46
37
  /**
@@ -51,10 +42,7 @@ function isBytey(value: unknown): value is number {
51
42
  */
52
43
  export function isColor(value: unknown): value is Color {
53
44
  return (
54
- typeof value === 'object' &&
55
- value !== null &&
56
- PROPERTY_COLOR in value &&
57
- value[PROPERTY_COLOR] === true
45
+ isPlainObject(value) && COLOR_PROPERTY.name in value && value[COLOR_PROPERTY.name] === true
58
46
  );
59
47
  }
60
48
 
@@ -87,7 +75,7 @@ function isColorValue(obj: unknown, properties: ColorProperty[]): boolean {
87
75
  }
88
76
 
89
77
  function isDegree(value: unknown): value is number {
90
- return typeof value === 'number' && between(value, 0, MAX_DEGREE);
78
+ return typeof value === 'number' && between(value, 0, COLOR_MAX.degree);
91
79
  }
92
80
 
93
81
  /**
@@ -111,14 +99,16 @@ export function isHexColor(value: unknown, alpha?: boolean): value is string {
111
99
  return false;
112
100
  }
113
101
 
114
- if (!(EXPRESSION_HEX_SHORT.test(value) || EXPRESSION_HEX_LONG.test(value))) {
102
+ if (!(COLOR_EXPRESSION.hexShort.test(value) || COLOR_EXPRESSION.hexLong.test(value))) {
115
103
  return false;
116
104
  }
117
105
 
118
106
  if (alpha === false) {
119
- const unprefixed = value.replace(EXPRESSION_PREFIX, '');
107
+ const unprefixed = value.replace(COLOR_EXPRESSION.prefix, '');
120
108
 
121
- return unprefixed.length === LENGTH_SHORT || unprefixed.length === LENGTH_LONG;
109
+ return (
110
+ unprefixed.length === COLOR_LENGTHS.hexShort || unprefixed.length === COLOR_LENGTHS.hexLong
111
+ );
122
112
  }
123
113
 
124
114
  return true;
@@ -131,11 +121,11 @@ export function isHexColor(value: unknown, alpha?: boolean): value is string {
131
121
  * @returns `true` if the value is an _HSLA_ color, otherwise `false`
132
122
  */
133
123
  export function isHslaColor(value: unknown): value is HSLAColor {
134
- return isColorValue(value, KEYS_HSLA);
124
+ return isColorValue(value, COLOR_KEYS.hsla);
135
125
  }
136
126
 
137
127
  export function isHslaLike(value: unknown): value is Record<keyof HSLAColor, unknown> {
138
- return hasKeys(value, KEYS_HSLA);
128
+ return hasKeys(value, COLOR_KEYS.hsla);
139
129
  }
140
130
 
141
131
  /**
@@ -145,11 +135,11 @@ export function isHslaLike(value: unknown): value is Record<keyof HSLAColor, unk
145
135
  * @returns `true` if the value is an _HSL_ color, otherwise `false`
146
136
  */
147
137
  export function isHslColor(value: unknown): value is HSLColor {
148
- return isColorValue(value, KEYS_HSLA) || isColorValue(value, KEYS_HSL);
138
+ return isColorValue(value, COLOR_KEYS.hsla) || isColorValue(value, COLOR_KEYS.hsl);
149
139
  }
150
140
 
151
141
  export function isHslLike(value: unknown): value is Record<keyof HSLColor, unknown> {
152
- return hasKeys(value, KEYS_HSL);
142
+ return hasKeys(value, COLOR_KEYS.hsl);
153
143
  }
154
144
 
155
145
  /**
@@ -159,11 +149,11 @@ export function isHslLike(value: unknown): value is Record<keyof HSLColor, unkno
159
149
  * @returns `true` if the value is an _HWBA_ color, otherwise `false`
160
150
  */
161
151
  export function isHwbaColor(value: unknown): value is HWBAColor {
162
- return isColorValue(value, KEYS_HWBA);
152
+ return isColorValue(value, COLOR_KEYS.hwba);
163
153
  }
164
154
 
165
155
  export function isHwbaLike(value: unknown): value is Record<keyof HWBAColor, unknown> {
166
- return hasKeys(value, KEYS_HWBA);
156
+ return hasKeys(value, COLOR_KEYS.hwba);
167
157
  }
168
158
 
169
159
  /**
@@ -173,11 +163,11 @@ export function isHwbaLike(value: unknown): value is Record<keyof HWBAColor, unk
173
163
  * @returns `true` if the value is an _HWB_ color, otherwise `false`
174
164
  */
175
165
  export function isHwbColor(value: unknown): value is HWBColor {
176
- return isColorValue(value, KEYS_HWB) || isColorValue(value, KEYS_HWBA);
166
+ return isColorValue(value, COLOR_KEYS.hwb) || isColorValue(value, COLOR_KEYS.hwba);
177
167
  }
178
168
 
179
169
  export function isHwbLike(value: unknown): value is Record<keyof HWBColor, unknown> {
180
- return hasKeys(value, KEYS_HWB);
170
+ return hasKeys(value, COLOR_KEYS.hwb);
181
171
  }
182
172
 
183
173
  /**
@@ -187,11 +177,11 @@ export function isHwbLike(value: unknown): value is Record<keyof HWBColor, unkno
187
177
  * @returns `true` if the value is an _RGBA_ color, otherwise `false`
188
178
  */
189
179
  export function isRgbaColor(value: unknown): value is RGBAColor {
190
- return isColorValue(value, KEYS_RGBA);
180
+ return isColorValue(value, COLOR_KEYS.rgba);
191
181
  }
192
182
 
193
183
  export function isRgbaLike(value: unknown): value is Record<keyof RGBAColor, unknown> {
194
- return hasKeys(value, KEYS_RGBA);
184
+ return hasKeys(value, COLOR_KEYS.rgba);
195
185
  }
196
186
 
197
187
  /**
@@ -201,15 +191,15 @@ export function isRgbaLike(value: unknown): value is Record<keyof RGBAColor, unk
201
191
  * @returns `true` if the value is an _RGB_ color, otherwise `false`
202
192
  */
203
193
  export function isRgbColor(value: unknown): value is RGBColor {
204
- return isColorValue(value, KEYS_RGBA) || isColorValue(value, KEYS_RGB);
194
+ return isColorValue(value, COLOR_KEYS.rgba) || isColorValue(value, COLOR_KEYS.rgb);
205
195
  }
206
196
 
207
197
  export function isRgbLike(value: unknown): value is Record<keyof RGBColor, unknown> {
208
- return hasKeys(value, KEYS_RGB);
198
+ return hasKeys(value, COLOR_KEYS.rgb);
209
199
  }
210
200
 
211
201
  function isPercentage(value: unknown): value is number {
212
- return typeof value === 'number' && between(value, 0, MAX_PERCENT);
202
+ return typeof value === 'number' && between(value, 0, COLOR_MAX.percent);
213
203
  }
214
204
 
215
205
  // #endregion
@@ -1,19 +1,7 @@
1
- import {
2
- DEFAULT_HSL,
3
- DEFAULT_HWB,
4
- DEFAULT_RGB,
5
- HEX_BLACK,
6
- KEYS_HSL,
7
- KEYS_HWB,
8
- KEYS_RGB,
9
- LENGTH_LONG,
10
- MAX_PERCENT,
11
- TYPE_HEX,
12
- TYPE_HSL,
13
- TYPE_HWB,
14
- TYPE_RGB,
15
- } from '../constants';
1
+ import type {Subscriptions} from '../../internal/subscription';
2
+ import {COLOR_DEFAULTS, COLOR_KEYS, COLOR_LENGTHS, COLOR_MAX, COLOR_TYPE} from '../constants';
16
3
  import type {
4
+ Color,
17
5
  ColorState,
18
6
  ColorType,
19
7
  HSLAColor,
@@ -67,15 +55,15 @@ export function getColorState(value: unknown): ColorState {
67
55
  origin: undefined as never,
68
56
  };
69
57
 
70
- if (KEYS_HSL.every(key => key in value)) {
58
+ if (COLOR_KEYS.hsl.every(key => key in value)) {
71
59
  state.hsl = getHslValue(value as Record<keyof HSLColor, unknown>);
72
- state.origin = TYPE_HSL;
73
- } else if (KEYS_HWB.every(key => key in value)) {
60
+ state.origin = COLOR_TYPE.hsl;
61
+ } else if (COLOR_KEYS.hwb.every(key => key in value)) {
74
62
  state.hwb = getHwbValue(value as Record<keyof HWBColor, unknown>);
75
- state.origin = TYPE_HWB;
76
- } else if (KEYS_RGB.every(key => key in value)) {
63
+ state.origin = COLOR_TYPE.hwb;
64
+ } else if (COLOR_KEYS.rgb.every(key => key in value)) {
77
65
  state.rgb = getRgbValue(value as Record<keyof RGBColor, unknown>);
78
- state.origin = TYPE_RGB;
66
+ state.origin = COLOR_TYPE.rgb;
79
67
  }
80
68
 
81
69
  if (state.origin != null) {
@@ -88,28 +76,30 @@ export function getColorState(value: unknown): ColorState {
88
76
 
89
77
  function getColorStateForHex(value: string): ColorState {
90
78
  const normalized = getNormalizedHex(value, true);
91
- const hex = normalized.slice(0, LENGTH_LONG);
79
+ const hex = normalized.slice(0, COLOR_LENGTHS.hexLong);
92
80
 
93
81
  return {
94
82
  hex,
95
- alpha: getAlpha(normalized.slice(LENGTH_LONG), true),
96
- origin: TYPE_HEX,
83
+ alpha: getAlpha(normalized.slice(COLOR_LENGTHS.hexLong), true),
84
+ origin: COLOR_TYPE.hex,
97
85
  };
98
86
  }
99
87
 
100
88
  function getDefaultColorState(): ColorState {
101
89
  return {
102
- alpha: getAlpha(MAX_PERCENT, false),
103
- hex: HEX_BLACK,
104
- hsl: {...DEFAULT_HSL},
105
- hwb: {...DEFAULT_HWB},
106
- rgb: {...DEFAULT_RGB},
107
- origin: TYPE_HEX,
90
+ alpha: getAlpha(COLOR_MAX.percent, false),
91
+ hex: COLOR_DEFAULTS.hexBlack,
92
+ hsl: {...COLOR_DEFAULTS.hsl},
93
+ hwb: {...COLOR_DEFAULTS.hwb},
94
+ rgb: {...COLOR_DEFAULTS.rgb},
95
+ origin: COLOR_TYPE.hex,
108
96
  };
109
97
  }
110
98
 
111
99
  function setColorValue<Type extends ColorType>(
100
+ color: Color,
112
101
  state: ColorState,
102
+ subscriptions: Subscriptions<Function>,
113
103
  type: Type,
114
104
  value: ColorState[Type],
115
105
  alpha?: number | string,
@@ -123,11 +113,31 @@ function setColorValue<Type extends ColorType>(
123
113
  state[type] = value;
124
114
 
125
115
  if (alpha != null) {
126
- state.alpha = getAlpha(alpha, type === TYPE_HEX);
116
+ state.alpha = getAlpha(alpha, type === COLOR_TYPE.hex);
117
+ }
118
+
119
+ for (const type of COLOR_TYPE.all) {
120
+ const callbacks = subscriptions.values.to.keyed?.get(type);
121
+
122
+ if (callbacks != null) {
123
+ for (const callback of callbacks.values()) {
124
+ callback(color[type]);
125
+ }
126
+ }
127
+ }
128
+
129
+ for (const callback of subscriptions.values.to.any.values()) {
130
+ callback(color);
127
131
  }
128
132
  }
129
133
 
130
- export function setHexColor(state: ColorState, value: string, alpha: boolean): void {
134
+ export function setHexColor(
135
+ color: Color,
136
+ state: ColorState,
137
+ subscriptions: Subscriptions<Function>,
138
+ value: string,
139
+ alpha: boolean,
140
+ ): void {
131
141
  if (!isHexColor(value) || (!alpha && value === state.hex)) {
132
142
  return;
133
143
  }
@@ -135,21 +145,31 @@ export function setHexColor(state: ColorState, value: string, alpha: boolean): v
135
145
  const normalized = getNormalizedHex(value, true);
136
146
 
137
147
  setColorValue(
148
+ color,
138
149
  state,
139
- TYPE_HEX,
140
- normalized.slice(0, LENGTH_LONG),
141
- alpha ? normalized.slice(LENGTH_LONG) : undefined,
150
+ subscriptions,
151
+ COLOR_TYPE.hex,
152
+ normalized.slice(0, COLOR_LENGTHS.hexLong),
153
+ alpha ? normalized.slice(COLOR_LENGTHS.hexLong) : undefined,
142
154
  );
143
155
  }
144
156
 
145
- export function setHSLColor(state: ColorState, value: unknown, alpha: boolean): void {
157
+ export function setHSLColor(
158
+ color: Color,
159
+ state: ColorState,
160
+ subscriptions: Subscriptions<Function>,
161
+ value: unknown,
162
+ alpha: boolean,
163
+ ): void {
146
164
  if (!isHslLike(value)) {
147
165
  return;
148
166
  }
149
167
 
150
168
  setColorValue(
169
+ color,
151
170
  state,
152
- TYPE_HSL,
171
+ subscriptions,
172
+ COLOR_TYPE.hsl,
153
173
  {
154
174
  hue: getDegrees((value as HSLColor).hue),
155
175
  saturation: getPercentage((value as HSLColor).saturation),
@@ -159,14 +179,22 @@ export function setHSLColor(state: ColorState, value: unknown, alpha: boolean):
159
179
  );
160
180
  }
161
181
 
162
- export function setHWBColor(state: ColorState, value: unknown, alpha: boolean): void {
182
+ export function setHWBColor(
183
+ color: Color,
184
+ state: ColorState,
185
+ subscriptions: Subscriptions<Function>,
186
+ value: unknown,
187
+ alpha: boolean,
188
+ ): void {
163
189
  if (!isHwbLike(value)) {
164
190
  return;
165
191
  }
166
192
 
167
193
  setColorValue(
194
+ color,
168
195
  state,
169
- TYPE_HWB,
196
+ subscriptions,
197
+ COLOR_TYPE.hwb,
170
198
  {
171
199
  hue: getDegrees((value as HWBColor).hue),
172
200
  whiteness: getPercentage((value as HWBColor).whiteness),
@@ -176,14 +204,22 @@ export function setHWBColor(state: ColorState, value: unknown, alpha: boolean):
176
204
  );
177
205
  }
178
206
 
179
- export function setRGBColor(state: ColorState, value: unknown, alpha: boolean): void {
207
+ export function setRGBColor(
208
+ color: Color,
209
+ state: ColorState,
210
+ subscriptions: Subscriptions<Function>,
211
+ value: unknown,
212
+ alpha: boolean,
213
+ ): void {
180
214
  if (!isRgbLike(value)) {
181
215
  return;
182
216
  }
183
217
 
184
218
  setColorValue(
219
+ color,
185
220
  state,
186
- TYPE_RGB,
221
+ subscriptions,
222
+ COLOR_TYPE.rgb,
187
223
  {
188
224
  red: getHexValue((value as RGBColor).red),
189
225
  green: getHexValue((value as RGBColor).green),
@@ -1,5 +1,8 @@
1
1
  // #region Types
2
2
 
3
+ import type {Subscription} from '../internal/subscription';
4
+ import type {COLOR_ALPHA, COLOR_TYPE} from './constants';
5
+
3
6
  export type Alpha = {
4
7
  hex: string;
5
8
  value: number;
@@ -152,6 +155,85 @@ export type Color = {
152
155
  */
153
156
  set rgba(value: RGBAColor);
154
157
 
158
+ /**
159
+ * Subscribe to alpha channel _(opacity)_ changes of the color
160
+ *
161
+ * @param key Color property to subscribe to
162
+ * @param callback Callback function for changes
163
+ */
164
+ subscribe(key: 'alpha', callback: (value: number) => void): Subscription;
165
+
166
+ /**
167
+ * Subscribe to hex color changes of the color
168
+ *
169
+ * @param key Color type to subscribe to
170
+ * @param callback Callback function for changes
171
+ */
172
+ subscribe(key: typeof COLOR_TYPE.hex, callback: (value: string) => void): Subscription;
173
+
174
+ /**
175
+ * Subscribe to hex color changes of the color with alpha channel _(opacity)_
176
+ *
177
+ * @param key Color type to subscribe to
178
+ * @param callback Callback function for changes
179
+ */
180
+ subscribe(key: typeof COLOR_TYPE.hexa, callback: (value: string) => void): Subscription;
181
+
182
+ /**
183
+ * Subscribe to _HSL_ color changes of the color
184
+ *
185
+ * @param key Color type to subscribe to
186
+ * @param callback Callback function for changes
187
+ */
188
+ subscribe(key: typeof COLOR_TYPE.hsl, callback: (value: HSLColor) => void): Subscription;
189
+
190
+ /**
191
+ * Subscribe to _HSL(A)_ color changes of the color
192
+ *
193
+ * @param key Color type to subscribe to
194
+ * @param callback Callback function for changes
195
+ */
196
+ subscribe(key: typeof COLOR_TYPE.hsla, callback: (value: HSLAColor) => void): Subscription;
197
+
198
+ /**
199
+ * Subscribe to _HWB_ color changes of the color
200
+ *
201
+ * @param key Color type to subscribe to
202
+ * @param callback Callback function for changes
203
+ */
204
+ subscribe(key: typeof COLOR_TYPE.hwb, callback: (value: HWBColor) => void): Subscription;
205
+
206
+ /**
207
+ * Subscribe to _HWB(A)_ color changes of the color
208
+ *
209
+ * @param key Color type to subscribe to
210
+ * @param callback Callback function for changes
211
+ */
212
+ subscribe(key: typeof COLOR_TYPE.hwba, callback: (value: HWBAColor) => void): Subscription;
213
+
214
+ /**
215
+ * Subscribe to _RGB_ color changes of the color
216
+ *
217
+ * @param key Color type to subscribe to
218
+ * @param callback Callback function for changes
219
+ */
220
+ subscribe(key: typeof COLOR_TYPE.rgb, callback: (value: RGBColor) => void): Subscription;
221
+
222
+ /**
223
+ * Subscribe to _RGBA_ color changes of the color
224
+ *
225
+ * @param key Color type to subscribe to
226
+ * @param callback Callback function for changes
227
+ */
228
+ subscribe(key: typeof COLOR_TYPE.rgba, callback: (value: RGBAColor) => void): Subscription;
229
+
230
+ /**
231
+ * Subscribe to any color changes of the color
232
+ *
233
+ * @param callback Callback function for changes
234
+ */
235
+ subscribe(callback: (value: Color) => void): Subscription;
236
+
155
237
  /**
156
238
  * Get the color as a hex string
157
239
  *
@@ -190,6 +272,13 @@ export type Color = {
190
272
  * @returns Hex color string
191
273
  */
192
274
  toString(): string;
275
+
276
+ /**
277
+ * Unsubscribe from all color changes of the color
278
+ *
279
+ * _(To unsubscribe from a specific color change, use the `unsubscribe()` method on the `Subscription` returned by the individual `subscribe()` method)_
280
+ */
281
+ unsubscribe(): void;
193
282
  };
194
283
 
195
284
  type ColorWithAlpha = {
@@ -262,7 +351,11 @@ export type RGBColor = {
262
351
  red: number;
263
352
  };
264
353
 
265
- export type ColorProperty = 'alpha' | keyof HSLColor | keyof HWBColor | keyof RGBColor;
354
+ export type ColorProperty =
355
+ | typeof COLOR_ALPHA.name
356
+ | keyof HSLColor
357
+ | keyof HWBColor
358
+ | keyof RGBColor;
266
359
 
267
360
  export type ColorState = {
268
361
  alpha: Alpha;