@oscarpalmer/atoms 0.118.0 → 0.119.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 (49) hide show
  1. package/dist/atoms.full.js +208 -137
  2. package/dist/color/misc/get.js +6 -2
  3. package/dist/function.js +29 -39
  4. package/dist/index.js +4 -3
  5. package/dist/internal/array/chunk.js +2 -2
  6. package/dist/internal/array/compact.js +2 -2
  7. package/dist/internal/array/insert.js +3 -3
  8. package/dist/internal/frame-rate.js +5 -9
  9. package/dist/internal/math/aggregate.js +6 -2
  10. package/dist/internal/random.js +6 -3
  11. package/dist/internal/value/equal.js +6 -2
  12. package/dist/logger.js +19 -8
  13. package/dist/math.js +3 -5
  14. package/dist/string/case.js +36 -10
  15. package/dist/string/index.js +2 -2
  16. package/dist/string/misc.js +20 -9
  17. package/dist/string/template.js +24 -7
  18. package/dist/value/merge.js +10 -4
  19. package/dist/value/partial.js +1 -1
  20. package/dist/value/smush.js +11 -5
  21. package/package.json +6 -6
  22. package/src/color/misc/get.ts +6 -3
  23. package/src/function.ts +59 -54
  24. package/src/internal/array/chunk.ts +3 -4
  25. package/src/internal/array/compact.ts +6 -3
  26. package/src/internal/array/insert.ts +9 -6
  27. package/src/internal/frame-rate.ts +9 -13
  28. package/src/internal/is.ts +1 -1
  29. package/src/internal/math/aggregate.ts +12 -2
  30. package/src/internal/random.ts +13 -9
  31. package/src/internal/value/equal.ts +46 -19
  32. package/src/logger.ts +38 -19
  33. package/src/math.ts +4 -8
  34. package/src/query.ts +1 -1
  35. package/src/string/case.ts +66 -12
  36. package/src/string/misc.ts +33 -13
  37. package/src/string/template.ts +59 -18
  38. package/src/value/merge.ts +47 -15
  39. package/src/value/partial.ts +3 -1
  40. package/src/value/smush.ts +13 -4
  41. package/types/function.d.ts +17 -3
  42. package/types/internal/array/chunk.d.ts +1 -1
  43. package/types/internal/frame-rate.d.ts +1 -1
  44. package/types/internal/math/aggregate.d.ts +2 -1
  45. package/types/internal/value/equal.d.ts +27 -11
  46. package/types/logger.d.ts +4 -3
  47. package/types/string/misc.d.ts +6 -0
  48. package/types/string/template.d.ts +20 -3
  49. package/types/value/merge.d.ts +19 -3
@@ -5,25 +5,21 @@ function calculate() {
5
5
  function step(now) {
6
6
  if (last != null) values.push(now - last);
7
7
  last = now;
8
- if (values.length >= CALCULATION_TOTAL) resolve(values.sort().slice(CALCULATION_TRIM_PART, -CALCULATION_TRIM_PART).reduce((first, second) => first + second, 0) / (values.length - CALCULATION_TRIM_TOTAL));
8
+ if (values.length >= TOTAL) resolve(values.sort().slice(TRIM_PART, -TRIM_PART).reduce((first, second) => first + second, 0) / (values.length - TRIM_TOTAL));
9
9
  else requestAnimationFrame(step);
10
10
  }
11
11
  requestAnimationFrame(step);
12
12
  });
13
13
  }
14
- const CALCULATION_TOTAL = 10;
15
- const CALCULATION_TRIM_PART = 2;
16
- const CALCULATION_TRIM_TOTAL = 4;
17
- let FRAME_RATE_MS = 1e3 / 60;
18
- calculate().then((value) => {
19
- FRAME_RATE_MS = value;
20
- });
21
- var frame_rate_default = FRAME_RATE_MS;
14
+ const TOTAL = 10;
15
+ const TRIM_PART = 2;
16
+ const TRIM_TOTAL = 4;
17
+ var frame_rate_default = await calculate();
22
18
  function chunk(array, size) {
23
19
  if (!Array.isArray(array)) return [];
24
20
  if (array.length === 0) return [];
25
21
  const { length } = array;
26
- const actualSize = typeof size === "number" && size > 0 && size <= DEFAULT_SIZE ? size : DEFAULT_SIZE;
22
+ const actualSize = typeof size === "number" && size > 0 && size <= MAX_SIZE ? size : MAX_SIZE;
27
23
  if (length <= actualSize) return [array];
28
24
  const chunks = [];
29
25
  let index = 0;
@@ -33,15 +29,15 @@ function chunk(array, size) {
33
29
  }
34
30
  return chunks;
35
31
  }
