diff options
| author | Adam <[email protected]> | 2026-01-20 07:10:40 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2026-01-20 07:33:44 -0600 |
| commit | 340285575b510f4ab466fa80d0de1cf20b4e048a (patch) | |
| tree | 9587a21664547875d060258ad7ee7b3de0dba290 /packages/ui/src/components/select.tsx | |
| parent | dd5b5f5482df86959f0ea90e20f86ca7a5e19b08 (diff) | |
| download | opencode-340285575b510f4ab466fa80d0de1cf20b4e048a.tar.gz opencode-340285575b510f4ab466fa80d0de1cf20b4e048a.zip | |
chore: cleanup
Diffstat (limited to 'packages/ui/src/components/select.tsx')
| -rw-r--r-- | packages/ui/src/components/select.tsx | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/packages/ui/src/components/select.tsx b/packages/ui/src/components/select.tsx index e60fcbee1..245a36d38 100644 --- a/packages/ui/src/components/select.tsx +++ b/packages/ui/src/components/select.tsx @@ -1,5 +1,5 @@ import { Select as Kobalte } from "@kobalte/core/select" -import { createMemo, splitProps, type ComponentProps, type JSX } from "solid-js" +import { createMemo, onCleanup, splitProps, type ComponentProps, type JSX } from "solid-js" import { pipe, groupBy, entries, map } from "remeda" import { Button, ButtonProps } from "./button" import { Icon } from "./icon" @@ -12,6 +12,7 @@ export type SelectProps<T> = Omit<ComponentProps<typeof Kobalte<T>>, "value" | " label?: (x: T) => string groupBy?: (x: T) => string onSelect?: (value: T | undefined) => void + onHighlight?: (value: T | undefined) => (() => void) | void class?: ComponentProps<"div">["class"] classList?: ComponentProps<"div">["classList"] children?: (item: T | undefined) => JSX.Element @@ -28,8 +29,40 @@ export function Select<T>(props: SelectProps<T> & ButtonProps) { "label", "groupBy", "onSelect", + "onHighlight", + "onOpenChange", "children", ]) + + const state = { + key: undefined as string | undefined, + cleanup: undefined as (() => void) | void, + } + + const stop = () => { + state.cleanup?.() + state.cleanup = undefined + state.key = undefined + } + + const keyFor = (item: T) => (local.value ? local.value(item) : (item as string)) + + const move = (item: T | undefined) => { + if (!local.onHighlight) return + if (!item) { + stop() + return + } + + const key = keyFor(item) + if (state.key === key) return + state.cleanup?.() + state.cleanup = local.onHighlight(item) + state.key = key + } + + onCleanup(stop) + const grouped = createMemo(() => { const result = pipe( local.options, @@ -58,12 +91,14 @@ export function Select<T>(props: SelectProps<T> & ButtonProps) { )} itemComponent={(itemProps) => ( <Kobalte.Item + {...itemProps} data-slot="select-select-item" classList={{ ...(local.classList ?? {}), [local.class ?? ""]: !!local.class, }} - {...itemProps} + onPointerEnter={() => move(itemProps.item.rawValue)} + onPointerMove={() => move(itemProps.item.rawValue)} > <Kobalte.ItemLabel data-slot="select-select-item-label"> {local.children @@ -79,6 +114,11 @@ export function Select<T>(props: SelectProps<T> & ButtonProps) { )} onChange={(v) => { local.onSelect?.(v ?? undefined) + stop() + }} + onOpenChange={(open) => { + local.onOpenChange?.(open) + if (!open) stop() }} > <Kobalte.Trigger |
