JSPM

@ariakit/utils

0.1.2
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 242170
  • Score
    100M100P100Q167115F
  • License MIT

Ariakit utilities

Package Exports

  • @ariakit/utils
  • @ariakit/utils/package.json

Readme

@ariakit/utils

Important: This package is an internal dependency of Ariakit and does not follow semantic versioning, meaning breaking changes may occur in patch and minor versions.

Shared framework-agnostic utilities used by Ariakit packages.

Contents

Installation

npm i @ariakit/utils

Usage

Import helpers from the package root:

import { invariant } from "@ariakit/utils";

This package is ESM-only and exposes a single public entrypoint.

API reference

Array utilities

Array helpers used by Ariakit packages.

toArray

function toArray<T>(arg: T): T extends readonly any[] ? T : T[];

Transforms arg into an array if it's not already.

Example:

toArray("a"); // ["a"]
toArray(["a"]); // ["a"]

addItemToArray

function addItemToArray<T extends any[]>(
  array: T,
  item: T[number],
  index = -1,
): T;

Immutably adds an item to an array.

Returns: A new array with the item in the passed array index.

Example:

addItemToArray(["a", "b", "d"], "c", 2); // ["a", "b", "c", "d"]

flatten2DArray

function flatten2DArray<T>(array: T[][]): T[];

Flattens a 2D array into a one-dimensional array.

Returns: A one-dimensional array.

Example:

flatten2DArray([["a"], ["b"], ["c"]]); // ["a", "b", "c"]

reverseArray

function reverseArray<T>(array: T[]): T[];

Immutably reverses an array.

Returns: Reversed array.

Example:

reverseArray(["a", "b", "c"]); // ["c", "b", "a"]

DOM utilities

DOM helpers for browser, iframe, text input, popup, and scrolling behavior.

canUseDOM

const canUseDOM: boolean;

It's true if it is running in a browser environment or false if it is not (SSR).

Example:

const title = canUseDOM ? document.title : "";

getDocument

function getDocument(node?: Window | Document | Node | null): Document;

Returns element.ownerDocument || document.

getWindow

function getWindow(node?: Window | Document | Node | null): Window;

Returns element.ownerDocument.defaultView || window.

getActiveElement

function getActiveElement(
  node?: Node | null,
  activeDescendant = false,
): HTMLElement | null;

Returns element.ownerDocument.activeElement.

contains

function contains(parent: Node, child: Node): boolean;

Similar to Element.prototype.contains, but a little bit faster when element is the same as child.

Example:

contains(document.getElementById("parent"), document.getElementById("child"));

isElement

function isElement(target: EventTarget | null | undefined): target is Element;

Checks whether the given event target is an element.

event.target and event.relatedTarget are EventTargets, which aren't necessarily elements — for example window or an XMLHttpRequest when an event is dispatched programmatically. Calling Element-only methods such as hasAttribute on those throws, so guard with this before treating them as elements. When you only need a Node — for example to call contains — use isNode instead.

It tests nodeType rather than instanceof Element so that elements coming from same-origin child frames (which addGlobalEventListener also listens on) aren't wrongly rejected for belonging to a different realm.

Example:

if (isElement(event.target)) {
  event.target.hasAttribute("data-active");
}

isNode

function isNode(target: EventTarget | null | undefined): target is Node;

Checks whether the given event target is a node.

Like isElement, but only requires the target to be a Node rather than an element — useful before calling contains, which accepts any node. It still rejects non-node EventTargets (such as window or an XMLHttpRequest) that would make contains throw.

Example:

if (isNode(event.target)) {
  contains(element, event.target);
}

isFrame

function isFrame(element: Element): element is HTMLIFrameElement;

Checks whether element is a frame element.

isButton

function isButton(element: { tagName: string; type?: string }): boolean;

Checks whether element is a native HTML button element.

Example:

isButton(document.querySelector("button")); // true
isButton(document.querySelector("input[type='button']")); // true
isButton(document.querySelector("div")); // false
isButton(document.querySelector("input[type='text']")); // false
isButton(document.querySelector("div[role='button']")); // false

isVisible

function isVisible(element: Element): boolean;

Checks if the element is visible or not.

isTextField

function isTextField(
  element: Element,
): element is HTMLInputElement | HTMLTextAreaElement;

Check whether the given element is a text field, where text field is defined by the ability to select within the input.

Example:

isTextField(document.querySelector("div")); // false
isTextField(document.querySelector("input")); // true
isTextField(document.querySelector("input[type='button']")); // false
isTextField(document.querySelector("textarea")); // true

isTextbox

