diff --git a/components/editor/tool-options.tsx b/components/editor/tool-options.tsx
index 32118c4..c244b0b 100644
--- a/components/editor/tool-options.tsx
+++ b/components/editor/tool-options.tsx
@@ -4,6 +4,9 @@ import { useToolStore } from '@/store';
import { useShapeStore } from '@/store/shape-store';
import { useSelectionStore } from '@/store/selection-store';
import { useTextStore } from '@/store/text-store';
+import { WEB_SAFE_FONTS, GOOGLE_FONTS } from '@/lib/text-utils';
+import { googleFontsLoader } from '@/lib/google-fonts-loader';
+import { useCallback } from 'react';
export function ToolOptions() {
const { activeTool, settings, setSize, setOpacity, setHardness, setColor, setFlow } = useToolStore();
@@ -21,6 +24,22 @@ export function ToolOptions() {
setColor: setTextColor,
} = useTextStore();
+ // Handle font change with Google Fonts loading
+ const handleFontChange = useCallback(
+ async (fontFamily: string) => {
+ // Check if it's a Google Font
+ if (GOOGLE_FONTS.includes(fontFamily as any)) {
+ try {
+ await googleFontsLoader.loadFont(fontFamily);
+ } catch (error) {
+ console.error('Failed to load Google Font:', error);
+ }
+ }
+ setFontFamily(fontFamily);
+ },
+ [setFontFamily]
+ );
+
// Drawing tools: brush, pencil, eraser
const isDrawingTool = ['brush', 'eraser', 'pencil'].includes(activeTool);
const showHardness = ['brush'].includes(activeTool);
@@ -233,25 +252,24 @@ export function ToolOptions() {
diff --git a/lib/google-fonts-loader.ts b/lib/google-fonts-loader.ts
new file mode 100644
index 0000000..d26aa89
--- /dev/null
+++ b/lib/google-fonts-loader.ts
@@ -0,0 +1,149 @@
+/**
+ * Google Fonts Loader
+ * Handles dynamic loading and caching of Google Fonts
+ */
+
+export interface FontLoadStatus {
+ loaded: boolean;
+ loading: boolean;
+ error: string | null;
+}
+
+class GoogleFontsLoader {
+ private loadedFonts = new Set();
+ private loadingFonts = new Map>();
+ private fontStatuses = new Map();
+
+ /**
+ * Load a Google Font dynamically
+ */
+ async loadFont(fontFamily: string): Promise {
+ // Already loaded
+ if (this.loadedFonts.has(fontFamily)) {
+ return Promise.resolve();
+ }
+
+ // Currently loading
+ if (this.loadingFonts.has(fontFamily)) {
+ return this.loadingFonts.get(fontFamily)!;
+ }
+
+ // Start loading
+ this.fontStatuses.set(fontFamily, {
+ loaded: false,
+ loading: true,
+ error: null,
+ });
+
+ const loadPromise = this.loadFontImpl(fontFamily);
+ this.loadingFonts.set(fontFamily, loadPromise);
+
+ try {
+ await loadPromise;
+ this.loadedFonts.add(fontFamily);
+ this.fontStatuses.set(fontFamily, {
+ loaded: true,
+ loading: false,
+ error: null,
+ });
+ } catch (error) {
+ this.fontStatuses.set(fontFamily, {
+ loaded: false,
+ loading: false,
+ error: error instanceof Error ? error.message : 'Unknown error',
+ });
+ throw error;
+ } finally {
+ this.loadingFonts.delete(fontFamily);
+ }
+ }
+
+ /**
+ * Implementation of font loading
+ */
+ private async loadFontImpl(fontFamily: string): Promise {
+ return new Promise((resolve, reject) => {
+ // Check if font is already loaded in browser
+ if (document.fonts.check(`16px "${fontFamily}"`)) {
+ resolve();
+ return;
+ }
+
+ // Create link element to load font
+ const link = document.createElement('link');
+ link.rel = 'stylesheet';
+ link.href = `https://fonts.googleapis.com/css2?family=${fontFamily.replace(
+ / /g,
+ '+'
+ )}:wght@100;300;400;500;700;900&display=swap`;
+
+ link.onload = () => {
+ // Wait for font to be ready
+ document.fonts
+ .load(`16px "${fontFamily}"`)
+ .then(() => {
+ resolve();
+ })
+ .catch(reject);
+ };
+
+ link.onerror = () => {
+ reject(new Error(`Failed to load font: ${fontFamily}`));
+ };
+
+ document.head.appendChild(link);
+ });
+ }
+
+ /**
+ * Preload multiple fonts
+ */
+ async preloadFonts(fontFamilies: string[]): Promise {
+ await Promise.allSettled(fontFamilies.map((font) => this.loadFont(font)));
+ }
+
+ /**
+ * Get font loading status
+ */
+ getStatus(fontFamily: string): FontLoadStatus {
+ return (
+ this.fontStatuses.get(fontFamily) || {
+ loaded: false,
+ loading: false,
+ error: null,
+ }
+ );
+ }
+
+ /**
+ * Check if font is loaded
+ */
+ isLoaded(fontFamily: string): boolean {
+ return this.loadedFonts.has(fontFamily);
+ }
+
+ /**
+ * Check if font is currently loading
+ */
+ isLoading(fontFamily: string): boolean {
+ return this.loadingFonts.has(fontFamily);
+ }
+
+ /**
+ * Clear cache (for testing)
+ */
+ clearCache(): void {
+ this.loadedFonts.clear();
+ this.loadingFonts.clear();
+ this.fontStatuses.clear();
+ }
+}
+
+// Singleton instance
+export const googleFontsLoader = new GoogleFontsLoader();
+
+// Preload popular fonts on app start
+if (typeof window !== 'undefined') {
+ // Preload most popular fonts
+ googleFontsLoader.preloadFonts(['Roboto', 'Open Sans', 'Lato', 'Montserrat']);
+}