@oscarpalmer/atoms 0.191.0 → 0.192.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 (44) 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 +117 -45
  19. package/dist/index.mjs +522 -360
  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/package.json +1 -1
  24. package/src/beacon.ts +32 -117
  25. package/src/color/constants.ts +115 -78
  26. package/src/color/instance.ts +65 -12
  27. package/src/color/misc/alpha.ts +13 -21
  28. package/src/color/misc/format.ts +4 -4
  29. package/src/color/misc/get.ts +23 -40
  30. package/src/color/misc/is.ts +29 -39
  31. package/src/color/misc/state.ts +77 -41
  32. package/src/color/models.ts +94 -1
  33. package/src/color/space/hex.ts +18 -23
  34. package/src/color/space/hsl.ts +16 -24
  35. package/src/color/space/hwb.ts +10 -10
  36. package/src/color/space/rgb.ts +19 -16
  37. package/src/herald.ts +1 -3
  38. package/src/index.ts +1 -0
  39. package/src/internal/subscription.ts +264 -0
  40. package/src/models.ts +5 -0
  41. package/src/string/fuzzy.ts +1 -1
  42. package/src/value/freeze.ts +2 -2
  43. package/src/value/shake.ts +1 -1
  44. package/src/value/transform.ts +1 -1
@@ -1,16 +1,16 @@
1
- import "../constants.mjs";
1
+ import { COLOR_TYPE } from "../constants.mjs";
2
2
  import { getColorFromState } from "./state.mjs";
3
3
  //#region src/color/misc/format.ts
4
4
  function formatHslColor(state, alpha) {
5
- const { hue, lightness, saturation } = getColorFromState(state, "hsl");
5
+ const { hue, lightness, saturation } = getColorFromState(state, COLOR_TYPE.hsl);
6
6
  return `hsl(${hue}deg ${saturation}% ${lightness}%${getSuffix(state, alpha)})`;
7
7
  }
8
8
  function formatHwbColor(state, alpha) {
9
- const { blackness, hue, whiteness } = getColorFromState(state, "hwb");
9
+ const { blackness, hue, whiteness } = getColorFromState(state, COLOR_TYPE.hwb);
10
10
  return `hwb(${hue}deg ${whiteness}% ${blackness}%${getSuffix(state, alpha)})`;
11
11
  }
12
12
  function formatRgbColor(state, alpha) {
13
- const { blue, green, red } = getColorFromState(state, "rgb");
13
+ const { blue, green, red } = getColorFromState(state, COLOR_TYPE.rgb);
14
14
  return `rgb(${red} ${green} ${blue}${getSuffix(state, alpha)})`;
15
15
  }
