feature/ux-improvements #26

Merged
ilia merged 73 commits from feature/ux-improvements into main 2026-02-18 14:43:05 +00:00
2 changed files with 40 additions and 58 deletions
Showing only changes of commit c2d0992015 - Show all commits

View File

@@ -3,7 +3,7 @@
- Renders a virtualized list of fonts
- Handles font registration with the manager
-->
<script lang="ts" generics="T extends UnifiedFont">
<script lang="ts">
import {
Skeleton,
VirtualList,
@@ -11,26 +11,23 @@ import {
import type { ComponentProps } from 'svelte';
import { fade } from 'svelte/transition';
import { getFontUrl } from '../../lib';
import type { FontConfigRequest } from '../../model';
import {
type FontConfigRequest,
type UnifiedFont,
appliedFontsManager,
unifiedFontStore,
} from '../../model';
interface Props extends
Omit<
ComponentProps<typeof VirtualList<T>>,
'onVisibleItemsChange'
ComponentProps<typeof VirtualList<UnifiedFont>>,
'items' | 'total' | 'isLoading' | 'onVisibleItemsChange' | 'onNearBottom'
>
{
/**
* Callback for when visible items change
*/
onVisibleItemsChange?: (items: T[]) => void;
/**
* Callback for when near bottom is reached
*/
onNearBottom?: (lastVisibleIndex: number) => void;
onVisibleItemsChange?: (items: UnifiedFont[]) => void;
/**
* Weight of the font
*/
@@ -38,23 +35,20 @@ interface Props extends
* Weight of the font
*/
weight: number;
/**
* Whether the list is in a loading state
*/
isLoading?: boolean;
}
let {
items,
children,
onVisibleItemsChange,
onNearBottom,
weight,
isLoading = false,
...rest
}: Props = $props();
function handleInternalVisibleChange(visibleItems: T[]) {
const isLoading = $derived(
unifiedFontStore.isFetching || unifiedFontStore.isLoading,
);
function handleInternalVisibleChange(visibleItems: UnifiedFont[]) {
const configs: FontConfigRequest[] = [];
visibleItems.forEach(item => {
@@ -77,9 +71,32 @@ function handleInternalVisibleChange(visibleItems: T[]) {
// onVisibleItemsChange?.(visibleItems);
}
function handleNearBottom(lastVisibleIndex: number) {
// Forward the call to any external listener
onNearBottom?.(lastVisibleIndex);
/**
* 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 by VirtualList when the user scrolls within 5 items of the end
* of the loaded items. Only fetches if there are more pages available.
*/
function handleNearBottom(_lastVisibleIndex: number) {
const { hasMore } = unifiedFontStore.pagination;
// VirtualList already checks if we're near the bottom of loaded items
if (hasMore && !unifiedFontStore.isFetching) {
loadMore();
}
}
</script>
@@ -99,10 +116,11 @@ function handleNearBottom(lastVisibleIndex: number) {
</div>
{:else}
<VirtualList
{items}
{...rest}
items={unifiedFontStore.fonts}
total={unifiedFontStore.pagination.total}
onVisibleItemsChange={handleInternalVisibleChange}
onNearBottom={handleNearBottom}
{...rest}
>
{#snippet children(scope)}
{@render children(scope)}

View File

@@ -24,38 +24,6 @@ let innerHeight = $state(0);
// Is the component above the middle of the viewport?
let isAboveMiddle = $state(false);
const isLoading = $derived(
unifiedFontStore.isFetching || unifiedFontStore.isLoading,
);
/**
* 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 by VirtualList when the user scrolls within 5 items of the end
* of the loaded items. Only fetches if there are more pages available.
*/
function handleNearBottom(_lastVisibleIndex: number) {
const { hasMore } = unifiedFontStore.pagination;
// VirtualList already checks if we're near the bottom of loaded items
if (hasMore && !unifiedFontStore.isFetching) {
loadMore();
}
}
/**
* Calculate display range for pagination info
*/
@@ -83,13 +51,9 @@ const checkPosition = throttle(() => {
<div bind:this={wrapper}>
<FontVirtualList
items={unifiedFontStore.fonts}
total={unifiedFontStore.pagination.total}
onNearBottom={handleNearBottom}
itemHeight={220}
useWindowScroll={true}
weight={controlManager.weight}
{isLoading}
>
{#snippet children({
item: font,