36
- const DEFAULT_SIZE = 5e3;
32
+ const MAX_SIZE = 5e3;
37
33
  function compact(array, strict) {
38
34
  if (!Array.isArray(array)) return [];
35
+ if (strict === true) return array.filter(Boolean);
39
36
  const { length } = array;
40
- const isStrict = strict ?? false;
41
37
  const compacted = [];
42
38
  for (let index = 0; index < length; index += 1) {
43
39
  const item = array[index];
44
- if (isStrict && !!item || !isStrict && item != null) compacted.push(item);
40
+ if (item != null) compacted.push(item);
45
41
  }
46
42
  return compacted;
47
43
  }
@@ -76,15 +72,18 @@ const TYPED_ARRAYS = new Set([
76
72
  BigInt64Array,
77
73
  BigUint64Array
78
74
  ]);
79
- function getRandomFloat(minimum, maximum) {
75
+ function _getRandomFloat(inclusive, minimum, maximum) {
80
76
  let maxFloat = isNumber(maximum) && maximum <= Number.MAX_SAFE_INTEGER ? maximum : Number.MAX_SAFE_INTEGER;
81
77
  let minFloat = isNumber(minimum) && minimum >= Number.MIN_SAFE_INTEGER ? minimum : Number.MIN_SAFE_INTEGER;
82
78
  if (minFloat === maxFloat) return minFloat;
83
79
  if (minFloat > maxFloat) [minFloat, maxFloat] = [maxFloat, minFloat];
84
- return Math.random() * (maxFloat + 1 - minFloat) + minFloat;
80
+ return Math.random() * (maxFloat + (inclusive ? 1 : 0) - minFloat) + minFloat;
81
+ }
82
+ function getRandomFloat(minimum, maximum) {
83
+ return _getRandomFloat(false, minimum, maximum);
85
84
  }
86
85
  function getRandomInteger(minimum, maximum) {
87
- return Math.floor(getRandomFloat(minimum, maximum));
86
+ return Math.floor(_getRandomFloat(true, minimum, maximum));
88
87
  }
89
88
  function shuffle(array) {
90
89
  if (!Array.isArray(array)) return [];
@@ -219,7 +218,8 @@ function insertChunkedValues(type, array, items, start, deleteCount) {
219
218
  const lastIndex = chunked.length - 1;
220
219
  let index = Number(chunked.length);
221
220
  let returned;
222
- while (--index >= 0) {
221
+ while (index > 0) {
222
+ index -= 1;
223
223
  const result = array.splice(actualStart, index === lastIndex ? actualDeleteCount : 0, ...chunked[index]);
224
224
  if (returned == null) returned = result;
225
225
  else returned.push(...result);
@@ -229,8 +229,7 @@ function insertChunkedValues(type, array, items, start, deleteCount) {
229
229
  }
230
230
  function insertValues(type, array, items, start, deleteCount) {
231
231
  const spliceArray = type === "insert" || type === "splice";
232
- if (!Array.isArray(array) || typeof start !== "number") return spliceArray ? [] : 0;
233
- if (!Array.isArray(items) || items.length === 0) return spliceArray ? [] : 0;
232
+ if (!Array.isArray(array) || typeof start !== "number" || !Array.isArray(items) || items.length === 0) return spliceArray ? [] : 0;
234
233
  return insertChunkedValues(type, array, items, start, spliceArray ? deleteCount : 0);
235
234
  }
236
235
  function insert(array, indexOrItems, items) {
@@ -265,11 +264,15 @@ function aggregate(type, array, key) {
265
264
  };
266
265
  }
267
266
  function max(array, key) {
268
- return aggregate("max", array, key).value;
267
+ return getAggregated("max", array, key);
269
268
  }
270
269
  function calculateSum(current, value, notNumber) {
271
270
  return notNumber ? value : current + value;
272
271
  }
272
+ function getAggregated(type, array, key) {
273
+ const aggregated = aggregate(type, array, key);
274
+ return aggregated.count > 0 ? aggregated.value : NaN;
275
+ }
273
276
  const aggregators = {
274
277
  average: calculateSum,
275
278
  max: (current, value, notNumber) => notNumber || value > current ? value : current,
@@ -772,8 +775,12 @@ function getForegroundColor(value) {
772
775
  green / MAX_HEX,
773
776
  red / MAX_HEX
774
777
  ];
775
- for (let color of values) if (color <= SRGB_LUMINANCE_MINIMUM) color /= SRGB_LUMINANCE_MULTIPLIER;
776
- else color = ((color + SRGB_LUMINANCE_OFFSET) / SRGB_LUMINANCE_MODIFIER) ** SRGB_LUMINANCE_EXPONENT;
778
+ const { length } = values;
779
+ for (let index = 0; index < length; index += 1) {
780
+ const color = values[index];
781
+ if (color <= SRGB_LUMINANCE_MINIMUM) values[index] /= SRGB_LUMINANCE_MULTIPLIER;
782
+ else values[index] = ((color + SRGB_LUMINANCE_OFFSET) / SRGB_LUMINANCE_MODIFIER) ** SRGB_LUMINANCE_EXPONENT;
783
+ }
777
784
  return new Color(SRGB_LUMINANCE_RED * values[2] + SRGB_LUMINANCE_GREEN * values[1] + SRGB_LUMINANCE_BLUE * values[0] > SRGB_LUMINANCE_THRESHOLD ? HEX_BLACK : HEX_WHITE);
778
785
  }
779
786
  function getHexaColor(value) {
@@ -1103,6 +1110,34 @@ var Color = class {
1103
1110
  function getColor(value) {
1104
1111
  return isColor(value) ? value : new Color(value);
1105
1112
  }
1113
+ function isEmpty(value) {
1114
+ if (value == null) return true;
1115
+ if (typeof value === "string") return value.length === 0;
1116
+ const values = getArray(value);
1117
+ const { length } = values;
1118
+ for (let index = 0; index < length; index += 1) if (values[index] != null) return false;
1119
+ return true;
1120
+ }
1121
+ function isNullable(value) {
1122
+ return value == null;
1123
+ }
1124
+ function isNullableOrEmpty(value) {
1125
+ return value == null || getString(value) === "";
1126
+ }
1127
+ function isNullableOrWhitespace(value) {
1128
+ return value == null || EXPRESSION_WHITESPACE.test(getString(value));
1129
+ }
1130
+ function isNumerical(value) {
1131
+ return isNumber(value) || typeof value === "string" && value.trim().length > 0 && !Number.isNaN(+value);
1132
+ }
1133
+ function isObject(value) {
1134
+ return typeof value === "object" && value !== null || typeof value === "function";
1135
+ }
1136
+ function isPrimitive(value) {
1137
+ return value == null || EXPRESSION_PRIMITIVE.test(typeof value);
1138
+ }
1139
+ const EXPRESSION_PRIMITIVE = /^(bigint|boolean|number|string|symbol)$/;
1140
+ const EXPRESSION_WHITESPACE = /^\s*$/;
1106
1141
  var SizedMap = class extends Map {
1107
1142
  #maximumSize;
1108
1143
  get full() {
@@ -1181,10 +1216,10 @@ var Memoized = class {
1181
1216
  get size() {
1182
1217
  return this.#state.cache?.size ?? NaN;
1183
1218
  }
1184
- constructor(callback, size) {
1185
- const cache = new SizedMap(size);
1219
+ constructor(callback, options) {
1220
+ const cache = new SizedMap(options.cacheSize);
1186
1221
  const getter = (...parameters) => {
1187
- const key = parameters.length === 1 ? parameters[0] : join(parameters.map(getString), "_");
1222
+ const key = options.cacheKey?.(...parameters) ?? (parameters.length === 1 ? parameters[0] : join(parameters.map(getString), "_"));
1188
1223
  if (cache.has(key)) return cache.get(key);
1189
1224
  const value = callback(...parameters);
1190
1225
  cache.set(key, value);
@@ -1218,89 +1253,49 @@ var Memoized = class {
1218
1253
  }
1219
1254
  };
1220
1255
  function debounce(callback, time) {
1221
- const interval = typeof time === "number" && time >= frame_rate_default ? time : frame_rate_default;
1222
- function step(now, parameters) {
1223
- if (interval === frame_rate_default || now - start >= interval) callback(...parameters);
1224
- else frame = requestAnimationFrame((next) => {
1225
- step(next, parameters);
1226
- });
1227
- }
1228
- let frame;
1229
- let start;
1230
- const debounced = (...parameters) => {
1231
- debounced.cancel();
1232
- frame = requestAnimationFrame((now) => {
1233
- start = now - frame_rate_default;
1234
- step(now, parameters);
1235
- });
1236
- };
1237
- debounced.cancel = () => {
1238
- if (frame != null) {
1239
- cancelAnimationFrame(frame);
1240
- frame = void 0;
1241
- }
1242
- };
1243
- return debounced;
1256
+ return getLimiter(callback, false, time);
1244
1257
  }
1245
- function memoize(callback, cacheSize) {
1246
- return new Memoized(callback, typeof cacheSize === "number" && cacheSize > 0 ? cacheSize : DEFAULT_CACHE_SIZE);
1247
- }
1248
- function throttle(callback, time) {
1258
+ function getLimiter(callback, throttler, time) {
1249
1259
  const interval = typeof time === "number" && time >= frame_rate_default ? time : frame_rate_default;
1250
1260
  function step(now, parameters) {
1251
- if (interval === frame_rate_default || now - last >= interval) {
1252
- last = now;
1261
+ if (interval === frame_rate_default || now - timestamp >= interval) {
1262
+ if (throttler) timestamp = now;
1253
1263
  callback(...parameters);
1254
1264
  } else frame = requestAnimationFrame((next) => {
1255
1265
  step(next, parameters);
1256
1266
  });
1257
1267
  }
1258
- let last;
1259
1268
  let frame;
1260
- const throttler = (...parameters) => {
1261
- throttler.cancel();
1269
+ let timestamp;
1270
+ const limiter = (...parameters) => {
1271
+ limiter.cancel();
1262
1272
  frame = requestAnimationFrame((now) => {
1263
- last ??= now - frame_rate_default;
1273
+ timestamp ??= now - frame_rate_default;
1264
1274
  step(now, parameters);
1265
1275
  });
1266
1276
  };
1267
- throttler.cancel = () => {
1277
+ limiter.cancel = () => {
1268
1278
  if (frame != null) {
1269
1279
  cancelAnimationFrame(frame);
1270
1280
  frame = void 0;
1271
1281
  }
1272
1282
  };
1273
- return throttler;
1283
+ return limiter;
1274
1284
  }
1275
- const DEFAULT_CACHE_SIZE = 65536;
1276
- function isEmpty(value) {
1277
- if (value == null) return true;
1278
- if (typeof value === "string") return value.length === 0;
1279
- const values = getArray(value);
1280
- const { length } = values;
1281
- for (let index = 0; index < length; index += 1) if (values[index] != null) return false;
1282
- return true;
1283
- }
1284
- function isNullable(value) {
1285
- return value == null;
1286
- }
1287
- function isNullableOrEmpty(value) {
1288
- return value == null || getString(value) === "";
1289
- }
1290
- function isNullableOrWhitespace(value) {
1291
- return value == null || EXPRESSION_WHITESPACE.test(getString(value));
1292
- }
1293
- function isNumerical(value) {
1294
- return isNumber(value) || typeof value === "string" && value.trim().length > 0 && !Number.isNaN(+value);
1285
+ function getMemoizationOptions(input) {
1286
+ const { cacheKey, cacheSize } = isPlainObject(input) ? input : {};
1287
+ return {
1288
+ cacheKey: typeof cacheKey === "function" ? cacheKey : void 0,
1289
+ cacheSize: typeof cacheSize === "number" && cacheSize > 0 ? cacheSize : DEFAULT_CACHE_SIZE
1290
+ };
1295
1291
  }
1296
- function isObject(value) {
1297
- return typeof value === "object" && value !== null || typeof value === "function";
1292
+ function memoize(callback, options) {
1293
+ return new Memoized(callback, getMemoizationOptions(options));
1298
1294
  }
1299
- function isPrimitive(value) {
1300
- return value == null || EXPRESSION_PRIMITIVE.test(typeof value);
1295
+ function throttle(callback, time) {
1296
+ return getLimiter(callback, true, time);
1301
1297
  }
1302
- const EXPRESSION_PRIMITIVE = /^(bigint|boolean|number|string|symbol)$/;
1303
- const EXPRESSION_WHITESPACE = /^\s*$/;
1298
+ const DEFAULT_CACHE_SIZE = 1024;
1304
1299
  let enabled = true;
1305
1300
  var Logger = class {
1306
1301
  get debug() {
@@ -1338,8 +1333,21 @@ var Logger = class {
1338
1333
  }
1339
1334
  };
1340
1335
  var Time = class {
1336
+ #logger;
1337
+ #stopper;
1341
1338
  #state;
1339
+ get active() {
1340
+ return this.#state.started && !this.#state.stopped && enabled;
1341
+ }
1342
+ get log() {
1343
+ return this.active ? this.#logger : noop;
1344
+ }
1345
+ get stop() {
1346
+ return this.active ? this.#stopTimer() : noop;
1347
+ }
1342
1348
  constructor(label) {
1349
+ this.#logger = console.timeLog.bind(console, label);
1350
+ this.#stopper = console.timeEnd.bind(console, label);
1343
1351
  this.#state = {
1344
1352
  label,
1345
1353
  started: enabled,
@@ -1347,14 +1355,12 @@ var Time = class {
1347
1355
  };
1348
1356
  if (this.#state.started) console.time(label);
1349
1357
  }
1350
- log() {
1351
- if (this.#state.started && !this.#state.stopped && enabled) console.timeLog(this.#state.label);
1352
- }
1353
- stop() {
1354
- if (this.#state.started && !this.#state.stopped) {
1355
- this.#state.stopped = true;
1356
- console.timeEnd(this.#state.label);
1357
- }
1358
+ #stopTimer() {
1359
+ const stopper = this.#stopper;
1360
+ this.#state.stopped = true;
1361
+ this.#logger = void 0;
1362
+ this.#stopper = void 0;
1363
+ return stopper;
1358
1364
  }
1359
1365
  };
1360
1366
  const logger = new Logger();
@@ -1376,8 +1382,7 @@ function count(array, key, value) {
1376
1382
  return counted;
1377
1383
  }
1378
1384
  function min(array, key) {
1379
- const aggregated = aggregate("min", array, key);
1380
- return aggregated.count > 0 ? aggregated.value : NaN;
1385
+ return getAggregated("min", array, key);
1381
1386
  }
1382
1387
  function round(value, decimals) {
1383
1388
  if (typeof value !== "number") return NaN;
@@ -1386,8 +1391,7 @@ function round(value, decimals) {
1386
1391
  return Math.round((value + Number.EPSILON) * mod) / mod;
1387
1392
  }
1388
1393
  function sum(array, key) {
1389
- const aggregated = aggregate("sum", array, key);
1390
- return aggregated.count > 0 ? aggregated.value : NaN;
1394
+ return getAggregated("sum", array, key);
1391
1395
  }
1392
1396
  function findKey(needle, haystack) {
1393
1397
  const keys = Object.keys(haystack);
@@ -1525,33 +1529,44 @@ const BOOLEAN_MODIFIER = .5;
1525
1529
  const HEX_CHARACTERS = "0123456789ABCDEF";
1526
1530
  const HEX_MAXIMUM = 15;
1527
1531
  function camelCase(value) {
1528
- return toCase(value, "", true, false);
1532
+ return toCase(TYPE_CAMEL, value, true, false);
1529
1533
  }
1530
1534
  function capitalize(value) {
1531
1535
  if (typeof value !== "string" || value.length === 0) return "";
1532
- return value.length === 1 ? value.toLocaleUpperCase() : `${value.charAt(0).toLocaleUpperCase()}${value.slice(1).toLocaleLowerCase()}`;
1536
+ memoizedCapitalize ??= memoize((v) => v.length === 1 ? v.toLocaleUpperCase() : `${v.charAt(0).toLocaleUpperCase()}${v.slice(1).toLocaleLowerCase()}`);
1537
+ return memoizedCapitalize.run(value);
1533
1538
  }
1534
1539
  function kebabCase(value) {
1535
- return toCase(value, "-", false, false);
1540
+ return toCase(TYPE_KEBAB, value, false, false);
1536
1541
  }
1537
1542
  function pascalCase(value) {
1538
- return toCase(value, "", true, true);
1543
+ return toCase(TYPE_PASCAL, value, true, true);
1539
1544
  }
1540
1545
  function snakeCase(value) {
1541
- return toCase(value, "_", false, false);
1546
+ return toCase(TYPE_SNAKE, value, false, false);
1542
1547
  }
1543
1548
  function titleCase(value) {
1544
1549
  if (typeof value !== "string") return "";
1545
- return value.length < 1 ? capitalize(value) : join(words(value).map(capitalize), " ");
1546
- }
1547
- function toCase(value, delimiter, capitalizeAny, capitalizeFirst) {
1550
+ memoizedTitleCase ??= memoize((v) => v.length < 1 ? capitalize(v) : join(words(v).map(capitalize), " "));
1551
+ return memoizedTitleCase.run(value);
1552
+ }
1553
+ function toCase(type, value, capitalizeAny, capitalizeFirst) {
1554
+ memoizers[type] ??= memoize(toCaseCallback.bind({
1555
+ type,
1556
+ capitalizeAny,
1557
+ capitalizeFirst
1558
+ }));
1559
+ return memoizers[type].run(value);
1560
+ }
1561
+ function toCaseCallback(value) {
1548
1562
  if (typeof value !== "string") return "";
1549
1563
  if (value.length < 1) return value;
1564
+ const { capitalizeAny, capitalizeFirst, type } = this;
1550
1565
  const parts = words(value);
1551
1566
  const partsLength = parts.length;
1552
1567
  const result = [];
1553
1568
  for (let partIndex = 0; partIndex < partsLength; partIndex += 1) {
1554
- const items = parts[partIndex].replace(EXPRESSION_ACRONYM, (full, one, two, three) => three === "s" ? full : `${one}-${two}${three}`).replace(EXPRESSION_CAMEL_CASE, "$1-$2").split("-");
1569
+ const items = parts[partIndex].replace(EXPRESSION_ACRONYM, (full, one, two, three) => three === "s" ? full : `${one}-${two}${three}`).replace(EXPRESSION_CAMEL_CASE, REPLACEMENT_CAMEL_CASE).split("-");
1555
1570
  const itemsLength = items.length;
1556
1571
  const partResult = [];
1557
1572
  let itemCount = 0;
@@ -1562,17 +1577,42 @@ function toCase(value, delimiter, capitalizeAny, capitalizeFirst) {
1562
1577
  else partResult.push(capitalize(item));
1563
1578
  itemCount += 1;
1564
1579
  }
1565
- result.push(join(partResult, delimiter));
1580
+ result.push(join(partResult, delimiters[type]));
1566
1581
  }
1567
- return join(result, delimiter);
1582
+ return join(result, delimiters[type]);
1568
1583
  }
1569
1584
  const EXPRESSION_CAMEL_CASE = /(\p{Ll})(\p{Lu})/gu;
1570
1585
  const EXPRESSION_ACRONYM = /(\p{Lu}*)(\p{Lu})(\p{Ll}+)/gu;
1586
+ const REPLACEMENT_CAMEL_CASE = "$1-$2";
1587
+ const TYPE_CAMEL = "camel";
1588
+ const TYPE_KEBAB = "kebab";
1589
+ const TYPE_PASCAL = "pascal";
1590
+ const TYPE_SNAKE = "snake";
1591
+ const delimiters = {
1592
+ [TYPE_CAMEL]: "",
1593
+ [TYPE_KEBAB]: "-",
1594
+ [TYPE_PASCAL]: "",
1595
+ [TYPE_SNAKE]: "_"
1596
+ };
1597
+ const memoizers = {};
1598
+ let memoizedCapitalize;
1599
+ let memoizedTitleCase;
1571
1600
  function createUuid() {
1572
- return TEMPLATE_UUID.replace(EXPRESSION_UUID_PART, (substring) => {
1573
- const digit = Number.parseInt(substring, 10);
1574
- return (digit ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> digit / 4).toString(16);
1575
- });
1601
+ return getUuid();
1602
+ }
1603
+ function getUuid() {
1604
+ const bytes = new Uint8Array(16);
1605
+ crypto.getRandomValues(bytes);
1606
+ bytes[6] = bytes[6] & 15 | 64;
1607
+ bytes[8] = bytes[8] & 63 | 128;
1608
+ const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
1609
+ return [
1610
+ hex.substring(0, 8),
1611
+ hex.substring(8, 12),
1612
+ hex.substring(12, 16),
1613
+ hex.substring(16, 20),
1614
+ hex.substring(20, 32)
1615
+ ].join("-");
1576
1616
  }
1577
1617
  function parse(value, reviver) {
1578
1618
  try {
@@ -1582,14 +1622,14 @@ function parse(value, reviver) {
1582
1622
  }
1583
1623
  }
1584
1624
  function truncate(value, length, suffix) {
1585
- if (typeof value !== "string" || typeof length !== "number" || length <= 0) return "";
1625
+ if (typeof value !== "string" || typeof length !== "number" || length === 0) return "";
1586
1626
  if (length >= value.length) return value;
1587
1627
  const actualSuffix = typeof suffix === "string" ? suffix : "";
1588
- const truncatedLength = length - actualSuffix.length;
1628
+ const actualSuffixLength = actualSuffix.length;
1629
+ if (length <= actualSuffixLength) return actualSuffix;
1630
+ const truncatedLength = length - actualSuffixLength;
1589
1631
  return `${value.slice(0, truncatedLength)}${actualSuffix}`;
1590
1632
  }
1591
- const EXPRESSION_UUID_PART = /[018]/g;
1592
- const TEMPLATE_UUID = "10000000-1000-4000-8000-100000000000";
1593
1633
  function getValue(data, path, ignoreCase) {
1594
1634
  if (typeof data !== "object" || data === null || typeof path !== "string" || path.trim().length === 0) return;
1595
1635
  const shouldIgnoreCase = ignoreCase === true;
@@ -1601,24 +1641,43 @@ function getValue(data, path, ignoreCase) {
1601
1641
  while (index < length && value != null) value = handleValue(value, paths[index++], null, true, shouldIgnoreCase);
1602
1642
  return value;
1603
1643
  }
1604
- function template(value, variables, options) {
1644
+ function getTemplateOptions(input) {
1645
+ const options = isPlainObject(input) ? input : {};
1646
+ return {
1647
+ ignoreCase: options.ignoreCase === true,
1648
+ pattern: options.pattern instanceof RegExp ? options.pattern : EXPRESSION_VARIABLE
1649
+ };
1650
+ }
1651
+ function handleTemplate(value, pattern, ignoreCase, variables) {
1605
1652
  if (typeof value !== "string") return "";
1606
1653
  if (typeof variables !== "object" || variables === null) return value;
1607
- const hasOptions = typeof options === "object" && options != null;
1608
- const ignoreCase = hasOptions && options?.ignoreCase === true;
1609
- const pattern = hasOptions && options?.pattern instanceof RegExp ? options.pattern : EXPRESSION_VARIABLE;
1610
1654
  const values = {};
1611
1655
  return value.replace(pattern, (_, key) => {
1612
- if (values[key] != null) return values[key];
1613
- const templateValue = getValue(variables, key, ignoreCase);
1614
- values[key] = templateValue == null ? "" : getString(templateValue);
1656
+ if (values[key] == null) {
1657
+ const templateValue = getValue(variables, key, ignoreCase);
1658
+ values[key] = templateValue == null ? "" : getString(templateValue);
1659
+ }
1615
1660
  return values[key];
1616
1661
  });
1617
1662
  }
1663
+ const template = ((value, variables, options) => {
1664
+ const { ignoreCase, pattern } = getTemplateOptions(options);
1665
+ return handleTemplate(value, pattern, ignoreCase, variables);
1666
+ });
1667
+ template.initialize = (options) => {
1668
+ const { ignoreCase, pattern } = getTemplateOptions(options);
1669
+ return (value, variables) => {
1670
+ return handleTemplate(value, pattern, ignoreCase, variables);
1671
+ };
1672
+ };
1618
1673
  const EXPRESSION_VARIABLE = /{{([\s\S]+?)}}/g;
1619
- function equal(first, second, options) {
1674
+ const equal = ((first, second, options) => {
1620
1675
  return equalValue(first, second, getEqualOptions(options));
1621
- }
1676
+ });
1677
+ equal.initialize = (options) => {
1678
+ const actual = getEqualOptions(options);
1679
+ return (first, second) => equalValue(first, second, actual);
1680
+ };
1622
1681
  function equalArray(first, second, options) {
1623
1682
  const { length } = first;
1624
1683
  if (length !== second.length) return false;
@@ -1932,7 +1991,7 @@ function setChanges(parameters) {
1932
1991
  const diffsLength = diffs.length;
1933
1992
  for (let diffIndex = 0; diffIndex < diffsLength; diffIndex += 1) changes.push(diffs[diffIndex]);
1934
1993
  }
1935
- function getOptions(options) {
1994
+ function getMergeOptions(options) {
1936
1995
  const actual = {
1937
1996
  replaceableObjects: void 0,
1938
1997
  skipNullableInArrays: false
@@ -1946,10 +2005,16 @@ function getReplaceableObjects(value) {
1946
2005
  const items = (Array.isArray(value) ? value : [value]).filter((item) => typeof item === "string" || item instanceof RegExp);
1947
2006
  if (items.length > 0) return (name) => items.some((item) => typeof item === "string" ? item === name : item.test(name));
1948
2007
  }
1949
- function merge(values, options) {
1950
- if (!Array.isArray(values) || values.length === 0) return {};
1951
- return mergeValues(values, getOptions(options), true);
2008
+ function handleMerge(values, options) {
2009
+ return !Array.isArray(values) || values.length === 0 ? {} : mergeValues(values, options, true);
1952
2010
  }
2011
+ const merge = ((values, options) => {
2012
+ return handleMerge(values, getMergeOptions(options));
2013
+ });
2014
+ merge.initialize = (options) => {
2015
+ const actual = getMergeOptions(options);
2016
+ return (values) => handleMerge(values, actual);
2017
+ };
1953
2018
  function mergeObjects(values, options, prefix) {
1954
2019
  const { length } = values;
1955
2020
  const isArray = values.every(Array.isArray);
@@ -1980,7 +2045,7 @@ function partial(value, keys) {
1980
2045
  const result = {};
1981
2046
  for (let index = 0; index < length; index += 1) {
1982
2047
  const key = keys[index];
1983
- result[key] = value[key];
2048
+ if (key in value) result[key] = value[key];
1984
2049
  }
1985
2050
  return result;
1986
2051
  }
@@ -1993,11 +2058,17 @@ function flattenObject(value, depth, smushed, prefix) {
1993
2058
  for (let index = 0; index < length; index += 1) {
1994
2059
  const key = keys[index];
1995
2060
  const val = value[key];
1996
- if (isArrayOrPlainObject(val)) Object.assign(flattened, {
1997
- [join([prefix, key], ".")]: Array.isArray(val) ? [...val] : { ...val },
1998
- ...flattenObject(val, depth + 1, smushed, join([prefix, key], "."))
1999
- });
2000
- else flattened[join([prefix, key], ".")] = val;
2061
+ if (isArrayOrPlainObject(val)) {
2062
+ const prefixedKey = join([prefix, key], ".");
2063
+ flattened[prefixedKey] = Array.isArray(val) ? [...val] : { ...val };
2064
+ const nested = flattenObject(val, depth + 1, smushed, prefixedKey);
2065
+ const nestedKeys = Object.keys(nested);
2066
+ const nestedLength = nestedKeys.length;
2067
+ for (let nestedIndex = 0; nestedIndex < nestedLength; nestedIndex += 1) {
2068
+ const nestedKey = nestedKeys[nestedIndex];
2069
+ flattened[nestedKey] = nested[nestedKey];
2070
+ }
2071
+ } else flattened[join([prefix, key], ".")] = val;
2001
2072
  }
2002
2073
  smushed.set(value, flattened);
2003
2074
  return flattened;
@@ -2033,4 +2104,4 @@ function unsmush(value) {
2033
2104
  }
2034
2105
  return unsmushed;
2035
2106
  }
2036
- export { frame_rate_default as FRAME_RATE_MS, SizedMap, SizedSet, average, beacon, between, camelCase, capitalize, chunk, clamp, clone, compact, compare, count, createUuid, debounce, diff, equal, exists, filter, find, flatten, fromQuery, getArray, getColor, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getString, getValue, groupBy, hexToHsl, hexToHsla, hexToRgb, hexToRgba, hslToHex, hslToRgb, hslToRgba, indexOf, insert, isArrayOrPlainObject, isColor, isEmpty, isHexColor, isHslColor, isHslLike, isHslaColor, isKey, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isPlainObject, isPrimitive, isRgbColor, isRgbLike, isRgbaColor, isTypedArray, join, kebabCase, logger, max, memoize, merge, min, noop, parse, partial, pascalCase, push, rgbToHex, rgbToHsl, rgbToHsla, round, setValue, shuffle, smush, snakeCase, sort, splice, sum, template, throttle, titleCase, toMap, toQuery, toRecord, toSet, truncate, unique, unsmush, words };
2107
+ export { frame_rate_default as FRAME_RATE_MS, SizedMap, SizedSet, average, beacon, between, camelCase, capitalize, chunk, clamp, clone, compact, compare, count, createUuid, debounce, diff, equal, exists, filter, find, flatten, fromQuery, getArray, getColor, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getString, getUuid, getValue, groupBy, hexToHsl, hexToHsla, hexToRgb, hexToRgba, hslToHex, hslToRgb, hslToRgba, indexOf, insert, isArrayOrPlainObject, isColor, isEmpty, isHexColor, isHslColor, isHslLike, isHslaColor, isKey, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isPlainObject, isPrimitive, isRgbColor, isRgbLike, isRgbaColor, isTypedArray, join, kebabCase, logger, max, memoize, merge, min, noop, parse, partial, pascalCase, push, rgbToHex, rgbToHsl, rgbToHsla, round, setValue, shuffle, smush, snakeCase, sort, splice, sum, template, throttle, titleCase, toMap, toQuery, toRecord, toSet, truncate, unique, unsmush, words };
@@ -13,8 +13,12 @@ function getForegroundColor(value) {
13
13
  green / 255,
14
14
  red / 255
15
15
  ];
16
- for (let color of values) if (color <= .03928) color /= SRGB_LUMINANCE_MULTIPLIER;
17
- else color = ((color + SRGB_LUMINANCE_OFFSET) / SRGB_LUMINANCE_MODIFIER) ** SRGB_LUMINANCE_EXPONENT;
16
+ const { length } = values;
17
+ for (let index = 0; index < length; index += 1) {
18
+ const color = values[index];
19
+ if (color <= .03928) values[index] /= SRGB_LUMINANCE_MULTIPLIER;
20
+ else values[index] = ((color + SRGB_LUMINANCE_OFFSET) / SRGB_LUMINANCE_MODIFIER) ** SRGB_LUMINANCE_EXPONENT;
21
+ }
18
22
  return new Color(.2126 * values[2] + .7152 * values[1] + .0722 * values[0] > .625 ? HEX_BLACK : HEX_WHITE);
19
23
  }
20
24
  function getHexaColor(value) {