@react-hive/honey-utils 4.3.0 → 5.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/README.md +24 -12
- package/dist/README.md +24 -12
- package/dist/a11y/focus/is-html-element-focusable.d.ts +8 -6
- package/dist/a11y/focus/move-focus-within-container.d.ts +1 -1
- package/dist/array/chunk.d.ts +4 -1
- package/dist/array/compose.d.ts +7 -3
- package/dist/array/get-adjacent-items.d.ts +1 -1
- package/dist/array/index.d.ts +1 -0
- package/dist/array/intersection.d.ts +2 -1
- package/dist/array/is-array.d.ts +6 -0
- package/dist/array/is-empty-array.d.ts +7 -0
- package/dist/array/pipe.d.ts +5 -2
- package/dist/array/to-map-by.d.ts +48 -0
- package/dist/async/async.d.ts +10 -1
- package/dist/async/retry.d.ts +4 -3
- package/dist/dom/data-transfer.d.ts +22 -4
- package/dist/dom/dom.d.ts +7 -5
- package/dist/dom/transform/parse-2d-matrix.d.ts +5 -0
- package/dist/encoding/decode-base64-json.d.ts +22 -1
- package/dist/encoding/decode-base64.d.ts +23 -1
- package/dist/encoding/encode-base64-json.d.ts +16 -0
- package/dist/encoding/encode-base64.d.ts +20 -0
- package/dist/env/storage/local-storage-json.d.ts +1 -1
- package/dist/env/storage/local-storage.d.ts +1 -6
- package/dist/file.d.ts +3 -2
- package/dist/function/function.d.ts +12 -0
- package/dist/geometry/apply-inertia-step.d.ts +1 -1
- package/dist/geometry/layout/calculate-center-offset.d.ts +11 -1
- package/dist/geometry/layout/clamp-offset-to-overflow.d.ts +6 -0
- package/dist/geometry/resolve-bounded-delta.d.ts +1 -1
- package/dist/guards.d.ts +24 -3
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.dev.cjs +402 -97
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/intersection/get-dom-rect-intersection-ratio.d.ts +8 -1
- package/dist/intersection/resolve-axis-delta.d.ts +7 -0
- package/dist/json/parse-json.d.ts +22 -1
- package/dist/math/hash-string.d.ts +1 -1
- package/dist/math/math.d.ts +17 -1
- package/dist/object.d.ts +7 -1
- package/dist/string/for-each-char.d.ts +1 -1
- package/dist/string/is-nil-or-empty-string.d.ts +1 -1
- package/dist/string/parse-file-name.d.ts +1 -1
- package/dist/tree/flatten-tree.d.ts +2 -2
- package/dist/tree/get-tree-children.d.ts +2 -2
- package/dist/tree/search-tree.d.ts +2 -2
- package/dist/tree/tree.types.d.ts +1 -1
- package/package.json +8 -7
- package/dist/geometry/apply-inertia-step.spec.d.ts +0 -1
- package/dist/geometry/resolve-bounded-delta.spec.d.ts +0 -1
- package/dist/id/generate-ephemeral-id.spec.d.ts +0 -1
package/README.md
CHANGED
|
@@ -99,7 +99,7 @@ splitStringIntoWords('hello world');
|
|
|
99
99
|
* Generate a hash from a string
|
|
100
100
|
*/
|
|
101
101
|
const hash = hashString('background-color: red;');
|
|
102
|
-
// ➜ '
|
|
102
|
+
// ➜ '1s0s409'
|
|
103
103
|
```
|
|
104
104
|
|
|
105
105
|
### Encoding Utilities
|
|
@@ -230,6 +230,7 @@ import {
|
|
|
230
230
|
intersection,
|
|
231
231
|
difference,
|
|
232
232
|
toggleArrayItem,
|
|
233
|
+
toMapBy,
|
|
233
234
|
pipe,
|
|
234
235
|
compose,
|
|
235
236
|
} from '@react-hive/honey-utils';
|
|
@@ -290,6 +291,16 @@ toggleArrayItem(['a', 'b'], 'b', false);
|
|
|
290
291
|
toggleArrayItem(['a', 'b'], 'a');
|
|
291
292
|
// ➜ ['b']
|
|
292
293
|
|
|
294
|
+
/**
|
|
295
|
+
* Index an array by a key
|
|
296
|
+
*/
|
|
297
|
+
const users = [{ id: 'u1', name: 'Ann' }, { id: 'u2', name: 'Bob' }];
|
|
298
|
+
|
|
299
|
+
toMapBy(users, user => user.id);
|
|
300
|
+
// ➜ Map { 'u1' => { id: 'u1', name: 'Ann' }, 'u2' => { id: 'u2', name: 'Bob' } }
|
|
301
|
+
toMapBy(users, user => user.id, user => user.name);
|
|
302
|
+
// ➜ Map { 'u1' => 'Ann', 'u2' => 'Bob' }
|
|
303
|
+
|
|
293
304
|
/**
|
|
294
305
|
* Compose functions from left to right
|
|
295
306
|
*/
|
|
@@ -709,7 +720,7 @@ function divide(a: number, b: number): number {
|
|
|
709
720
|
---
|
|
710
721
|
|
|
711
722
|
- `isString(value: unknown): value is string` - Checks if a value is a `string`.
|
|
712
|
-
- `isNilOrEmptyString(value: unknown): value is null | undefined` - Checks if a value is `null`, `undefined`, or an empty string.
|
|
723
|
+
- `isNilOrEmptyString(value: unknown): value is null | undefined | ''` - Checks if a value is `null`, `undefined`, or an empty string.
|
|
713
724
|
- `toKebabCase(input: string): string` - Converts a string to kebab-case.
|
|
714
725
|
- `camelToDashCase(input: string): string` - Converts camelCase to dash-case.
|
|
715
726
|
- `splitStringIntoWords(input: string): string[]` - Splits a string into an array of words.
|
|
@@ -744,7 +755,7 @@ function divide(a: number, b: number): number {
|
|
|
744
755
|
|
|
745
756
|
---
|
|
746
757
|
|
|
747
|
-
- `definedProps<T extends object>(obj: T): DefinedProps<T>` - Creates a new object by removing all properties whose values are `undefined
|
|
758
|
+
- `definedProps<T extends object>(obj: T): DefinedProps<T>` - Creates a new object by removing all properties whose values are `undefined`, symbol-keyed ones included. A key that may be `undefined` comes out optional.
|
|
748
759
|
|
|
749
760
|
### Array Utilities
|
|
750
761
|
|
|
@@ -754,8 +765,9 @@ function divide(a: number, b: number): number {
|
|
|
754
765
|
- `isEmptyArray(value: unknown): value is []` - Checks if a value is an empty array.
|
|
755
766
|
- `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 type `T`.
|
|
756
767
|
- `unique<T>(array: T[]): T[]` - Returns a new array with all duplicate elements removed. Keeps only the first occurrence of each value.
|
|
757
|
-
- `
|
|
758
|
-
- `
|
|
768
|
+
- `toMapBy<Item, Key, Value>(items: readonly Item[], getKey: (item: Item, index: number) => Key, getValue?: (item: Item, index: number) => Value): Map<Key, Item | Value>` - Indexes an array by a key: a `Map` from each item's key to the item, or to what `getValue` returns for it. Where two items share a key, the later one wins.
|
|
769
|
+
- `chunk<T>(array: T[], size: number): T[][]` - Splits an array into smaller arrays ("chunks") of the specified size. Throws unless `size` is a positive whole number.
|
|
770
|
+
- `intersection<T>(...arrays: T[][]): T[]` - Returns an array of elements that exist in all provided arrays, each once, in the order of the first array.
|
|
759
771
|
- `difference<T>(array: T[], exclude: T[]): T[]` - Returns a new array that contains items from `array` that are not present in `exclude`.
|
|
760
772
|
- `pipe(...fns: Function[]): Function` - Composes unary functions left-to-right. Returns a new function that applies all given functions in a sequence.
|
|
761
773
|
- `compose(...fns: Function[]): Function` - Composes unary functions **right-to-left**. Same as `pipe`, but applies functions in reverse order.
|
|
@@ -770,7 +782,7 @@ function divide(a: number, b: number): number {
|
|
|
770
782
|
- `noop(): void` - A no-operation function.
|
|
771
783
|
- `not<Args extends any[]>(fn: (...args: Args) => any): (...args: Args) => boolean` - Creates a new function that negates the result of the given predicate function. Useful for logical inversions, e.g., turning `isEven` into `isOdd`.
|
|
772
784
|
- `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.
|
|
773
|
-
- `once<T extends (...args: any[]) => any>(fn: T): T` - Wraps a function so it can only be executed once. The result of the first invocation is cached and returned for all subsequent calls. Preserves both the original function’s parameter types and `this` binding.
|
|
785
|
+
- `once<T extends (...args: any[]) => any>(fn: T): T` - Wraps a function so it can only be executed once. The result of the first invocation is cached and returned for all subsequent calls; if it throws, every call throws that same error. Preserves both the original function’s parameter types and `this` binding.
|
|
774
786
|
|
|
775
787
|
### Type Guards
|
|
776
788
|
|
|
@@ -779,9 +791,9 @@ function divide(a: number, b: number): number {
|
|
|
779
791
|
- `assert(condition: any, message: string): asserts condition` - Asserts that a condition is truthy, throwing an error with the provided message if it's not.
|
|
780
792
|
- `isNumber(value: unknown): value is number` - Checks if a value is a `number`.
|
|
781
793
|
- `isBool(value: unknown): value is boolean` - Checks if a value is a `boolean`.
|
|
782
|
-
- `isObject(value: unknown): value is object` - Checks if a value is an `object
|
|
794
|
+
- `isObject(value: unknown): value is object` - Checks if a value is an `object`, `null` excluded.
|
|
783
795
|
- `isNil(value: unknown): value is null | undefined` - Checks if a value is `null` or `undefined`.
|
|
784
|
-
- `isEmptyObject(value: unknown): value is Record<string, never>` - Checks if a value is an empty object.
|
|
796
|
+
- `isEmptyObject(value: unknown): value is Record<string, never>` - Checks if a value is an empty object - no own enumerable properties, symbol-keyed ones included.
|
|
785
797
|
- `isNull(value: unknown): value is null` - Checks if a value is `null`.
|
|
786
798
|
- `isUndefined(value: unknown): value is undefined` - Checks if a value is `undefined`.
|
|
787
799
|
- `isDefined<T>(value: T): value is NonNullable<T>` - Checks if a value is neither `null` nor `undefined`.
|
|
@@ -838,7 +850,7 @@ function divide(a: number, b: number): number {
|
|
|
838
850
|
- `cloneBlob(blob: Blob): Blob` - Creates a clone of a Blob object with the same content and type as the original.
|
|
839
851
|
- `getElementOffsetRect(element: HTMLElement): DOMRect` - Returns a `DOMRect` representing the element's layout position using `offsetLeft`, `offsetTop`, and `clientWidth`/`clientHeight`.
|
|
840
852
|
- `isAnchorHtmlElement(element: HTMLElement): element is HTMLAnchorElement` - Determines whether the provided element is an `<a>` tag. Acts as a type guard that narrows the element to `HTMLAnchorElement`.
|
|
841
|
-
- `isContentEditableHtmlElement(element: HTMLElement): boolean` - Returns `true` if the element
|
|
853
|
+
- `isContentEditableHtmlElement(element: HTMLElement): boolean` - Returns `true` if the element's `contenteditable` is `""`, `"true"` or `"plaintext-only"` (in any case), making it user-editable and implicitly focusable.
|
|
842
854
|
|
|
843
855
|
#### File
|
|
844
856
|
|
|
@@ -890,8 +902,8 @@ function divide(a: number, b: number): number {
|
|
|
890
902
|
- `everyAsync<Item>(array: Item[], predicate): Promise<boolean>` - Returns `true` if **all** items in the array pass the async predicate.
|
|
891
903
|
- `findAsync<Item>(array: Item[], predicate): Promise<Nullable<Item>>` - Returns the first array item that passes the async predicate, or `null` if no match is found.
|
|
892
904
|
- `delay(delayMs: number): Promise<void>` - Creates a promise that resolves after the specified delay in milliseconds.
|
|
893
|
-
- `timeout<T>(promise: Promise<T>, timeoutMs: number, message?: string): Promise<T>` - Wraps a promise with a timeout. If the promise does not settle within the given duration, it rejects with a timeout error.
|
|
894
|
-
- `retry<
|
|
905
|
+
- `timeout<T>(promise: Promise<T>, timeoutMs: number, message?: string): Promise<T>` - Wraps a promise with a timeout. If the promise does not settle within the given duration, it rejects with a timeout error. Its timer is cleared however the race ends.
|
|
906
|
+
- `retry<Args, TaskResult>(task: (...args: Args) => Promise<TaskResult>, options?: RetryOptions): (...args: Args) => Promise<TaskResult>` - Wraps an asynchronous function with retry logic, with configurable max attempts (at least one), delay between retries, exponential backoff, and retry callbacks.
|
|
895
907
|
|
|
896
908
|
### Intersection Utilities
|
|
897
909
|
|
|
@@ -906,7 +918,7 @@ function divide(a: number, b: number): number {
|
|
|
906
918
|
|
|
907
919
|
#### Focus
|
|
908
920
|
|
|
909
|
-
- `isHtmlElementFocusable(element: Nullable<HTMLElement>): boolean` - Checks whether an element is considered focusable according to browser rules. Factors include: visibility, `display
|
|
921
|
+
- `isHtmlElementFocusable(element: Nullable<HTMLElement>): boolean` - Checks whether an element is considered focusable according to browser rules. Factors include: visibility, `display` (an ancestor's too), `:disabled` (a disabled `<fieldset>`'s controls too), a valid `tabindex` (negative removes it, non-negative makes any element focusable), native focusable tags, and `contenteditable`.
|
|
910
922
|
- `getFocusableHtmlElements(container: HTMLElement): HTMLElement[]` - Returns all focusable descendant elements within a container, using `isHtmlElementFocusable` to filter them.
|
|
911
923
|
- `moveFocusWithinContainer(direction: FocusMoveDirection, container?: Nullable<HTMLElement>, options?: MoveFocusWithinContainerOptions): void` - Moves focus to the next or previous focusable element within a container. Supports cyclic navigation, optional wrapping control, and custom focus index resolution for advanced keyboard navigation patterns (e.g. roving tabindex).
|
|
912
924
|
|
package/dist/README.md
CHANGED
|
@@ -99,7 +99,7 @@ splitStringIntoWords('hello world');
|
|
|
99
99
|
* Generate a hash from a string
|
|
100
100
|
*/
|
|
101
101
|
const hash = hashString('background-color: red;');
|
|
102
|
-
// ➜ '
|
|
102
|
+
// ➜ '1s0s409'
|
|
103
103
|
```
|
|
104
104
|
|
|
105
105
|
### Encoding Utilities
|
|
@@ -230,6 +230,7 @@ import {
|
|
|
230
230
|
intersection,
|
|
231
231
|
difference,
|
|
232
232
|
toggleArrayItem,
|
|
233
|
+
toMapBy,
|
|
233
234
|
pipe,
|
|
234
235
|
compose,
|
|
235
236
|
} from '@react-hive/honey-utils';
|
|
@@ -290,6 +291,16 @@ toggleArrayItem(['a', 'b'], 'b', false);
|
|
|
290
291
|
toggleArrayItem(['a', 'b'], 'a');
|
|
291
292
|
// ➜ ['b']
|
|
292
293
|
|
|
294
|
+
/**
|
|
295
|
+
* Index an array by a key
|
|
296
|
+
*/
|
|
297
|
+
const users = [{ id: 'u1', name: 'Ann' }, { id: 'u2', name: 'Bob' }];
|
|
298
|
+
|
|
299
|
+
toMapBy(users, user => user.id);
|
|
300
|
+
// ➜ Map { 'u1' => { id: 'u1', name: 'Ann' }, 'u2' => { id: 'u2', name: 'Bob' } }
|
|
301
|
+
toMapBy(users, user => user.id, user => user.name);
|
|
302
|
+
// ➜ Map { 'u1' => 'Ann', 'u2' => 'Bob' }
|
|
303
|
+
|
|
293
304
|
/**
|
|
294
305
|
* Compose functions from left to right
|
|
295
306
|
*/
|
|
@@ -709,7 +720,7 @@ function divide(a: number, b: number): number {
|
|
|
709
720
|
---
|
|
710
721
|
|
|
711
722
|
- `isString(value: unknown): value is string` - Checks if a value is a `string`.
|
|
712
|
-
- `isNilOrEmptyString(value: unknown): value is null | undefined` - Checks if a value is `null`, `undefined`, or an empty string.
|
|
723
|
+
- `isNilOrEmptyString(value: unknown): value is null | undefined | ''` - Checks if a value is `null`, `undefined`, or an empty string.
|
|
713
724
|
- `toKebabCase(input: string): string` - Converts a string to kebab-case.
|
|
714
725
|
- `camelToDashCase(input: string): string` - Converts camelCase to dash-case.
|
|
715
726
|
- `splitStringIntoWords(input: string): string[]` - Splits a string into an array of words.
|
|
@@ -744,7 +755,7 @@ function divide(a: number, b: number): number {
|
|
|
744
755
|
|
|
745
756
|
---
|
|
746
757
|
|
|
747
|
-
- `definedProps<T extends object>(obj: T): DefinedProps<T>` - Creates a new object by removing all properties whose values are `undefined
|
|
758
|
+
- `definedProps<T extends object>(obj: T): DefinedProps<T>` - Creates a new object by removing all properties whose values are `undefined`, symbol-keyed ones included. A key that may be `undefined` comes out optional.
|
|
748
759
|
|
|
749
760
|
### Array Utilities
|
|
750
761
|
|
|
@@ -754,8 +765,9 @@ function divide(a: number, b: number): number {
|
|
|
754
765
|
- `isEmptyArray(value: unknown): value is []` - Checks if a value is an empty array.
|
|
755
766
|
- `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 type `T`.
|
|
756
767
|
- `unique<T>(array: T[]): T[]` - Returns a new array with all duplicate elements removed. Keeps only the first occurrence of each value.
|
|
757
|
-
- `
|
|
758
|
-
- `
|
|
768
|
+
- `toMapBy<Item, Key, Value>(items: readonly Item[], getKey: (item: Item, index: number) => Key, getValue?: (item: Item, index: number) => Value): Map<Key, Item | Value>` - Indexes an array by a key: a `Map` from each item's key to the item, or to what `getValue` returns for it. Where two items share a key, the later one wins.
|
|
769
|
+
- `chunk<T>(array: T[], size: number): T[][]` - Splits an array into smaller arrays ("chunks") of the specified size. Throws unless `size` is a positive whole number.
|
|
770
|
+
- `intersection<T>(...arrays: T[][]): T[]` - Returns an array of elements that exist in all provided arrays, each once, in the order of the first array.
|
|
759
771
|
- `difference<T>(array: T[], exclude: T[]): T[]` - Returns a new array that contains items from `array` that are not present in `exclude`.
|
|
760
772
|
- `pipe(...fns: Function[]): Function` - Composes unary functions left-to-right. Returns a new function that applies all given functions in a sequence.
|
|
761
773
|
- `compose(...fns: Function[]): Function` - Composes unary functions **right-to-left**. Same as `pipe`, but applies functions in reverse order.
|
|
@@ -770,7 +782,7 @@ function divide(a: number, b: number): number {
|
|
|
770
782
|
- `noop(): void` - A no-operation function.
|
|
771
783
|
- `not<Args extends any[]>(fn: (...args: Args) => any): (...args: Args) => boolean` - Creates a new function that negates the result of the given predicate function. Useful for logical inversions, e.g., turning `isEven` into `isOdd`.
|
|
772
784
|
- `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.
|
|
773
|
-
- `once<T extends (...args: any[]) => any>(fn: T): T` - Wraps a function so it can only be executed once. The result of the first invocation is cached and returned for all subsequent calls. Preserves both the original function’s parameter types and `this` binding.
|
|
785
|
+
- `once<T extends (...args: any[]) => any>(fn: T): T` - Wraps a function so it can only be executed once. The result of the first invocation is cached and returned for all subsequent calls; if it throws, every call throws that same error. Preserves both the original function’s parameter types and `this` binding.
|
|
774
786
|
|
|
775
787
|
### Type Guards
|
|
776
788
|
|
|
@@ -779,9 +791,9 @@ function divide(a: number, b: number): number {
|
|
|
779
791
|
- `assert(condition: any, message: string): asserts condition` - Asserts that a condition is truthy, throwing an error with the provided message if it's not.
|
|
780
792
|
- `isNumber(value: unknown): value is number` - Checks if a value is a `number`.
|
|
781
793
|
- `isBool(value: unknown): value is boolean` - Checks if a value is a `boolean`.
|
|
782
|
-
- `isObject(value: unknown): value is object` - Checks if a value is an `object
|
|
794
|
+
- `isObject(value: unknown): value is object` - Checks if a value is an `object`, `null` excluded.
|
|
783
795
|
- `isNil(value: unknown): value is null | undefined` - Checks if a value is `null` or `undefined`.
|
|
784
|
-
- `isEmptyObject(value: unknown): value is Record<string, never>` - Checks if a value is an empty object.
|
|
796
|
+
- `isEmptyObject(value: unknown): value is Record<string, never>` - Checks if a value is an empty object - no own enumerable properties, symbol-keyed ones included.
|
|
785
797
|
- `isNull(value: unknown): value is null` - Checks if a value is `null`.
|
|
786
798
|
- `isUndefined(value: unknown): value is undefined` - Checks if a value is `undefined`.
|
|
787
799
|
- `isDefined<T>(value: T): value is NonNullable<T>` - Checks if a value is neither `null` nor `undefined`.
|
|
@@ -838,7 +850,7 @@ function divide(a: number, b: number): number {
|
|
|
838
850
|
- `cloneBlob(blob: Blob): Blob` - Creates a clone of a Blob object with the same content and type as the original.
|
|
839
851
|
- `getElementOffsetRect(element: HTMLElement): DOMRect` - Returns a `DOMRect` representing the element's layout position using `offsetLeft`, `offsetTop`, and `clientWidth`/`clientHeight`.
|
|
840
852
|
- `isAnchorHtmlElement(element: HTMLElement): element is HTMLAnchorElement` - Determines whether the provided element is an `<a>` tag. Acts as a type guard that narrows the element to `HTMLAnchorElement`.
|
|
841
|
-
- `isContentEditableHtmlElement(element: HTMLElement): boolean` - Returns `true` if the element
|
|
853
|
+
- `isContentEditableHtmlElement(element: HTMLElement): boolean` - Returns `true` if the element's `contenteditable` is `""`, `"true"` or `"plaintext-only"` (in any case), making it user-editable and implicitly focusable.
|
|
842
854
|
|
|
843
855
|
#### File
|
|
844
856
|
|
|
@@ -890,8 +902,8 @@ function divide(a: number, b: number): number {
|
|
|
890
902
|
- `everyAsync<Item>(array: Item[], predicate): Promise<boolean>` - Returns `true` if **all** items in the array pass the async predicate.
|
|
891
903
|
- `findAsync<Item>(array: Item[], predicate): Promise<Nullable<Item>>` - Returns the first array item that passes the async predicate, or `null` if no match is found.
|
|
892
904
|
- `delay(delayMs: number): Promise<void>` - Creates a promise that resolves after the specified delay in milliseconds.
|
|
893
|
-
- `timeout<T>(promise: Promise<T>, timeoutMs: number, message?: string): Promise<T>` - Wraps a promise with a timeout. If the promise does not settle within the given duration, it rejects with a timeout error.
|
|
894
|
-
- `retry<
|
|
905
|
+
- `timeout<T>(promise: Promise<T>, timeoutMs: number, message?: string): Promise<T>` - Wraps a promise with a timeout. If the promise does not settle within the given duration, it rejects with a timeout error. Its timer is cleared however the race ends.
|
|
906
|
+
- `retry<Args, TaskResult>(task: (...args: Args) => Promise<TaskResult>, options?: RetryOptions): (...args: Args) => Promise<TaskResult>` - Wraps an asynchronous function with retry logic, with configurable max attempts (at least one), delay between retries, exponential backoff, and retry callbacks.
|
|
895
907
|
|
|
896
908
|
### Intersection Utilities
|
|
897
909
|
|
|
@@ -906,7 +918,7 @@ function divide(a: number, b: number): number {
|
|
|
906
918
|
|
|
907
919
|
#### Focus
|
|
908
920
|
|
|
909
|
-
- `isHtmlElementFocusable(element: Nullable<HTMLElement>): boolean` - Checks whether an element is considered focusable according to browser rules. Factors include: visibility, `display
|
|
921
|
+
- `isHtmlElementFocusable(element: Nullable<HTMLElement>): boolean` - Checks whether an element is considered focusable according to browser rules. Factors include: visibility, `display` (an ancestor's too), `:disabled` (a disabled `<fieldset>`'s controls too), a valid `tabindex` (negative removes it, non-negative makes any element focusable), native focusable tags, and `contenteditable`.
|
|
910
922
|
- `getFocusableHtmlElements(container: HTMLElement): HTMLElement[]` - Returns all focusable descendant elements within a container, using `isHtmlElementFocusable` to filter them.
|
|
911
923
|
- `moveFocusWithinContainer(direction: FocusMoveDirection, container?: Nullable<HTMLElement>, options?: MoveFocusWithinContainerOptions): void` - Moves focus to the next or previous focusable element within a container. Supports cyclic navigation, optional wrapping control, and custom focus index resolution for advanced keyboard navigation patterns (e.g. roving tabindex).
|
|
912
924
|
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import type { Nullable } from '
|
|
1
|
+
import type { Nullable } from '../../types';
|
|
2
2
|
export declare const FOCUSABLE_HTML_TAGS: string[];
|
|
3
3
|
/**
|
|
4
4
|
* Determines whether an HTMLElement is focusable under standard browser rules.
|
|
5
5
|
*
|
|
6
6
|
* The function checks a combination of factors:
|
|
7
|
-
* - The element must be rendered
|
|
8
|
-
*
|
|
9
|
-
* -
|
|
7
|
+
* - The element must be rendered: neither it nor an ancestor has `display: none`, and it is not
|
|
8
|
+
* `visibility: hidden`.
|
|
9
|
+
* - Disabled form controls are never focusable - including those inside a disabled `<fieldset>`.
|
|
10
|
+
* - Elements with a negative `tabindex` are intentionally removed from the focus order.
|
|
11
|
+
* - Any element with a valid, non-negative `tabindex` is focusable. A `tabindex` that is not an
|
|
12
|
+
* integer is ignored, as browsers ignore it.
|
|
10
13
|
* - Certain native HTML elements are inherently focusable (e.g. inputs, buttons, anchors with `href`).
|
|
11
|
-
* -
|
|
12
|
-
* - Any element with a valid `tabindex` (not null) is considered focusable.
|
|
14
|
+
* - Editable elements (`contenteditable`) are treated as focusable.
|
|
13
15
|
*
|
|
14
16
|
* This logic approximates how browsers and the accessibility tree
|
|
15
17
|
* determine real-world focusability—not just tabindex presence.
|
package/dist/array/chunk.d.ts
CHANGED
|
@@ -6,11 +6,14 @@
|
|
|
6
6
|
* @template T - The type of the items in the array.
|
|
7
7
|
*
|
|
8
8
|
* @param array - The input array to be chunked.
|
|
9
|
-
* @param size - The size of each chunk. Must be
|
|
9
|
+
* @param size - The size of each chunk. Must be a positive whole number.
|
|
10
10
|
*
|
|
11
11
|
* @returns An array of chunks, where each chunk is an array of the specified size
|
|
12
12
|
* (except possibly the last chunk, which may be smaller).
|
|
13
13
|
*
|
|
14
|
+
* @throws {Error} When `size` is not a positive whole number - a fractional size would give
|
|
15
|
+
* chunks of other sizes, and `Infinity` none at all.
|
|
16
|
+
*
|
|
14
17
|
* @example
|
|
15
18
|
* ```ts
|
|
16
19
|
* chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]
|
package/dist/array/compose.d.ts
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Any unary function: one taking a typed argument is assignable here, where it is not to
|
|
3
|
+
* `ComposeFn`.
|
|
4
|
+
*/
|
|
5
|
+
type AnyUnaryFn = (arg: never) => unknown;
|
|
2
6
|
type Compose = {
|
|
3
7
|
<A, R>(fn1: (a: A) => R): (a: A) => R;
|
|
4
8
|
<A, B, R>(fn1: (b: B) => R, fn2: (a: A) => B): (a: A) => R;
|
|
5
9
|
<A, B, C, R>(fn1: (c: C) => R, fn2: (b: B) => C, fn3: (a: A) => B): (a: A) => R;
|
|
6
10
|
<A, B, C, D, R>(fn1: (d: D) => R, fn2: (c: C) => D, fn3: (b: B) => C, fn4: (a: A) => B): (a: A) => R;
|
|
7
11
|
<A, B, C, D, E, R>(fn1: (e: E) => R, fn2: (d: D) => E, fn3: (c: C) => D, fn4: (b: B) => C, fn5: (a: A) => B): (a: A) => R;
|
|
8
|
-
(...fns:
|
|
12
|
+
(...fns: AnyUnaryFn[]): (arg: unknown) => unknown;
|
|
9
13
|
};
|
|
10
14
|
/**
|
|
11
15
|
* Composes multiple unary functions into a single function, applying them from **right to left**.
|
|
12
16
|
*
|
|
13
17
|
* Often used for building functional pipelines where the innermost function runs first.
|
|
14
|
-
* Types are inferred up to 5 chained functions for full type safety.
|
|
18
|
+
* Types are inferred up to 5 chained functions for full type safety. Beyond that, it falls back to the unknown.
|
|
15
19
|
*
|
|
16
20
|
* @param fns - A list of unary functions to compose.
|
|
17
21
|
*
|
package/dist/array/index.d.ts
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @param arrays - Two or more arrays to find common elements from.
|
|
7
7
|
*
|
|
8
|
-
* @returns A new array containing only the elements that exist in all input arrays
|
|
8
|
+
* @returns A new array containing only the elements that exist in all input arrays, each once, in
|
|
9
|
+
* the order of the first array.
|
|
9
10
|
*
|
|
10
11
|
* @example
|
|
11
12
|
* ```ts
|
package/dist/array/is-array.d.ts
CHANGED
|
@@ -4,5 +4,11 @@
|
|
|
4
4
|
* @param value - The value to check.
|
|
5
5
|
*
|
|
6
6
|
* @returns `true` if the value is an array; otherwise, `false`.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* isArray([1, 2]); // true
|
|
11
|
+
* isArray('12'); // false
|
|
12
|
+
* ```
|
|
7
13
|
*/
|
|
8
14
|
export declare const isArray: (value: unknown) => value is unknown[];
|
|
@@ -4,5 +4,12 @@
|
|
|
4
4
|
* @param value - The value to check.
|
|
5
5
|
*
|
|
6
6
|
* @returns `true` if the value is an empty array; otherwise, `false`.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* isEmptyArray([]); // true
|
|
11
|
+
* isEmptyArray([1]); // false
|
|
12
|
+
* isEmptyArray({}); // false
|
|
13
|
+
* ```
|
|
7
14
|
*/
|
|
8
15
|
export declare const isEmptyArray: (value: unknown) => value is [];
|
package/dist/array/pipe.d.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Any unary function: one taking a typed argument is assignable here, where it is not to `PipeFn`.
|
|
3
|
+
*/
|
|
4
|
+
type AnyUnaryFn = (arg: never) => unknown;
|
|
2
5
|
type Pipe = {
|
|
3
6
|
<A, B>(fn1: (a: A) => B): (a: A) => B;
|
|
4
7
|
<A, B, C>(fn1: (a: A) => B, fn2: (b: B) => C): (a: A) => C;
|
|
5
8
|
<A, B, C, D>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D): (a: A) => D;
|
|
6
9
|
<A, B, C, D, E>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E): (a: A) => E;
|
|
7
10
|
<A, B, C, D, E, F>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F): (a: A) => F;
|
|
8
|
-
(...fns:
|
|
11
|
+
(...fns: AnyUnaryFn[]): (arg: unknown) => unknown;
|
|
9
12
|
};
|
|
10
13
|
/**
|
|
11
14
|
* Composes multiple unary functions into a single function, applying them from left to right.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Indexes an array by a key: a `Map` from each item's key to the item itself.
|
|
3
|
+
*
|
|
4
|
+
* Items are added in order, so where two share a key the later one wins, as with
|
|
5
|
+
* `new Map(entries)`.
|
|
6
|
+
*
|
|
7
|
+
* @template Item - The type of the items in the array.
|
|
8
|
+
* @template Key - The type of the keys.
|
|
9
|
+
*
|
|
10
|
+
* @param items - The items to index.
|
|
11
|
+
* @param getKey - Returns the key an item is stored under.
|
|
12
|
+
*
|
|
13
|
+
* @returns A new `Map` from each key to its item.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const users = [{ id: 'u1', name: 'Ann' }, { id: 'u2', name: 'Bob' }];
|
|
18
|
+
*
|
|
19
|
+
* toMapBy(users, user => user.id);
|
|
20
|
+
* // Map { 'u1' => { id: 'u1', name: 'Ann' }, 'u2' => { id: 'u2', name: 'Bob' } }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function toMapBy<Item, Key>(items: readonly Item[], getKey: (item: Item, index: number) => Key): Map<Key, Item>;
|
|
24
|
+
/**
|
|
25
|
+
* Indexes an array by a key: a `Map` from each item's key to what `getValue` returns for the item.
|
|
26
|
+
*
|
|
27
|
+
* Items are added in order, so where two share a key the later one wins, as with
|
|
28
|
+
* `new Map(entries)`.
|
|
29
|
+
*
|
|
30
|
+
* @template Item - The type of the items in the array.
|
|
31
|
+
* @template Key - The type of the keys.
|
|
32
|
+
* @template Value - The type of the values.
|
|
33
|
+
*
|
|
34
|
+
* @param items - The items to index.
|
|
35
|
+
* @param getKey - Returns the key an item is stored under.
|
|
36
|
+
* @param getValue - Returns the value stored for an item.
|
|
37
|
+
*
|
|
38
|
+
* @returns A new `Map` from each key to its value.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* const users = [{ id: 'u1', name: 'Ann' }, { id: 'u2', name: 'Bob' }];
|
|
43
|
+
*
|
|
44
|
+
* toMapBy(users, user => user.id, user => user.name);
|
|
45
|
+
* // Map { 'u1' => 'Ann', 'u2' => 'Bob' }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function toMapBy<Item, Key, Value>(items: readonly Item[], getKey: (item: Item, index: number) => Key, getValue: (item: Item, index: number) => Value): Map<Key, Value>;
|
package/dist/async/async.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Nullable } from '
|
|
1
|
+
import type { Nullable } from '../types';
|
|
2
2
|
/**
|
|
3
3
|
* Checks if a value is a Promise.
|
|
4
4
|
*
|
|
@@ -109,6 +109,9 @@ export declare const filterParallel: <Item>(array: Item[], predicate: (item: Ite
|
|
|
109
109
|
/**
|
|
110
110
|
* Asynchronously checks if at least one element in the array satisfies the async condition.
|
|
111
111
|
*
|
|
112
|
+
* Runs one item at a time, in order, and stops at the first item that satisfies it - as
|
|
113
|
+
* `Array.prototype.some` does.
|
|
114
|
+
*
|
|
112
115
|
* @param array - The array of items to check.
|
|
113
116
|
* @param predicate - An async function that returns a boolean.
|
|
114
117
|
*
|
|
@@ -118,6 +121,9 @@ export declare const someAsync: <Item>(array: Item[], predicate: (item: Item, in
|
|
|
118
121
|
/**
|
|
119
122
|
* Asynchronously checks if all elements in the array satisfy the async condition.
|
|
120
123
|
*
|
|
124
|
+
* Runs one item at a time, in order, and stops at the first item that fails it - as
|
|
125
|
+
* `Array.prototype.every` does.
|
|
126
|
+
*
|
|
121
127
|
* @param array - The array of items to check.
|
|
122
128
|
* @param predicate - An async function that returns a boolean.
|
|
123
129
|
*
|
|
@@ -140,6 +146,9 @@ export declare const reduceAsync: <Item, Accumulator>(array: Item[], fn: (accumu
|
|
|
140
146
|
/**
|
|
141
147
|
* Asynchronously finds the first element that satisfies the async condition.
|
|
142
148
|
*
|
|
149
|
+
* Runs one item at a time, in order, and stops at the first match - as `Array.prototype.find`
|
|
150
|
+
* does.
|
|
151
|
+
*
|
|
143
152
|
* @param array - The array of items to search.
|
|
144
153
|
* @param predicate - An async function that returns a boolean.
|
|
145
154
|
*
|
package/dist/async/retry.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
interface RetryOptions {
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* The total number of attempts, the first one included, before the last error is thrown. Taken
|
|
4
|
+
* as at least 1.
|
|
4
5
|
*
|
|
5
6
|
* @default 3
|
|
6
7
|
*/
|
|
@@ -35,7 +36,7 @@ interface RetryOptions {
|
|
|
35
36
|
*
|
|
36
37
|
* Useful for operations that may fail intermittently, such as network requests.
|
|
37
38
|
*
|
|
38
|
-
* @template
|
|
39
|
+
* @template Args - The arguments the async function takes.
|
|
39
40
|
* @template TaskResult - The result type of the async function.
|
|
40
41
|
*
|
|
41
42
|
* @param task - The async function to wrap with retry logic.
|
|
@@ -68,5 +69,5 @@ interface RetryOptions {
|
|
|
68
69
|
* .catch(error => console.error('Failed after retries:', error));
|
|
69
70
|
* ```
|
|
70
71
|
*/
|
|
71
|
-
export declare const retry: <
|
|
72
|
+
export declare const retry: <Args extends unknown[], TaskResult>(task: (...args: Args) => Promise<TaskResult>, { maxAttempts, delayMs, backoff, onRetry }?: RetryOptions) => ((...args: Args) => Promise<TaskResult>);
|
|
72
73
|
export {};
|
|
@@ -1,19 +1,37 @@
|
|
|
1
|
-
import type { Nullable } from '
|
|
1
|
+
import type { Nullable } from '../types';
|
|
2
2
|
export declare const DATA_TRANSFER_JSON_MIME = "application/json";
|
|
3
3
|
/**
|
|
4
4
|
* Serializes and stores JSON data in a DataTransfer object.
|
|
5
5
|
*
|
|
6
6
|
* Useful for drag-and-drop communication between elements.
|
|
7
7
|
*
|
|
8
|
-
* @
|
|
9
|
-
*
|
|
8
|
+
* @template T - The type of the data.
|
|
9
|
+
*
|
|
10
|
+
* @param dataTransfer - DataTransfer instance from a drag event.
|
|
11
|
+
* @param data - Data to serialize.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* element.addEventListener('dragstart', event => {
|
|
16
|
+
* setDataTransferJson(event.dataTransfer, { id: 'card-1' });
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
10
19
|
*/
|
|
11
20
|
export declare const setDataTransferJson: <T>(dataTransfer: DataTransfer, data: T) => void;
|
|
12
21
|
/**
|
|
13
22
|
* Retrieves and parses JSON data from a DataTransfer object.
|
|
14
23
|
*
|
|
15
|
-
* @
|
|
24
|
+
* @template Value - The type the JSON is expected to have.
|
|
25
|
+
*
|
|
26
|
+
* @param dataTransfer - DataTransfer instance from a drop event.
|
|
16
27
|
*
|
|
17
28
|
* @returns Parsed JSON value or null if not present or invalid.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* element.addEventListener('drop', event => {
|
|
33
|
+
* const card = getDataTransferJson<{ id: string }>(event.dataTransfer);
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
18
36
|
*/
|
|
19
37
|
export declare const getDataTransferJson: <Value>(dataTransfer: DataTransfer) => Nullable<Value>;
|
package/dist/dom/dom.d.ts
CHANGED
|
@@ -9,8 +9,9 @@ export declare const cloneBlob: (blob: Blob) => Blob;
|
|
|
9
9
|
/**
|
|
10
10
|
* Returns the bounding DOMRect of an element based on offset and client dimensions.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
12
|
+
* Unlike `getBoundingClientRect()`, the rect is the element's layout box, before any CSS
|
|
13
|
+
* transform - so it stays put while the element or its container is being translated or scaled.
|
|
14
|
+
* Reading it still needs layout, as `getBoundingClientRect()` does.
|
|
14
15
|
*
|
|
15
16
|
* @param element - The target HTML element.
|
|
16
17
|
* @returns A `DOMRect` representing the element’s offset position and size.
|
|
@@ -32,11 +33,12 @@ export declare const isAnchorHtmlElement: (element: HTMLElement) => element is H
|
|
|
32
33
|
/**
|
|
33
34
|
* Checks whether an element is explicitly marked as contenteditable.
|
|
34
35
|
*
|
|
35
|
-
* Browsers treat elements
|
|
36
|
-
*
|
|
36
|
+
* Browsers treat editable elements as focusable, even if they are not normally
|
|
37
|
+
* keyboard-focusable. An element is editable with `contenteditable` set to `""` (the bare
|
|
38
|
+
* attribute), `"true"` or `"plaintext-only"`, in any case.
|
|
37
39
|
*
|
|
38
40
|
* @param element - The element to inspect.
|
|
39
41
|
*
|
|
40
|
-
* @returns True if `contenteditable
|
|
42
|
+
* @returns True if the element's own `contenteditable` makes it editable.
|
|
41
43
|
*/
|
|
42
44
|
export declare const isContentEditableHtmlElement: (element: HTMLElement) => boolean;
|
|
@@ -11,6 +11,11 @@ interface HTMLElementTransformationValues {
|
|
|
11
11
|
*
|
|
12
12
|
* Only works with 2D transforms (i.e., `matrix(a, b, c, d, e, f)`).
|
|
13
13
|
*
|
|
14
|
+
* The values are the matrix's own entries rather than decomposed angles and factors: `scaleX` is
|
|
15
|
+
* `a`, `skewY` is `b`, `skewX` is `c`, `scaleY` is `d`, and the translation is `e` and `f`. They read
|
|
16
|
+
* as scale and skew only for a transform with no rotation - `rotate(90deg)` gives `scaleX` and
|
|
17
|
+
* `scaleY` of 0 - and a skew is its tangent (`skewX(30deg)` gives `skewX` ≈ 0.577), not its angle.
|
|
18
|
+
*
|
|
14
19
|
* @param element - The element with a CSS transform applied.
|
|
15
20
|
* @returns An object with parsed transformation values.
|
|
16
21
|
*
|
|
@@ -1,2 +1,23 @@
|
|
|
1
|
-
import type { Nullable } from '
|
|
1
|
+
import type { Nullable } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Decodes a base64 string and parses the JSON it holds - the reverse of `encodeBase64Json`.
|
|
4
|
+
*
|
|
5
|
+
* Never throws: a value that is not valid base64, or does not decode to valid JSON, gives `null`.
|
|
6
|
+
* The result is only cast to `Value`, not checked against it.
|
|
7
|
+
*
|
|
8
|
+
* @template Value - The type the JSON is expected to have.
|
|
9
|
+
*
|
|
10
|
+
* @param value - The base64 string to decode.
|
|
11
|
+
*
|
|
12
|
+
* @returns The parsed value, or `null` when the value cannot be decoded or parsed.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* decodeBase64Json<{ name: string; age: number }>('eyJuYW1lIjoiTWlrZSIsImFnZSI6MzN9');
|
|
17
|
+
* // ➜ { name: 'Mike', age: 33 }
|
|
18
|
+
*
|
|
19
|
+
* decodeBase64Json('SGVsbG8=');
|
|
20
|
+
* // ➜ null - "Hello" is not JSON
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
2
23
|
export declare const decodeBase64Json: <Value>(value: string) => Nullable<Value>;
|
|
@@ -1,2 +1,24 @@
|
|
|
1
|
-
import type { Nullable } from '
|
|
1
|
+
import type { Nullable } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Decodes a base64 string to the UTF-8 text it encodes - the reverse of `encodeBase64`.
|
|
4
|
+
*
|
|
5
|
+
* Never throws: a value that is not padded base64 of the standard alphabet, or whose bytes are not
|
|
6
|
+
* valid UTF-8, decodes to `null`.
|
|
7
|
+
*
|
|
8
|
+
* Uses `Uint8Array.fromBase64` where the runtime has it, Node's `Buffer` otherwise, and `atob`
|
|
9
|
+
* last.
|
|
10
|
+
*
|
|
11
|
+
* @param value - The base64 string to decode.
|
|
12
|
+
*
|
|
13
|
+
* @returns The decoded text, or `null` when the value is not valid base64 of UTF-8 text.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* decodeBase64('SGVsbG8=');
|
|
18
|
+
* // ➜ 'Hello'
|
|
19
|
+
*
|
|
20
|
+
* decodeBase64('not base64!');
|
|
21
|
+
* // ➜ null
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
2
24
|
export declare const decodeBase64: (value: string) => Nullable<string>;
|