Files
frontend-svelte/src/widgets/SampleList/ui/SampleList/SampleList.svelte

81 lines
2.1 KiB
Svelte

<!--
Component: SampleList
Renders a list of fonts in a virtualized list to improve performance.
- Includes pagination with auto-loading when scrolling near the bottom.
- Provides a typography menu for font setup.
-->
<script lang="ts">
import {
FontListItem,
FontVirtualList,
unifiedFontStore,
} from '$entities/Font';
import { FontSampler } from '$features/DisplayFont';
import {
TypographyMenu,
controlManager,
} from '$features/SetupFont';
import { throttle } from '$shared/lib/utils';
let text = $state('The quick brown fox jumps over the lazy dog...');
let wrapper = $state<HTMLDivElement | null>(null);
// Binds to the actual window height
let innerHeight = $state(0);
// Is the component above the middle of the viewport?
let isAboveMiddle = $state(false);
/**
* 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`;
});
const checkPosition = throttle(() => {
if (!wrapper) return;
const rect = wrapper.getBoundingClientRect();
const viewportMiddle = innerHeight / 2;
isAboveMiddle = rect.top < viewportMiddle;
}, 100);
</script>
<svelte:window
bind:innerHeight
onscroll={checkPosition}
onresize={checkPosition}
/>
<div bind:this={wrapper}>
<FontVirtualList
itemHeight={220}
useWindowScroll={true}
weight={controlManager.weight}
>
{#snippet children({
item: font,
isFullyVisible,
isPartiallyVisible,
proximity,
index,
})}
<FontListItem
{font}
{isFullyVisible}
{isPartiallyVisible}
{proximity}
>
<FontSampler {font} bind:text {index} />
</FontListItem>
{/snippet}
</FontVirtualList>
<TypographyMenu
class="fixed bottom-4 sm:bottom-5 right-4 sm:left-1/2 sm:right-[unset] sm:-translate-x-1/2"
hidden={!isAboveMiddle}
/>
</div>