chore: cleanup

This commit is contained in:
Adam
2026-01-20 07:10:40 -06:00
parent dd5b5f5482
commit 340285575b
4 changed files with 142 additions and 18 deletions

View File

@@ -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