diff options
| -rw-r--r-- | apps/web/src/app/layout.tsx | 9 | ||||
| -rw-r--r-- | apps/web/src/components/editor/preview-panel.tsx | 8 | ||||
| -rw-r--r-- | apps/web/src/components/editor/properties-panel.tsx | 16 | ||||
| -rw-r--r-- | apps/web/src/components/editor/timeline-element.tsx | 2 | ||||
| -rw-r--r-- | apps/web/src/components/editor/timeline-track.tsx | 2 | ||||
| -rw-r--r-- | apps/web/src/components/editor/timeline.tsx | 2 | ||||
| -rw-r--r-- | apps/web/src/constants/font-constants.ts | 79 | ||||
| -rw-r--r-- | apps/web/src/lib/font-config.ts | 39 |
8 files changed, 142 insertions, 15 deletions
diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx index 6dd74b89..6d0ebc64 100644 --- a/apps/web/src/app/layout.tsx +++ b/apps/web/src/app/layout.tsx @@ -1,4 +1,3 @@ -import { Inter } from "next/font/google"; import { ThemeProvider } from "next-themes"; import { Analytics } from "@vercel/analytics/react"; import Script from "next/script"; @@ -8,11 +7,7 @@ import { TooltipProvider } from "../components/ui/tooltip"; import { DevelopmentDebug } from "../components/development-debug"; import { StorageProvider } from "../components/storage-provider"; import { baseMetaData } from "./metadata"; - -const inter = Inter({ - subsets: ["latin"], - variable: "--font-inter", -}); +import { defaultFont } from "../lib/font-config"; export const metadata = baseMetaData; @@ -23,7 +18,7 @@ export default function RootLayout({ }>) { return ( <html lang="en" suppressHydrationWarning> - <body className={`${inter.variable} font-sans antialiased`}> + <body className={`${defaultFont.className} font-sans antialiased`}> <ThemeProvider attribute="class" forcedTheme="dark" enableSystem> <TooltipProvider> <StorageProvider>{children}</StorageProvider> diff --git a/apps/web/src/components/editor/preview-panel.tsx b/apps/web/src/components/editor/preview-panel.tsx index 09341ee9..c5621fea 100644 --- a/apps/web/src/components/editor/preview-panel.tsx +++ b/apps/web/src/components/editor/preview-panel.tsx @@ -20,6 +20,7 @@ import { Play, Pause } from "lucide-react"; import { useState, useRef, useEffect } from "react"; import { cn } from "@/lib/utils"; import { formatTimeCode } from "@/lib/time"; +import { FONT_CLASS_MAP } from "@/lib/font-config"; interface ActiveElement { element: TimelineElement; @@ -141,6 +142,9 @@ export function PreviewPanel() { // Text elements if (element.type === "text") { + const fontClassName = + FONT_CLASS_MAP[element.fontFamily as keyof typeof FONT_CLASS_MAP] || ""; + return ( <div key={element.id} @@ -154,9 +158,9 @@ export function PreviewPanel() { }} > <div + className={fontClassName} style={{ fontSize: `${element.fontSize}px`, - fontFamily: element.fontFamily, color: element.color, backgroundColor: element.backgroundColor, textAlign: element.textAlign, @@ -166,6 +170,8 @@ export function PreviewPanel() { padding: "4px 8px", borderRadius: "2px", whiteSpace: "pre-wrap", + // Fallback for system fonts that don't have classes + ...(fontClassName === "" && { fontFamily: element.fontFamily }), }} > {element.content} diff --git a/apps/web/src/components/editor/properties-panel.tsx b/apps/web/src/components/editor/properties-panel.tsx index e9b651bc..a0532ab3 100644 --- a/apps/web/src/components/editor/properties-panel.tsx +++ b/apps/web/src/components/editor/properties-panel.tsx @@ -15,6 +15,7 @@ import { SelectValue, SelectItem, } from "../ui/select"; +import { FONT_OPTIONS, type FontFamily } from "@/constants/font-constants"; export function PropertiesPanel() { const { activeProject } = useProjectStore(); @@ -49,14 +50,21 @@ export function PropertiesPanel() { /> <div className="flex items-center justify-between gap-6"> <Label className="text-xs">Font</Label> - <Select> + <Select + defaultValue={element.fontFamily} + onValueChange={(value: FontFamily) => + updateTextElement(trackId, element.id, { fontFamily: value }) + } + > <SelectTrigger className="w-full text-xs"> <SelectValue placeholder="Select a font" /> </SelectTrigger> <SelectContent> - <SelectItem value="Arial">Arial</SelectItem> - <SelectItem value="Helvetica">Helvetica</SelectItem> - <SelectItem value="Times New Roman">Times New Roman</SelectItem> + {FONT_OPTIONS.map((font) => ( + <SelectItem key={font.value} value={font.value}> + {font.label} + </SelectItem> + ))} </SelectContent> </Select> </div> diff --git a/apps/web/src/components/editor/timeline-element.tsx b/apps/web/src/components/editor/timeline-element.tsx index c5801652..1cd22c74 100644 --- a/apps/web/src/components/editor/timeline-element.tsx +++ b/apps/web/src/components/editor/timeline-element.tsx @@ -24,7 +24,7 @@ import { useTimelineElementResize } from "@/hooks/use-timeline-element-resize"; import { getTrackElementClasses, TIMELINE_CONSTANTS, -} from "@/lib/timeline-constants"; +} from "@/constants/timeline-constants"; import { DropdownMenu, DropdownMenuContent, diff --git a/apps/web/src/components/editor/timeline-track.tsx b/apps/web/src/components/editor/timeline-track.tsx index 8734d0fb..7e2e93e0 100644 --- a/apps/web/src/components/editor/timeline-track.tsx +++ b/apps/web/src/components/editor/timeline-track.tsx @@ -17,7 +17,7 @@ import type { TimelineElement as TimelineElementType, DragData, } from "@/types/timeline"; -import { TIMELINE_CONSTANTS } from "@/lib/timeline-constants"; +import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants"; export function TimelineTrackContent({ track, diff --git a/apps/web/src/components/editor/timeline.tsx b/apps/web/src/components/editor/timeline.tsx index ee56cbe5..abbf5bba 100644 --- a/apps/web/src/components/editor/timeline.tsx +++ b/apps/web/src/components/editor/timeline.tsx @@ -50,7 +50,7 @@ import { getCumulativeHeightBefore, getTotalTracksHeight, TIMELINE_CONSTANTS, -} from "@/lib/timeline-constants"; +} from "@/constants/timeline-constants"; export function Timeline() { // Timeline shows all tracks (video, audio, effects) and their elements. diff --git a/apps/web/src/constants/font-constants.ts b/apps/web/src/constants/font-constants.ts new file mode 100644 index 00000000..bfddc182 --- /dev/null +++ b/apps/web/src/constants/font-constants.ts @@ -0,0 +1,79 @@ +export interface FontOption {
+ value: string;
+ label: string;
+ category: "system" | "google" | "custom";
+ weights?: number[];
+ hasClassName?: boolean;
+}
+
+export const FONT_OPTIONS: FontOption[] = [
+ // System fonts (always available)
+ { value: "Arial", label: "Arial", category: "system", hasClassName: false },
+ {
+ value: "Helvetica",
+ label: "Helvetica",
+ category: "system",
+ hasClassName: false,
+ },
+ {
+ value: "Times New Roman",
+ label: "Times New Roman",
+ category: "system",
+ hasClassName: false,
+ },
+ {
+ value: "Georgia",
+ label: "Georgia",
+ category: "system",
+ hasClassName: false,
+ },
+
+ // Google Fonts (loaded in layout.tsx)
+ {
+ value: "Inter",
+ label: "Inter",
+ category: "google",
+ weights: [400, 700],
+ hasClassName: true,
+ },
+ {
+ value: "Roboto",
+ label: "Roboto",
+ category: "google",
+ weights: [400, 700],
+ hasClassName: true,
+ },
+ {
+ value: "Open Sans",
+ label: "Open Sans",
+ category: "google",
+ hasClassName: true,
+ },
+ {
+ value: "Playfair Display",
+ label: "Playfair Display",
+ category: "google",
+ hasClassName: true,
+ },
+ {
+ value: "Comic Neue",
+ label: "Comic Neue",
+ category: "google",
+ hasClassName: false,
+ },
+] as const;
+
+export const DEFAULT_FONT = "Arial";
+
+// Type-safe font family union
+export type FontFamily = (typeof FONT_OPTIONS)[number]["value"];
+
+// Helper functions
+export const getFontByValue = (value: string): FontOption | undefined =>
+ FONT_OPTIONS.find((font) => font.value === value);
+
+export const getGoogleFonts = (): FontOption[] =>
+ FONT_OPTIONS.filter((font) => font.category === "google");
+
+export const getSystemFonts = (): FontOption[] =>
+ FONT_OPTIONS.filter((font) => font.category === "system");
diff --git a/apps/web/src/lib/font-config.ts b/apps/web/src/lib/font-config.ts new file mode 100644 index 00000000..0389054a --- /dev/null +++ b/apps/web/src/lib/font-config.ts @@ -0,0 +1,39 @@ +import {
+ Inter,
+ Roboto,
+ Open_Sans,
+ Playfair_Display,
+ Comic_Neue,
+} from "next/font/google";
+
+// Configure all fonts
+const inter = Inter({ subsets: ["latin"] });
+const roboto = Roboto({ subsets: ["latin"], weight: ["400", "700"] });
+const openSans = Open_Sans({ subsets: ["latin"] });
+const playfairDisplay = Playfair_Display({ subsets: ["latin"] });
+const comicNeue = Comic_Neue({ subsets: ["latin"], weight: ["400", "700"] });
+
+// Export font class mapping for use in components
+export const FONT_CLASS_MAP = {
+ Inter: inter.className,
+ Roboto: roboto.className,
+ "Open Sans": openSans.className,
+ "Playfair Display": playfairDisplay.className,
+ "Comic Neue": comicNeue.className,
+ Arial: "",
+ Helvetica: "",
+ "Times New Roman": "",
+ Georgia: "",
+} as const;
+
+// Export individual fonts for use in layout
+export const fonts = {
+ inter,
+ roboto,
+ openSans,
+ playfairDisplay,
+ comicNeue,
+};
+
+// Default font for the body
+export const defaultFont = inter;
|
