import { mergeDefaultProps, mergeRefs } from "@kobalte/utils"; import { type Component, type ValidComponent, createEffect, onCleanup, splitProps, } from "solid-js"; import { useFormControlContext } from "../form-control"; import * as Listbox from "../listbox"; import type { ElementOf, PolymorphicProps } from "../polymorphic"; import { useComboboxContext } from "./combobox-context"; export interface ComboboxListboxOptions extends Pick< Listbox.ListboxRootOptions, "scrollRef" | "scrollToItem" | "children" > {} export interface ComboboxListboxCommonProps< T extends HTMLElement = HTMLElement, > { id: string; ref: T | ((el: T) => void); } export interface ComboboxListboxRenderProps extends ComboboxListboxCommonProps, Listbox.ListboxRootRenderProps { "aria-label": string | undefined; "aria-labelledby": string | undefined; } export type ComboboxListboxProps< Option, OptGroup = never, T extends ValidComponent | HTMLElement = HTMLElement, > = ComboboxListboxOptions & Partial>>; /** * Contains all the items of a `Combobox`. */ export function ComboboxListbox< Option = any, OptGroup = never, T extends ValidComponent = "ul", >(props: PolymorphicProps>) { const formControlContext = useFormControlContext(); const context = useComboboxContext(); const mergedProps = mergeDefaultProps( { id: context.generateId("listbox"), }, props as ComboboxListboxProps, ); const [local, others] = splitProps(mergedProps, ["ref"]); const ariaLabelledBy = () => { return formControlContext.getAriaLabelledBy( others.id, context.listboxAriaLabel(), undefined, ); }; createEffect(() => onCleanup(context.registerListboxId(others.id!))); return ( > > ref={mergeRefs(context.setListboxRef, local.ref)} state={context.listState()} autoFocus={context.autoFocus()} shouldUseVirtualFocus shouldSelectOnPressUp shouldFocusOnHover aria-label={context.listboxAriaLabel()} aria-labelledby={ariaLabelledBy()} renderItem={context.renderItem} renderSection={context.renderSection} virtualized={context.isVirtualized()} {...others} /> ); }