@react-hive/honey-utils 1.5.0 → 1.7.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/README.md CHANGED
@@ -37,7 +37,7 @@ pnpm add @react-hive/honey-utils
37
37
 
38
38
  ### Importing
39
39
 
40
- ```typescript
40
+ ```ts
41
41
  // Import specific utilities
42
42
  import { toKebabCase, isString, boolFilter } from '@react-hive/honey-utils';
43
43
 
@@ -47,67 +47,185 @@ import * as HoneyUtils from '@react-hive/honey-utils';
47
47
 
48
48
  ### String Utilities
49
49
 
50
- ```typescript
50
+ ```ts
51
51
  import { toKebabCase, camelToDashCase, splitStringIntoWords, hashString } from '@react-hive/honey-utils';
52
52
 
53
- // Convert string to kebab-case
53
+ /**
54
+ * Convert string to kebab-case
55
+ */
54
56
  toKebabCase('helloWorld'); // 'hello-world'
55
57
 
56
- // Convert camelCase to dash-case
58
+ /**
59
+ * Convert camelCase to dash-case
60
+ */
57
61
  camelToDashCase('helloWorld'); // 'hello-world'
58
62
 
59
- // Split string into words
63
+ /**
64
+ * Split string into words
65
+ */
60
66
  splitStringIntoWords('hello world'); // ['hello', 'world']
61
67
 
62
- // Generate a hash from a string
68
+ /**
69
+ * Generate a hash from a string
70
+ */
63
71
  const hash = hashString('background-color: red;'); // 'e4k1z0x'
