@oscarpalmer/atoms 0.190.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.
- package/dist/beacon.d.mts +6 -44
- package/dist/beacon.mjs +20 -67
- package/dist/color/constants.d.mts +82 -35
- package/dist/color/constants.mjs +106 -61
- package/dist/color/index.d.mts +3 -3
- package/dist/color/index.mjs +2 -2
- package/dist/color/instance.mjs +60 -35
- package/dist/color/misc/alpha.d.mts +1 -1
- package/dist/color/misc/alpha.mjs +12 -10
- package/dist/color/misc/format.d.mts +7 -0
- package/dist/color/misc/format.mjs +20 -0
- package/dist/color/misc/get.mjs +25 -25
- package/dist/color/misc/is.d.mts +0 -36
- package/dist/color/misc/is.mjs +22 -57
- package/dist/color/misc/state.d.mts +8 -6
- package/dist/color/misc/state.mjs +79 -88
- package/dist/color/models.d.mts +106 -6
- package/dist/color/space/hex.d.mts +3 -2
- package/dist/color/space/hex.mjs +22 -10
- package/dist/color/space/hsl.d.mts +3 -2
- package/dist/color/space/hsl.mjs +26 -14
- package/dist/color/space/hwb.d.mts +3 -2
- package/dist/color/space/hwb.mjs +20 -8
- package/dist/color/space/rgb.d.mts +3 -2
- package/dist/color/space/rgb.mjs +27 -15
- package/dist/herald.d.mts +2 -3
- package/dist/index.d.mts +139 -73
- package/dist/index.mjs +653 -477
- package/dist/internal/subscription.d.mts +52 -0
- package/dist/internal/subscription.mjs +127 -0
- package/dist/models.d.mts +5 -1
- package/package.json +4 -4
- package/src/beacon.ts +32 -117
- package/src/color/constants.ts +115 -66
- package/src/color/index.ts +26 -8
- package/src/color/instance.ts +113 -45
- package/src/color/misc/alpha.ts +18 -20
- package/src/color/misc/format.ts +29 -0
- package/src/color/misc/get.ts +31 -41
- package/src/color/misc/is.ts +31 -71
- package/src/color/misc/state.ts +165 -141
- package/src/color/models.ts +126 -5
- package/src/color/space/hex.ts +46 -18
- package/src/color/space/hsl.ts +44 -14
- package/src/color/space/hwb.ts +38 -8
- package/src/color/space/rgb.ts +48 -15
- package/src/herald.ts +1 -3
- package/src/index.ts +1 -0
- package/src/internal/subscription.ts +264 -0
- package/src/models.ts +5 -0
- package/src/string/fuzzy.ts +1 -1
- package/src/value/freeze.ts +2 -2
- package/src/value/shake.ts +1 -1
- package/src/value/transform.ts +1 -1
- package/dist/color/misc/index.d.mts +0 -7
- package/dist/color/misc/index.mjs +0 -15
- package/src/color/misc/index.ts +0 -29
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Key } from "../models.mjs";
|
|
2
|
+
//#region src/internal/subscription.d.ts
|
|
3
|
+
type Subscription = {
|
|
4
|
+
/**
|
|
5
|
+
* Is the subscription active?
|
|
6
|
+
*/
|
|
7
|
+
get active(): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Unsubscribe from changes
|
|
10
|
+
*/
|
|
11
|
+
unsubscribe(): void;
|
|
12
|
+
};
|
|
13
|
+
type SubscriptionParameters = {
|
|
14
|
+
isActive?: () => boolean;
|
|
15
|
+
key?: Key;
|
|
16
|
+
property: SubscriptionProperty;
|
|
17
|
+
subscriptions: Subscriptions;
|
|
18
|
+
value: unknown;
|
|
19
|
+
};
|
|
20
|
+
type SubscriptionProperty = {
|
|
21
|
+
key: string;
|
|
22
|
+
value: unknown;
|
|
23
|
+
};
|
|
24
|
+
type Subscriptions<Value = unknown> = {
|
|
25
|
+
items: SubscriptionsItems;
|
|
26
|
+
keys?: Set<Key>;
|
|
27
|
+
values: SubscriptionsValues<Value>;
|
|
28
|
+
};
|
|
29
|
+
type SubscriptionsItems = {
|
|
30
|
+
any: Set<Subscription>;
|
|
31
|
+
keyed?: Map<Key, Set<Subscription>>;
|
|
32
|
+
};
|
|
33
|
+
type SubscriptionsValues<Value = unknown> = {
|
|
34
|
+
from: SubscriptionsValuesItem<Value, Subscription>;
|
|
35
|
+
to: SubscriptionsValuesItem<Subscription, Value>;
|
|
36
|
+
};
|
|
37
|
+
type SubscriptionsValuesItem<MapKey, MapValue> = {
|
|
38
|
+
any: Map<MapKey, MapValue>;
|
|
39
|
+
keyed?: Map<Key, Map<MapKey, MapValue>>;
|
|
40
|
+
};
|
|
41
|
+
declare function clearSubscriptions(store: Subscriptions): void;
|
|
42
|
+
declare function getSubscription(parameters: SubscriptionParameters): Subscription;
|
|
43
|
+
declare function getSubscriptions<Value = unknown>(keys?: Set<Key>): Subscriptions<Value>;
|
|
44
|
+
/**
|
|
45
|
+
* Is the value a subscription?
|
|
46
|
+
*
|
|
47
|
+
* @param value Value to check
|
|
48
|
+
* @returns `true` if the value is a subscription, otherwise `false`
|
|
49
|
+
*/
|
|
50
|
+
declare function isSubscription(value: unknown): value is Subscription;
|
|
51
|
+
//#endregion
|
|
52
|
+
export { Subscription, SubscriptionParameters, SubscriptionProperty, Subscriptions, clearSubscriptions, getSubscription, getSubscriptions, isSubscription };
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { isPlainObject } from "./is.mjs";
|
|
2
|
+
//#region src/internal/subscription.ts
|
|
3
|
+
function addSubscription(subscription, state) {
|
|
4
|
+
const { key, subscriptions, value } = state.parameters;
|
|
5
|
+
const { items, values } = subscriptions;
|
|
6
|
+
if (key == null) {
|
|
7
|
+
items.any.add(subscription);
|
|
8
|
+
values.from.any.set(value, subscription);
|
|
9
|
+
values.to.any.set(subscription, value);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (items.keyed == null || values.from.keyed == null || values.to.keyed == null)
|
|
13
|
+
// istanbul ignore next
|
|
14
|
+
return;
|
|
15
|
+
let keyedItems = items.keyed.get(key);
|
|
16
|
+
if (keyedItems == null) {
|
|
17
|
+
keyedItems = /* @__PURE__ */ new Set();
|
|
18
|
+
items.keyed.set(key, keyedItems);
|
|
19
|
+
}
|
|
20
|
+
keyedItems.add(subscription);
|
|
21
|
+
let keyedFrom = values.from.keyed.get(key);
|
|
22
|
+
if (keyedFrom == null) {
|
|
23
|
+
keyedFrom = /* @__PURE__ */ new Map();
|
|
24
|
+
values.from.keyed.set(key, keyedFrom);
|
|
25
|
+
}
|
|
26
|
+
keyedFrom.set(value, subscription);
|
|
27
|
+
let keyedTo = values.to.keyed.get(key);
|
|
28
|
+
if (keyedTo == null) {
|
|
29
|
+
keyedTo = /* @__PURE__ */ new Map();
|
|
30
|
+
values.to.keyed.set(key, keyedTo);
|
|
31
|
+
}
|
|
32
|
+
keyedTo.set(subscription, value);
|
|
33
|
+
}
|
|
34
|
+
function clearSubscriptions(store) {
|
|
35
|
+
for (const susbcription of store.values.to.any.keys()) susbcription.unsubscribe();
|
|
36
|
+
if (store.values.to.keyed != null) for (const values of store.values.to.keyed.values()) for (const susbcription of values.keys()) susbcription.unsubscribe();
|
|
37
|
+
}
|
|
38
|
+
function getExistingSubscription(state) {
|
|
39
|
+
const { parameters } = state;
|
|
40
|
+
const { values } = parameters.subscriptions;
|
|
41
|
+
return parameters.key == null ? values.from.any.get(parameters.value) : values.from.keyed?.get(parameters.key)?.get(parameters.value);
|
|
42
|
+
}
|
|
43
|
+
function getSubscription(parameters) {
|
|
44
|
+
const state = {
|
|
45
|
+
parameters,
|
|
46
|
+
active: true
|
|
47
|
+
};
|
|
48
|
+
const existing = getExistingSubscription(state);
|
|
49
|
+
if (existing != null) return existing;
|
|
50
|
+
if (parameters.subscriptions.keys != null && parameters.key != null && !parameters.subscriptions.keys.has(parameters.key)) throw new Error();
|
|
51
|
+
const instance = { unsubscribe: () => {
|
|
52
|
+
removeSubscription(instance, state);
|
|
53
|
+
} };
|
|
54
|
+
Object.defineProperties(instance, {
|
|
55
|
+
[PROPERTY]: {
|
|
56
|
+
enumerable: false,
|
|
57
|
+
value: true
|
|
58
|
+
},
|
|
59
|
+
[parameters.property.key]: {
|
|
60
|
+
enumerable: false,
|
|
61
|
+
value: parameters.property.value
|
|
62
|
+
},
|
|
63
|
+
active: {
|
|
64
|
+
enumerable: true,
|
|
65
|
+
get: () => (parameters.isActive?.() ?? true) && state.active
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
addSubscription(instance, state);
|
|
69
|
+
return Object.freeze(instance);
|
|
70
|
+
}
|
|
71
|
+
function getSubscriptions(keys) {
|
|
72
|
+
return {
|
|
73
|
+
keys,
|
|
74
|
+
items: {
|
|
75
|
+
any: /* @__PURE__ */ new Set(),
|
|
76
|
+
keyed: keys == null ? void 0 : /* @__PURE__ */ new Map()
|
|
77
|
+
},
|
|
78
|
+
values: {
|
|
79
|
+
from: {
|
|
80
|
+
any: /* @__PURE__ */ new Map(),
|
|
81
|
+
keyed: keys == null ? void 0 : /* @__PURE__ */ new Map()
|
|
82
|
+
},
|
|
83
|
+
to: {
|
|
84
|
+
any: /* @__PURE__ */ new Map(),
|
|
85
|
+
keyed: keys == null ? void 0 : /* @__PURE__ */ new Map()
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Is the value a subscription?
|
|
92
|
+
*
|
|
93
|
+
* @param value Value to check
|
|
94
|
+
* @returns `true` if the value is a subscription, otherwise `false`
|
|
95
|
+
*/
|
|
96
|
+
function isSubscription(value) {
|
|
97
|
+
return isPlainObject(value) && PROPERTY in value && value[PROPERTY] === true;
|
|
98
|
+
}
|
|
99
|
+
function removeFromStore(items, values, subscription, value, key) {
|
|
100
|
+
items.delete(subscription);
|
|
101
|
+
if (key == null) {
|
|
102
|
+
values.from.any.delete(value);
|
|
103
|
+
values.to.any.delete(subscription);
|
|
104
|
+
} else {
|
|
105
|
+
values.from.keyed?.get(key)?.delete(value);
|
|
106
|
+
values.to.keyed?.get(key)?.delete(subscription);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function removeSubscription(subscription, state) {
|
|
110
|
+
if (!state.active) return;
|
|
111
|
+
state.active = false;
|
|
112
|
+
const { key, subscriptions, value } = state.parameters;
|
|
113
|
+
const { items, values } = subscriptions;
|
|
114
|
+
if (key == null) {
|
|
115
|
+
removeFromStore(items.any, values, subscription, value);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const keyed = items.keyed?.get(key);
|
|
119
|
+
if (items.keyed == null || keyed == null)
|
|
120
|
+
// istanbul ignore next
|
|
121
|
+
return;
|
|
122
|
+
removeFromStore(keyed, values, subscription, value, key);
|
|
123
|
+
if (keyed.size === 0) items.keyed.delete(key);
|
|
124
|
+
}
|
|
125
|
+
const PROPERTY = "$subscription";
|
|
126
|
+
//#endregion
|
|
127
|
+
export { clearSubscriptions, getSubscription, getSubscriptions, isSubscription };
|
package/dist/models.d.mts
CHANGED
|
@@ -156,5 +156,9 @@ type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint
|
|
|
156
156
|
* Thanks, type-fest!
|
|
157
157
|
*/
|
|
158
158
|
type UnionToIntersection<Union> = (Union extends unknown ? (distributedUnion: Union) => void : never) extends ((mergedIntersection: infer Intersection) => void) ? Intersection & Union : never;
|
|
159
|
+
/**
|
|
160
|
+
* A function that unsubscribes from a subscription
|
|
161
|
+
*/
|
|
162
|
+
type Unsubscriber = () => void;
|
|
159
163
|
//#endregion
|
|
160
|
-
export { ArrayOrPlainObject, AsyncCancelableCallback, BuiltIns, CancelableCallback, Constructor, EventPosition, GenericAsyncCallback, GenericCallback, Key, KeyedValue, NestedArray, NestedKeys, NestedPartial, NestedValue, NestedValues, NumericalKeys, NumericalValues, OnceAsyncCallback, OnceCallback, PlainObject, Primitive, RequiredKeys, Simplify, ToString, TypedArray, UnionToIntersection };
|
|
164
|
+
export { ArrayOrPlainObject, AsyncCancelableCallback, BuiltIns, CancelableCallback, Constructor, EventPosition, GenericAsyncCallback, GenericCallback, Key, KeyedValue, NestedArray, NestedKeys, NestedPartial, NestedValue, NestedValues, NumericalKeys, NumericalValues, OnceAsyncCallback, OnceCallback, PlainObject, Primitive, RequiredKeys, Simplify, ToString, TypedArray, UnionToIntersection, Unsubscriber };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oscarpalmer/atoms",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.192.0",
|
|
4
4
|
"description": "Atomic utilities for making your JavaScript better.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"helper",
|
|
@@ -257,10 +257,10 @@
|
|
|
257
257
|
"watch": "npx vite build --watch"
|
|
258
258
|
},
|
|
259
259
|
"devDependencies": {
|
|
260
|
-
"@oxlint/plugins": "^1.
|
|
260
|
+
"@oxlint/plugins": "^1.79",
|
|
261
261
|
"@types/node": "^26.2",
|
|
262
|
-
"@vitest/coverage-istanbul": "4.1
|
|
263
|
-
"eslint": "^10.
|
|
262
|
+
"@vitest/coverage-istanbul": "^4.1",
|
|
263
|
+
"eslint": "^10.9",
|
|
264
264
|
"jsdom": "^30",
|
|
265
265
|
"tsdown": "^0.22",
|
|
266
266
|
"typescript": "^6",
|
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
|
-
*
|
|
35
|
+
* Deactivate the beacon
|
|
33
36
|
*/
|
|
34
|
-
|
|
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
|
-
*
|
|
89
|
-
*/
|
|
90
|
-
get closed(): boolean;
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Close the observable
|
|
88
|
+
* Deactivate the observable
|
|
94
89
|
*/
|
|
95
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
255
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
package/src/color/constants.ts
CHANGED
|
@@ -1,88 +1,137 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
26
|
+
// #endregion
|
|
10
27
|
|
|
11
|
-
|
|
28
|
+
// #region Variables
|
|
12
29
|
|
|
13
|
-
export const
|
|
14
|
-
|
|
15
|
-
|
|
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
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
red: 0,
|
|
69
|
+
export const COLOR_LENGTHS = {
|
|
70
|
+
hexLong: 6,
|
|
71
|
+
hexShort: 3,
|
|
34
72
|
};
|
|
35
73
|
|
|
36
|
-
export const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
export const HEX_WHITE = 'ffffff';
|
|
45
|
-
|
|
46
|
-
export const LENGTH_LONG = 6;
|
|
47
|
-
|
|
48
|
-
export const LENGTH_SHORT = 3;
|
|
49
|
-
|
|
50
|
-
export const KEYS_HSL: Array<keyof HSLColor> = ['hue', 'saturation', 'lightness'];
|
|
51
|
-
|
|
52
|
-
export const KEYS_HSLA: Array<keyof HSLAColor> = [...KEYS_HSL, 'alpha'];
|
|
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
|
+
};
|
|
53
82
|
|
|
54
|
-
|
|
83
|
+
COLOR_KEYS.hsla = [...COLOR_KEYS.hsl, COLOR_ALPHA.name as keyof Alpha] as Array<keyof HSLAColor>;
|
|
55
84
|
|
|
56
|
-
|
|
85
|
+
COLOR_KEYS.hwba = [...COLOR_KEYS.hwb, COLOR_ALPHA.name as keyof Alpha] as Array<keyof HWBAColor>;
|
|
57
86
|
|
|
58
|
-
|
|
87
|
+
COLOR_KEYS.rgba = [...COLOR_KEYS.rgb, COLOR_ALPHA.name as keyof Alpha] as Array<keyof RGBAColor>;
|
|
59
88
|
|
|
60
|
-
export const
|
|
89
|
+
export const COLOR_MAX = {
|
|
90
|
+
degree: 360,
|
|
91
|
+
hex: 255,
|
|
92
|
+
percent: 100,
|
|
93
|
+
};
|
|
61
94
|
|
|
62
|
-
export const
|
|
95
|
+
export const COLOR_PROPERTY = {
|
|
96
|
+
name: '$color',
|
|
97
|
+
subscription: 'subscription',
|
|
98
|
+
};
|
|
63
99
|
|
|
64
|
-
export const
|
|
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
|
+
};
|
|
65
111
|
|
|
66
|
-
|
|
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>);
|
|
67
123
|
|
|
68
124
|
// https://www.w3.org/TR/WCAG20/#relativeluminancedef
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
export const SRGB_LUMINANCE_MULTIPLIER = 12.92;
|
|
81
|
-
|
|
82
|
-
export const SRGB_LUMINANCE_OFFSET = 0.055;
|
|
83
|
-
|
|
84
|
-
export const SRGB_LUMINANCE_RED = 0.2126;
|
|
85
|
-
|
|
86
|
-
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
|
+
};
|
|
87
136
|
|
|
88
137
|
// #endregion
|