import { useState, useEffect } from 'react' export interface FontOption { label: string value: string } const DEFAULT_FONTS: FontOption[] = [ { label: '黑体', value: 'SimHei, sans-serif' }, { label: '宋体', value: 'SimSun, serif' }, { label: '微软雅黑', value: 'Microsoft YaHei, sans-serif', }, { label: 'PingFang SC', value: 'PingFang SC, sans-serif' }, { label: 'Inter', value: 'Inter, sans-serif' }, ] let cachedFonts: FontOption[] | null = null export function useLocalFonts() { const [fonts, setFonts] = useState(cachedFonts || DEFAULT_FONTS) const [loading, setLoading] = useState(false) useEffect(() => { if (cachedFonts && cachedFonts.length > DEFAULT_FONTS.length) { return } async function loadLocalFonts() { // Check if the API is supported if (!('queryLocalFonts' in window)) { return } try { setLoading(true) // @ts-expect-error - queryLocalFonts is a new API const localFonts = await window.queryLocalFonts() // Group by family and take the first one (usually the regular style) // or just use unique families const families = new Set() const dynamicFonts: FontOption[] = [] localFonts.forEach((font: any) => { if (!families.has(font.family)) { families.add(font.family) dynamicFonts.push({ label: font.family, value: font.family, }) } }) // Sort alphabetically dynamicFonts.sort((a, b) => a.label.localeCompare(b.label)) // Combine with defaults, ensuring no duplicates by family name const combined = [...DEFAULT_FONTS] const defaultFamilies = new Set(DEFAULT_FONTS.map(f => f.label)) dynamicFonts.forEach(df => { if (!defaultFamilies.has(df.label)) { combined.push(df) } }) cachedFonts = combined setFonts(combined) } catch (err) { console.error('Failed to query local fonts:', err) // Fallback is already set as initial state } finally { setLoading(false) } } loadLocalFonts() }, []) return { fonts, loading } }