@oscarpalmer/atoms 0.19.0 → 0.21.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/js/index.js +51 -38
- package/dist/js/is.js +44 -0
- package/dist/js/is.mjs +36 -0
- package/dist/js/proxy.js +67 -15
- package/dist/js/proxy.mjs +29 -14
- package/dist/js/string.js +0 -4
- package/dist/js/string.mjs +0 -4
- package/dist/js/value.js +25 -22
- package/dist/js/value.mjs +14 -22
- package/package.json +7 -1
- package/src/js/array.ts +3 -2
- package/src/js/is.ts +77 -0
- package/src/js/proxy.ts +45 -23
- package/src/js/string.ts +0 -9
- package/src/js/value.ts +31 -38
- package/types/is.d.ts +30 -0
- package/types/proxy.d.ts +11 -2
- package/types/string.d.ts +0 -4
- package/types/value.d.ts +13 -16
- package/dist/js/colour.mjs +0 -124
package/dist/js/index.js
CHANGED
|
@@ -275,8 +275,17 @@ function getString(value) {
|
|
|
275
275
|
const result = value?.toString?.() ?? value;
|
|
276
276
|
return result?.toString?.() ?? String(result);
|
|
277
277
|
}
|
|
278
|
-
|
|
279
|
-
|
|
278
|
+
|
|
279
|
+
// src/js/is.ts
|
|
280
|
+
function isArrayOrPlainObject(value) {
|
|
281
|
+
return Array.isArray(value) || isPlainObject(value);
|
|
282
|
+
}
|
|
283
|
+
function isPlainObject(value) {
|
|
284
|
+
if (typeof value !== "object" || value === null) {
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
const prototype = Object.getPrototypeOf(value);
|
|
288
|
+
return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in value) && !(Symbol.iterator in value);
|
|
280
289
|
}
|
|
281
290
|
|
|
282
291
|
// src/js/value.ts
|
|
@@ -286,13 +295,13 @@ var _getDiffs = function(first, second, prefix) {
|
|
|
286
295
|
let outer = 0;
|
|
287
296
|
for (;outer < 2; outer += 1) {
|
|
288
297
|
const value = outer === 0 ? first : second;
|
|
289
|
-
if (!
|
|
298
|
+
if (!value) {
|
|
290
299
|
continue;
|
|
291
300
|
}
|
|
292
301
|
const keys = Object.keys(value);
|
|
293
|
-
const
|
|
302
|
+
const { length } = keys;
|
|
294
303
|
let inner = 0;
|
|
295
|
-
for (;inner <
|
|
304
|
+
for (;inner < length; inner += 1) {
|
|
296
305
|
const key = keys[inner];
|
|
297
306
|
if (checked.has(key)) {
|
|
298
307
|
continue;
|
|
@@ -306,7 +315,9 @@ var _getDiffs = function(first, second, prefix) {
|
|
|
306
315
|
to,
|
|
307
316
|
key: prefixed
|
|
308
317
|
});
|
|
309
|
-
|
|
318
|
+
if (isArrayOrPlainObject(from) && isArrayOrPlainObject(to)) {
|
|
319
|
+
changes.push(..._getDiffs(from, to, prefixed));
|
|
320
|
+
}
|
|
310
321
|
}
|
|
311
322
|
checked.add(key);
|
|
312
323
|
}
|
|
@@ -345,8 +356,8 @@ function diff(first, second) {
|
|
|
345
356
|
values: {}
|
|
346
357
|
};
|
|
347
358
|
const same = Object.is(first, second);
|
|
348
|
-
const firstIsArrayOrObject =
|
|
349
|
-
const secondIsArrayOrObject =
|
|
359
|
+
const firstIsArrayOrObject = isArrayOrPlainObject(first);
|
|
360
|
+
const secondIsArrayOrObject = isArrayOrPlainObject(second);
|
|
350
361
|
if (same || !firstIsArrayOrObject && !secondIsArrayOrObject) {
|
|
351
362
|
result.type = same ? "none" : "full";
|
|
352
363
|
return result;
|
|
@@ -379,20 +390,11 @@ function get(data, key) {
|
|
|
379
390
|
}
|
|
380
391
|
return value;
|
|
381
392
|
}
|
|
382
|
-
function isArrayOrObject(value) {
|
|
383
|
-
return /^(array|object)$/i.test(value?.constructor?.name);
|
|
384
|
-
}
|
|
385
|
-
function isNullable(value) {
|
|
386
|
-
return value == null;
|
|
387
|
-
}
|
|
388
|
-
function isObject(value) {
|
|
389
|
-
return /^object$/i.test(value?.constructor?.name);
|
|
390
|
-
}
|
|
391
393
|
function merge(...values) {
|
|
392
394
|
if (values.length === 0) {
|
|
393
395
|
return {};
|
|
394
396
|
}
|
|
395
|
-
const actual = values.filter(
|
|
397
|
+
const actual = values.filter((value) => isArrayOrPlainObject(value));
|
|
396
398
|
const result = actual.every(Array.isArray) ? [] : {};
|
|
397
399
|
const { length } = actual;
|
|
398
400
|
let itemIndex = 0;
|
|
@@ -405,8 +407,8 @@ function merge(...values) {
|
|
|
405
407
|
const key = keys[keyIndex];
|
|
406
408
|
const next = item[key];
|
|
407
409
|
const previous = result[key];
|
|
408
|
-
if (
|
|
409
|
-
result[key] =
|
|
410
|
+
if (isArrayOrPlainObject(next)) {
|
|
411
|
+
result[key] = isArrayOrPlainObject(previous) ? merge(previous, next) : merge(next);
|
|
410
412
|
} else {
|
|
411
413
|
result[key] = next;
|
|
412
414
|
}
|
|
@@ -417,11 +419,12 @@ function merge(...values) {
|
|
|
417
419
|
function set(data, key, value) {
|
|
418
420
|
const parts = getString(key).split(".");
|
|
419
421
|
const { length } = parts;
|
|
422
|
+
const lastIndex = length - 1;
|
|
420
423
|
let index = 0;
|
|
421
424
|
let target = typeof data === "object" ? data ?? {} : {};
|
|
422
425
|
for (;index < length; index += 1) {
|
|
423
426
|
const part = parts[index];
|
|
424
|
-
if (parts.indexOf(part) ===
|
|
427
|
+
if (parts.indexOf(part) === lastIndex) {
|
|
425
428
|
_setValue(target, part, value);
|
|
426
429
|
break;
|
|
427
430
|
}
|
|
@@ -436,36 +439,50 @@ function set(data, key, value) {
|
|
|
436
439
|
}
|
|
437
440
|
|
|
438
441
|
// src/js/proxy.ts
|
|
439
|
-
var _createProxy = function(
|
|
440
|
-
if (!
|
|
442
|
+
var _createProxy = function(existing, value2) {
|
|
443
|
+
if (!isArrayOrPlainObject(value2) || _isProxy(value2) && value2.$ === existing) {
|
|
441
444
|
return value2;
|
|
442
445
|
}
|
|
443
446
|
const isArray = Array.isArray(value2);
|
|
444
|
-
const
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
447
|
+
const proxy = new Proxy(isArray ? [] : {}, {
|
|
448
|
+
get(target, property) {
|
|
449
|
+
return property === "$" ? manager : Reflect.get(target, property);
|
|
450
|
+
},
|
|
451
|
+
set(target, property, value3) {
|
|
452
|
+
return property === "$" || Reflect.set(target, property, _createProxy(manager, value3));
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
const manager = existing ?? new Manager(proxy);
|
|
456
|
+
Object.defineProperty(proxy, "$", {
|
|
457
|
+
value: manager
|
|
448
458
|
});
|
|
449
459
|
const keys = Object.keys(value2);
|
|
450
|
-
const
|
|
460
|
+
const { length } = keys;
|
|
451
461
|
let index = 0;
|
|
452
|
-
for (;index <
|
|
462
|
+
for (;index < length; index += 1) {
|
|
453
463
|
const key = keys[index];
|
|
454
|
-
|
|
464
|
+
proxy[key] = value2[key];
|
|
455
465
|
}
|
|
456
|
-
return
|
|
466
|
+
return proxy;
|
|
457
467
|
};
|
|
458
468
|
var _isProxy = function(value2) {
|
|
459
|
-
return value2?.$ instanceof
|
|
469
|
+
return value2?.$ instanceof Manager;
|
|
460
470
|
};
|
|
461
471
|
function proxy(value2) {
|
|
462
|
-
if (!
|
|
472
|
+
if (!isArrayOrPlainObject(value2)) {
|
|
463
473
|
throw new Error("Proxy value must be an array or object");
|
|
464
474
|
}
|
|
465
475
|
return _createProxy(undefined, value2);
|
|
466
476
|
}
|
|
467
477
|
|
|
468
|
-
class
|
|
478
|
+
class Manager {
|
|
479
|
+
owner;
|
|
480
|
+
constructor(owner) {
|
|
481
|
+
this.owner = owner;
|
|
482
|
+
}
|
|
483
|
+
clone() {
|
|
484
|
+
return clone(merge(this.owner));
|
|
485
|
+
}
|
|
469
486
|
}
|
|
470
487
|
// src/js/timer.ts
|
|
471
488
|
function repeat(callback, options) {
|
|
@@ -559,10 +576,6 @@ export {
|
|
|
559
576
|
push,
|
|
560
577
|
proxy,
|
|
561
578
|
merge,
|
|
562
|
-
isObject,
|
|
563
|
-
isNullableOrWhitespace,
|
|
564
|
-
isNullable,
|
|
565
|
-
isArrayOrObject,
|
|
566
579
|
insert,
|
|
567
580
|
indexOf,
|
|
568
581
|
groupBy,
|
package/dist/js/is.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// src/js/string.ts
|
|
2
|
+
function getString(value) {
|
|
3
|
+
if (typeof value === "string") {
|
|
4
|
+
return value;
|
|
5
|
+
}
|
|
6
|
+
const result = value?.toString?.() ?? value;
|
|
7
|
+
return result?.toString?.() ?? String(result);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// src/js/is.ts
|
|
11
|
+
function isArrayOrPlainObject(value) {
|
|
12
|
+
return Array.isArray(value) || isPlainObject(value);
|
|
13
|
+
}
|
|
14
|
+
function isNullable(value) {
|
|
15
|
+
return value == null;
|
|
16
|
+
}
|
|
17
|
+
function isNullableOrWhitespace(value) {
|
|
18
|
+
return value == null || getString(value).trim().length === 0;
|
|
19
|
+
}
|
|
20
|
+
function isNumber(value) {
|
|
21
|
+
return typeof value === "number" && !Number.isNaN(value);
|
|
22
|
+
}
|
|
23
|
+
function isNumerical(value) {
|
|
24
|
+
return isNumber(value) || typeof value === "string" && value.trim().length > 0 && !Number.isNaN(+value);
|
|
25
|
+
}
|
|
26
|
+
function isObject(value) {
|
|
27
|
+
return typeof value === "object" && value !== null || typeof value === "function";
|
|
28
|
+
}
|
|
29
|
+
function isPlainObject(value) {
|
|
30
|
+
if (typeof value !== "object" || value === null) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
const prototype = Object.getPrototypeOf(value);
|
|
34
|
+
return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in value) && !(Symbol.iterator in value);
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
isPlainObject,
|
|
38
|
+
isObject,
|
|
39
|
+
isNumerical,
|
|
40
|
+
isNumber,
|
|
41
|
+
isNullableOrWhitespace,
|
|
42
|
+
isNullable,
|
|
43
|
+
isArrayOrPlainObject
|
|
44
|
+
};
|
package/dist/js/is.mjs
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// src/js/is.ts
|
|
2
|
+
import {getString} from "./string";
|
|
3
|
+
function isArrayOrPlainObject(value) {
|
|
4
|
+
return Array.isArray(value) || isPlainObject(value);
|
|
5
|
+
}
|
|
6
|
+
function isNullable(value) {
|
|
7
|
+
return value == null;
|
|
8
|
+
}
|
|
9
|
+
function isNullableOrWhitespace(value) {
|
|
10
|
+
return value == null || getString(value).trim().length === 0;
|
|
11
|
+
}
|
|
12
|
+
function isNumber(value) {
|
|
13
|
+
return typeof value === "number" && !Number.isNaN(value);
|
|
14
|
+
}
|
|
15
|
+
function isNumerical(value) {
|
|
16
|
+
return isNumber(value) || typeof value === "string" && value.trim().length > 0 && !Number.isNaN(+value);
|
|
17
|
+
}
|
|
18
|
+
function isObject(value) {
|
|
19
|
+
return typeof value === "object" && value !== null || typeof value === "function";
|
|
20
|
+
}
|
|
21
|
+
function isPlainObject(value) {
|
|
22
|
+
if (typeof value !== "object" || value === null) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
const prototype = Object.getPrototypeOf(value);
|
|
26
|
+
return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in value) && !(Symbol.iterator in value);
|
|
27
|
+
}
|
|
28
|
+
export {
|
|
29
|
+
isPlainObject,
|
|
30
|
+
isObject,
|
|
31
|
+
isNumerical,
|
|
32
|
+
isNumber,
|
|
33
|
+
isNullableOrWhitespace,
|
|
34
|
+
isNullable,
|
|
35
|
+
isArrayOrPlainObject
|
|
36
|
+
};
|
package/dist/js/proxy.js
CHANGED
|
@@ -1,39 +1,91 @@
|
|
|
1
|
+
// src/js/is.ts
|
|
2
|
+
function isArrayOrPlainObject(value) {
|
|
3
|
+
return Array.isArray(value) || isPlainObject(value);
|
|
4
|
+
}
|
|
5
|
+
function isPlainObject(value) {
|
|
6
|
+
if (typeof value !== "object" || value === null) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
const prototype = Object.getPrototypeOf(value);
|
|
10
|
+
return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in value) && !(Symbol.iterator in value);
|
|
11
|
+
}
|
|
12
|
+
|
|
1
13
|
// src/js/value.ts
|
|
2
|
-
function
|
|
3
|
-
return
|
|
14
|
+
function clone(value) {
|
|
15
|
+
return structuredClone(value);
|
|
16
|
+
}
|
|
17
|
+
function merge(...values) {
|
|
18
|
+
if (values.length === 0) {
|
|
19
|
+
return {};
|
|
20
|
+
}
|
|
21
|
+
const actual = values.filter((value) => isArrayOrPlainObject(value));
|
|
22
|
+
const result = actual.every(Array.isArray) ? [] : {};
|
|
23
|
+
const { length } = actual;
|
|
24
|
+
let itemIndex = 0;
|
|
25
|
+
for (;itemIndex < length; itemIndex += 1) {
|
|
26
|
+
const item = actual[itemIndex];
|
|
27
|
+
const keys = Object.keys(item);
|
|
28
|
+
const size = keys.length;
|
|
29
|
+
let keyIndex = 0;
|
|
30
|
+
for (;keyIndex < size; keyIndex += 1) {
|
|
31
|
+
const key = keys[keyIndex];
|
|
32
|
+
const next = item[key];
|
|
33
|
+
const previous = result[key];
|
|
34
|
+
if (isArrayOrPlainObject(next)) {
|
|
35
|
+
result[key] = isArrayOrPlainObject(previous) ? merge(previous, next) : merge(next);
|
|
36
|
+
} else {
|
|
37
|
+
result[key] = next;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
4
42
|
}
|
|
5
43
|
|
|
6
44
|
// src/js/proxy.ts
|
|
7
|
-
var _createProxy = function(
|
|
8
|
-
if (!
|
|
45
|
+
var _createProxy = function(existing, value2) {
|
|
46
|
+
if (!isArrayOrPlainObject(value2) || _isProxy(value2) && value2.$ === existing) {
|
|
9
47
|
return value2;
|
|
10
48
|
}
|
|
11
49
|
const isArray = Array.isArray(value2);
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
50
|
+
const proxy = new Proxy(isArray ? [] : {}, {
|
|
51
|
+
get(target, property) {
|
|
52
|
+
return property === "$" ? manager : Reflect.get(target, property);
|
|
53
|
+
},
|
|
54
|
+
set(target, property, value3) {
|
|
55
|
+
return property === "$" || Reflect.set(target, property, _createProxy(manager, value3));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
const manager = existing ?? new Manager(proxy);
|
|
59
|
+
Object.defineProperty(proxy, "$", {
|
|
60
|
+
value: manager
|
|
16
61
|
});
|
|
17
62
|
const keys = Object.keys(value2);
|
|
18
|
-
const
|
|
63
|
+
const { length } = keys;
|
|
19
64
|
let index = 0;
|
|
20
|
-
for (;index <
|
|
65
|
+
for (;index < length; index += 1) {
|
|
21
66
|
const key = keys[index];
|
|
22
|
-
|
|
67
|
+
proxy[key] = value2[key];
|
|
23
68
|
}
|
|
24
|
-
return
|
|
69
|
+
return proxy;
|
|
25
70
|
};
|
|
26
71
|
var _isProxy = function(value2) {
|
|
27
|
-
return value2?.$ instanceof
|
|
72
|
+
return value2?.$ instanceof Manager;
|
|
28
73
|
};
|
|
29
74
|
function proxy(value2) {
|
|
30
|
-
if (!
|
|
75
|
+
if (!isArrayOrPlainObject(value2)) {
|
|
31
76
|
throw new Error("Proxy value must be an array or object");
|
|
32
77
|
}
|
|
33
78
|
return _createProxy(undefined, value2);
|
|
34
79
|
}
|
|
35
80
|
|
|
36
|
-
class
|
|
81
|
+
class Manager {
|
|
82
|
+
owner;
|
|
83
|
+
constructor(owner) {
|
|
84
|
+
this.owner = owner;
|
|
85
|
+
}
|
|
86
|
+
clone() {
|
|
87
|
+
return clone(merge(this.owner));
|
|
88
|
+
}
|
|
37
89
|
}
|
|
38
90
|
export {
|
|
39
91
|
proxy
|
package/dist/js/proxy.mjs
CHANGED
|
@@ -1,35 +1,50 @@
|
|
|
1
1
|
// src/js/proxy.ts
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import {isArrayOrPlainObject} from "./is";
|
|
3
|
+
import {clone, merge} from "./value";
|
|
4
|
+
var _createProxy = function(existing, value2) {
|
|
5
|
+
if (!isArrayOrPlainObject(value2) || _isProxy(value2) && value2.$ === existing) {
|
|
5
6
|
return value2;
|
|
6
7
|
}
|
|
7
8
|
const isArray = Array.isArray(value2);
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const proxy = new Proxy(isArray ? [] : {}, {
|
|
10
|
+
get(target, property) {
|
|
11
|
+
return property === "$" ? manager : Reflect.get(target, property);
|
|
12
|
+
},
|
|
13
|
+
set(target, property, value3) {
|
|
14
|
+
return property === "$" || Reflect.set(target, property, _createProxy(manager, value3));
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
const manager = existing ?? new Manager(proxy);
|
|
18
|
+
Object.defineProperty(proxy, "$", {
|
|
19
|
+
value: manager
|
|
12
20
|
});
|
|
13
21
|
const keys = Object.keys(value2);
|
|
14
|
-
const
|
|
22
|
+
const { length } = keys;
|
|
15
23
|
let index = 0;
|
|
16
|
-
for (;index <
|
|
24
|
+
for (;index < length; index += 1) {
|
|
17
25
|
const key = keys[index];
|
|
18
|
-
|
|
26
|
+
proxy[key] = value2[key];
|
|
19
27
|
}
|
|
20
|
-
return
|
|
28
|
+
return proxy;
|
|
21
29
|
};
|
|
22
30
|
var _isProxy = function(value2) {
|
|
23
|
-
return value2?.$ instanceof
|
|
31
|
+
return value2?.$ instanceof Manager;
|
|
24
32
|
};
|
|
25
33
|
function proxy(value2) {
|
|
26
|
-
if (!
|
|
34
|
+
if (!isArrayOrPlainObject(value2)) {
|
|
27
35
|
throw new Error("Proxy value must be an array or object");
|
|
28
36
|
}
|
|
29
37
|
return _createProxy(undefined, value2);
|
|
30
38
|
}
|
|
31
39
|
|
|
32
|
-
class
|
|
40
|
+
class Manager {
|
|
41
|
+
owner;
|
|
42
|
+
constructor(owner) {
|
|
43
|
+
this.owner = owner;
|
|
44
|
+
}
|
|
45
|
+
clone() {
|
|
46
|
+
return clone(merge(this.owner));
|
|
47
|
+
}
|
|
33
48
|
}
|
|
34
49
|
export {
|
|
35
50
|
proxy
|
package/dist/js/string.js
CHANGED
|
@@ -9,11 +9,7 @@ function getString(value) {
|
|
|
9
9
|
const result = value?.toString?.() ?? value;
|
|
10
10
|
return result?.toString?.() ?? String(result);
|
|
11
11
|
}
|
|
12
|
-
function isNullableOrWhitespace(value) {
|
|
13
|
-
return value == null || getString(value).trim().length === 0;
|
|
14
|
-
}
|
|
15
12
|
export {
|
|
16
|
-
isNullableOrWhitespace,
|
|
17
13
|
getString,
|
|
18
14
|
createUuid
|
|
19
15
|
};
|
package/dist/js/string.mjs
CHANGED
|
@@ -9,11 +9,7 @@ function getString(value) {
|
|
|
9
9
|
const result = value?.toString?.() ?? value;
|
|
10
10
|
return result?.toString?.() ?? String(result);
|
|
11
11
|
}
|
|
12
|
-
function isNullableOrWhitespace(value) {
|
|
13
|
-
return value == null || getString(value).trim().length === 0;
|
|
14
|
-
}
|
|
15
12
|
export {
|
|
16
|
-
isNullableOrWhitespace,
|
|
17
13
|
getString,
|
|
18
14
|
createUuid
|
|
19
15
|
};
|
package/dist/js/value.js
CHANGED
|
@@ -7,6 +7,18 @@ function getString(value) {
|
|
|
7
7
|
return result?.toString?.() ?? String(result);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
// src/js/is.ts
|
|
11
|
+
function isArrayOrPlainObject(value) {
|
|
12
|
+
return Array.isArray(value) || isPlainObject(value);
|
|
13
|
+
}
|
|
14
|
+
function isPlainObject(value) {
|
|
15
|
+
if (typeof value !== "object" || value === null) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
const prototype = Object.getPrototypeOf(value);
|
|
19
|
+
return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in value) && !(Symbol.iterator in value);
|
|
20
|
+
}
|
|
21
|
+
|
|
10
22
|
// src/js/value.ts
|
|
11
23
|
var _getDiffs = function(first, second, prefix) {
|
|
12
24
|
const changes = [];
|
|
@@ -14,13 +26,13 @@ var _getDiffs = function(first, second, prefix) {
|
|
|
14
26
|
let outer = 0;
|
|
15
27
|
for (;outer < 2; outer += 1) {
|
|
16
28
|
const value = outer === 0 ? first : second;
|
|
17
|
-
if (!
|
|
29
|
+
if (!value) {
|
|
18
30
|
continue;
|
|
19
31
|
}
|
|
20
32
|
const keys = Object.keys(value);
|
|
21
|
-
const
|
|
33
|
+
const { length } = keys;
|
|
22
34
|
let inner = 0;
|
|
23
|
-
for (;inner <
|
|
35
|
+
for (;inner < length; inner += 1) {
|
|
24
36
|
const key = keys[inner];
|
|
25
37
|
if (checked.has(key)) {
|
|
26
38
|
continue;
|
|
@@ -34,7 +46,9 @@ var _getDiffs = function(first, second, prefix) {
|
|
|
34
46
|
to,
|
|
35
47
|
key: prefixed
|
|
36
48
|
});
|
|
37
|
-
|
|
49
|
+
if (isArrayOrPlainObject(from) && isArrayOrPlainObject(to)) {
|
|
50
|
+
changes.push(..._getDiffs(from, to, prefixed));
|
|
51
|
+
}
|
|
38
52
|
}
|
|
39
53
|
checked.add(key);
|
|
40
54
|
}
|
|
@@ -73,8 +87,8 @@ function diff(first, second) {
|
|
|
73
87
|
values: {}
|
|
74
88
|
};
|
|
75
89
|
const same = Object.is(first, second);
|
|
76
|
-
const firstIsArrayOrObject =
|
|
77
|
-
const secondIsArrayOrObject =
|
|
90
|
+
const firstIsArrayOrObject = isArrayOrPlainObject(first);
|
|
91
|
+
const secondIsArrayOrObject = isArrayOrPlainObject(second);
|
|
78
92
|
if (same || !firstIsArrayOrObject && !secondIsArrayOrObject) {
|
|
79
93
|
result.type = same ? "none" : "full";
|
|
80
94
|
return result;
|
|
@@ -107,20 +121,11 @@ function get(data, key) {
|
|
|
107
121
|
}
|
|
108
122
|
return value;
|
|
109
123
|
}
|
|
110
|
-
function isArrayOrObject(value) {
|
|
111
|
-
return /^(array|object)$/i.test(value?.constructor?.name);
|
|
112
|
-
}
|
|
113
|
-
function isNullable(value) {
|
|
114
|
-
return value == null;
|
|
115
|
-
}
|
|
116
|
-
function isObject(value) {
|
|
117
|
-
return /^object$/i.test(value?.constructor?.name);
|
|
118
|
-
}
|
|
119
124
|
function merge(...values) {
|
|
120
125
|
if (values.length === 0) {
|
|
121
126
|
return {};
|
|
122
127
|
}
|
|
123
|
-
const actual = values.filter(
|
|
128
|
+
const actual = values.filter((value) => isArrayOrPlainObject(value));
|
|
124
129
|
const result = actual.every(Array.isArray) ? [] : {};
|
|
125
130
|
const { length } = actual;
|
|
126
131
|
let itemIndex = 0;
|
|
@@ -133,8 +138,8 @@ function merge(...values) {
|
|
|
133
138
|
const key = keys[keyIndex];
|
|
134
139
|
const next = item[key];
|
|
135
140
|
const previous = result[key];
|
|
136
|
-
if (
|
|
137
|
-
result[key] =
|
|
141
|
+
if (isArrayOrPlainObject(next)) {
|
|
142
|
+
result[key] = isArrayOrPlainObject(previous) ? merge(previous, next) : merge(next);
|
|
138
143
|
} else {
|
|
139
144
|
result[key] = next;
|
|
140
145
|
}
|
|
@@ -145,11 +150,12 @@ function merge(...values) {
|
|
|
145
150
|
function set(data, key, value) {
|
|
146
151
|
const parts = getString(key).split(".");
|
|
147
152
|
const { length } = parts;
|
|
153
|
+
const lastIndex = length - 1;
|
|
148
154
|
let index = 0;
|
|
149
155
|
let target = typeof data === "object" ? data ?? {} : {};
|
|
150
156
|
for (;index < length; index += 1) {
|
|
151
157
|
const part = parts[index];
|
|
152
|
-
if (parts.indexOf(part) ===
|
|
158
|
+
if (parts.indexOf(part) === lastIndex) {
|
|
153
159
|
_setValue(target, part, value);
|
|
154
160
|
break;
|
|
155
161
|
}
|
|
@@ -165,9 +171,6 @@ function set(data, key, value) {
|
|
|
165
171
|
export {
|
|
166
172
|
set,
|
|
167
173
|
merge,
|
|
168
|
-
isObject,
|
|
169
|
-
isNullable,
|
|
170
|
-
isArrayOrObject,
|
|
171
174
|
get,
|
|
172
175
|
diff,
|
|
173
176
|
clone
|
package/dist/js/value.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/js/value.ts
|
|
2
|
+
import {isArrayOrPlainObject} from "./is";
|
|
2
3
|
import {getString} from "./string";
|
|
3
4
|
var _getDiffs = function(first, second, prefix) {
|
|
4
5
|
const changes = [];
|
|
@@ -6,13 +7,13 @@ var _getDiffs = function(first, second, prefix) {
|
|
|
6
7
|
let outer = 0;
|
|
7
8
|
for (;outer < 2; outer += 1) {
|
|
8
9
|
const value = outer === 0 ? first : second;
|
|
9
|
-
if (!
|
|
10
|
+
if (!value) {
|
|
10
11
|
continue;
|
|
11
12
|
}
|
|
12
13
|
const keys = Object.keys(value);
|
|
13
|
-
const
|
|
14
|
+
const { length } = keys;
|
|
14
15
|
let inner = 0;
|
|
15
|
-
for (;inner <
|
|
16
|
+
for (;inner < length; inner += 1) {
|
|
16
17
|
const key = keys[inner];
|
|
17
18
|
if (checked.has(key)) {
|
|
18
19
|
continue;
|
|
@@ -26,7 +27,9 @@ var _getDiffs = function(first, second, prefix) {
|
|
|
26
27
|
to,
|
|
27
28
|
key: prefixed
|
|
28
29
|
});
|
|
29
|
-
|
|
30
|
+
if (isArrayOrPlainObject(from) && isArrayOrPlainObject(to)) {
|
|
31
|
+
changes.push(..._getDiffs(from, to, prefixed));
|
|
32
|
+
}
|
|
30
33
|
}
|
|
31
34
|
checked.add(key);
|
|
32
35
|
}
|
|
@@ -65,8 +68,8 @@ function diff(first, second) {
|
|
|
65
68
|
values: {}
|
|
66
69
|
};
|
|
67
70
|
const same = Object.is(first, second);
|
|
68
|
-
const firstIsArrayOrObject =
|
|
69
|
-
const secondIsArrayOrObject =
|
|
71
|
+
const firstIsArrayOrObject = isArrayOrPlainObject(first);
|
|
72
|
+
const secondIsArrayOrObject = isArrayOrPlainObject(second);
|
|
70
73
|
if (same || !firstIsArrayOrObject && !secondIsArrayOrObject) {
|
|
71
74
|
result.type = same ? "none" : "full";
|
|
72
75
|
return result;
|
|
@@ -99,20 +102,11 @@ function get(data, key) {
|
|
|
99
102
|
}
|
|
100
103
|
return value;
|
|
101
104
|
}
|
|
102
|
-
function isArrayOrObject(value) {
|
|
103
|
-
return /^(array|object)$/i.test(value?.constructor?.name);
|
|
104
|
-
}
|
|
105
|
-
function isNullable(value) {
|
|
106
|
-
return value == null;
|
|
107
|
-
}
|
|
108
|
-
function isObject(value) {
|
|
109
|
-
return /^object$/i.test(value?.constructor?.name);
|
|
110
|
-
}
|
|
111
105
|
function merge(...values) {
|
|
112
106
|
if (values.length === 0) {
|
|
113
107
|
return {};
|
|
114
108
|
}
|
|
115
|
-
const actual = values.filter(
|
|
109
|
+
const actual = values.filter((value) => isArrayOrPlainObject(value));
|
|
116
110
|
const result = actual.every(Array.isArray) ? [] : {};
|
|
117
111
|
const { length } = actual;
|
|
118
112
|
let itemIndex = 0;
|
|
@@ -125,8 +119,8 @@ function merge(...values) {
|
|
|
125
119
|
const key = keys[keyIndex];
|
|
126
120
|
const next = item[key];
|
|
127
121
|
const previous = result[key];
|
|
128
|
-
if (
|
|
129
|
-
result[key] =
|
|
122
|
+
if (isArrayOrPlainObject(next)) {
|
|
123
|
+
result[key] = isArrayOrPlainObject(previous) ? merge(previous, next) : merge(next);
|
|
130
124
|
} else {
|
|
131
125
|
result[key] = next;
|
|
132
126
|
}
|
|
@@ -137,11 +131,12 @@ function merge(...values) {
|
|
|
137
131
|
function set(data, key, value) {
|
|
138
132
|
const parts = getString(key).split(".");
|
|
139
133
|
const { length } = parts;
|
|
134
|
+
const lastIndex = length - 1;
|
|
140
135
|
let index = 0;
|
|
141
136
|
let target = typeof data === "object" ? data ?? {} : {};
|
|
142
137
|
for (;index < length; index += 1) {
|
|
143
138
|
const part = parts[index];
|
|
144
|
-
if (parts.indexOf(part) ===
|
|
139
|
+
if (parts.indexOf(part) === lastIndex) {
|
|
145
140
|
_setValue(target, part, value);
|
|
146
141
|
break;
|
|
147
142
|
}
|
|
@@ -157,9 +152,6 @@ function set(data, key, value) {
|
|
|
157
152
|
export {
|
|
158
153
|
set,
|
|
159
154
|
merge,
|
|
160
|
-
isObject,
|
|
161
|
-
isNullable,
|
|
162
|
-
isArrayOrObject,
|
|
163
155
|
get,
|
|
164
156
|
diff,
|
|
165
157
|
clone
|
package/package.json
CHANGED
|
@@ -36,6 +36,12 @@
|
|
|
36
36
|
"require": "./dist/js/element/focusable.js",
|
|
37
37
|
"types": "./types/element/focusable.d.ts"
|
|
38
38
|
},
|
|
39
|
+
"./is": {
|
|
40
|
+
"bun": "./src/js/is.ts",
|
|
41
|
+
"import": "./dist/js/is.mjs",
|
|
42
|
+
"require": "./dist/js/is.js",
|
|
43
|
+
"types": "./types/is.d.ts"
|
|
44
|
+
},
|
|
39
45
|
"./number": {
|
|
40
46
|
"bun": "./src/js/number.ts",
|
|
41
47
|
"import": "./dist/js/number.mjs",
|
|
@@ -99,5 +105,5 @@
|
|
|
99
105
|
},
|
|
100
106
|
"type": "module",
|
|
101
107
|
"types": "./types/index.d.ts",
|
|
102
|
-
"version": "0.
|
|
108
|
+
"version": "0.21.0"
|
|
103
109
|
}
|
package/src/js/array.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {PlainObject} from './is';
|
|
2
|
+
import {Key} from './value';
|
|
2
3
|
|
|
3
4
|
type BooleanCallback<T> = (item: T, index: number, array: T[]) => boolean;
|
|
4
5
|
|
|
@@ -35,7 +36,7 @@ function _getCallbacks<T>(
|
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
return {
|
|
38
|
-
key: (item: T) => (item as
|
|
39
|
+
key: (item: T) => (item as PlainObject)?.[key as string] as Key,
|
|
39
40
|
};
|
|
40
41
|
}
|
|
41
42
|
|
package/src/js/is.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {getString} from './string';
|
|
2
|
+
|
|
3
|
+
export type ArrayOrPlainObject = unknown[] | PlainObject;
|
|
4
|
+
|
|
5
|
+
export type PlainObject = Record<string, unknown>;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Is the value an array or a plain object?
|
|
9
|
+
*/
|
|
10
|
+
export function isArrayOrPlainObject(
|
|
11
|
+
value: unknown,
|
|
12
|
+
): value is ArrayOrPlainObject {
|
|
13
|
+
return Array.isArray(value) || isPlainObject(value);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Is the value undefined or null?
|
|
18
|
+
*/
|
|
19
|
+
export function isNullable(value: unknown): value is undefined | null {
|
|
20
|
+
return value == null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Is the value undefined, null, or an empty string?
|
|
25
|
+
*/
|
|
26
|
+
export function isNullableOrWhitespace(
|
|
27
|
+
value: unknown,
|
|
28
|
+
): value is undefined | null | '' {
|
|
29
|
+
return value == null || getString(value).trim().length === 0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Is the value a number?
|
|
34
|
+
*/
|
|
35
|
+
export function isNumber(value: unknown): value is number {
|
|
36
|
+
return typeof value === 'number' && !Number.isNaN(value);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Is the value a number, or a number-like string?
|
|
41
|
+
*/
|
|
42
|
+
export function isNumerical(value: unknown): value is number | `${number}` {
|
|
43
|
+
return (
|
|
44
|
+
isNumber(value) ||
|
|
45
|
+
(typeof value === 'string' &&
|
|
46
|
+
value.trim().length > 0 &&
|
|
47
|
+
!Number.isNaN(+value))
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Is the value an object?
|
|
53
|
+
*/
|
|
54
|
+
export function isObject(value: unknown): value is object {
|
|
55
|
+
return (
|
|
56
|
+
(typeof value === 'object' && value !== null) || typeof value === 'function'
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Is the value a generic object?
|
|
62
|
+
*/
|
|
63
|
+
export function isPlainObject(value: unknown): value is PlainObject {
|
|
64
|
+
if (typeof value !== 'object' || value === null) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const prototype = Object.getPrototypeOf(value);
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
(prototype === null ||
|
|
72
|
+
prototype === Object.prototype ||
|
|
73
|
+
Object.getPrototypeOf(prototype) === null) &&
|
|
74
|
+
!(Symbol.toStringTag in value) &&
|
|
75
|
+
!(Symbol.iterator in value)
|
|
76
|
+
);
|
|
77
|
+
}
|
package/src/js/proxy.ts
CHANGED
|
@@ -1,49 +1,71 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {ArrayOrPlainObject, PlainObject, isArrayOrPlainObject} from './is';
|
|
2
|
+
import {clone, merge} from './value';
|
|
2
3
|
|
|
3
|
-
class
|
|
4
|
+
class Manager<T extends ArrayOrPlainObject = PlainObject> {
|
|
5
|
+
constructor(readonly owner: Proxied<T>) {}
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
7
|
+
clone(): Proxied<T> {
|
|
8
|
+
return clone(merge(this.owner)) as Proxied<T>;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type Proxied<T extends ArrayOrPlainObject = PlainObject> = {
|
|
13
|
+
$: Manager<T>;
|
|
14
|
+
} & T;
|
|
8
15
|
|
|
9
|
-
function _createProxy<T extends
|
|
10
|
-
|
|
16
|
+
function _createProxy<T extends ArrayOrPlainObject>(
|
|
17
|
+
existing: Manager | undefined,
|
|
11
18
|
value: T,
|
|
12
|
-
):
|
|
13
|
-
if (
|
|
19
|
+
): unknown {
|
|
20
|
+
if (
|
|
21
|
+
!isArrayOrPlainObject(value) ||
|
|
22
|
+
(_isProxy(value) && value.$ === existing)
|
|
23
|
+
) {
|
|
14
24
|
return value;
|
|
15
25
|
}
|
|
16
26
|
|
|
17
27
|
const isArray = Array.isArray(value);
|
|
18
|
-
const proxyBlob = blob ?? new ProxyBlob();
|
|
19
|
-
const proxyValue = new Proxy(isArray ? [] : {}, {});
|
|
20
28
|
|
|
21
|
-
|
|
22
|
-
|
|
29
|
+
const proxy = new Proxy(isArray ? [] : {}, {
|
|
30
|
+
get(target, property) {
|
|
31
|
+
return property === '$' ? manager : Reflect.get(target, property);
|
|
32
|
+
},
|
|
33
|
+
set(target, property, value) {
|
|
34
|
+
return (
|
|
35
|
+
property === '$' ||
|
|
36
|
+
Reflect.set(target, property, _createProxy(manager, value))
|
|
37
|
+
);
|
|
38
|
+
},
|
|
39
|
+
}) as Proxied;
|
|
40
|
+
|
|
41
|
+
const manager = existing ?? new Manager(proxy);
|
|
42
|
+
|
|
43
|
+
Object.defineProperty(proxy, '$', {
|
|
44
|
+
value: manager,
|
|
23
45
|
});
|
|
24
46
|
|
|
25
|
-
const keys =
|
|
26
|
-
const
|
|
47
|
+
const keys = Object.keys(value);
|
|
48
|
+
const {length} = keys;
|
|
27
49
|
|
|
28
50
|
let index = 0;
|
|
29
51
|
|
|
30
|
-
for (; index <
|
|
52
|
+
for (; index < length; index += 1) {
|
|
31
53
|
const key = keys[index];
|
|
32
54
|
|
|
33
|
-
|
|
55
|
+
proxy[key as never] = value[key as never];
|
|
34
56
|
}
|
|
35
57
|
|
|
36
|
-
return
|
|
58
|
+
return proxy;
|
|
37
59
|
}
|
|
38
60
|
|
|
39
|
-
function _isProxy(value: unknown): value is
|
|
40
|
-
return (value as
|
|
61
|
+
function _isProxy(value: unknown): value is Proxied {
|
|
62
|
+
return (value as Proxied)?.$ instanceof Manager;
|
|
41
63
|
}
|
|
42
64
|
|
|
43
|
-
export function proxy<T extends
|
|
44
|
-
if (!
|
|
65
|
+
export function proxy<T extends PlainObject>(value: T): Proxied<T> {
|
|
66
|
+
if (!isArrayOrPlainObject(value)) {
|
|
45
67
|
throw new Error('Proxy value must be an array or object');
|
|
46
68
|
}
|
|
47
69
|
|
|
48
|
-
return _createProxy(undefined, value)
|
|
70
|
+
return _createProxy(undefined, value) as Proxied<T>;
|
|
49
71
|
}
|
package/src/js/string.ts
CHANGED
|
@@ -24,12 +24,3 @@ export function getString(value: unknown): string {
|
|
|
24
24
|
|
|
25
25
|
return result?.toString?.() ?? String(result);
|
|
26
26
|
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Is the value undefined, null, or an empty string?
|
|
30
|
-
*/
|
|
31
|
-
export function isNullableOrWhitespace(
|
|
32
|
-
value: unknown,
|
|
33
|
-
): value is undefined | null | '' {
|
|
34
|
-
return value == null || getString(value).trim().length === 0;
|
|
35
|
-
}
|
package/src/js/value.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import {chunk} from './array';
|
|
2
|
+
import {ArrayOrPlainObject, PlainObject, isArrayOrPlainObject} from './is';
|
|
1
3
|
import {getString} from './string';
|
|
2
4
|
|
|
3
|
-
export type ArrayOrObject = unknown[] | GenericObject;
|
|
4
|
-
|
|
5
5
|
export type DiffType = 'full' | 'none' | 'partial';
|
|
6
6
|
|
|
7
7
|
export type DiffResult<T1 = unknown, T2 = T1> = {
|
|
@@ -15,15 +15,13 @@ export type DiffValue<T1 = unknown, T2 = T1> = {
|
|
|
15
15
|
to: T2;
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
export type GenericObject = Record<string, unknown>;
|
|
19
|
-
|
|
20
18
|
export type Key = number | string;
|
|
21
19
|
|
|
22
20
|
type KeyedDiffValue = {
|
|
23
21
|
key: string;
|
|
24
22
|
} & DiffValue;
|
|
25
23
|
|
|
26
|
-
export type ValueObject =
|
|
24
|
+
export type ValueObject = ArrayOrPlainObject | Map<unknown, unknown>;
|
|
27
25
|
|
|
28
26
|
function _getDiffs(
|
|
29
27
|
first: unknown,
|
|
@@ -38,16 +36,16 @@ function _getDiffs(
|
|
|
38
36
|
for (; outer < 2; outer += 1) {
|
|
39
37
|
const value = outer === 0 ? first : second;
|
|
40
38
|
|
|
41
|
-
if (!
|
|
39
|
+
if (!value) {
|
|
42
40
|
continue;
|
|
43
41
|
}
|
|
44
42
|
|
|
45
43
|
const keys = Object.keys(value);
|
|
46
|
-
const
|
|
44
|
+
const {length} = keys;
|
|
47
45
|
|
|
48
46
|
let inner = 0;
|
|
49
47
|
|
|
50
|
-
for (; inner <
|
|
48
|
+
for (; inner < length; inner += 1) {
|
|
51
49
|
const key = keys[inner];
|
|
52
50
|
|
|
53
51
|
if (checked.has(key)) {
|
|
@@ -66,7 +64,9 @@ function _getDiffs(
|
|
|
66
64
|
key: prefixed,
|
|
67
65
|
});
|
|
68
66
|
|
|
69
|
-
|
|
67
|
+
if (isArrayOrPlainObject(from) && isArrayOrPlainObject(to)) {
|
|
68
|
+
changes.push(..._getDiffs(from, to, prefixed));
|
|
69
|
+
}
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
checked.add(key);
|
|
@@ -121,6 +121,16 @@ export function clone<T>(value: T): T {
|
|
|
121
121
|
return structuredClone(value);
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
/**
|
|
125
|
+
* - Find the differences between two values
|
|
126
|
+
* - Returns an object holding the result:
|
|
127
|
+
* - `original` holds the original values
|
|
128
|
+
* - `type` is the type of difference:
|
|
129
|
+
* - `full` if the values are completely different
|
|
130
|
+
* - `none` if the values are the same
|
|
131
|
+
* - `partial` if the values are partially different
|
|
132
|
+
* - `values` holds the differences with dot-notation keys
|
|
133
|
+
*/
|
|
124
134
|
export function diff<T1 = unknown, T2 = T1>(
|
|
125
135
|
first: T1,
|
|
126
136
|
second: T2,
|
|
@@ -136,8 +146,8 @@ export function diff<T1 = unknown, T2 = T1>(
|
|
|
136
146
|
|
|
137
147
|
const same = Object.is(first, second);
|
|
138
148
|
|
|
139
|
-
const firstIsArrayOrObject =
|
|
140
|
-
const secondIsArrayOrObject =
|
|
149
|
+
const firstIsArrayOrObject = isArrayOrPlainObject(first);
|
|
150
|
+
const secondIsArrayOrObject = isArrayOrPlainObject(second);
|
|
141
151
|
|
|
142
152
|
if (same || (!firstIsArrayOrObject && !secondIsArrayOrObject)) {
|
|
143
153
|
result.type = same ? 'none' : 'full';
|
|
@@ -190,37 +200,19 @@ export function get(data: ValueObject, key: Key): unknown {
|
|
|
190
200
|
return value;
|
|
191
201
|
}
|
|
192
202
|
|
|
193
|
-
/**
|
|
194
|
-
* Is the value an array or a generic object?
|
|
195
|
-
*/
|
|
196
|
-
export function isArrayOrObject(value: unknown): value is ArrayOrObject {
|
|
197
|
-
return /^(array|object)$/i.test((value as ArrayOrObject)?.constructor?.name);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Is the value undefined or null?
|
|
202
|
-
*/
|
|
203
|
-
export function isNullable(value: unknown): value is undefined | null {
|
|
204
|
-
return value == null;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Is the value a generic object?
|
|
209
|
-
*/
|
|
210
|
-
export function isObject(value: unknown): value is GenericObject {
|
|
211
|
-
return /^object$/i.test((value as GenericObject)?.constructor?.name);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
203
|
/**
|
|
215
204
|
* Merges multiple arrays or objects into a single one
|
|
216
205
|
*/
|
|
217
|
-
export function merge<T =
|
|
206
|
+
export function merge<T = ArrayOrPlainObject>(...values: T[]): T {
|
|
218
207
|
if (values.length === 0) {
|
|
219
208
|
return {} as T;
|
|
220
209
|
}
|
|
221
210
|
|
|
222
|
-
const actual = values.filter(
|
|
223
|
-
|
|
211
|
+
const actual = values.filter(value =>
|
|
212
|
+
isArrayOrPlainObject(value),
|
|
213
|
+
) as PlainObject[];
|
|
214
|
+
|
|
215
|
+
const result = (actual.every(Array.isArray) ? [] : {}) as PlainObject;
|
|
224
216
|
|
|
225
217
|
const {length} = actual;
|
|
226
218
|
|
|
@@ -238,8 +230,8 @@ export function merge<T = ArrayOrObject>(...values: T[]): T {
|
|
|
238
230
|
const next = item[key];
|
|
239
231
|
const previous = result[key];
|
|
240
232
|
|
|
241
|
-
if (
|
|
242
|
-
result[key] =
|
|
233
|
+
if (isArrayOrPlainObject(next)) {
|
|
234
|
+
result[key] = isArrayOrPlainObject(previous)
|
|
243
235
|
? merge(previous, next)
|
|
244
236
|
: merge(next);
|
|
245
237
|
} else {
|
|
@@ -264,6 +256,7 @@ export function set<T extends ValueObject>(
|
|
|
264
256
|
): T {
|
|
265
257
|
const parts = getString(key).split('.');
|
|
266
258
|
const {length} = parts;
|
|
259
|
+
const lastIndex = length - 1;
|
|
267
260
|
|
|
268
261
|
let index = 0;
|
|
269
262
|
let target: ValueObject = typeof data === 'object' ? data ?? {} : {};
|
|
@@ -271,7 +264,7 @@ export function set<T extends ValueObject>(
|
|
|
271
264
|
for (; index < length; index += 1) {
|
|
272
265
|
const part = parts[index];
|
|
273
266
|
|
|
274
|
-
if (parts.indexOf(part) ===
|
|
267
|
+
if (parts.indexOf(part) === lastIndex) {
|
|
275
268
|
_setValue(target, part, value);
|
|
276
269
|
|
|
277
270
|
break;
|
package/types/is.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type ArrayOrPlainObject = unknown[] | PlainObject;
|
|
2
|
+
export type PlainObject = Record<string, unknown>;
|
|
3
|
+
/**
|
|
4
|
+
* Is the value an array or a plain object?
|
|
5
|
+
*/
|
|
6
|
+
export declare function isArrayOrPlainObject(value: unknown): value is ArrayOrPlainObject;
|
|
7
|
+
/**
|
|
8
|
+
* Is the value undefined or null?
|
|
9
|
+
*/
|
|
10
|
+
export declare function isNullable(value: unknown): value is undefined | null;
|
|
11
|
+
/**
|
|
12
|
+
* Is the value undefined, null, or an empty string?
|
|
13
|
+
*/
|
|
14
|
+
export declare function isNullableOrWhitespace(value: unknown): value is undefined | null | '';
|
|
15
|
+
/**
|
|
16
|
+
* Is the value a number?
|
|
17
|
+
*/
|
|
18
|
+
export declare function isNumber(value: unknown): value is number;
|
|
19
|
+
/**
|
|
20
|
+
* Is the value a number, or a number-like string?
|
|
21
|
+
*/
|
|
22
|
+
export declare function isNumerical(value: unknown): value is number | `${number}`;
|
|
23
|
+
/**
|
|
24
|
+
* Is the value an object?
|
|
25
|
+
*/
|
|
26
|
+
export declare function isObject(value: unknown): value is object;
|
|
27
|
+
/**
|
|
28
|
+
* Is the value a generic object?
|
|
29
|
+
*/
|
|
30
|
+
export declare function isPlainObject(value: unknown): value is PlainObject;
|
package/types/proxy.d.ts
CHANGED
|
@@ -1,2 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { ArrayOrPlainObject, PlainObject } from './is';
|
|
2
|
+
declare class Manager<T extends ArrayOrPlainObject = PlainObject> {
|
|
3
|
+
readonly owner: Proxied<T>;
|
|
4
|
+
constructor(owner: Proxied<T>);
|
|
5
|
+
clone(): Proxied<T>;
|
|
6
|
+
}
|
|
7
|
+
export type Proxied<T extends ArrayOrPlainObject = PlainObject> = {
|
|
8
|
+
$: Manager<T>;
|
|
9
|
+
} & T;
|
|
10
|
+
export declare function proxy<T extends PlainObject>(value: T): Proxied<T>;
|
|
11
|
+
export {};
|
package/types/string.d.ts
CHANGED
|
@@ -6,7 +6,3 @@ export declare function createUuid(): string;
|
|
|
6
6
|
* Get the string value from any value
|
|
7
7
|
*/
|
|
8
8
|
export declare function getString(value: unknown): string;
|
|
9
|
-
/**
|
|
10
|
-
* Is the value undefined, null, or an empty string?
|
|
11
|
-
*/
|
|
12
|
-
export declare function isNullableOrWhitespace(value: unknown): value is undefined | null | '';
|
package/types/value.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import { ArrayOrPlainObject } from './is';
|
|
2
2
|
export type DiffType = 'full' | 'none' | 'partial';
|
|
3
3
|
export type DiffResult<T1 = unknown, T2 = T1> = {
|
|
4
4
|
original: DiffValue<T1, T2>;
|
|
@@ -9,13 +9,22 @@ export type DiffValue<T1 = unknown, T2 = T1> = {
|
|
|
9
9
|
from: T1;
|
|
10
10
|
to: T2;
|
|
11
11
|
};
|
|
12
|
-
export type GenericObject = Record<string, unknown>;
|
|
13
12
|
export type Key = number | string;
|
|
14
|
-
export type ValueObject =
|
|
13
|
+
export type ValueObject = ArrayOrPlainObject | Map<unknown, unknown>;
|
|
15
14
|
/**
|
|
16
15
|
* Clones any kind of value
|
|
17
16
|
*/
|
|
18
17
|
export declare function clone<T>(value: T): T;
|
|
18
|
+
/**
|
|
19
|
+
* - Find the differences between two values
|
|
20
|
+
* - Returns an object holding the result:
|
|
21
|
+
* - `original` holds the original values
|
|
22
|
+
* - `type` is the type of difference:
|
|
23
|
+
* - `full` if the values are completely different
|
|
24
|
+
* - `none` if the values are the same
|
|
25
|
+
* - `partial` if the values are partially different
|
|
26
|
+
* - `values` holds the differences with dot-notation keys
|
|
27
|
+
*/
|
|
19
28
|
export declare function diff<T1 = unknown, T2 = T1>(first: T1, second: T2): DiffResult<T1, T2>;
|
|
20
29
|
/**
|
|
21
30
|
* - Get the value from an object using a key path
|
|
@@ -23,22 +32,10 @@ export declare function diff<T1 = unknown, T2 = T1>(first: T1, second: T2): Diff
|
|
|
23
32
|
* - Returns `undefined` if the value is not found
|
|
24
33
|
*/
|
|
25
34
|
export declare function get(data: ValueObject, key: Key): unknown;
|
|
26
|
-
/**
|
|
27
|
-
* Is the value an array or a generic object?
|
|
28
|
-
*/
|
|
29
|
-
export declare function isArrayOrObject(value: unknown): value is ArrayOrObject;
|
|
30
|
-
/**
|
|
31
|
-
* Is the value undefined or null?
|
|
32
|
-
*/
|
|
33
|
-
export declare function isNullable(value: unknown): value is undefined | null;
|
|
34
|
-
/**
|
|
35
|
-
* Is the value a generic object?
|
|
36
|
-
*/
|
|
37
|
-
export declare function isObject(value: unknown): value is GenericObject;
|
|
38
35
|
/**
|
|
39
36
|
* Merges multiple arrays or objects into a single one
|
|
40
37
|
*/
|
|
41
|
-
export declare function merge<T =
|
|
38
|
+
export declare function merge<T = ArrayOrPlainObject>(...values: T[]): T;
|
|
42
39
|
/**
|
|
43
40
|
* - Set the value in an object using a key path
|
|
44
41
|
* - You can set a nested value by using dot notation, e.g., `foo.bar.baz`
|
package/dist/js/colour.mjs
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
// src/js/colour.ts
|
|
2
|
-
import {between} from "./number";
|
|
3
|
-
var _normaliseHex = function(value) {
|
|
4
|
-
return typeof value === "string" ? value.replace(hexTrim, "") : undefined;
|
|
5
|
-
};
|
|
6
|
-
function hexToHSL(value) {
|
|
7
|
-
return rgbToHSL(hexToRGB(value));
|
|
8
|
-
}
|
|
9
|
-
function hexToRGB(value) {
|
|
10
|
-
const normalised = _normaliseHex(value);
|
|
11
|
-
if (!isHexColour(normalised)) {
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
const matches = normalised.match(hexGroups);
|
|
15
|
-
if (matches === null) {
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
return {
|
|
19
|
-
blue: parseInt(matches[1], 16),
|
|
20
|
-
green: parseInt(matches[2], 16),
|
|
21
|
-
red: parseInt(matches[3], 16)
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
function hslToHex(value) {
|
|
25
|
-
if (isHSLColour(value)) {
|
|
26
|
-
return rgbToHex(hslToRGB(value));
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
function hslToRGB(value) {
|
|
30
|
-
if (!isHSLColour(value)) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
function getValue(value2) {
|
|
34
|
-
const k = (value2 + hue / 30) % 12;
|
|
35
|
-
const a = saturation * Math.min(lightness, 1 - lightness);
|
|
36
|
-
return lightness - a * Math.max(-1, Math.min(k - 3, 9 - k, 1));
|
|
37
|
-
}
|
|
38
|
-
let hue = Number(value.hue);
|
|
39
|
-
let lightness = Number(value.lightness);
|
|
40
|
-
let saturation = Number(value.saturation);
|
|
41
|
-
hue %= 360;
|
|
42
|
-
if (hue < 0) {
|
|
43
|
-
hue += 360;
|
|
44
|
-
}
|
|
45
|
-
lightness /= 100;
|
|
46
|
-
saturation /= 100;
|
|
47
|
-
return {
|
|
48
|
-
blue: Math.round(getValue(4) * 255),
|
|
49
|
-
green: Math.round(getValue(8) * 255),
|
|
50
|
-
red: Math.round(getValue(0) * 255)
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
function isHexColour(value) {
|
|
54
|
-
return typeof value === "string" && hexValue.test(value);
|
|
55
|
-
}
|
|
56
|
-
function isHSLColour(value) {
|
|
57
|
-
return ["hue", "lightness", "saturation"].every((key) => between(value?.[key], 0, key === "hue" ? 360 : 100));
|
|
58
|
-
}
|
|
59
|
-
function isRGBColour(value) {
|
|
60
|
-
return ["red", "green", "blue"].every((key) => between(value?.[key], 0, 255));
|
|
61
|
-
}
|
|
62
|
-
function rgbToHex(value) {
|
|
63
|
-
if (isRGBColour(value)) {
|
|
64
|
-
return `#${(value.blue | value.green << 8 | value.red << 16 | 1 << 24).toString(16).slice(1)}`;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
function rgbToHSL(value) {
|
|
68
|
-
if (!isRGBColour(value)) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
let red = Number(value.red);
|
|
72
|
-
let green = Number(value.green);
|
|
73
|
-
let blue = Number(value.blue);
|
|
74
|
-
red /= 255;
|
|
75
|
-
green /= 255;
|
|
76
|
-
blue /= 255;
|
|
77
|
-
const min = Math.min(red, green, blue);
|
|
78
|
-
const max = Math.max(red, green, blue);
|
|
79
|
-
const chroma = max - min;
|
|
80
|
-
const lightness = max - chroma / 2;
|
|
81
|
-
let hue = 0;
|
|
82
|
-
let saturation = 0;
|
|
83
|
-
switch (chroma) {
|
|
84
|
-
case red: {
|
|
85
|
-
hue = (green - blue) / chroma % 6;
|
|
86
|
-
break;
|
|
87
|
-
}
|
|
88
|
-
case green: {
|
|
89
|
-
hue = (blue - red) / chroma + 2;
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
case blue: {
|
|
93
|
-
hue = (red - green) / chroma + 2;
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
default: {
|
|
97
|
-
break;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
saturation = max === 0 || lightness === 0 || lightness === 0 ? 0 : (max - lightness) / Math.min(lightness, 1 - lightness);
|
|
101
|
-
hue *= 60;
|
|
102
|
-
if (hue < 0) {
|
|
103
|
-
hue += 360;
|
|
104
|
-
}
|
|
105
|
-
return {
|
|
106
|
-
hue: Math.round(hue),
|
|
107
|
-
saturation: Math.round(saturation * 100),
|
|
108
|
-
lightness: Math.round(lightness * 100)
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
var hexGroups = /^([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i;
|
|
112
|
-
var hexTrim = /^(#|\s)|\s$/g;
|
|
113
|
-
var hexValue = /^([\da-f]{3}){1,2}$/i;
|
|
114
|
-
export {
|
|
115
|
-
rgbToHex,
|
|
116
|
-
rgbToHSL,
|
|
117
|
-
isRGBColour,
|
|
118
|
-
isHexColour,
|
|
119
|
-
isHSLColour,
|
|
120
|
-
hslToRGB,
|
|
121
|
-
hslToHex,
|
|
122
|
-
hexToRGB,
|
|
123
|
-
hexToHSL
|
|
124
|
-
};
|