@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
package/src/beacon.ts CHANGED
@@ -1,5 +1,13 @@
1
1
  import {noop} from './internal/function/misc';
2
2
  import {isPlainObject} from './internal/is';
3
+ import {
4
+ clearSubscriptions,
5
+ getSubscription,
6
+ getSubscriptions,
7
+ type Subscription,
8
+ type SubscriptionProperty,
9
+ type Subscriptions,
10
+ } from './internal/subscription';
3
11
  import type {PlainObject} from './models';
4
12
 
5
13
  // #region Types
@@ -13,11 +21,6 @@ export type Beacon<Value> = {
13
21
  */
14
22
  get active(): boolean;
15
23
 
16
- /**
17
- * Is the beacon closed?
18
- */
19
- get closed(): boolean;
20
-
21
24
  /**
22
25
  * The observable that can be subscribed to
23
26
  */
@@ -29,9 +32,9 @@ export type Beacon<Value> = {
29
32
  get value(): Value;
30
33
 
31
34
  /**
32
- * Close the beacon
35
+ * Deactivate the beacon
33
36
  */
34
- close(): void;
37
+ deactivate(): void;
35
38
 
36
39
  /**
37
40
  * Emit a new value
@@ -55,9 +58,6 @@ export type Beacon<Value> = {
55
58
  finish(): void;
56
59
  };
57
60
 
58
- /**
59
- * Options for Beacon
60
- */
61
61
  export type BeaconOptions<Value> = {
62
62
  /**
63
63
  * Method for comparing values for equality
@@ -73,8 +73,8 @@ export type BeaconOptions<Value> = {
73
73
  type BeaconState<Value> = {
74
74
  active: boolean;
75
75
  observable: Observable<Value>;
76
- observers: Map<Subscription, Observer<Value>>;
77
76
  options: Required<BeaconOptions<Value>>;
77
+ subscriptions: Subscriptions<Observer<unknown>>;
78
78
  value: Value;
79
79
  };
80
80
 
@@ -85,14 +85,9 @@ export type Observable<Value> = {
85
85
  get active(): boolean;
86
86
 
87
87
  /**
88
- * Is the observable closed?
89
- */
90
- get closed(): boolean;
91
-
92
- /**
93
- * Close the observable
88
+ * Deactivate the observable
94
89
  */
95
- close(): void;
90
+ deactivate(): void;
96
91
 
97
92
  /**
98
93
  * Subscribe to value changes
@@ -122,9 +117,6 @@ type ObservableState<Value> = {
122
117
  beacon: BeaconState<Value>;
123
118
  };
124
119
 
125
- /**
126
- * An observer receives notifications from an observable
127
- */
128
120
  type Observer<Value> = {
129
121
  /**
130
122
  * Callback for when the observable is completed
@@ -140,28 +132,6 @@ type Observer<Value> = {
140
132
  next?: (value: Value) => void;
141
133
  };
142
134
 
143
- export type Subscription = {
144
- /**
145
- * Is the subscription active?
146
- */
147
- get active(): boolean;
148
-
149
- /**
150
- * Is the subscription closed?
151
- */
152
- get closed(): boolean;
153
-
154
- /**
155
- * Close the subscription
156
- */
157
- close(): void;
158
-
159
- /**
160
- * Unsubscribe from its observable
161
- */
162
- unsubscribe(): void;
163
- };
164
-
165
135
  // #endregion
166
136
 
167
137
  // #region Functions
@@ -178,12 +148,12 @@ export function beacon<Value>(value: Value, options?: BeaconOptions<Value>): Bea
178
148
  value,
179
149
  active: true,
180
150
  observable: undefined as never,
181
- observers: new Map(),
182
151
  options: getBeaconOptions(options),
152
+ subscriptions: getSubscriptions(),
183
153
  };
184
154
 
185
155
  const instance = {
186
- close: (): void => {
156
+ deactivate: (): void => {
187
157
  finishBeacon(state, false);
188
158
  },
189
159
  emit: (value: Value, finish?: boolean): void => {
@@ -206,10 +176,6 @@ export function beacon<Value>(value: Value, options?: BeaconOptions<Value>): Bea
206
176
  enumerable: true,
207
177
  get: () => state.active,
208
178
  },
209
- closed: {
210
- enumerable: true,
211
- get: () => !state.active,
212
- },
213
179
  observable: {
214
180
  enumerable: true,
215
181
  get: () => {
@@ -238,21 +204,15 @@ function finishBeacon<Value>(state: BeaconState<Value>, emit: boolean): void {
238
204
 
239
205
  state.active = false;
240
206
 
241
- const entries = [...state.observers.entries()];
242
- const {length} = entries;
243
-
244
- for (let index = 0; index < length; index += 1) {
245
- const [subscription, observer] = entries[index];
246
-
207
+ for (const [, observer] of state.subscriptions.values.to.any) {
247
208
  if (emit) {
248
209
  observer.complete?.();
249
210
  }
250
-
251
- subscription.close();
252
211
  }
253
212
 
254
- state.observable?.close();
255
- state.observers.clear();
213
+ clearSubscriptions(state.subscriptions);
214
+
215
+ state.observable?.deactivate();
256
216
 
257
217
  state.observable = undefined as never;
258
218
  }
@@ -317,16 +277,6 @@ export function isObservable<Value = unknown>(value: unknown): value is Observab
317
277
  return isBeaconInstance<Observable<Value>>(NAME_OBSERVABLE, value);
318
278
  }
319
279
 
320
- /**
321
- * Is the value a subscription?
322
- *
323
- * @param value Value to check
324
- * @returns `true` if the value is a subscription, otherwise `false`
325
- */
326
- export function isSubscription(value: unknown): value is Subscription {
327
- return isBeaconInstance<Subscription>(NAME_SUBSCRIPTION, value);
328
- }
329
-
330
280
  function observe<Value>(beacon: BeaconState<Value>): Observable<Value> {
331
281
  const state: ObservableState<Value> = {
332
282
  beacon,
@@ -334,7 +284,7 @@ function observe<Value>(beacon: BeaconState<Value>): Observable<Value> {
334
284
  };
335
285
 
336
286
  const instance = {
337
- close: (): void => {
287
+ deactivate: (): void => {
338
288
  state.active = false;
339
289
  },
340
290
  subscribe(
@@ -347,9 +297,13 @@ function observe<Value>(beacon: BeaconState<Value>): Observable<Value> {
347
297
  }
348
298
 
349
299
  const observer = getObserver(first, second, third);
350
- const subscription = subscribe(state);
351
300
 
352
- beacon.observers.set(subscription, observer);
301
+ const subscription = getSubscription({
302
+ isActive: () => beacon.active && state.active,
303
+ property: beaconSubscription,
304
+ subscriptions: beacon.subscriptions,
305
+ value: observer,
306
+ });
353
307
 
354
308
  observer.next?.(beacon.value);
355
309
 
@@ -366,53 +320,11 @@ function observe<Value>(beacon: BeaconState<Value>): Observable<Value> {
366
320
  enumerable: true,
367
321
  get: () => beacon.active && state.active,
368
322
  },
369
- closed: {
370
- enumerable: true,
371
- get: () => !beacon.active || !state.active,
372
- },
373
323
  });
374
324
 
375
325
  return Object.freeze(instance) as Observable<Value>;
376
326
  }
377
327
 
378
- function subscribe<Value>(observable: ObservableState<Value>): Subscription {
379
- function unsubscribe(): void {
380
- if (active) {
381
- active = false;
382
-
383
- observable.beacon.observers.delete(instance as Subscription);
384
- }
385
- }
386
-
387
- let active = true;
388
-
389
- const instance = {
390
- close: (): void => {
391
- unsubscribe();
392
- },
393
- unsubscribe: (): void => {
394
- unsubscribe();
395
- },
396
- };
397
-
398
- Object.defineProperties(instance, {
399
- [KEY_BEACON]: {
400
- enumerable: false,
401
- value: NAME_SUBSCRIPTION,
402
- },
403
- active: {
404
- enumerable: true,
405
- get: () => observable.beacon.active && observable.active && active,
406
- },
407
- closed: {
408
- enumerable: true,
409
- get: () => !observable.beacon.active || !observable.active || !active,
410
- },
411
- });
412
-
413
- return Object.freeze(instance) as Subscription;
414
- }
415
-
416
328
  function update<Value>(
417
329
  type: keyof Observer<never>,
418
330
  state: BeaconState<Value>,
@@ -431,7 +343,7 @@ function update<Value>(
431
343
  state.value = value as Value;
432
344
  }
433
345
 
434
- for (const [, observer] of state.observers) {
346
+ for (const [, observer] of state.subscriptions.values.to.any) {
435
347
  observer[type]?.(value as never);
436
348
  }
437
349
 
@@ -454,10 +366,13 @@ const NAME_BEACON = 'beacon';
454
366
 
455
367
  const NAME_OBSERVABLE = 'observable';
456
368
 
457
- const NAME_SUBSCRIPTION = 'subscription';
458
-
459
369
  const TYPE_ERROR = 'error';
460
370
 
461
371
  const TYPE_NEXT = 'next';
462
372
 
373
+ const beaconSubscription: SubscriptionProperty = {
374
+ key: KEY_BEACON,
375
+ value: 'subscription',
376
+ };
377
+
463
378
  // #endregion
@@ -1,100 +1,137 @@
1
- import type {Alpha, HSLAColor, HSLColor, HWBAColor, HWBColor, RGBAColor, RGBColor} from './models';
2
-
3
- // #region Variables
4
-
5
- export const ALPHA_FULL_HEX_SHORT = 'f';
6
-
7
- export const ALPHA_FULL_HEX_LONG = `${ALPHA_FULL_HEX_SHORT}${ALPHA_FULL_HEX_SHORT}`;
1
+ import type {
2
+ Alpha,
3
+ ColorTypeExtended,
4
+ HSLAColor,
5
+ HSLColor,
6
+ HWBAColor,
7
+ HWBColor,
8
+ RGBAColor,
9
+ RGBColor,
10
+ } from './models';
11
+
12
+ // #region Types
13
+
14
+ type ColorTypes = {
15
+ all: Set<'alpha' | ColorTypeExtended>;
16
+ hex: 'hex';
17
+ hexa: 'hexa';
18
+ hsl: 'hsl';
19
+ hsla: 'hsla';
20
+ hwb: 'hwb';
21
+ hwba: 'hwba';
22
+ rgb: 'rgb';
23
+ rgba: 'rgba';
24
+ };
8
25
 
9
- export const ALPHA_NONE_HEX = '00';
26
+ // #endregion
10
27
 
11
- export const ALPHA_NONE_VALUE = 0;
28
+ // #region Variables
12
29
 
13
- export const DEFAULT_ALPHA: Alpha = {
14
- hex: ALPHA_FULL_HEX_LONG,
15
- value: 100,
30
+ export const COLOR_ALPHA = {
31
+ fullHexShort: 'f',
32
+ fullHexLong: 'ff',
33
+ name: 'alpha',
34
+ noneHex: '00',
35
+ noneValue: 0,
16
36
  };
17
37
 
18
- export const DEFAULT_HSL: HSLColor = {
19
- hue: 0,
20
- saturation: 0,
21
- lightness: 0,
38
+ export const COLOR_DEFAULTS = {
39
+ alpha: {
40
+ hex: COLOR_ALPHA.fullHexLong,
41
+ value: 100,
42
+ },
43
+ hexBlack: '000000',
44
+ hexWhite: 'ffffff',
45
+ hsl: {
46
+ hue: 0,
47
+ saturation: 0,
48
+ lightness: 0,
49
+ },
50
+ hwb: {
51
+ hue: 0,
52
+ whiteness: 0,
53
+ blackness: 100,
54
+ },
55
+ rgb: {
56
+ blue: 0,
57
+ green: 0,
58
+ red: 0,
59
+ },
22
60
  };
23
61
 
24
- export const DEFAULT_HWB: HWBColor = {
25
- hue: 0,
26
- whiteness: 0,
27
- blackness: 100,
62
+ export const COLOR_EXPRESSION = {
63
+ alphaHex: /^([a-f0-9]{1,2})$/i,
64
+ hexLong: /^#?([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?$/i,
65
+ hexShort: /^#?([a-f0-9]{3,4})$/i,
66
+ prefix: /^#/,
28
67
  };
29
68
 
30
- export const DEFAULT_RGB: RGBColor = {
31
- blue: 0,
32
- green: 0,
33
- red: 0,
69
+ export const COLOR_LENGTHS = {
70
+ hexLong: 6,
71
+ hexShort: 3,
34
72
  };
35
73
 
36
- export const EXPRESSION_ALPHA_HEX = /^([a-f0-9]{1,2})$/i;
37
-
38
- export const EXPRESSION_HEX_LONG = /^#?([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?$/i;
39
-
40
- export const EXPRESSION_HEX_SHORT = /^#?([a-f0-9]{3,4})$/i;
41
-
42
- export const EXPRESSION_PREFIX = /^#/;
43
-
44
- export const HEX_BLACK = '000000';
45
-
46
- export const HEX_WHITE = 'ffffff';
47
-
48
- export const LENGTH_LONG = 6;
49
-
50
- export const LENGTH_SHORT = 3;
51
-
52
- export const KEYS_HSL: Array<keyof HSLColor> = ['hue', 'saturation', 'lightness'];
53
-
54
- export const KEYS_HSLA: Array<keyof HSLAColor> = [...KEYS_HSL, 'alpha'];
55
-
56
- export const KEYS_HWB: Array<keyof HWBColor> = ['hue', 'whiteness', 'blackness'];
57
-
58
- export const KEYS_HWBA: Array<keyof HWBAColor> = [...KEYS_HWB, 'alpha'];
59
-
60
- export const KEYS_RGB: Array<keyof RGBColor> = ['red', 'green', 'blue'];
61
-
62
- export const KEYS_RGBA: Array<keyof RGBAColor> = [...KEYS_RGB, 'alpha'];
63
-
64
- export const MAX_DEGREE = 360;
74
+ export const COLOR_KEYS = {
75
+ hsl: ['hue', 'saturation', 'lightness'] as Array<keyof HSLColor>,
76
+ hsla: [] as Array<keyof HSLAColor>,
77
+ hwb: ['hue', 'whiteness', 'blackness'] as Array<keyof HWBColor>,
78
+ hwba: [] as Array<keyof HWBAColor>,
79
+ rgb: ['red', 'green', 'blue'] as Array<keyof RGBColor>,
80
+ rgba: [] as Array<keyof RGBAColor>,
81
+ };
65
82
 
66
- export const MAX_HEX = 255;
83
+ COLOR_KEYS.hsla = [...COLOR_KEYS.hsl, COLOR_ALPHA.name as keyof Alpha] as Array<keyof HSLAColor>;
67
84
 
68
- export const MAX_PERCENT = 100;
85
+ COLOR_KEYS.hwba = [...COLOR_KEYS.hwb, COLOR_ALPHA.name as keyof Alpha] as Array<keyof HWBAColor>;
69
86
 
70
- export const PROPERTY_COLOR = '$color';
87
+ COLOR_KEYS.rgba = [...COLOR_KEYS.rgb, COLOR_ALPHA.name as keyof Alpha] as Array<keyof RGBAColor>;
71
88
 
72
- export const TYPE_HEX = 'hex';
89
+ export const COLOR_MAX = {
90
+ degree: 360,
91
+ hex: 255,
92
+ percent: 100,
93
+ };
73
94
 
74
- export const TYPE_HSL = 'hsl';
95
+ export const COLOR_PROPERTY = {
96
+ name: '$color',
97
+ subscription: 'subscription',
98
+ };
75
99
 
76
- export const TYPE_HWB = 'hwb';
100
+ export const COLOR_TYPE: ColorTypes = {
101
+ all: undefined as unknown as Set<'alpha' | ColorTypeExtended>,
102
+ hex: 'hex',
103
+ hexa: 'hexa',
104
+ hsl: 'hsl',
105
+ hsla: 'hsla',
106
+ hwb: 'hwb',
107
+ hwba: 'hwba',
108
+ rgb: 'rgb',
109
+ rgba: 'rgba',
110
+ };
77
111
 
78
- export const TYPE_RGB = 'rgb';
112
+ COLOR_TYPE.all = new Set([
113
+ COLOR_ALPHA.name as 'alpha',
114
+ COLOR_TYPE.hex,
115
+ COLOR_TYPE.hexa,
116
+ COLOR_TYPE.hsl,
117
+ COLOR_TYPE.hsla,
118
+ COLOR_TYPE.hwb,
119
+ COLOR_TYPE.hwba,
120
+ COLOR_TYPE.rgb,
121
+ COLOR_TYPE.rgba,
122
+ ] as Array<'alpha' | ColorTypeExtended>);
79
123
 
80
124
  // https://www.w3.org/TR/WCAG20/#relativeluminancedef
81
-
82
- export const SRGB_LUMINANCE_BLUE = 0.0722;
83
-
84
- export const SRGB_LUMINANCE_EXPONENT = 2.4;
85
-
86
- export const SRGB_LUMINANCE_GREEN = 0.7152;
87
-
88
- export const SRGB_LUMINANCE_MINIMUM = 0.03928;
89
-
90
- export const SRGB_LUMINANCE_MODIFIER = 1.055;
91
-
92
- export const SRGB_LUMINANCE_MULTIPLIER = 12.92;
93
-
94
- export const SRGB_LUMINANCE_OFFSET = 0.055;
95
-
96
- export const SRGB_LUMINANCE_RED = 0.2126;
97
-
98
- export const SRGB_LUMINANCE_THRESHOLD = 0.625;
125
+ export const COLOR_SRGB = {
126
+ luminanceBlue: 0.0722,
127
+ luminanceExponent: 2.4,
128
+ luminanceGreen: 0.7152,
129
+ luminanceMinimum: 0.03928,
130
+ luminanceModifier: 1.055,
131
+ luminanceMultiplier: 12.92,
132
+ luminanceOffset: 0.055,
133
+ luminanceRed: 0.2126,
134
+ luminanceThreshold: 0.625,
135
+ };
99
136
 
100
137
  // #endregion
@@ -1,4 +1,12 @@
1
- import {PROPERTY_COLOR, TYPE_HEX, TYPE_HSL, TYPE_HWB, TYPE_RGB} from './constants';
1
+ import {
2
+ clearSubscriptions,
3
+ getSubscription,
4
+ getSubscriptions,
5
+ type Subscription,
6
+ type SubscriptionProperty,
7
+ type Subscriptions,
8
+ } from '../internal/subscription';
9
+ import {COLOR_PROPERTY, COLOR_TYPE} from './constants';
2
10
  import {getAlpha} from './misc/alpha';
3
11
  import {formatHslColor, formatHwbColor, formatRgbColor} from './misc/format';
4
12
  import {
@@ -13,7 +21,13 @@ import type {Color, ColorState, ColorType} from './models';
13
21
 
14
22
  // #region Types
15
23
 
16
- type SetValue = (state: ColorState, value: any, alpha: boolean) => void;
24
+ type SetValue = (
25
+ color: Color,
26
+ state: ColorState,
27
+ subscriptions: Subscriptions<Function>,
28
+ value: any,
29
+ alpha: boolean,
30
+ ) => void;
17
31
 
18
32
  type SetValues = Record<ColorType, SetValue>;
19
33
 
@@ -24,17 +38,22 @@ type SetValues = Record<ColorType, SetValue>;
24
38
  export function color(value: unknown): Color {
25
39
  const state = getColorState(value);
26
40
 
41
+ const subscriptions = getSubscriptions<Function>(COLOR_TYPE.all);
42
+
27
43
  const instance = {
44
+ subscribe: (first?: unknown, second?: unknown) =>
45
+ subscribeToColor(subscriptions, first, second),
28
46
  toHexString: (alpha?: boolean) =>
29
47
  `#${alpha === true ? (instance as Color).hexa : (instance as Color).hex}`,
30
48
  toHslString: (alpha?: boolean) => formatHslColor(state, alpha),
31
49
  toHwbString: (alpha?: boolean) => formatHwbColor(state, alpha),
32
50
  toRgbString: (alpha?: boolean) => formatRgbColor(state, alpha),
33
51
  toString: () => (instance as Color).toHexString(),
52
+ unsubscribe: () => clearSubscriptions(subscriptions),
34
53
  };
35
54
 
36
55
  Object.defineProperties(instance, {
37
- [PROPERTY_COLOR]: {
56
+ [COLOR_PROPERTY.name]: {
38
57
  enumerable: false,
39
58
  value: true,
40
59
  },
@@ -43,18 +62,18 @@ export function color(value: unknown): Color {
43
62
  get: () => state.alpha.value,
44
63
  set: (value: unknown) => setAlphaValue(state, value),
45
64
  },
46
- hex: getProperty(TYPE_HEX, state, false),
47
- hexa: getProperty(TYPE_HEX, state, true),
48
- hsl: getProperty(TYPE_HSL, state, false),
49
- hsla: getProperty(TYPE_HSL, state, true),
50
- hwb: getProperty(TYPE_HWB, state, false),
51
- hwba: getProperty(TYPE_HWB, state, true),
65
+ hex: getProperty(COLOR_TYPE.hex, instance as Color, state, subscriptions, false),
66
+ hexa: getProperty(COLOR_TYPE.hex, instance as Color, state, subscriptions, true),
67
+ hsl: getProperty(COLOR_TYPE.hsl, instance as Color, state, subscriptions, false),
68
+ hsla: getProperty(COLOR_TYPE.hsl, instance as Color, state, subscriptions, true),
69
+ hwb: getProperty(COLOR_TYPE.hwb, instance as Color, state, subscriptions, false),
70
+ hwba: getProperty(COLOR_TYPE.hwb, instance as Color, state, subscriptions, true),
52
71
  origin: {
53
72
  enumerable: true,
54
73
  get: () => state.origin,
55
74
  },
56
- rgb: getProperty(TYPE_RGB, state, false),
57
- rgba: getProperty(TYPE_RGB, state, true),
75
+ rgb: getProperty(COLOR_TYPE.rgb, instance as Color, state, subscriptions, false),
76
+ rgba: getProperty(COLOR_TYPE.rgb, instance as Color, state, subscriptions, true),
58
77
  });
59
78
 
60
79
  return Object.freeze(instance) as Color;
@@ -62,7 +81,9 @@ export function color(value: unknown): Color {
62
81
 
63
82
  function getProperty(
64
83
  space: keyof typeof setters,
84
+ color: Color,
65
85
  state: ColorState,
86
+ subscriptions: Subscriptions<Function>,
66
87
  alpha: boolean,
67
88
  ): PropertyDescriptor {
68
89
  const setValue = setters[space];
@@ -70,7 +91,7 @@ function getProperty(
70
91
  return {
71
92
  enumerable: true,
72
93
  get: () => getValue(space, state, alpha),
73
- set: (value: unknown) => setValue(state, value, alpha),
94
+ set: (value: unknown) => setValue(color, state, subscriptions, value, alpha),
74
95
  };
75
96
  }
76
97
 
@@ -95,10 +116,42 @@ function setAlphaValue(state: ColorState, value: unknown): void {
95
116
  }
96
117
  }
97
118
 
119
+ function subscribeToColor(
120
+ subscriptions: Subscriptions,
121
+ first: unknown,
122
+ second?: unknown,
123
+ ): Subscription {
124
+ let key: string | undefined;
125
+ let value: Function | undefined;
126
+
127
+ if (typeof first === 'string') {
128
+ key = first;
129
+ value = second as Function;
130
+ } else if (typeof first === 'function') {
131
+ value = first;
132
+ }
133
+
134
+ if (typeof value !== 'function') {
135
+ throw new Error();
136
+ }
137
+
138
+ return getSubscription({
139
+ key,
140
+ subscriptions,
141
+ value,
142
+ property: colorSubscription,
143
+ });
144
+ }
145
+
98
146
  // #endregion
99
147
 
100
148
  // #region Variables
101
149
 
150
+ const colorSubscription: SubscriptionProperty = {
151
+ key: COLOR_PROPERTY.name,
152
+ value: COLOR_PROPERTY.subscription,
153
+ };
154
+
102
155
  const setters: SetValues = {
103
156
  hex: setHexColor,
104
157
  hsl: setHSLColor,
@@ -1,14 +1,6 @@
1
- import {clamp} from '../..';
2
1
  import {round} from '../../internal/math/misc';
3
- import {
4
- ALPHA_FULL_HEX_LONG,
5
- ALPHA_NONE_HEX,
6
- ALPHA_NONE_VALUE,
7
- DEFAULT_ALPHA,
8
- EXPRESSION_ALPHA_HEX,
9
- MAX_HEX,
10
- MAX_PERCENT,
11
- } from '../constants';
2
+ import {clamp} from '../../internal/number';
3
+ import {COLOR_ALPHA, COLOR_DEFAULTS, COLOR_EXPRESSION, COLOR_MAX} from '../constants';
12
4
  import type {Alpha} from '../models';
13
5
 
14
6
  // #region Functions
@@ -18,14 +10,14 @@ export function getAlpha(value: unknown, hex: boolean): Alpha {
18
10
  return getAlphaFromValue(value);
19
11
  }
20
12
 
21
- if (typeof value !== 'string' || value.toLowerCase() === ALPHA_FULL_HEX_LONG) {
22
- return {...DEFAULT_ALPHA};
13
+ if (typeof value !== 'string' || value.toLowerCase() === COLOR_ALPHA.fullHexLong) {
14
+ return {...COLOR_DEFAULTS.alpha};
23
15
  }
24
16
 
25
- if (hex && EXPRESSION_ALPHA_HEX.test(value)) {
17
+ if (hex && COLOR_EXPRESSION.alphaHex.test(value)) {
26
18
  return {
27
19
  hex: value,
28
- value: Number.parseInt(value, 16) / MAX_HEX,
20
+ value: Number.parseInt(value, 16) / COLOR_MAX.hex,
29
21
  };
30
22
  }
31
23
 
@@ -33,15 +25,15 @@ export function getAlpha(value: unknown, hex: boolean): Alpha {
33
25
  }
34
26
 
35
27
  export function getAlphaHexadecimal(value: number): string {
36
- if (value === ALPHA_NONE_VALUE) {
37
- return ALPHA_NONE_HEX;
28
+ if (value === COLOR_ALPHA.noneValue) {
29
+ return COLOR_ALPHA.noneHex;
38
30
  }
39
31
 
40
- if (value === MAX_PERCENT) {
41
- return ALPHA_FULL_HEX_LONG;
32
+ if (value === COLOR_MAX.percent) {
33
+ return COLOR_ALPHA.fullHexLong;
42
34
  }
43
35
 
44
- return round((value / MAX_PERCENT) * MAX_HEX).toString(16);
36
+ return round((value / COLOR_MAX.percent) * COLOR_MAX.hex).toString(16);
45
37
  }
46
38
 
47
39
  function getAlphaFromValue(value: number): Alpha {
@@ -55,10 +47,10 @@ function getAlphaFromValue(value: number): Alpha {
55
47
 
56
48
  export function getAlphaValue(original: number): number {
57
49
  if (Number.isNaN(original)) {
58
- return MAX_PERCENT;
50
+ return COLOR_MAX.percent;
59
51
  }
60
52
 
61
- return clamp(original, ALPHA_NONE_VALUE, MAX_PERCENT);
53
+ return clamp(original, COLOR_ALPHA.noneValue, COLOR_MAX.percent);
62
54
  }
63
55
 
64
56
  // #endregion