import React , { ElementType , AllHTMLAttributes , forwardRef , useContext , Ref , } from 'react' ; import cn from 'classnames' ; import { useToggle } from 'react-use' ; import { Link } from '../Link/Link' ; import { Box } from '../Box/Box' ; import { UseBoxStylesProps } from '../Box/useBoxStyles' ; import { ColorSchemeContext , ColorSchemes , } from '../context/ColorSchemeContext/ColorSchemeContext' ; import * as styles from './FocusableBox.css' ; interface Props extends Omit < UseBoxStylesProps , 'component' > , Omit < AllHTMLAttributes < HTMLElement > , 'width' | 'height' | 'className' | 'color' > { component ? : ElementType ; ref ? : Ref < HTMLElement > ; color ? : ColorSchemes ; } type NoNullColorScheme = Exclude < ColorSchemes , null > ; export const FocusableBox = forwardRef < HTMLElement , Props > ( ( { component = Link , display = 'flex' , color = 'purple' , children , className , onFocus , onBlur , ... rest } , ref ) => { const { colorScheme } = useContext ( ColorSchemeContext ) ; const [ isFocused , toggleIsFocused ] = useToggle ( false ) ; const [ isHovered , toggleIsHovered ] = useToggle ( false ) ; const colorKey = colorScheme ?? ( color as NoNullColorScheme ) ; return ( < Box component = { component } display = { display } className = { cn ( styles . focusable , styles . colorSchemes [ colorKey ] , className ) } onFocus = { toggleIsFocused } onBlur = { toggleIsFocused } onMouseOver = { toggleIsHovered } onMouseOut = { toggleIsHovered } ref = { ref } { ... rest } > { typeof children === 'function' ? children ( { isFocused , isHovered } ) : children } < /Box>); } ) ;