A lightweight TypeScript utility library providing a collection of helper functions for common programming tasks.
- 🔍 Type Guards - Functions for runtime type checking
- 🧵 String Utilities - String manipulation and transformation
- 🔢 Array Utilities - Array filtering and manipulation
- 🧮 Math Utilities - Common mathematical calculations
- 🎯 Function Utilities - Function handling helpers
- 🖥️ DOM Utilities - Browser DOM manipulation helpers
- 📦 Zero Dependencies - Lightweight and dependency-free
- 📝 TypeScript Support - Full TypeScript type definitions
# Using npm
npm install @react-hive/honey-utils
# Using yarn
yarn add @react-hive/honey-utils
# Using pnpm
pnpm add @react-hive/honey-utils
// Import specific utilities
import { toKebabCase, isString, boolFilter } from '@react-hive/honey-utils';
// Or import everything
import * as HoneyUtils from '@react-hive/honey-utils';
import { toKebabCase, camelToDashCase, splitStringIntoWords, hashString } from '@react-hive/honey-utils';
/**
* Convert string to kebab-case
*/
toKebabCase('helloWorld'); // 'hello-world'
/**
* Convert camelCase to dash-case
*/
camelToDashCase('helloWorld'); // 'hello-world'
/**
* Split string into words
*/
splitStringIntoWords('hello world'); // ['hello', 'world']
/**
* Generate a hash from a string
*/
const hash = hashString('background-color: red;'); // 'e4k1z0x'
import {
compact,
unique,
chunk,
intersection,
difference,
pipe,
compose,
} from '@react-hive/honey-utils';
/**
* Filter out falsy values from an array
*/
compact([0, 1, false, 2, '', 3, null, undefined, true]);
// ➜ [1, 2, 3, true]
/**
* Remove duplicate values from an array
*/
unique([1, 2, 2, 3, 1, 4]);
// ➜ [1, 2, 3, 4]
/**
* Split an array into chunks of specified size
*/
chunk([1, 2, 3, 4, 5], 2);
// ➜ [[1, 2], [3, 4], [5]]
/**
* Find common elements between arrays
*/
intersection([1, 2, 3], [2, 3, 4]);
// ➜ [2, 3]
/**
* Find elements in one array not in another
*/
difference([1, 2, 3, 4], [2, 4]);
// ➜ [1, 3]
/**
* Compose functions from left to right
*/
const double = (n: number) => n * 2;
const increment = (n: number) => n + 1;
pipe(double, increment)(3);
// ➜ 7 → increment(double(3)) → increment(6)
/**
* Compose functions from right to left
*/
compose(increment, double)(3);
// ➜ 7 → increment(double(3)) → increment(6)
import {
runParallel,
runSequential,
reduceAsync,
filterParallel,
someAsync,
everyAsync,
findAsync,
} from '@react-hive/honey-utils';
/**
* Run async operations in parallel and collect results
*/
await runParallel([1, 2, 3], async (n) => {
await delay(100);
return n * 2;
});
// ➜ [2, 4, 6]
/**
* Run async operations sequentially and collect results
*/
await runSequential([1, 2, 3], async (n, i) => {
await delay(100);
return n * i;
});
// ➜ [0, 2, 6]
/**
* Reduce array asynchronously
*/
await reduceAsync([1, 2, 3], async (acc, n) => {
await delay(50);
return acc + n;
}, 0);
// ➜ 6
/**
* Filter array asynchronously
*/
await filterParallel([1, 2, 3, 4], async (n) => {
await delay(30);
return n % 2 === 0;
});
// ➜ [2, 4]
/**
* Check if some items match condition asynchronously
*/
await someAsync([1, 3, 5], async (n) => {
await delay(10);
return n % 2 === 0;
});
// ➜ false
/**
* Check if all items match condition asynchronously
*/
await everyAsync([2, 4, 6], async (n) => {
await delay(10);
return n % 2 === 0;
});
// ➜ true
/**
* Find first matching item asynchronously
*/
await findAsync([1, 3, 4, 5], async (n) => {
await delay(20);
return n % 2 === 0;
});
// ➜ 4
import { noop, invokeIfFunction, delay, retry } from '@react-hive/honey-utils';
/**
* No-operation function. Does nothing
*/
noop();
/**
* Invoke if function, otherwise return value
*/
const fn = (x: number) => x * 2;
invokeIfFunction(fn, 5); // 10
invokeIfFunction('not a function', 5); // 'not a function'
/**
* Waits for 1 second before continuing
*/
await delay(1000);
/**
* Retry an async function with configurable options
*/
async function fetchData() {
const response = await fetch('/api/data');
if (!response.ok) {
throw new Error('Network error');
}
return await response.json();
}
const fetchWithRetry = retry(fetchData, {
maxAttempts: 5,
delayMs: 500,
backoff: true,
onRetry: (attempt, error) => {
console.warn(`Attempt ${attempt} failed:`, error);
}
});
fetchWithRetry()
.then(data => console.log('Success:', data))
.catch(error => console.error('Failed after retries:', error));
import {
isString,
isNumber,
isBool,
isObject,
isFunction,
isPromise,
isNil,
isNilOrEmptyString,
isArray,
isEmptyArray,
isEmptyObject,
isNull,
isUndefined,
isDate,
isValidDate,
isRegExp,
isMap,
isSet
} from '@react-hive/honey-utils';
/**
* Check if value is a string
*/
isString('hello'); // true
isString(123); // false
/**
* Check if value is a number
*/
isNumber(123); // true
isNumber('123'); // false
/**
* Check if value is a boolean
*/
isBool(true); // true
isBool('true'); // false
/**
* Check if value is an object
*/
isObject({}); // true
isObject('object'); // false
/**
* Check if value is a function
*/
isFunction(() => {}); // true
isFunction({}); // false
/**
* Check if value is a Promise
*/
isPromise(Promise.resolve()); // true
isPromise({}); // false
/**
* Check if value is null or undefined
*/
isNil(null); // true
isNil(undefined); // true
isNil(''); // false
/**
* Check if value is null, undefined, or empty string
*/
isNilOrEmptyString(''); // true
isNilOrEmptyString(null); // true
isNilOrEmptyString('hello'); // false
/**
* Check if value is an array
*/
isArray([1, 2, 3]); // true
isArray({}); // false
/**
* Check if value is an empty array
*/
isEmptyArray([]); // true
isEmptyArray([1, 2, 3]); // false
/**
* Check if value is an empty object
*/
isEmptyObject({}); // true
isEmptyObject({ key: 'value' }); // false
/**
* Check if value is a Date object
*/
isDate(new Date()); // true
isDate('2023-01-01'); // false
/**
* Check if value is a valid Date object
*/
isValidDate(new Date()); // true
isValidDate(new Date('invalid')); // false
/**
* Check if value is a RegExp
*/
isRegExp(/test/); // true
isRegExp('test'); // false
/**
* Check if value is a Map or Set
*/
isMap(new Map()); // true
isSet(new Set()); // true
import {
calculateEuclideanDistance,
calculateMovingSpeed,
calculatePercentage
} from '@react-hive/honey-utils';
/**
* Calculate Euclidean distance between two points
*/
calculateEuclideanDistance(0, 0, 3, 4); // 5
/**
* Calculate moving speed
*/
calculateMovingSpeed(100, 5); // 20
/**
* Calculate percentage of a value
*/
calculatePercentage(200, 25); // 50
import { parse2DMatrix, cloneBlob, convertBlobToFile } from '@react-hive/honey-utils';
// Extract transformation values from an HTML element's 2D matrix
const element = document.getElementById('my-element');
if (element) {
const { translateX, translateY, scaleX, scaleY, skewX, skewY } = parse2DMatrix(element);
console.log(`Element is translated by ${translateX}px horizontally and ${translateY}px vertically`);
console.log(`Element is scaled by ${scaleX} horizontally and ${scaleY} vertically`);
console.log(`Element is skewed by ${skewX} horizontally and ${skewY} vertically`);
}
// Clone a Blob object
const originalBlob = new Blob(['Hello World'], { type: 'text/plain' });
const clonedBlob = cloneBlob(originalBlob);
console.log(clonedBlob.type); // 'text/plain'
// Convert a Blob to a File
const blob = new Blob(['Hello world'], { type: 'text/plain' });
const file = convertBlobToFile(blob, 'hello.txt');
console.log(file instanceof File); // true
console.log(file.name); // 'hello.txt'
console.log(file.type); // 'text/plain'
import { assert } from '@react-hive/honey-utils';
// Assert a condition
function divide(a: number, b: number): number {
assert(b !== 0, 'Cannot divide by zero');
return a / b;
}
toKebabCase(input: string): string
- Converts a string to kebab-case.camelToDashCase(input: string): string
- Converts camelCase to dash-case.splitStringIntoWords(input: string): string[]
- Splits a string into an array of words.hashString(input: string): string
- Generates a short hash from a string.
compact<T>(array: (T | Falsy)[]): T[]
– Returns a new array with all falsy values (false, null, undefined, 0, '', NaN) removed, preserving only truthy items of typeT
.unique<T>(array: T[]): T[]
- Returns a new array with all duplicate elements removed. Keeps only the first occurrence of each value.chunk<T>(array: T[], size: number): T[][]
- Splits an array into smaller arrays ("chunks") of the specified size.intersection<T>(...arrays: T[][]): T[]
- Returns an array of elements that exist in all provided arrays.difference<T>(array: T[], exclude: T[]): T[]
- Returns a new array that contains items fromarray
that are not present inexclude
.pipe(...fns: Function[]): Function
- Composes unary functions left-to-right. Returns a new function that applies all given functions in a sequence.compose(...fns: Function[]): Function
- Composes unary functions right-to-left. Same aspipe
, but applies functions in reverse order.
noop(): void
- A no-operation function.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.delay(delayMs: number): Promise<void>
- Creates a promise that resolves after the specified delay in milliseconds.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.
assert(condition: any, message: string): asserts condition
- Asserts that a condition is truthy, throwing an error with the provided message if it's not.isString(value: unknown): value is string
- Checks if a value is astring
.isNumber(value: unknown): value is number
- Checks if a value is anumber
.isBool(value: unknown): value is boolean
- Checks if a value is aboolean
.isObject(value: unknown): value is object
- Checks if a value is anobject
.isFunction(value: unknown): value is Function
- Checks if a value is afunction
.isPromise<T = unknown>(value: unknown): value is Promise<T>
- Checks if a value is aPromise
.isNil(value: unknown): value is null | undefined
- Checks if a value isnull
orundefined
.isNilOrEmptyString(value: unknown): value is null | undefined
- Checks if a value isnull
,undefined
, or an empty string.isArray(value: unknown): value is unknown[]
- Checks if a value is an array.isEmptyArray(value: unknown): value is []
- Checks if a value is an empty array.isEmptyObject(value: unknown): value is Record<string, never>
- Checks if a value is an empty object.isNull(value: unknown): value is null
- Checks if a value isnull
.isUndefined(value: unknown): value is undefined
- Checks if a value isundefined
.isDefined<T>(value: T): value is NonNullable<T>
- Checks if a value is neithernull
norundefined
.isFiniteNumber(value: unknown): value is number
- Checks if a value is a finite number.isInteger(value: unknown): value is number
- Checks if a value is an integer.isDate(value: unknown): value is Date
- Checks if a value is aDate
object.isValidDate(value: unknown): value is Date
- Checks if a value is a validDate
object.isRegExp(value: unknown): value is RegExp
- Checks if a value is aRegExp
object.isMap(value: unknown): value is Map<unknown, unknown>
- Checks if a value is aMap
.isSet(value: unknown): value is Set<unknown>
- Checks if a value is aSet
.isSymbol(value: unknown): value is symbol
- Checks if a value is aSymbol
.
calculateEuclideanDistance(startX: number, startY: number, endX: number, endY: number): number
- Calculates the Euclidean distance between two points.calculateMovingSpeed(distance: number, elapsedTime: number): number
- Calculates moving speed.calculatePercentage(value: number, percentage: number): number
- Calculates the specified percentage of a value.
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.cloneBlob(blob: Blob): Blob
- Creates a clone of a Blob object with the same content and type as the original.convertBlobToFile(blob: Blob, fileName: string): File
- Converts a Blob object into a File object with the specified name.getDOMRectIntersectionRatio(sourceRect: DOMRect, targetRect: DOMRect): number
- Calculates the ratio of thetargetRect
that is overlapped by thesourceRect
. Returns a number between0
(no overlap) and1
(fully covered).getElementOffsetRect(element: HTMLElement): DOMRect
- Returns aDOMRect
representing the element's layout position usingoffsetLeft
,offsetTop
, andclientWidth
/clientHeight
.
runSequential<Item, Result>(array: Item[], fn: (item, index, array) => Promise<Result>): Promise<Result[]>
- Runs asynchronous operations on each array item sequentially and returns the results in the original order.runParallel<Item, Result>(array: Item[], fn: (item, index, array) => Promise<Result>): Promise<Result[]>
- Executes an asynchronous function for each array item in parallel and returns a promise of all results.reduceAsync<Item, Accumulator>(array: Item[], fn, initialValue): Promise<Accumulator>
- Asynchronously reduces an array to a single accumulated value. Each step waits for the previous promise to resolve.filterSequential<Item>(array: Item[], predicate): Promise<Item[]>
– Filters an array using an asynchronous predicate sequentially. Each item is processed one after another, and only those for which predicate(item) returns true are included in the result.filterParallel<Item>(array: Item[], predicate): Promise<Item[]>
– Filters an array using an asynchronous predicate in parallel. Returns a promise that resolves with only the items for which predicate(item) returnstrue
.someAsync<Item>(array: Item[], predicate): Promise<boolean>
- Returnstrue
if any item in the array passes the async predicate.everyAsync<Item>(array: Item[], predicate): Promise<boolean>
- Returnstrue
if all items in the array pass the async predicate.findAsync<Item>(array: Item[], predicate): Promise<Item | null>
- Returns the first array item that passes the async predicate, ornull
if no match is found.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Mykhailo Aliinyk [email protected]