返回 presentation-ai
slideFormats.ts
根目录 / src / config / slideFormats.ts
1 /**
2 * Centralized configuration for slide formats, widths, and aspect ratios.
3 * This file consolidates all slide sizing logic for easy maintenance and extension.
4 */
5
6 // Aspect ratio constants
7 export const ASPECT_RATIOS = {
8 A4: Math.SQRT2, // ~1.414
9 LETTER: 11 / 8.5, // ~1.294
10 } as const;
11
12 // Base widths for different slide width sizes
13 export const BASE_WIDTHS = {
14 S: 896, // max-w-4xl
15 M: 1024, // max-w-5xl
16 L: 1152, // max-w-6xl
17 } as const;
18
19 // Format category base widths (when not using S/M/L sizing)
20 export const FORMAT_CATEGORY_WIDTHS = {
21 document: 1024,
22 webpage: 1024,
23 presentation: 1024,
24 default: 1024,
25 } as const;
26
27 // Social format widths for different aspect ratios
28 export const SOCIAL_ASPECT_WIDTHS = {
29 "1:1": 720, // Square
30 "4:5": 720, // Portrait
31 "9:16": 540, // Story (vertical)
32 "16:9": 1024, // Wide (if needed)
33 default: 640, // Fallback
34 } as const;
35
36 // Tall format configuration
37 export const TALL_FORMAT = {
38 minHeightPx: 1200, // Static pixel value instead of 85vh
39 } as const;
40
41 /**
42 * Get the base width for a slide based on format category, width size, and aspect ratio.
43 *
44 * @param formatCategory - The format category (presentation, social, document, webpage)
45 * @param widthSize - The width size preset (S, M, L)
46 * @param aspectRatio - Optional aspect ratio for social format differentiation
47 * @returns The base width in pixels
48 */
49 export function getSlideBaseWidth(
50 formatCategory: "presentation" | "social" | "document" | "webpage",
51 widthSize: "S" | "M" | "L" = "M",
52 aspectRatio?: { type: string; value?: string },
53 ): number {
54 // Social format uses aspect-ratio-specific widths
55 if (
56 formatCategory === "social" &&
57 aspectRatio?.type === "ratio" &&
58 aspectRatio.value
59 ) {
60 const ratioValue = aspectRatio.value as keyof typeof SOCIAL_ASPECT_WIDTHS;
61 return SOCIAL_ASPECT_WIDTHS[ratioValue] ?? SOCIAL_ASPECT_WIDTHS.default;
62 }
63
64 // Social format fallback (if no specific aspect ratio)
65 if (formatCategory === "social") {
66 return SOCIAL_ASPECT_WIDTHS.default;
67 }
68
69 // Other formats use S/M/L sizing or category defaults
70 if (formatCategory === "presentation" || formatCategory === "webpage") {
71 return BASE_WIDTHS[widthSize];
72 }
73
74 return (
75 FORMAT_CATEGORY_WIDTHS[formatCategory] ?? FORMAT_CATEGORY_WIDTHS.default
76 );
77 }
78
79 /**
80 * Get the aspect ratio value for preset types (A4, Letter).
81 */
82 export function getPresetAspectRatio(preset: "A4" | "Letter" | string): number {
83 if (preset.toLowerCase() === "letter") {
84 return ASPECT_RATIOS.LETTER;
85 }
86 return ASPECT_RATIOS.A4;
87 }
88
89 /**
90 * Calculate the height in pixels based on width and aspect ratio.
91 */
92 export function calculateHeightFromRatio(
93 width: number,
94 aspectRatio: { type: string; value?: string },
95 ): { minHeightPx?: number; minHeightCSS?: string } {
96 if (aspectRatio.type === "fluid") {
97 return {}; // No height constraint
98 }
99
100 if (aspectRatio.type === "tall") {
101 return {
102 minHeightPx: TALL_FORMAT.minHeightPx,
103 minHeightCSS: `${TALL_FORMAT.minHeightPx}px`,
104 };
105 }
106
107 if (aspectRatio.type === "ratio" && aspectRatio.value) {
108 const parts = aspectRatio.value.split(":");
109 const w = Number(parts[0] || 0);
110 const h = Number(parts[1] || 0);
111 if (w > 0 && h > 0) {
112 const heightPx = Math.round(width * (h / w));
113 return {
114 minHeightPx: heightPx,
115 minHeightCSS: `${heightPx}px`,
116 };
117 }
118 }
119
120 if (aspectRatio.type === "preset" && aspectRatio.value) {
121 const ratio = getPresetAspectRatio(aspectRatio.value);
122 const heightPx = Math.round(width * ratio);
123 return {
124 minHeightPx: heightPx,
125 minHeightCSS: `${heightPx}px`,
126 };
127 }
128
129 return {};
130 }
131
132 // Export all config values for direct access if needed
133 export const SLIDE_FORMAT_CONFIG = {
134 aspectRatios: ASPECT_RATIOS,
135 baseWidths: BASE_WIDTHS,
136 formatCategoryWidths: FORMAT_CATEGORY_WIDTHS,
137 socialAspectWidths: SOCIAL_ASPECT_WIDTHS,
138 tallFormat: TALL_FORMAT,
139 getSlideBaseWidth,
140 getPresetAspectRatio,
141 calculateHeightFromRatio,
142 } as const;
143
143 lines TYPESCRIPT