feat(VirtualList): add auto-pagination and correct scrollbar height
- Add 'total' prop to VirtualList for accurate scrollbar height in pagination scenarios - Add 'onNearBottom' callback to trigger auto-loading when user scrolls near end - Update FontVirtualList to forward the new props - Implement auto-pagination in SuggestedFonts component (remove manual Load More button) - Display loading indicator when fetching next batch - Show accurate font count (e.g., "Showing 150 of 1920 fonts") Key changes: - VirtualList now uses total count for height calculation instead of items.length - Auto-fetches next page when user scrolls within 5 items of the end - Only fetches if hasMore is true and not already fetching - Backward compatible: total defaults to items.length when not provided
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<!--
|
||||
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 {
|
||||
@@ -8,9 +9,58 @@ import {
|
||||
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>
|
||||
|
||||
<FontVirtualList items={unifiedFontStore.fonts}>
|
||||
{#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}
|
||||
|
||||
Reference in New Issue
Block a user