function isTextbox(element: HTMLElement): boolean;

Check whether the given element is a text field or a content editable element.

getTextboxValue

function getTextboxValue(element: HTMLElement): string;

Returns the value of the text field or content editable element as a string.

getTextboxSelection

function getTextboxSelection(element: HTMLElement): {
  start: number;
  end: number;
};

Returns the start and end offsets of the selection in the element.

getPopupRole

function getPopupRole(
  element?: Element | null,
  fallback?: AriaHasPopup,
): AriaHasPopup;

Returns the popup role from the element's role attribute, if it has one.

getPopupItemRole

function getPopupItemRole(
  element?: Element | null,
  fallback?: AriaRole,
): string | undefined;

Returns the item role attribute based on the popup's role.

scrollIntoViewIfNeeded

function scrollIntoViewIfNeeded(
  element: Element,
  arg?: boolean | ScrollIntoViewOptions,
): void;

Calls element.scrollIntoView() if the element is hidden or partly hidden in the viewport.

getScrollingElement

function getScrollingElement(
  element?: Element | null,
): HTMLElement | Element | null;

Returns the scrolling container element of a given element.

isPartiallyHidden

function isPartiallyHidden(element: Element): boolean;

Determines whether an element is hidden or partially hidden in the viewport.

setSelectionRange

function setSelectionRange(
  element: HTMLInputElement | HTMLTextAreaElement,
  ...args: Parameters<typeof HTMLInputElement.prototype.setSelectionRange>
): void;

SelectionRange only works on a few types of input. Calling setSelectionRange on an unsupported input type may throw an error on certain browsers. To avoid it, we check if its type supports SelectionRange first. It will be a noop to non-supported types until we find a workaround.

See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange

sortBasedOnDOMPosition

function sortBasedOnDOMPosition<T>(
  items: T[],
  getElement: (item: T) => Element | null | undefined,
): T[];

Sort the items based on their DOM position.

Event utilities

Event helpers for dispatching and interpreting browser events.

isPortalEvent

function isPortalEvent(event: Pick<Event, "currentTarget" | "target">): boolean;

Returns true if event has been fired within a React Portal element.

isSelfTarget

function isSelfTarget(event: Pick<Event, "target" | "currentTarget">): boolean;

Returns true if event.target and event.currentTarget are the same.

isOpeningInNewTab

function isOpeningInNewTab(
  event: Pick<MouseEvent, "currentTarget" | "metaKey" | "ctrlKey">,
): boolean;

Checks whether the user event is triggering a page navigation in a new tab.

isDownloading

function isDownloading(
  event: Pick<MouseEvent, "altKey" | "currentTarget">,
): boolean;

Checks whether the user event is triggering a download.

fireEvent

function fireEvent(
  element: Element,
  type: string,
  eventInit?: EventInit,
): boolean;

Creates and dispatches an event.

Example:

fireEvent(document.getElementById("id"), "blur", {
  bubbles: true,
  cancelable: true,
});

fireBlurEvent

function fireBlurEvent(element: Element, eventInit?: FocusEventInit): boolean;

Creates and dispatches a blur event.

Example:

fireBlurEvent(document.getElementById("id"));

fireFocusEvent

function fireFocusEvent(element: Element, eventInit?: FocusEventInit): boolean;

Creates and dispatches a focus event.

Example:

fireFocusEvent(document.getElementById("id"));

fireKeyboardEvent

function fireKeyboardEvent(
  element: Element,
  type: string,
  eventInit?: KeyboardEventInit,
): boolean;

Creates and dispatches a keyboard event.

Example:

fireKeyboardEvent(document.getElementById("id"), "keydown", {
  key: "ArrowDown",
  shiftKey: true,
});

fireClickEvent

function fireClickEvent(
  element: Element,
  eventInit?: PointerEventInit,
): boolean;

Creates and dispatches a click event.

Example:

fireClickEvent(document.getElementById("id"));

isFocusEventOutside

function isFocusEventOutside(
  event: Pick<FocusEvent, "currentTarget" | "relatedTarget">,
  container?: Element | null,
): boolean;

Checks whether the focus/blur event is happening from/to outside of the container element.

Example:

const element = document.getElementById("id");
element.addEventListener("blur", (event) => {
  if (isFocusEventOutside(event)) {
    // ...
  }
});

getInputType

function getInputType(
  event: Event | { nativeEvent: Event },
): string | undefined;

Returns the inputType property of the event, if available.

queueBeforeEvent

function queueBeforeEvent(
  element: Element,
  type: string,
  callback: () => void,
  timeout?: number,
): () => void;

