Files
test1/components/image-editor/hooks/use-local-fonts.ts
2026-03-20 07:33:46 +00:00

84 lines
2.2 KiB
TypeScript

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<FontOption[]>(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<string>()
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 }
}