Fixes/request deduplication #44

Merged
ilia merged 4 commits from fixes/request-deduplication into main 2026-05-28 19:54:58 +00:00
2 changed files with 17 additions and 0 deletions
Showing only changes of commit c90a258f6c - Show all commits
@@ -40,6 +40,10 @@ interface Props extends
* Skeleton snippet
*/
skeleton?: Snippet;
/**
* Empty-state snippet rendered when the query settled with zero fonts
*/
empty?: Snippet;
}
let {
@@ -47,6 +51,7 @@ let {
onVisibleItemsChange,
weight,
skeleton,
empty,
...rest
}: Props = $props();
@@ -59,6 +64,8 @@ let isCatchingUp = $state(false);
const showInitialSkeleton = $derived(!!skeleton && isLoading && fontCatalogStore.fonts.length === 0);
const showCatchupSkeleton = $derived(!!skeleton && isCatchingUp);
// Settled query with no matches — empty state replaces the (otherwise blank) list.
const showEmpty = $derived(!!empty && !isLoading && !isCatchingUp && fontCatalogStore.fonts.length === 0);
function handleInternalVisibleChange(items: UnifiedFont[]) {
visibleFonts = items;
@@ -163,6 +170,10 @@ function handleNearBottom(_lastVisibleIndex: number) {
<div class="overflow-hidden h-full" transition:fade={{ duration: 300 }}>
{@render skeleton()}
</div>
{:else if showEmpty && empty}
<div class="h-full" transition:fade={{ duration: 200 }}>
{@render empty()}
</div>
{:else}
<!-- VirtualList persists during pagination - no destruction/recreation -->
<VirtualList
@@ -104,6 +104,12 @@ function isFontReady(font: UnifiedFont): boolean {
gap={2}
class="bg-transparent min-h-0 h-full scroll-stable py-2 pl-6 pr-4"
>
{#snippet empty()}
<div class="px-6 py-12 flex items-center justify-center">
<Label variant="muted" size="sm">No typefaces found</Label>
</div>
{/snippet}
{#snippet skeleton()}
<div class="py-2.5 md:py-3 px-7">
{#each { length: 50 } as _, index (index)}