import { useState, useEffect, useRef, useMemo } from 'react'; import { Search, Check, ChevronDown, Loader2 } from 'lucide-react'; import { getPopularFonts, filterFonts, loadGoogleFont, isFontLoaded, FONT_CATEGORIES, type GoogleFont, } from '../../services/fonts-service'; interface FontPickerProps { value: string; onChange: (fontFamily: string) => void; } export function FontPicker({ value, onChange }: FontPickerProps) { const [isOpen, setIsOpen] = useState(false); const [search, setSearch] = useState(''); const [category, setCategory] = useState('all'); const [loadingFont, setLoadingFont] = useState(null); const containerRef = useRef(null); const listRef = useRef(null); const fonts = useMemo(() => getPopularFonts(), []); const filteredFonts = useMemo(() => filterFonts(fonts, category, search), [fonts, category, search]); useEffect(() => { loadGoogleFont(value); }, [value]); useEffect(() => { if (!isOpen) return; const handleClickOutside = (e: MouseEvent) => { if (containerRef.current && !containerRef.current.contains(e.target as Node)) { setIsOpen(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, [isOpen]); useEffect(() => { if (isOpen && listRef.current) { filteredFonts.slice(0, 10).forEach((font) => { if (!isFontLoaded(font.family)) { loadGoogleFont(font.family, ['400']); } }); } }, [isOpen, filteredFonts]); const handleSelect = async (font: GoogleFont) => { setLoadingFont(font.family); try { await loadGoogleFont(font.family, font.variants.slice(0, 4)); onChange(font.family); setIsOpen(false); setSearch(''); } finally { setLoadingFont(null); } }; const handleScroll = (e: React.UIEvent) => { const container = e.currentTarget; const scrollBottom = container.scrollHeight - container.scrollTop - container.clientHeight; if (scrollBottom < 200) { const startIndex = Math.floor(container.scrollTop / 40); const endIndex = Math.min(startIndex + 15, filteredFonts.length); filteredFonts.slice(startIndex, endIndex).forEach((font) => { if (!isFontLoaded(font.family)) { loadGoogleFont(font.family, ['400']); } }); } }; return (
{isOpen && (
setSearch(e.target.value)} placeholder="Search fonts..." className="w-full pl-7 pr-2 py-1.5 text-xs bg-background border border-input rounded-md focus:outline-none focus:ring-1 focus:ring-primary" autoFocus />
{FONT_CATEGORIES.map((cat) => ( ))}
{filteredFonts.length === 0 ? (
No fonts found
) : ( filteredFonts.map((font) => ( )) )}
)}
); }