Runs a callback on the next animation frame, but before a certain event.

addGlobalEventListener

function addGlobalEventListener<K extends keyof DocumentEventMap>(
  type: K,
  listener: (event: DocumentEventMap[K]) => any,
  options?: boolean | AddEventListenerOptions,
  scope?: Window,
): () => void;
function addGlobalEventListener(
  type: string,
  listener: EventListenerOrEventListenerObject,
  options?: boolean | AddEventListenerOptions,
  scope?: Window,
): () => void;

Adds a global event listener, including on child frames.

Focus utilities

Focus management helpers for focusable and tabbable elements.

isFocusable

function isFocusable(element: Element): boolean;

Checks whether element is focusable or not.

Example:

isFocusable(document.querySelector("input")); // true
isFocusable(document.querySelector("input[tabindex='-1']")); // true
isFocusable(document.querySelector("input[hidden]")); // false
isFocusable(document.querySelector("input:disabled")); // false

isTabbable

function isTabbable(
  element: Element | HTMLElement | HTMLInputElement,
): element is HTMLElement;

Checks whether element is tabbable or not.

Example:

isTabbable(document.querySelector("input")); // true
isTabbable(document.querySelector("input[tabindex='-1']")); // false
isTabbable(document.querySelector("input[hidden]")); // false
isTabbable(document.querySelector("input:disabled")); // false

getAllFocusableIn

function getAllFocusableIn(
  container: HTMLElement,
  includeContainer?: boolean,
): HTMLElement[];

Returns all the focusable elements in container.

getAllFocusable

function getAllFocusable(includeBody?: boolean): HTMLElement[];

Returns all the focusable elements in the document.

getFirstFocusableIn

function getFirstFocusableIn(
  container: HTMLElement,
  includeContainer?: boolean,
): HTMLElement | null;

Returns the first focusable element in container.

getFirstFocusable

function getFirstFocusable(includeBody?: boolean): HTMLElement | null;

Returns the first focusable element in the document.

getAllTabbableIn

function getAllTabbableIn(
  container: HTMLElement,
  includeContainer?: boolean,
  fallbackToFocusable?: boolean,
): HTMLElement[];

Returns all the tabbable elements in container, including the container itself.

getAllTabbable

function getAllTabbable(fallbackToFocusable?: boolean): HTMLElement[];

Returns all the tabbable elements in the document.

getFirstTabbableIn

function getFirstTabbableIn(
  container: HTMLElement,
  includeContainer?: boolean,
  fallbackToFocusable?: boolean,
): HTMLElement | null;

Returns the first tabbable element in container, including the container itself if it's tabbable.

getFirstTabbable

function getFirstTabbable(fallbackToFocusable?: boolean): HTMLElement | null;

Returns the first tabbable element in the document.

getLastTabbableIn

function getLastTabbableIn(
  container: HTMLElement,
  includeContainer?: boolean,
  fallbackToFocusable?: boolean,
): HTMLElement | null;

Returns the last tabbable element in container, including the container itself if it's tabbable.

getLastTabbable

function getLastTabbable(fallbackToFocusable?: boolean): HTMLElement | null;

Returns the last tabbable element in the document.

getNextTabbableIn

function getNextTabbableIn(
  container: HTMLElement,
  includeContainer?: boolean,
  fallbackToFirst?: boolean,
  fallbackToFocusable?: boolean,
): HTMLElement | null;

Returns the next tabbable element in container.

getNextTabbable

function getNextTabbable(
  fallbackToFirst?: boolean,
  fallbackToFocusable?: boolean,
): HTMLElement | null;

Returns the next tabbable element in the document.

getPreviousTabbableIn

function getPreviousTabbableIn(
  container: HTMLElement,
  includeContainer?: boolean,
  fallbackToLast?: boolean,
  fallbackToFocusable?: boolean,
): HTMLElement | null;

Returns the previous tabbable element in container.

getPreviousTabbable

function getPreviousTabbable(
  fallbackToFirst?: boolean,
  fallbackToFocusable?: boolean,
): HTMLElement | null;

Returns the previous tabbable element in the document.

getClosestFocusable

function getClosestFocusable(element?: HTMLElement | null): HTMLElement | null;

Returns the closest focusable element.

hasFocus

function hasFocus(element: Element): boolean;

Checks if element has focus. Elements that are referenced by aria-activedescendant are also considered.

Example:

hasFocus(document.getElementById("id"));

hasFocusWithin

function hasFocusWithin(element: Node | Element): boolean;

Checks if element has focus within. Elements that are referenced by aria-activedescendant are also considered.

