import type { KeyboardEvent, ReactElement, ReactNode } from 'react'; import { Children, cloneElement } from 'react'; import { FocusScope, mergeProps, useFocusManager } from 'react-aria'; import { createComponent } from '../../utils'; import type { FocusScopeProps } from './FocusScope'; type GroupChildrenProps = { children: ReactNode; }; const GroupChildren = createComponent(({ children }) => { const { onKeyDown } = useFocusNavigator(); if (isRightChildrenType(children)) { return ( <> {Children.map(children as ReactElement[], (child: ReactElement) => { return cloneElement(child, mergeProps(child.props, { onKeyDown })); })} ); } throw new Error('Children type not accepted'); }); export type FocusArrowNavigatorProps = FocusScopeProps & { children: ReactNode; }; export const FocusArrowNavigator = createComponent( ({ children, ...props }) => ( {children} ), ); export function useFocusNavigator() { const focusManager = useFocusManager(); const onKeyDown = (e: KeyboardEvent) => { if (e.key === 'ArrowRight') { focusManager.focusNext(); } if (e.key === 'ArrowLeft') { focusManager.focusPrevious(); } if (e.key === 'ArrowUp') { focusManager.focusNext(); } if (e.key === 'ArrowDown') { focusManager.focusPrevious(); } }; return { onKeyDown, }; } function isRightChildrenType(children: ReactNode) { return ( typeof children !== 'boolean' && typeof children !== 'string' && typeof children !== 'undefined' && typeof children !== 'number' ); }