@djangocfg/nextjs 2.1.225 → 2.1.226
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -80
- package/dist/config/index.mjs +6 -17
- package/dist/config/index.mjs.map +1 -1
- package/dist/index.d.mts +1 -6
- package/dist/index.mjs +9 -865
- package/dist/index.mjs.map +1 -1
- package/dist/og-image/index.d.mts +40 -100
- package/dist/og-image/index.mjs +46 -823
- package/dist/og-image/index.mjs.map +1 -1
- package/package.json +14 -25
- package/src/index.ts +0 -3
- package/src/og-image/README.md +142 -53
- package/src/og-image/index.ts +3 -27
- package/src/og-image/metadata.ts +67 -0
- package/src/og-image/types.ts +28 -44
- package/src/og-image/url.ts +58 -0
- package/dist/og-image/components/index.d.mts +0 -59
- package/dist/og-image/components/index.mjs +0 -338
- package/dist/og-image/components/index.mjs.map +0 -1
- package/dist/og-image/utils/index.d.mts +0 -308
- package/dist/og-image/utils/index.mjs +0 -327
- package/dist/og-image/utils/index.mjs.map +0 -1
- package/src/og-image/components/DefaultTemplate.tsx +0 -369
- package/src/og-image/components/index.ts +0 -9
- package/src/og-image/route.tsx +0 -312
- package/src/og-image/utils/fonts.ts +0 -150
- package/src/og-image/utils/index.ts +0 -28
- package/src/og-image/utils/metadata.ts +0 -269
- package/src/og-image/utils/url.ts +0 -386
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { OGImageParams } from './types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolves the base URL for og:image meta tags.
|
|
5
|
+
* Must be publicly accessible by crawlers (Twitter, Facebook, etc).
|
|
6
|
+
*
|
|
7
|
+
* Priority:
|
|
8
|
+
* 1. NEXT_PUBLIC_MEDIA_URL — explicit media domain (nginx proxy or CDN)
|
|
9
|
+
* 2. NEXT_PUBLIC_API_URL — direct Django API domain
|
|
10
|
+
* 3. NEXT_PUBLIC_SITE_URL — site domain (same-domain/static build)
|
|
11
|
+
* 4. '' — relative URL (last resort)
|
|
12
|
+
*
|
|
13
|
+
* Use cases:
|
|
14
|
+
* - Same domain (static build): API_URL='' → relative /cfg/og/...
|
|
15
|
+
* - Split domain (standalone): API_URL=https://api.x.com → absolute
|
|
16
|
+
* - Media via nginx proxy: MEDIA_URL=https://x.com, API_URL=https://api.x.com
|
|
17
|
+
* - CDN: MEDIA_URL=https://cdn.x.com
|
|
18
|
+
*/
|
|
19
|
+
function resolveOgPublicBase(): string {
|
|
20
|
+
if (typeof process === 'undefined') return ''
|
|
21
|
+
return (
|
|
22
|
+
process.env.NEXT_PUBLIC_MEDIA_URL?.replace(/\/$/, '') ??
|
|
23
|
+
process.env.NEXT_PUBLIC_API_URL?.replace(/\/$/, '') ??
|
|
24
|
+
process.env.NEXT_PUBLIC_SITE_URL?.replace(/\/$/, '') ??
|
|
25
|
+
''
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function encodeBase64(str: string): string {
|
|
30
|
+
if (typeof Buffer !== 'undefined') {
|
|
31
|
+
return Buffer.from(str).toString('base64url')
|
|
32
|
+
}
|
|
33
|
+
// Browser fallback
|
|
34
|
+
return btoa(unescape(encodeURIComponent(str)))
|
|
35
|
+
.replace(/\+/g, '-')
|
|
36
|
+
.replace(/\//g, '_')
|
|
37
|
+
.replace(/=+$/, '')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function cleanParams(params: OGImageParams): Record<string, unknown> {
|
|
41
|
+
return Object.fromEntries(
|
|
42
|
+
Object.entries(params).filter(
|
|
43
|
+
([, v]) => v !== undefined && v !== null && v !== ''
|
|
44
|
+
)
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Builds an absolute (or relative) OG image URL pointing to Django's
|
|
50
|
+
* django_ogimage endpoint: /cfg/og/<base64params>/
|
|
51
|
+
*
|
|
52
|
+
* The URL is suitable for use in og:image and twitter:image meta tags.
|
|
53
|
+
*/
|
|
54
|
+
export function buildOgUrl(params: OGImageParams): string {
|
|
55
|
+
const b64 = encodeBase64(JSON.stringify(cleanParams(params)))
|
|
56
|
+
const base = resolveOgPublicBase()
|
|
57
|
+
return `${base}/cfg/og/${b64}/`
|
|
58
|
+
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { ReactElement } from 'react';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* OG Image Types
|
|
5
|
-
*
|
|
6
|
-
* Shared types for OG image templates and handlers
|
|
7
|
-
* This file is safe to import in client components
|
|
8
|
-
*/
|
|
9
|
-
interface OgImageTemplateProps {
|
|
10
|
-
title: string;
|
|
11
|
-
description?: string;
|
|
12
|
-
subtitle?: string;
|
|
13
|
-
siteName?: string;
|
|
14
|
-
logo?: string;
|
|
15
|
-
showLogo?: boolean;
|
|
16
|
-
showSiteName?: boolean;
|
|
17
|
-
backgroundType?: 'gradient' | 'solid';
|
|
18
|
-
gradientStart?: string;
|
|
19
|
-
gradientEnd?: string;
|
|
20
|
-
backgroundColor?: string;
|
|
21
|
-
titleSize?: number;
|
|
22
|
-
titleWeight?: number;
|
|
23
|
-
titleColor?: string;
|
|
24
|
-
descriptionSize?: number;
|
|
25
|
-
descriptionColor?: string;
|
|
26
|
-
siteNameSize?: number;
|
|
27
|
-
siteNameColor?: string;
|
|
28
|
-
padding?: number;
|
|
29
|
-
logoSize?: number;
|
|
30
|
-
devMode?: boolean;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Default OG Image Template
|
|
35
|
-
*
|
|
36
|
-
* A modern, gradient-based template for OG images
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Default OG Image Template Component
|
|
41
|
-
*
|
|
42
|
-
* Features:
|
|
43
|
-
* - Modern gradient background
|
|
44
|
-
* - Responsive text sizing
|
|
45
|
-
* - Optional logo and site name
|
|
46
|
-
* - Clean typography
|
|
47
|
-
* - Full customization support
|
|
48
|
-
*
|
|
49
|
-
* @param props - Template props with title, description, siteName, logo and optional customization
|
|
50
|
-
*/
|
|
51
|
-
declare function DefaultTemplate({ title, description, siteName, logo, showLogo, showSiteName, backgroundType, gradientStart, gradientEnd, backgroundColor, titleSize, titleWeight, titleColor, descriptionSize, descriptionColor, siteNameSize, siteNameColor, padding, logoSize, devMode, }: OgImageTemplateProps): ReactElement;
|
|
52
|
-
/**
|
|
53
|
-
* Simple light template variant
|
|
54
|
-
*
|
|
55
|
-
* Light background variant with dark text
|
|
56
|
-
*/
|
|
57
|
-
declare function LightTemplate({ title, description, siteName, logo, showLogo, showSiteName, backgroundType, gradientStart, gradientEnd, backgroundColor, titleSize, titleWeight, titleColor, descriptionSize, descriptionColor, siteNameSize, siteNameColor, padding, logoSize, devMode, }: OgImageTemplateProps): ReactElement;
|
|
58
|
-
|
|
59
|
-
export { DefaultTemplate, LightTemplate, type OgImageTemplateProps };
|
|
@@ -1,338 +0,0 @@
|
|
|
1
|
-
// src/og-image/components/DefaultTemplate.tsx
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
function DefaultTemplate({
|
|
4
|
-
title,
|
|
5
|
-
description,
|
|
6
|
-
siteName,
|
|
7
|
-
logo,
|
|
8
|
-
// Visibility flags
|
|
9
|
-
showLogo = true,
|
|
10
|
-
showSiteName = true,
|
|
11
|
-
// Background customization
|
|
12
|
-
backgroundType = "gradient",
|
|
13
|
-
gradientStart = "#667eea",
|
|
14
|
-
gradientEnd = "#764ba2",
|
|
15
|
-
backgroundColor = "#ffffff",
|
|
16
|
-
// Typography - Title
|
|
17
|
-
titleSize,
|
|
18
|
-
titleWeight = 800,
|
|
19
|
-
titleColor = "white",
|
|
20
|
-
// Typography - Description
|
|
21
|
-
descriptionSize = 32,
|
|
22
|
-
descriptionColor = "rgba(255, 255, 255, 0.85)",
|
|
23
|
-
// Typography - Site Name
|
|
24
|
-
siteNameSize = 28,
|
|
25
|
-
siteNameColor = "rgba(255, 255, 255, 0.95)",
|
|
26
|
-
// Layout
|
|
27
|
-
padding = 80,
|
|
28
|
-
logoSize = 48,
|
|
29
|
-
// Dev mode
|
|
30
|
-
devMode = false
|
|
31
|
-
}) {
|
|
32
|
-
const calculatedTitleSize = titleSize || (title.length > 60 ? 56 : 72);
|
|
33
|
-
const backgroundStyle = backgroundType === "gradient" ? `linear-gradient(135deg, ${gradientStart} 0%, ${gradientEnd} 100%)` : backgroundColor;
|
|
34
|
-
const gridOverlay = devMode ? /* @__PURE__ */ jsx(
|
|
35
|
-
"div",
|
|
36
|
-
{
|
|
37
|
-
style: {
|
|
38
|
-
position: "absolute",
|
|
39
|
-
top: 0,
|
|
40
|
-
left: 0,
|
|
41
|
-
right: 0,
|
|
42
|
-
bottom: 0,
|
|
43
|
-
backgroundImage: `
|
|
44
|
-
linear-gradient(rgba(0, 0, 0, 0.1) 1px, transparent 1px),
|
|
45
|
-
linear-gradient(90deg, rgba(0, 0, 0, 0.1) 1px, transparent 1px)
|
|
46
|
-
`,
|
|
47
|
-
backgroundSize: "20px 20px",
|
|
48
|
-
pointerEvents: "none",
|
|
49
|
-
zIndex: 10
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
) : null;
|
|
53
|
-
return /* @__PURE__ */ jsxs(
|
|
54
|
-
"div",
|
|
55
|
-
{
|
|
56
|
-
style: {
|
|
57
|
-
height: "100%",
|
|
58
|
-
width: "100%",
|
|
59
|
-
display: "flex",
|
|
60
|
-
flexDirection: "column",
|
|
61
|
-
alignItems: "flex-start",
|
|
62
|
-
justifyContent: "space-between",
|
|
63
|
-
background: backgroundStyle,
|
|
64
|
-
padding: `${padding}px`,
|
|
65
|
-
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
66
|
-
position: "relative"
|
|
67
|
-
},
|
|
68
|
-
children: [
|
|
69
|
-
gridOverlay,
|
|
70
|
-
(showLogo && logo || showSiteName && siteName) && /* @__PURE__ */ jsxs(
|
|
71
|
-
"div",
|
|
72
|
-
{
|
|
73
|
-
style: {
|
|
74
|
-
display: "flex",
|
|
75
|
-
alignItems: "center",
|
|
76
|
-
gap: "16px"
|
|
77
|
-
},
|
|
78
|
-
children: [
|
|
79
|
-
showLogo && logo && // eslint-disable-next-line @next/next/no-img-element
|
|
80
|
-
/* @__PURE__ */ jsx(
|
|
81
|
-
"img",
|
|
82
|
-
{
|
|
83
|
-
src: logo,
|
|
84
|
-
alt: "Logo",
|
|
85
|
-
width: logoSize,
|
|
86
|
-
height: logoSize,
|
|
87
|
-
style: {
|
|
88
|
-
borderRadius: "8px"
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
),
|
|
92
|
-
showSiteName && siteName && /* @__PURE__ */ jsx(
|
|
93
|
-
"div",
|
|
94
|
-
{
|
|
95
|
-
style: {
|
|
96
|
-
fontSize: siteNameSize,
|
|
97
|
-
fontWeight: 600,
|
|
98
|
-
color: siteNameColor,
|
|
99
|
-
letterSpacing: "-0.02em"
|
|
100
|
-
},
|
|
101
|
-
children: siteName
|
|
102
|
-
}
|
|
103
|
-
)
|
|
104
|
-
]
|
|
105
|
-
}
|
|
106
|
-
),
|
|
107
|
-
/* @__PURE__ */ jsxs(
|
|
108
|
-
"div",
|
|
109
|
-
{
|
|
110
|
-
style: {
|
|
111
|
-
display: "flex",
|
|
112
|
-
flexDirection: "column",
|
|
113
|
-
gap: "24px",
|
|
114
|
-
flex: 1,
|
|
115
|
-
justifyContent: "center"
|
|
116
|
-
},
|
|
117
|
-
children: [
|
|
118
|
-
/* @__PURE__ */ jsx(
|
|
119
|
-
"div",
|
|
120
|
-
{
|
|
121
|
-
style: {
|
|
122
|
-
fontSize: calculatedTitleSize,
|
|
123
|
-
fontWeight: titleWeight,
|
|
124
|
-
color: titleColor,
|
|
125
|
-
lineHeight: 1.1,
|
|
126
|
-
letterSpacing: "-0.03em",
|
|
127
|
-
textShadow: backgroundType === "gradient" ? "0 2px 20px rgba(0, 0, 0, 0.2)" : "none",
|
|
128
|
-
maxWidth: "100%",
|
|
129
|
-
wordWrap: "break-word"
|
|
130
|
-
},
|
|
131
|
-
children: title
|
|
132
|
-
}
|
|
133
|
-
),
|
|
134
|
-
description && /* @__PURE__ */ jsx(
|
|
135
|
-
"div",
|
|
136
|
-
{
|
|
137
|
-
style: {
|
|
138
|
-
fontSize: descriptionSize,
|
|
139
|
-
fontWeight: 400,
|
|
140
|
-
color: descriptionColor,
|
|
141
|
-
lineHeight: 1.5,
|
|
142
|
-
letterSpacing: "-0.01em",
|
|
143
|
-
maxWidth: "90%",
|
|
144
|
-
display: "-webkit-box",
|
|
145
|
-
WebkitLineClamp: 2,
|
|
146
|
-
WebkitBoxOrient: "vertical",
|
|
147
|
-
overflow: "hidden"
|
|
148
|
-
},
|
|
149
|
-
children: description
|
|
150
|
-
}
|
|
151
|
-
)
|
|
152
|
-
]
|
|
153
|
-
}
|
|
154
|
-
),
|
|
155
|
-
/* @__PURE__ */ jsx(
|
|
156
|
-
"div",
|
|
157
|
-
{
|
|
158
|
-
style: {
|
|
159
|
-
display: "flex",
|
|
160
|
-
width: "100%",
|
|
161
|
-
height: "4px",
|
|
162
|
-
background: backgroundType === "gradient" ? `linear-gradient(90deg, ${gradientStart} 0%, ${gradientEnd} 100%)` : gradientStart,
|
|
163
|
-
borderRadius: "2px"
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
)
|
|
167
|
-
]
|
|
168
|
-
}
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
function LightTemplate({
|
|
172
|
-
title,
|
|
173
|
-
description,
|
|
174
|
-
siteName,
|
|
175
|
-
logo,
|
|
176
|
-
// Visibility flags
|
|
177
|
-
showLogo = true,
|
|
178
|
-
showSiteName = true,
|
|
179
|
-
// Background customization (defaults to light theme)
|
|
180
|
-
backgroundType = "solid",
|
|
181
|
-
gradientStart = "#667eea",
|
|
182
|
-
gradientEnd = "#764ba2",
|
|
183
|
-
backgroundColor = "#ffffff",
|
|
184
|
-
// Typography - Title
|
|
185
|
-
titleSize,
|
|
186
|
-
titleWeight = 800,
|
|
187
|
-
titleColor = "#111",
|
|
188
|
-
// Typography - Description
|
|
189
|
-
descriptionSize = 32,
|
|
190
|
-
descriptionColor = "#666",
|
|
191
|
-
// Typography - Site Name
|
|
192
|
-
siteNameSize = 28,
|
|
193
|
-
siteNameColor = "#111",
|
|
194
|
-
// Layout
|
|
195
|
-
padding = 80,
|
|
196
|
-
logoSize = 48,
|
|
197
|
-
// Dev mode
|
|
198
|
-
devMode = false
|
|
199
|
-
}) {
|
|
200
|
-
const calculatedTitleSize = titleSize || (title.length > 60 ? 56 : 72);
|
|
201
|
-
const backgroundStyle = backgroundType === "gradient" ? `linear-gradient(135deg, ${gradientStart} 0%, ${gradientEnd} 100%)` : backgroundColor;
|
|
202
|
-
const gridOverlay = devMode ? /* @__PURE__ */ jsx(
|
|
203
|
-
"div",
|
|
204
|
-
{
|
|
205
|
-
style: {
|
|
206
|
-
position: "absolute",
|
|
207
|
-
top: 0,
|
|
208
|
-
left: 0,
|
|
209
|
-
right: 0,
|
|
210
|
-
bottom: 0,
|
|
211
|
-
backgroundImage: `
|
|
212
|
-
linear-gradient(rgba(0, 0, 0, 0.1) 1px, transparent 1px),
|
|
213
|
-
linear-gradient(90deg, rgba(0, 0, 0, 0.1) 1px, transparent 1px)
|
|
214
|
-
`,
|
|
215
|
-
backgroundSize: "20px 20px",
|
|
216
|
-
pointerEvents: "none",
|
|
217
|
-
zIndex: 10
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
) : null;
|
|
221
|
-
return /* @__PURE__ */ jsxs(
|
|
222
|
-
"div",
|
|
223
|
-
{
|
|
224
|
-
style: {
|
|
225
|
-
height: "100%",
|
|
226
|
-
width: "100%",
|
|
227
|
-
display: "flex",
|
|
228
|
-
flexDirection: "column",
|
|
229
|
-
alignItems: "flex-start",
|
|
230
|
-
justifyContent: "space-between",
|
|
231
|
-
background: backgroundStyle,
|
|
232
|
-
padding: `${padding}px`,
|
|
233
|
-
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
234
|
-
position: "relative"
|
|
235
|
-
},
|
|
236
|
-
children: [
|
|
237
|
-
gridOverlay,
|
|
238
|
-
(showLogo && logo || showSiteName && siteName) && /* @__PURE__ */ jsxs(
|
|
239
|
-
"div",
|
|
240
|
-
{
|
|
241
|
-
style: {
|
|
242
|
-
display: "flex",
|
|
243
|
-
alignItems: "center",
|
|
244
|
-
gap: "16px"
|
|
245
|
-
},
|
|
246
|
-
children: [
|
|
247
|
-
showLogo && logo && // eslint-disable-next-line @next/next/no-img-element
|
|
248
|
-
/* @__PURE__ */ jsx(
|
|
249
|
-
"img",
|
|
250
|
-
{
|
|
251
|
-
src: logo,
|
|
252
|
-
alt: "Logo",
|
|
253
|
-
width: logoSize,
|
|
254
|
-
height: logoSize,
|
|
255
|
-
style: {
|
|
256
|
-
borderRadius: "8px"
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
),
|
|
260
|
-
showSiteName && siteName && /* @__PURE__ */ jsx(
|
|
261
|
-
"div",
|
|
262
|
-
{
|
|
263
|
-
style: {
|
|
264
|
-
fontSize: siteNameSize,
|
|
265
|
-
fontWeight: 600,
|
|
266
|
-
color: siteNameColor,
|
|
267
|
-
letterSpacing: "-0.02em"
|
|
268
|
-
},
|
|
269
|
-
children: siteName
|
|
270
|
-
}
|
|
271
|
-
)
|
|
272
|
-
]
|
|
273
|
-
}
|
|
274
|
-
),
|
|
275
|
-
/* @__PURE__ */ jsxs(
|
|
276
|
-
"div",
|
|
277
|
-
{
|
|
278
|
-
style: {
|
|
279
|
-
display: "flex",
|
|
280
|
-
flexDirection: "column",
|
|
281
|
-
gap: "24px",
|
|
282
|
-
flex: 1,
|
|
283
|
-
justifyContent: "center"
|
|
284
|
-
},
|
|
285
|
-
children: [
|
|
286
|
-
/* @__PURE__ */ jsx(
|
|
287
|
-
"div",
|
|
288
|
-
{
|
|
289
|
-
style: {
|
|
290
|
-
fontSize: calculatedTitleSize,
|
|
291
|
-
fontWeight: titleWeight,
|
|
292
|
-
color: titleColor,
|
|
293
|
-
lineHeight: 1.1,
|
|
294
|
-
letterSpacing: "-0.03em",
|
|
295
|
-
maxWidth: "100%",
|
|
296
|
-
wordWrap: "break-word"
|
|
297
|
-
},
|
|
298
|
-
children: title
|
|
299
|
-
}
|
|
300
|
-
),
|
|
301
|
-
description && /* @__PURE__ */ jsx(
|
|
302
|
-
"div",
|
|
303
|
-
{
|
|
304
|
-
style: {
|
|
305
|
-
fontSize: descriptionSize,
|
|
306
|
-
fontWeight: 400,
|
|
307
|
-
color: descriptionColor,
|
|
308
|
-
lineHeight: 1.5,
|
|
309
|
-
letterSpacing: "-0.01em",
|
|
310
|
-
maxWidth: "90%"
|
|
311
|
-
},
|
|
312
|
-
children: description
|
|
313
|
-
}
|
|
314
|
-
)
|
|
315
|
-
]
|
|
316
|
-
}
|
|
317
|
-
),
|
|
318
|
-
/* @__PURE__ */ jsx(
|
|
319
|
-
"div",
|
|
320
|
-
{
|
|
321
|
-
style: {
|
|
322
|
-
display: "flex",
|
|
323
|
-
width: "100%",
|
|
324
|
-
height: "4px",
|
|
325
|
-
background: backgroundType === "gradient" ? `linear-gradient(90deg, ${gradientStart} 0%, ${gradientEnd} 100%)` : gradientStart,
|
|
326
|
-
borderRadius: "2px"
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
)
|
|
330
|
-
]
|
|
331
|
-
}
|
|
332
|
-
);
|
|
333
|
-
}
|
|
334
|
-
export {
|
|
335
|
-
DefaultTemplate,
|
|
336
|
-
LightTemplate
|
|
337
|
-
};
|
|
338
|
-
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/og-image/components/DefaultTemplate.tsx"],"sourcesContent":["/**\n * Default OG Image Template\n *\n * A modern, gradient-based template for OG images\n */\n\nimport type { ReactElement } from 'react';\nimport type { OgImageTemplateProps } from '../types';\n\n/**\n * Default OG Image Template Component\n *\n * Features:\n * - Modern gradient background\n * - Responsive text sizing\n * - Optional logo and site name\n * - Clean typography\n * - Full customization support\n *\n * @param props - Template props with title, description, siteName, logo and optional customization\n */\nexport function DefaultTemplate({\n title,\n description,\n siteName,\n logo,\n // Visibility flags\n showLogo = true,\n showSiteName = true,\n // Background customization\n backgroundType = 'gradient',\n gradientStart = '#667eea',\n gradientEnd = '#764ba2',\n backgroundColor = '#ffffff',\n // Typography - Title\n titleSize,\n titleWeight = 800,\n titleColor = 'white',\n // Typography - Description\n descriptionSize = 32,\n descriptionColor = 'rgba(255, 255, 255, 0.85)',\n // Typography - Site Name\n siteNameSize = 28,\n siteNameColor = 'rgba(255, 255, 255, 0.95)',\n // Layout\n padding = 80,\n logoSize = 48,\n // Dev mode\n devMode = false,\n}: OgImageTemplateProps): ReactElement {\n // Calculate title size if not provided (responsive based on title length)\n const calculatedTitleSize = titleSize || (title.length > 60 ? 56 : 72);\n \n // Determine background style\n const backgroundStyle =\n backgroundType === 'gradient'\n ? `linear-gradient(135deg, ${gradientStart} 0%, ${gradientEnd} 100%)`\n : backgroundColor;\n\n // Grid overlay for dev mode\n const gridOverlay = devMode ? (\n <div\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundImage: `\n linear-gradient(rgba(0, 0, 0, 0.1) 1px, transparent 1px),\n linear-gradient(90deg, rgba(0, 0, 0, 0.1) 1px, transparent 1px)\n `,\n backgroundSize: '20px 20px',\n pointerEvents: 'none',\n zIndex: 10,\n }}\n />\n ) : null;\n\n return (\n <div\n style={{\n height: '100%',\n width: '100%',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'flex-start',\n justifyContent: 'space-between',\n background: backgroundStyle,\n padding: `${padding}px`,\n fontFamily: 'system-ui, -apple-system, sans-serif',\n position: 'relative',\n }}\n >\n {gridOverlay}\n \n {/* Header with logo and site name */}\n {((showLogo && logo) || (showSiteName && siteName)) && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '16px',\n }}\n >\n {showLogo && logo && (\n // eslint-disable-next-line @next/next/no-img-element\n <img\n src={logo}\n alt=\"Logo\"\n width={logoSize}\n height={logoSize}\n style={{\n borderRadius: '8px',\n }}\n />\n )}\n {showSiteName && siteName && (\n <div\n style={{\n fontSize: siteNameSize,\n fontWeight: 600,\n color: siteNameColor,\n letterSpacing: '-0.02em',\n }}\n >\n {siteName}\n </div>\n )}\n </div>\n )}\n\n {/* Main content */}\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: '24px',\n flex: 1,\n justifyContent: 'center',\n }}\n >\n {/* Title */}\n <div\n style={{\n fontSize: calculatedTitleSize,\n fontWeight: titleWeight,\n color: titleColor,\n lineHeight: 1.1,\n letterSpacing: '-0.03em',\n textShadow: backgroundType === 'gradient' ? '0 2px 20px rgba(0, 0, 0, 0.2)' : 'none',\n maxWidth: '100%',\n wordWrap: 'break-word',\n }}\n >\n {title}\n </div>\n\n {/* Description */}\n {description && (\n <div\n style={{\n fontSize: descriptionSize,\n fontWeight: 400,\n color: descriptionColor,\n lineHeight: 1.5,\n letterSpacing: '-0.01em',\n maxWidth: '90%',\n display: '-webkit-box',\n WebkitLineClamp: 2,\n WebkitBoxOrient: 'vertical',\n overflow: 'hidden',\n }}\n >\n {description}\n </div>\n )}\n </div>\n\n {/* Footer decoration */}\n <div\n style={{\n display: 'flex',\n width: '100%',\n height: '4px',\n background: backgroundType === 'gradient' \n ? `linear-gradient(90deg, ${gradientStart} 0%, ${gradientEnd} 100%)`\n : gradientStart,\n borderRadius: '2px',\n }}\n />\n </div>\n );\n}\n\n/**\n * Simple light template variant\n * \n * Light background variant with dark text\n */\nexport function LightTemplate({\n title,\n description,\n siteName,\n logo,\n // Visibility flags\n showLogo = true,\n showSiteName = true,\n // Background customization (defaults to light theme)\n backgroundType = 'solid',\n gradientStart = '#667eea',\n gradientEnd = '#764ba2',\n backgroundColor = '#ffffff',\n // Typography - Title\n titleSize,\n titleWeight = 800,\n titleColor = '#111',\n // Typography - Description\n descriptionSize = 32,\n descriptionColor = '#666',\n // Typography - Site Name\n siteNameSize = 28,\n siteNameColor = '#111',\n // Layout\n padding = 80,\n logoSize = 48,\n // Dev mode\n devMode = false,\n}: OgImageTemplateProps): ReactElement {\n // Calculate title size if not provided (responsive based on title length)\n const calculatedTitleSize = titleSize || (title.length > 60 ? 56 : 72);\n \n // Determine background style\n const backgroundStyle =\n backgroundType === 'gradient'\n ? `linear-gradient(135deg, ${gradientStart} 0%, ${gradientEnd} 100%)`\n : backgroundColor;\n\n // Grid overlay for dev mode\n const gridOverlay = devMode ? (\n <div\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundImage: `\n linear-gradient(rgba(0, 0, 0, 0.1) 1px, transparent 1px),\n linear-gradient(90deg, rgba(0, 0, 0, 0.1) 1px, transparent 1px)\n `,\n backgroundSize: '20px 20px',\n pointerEvents: 'none',\n zIndex: 10,\n }}\n />\n ) : null;\n\n return (\n <div\n style={{\n height: '100%',\n width: '100%',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'flex-start',\n justifyContent: 'space-between',\n background: backgroundStyle,\n padding: `${padding}px`,\n fontFamily: 'system-ui, -apple-system, sans-serif',\n position: 'relative',\n }}\n >\n {gridOverlay}\n \n {/* Header with logo and site name */}\n {((showLogo && logo) || (showSiteName && siteName)) && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '16px',\n }}\n >\n {showLogo && logo && (\n // eslint-disable-next-line @next/next/no-img-element\n <img\n src={logo}\n alt=\"Logo\"\n width={logoSize}\n height={logoSize}\n style={{\n borderRadius: '8px',\n }}\n />\n )}\n {showSiteName && siteName && (\n <div\n style={{\n fontSize: siteNameSize,\n fontWeight: 600,\n color: siteNameColor,\n letterSpacing: '-0.02em',\n }}\n >\n {siteName}\n </div>\n )}\n </div>\n )}\n\n {/* Main content */}\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: '24px',\n flex: 1,\n justifyContent: 'center',\n }}\n >\n {/* Title */}\n <div\n style={{\n fontSize: calculatedTitleSize,\n fontWeight: titleWeight,\n color: titleColor,\n lineHeight: 1.1,\n letterSpacing: '-0.03em',\n maxWidth: '100%',\n wordWrap: 'break-word',\n }}\n >\n {title}\n </div>\n\n {/* Description */}\n {description && (\n <div\n style={{\n fontSize: descriptionSize,\n fontWeight: 400,\n color: descriptionColor,\n lineHeight: 1.5,\n letterSpacing: '-0.01em',\n maxWidth: '90%',\n }}\n >\n {description}\n </div>\n )}\n </div>\n\n {/* Footer decoration */}\n <div\n style={{\n display: 'flex',\n width: '100%',\n height: '4px',\n background: backgroundType === 'gradient' \n ? `linear-gradient(90deg, ${gradientStart} 0%, ${gradientEnd} 100%)`\n : gradientStart,\n borderRadius: '2px',\n }}\n />\n </div>\n );\n}\n\n"],"mappings":"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","names":[]}
|