import { callHandler, mergeDefaultProps, mergeRefs } from "@kobalte/utils"; import { type Component, type JSX, type ValidComponent, createEffect, onCleanup, splitProps, } from "solid-js"; import * as Listbox from "../listbox"; import type { ListboxRootCommonProps, ListboxRootRenderProps, } from "../listbox"; import type { ElementOf, PolymorphicProps } from "../polymorphic"; import { useSelectContext } from "./select-context"; export interface SelectListboxOptions extends Pick< Listbox.ListboxRootOptions, "scrollRef" | "scrollToItem" | "children" > {} export interface SelectListboxCommonProps extends ListboxRootCommonProps { "aria-labelledby": string | undefined; } export interface SelectListboxRenderProps extends SelectListboxCommonProps, ListboxRootRenderProps {} export type SelectListboxProps< Option, OptGroup = never, T extends ValidComponent | HTMLElement = HTMLElement, > = SelectListboxOptions & Partial>>; /** * Contains all the items of a `Select`. */ export function SelectListbox< Option = any, OptGroup = never, T extends ValidComponent = "ul", >(props: PolymorphicProps>) { const context = useSelectContext(); const mergedProps = mergeDefaultProps( { id: context.generateId("listbox"), }, props as SelectListboxProps, ); const [local, others] = splitProps(mergedProps, ["ref", "id", "onKeyDown"]); createEffect(() => onCleanup(context.registerListboxId(local.id))); const onKeyDown: JSX.EventHandlerUnion = (e) => { callHandler(e, local.onKeyDown); // Prevent from clearing the selection by `createSelectableCollection` on escape. if (e.key === "Escape") { e.preventDefault(); } }; return ( > > ref={mergeRefs(context.setListboxRef, local.ref)} id={local.id} state={context.listState()} virtualized={context.isVirtualized()} autoFocus={context.autoFocus()} shouldSelectOnPressUp shouldFocusOnHover shouldFocusWrap={context.shouldFocusWrap()} disallowTypeAhead={context.disallowTypeAhead()} aria-labelledby={context.listboxAriaLabelledBy()} renderItem={context.renderItem} renderSection={context.renderSection} onKeyDown={onKeyDown} {...others} /> ); }