Example:

hasFocusWithin(document.getElementById("id"));

focusIfNeeded

function focusIfNeeded(element: HTMLElement): void;

Focus on an element only if it's not already focused.

disableFocus

function disableFocus(element: HTMLElement): void;

Disable focus on element.

disableFocusIn

function disableFocusIn(
  container: HTMLElement,
  includeContainer?: boolean,
): void;

Makes elements inside container not tabbable.

restoreFocusIn

function restoreFocusIn(container: HTMLElement): void;

Restores tabbable elements inside container that were affected by disableFocusIn.

focusIntoView

function focusIntoView(
  element: HTMLElement,
  options?: ScrollIntoViewOptions,
): void;

Focus on element and scroll into view.

General utilities

General-purpose helpers for state, objects, strings, scheduling, and assertions.

noop

function noop(..._: any[]): any;

Empty function.

shallowEqual

function shallowEqual(a?: AnyObject, b?: AnyObject): boolean;

Compares two objects.

Example:

shallowEqual({ a: "a" }, {}); // false
shallowEqual({ a: "a" }, { b: "b" }); // false
shallowEqual({ a: "a" }, { a: "a" }); // true
shallowEqual({ a: "a" }, { a: "a", b: "b" }); // false

applyState

function applyState<T>(
  argument: SetStateAction<T>,
  currentValue: T | (() => T),
): T;

Receives a setState argument and calls it with currentValue if it's a function. Otherwise return the argument as the new value.

Example:

applyState((value) => value + 1, 1); // 2
applyState(2, 1); // 2

isObject

function isObject(arg: any): arg is Record<any, unknown>;

Checks whether arg is an object or not.

isEmpty

function isEmpty(arg: any): boolean;

Checks whether arg is empty or not.

Example:

isEmpty([]); // true
isEmpty(["a"]); // false
isEmpty({}); // true
isEmpty({ a: "a" }); // false
isEmpty(); // true
isEmpty(null); // true
isEmpty(undefined); // true
isEmpty(""); // true

isInteger

function isInteger(arg: any): boolean;

Checks whether arg is an integer or not.

Example:

isInteger(1); // true
isInteger(1.5); // false
isInteger("1"); // true
isInteger("1.5"); // false

hasOwnProperty

function hasOwnProperty<T extends AnyObject>(
  object: T,
  prop: keyof any,
): prop is keyof T;

Checks whether prop is an own property of obj or not.

chain

function chain<T>(
  ...fns: T[]
): (...args: T extends AnyFunction ? Parameters<T> : never) => void;

Receives functions as arguments and returns a new function that calls all.

cx

function cx(
  ...args: Array<string | null | false | 0 | undefined>
): string | undefined;

Returns a string with the truthy values of args separated by space.

normalizeString

function normalizeString(str: string): string;

Removes diacritics from a string.

omit

function omit<T extends AnyObject, K extends keyof T>(
  object: T,
  keys: ReadonlyArray<K> | K[],
): Omit<T, K>;

Omits specific keys from an object.

Example:

omit({ a: "a", b: "b" }, ["a"]); // { b: "b" }

pick

function pick<T extends AnyObject, K extends keyof T>(
  object: T,
  paths: ReadonlyArray<K> | K[],
): Pick<T, K>;

Picks specific keys from an object.

Example:

pick({ a: "a", b: "b" }, ["a"]); // { a: "a" }

identity

function identity<T>(value: T): T;

Returns the same argument.

beforePaint

function beforePaint(cb: () => void = noop): () => void;

Runs right before the next paint.

afterPaint

function afterPaint(cb: () => void = noop): () => void;

Runs after the next paint.

invariant

function invariant(
  condition: any,
  message?: string | boolean,
): asserts condition;

Asserts that a condition is true, otherwise throws an error.

Example:

invariant(
  condition,
  process.env.NODE_ENV !== "production" && "Invariant failed",
);

getKeys

function getKeys<T extends object>(obj: T): (keyof T)[];

Similar to Object.keys but returns a type-safe array of keys.

isFalsyBooleanCallback

function isFalsyBooleanCallback<T extends unknown[]>(
  booleanOrCallback?: boolean | ((...args: T) => boolean),
  ...args: T
): boolean;

Checks whether a boolean event prop (e.g., hideOnInteractOutside) was intentionally set to false, either with a boolean value or a callback that returns false.

disabledFromProps

function disabledFromProps(props: {
  disabled?: boolean;
  "aria-disabled"?: boolean | "true" | "false";
}): boolean;

Checks whether something is disabled or not based on its props.

disabledFromElement

