UNPKG

@wordpress/components

Version:
236 lines (232 loc) 6.75 kB
/** * Composite is a component that may contain navigable items represented by * Composite.Item. It's inspired by the WAI-ARIA Composite Role and implements * all the keyboard navigation mechanisms to ensure that there's only one * tab stop for the whole Composite element. This means that it can behave as * a roving tabindex or aria-activedescendant container. * * @see https://ariakit.org/components/composite */ /** * External dependencies */ import * as Ariakit from '@ariakit/react'; /** * WordPress dependencies */ import { isRTL } from '@wordpress/i18n'; import { useMemo, forwardRef } from '@wordpress/element'; /** * Internal dependencies */ import { CompositeContext } from './context'; import { CompositeGroup } from './group'; import { CompositeGroupLabel } from './group-label'; import { CompositeHover } from './hover'; import { CompositeItem } from './item'; import { CompositeRow } from './row'; import { CompositeTypeahead } from './typeahead'; import { jsx as _jsx } from "react/jsx-runtime"; /** * Renders a widget based on the WAI-ARIA [`composite`](https://w3c.github.io/aria/#composite) * role, which provides a single tab stop on the page and arrow key navigation * through the focusable descendants. * * @example * ```jsx * import { Composite } from '@wordpress/components'; * * <Composite> * <Composite.Item>Item 1</Composite.Item> * <Composite.Item>Item 2</Composite.Item> * </Composite> * ``` */ export const Composite = Object.assign(forwardRef(function Composite({ // Composite store props activeId, defaultActiveId, setActiveId, focusLoop = false, focusWrap = false, focusShift = false, virtualFocus = false, orientation = 'both', rtl = isRTL(), // Composite component props children, disabled = false, // Rest props ...props }, ref) { // @ts-expect-error The store prop is undocumented and only used by the // legacy compat layer. const storeProp = props.store; const internalStore = Ariakit.useCompositeStore({ activeId, defaultActiveId, setActiveId, focusLoop, focusWrap, focusShift, virtualFocus, orientation, rtl }); const store = storeProp !== null && storeProp !== void 0 ? storeProp : internalStore; const contextValue = useMemo(() => ({ store }), [store]); return /*#__PURE__*/_jsx(Ariakit.Composite, { disabled: disabled, store: store, ...props, ref: ref, children: /*#__PURE__*/_jsx(CompositeContext.Provider, { value: contextValue, children: children }) }); }), { /** * Renders a group element for composite items. * * @example * ```jsx * import { Composite } from '@wordpress/components'; * * <Composite> * <Composite.Group> * <Composite.GroupLabel>Label</Composite.GroupLabel> * <Composite.Item>Item 1</Composite.Item> * <Composite.Item>Item 2</Composite.Item> * </CompositeGroup> * </Composite> * ``` */ Group: Object.assign(CompositeGroup, { displayName: 'Composite.Group' }), /** * Renders a label in a composite group. This component must be wrapped with * `Composite.Group` so the `aria-labelledby` prop is properly set on the * composite group element. * * @example * ```jsx * import { Composite } from '@wordpress/components'; * * <Composite> * <Composite.Group> * <Composite.GroupLabel>Label</Composite.GroupLabel> * <Composite.Item>Item 1</Composite.Item> * <Composite.Item>Item 2</Composite.Item> * </CompositeGroup> * </Composite> * ``` */ GroupLabel: Object.assign(CompositeGroupLabel, { displayName: 'Composite.GroupLabel' }), /** * Renders a composite item. * * @example * ```jsx * import { Composite } from '@wordpress/components'; * * <Composite> * <Composite.Item>Item 1</Composite.Item> * <Composite.Item>Item 2</Composite.Item> * <Composite.Item>Item 3</Composite.Item> * </Composite> * ``` */ Item: Object.assign(CompositeItem, { displayName: 'Composite.Item' }), /** * Renders a composite row. Wrapping `Composite.Item` elements within * `Composite.Row` will create a two-dimensional composite widget, such as a * grid. * * @example * ```jsx * import { Composite } from '@wordpress/components'; * * <Composite> * <Composite.Row> * <Composite.Item>Item 1.1</Composite.Item> * <Composite.Item>Item 1.2</Composite.Item> * <Composite.Item>Item 1.3</Composite.Item> * </Composite.Row> * <Composite.Row> * <Composite.Item>Item 2.1</Composite.Item> * <Composite.Item>Item 2.2</Composite.Item> * <Composite.Item>Item 2.3</Composite.Item> * </Composite.Row> * </Composite> * ``` */ Row: Object.assign(CompositeRow, { displayName: 'Composite.Row' }), /** * Renders an element in a composite widget that receives focus on mouse move * and loses focus to the composite base element on mouse leave. This should * be combined with the `Composite.Item` component. * * @example * ```jsx * import { Composite } from '@wordpress/components'; * * <Composite> * <Composite.Hover render={ <Composite.Item /> }> * Item 1 * </Composite.Hover> * <Composite.Hover render={ <Composite.Item /> }> * Item 2 * </Composite.Hover> * </Composite> * ``` */ Hover: Object.assign(CompositeHover, { displayName: 'Composite.Hover' }), /** * Renders a component that adds typeahead functionality to composite * components. Hitting printable character keys will move focus to the next * composite item that begins with the input characters. * * @example * ```jsx * import { Composite } from '@wordpress/components'; * * <Composite render={ <CompositeTypeahead /> }> * <Composite.Item>Item 1</Composite.Item> * <Composite.Item>Item 2</Composite.Item> * </Composite> * ``` */ Typeahead: Object.assign(CompositeTypeahead, { displayName: 'Composite.Typeahead' }), /** * The React context used by the composite components. It can be used by * to access the composite store, and to forward the context when composite * sub-components are rendered across portals (ie. `SlotFill` components) * that would not otherwise forward the context to the `Fill` children. * * @example * ```jsx * import { Composite } from '@wordpress/components'; * import { useContext } from '@wordpress/element'; * * const compositeContext = useContext( Composite.Context ); * ``` */ Context: Object.assign(CompositeContext, { displayName: 'Composite.Context' }) }); //# sourceMappingURL=index.js.map