Files
frontend-svelte/src/features/GetFonts/ui/SuggestedFonts/SuggestedFonts.svelte

68 lines
2.0 KiB
Svelte
Raw Normal View History

<!--
Component: SuggestedFonts
Renders a list of suggested fonts in a virtualized list to improve performance.
Includes pagination with auto-loading when scrolling near the bottom.
-->
<script lang="ts">
import {
FontListItem,
FontVirtualList,
unifiedFontStore,
} from '$entities/Font';
import { cn } from '$shared/shadcn/utils/shadcn-utils';
/**
* Load more fonts by moving to the next page
*/
function loadMore() {
if (!unifiedFontStore.pagination.hasMore || unifiedFontStore.isFetching) {
return;
}
unifiedFontStore.nextPage();
}
/**
* Handle scroll near bottom - auto-load next page
*
* Triggered when the user scrolls within 5 items of the end of the list.
* Only fetches if there are more pages available and not already fetching.
*/
function handleNearBottom(lastVisibleIndex: number) {
const { hasMore, total } = unifiedFontStore.pagination;
const itemsRemaining = total - lastVisibleIndex;
// Only trigger if within 5 items of the end, more data exists, and not already fetching
if (itemsRemaining <= 5 && hasMore && !unifiedFontStore.isFetching) {
loadMore();
}
}
/**
* Calculate display range for pagination info
*/
const displayRange = $derived.by(() => {
const { offset, limit, total } = unifiedFontStore.pagination;
const loadedCount = Math.min(offset + limit, total);
return `Showing ${loadedCount} of ${total} fonts`;
});
</script>
{#if unifiedFontStore.pagination.total > 0 && !unifiedFontStore.isLoading}
<div class="text-sm text-muted-foreground px-2 py-2">
{displayRange}
{#if unifiedFontStore.isFetching}
<span class="ml-2 text-xs text-muted-foreground/70">(Loading...)</span>
{/if}
</div>
{/if}
<FontVirtualList
items={unifiedFontStore.fonts}
total={unifiedFontStore.pagination.total}
onNearBottom={handleNearBottom}
>
{#snippet children({ item: font, isVisible, proximity })}
<FontListItem {font} {isVisible} {proximity} />
{/snippet}
</FontVirtualList>