"use client"; import { Input } from "components/Input"; import { useRef, useState } from "react"; import { Menu, MenuItem, RadioMenuGroup, RadioMenuItem } from "components/Menu"; import { useIsMobile } from "src/hooks/isMobile"; import { fonts, defaultFontId, FontConfig, isCustomFontId, parseGoogleFontInput, createCustomFontId, getFontConfig, } from "src/fonts"; import { ButtonPrimary } from "components/Buttons"; import { useSmoker } from "components/Toast"; import { DotLoader } from "components/utils/DotLoader"; export const FontPicker = (props: { label: string; value: string | undefined; onChange: (fontId: string) => void; }) => { let isMobile = useIsMobile(); let smoker = useSmoker(); let inputWrapperRef = useRef(null); let [showCustomInput, setShowCustomInput] = useState(false); let [customFontValue, setCustomFontValue] = useState(""); let fontId = props.value || defaultFontId; let font = getFontConfig(fontId); let isCustom = isCustomFontId(fontId); let fontList = Object.values(fonts).sort((a, b) => a.displayName.localeCompare(b.displayName), ); let [loading, setLoading] = useState(false); const handleCustomSubmit = async () => { const parsed = parseGoogleFontInput(customFontValue); if (!parsed) return; setLoading(true); try { const url = `https://fonts.googleapis.com/css2?family=${parsed.googleFontsFamily}&display=swap`; const res = await fetch(url, { method: "HEAD" }); if (!res.ok) { const rect = inputWrapperRef.current?.getBoundingClientRect(); smoker({ error: true, position: { x: rect ? rect.left + rect.width / 2 : 0, y: rect ? rect.top - 8 : 0, }, text: "No font found!", }); return; } const customId = createCustomFontId( parsed.fontName, parsed.googleFontsFamily, ); props.onChange(customId); setShowCustomInput(false); setCustomFontValue(""); } catch { const rect = inputWrapperRef.current?.getBoundingClientRect(); smoker({ error: true, position: { x: rect ? rect.left + rect.width / 2 : 0, y: rect ? rect.top - 8 : 0, }, text: "No font found!", }); } finally { setLoading(false); } }; return (
Aa
{props.label}
{font.displayName}
} side={isMobile ? "bottom" : "right"} align="start" className="w-fit !gap-0 !outline-none max-h-72 " > {showCustomInput ? (
Paste any Google Font name
This is case sensitive
setCustomFontValue(e.currentTarget.value)} onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); handleCustomSubmit(); } else if (e.key === "Escape") { setShowCustomInput(false); setCustomFontValue(""); } }} />
{loading ? : "Add Font"}
) : (
{fontList.map((fontOption) => { return ( ); })} {isCustom && ( )}
{ e.preventDefault(); setShowCustomInput(true); }} > Add a Custom Font
)}
); }; const FontOption = (props: { font: FontConfig; selected: boolean }) => { return ( {props.font.displayName} ); };