kunkun/packages/ui/src/components/extension/templates/virtual-command-group.svelte
Huakun 41302a29ff
fix: list view item's action panel and listview undefined error (#224)
* fix: list view item's action panel and listview undefined error

* chore: increase Node.js memory limit for build processes

* chore: configure Node.js memory limit for Tauri build process

* refactor: delete unecessary ui component code
2025-03-01 21:43:23 -05:00

91 lines
2.3 KiB
Svelte

<script lang="ts">
import { ListSchema } from "@kksh/api/models"
import { createVirtualizer, type VirtualItem } from "@tanstack/svelte-virtual"
import Fuse from "fuse.js"
import { getContext } from "svelte"
import { DraggableCommandGroup } from "../../custom"
import ListItem from "./list-item.svelte"
let {
heading,
filterMode,
items,
parentRef,
searchTerm,
sectionHeight = $bindable(0),
sectionRef = $bindable(null),
scrollMargin = $bindable(0),
onListItemSelected
}: {
heading: string
filterMode: "none" | "default"
items: ListSchema.Item[]
sectionHeight: number
searchTerm: string
parentRef: HTMLDivElement | null
sectionRef: HTMLDivElement | null
scrollMargin: number
onListItemSelected?: (value: string) => void
} = $props()
const fuse = new Fuse(items, {
includeScore: true,
threshold: 0.2,
keys: ["title", "subTitle", "keywords"]
})
const itemHeight = getContext<number>("itemHeight") ?? 30
let virtualizer = createVirtualizer<HTMLDivElement, HTMLDivElement>({
count: items.length,
getScrollElement: () => parentRef,
estimateSize: () => itemHeight,
overscan: 5
})
let virtualItems: VirtualItem[] = $state([])
let itemsTotalSize = $state(0)
let resultingItems = $derived(
// when search term changes, update the resulting items
filterMode === "none"
? searchTerm.length > 0
? fuse.search(searchTerm).map((item) => item.item)
: items
: items
)
$effect(() => {
// when props.items update, update the fuse collection
fuse.setCollection(items)
})
$effect(() => {
// when resultingItems changes, update virtualizer count and scrollMargin
$virtualizer.setOptions({ count: resultingItems.length, scrollMargin })
virtualItems = $virtualizer.getVirtualItems()
itemsTotalSize = $virtualizer.getTotalSize()
})
$effect(() => {
sectionHeight = itemsTotalSize + itemHeight
})
</script>
<DraggableCommandGroup
heading={`${heading} (${items.length})`}
bind:ref={sectionRef}
class="relative"
style="height: {sectionHeight}px;"
>
{#each virtualItems as row (row.index)}
{@const item = resultingItems[row.index]}
{#if item}
<ListItem
height={row.size}
translateY={row.start - scrollMargin + itemHeight}
{item}
onSelect={() => onListItemSelected?.(item.value)}
/>
{/if}
{/each}
</DraggableCommandGroup>