@burdenoff/website-sdk 2026.516.14 → 2026.516.16
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/dist/content/index.d.mts +43 -7
- package/dist/content/index.d.ts +43 -7
- package/dist/content/index.js +404 -0
- package/dist/content/index.js.map +1 -1
- package/dist/content/index.mjs +404 -2
- package/dist/content/index.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +351 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +350 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/content/index.d.mts
CHANGED
|
@@ -11,14 +11,32 @@ interface ContentPageData {
|
|
|
11
11
|
seoKeywords?: string | null;
|
|
12
12
|
lastUpdated: string;
|
|
13
13
|
version: number;
|
|
14
|
+
tags?: string[];
|
|
15
|
+
excerpt?: string | null;
|
|
16
|
+
thumbnail?: string | null;
|
|
17
|
+
author?: string | null;
|
|
18
|
+
publishedAt?: string | null;
|
|
19
|
+
readingTime?: number | null;
|
|
20
|
+
featured?: boolean;
|
|
21
|
+
category?: string | null;
|
|
22
|
+
}
|
|
23
|
+
interface ContentPageListItem {
|
|
24
|
+
id: string;
|
|
25
|
+
title: string;
|
|
26
|
+
slug: string;
|
|
27
|
+
lastUpdated: string;
|
|
28
|
+
tags?: string[];
|
|
29
|
+
excerpt?: string | null;
|
|
30
|
+
thumbnail?: string | null;
|
|
31
|
+
author?: string | null;
|
|
32
|
+
publishedAt?: string | null;
|
|
33
|
+
readingTime?: number | null;
|
|
34
|
+
featured?: boolean;
|
|
35
|
+
category?: string | null;
|
|
36
|
+
seoDescription?: string | null;
|
|
14
37
|
}
|
|
15
38
|
interface ContentPageListData {
|
|
16
|
-
items:
|
|
17
|
-
id: string;
|
|
18
|
-
title: string;
|
|
19
|
-
slug: string;
|
|
20
|
-
lastUpdated: string;
|
|
21
|
-
}>;
|
|
39
|
+
items: ContentPageListItem[];
|
|
22
40
|
total: number;
|
|
23
41
|
hasMore: boolean;
|
|
24
42
|
}
|
|
@@ -72,4 +90,22 @@ declare function ContentRenderer({ content, format, className, }: {
|
|
|
72
90
|
className?: string;
|
|
73
91
|
}): react_jsx_runtime.JSX.Element;
|
|
74
92
|
|
|
75
|
-
|
|
93
|
+
interface BlogListPageProps {
|
|
94
|
+
productName?: string;
|
|
95
|
+
heroTitle?: string;
|
|
96
|
+
heroSubtitle?: string;
|
|
97
|
+
blogPostBasePath?: string;
|
|
98
|
+
className?: string;
|
|
99
|
+
seoTitle?: string;
|
|
100
|
+
seoDescription?: string;
|
|
101
|
+
seoKeywords?: string;
|
|
102
|
+
}
|
|
103
|
+
interface BlogPostPageProps {
|
|
104
|
+
productName?: string;
|
|
105
|
+
blogListUrl?: string;
|
|
106
|
+
className?: string;
|
|
107
|
+
}
|
|
108
|
+
declare function BlogListPage(props: BlogListPageProps): react_jsx_runtime.JSX.Element;
|
|
109
|
+
declare function BlogPostPage(props: BlogPostPageProps): react_jsx_runtime.JSX.Element;
|
|
110
|
+
|
|
111
|
+
export { BlogListPage, type BlogListPageProps, BlogPostPage, type BlogPostPageProps, type ContentPageData, type ContentPageListData, type ContentPageListItem, ContentRenderer, type UseContentPageOptions, useContentPage, useContentPages };
|
package/dist/content/index.d.ts
CHANGED
|
@@ -11,14 +11,32 @@ interface ContentPageData {
|
|
|
11
11
|
seoKeywords?: string | null;
|
|
12
12
|
lastUpdated: string;
|
|
13
13
|
version: number;
|
|
14
|
+
tags?: string[];
|
|
15
|
+
excerpt?: string | null;
|
|
16
|
+
thumbnail?: string | null;
|
|
17
|
+
author?: string | null;
|
|
18
|
+
publishedAt?: string | null;
|
|
19
|
+
readingTime?: number | null;
|
|
20
|
+
featured?: boolean;
|
|
21
|
+
category?: string | null;
|
|
22
|
+
}
|
|
23
|
+
interface ContentPageListItem {
|
|
24
|
+
id: string;
|
|
25
|
+
title: string;
|
|
26
|
+
slug: string;
|
|
27
|
+
lastUpdated: string;
|
|
28
|
+
tags?: string[];
|
|
29
|
+
excerpt?: string | null;
|
|
30
|
+
thumbnail?: string | null;
|
|
31
|
+
author?: string | null;
|
|
32
|
+
publishedAt?: string | null;
|
|
33
|
+
readingTime?: number | null;
|
|
34
|
+
featured?: boolean;
|
|
35
|
+
category?: string | null;
|
|
36
|
+
seoDescription?: string | null;
|
|
14
37
|
}
|
|
15
38
|
interface ContentPageListData {
|
|
16
|
-
items:
|
|
17
|
-
id: string;
|
|
18
|
-
title: string;
|
|
19
|
-
slug: string;
|
|
20
|
-
lastUpdated: string;
|
|
21
|
-
}>;
|
|
39
|
+
items: ContentPageListItem[];
|
|
22
40
|
total: number;
|
|
23
41
|
hasMore: boolean;
|
|
24
42
|
}
|
|
@@ -72,4 +90,22 @@ declare function ContentRenderer({ content, format, className, }: {
|
|
|
72
90
|
className?: string;
|
|
73
91
|
}): react_jsx_runtime.JSX.Element;
|
|
74
92
|
|
|
75
|
-
|
|
93
|
+
interface BlogListPageProps {
|
|
94
|
+
productName?: string;
|
|
95
|
+
heroTitle?: string;
|
|
96
|
+
heroSubtitle?: string;
|
|
97
|
+
blogPostBasePath?: string;
|
|
98
|
+
className?: string;
|
|
99
|
+
seoTitle?: string;
|
|
100
|
+
seoDescription?: string;
|
|
101
|
+
seoKeywords?: string;
|
|
102
|
+
}
|
|
103
|
+
interface BlogPostPageProps {
|
|
104
|
+
productName?: string;
|
|
105
|
+
blogListUrl?: string;
|
|
106
|
+
className?: string;
|
|
107
|
+
}
|
|
108
|
+
declare function BlogListPage(props: BlogListPageProps): react_jsx_runtime.JSX.Element;
|
|
109
|
+
declare function BlogPostPage(props: BlogPostPageProps): react_jsx_runtime.JSX.Element;
|
|
110
|
+
|
|
111
|
+
export { BlogListPage, type BlogListPageProps, BlogPostPage, type BlogPostPageProps, type ContentPageData, type ContentPageListData, type ContentPageListItem, ContentRenderer, type UseContentPageOptions, useContentPage, useContentPages };
|
package/dist/content/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var react = require('react');
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
+
var reactHelmetAsync = require('react-helmet-async');
|
|
5
6
|
|
|
6
7
|
var __defProp = Object.defineProperty;
|
|
7
8
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -206,6 +207,15 @@ var PUBLIC_CONTENT_PAGES_QUERY = `
|
|
|
206
207
|
title
|
|
207
208
|
slug
|
|
208
209
|
lastUpdated
|
|
210
|
+
tags
|
|
211
|
+
excerpt
|
|
212
|
+
thumbnail
|
|
213
|
+
author
|
|
214
|
+
publishedAt
|
|
215
|
+
readingTime
|
|
216
|
+
featured
|
|
217
|
+
category
|
|
218
|
+
seoDescription
|
|
209
219
|
}
|
|
210
220
|
total
|
|
211
221
|
hasMore
|
|
@@ -303,7 +313,401 @@ function ContentRenderer({
|
|
|
303
313
|
}
|
|
304
314
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: /* @__PURE__ */ jsxRuntime.jsx("pre", { style: { whiteSpace: "pre-wrap", fontFamily: "inherit" }, children: content }) });
|
|
305
315
|
}
|
|
316
|
+
function PageHead({
|
|
317
|
+
title,
|
|
318
|
+
description,
|
|
319
|
+
productName,
|
|
320
|
+
keywords,
|
|
321
|
+
image,
|
|
322
|
+
url,
|
|
323
|
+
favicon,
|
|
324
|
+
robots = "index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1",
|
|
325
|
+
locale = "en_US",
|
|
326
|
+
twitterHandle,
|
|
327
|
+
themeColor = "#000000",
|
|
328
|
+
structuredData,
|
|
329
|
+
additionalMeta
|
|
330
|
+
}) {
|
|
331
|
+
const fullTitle = productName && !title.includes(productName) ? `${title} | ${productName}` : title;
|
|
332
|
+
const fullImageUrl = image && !image.startsWith("http") && url ? `${url.replace(/\/$/, "")}${image}` : image;
|
|
333
|
+
const structuredDataItems = structuredData ? Array.isArray(structuredData) ? structuredData : [structuredData] : [];
|
|
334
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactHelmetAsync.Helmet, { children: [
|
|
335
|
+
/* @__PURE__ */ jsxRuntime.jsx("title", { children: fullTitle }),
|
|
336
|
+
/* @__PURE__ */ jsxRuntime.jsx("meta", { name: "title", content: fullTitle }),
|
|
337
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "description", content: description }),
|
|
338
|
+
keywords && /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "keywords", content: keywords }),
|
|
339
|
+
/* @__PURE__ */ jsxRuntime.jsx("meta", { name: "author", content: "Burdenoff Consultancy Services Pvt Ltd" }),
|
|
340
|
+
/* @__PURE__ */ jsxRuntime.jsx("meta", { name: "robots", content: robots }),
|
|
341
|
+
url && /* @__PURE__ */ jsxRuntime.jsx("link", { rel: "canonical", href: url }),
|
|
342
|
+
favicon && /* @__PURE__ */ jsxRuntime.jsx("link", { rel: "icon", href: favicon }),
|
|
343
|
+
/* @__PURE__ */ jsxRuntime.jsx("meta", { property: "og:type", content: "website" }),
|
|
344
|
+
/* @__PURE__ */ jsxRuntime.jsx("meta", { property: "og:title", content: fullTitle }),
|
|
345
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("meta", { property: "og:description", content: description }),
|
|
346
|
+
fullImageUrl && /* @__PURE__ */ jsxRuntime.jsx("meta", { property: "og:image", content: fullImageUrl }),
|
|
347
|
+
url && /* @__PURE__ */ jsxRuntime.jsx("meta", { property: "og:url", content: url }),
|
|
348
|
+
/* @__PURE__ */ jsxRuntime.jsx("meta", { property: "og:locale", content: locale }),
|
|
349
|
+
productName && /* @__PURE__ */ jsxRuntime.jsx("meta", { property: "og:site_name", content: productName }),
|
|
350
|
+
/* @__PURE__ */ jsxRuntime.jsx("meta", { name: "twitter:card", content: "summary_large_image" }),
|
|
351
|
+
/* @__PURE__ */ jsxRuntime.jsx("meta", { name: "twitter:title", content: fullTitle }),
|
|
352
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "twitter:description", content: description }),
|
|
353
|
+
fullImageUrl && /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "twitter:image", content: fullImageUrl }),
|
|
354
|
+
twitterHandle && /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "twitter:creator", content: twitterHandle }),
|
|
355
|
+
/* @__PURE__ */ jsxRuntime.jsx("meta", { name: "theme-color", content: themeColor }),
|
|
356
|
+
structuredDataItems.map((data, index) => /* @__PURE__ */ jsxRuntime.jsx("script", { type: "application/ld+json", children: JSON.stringify(data) }, `ld-${index}`)),
|
|
357
|
+
additionalMeta?.map((meta, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
358
|
+
"meta",
|
|
359
|
+
{
|
|
360
|
+
...meta.name ? { name: meta.name } : {},
|
|
361
|
+
...meta.property ? { property: meta.property } : {},
|
|
362
|
+
content: meta.content
|
|
363
|
+
},
|
|
364
|
+
`meta-${index}`
|
|
365
|
+
))
|
|
366
|
+
] });
|
|
367
|
+
}
|
|
368
|
+
var BLOG_POSTS_QUERY = `
|
|
369
|
+
query BlogPosts($productId: String!, $limit: Int, $offset: Int) {
|
|
370
|
+
publicContentPages(productId: $productId, limit: $limit, offset: $offset) {
|
|
371
|
+
items {
|
|
372
|
+
id
|
|
373
|
+
title
|
|
374
|
+
slug
|
|
375
|
+
lastUpdated
|
|
376
|
+
tags
|
|
377
|
+
excerpt
|
|
378
|
+
thumbnail
|
|
379
|
+
author
|
|
380
|
+
publishedAt
|
|
381
|
+
readingTime
|
|
382
|
+
featured
|
|
383
|
+
category
|
|
384
|
+
seoDescription
|
|
385
|
+
}
|
|
386
|
+
total
|
|
387
|
+
hasMore
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
`;
|
|
391
|
+
var BLOG_POST_QUERY = `
|
|
392
|
+
query BlogPost($slug: String!, $productId: String) {
|
|
393
|
+
publicContentPage(slug: $slug, productId: $productId) {
|
|
394
|
+
id
|
|
395
|
+
title
|
|
396
|
+
slug
|
|
397
|
+
content
|
|
398
|
+
contentFormat
|
|
399
|
+
seoTitle
|
|
400
|
+
seoDescription
|
|
401
|
+
seoKeywords
|
|
402
|
+
lastUpdated
|
|
403
|
+
tags
|
|
404
|
+
excerpt
|
|
405
|
+
thumbnail
|
|
406
|
+
author
|
|
407
|
+
publishedAt
|
|
408
|
+
readingTime
|
|
409
|
+
category
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
`;
|
|
413
|
+
function BlogCard({
|
|
414
|
+
post,
|
|
415
|
+
basePath = "/blog"
|
|
416
|
+
}) {
|
|
417
|
+
const date = post.publishedAt || post.lastUpdated;
|
|
418
|
+
const formattedDate = date ? new Date(date).toLocaleDateString("en-US", {
|
|
419
|
+
year: "numeric",
|
|
420
|
+
month: "long",
|
|
421
|
+
day: "numeric"
|
|
422
|
+
}) : "";
|
|
423
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
424
|
+
"a",
|
|
425
|
+
{
|
|
426
|
+
href: `${basePath}/${post.slug}`,
|
|
427
|
+
className: "group block bg-card border rounded-xl overflow-hidden hover:shadow-lg hover:border-primary/30 transition-all duration-300",
|
|
428
|
+
children: [
|
|
429
|
+
post.thumbnail ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-[16/9] overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
430
|
+
"img",
|
|
431
|
+
{
|
|
432
|
+
src: post.thumbnail,
|
|
433
|
+
alt: post.title,
|
|
434
|
+
className: "w-full h-full object-cover group-hover:scale-105 transition-transform duration-300",
|
|
435
|
+
loading: "lazy"
|
|
436
|
+
}
|
|
437
|
+
) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-[16/9] bg-muted/50 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
438
|
+
"svg",
|
|
439
|
+
{
|
|
440
|
+
className: "w-12 h-12 text-muted-foreground/20",
|
|
441
|
+
fill: "none",
|
|
442
|
+
viewBox: "0 0 24 24",
|
|
443
|
+
stroke: "currentColor",
|
|
444
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
445
|
+
"path",
|
|
446
|
+
{
|
|
447
|
+
strokeLinecap: "round",
|
|
448
|
+
strokeLinejoin: "round",
|
|
449
|
+
strokeWidth: 1.5,
|
|
450
|
+
d: "M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"
|
|
451
|
+
}
|
|
452
|
+
)
|
|
453
|
+
}
|
|
454
|
+
) }),
|
|
455
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-5 sm:p-6", children: [
|
|
456
|
+
post.category && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block text-xs font-medium text-primary bg-primary/10 px-2.5 py-1 rounded-full mb-3", children: post.category }),
|
|
457
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-foreground mb-2 group-hover:text-primary transition-colors line-clamp-2", children: post.title }),
|
|
458
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mb-4 line-clamp-3", children: post.excerpt || post.seoDescription || "" }),
|
|
459
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-xs text-muted-foreground", children: [
|
|
460
|
+
post.author && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: post.author }),
|
|
461
|
+
post.author && formattedDate && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
462
|
+
formattedDate && /* @__PURE__ */ jsxRuntime.jsx("span", { children: formattedDate }),
|
|
463
|
+
post.readingTime && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
464
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
465
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
466
|
+
post.readingTime,
|
|
467
|
+
" min read"
|
|
468
|
+
] })
|
|
469
|
+
] })
|
|
470
|
+
] })
|
|
471
|
+
] })
|
|
472
|
+
]
|
|
473
|
+
}
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
function BlogListPage(props) {
|
|
477
|
+
const {
|
|
478
|
+
productName,
|
|
479
|
+
heroTitle = "Blog",
|
|
480
|
+
heroSubtitle = "Latest updates, engineering insights, and product news",
|
|
481
|
+
blogPostBasePath = "/blog",
|
|
482
|
+
className = "",
|
|
483
|
+
seoTitle,
|
|
484
|
+
seoDescription,
|
|
485
|
+
seoKeywords
|
|
486
|
+
} = props;
|
|
487
|
+
const client = useWebSDK();
|
|
488
|
+
const config = useWebSDKConfig();
|
|
489
|
+
const { product } = useProduct();
|
|
490
|
+
const resolvedProductId = product?.id || config.productId;
|
|
491
|
+
const [posts, setPosts] = react.useState([]);
|
|
492
|
+
const [total, setTotal] = react.useState(0);
|
|
493
|
+
const [loading, setLoading] = react.useState(true);
|
|
494
|
+
const [error, setError] = react.useState(null);
|
|
495
|
+
const [offset, setOffset] = react.useState(0);
|
|
496
|
+
const limit = 12;
|
|
497
|
+
const fetchPosts = react.useCallback(async () => {
|
|
498
|
+
if (!resolvedProductId) return;
|
|
499
|
+
setLoading(true);
|
|
500
|
+
try {
|
|
501
|
+
const result = await client.query(BLOG_POSTS_QUERY, {
|
|
502
|
+
productId: resolvedProductId,
|
|
503
|
+
limit,
|
|
504
|
+
offset
|
|
505
|
+
});
|
|
506
|
+
if (result.errors?.length) {
|
|
507
|
+
setError(result.errors[0]?.message ?? "Failed to load posts");
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
const blogPosts = (result.data?.publicContentPages?.items || []).filter(
|
|
511
|
+
(p) => p.tags?.includes("blog")
|
|
512
|
+
);
|
|
513
|
+
setPosts(blogPosts);
|
|
514
|
+
setTotal(result.data?.publicContentPages?.total || 0);
|
|
515
|
+
setError(null);
|
|
516
|
+
} catch {
|
|
517
|
+
setError("Failed to load blog posts");
|
|
518
|
+
} finally {
|
|
519
|
+
setLoading(false);
|
|
520
|
+
}
|
|
521
|
+
}, [client, resolvedProductId, offset]);
|
|
522
|
+
react.useEffect(() => {
|
|
523
|
+
fetchPosts();
|
|
524
|
+
}, [fetchPosts]);
|
|
525
|
+
const featuredPosts = posts.filter((p) => p.featured);
|
|
526
|
+
const regularPosts = posts.filter((p) => !p.featured);
|
|
527
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `w-full ${className}`, children: [
|
|
528
|
+
seoTitle && /* @__PURE__ */ jsxRuntime.jsx(
|
|
529
|
+
PageHead,
|
|
530
|
+
{
|
|
531
|
+
title: seoTitle,
|
|
532
|
+
description: seoDescription || heroSubtitle,
|
|
533
|
+
productName,
|
|
534
|
+
keywords: seoKeywords
|
|
535
|
+
}
|
|
536
|
+
),
|
|
537
|
+
/* @__PURE__ */ jsxRuntime.jsx("section", { className: "py-16 sm:py-20 md:py-24", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center max-w-3xl mx-auto", children: [
|
|
538
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight text-foreground", children: heroTitle }),
|
|
539
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-4 text-lg text-muted-foreground", children: heroSubtitle })
|
|
540
|
+
] }) }) }),
|
|
541
|
+
/* @__PURE__ */ jsxRuntime.jsx("section", { className: "pb-16 sm:pb-20", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid md:grid-cols-2 lg:grid-cols-3 gap-6 sm:gap-8", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
542
|
+
"div",
|
|
543
|
+
{
|
|
544
|
+
className: "bg-card border rounded-xl overflow-hidden animate-pulse",
|
|
545
|
+
children: [
|
|
546
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-[16/9] bg-muted" }),
|
|
547
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6 space-y-3", children: [
|
|
548
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-muted rounded w-1/4" }),
|
|
549
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-6 bg-muted rounded w-3/4" }),
|
|
550
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-muted rounded" }),
|
|
551
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-muted rounded w-1/2" })
|
|
552
|
+
] })
|
|
553
|
+
]
|
|
554
|
+
},
|
|
555
|
+
i
|
|
556
|
+
)) }) : error ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: error }) }) : posts.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: "No blog posts yet. Check back soon!" }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
557
|
+
featuredPosts.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid md:grid-cols-2 gap-6 sm:gap-8 mb-8", children: featuredPosts.map((post) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
558
|
+
BlogCard,
|
|
559
|
+
{
|
|
560
|
+
post,
|
|
561
|
+
basePath: blogPostBasePath
|
|
562
|
+
},
|
|
563
|
+
post.id
|
|
564
|
+
)) }),
|
|
565
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid md:grid-cols-2 lg:grid-cols-3 gap-6 sm:gap-8", children: regularPosts.map((post) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
566
|
+
BlogCard,
|
|
567
|
+
{
|
|
568
|
+
post,
|
|
569
|
+
basePath: blogPostBasePath
|
|
570
|
+
},
|
|
571
|
+
post.id
|
|
572
|
+
)) }),
|
|
573
|
+
total > limit && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-center gap-4 mt-12", children: [
|
|
574
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
575
|
+
"button",
|
|
576
|
+
{
|
|
577
|
+
onClick: () => setOffset(Math.max(0, offset - limit)),
|
|
578
|
+
disabled: offset === 0,
|
|
579
|
+
className: "px-5 py-2.5 text-sm font-medium border rounded-lg disabled:opacity-40 hover:bg-muted transition-colors",
|
|
580
|
+
children: "Previous"
|
|
581
|
+
}
|
|
582
|
+
),
|
|
583
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
584
|
+
"button",
|
|
585
|
+
{
|
|
586
|
+
onClick: () => setOffset(offset + limit),
|
|
587
|
+
disabled: offset + limit >= total,
|
|
588
|
+
className: "px-5 py-2.5 text-sm font-medium border rounded-lg disabled:opacity-40 hover:bg-muted transition-colors",
|
|
589
|
+
children: "Next"
|
|
590
|
+
}
|
|
591
|
+
)
|
|
592
|
+
] })
|
|
593
|
+
] }) }) })
|
|
594
|
+
] });
|
|
595
|
+
}
|
|
596
|
+
function BlogPostPage(props) {
|
|
597
|
+
const { productName, blogListUrl = "/blog", className = "" } = props;
|
|
598
|
+
const client = useWebSDK();
|
|
599
|
+
const config = useWebSDKConfig();
|
|
600
|
+
const { product } = useProduct();
|
|
601
|
+
const resolvedProductId = product?.id || config.productId;
|
|
602
|
+
const [post, setPost] = react.useState(null);
|
|
603
|
+
const [loading, setLoading] = react.useState(true);
|
|
604
|
+
const [error, setError] = react.useState(null);
|
|
605
|
+
const slug = typeof window !== "undefined" ? window.location.pathname.split("/").pop() || "" : "";
|
|
606
|
+
react.useEffect(() => {
|
|
607
|
+
if (!slug || !resolvedProductId) return;
|
|
608
|
+
async function fetchPost() {
|
|
609
|
+
setLoading(true);
|
|
610
|
+
try {
|
|
611
|
+
const result = await client.query(BLOG_POST_QUERY, {
|
|
612
|
+
slug,
|
|
613
|
+
productId: resolvedProductId
|
|
614
|
+
});
|
|
615
|
+
if (result.errors?.length) {
|
|
616
|
+
setError(result.errors[0]?.message ?? "Failed to load post");
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
setPost(result.data?.publicContentPage ?? null);
|
|
620
|
+
setError(null);
|
|
621
|
+
} catch {
|
|
622
|
+
setError("Failed to load blog post");
|
|
623
|
+
} finally {
|
|
624
|
+
setLoading(false);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
fetchPost();
|
|
628
|
+
}, [client, slug, resolvedProductId]);
|
|
629
|
+
if (loading) {
|
|
630
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-full ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-24", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "animate-pulse space-y-6", children: [
|
|
631
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-8 bg-muted rounded w-2/3" }),
|
|
632
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-muted rounded w-1/3" }),
|
|
633
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-[16/9] bg-muted rounded-xl" }),
|
|
634
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-muted rounded" }, i)) })
|
|
635
|
+
] }) }) });
|
|
636
|
+
}
|
|
637
|
+
if (error || !post) {
|
|
638
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-full ${className}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-24 text-center", children: [
|
|
639
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-bold mb-4", children: "Post not found" }),
|
|
640
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground mb-6", children: error || "This blog post doesn't exist or has been removed." }),
|
|
641
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
642
|
+
"a",
|
|
643
|
+
{
|
|
644
|
+
href: blogListUrl,
|
|
645
|
+
className: "text-primary hover:underline font-medium",
|
|
646
|
+
children: "\u2190 Back to Blog"
|
|
647
|
+
}
|
|
648
|
+
)
|
|
649
|
+
] }) });
|
|
650
|
+
}
|
|
651
|
+
const date = post.publishedAt || post.lastUpdated;
|
|
652
|
+
const formattedDate = date ? new Date(date).toLocaleDateString("en-US", {
|
|
653
|
+
year: "numeric",
|
|
654
|
+
month: "long",
|
|
655
|
+
day: "numeric"
|
|
656
|
+
}) : "";
|
|
657
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `w-full ${className}`, children: [
|
|
658
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
659
|
+
PageHead,
|
|
660
|
+
{
|
|
661
|
+
title: post.seoTitle || post.title,
|
|
662
|
+
description: post.seoDescription || post.excerpt || "",
|
|
663
|
+
productName,
|
|
664
|
+
keywords: post.seoKeywords || ""
|
|
665
|
+
}
|
|
666
|
+
),
|
|
667
|
+
/* @__PURE__ */ jsxRuntime.jsxs("article", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-16 sm:py-20", children: [
|
|
668
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
669
|
+
"a",
|
|
670
|
+
{
|
|
671
|
+
href: blogListUrl,
|
|
672
|
+
className: "inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground mb-8 transition-colors",
|
|
673
|
+
children: "\u2190 Back to Blog"
|
|
674
|
+
}
|
|
675
|
+
),
|
|
676
|
+
post.category && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block text-xs font-medium text-primary bg-primary/10 px-2.5 py-1 rounded-full mb-4", children: post.category }),
|
|
677
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight text-foreground mb-4", children: post.title }),
|
|
678
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-sm text-muted-foreground mb-8", children: [
|
|
679
|
+
post.author && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-foreground", children: post.author }),
|
|
680
|
+
post.author && formattedDate && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
681
|
+
formattedDate && /* @__PURE__ */ jsxRuntime.jsx("span", { children: formattedDate }),
|
|
682
|
+
post.readingTime && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
683
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
684
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
685
|
+
post.readingTime,
|
|
686
|
+
" min read"
|
|
687
|
+
] })
|
|
688
|
+
] })
|
|
689
|
+
] }),
|
|
690
|
+
post.thumbnail && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-[16/9] rounded-xl overflow-hidden mb-10", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
691
|
+
"img",
|
|
692
|
+
{
|
|
693
|
+
src: post.thumbnail,
|
|
694
|
+
alt: post.title,
|
|
695
|
+
className: "w-full h-full object-cover"
|
|
696
|
+
}
|
|
697
|
+
) }),
|
|
698
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "prose prose-gray dark:prose-invert max-w-none", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
699
|
+
ContentRenderer,
|
|
700
|
+
{
|
|
701
|
+
content: post.content,
|
|
702
|
+
format: post.contentFormat
|
|
703
|
+
}
|
|
704
|
+
) })
|
|
705
|
+
] })
|
|
706
|
+
] });
|
|
707
|
+
}
|
|
306
708
|
|
|
709
|
+
exports.BlogListPage = BlogListPage;
|
|
710
|
+
exports.BlogPostPage = BlogPostPage;
|
|
307
711
|
exports.ContentRenderer = ContentRenderer;
|
|
308
712
|
exports.useContentPage = useContentPage;
|
|
309
713
|
exports.useContentPages = useContentPages;
|