Files
pybricks-code/src/components/toolbar/aria.ts
T
David Lechner 9d71bb4734 eslint: enable react-hooks checks
Also fix all errors, which can lead to subtile bugs.

Mostly fixings deps and refactoring to make typescript happy.
2022-12-17 13:56:01 -06:00

78 lines
2.3 KiB
TypeScript

// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
import { filterDOMProps } from '@react-aria/utils';
import {
FocusEventHandler,
HTMLAttributes,
KeyboardEventHandler,
useCallback,
useContext,
} from 'react';
import { FocusScope, mergeProps, useFocusManager } from 'react-aria';
import { ToolbarStateContext } from './state';
import type { AriaToolbarProps } from './types';
// for doc comment link
FocusScope;
type ToolbarAria = {
toolbarProps: HTMLAttributes<HTMLElement>;
};
/** React hook for creating toolbar element props. */
export function useToolbar(props: AriaToolbarProps): ToolbarAria {
const domProps = filterDOMProps(props, { labelable: true });
return { toolbarProps: mergeProps(domProps, { role: 'toolbar' }) };
}
type ToolbarItemFocusAria = {
toolbarItemFocusProps: HTMLAttributes<HTMLElement>;
excludeFromTabOrder: boolean;
};
/**
* React hook for creating toolbar item element props for focus management.
*
* Using this hook requires the current element to be inside of an
* {@link ToolbarStateContext} and to be inside of a {@link FocusScope}.
*/
export function useToolbarItemFocus(props: { id: string }): ToolbarItemFocusAria {
const { id } = props;
const { lastFocusedItem, setLastFocusedItem } = useContext(ToolbarStateContext);
const focusManager = useFocusManager();
const onKeyDown = useCallback<KeyboardEventHandler<HTMLElement>>(
(e) => {
switch (e.key) {
case 'ArrowLeft':
focusManager.focusPrevious({ wrap: true });
break;
case 'ArrowRight':
focusManager.focusNext({ wrap: true });
break;
case 'Home':
focusManager.focusFirst();
break;
case 'End':
focusManager.focusLast();
break;
default:
return;
}
},
[focusManager],
);
const onFocus = useCallback<FocusEventHandler<HTMLElement>>(
(e) => {
setLastFocusedItem(e.target.id);
},
[setLastFocusedItem],
);
const excludeFromTabOrder = id !== lastFocusedItem;
return { toolbarItemFocusProps: { onKeyDown, onFocus }, excludeFromTabOrder };
}