@react-hive/honey-utils 1.4.0 โ†’ 1.6.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
@@ -3,10 +3,16 @@
3
3
  [![npm version](https://img.shields.io/npm/v/@react-hive/honey-utils.svg)](https://www.npmjs.com/package/@react-hive/honey-utils)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
+ <p align="center">
7
+ <img src="./logo.png" alt="honey-utils logo" width="200" height="200">
8
+ </p>
9
+
6
10
  A lightweight TypeScript utility library providing a collection of helper functions for common programming tasks.
7
11
 
8
12
  ## Features
9
13
 
14
+ ---
15
+
10
16
  - ๐Ÿ” **Type Guards** - Functions for runtime type checking
11
17
  - ๐Ÿงต **String Utilities** - String manipulation and transformation
12
18
  - ๐Ÿ”ข **Array Utilities** - Array filtering and manipulation
@@ -18,6 +24,8 @@ A lightweight TypeScript utility library providing a collection of helper functi
18
24
 
19
25
  ## Installation
20
26
 
27
+ ---
28
+
21
29
  ```bash
22
30
  # Using npm
23
31
  npm install @react-hive/honey-utils
@@ -31,9 +39,11 @@ pnpm add @react-hive/honey-utils
31
39
 
32
40
  ## Usage
33
41
 
42
+ ---
43
+
34
44
  ### Importing
35
45
 
36
- ```typescript
46
+ ```ts
37
47
  // Import specific utilities
38
48
  import { toKebabCase, isString, boolFilter } from '@react-hive/honey-utils';
39
49
 
@@ -43,7 +53,7 @@ import * as HoneyUtils from '@react-hive/honey-utils';
43
53
 
44
54
  ### String Utilities
45
55
 
46
- ```typescript
56
+ ```ts
47
57
  import { toKebabCase, camelToDashCase, splitStringIntoWords, hashString } from '@react-hive/honey-utils';
48
58
 
49
59
  // Convert string to kebab-case
@@ -61,35 +71,103 @@ const hash = hashString('background-color: red;'); // 'e4k1z0x'
61
71
 
62
72
  ### Array Utilities
63
73
 
64
- ```typescript
65
- import {
66
- boolFilter,
67
- unique,
68
- chunk,
69
- intersection,
70
- difference
74
+ ```ts
75
+ import {
76
+ boolFilter,
77
+ unique,
78
+ chunk,
79
+ intersection,
80
+ difference,
81
+ mapAsync,
82
+ forAsync,
83
+ reduceAsync,
84
+ filterAsync,
85
+ someAsync,
86
+ everyAsync,
87
+ findAsync,
71
88
  } from '@react-hive/honey-utils';
72
89
 
73
90
  // Filter out falsy values from an array
74
- boolFilter([0, 1, false, 2, '', 3, null, undefined, true]); // [1, 2, 3, true]
91
+ boolFilter([0, 1, false, 2, '', 3, null, undefined, true]);
92
+ // โžœ [1, 2, 3, true]
75
93
 
76
94
  // Remove duplicate values from an array
77
- unique([1, 2, 2, 3, 1, 4]); // [1, 2, 3, 4]
95
+ unique([1, 2, 2, 3, 1, 4]);
96
+ // โžœ [1, 2, 3, 4]
78
97
 
79
98
  // Split an array into chunks of specified size
80
- chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]
99
+ chunk([1, 2, 3, 4, 5], 2);
100
+ // โžœ [[1, 2], [3, 4], [5]]
81
101
 
82
102
  // Find common elements between arrays
83
- intersection([1, 2, 3], [2, 3, 4]); // [2, 3]
103
+ intersection([1, 2, 3], [2, 3, 4]);
104
+ // โžœ [2, 3]
84
105
 
85
106
  // Find elements in one array not in another
86
- difference([1, 2, 3, 4], [2, 4]); // [1, 3]
107
+ difference([1, 2, 3, 4], [2, 4]);
108
+ // โžœ [1, 3]
109
+
110
+ // Run async operations in parallel and collect results
111
+ await mapAsync([1, 2, 3], async (n) => {
112
+ await delay(100);
113
+
114
+ return n * 2;
115
+ });
116
+ // โžœ [2, 4, 6]
117
+
118
+ // Run async operations sequentially and collect results
119
+ await forAsync([1, 2, 3], async (n, i) => {
120
+ await delay(100);
121
+
122
+ return n * i;
123
+ });
124
+ // โžœ [0, 2, 6]
125
+
126
+ // Reduce array asynchronously
127
+ await reduceAsync([1, 2, 3], async (acc, n) => {
128
+ await delay(50);
129
+
130
+ return acc + n;
131
+ }, 0);
132
+ // โžœ 6
133
+
134
+ // Filter array asynchronously
135
+ await filterAsync([1, 2, 3, 4], async (n) => {
136
+ await delay(30);
137
+
138
+ return n % 2 === 0;
139
+ });
140
+ // โžœ [2, 4]
141
+
142
+ // Check if some items match condition asynchronously
143
+ await someAsync([1, 3, 5], async (n) => {
144
+ await delay(10);
145
+
146
+ return n % 2 === 0;
147
+ });
148
+ // โžœ false
149
+
150
+ // Check if all items match condition asynchronously
151
+ await everyAsync([2, 4, 6], async (n) => {
152
+ await delay(10);
153
+
154
+ return n % 2 === 0;
155
+ });
156
+ // โžœ true
157
+
158
+ // Find first matching item asynchronously
159
+ await findAsync([1, 3, 4, 5], async (n) => {
160
+ await delay(20);
161
+
162
+ return n % 2 === 0;
163
+ });
164
+ // โžœ 4
87
165
  ```
88
166
 
89
167
  ### Function Utilities
90
168
 
91
- ```typescript
92
- import { noop, invokeIfFunction } from '@react-hive/honey-utils';
169
+ ```ts
170
+ import { noop, invokeIfFunction, delay, retry } from '@react-hive/honey-utils';
93
171
 
94
172
  // No-operation function
95
173
  noop(); // does nothing
@@ -99,11 +177,38 @@ const fn = (x: number) => x * 2;
99
177
 
100
178
  invokeIfFunction(fn, 5); // 10
101
179
  invokeIfFunction('not a function', 5); // 'not a function'
180
+
181
+ // Create a promise that resolves after a specified delay
182
+ await delay(1000); // Waits for 1 second before continuing
183
+
184
+ // Retry an async function with configurable options
185
+ async function fetchData() {
186
+ const response = await fetch('/api/data');
187
+
188
+ if (!response.ok) {
189
+ throw new Error('Network error');
190
+ }
191
+
192
+ return await response.json();
193
+ }
194
+
195
+ const fetchWithRetry = retry(fetchData, {
196
+ maxAttempts: 5,
197
+ delayMs: 500,
198
+ backoff: true,
199
+ onRetry: (attempt, error) => {
200
+ console.warn(`Attempt ${attempt} failed:`, error);
201
+ }
202
+ });
203
+
204
+ fetchWithRetry()
205
+ .then(data => console.log('Success:', data))
206
+ .catch(error => console.error('Failed after retries:', error));
102
207
  ```
103
208
 
104
209
  ### Type Guards
105
210
 
106
- ```typescript
211
+ ```ts
107
212
  import {
108
213
  isString,
109
214
  isNumber,
@@ -190,7 +295,7 @@ isSet(new Set()); // true
190
295
 
191
296
  ### Math Utilities
192
297
 
193
- ```typescript
298
+ ```ts
194
299
  import {
195
300
  calculateEuclideanDistance,
196
301
  calculateMovingSpeed,
@@ -209,21 +314,37 @@ calculatePercentage(200, 25); // 50
209
314
 
210
315
  ### DOM Utilities
211
316
 
212
- ```typescript
213
- import { getTransformationValues } from '@react-hive/honey-utils';
317
+ ```ts
318
+ import { parse2DMatrix, cloneBlob, convertBlobToFile } from '@react-hive/honey-utils';
214
319
 
215
- // Get transformation values from an HTML element
320
+ // Extract transformation values from an HTML element's 2D matrix
216
321
  const element = document.getElementById('my-element');
217
322
  if (element) {
218
- const { translateX, translateY } = getTransformationValues(element);
323
+ const { translateX, translateY, scaleX, scaleY, skewX, skewY } = parse2DMatrix(element);
219
324
 
220
325
  console.log(`Element is translated by ${translateX}px horizontally and ${translateY}px vertically`);
326
+ console.log(`Element is scaled by ${scaleX} horizontally and ${scaleY} vertically`);
327
+ console.log(`Element is skewed by ${skewX} horizontally and ${skewY} vertically`);
221
328
  }
329
+
330
+ // Clone a Blob object
331
+ const originalBlob = new Blob(['Hello World'], { type: 'text/plain' });
332
+ const clonedBlob = cloneBlob(originalBlob);
333
+
334
+ console.log(clonedBlob.type); // 'text/plain'
335
+
336
+ // Convert a Blob to a File
337
+ const blob = new Blob(['Hello world'], { type: 'text/plain' });
338
+ const file = convertBlobToFile(blob, 'hello.txt');
339
+
340
+ console.log(file instanceof File); // true
341
+ console.log(file.name); // 'hello.txt'
342
+ console.log(file.type); // 'text/plain'
222
343
  ```
223
344
 
224
345
  ### Assert Function
225
346
 
226
- ```typescript
347
+ ```ts
227
348
  import { assert } from '@react-hive/honey-utils';
228
349
 
229
350
  // Assert a condition
@@ -235,64 +356,78 @@ function divide(a: number, b: number): number {
235
356
 
236
357
  ## API Documentation
237
358
 
359
+ ---
360
+
238
361
  ### String Utilities
239
362
 
240
- - **toKebabCase(input: string): string** - Converts a string to kebab-case
241
- - **camelToDashCase(input: string): string** - Converts camelCase to dash-case
242
- - **splitStringIntoWords(input: string): string[]** - Splits a string into an array of words
243
- - **hashString(input: string): string** - Generates a short hash from a string
363
+ - `toKebabCase(input: string): string` - Converts a string to kebab-case.
364
+ - `camelToDashCase(input: string): string` - Converts camelCase to dash-case.
365
+ - `splitStringIntoWords(input: string): string[]` - Splits a string into an array of words.
366
+ - `hashString(input: string): string` - Generates a short hash from a string.
244
367
 
245
368
  ### Array Utilities
246
369
 
247
- - **boolFilter<T>(array: (T | false | null | undefined)[]): T[]** - Filters out falsy values from an array
248
- - **unique<T>(array: T[]): T[]** - Returns a new array with duplicate values removed
249
- - **chunk<T>(array: T[], size: number): T[][]** - Splits an array into chunks of the specified size
250
- - **intersection<T>(...arrays: T[][]): T[]** - Returns an array containing elements that exist in all provided arrays
251
- - **difference<T>(array: T[], exclude: T[]): T[]** - Returns elements from the first array that don't exist in the second array
370
+ #### Synchronous Utilities
371
+
372
+ - `boolFilter<T>(array: (T | false | null | undefined)[]): T[]` - Filters out falsy values (`false`, `null`, `undefined`) from an array while keeping valid items.
373
+ - `unique<T>(array: T[]): T[]` - Returns a new array with all duplicate elements removed. Keeps only the first occurrence of each value.
374
+ - `chunk<T>(array: T[], size: number): T[][]` - Splits an array into smaller arrays ("chunks") of the specified size.
375
+ - `intersection<T>(...arrays: T[][]): T[]` - Returns an array of elements that exist in all provided arrays.
376
+ - `difference<T>(array: T[], exclude: T[]): T[]` - Returns a new array that contains items from `array` that are not present in `exclude`.
377
+
378
+ #### Asynchronous Utilities
379
+
380
+ - `forAsync<Item, Result>(array: Item[], callbackFn: (item, index, array) => Promise<Result>): Promise<Result[]>` - Runs asynchronous operations on each array item *sequentially* and returns the results in the original order.
381
+ - `mapAsync<Item, Return>(array: Item[], callbackFn: (item, index, array) => Promise<Return>): Promise<Return[]>` - Executes an asynchronous function for each array item *in parallel* and returns a promise of all results.
382
+ - `reduceAsync<Item, Accumulator>(array: Item[], callbackFn, initialValue): Promise<Accumulator>` - Asynchronously reduces an array to a single accumulated value. Each step waits for the previous promise to resolve.
383
+ - `filterAsync<Item>(array: Item[], callbackFn): Promise<Item[]>` - Runs an asynchronous filter operation. Only includes items where `callbackFn(item)` resolves to `true`.
384
+ - `someAsync<Item>(array: Item[], callbackFn): Promise<boolean>` - Returns `true` if **any** item in the array passes the async predicate.
385
+ - `everyAsync<Item>(array: Item[], callbackFn): Promise<boolean>` - Returns `true` if **all** items in the array pass the async predicate.
386
+ - `findAsync<Item>(array: Item[], callbackFn): Promise<Item | null>` - Returns the first array item that passes the async predicate, or `null` if no match is found.
252
387
 
253
388
  ### Function Utilities
254
389
 
255
- - **noop(): void** - A no-operation function
256
- - **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
390
+ - `noop(): void` - A no-operation function.
391
+ - `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.
392
+ - `delay(delayMs: number): Promise<void>` - Creates a promise that resolves after the specified delay in milliseconds.
393
+ - `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.
257
394
 
258
395
  ### Type Guards
259
396
 
260
- - **isString(value: unknown): value is string** - Checks if a value is a string
261
- - **isNumber(value: unknown): value is number** - Checks if a value is a number
262
- - **isBool(value: unknown): value is boolean** - Checks if a value is a boolean
263
- - **isObject(value: unknown): value is object** - Checks if a value is an object
264
- - **isFunction(value: unknown): value is Function** - Checks if a value is a function
265
- - **isPromise<T = unknown>(value: unknown): value is Promise<T>** - Checks if a value is a Promise
266
- - **isNil(value: unknown): value is null | undefined** - Checks if a value is null or undefined
267
- - **isNilOrEmptyString(value: unknown): value is null | undefined** - Checks if a value is null, undefined, or an empty string
268
- - **isArray(value: unknown): value is unknown[]** - Checks if a value is an array
269
- - **isEmptyArray(value: unknown): value is []** - Checks if a value is an empty array
270
- - **isEmptyObject(value: unknown): value is Record<string, never>** - Checks if a value is an empty object
271
- - **isNull(value: unknown): value is null** - Checks if a value is null
272
- - **isUndefined(value: unknown): value is undefined** - Checks if a value is undefined
273
- - **isFiniteNumber(value: unknown): value is number** - Checks if a value is a finite number
274
- - **isInteger(value: unknown): value is number** - Checks if a value is an integer
275
- - **isNaN(value: unknown): boolean** - Checks if a value is NaN
276
- - **isDate(value: unknown): value is Date** - Checks if a value is a Date object
277
- - **isValidDate(value: unknown): value is Date** - Checks if a value is a valid Date object (not Invalid Date)
278
- - **isRegExp(value: unknown): value is RegExp** - Checks if a value is a RegExp object
279
- - **isMap(value: unknown): value is Map<unknown, unknown>** - Checks if a value is a Map
280
- - **isSet(value: unknown): value is Set<unknown>** - Checks if a value is a Set
281
- - **isSymbol(value: unknown): value is symbol** - Checks if a value is a Symbol
397
+ - `assert(condition: any, message: string): asserts condition` - Asserts that a condition is truthy, throwing an error with the provided message if it's not.
398
+ - `isString(value: unknown): value is string` - Checks if a value is a string.
399
+ - `isNumber(value: unknown): value is number` - Checks if a value is a number.
400
+ - `isBool(value: unknown): value is boolean` - Checks if a value is a boolean.
401
+ - `isObject(value: unknown): value is object` - Checks if a value is an object.
402
+ - `isFunction(value: unknown): value is Function` - Checks if a value is a function.
403
+ - `isPromise<T = unknown>(value: unknown): value is Promise<T>` - Checks if a value is a Promise.
404
+ - `isNil(value: unknown): value is null | undefined` - Checks if a value is null or undefined.
405
+ - `isNilOrEmptyString(value: unknown): value is null | undefined` - Checks if a value is null, undefined, or an empty string.
406
+ - `isArray(value: unknown): value is unknown[]` - Checks if a value is an array.
407
+ - `isEmptyArray(value: unknown): value is []` - Checks if a value is an empty array.
408
+ - `isEmptyObject(value: unknown): value is Record<string, never>` - Checks if a value is an empty object.
409
+ - `isNull(value: unknown): value is null` - Checks if a value is null.
410
+ - `isUndefined(value: unknown): value is undefined` - Checks if a value is undefined.
411
+ - `isFiniteNumber(value: unknown): value is number` - Checks if a value is a finite number.
412
+ - `isInteger(value: unknown): value is number` - Checks if a value is an integer.
413
+ - `isDate(value: unknown): value is Date` - Checks if a value is a Date object.
414
+ - `isValidDate(value: unknown): value is Date` - Checks if a value is a valid Date object (not Invalid Date).
415
+ - `isRegExp(value: unknown): value is RegExp` - Checks if a value is a RegExp object.
416
+ - `isMap(value: unknown): value is Map<unknown, unknown>` - Checks if a value is a Map.
417
+ - `isSet(value: unknown): value is Set<unknown>` - Checks if a value is a Set.
418
+ - `isSymbol(value: unknown): value is symbol` - Checks if a value is a Symbol.
282
419
 
283
420
  ### Math Utilities
284
421
 
285
- - **calculateEuclideanDistance(startX: number, startY: number, endX: number, endY: number): number** - Calculates the Euclidean distance between two points
286
- - **calculateMovingSpeed(delta: number, elapsedTime: number): number** - Calculates moving speed
287
- - **calculatePercentage(value: number, percentage: number): number** - Calculates the specified percentage of a value
422
+ - `calculateEuclideanDistance(startX: number, startY: number, endX: number, endY: number): number` - Calculates the Euclidean distance between two points.
423
+ - `calculateMovingSpeed(delta: number, elapsedTime: number): number` - Calculates moving speed.
424
+ - `calculatePercentage(value: number, percentage: number): number` - Calculates the specified percentage of a value.
288
425
 
289
426
  ### DOM Utilities
290
427
 
291
- - **getTransformationValues(element: HTMLElement): { translateX: number, translateY: number }** - Gets transformation values from an HTML element
292
-
293
- ### Other Utilities
294
-
295
- - **assert(condition: any, message: string): asserts condition** - Asserts that a condition is truthy, throwing an error with the provided message if it's not
428
+ - `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.
429
+ - `cloneBlob(blob: Blob): Blob` - Creates a clone of a Blob object with the same content and type as the original.
430
+ - `convertBlobToFile(blob: Blob, fileName: string): File` - Converts a Blob object into a File object with the specified name.
296
431
 
297
432
  ## Contributing
298
433