@oscarpalmer/atoms 0.180.0 → 0.182.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 (46) hide show
  1. package/dist/array/find.d.mts +42 -1
  2. package/dist/array/find.mjs +5 -1
  3. package/dist/array/get.mjs +2 -2
  4. package/dist/array/index.d.mts +3 -3
  5. package/dist/array/index.mjs +3 -3
  6. package/dist/index.d.mts +238 -25
  7. package/dist/index.mjs +242 -19
  8. package/dist/internal/array/find.d.mts +4 -3
  9. package/dist/internal/array/find.mjs +5 -2
  10. package/dist/internal/array/index-of.d.mts +42 -1
  11. package/dist/internal/array/index-of.mjs +5 -1
  12. package/dist/internal/math/aggregate.mjs +2 -2
  13. package/dist/internal/result.mjs +2 -2
  14. package/dist/internal/string.d.mts +5 -3
  15. package/dist/internal/string.mjs +14 -5
  16. package/dist/internal/value/equal.mjs +2 -2
  17. package/dist/internal/value/handlers.mjs +2 -2
  18. package/dist/kalas.d.mts +61 -0
  19. package/dist/kalas.mjs +93 -0
  20. package/dist/string/case.mjs +10 -4
  21. package/dist/string/normalize.d.mts +55 -0
  22. package/dist/string/normalize.mjs +93 -0
  23. package/dist/value/index.d.mts +2 -1
  24. package/dist/value/index.mjs +2 -1
  25. package/dist/value/merge.d.mts +13 -0
  26. package/dist/value/merge.mjs +3 -1
  27. package/dist/value/shake.d.mts +7 -0
  28. package/dist/value/shake.mjs +16 -0
  29. package/package.json +1 -1
  30. package/src/array/exists.ts +1 -1
  31. package/src/array/find.ts +58 -0
  32. package/src/array/get.ts +2 -2
  33. package/src/index.ts +3 -0
  34. package/src/internal/array/find.ts +24 -4
  35. package/src/internal/array/index-of.ts +59 -1
  36. package/src/internal/math/aggregate.ts +2 -2
  37. package/src/internal/result.ts +6 -3
  38. package/src/internal/string.ts +26 -8
  39. package/src/internal/value/equal.ts +2 -2
  40. package/src/internal/value/handlers.ts +2 -2
  41. package/src/kalas.ts +167 -0
  42. package/src/string/case.ts +20 -4
  43. package/src/string/normalize.ts +169 -0
  44. package/src/value/index.ts +1 -0
  45. package/src/value/merge.ts +17 -1
  46. package/src/value/shake.ts +36 -0
