Files
tweakcn/components/dynamic-font-loader.tsx
Sahaj Jain 8c107dd53e Feature/dynamic fonts (#197)
* chore: allow overriding ControlSection classNames

* feat: Support Google Fonts API and load fonts dynamically

* feat: Enforce System Prompt to use Google Fonts API if needed

* styles: Improve GoogleFontPicker styles

* feat: Pull Fonts from fileSystem instead of hitting the Google Fonts API every time

* feat: Improve System Prompt to reference Google Fonts

* refactor: Use Next.js Cache instead of manually fetching and reading from the filesystem

* feat: Only enable Font picker fetch when it's open

* chore: Remove JSON for Google Fonts catalogue

* feat: Scroll to selected font if it's already fetched and add clean search button

* chore: update imports

* fix: dashboard preview

---------

Co-authored-by: Luis Llanes <luisllaboj@gmail.com>
2025-07-27 23:40:36 +05:30

43 lines
1.2 KiB
TypeScript

"use client";
import { useMounted } from "@/hooks/use-mounted";
import { useEditorStore } from "@/store/editor-store";
import { extractFontFamily, getDefaultWeights } from "@/utils/fonts";
import { loadGoogleFont } from "@/utils/fonts/google-fonts";
import { useEffect, useMemo } from "react";
export function DynamicFontLoader() {
const { themeState } = useEditorStore();
const isMounted = useMounted();
const fontSans = themeState.styles.light["font-sans"];
const fontSerif = themeState.styles.light["font-serif"];
const fontMono = themeState.styles.light["font-mono"];
const currentFonts = useMemo(() => {
return {
sans: fontSans,
serif: fontSerif,
mono: fontMono,
} as const;
}, [fontSans, fontSerif, fontMono]);
useEffect(() => {
if (!isMounted) return;
try {
Object.entries(currentFonts).forEach(([_type, fontValue]) => {
const fontFamily = extractFontFamily(fontValue);
if (fontFamily) {
const weights = getDefaultWeights(["400", "500", "600", "700"]);
loadGoogleFont(fontFamily, weights);
}
});
} catch (e) {
console.warn("DynamicFontLoader: Failed to load Google fonts:", e);
}
}, [isMounted, currentFonts]);
return null;
}