UNPKG

@workday/canvas-kit-react

Version:

The parent module that contains all Workday Canvas Kit React components

70 lines (69 loc) 3.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.useListItemRovingFocus = void 0; const react_1 = __importDefault(require("react")); const common_1 = require("@workday/canvas-kit-react/common"); const useCursorListModel_1 = require("./useCursorListModel"); const keyUtils_1 = require("./keyUtils"); const focusOnCurrentCursor_1 = require("./focusOnCurrentCursor"); /** * This elemProps hook is used for cursor navigation by using [Roving * Tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex). Only a single item in the * collection has a tab stop. Pressing an arrow key moves the tab stop to a different item in the * corresponding direction. See the [Roving Tabindex](#roving-tabindex) example. This elemProps hook * should be applied to an `*.Item` component. * * ```ts * const useMyItem = composeHooks( * useListItemRovingFocus, // adds the roving tabindex support * useListItemRegister * ); ``` */ exports.useListItemRovingFocus = (0, common_1.createElemPropsHook)(useCursorListModel_1.useCursorListModel)((model, _ref, elemProps = {}) => { // Create a ref out of state. We don't want to watch state on unmount, so we use a ref to get the // current value at the time of unmounting. Otherwise, `state.items` would be a cached value of an // empty array const stateRef = react_1.default.useRef(model.state); stateRef.current = model.state; const keyElementRef = react_1.default.useRef(null); const isRTL = (0, common_1.useIsRTL)(); react_1.default.useEffect(() => { // If the cursor change was triggered by this hook, we should change focus if (keyElementRef.current) { (0, focusOnCurrentCursor_1.focusOnCurrentCursor)(model, model.state.cursorId, keyElementRef.current).then(() => { // Reset key element since focus was successful keyElementRef.current = null; }); } // we only want to run this effect if the cursor changes and not any other time // eslint-disable-next-line react-hooks/exhaustive-deps }, [model.state.cursorId]); // Roving focus must always have a focus stop to function correctly react_1.default.useEffect(() => { if (!model.state.cursorId && model.state.items.length) { model.events.goTo({ id: model.state.items[0].id }); } }, [model.state.cursorId, model.state.items, model.events]); return { onKeyDown(event) { const handled = (0, keyUtils_1.keyboardEventToCursorEvents)(event, model, isRTL); if (handled) { event.preventDefault(); keyElementRef.current = event.currentTarget; } }, onClick() { model.events.goTo({ id: elemProps['data-id'] }); }, 'data-focus-id': `${model.state.id}-${elemProps['data-id']}`, tabIndex: !model.state.cursorId ? 0 // cursor isn't known yet, be safe and mark this as focusable : !!elemProps['data-id'] && model.state.cursorId === elemProps['data-id'] ? 0 // A name is known and cursor is here : -1, // A name is known an cursor is somewhere else }; });