package/dist/index.mjs CHANGED
@@ -21,9 +21,12 @@ function findValue(type, array, parameters, reversed) {
21
21
  if (!Array.isArray(array) || array.length === 0) return findIndex ? -1 : void 0;
22
22
  const { bool, key, value } = getFindParameters(parameters);
23
23
  const callbacks = getArrayCallbacks(bool, key);
24
- if (callbacks?.bool == null && callbacks?.keyed == null) return findIndex ? array.indexOf(value) : array.find((item) => Object.is(item, value));
24
+ if (callbacks?.bool == null && callbacks?.keyed == null) {
25
+ if (findIndex) return reversed ? array.lastIndexOf(value) : array.indexOf(value);
26
+ return reversed ? array.findLast((item) => Object.is(item, value)) : array.find((item) => Object.is(item, value));
27
+ }
25
28
  if (callbacks.bool != null) {
26
- const index = array.findIndex(callbacks.bool);
29
+ const index = reversed ? array.findLastIndex(callbacks.bool) : array.findIndex(callbacks.bool);
27
30
  return findIndex ? index : array[index];
28
31
  }
29
32
  return findValueInArray(array, callbacks.keyed, value, findIndex, reversed);
@@ -177,6 +180,10 @@ function compact(array, strict) {
177
180
  function indexOf(array, ...parameters) {
178
181
  return findValue(FIND_VALUE_INDEX, array, parameters, false);
179
182
  }
183
+ indexOf.last = lastIndexOf;
184
+ function lastIndexOf(array, ...parameters) {
185
+ return findValue(FIND_VALUE_INDEX, array, parameters, true);
186
+ }
180
187
  //#endregion
181
188
  //#region src/internal/is.ts
182
189
  /**
@@ -426,6 +433,10 @@ function exists(array, ...parameters) {
426
433
  function find(array, ...parameters) {
427
434
  return findValue(FIND_VALUE_ITEM, array, parameters, false);
428
435
  }
436
+ find.last = findLast;
437
+ function findLast(array, ...parameters) {
438
+ return findValue(FIND_VALUE_ITEM, array, parameters, true);
439
+ }
429
440
  //#endregion
430
441
  //#region src/array/flatten.ts
431
442
  /**
@@ -460,7 +471,7 @@ function times(length, value) {
460
471
  function getArray(value, indiced) {
461
472
  if (Array.isArray(value)) return value;
462
473
  if (value instanceof Map || value instanceof Set) return [...value.values()];
463
- if (!isPlainObject(value)) return [value];
474
+ if (isNonPlainObject(value)) return [value];
464
475
  if (indiced !== true) return Object.values(value);
465
476
  const keys = Object.keys(value);
466
477
  const { length } = keys;
@@ -609,10 +620,10 @@ function select(array, ...parameters) {
609
620
  //#region src/array/single.ts
610
621
  function single(array, ...parameters) {
611
622
  const { matched } = findValues("all", array, parameters);
612
- if (matched.length > 1) throw new Error(MESSAGE);
623
+ if (matched.length > 1) throw new Error(MESSAGE$1);
613
624
  return matched[0];
614
625
  }
615
- const MESSAGE = "Multiple items were found";
626
+ const MESSAGE$1 = "Multiple items were found";
616
627
  //#endregion
617
628
  //#region src/array/slice.ts
618
629
  function drop(array, first, second) {
@@ -831,7 +842,7 @@ function aggregate(type, array, key) {
831
842
  for (let index = 0; index < length; index += 1) {
832
843
  const item = array[index];
833
844
  const value = callback == null ? item : callback(item, index, array);
834
- if (!isNumber(value)) continue;
845
+ if (isNonNumber(value)) continue;
835
846
  aggregated = aggregator(aggregated, value, notNumber);
836
847
  counted += 1;
837
848
  notNumber = false;
@@ -881,13 +892,23 @@ function ignoreKey(key) {
881
892
  return EXPRESSION_IGNORED.test(key);
882
893
  }
883
894
  /**
884
- * Join an array of values into a string
885
- * @param value Array of values
895
+ * Join an array of values into a string _(while ignoring empty values)_
896
+ *
897
+ * _(`null`, `undefined`, and any values that become whitespace-only strings are considered empty)_
898
+ * @param array Array of values
886
899
  * @param delimiter Delimiter to use between values
887
900
  * @returns Joined string
888
901
  */
889
- function join(value, delimiter) {
890
- return compact(value).map(getString).join(typeof delimiter === "string" ? delimiter : "");
902
+ function join(array, delimiter) {
903
+ if (!Array.isArray(array)) return "";
904
+ const { length } = array;
905
+ if (length === 0) return "";
906
+ const values = [];
907
+ for (let index = 0; index < length; index += 1) {
908
+ const item = getString(array[index]);
909
+ if (item.trim().length > 0) values.push(item);
910
+ }
911
+ return values.join(typeof delimiter === "string" ? delimiter : "");
891
912
  }
892
913
  function tryCallback(value, callback) {
893
914
  try {
@@ -940,7 +961,7 @@ function getHandlers(owner, options) {
940
961
  if (isConstructable(first) && isConstructable(second) && first.constructor === second.constructor) return handlers.get(first.constructor);
941
962
  },
942
963
  register(constructor, handler) {
943
- if (!isConstructor(constructor) || handler === owner) return;
964
+ if (isNonConstructor(constructor) || handler === owner) return;
944
965
  let actual = handler ?? options.method;
945
966
  if (typeof actual !== "function" && typeof actual !== "string") return;
946
967
  if (typeof actual === "string") actual = typeof constructor.prototype[actual] === "function" ? actual : void 0;
@@ -1890,7 +1911,7 @@ const MESSAGE_FAILED = "Retry failed";
1890
1911
  //#endregion
1891
1912
  //#region src/internal/result.ts
1892
1913
  function _isResult(value, okValue) {
1893
- if (!isPlainObject(value)) return false;
1914
+ if (isNonPlainObject(value)) return false;
1894
1915
  return value.ok === okValue && (okValue ? PROPERTY_VALUE : PROPERTY_ERROR) in value;
1895
1916
  }
1896
1917
  function isError(value, extended) {
@@ -2106,7 +2127,7 @@ function getEqualOptions(input) {
2106
2127
  options.ignoreCase = input;
2107
2128
  return options;
2108
2129
  }
2109
- if (!isPlainObject(input)) return options;
2130
+ if (isNonPlainObject(input)) return options;
2110
2131
  options.ignoreCase = typeof input.ignoreCase === "boolean" ? input.ignoreCase : false;
2111
2132
  options.ignoreExpressions.values = (Array.isArray(input.ignoreKeys) ? input.ignoreKeys : [input.ignoreKeys]).filter((key) => key instanceof RegExp);
2112
2133
  options.ignoreKeys.values = new Set((Array.isArray(input.ignoreKeys) ? input.ignoreKeys : [input.ignoreKeys]).filter((key) => typeof key === "string"));
@@ -2268,6 +2289,97 @@ function setValue(data, path, value, ignoreCase) {
2268
2289
  }
2269
2290
  const EXPRESSION_INDEX = /^\d+$/;
2270
2291
  //#endregion
2292
+ //#region src/kalas.ts
2293
+ var Events = class {
2294
+ #kalas;
2295
+ constructor(kalas) {
2296
+ this.#kalas = kalas;
2297
+ }
2298
+ /**
2299
+ * Subscribe to an event with a callback
2300
+ * @param event Event name
2301
+ * @param callback Callback function
2302
+ * @returns Unsubscriber function
2303
+ */
2304
+ subscribe(event, callback) {
2305
+ return this.#kalas.subscribe(event, callback);
2306
+ }
2307
+ /**
2308
+ * Unsubscribe from an event with a callback _(or all callbacks, if no callback is provided)_
2309
+ * @param event Event name
2310
+ * @param callback Callback function
2311
+ * @returns Unsubscriber function
2312
+ */
2313
+ unsubscribe(event, callback) {
2314
+ return this.#kalas.unsubscribe(event, callback);
2315
+ }
2316
+ };
2317
+ var Kalas = class {
2318
+ #names;
2319
+ #subscribers = /* @__PURE__ */ new Map();
2320
+ constructor(names) {
2321
+ this.#names = new Set(names);
2322
+ Object.defineProperty(this, "events", { value: new Events(this) });
2323
+ }
2324
+ /**
2325
+ * Remove all event subscribers
2326
+ */
2327
+ clear() {
2328
+ this.#subscribers.clear();
2329
+ }
2330
+ /**
2331
+ * Emit an event with parameters
2332
+ * @param event Event name
2333
+ * @param parameters Event parameters
2334
+ */
2335
+ emit(event, ...parameters) {
2336
+ const subscribers = this.#subscribers.get(event);
2337
+ if (subscribers == null) return;
2338
+ for (const callback of subscribers) callback(...parameters);
2339
+ }
2340
+ /**
2341
+ * Subscribe to an event with a callback
2342
+ * @param event Event name
2343
+ * @param callback Callback function
2344
+ * @returns Unsubscriber function
2345
+ */
2346
+ subscribe(event, callback) {
2347
+ if (!this.#names.has(event) || typeof callback !== "function") return noop;
2348
+ let subscribers = this.#subscribers.get(event);
2349
+ if (subscribers == null) {
2350
+ subscribers = /* @__PURE__ */ new Set();
2351
+ this.#subscribers.set(event, subscribers);
2352
+ }
2353
+ subscribers.add(callback);
2354
+ return () => {
2355
+ subscribers?.delete(callback);
2356
+ };
2357
+ }
2358
+ /**
2359
+ * Unsubscribe from an event with a callback _(or all callbacks, if no callback is provided)_
2360
+ * @param event Event name
2361
+ * @param callback Callback function
2362
+ */
2363
+ unsubscribe(event, callback) {
2364
+ if (!this.#names.has(event) || (callback != null ? typeof callback !== "function" : false)) return;
2365
+ const subscribers = this.#subscribers.get(event);
2366
+ if (subscribers == null) return;
2367
+ if (callback == null) subscribers.clear();
2368
+ else subscribers.delete(callback);
2369
+ if (callback == null || subscribers.size === 0) this.#subscribers.delete(event);
2370
+ }
2371
+ };
2372
+ /**
2373
+ * Create a Kalas _(party)_ for named events
2374
+ * @param names Event names
2375
+ * @returns Kalas instance
2376
+ */
2377
+ function kalas(names) {
2378
+ if (!Array.isArray(names) || names.length === 0 || !names.every((name) => typeof name === "string")) throw new Error(MESSAGE);
2379
+ return new Kalas(names);
2380
+ }
2381
+ const MESSAGE = "Kalas requires an array of event names.";
2382
+ //#endregion
2271
2383
  //#region src/string/case.ts
2272
2384
  /**
2273
2385
  * Convert a string to camel case _(thisIsCamelCase)_
@@ -2301,7 +2413,9 @@ function kebabCase(value) {
2301
2413
  * @returns Lower-cased string
2302
2414
  */
2303
2415
  function lowerCase(value) {
2304
- return typeof value === "string" ? value.toLocaleLowerCase() : "";
2416
+ if (typeof value !== "string") return "";
2417
+ memoizedLowerCase ??= memoize((v) => v.toLocaleLowerCase());
2418
+ return memoizedLowerCase.run(value);
2305
2419
  }
2306
2420
  /**
2307
2421
  * Convert a string to pascal case _(ThisIsPascalCase)_
@@ -2325,8 +2439,8 @@ function snakeCase(value) {
2325
2439
  * @returns Title-cased string
2326
2440
  */
2327
2441
  function titleCase(value) {
2328
- if (typeof value !== "string") return "";
2329
- memoizedTitleCase ??= memoize((v) => v.length < 1 ? capitalize(v) : join(words(v).map(capitalize), " "));
2442
+ if (typeof value !== "string" || value.length === 0) return "";
2443
+ memoizedTitleCase ??= memoize((v) => v.length < 2 ? capitalize(v) : join(words(v).map(capitalize), " "));
2330
2444
  return memoizedTitleCase.run(value);
2331
2445
  }
2332
2446
  function toCase(type, value, capitalizeAny, capitalizeFirst) {
@@ -2366,7 +2480,9 @@ function toCaseCallback(value) {
2366
2480
  * @returns Upper-cased string
2367
2481
  */
2368
2482
  function upperCase(value) {
2369
- return typeof value === "string" ? value.toLocaleUpperCase() : "";
2483
+ if (typeof value !== "string" || value.length === 0) return "";
2484
+ memoizedUpperCase ??= memoize((v) => v.toLocaleUpperCase());
2485
+ return memoizedUpperCase.run(value);
2370
2486
  }
2371
2487
  const CASE_CAMEL = "camel";
2372
2488
  const CASE_KEBAB = "kebab";
@@ -2387,7 +2503,9 @@ const delimiters = {
2387
2503
  [CASE_SNAKE]: DELIMITER_UNDERSCORE
2388
2504
  };
2389
2505
  let memoizedCapitalize;
2506
+ let memoizedLowerCase;
2390
2507
  let memoizedTitleCase;
2508
+ let memoizedUpperCase;
2391
2509
  //#endregion
2392
2510
  //#region src/is.ts
2393
2511
  /**
@@ -2801,6 +2919,95 @@ function truncate(value, length, suffix) {
2801
2919
  }
2802
2920
  const ZERO = "0";
2803
2921
  //#endregion
2922
+ //#region src/string/normalize.ts
2923
+ /**
2924
+ * Deburr a string, removing diacritical marks
2925
+ * @param value String to deburr
2926
+ * @returns Deburred string
2927
+ */
2928
+ function deburr(value) {
2929
+ if (typeof value !== "string") return "";
2930
+ deburrMemoizer ??= memoize((value) => {
2931
+ let deburred = value.normalize(DEBURR_NORMALIZATION).replace(DEBURR_PATTERN_SIMPLE, "");
2932
+ deburred = deburred.replace(DEBURR_PATTERN_CHARACTERS, (_, character) => DEBURR_CHARACTERS[character]);
2933
+ return deburred;
2934
+ });
2935
+ return deburrMemoizer.run(value);
2936
+ }
2937
+ function getNormalizeOptions(input) {
2938
+ const options = isPlainObject(input) ? input : {};
2939
+ return {
2940
+ deburr: options.deburr !== false,
2941
+ lowerCase: options.lowerCase !== false,
2942
+ trim: options.trim !== false
2943
+ };
2944
+ }
2945
+ /**
2946
+ * Initialize a string normalizer
2947
+ * @param options Normalization options
2948
+ * @returns Normalizer function
2949
+ */
2950
+ function initializeNormalizer(options) {
2951
+ const normalization = getNormalizeOptions(options);
2952
+ return (value) => normalizeString(value, normalization);
2953
+ }
2954
+ /**
2955
+ * Normalize a string
2956
+ *
2957
+ * By default, the string will be trimmed, deburred, and then lowercased
2958
+ * @param value String to normalize
2959
+ * @param options Normalization options
2960
+ * @returns Normalized string
2961
+ */
2962
+ function normalize(value, options) {
2963
+ return normalizeString(value, getNormalizeOptions(options));
2964
+ }
2965
+ normalize.initialize = initializeNormalizer;
2966
+ function normalizeString(value, options) {
2967
+ if (typeof value !== "string") return "";
2968
+ let result = value;
2969
+ if (options.trim) result = result.trim();
2970
+ if (options.deburr) result = deburr(result);
2971
+ if (options.lowerCase) result = lowerCase(result);
2972
+ return result;
2973
+ }
2974
+ const DEBURR_CHARACTERS = {
2975
+ Æ: "AE",
2976
+ æ: "ae",
2977
+ Ð: "D",
2978
+ ð: "d",
2979
+ Đ: "D",
2980
+ đ: "d",
2981
+ Ħ: "H",
2982
+ ħ: "h",
2983
+ IJ: "IJ",
2984
+ ij: "ij",
2985
+ İ: "I",
2986
+ ı: "i",
2987
+ ĸ: "k",
2988
+ Ŀ: "L",
2989
+ ŀ: "l",
2990
+ Ł: "L",
2991
+ ł: "l",
2992
+ Ŋ: "N",
2993
+ ŋ: "n",
2994
+ ʼn: "'n",
2995
+ Œ: "OE",
2996
+ œ: "oe",
2997
+ Ø: "O",
2998
+ ø: "o",
2999
+ ſ: "s",
3000
+ ß: "ss",
3001
+ Þ: "TH",
3002
+ þ: "th",
3003
+ Ŧ: "T",
3004
+ ŧ: "t"
3005
+ };
3006
+ const DEBURR_NORMALIZATION = "NFD";
3007
+ const DEBURR_PATTERN_CHARACTERS = new RegExp(`(${Object.keys(DEBURR_CHARACTERS).join("|")})`, "g");
3008
+ const DEBURR_PATTERN_SIMPLE = /[\u0300-\u036f]/g;
3009
+ let deburrMemoizer;
3010
+ //#endregion
2804
3011
  //#region src/string/template.ts
2805
3012
  function getTemplateOptions(input) {
2806
3013
  const options = isPlainObject(input) ? input : {};
@@ -3134,6 +3341,20 @@ function pick(value, keys) {
3134
3341
  return partial(value, keys, false);
3135
3342
  }
3136
3343
  //#endregion
3344
+ //#region src/value/shake.ts
3345
+ function shake(value) {
3346
+ const shaken = {};
3347
+ if (isNonPlainObject(value)) return shaken;
3348
+ const keys = Object.keys(value);
3349
+ const { length } = keys;
3350
+ for (let index = 0; index < length; index += 1) {
3351
+ const key = keys[index];
3352
+ const val = value[key];
3353
+ if (val !== void 0) shaken[key] = val;
3354
+ }
3355
+ return shaken;
3356
+ }
3357
+ //#endregion
3137
3358
  //#region src/value/smush.ts
3138
3359
  function flattenObject(value, depth, smushed, prefix) {
3139
3360
  if (depth >= MAX_DEPTH) return {};
@@ -3206,12 +3427,14 @@ function unsmush(value) {
3206
3427
  //#region src/value/merge.ts
3207
3428
  function getMergeOptions(options) {
3208
3429
  const actual = {
3430
+ assignValues: false,
3209
3431
  replaceableObjects: void 0,
3210
3432
  skipNullableAny: false,
3211
3433
  skipNullableInArrays: false
3212
3434
  };
3213
3435
  if (typeof options !== "object" || options == null) return actual;
3214
3436
  actual.replaceableObjects = getReplaceableObjects(options.replaceableObjects);
3437
+ actual.assignValues = options.assignValues === true;
3215
3438
  actual.skipNullableAny = options.skipNullableAny === true;
3216
3439
  actual.skipNullableInArrays = options.skipNullableInArrays === true;
3217
3440
  return actual;
@@ -3241,7 +3464,7 @@ merge.initialize = initializeMerger;
3241
3464
  function mergeObjects(values, options, prefix) {
3242
3465
  const { length } = values;
3243
3466
  const isArray = values.every(Array.isArray);
3244
- const merged = isArray ? [] : {};
3467
+ const merged = options.assignValues ? values[0] : isArray ? [] : {};
3245
3468
  for (let outerIndex = 0; outerIndex < length; outerIndex += 1) {
3246
3469
  const item = values[outerIndex];
3247
3470
  const keys = Object.keys(item);
@@ -5017,4 +5240,4 @@ var SizedSet = class extends Set {
5017
5240
  }
5018
5241
  };
5019
5242
  //#endregion
5020
- export { CancelablePromise, PROMISE_ABORT_EVENT, PROMISE_ABORT_OPTIONS, PROMISE_ERROR_NAME, PROMISE_MESSAGE_EXPECTATION_ATTEMPT, PROMISE_MESSAGE_EXPECTATION_RESULT, PROMISE_MESSAGE_EXPECTATION_TIMED, PROMISE_MESSAGE_TIMEOUT, PROMISE_STRATEGY_ALL, PROMISE_STRATEGY_DEFAULT, PROMISE_TYPE_FULFILLED, PROMISE_TYPE_REJECTED, PromiseTimeoutError, QueueError, RetryError, SORT_DIRECTION_ASCENDING, SORT_DIRECTION_DESCENDING, SizedMap, SizedSet, assert, assertCondition, assertDefined, assertInstanceOf, assertIs, asyncAttempt, asyncDebounce, asyncFlow, asyncMatchResult, asyncOnce, asyncPipe, asyncThrottle, attempt, attemptAsyncFlow, attemptAsyncPipe, attemptFlow, attemptPipe, attemptPromise, average, beacon, between, camelCase, cancelable, capitalize, ceil, chunk, clamp, clone, compact, compare, count, debounce, dedent, delay, deregisterCloner, deregisterComparator, deregisterEqualizer, diff, difference, drop, endsWith, endsWithArray, equal, error, exclude, exists, filter, find, first, firstOrDefault, flatten, floor, flow, fromQuery, toPromise as fromResult, toPromise, fuzzy, fuzzyMatch, getArray, getArrayPosition, getColor, getError, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getSortedIndex, getString, getTimedPromise, getUuid, getValue, groupArraysBy, groupBy, handleResult, hasValue, hexToHsl, hexToHsla, hexToRgb, hexToRgba, hslToHex, hslToRgb, hslToRgba, ignoreKey, inMap, inSet, includes, includesArray, indexOf, indexOfArray, initializeEqualizer, initializeMerger, initializeSorter, initializeTemplater, insert, intersection, isArrayOrPlainObject, isColor, isConstructor, isEmpty, isError, isFulfilled, isHexColor, isHslColor, isHslLike, isHslaColor, isInstanceOf, isKey, isNonArrayOrPlainObject, isNonConstructor, isNonEmpty, isNonInstanceOf, isNonKey, isNonNullable, isNonNullableOrEmpty, isNonNullableOrWhitespace, isNonNumber, isNonNumerical, isNonObject, isNonPlainObject, isNonPrimitive, isNonTypedArray, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isOk, isPlainObject, isPrimitive, isRejected, isResult, isRgbColor, isRgbLike, isRgbaColor, isSorted, isTypedArray, join, kebabCase, last, lastOrDefault, logger, lowerCase, matchResult, max, median, memoize, merge, min, move, moveIndices, moveToIndex, noop, ok, omit, once, parse, partition, pascalCase, pick, pipe, promises, push, queue, range, registerCloner, registerComparator, registerEqualizer, resultPromises, retry, reverse, rgbToHex, rgbToHsl, rgbToHsla, round, select, setValue, settlePromise, shuffle, single, slice, smush, snakeCase, sort, splice, startsWith, startsWithArray, sum, swap, take, template, throttle, timed, times, titleCase, toMap, toMapArrays, toQuery, toRecord, toRecordArrays, toResult, toSet, toggle, trim, truncate, tryDecode, tryEncode, union, unique, unsmush, unwrap, update, upperCase, words };
5243
+ export { CancelablePromise, PROMISE_ABORT_EVENT, PROMISE_ABORT_OPTIONS, PROMISE_ERROR_NAME, PROMISE_MESSAGE_EXPECTATION_ATTEMPT, PROMISE_MESSAGE_EXPECTATION_RESULT, PROMISE_MESSAGE_EXPECTATION_TIMED, PROMISE_MESSAGE_TIMEOUT, PROMISE_STRATEGY_ALL, PROMISE_STRATEGY_DEFAULT, PROMISE_TYPE_FULFILLED, PROMISE_TYPE_REJECTED, PromiseTimeoutError, QueueError, RetryError, SORT_DIRECTION_ASCENDING, SORT_DIRECTION_DESCENDING, SizedMap, SizedSet, assert, assertCondition, assertDefined, assertInstanceOf, assertIs, asyncAttempt, asyncDebounce, asyncFlow, asyncMatchResult, asyncOnce, asyncPipe, asyncThrottle, attempt, attemptAsyncFlow, attemptAsyncPipe, attemptFlow, attemptPipe, attemptPromise, average, beacon, between, camelCase, cancelable, capitalize, ceil, chunk, clamp, clone, compact, compare, count, debounce, deburr, dedent, delay, deregisterCloner, deregisterComparator, deregisterEqualizer, diff, difference, drop, endsWith, endsWithArray, equal, error, exclude, exists, filter, find, findLast, first, firstOrDefault, flatten, floor, flow, fromQuery, toPromise as fromResult, toPromise, fuzzy, fuzzyMatch, getArray, getArrayPosition, getColor, getError, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getSortedIndex, getString, getTimedPromise, getUuid, getValue, groupArraysBy, groupBy, handleResult, hasValue, hexToHsl, hexToHsla, hexToRgb, hexToRgba, hslToHex, hslToRgb, hslToRgba, ignoreKey, inMap, inSet, includes, includesArray, indexOf, indexOfArray, initializeEqualizer, initializeMerger, initializeNormalizer, initializeSorter, initializeTemplater, insert, intersection, isArrayOrPlainObject, isColor, isConstructor, isEmpty, isError, isFulfilled, isHexColor, isHslColor, isHslLike, isHslaColor, isInstanceOf, isKey, isNonArrayOrPlainObject, isNonConstructor, isNonEmpty, isNonInstanceOf, isNonKey, isNonNullable, isNonNullableOrEmpty, isNonNullableOrWhitespace, isNonNumber, isNonNumerical, isNonObject, isNonPlainObject, isNonPrimitive, isNonTypedArray, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isOk, isPlainObject, isPrimitive, isRejected, isResult, isRgbColor, isRgbLike, isRgbaColor, isSorted, isTypedArray, join, kalas, kebabCase, last, lastIndexOf, lastOrDefault, logger, lowerCase, matchResult, max, median, memoize, merge, min, move, moveIndices, moveToIndex, noop, normalize, ok, omit, once, parse, partition, pascalCase, pick, pipe, promises, push, queue, range, registerCloner, registerComparator, registerEqualizer, resultPromises, retry, reverse, rgbToHex, rgbToHsl, rgbToHsla, round, select, setValue, settlePromise, shake, shuffle, single, slice, smush, snakeCase, sort, splice, startsWith, startsWithArray, sum, swap, take, template, throttle, timed, times, titleCase, toMap, toMapArrays, toQuery, toRecord, toRecordArrays, toResult, toSet, toggle, trim, truncate, tryDecode, tryEncode, union, unique, unsmush, unwrap, update, upperCase, words };
@@ -10,12 +10,13 @@ type Parameters = {
10
10
  key?: unknown;
11
11
  value?: unknown;
12
12
  };
13
- declare function findValue(type: FindValueType, array: unknown[], parameters: unknown[], reversed: boolean): unknown;
13
+ declare function findValue(type: Exclude<FindValueType, 'item'>, array: unknown[], parameters: unknown[], reversed: boolean): number;
14
+ declare function findValue(type: Exclude<FindValueType, 'index'>, array: unknown[], parameters: unknown[], reversed: boolean): unknown;
14
15
  declare function findAbsoluteValueOrDefault(array: unknown[], parameters: unknown[], defaultValue: unknown, useDefaultValue: boolean, reversed: boolean): unknown;
15
16
  declare function findValues(type: FindValuesType, array: unknown[], parameters: unknown[], mapper?: unknown): FindValuesResult;
16
17
  declare function getFindParameters(original: unknown[]): Parameters;
17
- declare const FIND_VALUE_INDEX: FindValueType;
18
- declare const FIND_VALUE_ITEM: FindValueType;
18
+ declare const FIND_VALUE_INDEX = "index";
19
+ declare const FIND_VALUE_ITEM = "item";
19
20
  declare const FIND_VALUES_ALL: FindValuesType;
20
21
  declare const FIND_VALUES_UNIQUE: FindValuesType;
21
22
  //#endregion
@@ -5,9 +5,12 @@ function findValue(type, array, parameters, reversed) {
5
5
  if (!Array.isArray(array) || array.length === 0) return findIndex ? -1 : void 0;
6
6
  const { bool, key, value } = getFindParameters(parameters);
7
7
  const callbacks = getArrayCallbacks(bool, key);
8
- if (callbacks?.bool == null && callbacks?.keyed == null) return findIndex ? array.indexOf(value) : array.find((item) => Object.is(item, value));
8
+ if (callbacks?.bool == null && callbacks?.keyed == null) {
9
+ if (findIndex) return reversed ? array.lastIndexOf(value) : array.indexOf(value);
10
+ return reversed ? array.findLast((item) => Object.is(item, value)) : array.find((item) => Object.is(item, value));
11
+ }
9
12
  if (callbacks.bool != null) {
10
- const index = array.findIndex(callbacks.bool);
13
+ const index = reversed ? array.findLastIndex(callbacks.bool) : array.findIndex(callbacks.bool);
11
14
  return findIndex ? index : array[index];
12
15
  }
13
16
  return findValueInArray(array, callbacks.keyed, value, findIndex, reversed);
@@ -31,5 +31,46 @@ declare function indexOf<Item>(array: Item[], filter: (item: Item, index: number
31
31
  * @returns Index of the first matching item, or `-1` if no match is found
32
32
  */
33
33
  declare function indexOf<Item>(array: Item[], item: Item): number;
34
+ declare namespace indexOf {
35
+ var last: typeof lastIndexOf;
36
+ }
37
+ /**
38
+ * Get the index of the last matching item by callback
39
+ *
40
+ * Available as `lastIndexOf` and `indexOf.last`
41
+ * @param array Array to search in
42
+ * @param callback Callback to get an item's value
43
+ * @param value Value to match against
44
+ * @returns Index of the last matching item, or `-1` if no match is found
45
+ */
46
+ declare function lastIndexOf<Item, Callback extends (item: Item, index: number, array: Item[]) => unknown>(array: Item[], callback: Callback, value: ReturnType<Callback>): number;
47
+ /**
48
+ * Get the index of the last matching item by key
49
+ *
50
+ * Available as `lastIndexOf` and `indexOf.last`
51
+ * @param array Array to search in
52
+ * @param key Key to match items by
53
+ * @param value Value to match against
54
+ * @returns Index of the last matching item, or `-1` if no match is found
55
+ */
56
+ declare function lastIndexOf<Item extends PlainObject, ItemKey extends keyof Item>(array: Item[], key: ItemKey, value: Item[ItemKey]): number;
57
+ /**
58
+ * Get the index of the last item matching the filter
59
+ *
60
+ * Available as `lastIndexOf` and `indexOf.last`
61
+ * @param array Array to search in
62
+ * @param filter Filter callback to match items
63
+ * @returns Index of the last matching item, or `-1` if no match is found
64
+ */
65
+ declare function lastIndexOf<Item>(array: Item[], filter: (item: Item, index: number, array: Item[]) => boolean): number;
66
+ /**
67
+ * Get the index of the last item matching the given item
68
+ *
69
+ * Available as `lastIndexOf` and `indexOf.last`
70
+ * @param array Array to search in
71
+ * @param item Item to match against
72
+ * @returns Index of the last matching item, or `-1` if no match is found
73
+ */
74
+ declare function lastIndexOf<Item>(array: Item[], item: Item): number;
34
75
  //#endregion
35
- export { indexOf };
76
+ export { indexOf, lastIndexOf };
@@ -3,5 +3,9 @@ import { FIND_VALUE_INDEX, findValue } from "./find.mjs";
3
3
  function indexOf(array, ...parameters) {
4
4
  return findValue(FIND_VALUE_INDEX, array, parameters, false);
5
5
  }
6
+ indexOf.last = lastIndexOf;
7
+ function lastIndexOf(array, ...parameters) {
8
+ return findValue(FIND_VALUE_INDEX, array, parameters, true);
9
+ }
6
10
  //#endregion
7
- export { indexOf };
11
+ export { indexOf, lastIndexOf };
@@ -1,4 +1,4 @@
1
- import { isNumber } from "../is.mjs";
1
+ import { isNonNumber } from "../is.mjs";
2
2
  //#region src/internal/math/aggregate.ts
3
3
  function aggregate(type, array, key) {
4
4
  const length = Array.isArray(array) ? array.length : 0;
@@ -14,7 +14,7 @@ function aggregate(type, array, key) {
14
14
  for (let index = 0; index < length; index += 1) {
15
15
  const item = array[index];
16
16
  const value = callback == null ? item : callback(item, index, array);
17
- if (!isNumber(value)) continue;
17
+ if (isNonNumber(value)) continue;
18
18
  aggregated = aggregator(aggregated, value, notNumber);
19
19
  counted += 1;
20
20
  notNumber = false;
@@ -1,7 +1,7 @@
1
- import { isPlainObject } from "./is.mjs";
1
+ import { isNonPlainObject } from "./is.mjs";
2
2
  //#region src/internal/result.ts
3
3
  function _isResult(value, okValue) {
4
- if (!isPlainObject(value)) return false;
4
+ if (isNonPlainObject(value)) return false;
5
5
  return value.ok === okValue && (okValue ? PROPERTY_VALUE : PROPERTY_ERROR) in value;
6
6
  }
7
7
  function isError(value, extended) {
@@ -7,12 +7,14 @@
7
7
  declare function getString(value: unknown): string;
8
8
  declare function ignoreKey(key: string): boolean;
9
9
  /**
10
- * Join an array of values into a string
11
- * @param value Array of values
10
+ * Join an array of values into a string _(while ignoring empty values)_
11
+ *
12
+ * _(`null`, `undefined`, and any values that become whitespace-only strings are considered empty)_
13
+ * @param array Array of values
12
14
  * @param delimiter Delimiter to use between values
13
15
  * @returns Joined string
14
16
  */
15
- declare function join(value: unknown[], delimiter?: string): string;
17
+ declare function join(array: unknown[], delimiter?: string): string;
16
18
  declare function tryDecode(value: string): string;
17
19
  declare function tryEncode(value: boolean | number | string): unknown;
18
20
  /**
@@ -1,4 +1,3 @@
1
- import { compact } from "./array/compact.mjs";
2
1
  //#region src/internal/string.ts
3
2
  /**
4
3
  * Get the string value from any value
@@ -17,13 +16,23 @@ function ignoreKey(key) {
17
16
  return EXPRESSION_IGNORED.test(key);
18
17
  }
19
18
  /**
20
- * Join an array of values into a string
21
- * @param value Array of values
19
+ * Join an array of values into a string _(while ignoring empty values)_
20
+ *
21
+ * _(`null`, `undefined`, and any values that become whitespace-only strings are considered empty)_
22
+ * @param array Array of values
22
23
  * @param delimiter Delimiter to use between values
23
24
  * @returns Joined string
24
25
  */
25
- function join(value, delimiter) {
26
- return compact(value).map(getString).join(typeof delimiter === "string" ? delimiter : "");
26
+ function join(array, delimiter) {
27
+ if (!Array.isArray(array)) return "";
28
+ const { length } = array;
29
+ if (length === 0) return "";
30
+ const values = [];
31
+ for (let index = 0; index < length; index += 1) {
32
+ const item = getString(array[index]);
33
+ if (item.trim().length > 0) values.push(item);
34
+ }
35
+ return values.join(typeof delimiter === "string" ? delimiter : "");
27
36
  }
28
37
  function tryCallback(value, callback) {
29
38
  try {
@@ -1,4 +1,4 @@
1
- import { isPlainObject, isPrimitive, isTypedArray } from "../is.mjs";
1
+ import { isNonPlainObject, isPlainObject, isPrimitive, isTypedArray } from "../is.mjs";
2
2
  import { getCompareHandlers } from "./handlers.mjs";
3
3
  //#region src/internal/value/equal.ts
4
4
  /**
@@ -131,7 +131,7 @@ function getEqualOptions(input) {
131
131
  options.ignoreCase = input;
132
132
  return options;
133
133
  }
134
- if (!isPlainObject(input)) return options;
134
+ if (isNonPlainObject(input)) return options;
135
135
  options.ignoreCase = typeof input.ignoreCase === "boolean" ? input.ignoreCase : false;
136
136
  options.ignoreExpressions.values = (Array.isArray(input.ignoreKeys) ? input.ignoreKeys : [input.ignoreKeys]).filter((key) => key instanceof RegExp);
137
137
  options.ignoreKeys.values = new Set((Array.isArray(input.ignoreKeys) ? input.ignoreKeys : [input.ignoreKeys]).filter((key) => typeof key === "string"));
@@ -1,4 +1,4 @@
1
- import { isConstructor } from "../is.mjs";
1
+ import { isNonConstructor } from "../is.mjs";
2
2
  //#region src/internal/value/handlers.ts
3
3
  function getCompareHandlers(owner, options) {
4
4
  const handlers = getHandlers(owner, options);
@@ -26,7 +26,7 @@ function getHandlers(owner, options) {
26
26
  if (isConstructable(first) && isConstructable(second) && first.constructor === second.constructor) return handlers.get(first.constructor);
27
27
  },
28
28
  register(constructor, handler) {
29
- if (!isConstructor(constructor) || handler === owner) return;
29
+ if (isNonConstructor(constructor) || handler === owner) return;
30
30
  let actual = handler ?? options.method;
31
31
  if (typeof actual !== "function" && typeof actual !== "string") return;
32
32
  if (typeof actual === "string") actual = typeof constructor.prototype[actual] === "function" ? actual : void 0;