import "./Listbox.css" ; import { Box } from "../../box" ; import { CollectionItem } from "../../collection" ; import { ComponentProps , FocusEvent , KeyboardEvent , MouseEvent , ReactElement , ReactNode , forwardRef , useMemo } from "react" ; import { InteractionProps , InternalProps , Keys , OmitInternalProps , SlotElements , StyledComponentProps , cssModule , isNil , mergeProps , useEventCallback , useRefState , useSlots } from "../../shared" ; import { OptionKeyProp } from "./Listbox" ; import { Text } from "../../typography" ; import { TooltipTrigger } from "../../tooltip" ; import { useListboxContext } from "./ListboxContext" ; const DefaultElement = "div" ; export interface InnerListboxOptionProps extends InternalProps , InteractionProps , StyledComponentProps < typeof DefaultElement > { /**
     * React children.
     */ children : ReactNode ; /**
     * Whether or not the option is disabled.
     */ disabled ? : boolean ; /**
    * Matching collection item.
    */ item : CollectionItem ; } export function InnerListboxOption ( { active , as = DefaultElement , children , disabled , focus , forwardedRef , hover , id , item : { key , tooltip } , ... rest } ) { const { focusManager , focusOnHover , onFocus , onSelect , selectedKeys } = useListboxContext ( ) ; const [ hasMouseOverRef , setHasMouseOver ] = useRefState ( false ) ; const handleClick = useEventCallback ( ( event ) => { onSelect ( event , key ) ; } ) ; const handleKeyUp = useEventCallback ( ( event ) => { if ( event . key === Keys . space ) { event . preventDefault ( ) ; } } ) ; const handleFocus = useEventCallback ( ( event ) => { if ( ! hasMouseOverRef . current ) { const activeElement = focusManager . focusKey ( key ) ; if ( ! isNil ( onFocus ) ) { onFocus ( event , key , activeElement ) ; } } } ) ; const handleMouseEnter = useEventCallback ( ( event ) => { setHasMouseOver ( true ) ; const activeElement = focusManager . focusKey ( key ) ; if ( ! isNil ( onFocus ) ) { onFocus ( event , activeElement . getAttribute ( OptionKeyProp ) , activeElement ) ; } } ) ; const handleMouseLeave = useEventCallback ( ( ) => { setHasMouseOver ( false ) ; } ) ; const { avatar , description , "end-icon" : endIcon , icon , text } = useSlots ( children , useMemo ( ( ) => ( { _ : { defaultWrapper : Text } , avatar : ( avatarElement , slotElements ) => { return { className : "o-ui-listbox-option-avatar" , size : isNil ( slotElements . description ) ? "2xs" : "sm" } ; } , description : { className : "o-ui-listbox-option-description" , id : `${ id }-description` , size : "md" } , "end-icon" : { className : "o-ui-listbox-option-end-icon" , size : "sm" } , icon : ( iconElement , slotElements ) => { return { className : "o-ui-listbox-option-start-icon" , size : isNil ( slotElements . description ) ? "sm" : "lg" } ; } , text : { className : "o-ui-listbox-option-label" , id : `${ id }-label` } } ) , [ id ] ) ) ; const labelId = text ?. props ?. id ; const descriptionId = description ?. props ?. id ; const optionMarkup = ( < Box { ... mergeProps ( rest , { "aria-describedby" : description && descriptionId , "aria-disabled" : disabled , "aria-labelledby" : labelId , "aria-selected" : ! disabled && selectedKeys . includes ( key ) , as , className : cssModule ( "o-ui-listbox-option" , description && "has-description" , focusOnHover && "no-hover" , active && "active" , focus && "focus" , hover && "hover" ) , id , onClick : ! disabled ? handleClick : undefined , [ OptionKeyProp as string ] : key , onFocus : ! disabled ? handleFocus : undefined , onKeyUp : ! disabled ? handleKeyUp : undefined , onMouseEnter : ! disabled && focusOnHover ? handleMouseEnter : undefined , onMouseLeave : ! disabled ? handleMouseLeave : undefined , ref : forwardedRef , role : "option" , tabIndex : ! disabled ? - 1 : undefined } ) } > { icon } { avatar } { text } { description } { endIcon } < /Box>); if ( ! isNil ( tooltip ) ) { const { content : tooltipContent , props : tooltipProps } = tooltip ; return ( < TooltipTrigger { ... mergeProps ( tooltipProps , { position : "left" as const } ) } > { optionMarkup } { tooltipContent } < /TooltipTrigger>); } return optionMarkup ; } InnerListboxOption . defaultElement = DefaultElement ; export const ListboxOption = forwardRef < any , OmitInternalProps < InnerListboxOptionProps > > ( ( props , ref ) => ( < InnerListboxOption { ... props } forwardedRef = { ref } / > ) ) ; export type ListboxOptionProps = ComponentProps < typeof ListboxOption > ;