64
72
  ```
65
73
 
66
74
  ### Array Utilities
67
75
 
68
- ```typescript
69
- import {
70
- boolFilter,
71
- unique,
72
- chunk,
73
- intersection,
74
- difference
76
+ ```ts
77
+ import {
78
+ boolFilter,
79
+ unique,
80
+ chunk,
81
+ intersection,
82
+ difference,
83
+ mapAsync,
84
+ forAsync,
85
+ reduceAsync,
86
+ filterAsync,
87
+ someAsync,
88
+ everyAsync,
89
+ findAsync,
90
+ pipe,
91
+ compose,
75
92
  } from '@react-hive/honey-utils';
76
93
 
77
- // Filter out falsy values from an array
78
- boolFilter([0, 1, false, 2, '', 3, null, undefined, true]); // [1, 2, 3, true]
79
-
80
- // Remove duplicate values from an array
81
- unique([1, 2, 2, 3, 1, 4]); // [1, 2, 3, 4]
82
-
83
- // Split an array into chunks of specified size
84
- chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]
85
-
86
- // Find common elements between arrays
87
- intersection([1, 2, 3], [2, 3, 4]); // [2, 3]
88
-
89
- // Find elements in one array not in another
90
- difference([1, 2, 3, 4], [2, 4]); // [1, 3]
94
+ /**
95
+ * Filter out falsy values from an array
96
+ */
97
+ boolFilter([0, 1, false, 2, '', 3, null, undefined, true]);
98
+ // [1, 2, 3, true]
99
+
100
+ /**
101
+ * Remove duplicate values from an array
102
+ */
103
+ unique([1, 2, 2, 3, 1, 4]);
104
+ // ➜ [1, 2, 3, 4]
105
+
106
+ /**
107
+ * Split an array into chunks of specified size
108
+ */
109
+ chunk([1, 2, 3, 4, 5], 2);
110
+ // ➜ [[1, 2], [3, 4], [5]]
111
+
112
+ /**
113
+ * Find common elements between arrays
114
+ */
115
+ intersection([1, 2, 3], [2, 3, 4]);
116
+ // ➜ [2, 3]
117
+
118
+ /**
119
+ * Find elements in one array not in another
120
+ */
121
+ difference([1, 2, 3, 4], [2, 4]);
122
+ // ➜ [1, 3]
123
+
124
+ /**
125
+ * Run async operations in parallel and collect results
126
+ */
127
+ await mapAsync([1, 2, 3], async (n) => {
128
+ await delay(100);
129
+ return n * 2;
130
+ });
131
+ // ➜ [2, 4, 6]
132
+
133
+ /**
134
+ * Run async operations sequentially and collect results
135
+ */
136
+ await forAsync([1, 2, 3], async (n, i) => {
137
+ await delay(100);
138
+ return n * i;
139
+ });
140
+ // ➜ [0, 2, 6]
141
+
142
+ /**
143
+ * Reduce array asynchronously
144
+ */
145
+ await reduceAsync([1, 2, 3], async (acc, n) => {
146
+ await delay(50);
147
+ return acc + n;
148
+ }, 0);
149
+ // ➜ 6
150
+
151
+ /**
152
+ * Filter array asynchronously
153
+ */
154
+ await filterAsync([1, 2, 3, 4], async (n) => {
155
+ await delay(30);
156
+ return n % 2 === 0;
157
+ });
158
+ // ➜ [2, 4]
159
+
160
+ /**
161
+ * Check if some items match condition asynchronously
162
+ */
163
+ await someAsync([1, 3, 5], async (n) => {
164
+ await delay(10);
165
+ return n % 2 === 0;
166
+ });
167
+ // ➜ false
168
+
169
+ /**
170
+ * Check if all items match condition asynchronously
171
+ */
172
+ await everyAsync([2, 4, 6], async (n) => {
173
+ await delay(10);
174
+ return n % 2 === 0;
175
+ });
176
+ // ➜ true
177
+
178
+ /**
179
+ * Find first matching item asynchronously
180
+ */
181
+ await findAsync([1, 3, 4, 5], async (n) => {
182
+ await delay(20);
183
+ return n % 2 === 0;
184
+ });
185
+ // ➜ 4
186
+
187
+ /**
188
+ * Compose functions from left to right
189
+ */
190
+ const double = (n: number) => n * 2;
191
+ const increment = (n: number) => n + 1;
192
+
193
+ pipe(double, increment)(3);
194
+ // ➜ 7 → increment(double(3)) → increment(6)
195
+
196
+ /**
197
+ * Compose functions from right to left
198
+ */
199
+ compose(increment, double)(3);
200
+ // ➜ 7 → increment(double(3)) → increment(6)
91
201
  ```
92
202
 
93
203
  ### Function Utilities
94
204
 
95
- ```typescript
205
+ ```ts
96
206
  import { noop, invokeIfFunction, delay, retry } from '@react-hive/honey-utils';
97
207
 
98
- // No-operation function
99
- noop(); // does nothing
208
+ /**
209
+ * No-operation function. Does nothing
210
+ */
211
+ noop();
100
212
 
101
- // Invoke if function, otherwise return value
213
+ /**
214
+ * Invoke if function, otherwise return value
215
+ */
102
216
  const fn = (x: number) => x * 2;
103
217
 
104
218
  invokeIfFunction(fn, 5); // 10
105
219
  invokeIfFunction('not a function', 5); // 'not a function'
106
220
 
107
- // Create a promise that resolves after a specified delay
108
- await delay(1000); // Waits for 1 second before continuing
221
+ /**
222
+ * Waits for 1 second before continuing
223
+ */
224
+ await delay(1000);
109
225
 
110
- // Retry an async function with configurable options
226
+ /**
227
+ * Retry an async function with configurable options
228
+ */
111
229
  async function fetchData() {
112
230
  const response = await fetch('/api/data');
113
231
 
@@ -134,7 +252,7 @@ fetchWithRetry()
134
252
 
135
253
  ### Type Guards
136
254
 
137
- ```typescript
255
+ ```ts
138
256
  import {
139
257
  isString,
140
258
  isNumber,
@@ -156,105 +274,157 @@ import {
156
274
  isSet
157
275
  } from '@react-hive/honey-utils';
158
276
 
159
- // Check if value is a string
277
+ /**
278
+ * Check if value is a string
279
+ */
160
280
  isString('hello'); // true
161
281
  isString(123); // false
162
282
 
163
- // Check if value is a number
283
+ /**
284
+ * Check if value is a number
285
+ */
164
286
  isNumber(123); // true
165
287
  isNumber('123'); // false
166
288
 
167
- // Check if value is a boolean
289
+ /**
290
+ * Check if value is a boolean
291
+ */
168
292
  isBool(true); // true
169
293
  isBool('true'); // false
170
294
 
171
- // Check if value is an object
295
+ /**
296
+ * Check if value is an object
297
+ */
172
298
  isObject({}); // true
173
299
  isObject('object'); // false
174
300
 
175
- // Check if value is a function
301
+ /**
302
+ * Check if value is a function
303
+ */
176
304
  isFunction(() => {}); // true
177
305
  isFunction({}); // false
178
306
 
179
- // Check if value is a Promise
307
+ /**
308
+ * Check if value is a Promise
309
+ */
180
310
  isPromise(Promise.resolve()); // true
181
311
  isPromise({}); // false
182
312
 
183
- // Check if value is null or undefined
313
+ /**
314
+ * Check if value is null or undefined
315
+ */
184
316
  isNil(null); // true
185
317
  isNil(undefined); // true
186
318
  isNil(''); // false
187
319
 
188
- // Check if value is null, undefined, or empty string
320
+ /**
321
+ * Check if value is null, undefined, or empty string
322
+ */
189
323
  isNilOrEmptyString(''); // true
190
324
  isNilOrEmptyString(null); // true
191
325
  isNilOrEmptyString('hello'); // false
192
326
 
193
- // Check if value is an array
327
+ /**
328
+ * Check if value is an array
329
+ */
194
330
  isArray([1, 2, 3]); // true
195
331
  isArray({}); // false
196
332
 
197
- // Check if value is an empty array
333
+ /**
334
+ * Check if value is an empty array
335
+ */
198
336
  isEmptyArray([]); // true
199
337
  isEmptyArray([1, 2, 3]); // false
200
338
 
201
- // Check if value is an empty object
339
+ /**
340
+ * Check if value is an empty object
341
+ */
202
342
  isEmptyObject({}); // true
203
343
  isEmptyObject({ key: 'value' }); // false
204
344
 
205
- // Check if value is a Date object
345
+ /**
346
+ * Check if value is a Date object
347
+ */
206
348
  isDate(new Date()); // true
207
349
  isDate('2023-01-01'); // false
208
350
 
209
- // Check if value is a valid Date object
351
+ /**
352
+ * Check if value is a valid Date object
353
+ */
210
354
  isValidDate(new Date()); // true
211
355
  isValidDate(new Date('invalid')); // false
212
356
 
213
- // Check if value is a RegExp
357
+ /**
358
+ * Check if value is a RegExp
359
+ */
214
360
  isRegExp(/test/); // true
215
361
  isRegExp('test'); // false
216
362
 
217
- // Check if value is a Map or Set
363
+ /**
364
+ * Check if value is a Map or Set
365
+ */
218
366
  isMap(new Map()); // true
219
367
  isSet(new Set()); // true
220
368
  ```
221
369
 
222
370
  ### Math Utilities
223
371
 
224
- ```typescript
372
+ ```ts
225
373
  import {
226
374
  calculateEuclideanDistance,
227
375
  calculateMovingSpeed,
228
376
  calculatePercentage
229
377
  } from '@react-hive/honey-utils';
230
378
 
231
- // Calculate Euclidean distance between two points
379
+ /**
380
+ * Calculate Euclidean distance between two points
381
+ */
232
382
  calculateEuclideanDistance(0, 0, 3, 4); // 5
233
383
 
234
- // Calculate moving speed
384
+ /**
385
+ * Calculate moving speed
386
+ */
235
387
  calculateMovingSpeed(100, 5); // 20
236
388
 
237
- // Calculate percentage of a value
389
+ /**
390
+ * Calculate percentage of a value
391
+ */
238
392
  calculatePercentage(200, 25); // 50
239
393
  ```
240
394
 
241
395
  ### DOM Utilities
242
396
 
243
- ```typescript
244
- import { getTransformationValues } from '@react-hive/honey-utils';
397
+ ```ts
398
+ import { parse2DMatrix, cloneBlob, convertBlobToFile } from '@react-hive/honey-utils';
245
399
 
246
- // Get transformation values from an HTML element
400
+ // Extract transformation values from an HTML element's 2D matrix
247
401
  const element = document.getElementById('my-element');
248
402
  if (element) {
249
- const { translateX, translateY } = getTransformationValues(element);
403
+ const { translateX, translateY, scaleX, scaleY, skewX, skewY } = parse2DMatrix(element);
250
404
 
251
405
  console.log(`Element is translated by ${translateX}px horizontally and ${translateY}px vertically`);
406
+ console.log(`Element is scaled by ${scaleX} horizontally and ${scaleY} vertically`);
407
+ console.log(`Element is skewed by ${skewX} horizontally and ${skewY} vertically`);
252
408
  }
409
+
410
+ // Clone a Blob object
411
+ const originalBlob = new Blob(['Hello World'], { type: 'text/plain' });
412
+ const clonedBlob = cloneBlob(originalBlob);
413
+
414
+ console.log(clonedBlob.type); // 'text/plain'
415
+
416
+ // Convert a Blob to a File
417
+ const blob = new Blob(['Hello world'], { type: 'text/plain' });
418
+ const file = convertBlobToFile(blob, 'hello.txt');
419
+
420
+ console.log(file instanceof File); // true
421
+ console.log(file.name); // 'hello.txt'
422
+ console.log(file.type); // 'text/plain'
253
423
  ```
254
424
 
255
425
  ### Assert Function
256
426
 
257
- ```typescript
427
+ ```ts
258
428
  import { assert } from '@react-hive/honey-utils';
259
429
 
260
430
  // Assert a condition
@@ -268,64 +438,77 @@ function divide(a: number, b: number): number {
268
438
 
269
439
  ### String Utilities
270
440
 
271
- - **toKebabCase(input: string): string** - Converts a string to kebab-case
272
- - **camelToDashCase(input: string): string** - Converts camelCase to dash-case
273
- - **splitStringIntoWords(input: string): string[]** - Splits a string into an array of words
274
- - **hashString(input: string): string** - Generates a short hash from a string
441
+ - `toKebabCase(input: string): string` - Converts a string to kebab-case.
442
+ - `camelToDashCase(input: string): string` - Converts camelCase to dash-case.
443
+ - `splitStringIntoWords(input: string): string[]` - Splits a string into an array of words.
444
+ - `hashString(input: string): string` - Generates a short hash from a string.
275
445
 
276
446
  ### Array Utilities
277
447
 
278
- - **boolFilter<T>(array: (T | false | null | undefined)[]): T[]** - Filters out falsy values from an array
279
- - **unique<T>(array: T[]): T[]** - Returns a new array with duplicate values removed
280
- - **chunk<T>(array: T[], size: number): T[][]** - Splits an array into chunks of the specified size
281
- - **intersection<T>(...arrays: T[][]): T[]** - Returns an array containing elements that exist in all provided arrays
282
- - **difference<T>(array: T[], exclude: T[]): T[]** - Returns elements from the first array that don't exist in the second array
448
+ #### Synchronous Utilities
449
+
450
+ - `boolFilter<T>(array: (T | false | null | undefined)[]): T[]` - Filters out falsy values (`false`, `null`, `undefined`) from an array while keeping valid items.
451
+ - `unique<T>(array: T[]): T[]` - Returns a new array with all duplicate elements removed. Keeps only the first occurrence of each value.
452
+ - `chunk<T>(array: T[], size: number): T[][]` - Splits an array into smaller arrays ("chunks") of the specified size.
453
+ - `intersection<T>(...arrays: T[][]): T[]` - Returns an array of elements that exist in all provided arrays.
454
+ - `difference<T>(array: T[], exclude: T[]): T[]` - Returns a new array that contains items from `array` that are not present in `exclude`.
455
+ - `pipe(...fns: Function[]): Function` - Composes unary functions left-to-right. Returns a new function that applies all given functions in a sequence.
456
+ - `compose(...fns: Function[]): Function` - Composes unary functions **right-to-left**. Same as `pipe`, but applies functions in reverse order.
457
+
458
+ #### Asynchronous Utilities
459
+
460
+ - `forAsync<Item, Result>(array: Item[], predicate: (item, index, array) => Promise<Result>): Promise<Result[]>` - Runs asynchronous operations on each array item *sequentially* and returns the results in the original order.
461
+ - `mapAsync<Item, Return>(array: Item[], predicate: (item, index, array) => Promise<Return>): Promise<Return[]>` - Executes an asynchronous function for each array item *in parallel* and returns a promise of all results.
462
+ - `reduceAsync<Item, Accumulator>(array: Item[], predicate, initialValue): Promise<Accumulator>` - Asynchronously reduces an array to a single accumulated value. Each step waits for the previous promise to resolve.
463
+ - `filterAsync<Item>(array: Item[], predicate): Promise<Item[]>` - Runs an asynchronous filter operation. Only includes items where `predicate(item)` resolves to `true`.
464
+ - `someAsync<Item>(array: Item[], predicate): Promise<boolean>` - Returns `true` if **any** item in the array passes the async predicate.
465
+ - `everyAsync<Item>(array: Item[], predicate): Promise<boolean>` - Returns `true` if **all** items in the array pass the async predicate.
466
+ - `findAsync<Item>(array: Item[], predicate): Promise<Item | null>` - Returns the first array item that passes the async predicate, or `null` if no match is found.
283
467
 
284
468
  ### Function Utilities
285
469
 
286
- - **noop(): void** - A no-operation function
287
- - **invokeIfFunction<Args extends any[], Result>(input: ((...args: Args) => Result) | Result, ...args: Args): Result** - Invokes the input if it's a function, otherwise returns it as-is
288
- - **delay(delayMs: number): Promise<void>** - Creates a promise that resolves after the specified delay in milliseconds
289
- - **retry<Task, TaskResult>(task: Task, options?: RetryOptions): Function** - Wraps an asynchronous function with retry logic, with configurable max attempts, delay between retries, exponential backoff, and retry callbacks
470
+ - `noop(): void` - A no-operation function.
471
+ - `invokeIfFunction<Args extends any[], Result>(input: ((...args: Args) => Result) | Result, ...args: Args): Result` - Invokes the input if it's a function, otherwise returns it as-is.
472
+ - `delay(delayMs: number): Promise<void>` - Creates a promise that resolves after the specified delay in milliseconds.
473
+ - `retry<Task, TaskResult>(task: Task, options?: RetryOptions): Function` - Wraps an asynchronous function with retry logic, with configurable max attempts, delay between retries, exponential backoff, and retry callbacks.
290
474
 
291
475
  ### Type Guards
292
476
 
293
- - **isString(value: unknown): value is string** - Checks if a value is a string
294
- - **isNumber(value: unknown): value is number** - Checks if a value is a number
295
- - **isBool(value: unknown): value is boolean** - Checks if a value is a boolean
296
- - **isObject(value: unknown): value is object** - Checks if a value is an object
297
- - **isFunction(value: unknown): value is Function** - Checks if a value is a function
298
- - **isPromise<T = unknown>(value: unknown): value is Promise<T>** - Checks if a value is a Promise
299
- - **isNil(value: unknown): value is null | undefined** - Checks if a value is null or undefined
300
- - **isNilOrEmptyString(value: unknown): value is null | undefined** - Checks if a value is null, undefined, or an empty string
301
- - **isArray(value: unknown): value is unknown[]** - Checks if a value is an array
302
- - **isEmptyArray(value: unknown): value is []** - Checks if a value is an empty array
303
- - **isEmptyObject(value: unknown): value is Record<string, never>** - Checks if a value is an empty object
304
- - **isNull(value: unknown): value is null** - Checks if a value is null
305
- - **isUndefined(value: unknown): value is undefined** - Checks if a value is undefined
306
- - **isFiniteNumber(value: unknown): value is number** - Checks if a value is a finite number
307
- - **isInteger(value: unknown): value is number** - Checks if a value is an integer
308
- - **isNaN(value: unknown): boolean** - Checks if a value is NaN
309
- - **isDate(value: unknown): value is Date** - Checks if a value is a Date object
310
- - **isValidDate(value: unknown): value is Date** - Checks if a value is a valid Date object (not Invalid Date)
311
- - **isRegExp(value: unknown): value is RegExp** - Checks if a value is a RegExp object
312
- - **isMap(value: unknown): value is Map<unknown, unknown>** - Checks if a value is a Map
313
- - **isSet(value: unknown): value is Set<unknown>** - Checks if a value is a Set
314
- - **isSymbol(value: unknown): value is symbol** - Checks if a value is a Symbol
477
+ - `assert(condition: any, message: string): asserts condition` - Asserts that a condition is truthy, throwing an error with the provided message if it's not.
478
+ - `isString(value: unknown): value is string` - Checks if a value is a `string`.
479
+ - `isNumber(value: unknown): value is number` - Checks if a value is a `number`.
480
+ - `isBool(value: unknown): value is boolean` - Checks if a value is a `boolean`.
481
+ - `isObject(value: unknown): value is object` - Checks if a value is an `object`.
482
+ - `isFunction(value: unknown): value is Function` - Checks if a value is a `function`.
483
+ - `isPromise<T = unknown>(value: unknown): value is Promise<T>` - Checks if a value is a `Promise`.
484
+ - `isNil(value: unknown): value is null | undefined` - Checks if a value is `null` or `undefined`.
485
+ - `isNilOrEmptyString(value: unknown): value is null | undefined` - Checks if a value is `null`, `undefined`, or an empty string.
486
+ - `isArray(value: unknown): value is unknown[]` - Checks if a value is an array.
487
+ - `isEmptyArray(value: unknown): value is []` - Checks if a value is an empty array.
488
+ - `isEmptyObject(value: unknown): value is Record<string, never>` - Checks if a value is an empty object.
489
+ - `isNull(value: unknown): value is null` - Checks if a value is `null`.
490
+ - `isUndefined(value: unknown): value is undefined` - Checks if a value is `undefined`.
491
+ - `isDefined<T>(value: T): value is NonNullable<T>` - Checks if a value is neither `null` nor `undefined`.
492
+ - `isFiniteNumber(value: unknown): value is number` - Checks if a value is a finite number.
493
+ - `isInteger(value: unknown): value is number` - Checks if a value is an integer.
494
+ - `isDate(value: unknown): value is Date` - Checks if a value is a `Date` object.
495
+ - `isValidDate(value: unknown): value is Date` - Checks if a value is a valid `Date` object.
496
+ - `isRegExp(value: unknown): value is RegExp` - Checks if a value is a `RegExp` object.
497
+ - `isMap(value: unknown): value is Map<unknown, unknown>` - Checks if a value is a `Map`.
498
+ - `isSet(value: unknown): value is Set<unknown>` - Checks if a value is a `Set`.
499
+ - `isSymbol(value: unknown): value is symbol` - Checks if a value is a `Symbol`.
315
500
 
316
501
  ### Math Utilities
317
502
 
318
- - **calculateEuclideanDistance(startX: number, startY: number, endX: number, endY: number): number** - Calculates the Euclidean distance between two points
319
- - **calculateMovingSpeed(delta: number, elapsedTime: number): number** - Calculates moving speed
320
- - **calculatePercentage(value: number, percentage: number): number** - Calculates the specified percentage of a value
503
+ - `calculateEuclideanDistance(startX: number, startY: number, endX: number, endY: number): number` - Calculates the Euclidean distance between two points.
504
+ - `calculateMovingSpeed(delta: number, elapsedTime: number): number` - Calculates moving speed.
505
+ - `calculatePercentage(value: number, percentage: number): number` - Calculates the specified percentage of a value.
321
506
 
322
507
  ### DOM Utilities
323
508
 
324
- - **getTransformationValues(element: HTMLElement): { translateX: number, translateY: number }** - Gets transformation values from an HTML element
325
-
326
- ### Other Utilities
327
-
328
- - **assert(condition: any, message: string): asserts condition** - Asserts that a condition is truthy, throwing an error with the provided message if it's not
509
+ - `parse2DMatrix(element: HTMLElement): { translateX: number, translateY: number, scaleX: number, scaleY: number, skewX: number, skewY: number }` - Extracts transformation values (translate, scale, skew) from the 2D transformation matrix of a given HTML element.
510
+ - `cloneBlob(blob: Blob): Blob` - Creates a clone of a Blob object with the same content and type as the original.
511
+ - `convertBlobToFile(blob: Blob, fileName: string): File` - Converts a Blob object into a File object with the specified name.
329
512
 
330
513
  ## Contributing
331
514