function disabledFromElement(element: Element): boolean;

Checks whether something is disabled or not based on its DOM attributes.

removeUndefinedValues

function removeUndefinedValues<T extends AnyObject>(obj: T): T;

Removes undefined values from an object.

defaultValue

type DefaultValue<T extends readonly any[], Other = never> = T extends [
  infer Head,
  ...infer Rest,
]
  ? Rest extends []
    ? T[number] | Other
    : undefined extends Head
      ? DefaultValue<Rest, Exclude<Other | Head, undefined>>
      : Exclude<T[number], undefined>
  : never;

function defaultValue<T extends readonly any[]>(...values: T): DefaultValue<T>;

Returns the first value that is not undefined.

Platform utilities

Browser and platform detection helpers.

isTouchDevice

function isTouchDevice(): boolean;

Detects if the device has touch capabilities.

isApple

function isApple(): boolean;

Detects Apple device.

isSafari

function isSafari(): boolean;

Detects Safari browser.

isFirefox

function isFirefox(): boolean;

Detects Firefox browser.

isMac

function isMac(): boolean;

Detects Mac computer.

Type utilities

Shared type utilities used across Ariakit packages.

AnyObject

type AnyObject = Record<string, any>;

Any object.

EmptyObject

type EmptyObject = Record<keyof any, never>;

Empty object.

AnyFunction

type AnyFunction = (...args: any) => any;

Any function.

BivariantCallback

type BivariantCallback<T extends AnyFunction> = {
  bivarianceHack(...args: Parameters<T>): ReturnType<T>;
}["bivarianceHack"];

Workaround for variance issues.

SetStateAction

type SetStateAction<T> = T | BivariantCallback<(prevState: T) => T>;

SetState

type SetState<T> = BivariantCallback<(value: SetStateAction<T>) => void>;

The type of the setState function in [state, setState] = useState().

BooleanOrCallback

type BooleanOrCallback<T> = boolean | BivariantCallback<(arg: T) => boolean>;

A boolean value or a callback that returns a boolean value.

StringWithValue

type StringWithValue<T extends string> = T | (string & Record<never, never>);

A string that will provide autocomplete for specific strings.

ToPrimitive

type ToPrimitive<T> = T extends string
  ? string
  : T extends number
    ? number
    : T extends boolean
      ? boolean
      : T extends AnyFunction
        ? (...args: Parameters<T>) => ReturnType<T>
        : T;

Transforms a type into a primitive type.

Example:

// string
ToPrimitive<"a">;
// number
ToPrimitive<1>;

PickByValue

type PickByValue<T, Value> = {
  [K in keyof T as [Value] extends [T[K]]
    ? T[K] extends Value | undefined
      ? K
      : never
    : never]: T[K];
};

Picks only the properties from a type that have a specific value.

PickRequired

type PickRequired<T, P extends keyof T> = T &
  {
    [K in keyof T]: Pick<Required<T>, K>;
  }[P];

Picks only the required properties from a type.

AriaHasPopup

type AriaHasPopup =
  | boolean
  | "false"
  | "true"
  | "menu"
  | "listbox"
  | "tree"
  | "grid"
  | "dialog"
  | undefined;

Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element.

AriaRole

type AriaRole =
  | "alert"
  | "alertdialog"
  | "application"
  | "article"
  | "banner"
  | "button"
  | "cell"
  | "checkbox"
  | "columnheader"
  | "combobox"
  | "complementary"
  | "contentinfo"
  | "definition"
  // ... 53 more lines
  | "tree"
  | "treegrid"
  | "treeitem"
  | (string & {});

All the WAI-ARIA 1.1 role attribute values from https://www.w3.org/TR/wai-aria-1.1/#role_definitions

Undo utilities

Undo and redo manager utilities.

UndoManager

type Callback = void | (() => Callback | Promise<Callback>);

const UndoManager: {
  canUndo: () => boolean;
  canRedo: () => boolean;
  undo: () => Promise<void>;
  redo: () => Promise<void>;
  execute: (callback: Callback, group?: string) => Promise<void>;
};

Shared undo manager instance.

createUndoManager

type Callback = void | (() => Callback | Promise<Callback>);

interface CreateUndoManagerOptions {
  limit?: number;
}

function createUndoManager({ limit = 100 }: CreateUndoManagerOptions = {}): {
  canUndo: () => boolean;
  canRedo: () => boolean;
  undo: () => Promise<void>;
  redo: () => Promise<void>;
  execute: (callback: Callback, group?: string) => Promise<void>;
};

Creates an undo manager with undo and redo stacks.