@sonordev/site-kit 1.2.7

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.
Files changed (300) hide show
  1. package/README.md +376 -0
  2. package/dist/SetupWizard-Cki06kB0.d.mts +12 -0
  3. package/dist/SetupWizard-Cki06kB0.d.ts +12 -0
  4. package/dist/analytics/index.d.mts +93 -0
  5. package/dist/analytics/index.d.ts +93 -0
  6. package/dist/analytics/index.js +89 -0
  7. package/dist/analytics/index.js.map +1 -0
  8. package/dist/analytics/index.mjs +71 -0
  9. package/dist/analytics/index.mjs.map +1 -0
  10. package/dist/api-CWtoFJCO.d.mts +137 -0
  11. package/dist/api-CWtoFJCO.d.ts +137 -0
  12. package/dist/blog/index.d.mts +305 -0
  13. package/dist/blog/index.d.ts +305 -0
  14. package/dist/blog/index.js +1578 -0
  15. package/dist/blog/index.js.map +1 -0
  16. package/dist/blog/index.mjs +1562 -0
  17. package/dist/blog/index.mjs.map +1 -0
  18. package/dist/blog/server.d.mts +229 -0
  19. package/dist/blog/server.d.ts +229 -0
  20. package/dist/blog/server.js +692 -0
  21. package/dist/blog/server.js.map +1 -0
  22. package/dist/blog/server.mjs +666 -0
  23. package/dist/blog/server.mjs.map +1 -0
  24. package/dist/chunk-24277A3Q.mjs +968 -0
  25. package/dist/chunk-24277A3Q.mjs.map +1 -0
  26. package/dist/chunk-373TK6TZ.js +321 -0
  27. package/dist/chunk-373TK6TZ.js.map +1 -0
  28. package/dist/chunk-3MYZS6PD.js +30 -0
  29. package/dist/chunk-3MYZS6PD.js.map +1 -0
  30. package/dist/chunk-43GBM4SX.js +283 -0
  31. package/dist/chunk-43GBM4SX.js.map +1 -0
  32. package/dist/chunk-4XPGGLVP.mjs +53 -0
  33. package/dist/chunk-4XPGGLVP.mjs.map +1 -0
  34. package/dist/chunk-622GAQP5.js +2008 -0
  35. package/dist/chunk-622GAQP5.js.map +1 -0
  36. package/dist/chunk-6BIPAKL4.mjs +28 -0
  37. package/dist/chunk-6BIPAKL4.mjs.map +1 -0
  38. package/dist/chunk-6ZCISNAB.mjs +343 -0
  39. package/dist/chunk-6ZCISNAB.mjs.map +1 -0
  40. package/dist/chunk-72MQFHYJ.js +1429 -0
  41. package/dist/chunk-72MQFHYJ.js.map +1 -0
  42. package/dist/chunk-7557OTHW.js +62 -0
  43. package/dist/chunk-7557OTHW.js.map +1 -0
  44. package/dist/chunk-7FUV73JZ.js +981 -0
  45. package/dist/chunk-7FUV73JZ.js.map +1 -0
  46. package/dist/chunk-7RF6PVHA.mjs +324 -0
  47. package/dist/chunk-7RF6PVHA.mjs.map +1 -0
  48. package/dist/chunk-7RYCHO6D.mjs +134 -0
  49. package/dist/chunk-7RYCHO6D.mjs.map +1 -0
  50. package/dist/chunk-7UKPRW25.mjs +1999 -0
  51. package/dist/chunk-7UKPRW25.mjs.map +1 -0
  52. package/dist/chunk-7URAOG2M.js +14864 -0
  53. package/dist/chunk-7URAOG2M.js.map +1 -0
  54. package/dist/chunk-AFAO3TGS.mjs +810 -0
  55. package/dist/chunk-AFAO3TGS.mjs.map +1 -0
  56. package/dist/chunk-BYLIU6XG.js +343 -0
  57. package/dist/chunk-BYLIU6XG.js.map +1 -0
  58. package/dist/chunk-D63MUKZ6.mjs +4423 -0
  59. package/dist/chunk-D63MUKZ6.mjs.map +1 -0
  60. package/dist/chunk-DDKW2FNA.js +390 -0
  61. package/dist/chunk-DDKW2FNA.js.map +1 -0
  62. package/dist/chunk-DQYMKR27.mjs +341 -0
  63. package/dist/chunk-DQYMKR27.mjs.map +1 -0
  64. package/dist/chunk-DW5UJKHH.js +221 -0
  65. package/dist/chunk-DW5UJKHH.js.map +1 -0
  66. package/dist/chunk-EEZCR6E6.js +50 -0
  67. package/dist/chunk-EEZCR6E6.js.map +1 -0
  68. package/dist/chunk-GCJXQ4AG.mjs +59 -0
  69. package/dist/chunk-GCJXQ4AG.mjs.map +1 -0
  70. package/dist/chunk-JGNQK2G6.mjs +14845 -0
  71. package/dist/chunk-JGNQK2G6.mjs.map +1 -0
  72. package/dist/chunk-JTLOJLWQ.mjs +563 -0
  73. package/dist/chunk-JTLOJLWQ.mjs.map +1 -0
  74. package/dist/chunk-K23A4G76.mjs +202 -0
  75. package/dist/chunk-K23A4G76.mjs.map +1 -0
  76. package/dist/chunk-KKU3K7RG.js +336 -0
  77. package/dist/chunk-KKU3K7RG.js.map +1 -0
  78. package/dist/chunk-KUGMH4ZF.js +571 -0
  79. package/dist/chunk-KUGMH4ZF.js.map +1 -0
  80. package/dist/chunk-LBVWVP72.js +110 -0
  81. package/dist/chunk-LBVWVP72.js.map +1 -0
  82. package/dist/chunk-LIVWLY2P.js +138 -0
  83. package/dist/chunk-LIVWLY2P.js.map +1 -0
  84. package/dist/chunk-M2T6R7BA.mjs +1003 -0
  85. package/dist/chunk-M2T6R7BA.mjs.map +1 -0
  86. package/dist/chunk-MV3QN7PW.mjs +47 -0
  87. package/dist/chunk-MV3QN7PW.mjs.map +1 -0
  88. package/dist/chunk-OB7E654K.js +72 -0
  89. package/dist/chunk-OB7E654K.js.map +1 -0
  90. package/dist/chunk-OIIKTGRL.mjs +380 -0
  91. package/dist/chunk-OIIKTGRL.mjs.map +1 -0
  92. package/dist/chunk-P3UWIUJS.mjs +1427 -0
  93. package/dist/chunk-P3UWIUJS.mjs.map +1 -0
  94. package/dist/chunk-PKN27UMH.mjs +136 -0
  95. package/dist/chunk-PKN27UMH.mjs.map +1 -0
  96. package/dist/chunk-QXV4667R.mjs +105 -0
  97. package/dist/chunk-QXV4667R.mjs.map +1 -0
  98. package/dist/chunk-S7FRYNSU.mjs +315 -0
  99. package/dist/chunk-S7FRYNSU.mjs.map +1 -0
  100. package/dist/chunk-TFLQX7K7.mjs +68 -0
  101. package/dist/chunk-TFLQX7K7.mjs.map +1 -0
  102. package/dist/chunk-UWE5PCYJ.mjs +279 -0
  103. package/dist/chunk-UWE5PCYJ.mjs.map +1 -0
  104. package/dist/chunk-UYFDNX2F.js +4469 -0
  105. package/dist/chunk-UYFDNX2F.js.map +1 -0
  106. package/dist/chunk-W4PALSGM.js +350 -0
  107. package/dist/chunk-W4PALSGM.js.map +1 -0
  108. package/dist/chunk-WECQ6KOB.js +1008 -0
  109. package/dist/chunk-WECQ6KOB.js.map +1 -0
  110. package/dist/chunk-XQQWI6WB.js +814 -0
  111. package/dist/chunk-XQQWI6WB.js.map +1 -0
  112. package/dist/chunk-XZJOZJB6.js +140 -0
  113. package/dist/chunk-XZJOZJB6.js.map +1 -0
  114. package/dist/chunk-ZSMWDLMK.js +63 -0
  115. package/dist/chunk-ZSMWDLMK.js.map +1 -0
  116. package/dist/cli/index.js +37243 -0
  117. package/dist/cli/index.js.map +1 -0
  118. package/dist/cli/index.mjs +37209 -0
  119. package/dist/cli/index.mjs.map +1 -0
  120. package/dist/commerce/index.d.mts +170 -0
  121. package/dist/commerce/index.d.ts +170 -0
  122. package/dist/commerce/index.js +174 -0
  123. package/dist/commerce/index.js.map +1 -0
  124. package/dist/commerce/index.mjs +5 -0
  125. package/dist/commerce/index.mjs.map +1 -0
  126. package/dist/commerce/server.d.mts +107 -0
  127. package/dist/commerce/server.d.ts +107 -0
  128. package/dist/commerce/server.js +187 -0
  129. package/dist/commerce/server.js.map +1 -0
  130. package/dist/commerce/server.mjs +177 -0
  131. package/dist/commerce/server.mjs.map +1 -0
  132. package/dist/config/index.d.mts +43 -0
  133. package/dist/config/index.d.ts +43 -0
  134. package/dist/config/index.js +66 -0
  135. package/dist/config/index.js.map +1 -0
  136. package/dist/config/index.mjs +64 -0
  137. package/dist/config/index.mjs.map +1 -0
  138. package/dist/engage/index.d.mts +33 -0
  139. package/dist/engage/index.d.ts +33 -0
  140. package/dist/engage/index.js +22 -0
  141. package/dist/engage/index.js.map +1 -0
  142. package/dist/engage/index.mjs +5 -0
  143. package/dist/engage/index.mjs.map +1 -0
  144. package/dist/forms/index.d.mts +437 -0
  145. package/dist/forms/index.d.ts +437 -0
  146. package/dist/forms/index.js +1168 -0
  147. package/dist/forms/index.js.map +1 -0
  148. package/dist/forms/index.mjs +1142 -0
  149. package/dist/forms/index.mjs.map +1 -0
  150. package/dist/generators-2XKQMPKH.mjs +4 -0
  151. package/dist/generators-2XKQMPKH.mjs.map +1 -0
  152. package/dist/generators-DTMO36DV.js +33 -0
  153. package/dist/generators-DTMO36DV.js.map +1 -0
  154. package/dist/images/index.d.mts +4 -0
  155. package/dist/images/index.d.ts +4 -0
  156. package/dist/images/index.js +46 -0
  157. package/dist/images/index.js.map +1 -0
  158. package/dist/images/index.mjs +5 -0
  159. package/dist/images/index.mjs.map +1 -0
  160. package/dist/images/server.d.mts +69 -0
  161. package/dist/images/server.d.ts +69 -0
  162. package/dist/images/server.js +21 -0
  163. package/dist/images/server.js.map +1 -0
  164. package/dist/images/server.mjs +4 -0
  165. package/dist/images/server.mjs.map +1 -0
  166. package/dist/index.d.mts +846 -0
  167. package/dist/index.d.ts +846 -0
  168. package/dist/index.js +2623 -0
  169. package/dist/index.js.map +1 -0
  170. package/dist/index.mjs +2416 -0
  171. package/dist/index.mjs.map +1 -0
  172. package/dist/layout/index.d.mts +53 -0
  173. package/dist/layout/index.d.ts +53 -0
  174. package/dist/layout/index.js +187 -0
  175. package/dist/layout/index.js.map +1 -0
  176. package/dist/layout/index.mjs +185 -0
  177. package/dist/layout/index.mjs.map +1 -0
  178. package/dist/llms/index.d.mts +448 -0
  179. package/dist/llms/index.d.ts +448 -0
  180. package/dist/llms/index.js +581 -0
  181. package/dist/llms/index.js.map +1 -0
  182. package/dist/llms/index.mjs +529 -0
  183. package/dist/llms/index.mjs.map +1 -0
  184. package/dist/manifest/index.d.mts +62 -0
  185. package/dist/manifest/index.d.ts +62 -0
  186. package/dist/manifest/index.js +85 -0
  187. package/dist/manifest/index.js.map +1 -0
  188. package/dist/manifest/index.mjs +83 -0
  189. package/dist/manifest/index.mjs.map +1 -0
  190. package/dist/middleware/index.d.mts +63 -0
  191. package/dist/middleware/index.d.ts +63 -0
  192. package/dist/middleware/index.js +54 -0
  193. package/dist/middleware/index.js.map +1 -0
  194. package/dist/middleware/index.mjs +51 -0
  195. package/dist/middleware/index.mjs.map +1 -0
  196. package/dist/migrator-2MQHOFDQ.mjs +4 -0
  197. package/dist/migrator-2MQHOFDQ.mjs.map +1 -0
  198. package/dist/migrator-THJCF6MZ.js +37 -0
  199. package/dist/migrator-THJCF6MZ.js.map +1 -0
  200. package/dist/redirects/index.d.mts +78 -0
  201. package/dist/redirects/index.d.ts +78 -0
  202. package/dist/redirects/index.js +26 -0
  203. package/dist/redirects/index.js.map +1 -0
  204. package/dist/redirects/index.mjs +5 -0
  205. package/dist/redirects/index.mjs.map +1 -0
  206. package/dist/reputation/index.d.mts +57 -0
  207. package/dist/reputation/index.d.ts +57 -0
  208. package/dist/reputation/index.js +21 -0
  209. package/dist/reputation/index.js.map +1 -0
  210. package/dist/reputation/index.mjs +4 -0
  211. package/dist/reputation/index.mjs.map +1 -0
  212. package/dist/robots/index.d.mts +38 -0
  213. package/dist/robots/index.d.ts +38 -0
  214. package/dist/robots/index.js +52 -0
  215. package/dist/robots/index.js.map +1 -0
  216. package/dist/robots/index.mjs +50 -0
  217. package/dist/robots/index.mjs.map +1 -0
  218. package/dist/routing-B5XS-6_W.d.mts +118 -0
  219. package/dist/routing-DZYzyDHw.d.ts +118 -0
  220. package/dist/scanner-GAF5PO5F.js +53 -0
  221. package/dist/scanner-GAF5PO5F.js.map +1 -0
  222. package/dist/scanner-LKJKW7IT.mjs +4 -0
  223. package/dist/scanner-LKJKW7IT.mjs.map +1 -0
  224. package/dist/securityHeaders-nwZ6nP4g.d.mts +24 -0
  225. package/dist/securityHeaders-nwZ6nP4g.d.ts +24 -0
  226. package/dist/seo/index.d.mts +600 -0
  227. package/dist/seo/index.d.ts +600 -0
  228. package/dist/seo/index.js +883 -0
  229. package/dist/seo/index.js.map +1 -0
  230. package/dist/seo/index.mjs +773 -0
  231. package/dist/seo/index.mjs.map +1 -0
  232. package/dist/seo/register-sitemap-cli.js +151 -0
  233. package/dist/seo/register-sitemap-cli.js.map +1 -0
  234. package/dist/seo/register-sitemap-cli.mjs +144 -0
  235. package/dist/seo/register-sitemap-cli.mjs.map +1 -0
  236. package/dist/seo/server.d.mts +107 -0
  237. package/dist/seo/server.d.ts +107 -0
  238. package/dist/seo/server.js +207 -0
  239. package/dist/seo/server.js.map +1 -0
  240. package/dist/seo/server.mjs +186 -0
  241. package/dist/seo/server.mjs.map +1 -0
  242. package/dist/server-api-EWXKOQZA.mjs +4 -0
  243. package/dist/server-api-EWXKOQZA.mjs.map +1 -0
  244. package/dist/server-api-GJPNRYUP.js +81 -0
  245. package/dist/server-api-GJPNRYUP.js.map +1 -0
  246. package/dist/setup/client.d.mts +60 -0
  247. package/dist/setup/client.d.ts +60 -0
  248. package/dist/setup/client.js +31 -0
  249. package/dist/setup/client.js.map +1 -0
  250. package/dist/setup/client.mjs +6 -0
  251. package/dist/setup/client.mjs.map +1 -0
  252. package/dist/setup/index.d.mts +5 -0
  253. package/dist/setup/index.d.ts +5 -0
  254. package/dist/setup/index.js +35 -0
  255. package/dist/setup/index.js.map +1 -0
  256. package/dist/setup/index.mjs +6 -0
  257. package/dist/setup/index.mjs.map +1 -0
  258. package/dist/setup/server.d.mts +14 -0
  259. package/dist/setup/server.d.ts +14 -0
  260. package/dist/setup/server.js +13 -0
  261. package/dist/setup/server.js.map +1 -0
  262. package/dist/setup/server.mjs +4 -0
  263. package/dist/setup/server.mjs.map +1 -0
  264. package/dist/site-config/index.d.mts +24 -0
  265. package/dist/site-config/index.d.ts +24 -0
  266. package/dist/site-config/index.js +17 -0
  267. package/dist/site-config/index.js.map +1 -0
  268. package/dist/site-config/index.mjs +4 -0
  269. package/dist/site-config/index.mjs.map +1 -0
  270. package/dist/sitemap/index.d.mts +96 -0
  271. package/dist/sitemap/index.d.ts +96 -0
  272. package/dist/sitemap/index.js +288 -0
  273. package/dist/sitemap/index.js.map +1 -0
  274. package/dist/sitemap/index.mjs +285 -0
  275. package/dist/sitemap/index.mjs.map +1 -0
  276. package/dist/socket-loader-J26QHHOB.js +16 -0
  277. package/dist/socket-loader-J26QHHOB.js.map +1 -0
  278. package/dist/socket-loader-R7S2YJ2J.mjs +14 -0
  279. package/dist/socket-loader-R7S2YJ2J.mjs.map +1 -0
  280. package/dist/types-0dmq3k20.d.mts +168 -0
  281. package/dist/types-0dmq3k20.d.ts +168 -0
  282. package/dist/types-Blb2QNkV.d.mts +263 -0
  283. package/dist/types-Blb2QNkV.d.ts +263 -0
  284. package/dist/types-BnCwwUX3.d.mts +250 -0
  285. package/dist/types-BnCwwUX3.d.ts +250 -0
  286. package/dist/types-CGlnp43R.d.mts +312 -0
  287. package/dist/types-CGlnp43R.d.ts +312 -0
  288. package/dist/types-D08004rU.d.mts +179 -0
  289. package/dist/types-D08004rU.d.ts +179 -0
  290. package/dist/types-DNSYU7qI.d.mts +127 -0
  291. package/dist/types-DNSYU7qI.d.ts +127 -0
  292. package/dist/types-KZP_VWZp.d.mts +266 -0
  293. package/dist/types-KZP_VWZp.d.ts +266 -0
  294. package/dist/useEventModal-BVTx69XE.d.mts +274 -0
  295. package/dist/useEventModal-Dx1dItTJ.d.ts +274 -0
  296. package/dist/web-vitals-444RLW3B.js +252 -0
  297. package/dist/web-vitals-444RLW3B.js.map +1 -0
  298. package/dist/web-vitals-KPICZIEF.mjs +241 -0
  299. package/dist/web-vitals-KPICZIEF.mjs.map +1 -0
  300. package/package.json +192 -0
