@ariakit/core
Version:
Ariakit core
322 lines (321 loc) • 14.3 kB
TypeScript
import type { CollectionStoreFunctions, CollectionStoreItem, CollectionStoreOptions, CollectionStoreState } from "../collection/collection-store.ts";
import type { Store, StoreOptions, StoreProps } from "../utils/store.ts";
import type { SetState } from "../utils/types.ts";
type Orientation = "horizontal" | "vertical" | "both";
interface NextOptions extends Pick<Partial<CompositeStoreState>, "activeId" | "focusShift" | "focusLoop" | "focusWrap" | "includesBaseElement" | "renderedItems" | "rtl"> {
/**
* The number of items to skip.
*/
skip?: number;
}
/**
* Creates a composite store.
*/
export declare function createCompositeStore<T extends CompositeStoreItem = CompositeStoreItem>(props?: CompositeStoreProps<T>): CompositeStore<T>;
export type CompositeStoreOrientation = Orientation;
export interface CompositeStoreItem extends CollectionStoreItem {
/**
* The row id of the item. This is only used on two-dimensional composite
* widgets (when using
* [`CompositeRow`](https://ariakit.org/reference/composite-row)).
*/
rowId?: string;
/**
* If enabled, the item will be disabled and users won't be able to focus on
* it using arrow keys.
*/
disabled?: boolean;
/**
* The item children. This can be used for typeahead purposes.
*/
children?: string;
}
export interface CompositeStoreState<T extends CompositeStoreItem = CompositeStoreItem> extends CollectionStoreState<T> {
/**
* The ID of the composite store is used to reference elements within the
* composite widget before hydration. If not provided, a random ID will be
* generated.
*/
id: string;
/**
* The composite element itself. Typically, it's the wrapper element that
* contains composite items. However, in a combobox, it's the input element.
*
* Live examples:
* - [Sliding Menu](https://ariakit.org/examples/menu-slide)
*/
baseElement: HTMLElement | null;
/**
* If enabled, the composite element will act as an
* [aria-activedescendant](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_focus_activedescendant)
* container instead of [roving
* tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex).
* DOM focus will remain on the composite element while its items receive
* virtual focus.
*
* In both scenarios, the item in focus will carry the
* [`data-active-item`](https://ariakit.org/guide/styling#data-active-item)
* attribute.
*
* Live examples:
* - [Select with Combobox and
* Tabs](https://ariakit.org/examples/select-combobox-tab)
* @default false
*/
virtualFocus: boolean;
/**
* Defines the orientation of the composite widget. If the composite has a
* single row or column (one-dimensional), the `orientation` value determines
* which arrow keys can be used to move focus:
* - `both`: all arrow keys work.
* - `horizontal`: only left and right arrow keys work.
* - `vertical`: only up and down arrow keys work.
*
* It doesn't have any effect on two-dimensional composites.
* @default "both"
*/
orientation: Orientation;
/**
* Determines how the
* [`next`](https://ariakit.org/reference/use-composite-store#next) and
* [`previous`](https://ariakit.org/reference/use-composite-store#previous)
* functions will behave. If `rtl` is set to `true`, they will be inverted.
*
* This only affects the composite widget behavior. You still need to set
* `dir="rtl"` on HTML/CSS.
* @default false
*/
rtl: boolean;
/**
* Determines how the focus behaves when the user reaches the end of the
* composite widget.
*
* On one-dimensional composite widgets:
* - `true` loops from the last item to the first item and vice-versa.
* - `horizontal` loops only if
* [`orientation`](https://ariakit.org/reference/composite-provider#orientation)
* is `horizontal` or not set.
* - `vertical` loops only if
* [`orientation`](https://ariakit.org/reference/composite-provider#orientation)
* is `vertical` or not set.
* - If
* [`includesBaseElement`](https://ariakit.org/reference/composite-provider#includesbaseelement)
* is set to `true` (or
* [`activeId`](https://ariakit.org/reference/composite-provider#activeid)
* is initially set to `null`), the composite element will be focused in
* between the last and first items.
*
* On two-dimensional composite widgets (when using
* [`CompositeRow`](https://ariakit.org/reference/composite-row) or explicitly
* passing a [`rowId`](https://ariakit.org/reference/composite-item#rowid)
* prop to composite items):
* - `true` loops from the last row/column item to the first item in the same
* row/column and vice-versa. If it's the last item in the last row, it
* moves to the first item in the first row and vice-versa.
* - `horizontal` loops only from the last row item to the first item in the
* same row.
* - `vertical` loops only from the last column item to the first item in the
* column row.
* - If
* [`includesBaseElement`](https://ariakit.org/reference/composite-provider#includesbaseelement)
* is set to `true` (or
* [`activeId`](https://ariakit.org/reference/composite-provider#activeid)
* is initially set to `null`), vertical loop will have no effect as moving
* down from the last row or up from the first row will focus on the
* composite element.
* - If
* [`focusWrap`](https://ariakit.org/reference/composite-provider#focuswrap)
* matches the value of `focusLoop`, it'll wrap between the last item in the
* last row or column and the first item in the first row or column and
* vice-versa.
*
* Live examples:
* - [Command Menu](https://ariakit.org/examples/dialog-combobox-command-menu)
* - [Command Menu with
* Tabs](https://ariakit.org/examples/dialog-combobox-tab-command-menu)
* @default false
*/
focusLoop: boolean | Orientation;
/**
* **Works only on two-dimensional composite widgets**.
*
* If enabled, moving to the next item from the last one in a row or column
* will focus on the first item in the next row or column and vice-versa.
* - `true` wraps between rows and columns.
* - `horizontal` wraps only between rows.
* - `vertical` wraps only between columns.
* - If
* [`focusLoop`](https://ariakit.org/reference/composite-provider#focusloop)
* matches the value of `focusWrap`, it'll wrap between the last item in the
* last row or column and the first item in the first row or column and
* vice-versa.
*
* Live examples:
* - [Command Menu with
* Tabs](https://ariakit.org/examples/dialog-combobox-tab-command-menu)
* @default false
*/
focusWrap: boolean | Orientation;
/**
* **Works only on two-dimensional composite widgets**.
*
* If enabled, moving up or down when there's no next item or when the next
* item is disabled will shift to the item right before it.
*
* Live examples:
* - [Command Menu with
* Tabs](https://ariakit.org/examples/dialog-combobox-tab-command-menu)
* @default false
*/
focusShift: boolean;
/**
* The number of times the
* [`move`](https://ariakit.org/reference/use-composite-store#move) function
* has been called.
*/
moves: number;
/**
* Indicates if the composite base element (the one with a [composite
* role](https://w3c.github.io/aria/#composite)) should be part of the focus
* order when navigating with arrow keys. In other words, moving to the
* previous element when the first item is in focus will focus on the
* composite element itself. The same applies to the last item when moving to
* the next element.
*
* Live examples:
* - [Submenu with
* Combobox](https://ariakit.org/examples/menu-nested-combobox)
* - [Command Menu](https://ariakit.org/examples/dialog-combobox-command-menu)
* @default false
*/
includesBaseElement: boolean;
/**
* The current active item `id`. The active item is the element within the
* composite widget that has either DOM or virtual focus (in case
* [`virtualFocus`](https://ariakit.org/reference/composite-provider#virtualfocus)
* is enabled).
* - `null` represents the base composite element (the one with a [composite
* role](https://w3c.github.io/aria/#composite)). Users will be able to
* navigate out of it using arrow keys.
* - If `activeId` is initially set to `null`, the
* [`includesBaseElement`](https://ariakit.org/reference/composite-provider#includesbaseelement)
* prop will also default to `true`, which means the base composite element
* itself will have focus and users will be able to navigate to it using
* arrow keys.
*
* Live examples:
* - [Combobox with Tabs](https://ariakit.org/examples/combobox-tabs)
*/
activeId: string | null | undefined;
}
export interface CompositeStoreFunctions<T extends CompositeStoreItem = CompositeStoreItem> extends CollectionStoreFunctions<T> {
/**
* Sets the `baseElement` state.
*/
setBaseElement: SetState<CompositeStoreState<T>["baseElement"]>;
/**
* Sets the
* [`activeId`](https://ariakit.org/reference/composite-provider#activeid)
* state _without moving focus_. If you want to move focus, use the
* [`move`](https://ariakit.org/reference/use-composite-store#move) function
* instead.
* @example
* // Sets the composite element as the active item
* store.setActiveId(null);
* // Sets the item with id "item-1" as the active item
* store.setActiveId("item-1");
* // Sets the next item as the active item
* store.setActiveId(store.next());
*/
setActiveId: SetState<CompositeStoreState<T>["activeId"]>;
/**
* Moves focus to a given item id and sets it as the active item.
* - Passing `null` will focus on the composite element itself (the one with a
* [composite role](https://w3c.github.io/aria/#composite)). Users will be
* able to navigate out of it using arrow keys.
* - If you want to set the active item id _without moving focus_, use the
* [`setActiveId`](https://ariakit.org/reference/use-composite-store#setactiveid)
* function instead.
*
* Live examples:
* - [Select Grid](https://ariakit.org/examples/select-grid)
* @example
* // Moves focus to the composite element
* store.move(null);
* // Moves focus to the item with id "item-1"
* store.move("item-1");
* // Moves focus to the next item
* store.move(store.next());
*/
move: (id?: string | null) => void;
/**
* Returns the id of the next enabled item based on the current
* [`activeId`](https://ariakit.org/reference/composite-provider#activeid)
* state. You can pass additional options to override the current state.
* @example
* const nextId = store.next();
*/
next(options?: NextOptions): string | null | undefined;
/**
* @deprecated Use the object syntax instead: `next({ skip: 2 })`.
*/
next(skip?: number): string | null | undefined;
/**
* Returns the id of the previous enabled item based on the current
* [`activeId`](https://ariakit.org/reference/composite-provider#activeid)
* state. You can pass additional options to override the current state.
* @example
* const previousId = store.previous();
*/
previous(options?: NextOptions): string | null | undefined;
/**
* @deprecated Use the object syntax instead: `previous({ skip: 2 })`.
*/
previous(skip?: number): string | null | undefined;
/**
* Returns the id of the enabled item above based on the current
* [`activeId`](https://ariakit.org/reference/composite-provider#activeid)
* state. You can pass additional options to override the current state.
* @example
* const upId = store.up();
*/
up(options?: NextOptions): string | null | undefined;
/**
* @deprecated Use the object syntax instead: `up({ skip: 2 })`.
*/
up(skip?: number): string | null | undefined;
/**
* Returns the id of the enabled item below based on the current
* [`activeId`](https://ariakit.org/reference/composite-provider#activeid)
* state. You can pass additional options to override the current state.
* @example
* const downId = store.down();
*/
down(options?: NextOptions): string | null | undefined;
/**
* @deprecated Use the object syntax instead: `down({ skip: 2 })`.
*/
down(skip?: number): string | null | undefined;
/**
* Returns the id of the first enabled item.
*/
first: () => string | null | undefined;
/**
* Returns the id of the last enabled item.
*/
last: () => string | null | undefined;
}
export interface CompositeStoreOptions<T extends CompositeStoreItem = CompositeStoreItem> extends CollectionStoreOptions<T>, StoreOptions<CompositeStoreState<T>, "id" | "virtualFocus" | "orientation" | "rtl" | "focusLoop" | "focusWrap" | "focusShift" | "includesBaseElement" | "activeId"> {
/**
* The composite item id that should be active by default when the composite
* widget is rendered. If `null`, the composite element itself will have focus
* and users will be able to navigate to it using arrow keys. If `undefined`,
* the first enabled item will be focused.
*/
defaultActiveId?: CompositeStoreState<T>["activeId"];
}
export interface CompositeStoreProps<T extends CompositeStoreItem = CompositeStoreItem> extends CompositeStoreOptions<T>, StoreProps<CompositeStoreState<T>> {
}
export interface CompositeStore<T extends CompositeStoreItem = CompositeStoreItem> extends CompositeStoreFunctions<T>, Store<CompositeStoreState<T>> {
}
export {};