import { createEffect, Show, For, type JSX, splitProps } from "solid-js" import { Dialog, DialogProps, Icon, IconButton, Input } from "@opencode-ai/ui" import { createStore } from "solid-js/store" import { FilteredListProps, useFilteredList } from "@opencode-ai/ui/hooks" interface SelectDialogProps extends FilteredListProps, Pick { title: string placeholder?: string emptyMessage?: string children: (item: T) => JSX.Element onSelect?: (value: T | undefined) => void } export function SelectDialog(props: SelectDialogProps) { const [dialog, others] = splitProps(props, ["trigger", "onOpenChange", "defaultOpen"]) let closeButton!: HTMLButtonElement let scrollRef: HTMLDivElement | undefined const [store, setStore] = createStore({ mouseActive: false, }) const { filter, grouped, flat, reset, clear, active, setActive, onKeyDown, onInput } = useFilteredList({ items: others.items, key: others.key, filterKeys: others.filterKeys, current: others.current, groupBy: others.groupBy, sortBy: others.sortBy, sortGroupsBy: others.sortGroupsBy, }) createEffect(() => { filter() scrollRef?.scrollTo(0, 0) reset() }) createEffect(() => { const all = flat() if (store.mouseActive || all.length === 0) return if (active() === others.key(all[0])) { scrollRef?.scrollTo(0, 0) return } const element = scrollRef?.querySelector(`[data-key="${active()}"]`) element?.scrollIntoView({ block: "nearest", behavior: "smooth" }) }) const handleInput = (value: string) => { onInput(value) reset() } const handleSelect = (item: T | undefined) => { others.onSelect?.(item) closeButton.click() } const handleKey = (e: KeyboardEvent) => { setStore("mouseActive", false) if (e.key === "Escape") return if (e.key === "Enter") { e.preventDefault() const selected = flat().find((x) => others.key(x) === active()) if (selected) handleSelect(selected) } else { onKeyDown(e) } } const handleOpenChange = (open: boolean) => { if (!open) clear() props.onOpenChange?.(open) } return ( {others.title}
handleInput(value)} onKeyDown={handleKey} placeholder={others.placeholder} autofocus spellcheck={false} autocorrect="off" autocomplete="off" autocapitalize="off" />
{ onInput("") reset() }} />
0} fallback={
{props.emptyMessage ?? "No search results"} for{" "} "{filter()}"
} > {(group) => (
{group.category}
{(item) => ( )}
)}
) }