16
16
  function getSuffix(state, alpha) {
@@ -1,5 +1,5 @@
1
1
  import { clamp } from "../../internal/number.mjs";
2
- import { HEX_BLACK, HEX_WHITE, SRGB_LUMINANCE_EXPONENT, SRGB_LUMINANCE_MODIFIER, SRGB_LUMINANCE_MULTIPLIER, SRGB_LUMINANCE_OFFSET } from "../constants.mjs";
2
+ import { COLOR_DEFAULTS, COLOR_MAX, COLOR_SRGB, COLOR_TYPE } from "../constants.mjs";
3
3
  import { round } from "../../internal/math/misc.mjs";
4
4
  import { getColorFromState, getColorState } from "./state.mjs";
5
5
  import { color } from "../instance.mjs";
@@ -8,19 +8,19 @@ function getClampedValue(value, minimum, maximum, rounding) {
8
8
  return typeof value === "number" && !Number.isNaN(value) ? clamp(rounding ?? false ? round(value) : value, minimum, maximum) : minimum;
9
9
  }
10
10
  function getForegroundColor(value, hex) {
11
- const { blue, green, red } = getColorFromState(getColorState(value), "rgb");
11
+ const { blue, green, red } = getColorFromState(getColorState(value), COLOR_TYPE.rgb);
12
12
  const values = [
13
- blue / 255,
14
- green / 255,
15
- red / 255
13
+ blue / COLOR_MAX.hex,
14
+ green / COLOR_MAX.hex,
15
+ red / COLOR_MAX.hex
16
16
  ];
17
17
  const { length } = values;
18
18
  for (let index = 0; index < length; index += 1) {
19
19
  const color = values[index];
20
- if (color <= .03928) values[index] /= SRGB_LUMINANCE_MULTIPLIER;
21
- else values[index] = ((color + SRGB_LUMINANCE_OFFSET) / SRGB_LUMINANCE_MODIFIER) ** SRGB_LUMINANCE_EXPONENT;
20
+ if (color <= COLOR_SRGB.luminanceMinimum) values[index] /= COLOR_SRGB.luminanceMultiplier;
21
+ else values[index] = ((color + COLOR_SRGB.luminanceOffset) / COLOR_SRGB.luminanceModifier) ** COLOR_SRGB.luminanceExponent;
22
22
  }
23
- const foreground = .2126 * values[2] + .7152 * values[1] + .0722 * values[0] > .625 ? HEX_BLACK : HEX_WHITE;
23
+ const foreground = COLOR_SRGB.luminanceRed * values[2] + COLOR_SRGB.luminanceGreen * values[1] + COLOR_SRGB.luminanceBlue * values[0] > COLOR_SRGB.luminanceThreshold ? COLOR_DEFAULTS.hexBlack : COLOR_DEFAULTS.hexWhite;
24
24
  return hex === true ? foreground : color(foreground);
25
25
  }
26
26
  /**
@@ -46,13 +46,13 @@ function getHexaColor(value) {
46
46
  * @returns Hex color string
47
47
  */
48
48
  function getHexColor(value) {
49
- return getColorFromState(getColorState(value), "hex");
49
+ return getColorFromState(getColorState(value), COLOR_TYPE.hex);
50
50
  }
51
51
  function getHexValue(value) {
52
- return getClampedValue(value, 0, 255, true);
52
+ return getClampedValue(value, 0, COLOR_MAX.hex, true);
53
53
  }
54
54
  function getDegrees(value) {
55
- return getClampedValue(value, 0, 360);
55
+ return getClampedValue(value, 0, COLOR_MAX.degree);
56
56
  }
57
57
  /**
58
58
  * Get the _HSLA_ color from any kind of value
@@ -66,7 +66,7 @@ function getDegrees(value) {
66
66
  function getHslaColor(value) {
67
67
  const state = getColorState(value);
68
68
  return {
69
- ...getColorFromState(state, "hsl"),
69
+ ...getColorFromState(state, COLOR_TYPE.hsl),
70
70
  alpha: state.alpha.value
71
71
  };
72
72
  }
@@ -80,7 +80,7 @@ function getHslaColor(value) {
80
80
  * @returns _HWB_ color
81
81
  */
82
82
  function getHwbColor(value) {
83
- return getColorFromState(getColorState(value), "hwb");
83
+ return getColorFromState(getColorState(value), COLOR_TYPE.hwb);
84
84
  }
85
85
  /**
86
86
  * Get the _HWBA_ color from any kind of value
@@ -94,7 +94,7 @@ function getHwbColor(value) {
94
94
  function getHwbaColor(value) {
95
95
  const state = getColorState(value);
96
96
  return {
97
- ...getColorFromState(state, "hwb"),
97
+ ...getColorFromState(state, COLOR_TYPE.hwb),
98
98
  alpha: state.alpha.value
99
99
  };
100
100
  }
@@ -108,10 +108,10 @@ function getHwbaColor(value) {
108
108
  * @returns _HSL_ color
109
109
  */
110
110
  function getHslColor(value) {
111
- return getColorFromState(getColorState(value), "hsl");
111
+ return getColorFromState(getColorState(value), COLOR_TYPE.hsl);
112
112
  }
113
113
  function getPercentage(value) {
114
- return getClampedValue(value, 0, 100);
114
+ return getClampedValue(value, 0, COLOR_MAX.percent);
115
115
  }
116
116
  /**
117
117
  * Get the _RGBA_ color from any kind of value
@@ -125,7 +125,7 @@ function getPercentage(value) {
125
125
  function getRgbaColor(value) {
126
126
  const state = getColorState(value);
127
127
  return {
128
- ...getColorFromState(state, "rgb"),
128
+ ...getColorFromState(state, COLOR_TYPE.rgb),
129
129
  alpha: state.alpha.value
130
130
  };
131
131
  }
@@ -139,7 +139,7 @@ function getRgbaColor(value) {
139
139
  * @returns _RGB_ color
140
140
  */
141
141
  function getRgbColor(value) {
142
- return getColorFromState(getColorState(value), "rgb");
142
+ return getColorFromState(getColorState(value), COLOR_TYPE.rgb);
143
143
  }
144
144
  //#endregion
145
145
  export { getDegrees, getForegroundColor, getHexColor, getHexValue, getHexaColor, getHslColor, getHslaColor, getHwbColor, getHwbaColor, getPercentage, getRgbColor, getRgbaColor };
@@ -1,14 +1,15 @@
1
+ import { isPlainObject } from "../../internal/is.mjs";
1
2
  import { between } from "../../internal/number.mjs";
2
- import { EXPRESSION_HEX_LONG, EXPRESSION_HEX_SHORT, EXPRESSION_PREFIX, KEYS_HSL, KEYS_HSLA, KEYS_HWB, KEYS_HWBA, KEYS_RGB, KEYS_RGBA } from "../constants.mjs";
3
+ import { COLOR_ALPHA, COLOR_EXPRESSION, COLOR_KEYS, COLOR_LENGTHS, COLOR_MAX, COLOR_PROPERTY } from "../constants.mjs";
3
4
  //#region src/color/misc/is.ts
4
5
  function hasKeys(value, keys) {
5
6
  return typeof value === "object" && value !== null && keys.every((key) => key in value);
6
7
  }
7
8
  function isAlpha(value) {
8
- return typeof value === "number" && between(value, 0, 100);
9
+ return typeof value === "number" && between(value, COLOR_ALPHA.noneValue, COLOR_MAX.percent);
9
10
  }
10
11
  function isBytey(value) {
11
- return typeof value === "number" && between(value, 0, 255);
12
+ return typeof value === "number" && between(value, 0, COLOR_MAX.hex);
12
13
  }
13
14
  /**
14
15
  * Is the value a _Color_?
@@ -17,7 +18,7 @@ function isBytey(value) {
17
18
  * @returns `true` if the value is a _Color_, otherwise `false`
18
19
  */
19
20
  function isColor(value) {
20
- return typeof value === "object" && value !== null && "$color" in value && value["$color"] === true;
21
+ return isPlainObject(value) && COLOR_PROPERTY.name in value && value[COLOR_PROPERTY.name] === true;
21
22
  }
22
23
  function isColorValue(obj, properties) {
23
24
  if (typeof obj !== "object" || obj === null) return false;
@@ -31,7 +32,7 @@ function isColorValue(obj, properties) {
31
32
  return true;
32
33
  }
33
34
  function isDegree(value) {
34
- return typeof value === "number" && between(value, 0, 360);
35
+ return typeof value === "number" && between(value, 0, COLOR_MAX.degree);
35
36
  }
36
37
  /**
37
38
  * Is the value a hex color?
@@ -51,10 +52,10 @@ function isDegree(value) {
51
52
  */
52
53
  function isHexColor(value, alpha) {
53
54
  if (typeof value !== "string") return false;
54
- if (!(EXPRESSION_HEX_SHORT.test(value) || EXPRESSION_HEX_LONG.test(value))) return false;
55
+ if (!(COLOR_EXPRESSION.hexShort.test(value) || COLOR_EXPRESSION.hexLong.test(value))) return false;
55
56
  if (alpha === false) {
56
- const unprefixed = value.replace(EXPRESSION_PREFIX, "");
57
- return unprefixed.length === 3 || unprefixed.length === 6;
57
+ const unprefixed = value.replace(COLOR_EXPRESSION.prefix, "");
58
+ return unprefixed.length === COLOR_LENGTHS.hexShort || unprefixed.length === COLOR_LENGTHS.hexLong;
58
59
  }
59
60
  return true;
60
61
  }
@@ -65,10 +66,10 @@ function isHexColor(value, alpha) {
65
66
  * @returns `true` if the value is an _HSLA_ color, otherwise `false`
66
67
  */
67
68
  function isHslaColor(value) {
68
- return isColorValue(value, KEYS_HSLA);
69
+ return isColorValue(value, COLOR_KEYS.hsla);
69
70
  }
70
71
  function isHslaLike(value) {
71
- return hasKeys(value, KEYS_HSLA);
72
+ return hasKeys(value, COLOR_KEYS.hsla);
72
73
  }
73
74
  /**
74
75
  * Is the value an _HSL_ color?
@@ -77,10 +78,10 @@ function isHslaLike(value) {
77
78
  * @returns `true` if the value is an _HSL_ color, otherwise `false`
78
79
  */
79
80
  function isHslColor(value) {
80
- return isColorValue(value, KEYS_HSLA) || isColorValue(value, KEYS_HSL);
81
+ return isColorValue(value, COLOR_KEYS.hsla) || isColorValue(value, COLOR_KEYS.hsl);
81
82
  }
82
83
  function isHslLike(value) {
83
- return hasKeys(value, KEYS_HSL);
84
+ return hasKeys(value, COLOR_KEYS.hsl);
84
85
  }
85
86
  /**
86
87
  * Is the value an _HWBA_ color?
@@ -89,10 +90,10 @@ function isHslLike(value) {
89
90
  * @returns `true` if the value is an _HWBA_ color, otherwise `false`
90
91
  */
91
92
  function isHwbaColor(value) {
92
- return isColorValue(value, KEYS_HWBA);
93
+ return isColorValue(value, COLOR_KEYS.hwba);
93
94
  }
94
95
  function isHwbaLike(value) {
95
- return hasKeys(value, KEYS_HWBA);
96
+ return hasKeys(value, COLOR_KEYS.hwba);
96
97
  }
97
98
  /**
98
99
  * Is the value an _HWB_ color?
@@ -101,10 +102,10 @@ function isHwbaLike(value) {
101
102
  * @returns `true` if the value is an _HWB_ color, otherwise `false`
102
103
  */
103
104
  function isHwbColor(value) {
104
- return isColorValue(value, KEYS_HWB) || isColorValue(value, KEYS_HWBA);
105
+ return isColorValue(value, COLOR_KEYS.hwb) || isColorValue(value, COLOR_KEYS.hwba);
105
106
  }
106
107
  function isHwbLike(value) {
107
- return hasKeys(value, KEYS_HWB);
108
+ return hasKeys(value, COLOR_KEYS.hwb);
108
109
  }
109
110
  /**
110
111
  * Is the value an _RGBA_ color?
@@ -113,10 +114,10 @@ function isHwbLike(value) {
113
114
  * @returns `true` if the value is an _RGBA_ color, otherwise `false`
114
115
  */
115
116
  function isRgbaColor(value) {
116
- return isColorValue(value, KEYS_RGBA);
117
+ return isColorValue(value, COLOR_KEYS.rgba);
117
118
  }
118
119
  function isRgbaLike(value) {
119
- return hasKeys(value, KEYS_RGBA);
120
+ return hasKeys(value, COLOR_KEYS.rgba);
120
121
  }
121
122
  /**
122
123
  * Is the value an _RGB_ color?
@@ -125,13 +126,13 @@ function isRgbaLike(value) {
125
126
  * @returns `true` if the value is an _RGB_ color, otherwise `false`
126
127
  */
127
128
  function isRgbColor(value) {
128
- return isColorValue(value, KEYS_RGBA) || isColorValue(value, KEYS_RGB);
129
+ return isColorValue(value, COLOR_KEYS.rgba) || isColorValue(value, COLOR_KEYS.rgb);
129
130
  }
130
131
  function isRgbLike(value) {
131
- return hasKeys(value, KEYS_RGB);
132
+ return hasKeys(value, COLOR_KEYS.rgb);
132
133
  }
133
134
  function isPercentage(value) {
134
- return typeof value === "number" && between(value, 0, 100);
135
+ return typeof value === "number" && between(value, 0, COLOR_MAX.percent);
135
136
  }
136
137
  const validators = {
137
138
  alpha: isAlpha,
@@ -1,10 +1,11 @@
1
- import { ColorState, ColorType } from "../models.mjs";
1
+ import { Subscriptions } from "../../internal/subscription.mjs";
2
+ import { Color, ColorState, ColorType } from "../models.mjs";
2
3
  //#region src/color/misc/state.d.ts
3
4
  declare function getColorFromState<Type extends ColorType>(state: ColorState, type: Type): NonNullable<ColorState[Type]>;
4
5
  declare function getColorState(value: unknown): ColorState;
5
- declare function setHexColor(state: ColorState, value: string, alpha: boolean): void;
6
- declare function setHSLColor(state: ColorState, value: unknown, alpha: boolean): void;
7
- declare function setHWBColor(state: ColorState, value: unknown, alpha: boolean): void;
8
- declare function setRGBColor(state: ColorState, value: unknown, alpha: boolean): void;
6
+ declare function setHexColor(color: Color, state: ColorState, subscriptions: Subscriptions<Function>, value: string, alpha: boolean): void;
7
+ declare function setHSLColor(color: Color, state: ColorState, subscriptions: Subscriptions<Function>, value: unknown, alpha: boolean): void;
8
+ declare function setHWBColor(color: Color, state: ColorState, subscriptions: Subscriptions<Function>, value: unknown, alpha: boolean): void;
9
+ declare function setRGBColor(color: Color, state: ColorState, subscriptions: Subscriptions<Function>, value: unknown, alpha: boolean): void;
9
10
  //#endregion
10
11
  export { getColorFromState, getColorState, setHSLColor, setHWBColor, setHexColor, setRGBColor };
@@ -1,4 +1,4 @@
1
- import { DEFAULT_HSL, DEFAULT_HWB, DEFAULT_RGB, HEX_BLACK, KEYS_HSL, KEYS_HWB, KEYS_RGB } from "../constants.mjs";
1
+ import { COLOR_DEFAULTS, COLOR_KEYS, COLOR_LENGTHS, COLOR_MAX, COLOR_TYPE } from "../constants.mjs";
2
2
  import { getAlpha } from "./alpha.mjs";
3
3
  import { getDegrees, getHexValue, getPercentage } from "./get.mjs";
4
4
  import { isColor, isHexColor, isHslLike, isHwbLike, isRgbLike } from "./is.mjs";
@@ -27,15 +27,15 @@ function getColorState(value) {
27
27
  alpha: getAlpha(value.alpha, false),
28
28
  origin: void 0
29
29
  };
30
- if (KEYS_HSL.every((key) => key in value)) {
30
+ if (COLOR_KEYS.hsl.every((key) => key in value)) {
31
31
  state.hsl = getHslValue(value);
32
- state.origin = "hsl";
33
- } else if (KEYS_HWB.every((key) => key in value)) {
32
+ state.origin = COLOR_TYPE.hsl;
33
+ } else if (COLOR_KEYS.hwb.every((key) => key in value)) {
34
34
  state.hwb = getHwbValue(value);
35
- state.origin = "hwb";
36
- } else if (KEYS_RGB.every((key) => key in value)) {
35
+ state.origin = COLOR_TYPE.hwb;
36
+ } else if (COLOR_KEYS.rgb.every((key) => key in value)) {
37
37
  state.rgb = getRgbValue(value);
38
- state.origin = "rgb";
38
+ state.origin = COLOR_TYPE.rgb;
39
39
  }
40
40
  if (state.origin != null) return state;
41
41
  }
@@ -44,54 +44,59 @@ function getColorState(value) {
44
44
  function getColorStateForHex(value) {
45
45
  const normalized = getNormalizedHex(value, true);
46
46
  return {
47
- hex: normalized.slice(0, 6),
48
- alpha: getAlpha(normalized.slice(6), true),
49
- origin: "hex"
47
+ hex: normalized.slice(0, COLOR_LENGTHS.hexLong),
48
+ alpha: getAlpha(normalized.slice(COLOR_LENGTHS.hexLong), true),
49
+ origin: COLOR_TYPE.hex
50
50
  };
51
51
  }
52
52
  function getDefaultColorState() {
53
53
  return {
54
- alpha: getAlpha(100, false),
55
- hex: HEX_BLACK,
56
- hsl: { ...DEFAULT_HSL },
57
- hwb: { ...DEFAULT_HWB },
58
- rgb: { ...DEFAULT_RGB },
59
- origin: "hex"
54
+ alpha: getAlpha(COLOR_MAX.percent, false),
55
+ hex: COLOR_DEFAULTS.hexBlack,
56
+ hsl: { ...COLOR_DEFAULTS.hsl },
57
+ hwb: { ...COLOR_DEFAULTS.hwb },
58
+ rgb: { ...COLOR_DEFAULTS.rgb },
59
+ origin: COLOR_TYPE.hex
60
60
  };
61
61
  }
62
- function setColorValue(state, type, value, alpha) {
62
+ function setColorValue(color, state, subscriptions, type, value, alpha) {
63
63
  state.hex = void 0;
64
64
  state.hsl = void 0;
65
65
  state.hwb = void 0;
66
66
  state.rgb = void 0;
67
67
  state.origin = type;
68
68
  state[type] = value;
69
- if (alpha != null) state.alpha = getAlpha(alpha, type === "hex");
69
+ if (alpha != null) state.alpha = getAlpha(alpha, type === COLOR_TYPE.hex);
70
+ for (const type of COLOR_TYPE.all) {
71
+ const callbacks = subscriptions.values.to.keyed?.get(type);
72
+ if (callbacks != null) for (const callback of callbacks.values()) callback(color[type]);
73
+ }
74
+ for (const callback of subscriptions.values.to.any.values()) callback(color);
70
75
  }
71
- function setHexColor(state, value, alpha) {
76
+ function setHexColor(color, state, subscriptions, value, alpha) {
72
77
  if (!isHexColor(value) || !alpha && value === state.hex) return;
73
78
  const normalized = getNormalizedHex(value, true);
74
- setColorValue(state, "hex", normalized.slice(0, 6), alpha ? normalized.slice(6) : void 0);
79
+ setColorValue(color, state, subscriptions, COLOR_TYPE.hex, normalized.slice(0, COLOR_LENGTHS.hexLong), alpha ? normalized.slice(COLOR_LENGTHS.hexLong) : void 0);
75
80
  }
76
- function setHSLColor(state, value, alpha) {
81
+ function setHSLColor(color, state, subscriptions, value, alpha) {
77
82
  if (!isHslLike(value)) return;
78
- setColorValue(state, "hsl", {
83
+ setColorValue(color, state, subscriptions, COLOR_TYPE.hsl, {
79
84
  hue: getDegrees(value.hue),
80
85
  saturation: getPercentage(value.saturation),
81
86
  lightness: getPercentage(value.lightness)
82
87
  }, alpha ? value.alpha : void 0);
83
88
  }
84
- function setHWBColor(state, value, alpha) {
89
+ function setHWBColor(color, state, subscriptions, value, alpha) {
85
90
  if (!isHwbLike(value)) return;
86
- setColorValue(state, "hwb", {
91
+ setColorValue(color, state, subscriptions, COLOR_TYPE.hwb, {
87
92
  hue: getDegrees(value.hue),
88
93
  whiteness: getPercentage(value.whiteness),
89
94
  blackness: getPercentage(value.blackness)
90
95
  }, alpha ? value.alpha : void 0);
91
96
  }
92
- function setRGBColor(state, value, alpha) {
97
+ function setRGBColor(color, state, subscriptions, value, alpha) {
93
98
  if (!isRgbLike(value)) return;
94
- setColorValue(state, "rgb", {
99
+ setColorValue(color, state, subscriptions, COLOR_TYPE.rgb, {
95
100
  red: getHexValue(value.red),
96
101
  green: getHexValue(value.green),
97
102
  blue: getHexValue(value.blue)
@@ -1,3 +1,5 @@
1
+ import { Subscription } from "../internal/subscription.mjs";
2
+ import { COLOR_ALPHA, COLOR_TYPE } from "./constants.mjs";
1
3
  //#region src/color/models.d.ts
2
4
  type Alpha = {
3
5
  hex: string;
@@ -131,6 +133,75 @@ type Color = {
131
133
  * @param value New _RGBA_ color
132
134
  */
133
135
  set rgba(value: RGBAColor);
136
+ /**
137
+ * Subscribe to alpha channel _(opacity)_ changes of the color
138
+ *
139
+ * @param key Color property to subscribe to
140
+ * @param callback Callback function for changes
141
+ */
142
+ subscribe(key: 'alpha', callback: (value: number) => void): Subscription;
143
+ /**
144
+ * Subscribe to hex color changes of the color
145
+ *
146
+ * @param key Color type to subscribe to
147
+ * @param callback Callback function for changes
148
+ */
149
+ subscribe(key: typeof COLOR_TYPE.hex, callback: (value: string) => void): Subscription;
150
+ /**
151
+ * Subscribe to hex color changes of the color with alpha channel _(opacity)_
152
+ *
153
+ * @param key Color type to subscribe to
154
+ * @param callback Callback function for changes
155
+ */
156
+ subscribe(key: typeof COLOR_TYPE.hexa, callback: (value: string) => void): Subscription;
157
+ /**
158
+ * Subscribe to _HSL_ color changes of the color
159
+ *
160
+ * @param key Color type to subscribe to
161
+ * @param callback Callback function for changes
162
+ */
163
+ subscribe(key: typeof COLOR_TYPE.hsl, callback: (value: HSLColor) => void): Subscription;
164
+ /**
165
+ * Subscribe to _HSL(A)_ color changes of the color
166
+ *
167
+ * @param key Color type to subscribe to
168
+ * @param callback Callback function for changes
169
+ */
170
+ subscribe(key: typeof COLOR_TYPE.hsla, callback: (value: HSLAColor) => void): Subscription;
171
+ /**
172
+ * Subscribe to _HWB_ color changes of the color
173
+ *
174
+ * @param key Color type to subscribe to
175
+ * @param callback Callback function for changes
176
+ */
177
+ subscribe(key: typeof COLOR_TYPE.hwb, callback: (value: HWBColor) => void): Subscription;
178
+ /**
179
+ * Subscribe to _HWB(A)_ color changes of the color
180
+ *
181
+ * @param key Color type to subscribe to
182
+ * @param callback Callback function for changes
183
+ */
184
+ subscribe(key: typeof COLOR_TYPE.hwba, callback: (value: HWBAColor) => void): Subscription;
185
+ /**
186
+ * Subscribe to _RGB_ color changes of the color
187
+ *
188
+ * @param key Color type to subscribe to
189
+ * @param callback Callback function for changes
190
+ */
191
+ subscribe(key: typeof COLOR_TYPE.rgb, callback: (value: RGBColor) => void): Subscription;
192
+ /**
193
+ * Subscribe to _RGBA_ color changes of the color
194
+ *
195
+ * @param key Color type to subscribe to
196
+ * @param callback Callback function for changes
197
+ */
198
+ subscribe(key: typeof COLOR_TYPE.rgba, callback: (value: RGBAColor) => void): Subscription;
199
+ /**
200
+ * Subscribe to any color changes of the color
201
+ *
202
+ * @param callback Callback function for changes
203
+ */
204
+ subscribe(callback: (value: Color) => void): Subscription;
134
205
  /**
135
206
  * Get the color as a hex string
136
207
  *
@@ -165,6 +236,12 @@ type Color = {
165
236
  * @returns Hex color string
166
237
  */
167
238
  toString(): string;
239
+ /**
240
+ * Unsubscribe from all color changes of the color
241
+ *
242
+ * _(To unsubscribe from a specific color change, use the `unsubscribe()` method on the `Subscription` returned by the individual `subscribe()` method)_
243
+ */
244
+ unsubscribe(): void;
168
245
  };
169
246
  type ColorWithAlpha = {
170
247
  /**
@@ -229,7 +306,7 @@ type RGBColor = {
229
306
  */
230
307
  red: number;
231
308
  };
232
- type ColorProperty = 'alpha' | keyof HSLColor | keyof HWBColor | keyof RGBColor;
309
+ type ColorProperty = typeof COLOR_ALPHA.name | keyof HSLColor | keyof HWBColor | keyof RGBColor;
233
310
  type ColorState = {
234
311
  alpha: Alpha;
235
312
  hex?: string;
@@ -1,17 +1,17 @@
1
1
  import { join } from "../../internal/string.mjs";
2
- import { ALPHA_FULL_HEX_LONG, EXPRESSION_HEX_LONG, EXPRESSION_PREFIX, HEX_BLACK } from "../constants.mjs";
2
+ import { COLOR_ALPHA, COLOR_DEFAULTS, COLOR_EXPRESSION, COLOR_LENGTHS, COLOR_MAX, COLOR_TYPE } from "../constants.mjs";
3
3
  import { getHexValue, getPercentage } from "../misc/get.mjs";
4
4
  import { isHexColor } from "../misc/is.mjs";
5
5
  import { convertRgbToHsla, convertRgbToHwba } from "./rgb.mjs";
6
6
  //#region src/color/space/hex.ts
7
7
  function convertHexToRgba(value) {
8
8
  const normalized = getNormalizedHex(value, true);
9
- const pairs = EXPRESSION_HEX_LONG.exec(normalized);
9
+ const pairs = COLOR_EXPRESSION.hexLong.exec(normalized);
10
10
  const values = [];
11
11
  const { length } = pairs;
12
12
  for (let index = 1; index < length; index += 1) values.push(Number.parseInt(pairs[index], 16));
13
13
  return {
14
- alpha: getPercentage(values[3] / 255 * 100),
14
+ alpha: getPercentage(values[3] / COLOR_MAX.hex * 100),
15
15
  blue: getHexValue(values[2]),
16
16
  green: getHexValue(values[1]),
17
17
  red: getHexValue(values[0])
@@ -19,13 +19,13 @@ function convertHexToRgba(value) {
19
19
  }
20
20
  function getColorFromHex(state, type) {
21
21
  switch (type) {
22
- case "hsl":
22
+ case COLOR_TYPE.hsl:
23
23
  state.hsl ??= hexToHsl(state.hex);
24
24
  break;
25
- case "hwb":
25
+ case COLOR_TYPE.hwb:
26
26
  state.hwb ??= hexToHwb(state.hex);
27
27
  break;
28
- case "rgb": state.rgb ??= hexToRgb(state.hex);
28
+ case COLOR_TYPE.rgb: state.rgb ??= hexToRgb(state.hex);
29
29
  }
30
30
  return state[type];
31
31
  }
@@ -40,14 +40,14 @@ function getColorFromHex(state, type) {
40
40
  */
41
41
  function getNormalizedHex(value, alpha) {
42
42
  const includeAlpha = alpha ?? false;
43
- if (!isHexColor(value)) return `${HEX_BLACK}${includeAlpha ? ALPHA_FULL_HEX_LONG : ""}`;
44
- const normalized = value.replace(EXPRESSION_PREFIX, "");
45
- if (normalized.length < 6) {
46
- const hex = normalized.slice(0, 3);
47
- const a = includeAlpha ? normalized[3] ?? "f" : "";
43
+ if (!isHexColor(value)) return `${COLOR_DEFAULTS.hexBlack}${includeAlpha ? COLOR_ALPHA.fullHexLong : ""}`;
44
+ const normalized = value.replace(COLOR_EXPRESSION.prefix, "");
45
+ if (normalized.length < COLOR_LENGTHS.hexLong) {
46
+ const hex = normalized.slice(0, COLOR_LENGTHS.hexShort);
47
+ const a = includeAlpha ? normalized[COLOR_LENGTHS.hexShort] ?? COLOR_ALPHA.fullHexShort : "";
48
48
  return join(`${hex}${a}`.split("").map((character) => character.repeat(2)));
49
49
  }
50
- return `${normalized.slice(0, 6)}${includeAlpha ? normalized.slice(6) || ALPHA_FULL_HEX_LONG : ""}`;
50
+ return `${normalized.slice(0, COLOR_LENGTHS.hexLong)}${includeAlpha ? normalized.slice(COLOR_LENGTHS.hexLong) || COLOR_ALPHA.fullHexLong : ""}`;
51
51
  }
52
52
  /**
53
53
  * Convert a hex color string to a _HSL_ color
@@ -1,31 +1,31 @@
1
- import { DEFAULT_HSL } from "../constants.mjs";
1
+ import { COLOR_DEFAULTS, COLOR_MAX, COLOR_TYPE } from "../constants.mjs";
2
2
  import { getAlphaValue } from "../misc/alpha.mjs";
3
3
  import { getDegrees, getHexValue, getPercentage } from "../misc/get.mjs";
4
4
  import { isHslLike } from "../misc/is.mjs";
5
5
  import { convertRgbToHex } from "./rgb.mjs";
6
6
  //#region src/color/space/hsl.ts
7
7
  function convertHslToHwba(input) {
8
- let { hue, lightness, saturation } = isHslLike(input) ? getHslValue(input) : { ...DEFAULT_HSL };
9
- lightness /= 100;
10
- saturation /= 100;
8
+ let { hue, lightness, saturation } = isHslLike(input) ? getHslValue(input) : { ...COLOR_DEFAULTS.hsl };
9
+ lightness /= COLOR_MAX.percent;
10
+ saturation /= COLOR_MAX.percent;
11
11
  const value = lightness + saturation * Math.min(lightness, 1 - lightness);
12
12
  if (value === 0) saturation = 0;
13
13
  else saturation = 2 * (1 - lightness / value);
14
14
  const blackness = 1 - value;
15
15
  return {
16
16
  hue,
17
- whiteness: (1 - saturation) * value * 100,
18
- blackness: blackness * 100,
19
- alpha: getAlphaValue(input?.alpha ?? 100)
17
+ whiteness: (1 - saturation) * value * COLOR_MAX.percent,
18
+ blackness: blackness * COLOR_MAX.percent,
19
+ alpha: getAlphaValue(input?.alpha ?? COLOR_MAX.percent)
20
20
  };
21
21
  }
22
22
  function convertHslToRgba(input) {
23
- const hsl = isHslLike(input) ? getHslValue(input) : { ...DEFAULT_HSL };
24
- const hue = hsl.hue % 360;
25
- const saturation = hsl.saturation / 100;
26
- const lightness = hsl.lightness / 100;
23
+ const hsl = isHslLike(input) ? getHslValue(input) : { ...COLOR_DEFAULTS.hsl };
24
+ const hue = hsl.hue % COLOR_MAX.degree;
25
+ const saturation = hsl.saturation / COLOR_MAX.percent;
26
+ const lightness = hsl.lightness / COLOR_MAX.percent;
27
27
  return {
28
- alpha: getAlphaValue(input?.alpha ?? 100),
28
+ alpha: getAlphaValue(input?.alpha ?? COLOR_MAX.percent),
29
29
  blue: getHexValue(getHexyValue(hue, lightness, saturation, 4)),
30
30
  green: getHexValue(getHexyValue(hue, lightness, saturation, 8)),
31
31
  red: getHexValue(getHexyValue(hue, lightness, saturation, 0))
@@ -33,19 +33,19 @@ function convertHslToRgba(input) {
33
33
  }
34
34
  function getColorFromHsl(state, type) {
35
35
  switch (type) {
36
- case "hex":
36
+ case COLOR_TYPE.hex:
37
37
  state.hex = hslToHex(state.hsl);
38
38
  break;
39
- case "hwb":
39
+ case COLOR_TYPE.hwb:
40
40
  state.hwb = hslToHwb(state.hsl);
41
41
  break;
42
- case "rgb": state.rgb = hslToRgb(state.hsl);
42
+ case COLOR_TYPE.rgb: state.rgb = hslToRgb(state.hsl);
43
43
  }
44
44
  return state[type];
45
45
  }
46
46
  function getHexyValue(hue, lightness, saturation, value) {
47
47
  const part = (value + hue / 30) % 12;
48
- return (lightness - saturation * Math.min(lightness, 1 - lightness) * Math.max(-1, Math.min(part - 3, 9 - part, 1))) * 255;
48
+ return (lightness - saturation * Math.min(lightness, 1 - lightness) * Math.max(-1, Math.min(part - 3, 9 - part, 1))) * COLOR_MAX.hex;
49
49
  }
50
50
  function getHslValue(value) {
51
51
  return {
@@ -1,4 +1,4 @@
1
- import { DEFAULT_HWB } from "../constants.mjs";
1
+ import { COLOR_DEFAULTS, COLOR_MAX, COLOR_TYPE } from "../constants.mjs";
2
2
  import { getAlphaValue } from "../misc/alpha.mjs";
3
3
  import { getDegrees, getPercentage } from "../misc/get.mjs";
4
4
  import { isHwbLike } from "../misc/is.mjs";
@@ -6,9 +6,9 @@ import { rgbToHex } from "./rgb.mjs";
6
6
  import { hslToRgb, hslToRgba } from "./hsl.mjs";
7
7
  //#region src/color/space/hwb.ts
8
8
  function convertHwbToHsl(input) {
9
- let { blackness, hue, whiteness } = isHwbLike(input) ? getHwbValue(input) : DEFAULT_HWB;
10
- blackness /= 100;
11
- whiteness /= 100;
9
+ let { blackness, hue, whiteness } = isHwbLike(input) ? getHwbValue(input) : COLOR_DEFAULTS.hwb;
10
+ blackness /= COLOR_MAX.percent;
11
+ whiteness /= COLOR_MAX.percent;
12
12
  if (blackness + whiteness > 1) {
13
13
  const total = blackness + whiteness;
14
14
  blackness /= total;
@@ -17,20 +17,20 @@ function convertHwbToHsl(input) {
17
17
  const lightness = (1 - blackness + whiteness) / 2;
18
18
  return {
19
19
  hue,
20
- saturation: getHwbSaturation(blackness, whiteness, lightness) * 100,
21
- lightness: lightness * 100,
22
- alpha: getAlphaValue(input?.alpha ?? 100)
20
+ saturation: getHwbSaturation(blackness, whiteness, lightness) * COLOR_MAX.percent,
21
+ lightness: lightness * COLOR_MAX.percent,
22
+ alpha: getAlphaValue(input?.alpha ?? COLOR_MAX.percent)
23
23
  };
24
24
  }
25
25
  function getColorFromHwb(state, type) {
26
26
  switch (type) {
27
- case "hex":
27
+ case COLOR_TYPE.hex:
28
28
  state.hex = hwbToHex(state.hwb);
29
29
  break;
30
- case "hsl":
30
+ case COLOR_TYPE.hsl:
31
31
  state.hsl = hwbToHsl(state.hwb);
32
32
  break;
33
- case "rgb": state.rgb = hwbToRgb(state.hwb);
33
+ case COLOR_TYPE.rgb: state.rgb = hwbToRgb(state.hwb);
34
34
  }
35
35
  return state[type];
36
36
  }