magic-utils-yonava 1.0.2 → 1.0.4
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/clone.d.ts +9 -0
- package/dist/clone.js +15 -0
- package/dist/clone.test.d.ts +1 -0
- package/dist/clone.test.js +42 -0
- package/dist/colors.d.ts +522 -0
- package/{src/colors.ts → dist/colors.js} +224 -274
- package/dist/ctx/index.d.ts +10 -0
- package/dist/ctx/index.js +19 -0
- package/dist/debounce.d.ts +9 -0
- package/{src/debounce.ts → dist/debounce.js} +6 -6
- package/dist/debugging.d.ts +2 -0
- package/dist/debugging.js +21 -0
- package/dist/deepDelta/delta.test.d.ts +1 -0
- package/dist/deepDelta/delta.test.js +114 -0
- package/dist/deepDelta/index.d.ts +8 -0
- package/dist/deepDelta/index.js +40 -0
- package/dist/deepMerge.d.ts +16 -0
- package/dist/deepMerge.js +32 -0
- package/dist/deepMerge.test.d.ts +1 -0
- package/dist/deepMerge.test.js +68 -0
- package/dist/fps.d.ts +6 -0
- package/dist/fps.js +51 -0
- package/dist/fracDecConverter/index.d.ts +9 -0
- package/dist/fracDecConverter/index.js +34 -0
- package/dist/hashing.d.ts +2 -0
- package/dist/hashing.js +7 -0
- package/dist/id.d.ts +5 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/localStorage.d.ts +37 -0
- package/dist/localStorage.js +22 -0
- package/dist/math.d.ts +60 -0
- package/{src/math.ts → dist/math.js} +28 -32
- package/dist/math.test.d.ts +1 -0
- package/dist/math.test.js +42 -0
- package/{src/maybeGetter/index.ts → dist/maybeGetter/index.d.ts} +3 -18
- package/dist/maybeGetter/index.js +15 -0
- package/dist/mouse.d.ts +8 -0
- package/{src/mouse.ts → dist/mouse.js} +4 -4
- package/dist/random.d.ts +19 -0
- package/dist/random.js +21 -0
- package/dist/sets.d.ts +8 -0
- package/{src/sets.ts → dist/sets.js} +2 -2
- package/dist/string.d.ts +21 -0
- package/{src/string.ts → dist/string.js} +11 -11
- package/dist/string.test.d.ts +1 -0
- package/dist/string.test.js +14 -0
- package/{src/types.ts → dist/types.d.ts} +13 -38
- package/dist/types.js +1 -0
- package/dist/utils/clone.d.ts +9 -0
- package/dist/utils/clone.js +15 -0
- package/dist/utils/clone.test.d.ts +1 -0
- package/dist/utils/clone.test.js +42 -0
- package/dist/utils/colors.d.ts +522 -0
- package/dist/utils/colors.js +517 -0
- package/dist/utils/ctx/index.d.ts +10 -0
- package/dist/utils/ctx/index.js +19 -0
- package/dist/utils/debounce.d.ts +9 -0
- package/dist/utils/debounce.js +15 -0
- package/dist/utils/debugging.d.ts +2 -0
- package/dist/utils/debugging.js +21 -0
- package/dist/utils/deepDelta/delta.test.d.ts +1 -0
- package/dist/utils/deepDelta/delta.test.js +114 -0
- package/dist/utils/deepDelta/index.d.ts +8 -0
- package/dist/utils/deepDelta/index.js +40 -0
- package/dist/utils/deepMerge.d.ts +16 -0
- package/dist/utils/deepMerge.js +32 -0
- package/dist/utils/deepMerge.test.d.ts +1 -0
- package/dist/utils/deepMerge.test.js +68 -0
- package/dist/utils/fps.d.ts +6 -0
- package/dist/utils/fps.js +51 -0
- package/dist/utils/fracDecConverter/index.d.ts +9 -0
- package/dist/utils/fracDecConverter/index.js +34 -0
- package/dist/utils/hashing.d.ts +2 -0
- package/dist/utils/hashing.js +7 -0
- package/dist/utils/id.d.ts +5 -0
- package/dist/utils/id.js +5 -0
- package/dist/utils/localStorage.d.ts +37 -0
- package/dist/utils/localStorage.js +22 -0
- package/dist/utils/math.d.ts +60 -0
- package/dist/utils/math.js +89 -0
- package/dist/utils/math.test.d.ts +1 -0
- package/dist/utils/math.test.js +42 -0
- package/dist/utils/maybeGetter/index.d.ts +26 -0
- package/dist/utils/maybeGetter/index.js +15 -0
- package/dist/utils/mouse.d.ts +8 -0
- package/dist/utils/mouse.js +8 -0
- package/dist/utils/random.d.ts +19 -0
- package/dist/utils/random.js +21 -0
- package/dist/utils/sets.d.ts +8 -0
- package/dist/utils/sets.js +10 -0
- package/dist/utils/string.d.ts +21 -0
- package/dist/utils/string.js +31 -0
- package/dist/utils/string.test.d.ts +1 -0
- package/dist/utils/string.test.js +14 -0
- package/dist/utils/types.d.ts +54 -0
- package/dist/utils/types.js +1 -0
- package/package.json +4 -1
- package/src/clone.test.ts +0 -47
- package/src/clone.ts +0 -15
- package/src/ctx/index.ts +0 -20
- package/src/debugging.ts +0 -23
- package/src/deepDelta/delta.test.ts +0 -129
- package/src/deepDelta/index.ts +0 -48
- package/src/deepMerge.test.ts +0 -89
- package/src/deepMerge.ts +0 -37
- package/src/fps.ts +0 -64
- package/src/fracDecConverter/index.ts +0 -36
- package/src/hashing.ts +0 -9
- package/src/localStorage.ts +0 -49
- package/src/math.test.ts +0 -57
- package/src/random.ts +0 -27
- package/src/string.test.ts +0 -17
- package/tsconfig.json +0 -20
- /package/{src/id.ts → dist/id.js} +0 -0
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* {@link} https://en.wikipedia.org/wiki/Golden_ratio
|
|
4
4
|
*/
|
|
5
5
|
export const GOLDEN_RATIO = 1.618;
|
|
6
|
-
|
|
7
6
|
/**
|
|
8
7
|
* rounds a number to the nearest multiple of another number
|
|
9
8
|
*
|
|
@@ -14,10 +13,9 @@ export const GOLDEN_RATIO = 1.618;
|
|
|
14
13
|
* roundToNearest5(13) // 15
|
|
15
14
|
* roundToNearest5(12) // 10
|
|
16
15
|
*/
|
|
17
|
-
export const roundToNearestN = (nearest
|
|
18
|
-
|
|
16
|
+
export const roundToNearestN = (nearest) => (n) => {
|
|
17
|
+
return Math.round(n / nearest) * nearest;
|
|
19
18
|
};
|
|
20
|
-
|
|
21
19
|
/**
|
|
22
20
|
* get the prime factors of a number
|
|
23
21
|
*
|
|
@@ -26,22 +24,20 @@ export const roundToNearestN = (nearest: number) => (n: number) => {
|
|
|
26
24
|
* @example getPrimeFactors(12) // [2, 2, 3]
|
|
27
25
|
* getPrimeFactors(15) // [3, 5]
|
|
28
26
|
*/
|
|
29
|
-
export const getPrimeFactors = (num
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
27
|
+
export const getPrimeFactors = (num) => {
|
|
28
|
+
const factors = [];
|
|
29
|
+
let divisor = 2;
|
|
30
|
+
while (num >= 2) {
|
|
31
|
+
if (num % divisor === 0) {
|
|
32
|
+
factors.push(divisor);
|
|
33
|
+
num = num / divisor;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
divisor++;
|
|
37
|
+
}
|
|
39
38
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return factors;
|
|
39
|
+
return factors;
|
|
43
40
|
};
|
|
44
|
-
|
|
45
41
|
/**
|
|
46
42
|
* get the lowest prime factor of a number
|
|
47
43
|
*
|
|
@@ -51,11 +47,11 @@ export const getPrimeFactors = (num: number) => {
|
|
|
51
47
|
* lowestPrimeFactor(12) // 12 = 2 * 2 * 3, min(2, 2, 3) = 2
|
|
52
48
|
* lowestPrimeFactor(15) // 15 = 3 * 5, min(3, 5) = 3
|
|
53
49
|
*/
|
|
54
|
-
export const lowestPrimeFactor = (num
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
export const lowestPrimeFactor = (num) => {
|
|
51
|
+
if (num === 1)
|
|
52
|
+
return 1; // 1 has no prime factors
|
|
53
|
+
return Math.min(...getPrimeFactors(num));
|
|
57
54
|
};
|
|
58
|
-
|
|
59
55
|
/**
|
|
60
56
|
* get the greatest common divisor of two numbers.
|
|
61
57
|
* {@link} https://en.wikipedia.org/wiki/Euclidean_algorithm
|
|
@@ -67,18 +63,17 @@ export const lowestPrimeFactor = (num: number) => {
|
|
|
67
63
|
* @example gcd(12, 15) // 3
|
|
68
64
|
* gcd(12, 18) // 6
|
|
69
65
|
*/
|
|
70
|
-
export const gcd = (a
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
export const gcd = (a, b) => {
|
|
67
|
+
if (b === 0)
|
|
68
|
+
return a;
|
|
69
|
+
return gcd(b, a % b);
|
|
73
70
|
};
|
|
74
|
-
|
|
75
71
|
/**
|
|
76
72
|
* check if two numbers are within a certain tolerance of each other
|
|
77
73
|
*/
|
|
78
|
-
export const within = (tolerance
|
|
79
|
-
|
|
74
|
+
export const within = (tolerance) => (a, b) => {
|
|
75
|
+
return Math.abs(a - b) <= tolerance;
|
|
80
76
|
};
|
|
81
|
-
|
|
82
77
|
/**
|
|
83
78
|
* get the average of an array of numbers
|
|
84
79
|
*
|
|
@@ -87,7 +82,8 @@ export const within = (tolerance: number) => (a: number, b: number) => {
|
|
|
87
82
|
* @example average([1, 2, 3]) // 2
|
|
88
83
|
* average([1, 2, 3, 4]) // 2.5
|
|
89
84
|
*/
|
|
90
|
-
export const average = (arr
|
|
91
|
-
|
|
92
|
-
|
|
85
|
+
export const average = (arr) => {
|
|
86
|
+
if (arr.length === 0)
|
|
87
|
+
return 0;
|
|
88
|
+
return arr.reduce((acc, val) => acc + val, 0) / arr.length;
|
|
93
89
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { average, gcd, getPrimeFactors, lowestPrimeFactor, roundToNearestN, } from './math';
|
|
3
|
+
describe('roundToNearestN', () => {
|
|
4
|
+
test('rounds a number to the nearest multiple of n', () => {
|
|
5
|
+
const roundToNearest5 = roundToNearestN(5);
|
|
6
|
+
expect(roundToNearest5(13)).toBe(15);
|
|
7
|
+
expect(roundToNearest5(12)).toBe(10);
|
|
8
|
+
});
|
|
9
|
+
});
|
|
10
|
+
describe('getPrimeFactors', () => {
|
|
11
|
+
test('returns the prime factors of a number', () => {
|
|
12
|
+
expect(getPrimeFactors(12)).toEqual([2, 2, 3]);
|
|
13
|
+
expect(getPrimeFactors(15)).toEqual([3, 5]);
|
|
14
|
+
});
|
|
15
|
+
test('edge case: 1', () => {
|
|
16
|
+
expect(getPrimeFactors(1)).toEqual([]);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe('lowestPrimeFactor', () => {
|
|
20
|
+
test('returns the lowest prime factor of a number', () => {
|
|
21
|
+
expect(lowestPrimeFactor(12)).toBe(2);
|
|
22
|
+
expect(lowestPrimeFactor(15)).toBe(3);
|
|
23
|
+
});
|
|
24
|
+
test('edge case: 1', () => {
|
|
25
|
+
expect(lowestPrimeFactor(1)).toBe(1);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
describe('gcd', () => {
|
|
29
|
+
test('returns the greatest common divisor of two numbers', () => {
|
|
30
|
+
expect(gcd(12, 15)).toBe(3);
|
|
31
|
+
expect(gcd(12, 18)).toBe(6);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
describe('average', () => {
|
|
35
|
+
test('returns the average of a list of numbers', () => {
|
|
36
|
+
expect(average([1, 2, 3, 4, 5])).toBe(3);
|
|
37
|
+
expect(average([1, 2, 3, 4, 5, 6])).toBe(3.5);
|
|
38
|
+
});
|
|
39
|
+
test('edge case: empty list', () => {
|
|
40
|
+
expect(average([])).toBe(0);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { RemoveAnyArray } from '../types';
|
|
2
|
-
|
|
3
2
|
/**
|
|
4
3
|
* taking some data that may be a plain value or a function that returns that value
|
|
5
4
|
*
|
|
@@ -7,20 +6,14 @@ import type { RemoveAnyArray } from '../types';
|
|
|
7
6
|
* @template K - the type of the arguments necessary in order to resolve the value
|
|
8
7
|
*/
|
|
9
8
|
export type MaybeGetter<T, K extends any[] = []> = T | ((...arg: K) => T);
|
|
10
|
-
|
|
11
9
|
/**
|
|
12
10
|
* the value of a MaybeGetter
|
|
13
11
|
*/
|
|
14
|
-
export type UnwrapMaybeGetter<T> =
|
|
15
|
-
T extends MaybeGetter<infer U, infer _> ? U : T;
|
|
16
|
-
|
|
12
|
+
export type UnwrapMaybeGetter<T> = T extends MaybeGetter<infer U, infer _> ? U : T;
|
|
17
13
|
/**
|
|
18
14
|
* the parameters of a MaybeGetter
|
|
19
15
|
*/
|
|
20
|
-
export type MaybeGetterParams<T> = RemoveAnyArray<
|
|
21
|
-
T extends MaybeGetter<infer _, infer K> ? K : []
|
|
22
|
-
>;
|
|
23
|
-
|
|
16
|
+
export type MaybeGetterParams<T> = RemoveAnyArray<T extends MaybeGetter<infer _, infer K> ? K : []>;
|
|
24
17
|
/**
|
|
25
18
|
* unwraps a MaybeGetter into a value of type T.
|
|
26
19
|
*
|
|
@@ -30,12 +23,4 @@ export type MaybeGetterParams<T> = RemoveAnyArray<
|
|
|
30
23
|
* @example getValue(5) // 5
|
|
31
24
|
* getValue(() => 5) // 5
|
|
32
25
|
*/
|
|
33
|
-
export const getValue
|
|
34
|
-
value: MaybeGetter<T, K>,
|
|
35
|
-
...args: K
|
|
36
|
-
) => {
|
|
37
|
-
if (typeof value === 'function') {
|
|
38
|
-
return (value as (...args: K) => T)(...args);
|
|
39
|
-
}
|
|
40
|
-
return value;
|
|
41
|
-
};
|
|
26
|
+
export declare const getValue: <T, K extends any[]>(value: MaybeGetter<T, K>, ...args: K) => T;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* unwraps a MaybeGetter into a value of type T.
|
|
3
|
+
*
|
|
4
|
+
* @param value - the value to unwrap
|
|
5
|
+
* @param args - the arguments to pass to the getter if the value is a getter
|
|
6
|
+
* @returns T, which is UnwrapMaybeGetter<MaybeGetter<T, K>>
|
|
7
|
+
* @example getValue(5) // 5
|
|
8
|
+
* getValue(() => 5) // 5
|
|
9
|
+
*/
|
|
10
|
+
export const getValue = (value, ...args) => {
|
|
11
|
+
if (typeof value === 'function') {
|
|
12
|
+
return value(...args);
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
};
|
package/dist/mouse.d.ts
ADDED
package/dist/random.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* given two numbers, this function returns a random number between them (inclusive)
|
|
3
|
+
*
|
|
4
|
+
* @param min - the lowest number
|
|
5
|
+
* @param max - the highest number
|
|
6
|
+
* @returns a random number between min and max
|
|
7
|
+
*/
|
|
8
|
+
export declare const getRandomInRange: (min: number, max: number) => number;
|
|
9
|
+
export declare const getRandomPointOnCanvas: (canvas: HTMLCanvasElement, buffer?: number) => {
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* get a random element from an array
|
|
15
|
+
*
|
|
16
|
+
* @param array
|
|
17
|
+
* @returns random element from given array
|
|
18
|
+
*/
|
|
19
|
+
export declare const getRandomElement: <T>(array: ArrayLike<T>) => T;
|
package/dist/random.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* given two numbers, this function returns a random number between them (inclusive)
|
|
3
|
+
*
|
|
4
|
+
* @param min - the lowest number
|
|
5
|
+
* @param max - the highest number
|
|
6
|
+
* @returns a random number between min and max
|
|
7
|
+
*/
|
|
8
|
+
export const getRandomInRange = (min, max) => Math.round(Math.random() * (max - min) + min);
|
|
9
|
+
export const getRandomPointOnCanvas = (canvas, buffer = 50) => ({
|
|
10
|
+
x: getRandomInRange(buffer, canvas.width - buffer),
|
|
11
|
+
y: getRandomInRange(buffer, canvas.height - buffer),
|
|
12
|
+
});
|
|
13
|
+
/**
|
|
14
|
+
* get a random element from an array
|
|
15
|
+
*
|
|
16
|
+
* @param array
|
|
17
|
+
* @returns random element from given array
|
|
18
|
+
*/
|
|
19
|
+
export const getRandomElement = (array) => {
|
|
20
|
+
return array[Math.floor(Math.random() * array.length)];
|
|
21
|
+
};
|
package/dist/sets.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* combine an array of sets into a single set
|
|
3
|
+
*
|
|
4
|
+
* @param sets array of sets
|
|
5
|
+
* @returns a single set containing all elements from the input sets
|
|
6
|
+
* @example mergeSetArrayIntoSet([new Set([1, 2]), new Set([2, 3])]) // Set(1, 2, 3)
|
|
7
|
+
*/
|
|
8
|
+
export declare const mergeSetArrayIntoSet: <T>(sets: Set<T>[]) => Set<T>;
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
* @returns a single set containing all elements from the input sets
|
|
6
6
|
* @example mergeSetArrayIntoSet([new Set([1, 2]), new Set([2, 3])]) // Set(1, 2, 3)
|
|
7
7
|
*/
|
|
8
|
-
export const mergeSetArrayIntoSet =
|
|
9
|
-
|
|
8
|
+
export const mergeSetArrayIntoSet = (sets) => {
|
|
9
|
+
return sets.reduce((acc, set) => new Set([...acc, ...set]), new Set());
|
|
10
10
|
};
|
package/dist/string.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* makes the first letter of a string uppercase
|
|
3
|
+
*
|
|
4
|
+
* @param str - the string to capitalize
|
|
5
|
+
* @returns the capitalized string
|
|
6
|
+
* @example capitalize('hello') // 'Hello'
|
|
7
|
+
*/
|
|
8
|
+
export declare const capitalize: (str: string) => string;
|
|
9
|
+
/**
|
|
10
|
+
* turns a camelCase string into a title case string
|
|
11
|
+
*
|
|
12
|
+
* @param str - the string to convert
|
|
13
|
+
* @returns the title case string
|
|
14
|
+
* @example camelCaseToTitleCase('camelCase') // 'Camel Case'
|
|
15
|
+
*/
|
|
16
|
+
export declare const camelCaseToTitleCase: (str: string) => string;
|
|
17
|
+
/**
|
|
18
|
+
* turns an array of strings into a comma separated list with 'and' before the last item
|
|
19
|
+
* @example toCommaList(['a', 'b', 'c']) // 'a, b and c'
|
|
20
|
+
*/
|
|
21
|
+
export declare const getCommaList: (arr: string[]) => string;
|
|
@@ -5,9 +5,7 @@
|
|
|
5
5
|
* @returns the capitalized string
|
|
6
6
|
* @example capitalize('hello') // 'Hello'
|
|
7
7
|
*/
|
|
8
|
-
export const capitalize = (str
|
|
9
|
-
str.charAt(0).toUpperCase() + str.slice(1);
|
|
10
|
-
|
|
8
|
+
export const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
11
9
|
/**
|
|
12
10
|
* turns a camelCase string into a title case string
|
|
13
11
|
*
|
|
@@ -15,17 +13,19 @@ export const capitalize = (str: string) =>
|
|
|
15
13
|
* @returns the title case string
|
|
16
14
|
* @example camelCaseToTitleCase('camelCase') // 'Camel Case'
|
|
17
15
|
*/
|
|
18
|
-
export const camelCaseToTitleCase = (str
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
export const camelCaseToTitleCase = (str) => {
|
|
17
|
+
const result = str.replace(/([A-Z])/g, ' $1');
|
|
18
|
+
return capitalize(result);
|
|
21
19
|
};
|
|
22
20
|
/**
|
|
23
21
|
* turns an array of strings into a comma separated list with 'and' before the last item
|
|
24
22
|
* @example toCommaList(['a', 'b', 'c']) // 'a, b and c'
|
|
25
23
|
*/
|
|
26
|
-
export const getCommaList = (arr
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
export const getCommaList = (arr) => {
|
|
25
|
+
if (arr.length === 0)
|
|
26
|
+
return '';
|
|
27
|
+
if (arr.length === 1)
|
|
28
|
+
return arr[0];
|
|
29
|
+
const last = arr.pop();
|
|
30
|
+
return arr.join(', ') + ' and ' + last;
|
|
31
31
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { camelCaseToTitleCase, capitalize } from './string';
|
|
3
|
+
describe('capitalize', () => {
|
|
4
|
+
test('capitalizes the first letter of a string', () => {
|
|
5
|
+
expect(capitalize('hello')).toBe('Hello');
|
|
6
|
+
expect(capitalize('this is one string')).toBe('This is one string');
|
|
7
|
+
});
|
|
8
|
+
});
|
|
9
|
+
describe('camelCaseToTitleCase', () => {
|
|
10
|
+
test('converts camelCase to title case', () => {
|
|
11
|
+
expect(camelCaseToTitleCase('camelCase')).toBe('Camel Case');
|
|
12
|
+
expect(camelCaseToTitleCase('thisIsOneString')).toBe('This Is One String');
|
|
13
|
+
});
|
|
14
|
+
});
|
|
@@ -1,71 +1,45 @@
|
|
|
1
1
|
import type { Prettify, UnionToIntersection } from 'ts-essentials';
|
|
2
|
-
|
|
3
2
|
/**
|
|
4
3
|
* makes only certain keys K in an object T optional
|
|
5
4
|
* @example
|
|
6
5
|
* type T = PartiallyPartial<{ a: number, b: string }, 'a'> // { a?: number, b: string }
|
|
7
6
|
*/
|
|
8
|
-
export type PartiallyPartial<T, K extends keyof T> = Prettify<
|
|
9
|
-
Omit<T, K> & Partial<Pick<T, K>>
|
|
10
|
-
>;
|
|
11
|
-
|
|
7
|
+
export type PartiallyPartial<T, K extends keyof T> = Prettify<Omit<T, K> & Partial<Pick<T, K>>>;
|
|
12
8
|
/**
|
|
13
9
|
* makes only certain keys K in an object T required
|
|
14
10
|
* @example
|
|
15
11
|
* type T = PartiallyRequired<{ a?: number, b?: string }, 'a'> // { a: number, b?: string }
|
|
16
12
|
*/
|
|
17
|
-
export type PartiallyRequired<T, K extends keyof T> = Prettify<
|
|
18
|
-
Omit<T, K> & Required<Pick<T, K>>
|
|
19
|
-
>;
|
|
20
|
-
|
|
13
|
+
export type PartiallyRequired<T, K extends keyof T> = Prettify<Omit<T, K> & Required<Pick<T, K>>>;
|
|
21
14
|
/**
|
|
22
15
|
* takes `any[]` out of a union of arrays
|
|
23
16
|
* @example RemoveAnyArray<number[] | any[]> // number[]
|
|
24
17
|
*/
|
|
25
|
-
export type RemoveAnyArray<T extends unknown[]> = Exclude<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
>;
|
|
29
|
-
|
|
30
|
-
// HTML mouse and keyboard event types
|
|
31
|
-
|
|
18
|
+
export type RemoveAnyArray<T extends unknown[]> = Exclude<T, [
|
|
19
|
+
'!!!-@-NOT-A-TYPE-@-!!!'
|
|
20
|
+
][]>;
|
|
32
21
|
type EventNames = keyof HTMLElementEventMap;
|
|
33
|
-
|
|
34
22
|
type FilterEventNames<T> = {
|
|
35
|
-
|
|
23
|
+
[K in EventNames]: HTMLElementEventMap[K] extends T ? K : never;
|
|
36
24
|
}[EventNames];
|
|
37
|
-
|
|
38
25
|
type MouseEventNames = FilterEventNames<MouseEvent>;
|
|
39
26
|
type KeyboardEventNames = FilterEventNames<KeyboardEvent>;
|
|
40
|
-
|
|
41
27
|
type EventMap<T extends EventNames, E> = Record<T, (ev: E) => void>;
|
|
42
|
-
|
|
43
28
|
export type MouseEventMap = EventMap<MouseEventNames, MouseEvent>;
|
|
44
29
|
export type KeyboardEventMap = EventMap<KeyboardEventNames, KeyboardEvent>;
|
|
45
|
-
|
|
46
30
|
export type MouseEventEntries = [
|
|
47
|
-
|
|
48
|
-
|
|
31
|
+
keyof MouseEventMap,
|
|
32
|
+
(ev: MouseEvent) => void
|
|
49
33
|
][];
|
|
50
34
|
export type KeyboardEventEntries = [
|
|
51
|
-
|
|
52
|
-
|
|
35
|
+
keyof KeyboardEventMap,
|
|
36
|
+
(ev: KeyboardEvent) => void
|
|
53
37
|
][];
|
|
54
|
-
|
|
55
38
|
export type TimeoutHandler = ReturnType<typeof setTimeout>;
|
|
56
39
|
export type IntervalHandler = ReturnType<typeof setInterval>;
|
|
57
|
-
|
|
58
|
-
type LastOf<U> =
|
|
59
|
-
UnionToIntersection<U extends any ? () => U : never> extends () => infer R
|
|
60
|
-
? R
|
|
61
|
-
: never;
|
|
62
|
-
|
|
40
|
+
type LastOf<U> = UnionToIntersection<U extends any ? () => U : never> extends () => infer R ? R : never;
|
|
63
41
|
type Push<T extends any[], V> = [...T, V];
|
|
64
|
-
|
|
65
|
-
type UnionToTuple<T, L = LastOf<T>> = [T] extends [never]
|
|
66
|
-
? []
|
|
67
|
-
: Push<UnionToTuple<Exclude<T, L>>, L>;
|
|
68
|
-
|
|
42
|
+
type UnionToTuple<T, L = LastOf<T>> = [T] extends [never] ? [] : Push<UnionToTuple<Exclude<T, L>>, L>;
|
|
69
43
|
/**
|
|
70
44
|
* turns the keys of an object into a tuple
|
|
71
45
|
*
|
|
@@ -77,3 +51,4 @@ type UnionToTuple<T, L = LastOf<T>> = [T] extends [never]
|
|
|
77
51
|
* // ["name", "age", "id"]
|
|
78
52
|
*/
|
|
79
53
|
export type ObjectKeysToTuple<T extends object> = UnionToTuple<keyof T>;
|
|
54
|
+
export {};
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* clones an object while preserving the references of non-primitive values
|
|
3
|
+
*
|
|
4
|
+
* @param obj - the object to clone
|
|
5
|
+
* @returns the cloned object
|
|
6
|
+
*/
|
|
7
|
+
export const clone = (obj) => {
|
|
8
|
+
const cloned = { ...obj };
|
|
9
|
+
for (const key in cloned) {
|
|
10
|
+
if (typeof cloned[key] === 'object') {
|
|
11
|
+
cloned[key] = clone(cloned[key]);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return cloned;
|
|
15
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { expect, test } from "vitest";
|
|
2
|
+
import { clone } from "./clone";
|
|
3
|
+
import { delta } from "./deepDelta";
|
|
4
|
+
test("works on basic objects", () => {
|
|
5
|
+
const obj = { a: 1, b: 2 };
|
|
6
|
+
const cloned = clone(obj);
|
|
7
|
+
expect(cloned).not.toBe(obj);
|
|
8
|
+
expect(cloned).toEqual(obj);
|
|
9
|
+
});
|
|
10
|
+
test("works on nested objects", () => {
|
|
11
|
+
const obj = { a: { b: 1 } };
|
|
12
|
+
const cloned = clone(obj);
|
|
13
|
+
expect(cloned).not.toBe(obj);
|
|
14
|
+
expect(cloned).toEqual(obj);
|
|
15
|
+
});
|
|
16
|
+
test("works by preserving nested references", () => {
|
|
17
|
+
const objWithRef = { a: { b: () => { } }, c: { d: 1 } };
|
|
18
|
+
const cloned = clone(objWithRef);
|
|
19
|
+
objWithRef.c = {};
|
|
20
|
+
expect(cloned.a.b).toBe(objWithRef.a.b);
|
|
21
|
+
expect(cloned.c).toEqual({ d: 1 });
|
|
22
|
+
});
|
|
23
|
+
test("works with deep delta", () => {
|
|
24
|
+
const nodeSize = (node) => node.size;
|
|
25
|
+
const nodeBorderWidth = (node) => node.borderWidth;
|
|
26
|
+
const storedTheme = clone({
|
|
27
|
+
nodeSize,
|
|
28
|
+
nodeBorderWidth,
|
|
29
|
+
nodeBorderColor: "#000",
|
|
30
|
+
edgeWidth: 1,
|
|
31
|
+
edgeColor: "#123",
|
|
32
|
+
});
|
|
33
|
+
const incomingTheme = {
|
|
34
|
+
nodeSize,
|
|
35
|
+
nodeBorderWidth,
|
|
36
|
+
nodeBorderColor: "#000",
|
|
37
|
+
edgeWidth: 1,
|
|
38
|
+
edgeColor: "#123",
|
|
39
|
+
};
|
|
40
|
+
const diff = delta(storedTheme, incomingTheme);
|
|
41
|
+
expect(diff).toEqual(null);
|
|
42
|
+
});
|