@burdenoff/website-sdk 2026.516.13 → 2026.516.15

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.
@@ -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: Array<{
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
- export { type ContentPageData, type ContentPageListData, ContentRenderer, type UseContentPageOptions, useContentPage, useContentPages };
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 };
@@ -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: Array<{
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
- export { type ContentPageData, type ContentPageListData, ContentRenderer, type UseContentPageOptions, useContentPage, useContentPages };
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 };
@@ -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;