@xxanderwp/jstoolkit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +0 -0
- package/README.md +247 -0
- package/dist/index.d.ts +956 -0
- package/dist/index.esm.js +1459 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +1506 -0
- package/dist/index.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,1459 @@
|
|
|
1
|
+
import md5 from 'md5';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Generate a random string of specified length
|
|
5
|
+
* @param length - Length of the string to generate
|
|
6
|
+
* @param characters - Characters to use (default: alphanumeric)
|
|
7
|
+
* @returns Random string
|
|
8
|
+
*/
|
|
9
|
+
function randomString(length, characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') {
|
|
10
|
+
let result = '';
|
|
11
|
+
const charactersLength = characters.length;
|
|
12
|
+
for (let i = 0; i < length; i++) {
|
|
13
|
+
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
|
14
|
+
}
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Truncate a string to a specified length and add ellipsis
|
|
19
|
+
* @param str - String to truncate
|
|
20
|
+
* @param maxLength - Maximum length
|
|
21
|
+
* @param ellipsis - Ellipsis string (default: '...')
|
|
22
|
+
* @returns Truncated string
|
|
23
|
+
*/
|
|
24
|
+
function truncate(str, maxLength, ellipsis = '...') {
|
|
25
|
+
if (str.length <= maxLength)
|
|
26
|
+
return str;
|
|
27
|
+
return str.slice(0, maxLength - ellipsis.length) + ellipsis;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Capitalize the first letter of a string
|
|
31
|
+
* @param str - String to capitalize
|
|
32
|
+
* @returns Capitalized string
|
|
33
|
+
*/
|
|
34
|
+
function capitalize(str) {
|
|
35
|
+
if (!str)
|
|
36
|
+
return str;
|
|
37
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Convert string to camelCase
|
|
41
|
+
* @param str - String to convert
|
|
42
|
+
* @returns camelCase string
|
|
43
|
+
*/
|
|
44
|
+
function toCamelCase(str) {
|
|
45
|
+
return str
|
|
46
|
+
.replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''))
|
|
47
|
+
.replace(/^[A-Z]/, (c) => c.toLowerCase());
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Convert string to snake_case
|
|
51
|
+
* @param str - String to convert
|
|
52
|
+
* @returns snake_case string
|
|
53
|
+
*/
|
|
54
|
+
function toSnakeCase(str) {
|
|
55
|
+
return str
|
|
56
|
+
.replace(/([A-Z])/g, '_$1')
|
|
57
|
+
.toLowerCase()
|
|
58
|
+
.replace(/^_/, '');
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Convert string to kebab-case
|
|
62
|
+
* @param str - String to convert
|
|
63
|
+
* @returns kebab-case string
|
|
64
|
+
*/
|
|
65
|
+
function toKebabCase(str) {
|
|
66
|
+
return str
|
|
67
|
+
.replace(/([A-Z])/g, '-$1')
|
|
68
|
+
.toLowerCase()
|
|
69
|
+
.replace(/^-/, '');
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Remove all whitespace from a string
|
|
73
|
+
* @param str - String to process
|
|
74
|
+
* @returns String without whitespace
|
|
75
|
+
*/
|
|
76
|
+
function removeWhitespace(str) {
|
|
77
|
+
return str.replace(/\s+/g, '');
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Count occurrences of a substring in a string
|
|
81
|
+
* @param str - String to search in
|
|
82
|
+
* @param substring - Substring to count
|
|
83
|
+
* @returns Number of occurrences
|
|
84
|
+
*/
|
|
85
|
+
function countOccurrences(str, substring) {
|
|
86
|
+
if (!substring)
|
|
87
|
+
return 0;
|
|
88
|
+
return (str.match(new RegExp(substring, 'g')) || []).length;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
var string = /*#__PURE__*/Object.freeze({
|
|
92
|
+
__proto__: null,
|
|
93
|
+
capitalize: capitalize,
|
|
94
|
+
countOccurrences: countOccurrences,
|
|
95
|
+
randomString: randomString,
|
|
96
|
+
removeWhitespace: removeWhitespace,
|
|
97
|
+
toCamelCase: toCamelCase,
|
|
98
|
+
toKebabCase: toKebabCase,
|
|
99
|
+
toSnakeCase: toSnakeCase,
|
|
100
|
+
truncate: truncate
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Get a random element from an array
|
|
105
|
+
* @param arr - Array to pick from
|
|
106
|
+
* @returns Random element
|
|
107
|
+
*/
|
|
108
|
+
function randomElement(arr) {
|
|
109
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Get a random index from an array
|
|
113
|
+
* @param arr - Array to pick from
|
|
114
|
+
* @returns Random index
|
|
115
|
+
*/
|
|
116
|
+
function randomElementIndex(arr) {
|
|
117
|
+
return Math.floor(Math.random() * arr.length);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Shuffle an array using Fisher-Yates algorithm
|
|
121
|
+
* @param arr - Array to shuffle
|
|
122
|
+
* @returns Shuffled array (new array)
|
|
123
|
+
*/
|
|
124
|
+
function shuffle(arr) {
|
|
125
|
+
const result = [...arr];
|
|
126
|
+
for (let i = result.length - 1; i > 0; i--) {
|
|
127
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
128
|
+
[result[i], result[j]] = [result[j], result[i]];
|
|
129
|
+
}
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Split an array into chunks of specified size
|
|
134
|
+
* @param array - Array to chunk
|
|
135
|
+
* @param size - Size of each chunk
|
|
136
|
+
* @returns Array of chunks
|
|
137
|
+
*/
|
|
138
|
+
function chunk(array, size) {
|
|
139
|
+
const result = [];
|
|
140
|
+
for (let i = 0; i < array.length; i += size) {
|
|
141
|
+
result.push(array.slice(i, i + size));
|
|
142
|
+
}
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Remove duplicate values from an array
|
|
147
|
+
* @param arr - Array to deduplicate
|
|
148
|
+
* @returns Array without duplicates
|
|
149
|
+
*/
|
|
150
|
+
function unique(arr) {
|
|
151
|
+
return [...new Set(arr)];
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Get the intersection of two arrays
|
|
155
|
+
* @param arr1 - First array
|
|
156
|
+
* @param arr2 - Second array
|
|
157
|
+
* @returns Intersection array
|
|
158
|
+
*/
|
|
159
|
+
function intersection(arr1, arr2) {
|
|
160
|
+
const set2 = new Set(arr2);
|
|
161
|
+
return arr1.filter((item) => set2.has(item));
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Get the difference of two arrays (elements in arr1 but not in arr2)
|
|
165
|
+
* @param arr1 - First array
|
|
166
|
+
* @param arr2 - Second array
|
|
167
|
+
* @returns Difference array
|
|
168
|
+
*/
|
|
169
|
+
function difference(arr1, arr2) {
|
|
170
|
+
const set2 = new Set(arr2);
|
|
171
|
+
return arr1.filter((item) => !set2.has(item));
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Sort array in ascending or descending order
|
|
175
|
+
* @param array - Array to sort
|
|
176
|
+
* @param order - Sort order ('ASC' or 'DESC')
|
|
177
|
+
* @returns Sorted array
|
|
178
|
+
*/
|
|
179
|
+
function sort(array, order = 'ASC') {
|
|
180
|
+
return [...array].sort((a, b) => {
|
|
181
|
+
if (order === 'ASC') {
|
|
182
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
return a < b ? 1 : a > b ? -1 : 0;
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Sort array of objects by multiple properties
|
|
191
|
+
* @param array - Array to sort
|
|
192
|
+
* @param params - Sort parameters
|
|
193
|
+
* @returns Sorted array
|
|
194
|
+
*/
|
|
195
|
+
function sortBy(array, params) {
|
|
196
|
+
return [...array].sort((a, b) => {
|
|
197
|
+
for (const param of params) {
|
|
198
|
+
const aVal = a[param.key];
|
|
199
|
+
const bVal = b[param.key];
|
|
200
|
+
let result = 0;
|
|
201
|
+
if (param.order === 'ASC') {
|
|
202
|
+
result = aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
result = aVal < bVal ? 1 : aVal > bVal ? -1 : 0;
|
|
206
|
+
}
|
|
207
|
+
if (result !== 0)
|
|
208
|
+
return result;
|
|
209
|
+
}
|
|
210
|
+
return 0;
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Sort array items by key order priority
|
|
215
|
+
* @param items - Array to sort
|
|
216
|
+
* @param keyOrder - Priority order of keys
|
|
217
|
+
* @returns Sorted array
|
|
218
|
+
*/
|
|
219
|
+
function sortByKeys(items, keyOrder) {
|
|
220
|
+
const keyOrderMap = new Map(keyOrder.map((key, index) => [key, index]));
|
|
221
|
+
return [...items].sort((a, b) => {
|
|
222
|
+
let orderA = keyOrder.length;
|
|
223
|
+
let orderB = keyOrder.length;
|
|
224
|
+
for (const [key, index] of keyOrderMap) {
|
|
225
|
+
if (a.startsWith(key)) {
|
|
226
|
+
orderA = index;
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
for (const [key, index] of keyOrderMap) {
|
|
231
|
+
if (b.startsWith(key)) {
|
|
232
|
+
orderB = index;
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return orderA - orderB;
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Group array elements by a key function
|
|
241
|
+
* @param arr - Array to group
|
|
242
|
+
* @param keyFn - Function that returns the group key
|
|
243
|
+
* @returns Object with grouped elements
|
|
244
|
+
*/
|
|
245
|
+
function groupBy(arr, keyFn) {
|
|
246
|
+
return arr.reduce((result, item) => {
|
|
247
|
+
const key = keyFn(item);
|
|
248
|
+
if (!result[key]) {
|
|
249
|
+
result[key] = [];
|
|
250
|
+
}
|
|
251
|
+
result[key].push(item);
|
|
252
|
+
return result;
|
|
253
|
+
}, {});
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Flatten nested arrays to specified depth
|
|
257
|
+
* @param arr - Array to flatten
|
|
258
|
+
* @param depth - Depth to flatten (default: 1)
|
|
259
|
+
* @returns Flattened array
|
|
260
|
+
*/
|
|
261
|
+
function flatten$1(arr, depth = 1) {
|
|
262
|
+
if (depth === 0)
|
|
263
|
+
return arr;
|
|
264
|
+
return arr.reduce((acc, val) => {
|
|
265
|
+
return acc.concat(Array.isArray(val) ? flatten$1(val, depth - 1) : val);
|
|
266
|
+
}, []);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
var array = /*#__PURE__*/Object.freeze({
|
|
270
|
+
__proto__: null,
|
|
271
|
+
chunk: chunk,
|
|
272
|
+
difference: difference,
|
|
273
|
+
flatten: flatten$1,
|
|
274
|
+
groupBy: groupBy,
|
|
275
|
+
intersection: intersection,
|
|
276
|
+
randomElement: randomElement,
|
|
277
|
+
randomElementIndex: randomElementIndex,
|
|
278
|
+
shuffle: shuffle,
|
|
279
|
+
sort: sort,
|
|
280
|
+
sortBy: sortBy,
|
|
281
|
+
sortByKeys: sortByKeys,
|
|
282
|
+
unique: unique
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Generate a random integer between min and max (inclusive)
|
|
287
|
+
* @param min - Minimum value
|
|
288
|
+
* @param max - Maximum value
|
|
289
|
+
* @returns Random integer
|
|
290
|
+
*/
|
|
291
|
+
function randomInt$1(min, max) {
|
|
292
|
+
if (max < min) {
|
|
293
|
+
[max, min] = [min, max];
|
|
294
|
+
}
|
|
295
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Generate a random float between min and max
|
|
299
|
+
* @param min - Minimum value
|
|
300
|
+
* @param max - Maximum value
|
|
301
|
+
* @returns Random float
|
|
302
|
+
*/
|
|
303
|
+
function randomFloat$1(min, max) {
|
|
304
|
+
if (max < min) {
|
|
305
|
+
[max, min] = [min, max];
|
|
306
|
+
}
|
|
307
|
+
return Math.random() * (max - min) + min;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Round a number to specified decimal places
|
|
311
|
+
* @param value - Value to round
|
|
312
|
+
* @param decimals - Number of decimal places
|
|
313
|
+
* @param mode - Rounding mode ('round' or 'truncate')
|
|
314
|
+
* @returns Rounded number
|
|
315
|
+
*/
|
|
316
|
+
function round(value, decimals, mode = 'round') {
|
|
317
|
+
const factor = Math.pow(10, decimals);
|
|
318
|
+
if (mode === 'truncate') {
|
|
319
|
+
return Math.trunc(value * factor) / factor;
|
|
320
|
+
}
|
|
321
|
+
return Math.round(value * factor) / factor;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Linear interpolation between two values
|
|
325
|
+
* @param start - Start value
|
|
326
|
+
* @param end - End value
|
|
327
|
+
* @param amount - Interpolation amount (0-1)
|
|
328
|
+
* @returns Interpolated value
|
|
329
|
+
*/
|
|
330
|
+
function lerp(start, end, amount) {
|
|
331
|
+
amount = Math.max(0, Math.min(1, amount));
|
|
332
|
+
return start + (end - start) * amount;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Linear interpolation between two 2D points
|
|
336
|
+
* @param point1 - First point
|
|
337
|
+
* @param point2 - Second point
|
|
338
|
+
* @param amount - Interpolation amount (0-1)
|
|
339
|
+
* @returns Interpolated point
|
|
340
|
+
*/
|
|
341
|
+
function lerp2D(point1, point2, amount) {
|
|
342
|
+
return {
|
|
343
|
+
x: lerp(point1.x, point2.x, amount),
|
|
344
|
+
y: lerp(point1.y, point2.y, amount),
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Linear interpolation between two 3D vectors
|
|
349
|
+
* @param vec1 - First vector
|
|
350
|
+
* @param vec2 - Second vector
|
|
351
|
+
* @param amount - Interpolation amount (0-1)
|
|
352
|
+
* @returns Interpolated vector
|
|
353
|
+
*/
|
|
354
|
+
function lerp3D(vec1, vec2, amount) {
|
|
355
|
+
return {
|
|
356
|
+
x: lerp(vec1.x, vec2.x, amount),
|
|
357
|
+
y: lerp(vec1.y, vec2.y, amount),
|
|
358
|
+
z: lerp(vec1.z, vec2.z, amount),
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Calculate time-based interpolation value
|
|
363
|
+
* @param start - Start timestamp
|
|
364
|
+
* @param end - End timestamp
|
|
365
|
+
* @param current - Current timestamp (default: Date.now())
|
|
366
|
+
* @returns Interpolation value (0-1)
|
|
367
|
+
*/
|
|
368
|
+
function lerpTime(start, end, current = Date.now()) {
|
|
369
|
+
const duration = current - start;
|
|
370
|
+
return Math.max(0, Math.min(1, duration / (end - start)));
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Clamp a value between min and max
|
|
374
|
+
* @param value - Value to clamp
|
|
375
|
+
* @param min - Minimum value
|
|
376
|
+
* @param max - Maximum value
|
|
377
|
+
* @returns Clamped value
|
|
378
|
+
*/
|
|
379
|
+
function clamp(value, min, max) {
|
|
380
|
+
return Math.max(min, Math.min(max, value));
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Map a value from one range to another
|
|
384
|
+
* @param value - Value to map
|
|
385
|
+
* @param inMin - Input range minimum
|
|
386
|
+
* @param inMax - Input range maximum
|
|
387
|
+
* @param outMin - Output range minimum
|
|
388
|
+
* @param outMax - Output range maximum
|
|
389
|
+
* @returns Mapped value
|
|
390
|
+
*/
|
|
391
|
+
function mapRange(value, inMin, inMax, outMin, outMax) {
|
|
392
|
+
return ((value - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Calculate percentage
|
|
396
|
+
* @param value - Value
|
|
397
|
+
* @param total - Total value
|
|
398
|
+
* @returns Percentage (0-100)
|
|
399
|
+
*/
|
|
400
|
+
function percentage(value, total) {
|
|
401
|
+
if (total === 0)
|
|
402
|
+
return 0;
|
|
403
|
+
return (value / total) * 100;
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Calculate average of numbers
|
|
407
|
+
* @param numbers - Array of numbers
|
|
408
|
+
* @returns Average value
|
|
409
|
+
*/
|
|
410
|
+
function average(numbers) {
|
|
411
|
+
if (numbers.length === 0)
|
|
412
|
+
return 0;
|
|
413
|
+
return numbers.reduce((sum, num) => sum + num, 0) / numbers.length;
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Calculate sum of numbers
|
|
417
|
+
* @param numbers - Array of numbers
|
|
418
|
+
* @returns Sum
|
|
419
|
+
*/
|
|
420
|
+
function sum(numbers) {
|
|
421
|
+
return numbers.reduce((total, num) => total + num, 0);
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Find minimum value in array
|
|
425
|
+
* @param numbers - Array of numbers
|
|
426
|
+
* @returns Minimum value
|
|
427
|
+
*/
|
|
428
|
+
function min(numbers) {
|
|
429
|
+
return Math.min(...numbers);
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Find maximum value in array
|
|
433
|
+
* @param numbers - Array of numbers
|
|
434
|
+
* @returns Maximum value
|
|
435
|
+
*/
|
|
436
|
+
function max(numbers) {
|
|
437
|
+
return Math.max(...numbers);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
var math = /*#__PURE__*/Object.freeze({
|
|
441
|
+
__proto__: null,
|
|
442
|
+
average: average,
|
|
443
|
+
clamp: clamp,
|
|
444
|
+
lerp: lerp,
|
|
445
|
+
lerp2D: lerp2D,
|
|
446
|
+
lerp3D: lerp3D,
|
|
447
|
+
lerpTime: lerpTime,
|
|
448
|
+
mapRange: mapRange,
|
|
449
|
+
max: max,
|
|
450
|
+
min: min,
|
|
451
|
+
percentage: percentage,
|
|
452
|
+
randomFloat: randomFloat$1,
|
|
453
|
+
randomInt: randomInt$1,
|
|
454
|
+
round: round,
|
|
455
|
+
sum: sum
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Get current Unix timestamp in seconds
|
|
460
|
+
* @returns Current timestamp
|
|
461
|
+
*/
|
|
462
|
+
function timestamp() {
|
|
463
|
+
return Math.floor(Date.now() / 1000);
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Get current Unix timestamp in milliseconds
|
|
467
|
+
* @returns Current timestamp in ms
|
|
468
|
+
*/
|
|
469
|
+
function timestampMs() {
|
|
470
|
+
return Date.now();
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Format a number with leading zero
|
|
474
|
+
* @param num - Number to format
|
|
475
|
+
* @returns Formatted string
|
|
476
|
+
*/
|
|
477
|
+
function padZero(num) {
|
|
478
|
+
return `0${num}`.slice(-2);
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Get full date and time string
|
|
482
|
+
* @param date - Date object (default: current date)
|
|
483
|
+
* @returns Formatted date string (DD.MM.YYYY HH:MM)
|
|
484
|
+
*/
|
|
485
|
+
function formatDateTime(date = new Date()) {
|
|
486
|
+
return `${padZero(date.getDate())}.${padZero(date.getMonth() + 1)}.${date.getFullYear()} ${padZero(date.getHours())}:${padZero(date.getMinutes())}`;
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Get full date and time string with seconds
|
|
490
|
+
* @param date - Date object (default: current date)
|
|
491
|
+
* @returns Formatted date string (DD.MM.YYYY HH:MM:SS)
|
|
492
|
+
*/
|
|
493
|
+
function formatDateTimeSeconds(date = new Date()) {
|
|
494
|
+
return `${padZero(date.getDate())}.${padZero(date.getMonth() + 1)}.${date.getFullYear()} ${padZero(date.getHours())}:${padZero(date.getMinutes())}:${padZero(date.getSeconds())}`;
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Get date without time
|
|
498
|
+
* @param date - Date object (default: current date)
|
|
499
|
+
* @returns Formatted date string (DD.MM.YYYY)
|
|
500
|
+
*/
|
|
501
|
+
function formatDate(date = new Date()) {
|
|
502
|
+
return `${padZero(date.getDate())}.${padZero(date.getMonth() + 1)}.${date.getFullYear()}`;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Format timestamp to readable date/time string
|
|
506
|
+
* Shows only time if date is today, otherwise shows date and time
|
|
507
|
+
* @param time - Unix timestamp in seconds (default: current time)
|
|
508
|
+
* @param alwaysShowDate - Always show date even if today
|
|
509
|
+
* @returns Formatted string
|
|
510
|
+
*/
|
|
511
|
+
function formatTimestamp(time = timestamp(), alwaysShowDate = false) {
|
|
512
|
+
const now = new Date();
|
|
513
|
+
const date = new Date(time * 1000);
|
|
514
|
+
let result = `${padZero(date.getHours())}:${padZero(date.getMinutes())}`;
|
|
515
|
+
const isToday = now.getDate() === date.getDate() &&
|
|
516
|
+
now.getMonth() === date.getMonth() &&
|
|
517
|
+
now.getFullYear() === date.getFullYear();
|
|
518
|
+
if (alwaysShowDate || !isToday) {
|
|
519
|
+
const showYear = now.getFullYear() !== date.getFullYear() || alwaysShowDate;
|
|
520
|
+
result = `${padZero(date.getDate())}.${padZero(date.getMonth() + 1)}${showYear ? `.${date.getFullYear()}` : ''} ${result}`;
|
|
521
|
+
}
|
|
522
|
+
return result;
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* Convert seconds to formatted duration string (HH:MM:SS or D:HH:MM:SS)
|
|
526
|
+
* @param seconds - Duration in seconds
|
|
527
|
+
* @returns Formatted duration string
|
|
528
|
+
*/
|
|
529
|
+
function formatDuration(seconds) {
|
|
530
|
+
const days = Math.floor(seconds / 86400);
|
|
531
|
+
const hours = Math.floor((seconds % 86400) / 3600);
|
|
532
|
+
const minutes = Math.floor((seconds % 3600) / 60);
|
|
533
|
+
const secs = seconds % 60;
|
|
534
|
+
let result = '';
|
|
535
|
+
if (days > 0) {
|
|
536
|
+
result += `${days}:`;
|
|
537
|
+
}
|
|
538
|
+
result += `${hours.toString().padStart(2, '0')}:`;
|
|
539
|
+
result += `${minutes.toString().padStart(2, '0')}:`;
|
|
540
|
+
result += `${secs.toString().padStart(2, '0')}`;
|
|
541
|
+
return result;
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Convert milliseconds to formatted duration string with ms
|
|
545
|
+
* @param ms - Duration in milliseconds
|
|
546
|
+
* @returns Formatted duration string (HH:MM:SS.mmm)
|
|
547
|
+
*/
|
|
548
|
+
function formatDurationMs(ms) {
|
|
549
|
+
const seconds = Math.floor(ms / 1000);
|
|
550
|
+
let result = formatDuration(seconds);
|
|
551
|
+
const milliseconds = (ms % 1000).toString().padStart(3, '0');
|
|
552
|
+
result += `.${milliseconds}`;
|
|
553
|
+
return result;
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Sleep/delay for specified milliseconds
|
|
557
|
+
* @param ms - Milliseconds to sleep
|
|
558
|
+
* @returns Promise that resolves after delay
|
|
559
|
+
*/
|
|
560
|
+
function sleep(ms) {
|
|
561
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Check if a date is today
|
|
565
|
+
* @param date - Date to check
|
|
566
|
+
* @returns True if date is today
|
|
567
|
+
*/
|
|
568
|
+
function isToday(date) {
|
|
569
|
+
const today = new Date();
|
|
570
|
+
return (date.getDate() === today.getDate() &&
|
|
571
|
+
date.getMonth() === today.getMonth() &&
|
|
572
|
+
date.getFullYear() === today.getFullYear());
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Check if a date is yesterday
|
|
576
|
+
* @param date - Date to check
|
|
577
|
+
* @returns True if date is yesterday
|
|
578
|
+
*/
|
|
579
|
+
function isYesterday(date) {
|
|
580
|
+
const yesterday = new Date();
|
|
581
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
582
|
+
return (date.getDate() === yesterday.getDate() &&
|
|
583
|
+
date.getMonth() === yesterday.getMonth() &&
|
|
584
|
+
date.getFullYear() === yesterday.getFullYear());
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Get relative time string (e.g., "2 hours ago", "in 3 days")
|
|
588
|
+
* @param date - Date to compare
|
|
589
|
+
* @param now - Reference date (default: current date)
|
|
590
|
+
* @returns Relative time string
|
|
591
|
+
*/
|
|
592
|
+
function timeAgo(date, now = new Date()) {
|
|
593
|
+
const seconds = Math.floor((now.getTime() - date.getTime()) / 1000);
|
|
594
|
+
const isFuture = seconds < 0;
|
|
595
|
+
const absSeconds = Math.abs(seconds);
|
|
596
|
+
const intervals = [
|
|
597
|
+
{ label: 'year', seconds: 31536000 },
|
|
598
|
+
{ label: 'month', seconds: 2592000 },
|
|
599
|
+
{ label: 'week', seconds: 604800 },
|
|
600
|
+
{ label: 'day', seconds: 86400 },
|
|
601
|
+
{ label: 'hour', seconds: 3600 },
|
|
602
|
+
{ label: 'minute', seconds: 60 },
|
|
603
|
+
];
|
|
604
|
+
for (const interval of intervals) {
|
|
605
|
+
const count = Math.floor(absSeconds / interval.seconds);
|
|
606
|
+
if (count >= 1) {
|
|
607
|
+
const plural = count > 1 ? 's' : '';
|
|
608
|
+
return isFuture
|
|
609
|
+
? `in ${count} ${interval.label}${plural}`
|
|
610
|
+
: `${count} ${interval.label}${plural} ago`;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
return 'just now';
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
var time = /*#__PURE__*/Object.freeze({
|
|
617
|
+
__proto__: null,
|
|
618
|
+
formatDate: formatDate,
|
|
619
|
+
formatDateTime: formatDateTime,
|
|
620
|
+
formatDateTimeSeconds: formatDateTimeSeconds,
|
|
621
|
+
formatDuration: formatDuration,
|
|
622
|
+
formatDurationMs: formatDurationMs,
|
|
623
|
+
formatTimestamp: formatTimestamp,
|
|
624
|
+
isToday: isToday,
|
|
625
|
+
isYesterday: isYesterday,
|
|
626
|
+
padZero: padZero,
|
|
627
|
+
sleep: sleep,
|
|
628
|
+
timeAgo: timeAgo,
|
|
629
|
+
timestamp: timestamp,
|
|
630
|
+
timestampMs: timestampMs
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* Encode string to Base64
|
|
635
|
+
* @param str - String to encode
|
|
636
|
+
* @returns Base64 encoded string
|
|
637
|
+
*/
|
|
638
|
+
function toBase64(str) {
|
|
639
|
+
if (typeof Buffer !== 'undefined') {
|
|
640
|
+
return Buffer.from(str, 'utf-8').toString('base64');
|
|
641
|
+
}
|
|
642
|
+
// Browser environment
|
|
643
|
+
const codeUnits = new Uint16Array(str.length);
|
|
644
|
+
for (let i = 0; i < codeUnits.length; i++) {
|
|
645
|
+
codeUnits[i] = str.charCodeAt(i);
|
|
646
|
+
}
|
|
647
|
+
const uint8Array = new Uint8Array(codeUnits.buffer);
|
|
648
|
+
const chunkSize = 0x8000;
|
|
649
|
+
let result = '';
|
|
650
|
+
for (let i = 0; i < uint8Array.length; i += chunkSize) {
|
|
651
|
+
const chunk = uint8Array.subarray(i, i + chunkSize);
|
|
652
|
+
result += String.fromCharCode(...chunk);
|
|
653
|
+
}
|
|
654
|
+
return btoa(result);
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* Decode Base64 string
|
|
658
|
+
* @param encoded - Base64 encoded string
|
|
659
|
+
* @returns Decoded string
|
|
660
|
+
*/
|
|
661
|
+
function fromBase64(encoded) {
|
|
662
|
+
if (typeof Buffer !== 'undefined') {
|
|
663
|
+
return Buffer.from(encoded, 'base64').toString('utf-8');
|
|
664
|
+
}
|
|
665
|
+
// Browser environment
|
|
666
|
+
const binary = atob(encoded);
|
|
667
|
+
const bytes = new Uint8Array(binary.length);
|
|
668
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
669
|
+
bytes[i] = binary.charCodeAt(i);
|
|
670
|
+
}
|
|
671
|
+
return String.fromCharCode(...new Uint16Array(bytes.buffer));
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Generate MD5 hash of a string
|
|
675
|
+
* @param text - Text to hash
|
|
676
|
+
* @returns MD5 hash
|
|
677
|
+
*/
|
|
678
|
+
function hash(text) {
|
|
679
|
+
return md5(text);
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Encode URI component safely
|
|
683
|
+
* @param str - String to encode
|
|
684
|
+
* @returns Encoded URI component
|
|
685
|
+
*/
|
|
686
|
+
function encodeUri(str) {
|
|
687
|
+
return encodeURIComponent(str);
|
|
688
|
+
}
|
|
689
|
+
/**
|
|
690
|
+
* Decode URI component safely
|
|
691
|
+
* @param str - String to decode
|
|
692
|
+
* @returns Decoded URI component
|
|
693
|
+
*/
|
|
694
|
+
function decodeUri(str) {
|
|
695
|
+
try {
|
|
696
|
+
return decodeURIComponent(str);
|
|
697
|
+
}
|
|
698
|
+
catch {
|
|
699
|
+
return str;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Convert ArrayBuffer to Buffer (Node.js)
|
|
704
|
+
* @param ab - ArrayBuffer to convert
|
|
705
|
+
* @returns Buffer
|
|
706
|
+
*/
|
|
707
|
+
function arrayBufferToBuffer(ab) {
|
|
708
|
+
const buf = Buffer.alloc(ab.byteLength);
|
|
709
|
+
const view = new Uint8Array(ab);
|
|
710
|
+
for (let i = 0; i < buf.length; i++) {
|
|
711
|
+
buf[i] = view[i];
|
|
712
|
+
}
|
|
713
|
+
return buf;
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Convert hex string to bytes
|
|
717
|
+
* @param hex - Hex string
|
|
718
|
+
* @returns Uint8Array
|
|
719
|
+
*/
|
|
720
|
+
function hexToBytes(hex) {
|
|
721
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
722
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
723
|
+
bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
|
|
724
|
+
}
|
|
725
|
+
return bytes;
|
|
726
|
+
}
|
|
727
|
+
/**
|
|
728
|
+
* Convert bytes to hex string
|
|
729
|
+
* @param bytes - Byte array
|
|
730
|
+
* @returns Hex string
|
|
731
|
+
*/
|
|
732
|
+
function bytesToHex(bytes) {
|
|
733
|
+
return Array.from(bytes)
|
|
734
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
735
|
+
.join('');
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
var encoding = /*#__PURE__*/Object.freeze({
|
|
739
|
+
__proto__: null,
|
|
740
|
+
arrayBufferToBuffer: arrayBufferToBuffer,
|
|
741
|
+
bytesToHex: bytesToHex,
|
|
742
|
+
decodeUri: decodeUri,
|
|
743
|
+
encodeUri: encodeUri,
|
|
744
|
+
fromBase64: fromBase64,
|
|
745
|
+
hash: hash,
|
|
746
|
+
hexToBytes: hexToBytes,
|
|
747
|
+
toBase64: toBase64
|
|
748
|
+
});
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* Check if a string is a valid emoji
|
|
752
|
+
* @param str - String to check
|
|
753
|
+
* @returns True if string is an emoji
|
|
754
|
+
*/
|
|
755
|
+
function isEmoji(str) {
|
|
756
|
+
const emojiRegex = new RegExp('^(' +
|
|
757
|
+
// Regular and compound emojis
|
|
758
|
+
'(?:\\p{Extended_Pictographic}(?:\\p{Emoji_Modifier}|\\uFE0F)?' +
|
|
759
|
+
'(?:\\u200D\\p{Extended_Pictographic}(?:\\p{Emoji_Modifier}|\\uFE0F)?)*)' +
|
|
760
|
+
'|' +
|
|
761
|
+
// Flags (regional indicator pairs)
|
|
762
|
+
'(?:\\p{Regional_Indicator}{2})' +
|
|
763
|
+
')$', 'u');
|
|
764
|
+
return emojiRegex.test(str);
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Check if a URL is an image link
|
|
768
|
+
* @param url - URL to check
|
|
769
|
+
* @returns True if URL points to an image
|
|
770
|
+
*/
|
|
771
|
+
function isImageUrl(url) {
|
|
772
|
+
const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|webp|svg|ico)(\?.*)?$/i;
|
|
773
|
+
return imageExtensions.test(url);
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Check if a string is a valid email
|
|
777
|
+
* @param email - Email string to validate
|
|
778
|
+
* @returns True if email is valid
|
|
779
|
+
*/
|
|
780
|
+
function isEmail(email) {
|
|
781
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
782
|
+
return emailRegex.test(email);
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Check if a string is a valid URL
|
|
786
|
+
* @param url - URL string to validate
|
|
787
|
+
* @returns True if URL is valid
|
|
788
|
+
*/
|
|
789
|
+
function isUrl(url) {
|
|
790
|
+
try {
|
|
791
|
+
new URL(url);
|
|
792
|
+
return true;
|
|
793
|
+
}
|
|
794
|
+
catch {
|
|
795
|
+
return false;
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* Check if a string contains only numbers
|
|
800
|
+
* @param str - String to check
|
|
801
|
+
* @returns True if string contains only numbers
|
|
802
|
+
*/
|
|
803
|
+
function isNumeric(str) {
|
|
804
|
+
return /^\d+$/.test(str);
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Check if a string contains only letters
|
|
808
|
+
* @param str - String to check
|
|
809
|
+
* @returns True if string contains only letters
|
|
810
|
+
*/
|
|
811
|
+
function isAlpha(str) {
|
|
812
|
+
return /^[a-zA-Z]+$/.test(str);
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Check if a string contains only letters and numbers
|
|
816
|
+
* @param str - String to check
|
|
817
|
+
* @returns True if string is alphanumeric
|
|
818
|
+
*/
|
|
819
|
+
function isAlphanumeric(str) {
|
|
820
|
+
return /^[a-zA-Z0-9]+$/.test(str);
|
|
821
|
+
}
|
|
822
|
+
/**
|
|
823
|
+
* Check if a value is empty (null, undefined, empty string, empty array, empty object)
|
|
824
|
+
* @param value - Value to check
|
|
825
|
+
* @returns True if value is empty
|
|
826
|
+
*/
|
|
827
|
+
function isEmpty(value) {
|
|
828
|
+
if (value === null || value === undefined)
|
|
829
|
+
return true;
|
|
830
|
+
if (typeof value === 'string')
|
|
831
|
+
return value.trim().length === 0;
|
|
832
|
+
if (Array.isArray(value))
|
|
833
|
+
return value.length === 0;
|
|
834
|
+
if (typeof value === 'object')
|
|
835
|
+
return Object.keys(value).length === 0;
|
|
836
|
+
return false;
|
|
837
|
+
}
|
|
838
|
+
/**
|
|
839
|
+
* Check if a value is a plain object
|
|
840
|
+
* @param value - Value to check
|
|
841
|
+
* @returns True if value is a plain object
|
|
842
|
+
*/
|
|
843
|
+
function isPlainObject(value) {
|
|
844
|
+
return (typeof value === 'object' &&
|
|
845
|
+
value !== null &&
|
|
846
|
+
value.constructor === Object &&
|
|
847
|
+
Object.prototype.toString.call(value) === '[object Object]');
|
|
848
|
+
}
|
|
849
|
+
/**
|
|
850
|
+
* Extract URL information from a string
|
|
851
|
+
* @param str - String containing URL
|
|
852
|
+
* @returns URL info or null if no URL found
|
|
853
|
+
*/
|
|
854
|
+
function extractUrl(str) {
|
|
855
|
+
const urlRegex = /(https?:\/\/[^\s]+|www\.[^\s]+|[\w-]+\.[\w-]+[^\s]*)/i;
|
|
856
|
+
const match = str.match(urlRegex);
|
|
857
|
+
if (!match)
|
|
858
|
+
return null;
|
|
859
|
+
const rawUrl = match[0].startsWith('http') ? match[0] : `https://${match[0]}`;
|
|
860
|
+
try {
|
|
861
|
+
const parsed = new URL(rawUrl);
|
|
862
|
+
return {
|
|
863
|
+
url: parsed.href,
|
|
864
|
+
domain: parsed.hostname.replace(/^www\./, ''),
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
catch {
|
|
868
|
+
return null;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* Check if a string is a valid IPv4 address
|
|
873
|
+
* @param ip - IP address string
|
|
874
|
+
* @returns True if valid IPv4
|
|
875
|
+
*/
|
|
876
|
+
function isIPv4(ip) {
|
|
877
|
+
const ipv4Regex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
|
878
|
+
return ipv4Regex.test(ip);
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Check if a string is a valid hex color
|
|
882
|
+
* @param color - Color string
|
|
883
|
+
* @returns True if valid hex color
|
|
884
|
+
*/
|
|
885
|
+
function isHexColor(color) {
|
|
886
|
+
return /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(color);
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
var validation = /*#__PURE__*/Object.freeze({
|
|
890
|
+
__proto__: null,
|
|
891
|
+
extractUrl: extractUrl,
|
|
892
|
+
isAlpha: isAlpha,
|
|
893
|
+
isAlphanumeric: isAlphanumeric,
|
|
894
|
+
isEmail: isEmail,
|
|
895
|
+
isEmoji: isEmoji,
|
|
896
|
+
isEmpty: isEmpty,
|
|
897
|
+
isHexColor: isHexColor,
|
|
898
|
+
isIPv4: isIPv4,
|
|
899
|
+
isImageUrl: isImageUrl,
|
|
900
|
+
isNumeric: isNumeric,
|
|
901
|
+
isPlainObject: isPlainObject,
|
|
902
|
+
isUrl: isUrl
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
/**
|
|
906
|
+
* Format a number with thousands separators
|
|
907
|
+
* @param num - Number to format
|
|
908
|
+
* @param removeTrailingZeros - Remove .00 from integers (default: true)
|
|
909
|
+
* @returns Formatted number string
|
|
910
|
+
*/
|
|
911
|
+
function formatNumber(num, removeTrailingZeros = true) {
|
|
912
|
+
if (typeof num !== 'number') {
|
|
913
|
+
num = Number(num);
|
|
914
|
+
}
|
|
915
|
+
let n = num.toFixed(2);
|
|
916
|
+
if (removeTrailingZeros) {
|
|
917
|
+
n = n.replace('.00', '');
|
|
918
|
+
}
|
|
919
|
+
return n.replace(/.+?(?=\D|$)/, (match) => {
|
|
920
|
+
return match.replace(/(\d)(?=(?:\d{3})+$)/g, '$1 ');
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* Format bytes to human-readable size
|
|
925
|
+
* @param bytes - Number of bytes
|
|
926
|
+
* @param decimals - Decimal places (default: 2)
|
|
927
|
+
* @returns Formatted size string
|
|
928
|
+
*/
|
|
929
|
+
function formatBytes(bytes, decimals = 2) {
|
|
930
|
+
if (bytes === 0)
|
|
931
|
+
return '0 Bytes';
|
|
932
|
+
const k = 1024;
|
|
933
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
|
934
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
935
|
+
return (parseFloat((bytes / Math.pow(k, i)).toFixed(decimals)) + ' ' + sizes[i]);
|
|
936
|
+
}
|
|
937
|
+
/**
|
|
938
|
+
* Format a number as currency
|
|
939
|
+
* @param amount - Amount to format
|
|
940
|
+
* @param currency - Currency code (default: 'USD')
|
|
941
|
+
* @param locale - Locale for formatting (default: 'en-US')
|
|
942
|
+
* @returns Formatted currency string
|
|
943
|
+
*/
|
|
944
|
+
function formatCurrency(amount, currency = 'USD', locale = 'en-US') {
|
|
945
|
+
return new Intl.NumberFormat(locale, {
|
|
946
|
+
style: 'currency',
|
|
947
|
+
currency: currency,
|
|
948
|
+
}).format(amount);
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* Format a phone number (basic US format)
|
|
952
|
+
* @param phone - Phone number string
|
|
953
|
+
* @returns Formatted phone number
|
|
954
|
+
*/
|
|
955
|
+
function formatPhone(phone) {
|
|
956
|
+
const cleaned = phone.replace(/\D/g, '');
|
|
957
|
+
if (cleaned.length === 10) {
|
|
958
|
+
return `(${cleaned.slice(0, 3)}) ${cleaned.slice(3, 6)}-${cleaned.slice(6)}`;
|
|
959
|
+
}
|
|
960
|
+
if (cleaned.length === 11 && cleaned[0] === '1') {
|
|
961
|
+
return `+1 (${cleaned.slice(1, 4)}) ${cleaned.slice(4, 7)}-${cleaned.slice(7)}`;
|
|
962
|
+
}
|
|
963
|
+
return phone;
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* Format a credit card number with spaces
|
|
967
|
+
* @param cardNumber - Card number string
|
|
968
|
+
* @returns Formatted card number
|
|
969
|
+
*/
|
|
970
|
+
function formatCardNumber(cardNumber) {
|
|
971
|
+
const cleaned = cardNumber.replace(/\s/g, '');
|
|
972
|
+
const groups = cleaned.match(/.{1,4}/g);
|
|
973
|
+
return groups ? groups.join(' ') : cardNumber;
|
|
974
|
+
}
|
|
975
|
+
/**
|
|
976
|
+
* Mask sensitive data (show only last N characters)
|
|
977
|
+
* @param str - String to mask
|
|
978
|
+
* @param visibleChars - Number of visible characters at the end (default: 4)
|
|
979
|
+
* @param maskChar - Character to use for masking (default: '*')
|
|
980
|
+
* @returns Masked string
|
|
981
|
+
*/
|
|
982
|
+
function maskString(str, visibleChars = 4, maskChar = '*') {
|
|
983
|
+
if (str.length <= visibleChars)
|
|
984
|
+
return str;
|
|
985
|
+
const masked = maskChar.repeat(str.length - visibleChars);
|
|
986
|
+
return masked + str.slice(-visibleChars);
|
|
987
|
+
}
|
|
988
|
+
/**
|
|
989
|
+
* Format percentage
|
|
990
|
+
* @param value - Value to format
|
|
991
|
+
* @param decimals - Decimal places (default: 2)
|
|
992
|
+
* @returns Formatted percentage string
|
|
993
|
+
*/
|
|
994
|
+
function formatPercentage(value, decimals = 2) {
|
|
995
|
+
return `${value.toFixed(decimals)}%`;
|
|
996
|
+
}
|
|
997
|
+
/**
|
|
998
|
+
* Pluralize a word based on count
|
|
999
|
+
* @param count - Count number
|
|
1000
|
+
* @param singular - Singular form
|
|
1001
|
+
* @param plural - Plural form (optional, will add 's' if not provided)
|
|
1002
|
+
* @returns Pluralized string with count
|
|
1003
|
+
*/
|
|
1004
|
+
function pluralize(count, singular, plural) {
|
|
1005
|
+
const word = count === 1 ? singular : plural || `${singular}s`;
|
|
1006
|
+
return `${count} ${word}`;
|
|
1007
|
+
}
|
|
1008
|
+
/**
|
|
1009
|
+
* Abbreviate large numbers (1000 -> 1K, 1000000 -> 1M)
|
|
1010
|
+
* @param num - Number to abbreviate
|
|
1011
|
+
* @param decimals - Decimal places (default: 1)
|
|
1012
|
+
* @returns Abbreviated number string
|
|
1013
|
+
*/
|
|
1014
|
+
function abbreviateNumber(num, decimals = 1) {
|
|
1015
|
+
if (num < 1000)
|
|
1016
|
+
return num.toString();
|
|
1017
|
+
const units = ['K', 'M', 'B', 'T'];
|
|
1018
|
+
const order = Math.floor(Math.log10(num) / 3);
|
|
1019
|
+
const unitIndex = order - 1;
|
|
1020
|
+
if (unitIndex >= units.length) {
|
|
1021
|
+
return num.toExponential(decimals);
|
|
1022
|
+
}
|
|
1023
|
+
const value = num / Math.pow(1000, order);
|
|
1024
|
+
return `${value.toFixed(decimals)}${units[unitIndex]}`;
|
|
1025
|
+
}
|
|
1026
|
+
/**
|
|
1027
|
+
* Format file name with extension
|
|
1028
|
+
* @param name - File name without extension
|
|
1029
|
+
* @param extension - File extension
|
|
1030
|
+
* @returns Formatted file name
|
|
1031
|
+
*/
|
|
1032
|
+
function formatFileName(name, extension) {
|
|
1033
|
+
const cleanName = name.replace(/[^a-z0-9_-]/gi, '_');
|
|
1034
|
+
const cleanExt = extension.replace(/^\./, '');
|
|
1035
|
+
return `${cleanName}.${cleanExt}`;
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Title case a string (capitalize first letter of each word)
|
|
1039
|
+
* @param str - String to title case
|
|
1040
|
+
* @returns Title cased string
|
|
1041
|
+
*/
|
|
1042
|
+
function titleCase(str) {
|
|
1043
|
+
return str
|
|
1044
|
+
.toLowerCase()
|
|
1045
|
+
.split(' ')
|
|
1046
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
1047
|
+
.join(' ');
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
var format = /*#__PURE__*/Object.freeze({
|
|
1051
|
+
__proto__: null,
|
|
1052
|
+
abbreviateNumber: abbreviateNumber,
|
|
1053
|
+
formatBytes: formatBytes,
|
|
1054
|
+
formatCardNumber: formatCardNumber,
|
|
1055
|
+
formatCurrency: formatCurrency,
|
|
1056
|
+
formatFileName: formatFileName,
|
|
1057
|
+
formatNumber: formatNumber,
|
|
1058
|
+
formatPercentage: formatPercentage,
|
|
1059
|
+
formatPhone: formatPhone,
|
|
1060
|
+
maskString: maskString,
|
|
1061
|
+
pluralize: pluralize,
|
|
1062
|
+
titleCase: titleCase
|
|
1063
|
+
});
|
|
1064
|
+
|
|
1065
|
+
/**
|
|
1066
|
+
* Generate a random integer between min and max (inclusive)
|
|
1067
|
+
* @param min - Minimum value
|
|
1068
|
+
* @param max - Maximum value
|
|
1069
|
+
* @returns Random integer
|
|
1070
|
+
*/
|
|
1071
|
+
function randomInt(min, max) {
|
|
1072
|
+
if (max < min) {
|
|
1073
|
+
[max, min] = [min, max];
|
|
1074
|
+
}
|
|
1075
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
1076
|
+
}
|
|
1077
|
+
/**
|
|
1078
|
+
* Generate a random float between min and max
|
|
1079
|
+
* @param min - Minimum value
|
|
1080
|
+
* @param max - Maximum value
|
|
1081
|
+
* @returns Random float
|
|
1082
|
+
*/
|
|
1083
|
+
function randomFloat(min, max) {
|
|
1084
|
+
if (max < min) {
|
|
1085
|
+
[max, min] = [min, max];
|
|
1086
|
+
}
|
|
1087
|
+
return Math.random() * (max - min) + min;
|
|
1088
|
+
}
|
|
1089
|
+
/**
|
|
1090
|
+
* Generate a random boolean
|
|
1091
|
+
* @param probability - Probability of true (0-1, default: 0.5)
|
|
1092
|
+
* @returns Random boolean
|
|
1093
|
+
*/
|
|
1094
|
+
function randomBoolean(probability = 0.5) {
|
|
1095
|
+
return Math.random() < probability;
|
|
1096
|
+
}
|
|
1097
|
+
/**
|
|
1098
|
+
* Pick N random unique elements from an array
|
|
1099
|
+
* @param arr - Array to pick from
|
|
1100
|
+
* @param count - Number of elements to pick
|
|
1101
|
+
* @returns Array of random elements
|
|
1102
|
+
*/
|
|
1103
|
+
function randomSample(arr, count) {
|
|
1104
|
+
const shuffled = [...arr].sort(() => Math.random() - 0.5);
|
|
1105
|
+
return shuffled.slice(0, Math.min(count, arr.length));
|
|
1106
|
+
}
|
|
1107
|
+
/**
|
|
1108
|
+
* Generate a random hex color
|
|
1109
|
+
* @returns Random hex color string
|
|
1110
|
+
*/
|
|
1111
|
+
function randomColor() {
|
|
1112
|
+
return `#${Math.floor(Math.random() * 16777215)
|
|
1113
|
+
.toString(16)
|
|
1114
|
+
.padStart(6, '0')}`;
|
|
1115
|
+
}
|
|
1116
|
+
/**
|
|
1117
|
+
* Generate a random UUID v4
|
|
1118
|
+
* @returns UUID string
|
|
1119
|
+
*/
|
|
1120
|
+
function randomUUID() {
|
|
1121
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
1122
|
+
const r = (Math.random() * 16) | 0;
|
|
1123
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
1124
|
+
return v.toString(16);
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
1127
|
+
/**
|
|
1128
|
+
* Generate random weighted choice based on weights
|
|
1129
|
+
* @param items - Array of items
|
|
1130
|
+
* @param weights - Array of weights (must match items length)
|
|
1131
|
+
* @returns Random item based on weights
|
|
1132
|
+
*/
|
|
1133
|
+
function randomWeighted(items, weights) {
|
|
1134
|
+
if (items.length !== weights.length) {
|
|
1135
|
+
throw new Error('Items and weights arrays must have the same length');
|
|
1136
|
+
}
|
|
1137
|
+
const totalWeight = weights.reduce((sum, weight) => sum + weight, 0);
|
|
1138
|
+
let random = Math.random() * totalWeight;
|
|
1139
|
+
for (let i = 0; i < items.length; i++) {
|
|
1140
|
+
random -= weights[i];
|
|
1141
|
+
if (random <= 0) {
|
|
1142
|
+
return items[i];
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
return items[items.length - 1];
|
|
1146
|
+
}
|
|
1147
|
+
/**
|
|
1148
|
+
* Generate a random date between two dates
|
|
1149
|
+
* @param start - Start date
|
|
1150
|
+
* @param end - End date
|
|
1151
|
+
* @returns Random date
|
|
1152
|
+
*/
|
|
1153
|
+
function randomDate(start, end) {
|
|
1154
|
+
return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
var random = /*#__PURE__*/Object.freeze({
|
|
1158
|
+
__proto__: null,
|
|
1159
|
+
randomBoolean: randomBoolean,
|
|
1160
|
+
randomColor: randomColor,
|
|
1161
|
+
randomDate: randomDate,
|
|
1162
|
+
randomFloat: randomFloat,
|
|
1163
|
+
randomInt: randomInt,
|
|
1164
|
+
randomSample: randomSample,
|
|
1165
|
+
randomUUID: randomUUID,
|
|
1166
|
+
randomWeighted: randomWeighted
|
|
1167
|
+
});
|
|
1168
|
+
|
|
1169
|
+
/**
|
|
1170
|
+
* Deep clone an object
|
|
1171
|
+
* @param obj - Object to clone
|
|
1172
|
+
* @returns Cloned object
|
|
1173
|
+
*/
|
|
1174
|
+
function deepClone(obj) {
|
|
1175
|
+
if (obj === null || typeof obj !== 'object')
|
|
1176
|
+
return obj;
|
|
1177
|
+
if (obj instanceof Date)
|
|
1178
|
+
return new Date(obj.getTime());
|
|
1179
|
+
if (obj instanceof Array)
|
|
1180
|
+
return obj.map((item) => deepClone(item));
|
|
1181
|
+
if (obj instanceof Object) {
|
|
1182
|
+
const cloned = {};
|
|
1183
|
+
for (const key in obj) {
|
|
1184
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
1185
|
+
cloned[key] = deepClone(obj[key]);
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
return cloned;
|
|
1189
|
+
}
|
|
1190
|
+
return obj;
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* Deep merge two or more objects (mutates target)
|
|
1194
|
+
*/
|
|
1195
|
+
function deepMerge(target, ...sources) {
|
|
1196
|
+
for (const source of sources) {
|
|
1197
|
+
if (!isObject(source))
|
|
1198
|
+
continue;
|
|
1199
|
+
for (const key in source) {
|
|
1200
|
+
if (!Object.prototype.hasOwnProperty.call(source, key))
|
|
1201
|
+
continue;
|
|
1202
|
+
const sourceValue = source[key];
|
|
1203
|
+
const targetValue = target[key];
|
|
1204
|
+
if (isObject(sourceValue)) {
|
|
1205
|
+
if (!isObject(targetValue)) {
|
|
1206
|
+
target[key] = {};
|
|
1207
|
+
}
|
|
1208
|
+
deepMerge(target[key], sourceValue);
|
|
1209
|
+
}
|
|
1210
|
+
else {
|
|
1211
|
+
target[key] = sourceValue;
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
return target;
|
|
1216
|
+
}
|
|
1217
|
+
/**
|
|
1218
|
+
* Get nested property value from object using path
|
|
1219
|
+
* @param obj - Object to get value from
|
|
1220
|
+
* @param path - Property path (e.g., 'user.address.city')
|
|
1221
|
+
* @param defaultValue - Default value if path not found
|
|
1222
|
+
* @returns Property value or default
|
|
1223
|
+
*/
|
|
1224
|
+
function get(obj, path, defaultValue) {
|
|
1225
|
+
const keys = path.split('.');
|
|
1226
|
+
let result = obj;
|
|
1227
|
+
for (const key of keys) {
|
|
1228
|
+
if (result && typeof result === 'object' && key in result) {
|
|
1229
|
+
result = result[key];
|
|
1230
|
+
}
|
|
1231
|
+
else {
|
|
1232
|
+
return defaultValue;
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
return result;
|
|
1236
|
+
}
|
|
1237
|
+
/**
|
|
1238
|
+
* Set nested property value in object using path
|
|
1239
|
+
* @param obj - Object to set value in
|
|
1240
|
+
* @param path - Property path (e.g., 'user.address.city')
|
|
1241
|
+
* @param value - Value to set
|
|
1242
|
+
* @returns Modified object
|
|
1243
|
+
*/
|
|
1244
|
+
function set(obj, path, value) {
|
|
1245
|
+
const keys = path.split('.');
|
|
1246
|
+
const lastKey = keys.pop();
|
|
1247
|
+
let current = obj;
|
|
1248
|
+
for (const key of keys) {
|
|
1249
|
+
if (!(key in current) || typeof current[key] !== 'object') {
|
|
1250
|
+
current[key] = {};
|
|
1251
|
+
}
|
|
1252
|
+
current = current[key];
|
|
1253
|
+
}
|
|
1254
|
+
current[lastKey] = value;
|
|
1255
|
+
return obj;
|
|
1256
|
+
}
|
|
1257
|
+
/**
|
|
1258
|
+
* Pick specific properties from object
|
|
1259
|
+
* @param obj - Source object
|
|
1260
|
+
* @param keys - Keys to pick
|
|
1261
|
+
* @returns New object with picked properties
|
|
1262
|
+
*/
|
|
1263
|
+
function pick(obj, keys) {
|
|
1264
|
+
const result = {};
|
|
1265
|
+
for (const key of keys) {
|
|
1266
|
+
if (key in obj) {
|
|
1267
|
+
result[key] = obj[key];
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
return result;
|
|
1271
|
+
}
|
|
1272
|
+
/**
|
|
1273
|
+
* Omit specific properties from object
|
|
1274
|
+
* @param obj - Source object
|
|
1275
|
+
* @param keys - Keys to omit
|
|
1276
|
+
* @returns New object without omitted properties
|
|
1277
|
+
*/
|
|
1278
|
+
function omit(obj, keys) {
|
|
1279
|
+
const result = { ...obj };
|
|
1280
|
+
for (const key of keys) {
|
|
1281
|
+
delete result[key];
|
|
1282
|
+
}
|
|
1283
|
+
return result;
|
|
1284
|
+
}
|
|
1285
|
+
/**
|
|
1286
|
+
* Check if value is a plain object
|
|
1287
|
+
* @param value - Value to check
|
|
1288
|
+
* @returns True if plain object
|
|
1289
|
+
*/
|
|
1290
|
+
function isObject(value) {
|
|
1291
|
+
return value && typeof value === 'object' && !Array.isArray(value);
|
|
1292
|
+
}
|
|
1293
|
+
/**
|
|
1294
|
+
* Flatten nested object to single level with dot notation keys
|
|
1295
|
+
* @param obj - Object to flatten
|
|
1296
|
+
* @param prefix - Key prefix (used internally)
|
|
1297
|
+
* @returns Flattened object
|
|
1298
|
+
*/
|
|
1299
|
+
function flatten(obj, prefix = '') {
|
|
1300
|
+
const result = {};
|
|
1301
|
+
for (const key in obj) {
|
|
1302
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
1303
|
+
const newKey = prefix ? `${prefix}.${key}` : key;
|
|
1304
|
+
if (isObject(obj[key]) && !Array.isArray(obj[key])) {
|
|
1305
|
+
Object.assign(result, flatten(obj[key], newKey));
|
|
1306
|
+
}
|
|
1307
|
+
else {
|
|
1308
|
+
result[newKey] = obj[key];
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
return result;
|
|
1313
|
+
}
|
|
1314
|
+
/**
|
|
1315
|
+
* Unflatten object with dot notation keys to nested object
|
|
1316
|
+
* @param obj - Flattened object
|
|
1317
|
+
* @returns Nested object
|
|
1318
|
+
*/
|
|
1319
|
+
function unflatten(obj) {
|
|
1320
|
+
const result = {};
|
|
1321
|
+
for (const key in obj) {
|
|
1322
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
1323
|
+
set(result, key, obj[key]);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
return result;
|
|
1327
|
+
}
|
|
1328
|
+
/**
|
|
1329
|
+
* Get all keys from object including nested keys (dot notation)
|
|
1330
|
+
* @param obj - Object to get keys from
|
|
1331
|
+
* @param prefix - Key prefix (used internally)
|
|
1332
|
+
* @returns Array of all keys
|
|
1333
|
+
*/
|
|
1334
|
+
function keys(obj, prefix = '') {
|
|
1335
|
+
const result = [];
|
|
1336
|
+
for (const key in obj) {
|
|
1337
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
1338
|
+
const newKey = prefix ? `${prefix}.${key}` : key;
|
|
1339
|
+
result.push(newKey);
|
|
1340
|
+
if (isObject(obj[key]) && !Array.isArray(obj[key])) {
|
|
1341
|
+
result.push(...keys(obj[key], newKey));
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
return result;
|
|
1346
|
+
}
|
|
1347
|
+
/**
|
|
1348
|
+
* Get all values from object including nested values
|
|
1349
|
+
* @param obj - Object to get values from
|
|
1350
|
+
* @returns Array of all values
|
|
1351
|
+
*/
|
|
1352
|
+
function values(obj) {
|
|
1353
|
+
const result = [];
|
|
1354
|
+
for (const key in obj) {
|
|
1355
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
1356
|
+
if (isObject(obj[key]) && !Array.isArray(obj[key])) {
|
|
1357
|
+
result.push(...values(obj[key]));
|
|
1358
|
+
}
|
|
1359
|
+
else {
|
|
1360
|
+
result.push(obj[key]);
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
return result;
|
|
1365
|
+
}
|
|
1366
|
+
/**
|
|
1367
|
+
* Check if two objects are deeply equal
|
|
1368
|
+
* @param obj1 - First object
|
|
1369
|
+
* @param obj2 - Second object
|
|
1370
|
+
* @returns True if objects are equal
|
|
1371
|
+
*/
|
|
1372
|
+
function isEqual(obj1, obj2) {
|
|
1373
|
+
if (obj1 === obj2)
|
|
1374
|
+
return true;
|
|
1375
|
+
if (typeof obj1 !== 'object' ||
|
|
1376
|
+
typeof obj2 !== 'object' ||
|
|
1377
|
+
obj1 === null ||
|
|
1378
|
+
obj2 === null) {
|
|
1379
|
+
return false;
|
|
1380
|
+
}
|
|
1381
|
+
const keys1 = Object.keys(obj1);
|
|
1382
|
+
const keys2 = Object.keys(obj2);
|
|
1383
|
+
if (keys1.length !== keys2.length)
|
|
1384
|
+
return false;
|
|
1385
|
+
for (const key of keys1) {
|
|
1386
|
+
if (!keys2.includes(key) || !isEqual(obj1[key], obj2[key])) {
|
|
1387
|
+
return false;
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
return true;
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
var object = /*#__PURE__*/Object.freeze({
|
|
1394
|
+
__proto__: null,
|
|
1395
|
+
deepClone: deepClone,
|
|
1396
|
+
deepMerge: deepMerge,
|
|
1397
|
+
flatten: flatten,
|
|
1398
|
+
get: get,
|
|
1399
|
+
isEqual: isEqual,
|
|
1400
|
+
keys: keys,
|
|
1401
|
+
omit: omit,
|
|
1402
|
+
pick: pick,
|
|
1403
|
+
set: set,
|
|
1404
|
+
unflatten: unflatten,
|
|
1405
|
+
values: values
|
|
1406
|
+
});
|
|
1407
|
+
|
|
1408
|
+
// Import all modules
|
|
1409
|
+
// Default export - all utilities in one object (like original System class)
|
|
1410
|
+
const toolkit = {
|
|
1411
|
+
string,
|
|
1412
|
+
array,
|
|
1413
|
+
math,
|
|
1414
|
+
time,
|
|
1415
|
+
encoding,
|
|
1416
|
+
validation,
|
|
1417
|
+
format,
|
|
1418
|
+
random,
|
|
1419
|
+
object,
|
|
1420
|
+
// Convenience shortcuts at top level
|
|
1421
|
+
randomString: randomString,
|
|
1422
|
+
capitalize: capitalize,
|
|
1423
|
+
truncate: truncate,
|
|
1424
|
+
randomElement: randomElement,
|
|
1425
|
+
chunk: chunk,
|
|
1426
|
+
unique: unique,
|
|
1427
|
+
shuffle: shuffle,
|
|
1428
|
+
randomInt: randomInt$1,
|
|
1429
|
+
randomFloat: randomFloat$1,
|
|
1430
|
+
lerp: lerp,
|
|
1431
|
+
clamp: clamp,
|
|
1432
|
+
round: round,
|
|
1433
|
+
timestamp: timestamp,
|
|
1434
|
+
timestampMs: timestampMs,
|
|
1435
|
+
formatDateTime: formatDateTime,
|
|
1436
|
+
formatDuration: formatDuration,
|
|
1437
|
+
sleep: sleep,
|
|
1438
|
+
toBase64: toBase64,
|
|
1439
|
+
fromBase64: fromBase64,
|
|
1440
|
+
hash: hash,
|
|
1441
|
+
isEmail: isEmail,
|
|
1442
|
+
isUrl: isUrl,
|
|
1443
|
+
isEmpty: isEmpty,
|
|
1444
|
+
isEmoji: isEmoji,
|
|
1445
|
+
formatNumber: formatNumber,
|
|
1446
|
+
formatBytes: formatBytes,
|
|
1447
|
+
pluralize: pluralize,
|
|
1448
|
+
randomBoolean: randomBoolean,
|
|
1449
|
+
randomColor: randomColor,
|
|
1450
|
+
randomUUID: randomUUID,
|
|
1451
|
+
deepClone: deepClone,
|
|
1452
|
+
pick: pick,
|
|
1453
|
+
omit: omit,
|
|
1454
|
+
get: get,
|
|
1455
|
+
set: set,
|
|
1456
|
+
};
|
|
1457
|
+
|
|
1458
|
+
export { array, capitalize, chunk, clamp, deepClone, toolkit as default, encoding, format, formatBytes, formatDateTime, formatDuration, formatNumber, fromBase64, get, hash, isEmail, isEmoji, isEmpty, isUrl, lerp, math, object, omit, pick, pluralize, random, randomBoolean, randomColor, randomElement, randomFloat$1 as randomFloat, randomInt$1 as randomInt, randomString, randomUUID, round, set, shuffle, sleep, string, time, timestamp, timestampMs, toBase64, unique, validation };
|
|
1459
|
+
//# sourceMappingURL=index.esm.js.map
|