返回 presentation-ai
usePaginatedFonts.ts
根目录 / src / components / ui / font-picker / utils / usePaginatedFonts.ts
1 import { useCallback, useEffect, useMemo, useState } from "react";
2 import { type Font } from "../types";
3 // Hook for paginated font loading with virtual scrolling
4 export function usePaginatedFonts(
5 fonts: Font[],
6 searchValue: string,
7 chunkSize: number = 50,
8 ) {
9 const [visibleCount, setVisibleCount] = useState(chunkSize);
10 const [isLoadingMore, setIsLoadingMore] = useState(false); // Filter fonts based on search - immediate, no debounce
11
12 const filteredFonts = useMemo(() => {
13 if (!searchValue.trim()) return fonts;
14 const searchTerm = searchValue.toLowerCase();
15 return fonts.filter((font) => font.name.toLowerCase().includes(searchTerm));
16 }, [fonts, searchValue]); // Get visible fonts (paginated)
17
18 const visibleFonts = useMemo(() => {
19 return filteredFonts.slice(0, visibleCount);
20 }, [filteredFonts, visibleCount]); // Load more fonts
21
22 const loadMore = useCallback(() => {
23 if (isLoadingMore || visibleCount >= filteredFonts.length) return;
24
25 setIsLoadingMore(true); // Small delay to prevent too many rapid calls
26 setTimeout(() => {
27 setVisibleCount((prev) =>
28 Math.min(prev + chunkSize, filteredFonts.length),
29 );
30 setIsLoadingMore(false);
31 }, 100);
32 }, [isLoadingMore, visibleCount, filteredFonts.length, chunkSize]); // Reset visible count when search changes
33
34 useEffect(() => {
35 setVisibleCount(chunkSize);
36 }, [searchValue, chunkSize]);
37
38 const hasMore = visibleCount < filteredFonts.length;
39
40 return {
41 visibleFonts,
42 hasMore,
43 isLoadingMore,
44 loadMore,
45 totalCount: filteredFonts.length,
46 };
47 }
48
48 lines TYPESCRIPT