@fullstackdatasolutions/articles 0.4.3 → 0.5.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/dist/index.js CHANGED
@@ -91,7 +91,7 @@ function ArticleCategoryGrid({ categories, pageSize = 8 }) {
91
91
  }
92
92
 
93
93
  // src/ArticleSchemas.tsx
94
- import { jsx as jsx2 } from "react/jsx-runtime";
94
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
95
95
  function ArticleSchema({ article, articleUrl, siteName }) {
96
96
  const schema = __spreadProps(__spreadValues({
97
97
  "@context": "https://schema.org",
@@ -131,6 +131,86 @@ function BreadcrumbSchema({ items }) {
131
131
  }
132
132
  );
133
133
  }
134
+ function ArticleSEO({ article, articleUrl, siteName, siteLogo }) {
135
+ const publishedAt = article.date ? new Date(article.date).toISOString() : void 0;
136
+ const modifiedAt = article.lastmod ? new Date(article.lastmod).toISOString() : publishedAt;
137
+ const structuredData = __spreadValues(__spreadProps(__spreadValues(__spreadValues({
138
+ "@context": "https://schema.org",
139
+ "@type": article.articleType || "Article",
140
+ mainEntityOfPage: { "@type": "WebPage", "@id": articleUrl },
141
+ headline: article.title,
142
+ image: article.featuredImage ? { "@type": "ImageObject", url: article.featuredImage } : void 0
143
+ }, publishedAt && { datePublished: publishedAt }), modifiedAt && { dateModified: modifiedAt }), {
144
+ author: { "@type": "Person", name: article.author },
145
+ publisher: __spreadValues({
146
+ "@type": "Organization",
147
+ name: siteName
148
+ }, siteLogo && { logo: { "@type": "ImageObject", url: siteLogo } }),
149
+ description: article.excerpt
150
+ }), article.series && { isPartOf: { "@type": "Blog", name: article.series } });
151
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
152
+ /* @__PURE__ */ jsx2(
153
+ "script",
154
+ {
155
+ type: "application/ld+json",
156
+ dangerouslySetInnerHTML: { __html: JSON.stringify(structuredData) }
157
+ }
158
+ ),
159
+ article.faq && article.faq.length > 0 && /* @__PURE__ */ jsx2(
160
+ "script",
161
+ {
162
+ type: "application/ld+json",
163
+ dangerouslySetInnerHTML: {
164
+ __html: JSON.stringify({
165
+ "@context": "https://schema.org",
166
+ "@type": "FAQPage",
167
+ mainEntity: article.faq.map(({ question, answer }) => ({
168
+ "@type": "Question",
169
+ name: question,
170
+ acceptedAnswer: { "@type": "Answer", text: answer }
171
+ }))
172
+ })
173
+ }
174
+ }
175
+ ),
176
+ article.howTo && article.howTo.length > 0 && /* @__PURE__ */ jsx2(
177
+ "script",
178
+ {
179
+ type: "application/ld+json",
180
+ dangerouslySetInnerHTML: {
181
+ __html: JSON.stringify({
182
+ "@context": "https://schema.org",
183
+ "@type": "HowTo",
184
+ name: article.title,
185
+ step: article.howTo.map(({ name, text }) => ({
186
+ "@type": "HowToStep",
187
+ name,
188
+ text
189
+ }))
190
+ })
191
+ }
192
+ }
193
+ )
194
+ ] });
195
+ }
196
+ function FAQPageSchema({ items }) {
197
+ const schema = {
198
+ "@context": "https://schema.org",
199
+ "@type": "FAQPage",
200
+ mainEntity: items.map(({ question, answer }) => ({
201
+ "@type": "Question",
202
+ name: question,
203
+ acceptedAnswer: { "@type": "Answer", text: answer }
204
+ }))
205
+ };
206
+ return /* @__PURE__ */ jsx2(
207
+ "script",
208
+ {
209
+ type: "application/ld+json",
210
+ dangerouslySetInnerHTML: { __html: JSON.stringify(schema) }
211
+ }
212
+ );
213
+ }
134
214
  function CollectionPageSchema({
135
215
  title,
136
216
  description,
@@ -156,15 +236,15 @@ function CollectionPageSchema({
156
236
 
157
237
  // src/ArticleSearchBar.tsx
158
238
  import { Search, X } from "lucide-react";
159
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
239
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
160
240
  function ArticleSearchBar({
161
241
  value,
162
242
  onChange,
163
243
  disabled,
164
244
  resultCount
165
245
  }) {
166
- return /* @__PURE__ */ jsx3("section", { className: "py-8 bg-background border-b border-border", children: /* @__PURE__ */ jsxs2("div", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8", children: [
167
- /* @__PURE__ */ jsxs2("div", { className: "relative", children: [
246
+ return /* @__PURE__ */ jsx3("section", { className: "py-8 bg-background border-b border-border", children: /* @__PURE__ */ jsxs3("div", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8", children: [
247
+ /* @__PURE__ */ jsxs3("div", { className: "relative", children: [
168
248
  /* @__PURE__ */ jsx3(Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground h-5 w-5" }),
169
249
  /* @__PURE__ */ jsx3(
170
250
  "input",
@@ -194,17 +274,17 @@ function ArticleSearchBar({
194
274
 
195
275
  // src/ArticlesHero.tsx
196
276
  import Link2 from "next/link";
197
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
277
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
198
278
  var DEFAULT_TITLE = "Vox Populus Insights";
199
279
  var DEFAULT_DESCRIPTION = "Expert analysis, campaign strategies, and voter engagement insights from the frontlines of democracy.";
200
280
  function ArticlesHero({
201
281
  title = DEFAULT_TITLE,
202
282
  description = DEFAULT_DESCRIPTION
203
283
  }) {
204
- return /* @__PURE__ */ jsx4("section", { className: "bg-linear-to-r from-gray-50 to-gray-100 py-16 md:py-24", children: /* @__PURE__ */ jsx4("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxs3("div", { className: "max-w-3xl mx-auto text-center", children: [
284
+ return /* @__PURE__ */ jsx4("section", { className: "bg-linear-to-r from-gray-50 to-gray-100 py-16 md:py-24", children: /* @__PURE__ */ jsx4("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxs4("div", { className: "max-w-3xl mx-auto text-center", children: [
205
285
  /* @__PURE__ */ jsx4("h1", { className: "text-4xl md:text-5xl font-bold text-foreground mb-6", children: title }),
206
286
  /* @__PURE__ */ jsx4("p", { className: "text-xl text-muted-foreground mb-8", children: description }),
207
- /* @__PURE__ */ jsxs3("div", { className: "flex flex-col sm:flex-row gap-4 justify-center", children: [
287
+ /* @__PURE__ */ jsxs4("div", { className: "flex flex-col sm:flex-row gap-4 justify-center", children: [
208
288
  /* @__PURE__ */ jsx4(
209
289
  Link2,
210
290
  {
@@ -229,28 +309,28 @@ function ArticlesHero({
229
309
  import Link3 from "next/link";
230
310
  import Image2 from "next/image";
231
311
  import { ArrowRight, Calendar, Clock, User } from "lucide-react";
232
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
312
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
233
313
  function FeaturedArticle({ article }) {
234
- return /* @__PURE__ */ jsx5("section", { className: "py-16 bg-background", children: /* @__PURE__ */ jsx5("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxs4("div", { className: "grid lg:grid-cols-2 gap-12 items-center", children: [
235
- /* @__PURE__ */ jsxs4("div", { children: [
314
+ return /* @__PURE__ */ jsx5("section", { className: "py-16 bg-background", children: /* @__PURE__ */ jsx5("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxs5("div", { className: "grid lg:grid-cols-2 gap-12 items-center", children: [
315
+ /* @__PURE__ */ jsxs5("div", { children: [
236
316
  /* @__PURE__ */ jsx5("span", { className: "inline-block bg-primary/10 text-primary text-sm font-medium px-3 py-1 rounded-full mb-4", children: "FEATURED ARTICLE" }),
237
317
  /* @__PURE__ */ jsx5("h2", { className: "text-3xl font-bold text-foreground mb-4", children: article.title }),
238
318
  /* @__PURE__ */ jsx5("p", { className: "text-lg text-muted-foreground mb-6", children: article.excerpt }),
239
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-6 text-sm text-muted-foreground mb-6", children: [
240
- article.date && /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
319
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-6 text-sm text-muted-foreground mb-6", children: [
320
+ article.date && /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
241
321
  /* @__PURE__ */ jsx5(Calendar, { className: "h-4 w-4" }),
242
322
  /* @__PURE__ */ jsx5("span", { children: article.date })
243
323
  ] }),
244
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
324
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
245
325
  /* @__PURE__ */ jsx5(Clock, { className: "h-4 w-4" }),
246
326
  /* @__PURE__ */ jsx5("span", { children: article.readTime })
247
327
  ] }),
248
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
328
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
249
329
  /* @__PURE__ */ jsx5(User, { className: "h-4 w-4" }),
250
330
  /* @__PURE__ */ jsx5("span", { children: article.author })
251
331
  ] })
252
332
  ] }),
253
- /* @__PURE__ */ jsxs4(
333
+ /* @__PURE__ */ jsxs5(
254
334
  Link3,
255
335
  {
256
336
  href: `/articles/${article.slug}`,
@@ -262,7 +342,7 @@ function FeaturedArticle({ article }) {
262
342
  }
263
343
  )
264
344
  ] }),
265
- /* @__PURE__ */ jsxs4("div", { className: "bg-card rounded-lg p-8", children: [
345
+ /* @__PURE__ */ jsxs5("div", { className: "bg-card rounded-lg p-8", children: [
266
346
  /* @__PURE__ */ jsx5(
267
347
  Image2,
268
348
  {
@@ -288,9 +368,9 @@ import { useState as useState2, useEffect as useEffect2 } from "react";
288
368
  import Image3 from "next/image";
289
369
  import Link4 from "next/link";
290
370
  import { ArrowRight as ArrowRight2, Calendar as Calendar2, Clock as Clock2 } from "lucide-react";
291
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
371
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
292
372
  function ArticleCard({ article }) {
293
- return /* @__PURE__ */ jsxs5("div", { className: "rounded-lg border border-border bg-card text-card-foreground shadow-sm hover:shadow-lg transition-shadow duration-300", children: [
373
+ return /* @__PURE__ */ jsxs6("div", { className: "rounded-lg border border-border bg-card text-card-foreground shadow-sm hover:shadow-lg transition-shadow duration-300", children: [
294
374
  /* @__PURE__ */ jsx6("div", { className: "p-0", children: /* @__PURE__ */ jsx6(
295
375
  Image3,
296
376
  {
@@ -301,7 +381,7 @@ function ArticleCard({ article }) {
301
381
  height: 200
302
382
  }
303
383
  ) }),
304
- /* @__PURE__ */ jsxs5("div", { className: "p-6", children: [
384
+ /* @__PURE__ */ jsxs6("div", { className: "p-6", children: [
305
385
  /* @__PURE__ */ jsx6("div", { className: "flex gap-2 mb-3", children: /* @__PURE__ */ jsx6("span", { className: "bg-primary/10 text-primary text-xs font-medium px-2 py-1 rounded", children: article.category }) }),
306
386
  /* @__PURE__ */ jsx6("h3", { className: "text-lg font-semibold leading-none tracking-tight mb-2", children: /* @__PURE__ */ jsx6(
307
387
  Link4,
@@ -312,13 +392,13 @@ function ArticleCard({ article }) {
312
392
  }
313
393
  ) }),
314
394
  /* @__PURE__ */ jsx6("p", { className: "text-muted-foreground mb-4 line-clamp-3", children: article.excerpt }),
315
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between text-sm text-muted-foreground border-t pt-4", children: [
316
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-3", children: [
317
- article.date && /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
395
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between text-sm text-muted-foreground border-t pt-4", children: [
396
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3", children: [
397
+ article.date && /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
318
398
  /* @__PURE__ */ jsx6(Calendar2, { className: "h-3 w-3" }),
319
399
  /* @__PURE__ */ jsx6("span", { children: article.date })
320
400
  ] }),
321
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
401
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
322
402
  /* @__PURE__ */ jsx6(Clock2, { className: "h-3 w-3" }),
323
403
  /* @__PURE__ */ jsx6("span", { children: article.readTime })
324
404
  ] })
@@ -338,7 +418,7 @@ function ArticleCard({ article }) {
338
418
  }
339
419
 
340
420
  // src/LatestArticles.tsx
341
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
421
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
342
422
  function LatestArticles({ articles, pageSize }) {
343
423
  const [visibleCount, setVisibleCount] = useState2(pageSize);
344
424
  useEffect2(() => {
@@ -346,7 +426,7 @@ function LatestArticles({ articles, pageSize }) {
346
426
  }, [articles, pageSize]);
347
427
  const visible = articles.slice(0, visibleCount);
348
428
  const hasMore = visibleCount < articles.length;
349
- return /* @__PURE__ */ jsxs6("div", { children: [
429
+ return /* @__PURE__ */ jsxs7("div", { children: [
350
430
  /* @__PURE__ */ jsx7("div", { className: "grid md:grid-cols-2 lg:grid-cols-3 gap-8", children: visible.map((article) => /* @__PURE__ */ jsx7(ArticleCard, { article }, article.slug)) }),
351
431
  hasMore && /* @__PURE__ */ jsx7("div", { className: "mt-10 text-center", children: /* @__PURE__ */ jsx7(
352
432
  "button",
@@ -361,7 +441,7 @@ function LatestArticles({ articles, pageSize }) {
361
441
  }
362
442
 
363
443
  // src/LatestArticlesSection.tsx
364
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
444
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
365
445
  function DescriptionText({
366
446
  searchQuery,
367
447
  count
@@ -376,15 +456,15 @@ function LatestArticlesSection({
376
456
  onClearSearch,
377
457
  pageSize = 6
378
458
  }) {
379
- return /* @__PURE__ */ jsx8("section", { id: "latest", className: "py-16 bg-muted/50", children: /* @__PURE__ */ jsxs7("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: [
380
- /* @__PURE__ */ jsxs7("div", { className: "text-center mb-12", children: [
459
+ return /* @__PURE__ */ jsx8("section", { id: "latest", className: "py-16 bg-muted/50", children: /* @__PURE__ */ jsxs8("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: [
460
+ /* @__PURE__ */ jsxs8("div", { className: "text-center mb-12", children: [
381
461
  /* @__PURE__ */ jsx8("h2", { className: "text-3xl font-bold text-foreground mb-4", children: searchQuery ? "Search Results" : "Latest Articles" }),
382
462
  /* @__PURE__ */ jsx8(DescriptionText, { searchQuery, count: articles.length })
383
463
  ] }),
384
- articles.length === 0 && searchQuery ? /* @__PURE__ */ jsx8("div", { className: "text-center py-12", children: /* @__PURE__ */ jsxs7("div", { className: "max-w-md mx-auto", children: [
464
+ articles.length === 0 && searchQuery ? /* @__PURE__ */ jsx8("div", { className: "text-center py-12", children: /* @__PURE__ */ jsxs8("div", { className: "max-w-md mx-auto", children: [
385
465
  /* @__PURE__ */ jsx8(Search2, { className: "h-12 w-12 text-muted-foreground mx-auto mb-4" }),
386
466
  /* @__PURE__ */ jsx8("h3", { className: "text-lg font-semibold text-foreground mb-2", children: "No articles found" }),
387
- /* @__PURE__ */ jsxs7("p", { className: "text-muted-foreground mb-4", children: [
467
+ /* @__PURE__ */ jsxs8("p", { className: "text-muted-foreground mb-4", children: [
388
468
  `We couldn't find any articles matching "`,
389
469
  searchQuery,
390
470
  '". Try adjusting your search terms.'
@@ -482,7 +562,7 @@ function useArticles() {
482
562
  }
483
563
 
484
564
  // src/ArticlesPage.tsx
485
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
565
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
486
566
  function buildThemeVars(theme) {
487
567
  if (!theme) return {};
488
568
  const vars = {};
@@ -538,13 +618,13 @@ function renderSection(section, ctx, config) {
538
618
  return articles.length > 0 && !searchQuery ? /* @__PURE__ */ jsx9(FeaturedArticle, { article: articles[0] }, "featured") : null;
539
619
  case "latest":
540
620
  if (loading && articles.length === 0) {
541
- return /* @__PURE__ */ jsx9("section", { id: "latest", className: "py-16 bg-muted/50 flex-1", children: /* @__PURE__ */ jsx9("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex items-center justify-center py-24", children: /* @__PURE__ */ jsxs8("div", { className: "text-center", children: [
621
+ return /* @__PURE__ */ jsx9("section", { id: "latest", className: "py-16 bg-muted/50 flex-1", children: /* @__PURE__ */ jsx9("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex items-center justify-center py-24", children: /* @__PURE__ */ jsxs9("div", { className: "text-center", children: [
542
622
  /* @__PURE__ */ jsx9("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-primary mx-auto mb-4" }),
543
623
  /* @__PURE__ */ jsx9("p", { className: "text-muted-foreground", children: "Loading articles..." })
544
624
  ] }) }) }, "latest");
545
625
  }
546
626
  if (error) {
547
- return /* @__PURE__ */ jsx9("section", { id: "latest", className: "py-16 bg-muted/50 flex-1", children: /* @__PURE__ */ jsx9("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex items-center justify-center", children: /* @__PURE__ */ jsxs8("div", { className: "bg-red-50 border border-red-200 rounded-lg p-6 max-w-md text-center", children: [
627
+ return /* @__PURE__ */ jsx9("section", { id: "latest", className: "py-16 bg-muted/50 flex-1", children: /* @__PURE__ */ jsx9("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex items-center justify-center", children: /* @__PURE__ */ jsxs9("div", { className: "bg-red-50 border border-red-200 rounded-lg p-6 max-w-md text-center", children: [
548
628
  /* @__PURE__ */ jsx9("h3", { className: "text-lg font-semibold text-red-800 mb-2", children: "Error Loading Articles" }),
549
629
  /* @__PURE__ */ jsx9("p", { className: "text-red-600 mb-4", children: error }),
550
630
  /* @__PURE__ */ jsx9(
@@ -593,7 +673,7 @@ function ArticlesPage({ config }) {
593
673
  const articlesWithoutFeatured = hasFeatured ? state.articles.slice(1) : state.articles;
594
674
  const displayedArticles = state.searchQuery ? state.articles : articlesWithoutFeatured;
595
675
  const ctx = __spreadProps(__spreadValues({}, state), { displayedArticles, pageSize, categoriesPageSize });
596
- return /* @__PURE__ */ jsxs8("div", { style: themeVars, children: [
676
+ return /* @__PURE__ */ jsxs9("div", { style: themeVars, children: [
597
677
  layout.map((section) => renderSection(section, ctx, config)),
598
678
  state.articles.length > 0 && /* @__PURE__ */ jsx9(
599
679
  CollectionPageSchema,
@@ -611,7 +691,7 @@ function ArticlesPage({ config }) {
611
691
  import Image4 from "next/image";
612
692
  import Link5 from "next/link";
613
693
  import { Calendar as Calendar3, Clock as Clock3, User as User2 } from "lucide-react";
614
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
694
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
615
695
  function toSlug(cat) {
616
696
  return cat.toLowerCase().replaceAll(/\s+/g, "-").replaceAll(/[^a-z0-9-]/g, "");
617
697
  }
@@ -620,7 +700,7 @@ function ArticleDetailHero({
620
700
  categoryBasePath = "/articles/category",
621
701
  showDate = false
622
702
  }) {
623
- return /* @__PURE__ */ jsxs9(
703
+ return /* @__PURE__ */ jsxs10(
624
704
  "section",
625
705
  {
626
706
  style: {
@@ -654,7 +734,7 @@ function ArticleDetailHero({
654
734
  }
655
735
  }
656
736
  ),
657
- /* @__PURE__ */ jsxs9(
737
+ /* @__PURE__ */ jsxs10(
658
738
  "div",
659
739
  {
660
740
  style: {
@@ -699,7 +779,7 @@ function ArticleDetailHero({
699
779
  }
700
780
  ),
701
781
  /* @__PURE__ */ jsx10("h1", { className: "text-4xl md:text-5xl font-bold mb-4", children: article.title }),
702
- /* @__PURE__ */ jsxs9(
782
+ /* @__PURE__ */ jsxs10(
703
783
  "div",
704
784
  {
705
785
  style: {
@@ -711,17 +791,17 @@ function ArticleDetailHero({
711
791
  color: "rgba(255,255,255,0.8)"
712
792
  },
713
793
  children: [
714
- showDate && article.date && /* @__PURE__ */ jsxs9("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
794
+ showDate && article.date && /* @__PURE__ */ jsxs10("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
715
795
  /* @__PURE__ */ jsx10(Calendar3, { className: "h-4 w-4" }),
716
796
  /* @__PURE__ */ jsx10("span", { children: article.date })
717
797
  ] }),
718
- /* @__PURE__ */ jsxs9("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
798
+ /* @__PURE__ */ jsxs10("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
719
799
  /* @__PURE__ */ jsx10(Clock3, { className: "h-4 w-4" }),
720
800
  /* @__PURE__ */ jsx10("span", { children: article.readTime })
721
801
  ] }),
722
- /* @__PURE__ */ jsxs9("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
802
+ /* @__PURE__ */ jsxs10("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
723
803
  /* @__PURE__ */ jsx10(User2, { className: "h-4 w-4" }),
724
- /* @__PURE__ */ jsxs9("span", { children: [
804
+ /* @__PURE__ */ jsxs10("span", { children: [
725
805
  "By ",
726
806
  article.author
727
807
  ] })
@@ -740,7 +820,7 @@ function ArticleDetailHero({
740
820
  // src/CategoryArticlesPage.tsx
741
821
  import Image5 from "next/image";
742
822
  import Link6 from "next/link";
743
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
823
+ import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
744
824
  function getCategoryDescription(config, slug, categoryName) {
745
825
  var _a;
746
826
  const raw = (_a = config.categoryDescriptions) == null ? void 0 : _a[slug];
@@ -756,7 +836,7 @@ function CategoryArticlesPage({ category, articles, config }) {
756
836
  const description = getCategoryDescription(config, category, categoryName);
757
837
  const pageSize = (_a = config.pageSize) != null ? _a : DEFAULT_PAGE_SIZE;
758
838
  const siteUrl = config.siteUrl.replace(/\/$/, "");
759
- return /* @__PURE__ */ jsxs10("div", { children: [
839
+ return /* @__PURE__ */ jsxs11("div", { children: [
760
840
  /* @__PURE__ */ jsx11(
761
841
  BreadcrumbSchema,
762
842
  {
@@ -767,7 +847,7 @@ function CategoryArticlesPage({ category, articles, config }) {
767
847
  ]
768
848
  }
769
849
  ),
770
- /* @__PURE__ */ jsxs10(
850
+ /* @__PURE__ */ jsxs11(
771
851
  "section",
772
852
  {
773
853
  style: {
@@ -791,7 +871,7 @@ function CategoryArticlesPage({ category, articles, config }) {
791
871
  }
792
872
  ),
793
873
  /* @__PURE__ */ jsx11("div", { style: { position: "absolute", inset: 0, backgroundColor: "rgba(0,0,0,0.6)" } }),
794
- /* @__PURE__ */ jsxs10(
874
+ /* @__PURE__ */ jsxs11(
795
875
  "div",
796
876
  {
797
877
  style: {
@@ -805,7 +885,7 @@ function CategoryArticlesPage({ category, articles, config }) {
805
885
  /* @__PURE__ */ jsx11("p", { className: "text-sm font-semibold uppercase tracking-widest mb-3 opacity-80", children: "Category" }),
806
886
  /* @__PURE__ */ jsx11("h1", { className: "text-4xl md:text-5xl font-bold mb-3", children: categoryName }),
807
887
  description.long && /* @__PURE__ */ jsx11("p", { className: "text-lg opacity-90 max-w-2xl mx-auto mt-2", children: description.long }),
808
- /* @__PURE__ */ jsxs10("p", { className: "text-lg opacity-70 mt-2", children: [
888
+ /* @__PURE__ */ jsxs11("p", { className: "text-lg opacity-70 mt-2", children: [
809
889
  articles.length,
810
890
  " article",
811
891
  articles.length === 1 ? "" : "s"
@@ -816,8 +896,8 @@ function CategoryArticlesPage({ category, articles, config }) {
816
896
  ]
817
897
  }
818
898
  ),
819
- /* @__PURE__ */ jsx11("section", { className: "py-16 bg-muted/50 flex-1", children: /* @__PURE__ */ jsxs10("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: [
820
- /* @__PURE__ */ jsxs10("div", { className: "mb-8 flex items-center justify-between", children: [
899
+ /* @__PURE__ */ jsx11("section", { className: "py-16 bg-muted/50 flex-1", children: /* @__PURE__ */ jsxs11("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: [
900
+ /* @__PURE__ */ jsxs11("div", { className: "mb-8 flex items-center justify-between", children: [
821
901
  /* @__PURE__ */ jsx11(Link6, { href: "/articles", className: "text-sm text-primary hover:underline", children: "\u2190 All Articles" }),
822
902
  /* @__PURE__ */ jsx11("p", { className: "text-sm text-muted-foreground", children: description.short })
823
903
  ] }),
@@ -829,7 +909,7 @@ function CategoryArticlesPage({ category, articles, config }) {
829
909
  // src/ArticleSocialShare.tsx
830
910
  import { useState as useState4 } from "react";
831
911
  import { Share2, Copy, Check, Mail, MessageCircle, Users, FileText } from "lucide-react";
832
- import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
912
+ import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
833
913
  function ArticleSocialShare({ title, url, excerpt, shareMessage }) {
834
914
  const [copied, setCopied] = useState4(false);
835
915
  const encodedTitle = encodeURIComponent(title);
@@ -853,40 +933,40 @@ function ArticleSocialShare({ title, url, excerpt, shareMessage }) {
853
933
  }
854
934
  });
855
935
  const openShareWindow = (shareUrl) => {
856
- window.open(shareUrl, "_blank", "width=600,height=400,scrollbars=yes,resizable=yes");
936
+ globalThis.open(shareUrl, "_blank", "width=600,height=400,scrollbars=yes,resizable=yes");
857
937
  };
858
938
  const btnClass = "inline-flex items-center gap-2 px-3 py-1.5 text-sm rounded-md border border-border bg-background text-foreground hover:bg-primary/10 hover:border-primary hover:text-primary transition-colors cursor-pointer";
859
- return /* @__PURE__ */ jsxs11("div", { className: "border-t border-border pt-8 mt-8", children: [
860
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 mb-4", children: [
939
+ return /* @__PURE__ */ jsxs12("div", { className: "border-t border-border pt-8 mt-8", children: [
940
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2 mb-4", children: [
861
941
  /* @__PURE__ */ jsx12(Share2, { className: "h-5 w-5 text-muted-foreground" }),
862
942
  /* @__PURE__ */ jsx12("h3", { className: "text-lg font-semibold text-foreground", children: "Share this article" })
863
943
  ] }),
864
- /* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap gap-2", children: [
865
- /* @__PURE__ */ jsxs11("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.linkedin), children: [
944
+ /* @__PURE__ */ jsxs12("div", { className: "flex flex-wrap gap-2", children: [
945
+ /* @__PURE__ */ jsxs12("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.linkedin), children: [
866
946
  /* @__PURE__ */ jsx12(Users, { className: "h-4 w-4" }),
867
947
  "LinkedIn"
868
948
  ] }),
869
- /* @__PURE__ */ jsxs11("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.facebook), children: [
949
+ /* @__PURE__ */ jsxs12("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.facebook), children: [
870
950
  /* @__PURE__ */ jsx12("span", { className: "text-xs font-bold", children: "f" }),
871
951
  " Facebook"
872
952
  ] }),
873
- /* @__PURE__ */ jsxs11("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.twitter), children: [
953
+ /* @__PURE__ */ jsxs12("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.twitter), children: [
874
954
  /* @__PURE__ */ jsx12(MessageCircle, { className: "h-4 w-4" }),
875
955
  "Twitter"
876
956
  ] }),
877
- /* @__PURE__ */ jsxs11("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.reddit), children: [
957
+ /* @__PURE__ */ jsxs12("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.reddit), children: [
878
958
  /* @__PURE__ */ jsx12(FileText, { className: "h-4 w-4" }),
879
959
  "Reddit"
880
960
  ] }),
881
- /* @__PURE__ */ jsxs11("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.whatsapp), children: [
961
+ /* @__PURE__ */ jsxs12("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.whatsapp), children: [
882
962
  /* @__PURE__ */ jsx12(MessageCircle, { className: "h-4 w-4" }),
883
963
  "WhatsApp"
884
964
  ] }),
885
- /* @__PURE__ */ jsxs11("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.telegram), children: [
965
+ /* @__PURE__ */ jsxs12("button", { className: btnClass, onClick: () => openShareWindow(shareLinks.telegram), children: [
886
966
  /* @__PURE__ */ jsx12(MessageCircle, { className: "h-4 w-4" }),
887
967
  "Telegram"
888
968
  ] }),
889
- /* @__PURE__ */ jsxs11(
969
+ /* @__PURE__ */ jsxs12(
890
970
  "button",
891
971
  {
892
972
  className: btnClass,
@@ -899,7 +979,7 @@ function ArticleSocialShare({ title, url, excerpt, shareMessage }) {
899
979
  ]
900
980
  }
901
981
  ),
902
- /* @__PURE__ */ jsxs11("button", { className: btnClass, onClick: copyToClipboard, children: [
982
+ /* @__PURE__ */ jsxs12("button", { className: btnClass, onClick: copyToClipboard, children: [
903
983
  copied ? /* @__PURE__ */ jsx12(Check, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx12(Copy, { className: "h-4 w-4" }),
904
984
  copied ? "Copied!" : "Copy Link"
905
985
  ] })
@@ -911,34 +991,34 @@ function ArticleSocialShare({ title, url, excerpt, shareMessage }) {
911
991
  // src/ArticleNavigation.tsx
912
992
  import Link7 from "next/link";
913
993
  import { ChevronLeft, ChevronRight } from "lucide-react";
914
- import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
994
+ import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
915
995
  function truncateTitle(title, maxLength = 60) {
916
996
  return title.length > maxLength ? `${title.substring(0, maxLength)}...` : title;
917
997
  }
918
998
  function ArticleNavigation({ previous, next, basePath }) {
919
999
  if (!previous && !next) return null;
920
- return /* @__PURE__ */ jsx13("nav", { className: "mt-12 pt-8 border-t border-border", "aria-label": "Article navigation", children: /* @__PURE__ */ jsxs12("div", { className: "flex justify-between gap-4", children: [
921
- /* @__PURE__ */ jsx13("div", { className: "flex-1 min-w-0", children: previous && /* @__PURE__ */ jsxs12(
1000
+ return /* @__PURE__ */ jsx13("nav", { className: "mt-12 pt-8 border-t border-border", "aria-label": "Article navigation", children: /* @__PURE__ */ jsxs13("div", { className: "flex justify-between gap-4", children: [
1001
+ /* @__PURE__ */ jsx13("div", { className: "flex-1 min-w-0", children: previous && /* @__PURE__ */ jsxs13(
922
1002
  Link7,
923
1003
  {
924
1004
  href: `${basePath}/${previous.slug}`,
925
1005
  className: "group flex items-center gap-3 p-4 rounded-lg border border-border hover:border-primary/20 hover:bg-muted/50 transition-colors",
926
1006
  children: [
927
1007
  /* @__PURE__ */ jsx13(ChevronLeft, { className: "h-5 w-5 text-muted-foreground group-hover:text-primary shrink-0" }),
928
- /* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1", children: [
1008
+ /* @__PURE__ */ jsxs13("div", { className: "min-w-0 flex-1", children: [
929
1009
  /* @__PURE__ */ jsx13("div", { className: "text-sm text-muted-foreground mb-1", children: "Previous Article" }),
930
1010
  /* @__PURE__ */ jsx13("div", { className: "font-medium text-foreground truncate", title: previous.title, children: truncateTitle(previous.title) })
931
1011
  ] })
932
1012
  ]
933
1013
  }
934
1014
  ) }),
935
- /* @__PURE__ */ jsx13("div", { className: "flex-1 min-w-0", children: next && /* @__PURE__ */ jsxs12(
1015
+ /* @__PURE__ */ jsx13("div", { className: "flex-1 min-w-0", children: next && /* @__PURE__ */ jsxs13(
936
1016
  Link7,
937
1017
  {
938
1018
  href: `${basePath}/${next.slug}`,
939
1019
  className: "group flex items-center justify-end gap-3 p-4 rounded-lg border border-border hover:border-primary/20 hover:bg-muted/50 transition-colors",
940
1020
  children: [
941
- /* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1 text-right", children: [
1021
+ /* @__PURE__ */ jsxs13("div", { className: "min-w-0 flex-1 text-right", children: [
942
1022
  /* @__PURE__ */ jsx13("div", { className: "text-sm text-muted-foreground mb-1", children: "Next Article" }),
943
1023
  /* @__PURE__ */ jsx13("div", { className: "font-medium text-foreground truncate", title: next.title, children: truncateTitle(next.title) })
944
1024
  ] }),
@@ -949,13 +1029,60 @@ function ArticleNavigation({ previous, next, basePath }) {
949
1029
  ] }) });
950
1030
  }
951
1031
 
1032
+ // src/ArticleTOC.tsx
1033
+ import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
1034
+ function ArticleTOC({ toc, className }) {
1035
+ if (!toc.length) return null;
1036
+ return /* @__PURE__ */ jsxs14(
1037
+ "nav",
1038
+ {
1039
+ "aria-label": "Table of contents",
1040
+ className: `mb-8 rounded-lg border border-border bg-muted/40 px-6 py-4 ${className != null ? className : ""}`,
1041
+ children: [
1042
+ /* @__PURE__ */ jsx14("p", { className: "mb-3 text-sm font-semibold uppercase tracking-wide text-muted-foreground", children: "On this page" }),
1043
+ /* @__PURE__ */ jsx14("ul", { className: "space-y-1 text-sm", children: toc.map((item) => /* @__PURE__ */ jsx14("li", { style: { paddingLeft: `${Math.max(0, item.depth - 2) * 1}rem` }, children: /* @__PURE__ */ jsx14(
1044
+ "a",
1045
+ {
1046
+ href: `#${item.id}`,
1047
+ className: "text-muted-foreground hover:text-foreground transition-colors",
1048
+ children: item.text
1049
+ }
1050
+ ) }, item.id)) })
1051
+ ]
1052
+ }
1053
+ );
1054
+ }
1055
+
1056
+ // src/ScrollToTop.tsx
1057
+ import { useEffect as useEffect4, useState as useState5 } from "react";
1058
+ import { ArrowUp } from "lucide-react";
1059
+ import { jsx as jsx15 } from "react/jsx-runtime";
1060
+ function ScrollToTop() {
1061
+ const [visible, setVisible] = useState5(false);
1062
+ useEffect4(() => {
1063
+ const onScroll = () => setVisible(globalThis.scrollY > 300);
1064
+ globalThis.addEventListener("scroll", onScroll, { passive: true });
1065
+ return () => globalThis.removeEventListener("scroll", onScroll);
1066
+ }, []);
1067
+ if (!visible) return null;
1068
+ return /* @__PURE__ */ jsx15(
1069
+ "button",
1070
+ {
1071
+ "aria-label": "Scroll to top",
1072
+ onClick: () => globalThis.scrollTo({ top: 0, behavior: "smooth" }),
1073
+ className: "fixed bottom-8 right-8 z-50 rounded-full bg-primary p-2 shadow-md text-primary-foreground hover:bg-primary/90 transition-colors",
1074
+ children: /* @__PURE__ */ jsx15(ArrowUp, { className: "h-5 w-5" })
1075
+ }
1076
+ );
1077
+ }
1078
+
952
1079
  // src/CommentsSection.tsx
953
1080
  import { useSession, signIn } from "next-auth/react";
954
- import { useCallback as useCallback2, useEffect as useEffect4, useState as useState7 } from "react";
1081
+ import { useCallback as useCallback2, useEffect as useEffect5, useState as useState8 } from "react";
955
1082
 
956
1083
  // src/CommentForm.tsx
957
- import { useState as useState5 } from "react";
958
- import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
1084
+ import { useState as useState6 } from "react";
1085
+ import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
959
1086
  var MAX_LENGTH = 2e3;
960
1087
  var WARN_THRESHOLD = 1800;
961
1088
  function submitLabel(submitting, parentId) {
@@ -963,9 +1090,9 @@ function submitLabel(submitting, parentId) {
963
1090
  return parentId ? "Reply" : "Post comment";
964
1091
  }
965
1092
  function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
966
- const [body, setBody] = useState5("");
967
- const [submitting, setSubmitting] = useState5(false);
968
- const [error, setError] = useState5(null);
1093
+ const [body, setBody] = useState6("");
1094
+ const [submitting, setSubmitting] = useState6(false);
1095
+ const [error, setError] = useState6(null);
969
1096
  const remaining = MAX_LENGTH - body.length;
970
1097
  function handleSubmit(e) {
971
1098
  return __async(this, null, function* () {
@@ -994,8 +1121,8 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
994
1121
  }
995
1122
  });
996
1123
  }
997
- return /* @__PURE__ */ jsxs13("form", { onSubmit: handleSubmit, className: "space-y-2", children: [
998
- /* @__PURE__ */ jsx14(
1124
+ return /* @__PURE__ */ jsxs15("form", { onSubmit: handleSubmit, className: "space-y-2", children: [
1125
+ /* @__PURE__ */ jsx16(
999
1126
  "textarea",
1000
1127
  {
1001
1128
  value: body,
@@ -1008,13 +1135,13 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
1008
1135
  "aria-label": parentId ? "Reply text" : "Comment text"
1009
1136
  }
1010
1137
  ),
1011
- remaining <= MAX_LENGTH - WARN_THRESHOLD && /* @__PURE__ */ jsxs13("p", { className: `text-xs ${remaining < 0 ? "text-destructive" : "text-muted-foreground"}`, children: [
1138
+ remaining <= MAX_LENGTH - WARN_THRESHOLD && /* @__PURE__ */ jsxs15("p", { className: `text-xs ${remaining < 0 ? "text-destructive" : "text-muted-foreground"}`, children: [
1012
1139
  remaining,
1013
1140
  " characters remaining"
1014
1141
  ] }),
1015
- error && /* @__PURE__ */ jsx14("p", { className: "text-xs text-destructive", children: error }),
1016
- /* @__PURE__ */ jsxs13("div", { className: "flex gap-2", children: [
1017
- /* @__PURE__ */ jsx14(
1142
+ error && /* @__PURE__ */ jsx16("p", { className: "text-xs text-destructive", children: error }),
1143
+ /* @__PURE__ */ jsxs15("div", { className: "flex gap-2", children: [
1144
+ /* @__PURE__ */ jsx16(
1018
1145
  "button",
1019
1146
  {
1020
1147
  type: "submit",
@@ -1023,7 +1150,7 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
1023
1150
  children: submitLabel(submitting, parentId)
1024
1151
  }
1025
1152
  ),
1026
- onCancel && /* @__PURE__ */ jsx14(
1153
+ onCancel && /* @__PURE__ */ jsx16(
1027
1154
  "button",
1028
1155
  {
1029
1156
  type: "button",
@@ -1037,8 +1164,8 @@ function CommentForm({ articleSlug, parentId, onSuccess, onCancel }) {
1037
1164
  }
1038
1165
 
1039
1166
  // src/CommentItem.tsx
1040
- import { useState as useState6 } from "react";
1041
- import { Fragment, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
1167
+ import { useState as useState7 } from "react";
1168
+ import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
1042
1169
  function relativeTime(iso) {
1043
1170
  const diff = Date.now() - new Date(iso).getTime();
1044
1171
  const minutes = Math.floor(diff / 6e4);
@@ -1059,8 +1186,8 @@ function CommentItem({
1059
1186
  isReply = false,
1060
1187
  onRefresh
1061
1188
  }) {
1062
- const [showReplyForm, setShowReplyForm] = useState6(false);
1063
- const [deleting, setDeleting] = useState6(false);
1189
+ const [showReplyForm, setShowReplyForm] = useState7(false);
1190
+ const [deleting, setDeleting] = useState7(false);
1064
1191
  const replies = "replies" in comment ? comment.replies : [];
1065
1192
  const canReply = !isReply && !!currentUserId && !comment.isDeleted;
1066
1193
  const canDelete = !!currentUserId && currentUserId === comment.authorId && !comment.isDeleted;
@@ -1076,15 +1203,15 @@ function CommentItem({
1076
1203
  }
1077
1204
  });
1078
1205
  }
1079
- return /* @__PURE__ */ jsxs14("div", { className: `${isReply ? "ml-8 border-l-2 border-border pl-4" : ""}`, children: [
1080
- /* @__PURE__ */ jsx15("div", { className: "rounded-lg bg-muted/40 p-3 space-y-1", children: comment.isDeleted ? /* @__PURE__ */ jsx15("p", { className: "text-sm italic text-muted-foreground", children: "Comment removed" }) : /* @__PURE__ */ jsxs14(Fragment, { children: [
1081
- /* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between gap-2", children: [
1082
- /* @__PURE__ */ jsx15("span", { className: "text-sm font-medium text-foreground", children: comment.authorName }),
1083
- /* @__PURE__ */ jsx15("span", { className: "text-xs text-muted-foreground", children: relativeTime(comment.createdAt) })
1206
+ return /* @__PURE__ */ jsxs16("div", { className: `${isReply ? "ml-8 border-l-2 border-border pl-4" : ""}`, children: [
1207
+ /* @__PURE__ */ jsx17("div", { className: "rounded-lg bg-muted/40 p-3 space-y-1", children: comment.isDeleted ? /* @__PURE__ */ jsx17("p", { className: "text-sm italic text-muted-foreground", children: "Comment removed" }) : /* @__PURE__ */ jsxs16(Fragment2, { children: [
1208
+ /* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between gap-2", children: [
1209
+ /* @__PURE__ */ jsx17("span", { className: "text-sm font-medium text-foreground", children: comment.authorName }),
1210
+ /* @__PURE__ */ jsx17("span", { className: "text-xs text-muted-foreground", children: relativeTime(comment.createdAt) })
1084
1211
  ] }),
1085
- /* @__PURE__ */ jsx15("p", { className: "text-sm text-foreground whitespace-pre-wrap break-words", children: comment.body }),
1086
- /* @__PURE__ */ jsxs14("div", { className: "flex gap-3 pt-1", children: [
1087
- canReply && /* @__PURE__ */ jsx15(
1212
+ /* @__PURE__ */ jsx17("p", { className: "text-sm text-foreground whitespace-pre-wrap break-words", children: comment.body }),
1213
+ /* @__PURE__ */ jsxs16("div", { className: "flex gap-3 pt-1", children: [
1214
+ canReply && /* @__PURE__ */ jsx17(
1088
1215
  "button",
1089
1216
  {
1090
1217
  onClick: () => setShowReplyForm((v) => !v),
@@ -1092,7 +1219,7 @@ function CommentItem({
1092
1219
  children: showReplyForm ? "Cancel" : "Reply"
1093
1220
  }
1094
1221
  ),
1095
- canDelete && /* @__PURE__ */ jsx15(
1222
+ canDelete && /* @__PURE__ */ jsx17(
1096
1223
  "button",
1097
1224
  {
1098
1225
  onClick: handleDelete,
@@ -1103,7 +1230,7 @@ function CommentItem({
1103
1230
  )
1104
1231
  ] })
1105
1232
  ] }) }),
1106
- showReplyForm && /* @__PURE__ */ jsx15("div", { className: "mt-2 ml-2", children: /* @__PURE__ */ jsx15(
1233
+ showReplyForm && /* @__PURE__ */ jsx17("div", { className: "mt-2 ml-2", children: /* @__PURE__ */ jsx17(
1107
1234
  CommentForm,
1108
1235
  {
1109
1236
  articleSlug,
@@ -1115,7 +1242,7 @@ function CommentItem({
1115
1242
  onCancel: () => setShowReplyForm(false)
1116
1243
  }
1117
1244
  ) }),
1118
- replies.length > 0 && /* @__PURE__ */ jsx15("div", { className: "mt-2 space-y-2", children: replies.map((reply) => /* @__PURE__ */ jsx15(
1245
+ replies.length > 0 && /* @__PURE__ */ jsx17("div", { className: "mt-2 space-y-2", children: replies.map((reply) => /* @__PURE__ */ jsx17(
1119
1246
  CommentItem,
1120
1247
  {
1121
1248
  comment: __spreadProps(__spreadValues({}, reply), { replies: [] }),
@@ -1130,7 +1257,7 @@ function CommentItem({
1130
1257
  }
1131
1258
 
1132
1259
  // src/CommentThread.tsx
1133
- import { jsx as jsx16 } from "react/jsx-runtime";
1260
+ import { jsx as jsx18 } from "react/jsx-runtime";
1134
1261
  function CommentThread({
1135
1262
  comments,
1136
1263
  articleSlug,
@@ -1138,9 +1265,9 @@ function CommentThread({
1138
1265
  onRefresh
1139
1266
  }) {
1140
1267
  if (comments.length === 0) {
1141
- return /* @__PURE__ */ jsx16("p", { className: "text-sm text-muted-foreground text-center py-6", children: "No comments yet. Be the first to share your thoughts." });
1268
+ return /* @__PURE__ */ jsx18("p", { className: "text-sm text-muted-foreground text-center py-6", children: "No comments yet. Be the first to share your thoughts." });
1142
1269
  }
1143
- return /* @__PURE__ */ jsx16("div", { className: "space-y-4", children: comments.map((comment) => /* @__PURE__ */ jsx16(
1270
+ return /* @__PURE__ */ jsx18("div", { className: "space-y-4", children: comments.map((comment) => /* @__PURE__ */ jsx18(
1144
1271
  CommentItem,
1145
1272
  {
1146
1273
  comment,
@@ -1153,13 +1280,13 @@ function CommentThread({
1153
1280
  }
1154
1281
 
1155
1282
  // src/CommentsSection.tsx
1156
- import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
1283
+ import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
1157
1284
  function CommentsSection({ articleSlug, config }) {
1158
1285
  var _a, _b, _c, _d, _e, _f;
1159
1286
  const { data: session, status } = useSession();
1160
- const [comments, setComments] = useState7([]);
1161
- const [loading, setLoading] = useState7(true);
1162
- const [fetchError, setFetchError] = useState7(null);
1287
+ const [comments, setComments] = useState8([]);
1288
+ const [loading, setLoading] = useState8(true);
1289
+ const [fetchError, setFetchError] = useState8(null);
1163
1290
  const perArticleEnabled = (_b = (_a = config.perArticleOverride) == null ? void 0 : _a[articleSlug]) != null ? _b : true;
1164
1291
  const enabled = config.enabled && perArticleEnabled;
1165
1292
  const currentUserId = (_f = (_e = (_c = session == null ? void 0 : session.user) == null ? void 0 : _c.email) != null ? _e : (_d = session == null ? void 0 : session.user) == null ? void 0 : _d.name) != null ? _f : void 0;
@@ -1177,7 +1304,7 @@ function CommentsSection({ articleSlug, config }) {
1177
1304
  setLoading(false);
1178
1305
  }
1179
1306
  }), [articleSlug]);
1180
- useEffect4(() => {
1307
+ useEffect5(() => {
1181
1308
  if (enabled) {
1182
1309
  fetchComments().catch(() => void 0);
1183
1310
  }
@@ -1185,10 +1312,10 @@ function CommentsSection({ articleSlug, config }) {
1185
1312
  if (!enabled) return null;
1186
1313
  const count = comments.length;
1187
1314
  const label = count === 1 ? "1 comment" : `${count} comments`;
1188
- return /* @__PURE__ */ jsxs15("section", { "aria-label": "Comments", className: "mt-12 pt-8 border-t border-border space-y-6", children: [
1189
- /* @__PURE__ */ jsx17("h2", { className: "text-xl font-semibold text-foreground", children: loading ? "Comments" : label }),
1190
- status === "authenticated" ? /* @__PURE__ */ jsx17(CommentForm, { articleSlug, onSuccess: fetchComments }) : /* @__PURE__ */ jsxs15("p", { className: "text-sm text-muted-foreground", children: [
1191
- /* @__PURE__ */ jsx17(
1315
+ return /* @__PURE__ */ jsxs17("section", { "aria-label": "Comments", className: "mt-12 pt-8 border-t border-border space-y-6", children: [
1316
+ /* @__PURE__ */ jsx19("h2", { className: "text-xl font-semibold text-foreground", children: loading ? "Comments" : label }),
1317
+ status === "authenticated" ? /* @__PURE__ */ jsx19(CommentForm, { articleSlug, onSuccess: fetchComments }) : /* @__PURE__ */ jsxs17("p", { className: "text-sm text-muted-foreground", children: [
1318
+ /* @__PURE__ */ jsx19(
1192
1319
  "button",
1193
1320
  {
1194
1321
  onClick: () => signIn(),
@@ -1199,8 +1326,8 @@ function CommentsSection({ articleSlug, config }) {
1199
1326
  " ",
1200
1327
  "to join the discussion."
1201
1328
  ] }),
1202
- fetchError && /* @__PURE__ */ jsx17("p", { className: "text-sm text-destructive", children: fetchError }),
1203
- loading ? /* @__PURE__ */ jsx17("p", { className: "text-sm text-muted-foreground", children: "Loading comments\u2026" }) : /* @__PURE__ */ jsx17(
1329
+ fetchError && /* @__PURE__ */ jsx19("p", { className: "text-sm text-destructive", children: fetchError }),
1330
+ loading ? /* @__PURE__ */ jsx19("p", { className: "text-sm text-muted-foreground", children: "Loading comments\u2026" }) : /* @__PURE__ */ jsx19(
1204
1331
  CommentThread,
1205
1332
  {
1206
1333
  comments,
@@ -1216,9 +1343,11 @@ export {
1216
1343
  ArticleCategoryGrid,
1217
1344
  ArticleDetailHero,
1218
1345
  ArticleNavigation,
1346
+ ArticleSEO,
1219
1347
  ArticleSchema,
1220
1348
  ArticleSearchBar,
1221
1349
  ArticleSocialShare,
1350
+ ArticleTOC,
1222
1351
  ArticlesHero,
1223
1352
  ArticlesPage,
1224
1353
  BreadcrumbSchema,
@@ -1231,9 +1360,11 @@ export {
1231
1360
  DEFAULT_CATEGORIES_PAGE_SIZE,
1232
1361
  DEFAULT_LAYOUT,
1233
1362
  DEFAULT_PAGE_SIZE,
1363
+ FAQPageSchema,
1234
1364
  FeaturedArticle,
1235
1365
  LatestArticles,
1236
1366
  LatestArticlesSection,
1367
+ ScrollToTop,
1237
1368
  useArticles
1238
1369
  };
1239
1370
  //# sourceMappingURL=index.js.map