@byloth/core 2.2.4 → 2.2.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@byloth/core",
3
- "version": "2.2.4",
3
+ "version": "2.2.5",
4
4
  "description": "An unopinionated collection of useful functions and classes that I use widely in all my projects. 🔧",
5
5
  "keywords": [
6
6
  "Core",
@@ -50,10 +50,10 @@
50
50
  "types": "src/index.ts",
51
51
  "devDependencies": {
52
52
  "@byloth/eslint-config-typescript": "^3.2.2",
53
- "@eslint/compat": "^2.0.2",
54
- "@types/node": "^22.19.11",
53
+ "@eslint/compat": "^2.0.3",
54
+ "@types/node": "^22.19.15",
55
55
  "@vitest/coverage-v8": "^4.0.18",
56
- "eslint": "^9.39.2",
56
+ "eslint": "^9.39.4",
57
57
  "husky": "^9.1.7",
58
58
  "jsdom": "^27.4.0",
59
59
  "typescript": "^5.9.3",
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- export const VERSION = "2.2.4";
1
+ export const VERSION = "2.2.5";
2
2
 
3
3
  export type { Constructor, Interval, Timeout, ValueOf } from "./core/types.js";
4
4
 
@@ -87,6 +87,7 @@ export type {
87
87
 
88
88
  export {
89
89
  average,
90
+ clamp,
90
91
  capitalize,
91
92
  chain,
92
93
  count,
@@ -16,9 +16,9 @@ import type { Callback } from "./types.js";
16
16
  * .add(() => console.log("Doing something else..."))
17
17
  * .add(() => console.log("Doing yet another thing..."));
18
18
  *
19
- * unsubscribeAll(); // Doing something...
20
- * // Doing something else...
21
- * // Doing yet another thing...
19
+ * unsubscribeAll(); // Doing something...
20
+ * // Doing something else...
21
+ * // Doing yet another thing...
22
22
  * ```
23
23
  *
24
24
  * ---
@@ -87,7 +87,7 @@ export default class Publisher<T extends CallbackMap<T> = CallbackMap>
87
87
  * context.subscribe("player:spawn", () => console.log("Player has spawned."));
88
88
  *
89
89
  * publisher.publish("player:spawn"); // "Player has spawned."
90
- * context.publish("player:death"); // * no output *
90
+ * context.publish("player:death"); // * no output *
91
91
  * ```
92
92
  *
93
93
  * ---
@@ -282,7 +282,7 @@ export default class ArrayView<T> extends Array<T>
282
282
  * ```ts
283
283
  * array.onAdd((value, index) => console.log(`Added ${value} at index ${index}`));
284
284
  *
285
- * array.push(2); // "Added 2 at index 0"
285
+ * array.push(2); // "Added 2 at index 0"
286
286
  * array.push(42); // "Added 42 at index 1"
287
287
  * ```
288
288
  *
@@ -306,7 +306,7 @@ export default class ArrayView<T> extends Array<T>
306
306
  * ```ts
307
307
  * array.onRemove((value, index) => console.log(`Removed ${value} at index ${index}`));
308
308
  *
309
- * array.pop(); // "Removed 8 at index 2"
309
+ * array.pop(); // "Removed 8 at index 2"
310
310
  * array.shift(); // "Removed 2 at index 0"
311
311
  * ```
312
312
  *
@@ -162,7 +162,7 @@ export default class MapView<K, V> extends Map<K, V>
162
162
  * ```ts
163
163
  * map.onAdd((key, value) => console.log(`Added ${key}: ${value}`));
164
164
  *
165
- * map.set("key1", 2); // "Added key1: 2"
165
+ * map.set("key1", 2); // "Added key1: 2"
166
166
  * map.set("answer", 42); // "Added answer: 42"
167
167
  * ```
168
168
  *
@@ -186,7 +186,7 @@ export default class MapView<K, V> extends Map<K, V>
186
186
  * ```ts
187
187
  * map.onRemove((key, value) => console.log(`Removed ${key}: ${value}`));
188
188
  *
189
- * map.delete("key1"); // "Removed key1: 2"
189
+ * map.delete("key1"); // "Removed key1: 2"
190
190
  * map.delete("answer"); // "Removed answer: 42"
191
191
  * ```
192
192
  *
@@ -106,7 +106,7 @@ export default class SetView<T> extends Set<T>
106
106
  * @example
107
107
  * ```ts
108
108
  * const set = new SetView<number>([2, 4, 8]);
109
- * set.delete(4); // true
109
+ * set.delete(4); // true
110
110
  * set.delete(16); // false
111
111
  *
112
112
  * console.log(set); // SetView(2) { 2, 8 }
@@ -156,7 +156,7 @@ export default class SetView<T> extends Set<T>
156
156
  * ```ts
157
157
  * set.onAdd((value) => console.log(`Added ${value}`));
158
158
  *
159
- * set.add(2); // "Added 2"
159
+ * set.add(2); // "Added 2"
160
160
  * set.add(42); // "Added 42"
161
161
  * ```
162
162
  *
@@ -180,7 +180,7 @@ export default class SetView<T> extends Set<T>
180
180
  * ```ts
181
181
  * set.onRemove((value) => console.log(`Removed ${value}`));
182
182
  *
183
- * set.delete(2); // "Removed 2"
183
+ * set.delete(2); // "Removed 2"
184
184
  * set.delete(42); // "Removed 42"
185
185
  * ```
186
186
  *
@@ -29,7 +29,7 @@ export interface ReadonlyMapView<K, V> extends ReadonlyMap<K, V>
29
29
  * ```ts
30
30
  * map.onAdd((key, value) => console.log(`Added ${key}: ${value}`));
31
31
  *
32
- * map.set("key1", 2); // "Added key1: 2"
32
+ * map.set("key1", 2); // "Added key1: 2"
33
33
  * map.set("answer", 42); // "Added answer: 42"
34
34
  * ```
35
35
  *
@@ -50,7 +50,7 @@ export interface ReadonlyMapView<K, V> extends ReadonlyMap<K, V>
50
50
  * ```ts
51
51
  * map.onRemove((key, value) => console.log(`Removed ${key}: ${value}`));
52
52
  *
53
- * map.delete("key1"); // "Removed key1: 2"
53
+ * map.delete("key1"); // "Removed key1: 2"
54
54
  * map.delete("answer"); // "Removed answer: 42"
55
55
  * ```
56
56
  *
@@ -104,7 +104,7 @@ export interface ReadonlySetView<T> extends ReadonlySet<T>
104
104
  * ```ts
105
105
  * set.onAdd((value) => console.log(`Added ${value}`));
106
106
  *
107
- * set.add(2); // "Added 2"
107
+ * set.add(2); // "Added 2"
108
108
  * set.add(42); // "Added 42"
109
109
  * ```
110
110
  *
@@ -125,7 +125,7 @@ export interface ReadonlySetView<T> extends ReadonlySet<T>
125
125
  * ```ts
126
126
  * set.onRemove((value) => console.log(`Removed ${value}`));
127
127
  *
128
- * set.delete(2); // "Removed 2"
128
+ * set.delete(2); // "Removed 2"
129
129
  * set.delete(42); // "Removed 42"
130
130
  * ```
131
131
  *
@@ -696,7 +696,7 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
696
696
  * const iterator = new SmartAsyncIterator<number>([-2, -1, 0, 1, 2]);
697
697
  * const result = iterator.take(3);
698
698
  *
699
- * console.log(await result.toArray()); // [-2, -1, 0]
699
+ * console.log(await result.toArray()); // [-2, -1, 0]
700
700
  * console.log(await iterator.toArray()); // [1, 2]
701
701
  * ```
702
702
  *
@@ -580,7 +580,7 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
580
580
  * const iterator = new SmartIterator<number>([-2, -1, 0, 1, 2]);
581
581
  * const result = iterator.take(3);
582
582
  *
583
- * console.log(result.toArray()); // [-2, -1, 0]
583
+ * console.log(result.toArray()); // [-2, -1, 0]
584
584
  * console.log(iterator.toArray()); // [1, 2]
585
585
  * ```
586
586
  *
@@ -17,12 +17,12 @@ import type { FulfilledHandler, PromiseExecutor, RejectedHandler } from "./types
17
17
  * setTimeout(() => resolve("Hello, World!"), 1_000);
18
18
  * });
19
19
  *
20
- * console.log(promise.isPending); // true
20
+ * console.log(promise.isPending); // true
21
21
  * console.log(promise.isFulfilled); // false
22
22
  *
23
23
  * console.log(await promise); // "Hello, World!"
24
24
  *
25
- * console.log(promise.isPending); // false
25
+ * console.log(promise.isPending); // false
26
26
  * console.log(promise.isFulfilled); // true
27
27
  * ```
28
28
  *
@@ -39,14 +39,14 @@ export default class SmartPromise<T = void> implements Promise<T>
39
39
  *
40
40
  * @example
41
41
  * ```ts
42
- * const request = fetch("https://api.example.com/data");
43
- * const smartRequest = SmartPromise.FromPromise(request);
42
+ * const response = fetch("https://api.example.com/data");
43
+ * const smartResponse = SmartPromise.FromPromise(response);
44
44
  *
45
- * console.log(request.isPending); // Throws an error: `isPending` is not a property of `Promise`.
46
- * console.log(smartRequest.isPending); // true
45
+ * console.log(response.isPending); // Throws an error: `isPending` is not a property of `Promise`.
46
+ * console.log(smartResponse.isPending); // true
47
47
  *
48
- * const response = await request;
49
- * console.log(smartRequest.isFulfilled); // true
48
+ * const response = await response;
49
+ * console.log(smartResponse.isFulfilled); // true
50
50
  * ```
51
51
  *
52
52
  * ---
@@ -323,8 +323,8 @@ export default class SmartPromise<T = void> implements Promise<T>
323
323
  *
324
324
  *
325
325
  * promise
326
- * .then(() => console.log("OK!")) // Logs "OK!" if the promise is fulfilled.
327
- * .catch(() => console.log("KO!")) // Logs "KO!" if the promise is rejected.
326
+ * .then(() => console.log("OK!")) // Logs "OK!" if the promise is fulfilled.
327
+ * .catch(() => console.log("KO!")) // Logs "KO!" if the promise is rejected.
328
328
  * .finally(() => console.log("Done!")); // Always logs "Done!".
329
329
  * ```
330
330
  *
@@ -20,7 +20,7 @@ import type { MaybePromise, PromiseExecutor } from "./types.js";
20
20
  * }, 5_000);
21
21
  *
22
22
  * promise
23
- * .then((result) => console.log(result)) // "Hello, World!"
23
+ * .then((result) => console.log(result)) // "Hello, World!"
24
24
  * .catch((error) => console.error(error)); // "Uncaught TimeoutException: The operation has timed out."
25
25
  * ```
26
26
  *
@@ -5,5 +5,5 @@ export { delay, nextAnimationFrame, yieldToEventLoop } from "./async.js";
5
5
  export { dateDifference, dateRange, dateRound, getWeek, TimeUnit, WeekDay } from "./date.js";
6
6
  export { loadScript } from "./dom.js";
7
7
  export { chain, count, enumerate, range, shuffle, unique, zip } from "./iterator.js";
8
- export { average, hash, sum } from "./math.js";
8
+ export { average, clamp, hash, sum } from "./math.js";
9
9
  export { capitalize } from "./string.js";
package/src/utils/math.ts CHANGED
@@ -9,7 +9,7 @@ import { zip } from "./iterator.js";
9
9
  *
10
10
  * @example
11
11
  * ```ts
12
- * average([1, 2, 3, 4, 5]); // 3
12
+ * average([1, 2, 3, 4, 5]); // 3
13
13
  * average([6, 8.5, 4], [3, 2, 1]); // 6.5
14
14
  * ```
15
15
  *
@@ -71,6 +71,39 @@ export function average<T extends number>(values: Iterable<T>, weights?: Iterabl
71
71
  return _sum / _count;
72
72
  }
73
73
 
74
+ /**
75
+ * Clamps a given value between a minimum and a maximum bound.
76
+ *
77
+ * ---
78
+ *
79
+ * @example
80
+ * ```ts
81
+ * clamp(5, 0, 10); // 5
82
+ * clamp(-3, 0, 10); // 0
83
+ * clamp(15, 0, 10); // 10
84
+ * ```
85
+ *
86
+ * ---
87
+ *
88
+ * @param value The value to clamp.
89
+ * @param min The minimum bound.
90
+ * @param max The maximum bound.
91
+ *
92
+ * @returns The clamped value between the specified bounds.
93
+ */
94
+ export function clamp(value: number, min: number, max: number): number
95
+ {
96
+ if (min > max)
97
+ {
98
+ throw new ValueException("The minimum bound must be less than or equal to the maximum bound.");
99
+ }
100
+
101
+ if (value < min) { return min; }
102
+ if (value > max) { return max; }
103
+
104
+ return value;
105
+ }
106
+
74
107
  /**
75
108
  * An utility function to compute the hash of a given string.
76
109
  *
@@ -83,7 +116,7 @@ export function average<T extends number>(values: Iterable<T>, weights?: Iterabl
83
116
  * @example
84
117
  * ```ts
85
118
  * hash("Hello, world!"); // -1880044555
86
- * hash("How are you?"); // 1761539132
119
+ * hash("How are you?"); // 1761539132
87
120
  * ```
88
121
  *
89
122
  * ---
@@ -338,8 +338,8 @@ export default class Random
338
338
  *
339
339
  * @example
340
340
  * ```ts
341
- * Random.Split(100, 3); // [28, 41, 31]
342
- * Random.Split(10, 4); // [3, 1, 4, 2]
341
+ * Random.Split(100, 3); // [28, 41, 31]
342
+ * Random.Split(10, 4); // [3, 1, 4, 2]
343
343
  * ```
344
344
  *
345
345
  * ---
@@ -368,9 +368,9 @@ export default class Random
368
368
  *
369
369
  * @example
370
370
  * ```ts
371
- * Random.Split([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4, 5]]
372
- * Random.Split([1, 2, 3, 4, 5], 2); // [[1, 2, 3, 4], [5]]
373
- * Random.Split("abcdef", 3); // [["a"], ["b", "c", "d"], ["e", "f"]]
371
+ * Random.Split([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4, 5]]
372
+ * Random.Split([1, 2, 3, 4, 5], 2); // [[1, 2, 3, 4], [5]]
373
+ * Random.Split("abcdef", 3); // [["a"], ["b", "c", "d"], ["e", "f"]]
374
374
  * ```
375
375
  *
376
376
  * ---