@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
@@ -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/dist/queue.d.mts CHANGED
@@ -3,7 +3,7 @@ import { GenericAsyncCallback, GenericCallback } from "./models.mjs";
3
3
  /**
4
4
  * A queue that can be used to manage (a)synchronous tasks with a specific key
5
5
  */
6
- type KeyedQueue<CallbackParameters extends Parameters<GenericAsyncCallback>, CallbackResult> = {
6
+ type KeyedQueue<Callback extends GenericCallback | GenericAsyncCallback, CallbackParameters extends unknown[] = Parameters<Callback>> = {
7
7
  /**
8
8
  * Get keys of all active queues
9
9
  */
@@ -52,7 +52,7 @@ type KeyedQueue<CallbackParameters extends Parameters<GenericAsyncCallback>, Cal
52
52
  * @param signal Optional signal to abort the item
53
53
  * @returns Queued item
54
54
  */
55
- add(key: string, parameters: Tail<CallbackParameters>, signal?: AbortSignal): Queued<CallbackResult>;
55
+ add(key: string, parameters: Tail<CallbackParameters>, signal?: AbortSignal): Queued<ReturnType<Callback>>;
56
56
  /**
57
57
  * Clear all items for a specific key _(or all items for all keys, if no key is provided)_
58
58
  *
@@ -65,7 +65,7 @@ type KeyedQueue<CallbackParameters extends Parameters<GenericAsyncCallback>, Cal
65
65
  * @param key Key to get the queue for
66
66
  * @returns Queue for the key, or `undefined` if it doesn't exist
67
67
  */
68
- get(key: string): Queue<Tail<CallbackParameters>, CallbackResult> | undefined;
68
+ get(key: string): Queue<Callback, Tail<CallbackParameters>> | undefined;
69
69
  /**
70
70
  * Pause the queue for a specific key _(or all queues, if no key is provided)_
71
71
  *
@@ -101,7 +101,7 @@ type KeyedQueue<CallbackParameters extends Parameters<GenericAsyncCallback>, Cal
101
101
  /**
102
102
  * A queue that can be used to manage (a)synchronous tasks
103
103
  */
104
- type Queue<CallbackParameters extends Parameters<GenericAsyncCallback>, CallbackResult> = {
104
+ type Queue<Callback extends GenericCallback | GenericAsyncCallback, CallbackParameters extends unknown[] = Parameters<Callback>> = {
105
105
  /**
106
106
  * Is the queue active?
107
107
  */
@@ -141,7 +141,7 @@ type Queue<CallbackParameters extends Parameters<GenericAsyncCallback>, Callback
141
141
  * @param signal Optional signal to abort the item
142
142
  * @returns Queued item
143
143
  */
144
- add(parameters: CallbackParameters, signal?: AbortSignal): Queued<CallbackResult>;
144
+ add(parameters: CallbackParameters, signal?: AbortSignal): Queued<ReturnType<Callback>>;
145
145
  /**
146
146
  * Remove and reject all items in the queue
147
147
  */
@@ -195,17 +195,7 @@ type Queued<Value> = {
195
195
  /**
196
196
  * Queued promise
197
197
  */
198
- readonly promise: Promise<QueuedResult<Value>>;
199
- };
200
- type QueuedResult<Value> = {
201
- /**
202
- * Has the queue finished processing all items?
203
- */
204
- finished: boolean;
205
- /**
206
- * Result for the queued promise
207
- */
208
- value: Value extends Promise<infer Result> ? Result : Value;
198
+ readonly promise: Promise<Value extends Promise<infer Result> ? Result : Value>;
209
199
  };
210
200
  type Tail<Values extends any[]> = Values extends [infer _, ...infer Rest] ? Rest : never;
211
201
  /**
@@ -214,17 +204,29 @@ type Tail<Values extends any[]> = Values extends [infer _, ...infer Rest] ? Rest
214
204
  * @param value Value to check
215
205
  * @returns `true` if the value is a keyed queue, otherwise `false`
216
206
  */
217
- declare function isKeyedQueue(value: unknown): value is KeyedQueue<unknown[], unknown>;
207
+ declare function isKeyedQueue(value: unknown): value is KeyedQueue<GenericAsyncCallback>;
218
208
  /**
219
209
  * Is the value a queue?
220
210
  *
221
211
  * @param value Value to check
222
212
  * @returns `true` if the value is a queue, otherwise `false`
223
213
  */
224
- declare function isQueue(value: unknown): value is Queue<unknown[], unknown>;
214
+ declare function isQueue(value: unknown): value is Queue<GenericCallback | GenericAsyncCallback>;
225
215
  declare function isQueueInstance<Instance>(name: string, value: unknown): value is Instance;
226
- declare function keyedQueue<Callback extends (key: string, ...parameters: any[]) => Promise<void>>(callback: Callback, options?: QueueOptions): KeyedQueue<Parameters<Callback>, Awaited<ReturnType<Callback>>>;
227
- declare function keyedQueue<Callback extends (key: string, ...parameters: any[]) => void>(callback: Callback, options?: QueueOptions): KeyedQueue<Parameters<Callback>, ReturnType<Callback>>;
216
+ /**
217
+ * Create a keyed queue for an asynchronous callback function, where each key has its own queue
218
+ *
219
+ * @param callback Callback function for queued items
220
+ * @param options Queue options
221
+ */
222
+ declare function keyedQueue<Callback extends (key: string, ...parameters: any[]) => Promise<void>>(callback: Callback, options?: QueueOptions): KeyedQueue<Callback, Parameters<Callback>>;
223
+ /**
224
+ * Create a keyed queue for an asynchronous callback function, where each key has its own queue
225
+ *
226
+ * @param callback Callback function for queued items
227
+ * @param options Queue options
228
+ */
229
+ declare function keyedQueue<Callback extends (key: string, ...parameters: any[]) => void>(callback: Callback, options?: QueueOptions): KeyedQueue<Callback, Parameters<Callback>>;
228
230
  /**
229
231
  * Create a queue for an asynchronous callback function
230
232
  *
@@ -232,7 +234,7 @@ declare function keyedQueue<Callback extends (key: string, ...parameters: any[])
232
234
  * @param options Queue options
233
235
  * @returns Queue instance
234
236
  */
235
- declare function queue<Callback extends GenericAsyncCallback>(callback: Callback, options?: QueueOptions): Queue<Parameters<Callback>, Awaited<ReturnType<Callback>>>;
237
+ declare function queue<Callback extends GenericAsyncCallback>(callback: Callback, options?: QueueOptions): Queue<Callback, Parameters<Callback>>;
236
238
  /**
237
239
  * Create a queue for a synchronous callback function
238
240
  *
@@ -240,9 +242,9 @@ declare function queue<Callback extends GenericAsyncCallback>(callback: Callback
240
242
  * @param options Queue options
241
243
  * @returns Queue instance
242
244
  */
243
- declare function queue<Callback extends GenericCallback>(callback: Callback, options?: QueueOptions): Queue<Parameters<Callback>, ReturnType<Callback>>;
245
+ declare function queue<Callback extends GenericCallback>(callback: Callback, options?: QueueOptions): Queue<Callback, Parameters<Callback>>;
244
246
  declare namespace queue {
245
247
  var keyed: typeof keyedQueue;
246
248
  }
247
249
  //#endregion
248
- export { KeyedQueue, Queue, QueueError, QueueOptions, Queued, QueuedResult, isKeyedQueue, isQueue, isQueueInstance, keyedQueue, queue };
250
+ export { KeyedQueue, Queue, QueueError, QueueOptions, Queued, isKeyedQueue, isQueue, isQueueInstance, keyedQueue, queue };
package/dist/queue.mjs CHANGED
@@ -125,6 +125,12 @@ function createQueue(callback, options, key) {
125
125
  function getBooleanOrDefault(value, defaultValue) {
126
126
  return typeof value === "boolean" ? value : defaultValue;
127
127
  }
128
+ function getItems(state) {
129
+ const size = {};
130
+ const queues = state.queues.entries();
131
+ for (const [key, queue] of queues) size[key] = queue.size;
132
+ return size;
133
+ }
128
134
  function getOptions(input) {
129
135
  const options = typeof input === "object" && input != null ? input : {};
130
136
  return {
@@ -148,7 +154,7 @@ function getStatus(state, status) {
148
154
  for (const [key, queue] of queues) if (queue[status]) result.push(key);
149
155
  return result;
150
156
  }
151
- function handleQueuedResult(item, error, result, finished) {
157
+ function handleQueuedResult(item, error, result) {
152
158
  item.signal?.removeEventListener(EVENT_NAME, item.abort);
153
159
  if (item.signal?.aborted ?? false) {
154
160
  item.reject();
@@ -158,10 +164,7 @@ function handleQueuedResult(item, error, result, finished) {
158
164
  item.reject(result);
159
165
  return;
160
166
  }
161
- item.resolve({
162
- finished,
163
- value: result
164
- });
167
+ item.resolve(result);
165
168
  }
166
169
  function handleQueues(state, type, key) {
167
170
  if (typeof key === "string") {
@@ -212,21 +215,7 @@ function keyedQueue(callback, options) {
212
215
  pause: (key) => {
213
216
  handleQueues(state, HANDLE_PAUSE, key);
214
217
  },
215
- remove: (key, id) => {
216
- if (key == null) {
217
- handleQueues(state, HANDLE_CLEAR);
218
- state.queues.clear();
219
- return;
220
- }
221
- const queue = getQueue(state, key);
222
- if (queue == null) return;
223
- if (typeof id === "number") {
224
- queue.remove(id);
225
- return;
226
- }
227
- queue.clear();
228
- state.queues.delete(key);
229
- },
218
+ remove: (key, id) => removeQueue(state, key, id),
230
219
  resume: (key) => {
231
220
  handleQueues(state, HANDLE_RESUME, key);
232
221
  }
@@ -258,12 +247,7 @@ function keyedQueue(callback, options) {
258
247
  },
259
248
  items: {
260
249
  enumerable: true,
261
- get: () => {
262
- const size = {};
263
- const queues = state.queues.entries();
264
- for (const [key, queue] of queues) size[key] = queue.size;
265
- return size;
266
- }
250
+ get: () => getItems(state)
267
251
  },
268
252
  keys: {
269
253
  enumerable: true,
@@ -288,6 +272,21 @@ function queue(callback, options) {
288
272
  return createQueue(callback, options);
289
273
  }
290
274
  queue.keyed = keyedQueue;
275
+ function removeQueue(state, key, id) {
276
+ if (key == null) {
277
+ handleQueues(state, HANDLE_CLEAR);
278
+ state.queues.clear();
279
+ return;
280
+ }
281
+ const queue = getQueue(state, key);
282
+ if (queue == null) return;
283
+ if (typeof id === "number") {
284
+ queue.remove(id);
285
+ return;
286
+ }
287
+ queue.clear();
288
+ state.queues.delete(key);
289
+ }
291
290
  async function run(state) {
292
291
  if (state.paused || state.runners >= state.options.concurrency) return;
293
292
  state.runners += 1;
@@ -307,11 +306,11 @@ async function run(state) {
307
306
  if (state.paused) {
308
307
  const paused = item;
309
308
  state.handled.push(() => {
310
- handleQueuedResult(paused, error, result, state.items.length === 0);
309
+ handleQueuedResult(paused, error, result);
311
310
  });
312
311
  break;
313
312
  }
314
- handleQueuedResult(item, error, result, state.items.length === 0);
313
+ handleQueuedResult(item, error, result);
315
314
  item = state.items.shift();
316
315
  }
317
316
  state.runners -= 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oscarpalmer/atoms",
3
- "version": "0.191.0",
3
+ "version": "0.193.0",
4
4
  "description": "Atomic utilities for making your JavaScript better.",
5
5
  "keywords": [
6
6
  "helper",