nhb-toolbox 4.28.21 → 4.28.24

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/CHANGELOG.md CHANGED
@@ -6,6 +6,11 @@ All notable changes to the package will be documented here.
6
6
 
7
7
  ---
8
8
 
9
+ ## [4.28.24] - 2025-12-11
10
+
11
+ - **Updated** *type names* `VoidFunction` to `VoidFn`. `DelayedFn<T>` is used for both *debounced* and *throttled* functions.
12
+ - **Added** *new* `Chronos` *business plugin methods* `weekendsBetween`, `weekendsInMonth` and `weekendsInYear`.
13
+
9
14
  ## [4.28.21] - 2025-12-07
10
15
 
11
16
  - **Added** *missing exports* for `getTimeZoneIds` and `getNativeTimeZoneId` *utilities*.
@@ -1,14 +1,71 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.naturalSort = naturalSort;
3
4
  exports.sortAnArray = sortAnArray;
4
5
  const non_primitives_1 = require("../guards/non-primitives");
5
6
  const primitives_1 = require("../guards/primitives");
6
- const utils_1 = require("./utils");
7
+ function naturalSort(a, b, options) {
8
+ const { caseInsensitive = true, localeAware = false } = options || {};
9
+ const _createChunks = (str) => {
10
+ const chunks = [];
11
+ let current = '';
12
+ let isNumeric = false;
13
+ for (const char of str) {
14
+ const charIsNum = !Number.isNaN(Number(char));
15
+ if (current?.length === 0) {
16
+ current = char;
17
+ isNumeric = charIsNum;
18
+ continue;
19
+ }
20
+ if (charIsNum === isNumeric) {
21
+ current += char;
22
+ }
23
+ else {
24
+ chunks?.push(isNumeric ? Number(current) : current);
25
+ current = char;
26
+ isNumeric = charIsNum;
27
+ }
28
+ }
29
+ if (current?.length > 0) {
30
+ chunks?.push(isNumeric ? Number(current) : current);
31
+ }
32
+ return chunks;
33
+ };
34
+ const aChunks = _createChunks(a);
35
+ const bChunks = _createChunks(b);
36
+ for (let i = 0; i < Math.min(aChunks?.length, bChunks?.length); i++) {
37
+ let aChunk = aChunks[i];
38
+ let bChunk = bChunks[i];
39
+ if (caseInsensitive && typeof aChunk === 'string' && typeof bChunk === 'string') {
40
+ aChunk = aChunk?.toLowerCase();
41
+ bChunk = bChunk?.toLowerCase();
42
+ }
43
+ if (typeof aChunk !== typeof bChunk) {
44
+ return typeof aChunk === 'string' ? 1 : -1;
45
+ }
46
+ if (aChunk !== bChunk) {
47
+ if (typeof aChunk === 'number' && typeof bChunk === 'number') {
48
+ return aChunk - bChunk;
49
+ }
50
+ if (typeof aChunk === 'string' && typeof bChunk === 'string') {
51
+ if (localeAware) {
52
+ const cmp = aChunk.localeCompare(bChunk, undefined, {
53
+ sensitivity: caseInsensitive ? 'accent' : 'variant',
54
+ });
55
+ if (cmp !== 0)
56
+ return cmp;
57
+ }
58
+ return aChunk < bChunk ? -1 : 1;
59
+ }
60
+ }
61
+ }
62
+ return aChunks?.length - bChunks?.length;
63
+ }
7
64
  function sortAnArray(array, options) {
8
65
  if (!(0, non_primitives_1.isValidArray)(array))
9
66
  return array;
10
67
  if ((0, non_primitives_1.isArrayOfType)(array, primitives_1.isString)) {
11
- return [...array].sort((a, b) => options?.sortOrder === 'desc' ? (0, utils_1.naturalSort)(b, a) : (0, utils_1.naturalSort)(a, b));
68
+ return [...array].sort((a, b) => options?.sortOrder === 'desc' ? naturalSort(b, a) : naturalSort(a, b));
12
69
  }
13
70
  if ((0, non_primitives_1.isArrayOfType)(array, primitives_1.isNumber)) {
14
71
  return [...array].sort((a, b) => (options?.sortOrder === 'desc' ? b - a : a - b));
@@ -28,15 +85,15 @@ function sortAnArray(array, options) {
28
85
  if (keyA == null || keyB == null) {
29
86
  return keyA == null ? 1 : -1;
30
87
  }
31
- if (typeof keyA === 'string' && typeof keyB === 'string') {
88
+ if ((0, primitives_1.isString)(keyA) && (0, primitives_1.isString)(keyB)) {
32
89
  return options?.sortOrder === 'desc' ?
33
- (0, utils_1.naturalSort)(keyB, keyA)
34
- : (0, utils_1.naturalSort)(keyA, keyB);
90
+ naturalSort(keyB, keyA)
91
+ : naturalSort(keyA, keyB);
35
92
  }
36
- if (typeof keyA === 'number' && typeof keyB === 'number') {
93
+ if ((0, primitives_1.isNumber)(keyA) && (0, primitives_1.isNumber)(keyB)) {
37
94
  return options?.sortOrder === 'desc' ? keyB - keyA : keyA - keyB;
38
95
  }
39
- if (typeof keyA === 'boolean' && typeof keyB === 'boolean') {
96
+ if ((0, primitives_1.isBoolean)(keyA) && (0, primitives_1.isBoolean)(keyB)) {
40
97
  return options?.sortOrder === 'desc' ?
41
98
  Number(keyB) - Number(keyA)
42
99
  : Number(keyA) - Number(keyB);
@@ -44,5 +101,5 @@ function sortAnArray(array, options) {
44
101
  return 0;
45
102
  });
46
103
  }
47
- return array;
104
+ return [...array];
48
105
  }
@@ -15,11 +15,12 @@ const businessPlugin = ($Chronos) => {
15
15
  mask[d] = false;
16
16
  return mask;
17
17
  };
18
- const _countWorkdays = (wStart, totalDays, mask, step = 1) => {
19
- let total = Math.floor(totalDays / 7) * mask.filter(Boolean).length;
20
- let dayIndex = wStart % 7;
21
- for (let i = 0; i < totalDays % 7; i++) {
22
- if (mask[dayIndex])
18
+ const _countDays = (sWeek, days, mask, step = 1, wd = true) => {
19
+ let total = Math.floor(days / 7) * mask.filter((m) => (wd ? Boolean(m) : !m)).length;
20
+ let dayIndex = ((sWeek % 7) + 7) % 7;
21
+ for (let i = 0; i < days % 7; i++) {
22
+ const isMatch = wd ? Boolean(mask[dayIndex]) : !mask[dayIndex];
23
+ if (isMatch)
23
24
  total++;
24
25
  dayIndex = (dayIndex + step + 7) % 7;
25
26
  }
@@ -67,26 +68,49 @@ const businessPlugin = ($Chronos) => {
67
68
  };
68
69
  $Chronos.prototype.workdaysBetween = function (to, wDef = 0, wLen = 2) {
69
70
  const end = cast(to).startOf('day');
70
- const start = this.clone().startOf('day');
71
+ const start = this.startOf('day');
71
72
  if (start.isSame(end, 'day'))
72
73
  return 0;
73
74
  const step = start.isBefore(end, 'day') ? 1 : -1;
74
75
  const totalDays = Math.abs(end.diff(start, 'day'));
75
76
  const weekendMask = _buildWeekendMask(wDef, wLen);
76
77
  const startWeekday = (start.isoWeekDay + step) % 7;
77
- return _countWorkdays(startWeekday, totalDays, weekendMask, step);
78
+ return _countDays(startWeekday, totalDays, weekendMask, step);
79
+ };
80
+ $Chronos.prototype.weekendsBetween = function (to, wDef = 0, wLen = 2) {
81
+ const end = cast(to).startOf('day');
82
+ const start = this.startOf('day');
83
+ if (start.isSame(end, 'day'))
84
+ return 0;
85
+ const step = start.isBefore(end, 'day') ? 1 : -1;
86
+ const totalDays = Math.abs(end.diff(start, 'day'));
87
+ const weekendMask = _buildWeekendMask(wDef, wLen);
88
+ const startWeekday = (start.isoWeekDay + step) % 7;
89
+ return _countDays(startWeekday, totalDays, weekendMask, step, false);
78
90
  };
79
91
  $Chronos.prototype.workdaysInMonth = function (wDef = 0, wLen = 2) {
80
92
  const daysInMonth = this.daysInMonth();
81
93
  const weekendMask = _buildWeekendMask(wDef, wLen);
82
94
  const startWeekday = this.startOf('month').isoWeekDay % 7;
83
- return _countWorkdays(startWeekday, daysInMonth, weekendMask);
95
+ return _countDays(startWeekday, daysInMonth, weekendMask);
96
+ };
97
+ $Chronos.prototype.weekendsInMonth = function (wDef = 0, wLen = 2) {
98
+ const daysInMonth = this.daysInMonth();
99
+ const weekendMask = _buildWeekendMask(wDef, wLen);
100
+ const startWeekday = this.startOf('month').isoWeekDay % 7;
101
+ return _countDays(startWeekday, daysInMonth, weekendMask, 1, false);
84
102
  };
85
103
  $Chronos.prototype.workdaysInYear = function (wDef = 0, wLen = 2) {
86
104
  const daysInYear = this.isLeapYear() ? 366 : 365;
87
105
  const weekendMask = _buildWeekendMask(wDef, wLen);
88
106
  const startWeekday = this.startOf('year').isoWeekDay % 7;
89
- return _countWorkdays(startWeekday, daysInYear, weekendMask);
107
+ return _countDays(startWeekday, daysInYear, weekendMask);
108
+ };
109
+ $Chronos.prototype.weekendsInYear = function (wDef = 0, wLen = 2) {
110
+ const daysInYear = this.isLeapYear() ? 366 : 365;
111
+ const weekendMask = _buildWeekendMask(wDef, wLen);
112
+ const startWeekday = this.startOf('year').isoWeekDay % 7;
113
+ return _countDays(startWeekday, daysInYear, weekendMask, 1, false);
90
114
  };
91
115
  $Chronos.prototype.isBusinessHour = function (options) {
92
116
  const _isBusinessHour = () => {
package/dist/cjs/index.js CHANGED
@@ -4,7 +4,7 @@ exports.convertToDecimal = exports.calculateLCM = exports.calculateLCD = exports
4
4
  exports.convertRomanToNumeric = exports.convertRomanToInteger = exports.convertRomanToArabic = exports.convertNumberToWordsOrdinal = exports.convertNumberToWords = exports.cardinalWordsToOrdinal = exports.arabicToRoman = exports.isPerfectSquare = exports.isPartOfFibonacciSeries = exports.isPartOfFibonacci = exports.isOddNumber = exports.isOdd = exports.isNumberInvalid = exports.isMultiple = exports.isInvalidNumber = exports.isFibonacci = exports.isEvenNumber = exports.isEven = exports.areNumbersInvalid = exports.areInvalidNumbers = exports.getNthFibonacci = exports.getMemoizedFibonacciSeries = exports.getMemoizedFibonacci = exports.getFibonacciSeriesMemo = exports.getFibonacciSeries = exports.getFibonacciNumbers = exports.getFibonacci = exports.generateFibonacci = exports.fibonacciGenerator = exports.calculatePercentage = exports.UnitConverter = exports.Unit = exports.Currency = exports.sumOfNumbers = exports.sumNumbers = exports.sumDigits = exports.roundToDecimal = exports.roundNumber = exports.reverseNumber = exports.getSumOfNumbers = exports.getRandomNumber = exports.getRandomInt = exports.getFactors = exports.getFactorial = exports.getDivisors = exports.getAverageOfNumbers = exports.getAverage = exports.factorsOf = exports.factorial = exports.convertToFixed = void 0;
5
5
  exports.convertHslToHex = exports.convertHslaToRgba = exports.convertHslaToHex8 = exports.convertHexToRgb = exports.convertHexToHsl = exports.convertHex8ToRgba = exports.convertHex8ToHsla = exports.convertColorCode = exports.getRandomHSL = exports.getRandomColor = exports.generateRandomHSLColor = exports.generateRandomHSL = exports.generateRandomColorInHexRGB = exports.generateRandomColor = exports.getColorForInitial = exports.getNumbersInRange = exports.roundToNearestInterval = exports.roundToNearest = exports.roundNumberToNearestInterval = exports.numberToOrdinal = exports.normalizeNumber = exports.getRandomFloat = exports.getRandomDecimal = exports.getOrdinalNumber = exports.getOrdinal = exports.formatCurrency = exports.convertToOrdinal = exports.convertNumberToOrdinal = exports.convertNumberToCurrency = exports.clampNumber = exports.cardinalToOrdinal = exports.isPrimeNumber = exports.isPrime = exports.getPrimeNumbers = exports.findPrimeNumbers = exports.wordToNumber = exports.wordsToNumber = exports.toRomanNumeral = exports.toRoman = exports.romanToNumeric = exports.romanToInteger = exports.romanToArabic = exports.numericToRoman = exports.numberToWordsOrdinal = exports.numberToWords = exports.numberToRoman = exports.integerToRoman = exports.convertWordToNumber = exports.convertWordsToNumber = exports.convertToRomanNumerals = void 0;
6
6
  exports.formatDateTime = exports.formatDate = exports.extractTotalMinutesFromTime = exports.extractTimeStringFromUTC = exports.extractTimeFromUTC = exports.extractMinutesFromUTC = exports.extractHourMinute = exports.convertMinutesToUTCOffset = exports.convertMinutesToTime = exports.convertMinutesToHourMinutes = exports.chronusts = exports.chronusjs = exports.chronus = exports.chronosts = exports.chronosjs = exports.chronos = exports.INTERNALS = exports.Chronus = exports.Chronos = exports.isValidUTCOffset = exports.isValidUTCOffSet = exports.isValidUTC = exports.isValidTimeZoneId = exports.isValidTimeString = exports.isValidTime = exports.isTimeWithUnit = exports.isNativeTimeZoneId = exports.isLeapYear = exports.isDateLike = exports.parseMSec = exports.parseMs = exports.greet = exports.getGreeting = exports.generateGreeting = exports.extractSolidColorValues = exports.extractAlphaColorValues = exports.Colour = exports.Color = exports.isRGBA = exports.isRGB = exports.isHSLA = exports.isHSL = exports.isHex8 = exports.isHex6 = exports.convertRgbToRgba = exports.convertRgbToHsl = exports.convertRgbToHex = exports.convertRgbaToHsla = exports.convertRgbaToHex8 = exports.convertHslToRgb = void 0;
7
- exports.convertIntoFormData = exports.naturalSortForString = exports.naturalSort = exports.compareSorter = exports.compareNaturally = exports.splitArrayByProperty = exports.splitArray = exports.rotateArray = exports.removeDuplicatesFromArray = exports.removeDuplicates = exports.moveArrayElement = exports.groupArrayByProperty = exports.getMissingElements = exports.getDuplicatesFromArray = exports.getDuplicates = exports.findMissingElements = exports.extractMissingElements = exports.extractDuplicatesFromArray = exports.extractDuplicates = exports.createOptionsArray = exports.sortAnArray = exports.Finder = exports.totalDeltaByField = exports.sumFieldDifference = exports.sumByField = exports.groupAndSumByField = exports.groupAndAvgByField = exports.groupAndAverageByField = exports.avgByField = exports.averageByField = exports.shuffleArray = exports.isValidEmptyArray = exports.isInvalidOrEmptyArray = exports.getLastArrayElement = exports.flattenArray = exports.filterArrayOfObjects = exports.minutesToUTCOffset = exports.getTotalMinutesFromUTC = exports.getTotalMinutesFromTime = exports.getTotalMinutes = exports.getTimeZoneIds = exports.getTimeZoneDetails = exports.getTimeStringFromUTC = exports.getTimeFromMinutes = exports.getNativeTimeZoneId = exports.getMinutesFromUTC = exports.getHourMinutesFromMinutes = exports.getCurrentTime = exports.getCurrentDateTime = exports.formatUTCOffset = void 0;
7
+ exports.convertIntoFormData = exports.splitArrayByProperty = exports.splitArray = exports.rotateArray = exports.removeDuplicatesFromArray = exports.removeDuplicates = exports.moveArrayElement = exports.groupArrayByProperty = exports.getMissingElements = exports.getDuplicatesFromArray = exports.getDuplicates = exports.findMissingElements = exports.extractMissingElements = exports.extractDuplicatesFromArray = exports.extractDuplicates = exports.createOptionsArray = exports.sortAnArray = exports.naturalSortForString = exports.naturalSort = exports.compareSorter = exports.compareNaturally = exports.Finder = exports.totalDeltaByField = exports.sumFieldDifference = exports.sumByField = exports.groupAndSumByField = exports.groupAndAvgByField = exports.groupAndAverageByField = exports.avgByField = exports.averageByField = exports.shuffleArray = exports.isValidEmptyArray = exports.isInvalidOrEmptyArray = exports.getLastArrayElement = exports.flattenArray = exports.filterArrayOfObjects = exports.minutesToUTCOffset = exports.getTotalMinutesFromUTC = exports.getTotalMinutesFromTime = exports.getTotalMinutes = exports.getTimeZoneIds = exports.getTimeZoneDetails = exports.getTimeStringFromUTC = exports.getTimeFromMinutes = exports.getNativeTimeZoneId = exports.getMinutesFromUTC = exports.getHourMinutesFromMinutes = exports.getCurrentTime = exports.getCurrentDateTime = exports.formatUTCOffset = void 0;
8
8
  exports.parseQueryStringLiteral = exports.parseQueryString = exports.literalQueryStringToObject = exports.getQueryStringAsObject = exports.getQueryParams = exports.generateQueryParams = exports.formatQueryParams = exports.createQueryParams = exports.removeObjectFields = exports.removeFields = exports.remapObjectFields = exports.remapFields = exports.pickObjectFieldsByCondition = exports.pickObjectFields = exports.pickFieldsByCondition = exports.pickFields = exports.omitObjectFields = exports.omitFields = exports.deleteObjectFields = exports.deleteFields = exports.convertObjectValues = exports.sanitizeData = exports.parseStringifiedObjectValues = exports.parseObjectValues = exports.parseJsonToObject = exports.mergeObjects = exports.mergeAndFlattenObjects = exports.flattenObjectKeyValue = exports.flattenObjectDotNotation = exports.extractUpdatedFields = exports.extractUpdatedAndNewFields = exports.extractNewFields = exports.extractObjectKeysDeep = exports.extractObjectKeys = exports.extractKeysDeep = exports.extractKeys = exports.countObjectFields = exports.cloneObject = exports.isValidFormData = exports.isOriginFileObj = exports.isFileUpload = exports.isFileOrBlob = exports.isFileList = exports.isFileArray = exports.isCustomFileArray = exports.isCustomFile = exports.serializeForm = exports.parseFormData = exports.createFormData = exports.createControlledFormData = void 0;
9
9
  exports.isArrayOfType = exports.isArray = exports.doesReturnPromise = exports.isUndefined = exports.isTruthy = exports.isSymbol = exports.isString = exports.isPrimitive = exports.isPositiveInteger = exports.isNumber = exports.isNull = exports.isNormalPrimitive = exports.isNonEmptyString = exports.isInteger = exports.isFalsy = exports.isBoolean = exports.isBigInt = exports.Paginator = exports.throttleAction = exports.stripJsonEdgeGarbage = exports.stableStringify = exports.parsePrimitivesDeep = exports.parseJsonDeep = exports.parseJSON = exports.joinArrayElements = exports.isDeepEqual = exports.getStaticMethodsCount = exports.getStaticMethodNames = exports.getStaticGetterNames = exports.getInstanceMethodsCount = exports.getInstanceMethodNames = exports.getInstanceGetterNames = exports.getClassDetails = exports.definePrototypeMethod = exports.deepParsePrimitives = exports.debounceAction = exports.countStaticMethods = exports.countInstanceMethods = exports.convertArrayToString = exports.saveToSessionStorage = exports.saveToLocalStorage = exports.removeFromSessionStorage = exports.removeFromLocalStorage = exports.getFromSessionStorage = exports.getFromLocalStorage = exports.toggleFullScreen = exports.smoothScrollTo = exports.copyToClipboard = exports.updateQueryParam = exports.queryStringToObject = void 0;
10
10
  exports.isValidURL = exports.isValidEmail = exports.isUUID = exports.isURL = exports.isPhoneNumber = exports.isNumericString = exports.isNodeEnvironment = exports.isNodeENV = exports.isNode = exports.isIPAddress = exports.isExpectedNodeENV = exports.isEnvironment = exports.isEmailArray = exports.isEmail = exports.isDateString = exports.isBrowser = exports.isBase64 = exports.httpStatus = exports.HttpStatus = exports.isValidSet = exports.isValidObject = exports.isValidMap = exports.isValidJSON = exports.isValidArray = exports.isSet = exports.isReturningPromise = exports.isRegularExpression = exports.isRegExp = exports.isPromise = exports.isObjectWithKeys = exports.isObjectEmpty = exports.isObject = exports.isNotEmptyObject = exports.isMethodDescriptor = exports.isMethod = exports.isMap = exports.isJSONObject = exports.isJSON = exports.isFunction = exports.isError = exports.isEmptyObjectGuard = exports.isEmptyObject = exports.isDate = exports.isArrayWithLength = void 0;
@@ -273,6 +273,10 @@ Object.defineProperty(exports, "totalDeltaByField", { enumerable: true, get: fun
273
273
  var Finder_1 = require("./array/Finder");
274
274
  Object.defineProperty(exports, "Finder", { enumerable: true, get: function () { return Finder_1.Finder; } });
275
275
  var sort_1 = require("./array/sort");
276
+ Object.defineProperty(exports, "compareNaturally", { enumerable: true, get: function () { return sort_1.naturalSort; } });
277
+ Object.defineProperty(exports, "compareSorter", { enumerable: true, get: function () { return sort_1.naturalSort; } });
278
+ Object.defineProperty(exports, "naturalSort", { enumerable: true, get: function () { return sort_1.naturalSort; } });
279
+ Object.defineProperty(exports, "naturalSortForString", { enumerable: true, get: function () { return sort_1.naturalSort; } });
276
280
  Object.defineProperty(exports, "sortAnArray", { enumerable: true, get: function () { return sort_1.sortAnArray; } });
277
281
  var transform_1 = require("./array/transform");
278
282
  Object.defineProperty(exports, "createOptionsArray", { enumerable: true, get: function () { return transform_1.createOptionsArray; } });
@@ -290,11 +294,6 @@ Object.defineProperty(exports, "removeDuplicatesFromArray", { enumerable: true,
290
294
  Object.defineProperty(exports, "rotateArray", { enumerable: true, get: function () { return transform_1.rotateArray; } });
291
295
  Object.defineProperty(exports, "splitArray", { enumerable: true, get: function () { return transform_1.splitArray; } });
292
296
  Object.defineProperty(exports, "splitArrayByProperty", { enumerable: true, get: function () { return transform_1.splitArrayByProperty; } });
293
- var utils_3 = require("./array/utils");
294
- Object.defineProperty(exports, "compareNaturally", { enumerable: true, get: function () { return utils_3.naturalSort; } });
295
- Object.defineProperty(exports, "compareSorter", { enumerable: true, get: function () { return utils_3.naturalSort; } });
296
- Object.defineProperty(exports, "naturalSort", { enumerable: true, get: function () { return utils_3.naturalSort; } });
297
- Object.defineProperty(exports, "naturalSortForString", { enumerable: true, get: function () { return utils_3.naturalSort; } });
298
297
  var convert_4 = require("./form/convert");
299
298
  Object.defineProperty(exports, "convertIntoFormData", { enumerable: true, get: function () { return convert_4.createControlledFormData; } });
300
299
  Object.defineProperty(exports, "createControlledFormData", { enumerable: true, get: function () { return convert_4.createControlledFormData; } });
@@ -356,10 +355,10 @@ Object.defineProperty(exports, "parseQueryString", { enumerable: true, get: func
356
355
  Object.defineProperty(exports, "parseQueryStringLiteral", { enumerable: true, get: function () { return query_1.parseQueryStringLiteral; } });
357
356
  Object.defineProperty(exports, "queryStringToObject", { enumerable: true, get: function () { return query_1.parseQueryString; } });
358
357
  Object.defineProperty(exports, "updateQueryParam", { enumerable: true, get: function () { return query_1.updateQueryParam; } });
359
- var utils_4 = require("./dom/utils");
360
- Object.defineProperty(exports, "copyToClipboard", { enumerable: true, get: function () { return utils_4.copyToClipboard; } });
361
- Object.defineProperty(exports, "smoothScrollTo", { enumerable: true, get: function () { return utils_4.smoothScrollTo; } });
362
- Object.defineProperty(exports, "toggleFullScreen", { enumerable: true, get: function () { return utils_4.toggleFullScreen; } });
358
+ var utils_3 = require("./dom/utils");
359
+ Object.defineProperty(exports, "copyToClipboard", { enumerable: true, get: function () { return utils_3.copyToClipboard; } });
360
+ Object.defineProperty(exports, "smoothScrollTo", { enumerable: true, get: function () { return utils_3.smoothScrollTo; } });
361
+ Object.defineProperty(exports, "toggleFullScreen", { enumerable: true, get: function () { return utils_3.toggleFullScreen; } });
363
362
  var storage_1 = require("./dom/storage");
364
363
  Object.defineProperty(exports, "getFromLocalStorage", { enumerable: true, get: function () { return storage_1.getFromLocalStorage; } });
365
364
  Object.defineProperty(exports, "getFromSessionStorage", { enumerable: true, get: function () { return storage_1.getFromSessionStorage; } });
@@ -1,20 +1,39 @@
1
1
  import type { GenericObject } from '../object/types';
2
- import type { OrderOption, SortByOption } from './types';
2
+ import type { BasicPrimitive } from '../types/index';
3
+ import type { OrderOption, SortByOption, SortNature } from './types';
3
4
  /**
4
- * * Sorts an array of objects.
5
+ * Compare two strings using natural sorting (e.g., `"file2"` < `"file10"`).
6
+ * - Optionally supports case-insensitive and locale-aware string chunk comparisons.
5
7
  *
6
- * - Sorts array by the specified field.
8
+ * @param a - The first string to compare.
9
+ * @param b - The second string to compare.
10
+ * @param options - Optional settings to configure comparison behavior.
11
+ * @returns A negative number if `a` comes before `b`, a positive number if `a` comes after `b`, or 0 if equal.
12
+ */
13
+ export declare function naturalSort(a: string, b: string, options?: SortNature): number;
14
+ /**
15
+ * * Sorts an array of objects based on the provided options.
16
+ *
17
+ * @remarks
18
+ * - Sorts array by the specified field in the options `sortByField`.
19
+ * - Uses {@link naturalSort} for sorting string values.
7
20
  *
8
21
  * @param array - The array of objects to sort.
9
- * @param options - Sorting options.
22
+ * @param options - Sorting options for objects.
10
23
  * @returns The sorted array.
11
24
  */
12
25
  export declare function sortAnArray<T extends GenericObject>(array: T[], options: SortByOption<T>): T[];
13
26
  /**
14
- * * Sorts an array of `strings`, `numbers` or `boolean`.
27
+ * * Sorts an array of `strings`, `numbers` or `boolean` based on the provided options.
28
+ *
29
+ * @remarks
30
+ * - If the array contains strings, it sorts them alphabetically.
31
+ * - If the array contains numbers, it sorts them numerically.
32
+ * - If the array contains booleans, it sorts them by their boolean value.
33
+ * - Uses {@link naturalSort} for sorting string values.
15
34
  *
16
35
  * @param array - The array of `strings`, `numbers` or `boolean` to sort.
17
36
  * @param options - Sorting options.
18
37
  * @returns The sorted array.
19
38
  */
20
- export declare function sortAnArray<T extends string | number | boolean>(array: T[], options?: OrderOption): T[];
39
+ export declare function sortAnArray<T extends BasicPrimitive>(array: T[], options?: OrderOption): T[];
@@ -266,7 +266,7 @@ declare module '../Chronos' {
266
266
  * @remarks This calculation is exclusive of the starting date and inclusive of the ending date.
267
267
  *
268
268
  * @example
269
- * new Chronos('2025-12-15').workdaysBetween(new Chronos('2025-12-21'));
269
+ * new Chronos('2025-12-15').workdaysBetween('2025-12-21');
270
270
  * // default weekend Friday & Saturday -> 4
271
271
  */
272
272
  workdaysBetween(other: ChronosInput, weekStartsOn?: Enumerate<7>, weekendLength?: NumberRange<1, 4>): number;
@@ -280,10 +280,39 @@ declare module '../Chronos' {
280
280
  * @remarks This calculation is exclusive of the starting date and inclusive of the ending date.
281
281
  *
282
282
  * @example
283
- * new Chronos('2025-12-15').workdaysBetween(new Chronos('2025-12-20'), [0, 6]);
283
+ * new Chronos('2025-12-15').workdaysBetween('2025-12-20', [0, 6]);
284
284
  * // custom weekend Sunday & Saturday -> 4
285
285
  */
286
286
  workdaysBetween(other: ChronosInput, weekendDays: RangeTuple<Enumerate<7>, 1, 4>): number;
287
+ /**
288
+ * @instance Calculates the number of weekends between the current date and another using week start day and weekend length.
289
+ *
290
+ * @param other The target date to compare against.
291
+ * @param weekStartsOn Optional. The day index (0–6) that the week starts on. Default is `0` (Sunday).
292
+ * @param weekendLength Optional. Number of consecutive days at the end of the week considered as weekend. Must be between 1 and 4. Default is `2`.
293
+ * @returns The total count of weekends between the two dates.
294
+ *
295
+ * @remarks This calculation is exclusive of the starting date and inclusive of the ending date.
296
+ *
297
+ * @example
298
+ * new Chronos('2025-12-15').weekendsBetween('2025-12-21');
299
+ * // default weekend Friday & Saturday -> 2
300
+ */
301
+ weekendsBetween(other: ChronosInput, weekStartsOn?: Enumerate<7>, weekendLength?: NumberRange<1, 4>): number;
302
+ /**
303
+ * @instance Calculates the number of weekends between the current date and another using custom weekend days.
304
+ *
305
+ * @param other The target date to compare against.
306
+ * @param weekendDays A tuple of custom weekend day indices (0–6). Must contain 1–4 elements.
307
+ * @returns The total count of weekends between the two dates.
308
+ *
309
+ * @remarks This calculation is exclusive of the starting date and inclusive of the ending date.
310
+ *
311
+ * @example
312
+ * new Chronos('2025-12-15').weekendsBetween('2025-12-20', [0, 6]);
313
+ * // custom weekend Sunday & Saturday -> 1
314
+ */
315
+ weekendsBetween(other: ChronosInput, weekendDays: RangeTuple<Enumerate<7>, 1, 4>): number;
287
316
  /**
288
317
  * @instance Counts the number of workdays in the current month using week start day and weekend length.
289
318
  *
@@ -305,6 +334,27 @@ declare module '../Chronos' {
305
334
  * new Chronos('2025-01-01').workdaysInMonth([0, 6]); // Sunday & Saturday are weekends
306
335
  */
307
336
  workdaysInMonth(weekendDays: RangeTuple<Enumerate<7>, 1, 4>): number;
337
+ /**
338
+ * @instance Counts the number of weekends in the current month using week start day and weekend length.
339
+ *
340
+ * @param weekStartsOn Optional. The day index (0–6) that the week starts on. Default is `0` (Sunday).
341
+ * @param weekendLength Optional. Number of consecutive days at the end of the week considered as weekend. Must be between 1 and 4. Default is `2`.
342
+ * @returns Number of weekends in the current month.
343
+ *
344
+ * @example
345
+ * new Chronos('2025-01-01').weekendsInMonth(); // default weekend Friday & Saturday -> 8
346
+ */
347
+ weekendsInMonth(weekStartsOn?: Enumerate<7>, weekendLength?: NumberRange<1, 4>): number;
348
+ /**
349
+ * @instance Counts the number of weekends in the current month using custom weekend days.
350
+ *
351
+ * @param weekendDays A tuple of custom weekend day indices (0–6). Must contain 1–4 elements.
352
+ * @returns Number of weekends in the current month.
353
+ *
354
+ * @example
355
+ * new Chronos('2025-01-01').weekendsInMonth([0, 6]); // Sunday & Saturday are weekends
356
+ */
357
+ weekendsInMonth(weekendDays: RangeTuple<Enumerate<7>, 1, 4>): number;
308
358
  /**
309
359
  * @instance Counts the number of workdays in the current year using week start day and weekend length.
310
360
  *
@@ -326,6 +376,27 @@ declare module '../Chronos' {
326
376
  * new Chronos('2025-01-01').workdaysInYear([0, 6]); // Sunday & Saturday are weekends
327
377
  */
328
378
  workdaysInYear(weekendDays: RangeTuple<Enumerate<7>, 1, 4>): number;
379
+ /**
380
+ * @instance Counts the number of weekends in the current year using week start day and weekend length.
381
+ *
382
+ * @param weekStartsOn Optional. The day index (0–6) that the week starts on. Default is `0` (Sunday).
383
+ * @param weekendLength Optional. Number of consecutive days at the end of the week considered as weekend. Must be between 1–4. Default is `2`.
384
+ * @returns Number of weekends in the current year.
385
+ *
386
+ * @example
387
+ * new Chronos('2025-01-01').weekendsInYear(); // default weekend Friday & Saturday -> 104
388
+ */
389
+ weekendsInYear(weekStartsOn?: Enumerate<7>, weekendLength?: NumberRange<1, 4>): number;
390
+ /**
391
+ * @instance Counts the number of weekends in the current year using custom weekend days.
392
+ *
393
+ * @param weekendDays A tuple of custom weekend day indices (0–6). Must contain 1–4 elements.
394
+ * @returns Number of weekends in the current year.
395
+ *
396
+ * @example
397
+ * new Chronos('2025-01-01').weekendsInYear([0, 6]); // Sunday & Saturday are weekends
398
+ */
399
+ weekendsInYear(weekendDays: RangeTuple<Enumerate<7>, 1, 4>): number;
329
400
  /**
330
401
  * @instance Checks if the current time fall within business hours using week start day and weekend length & other options.
331
402
  *
@@ -48,9 +48,8 @@ export { convertMinutesToTime as convertMinutesToHourMinutes, convertMinutesToTi
48
48
  export { filterArrayOfObjects, flattenArray, getLastArrayElement, isInvalidOrEmptyArray, isInvalidOrEmptyArray as isValidEmptyArray, shuffleArray, } from './array/basics';
49
49
  export { averageByField, averageByField as avgByField, groupAndAverageByField, groupAndAverageByField as groupAndAvgByField, groupAndSumByField, sumByField, sumFieldDifference, sumFieldDifference as totalDeltaByField, } from './array/calc';
50
50
  export { Finder } from './array/Finder';
51
- export { sortAnArray } from './array/sort';
51
+ export { naturalSort as compareNaturally, naturalSort as compareSorter, naturalSort, naturalSort as naturalSortForString, sortAnArray, } from './array/sort';
52
52
  export { createOptionsArray, getDuplicates as extractDuplicates, getDuplicates as extractDuplicatesFromArray, findMissingElements as extractMissingElements, findMissingElements, getDuplicates, getDuplicates as getDuplicatesFromArray, findMissingElements as getMissingElements, splitArrayByProperty as groupArrayByProperty, moveArrayElement, removeDuplicatesFromArray as removeDuplicates, removeDuplicatesFromArray, rotateArray, splitArray, splitArrayByProperty, } from './array/transform';
53
- export { naturalSort as compareNaturally, naturalSort as compareSorter, naturalSort, naturalSort as naturalSortForString, } from './array/utils';
54
53
  export { createControlledFormData as convertIntoFormData, createControlledFormData, createControlledFormData as createFormData, } from './form/convert';
55
54
  export { parseFormData, serializeForm } from './form/transform';
56
55
  export { isCustomFile, isCustomFileArray, isFileArray, isFileList, isFileOrBlob, isFileUpload, isOriginFileObj, isValidFormData, } from './form/guards';
@@ -6,7 +6,18 @@ declare const __brand: unique symbol;
6
6
  type $Brand<B> = {
7
7
  [__brand]: B;
8
8
  };
9
- /** Create a branded type */
9
+ /**
10
+ * * Creates a branded version of a base type by intersecting it with a unique compile-time marker.
11
+ *
12
+ * @param T - Base type to brand.
13
+ * @param B - Brand identifier used to distinguish this type from structurally similar types.
14
+
15
+ * @remarks Useful for preventing accidental mixing of structurally identical types, while keeping the runtime value unchanged.
16
+ *
17
+ * @example
18
+ * type UserId = Branded<string, 'UserId'>;
19
+ * const id = 'abc123' as UserId;
20
+ */
10
21
  export type Branded<T, B> = T & $Brand<B>;
11
22
  /** Represents a value that may or may not be present. */
12
23
  export type Maybe<T> = T | undefined;
@@ -16,10 +27,14 @@ export type FlattenPartial<T> = Partial<{
16
27
  }>;
17
28
  /** Union of `number` and numeric string */
18
29
  export type Numeric = number | `${number}`;
30
+ /** Union of Basic Primitive Types (i.e. `string | number | boolean`) */
31
+ export type BasicPrimitive = string | number | boolean;
32
+ /** `null` or `undefined` */
33
+ export type NullOrUndefined = null | undefined;
19
34
  /** Union of All Primitive Types (i.e. `string | number | boolean | symbol | bigint | null | undefined`) */
20
- export type Primitive = Maybe<string | number | boolean | symbol | bigint | null>;
35
+ export type Primitive = string | number | boolean | symbol | bigint | null | undefined;
21
36
  /** Union of Normal Primitive Types (i.e. `string | number | boolean | null | undefined`) */
22
- export type NormalPrimitive = Maybe<string | number | boolean | null>;
37
+ export type NormalPrimitive = string | number | boolean | null | undefined;
23
38
  /** Extract normal primitive key(s) (i.e. `string | number | boolean | null | undefined`) from an object */
24
39
  export type NormalPrimitiveKey<T> = {
25
40
  [K in keyof T]: T[K] extends NormalPrimitive ? K : never;
@@ -35,24 +50,23 @@ export type OwnKeys<T> = {
35
50
  }[keyof T];
36
51
  /** Extract primitive (string, number or boolean) key(s) from an object */
37
52
  export type NonNullishPrimitiveKey<T> = {
38
- [K in keyof T]: T[K] extends string | number | boolean ? K : never;
53
+ [K in keyof T]: T[K] extends BasicPrimitive ? K : never;
39
54
  }[keyof T];
40
- /** Falsy primitive type */
41
- export type FalsyPrimitive = Maybe<false | 0 | '' | null>;
55
+ /** Falsy primitive type */
56
+ export type FalsyPrimitive = false | '' | 0 | null | undefined;
42
57
  /** A generic class constructor */
43
58
  export type Constructor = new (...args: any[]) => any;
44
59
  /** Generic function type */
45
60
  export type GenericFn = (...args: any[]) => any;
46
61
  /** Generic function type that returns `void` */
47
- export type VoidFunction = (...args: any[]) => void;
48
- /** Debounced function type after certain delay */
49
- export type DelayedFn<T extends VoidFunction> = (...args: Parameters<T>) => void;
50
- /** Throttled function type after specific delay */
51
- export type ThrottledFn<T extends VoidFunction> = (...args: Parameters<T>) => void;
62
+ export type VoidFn = (...args: any[]) => void;
63
+ /** Delayed (debounced or throttled) function type after certain delay */
64
+ export type DelayedFn<T extends VoidFn> = (...args: Parameters<T>) => void;
65
+ export type { DelayedFn as ThrottledFn, VoidFn as VoidFunction };
52
66
  /** Asynchronous function type */
53
67
  export type AsyncFunction<T> = (...args: any[]) => Promise<T>;
54
68
  /** Advanced types to exclude from counting as object key */
55
- export type AdvancedTypes = Array<unknown> | File | FileList | Chronos | DateLike | Blob | Date | RegExp | WeakMap<WeakKey, unknown> | WeakSet<WeakKey> | Map<unknown, unknown> | Set<unknown> | Function | GenericFn | VoidFunction | AsyncFunction<unknown> | Promise<unknown> | Error | EvalError | RangeError | ReferenceError | SyntaxError | TypeError | URIError | bigint | symbol;
69
+ export type AdvancedTypes = Array<unknown> | File | FileList | Chronos | DateLike | Blob | Date | RegExp | WeakMap<WeakKey, unknown> | WeakSet<WeakKey> | Map<unknown, unknown> | Set<unknown> | Function | GenericFn | VoidFn | AsyncFunction<unknown> | Promise<unknown> | Error | EvalError | RangeError | ReferenceError | SyntaxError | TypeError | URIError | bigint | symbol;
56
70
  /** Helper to detect if a type has methods */
57
71
  export type HasMethods<T> = {
58
72
  [K in keyof T]: T[K] extends Function ? true : never;
@@ -139,4 +153,3 @@ export type List<T = any> = ReadonlyArray<T>;
139
153
  export type Serializer<T> = (value: T) => string;
140
154
  /** Function type for deserializing a string to a value of type `T`. */
141
155
  export type Deserializer<T> = (value: string) => T;
142
- export {};
@@ -1,5 +1,5 @@
1
1
  import type { GenericObject } from '../object/types';
2
- import type { ClassDetails, Constructor, DelayedFn, Maybe, Primitive, ThrottledFn, VoidFunction } from '../types/index';
2
+ import type { ClassDetails, Constructor, DelayedFn, Maybe, Primitive, VoidFn } from '../types/index';
3
3
  import type { ArrayOfObjectsToStringOptions, ArrayOfPrimitivesToStringOptions, ProtoMethodOptions } from './types';
4
4
  /**
5
5
  * * Deeply compare two values (arrays, objects, or primitive values).
@@ -55,7 +55,7 @@ export declare function convertArrayToString<T extends Primitive>(array: Maybe<T
55
55
  *
56
56
  * debouncedSearch('laptop'); // Executes after 300ms of inactivity.
57
57
  */
58
- export declare function debounceAction<T extends VoidFunction>(callback: T, delay?: number): DelayedFn<T>;
58
+ export declare function debounceAction<T extends VoidFn>(callback: T, delay?: number): DelayedFn<T>;
59
59
  /**
60
60
  * * A generic throttle function that ensures a callback is executed at most once per specified interval.
61
61
  *
@@ -70,7 +70,7 @@ export declare function debounceAction<T extends VoidFunction>(callback: T, dela
70
70
  *
71
71
  * window.addEventListener('resize', throttledResize);
72
72
  */
73
- export declare function throttleAction<T extends VoidFunction>(callback: T, delay?: number): ThrottledFn<T>;
73
+ export declare function throttleAction<T extends VoidFn>(callback: T, delay?: number): DelayedFn<T>;
74
74
  /**
75
75
  * * Retrieves the names of all instance methods defined directly on a class prototype.
76
76
  *
@@ -1,6 +1,62 @@
1
1
  import { isArrayOfType, isObject, isValidArray } from '../guards/non-primitives.js';
2
2
  import { isBoolean, isNumber, isString } from '../guards/primitives.js';
3
- import { naturalSort } from './utils.js';
3
+ export function naturalSort(a, b, options) {
4
+ const { caseInsensitive = true, localeAware = false } = options || {};
5
+ const _createChunks = (str) => {
6
+ const chunks = [];
7
+ let current = '';
8
+ let isNumeric = false;
9
+ for (const char of str) {
10
+ const charIsNum = !Number.isNaN(Number(char));
11
+ if (current?.length === 0) {
12
+ current = char;
13
+ isNumeric = charIsNum;
14
+ continue;
15
+ }
16
+ if (charIsNum === isNumeric) {
17
+ current += char;
18
+ }
19
+ else {
20
+ chunks?.push(isNumeric ? Number(current) : current);
21
+ current = char;
22
+ isNumeric = charIsNum;
23
+ }
24
+ }
25
+ if (current?.length > 0) {
26
+ chunks?.push(isNumeric ? Number(current) : current);
27
+ }
28
+ return chunks;
29
+ };
30
+ const aChunks = _createChunks(a);
31
+ const bChunks = _createChunks(b);
32
+ for (let i = 0; i < Math.min(aChunks?.length, bChunks?.length); i++) {
33
+ let aChunk = aChunks[i];
34
+ let bChunk = bChunks[i];
35
+ if (caseInsensitive && typeof aChunk === 'string' && typeof bChunk === 'string') {
36
+ aChunk = aChunk?.toLowerCase();
37
+ bChunk = bChunk?.toLowerCase();
38
+ }
39
+ if (typeof aChunk !== typeof bChunk) {
40
+ return typeof aChunk === 'string' ? 1 : -1;
41
+ }
42
+ if (aChunk !== bChunk) {
43
+ if (typeof aChunk === 'number' && typeof bChunk === 'number') {
44
+ return aChunk - bChunk;
45
+ }
46
+ if (typeof aChunk === 'string' && typeof bChunk === 'string') {
47
+ if (localeAware) {
48
+ const cmp = aChunk.localeCompare(bChunk, undefined, {
49
+ sensitivity: caseInsensitive ? 'accent' : 'variant',
50
+ });
51
+ if (cmp !== 0)
52
+ return cmp;
53
+ }
54
+ return aChunk < bChunk ? -1 : 1;
55
+ }
56
+ }
57
+ }
58
+ return aChunks?.length - bChunks?.length;
59
+ }
4
60
  export function sortAnArray(array, options) {
5
61
  if (!isValidArray(array))
6
62
  return array;
@@ -25,15 +81,15 @@ export function sortAnArray(array, options) {
25
81
  if (keyA == null || keyB == null) {
26
82
  return keyA == null ? 1 : -1;
27
83
  }
28
- if (typeof keyA === 'string' && typeof keyB === 'string') {
84
+ if (isString(keyA) && isString(keyB)) {
29
85
  return options?.sortOrder === 'desc' ?
30
86
  naturalSort(keyB, keyA)
31
87
  : naturalSort(keyA, keyB);
32
88
  }
33
- if (typeof keyA === 'number' && typeof keyB === 'number') {
89
+ if (isNumber(keyA) && isNumber(keyB)) {
34
90
  return options?.sortOrder === 'desc' ? keyB - keyA : keyA - keyB;
35
91
  }
36
- if (typeof keyA === 'boolean' && typeof keyB === 'boolean') {
92
+ if (isBoolean(keyA) && isBoolean(keyB)) {
37
93
  return options?.sortOrder === 'desc' ?
38
94
  Number(keyB) - Number(keyA)
39
95
  : Number(keyA) - Number(keyB);
@@ -41,5 +97,5 @@ export function sortAnArray(array, options) {
41
97
  return 0;
42
98
  });
43
99
  }
44
- return array;
100
+ return [...array];
45
101
  }
@@ -12,11 +12,12 @@ export const businessPlugin = ($Chronos) => {
12
12
  mask[d] = false;
13
13
  return mask;
14
14
  };
15
- const _countWorkdays = (wStart, totalDays, mask, step = 1) => {
16
- let total = Math.floor(totalDays / 7) * mask.filter(Boolean).length;
17
- let dayIndex = wStart % 7;
18
- for (let i = 0; i < totalDays % 7; i++) {
19
- if (mask[dayIndex])
15
+ const _countDays = (sWeek, days, mask, step = 1, wd = true) => {
16
+ let total = Math.floor(days / 7) * mask.filter((m) => (wd ? Boolean(m) : !m)).length;
17
+ let dayIndex = ((sWeek % 7) + 7) % 7;
18
+ for (let i = 0; i < days % 7; i++) {
19
+ const isMatch = wd ? Boolean(mask[dayIndex]) : !mask[dayIndex];
20
+ if (isMatch)
20
21
  total++;
21
22
  dayIndex = (dayIndex + step + 7) % 7;
22
23
  }
@@ -64,26 +65,49 @@ export const businessPlugin = ($Chronos) => {
64
65
  };
65
66
  $Chronos.prototype.workdaysBetween = function (to, wDef = 0, wLen = 2) {
66
67
  const end = cast(to).startOf('day');
67
- const start = this.clone().startOf('day');
68
+ const start = this.startOf('day');
68
69
  if (start.isSame(end, 'day'))
69
70
  return 0;
70
71
  const step = start.isBefore(end, 'day') ? 1 : -1;
71
72
  const totalDays = Math.abs(end.diff(start, 'day'));
72
73
  const weekendMask = _buildWeekendMask(wDef, wLen);
73
74
  const startWeekday = (start.isoWeekDay + step) % 7;
74
- return _countWorkdays(startWeekday, totalDays, weekendMask, step);
75
+ return _countDays(startWeekday, totalDays, weekendMask, step);
76
+ };
77
+ $Chronos.prototype.weekendsBetween = function (to, wDef = 0, wLen = 2) {
78
+ const end = cast(to).startOf('day');
79
+ const start = this.startOf('day');
80
+ if (start.isSame(end, 'day'))
81
+ return 0;
82
+ const step = start.isBefore(end, 'day') ? 1 : -1;
83
+ const totalDays = Math.abs(end.diff(start, 'day'));
84
+ const weekendMask = _buildWeekendMask(wDef, wLen);
85
+ const startWeekday = (start.isoWeekDay + step) % 7;
86
+ return _countDays(startWeekday, totalDays, weekendMask, step, false);
75
87
  };
76
88
  $Chronos.prototype.workdaysInMonth = function (wDef = 0, wLen = 2) {
77
89
  const daysInMonth = this.daysInMonth();
78
90
  const weekendMask = _buildWeekendMask(wDef, wLen);
79
91
  const startWeekday = this.startOf('month').isoWeekDay % 7;
80
- return _countWorkdays(startWeekday, daysInMonth, weekendMask);
92
+ return _countDays(startWeekday, daysInMonth, weekendMask);
93
+ };
94
+ $Chronos.prototype.weekendsInMonth = function (wDef = 0, wLen = 2) {
95
+ const daysInMonth = this.daysInMonth();
96
+ const weekendMask = _buildWeekendMask(wDef, wLen);
97
+ const startWeekday = this.startOf('month').isoWeekDay % 7;
98
+ return _countDays(startWeekday, daysInMonth, weekendMask, 1, false);
81
99
  };
82
100
  $Chronos.prototype.workdaysInYear = function (wDef = 0, wLen = 2) {
83
101
  const daysInYear = this.isLeapYear() ? 366 : 365;
84
102
  const weekendMask = _buildWeekendMask(wDef, wLen);
85
103
  const startWeekday = this.startOf('year').isoWeekDay % 7;
86
- return _countWorkdays(startWeekday, daysInYear, weekendMask);
104
+ return _countDays(startWeekday, daysInYear, weekendMask);
105
+ };
106
+ $Chronos.prototype.weekendsInYear = function (wDef = 0, wLen = 2) {
107
+ const daysInYear = this.isLeapYear() ? 366 : 365;
108
+ const weekendMask = _buildWeekendMask(wDef, wLen);
109
+ const startWeekday = this.startOf('year').isoWeekDay % 7;
110
+ return _countDays(startWeekday, daysInYear, weekendMask, 1, false);
87
111
  };
88
112
  $Chronos.prototype.isBusinessHour = function (options) {
89
113
  const _isBusinessHour = () => {
package/dist/esm/index.js CHANGED
@@ -33,9 +33,8 @@ export { convertMinutesToTime as convertMinutesToHourMinutes, convertMinutesToTi
33
33
  export { filterArrayOfObjects, flattenArray, getLastArrayElement, isInvalidOrEmptyArray, isInvalidOrEmptyArray as isValidEmptyArray, shuffleArray, } from './array/basics.js';
34
34
  export { averageByField, averageByField as avgByField, groupAndAverageByField, groupAndAverageByField as groupAndAvgByField, groupAndSumByField, sumByField, sumFieldDifference, sumFieldDifference as totalDeltaByField, } from './array/calc.js';
35
35
  export { Finder } from './array/Finder.js';
36
- export { sortAnArray } from './array/sort.js';
36
+ export { naturalSort as compareNaturally, naturalSort as compareSorter, naturalSort, naturalSort as naturalSortForString, sortAnArray, } from './array/sort.js';
37
37
  export { createOptionsArray, getDuplicates as extractDuplicates, getDuplicates as extractDuplicatesFromArray, findMissingElements as extractMissingElements, findMissingElements, getDuplicates, getDuplicates as getDuplicatesFromArray, findMissingElements as getMissingElements, splitArrayByProperty as groupArrayByProperty, moveArrayElement, removeDuplicatesFromArray as removeDuplicates, removeDuplicatesFromArray, rotateArray, splitArray, splitArrayByProperty, } from './array/transform.js';
38
- export { naturalSort as compareNaturally, naturalSort as compareSorter, naturalSort, naturalSort as naturalSortForString, } from './array/utils.js';
39
38
  export { createControlledFormData as convertIntoFormData, createControlledFormData, createControlledFormData as createFormData, } from './form/convert.js';
40
39
  export { parseFormData, serializeForm } from './form/transform.js';
41
40
  export { isCustomFile, isCustomFileArray, isFileArray, isFileList, isFileOrBlob, isFileUpload, isOriginFileObj, isValidFormData, } from './form/guards.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nhb-toolbox",
3
- "version": "4.28.21",
3
+ "version": "4.28.24",
4
4
  "description": "A versatile collection of smart, efficient, and reusable utility functions, classes and types for everyday development needs.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -41,9 +41,9 @@
41
41
  "devDependencies": {
42
42
  "@eslint/js": "^9.39.1",
43
43
  "@types/jest": "^30.0.0",
44
- "@types/node": "^24.10.1",
45
- "@typescript-eslint/eslint-plugin": "^8.48.1",
46
- "@typescript-eslint/parser": "^8.48.1",
44
+ "@types/node": "^25.0.0",
45
+ "@typescript-eslint/eslint-plugin": "^8.49.0",
46
+ "@typescript-eslint/parser": "^8.49.0",
47
47
  "eslint": "^9.39.1",
48
48
  "eslint-config-prettier": "^10.1.8",
49
49
  "eslint-plugin-prettier": "^5.5.4",
@@ -51,11 +51,11 @@
51
51
  "husky": "^9.1.7",
52
52
  "jest": "^30.2.0",
53
53
  "lint-staged": "^16.2.7",
54
- "nhb-scripts": "^1.8.88",
54
+ "nhb-scripts": "^1.9.0",
55
55
  "prettier": "^3.7.4",
56
56
  "ts-jest": "^29.4.6",
57
57
  "typescript": "^5.9.3",
58
- "typescript-eslint": "^8.48.1"
58
+ "typescript-eslint": "^8.49.0"
59
59
  },
60
60
  "keywords": [
61
61
  "toolbox",
@@ -1,60 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.naturalSort = naturalSort;
4
- function naturalSort(a, b, options) {
5
- const { caseInsensitive = true, localeAware = false } = options || {};
6
- const _createChunks = (str) => {
7
- const chunks = [];
8
- let current = '';
9
- let isNumeric = false;
10
- for (const char of str) {
11
- const charIsNum = !Number.isNaN(Number(char));
12
- if (current?.length === 0) {
13
- current = char;
14
- isNumeric = charIsNum;
15
- continue;
16
- }
17
- if (charIsNum === isNumeric) {
18
- current += char;
19
- }
20
- else {
21
- chunks?.push(isNumeric ? Number(current) : current);
22
- current = char;
23
- isNumeric = charIsNum;
24
- }
25
- }
26
- if (current?.length > 0) {
27
- chunks?.push(isNumeric ? Number(current) : current);
28
- }
29
- return chunks;
30
- };
31
- const aChunks = _createChunks(a);
32
- const bChunks = _createChunks(b);
33
- for (let i = 0; i < Math.min(aChunks?.length, bChunks?.length); i++) {
34
- let aChunk = aChunks[i];
35
- let bChunk = bChunks[i];
36
- if (caseInsensitive && typeof aChunk === 'string' && typeof bChunk === 'string') {
37
- aChunk = aChunk?.toLowerCase();
38
- bChunk = bChunk?.toLowerCase();
39
- }
40
- if (typeof aChunk !== typeof bChunk) {
41
- return typeof aChunk === 'string' ? 1 : -1;
42
- }
43
- if (aChunk !== bChunk) {
44
- if (typeof aChunk === 'number' && typeof bChunk === 'number') {
45
- return aChunk - bChunk;
46
- }
47
- if (typeof aChunk === 'string' && typeof bChunk === 'string') {
48
- if (localeAware) {
49
- const cmp = aChunk.localeCompare(bChunk, undefined, {
50
- sensitivity: caseInsensitive ? 'accent' : 'variant',
51
- });
52
- if (cmp !== 0)
53
- return cmp;
54
- }
55
- return aChunk < bChunk ? -1 : 1;
56
- }
57
- }
58
- }
59
- return aChunks?.length - bChunks?.length;
60
- }
@@ -1,13 +0,0 @@
1
- import type { SortNature } from './types';
2
- /**
3
- * * Compare two strings using natural sorting (e.g., "file2" < "file10").
4
- * Optionally supports case-insensitive and locale-aware string chunk comparisons.
5
- *
6
- * @param a - The first string to compare.
7
- * @param b - The second string to compare.
8
- * @param options - Optional settings to configure comparison behavior.
9
- * @param options.caseInsensitive - If true, compares string chunks without case sensitivity. Defaults to `true`.
10
- * @param options.localeAware - If true, uses localeCompare for string chunk comparisons. Defaults to `false`.
11
- * @returns A negative number if `a` comes before `b`, a positive number if `a` comes after `b`, or 0 if equal.
12
- */
13
- export declare function naturalSort(a: string, b: string, options?: SortNature): number;
@@ -1,57 +0,0 @@
1
- export function naturalSort(a, b, options) {
2
- const { caseInsensitive = true, localeAware = false } = options || {};
3
- const _createChunks = (str) => {
4
- const chunks = [];
5
- let current = '';
6
- let isNumeric = false;
7
- for (const char of str) {
8
- const charIsNum = !Number.isNaN(Number(char));
9
- if (current?.length === 0) {
10
- current = char;
11
- isNumeric = charIsNum;
12
- continue;
13
- }
14
- if (charIsNum === isNumeric) {
15
- current += char;
16
- }
17
- else {
18
- chunks?.push(isNumeric ? Number(current) : current);
19
- current = char;
20
- isNumeric = charIsNum;
21
- }
22
- }
23
- if (current?.length > 0) {
24
- chunks?.push(isNumeric ? Number(current) : current);
25
- }
26
- return chunks;
27
- };
28
- const aChunks = _createChunks(a);
29
- const bChunks = _createChunks(b);
30
- for (let i = 0; i < Math.min(aChunks?.length, bChunks?.length); i++) {
31
- let aChunk = aChunks[i];
32
- let bChunk = bChunks[i];
33
- if (caseInsensitive && typeof aChunk === 'string' && typeof bChunk === 'string') {
34
- aChunk = aChunk?.toLowerCase();
35
- bChunk = bChunk?.toLowerCase();
36
- }
37
- if (typeof aChunk !== typeof bChunk) {
38
- return typeof aChunk === 'string' ? 1 : -1;
39
- }
40
- if (aChunk !== bChunk) {
41
- if (typeof aChunk === 'number' && typeof bChunk === 'number') {
42
- return aChunk - bChunk;
43
- }
44
- if (typeof aChunk === 'string' && typeof bChunk === 'string') {
45
- if (localeAware) {
46
- const cmp = aChunk.localeCompare(bChunk, undefined, {
47
- sensitivity: caseInsensitive ? 'accent' : 'variant',
48
- });
49
- if (cmp !== 0)
50
- return cmp;
51
- }
52
- return aChunk < bChunk ? -1 : 1;
53
- }
54
- }
55
- }
56
- return aChunks?.length - bChunks?.length;
57
- }