@gosalesdeal/blog 0.1.0 → 0.3.0
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 +265 -34
- package/dist/client/blogClient.js +79 -13
- package/dist/client/blogClient.js.map +1 -1
- package/dist/components/BlogPost.d.ts +12 -1
- package/dist/components/BlogPost.js +27 -16
- package/dist/components/BlogPost.js.map +1 -1
- package/dist/components/BlogPostHeader.d.ts +15 -0
- package/dist/components/BlogPostHeader.js +41 -0
- package/dist/components/BlogPostHeader.js.map +1 -0
- package/dist/components/landing/BlogLayoutComponents.d.ts +14 -0
- package/dist/components/landing/BlogLayoutComponents.js +198 -0
- package/dist/components/landing/BlogLayoutComponents.js.map +1 -0
- package/dist/components/landing/FlexibleLayoutComponent.d.ts +40 -0
- package/dist/components/landing/FlexibleLayoutComponent.js +352 -0
- package/dist/components/landing/FlexibleLayoutComponent.js.map +1 -0
- package/dist/components/landing/HeroFeatureBanner.d.ts +36 -0
- package/dist/components/landing/HeroFeatureBanner.js +88 -0
- package/dist/components/landing/HeroFeatureBanner.js.map +1 -0
- package/dist/components/landing/HeroFeatureBannerComponent.d.ts +4 -0
- package/dist/components/landing/HeroFeatureBannerComponent.js +100 -0
- package/dist/components/landing/HeroFeatureBannerComponent.js.map +1 -0
- package/dist/components/landing/HeroFeatureBannerVideo.d.ts +34 -0
- package/dist/components/landing/HeroFeatureBannerVideo.js +261 -0
- package/dist/components/landing/HeroFeatureBannerVideo.js.map +1 -0
- package/dist/components/landing/HeroFeatureBannerVideoComponent.d.ts +5 -0
- package/dist/components/landing/HeroFeatureBannerVideoComponent.js +69 -0
- package/dist/components/landing/HeroFeatureBannerVideoComponent.js.map +1 -0
- package/dist/components/landing/VarietyReviewslistComponent.d.ts +4 -0
- package/dist/components/landing/VarietyReviewslistComponent.js +172 -0
- package/dist/components/landing/VarietyReviewslistComponent.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +25 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/postUtils.d.ts +3 -0
- package/dist/lib/postUtils.js +8 -0
- package/dist/lib/postUtils.js.map +1 -0
- package/dist/lib/resolveMediaSrc.d.ts +2 -0
- package/dist/lib/resolveMediaSrc.js +21 -0
- package/dist/lib/resolveMediaSrc.js.map +1 -0
- package/dist/render/BlockRenderer.js +5 -0
- package/dist/render/BlockRenderer.js.map +1 -1
- package/dist/render/LandingPageRenderer.d.ts +5 -0
- package/dist/render/LandingPageRenderer.js +50 -0
- package/dist/render/LandingPageRenderer.js.map +1 -0
- package/dist/render/landingPageHtml.d.ts +28 -0
- package/dist/render/landingPageHtml.js +205 -0
- package/dist/render/landingPageHtml.js.map +1 -0
- package/dist/styles.css +27 -0
- package/dist/types/blog.d.ts +8 -2
- package/package.json +13 -3
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
const FlexibleLayoutComponent = ({ props }) => {
|
|
3
|
+
const {
|
|
4
|
+
columnCount = 2,
|
|
5
|
+
columns = [],
|
|
6
|
+
columnRatio = "50-50",
|
|
7
|
+
containerMaxWidth = "1200px",
|
|
8
|
+
containerPadding = "0rem",
|
|
9
|
+
containerMarginTop = "0rem",
|
|
10
|
+
containerMarginBottom = "0rem",
|
|
11
|
+
containerBackgroundColor = "transparent",
|
|
12
|
+
containerBorderRadius = "0px",
|
|
13
|
+
columnGap = "2rem",
|
|
14
|
+
rowGap = "1rem",
|
|
15
|
+
stackOnMobile = true,
|
|
16
|
+
stackOnTablet = false,
|
|
17
|
+
reverseOnMobile = false,
|
|
18
|
+
mobileBreakpoint = "768px",
|
|
19
|
+
tabletBreakpoint = "1024px",
|
|
20
|
+
customCSS = "",
|
|
21
|
+
className = "",
|
|
22
|
+
containerClass = "",
|
|
23
|
+
columnsWrapperClass = ""
|
|
24
|
+
} = props;
|
|
25
|
+
let ratios = columnRatio.split("-").map((r) => `${r}%`);
|
|
26
|
+
if (ratios.length !== columnCount) {
|
|
27
|
+
const equalRatio = `${Math.floor(100 / columnCount)}%`;
|
|
28
|
+
ratios = Array(columnCount).fill(equalRatio);
|
|
29
|
+
}
|
|
30
|
+
const renderElement = (element) => {
|
|
31
|
+
const commonStyle = {
|
|
32
|
+
marginTop: element.marginTop || "0",
|
|
33
|
+
marginBottom: element.marginBottom || "0"
|
|
34
|
+
};
|
|
35
|
+
switch (element.type) {
|
|
36
|
+
case "heading": {
|
|
37
|
+
const level = element.headingLevel || "h2";
|
|
38
|
+
const headingProps = {
|
|
39
|
+
key: element.id,
|
|
40
|
+
className: element.customClass,
|
|
41
|
+
style: {
|
|
42
|
+
...commonStyle,
|
|
43
|
+
color: element.headingColor,
|
|
44
|
+
fontSize: element.headingSize,
|
|
45
|
+
fontWeight: element.headingWeight,
|
|
46
|
+
textAlign: element.headingAlign
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
switch (level) {
|
|
50
|
+
case "h1":
|
|
51
|
+
return /* @__PURE__ */ jsx("h1", { ...headingProps, children: element.headingText });
|
|
52
|
+
case "h2":
|
|
53
|
+
return /* @__PURE__ */ jsx("h2", { ...headingProps, children: element.headingText });
|
|
54
|
+
case "h3":
|
|
55
|
+
return /* @__PURE__ */ jsx("h3", { ...headingProps, children: element.headingText });
|
|
56
|
+
case "h4":
|
|
57
|
+
return /* @__PURE__ */ jsx("h4", { ...headingProps, children: element.headingText });
|
|
58
|
+
case "h5":
|
|
59
|
+
return /* @__PURE__ */ jsx("h5", { ...headingProps, children: element.headingText });
|
|
60
|
+
case "h6":
|
|
61
|
+
return /* @__PURE__ */ jsx("h6", { ...headingProps, children: element.headingText });
|
|
62
|
+
default:
|
|
63
|
+
return /* @__PURE__ */ jsx("h2", { ...headingProps, children: element.headingText });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
case "paragraph":
|
|
67
|
+
return /* @__PURE__ */ jsx(
|
|
68
|
+
"p",
|
|
69
|
+
{
|
|
70
|
+
className: element.customClass,
|
|
71
|
+
style: {
|
|
72
|
+
...commonStyle,
|
|
73
|
+
color: element.paragraphColor,
|
|
74
|
+
fontSize: element.paragraphSize,
|
|
75
|
+
textAlign: element.paragraphAlign,
|
|
76
|
+
lineHeight: element.paragraphLineHeight
|
|
77
|
+
},
|
|
78
|
+
children: element.paragraphText
|
|
79
|
+
},
|
|
80
|
+
element.id
|
|
81
|
+
);
|
|
82
|
+
case "image":
|
|
83
|
+
return /* @__PURE__ */ jsxs("div", { className: element.customClass, style: commonStyle, children: [
|
|
84
|
+
/* @__PURE__ */ jsx(
|
|
85
|
+
"img",
|
|
86
|
+
{
|
|
87
|
+
src: element.imageUrl || "https://via.placeholder.com/400x300",
|
|
88
|
+
alt: element.imageAlt || "Image",
|
|
89
|
+
style: {
|
|
90
|
+
width: element.imageWidth || "100%",
|
|
91
|
+
height: element.imageHeight || "auto",
|
|
92
|
+
objectFit: element.imageObjectFit,
|
|
93
|
+
borderRadius: element.imageBorderRadius,
|
|
94
|
+
display: "block"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
),
|
|
98
|
+
element.imageCaption && /* @__PURE__ */ jsx("p", { style: { fontSize: "0.875rem", color: "#6b7280", marginTop: "0.5rem", textAlign: "center" }, children: element.imageCaption })
|
|
99
|
+
] }, element.id);
|
|
100
|
+
case "video": {
|
|
101
|
+
const getVideoEmbedUrl = (url, type) => {
|
|
102
|
+
if (type === "youtube") {
|
|
103
|
+
const videoId = url.includes("v=") ? url.split("v=")[1]?.split("&")[0] : url.split("/").pop();
|
|
104
|
+
return `https://www.youtube.com/embed/${videoId}`;
|
|
105
|
+
} else if (type === "vimeo") {
|
|
106
|
+
const videoId = url.split("/").pop();
|
|
107
|
+
return `https://player.vimeo.com/video/${videoId}`;
|
|
108
|
+
}
|
|
109
|
+
return url;
|
|
110
|
+
};
|
|
111
|
+
return /* @__PURE__ */ jsx("div", { className: element.customClass, style: commonStyle, children: element.videoType === "direct" ? /* @__PURE__ */ jsx(
|
|
112
|
+
"video",
|
|
113
|
+
{
|
|
114
|
+
src: element.videoUrl,
|
|
115
|
+
controls: element.videoControls,
|
|
116
|
+
autoPlay: element.videoAutoplay,
|
|
117
|
+
style: {
|
|
118
|
+
width: element.videoWidth || "100%",
|
|
119
|
+
height: element.videoHeight || "auto",
|
|
120
|
+
borderRadius: "8px"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
) : /* @__PURE__ */ jsx(
|
|
124
|
+
"iframe",
|
|
125
|
+
{
|
|
126
|
+
src: getVideoEmbedUrl(element.videoUrl || "", element.videoType || "youtube"),
|
|
127
|
+
style: {
|
|
128
|
+
width: element.videoWidth || "100%",
|
|
129
|
+
height: element.videoHeight || "400px",
|
|
130
|
+
border: "none",
|
|
131
|
+
borderRadius: "8px"
|
|
132
|
+
},
|
|
133
|
+
allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
|
|
134
|
+
allowFullScreen: true
|
|
135
|
+
}
|
|
136
|
+
) }, element.id);
|
|
137
|
+
}
|
|
138
|
+
case "button":
|
|
139
|
+
return /* @__PURE__ */ jsx(
|
|
140
|
+
"a",
|
|
141
|
+
{
|
|
142
|
+
href: element.buttonUrl || "#",
|
|
143
|
+
target: element.buttonTarget,
|
|
144
|
+
className: element.customClass,
|
|
145
|
+
style: {
|
|
146
|
+
...commonStyle,
|
|
147
|
+
display: element.buttonFullWidth ? "block" : "inline-block",
|
|
148
|
+
padding: element.buttonSize === "small" ? "0.5rem 1rem" : element.buttonSize === "large" ? "1rem 2rem" : "0.75rem 1.5rem",
|
|
149
|
+
backgroundColor: element.buttonBgColor || "#3b82f6",
|
|
150
|
+
color: element.buttonTextColor || "#ffffff",
|
|
151
|
+
textDecoration: "none",
|
|
152
|
+
borderRadius: "6px",
|
|
153
|
+
fontWeight: "500",
|
|
154
|
+
textAlign: "center",
|
|
155
|
+
border: element.buttonStyle === "outline" ? "2px solid currentColor" : "none",
|
|
156
|
+
background: element.buttonStyle === "outline" || element.buttonStyle === "text" ? "transparent" : element.buttonBgColor
|
|
157
|
+
},
|
|
158
|
+
children: element.buttonText
|
|
159
|
+
},
|
|
160
|
+
element.id
|
|
161
|
+
);
|
|
162
|
+
case "list": {
|
|
163
|
+
const listProps = {
|
|
164
|
+
key: element.id,
|
|
165
|
+
className: element.customClass,
|
|
166
|
+
style: {
|
|
167
|
+
...commonStyle,
|
|
168
|
+
listStyle: element.listStyle === "default" ? void 0 : "none",
|
|
169
|
+
paddingLeft: element.listStyle === "default" ? "1.5rem" : "0"
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
const items = (element.listItems || []).map((item, idx) => /* @__PURE__ */ jsx("li", { style: { marginBottom: "0.5rem" }, children: item }, idx));
|
|
173
|
+
return element.listType === "ordered" ? /* @__PURE__ */ jsx("ol", { ...listProps, children: items }) : /* @__PURE__ */ jsx("ul", { ...listProps, children: items });
|
|
174
|
+
}
|
|
175
|
+
case "quote":
|
|
176
|
+
return /* @__PURE__ */ jsxs(
|
|
177
|
+
"blockquote",
|
|
178
|
+
{
|
|
179
|
+
className: element.customClass,
|
|
180
|
+
style: {
|
|
181
|
+
...commonStyle,
|
|
182
|
+
borderLeft: `4px solid ${element.quoteBorderColor || "#3b82f6"}`,
|
|
183
|
+
paddingLeft: "1.5rem",
|
|
184
|
+
fontStyle: "italic",
|
|
185
|
+
color: "#374151"
|
|
186
|
+
},
|
|
187
|
+
children: [
|
|
188
|
+
/* @__PURE__ */ jsx("p", { style: { marginBottom: "0.5rem" }, children: element.quoteText }),
|
|
189
|
+
element.quoteAuthor && /* @__PURE__ */ jsxs("footer", { style: { fontSize: "0.875rem", color: "#6b7280" }, children: [
|
|
190
|
+
"— ",
|
|
191
|
+
element.quoteAuthor
|
|
192
|
+
] })
|
|
193
|
+
]
|
|
194
|
+
},
|
|
195
|
+
element.id
|
|
196
|
+
);
|
|
197
|
+
case "divider":
|
|
198
|
+
return /* @__PURE__ */ jsx(
|
|
199
|
+
"hr",
|
|
200
|
+
{
|
|
201
|
+
className: element.customClass,
|
|
202
|
+
style: {
|
|
203
|
+
...commonStyle,
|
|
204
|
+
border: "none",
|
|
205
|
+
borderTop: `${element.dividerHeight || "1px"} ${element.dividerStyle || "solid"} ${element.dividerColor || "#e5e7eb"}`,
|
|
206
|
+
width: element.dividerWidth || "100%"
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
element.id
|
|
210
|
+
);
|
|
211
|
+
case "spacer":
|
|
212
|
+
return /* @__PURE__ */ jsx(
|
|
213
|
+
"div",
|
|
214
|
+
{
|
|
215
|
+
className: element.customClass,
|
|
216
|
+
style: {
|
|
217
|
+
height: element.spacerHeight || "2rem"
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
element.id
|
|
221
|
+
);
|
|
222
|
+
case "code":
|
|
223
|
+
return /* @__PURE__ */ jsx(
|
|
224
|
+
"pre",
|
|
225
|
+
{
|
|
226
|
+
className: element.customClass,
|
|
227
|
+
style: {
|
|
228
|
+
...commonStyle,
|
|
229
|
+
backgroundColor: element.codeTheme === "light" ? "#f3f4f6" : "#1e293b",
|
|
230
|
+
color: element.codeTheme === "light" ? "#1f2937" : "#e2e8f0",
|
|
231
|
+
padding: "1rem",
|
|
232
|
+
borderRadius: "6px",
|
|
233
|
+
overflow: "auto",
|
|
234
|
+
fontSize: "0.875rem",
|
|
235
|
+
fontFamily: "monospace"
|
|
236
|
+
},
|
|
237
|
+
children: /* @__PURE__ */ jsx("code", { children: element.codeContent })
|
|
238
|
+
},
|
|
239
|
+
element.id
|
|
240
|
+
);
|
|
241
|
+
case "badge":
|
|
242
|
+
return /* @__PURE__ */ jsx(
|
|
243
|
+
"span",
|
|
244
|
+
{
|
|
245
|
+
className: element.customClass,
|
|
246
|
+
style: {
|
|
247
|
+
...commonStyle,
|
|
248
|
+
display: "inline-block",
|
|
249
|
+
padding: "0.25rem 0.75rem",
|
|
250
|
+
backgroundColor: element.badgeBgColor || "#3b82f6",
|
|
251
|
+
color: element.badgeColor || "#ffffff",
|
|
252
|
+
borderRadius: "9999px",
|
|
253
|
+
fontSize: "0.875rem",
|
|
254
|
+
fontWeight: "500"
|
|
255
|
+
},
|
|
256
|
+
children: element.badgeText
|
|
257
|
+
},
|
|
258
|
+
element.id
|
|
259
|
+
);
|
|
260
|
+
case "alert": {
|
|
261
|
+
const alertColors = {
|
|
262
|
+
info: { bg: "#dbeafe", border: "#3b82f6", text: "#1e40af" },
|
|
263
|
+
success: { bg: "#d1fae5", border: "#10b981", text: "#065f46" },
|
|
264
|
+
warning: { bg: "#fef3c7", border: "#f59e0b", text: "#92400e" },
|
|
265
|
+
error: { bg: "#fee2e2", border: "#ef4444", text: "#991b1b" }
|
|
266
|
+
};
|
|
267
|
+
const alertStyle = alertColors[element.alertType || "info"];
|
|
268
|
+
return /* @__PURE__ */ jsx(
|
|
269
|
+
"div",
|
|
270
|
+
{
|
|
271
|
+
className: element.customClass,
|
|
272
|
+
style: {
|
|
273
|
+
...commonStyle,
|
|
274
|
+
backgroundColor: alertStyle.bg,
|
|
275
|
+
borderLeft: `4px solid ${alertStyle.border}`,
|
|
276
|
+
color: alertStyle.text,
|
|
277
|
+
padding: "1rem",
|
|
278
|
+
borderRadius: "6px"
|
|
279
|
+
},
|
|
280
|
+
children: element.alertText
|
|
281
|
+
},
|
|
282
|
+
element.id
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
default:
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
const responsiveCSS = `
|
|
290
|
+
@media (max-width: ${mobileBreakpoint}) {
|
|
291
|
+
.flexible-layout-container-${columnCount} {
|
|
292
|
+
${stackOnMobile ? "flex-direction: column !important;" : ""}
|
|
293
|
+
${reverseOnMobile ? "flex-direction: column-reverse !important;" : ""}
|
|
294
|
+
}
|
|
295
|
+
.flexible-layout-column-${columnCount} {
|
|
296
|
+
${stackOnMobile ? "width: 100% !important; flex: none !important;" : ""}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
@media (max-width: ${tabletBreakpoint}) and (min-width: ${mobileBreakpoint}) {
|
|
300
|
+
.flexible-layout-container-${columnCount} {
|
|
301
|
+
${stackOnTablet ? "flex-direction: column !important;" : ""}
|
|
302
|
+
}
|
|
303
|
+
.flexible-layout-column-${columnCount} {
|
|
304
|
+
${stackOnTablet ? "width: 100% !important; flex: none !important;" : ""}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
`;
|
|
308
|
+
return /* @__PURE__ */ jsxs(
|
|
309
|
+
"div",
|
|
310
|
+
{
|
|
311
|
+
className: `flexible-layout w-full mx-auto overflow-hidden ${containerClass} ${className || ""}`,
|
|
312
|
+
children: [
|
|
313
|
+
customCSS && /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: customCSS } }),
|
|
314
|
+
/* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: responsiveCSS } }),
|
|
315
|
+
/* @__PURE__ */ jsx(
|
|
316
|
+
"div",
|
|
317
|
+
{
|
|
318
|
+
className: `flexible-layout-container-${columnCount} flex w-full ${columnsWrapperClass}`,
|
|
319
|
+
style: {
|
|
320
|
+
gap: columnGap,
|
|
321
|
+
alignItems: "stretch"
|
|
322
|
+
},
|
|
323
|
+
children: columns.slice(0, columnCount).map((column, index) => /* @__PURE__ */ jsx(
|
|
324
|
+
"div",
|
|
325
|
+
{
|
|
326
|
+
className: `flexible-layout-column-${columnCount}`,
|
|
327
|
+
style: {
|
|
328
|
+
flex: `0 0 ${ratios[index] || "auto"}`,
|
|
329
|
+
minWidth: 0,
|
|
330
|
+
maxWidth: ratios[index] || "auto",
|
|
331
|
+
backgroundColor: column.backgroundColor,
|
|
332
|
+
padding: column.padding,
|
|
333
|
+
display: "flex",
|
|
334
|
+
flexDirection: "column",
|
|
335
|
+
justifyContent: column.alignment === "center" ? "center" : column.alignment === "bottom" ? "flex-end" : "flex-start",
|
|
336
|
+
boxSizing: "border-box",
|
|
337
|
+
overflow: "hidden"
|
|
338
|
+
},
|
|
339
|
+
children: /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: rowGap }, children: column.elements.map(renderElement) })
|
|
340
|
+
},
|
|
341
|
+
column.id
|
|
342
|
+
))
|
|
343
|
+
}
|
|
344
|
+
)
|
|
345
|
+
]
|
|
346
|
+
}
|
|
347
|
+
);
|
|
348
|
+
};
|
|
349
|
+
export {
|
|
350
|
+
FlexibleLayoutComponent
|
|
351
|
+
};
|
|
352
|
+
//# sourceMappingURL=FlexibleLayoutComponent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FlexibleLayoutComponent.js","sources":["../../../src/components/landing/FlexibleLayoutComponent.tsx"],"sourcesContent":["import React from 'react';\n\ninterface ColumnElement {\n id: string;\n type: string;\n [key: string]: any;\n}\n\ninterface Column {\n id: string;\n elements: ColumnElement[];\n width?: string;\n backgroundColor?: string;\n padding?: string;\n alignment?: 'top' | 'center' | 'bottom';\n}\n\ninterface FlexibleLayoutProps {\n props: {\n columnCount?: number;\n columns?: Column[];\n columnRatio?: string;\n containerMaxWidth?: string;\n containerPadding?: string;\n containerMarginTop?: string;\n containerMarginBottom?: string;\n containerBackgroundColor?: string;\n containerBorderRadius?: string;\n columnGap?: string;\n rowGap?: string;\n stackOnMobile?: boolean;\n stackOnTablet?: boolean;\n reverseOnMobile?: boolean;\n mobileBreakpoint?: string;\n tabletBreakpoint?: string;\n customCSS?: string;\n className?: string;\n containerClass?: string;\n columnsWrapperClass?: string;\n };\n}\n\nexport const FlexibleLayoutComponent: React.FC<FlexibleLayoutProps> = ({ props }) => {\n const {\n columnCount = 2,\n columns = [],\n columnRatio = '50-50',\n containerMaxWidth = '1200px',\n containerPadding = '0rem',\n containerMarginTop = '0rem',\n containerMarginBottom = '0rem',\n containerBackgroundColor = 'transparent',\n containerBorderRadius = '0px',\n columnGap = '2rem',\n rowGap = '1rem',\n stackOnMobile = true,\n stackOnTablet = false,\n reverseOnMobile = false,\n mobileBreakpoint = '768px',\n tabletBreakpoint = '1024px',\n customCSS = '',\n className = '',\n containerClass = '',\n columnsWrapperClass = '',\n } = props;\n\n void containerMaxWidth;\n void containerPadding;\n void containerMarginTop;\n void containerMarginBottom;\n void containerBackgroundColor;\n void containerBorderRadius;\n\n // Parse column ratios and ensure they match columnCount\n let ratios = columnRatio.split('-').map((r: string) => `${r}%`);\n \n // Safety check: if ratios don't match columnCount, use equal distribution\n if (ratios.length !== columnCount) {\n const equalRatio = `${Math.floor(100 / columnCount)}%`;\n ratios = Array(columnCount).fill(equalRatio);\n }\n\n const renderElement = (element: ColumnElement) => {\n const commonStyle: React.CSSProperties = {\n marginTop: element.marginTop || '0',\n marginBottom: element.marginBottom || '0',\n };\n\n switch (element.type) {\n case 'heading': {\n const level = element.headingLevel || 'h2';\n const headingProps = {\n key: element.id,\n className: element.customClass,\n style: {\n ...commonStyle,\n color: element.headingColor,\n fontSize: element.headingSize,\n fontWeight: element.headingWeight,\n textAlign: element.headingAlign as any,\n },\n };\n \n switch (level) {\n case 'h1': return <h1 {...headingProps}>{element.headingText}</h1>;\n case 'h2': return <h2 {...headingProps}>{element.headingText}</h2>;\n case 'h3': return <h3 {...headingProps}>{element.headingText}</h3>;\n case 'h4': return <h4 {...headingProps}>{element.headingText}</h4>;\n case 'h5': return <h5 {...headingProps}>{element.headingText}</h5>;\n case 'h6': return <h6 {...headingProps}>{element.headingText}</h6>;\n default: return <h2 {...headingProps}>{element.headingText}</h2>;\n }\n }\n\n case 'paragraph':\n return (\n <p\n key={element.id}\n className={element.customClass}\n style={{\n ...commonStyle,\n color: element.paragraphColor,\n fontSize: element.paragraphSize,\n textAlign: element.paragraphAlign as any,\n lineHeight: element.paragraphLineHeight,\n }}\n >\n {element.paragraphText}\n </p>\n );\n\n case 'image':\n return (\n <div key={element.id} className={element.customClass} style={commonStyle}>\n <img\n src={element.imageUrl || 'https://via.placeholder.com/400x300'}\n alt={element.imageAlt || 'Image'}\n style={{\n width: element.imageWidth || '100%',\n height: element.imageHeight || 'auto',\n objectFit: element.imageObjectFit as any,\n borderRadius: element.imageBorderRadius,\n display: 'block',\n }}\n />\n {element.imageCaption && (\n <p style={{ fontSize: '0.875rem', color: '#6b7280', marginTop: '0.5rem', textAlign: 'center' }}>\n {element.imageCaption}\n </p>\n )}\n </div>\n );\n\n case 'video': {\n const getVideoEmbedUrl = (url: string, type: string) => {\n if (type === 'youtube') {\n const videoId = url.includes('v=') ? url.split('v=')[1]?.split('&')[0] : url.split('/').pop();\n return `https://www.youtube.com/embed/${videoId}`;\n } else if (type === 'vimeo') {\n const videoId = url.split('/').pop();\n return `https://player.vimeo.com/video/${videoId}`;\n }\n return url;\n };\n\n return (\n <div key={element.id} className={element.customClass} style={commonStyle}>\n {element.videoType === 'direct' ? (\n <video\n src={element.videoUrl}\n controls={element.videoControls}\n autoPlay={element.videoAutoplay}\n style={{\n width: element.videoWidth || '100%',\n height: element.videoHeight || 'auto',\n borderRadius: '8px',\n }}\n />\n ) : (\n <iframe\n src={getVideoEmbedUrl(element.videoUrl || '', element.videoType || 'youtube')}\n style={{\n width: element.videoWidth || '100%',\n height: element.videoHeight || '400px',\n border: 'none',\n borderRadius: '8px',\n }}\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n />\n )}\n </div>\n );\n }\n\n case 'button':\n return (\n <a\n key={element.id}\n href={element.buttonUrl || '#'}\n target={element.buttonTarget}\n className={element.customClass}\n style={{\n ...commonStyle,\n display: element.buttonFullWidth ? 'block' : 'inline-block',\n padding: element.buttonSize === 'small' ? '0.5rem 1rem' : element.buttonSize === 'large' ? '1rem 2rem' : '0.75rem 1.5rem',\n backgroundColor: element.buttonBgColor || '#3b82f6',\n color: element.buttonTextColor || '#ffffff',\n textDecoration: 'none',\n borderRadius: '6px',\n fontWeight: '500',\n textAlign: 'center',\n border: element.buttonStyle === 'outline' ? '2px solid currentColor' : 'none',\n background: element.buttonStyle === 'outline' || element.buttonStyle === 'text' ? 'transparent' : element.buttonBgColor,\n }}\n >\n {element.buttonText}\n </a>\n );\n\n case 'list': {\n const listProps = {\n key: element.id,\n className: element.customClass,\n style: {\n ...commonStyle,\n listStyle: element.listStyle === 'default' ? undefined : 'none',\n paddingLeft: element.listStyle === 'default' ? '1.5rem' : '0',\n },\n };\n \n const items = (element.listItems || []).map((item: string, idx: number) => (\n <li key={idx} style={{ marginBottom: '0.5rem' }}>\n {item}\n </li>\n ));\n \n return element.listType === 'ordered' ? (\n <ol {...listProps}>{items}</ol>\n ) : (\n <ul {...listProps}>{items}</ul>\n );\n }\n\n case 'quote':\n return (\n <blockquote\n key={element.id}\n className={element.customClass}\n style={{\n ...commonStyle,\n borderLeft: `4px solid ${element.quoteBorderColor || '#3b82f6'}`,\n paddingLeft: '1.5rem',\n fontStyle: 'italic',\n color: '#374151',\n }}\n >\n <p style={{ marginBottom: '0.5rem' }}>{element.quoteText}</p>\n {element.quoteAuthor && (\n <footer style={{ fontSize: '0.875rem', color: '#6b7280' }}>— {element.quoteAuthor}</footer>\n )}\n </blockquote>\n );\n\n case 'divider':\n return (\n <hr\n key={element.id}\n className={element.customClass}\n style={{\n ...commonStyle,\n border: 'none',\n borderTop: `${element.dividerHeight || '1px'} ${element.dividerStyle || 'solid'} ${element.dividerColor || '#e5e7eb'}`,\n width: element.dividerWidth || '100%',\n }}\n />\n );\n\n case 'spacer':\n return (\n <div\n key={element.id}\n className={element.customClass}\n style={{\n height: element.spacerHeight || '2rem',\n }}\n />\n );\n\n case 'code':\n return (\n <pre\n key={element.id}\n className={element.customClass}\n style={{\n ...commonStyle,\n backgroundColor: element.codeTheme === 'light' ? '#f3f4f6' : '#1e293b',\n color: element.codeTheme === 'light' ? '#1f2937' : '#e2e8f0',\n padding: '1rem',\n borderRadius: '6px',\n overflow: 'auto',\n fontSize: '0.875rem',\n fontFamily: 'monospace',\n }}\n >\n <code>{element.codeContent}</code>\n </pre>\n );\n\n case 'badge':\n return (\n <span\n key={element.id}\n className={element.customClass}\n style={{\n ...commonStyle,\n display: 'inline-block',\n padding: '0.25rem 0.75rem',\n backgroundColor: element.badgeBgColor || '#3b82f6',\n color: element.badgeColor || '#ffffff',\n borderRadius: '9999px',\n fontSize: '0.875rem',\n fontWeight: '500',\n }}\n >\n {element.badgeText}\n </span>\n );\n\n case 'alert': {\n const alertColors: Record<string, any> = {\n info: { bg: '#dbeafe', border: '#3b82f6', text: '#1e40af' },\n success: { bg: '#d1fae5', border: '#10b981', text: '#065f46' },\n warning: { bg: '#fef3c7', border: '#f59e0b', text: '#92400e' },\n error: { bg: '#fee2e2', border: '#ef4444', text: '#991b1b' },\n };\n const alertStyle = alertColors[element.alertType || 'info'];\n\n return (\n <div\n key={element.id}\n className={element.customClass}\n style={{\n ...commonStyle,\n backgroundColor: alertStyle.bg,\n borderLeft: `4px solid ${alertStyle.border}`,\n color: alertStyle.text,\n padding: '1rem',\n borderRadius: '6px',\n }}\n >\n {element.alertText}\n </div>\n );\n }\n\n default:\n return null;\n }\n };\n\n const responsiveCSS = `\n @media (max-width: ${mobileBreakpoint}) {\n .flexible-layout-container-${columnCount} {\n ${stackOnMobile ? 'flex-direction: column !important;' : ''}\n ${reverseOnMobile ? 'flex-direction: column-reverse !important;' : ''}\n }\n .flexible-layout-column-${columnCount} {\n ${stackOnMobile ? 'width: 100% !important; flex: none !important;' : ''}\n }\n }\n @media (max-width: ${tabletBreakpoint}) and (min-width: ${mobileBreakpoint}) {\n .flexible-layout-container-${columnCount} {\n ${stackOnTablet ? 'flex-direction: column !important;' : ''}\n }\n .flexible-layout-column-${columnCount} {\n ${stackOnTablet ? 'width: 100% !important; flex: none !important;' : ''}\n }\n }\n `;\n\n return (\n <div\n className={`flexible-layout w-full mx-auto overflow-hidden ${containerClass} ${className || ''}`}\n // style={{\n // maxWidth: containerMaxWidth,\n // marginTop: containerMarginTop,\n // marginBottom: containerMarginBottom,\n // padding: containerPadding,\n // backgroundColor: containerBackgroundColor,\n // borderRadius: containerBorderRadius,\n // }}\n >\n {customCSS && <style dangerouslySetInnerHTML={{ __html: customCSS }} />}\n <style dangerouslySetInnerHTML={{ __html: responsiveCSS }} />\n\n <div\n className={`flexible-layout-container-${columnCount} flex w-full ${columnsWrapperClass}`}\n style={{\n gap: columnGap,\n alignItems: 'stretch',\n }}\n >\n {columns.slice(0, columnCount).map((column: Column, index: number) => (\n <div\n key={column.id}\n className={`flexible-layout-column-${columnCount}`}\n style={{\n flex: `0 0 ${ratios[index] || 'auto'}`,\n minWidth: 0,\n maxWidth: ratios[index] || 'auto',\n backgroundColor: column.backgroundColor,\n padding: column.padding,\n display: 'flex',\n flexDirection: 'column',\n justifyContent: column.alignment === 'center' ? 'center' : column.alignment === 'bottom' ? 'flex-end' : 'flex-start',\n boxSizing: 'border-box',\n overflow: 'hidden',\n }}\n >\n <div style={{ display: 'flex', flexDirection: 'column', gap: rowGap }}>\n {column.elements.map(renderElement)}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
export type HeroBullet = {
|
|
3
|
+
icon?: string;
|
|
4
|
+
text: React.ReactNode;
|
|
5
|
+
};
|
|
6
|
+
export type HeroFeatureBannerProps = {
|
|
7
|
+
/** Background image url (served from /public or absolute). */
|
|
8
|
+
bgImageSrc: string;
|
|
9
|
+
/** Alt text for decorative bg (optional). */
|
|
10
|
+
bgAlt?: string;
|
|
11
|
+
/** Main heading (can be JSX for line breaks). */
|
|
12
|
+
heading: React.ReactNode;
|
|
13
|
+
/** Bullets with optional icon. */
|
|
14
|
+
bullets?: HeroBullet[];
|
|
15
|
+
/** CTA button config. If omitted, button is hidden. */
|
|
16
|
+
cta?: {
|
|
17
|
+
label: string;
|
|
18
|
+
href?: string;
|
|
19
|
+
onClick?: () => void;
|
|
20
|
+
icon?: string;
|
|
21
|
+
};
|
|
22
|
+
/** CTA position: 'left' (with content), 'center', 'top-left', 'top-right', 'bottom-left', 'bottom-right' */
|
|
23
|
+
ctaPosition?: 'left' | 'center' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
24
|
+
/** Height of the hero (px). */
|
|
25
|
+
height?: number;
|
|
26
|
+
/** Corner radius utility class from PrimeFlex. */
|
|
27
|
+
rounded?: string;
|
|
28
|
+
/** If true, apply a subtle left-side gradient for contrast. */
|
|
29
|
+
leftTint?: boolean;
|
|
30
|
+
/** Content max width (px) */
|
|
31
|
+
contentMaxWidth?: number;
|
|
32
|
+
/** Extra classes */
|
|
33
|
+
className?: string;
|
|
34
|
+
};
|
|
35
|
+
declare const HeroFeatureBanner: React.FC<HeroFeatureBannerProps>;
|
|
36
|
+
export default HeroFeatureBanner;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Button } from "primereact/button";
|
|
3
|
+
import Image from "next/image";
|
|
4
|
+
const HeroFeatureBanner = ({
|
|
5
|
+
bgImageSrc,
|
|
6
|
+
bgAlt,
|
|
7
|
+
heading,
|
|
8
|
+
bullets = [],
|
|
9
|
+
cta,
|
|
10
|
+
ctaPosition = "left",
|
|
11
|
+
height = 520,
|
|
12
|
+
rounded = "",
|
|
13
|
+
leftTint = true,
|
|
14
|
+
contentMaxWidth = 720,
|
|
15
|
+
className = ""
|
|
16
|
+
}) => {
|
|
17
|
+
return /* @__PURE__ */ jsxs(
|
|
18
|
+
"section",
|
|
19
|
+
{
|
|
20
|
+
className: `relative w-full ${rounded} overflow-hidden ${className}`,
|
|
21
|
+
"aria-label": "Hero feature banner",
|
|
22
|
+
style: { minHeight: height },
|
|
23
|
+
children: [
|
|
24
|
+
/* @__PURE__ */ jsx("style", { children: `
|
|
25
|
+
.hfb-tint { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
|
|
26
|
+
.hfb-content { position: relative; z-index: 2; }
|
|
27
|
+
.hfb-bullet i { color: var(--primary-color); font-size: 1.1rem; }
|
|
28
|
+
` }),
|
|
29
|
+
/* @__PURE__ */ jsx(
|
|
30
|
+
Image,
|
|
31
|
+
{
|
|
32
|
+
src: bgImageSrc,
|
|
33
|
+
alt: bgAlt || "",
|
|
34
|
+
fill: true,
|
|
35
|
+
priority: true,
|
|
36
|
+
quality: 90,
|
|
37
|
+
sizes: "100vw",
|
|
38
|
+
style: {
|
|
39
|
+
objectFit: "cover",
|
|
40
|
+
objectPosition: "center right"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
),
|
|
44
|
+
leftTint && /* @__PURE__ */ jsx(
|
|
45
|
+
"div",
|
|
46
|
+
{
|
|
47
|
+
className: "hfb-tint"
|
|
48
|
+
}
|
|
49
|
+
),
|
|
50
|
+
/* @__PURE__ */ jsxs("div", { className: "hfb-content w-full h-full container", style: { position: "relative" }, children: [
|
|
51
|
+
/* @__PURE__ */ jsx("div", { className: "p-4 p-md-5", style: { height: "100%", display: "flex", flexDirection: "column", justifyContent: ctaPosition === "center" ? "center" : "flex-start" }, children: /* @__PURE__ */ jsxs("div", { style: { maxWidth: contentMaxWidth }, children: [
|
|
52
|
+
/* @__PURE__ */ jsx("h1", { className: "m-0 text-900", style: { fontSize: 56, lineHeight: 1.05, fontWeight: 800 }, children: heading }),
|
|
53
|
+
bullets?.length > 0 && /* @__PURE__ */ jsx("ul", { className: "list-none m-0 p-0 mt-4", children: bullets.map((b, i) => /* @__PURE__ */ jsxs("li", { className: "flex align-items-center gap-3 mb-3 hfb-bullet", children: [
|
|
54
|
+
/* @__PURE__ */ jsx("span", { className: "flex align-items-center justify-content-center", style: { width: 34, height: 34, background: "rgba(255,100,50,.12)" }, children: /* @__PURE__ */ jsx("i", { className: `pi ${b.icon ?? "pi-check-circle"}` }) }),
|
|
55
|
+
/* @__PURE__ */ jsx("span", { className: "text-800", style: { fontSize: 18 }, children: b.text })
|
|
56
|
+
] }, i)) }),
|
|
57
|
+
cta && ctaPosition === "left" && /* @__PURE__ */ jsx("div", { className: "mt-5", children: cta.href ? /* @__PURE__ */ jsxs("a", { href: cta.href, className: "p-button p-component p-button-rounded p-button-lg", style: { textDecoration: "none" }, children: [
|
|
58
|
+
/* @__PURE__ */ jsx("span", { className: "p-button-icon p-button-icon-left pi pi-arrow-right" }),
|
|
59
|
+
/* @__PURE__ */ jsx("span", { className: "p-button-label", children: cta.label })
|
|
60
|
+
] }) : /* @__PURE__ */ jsx(Button, { rounded: true, size: "large", label: cta.label, icon: cta.icon ?? "pi pi-arrow-right", onClick: cta.onClick }) })
|
|
61
|
+
] }) }),
|
|
62
|
+
cta && ctaPosition !== "left" && /* @__PURE__ */ jsx(
|
|
63
|
+
"div",
|
|
64
|
+
{
|
|
65
|
+
style: {
|
|
66
|
+
position: "absolute",
|
|
67
|
+
zIndex: 3,
|
|
68
|
+
...ctaPosition === "center" && { top: "50%", left: "50%", transform: "translate(-50%, -50%)" },
|
|
69
|
+
...ctaPosition === "top-left" && { top: "2rem", left: "2rem" },
|
|
70
|
+
...ctaPosition === "top-right" && { top: "2rem", right: "2rem" },
|
|
71
|
+
...ctaPosition === "bottom-left" && { bottom: "2rem", left: "2rem" },
|
|
72
|
+
...ctaPosition === "bottom-right" && { bottom: "2rem", right: "2rem" }
|
|
73
|
+
},
|
|
74
|
+
children: cta.href ? /* @__PURE__ */ jsxs("a", { href: cta.href, className: "p-button p-component p-button-rounded p-button-lg", style: { textDecoration: "none" }, children: [
|
|
75
|
+
/* @__PURE__ */ jsx("span", { className: "p-button-icon p-button-icon-left pi pi-arrow-right" }),
|
|
76
|
+
/* @__PURE__ */ jsx("span", { className: "p-button-label", children: cta.label })
|
|
77
|
+
] }) : /* @__PURE__ */ jsx(Button, { rounded: true, size: "large", label: cta.label, icon: cta.icon ?? "pi pi-arrow-right", onClick: cta.onClick })
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
] })
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
export {
|
|
86
|
+
HeroFeatureBanner as default
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=HeroFeatureBanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HeroFeatureBanner.js","sources":["../../../src/components/landing/HeroFeatureBanner.tsx"],"sourcesContent":["import React from 'react';\nimport { Button } from 'primereact/button';\nimport Image from 'next/image';\n\nexport type HeroBullet = {\n icon?: string; // PrimeIcons name (e.g., 'pi-pencil'), defaults to check-circle\n text: React.ReactNode;\n};\n\nexport type HeroFeatureBannerProps = {\n /** Background image url (served from /public or absolute). */\n bgImageSrc: string;\n /** Alt text for decorative bg (optional). */\n bgAlt?: string;\n /** Main heading (can be JSX for line breaks). */\n heading: React.ReactNode;\n /** Bullets with optional icon. */\n bullets?: HeroBullet[];\n /** CTA button config. If omitted, button is hidden. */\n cta?: {\n label: string;\n href?: string;\n onClick?: () => void; // in case used client-side\n icon?: string; // PrimeIcons name\n };\n /** CTA position: 'left' (with content), 'center', 'top-left', 'top-right', 'bottom-left', 'bottom-right' */\n ctaPosition?: 'left' | 'center' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\n /** Height of the hero (px). */\n height?: number; // default 520\n /** Corner radius utility class from PrimeFlex. */\n rounded?: string; // default 'border-round-2xl'\n /** If true, apply a subtle left-side gradient for contrast. */\n leftTint?: boolean;\n /** Content max width (px) */\n contentMaxWidth?: number; // default 680\n /** Extra classes */\n className?: string;\n};\n\n// RAFCE (SSR-friendly)\nconst HeroFeatureBanner: React.FC<HeroFeatureBannerProps> = ({\n bgImageSrc,\n bgAlt,\n heading,\n bullets = [],\n cta,\n ctaPosition = 'left',\n height = 520,\n rounded = '',\n leftTint = true,\n contentMaxWidth = 720,\n className = '',\n}) => {\n return (\n <section\n className={`relative w-full ${rounded} overflow-hidden ${className}`}\n aria-label=\"Hero feature banner\"\n style={{ minHeight: height }}\n >\n <style>{`\n .hfb-tint { position: absolute; inset: 0; pointer-events: none; z-index: 1; }\n .hfb-content { position: relative; z-index: 2; }\n .hfb-bullet i { color: var(--primary-color); font-size: 1.1rem; }\n `}</style>\n\n {/* Full-bleed background using Next.js Image */}\n <Image\n src={bgImageSrc}\n alt={bgAlt || ''}\n fill\n priority\n quality={90}\n sizes=\"100vw\"\n style={{\n objectFit: 'cover',\n objectPosition: 'center right',\n }}\n />\n\n {/* Optional readability tint on the left */}\n {leftTint && (\n <div\n className=\"hfb-tint\"\n // style={{\n // background:\n // 'linear-gradient(90deg, rgba(255,255,255,0.96) 0%, rgba(255,255,255,0.9) 32%, rgba(255,255,255,0.55) 55%, rgba(255,255,255,0.12) 75%, rgba(255,255,255,0) 100%)',\n // }}\n />\n )}\n\n {/* Content */}\n <div className=\"hfb-content w-full h-full container\" style={{ position: 'relative' }}>\n <div className=\"p-4 p-md-5\" style={{ height: '100%', display: 'flex', flexDirection: 'column', justifyContent: ctaPosition === 'center' ? 'center' : 'flex-start' }}>\n <div style={{ maxWidth: contentMaxWidth }}>\n <h1 className=\"m-0 text-900\" style={{ fontSize: 56, lineHeight: 1.05, fontWeight: 800 }}>\n {heading}\n </h1>\n\n {bullets?.length > 0 && (\n <ul className=\"list-none m-0 p-0 mt-4\">\n {bullets.map((b, i) => (\n <li key={i} className=\"flex align-items-center gap-3 mb-3 hfb-bullet\">\n <span className=\"flex align-items-center justify-content-center\" style={{ width: 34, height: 34, background: 'rgba(255,100,50,.12)' }}>\n <i className={`pi ${b.icon ?? 'pi-check-circle'}`} />\n </span>\n <span className=\"text-800\" style={{ fontSize: 18 }}>{b.text}</span>\n </li>\n ))}\n </ul>\n )}\n\n {cta && ctaPosition === 'left' && (\n <div className=\"mt-5\">\n {cta.href ? (\n <a href={cta.href} className=\"p-button p-component p-button-rounded p-button-lg\" style={{ textDecoration: 'none' }}>\n <span className=\"p-button-icon p-button-icon-left pi pi-arrow-right\" />\n <span className=\"p-button-label\">{cta.label}</span>\n </a>\n ) : (\n <Button rounded size=\"large\" label={cta.label} icon={cta.icon ?? 'pi pi-arrow-right'} onClick={cta.onClick} />\n )}\n </div>\n )}\n </div>\n </div>\n \n {/* Positioned CTA button */}\n {cta && ctaPosition !== 'left' && (\n <div \n style={{\n position: 'absolute',\n zIndex: 3,\n ...(ctaPosition === 'center' && { top: '50%', left: '50%', transform: 'translate(-50%, -50%)' }),\n ...(ctaPosition === 'top-left' && { top: '2rem', left: '2rem' }),\n ...(ctaPosition === 'top-right' && { top: '2rem', right: '2rem' }),\n ...(ctaPosition === 'bottom-left' && { bottom: '2rem', left: '2rem' }),\n ...(ctaPosition === 'bottom-right' && { bottom: '2rem', right: '2rem' }),\n }}\n >\n {cta.href ? (\n <a href={cta.href} className=\"p-button p-component p-button-rounded p-button-lg\" style={{ textDecoration: 'none' }}>\n <span className=\"p-button-icon p-button-icon-left pi pi-arrow-right\" />\n <span className=\"p-button-label\">{cta.label}</span>\n </a>\n ) : (\n <Button rounded size=\"large\" label={cta.label} icon={cta.icon ?? 'pi pi-arrow-right'} onClick={cta.onClick} />\n )}\n </div>\n )}\n </div>\n </section>\n );\n};\n\nexport default HeroFeatureBanner;\n"],"names":[],"mappings":"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"}
|