@@ -0,0 +1,1562 @@
1
+ import '../chunk-4XPGGLVP.mjs';
2
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
+ import React, { useState, useEffect } from 'react';
4
+
5
+ async function fetchBlogPost(apiUrl, apiKey, slug) {
6
+ try {
7
+ const response = await fetch(`${apiUrl}/public/blog/posts/${slug}`, {
8
+ headers: { "x-api-key": apiKey },
9
+ next: { revalidate: 60 }
10
+ });
11
+ if (!response.ok) {
12
+ if (response.status === 404) return null;
13
+ console.error("[Blog] Failed to fetch post:", response.statusText);
14
+ return null;
15
+ }
16
+ const data = await response.json();
17
+ return data.post;
18
+ } catch (error) {
19
+ console.error("[Blog] Error fetching post:", error);
20
+ return null;
21
+ }
22
+ }
23
+ async function fetchRelatedPosts(apiUrl, apiKey, postId, limit = 3) {
24
+ try {
25
+ const response = await fetch(`${apiUrl}/public/blog/related`, {
26
+ method: "POST",
27
+ headers: {
28
+ "Content-Type": "application/json",
29
+ "x-api-key": apiKey
30
+ },
31
+ body: JSON.stringify({ current_post_id: postId, limit }),
32
+ next: { revalidate: 300 }
33
+ });
34
+ if (!response.ok) return [];
35
+ const data = await response.json();
36
+ return data.posts || [];
37
+ } catch (error) {
38
+ console.error("[Blog] Error fetching related posts:", error);
39
+ return [];
40
+ }
41
+ }
42
+ function generateTableOfContents(html) {
43
+ const headingRegex = /<h([2-4])[^>]*(?:id="([^"]*)")?[^>]*>(.*?)<\/h[2-4]>/gi;
44
+ const items = [];
45
+ let match;
46
+ while ((match = headingRegex.exec(html)) !== null) {
47
+ const level = parseInt(match[1]);
48
+ const existingId = match[2];
49
+ const text = match[3].replace(/<[^>]*>/g, "");
50
+ const id = existingId || slugify(text);
51
+ items.push({ id, text, level });
52
+ }
53
+ return items;
54
+ }
55
+ function slugify(text) {
56
+ return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
57
+ }
58
+ async function BlogPost({
59
+ apiUrl = process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.uptrademedia.com",
60
+ apiKey = process.env.NEXT_PUBLIC_UPTRADE_API_KEY || "",
61
+ slug,
62
+ showToc = true,
63
+ showRelated = true,
64
+ relatedCount = 3,
65
+ showAuthor = true,
66
+ basePath = "/blog",
67
+ className,
68
+ styles = {},
69
+ unstyled = false,
70
+ children
71
+ }) {
72
+ const inlineStyle = (defaultStyle, classKey) => unstyled || styles[classKey] ? void 0 : defaultStyle;
73
+ if (!apiKey) {
74
+ console.warn("[Blog] No API key configured");
75
+ return null;
76
+ }
77
+ const post = await fetchBlogPost(apiUrl, apiKey, slug);
78
+ if (!post) {
79
+ return /* @__PURE__ */ jsxs(
80
+ "div",
81
+ {
82
+ className: `${styles.notFound || ""} ${className || ""}`.trim() || void 0,
83
+ style: inlineStyle({ textAlign: "center", padding: 60 }, "notFound"),
84
+ children: [
85
+ /* @__PURE__ */ jsx("h1", { style: inlineStyle({ fontSize: 24, marginBottom: 16 }, "notFound"), children: "Post Not Found" }),
86
+ /* @__PURE__ */ jsx("p", { style: inlineStyle({ color: "#6b7280" }, "notFound"), children: "The blog post you're looking for doesn't exist or has been removed." }),
87
+ /* @__PURE__ */ jsx(
88
+ "a",
89
+ {
90
+ href: basePath,
91
+ style: inlineStyle({
92
+ display: "inline-block",
93
+ marginTop: 24,
94
+ padding: "12px 24px",
95
+ backgroundColor: "#3b82f6",
96
+ color: "#fff",
97
+ borderRadius: 8,
98
+ textDecoration: "none"
99
+ }, "notFound"),
100
+ children: "\u2190 Back to Blog"
101
+ }
102
+ )
103
+ ]
104
+ }
105
+ );
106
+ }
107
+ const content = post.content_html || post.content || "";
108
+ const tableOfContents = showToc ? generateTableOfContents(content) : [];
109
+ const relatedPosts = showRelated ? await fetchRelatedPosts(apiUrl, apiKey, post.id, relatedCount) : [];
110
+ if (children) {
111
+ return children({ post, tableOfContents, relatedPosts });
112
+ }
113
+ const date = post.published_at ? new Date(post.published_at).toLocaleDateString("en-US", {
114
+ month: "long",
115
+ day: "numeric",
116
+ year: "numeric"
117
+ }) : null;
118
+ return /* @__PURE__ */ jsxs("article", { className: `${styles.article || ""} ${className || ""}`.trim() || void 0, children: [
119
+ /* @__PURE__ */ jsxs(
120
+ "header",
121
+ {
122
+ className: styles.header,
123
+ style: inlineStyle({ marginBottom: 32 }, "header"),
124
+ children: [
125
+ /* @__PURE__ */ jsxs(
126
+ "nav",
127
+ {
128
+ className: styles.breadcrumb,
129
+ style: inlineStyle({ marginBottom: 16, fontSize: 14, color: "#6b7280" }, "breadcrumb"),
130
+ children: [
131
+ /* @__PURE__ */ jsx(
132
+ "a",
133
+ {
134
+ href: basePath,
135
+ className: styles.breadcrumbLink,
136
+ style: inlineStyle({ color: "#3b82f6", textDecoration: "none" }, "breadcrumbLink"),
137
+ children: "Blog"
138
+ }
139
+ ),
140
+ post.category && /* @__PURE__ */ jsxs(Fragment, { children: [
141
+ /* @__PURE__ */ jsx("span", { style: inlineStyle({ margin: "0 8px" }, "breadcrumb"), children: "/" }),
142
+ /* @__PURE__ */ jsx(
143
+ "a",
144
+ {
145
+ href: `${basePath}?category=${post.category}`,
146
+ className: styles.breadcrumbLink,
147
+ style: inlineStyle({ color: "#3b82f6", textDecoration: "none" }, "breadcrumbLink"),
148
+ children: typeof post.category === "string" ? post.category : post.category?.name || "Uncategorized"
149
+ }
150
+ )
151
+ ] })
152
+ ]
153
+ }
154
+ ),
155
+ /* @__PURE__ */ jsx(
156
+ "h1",
157
+ {
158
+ className: styles.title,
159
+ style: inlineStyle({ fontSize: 36, fontWeight: 700, lineHeight: 1.2, marginBottom: 16 }, "title"),
160
+ children: post.title
161
+ }
162
+ ),
163
+ post.subtitle && /* @__PURE__ */ jsx(
164
+ "p",
165
+ {
166
+ className: styles.subtitle,
167
+ style: inlineStyle({ fontSize: 20, color: "#6b7280", marginBottom: 16 }, "subtitle"),
168
+ children: post.subtitle
169
+ }
170
+ ),
171
+ /* @__PURE__ */ jsxs(
172
+ "div",
173
+ {
174
+ className: styles.meta,
175
+ style: inlineStyle({ display: "flex", alignItems: "center", gap: 16, flexWrap: "wrap" }, "meta"),
176
+ children: [
177
+ post.author && /* @__PURE__ */ jsxs(
178
+ "span",
179
+ {
180
+ className: styles.metaItem,
181
+ style: inlineStyle({ fontSize: 14, color: "#374151" }, "metaItem"),
182
+ children: [
183
+ "By ",
184
+ typeof post.author === "string" ? post.author : post.author.name
185
+ ]
186
+ }
187
+ ),
188
+ date && /* @__PURE__ */ jsx(
189
+ "span",
190
+ {
191
+ className: styles.metaItem,
192
+ style: inlineStyle({ fontSize: 14, color: "#6b7280" }, "metaItem"),
193
+ children: date
194
+ }
195
+ ),
196
+ post.reading_time_minutes && /* @__PURE__ */ jsxs(
197
+ "span",
198
+ {
199
+ className: styles.metaItem,
200
+ style: inlineStyle({ fontSize: 14, color: "#9ca3af" }, "metaItem"),
201
+ children: [
202
+ post.reading_time_minutes,
203
+ " min read"
204
+ ]
205
+ }
206
+ )
207
+ ]
208
+ }
209
+ )
210
+ ]
211
+ }
212
+ ),
213
+ post.featured_image && /* @__PURE__ */ jsx(
214
+ "figure",
215
+ {
216
+ className: styles.featuredImageWrapper,
217
+ style: inlineStyle({ margin: "0 0 32px" }, "featuredImageWrapper"),
218
+ children: /* @__PURE__ */ jsx(
219
+ "img",
220
+ {
221
+ src: post.featured_image,
222
+ alt: post.featured_image_alt || post.title,
223
+ className: styles.featuredImage,
224
+ style: inlineStyle({
225
+ width: "100%",
226
+ maxHeight: 500,
227
+ objectFit: "cover",
228
+ borderRadius: 12
229
+ }, "featuredImage")
230
+ }
231
+ )
232
+ }
233
+ ),
234
+ /* @__PURE__ */ jsxs(
235
+ "div",
236
+ {
237
+ className: styles.contentLayout,
238
+ style: inlineStyle({
239
+ display: showToc && tableOfContents.length > 0 ? "grid" : "block",
240
+ gridTemplateColumns: showToc && tableOfContents.length > 0 ? "1fr 250px" : void 0,
241
+ gap: 48
242
+ }, "contentLayout"),
243
+ children: [
244
+ /* @__PURE__ */ jsx(
245
+ "div",
246
+ {
247
+ className: `blog-content ${styles.content || ""}`.trim(),
248
+ style: inlineStyle({
249
+ fontSize: 17,
250
+ lineHeight: 1.8,
251
+ color: "#374151"
252
+ }, "content"),
253
+ dangerouslySetInnerHTML: { __html: content }
254
+ }
255
+ ),
256
+ showToc && tableOfContents.length > 0 && /* @__PURE__ */ jsxs(
257
+ "aside",
258
+ {
259
+ className: styles.tocSidebar,
260
+ style: inlineStyle({
261
+ position: "sticky",
262
+ top: 100,
263
+ alignSelf: "start",
264
+ padding: 20,
265
+ backgroundColor: "#f9fafb",
266
+ borderRadius: 12
267
+ }, "tocSidebar"),
268
+ children: [
269
+ /* @__PURE__ */ jsx(
270
+ "h4",
271
+ {
272
+ className: styles.tocTitle,
273
+ style: inlineStyle({
274
+ margin: "0 0 12px",
275
+ fontSize: 12,
276
+ fontWeight: 600,
277
+ textTransform: "uppercase",
278
+ letterSpacing: "0.05em",
279
+ color: "#6b7280"
280
+ }, "tocTitle"),
281
+ children: "On This Page"
282
+ }
283
+ ),
284
+ /* @__PURE__ */ jsx(
285
+ "ul",
286
+ {
287
+ className: styles.tocList,
288
+ style: inlineStyle({ listStyle: "none", margin: 0, padding: 0 }, "tocList"),
289
+ children: tableOfContents.map((item) => /* @__PURE__ */ jsx(
290
+ "li",
291
+ {
292
+ className: styles.tocItem,
293
+ style: inlineStyle({
294
+ paddingLeft: (item.level - 2) * 12,
295
+ marginBottom: 8
296
+ }, "tocItem"),
297
+ children: /* @__PURE__ */ jsx(
298
+ "a",
299
+ {
300
+ href: `#${item.id}`,
301
+ className: styles.tocLink,
302
+ style: inlineStyle({
303
+ fontSize: 14,
304
+ color: "#6b7280",
305
+ textDecoration: "none"
306
+ }, "tocLink"),
307
+ children: item.text
308
+ }
309
+ )
310
+ },
311
+ item.id
312
+ ))
313
+ }
314
+ )
315
+ ]
316
+ }
317
+ )
318
+ ]
319
+ }
320
+ ),
321
+ post.tags && post.tags.length > 0 && /* @__PURE__ */ jsx(
322
+ "div",
323
+ {
324
+ className: styles.tags,
325
+ style: inlineStyle({ marginTop: 32, display: "flex", gap: 8, flexWrap: "wrap" }, "tags"),
326
+ children: post.tags.map((tag, index) => {
327
+ const tagName = typeof tag === "string" ? tag : tag?.name || "";
328
+ return /* @__PURE__ */ jsxs(
329
+ "a",
330
+ {
331
+ href: `${basePath}?tag=${tagName}`,
332
+ className: styles.tag,
333
+ style: inlineStyle({
334
+ padding: "4px 12px",
335
+ backgroundColor: "#f3f4f6",
336
+ borderRadius: 9999,
337
+ fontSize: 13,
338
+ color: "#374151",
339
+ textDecoration: "none"
340
+ }, "tag"),
341
+ children: [
342
+ "#",
343
+ tagName
344
+ ]
345
+ },
346
+ `${tagName}-${index}`
347
+ );
348
+ })
349
+ }
350
+ ),
351
+ (post.faq_items ?? post.faqItems) && Array.isArray(post.faq_items ?? post.faqItems) && (post.faq_items ?? post.faqItems).length > 0 && /* @__PURE__ */ jsxs(
352
+ "section",
353
+ {
354
+ className: styles.faqSection,
355
+ style: inlineStyle({ marginTop: 48 }, "faqSection"),
356
+ children: [
357
+ /* @__PURE__ */ jsx(
358
+ "h2",
359
+ {
360
+ className: styles.faqTitle,
361
+ style: inlineStyle({ fontSize: 24, fontWeight: 600, marginBottom: 24 }, "faqTitle"),
362
+ children: "Frequently Asked Questions"
363
+ }
364
+ ),
365
+ /* @__PURE__ */ jsx("div", { style: inlineStyle({ display: "flex", flexDirection: "column", gap: 16 }, "faqSection"), children: (post.faq_items ?? post.faqItems).map((faq, index) => /* @__PURE__ */ jsxs(
366
+ "details",
367
+ {
368
+ className: styles.faqItem,
369
+ style: inlineStyle({
370
+ padding: 16,
371
+ backgroundColor: "#f9fafb",
372
+ borderRadius: 8
373
+ }, "faqItem"),
374
+ children: [
375
+ /* @__PURE__ */ jsx(
376
+ "summary",
377
+ {
378
+ className: styles.faqQuestion,
379
+ style: inlineStyle({
380
+ fontWeight: 500,
381
+ cursor: "pointer",
382
+ listStyle: "none"
383
+ }, "faqQuestion"),
384
+ children: faq.question
385
+ }
386
+ ),
387
+ /* @__PURE__ */ jsx(
388
+ "p",
389
+ {
390
+ className: styles.faqAnswer,
391
+ style: inlineStyle({ marginTop: 12, color: "#6b7280" }, "faqAnswer"),
392
+ children: faq.answer
393
+ }
394
+ )
395
+ ]
396
+ },
397
+ index
398
+ )) })
399
+ ]
400
+ }
401
+ ),
402
+ showAuthor && post.author && typeof post.author === "object" && /* @__PURE__ */ jsx(AuthorSection, { author: normalizeAuthorForDisplay(post.author), className: styles.authorCard, unstyled }),
403
+ showRelated && relatedPosts.length > 0 && /* @__PURE__ */ jsxs(
404
+ "section",
405
+ {
406
+ className: styles.relatedSection,
407
+ style: inlineStyle({ marginTop: 48 }, "relatedSection"),
408
+ children: [
409
+ /* @__PURE__ */ jsx(
410
+ "h2",
411
+ {
412
+ className: styles.relatedTitle,
413
+ style: inlineStyle({ fontSize: 24, fontWeight: 600, marginBottom: 24 }, "relatedTitle"),
414
+ children: "Related Posts"
415
+ }
416
+ ),
417
+ /* @__PURE__ */ jsx(
418
+ "div",
419
+ {
420
+ className: styles.relatedGrid,
421
+ style: inlineStyle({
422
+ display: "grid",
423
+ gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))",
424
+ gap: 24
425
+ }, "relatedGrid"),
426
+ children: relatedPosts.map((relatedPost) => /* @__PURE__ */ jsxs(
427
+ "article",
428
+ {
429
+ className: styles.relatedCard,
430
+ style: inlineStyle({
431
+ backgroundColor: "#fff",
432
+ borderRadius: 12,
433
+ overflow: "hidden",
434
+ boxShadow: "0 1px 3px rgba(0,0,0,0.1)"
435
+ }, "relatedCard"),
436
+ children: [
437
+ relatedPost.featured_image && /* @__PURE__ */ jsx("a", { href: `${basePath}/${relatedPost.slug}`, children: /* @__PURE__ */ jsx(
438
+ "img",
439
+ {
440
+ src: relatedPost.featured_image,
441
+ alt: relatedPost.title,
442
+ style: inlineStyle({ width: "100%", height: 150, objectFit: "cover" }, "relatedCard")
443
+ }
444
+ ) }),
445
+ /* @__PURE__ */ jsxs("div", { style: inlineStyle({ padding: 16 }, "relatedCard"), children: [
446
+ /* @__PURE__ */ jsx("h3", { style: inlineStyle({ fontSize: 16, fontWeight: 600, marginBottom: 8 }, "relatedCard"), children: /* @__PURE__ */ jsx(
447
+ "a",
448
+ {
449
+ href: `${basePath}/${relatedPost.slug}`,
450
+ style: inlineStyle({ color: "inherit", textDecoration: "none" }, "relatedCard"),
451
+ children: relatedPost.title
452
+ }
453
+ ) }),
454
+ relatedPost.excerpt && /* @__PURE__ */ jsxs("p", { style: inlineStyle({ fontSize: 14, color: "#6b7280", margin: 0 }, "relatedCard"), children: [
455
+ relatedPost.excerpt.slice(0, 100),
456
+ "..."
457
+ ] })
458
+ ] })
459
+ ]
460
+ },
461
+ relatedPost.id
462
+ ))
463
+ }
464
+ )
465
+ ]
466
+ }
467
+ )
468
+ ] });
469
+ }
470
+ function normalizeAuthorForDisplay(author) {
471
+ const a = author;
472
+ const avatarUrl = a.avatar_url ?? a.image ?? a.image_url;
473
+ const socialLinks = a.social_links;
474
+ const socialProfiles = a.socialProfiles;
475
+ return {
476
+ id: a.id ?? "author",
477
+ project_id: a.project_id ?? "",
478
+ name: a.name ?? "Author",
479
+ slug: a.slug ?? "author",
480
+ bio: a.bio ?? void 0,
481
+ avatar_url: avatarUrl ?? void 0,
482
+ email: a.email ?? void 0,
483
+ website: a.website ?? a.url ?? void 0,
484
+ social_links: socialLinks ?? void 0,
485
+ is_active: a.is_active ?? true,
486
+ ...socialProfiles?.length ? { sameAs: socialProfiles } : {},
487
+ ...a.title ? { title: a.title } : {}
488
+ };
489
+ }
490
+ function AuthorSection({
491
+ author,
492
+ className,
493
+ unstyled = false
494
+ }) {
495
+ return /* @__PURE__ */ jsxs(
496
+ "section",
497
+ {
498
+ className,
499
+ style: unstyled || className ? void 0 : {
500
+ marginTop: 48,
501
+ padding: 24,
502
+ backgroundColor: "#f9fafb",
503
+ borderRadius: 12,
504
+ display: "flex",
505
+ gap: 20,
506
+ alignItems: "flex-start"
507
+ },
508
+ children: [
509
+ author.avatar_url && /* @__PURE__ */ jsx(
510
+ "img",
511
+ {
512
+ src: author.avatar_url,
513
+ alt: author.name,
514
+ style: unstyled || className ? void 0 : {
515
+ width: 80,
516
+ height: 80,
517
+ borderRadius: "50%",
518
+ objectFit: "cover"
519
+ }
520
+ }
521
+ ),
522
+ /* @__PURE__ */ jsxs("div", { children: [
523
+ /* @__PURE__ */ jsx("h3", { style: unstyled || className ? void 0 : { margin: "0 0 4px", fontSize: 18, fontWeight: 600 }, children: author.name }),
524
+ "title" in author && author.title && /* @__PURE__ */ jsx("p", { style: unstyled || className ? void 0 : { margin: "0 0 4px", fontSize: 14, color: "#6b7280" }, children: author.title }),
525
+ author.bio && /* @__PURE__ */ jsx("p", { style: unstyled || className ? void 0 : { margin: "0 0 12px", color: "#6b7280", fontSize: 14 }, children: author.bio }),
526
+ author.social_links && /* @__PURE__ */ jsxs("div", { style: unstyled || className ? void 0 : { display: "flex", gap: 16 }, children: [
527
+ author.social_links.twitter && /* @__PURE__ */ jsx(
528
+ "a",
529
+ {
530
+ href: `https://twitter.com/${author.social_links.twitter}`,
531
+ target: "_blank",
532
+ rel: "noopener noreferrer",
533
+ style: unstyled || className ? void 0 : { color: "#3b82f6", fontSize: 14 },
534
+ children: "Twitter"
535
+ }
536
+ ),
537
+ author.social_links.linkedin && /* @__PURE__ */ jsx(
538
+ "a",
539
+ {
540
+ href: author.social_links.linkedin,
541
+ target: "_blank",
542
+ rel: "noopener noreferrer",
543
+ style: unstyled || className ? void 0 : { color: "#3b82f6", fontSize: 14 },
544
+ children: "LinkedIn"
545
+ }
546
+ )
547
+ ] }),
548
+ "sameAs" in author && author.sameAs && author.sameAs.length > 0 && !author.social_links && /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: 16, flexWrap: "wrap" }, children: author.sameAs.map((url, i) => /* @__PURE__ */ jsx(
549
+ "a",
550
+ {
551
+ href: url,
552
+ target: "_blank",
553
+ rel: "noopener noreferrer",
554
+ style: { color: "#3b82f6", fontSize: 14 },
555
+ children: "Profile"
556
+ },
557
+ i
558
+ )) })
559
+ ] })
560
+ ]
561
+ }
562
+ );
563
+ }
564
+ async function fetchBlogList(params) {
565
+ const {
566
+ apiUrl,
567
+ apiKey,
568
+ category,
569
+ tag,
570
+ author,
571
+ featured,
572
+ search,
573
+ page = 1,
574
+ perPage = 12,
575
+ orderBy = "published_at",
576
+ order = "desc"
577
+ } = params;
578
+ const queryParams = new URLSearchParams();
579
+ if (category) queryParams.set("category", category);
580
+ if (tag) queryParams.set("tag", tag);
581
+ if (author) queryParams.set("author", author);
582
+ if (featured) queryParams.set("featured", "true");
583
+ if (search) queryParams.set("search", search);
584
+ queryParams.set("page", String(page));
585
+ queryParams.set("per_page", String(perPage));
586
+ queryParams.set("order_by", orderBy);
587
+ queryParams.set("order", order);
588
+ try {
589
+ const response = await fetch(`${apiUrl}/public/blog/posts?${queryParams}`, {
590
+ headers: {
591
+ "x-api-key": apiKey
592
+ },
593
+ next: { revalidate: 60 }
594
+ // Revalidate every 60 seconds
595
+ });
596
+ if (!response.ok) {
597
+ console.error("[Blog] Failed to fetch posts:", response.statusText);
598
+ return {
599
+ posts: [],
600
+ pagination: {
601
+ page: 1,
602
+ perPage: 12,
603
+ total: 0,
604
+ totalPages: 0,
605
+ hasNext: false,
606
+ hasPrev: false
607
+ }
608
+ };
609
+ }
610
+ const data = await response.json();
611
+ return {
612
+ posts: data.posts || [],
613
+ pagination: {
614
+ page: data.pagination?.page || 1,
615
+ perPage: data.pagination?.per_page || 12,
616
+ total: data.pagination?.total || 0,
617
+ totalPages: data.pagination?.total_pages || 0,
618
+ hasNext: data.pagination?.has_next || false,
619
+ hasPrev: data.pagination?.has_prev || false
620
+ }
621
+ };
622
+ } catch (error) {
623
+ console.error("[Blog] Error fetching posts:", error);
624
+ return {
625
+ posts: [],
626
+ pagination: {
627
+ page: 1,
628
+ perPage: 12,
629
+ total: 0,
630
+ totalPages: 0,
631
+ hasNext: false,
632
+ hasPrev: false
633
+ }
634
+ };
635
+ }
636
+ }
637
+ async function fetchCategories(apiUrl, apiKey) {
638
+ try {
639
+ const response = await fetch(`${apiUrl}/public/blog/categories`, {
640
+ headers: { "x-api-key": apiKey },
641
+ next: { revalidate: 300 }
642
+ // Cache for 5 minutes
643
+ });
644
+ if (!response.ok) return [];
645
+ const data = await response.json();
646
+ return data.categories || [];
647
+ } catch (error) {
648
+ console.error("[Blog] Error fetching categories:", error);
649
+ return [];
650
+ }
651
+ }
652
+ async function BlogList({
653
+ apiUrl = process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.uptrademedia.com",
654
+ apiKey = process.env.NEXT_PUBLIC_UPTRADE_API_KEY || "",
655
+ category,
656
+ tag,
657
+ author,
658
+ featured,
659
+ search,
660
+ page = 1,
661
+ perPage = 12,
662
+ orderBy = "published_at",
663
+ order = "desc",
664
+ showCategoryFilter = false,
665
+ showPagination = true,
666
+ className,
667
+ basePath = "/blog",
668
+ styles = {},
669
+ unstyled = false,
670
+ renderPost,
671
+ children
672
+ }) {
673
+ if (!apiKey) {
674
+ console.warn("[Blog] No API key configured");
675
+ return null;
676
+ }
677
+ const inlineStyle = (defaultStyle, classKey) => unstyled || styles[classKey] ? void 0 : defaultStyle;
678
+ const [blogData, categories] = await Promise.all([
679
+ fetchBlogList({
680
+ apiUrl,
681
+ apiKey,
682
+ category,
683
+ tag,
684
+ author,
685
+ featured,
686
+ search,
687
+ page,
688
+ perPage,
689
+ orderBy,
690
+ order
691
+ }),
692
+ showCategoryFilter ? fetchCategories(apiUrl, apiKey) : Promise.resolve([])
693
+ ]);
694
+ if (children) {
695
+ return children({ posts: blogData.posts, pagination: blogData.pagination, categories });
696
+ }
697
+ const { posts, pagination } = blogData;
698
+ if (posts.length === 0) {
699
+ return /* @__PURE__ */ jsx(
700
+ "div",
701
+ {
702
+ className: `${styles.container || ""} ${styles.emptyState || ""} ${className || ""}`.trim() || void 0,
703
+ style: inlineStyle({ textAlign: "center", padding: 40 }, "emptyState"),
704
+ children: /* @__PURE__ */ jsx("p", { style: inlineStyle({ color: "#6b7280" }, "emptyState"), children: "No posts found." })
705
+ }
706
+ );
707
+ }
708
+ return /* @__PURE__ */ jsxs("div", { className: `${styles.container || ""} ${className || ""}`.trim() || void 0, children: [
709
+ showCategoryFilter && categories.length > 0 && /* @__PURE__ */ jsxs(
710
+ "nav",
711
+ {
712
+ className: styles.categoryNav,
713
+ style: inlineStyle({ marginBottom: 24, display: "flex", gap: 8, flexWrap: "wrap" }, "categoryNav"),
714
+ children: [
715
+ /* @__PURE__ */ jsx(
716
+ "a",
717
+ {
718
+ href: basePath,
719
+ className: `${styles.categoryLink || ""} ${!category ? styles.categoryLinkActive || "" : styles.categoryLinkInactive || ""}`.trim() || void 0,
720
+ style: inlineStyle({
721
+ padding: "6px 12px",
722
+ borderRadius: 9999,
723
+ fontSize: 14,
724
+ textDecoration: "none",
725
+ backgroundColor: !category ? "#3b82f6" : "#f3f4f6",
726
+ color: !category ? "#fff" : "#374151"
727
+ }, "categoryLink"),
728
+ children: "All"
729
+ }
730
+ ),
731
+ categories.map((cat) => /* @__PURE__ */ jsxs(
732
+ "a",
733
+ {
734
+ href: `${basePath}?category=${cat.slug}`,
735
+ className: `${styles.categoryLink || ""} ${category === cat.slug ? styles.categoryLinkActive || "" : styles.categoryLinkInactive || ""}`.trim() || void 0,
736
+ style: inlineStyle({
737
+ padding: "6px 12px",
738
+ borderRadius: 9999,
739
+ fontSize: 14,
740
+ textDecoration: "none",
741
+ backgroundColor: category === cat.slug ? "#3b82f6" : "#f3f4f6",
742
+ color: category === cat.slug ? "#fff" : "#374151"
743
+ }, "categoryLink"),
744
+ children: [
745
+ cat.name,
746
+ " (",
747
+ cat.post_count,
748
+ ")"
749
+ ]
750
+ },
751
+ cat.slug
752
+ ))
753
+ ]
754
+ }
755
+ ),
756
+ /* @__PURE__ */ jsx(
757
+ "div",
758
+ {
759
+ className: styles.grid,
760
+ style: inlineStyle({
761
+ display: "grid",
762
+ gridTemplateColumns: "repeat(auto-fill, minmax(320px, 1fr))",
763
+ gap: 24
764
+ }, "grid"),
765
+ children: posts.map(
766
+ (post) => renderPost ? /* @__PURE__ */ jsx(React.Fragment, { children: renderPost(post) }, post.id) : /* @__PURE__ */ jsx(BlogPostCard, { post, basePath, styles, unstyled }, post.id)
767
+ )
768
+ }
769
+ ),
770
+ showPagination && pagination.totalPages > 1 && /* @__PURE__ */ jsxs(
771
+ "nav",
772
+ {
773
+ className: styles.pagination,
774
+ style: inlineStyle({
775
+ marginTop: 40,
776
+ display: "flex",
777
+ justifyContent: "center",
778
+ gap: 8
779
+ }, "pagination"),
780
+ children: [
781
+ pagination.hasPrev && /* @__PURE__ */ jsx(
782
+ "a",
783
+ {
784
+ href: buildPaginationUrl(basePath, page - 1, category),
785
+ className: styles.paginationLink,
786
+ style: inlineStyle(paginationLinkStyle, "paginationLink"),
787
+ children: "\u2190 Previous"
788
+ }
789
+ ),
790
+ /* @__PURE__ */ jsxs(
791
+ "span",
792
+ {
793
+ className: styles.paginationInfo,
794
+ style: inlineStyle({ padding: "8px 16px", color: "#6b7280" }, "paginationInfo"),
795
+ children: [
796
+ "Page ",
797
+ pagination.page,
798
+ " of ",
799
+ pagination.totalPages
800
+ ]
801
+ }
802
+ ),
803
+ pagination.hasNext && /* @__PURE__ */ jsx(
804
+ "a",
805
+ {
806
+ href: buildPaginationUrl(basePath, page + 1, category),
807
+ className: styles.paginationLink,
808
+ style: inlineStyle(paginationLinkStyle, "paginationLink"),
809
+ children: "Next \u2192"
810
+ }
811
+ )
812
+ ]
813
+ }
814
+ )
815
+ ] });
816
+ }
817
+ function BlogPostCard({ post, basePath, styles = {}, unstyled = false }) {
818
+ const date = post.published_at ? new Date(post.published_at).toLocaleDateString("en-US", {
819
+ month: "long",
820
+ day: "numeric",
821
+ year: "numeric"
822
+ }) : null;
823
+ const inlineStyle = (defaultStyle, classKey) => unstyled || styles[classKey] ? void 0 : defaultStyle;
824
+ return /* @__PURE__ */ jsxs(
825
+ "article",
826
+ {
827
+ className: styles.card,
828
+ style: inlineStyle({
829
+ backgroundColor: "#fff",
830
+ borderRadius: 12,
831
+ overflow: "hidden",
832
+ boxShadow: "0 1px 3px rgba(0,0,0,0.1)",
833
+ transition: "box-shadow 0.2s, transform 0.2s"
834
+ }, "card"),
835
+ children: [
836
+ post.featured_image && /* @__PURE__ */ jsx("a", { href: `${basePath}/${post.slug}`, className: styles.cardImageWrapper, children: /* @__PURE__ */ jsx(
837
+ "img",
838
+ {
839
+ src: post.featured_image,
840
+ alt: post.featured_image_alt || post.title,
841
+ className: styles.cardImage,
842
+ style: inlineStyle({
843
+ width: "100%",
844
+ height: 200,
845
+ objectFit: "cover"
846
+ }, "cardImage")
847
+ }
848
+ ) }),
849
+ /* @__PURE__ */ jsxs(
850
+ "div",
851
+ {
852
+ className: styles.cardBody,
853
+ style: inlineStyle({ padding: 20 }, "cardBody"),
854
+ children: [
855
+ /* @__PURE__ */ jsxs(
856
+ "div",
857
+ {
858
+ className: styles.cardMeta,
859
+ style: inlineStyle({ display: "flex", alignItems: "center", gap: 12, marginBottom: 12 }, "cardMeta"),
860
+ children: [
861
+ post.category && /* @__PURE__ */ jsx(
862
+ "span",
863
+ {
864
+ className: styles.cardCategory,
865
+ style: inlineStyle({
866
+ padding: "2px 8px",
867
+ borderRadius: 4,
868
+ fontSize: 12,
869
+ fontWeight: 500,
870
+ backgroundColor: "#eff6ff",
871
+ color: "#3b82f6",
872
+ textTransform: "uppercase"
873
+ }, "cardCategory"),
874
+ children: typeof post.category === "string" ? post.category : post.category?.name || "Uncategorized"
875
+ }
876
+ ),
877
+ date && /* @__PURE__ */ jsx(
878
+ "span",
879
+ {
880
+ className: styles.cardDate,
881
+ style: inlineStyle({ fontSize: 13, color: "#6b7280" }, "cardDate"),
882
+ children: date
883
+ }
884
+ )
885
+ ]
886
+ }
887
+ ),
888
+ /* @__PURE__ */ jsx(
889
+ "h3",
890
+ {
891
+ className: styles.cardTitle,
892
+ style: inlineStyle({ margin: "0 0 8px", fontSize: 18, fontWeight: 600, lineHeight: 1.4 }, "cardTitle"),
893
+ children: /* @__PURE__ */ jsx(
894
+ "a",
895
+ {
896
+ href: `${basePath}/${post.slug}`,
897
+ className: styles.cardTitleLink,
898
+ style: inlineStyle({ color: "inherit", textDecoration: "none" }, "cardTitleLink"),
899
+ children: post.title
900
+ }
901
+ )
902
+ }
903
+ ),
904
+ post.excerpt && /* @__PURE__ */ jsx(
905
+ "p",
906
+ {
907
+ className: styles.cardExcerpt,
908
+ style: inlineStyle({
909
+ margin: "0 0 16px",
910
+ fontSize: 14,
911
+ color: "#6b7280",
912
+ lineHeight: 1.6,
913
+ display: "-webkit-box",
914
+ WebkitLineClamp: 3,
915
+ WebkitBoxOrient: "vertical",
916
+ overflow: "hidden"
917
+ }, "cardExcerpt"),
918
+ children: post.excerpt
919
+ }
920
+ ),
921
+ /* @__PURE__ */ jsxs(
922
+ "div",
923
+ {
924
+ className: styles.cardFooter,
925
+ style: inlineStyle({ display: "flex", justifyContent: "space-between", alignItems: "center" }, "cardFooter"),
926
+ children: [
927
+ post.author && /* @__PURE__ */ jsxs(
928
+ "span",
929
+ {
930
+ className: styles.cardAuthor,
931
+ style: inlineStyle({ fontSize: 13, color: "#6b7280" }, "cardAuthor"),
932
+ children: [
933
+ "By ",
934
+ typeof post.author === "string" ? post.author : post.author.name
935
+ ]
936
+ }
937
+ ),
938
+ post.reading_time_minutes && /* @__PURE__ */ jsxs(
939
+ "span",
940
+ {
941
+ className: styles.cardReadingTime,
942
+ style: inlineStyle({ fontSize: 13, color: "#9ca3af" }, "cardReadingTime"),
943
+ children: [
944
+ post.reading_time_minutes,
945
+ " min read"
946
+ ]
947
+ }
948
+ )
949
+ ]
950
+ }
951
+ )
952
+ ]
953
+ }
954
+ )
955
+ ]
956
+ }
957
+ );
958
+ }
959
+ function buildPaginationUrl(basePath, page, category) {
960
+ const params = new URLSearchParams();
961
+ params.set("page", String(page));
962
+ if (category) params.set("category", category);
963
+ return `${basePath}?${params}`;
964
+ }
965
+ var paginationLinkStyle = {
966
+ padding: "8px 16px",
967
+ borderRadius: 8,
968
+ backgroundColor: "#3b82f6",
969
+ color: "#fff",
970
+ textDecoration: "none",
971
+ fontSize: 14,
972
+ fontWeight: 500
973
+ };
974
+ async function fetchRecentPosts(apiUrl, apiKey, limit = 5) {
975
+ try {
976
+ const response = await fetch(`${apiUrl}/public/blog/recent?limit=${limit}`, {
977
+ headers: { "x-api-key": apiKey },
978
+ next: { revalidate: 300 }
979
+ });
980
+ if (!response.ok) return [];
981
+ const data = await response.json();
982
+ return data.posts || [];
983
+ } catch (error) {
984
+ console.error("[Blog] Error fetching recent posts:", error);
985
+ return [];
986
+ }
987
+ }
988
+ async function fetchCategories2(apiUrl, apiKey) {
989
+ try {
990
+ const response = await fetch(`${apiUrl}/public/blog/categories`, {
991
+ headers: { "x-api-key": apiKey },
992
+ next: { revalidate: 300 }
993
+ });
994
+ if (!response.ok) return [];
995
+ const data = await response.json();
996
+ return data.categories || [];
997
+ } catch (error) {
998
+ console.error("[Blog] Error fetching categories:", error);
999
+ return [];
1000
+ }
1001
+ }
1002
+ async function fetchTags(apiUrl, apiKey) {
1003
+ try {
1004
+ const response = await fetch(`${apiUrl}/public/blog/tags`, {
1005
+ headers: { "x-api-key": apiKey },
1006
+ next: { revalidate: 300 }
1007
+ });
1008
+ if (!response.ok) return [];
1009
+ const data = await response.json();
1010
+ return data.tags || [];
1011
+ } catch (error) {
1012
+ console.error("[Blog] Error fetching tags:", error);
1013
+ return [];
1014
+ }
1015
+ }
1016
+ async function BlogSidebar({
1017
+ apiUrl = process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.uptrademedia.com",
1018
+ apiKey = process.env.NEXT_PUBLIC_UPTRADE_API_KEY || "",
1019
+ showCategories = true,
1020
+ showRecentPosts = true,
1021
+ recentPostsCount = 5,
1022
+ showTags = true,
1023
+ showSearch = true,
1024
+ basePath = "/blog",
1025
+ className,
1026
+ currentCategory,
1027
+ children
1028
+ }) {
1029
+ if (!apiKey) {
1030
+ console.warn("[Blog] No API key configured for sidebar");
1031
+ return null;
1032
+ }
1033
+ const [categories, recentPosts, tags] = await Promise.all([
1034
+ showCategories ? fetchCategories2(apiUrl, apiKey) : Promise.resolve([]),
1035
+ showRecentPosts ? fetchRecentPosts(apiUrl, apiKey, recentPostsCount) : Promise.resolve([]),
1036
+ showTags ? fetchTags(apiUrl, apiKey) : Promise.resolve([])
1037
+ ]);
1038
+ return /* @__PURE__ */ jsxs("aside", { className, style: { display: "flex", flexDirection: "column", gap: 32 }, children: [
1039
+ showSearch && /* @__PURE__ */ jsx(SearchWidget, { basePath }),
1040
+ showCategories && categories.length > 0 && /* @__PURE__ */ jsx(
1041
+ CategoriesWidget,
1042
+ {
1043
+ categories,
1044
+ basePath,
1045
+ currentCategory
1046
+ }
1047
+ ),
1048
+ showRecentPosts && recentPosts.length > 0 && /* @__PURE__ */ jsx(RecentPostsWidget, { posts: recentPosts, basePath }),
1049
+ showTags && tags.length > 0 && /* @__PURE__ */ jsx(TagsWidget, { tags, basePath }),
1050
+ children
1051
+ ] });
1052
+ }
1053
+ function SearchWidget({ basePath }) {
1054
+ return /* @__PURE__ */ jsxs("div", { style: widgetStyle, children: [
1055
+ /* @__PURE__ */ jsx("h4", { style: widgetTitleStyle, children: "Search" }),
1056
+ /* @__PURE__ */ jsx("form", { action: basePath, method: "get", children: /* @__PURE__ */ jsx(
1057
+ "input",
1058
+ {
1059
+ type: "search",
1060
+ name: "search",
1061
+ placeholder: "Search posts...",
1062
+ style: {
1063
+ width: "100%",
1064
+ padding: "10px 12px",
1065
+ border: "1px solid #e5e7eb",
1066
+ borderRadius: 8,
1067
+ fontSize: 14
1068
+ }
1069
+ }
1070
+ ) })
1071
+ ] });
1072
+ }
1073
+ function CategoriesWidget({
1074
+ categories,
1075
+ basePath,
1076
+ currentCategory
1077
+ }) {
1078
+ return /* @__PURE__ */ jsxs("div", { style: widgetStyle, children: [
1079
+ /* @__PURE__ */ jsx("h4", { style: widgetTitleStyle, children: "Categories" }),
1080
+ /* @__PURE__ */ jsxs("ul", { style: { listStyle: "none", margin: 0, padding: 0 }, children: [
1081
+ /* @__PURE__ */ jsx("li", { style: { marginBottom: 8 }, children: /* @__PURE__ */ jsx(
1082
+ "a",
1083
+ {
1084
+ href: basePath,
1085
+ style: {
1086
+ ...categoryLinkStyle,
1087
+ fontWeight: !currentCategory ? 600 : 400,
1088
+ color: !currentCategory ? "#3b82f6" : "#374151"
1089
+ },
1090
+ children: "All Posts"
1091
+ }
1092
+ ) }),
1093
+ categories.map((cat) => /* @__PURE__ */ jsx("li", { style: { marginBottom: 8 }, children: /* @__PURE__ */ jsxs(
1094
+ "a",
1095
+ {
1096
+ href: `${basePath}?category=${cat.slug}`,
1097
+ style: {
1098
+ ...categoryLinkStyle,
1099
+ fontWeight: currentCategory === cat.slug ? 600 : 400,
1100
+ color: currentCategory === cat.slug ? "#3b82f6" : "#374151"
1101
+ },
1102
+ children: [
1103
+ cat.name,
1104
+ /* @__PURE__ */ jsxs("span", { style: { color: "#9ca3af", marginLeft: 8 }, children: [
1105
+ "(",
1106
+ cat.post_count,
1107
+ ")"
1108
+ ] })
1109
+ ]
1110
+ }
1111
+ ) }, cat.slug))
1112
+ ] })
1113
+ ] });
1114
+ }
1115
+ function RecentPostsWidget({
1116
+ posts,
1117
+ basePath
1118
+ }) {
1119
+ return /* @__PURE__ */ jsxs("div", { style: widgetStyle, children: [
1120
+ /* @__PURE__ */ jsx("h4", { style: widgetTitleStyle, children: "Recent Posts" }),
1121
+ /* @__PURE__ */ jsx("ul", { style: { listStyle: "none", margin: 0, padding: 0 }, children: posts.map((post) => {
1122
+ const date = post.published_at ? new Date(post.published_at).toLocaleDateString("en-US", {
1123
+ month: "short",
1124
+ day: "numeric"
1125
+ }) : null;
1126
+ return /* @__PURE__ */ jsx(
1127
+ "li",
1128
+ {
1129
+ style: {
1130
+ marginBottom: 16,
1131
+ paddingBottom: 16,
1132
+ borderBottom: "1px solid #e5e7eb"
1133
+ },
1134
+ children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 12 }, children: [
1135
+ post.featured_image && /* @__PURE__ */ jsx("a", { href: `${basePath}/${post.slug}`, children: /* @__PURE__ */ jsx(
1136
+ "img",
1137
+ {
1138
+ src: post.featured_image,
1139
+ alt: "",
1140
+ style: {
1141
+ width: 64,
1142
+ height: 48,
1143
+ objectFit: "cover",
1144
+ borderRadius: 6,
1145
+ flexShrink: 0
1146
+ }
1147
+ }
1148
+ ) }),
1149
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
1150
+ /* @__PURE__ */ jsx(
1151
+ "a",
1152
+ {
1153
+ href: `${basePath}/${post.slug}`,
1154
+ style: {
1155
+ fontSize: 14,
1156
+ fontWeight: 500,
1157
+ color: "#374151",
1158
+ textDecoration: "none",
1159
+ display: "-webkit-box",
1160
+ WebkitLineClamp: 2,
1161
+ WebkitBoxOrient: "vertical",
1162
+ overflow: "hidden"
1163
+ },
1164
+ children: post.title
1165
+ }
1166
+ ),
1167
+ date && /* @__PURE__ */ jsx("span", { style: { fontSize: 12, color: "#9ca3af", display: "block", marginTop: 4 }, children: date })
1168
+ ] })
1169
+ ] })
1170
+ },
1171
+ post.id
1172
+ );
1173
+ }) })
1174
+ ] });
1175
+ }
1176
+ function TagsWidget({
1177
+ tags,
1178
+ basePath
1179
+ }) {
1180
+ return /* @__PURE__ */ jsxs("div", { style: widgetStyle, children: [
1181
+ /* @__PURE__ */ jsx("h4", { style: widgetTitleStyle, children: "Popular Tags" }),
1182
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 8 }, children: tags.slice(0, 15).map((tag) => /* @__PURE__ */ jsx(
1183
+ "a",
1184
+ {
1185
+ href: `${basePath}?tag=${tag.slug}`,
1186
+ style: {
1187
+ padding: "4px 10px",
1188
+ backgroundColor: "#f3f4f6",
1189
+ borderRadius: 9999,
1190
+ fontSize: 12,
1191
+ color: "#374151",
1192
+ textDecoration: "none",
1193
+ transition: "background-color 0.2s"
1194
+ },
1195
+ children: tag.name
1196
+ },
1197
+ tag.slug
1198
+ )) })
1199
+ ] });
1200
+ }
1201
+ function NewsletterWidget({
1202
+ title = "Subscribe to Our Newsletter",
1203
+ description = "Get the latest posts delivered straight to your inbox.",
1204
+ buttonText = "Subscribe"
1205
+ }) {
1206
+ return /* @__PURE__ */ jsxs("div", { style: { ...widgetStyle, backgroundColor: "#eff6ff" }, children: [
1207
+ /* @__PURE__ */ jsx("h4", { style: { ...widgetTitleStyle, color: "#1e40af" }, children: title }),
1208
+ /* @__PURE__ */ jsx("p", { style: { fontSize: 14, color: "#6b7280", marginBottom: 16 }, children: description }),
1209
+ /* @__PURE__ */ jsxs(
1210
+ "form",
1211
+ {
1212
+ onSubmit: (e) => {
1213
+ e.preventDefault();
1214
+ },
1215
+ style: { display: "flex", gap: 8 },
1216
+ children: [
1217
+ /* @__PURE__ */ jsx(
1218
+ "input",
1219
+ {
1220
+ type: "email",
1221
+ name: "email",
1222
+ placeholder: "Enter your email",
1223
+ required: true,
1224
+ style: {
1225
+ flex: 1,
1226
+ padding: "10px 12px",
1227
+ border: "1px solid #bfdbfe",
1228
+ borderRadius: 8,
1229
+ fontSize: 14
1230
+ }
1231
+ }
1232
+ ),
1233
+ /* @__PURE__ */ jsx(
1234
+ "button",
1235
+ {
1236
+ type: "submit",
1237
+ style: {
1238
+ padding: "10px 16px",
1239
+ backgroundColor: "#3b82f6",
1240
+ color: "#fff",
1241
+ border: "none",
1242
+ borderRadius: 8,
1243
+ fontSize: 14,
1244
+ fontWeight: 500,
1245
+ cursor: "pointer"
1246
+ },
1247
+ children: buttonText
1248
+ }
1249
+ )
1250
+ ]
1251
+ }
1252
+ )
1253
+ ] });
1254
+ }
1255
+ var widgetStyle = {
1256
+ padding: 20,
1257
+ backgroundColor: "#f9fafb",
1258
+ borderRadius: 12
1259
+ };
1260
+ var widgetTitleStyle = {
1261
+ margin: "0 0 16px",
1262
+ fontSize: 16,
1263
+ fontWeight: 600,
1264
+ color: "#111827"
1265
+ };
1266
+ var categoryLinkStyle = {
1267
+ display: "flex",
1268
+ alignItems: "center",
1269
+ fontSize: 14,
1270
+ textDecoration: "none"
1271
+ };
1272
+ async function BlogLayout({
1273
+ apiUrl = process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.uptrademedia.com",
1274
+ apiKey = process.env.NEXT_PUBLIC_UPTRADE_API_KEY || "",
1275
+ layout = "sidebar-right",
1276
+ showSidebar = true,
1277
+ sidebarProps = {},
1278
+ hero,
1279
+ maxWidth = 1280,
1280
+ basePath = "/blog",
1281
+ className,
1282
+ currentCategory,
1283
+ children
1284
+ }) {
1285
+ const hasSidebar = showSidebar && layout !== "full-width";
1286
+ return /* @__PURE__ */ jsxs("div", { className, children: [
1287
+ hero && /* @__PURE__ */ jsx(
1288
+ "section",
1289
+ {
1290
+ style: {
1291
+ padding: "60px 20px",
1292
+ backgroundColor: hero.backgroundColor || "#1e3a5f",
1293
+ backgroundImage: hero.backgroundImage ? `url(${hero.backgroundImage})` : void 0,
1294
+ backgroundSize: "cover",
1295
+ backgroundPosition: "center",
1296
+ color: "#fff",
1297
+ textAlign: "center"
1298
+ },
1299
+ children: /* @__PURE__ */ jsxs("div", { style: { maxWidth, margin: "0 auto" }, children: [
1300
+ hero.title && /* @__PURE__ */ jsx(
1301
+ "h1",
1302
+ {
1303
+ style: {
1304
+ fontSize: "clamp(32px, 5vw, 48px)",
1305
+ fontWeight: 700,
1306
+ marginBottom: 16
1307
+ },
1308
+ children: hero.title
1309
+ }
1310
+ ),
1311
+ hero.subtitle && /* @__PURE__ */ jsx(
1312
+ "p",
1313
+ {
1314
+ style: {
1315
+ fontSize: "clamp(16px, 2vw, 20px)",
1316
+ opacity: 0.9,
1317
+ maxWidth: 600,
1318
+ margin: "0 auto"
1319
+ },
1320
+ children: hero.subtitle
1321
+ }
1322
+ )
1323
+ ] })
1324
+ }
1325
+ ),
1326
+ /* @__PURE__ */ jsx(
1327
+ "div",
1328
+ {
1329
+ style: {
1330
+ maxWidth,
1331
+ margin: "0 auto",
1332
+ padding: "40px 20px"
1333
+ },
1334
+ children: /* @__PURE__ */ jsxs(
1335
+ "div",
1336
+ {
1337
+ style: {
1338
+ display: hasSidebar ? "grid" : "block",
1339
+ gridTemplateColumns: hasSidebar ? layout === "sidebar-left" ? "300px 1fr" : "1fr 300px" : void 0,
1340
+ gap: 48
1341
+ },
1342
+ children: [
1343
+ hasSidebar && layout === "sidebar-left" && /* @__PURE__ */ jsx(
1344
+ BlogSidebar,
1345
+ {
1346
+ apiUrl,
1347
+ apiKey,
1348
+ basePath,
1349
+ currentCategory,
1350
+ ...sidebarProps
1351
+ }
1352
+ ),
1353
+ /* @__PURE__ */ jsx("main", { style: { minWidth: 0 }, children }),
1354
+ hasSidebar && layout === "sidebar-right" && /* @__PURE__ */ jsx(
1355
+ BlogSidebar,
1356
+ {
1357
+ apiUrl,
1358
+ apiKey,
1359
+ basePath,
1360
+ currentCategory,
1361
+ ...sidebarProps
1362
+ }
1363
+ )
1364
+ ]
1365
+ }
1366
+ )
1367
+ }
1368
+ )
1369
+ ] });
1370
+ }
1371
+ async function BlogPage({ listComponent, ...layoutProps }) {
1372
+ return /* @__PURE__ */ jsx(BlogLayout, { ...layoutProps, children: listComponent });
1373
+ }
1374
+ async function BlogPostPage({ postComponent, ...layoutProps }) {
1375
+ return /* @__PURE__ */ jsx(BlogLayout, { ...layoutProps, showSidebar: false, layout: "full-width", children: /* @__PURE__ */ jsx("div", { style: { maxWidth: 800, margin: "0 auto" }, children: postComponent }) });
1376
+ }
1377
+ async function CategoryPage({
1378
+ category,
1379
+ categoryName,
1380
+ listComponent,
1381
+ hero,
1382
+ ...layoutProps
1383
+ }) {
1384
+ const categoryHero = hero || {
1385
+ title: categoryName || category,
1386
+ subtitle: `Browse all posts in ${categoryName || category}`,
1387
+ backgroundColor: "#1e3a5f"
1388
+ };
1389
+ return /* @__PURE__ */ jsx(BlogLayout, { ...layoutProps, hero: categoryHero, currentCategory: category, children: listComponent });
1390
+ }
1391
+ function AuthorCard({ author, showBio = true, showSocial = true, className }) {
1392
+ return /* @__PURE__ */ jsxs("div", { className, style: { display: "flex", gap: 16, alignItems: "flex-start" }, children: [
1393
+ author.avatar_url && /* @__PURE__ */ jsx(
1394
+ "img",
1395
+ {
1396
+ src: author.avatar_url,
1397
+ alt: author.name,
1398
+ style: {
1399
+ width: 64,
1400
+ height: 64,
1401
+ borderRadius: "50%",
1402
+ objectFit: "cover"
1403
+ }
1404
+ }
1405
+ ),
1406
+ /* @__PURE__ */ jsxs("div", { children: [
1407
+ /* @__PURE__ */ jsx("h4", { style: { margin: 0 }, children: author.name }),
1408
+ showBio && author.bio && /* @__PURE__ */ jsx("p", { style: { margin: "4px 0", color: "#6b7280", fontSize: 14 }, children: author.bio }),
1409
+ showSocial && author.social_links && /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 12, marginTop: 8 }, children: [
1410
+ author.social_links.twitter && /* @__PURE__ */ jsx("a", { href: `https://twitter.com/${author.social_links.twitter}`, target: "_blank", rel: "noopener noreferrer", children: "Twitter" }),
1411
+ author.social_links.linkedin && /* @__PURE__ */ jsx("a", { href: author.social_links.linkedin, target: "_blank", rel: "noopener noreferrer", children: "LinkedIn" }),
1412
+ author.social_links.github && /* @__PURE__ */ jsx("a", { href: `https://github.com/${author.social_links.github}`, target: "_blank", rel: "noopener noreferrer", children: "GitHub" })
1413
+ ] })
1414
+ ] })
1415
+ ] });
1416
+ }
1417
+ async function fetchRelatedPosts2(apiUrl, apiKey, currentPostId, limit) {
1418
+ try {
1419
+ const response = await fetch(`${apiUrl}/api/public/blog/related`, {
1420
+ method: "POST",
1421
+ headers: {
1422
+ "Content-Type": "application/json",
1423
+ "x-api-key": apiKey
1424
+ },
1425
+ body: JSON.stringify({
1426
+ currentPostId,
1427
+ limit
1428
+ })
1429
+ });
1430
+ if (!response.ok) {
1431
+ console.error("Failed to fetch related posts:", response.statusText);
1432
+ return [];
1433
+ }
1434
+ const data = await response.json();
1435
+ return data.posts || [];
1436
+ } catch (error) {
1437
+ console.error("Failed to fetch related posts:", error);
1438
+ return [];
1439
+ }
1440
+ }
1441
+ async function RelatedPosts({
1442
+ apiUrl = process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.uptrademedia.com",
1443
+ apiKey = process.env.NEXT_PUBLIC_UPTRADE_API_KEY || "",
1444
+ currentPostId,
1445
+ limit = 3,
1446
+ className,
1447
+ renderItem
1448
+ }) {
1449
+ if (!apiKey) {
1450
+ console.warn("[Blog] No API key configured for RelatedPosts");
1451
+ return null;
1452
+ }
1453
+ const posts = await fetchRelatedPosts2(apiUrl, apiKey, currentPostId, limit);
1454
+ if (posts.length === 0) return null;
1455
+ return /* @__PURE__ */ jsxs("section", { className, children: [
1456
+ /* @__PURE__ */ jsx("h3", { style: { marginBottom: 16 }, children: "Related Posts" }),
1457
+ /* @__PURE__ */ jsx("div", { style: { display: "grid", gap: 16 }, children: posts.map(
1458
+ (post) => renderItem ? renderItem(post) : /* @__PURE__ */ jsxs("article", { style: { borderBottom: "1px solid #e5e7eb", paddingBottom: 16 }, children: [
1459
+ post.featured_image && /* @__PURE__ */ jsx(
1460
+ "img",
1461
+ {
1462
+ src: post.featured_image,
1463
+ alt: post.title,
1464
+ style: {
1465
+ width: "100%",
1466
+ height: 120,
1467
+ objectFit: "cover",
1468
+ borderRadius: 8,
1469
+ marginBottom: 8
1470
+ }
1471
+ }
1472
+ ),
1473
+ /* @__PURE__ */ jsx("a", { href: `/blog/${post.slug}`, style: { textDecoration: "none" }, children: /* @__PURE__ */ jsx("h4", { style: { margin: 0, color: "inherit" }, children: post.title }) }),
1474
+ post.excerpt && /* @__PURE__ */ jsx("p", { style: { margin: "4px 0 0", fontSize: 14, color: "#6b7280" }, children: post.excerpt })
1475
+ ] }, post.id)
1476
+ ) })
1477
+ ] });
1478
+ }
1479
+ function parseHeadings(content) {
1480
+ const headingRegex = /<h([2-4])[^>]*id="([^"]*)"[^>]*>(.*?)<\/h[2-4]>/gi;
1481
+ const items = [];
1482
+ let match;
1483
+ while ((match = headingRegex.exec(content)) !== null) {
1484
+ items.push({
1485
+ level: parseInt(match[1]),
1486
+ id: match[2],
1487
+ text: match[3].replace(/<[^>]*>/g, "")
1488
+ // Strip any nested HTML
1489
+ });
1490
+ }
1491
+ return items;
1492
+ }
1493
+ function TableOfContents({
1494
+ content,
1495
+ className,
1496
+ maxDepth = 3
1497
+ }) {
1498
+ const [activeId, setActiveId] = useState("");
1499
+ const items = parseHeadings(content).filter((item) => item.level <= maxDepth);
1500
+ useEffect(() => {
1501
+ if (typeof window === "undefined") return;
1502
+ const observer = new IntersectionObserver(
1503
+ (entries) => {
1504
+ entries.forEach((entry) => {
1505
+ if (entry.isIntersecting) {
1506
+ setActiveId(entry.target.id);
1507
+ }
1508
+ });
1509
+ },
1510
+ {
1511
+ rootMargin: "-20% 0% -35% 0%",
1512
+ threshold: 0
1513
+ }
1514
+ );
1515
+ items.forEach((item) => {
1516
+ const element = document.getElementById(item.id);
1517
+ if (element) {
1518
+ observer.observe(element);
1519
+ }
1520
+ });
1521
+ return () => observer.disconnect();
1522
+ }, [items]);
1523
+ if (items.length === 0) return null;
1524
+ const handleClick = (id) => {
1525
+ const element = document.getElementById(id);
1526
+ if (element) {
1527
+ element.scrollIntoView({ behavior: "smooth" });
1528
+ }
1529
+ };
1530
+ return /* @__PURE__ */ jsxs("nav", { className, "aria-label": "Table of contents", children: [
1531
+ /* @__PURE__ */ jsx("h4", { style: { margin: "0 0 12px", fontSize: 14, fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.05em" }, children: "On This Page" }),
1532
+ /* @__PURE__ */ jsx("ul", { style: { listStyle: "none", margin: 0, padding: 0 }, children: items.map((item) => /* @__PURE__ */ jsx(
1533
+ "li",
1534
+ {
1535
+ style: {
1536
+ paddingLeft: (item.level - 2) * 12,
1537
+ marginBottom: 8
1538
+ },
1539
+ children: /* @__PURE__ */ jsx(
1540
+ "button",
1541
+ {
1542
+ onClick: () => handleClick(item.id),
1543
+ style: {
1544
+ all: "unset",
1545
+ cursor: "pointer",
1546
+ fontSize: 14,
1547
+ color: activeId === item.id ? "#2563eb" : "#6b7280",
1548
+ fontWeight: activeId === item.id ? 500 : 400,
1549
+ transition: "color 0.2s"
1550
+ },
1551
+ children: item.text
1552
+ }
1553
+ )
1554
+ },
1555
+ item.id
1556
+ )) })
1557
+ ] });
1558
+ }
1559
+
1560
+ export { AuthorCard, BlogLayout, BlogList, BlogPage, BlogPost, BlogPostPage, BlogSidebar, CategoryPage, NewsletterWidget, RelatedPosts, TableOfContents };
1561
+ //# sourceMappingURL=index.mjs.map
1562
+ //# sourceMappingURL=index.mjs.map