@sonordev/site-kit 4.3.2 → 5.1.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.
Files changed (296) hide show
  1. package/agent-manifest.json +8 -5
  2. package/dist/AnalyticsProvider-2LCSA6G3.mjs +10 -0
  3. package/dist/{AnalyticsProvider-TWRQHKPZ.mjs.map → AnalyticsProvider-2LCSA6G3.mjs.map} +1 -1
  4. package/dist/AnalyticsProvider-V2U3TQMH.js +31 -0
  5. package/dist/{AnalyticsProvider-DNMYYBKX.js.map → AnalyticsProvider-V2U3TQMH.js.map} +1 -1
  6. package/dist/BlogViewTracker-COTPD7WL.js +51 -0
  7. package/dist/BlogViewTracker-COTPD7WL.js.map +1 -0
  8. package/dist/BlogViewTracker-HG25ONRP.mjs +48 -0
  9. package/dist/BlogViewTracker-HG25ONRP.mjs.map +1 -0
  10. package/dist/ChatWidget-4QUJYFXU.js +20 -0
  11. package/dist/{ChatWidget-MDWEXISQ.js.map → ChatWidget-4QUJYFXU.js.map} +1 -1
  12. package/dist/ChatWidget-RWO7R7EJ.mjs +11 -0
  13. package/dist/{ChatWidget-UQMEJAHY.mjs.map → ChatWidget-RWO7R7EJ.mjs.map} +1 -1
  14. package/dist/EngageWidget-LF4AC4QN.mjs +9 -0
  15. package/dist/{EngageWidget-UIIN43ZU.mjs.map → EngageWidget-LF4AC4QN.mjs.map} +1 -1
  16. package/dist/EngageWidget-RSOXB3YM.js +18 -0
  17. package/dist/{EngageWidget-VRC7NUG6.js.map → EngageWidget-RSOXB3YM.js.map} +1 -1
  18. package/dist/{FileField-W4VXQ3CM.js → FileField-S2GUM3QB.js} +6 -6
  19. package/dist/{FileField-W4VXQ3CM.js.map → FileField-S2GUM3QB.js.map} +1 -1
  20. package/dist/{FileField-LVF3SCDC.mjs → FileField-YJ7DZXC3.mjs} +5 -5
  21. package/dist/{FileField-LVF3SCDC.mjs.map → FileField-YJ7DZXC3.mjs.map} +1 -1
  22. package/dist/{FormSpotlight-CRLFAPNI.js → FormSpotlight-7WAXLXZA.js} +15 -15
  23. package/dist/{FormSpotlight-CRLFAPNI.js.map → FormSpotlight-7WAXLXZA.js.map} +1 -1
  24. package/dist/{FormSpotlight-ZPISKGIX.mjs → FormSpotlight-HLH5LQKI.mjs} +3 -3
  25. package/dist/{FormSpotlight-ZPISKGIX.mjs.map → FormSpotlight-HLH5LQKI.mjs.map} +1 -1
  26. package/dist/{FormStage-QMRPAROJ.js → FormStage-LEZYERJB.js} +13 -13
  27. package/dist/{FormStage-QMRPAROJ.js.map → FormStage-LEZYERJB.js.map} +1 -1
  28. package/dist/{FormStage-WQOAP7CR.mjs → FormStage-Q5JW75AF.mjs} +3 -3
  29. package/dist/{FormStage-WQOAP7CR.mjs.map → FormStage-Q5JW75AF.mjs.map} +1 -1
  30. package/dist/ManagedForm-H4SEFSAF.js +23 -0
  31. package/dist/{ManagedForm-7L2W5BBZ.js.map → ManagedForm-H4SEFSAF.js.map} +1 -1
  32. package/dist/ManagedForm-U3NFIVEC.mjs +14 -0
  33. package/dist/{ManagedForm-D7CFOIXH.mjs.map → ManagedForm-U3NFIVEC.mjs.map} +1 -1
  34. package/dist/ManagedNewsletterForm-KT2NGUNW.js +64 -0
  35. package/dist/ManagedNewsletterForm-KT2NGUNW.js.map +1 -0
  36. package/dist/ManagedNewsletterForm-YKYW7B6P.mjs +62 -0
  37. package/dist/ManagedNewsletterForm-YKYW7B6P.mjs.map +1 -0
  38. package/dist/{SignalCore-JQLRWMPJ.mjs → SignalCore-2BH5PUGS.mjs} +5 -5
  39. package/dist/{SignalCore-JQLRWMPJ.mjs.map → SignalCore-2BH5PUGS.mjs.map} +1 -1
  40. package/dist/{SignalCore-DNXKQKRO.js → SignalCore-JM4ODFL2.js} +11 -11
  41. package/dist/{SignalCore-DNXKQKRO.js.map → SignalCore-JM4ODFL2.js.map} +1 -1
  42. package/dist/SitemapSync-5CXS2JGB.mjs +8 -0
  43. package/dist/{SitemapSync-RFY6PUG7.mjs.map → SitemapSync-5CXS2JGB.mjs.map} +1 -1
  44. package/dist/SitemapSync-J4UMJRTO.js +17 -0
  45. package/dist/{SitemapSync-SR6OJRIA.js.map → SitemapSync-J4UMJRTO.js.map} +1 -1
  46. package/dist/analytics/index.js +9 -9
  47. package/dist/analytics/index.mjs +4 -4
  48. package/dist/blog/AuthorCard.d.ts.map +1 -1
  49. package/dist/blog/AuthorPage.d.ts.map +1 -1
  50. package/dist/blog/BlogList.d.ts +7 -1
  51. package/dist/blog/BlogList.d.ts.map +1 -1
  52. package/dist/blog/BlogPost.d.ts +1 -1
  53. package/dist/blog/BlogPost.d.ts.map +1 -1
  54. package/dist/blog/BlogSidebar.d.ts +0 -7
  55. package/dist/blog/BlogSidebar.d.ts.map +1 -1
  56. package/dist/blog/BlogViewTracker.d.ts +10 -0
  57. package/dist/blog/BlogViewTracker.d.ts.map +1 -0
  58. package/dist/blog/ClusterLandingPage.d.ts.map +1 -1
  59. package/dist/blog/ManagedNewsletterForm.d.ts +13 -0
  60. package/dist/blog/ManagedNewsletterForm.d.ts.map +1 -0
  61. package/dist/blog/NewsletterShell.d.ts +18 -0
  62. package/dist/blog/NewsletterShell.d.ts.map +1 -0
  63. package/dist/blog/NewsletterWidget.d.ts +31 -0
  64. package/dist/blog/NewsletterWidget.d.ts.map +1 -0
  65. package/dist/blog/RelatedPosts.d.ts.map +1 -1
  66. package/dist/blog/author-social.d.ts +15 -0
  67. package/dist/blog/author-social.d.ts.map +1 -0
  68. package/dist/blog/author-social.test.d.ts +2 -0
  69. package/dist/blog/author-social.test.d.ts.map +1 -0
  70. package/dist/blog/blog-view-tracker.test.d.ts +2 -0
  71. package/dist/blog/blog-view-tracker.test.d.ts.map +1 -0
  72. package/dist/blog/category-metadata.test.d.ts +2 -0
  73. package/dist/blog/category-metadata.test.d.ts.map +1 -0
  74. package/dist/blog/index.d.ts +13 -7
  75. package/dist/blog/index.d.ts.map +1 -1
  76. package/dist/blog/index.js +94 -505
  77. package/dist/blog/index.js.map +1 -1
  78. package/dist/blog/index.mjs +59 -491
  79. package/dist/blog/index.mjs.map +1 -1
  80. package/dist/blog/newsletter-widget.test.d.ts +2 -0
  81. package/dist/blog/newsletter-widget.test.d.ts.map +1 -0
  82. package/dist/blog/reading-time.d.ts +10 -0
  83. package/dist/blog/reading-time.d.ts.map +1 -0
  84. package/dist/blog/reading-time.test.d.ts +2 -0
  85. package/dist/blog/reading-time.test.d.ts.map +1 -0
  86. package/dist/blog/server-core-contract.test.d.ts +2 -0
  87. package/dist/blog/server-core-contract.test.d.ts.map +1 -0
  88. package/dist/blog/server-core.d.ts +16 -4
  89. package/dist/blog/server-core.d.ts.map +1 -1
  90. package/dist/blog/server-ui.d.ts +5 -0
  91. package/dist/blog/server-ui.d.ts.map +1 -1
  92. package/dist/blog/server-ui.js +35 -10
  93. package/dist/blog/server-ui.js.map +1 -1
  94. package/dist/blog/server-ui.mjs +8 -6
  95. package/dist/blog/server-ui.mjs.map +1 -1
  96. package/dist/blog/server.d.ts +16 -4
  97. package/dist/blog/server.d.ts.map +1 -1
  98. package/dist/blog/server.js +40 -40
  99. package/dist/blog/server.mjs +1 -1
  100. package/dist/blog/tag-links.test.d.ts +2 -0
  101. package/dist/blog/tag-links.test.d.ts.map +1 -0
  102. package/dist/blog/types-wire-shape.test.d.ts +2 -0
  103. package/dist/blog/types-wire-shape.test.d.ts.map +1 -0
  104. package/dist/blog/types.d.ts +25 -19
  105. package/dist/blog/types.d.ts.map +1 -1
  106. package/dist/blog/widget-styles.d.ts +9 -0
  107. package/dist/blog/widget-styles.d.ts.map +1 -0
  108. package/dist/{chunk-I2IA3JXD.js → chunk-2EJX56YJ.js} +8 -8
  109. package/dist/{chunk-I2IA3JXD.js.map → chunk-2EJX56YJ.js.map} +1 -1
  110. package/dist/{chunk-NJ4YX3CI.mjs → chunk-2XHEUWHV.mjs} +4 -4
  111. package/dist/{chunk-NJ4YX3CI.mjs.map → chunk-2XHEUWHV.mjs.map} +1 -1
  112. package/dist/{chunk-RUOEUMAW.js → chunk-44ZTBQH4.js} +3 -3
  113. package/dist/{chunk-RUOEUMAW.js.map → chunk-44ZTBQH4.js.map} +1 -1
  114. package/dist/chunk-4SQ6PROR.mjs +6 -0
  115. package/dist/{chunk-NQNSATTA.mjs.map → chunk-4SQ6PROR.mjs.map} +1 -1
  116. package/dist/{chunk-D4KHH44S.mjs → chunk-4TU246Q4.mjs} +10 -3
  117. package/dist/chunk-4TU246Q4.mjs.map +1 -0
  118. package/dist/{chunk-BUF6IZUE.mjs → chunk-5G2ZRQMO.mjs} +3 -3
  119. package/dist/{chunk-BUF6IZUE.mjs.map → chunk-5G2ZRQMO.mjs.map} +1 -1
  120. package/dist/{chunk-A7OO6OPW.mjs → chunk-5W56B52Z.mjs} +3 -3
  121. package/dist/{chunk-A7OO6OPW.mjs.map → chunk-5W56B52Z.mjs.map} +1 -1
  122. package/dist/{chunk-LVM63JSA.mjs → chunk-6YKNDQYJ.mjs} +3 -3
  123. package/dist/{chunk-LVM63JSA.mjs.map → chunk-6YKNDQYJ.mjs.map} +1 -1
  124. package/dist/{chunk-JJS63TDR.mjs → chunk-A3VGZAZQ.mjs} +483 -21
  125. package/dist/chunk-A3VGZAZQ.mjs.map +1 -0
  126. package/dist/{chunk-YWBXKEAF.js → chunk-ACLBRIYD.js} +3 -3
  127. package/dist/{chunk-YWBXKEAF.js.map → chunk-ACLBRIYD.js.map} +1 -1
  128. package/dist/{chunk-OQTP5M5Y.js → chunk-ACWGG4VW.js} +9 -9
  129. package/dist/{chunk-OQTP5M5Y.js.map → chunk-ACWGG4VW.js.map} +1 -1
  130. package/dist/{chunk-NQEUFRMX.mjs → chunk-ADBLBGCQ.mjs} +3 -3
  131. package/dist/{chunk-NQEUFRMX.mjs.map → chunk-ADBLBGCQ.mjs.map} +1 -1
  132. package/dist/{chunk-45VPULF2.mjs → chunk-ADOGOLYO.mjs} +4 -4
  133. package/dist/{chunk-45VPULF2.mjs.map → chunk-ADOGOLYO.mjs.map} +1 -1
  134. package/dist/chunk-AK6JZ3OE.mjs +65 -0
  135. package/dist/chunk-AK6JZ3OE.mjs.map +1 -0
  136. package/dist/{chunk-UR4HKLHW.js → chunk-BGBJSMXT.js} +6 -6
  137. package/dist/{chunk-UR4HKLHW.js.map → chunk-BGBJSMXT.js.map} +1 -1
  138. package/dist/{chunk-INR6AQ54.mjs → chunk-BUDV7QHH.mjs} +4 -4
  139. package/dist/{chunk-INR6AQ54.mjs.map → chunk-BUDV7QHH.mjs.map} +1 -1
  140. package/dist/{chunk-C22WW7G2.mjs → chunk-BVLGJ2CZ.mjs} +3 -3
  141. package/dist/{chunk-C22WW7G2.mjs.map → chunk-BVLGJ2CZ.mjs.map} +1 -1
  142. package/dist/{chunk-6WJDTGM6.js → chunk-CBMHJPR7.js} +5 -5
  143. package/dist/{chunk-6WJDTGM6.js.map → chunk-CBMHJPR7.js.map} +1 -1
  144. package/dist/{chunk-H3F4GV2S.js → chunk-CGQO7MFO.js} +14 -14
  145. package/dist/{chunk-H3F4GV2S.js.map → chunk-CGQO7MFO.js.map} +1 -1
  146. package/dist/{chunk-ZXRORNAW.js → chunk-CKPFETIO.js} +4 -4
  147. package/dist/{chunk-ZXRORNAW.js.map → chunk-CKPFETIO.js.map} +1 -1
  148. package/dist/{chunk-EQZ42LAK.mjs → chunk-CYQB5GLU.mjs} +4 -4
  149. package/dist/{chunk-EQZ42LAK.mjs.map → chunk-CYQB5GLU.mjs.map} +1 -1
  150. package/dist/{chunk-6VHVIBLQ.mjs → chunk-DHXQBTXE.mjs} +62 -41
  151. package/dist/chunk-DHXQBTXE.mjs.map +1 -0
  152. package/dist/{chunk-5EFSD7VM.js → chunk-DKRXPXOR.js} +490 -20
  153. package/dist/chunk-DKRXPXOR.js.map +1 -0
  154. package/dist/chunk-DO6ATNLN.js +67 -0
  155. package/dist/chunk-DO6ATNLN.js.map +1 -0
  156. package/dist/{chunk-R6XBPA6C.mjs → chunk-DTNNZJYM.mjs} +4 -4
  157. package/dist/{chunk-R6XBPA6C.mjs.map → chunk-DTNNZJYM.mjs.map} +1 -1
  158. package/dist/{chunk-4OSZ2JD3.js → chunk-E3GHVAMK.js} +18 -18
  159. package/dist/{chunk-4OSZ2JD3.js.map → chunk-E3GHVAMK.js.map} +1 -1
  160. package/dist/{chunk-I6XKZNFT.mjs → chunk-EKTMXHBI.mjs} +3 -3
  161. package/dist/{chunk-I6XKZNFT.mjs.map → chunk-EKTMXHBI.mjs.map} +1 -1
  162. package/dist/{chunk-M52FYLV4.js → chunk-EZLK2OQL.js} +7 -7
  163. package/dist/{chunk-M52FYLV4.js.map → chunk-EZLK2OQL.js.map} +1 -1
  164. package/dist/{chunk-VLHHBJSV.js → chunk-FMOOQKZU.js} +8 -8
  165. package/dist/{chunk-VLHHBJSV.js.map → chunk-FMOOQKZU.js.map} +1 -1
  166. package/dist/{chunk-LQENHKD3.mjs → chunk-FZISCIJV.mjs} +4 -4
  167. package/dist/{chunk-LQENHKD3.mjs.map → chunk-FZISCIJV.mjs.map} +1 -1
  168. package/dist/{chunk-CQWG5ICB.js → chunk-GYAH4KFC.js} +4 -4
  169. package/dist/{chunk-CQWG5ICB.js.map → chunk-GYAH4KFC.js.map} +1 -1
  170. package/dist/{chunk-FIA3WNEM.js → chunk-GZVSGQKT.js} +3 -3
  171. package/dist/{chunk-FIA3WNEM.js.map → chunk-GZVSGQKT.js.map} +1 -1
  172. package/dist/{chunk-EUAOOOIE.js → chunk-HPIY7AR3.js} +14 -14
  173. package/dist/{chunk-EUAOOOIE.js.map → chunk-HPIY7AR3.js.map} +1 -1
  174. package/dist/chunk-HX6ZG3PP.js +19 -0
  175. package/dist/chunk-HX6ZG3PP.js.map +1 -0
  176. package/dist/{chunk-H27UCW6K.js → chunk-IQLYFQKZ.js} +15 -15
  177. package/dist/{chunk-H27UCW6K.js.map → chunk-IQLYFQKZ.js.map} +1 -1
  178. package/dist/{chunk-FBI6LYTM.js → chunk-JBGRXICL.js} +62 -41
  179. package/dist/chunk-JBGRXICL.js.map +1 -0
  180. package/dist/{chunk-E242GZNE.js → chunk-JEI3CSY4.js} +4 -4
  181. package/dist/{chunk-E242GZNE.js.map → chunk-JEI3CSY4.js.map} +1 -1
  182. package/dist/{chunk-6ABCPVJL.js → chunk-MCXHQHIX.js} +4 -4
  183. package/dist/{chunk-6ABCPVJL.js.map → chunk-MCXHQHIX.js.map} +1 -1
  184. package/dist/{chunk-JNKQKGYH.mjs → chunk-NIJVVW4G.mjs} +3 -3
  185. package/dist/{chunk-JNKQKGYH.mjs.map → chunk-NIJVVW4G.mjs.map} +1 -1
  186. package/dist/{chunk-TY3BPHTE.mjs → chunk-NSTY7ZZA.mjs} +7 -7
  187. package/dist/{chunk-TY3BPHTE.mjs.map → chunk-NSTY7ZZA.mjs.map} +1 -1
  188. package/dist/{chunk-3BXYZC3V.mjs → chunk-OAJVITNO.mjs} +3 -3
  189. package/dist/{chunk-3BXYZC3V.mjs.map → chunk-OAJVITNO.mjs.map} +1 -1
  190. package/dist/{chunk-36E6QKGL.mjs → chunk-OTHKWMDB.mjs} +3 -3
  191. package/dist/{chunk-36E6QKGL.mjs.map → chunk-OTHKWMDB.mjs.map} +1 -1
  192. package/dist/{chunk-ZWMAQ52D.mjs → chunk-ROJ25QM3.mjs} +3 -3
  193. package/dist/{chunk-ZWMAQ52D.mjs.map → chunk-ROJ25QM3.mjs.map} +1 -1
  194. package/dist/{chunk-NDS6MXIP.mjs → chunk-SXNKLHOX.mjs} +3 -3
  195. package/dist/{chunk-NDS6MXIP.mjs.map → chunk-SXNKLHOX.mjs.map} +1 -1
  196. package/dist/{chunk-VYNOQCEK.js → chunk-TAM2D54C.js} +14 -14
  197. package/dist/{chunk-VYNOQCEK.js.map → chunk-TAM2D54C.js.map} +1 -1
  198. package/dist/{chunk-VU45CH5R.mjs → chunk-TECD4AP7.mjs} +3 -3
  199. package/dist/{chunk-VU45CH5R.mjs.map → chunk-TECD4AP7.mjs.map} +1 -1
  200. package/dist/{chunk-MWKYLWCH.mjs → chunk-UMWVTIIZ.mjs} +8 -8
  201. package/dist/{chunk-MWKYLWCH.mjs.map → chunk-UMWVTIIZ.mjs.map} +1 -1
  202. package/dist/{chunk-ULP6BTN2.js → chunk-VCNPTLK2.js} +12 -12
  203. package/dist/{chunk-ULP6BTN2.js.map → chunk-VCNPTLK2.js.map} +1 -1
  204. package/dist/{chunk-FPWPRFTP.js → chunk-VIIGOCX4.js} +15 -15
  205. package/dist/{chunk-FPWPRFTP.js.map → chunk-VIIGOCX4.js.map} +1 -1
  206. package/dist/{chunk-PSBAUXUH.mjs → chunk-VWVUYL5J.mjs} +4 -4
  207. package/dist/{chunk-PSBAUXUH.mjs.map → chunk-VWVUYL5J.mjs.map} +1 -1
  208. package/dist/{chunk-67MTTPJV.js → chunk-WMNRTCYY.js} +11 -11
  209. package/dist/{chunk-67MTTPJV.js.map → chunk-WMNRTCYY.js.map} +1 -1
  210. package/dist/{chunk-C3M5E4YI.js → chunk-WZMM57R2.js} +5 -5
  211. package/dist/{chunk-C3M5E4YI.js.map → chunk-WZMM57R2.js.map} +1 -1
  212. package/dist/chunk-YFX3Q56O.mjs +16 -0
  213. package/dist/chunk-YFX3Q56O.mjs.map +1 -0
  214. package/dist/chunk-YPEX4RDE.js +8 -0
  215. package/dist/{chunk-UXIUJYFK.js.map → chunk-YPEX4RDE.js.map} +1 -1
  216. package/dist/{chunk-R7V7HNJJ.js → chunk-Z33JXJTJ.js} +10 -3
  217. package/dist/chunk-Z33JXJTJ.js.map +1 -0
  218. package/dist/{chunk-X2PAODFM.mjs → chunk-ZFZMN4LT.mjs} +3 -3
  219. package/dist/{chunk-X2PAODFM.mjs.map → chunk-ZFZMN4LT.mjs.map} +1 -1
  220. package/dist/cli/index.js +7 -27
  221. package/dist/cli/index.js.map +1 -1
  222. package/dist/cli/index.mjs +5 -25
  223. package/dist/cli/index.mjs.map +1 -1
  224. package/dist/client/index.js +4 -4
  225. package/dist/client/index.mjs +3 -3
  226. package/dist/commerce/index.js +56 -56
  227. package/dist/commerce/index.mjs +5 -5
  228. package/dist/commerce/server-result.test.d.ts +2 -0
  229. package/dist/commerce/server-result.test.d.ts.map +1 -0
  230. package/dist/commerce/server.d.ts +51 -0
  231. package/dist/commerce/server.d.ts.map +1 -1
  232. package/dist/commerce/server.js +57 -24
  233. package/dist/commerce/server.js.map +1 -1
  234. package/dist/commerce/server.mjs +54 -25
  235. package/dist/commerce/server.mjs.map +1 -1
  236. package/dist/engage/index.js +10 -10
  237. package/dist/engage/index.mjs +7 -7
  238. package/dist/fleet/index.js +8 -8
  239. package/dist/fleet/index.mjs +4 -4
  240. package/dist/forms/index.js +16 -16
  241. package/dist/forms/index.mjs +9 -9
  242. package/dist/forms/server.js +10 -10
  243. package/dist/forms/server.mjs +8 -8
  244. package/dist/forms/static.js +7 -7
  245. package/dist/forms/static.mjs +6 -6
  246. package/dist/images/index.js +11 -11
  247. package/dist/images/index.mjs +4 -4
  248. package/dist/index.js +63 -63
  249. package/dist/index.mjs +9 -9
  250. package/dist/layout/client.js +8 -8
  251. package/dist/layout/client.mjs +7 -7
  252. package/dist/layout/index.js +10 -10
  253. package/dist/layout/index.mjs +8 -8
  254. package/dist/llms/generateLLMsTxt.d.ts.map +1 -1
  255. package/dist/llms/humanize-industry.d.ts +9 -0
  256. package/dist/llms/humanize-industry.d.ts.map +1 -0
  257. package/dist/llms/humanize-industry.test.d.ts +2 -0
  258. package/dist/llms/humanize-industry.test.d.ts.map +1 -0
  259. package/dist/llms/index.js +12 -12
  260. package/dist/llms/index.mjs +2 -2
  261. package/dist/maps/index.js +5 -5
  262. package/dist/maps/index.mjs +3 -3
  263. package/dist/search/index.js +4 -4
  264. package/dist/search/index.mjs +3 -3
  265. package/dist/seo/client.js +5 -5
  266. package/dist/seo/client.mjs +4 -4
  267. package/dist/seo/index.js +5 -5
  268. package/dist/seo/index.mjs +4 -4
  269. package/dist/server/index.js +3 -3
  270. package/dist/server/index.mjs +2 -2
  271. package/dist/shared/version.d.ts +1 -1
  272. package/dist/signal/index.js +11 -11
  273. package/dist/signal/index.mjs +2 -2
  274. package/dist/sitemap/index.js +2 -2
  275. package/dist/sitemap/index.mjs +1 -1
  276. package/dist/sync/index.js +16 -16
  277. package/dist/sync/index.mjs +4 -4
  278. package/package.json +1 -1
  279. package/dist/AnalyticsProvider-DNMYYBKX.js +0 -31
  280. package/dist/AnalyticsProvider-TWRQHKPZ.mjs +0 -10
  281. package/dist/ChatWidget-MDWEXISQ.js +0 -20
  282. package/dist/ChatWidget-UQMEJAHY.mjs +0 -11
  283. package/dist/EngageWidget-UIIN43ZU.mjs +0 -9
  284. package/dist/EngageWidget-VRC7NUG6.js +0 -18
  285. package/dist/ManagedForm-7L2W5BBZ.js +0 -23
  286. package/dist/ManagedForm-D7CFOIXH.mjs +0 -14
  287. package/dist/SitemapSync-RFY6PUG7.mjs +0 -8
  288. package/dist/SitemapSync-SR6OJRIA.js +0 -17
  289. package/dist/chunk-5EFSD7VM.js.map +0 -1
  290. package/dist/chunk-6VHVIBLQ.mjs.map +0 -1
  291. package/dist/chunk-D4KHH44S.mjs.map +0 -1
  292. package/dist/chunk-FBI6LYTM.js.map +0 -1
  293. package/dist/chunk-JJS63TDR.mjs.map +0 -1
  294. package/dist/chunk-NQNSATTA.mjs +0 -6
  295. package/dist/chunk-R7V7HNJJ.js.map +0 -1
  296. package/dist/chunk-UXIUJYFK.js +0 -8
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/signal/SignalExperiment.tsx"],"names":[],"mappings":";;;;AAgDO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,YAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,eAAA,GAAkB,IAAA;AAAA,EAClB;AACF,CAAA,EAA0B;AACxB,EAAA,MAAM,EAAE,UAAA,EAAY,OAAA,EAAS,SAAA,EAAU,GAAI,oBAAoB,YAAY,CAAA;AAC3E,EAAA,MAAM,aAAa,cAAA,EAAe;AAGlC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,mBAAmB,OAAA,EAAS;AAC9B,MAAA,UAAA,CAAW;AAAA,QACT,UAAA,EAAY,YAAA;AAAA,QACZ,UAAA,EAAY,YAAA;AAAA,QACZ,UAAA,EAAY;AAAA,UACV,aAAA,EAAe,YAAA;AAAA,UACf,WAAA,EAAa;AAAA;AACf,OACD,CAAA;AAAA,IACH;AAAA,EACF,GAAG,CAAC,YAAA,EAAc,OAAA,EAAS,eAAA,EAAiB,UAAU,CAAC,CAAA;AAGvD,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,uBAAO,GAAA,CAAA,QAAA,EAAA,EAAG,mBAAS,EAAE,OAAA,EAAS,WAAW,SAAA,EAAW,SAAA,EAAW,CAAA,EAAE,CAAA;AAAA,EACnE;AAGA,EAAA,MAAM,kBAAkB,OAAA,IAAW,SAAA;AACnC,EAAA,MAAM,OAAA,GAAU,SAAS,eAAe,CAAA;AAExC,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,uCAAU,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,EACpB;AAGA,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,uCAAU,QAAA,EAAA,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,uBAAO,GAAA,CAAA,QAAA,EAAA,EAAG,QAAA,EAAA,QAAA,CAAS,OAAA,IAAW,IAAA,EAAK,CAAA;AACrC;AAYO,SAAS,qBAAqB,YAAA,EAAsB;AACzD,EAAA,OAAO,oBAAoB,YAAY,CAAA;AACzC;AAoBO,SAAS,oBAAA,CAAqB;AAAA,EACnC,YAAA;AAAA,EACA,WAAA,GAAc,OAAA;AAAA,EACd,KAAA;AAAA,EACA;AACF,CAAA,EAKG;AACD,EAAA,MAAM,aAAa,cAAA,EAAe;AAClC,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,mBAAA,CAAoB,YAAY,CAAA;AAEpD,EAAA,MAAM,oBAAoB,MAAM;AAC9B,IAAA,UAAA,CAAW;AAAA,MACT,UAAA,EAAY,YAAA;AAAA,MACZ,UAAA,EAAY,YAAA;AAAA,MACZ,UAAA,EAAY;AAAA,QACV,aAAA,EAAe,YAAA;AAAA,QACf,WAAA,EAAa,OAAA;AAAA,QACb,YAAA,EAAc,WAAA;AAAA,QACd;AAAA;AACF,KACD,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,OAAO,KAAA,CAAM,aAAa,QAAA,EAAU;AAAA,IAClC,OAAA,EAAS,CAAC,CAAA,KAAwB;AAChC,MAAA,iBAAA,EAAkB;AAElB,MAAA,IAAK,QAAA,CAAS,MAAsD,OAAA,EAAS;AAC3E,QAAC,QAAA,CAAS,KAAA,CAAsD,OAAA,CAAS,CAAC,CAAA;AAAA,MAC5E;AAAA,IACF;AAAA,GACD,CAAA;AACH","file":"chunk-LVM63JSA.mjs","sourcesContent":["/**\n * @sonordev/site-kit/signal - SignalExperiment\n * \n * A/B test component that renders different variants based on Signal assignment.\n * Uses Thompson Sampling (Bayesian bandit) for optimization.\n */\n\n'use client'\n\nimport React, { useMemo, useEffect } from 'react'\nimport { useSignalExperiment, useSignalEvent } from './SignalBridge'\n\ninterface SignalExperimentProps {\n /** Unique experiment ID */\n experimentId: string\n \n /** Variants to test - keys are variant names, values are React nodes */\n variants: Record<string, React.ReactNode>\n \n /** Fallback content if no assignment (defaults to 'control' variant) */\n fallback?: React.ReactNode\n \n /** Track impression automatically */\n trackImpression?: boolean\n \n /** Children function for more control */\n children?: (props: { variant: string; isControl: boolean }) => React.ReactNode\n}\n\n/**\n * Renders different content variants based on Signal's A/B assignment.\n * \n * @example\n * // Simple variant switching\n * <SignalExperiment experimentId=\"hero-cta\" variants={{\n * control: <Button>Get Started</Button>,\n * variant_a: <Button variant=\"primary\">Start Free Trial</Button>,\n * variant_b: <Button variant=\"secondary\">Book a Demo</Button>,\n * }} />\n * \n * @example\n * // With render prop for more control\n * <SignalExperiment experimentId=\"pricing-layout\">\n * {({ variant, isControl }) => (\n * <PricingSection layout={isControl ? 'cards' : 'table'} />\n * )}\n * </SignalExperiment>\n */\nexport function SignalExperiment({\n experimentId,\n variants,\n fallback,\n trackImpression = true,\n children,\n}: SignalExperimentProps) {\n const { assignment, variant, isControl } = useSignalExperiment(experimentId)\n const trackEvent = useSignalEvent()\n \n // Track impression when variant is rendered\n useEffect(() => {\n if (trackImpression && variant) {\n trackEvent({\n event_type: 'experiment',\n event_name: 'impression',\n event_data: {\n experiment_id: experimentId,\n variant_key: variant,\n },\n })\n }\n }, [experimentId, variant, trackImpression, trackEvent])\n \n // If using render prop\n if (children) {\n return <>{children({ variant: variant || 'control', isControl })}</>\n }\n \n // Determine what to render\n const selectedVariant = variant || 'control'\n const content = variants[selectedVariant]\n \n if (content !== undefined) {\n return <>{content}</>\n }\n \n // Fallback to provided fallback or control\n if (fallback) {\n return <>{fallback}</>\n }\n \n return <>{variants.control || null}</>\n}\n\n/**\n * Hook for conditional experiment logic\n * \n * @example\n * const { variant, isControl } = useExperimentVariant('pricing-test')\n * \n * return isControl \n * ? <OldPricing />\n * : <NewPricing showAnnual={variant === 'annual_first'} />\n */\nexport function useExperimentVariant(experimentId: string) {\n return useSignalExperiment(experimentId)\n}\n\n/**\n * Component for tracking experiment conversions\n * Wraps interactive elements to track when they convert\n * \n * @example\n * <SignalExperiment experimentId=\"signup-button\" variants={{\n * control: (\n * <ExperimentConversion experimentId=\"signup-button\" outcomeType=\"click\">\n * <Button>Sign Up</Button>\n * </ExperimentConversion>\n * ),\n * variant_a: (\n * <ExperimentConversion experimentId=\"signup-button\" outcomeType=\"click\">\n * <Button variant=\"large\">Join Now - It's Free!</Button>\n * </ExperimentConversion>\n * ),\n * }} />\n */\nexport function ExperimentConversion({\n experimentId,\n outcomeType = 'click',\n value,\n children,\n}: {\n experimentId: string\n outcomeType?: string\n value?: number\n children: React.ReactElement<{ onClick?: (e: React.MouseEvent) => void }>\n}) {\n const trackEvent = useSignalEvent()\n const { variant } = useSignalExperiment(experimentId)\n\n const handleInteraction = () => {\n trackEvent({\n event_type: 'experiment',\n event_name: 'conversion',\n event_data: {\n experiment_id: experimentId,\n variant_key: variant,\n outcome_type: outcomeType,\n value,\n },\n })\n }\n\n return React.cloneElement(children, {\n onClick: (e: React.MouseEvent) => {\n handleInteraction()\n // Call original onClick if exists\n if ((children.props as { onClick?: (e: React.MouseEvent) => void }).onClick) {\n (children.props as { onClick?: (e: React.MouseEvent) => void }).onClick!(e)\n }\n },\n })\n}\n"]}
1
+ {"version":3,"sources":["../src/signal/SignalExperiment.tsx"],"names":[],"mappings":";;;;AAgDO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,YAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,eAAA,GAAkB,IAAA;AAAA,EAClB;AACF,CAAA,EAA0B;AACxB,EAAA,MAAM,EAAE,UAAA,EAAY,OAAA,EAAS,SAAA,EAAU,GAAI,oBAAoB,YAAY,CAAA;AAC3E,EAAA,MAAM,aAAa,cAAA,EAAe;AAGlC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,mBAAmB,OAAA,EAAS;AAC9B,MAAA,UAAA,CAAW;AAAA,QACT,UAAA,EAAY,YAAA;AAAA,QACZ,UAAA,EAAY,YAAA;AAAA,QACZ,UAAA,EAAY;AAAA,UACV,aAAA,EAAe,YAAA;AAAA,UACf,WAAA,EAAa;AAAA;AACf,OACD,CAAA;AAAA,IACH;AAAA,EACF,GAAG,CAAC,YAAA,EAAc,OAAA,EAAS,eAAA,EAAiB,UAAU,CAAC,CAAA;AAGvD,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,uBAAO,GAAA,CAAA,QAAA,EAAA,EAAG,mBAAS,EAAE,OAAA,EAAS,WAAW,SAAA,EAAW,SAAA,EAAW,CAAA,EAAE,CAAA;AAAA,EACnE;AAGA,EAAA,MAAM,kBAAkB,OAAA,IAAW,SAAA;AACnC,EAAA,MAAM,OAAA,GAAU,SAAS,eAAe,CAAA;AAExC,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,uCAAU,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,EACpB;AAGA,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,uCAAU,QAAA,EAAA,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,uBAAO,GAAA,CAAA,QAAA,EAAA,EAAG,QAAA,EAAA,QAAA,CAAS,OAAA,IAAW,IAAA,EAAK,CAAA;AACrC;AAYO,SAAS,qBAAqB,YAAA,EAAsB;AACzD,EAAA,OAAO,oBAAoB,YAAY,CAAA;AACzC;AAoBO,SAAS,oBAAA,CAAqB;AAAA,EACnC,YAAA;AAAA,EACA,WAAA,GAAc,OAAA;AAAA,EACd,KAAA;AAAA,EACA;AACF,CAAA,EAKG;AACD,EAAA,MAAM,aAAa,cAAA,EAAe;AAClC,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,mBAAA,CAAoB,YAAY,CAAA;AAEpD,EAAA,MAAM,oBAAoB,MAAM;AAC9B,IAAA,UAAA,CAAW;AAAA,MACT,UAAA,EAAY,YAAA;AAAA,MACZ,UAAA,EAAY,YAAA;AAAA,MACZ,UAAA,EAAY;AAAA,QACV,aAAA,EAAe,YAAA;AAAA,QACf,WAAA,EAAa,OAAA;AAAA,QACb,YAAA,EAAc,WAAA;AAAA,QACd;AAAA;AACF,KACD,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,OAAO,KAAA,CAAM,aAAa,QAAA,EAAU;AAAA,IAClC,OAAA,EAAS,CAAC,CAAA,KAAwB;AAChC,MAAA,iBAAA,EAAkB;AAElB,MAAA,IAAK,QAAA,CAAS,MAAsD,OAAA,EAAS;AAC3E,QAAC,QAAA,CAAS,KAAA,CAAsD,OAAA,CAAS,CAAC,CAAA;AAAA,MAC5E;AAAA,IACF;AAAA,GACD,CAAA;AACH","file":"chunk-6YKNDQYJ.mjs","sourcesContent":["/**\n * @sonordev/site-kit/signal - SignalExperiment\n * \n * A/B test component that renders different variants based on Signal assignment.\n * Uses Thompson Sampling (Bayesian bandit) for optimization.\n */\n\n'use client'\n\nimport React, { useMemo, useEffect } from 'react'\nimport { useSignalExperiment, useSignalEvent } from './SignalBridge'\n\ninterface SignalExperimentProps {\n /** Unique experiment ID */\n experimentId: string\n \n /** Variants to test - keys are variant names, values are React nodes */\n variants: Record<string, React.ReactNode>\n \n /** Fallback content if no assignment (defaults to 'control' variant) */\n fallback?: React.ReactNode\n \n /** Track impression automatically */\n trackImpression?: boolean\n \n /** Children function for more control */\n children?: (props: { variant: string; isControl: boolean }) => React.ReactNode\n}\n\n/**\n * Renders different content variants based on Signal's A/B assignment.\n * \n * @example\n * // Simple variant switching\n * <SignalExperiment experimentId=\"hero-cta\" variants={{\n * control: <Button>Get Started</Button>,\n * variant_a: <Button variant=\"primary\">Start Free Trial</Button>,\n * variant_b: <Button variant=\"secondary\">Book a Demo</Button>,\n * }} />\n * \n * @example\n * // With render prop for more control\n * <SignalExperiment experimentId=\"pricing-layout\">\n * {({ variant, isControl }) => (\n * <PricingSection layout={isControl ? 'cards' : 'table'} />\n * )}\n * </SignalExperiment>\n */\nexport function SignalExperiment({\n experimentId,\n variants,\n fallback,\n trackImpression = true,\n children,\n}: SignalExperimentProps) {\n const { assignment, variant, isControl } = useSignalExperiment(experimentId)\n const trackEvent = useSignalEvent()\n \n // Track impression when variant is rendered\n useEffect(() => {\n if (trackImpression && variant) {\n trackEvent({\n event_type: 'experiment',\n event_name: 'impression',\n event_data: {\n experiment_id: experimentId,\n variant_key: variant,\n },\n })\n }\n }, [experimentId, variant, trackImpression, trackEvent])\n \n // If using render prop\n if (children) {\n return <>{children({ variant: variant || 'control', isControl })}</>\n }\n \n // Determine what to render\n const selectedVariant = variant || 'control'\n const content = variants[selectedVariant]\n \n if (content !== undefined) {\n return <>{content}</>\n }\n \n // Fallback to provided fallback or control\n if (fallback) {\n return <>{fallback}</>\n }\n \n return <>{variants.control || null}</>\n}\n\n/**\n * Hook for conditional experiment logic\n * \n * @example\n * const { variant, isControl } = useExperimentVariant('pricing-test')\n * \n * return isControl \n * ? <OldPricing />\n * : <NewPricing showAnnual={variant === 'annual_first'} />\n */\nexport function useExperimentVariant(experimentId: string) {\n return useSignalExperiment(experimentId)\n}\n\n/**\n * Component for tracking experiment conversions\n * Wraps interactive elements to track when they convert\n * \n * @example\n * <SignalExperiment experimentId=\"signup-button\" variants={{\n * control: (\n * <ExperimentConversion experimentId=\"signup-button\" outcomeType=\"click\">\n * <Button>Sign Up</Button>\n * </ExperimentConversion>\n * ),\n * variant_a: (\n * <ExperimentConversion experimentId=\"signup-button\" outcomeType=\"click\">\n * <Button variant=\"large\">Join Now - It's Free!</Button>\n * </ExperimentConversion>\n * ),\n * }} />\n */\nexport function ExperimentConversion({\n experimentId,\n outcomeType = 'click',\n value,\n children,\n}: {\n experimentId: string\n outcomeType?: string\n value?: number\n children: React.ReactElement<{ onClick?: (e: React.MouseEvent) => void }>\n}) {\n const trackEvent = useSignalEvent()\n const { variant } = useSignalExperiment(experimentId)\n\n const handleInteraction = () => {\n trackEvent({\n event_type: 'experiment',\n event_name: 'conversion',\n event_data: {\n experiment_id: experimentId,\n variant_key: variant,\n outcome_type: outcomeType,\n value,\n },\n })\n }\n\n return React.cloneElement(children, {\n onClick: (e: React.MouseEvent) => {\n handleInteraction()\n // Call original onClick if exists\n if ((children.props as { onClick?: (e: React.MouseEvent) => void }).onClick) {\n (children.props as { onClick?: (e: React.MouseEvent) => void }).onClick!(e)\n }\n },\n })\n}\n"]}
@@ -1,8 +1,8 @@
1
+ import { widgetStyle, widgetTitleStyle } from './chunk-YFX3Q56O.mjs';
1
2
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
3
  import { marked } from 'marked';
3
4
  import React from 'react';
4
5
 
5
- // src/blog/ServiceCallout.tsx
6
6
  var defaults = {
7
7
  featured: {
8
8
  wrapper: {
@@ -366,6 +366,27 @@ function addExternalLinkTargets(html, siteUrl) {
366
366
  });
367
367
  }
368
368
 
369
+ // src/blog/reading-time.ts
370
+ function readingTimeMinutes(post) {
371
+ const value = post.reading_time_minutes ?? post.reading_time;
372
+ return typeof value === "number" && value > 0 ? value : null;
373
+ }
374
+
375
+ // src/blog/author-social.ts
376
+ var withPrefix = (value, base) => value.startsWith("http") ? value : `${base}${value}`;
377
+ function getAuthorSocialLinks(author) {
378
+ const links = [];
379
+ const linkedin = author.linkedin_url || author.social_links?.linkedin;
380
+ if (linkedin) links.push({ label: "LinkedIn", href: withPrefix(linkedin, "https://linkedin.com/in/") });
381
+ const twitter = author.twitter_url ? author.twitter_url : author.social_links?.twitter ? withPrefix(author.social_links.twitter, "https://twitter.com/") : null;
382
+ if (twitter) links.push({ label: "Twitter", href: twitter });
383
+ const website = author.website_url || author.website;
384
+ if (website) links.push({ label: "Website", href: website });
385
+ const github = author.social_links?.github;
386
+ if (github) links.push({ label: "GitHub", href: withPrefix(github, "https://github.com/") });
387
+ return links;
388
+ }
389
+
369
390
  // src/blog/blog-styles.ts
370
391
  var blogPostCss = (
371
392
  /* css */
@@ -955,7 +976,11 @@ function getClusterNav(post) {
955
976
  return {
956
977
  cluster_name: post.cluster_name || "",
957
978
  cluster_slug: post.cluster_slug || "",
958
- pillar: isPillar ? null : post.parent_pillar_slug ? { slug: post.parent_pillar_slug, title: post.parent_pillar_title || "" } : null,
979
+ pillar: isPillar ? null : post.parent_pillar_slug ? {
980
+ slug: post.parent_pillar_slug,
981
+ title: post.parent_pillar_title || "",
982
+ category: post.parent_pillar_category || void 0
983
+ } : null,
959
984
  siblings: post.sibling_articles || [],
960
985
  is_pillar: isPillar
961
986
  };
@@ -1080,14 +1105,19 @@ async function BlogPost({
1080
1105
  ...item,
1081
1106
  answer: addExternalLinkTargets(item.answer || "", siteUrlResolved)
1082
1107
  })) ?? faqRaw;
1108
+ const { BlogViewTracker } = await import('./BlogViewTracker-HG25ONRP.mjs');
1083
1109
  if (children) {
1084
- return children({ post, tableOfContents, relatedPosts });
1110
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1111
+ /* @__PURE__ */ jsx(BlogViewTracker, { slug: post.slug }),
1112
+ children({ post, tableOfContents, relatedPosts })
1113
+ ] });
1085
1114
  }
1086
1115
  const { BlogPostFaqSection } = await import('./BlogPostFaqSection-P3GXVQPA.mjs');
1087
1116
  const date = post.published_at ? new Date(post.published_at).toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" }) : null;
1088
1117
  const hasToc = showToc && tableOfContents.length > 0;
1089
1118
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1090
1119
  !unstyled && /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: blogPostCss } }),
1120
+ /* @__PURE__ */ jsx(BlogViewTracker, { slug: post.slug }),
1091
1121
  /* @__PURE__ */ jsxs("article", { className: cls(unstyled, styles, "article", "sk-blog-article", className), children: [
1092
1122
  /* @__PURE__ */ jsxs("header", { className: cls(unstyled, styles, "header", "sk-blog-header"), children: [
1093
1123
  /* @__PURE__ */ jsxs("nav", { className: cls(unstyled, styles, "breadcrumb", "sk-blog-breadcrumb"), children: [
@@ -1113,9 +1143,9 @@ async function BlogPost({
1113
1143
  ] }),
1114
1144
  post.author && date && /* @__PURE__ */ jsx("span", { className: "sk-blog-meta-dot" }),
1115
1145
  date && /* @__PURE__ */ jsx("span", { className: cls(unstyled, styles, "metaItem", "sk-blog-meta-item"), children: date }),
1116
- date && post.reading_time_minutes && /* @__PURE__ */ jsx("span", { className: "sk-blog-meta-dot" }),
1117
- post.reading_time_minutes && /* @__PURE__ */ jsxs("span", { className: cls(unstyled, styles, "metaItem", "sk-blog-meta-item"), children: [
1118
- post.reading_time_minutes,
1146
+ date && readingTimeMinutes(post) && /* @__PURE__ */ jsx("span", { className: "sk-blog-meta-dot" }),
1147
+ readingTimeMinutes(post) && /* @__PURE__ */ jsxs("span", { className: cls(unstyled, styles, "metaItem", "sk-blog-meta-item"), children: [
1148
+ readingTimeMinutes(post),
1119
1149
  " min read"
1120
1150
  ] })
1121
1151
  ] })
@@ -1150,7 +1180,7 @@ async function BlogPost({
1150
1180
  ] }),
1151
1181
  post.tags && post.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: cls(unstyled, styles, "tags", "sk-blog-tags"), children: post.tags.map((tag, index) => {
1152
1182
  const tagName = typeof tag === "string" ? tag : tag?.name || "";
1153
- return /* @__PURE__ */ jsxs("a", { href: `${basePath}?tag=${tagName}`, className: cls(unstyled, styles, "tag", "sk-blog-tag"), children: [
1183
+ return /* @__PURE__ */ jsxs("a", { href: `${basePath}?tag=${encodeURIComponent(tagName)}`, className: cls(unstyled, styles, "tag", "sk-blog-tag"), children: [
1154
1184
  "#",
1155
1185
  tagName
1156
1186
  ] }, `${tagName}-${index}`);
@@ -1214,27 +1244,39 @@ function normalizeAuthorForDisplay(author) {
1214
1244
  slug: a.slug ?? "author",
1215
1245
  bio: a.bio ?? void 0,
1216
1246
  avatar_url: a.avatar_url ?? a.image ?? a.image_url ?? void 0,
1217
- email: a.email ?? void 0,
1218
1247
  website: a.website ?? a.url ?? void 0,
1219
1248
  social_links: a.social_links,
1249
+ // Real API columns (blog_authors) — previously dropped here, so
1250
+ // AuthorSection could never render socials from a live author row.
1251
+ linkedin_url: a.linkedin_url ?? void 0,
1252
+ twitter_url: a.twitter_url ?? void 0,
1253
+ website_url: a.website_url ?? void 0,
1254
+ same_as: a.same_as ?? void 0,
1220
1255
  is_active: a.is_active ?? true,
1221
- ...a.socialProfiles?.length ? { sameAs: a.socialProfiles } : {},
1256
+ ...normalizeSocialProfiles(a.socialProfiles).length ? { sameAs: normalizeSocialProfiles(a.socialProfiles) } : {},
1222
1257
  ...a.title ? { title: a.title } : {}
1223
1258
  };
1224
1259
  }
1260
+ function normalizeSocialProfiles(value) {
1261
+ if (Array.isArray(value)) return value.filter((v) => typeof v === "string" && !!v);
1262
+ if (value && typeof value === "object") {
1263
+ return Object.values(value).filter(
1264
+ (v) => typeof v === "string" && !!v
1265
+ );
1266
+ }
1267
+ return [];
1268
+ }
1225
1269
  function AuthorSection({ author, className, unstyled = false }) {
1226
1270
  const base = unstyled ? className : className || "sk-blog-author";
1271
+ const socialLinks = getAuthorSocialLinks(author);
1227
1272
  return /* @__PURE__ */ jsxs("section", { className: base || void 0, children: [
1228
1273
  author.avatar_url && /* @__PURE__ */ jsx("img", { src: author.avatar_url, alt: author.name, className: unstyled ? void 0 : "sk-blog-author-avatar" }),
1229
1274
  /* @__PURE__ */ jsxs("div", { children: [
1230
1275
  /* @__PURE__ */ jsx("h3", { className: unstyled ? void 0 : "sk-blog-author-name", children: author.name }),
1231
1276
  "title" in author && author.title && /* @__PURE__ */ jsx("p", { className: unstyled ? void 0 : "sk-blog-author-title", children: author.title }),
1232
1277
  author.bio && /* @__PURE__ */ jsx("p", { className: unstyled ? void 0 : "sk-blog-author-bio", children: author.bio }),
1233
- author.social_links && /* @__PURE__ */ jsxs("div", { className: unstyled ? void 0 : "sk-blog-author-links", children: [
1234
- author.social_links.twitter && /* @__PURE__ */ jsx("a", { href: `https://twitter.com/${author.social_links.twitter}`, target: "_blank", rel: "noopener noreferrer", children: "Twitter" }),
1235
- author.social_links.linkedin && /* @__PURE__ */ jsx("a", { href: author.social_links.linkedin, target: "_blank", rel: "noopener noreferrer", children: "LinkedIn" })
1236
- ] }),
1237
- "sameAs" in author && author.sameAs && author.sameAs.length > 0 && !author.social_links && /* @__PURE__ */ jsx("div", { className: unstyled ? void 0 : "sk-blog-author-links", children: author.sameAs.map((url, i) => /* @__PURE__ */ jsx("a", { href: url, target: "_blank", rel: "noopener noreferrer", children: "Profile" }, i)) })
1278
+ socialLinks.length > 0 && /* @__PURE__ */ jsx("div", { className: unstyled ? void 0 : "sk-blog-author-links", children: socialLinks.map((link) => /* @__PURE__ */ jsx("a", { href: link.href, target: "_blank", rel: "noopener noreferrer", children: link.label }, link.label)) }),
1279
+ "sameAs" in author && author.sameAs && author.sameAs.length > 0 && socialLinks.length === 0 && /* @__PURE__ */ jsx("div", { className: unstyled ? void 0 : "sk-blog-author-links", children: author.sameAs.map((url, i) => /* @__PURE__ */ jsx("a", { href: url, target: "_blank", rel: "noopener noreferrer", children: "Profile" }, i)) })
1238
1280
  ] })
1239
1281
  ] });
1240
1282
  }
@@ -1247,6 +1289,7 @@ async function fetchBlogList(params) {
1247
1289
  author,
1248
1290
  featured,
1249
1291
  search,
1292
+ cluster,
1250
1293
  page = 1,
1251
1294
  perPage = 12,
1252
1295
  orderBy = "published_at",
@@ -1258,7 +1301,7 @@ async function fetchBlogList(params) {
1258
1301
  if (author) queryParams.set("author", author);
1259
1302
  if (featured) queryParams.set("featured", "true");
1260
1303
  if (search) queryParams.set("search", search);
1261
- if (params.cluster) queryParams.set("cluster", params.cluster);
1304
+ if (cluster) queryParams.set("cluster", cluster);
1262
1305
  queryParams.set("page", String(page));
1263
1306
  queryParams.set("per_page", String(perPage));
1264
1307
  queryParams.set("order_by", orderBy);
@@ -1319,6 +1362,7 @@ async function BlogList({
1319
1362
  author,
1320
1363
  featured,
1321
1364
  search,
1365
+ cluster,
1322
1366
  page = 1,
1323
1367
  perPage = 12,
1324
1368
  orderBy = "published_at",
@@ -1337,7 +1381,7 @@ async function BlogList({
1337
1381
  return null;
1338
1382
  }
1339
1383
  const [blogData, categories] = await Promise.all([
1340
- fetchBlogList({ apiUrl, apiKey, category, tag, author, featured, search, page, perPage, orderBy, order }),
1384
+ fetchBlogList({ apiUrl, apiKey, category, tag, author, featured, search, cluster, page, perPage, orderBy, order }),
1341
1385
  showCategoryFilter ? fetchCategories(apiUrl, apiKey) : Promise.resolve([])
1342
1386
  ]);
1343
1387
  if (children) {
@@ -1428,8 +1472,8 @@ function BlogPostCard({ post, basePath, styles = {}, unstyled = false }) {
1428
1472
  "By ",
1429
1473
  typeof post.author === "string" ? post.author : post.author.name
1430
1474
  ] }),
1431
- post.reading_time_minutes && /* @__PURE__ */ jsxs("span", { className: cls2(unstyled, styles, "cardReadingTime", ""), children: [
1432
- post.reading_time_minutes,
1475
+ readingTimeMinutes(post) && /* @__PURE__ */ jsxs("span", { className: cls2(unstyled, styles, "cardReadingTime", ""), children: [
1476
+ readingTimeMinutes(post),
1433
1477
  " min read"
1434
1478
  ] })
1435
1479
  ] })
@@ -1442,7 +1486,425 @@ function buildPaginationUrl(basePath, page, category) {
1442
1486
  if (category) params.set("category", category);
1443
1487
  return `${basePath}?${params}`;
1444
1488
  }
1489
+ async function fetchRecentPosts(apiUrl, apiKey, limit = 5) {
1490
+ try {
1491
+ const response = await fetch(`${apiUrl}/public/blog/recent?limit=${limit}`, {
1492
+ headers: { "x-api-key": apiKey },
1493
+ next: { revalidate: 300 }
1494
+ });
1495
+ if (!response.ok) return [];
1496
+ const data = await response.json();
1497
+ return data.posts || [];
1498
+ } catch (error) {
1499
+ console.error("[Blog] Error fetching recent posts:", error);
1500
+ return [];
1501
+ }
1502
+ }
1503
+ async function fetchCategories2(apiUrl, apiKey) {
1504
+ try {
1505
+ const response = await fetch(`${apiUrl}/public/blog/categories`, {
1506
+ headers: { "x-api-key": apiKey },
1507
+ next: { revalidate: 300 }
1508
+ });
1509
+ if (!response.ok) return [];
1510
+ const data = await response.json();
1511
+ return data.categories || [];
1512
+ } catch (error) {
1513
+ console.error("[Blog] Error fetching categories:", error);
1514
+ return [];
1515
+ }
1516
+ }
1517
+ async function fetchTags(apiUrl, apiKey) {
1518
+ try {
1519
+ const response = await fetch(`${apiUrl}/public/blog/tags`, {
1520
+ headers: { "x-api-key": apiKey },
1521
+ next: { revalidate: 300 }
1522
+ });
1523
+ if (!response.ok) return [];
1524
+ const data = await response.json();
1525
+ return data.tags || [];
1526
+ } catch (error) {
1527
+ console.error("[Blog] Error fetching tags:", error);
1528
+ return [];
1529
+ }
1530
+ }
1531
+ async function BlogSidebar({
1532
+ apiUrl = process.env.SONOR_API_URL || "https://api.sonor.io",
1533
+ apiKey = process.env.SONOR_API_KEY || "",
1534
+ showCategories = true,
1535
+ showRecentPosts = true,
1536
+ recentPostsCount = 5,
1537
+ showTags = true,
1538
+ showSearch = true,
1539
+ basePath = "/blog",
1540
+ className,
1541
+ currentCategory,
1542
+ children
1543
+ }) {
1544
+ if (!apiKey) {
1545
+ console.warn("[Blog] No API key configured for sidebar");
1546
+ return null;
1547
+ }
1548
+ const [categories, recentPosts, tags] = await Promise.all([
1549
+ showCategories ? fetchCategories2(apiUrl, apiKey) : Promise.resolve([]),
1550
+ showRecentPosts ? fetchRecentPosts(apiUrl, apiKey, recentPostsCount) : Promise.resolve([]),
1551
+ showTags ? fetchTags(apiUrl, apiKey) : Promise.resolve([])
1552
+ ]);
1553
+ return /* @__PURE__ */ jsxs("aside", { className, style: { display: "flex", flexDirection: "column", gap: 32 }, children: [
1554
+ showSearch && /* @__PURE__ */ jsx(SearchWidget, { basePath }),
1555
+ showCategories && categories.length > 0 && /* @__PURE__ */ jsx(
1556
+ CategoriesWidget,
1557
+ {
1558
+ categories,
1559
+ basePath,
1560
+ currentCategory
1561
+ }
1562
+ ),
1563
+ showRecentPosts && recentPosts.length > 0 && /* @__PURE__ */ jsx(RecentPostsWidget, { posts: recentPosts, basePath }),
1564
+ showTags && tags.length > 0 && /* @__PURE__ */ jsx(TagsWidget, { tags, basePath }),
1565
+ children
1566
+ ] });
1567
+ }
1568
+ function SearchWidget({ basePath }) {
1569
+ return /* @__PURE__ */ jsxs("div", { style: widgetStyle, children: [
1570
+ /* @__PURE__ */ jsx("h4", { style: widgetTitleStyle, children: "Search" }),
1571
+ /* @__PURE__ */ jsx("form", { action: basePath, method: "get", children: /* @__PURE__ */ jsx(
1572
+ "input",
1573
+ {
1574
+ type: "search",
1575
+ name: "search",
1576
+ placeholder: "Search posts...",
1577
+ style: {
1578
+ width: "100%",
1579
+ padding: "10px 12px",
1580
+ border: "1px solid var(--sk-border)",
1581
+ borderRadius: 8,
1582
+ fontSize: 14
1583
+ }
1584
+ }
1585
+ ) })
1586
+ ] });
1587
+ }
1588
+ function CategoriesWidget({
1589
+ categories,
1590
+ basePath,
1591
+ currentCategory
1592
+ }) {
1593
+ return /* @__PURE__ */ jsxs("div", { style: widgetStyle, children: [
1594
+ /* @__PURE__ */ jsx("h4", { style: widgetTitleStyle, children: "Categories" }),
1595
+ /* @__PURE__ */ jsxs("ul", { style: { listStyle: "none", margin: 0, padding: 0 }, children: [
1596
+ /* @__PURE__ */ jsx("li", { style: { marginBottom: 8 }, children: /* @__PURE__ */ jsx(
1597
+ "a",
1598
+ {
1599
+ href: basePath,
1600
+ style: {
1601
+ ...categoryLinkStyle,
1602
+ fontWeight: !currentCategory ? 600 : 400,
1603
+ color: !currentCategory ? "var(--sk-primary)" : "var(--sk-text-primary)"
1604
+ },
1605
+ children: "All Posts"
1606
+ }
1607
+ ) }),
1608
+ categories.map((cat) => /* @__PURE__ */ jsx("li", { style: { marginBottom: 8 }, children: /* @__PURE__ */ jsxs(
1609
+ "a",
1610
+ {
1611
+ href: `${basePath}?category=${cat.slug}`,
1612
+ style: {
1613
+ ...categoryLinkStyle,
1614
+ fontWeight: currentCategory === cat.slug ? 600 : 400,
1615
+ color: currentCategory === cat.slug ? "var(--sk-primary)" : "var(--sk-text-primary)"
1616
+ },
1617
+ children: [
1618
+ cat.name,
1619
+ /* @__PURE__ */ jsxs("span", { style: { color: "var(--sk-text-tertiary)", marginLeft: 8 }, children: [
1620
+ "(",
1621
+ cat.post_count,
1622
+ ")"
1623
+ ] })
1624
+ ]
1625
+ }
1626
+ ) }, cat.slug))
1627
+ ] })
1628
+ ] });
1629
+ }
1630
+ function RecentPostsWidget({
1631
+ posts,
1632
+ basePath
1633
+ }) {
1634
+ return /* @__PURE__ */ jsxs("div", { style: widgetStyle, children: [
1635
+ /* @__PURE__ */ jsx("h4", { style: widgetTitleStyle, children: "Recent Posts" }),
1636
+ /* @__PURE__ */ jsx("ul", { style: { listStyle: "none", margin: 0, padding: 0 }, children: posts.map((post) => {
1637
+ const date = post.published_at ? new Date(post.published_at).toLocaleDateString("en-US", {
1638
+ month: "short",
1639
+ day: "numeric"
1640
+ }) : null;
1641
+ return /* @__PURE__ */ jsx(
1642
+ "li",
1643
+ {
1644
+ style: {
1645
+ marginBottom: 16,
1646
+ paddingBottom: 16,
1647
+ borderBottom: "1px solid var(--sk-border)"
1648
+ },
1649
+ children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 12 }, children: [
1650
+ post.featured_image && /* @__PURE__ */ jsx("a", { href: `${basePath}/${post.slug}`, children: /* @__PURE__ */ jsx(
1651
+ "img",
1652
+ {
1653
+ src: post.featured_image,
1654
+ alt: "",
1655
+ style: {
1656
+ width: 64,
1657
+ height: 48,
1658
+ objectFit: "cover",
1659
+ borderRadius: 6,
1660
+ flexShrink: 0
1661
+ }
1662
+ }
1663
+ ) }),
1664
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
1665
+ /* @__PURE__ */ jsx(
1666
+ "a",
1667
+ {
1668
+ href: `${basePath}/${post.slug}`,
1669
+ style: {
1670
+ fontSize: 14,
1671
+ fontWeight: 500,
1672
+ color: "var(--sk-text-primary)",
1673
+ textDecoration: "none",
1674
+ display: "-webkit-box",
1675
+ WebkitLineClamp: 2,
1676
+ WebkitBoxOrient: "vertical",
1677
+ overflow: "hidden"
1678
+ },
1679
+ children: post.title
1680
+ }
1681
+ ),
1682
+ date && /* @__PURE__ */ jsx("span", { style: { fontSize: 12, color: "var(--sk-text-tertiary)", display: "block", marginTop: 4 }, children: date })
1683
+ ] })
1684
+ ] })
1685
+ },
1686
+ post.id
1687
+ );
1688
+ }) })
1689
+ ] });
1690
+ }
1691
+ function TagsWidget({
1692
+ tags,
1693
+ basePath
1694
+ }) {
1695
+ return /* @__PURE__ */ jsxs("div", { style: widgetStyle, children: [
1696
+ /* @__PURE__ */ jsx("h4", { style: widgetTitleStyle, children: "Popular Tags" }),
1697
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 8 }, children: tags.slice(0, 15).map((tag) => /* @__PURE__ */ jsx(
1698
+ "a",
1699
+ {
1700
+ href: `${basePath}?tag=${encodeURIComponent(tag.name)}`,
1701
+ style: {
1702
+ padding: "4px 10px",
1703
+ backgroundColor: "var(--sk-bg-elevated)",
1704
+ borderRadius: 9999,
1705
+ fontSize: 12,
1706
+ color: "var(--sk-text-primary)",
1707
+ textDecoration: "none",
1708
+ transition: "background-color 0.2s"
1709
+ },
1710
+ children: tag.name
1711
+ },
1712
+ tag.slug
1713
+ )) })
1714
+ ] });
1715
+ }
1716
+ var categoryLinkStyle = {
1717
+ display: "flex",
1718
+ alignItems: "center",
1719
+ fontSize: 14,
1720
+ textDecoration: "none"
1721
+ };
1722
+ async function BlogLayout({
1723
+ apiUrl = process.env.SONOR_API_URL || "https://api.sonor.io",
1724
+ apiKey = process.env.SONOR_API_KEY || "",
1725
+ layout = "sidebar-right",
1726
+ showSidebar = true,
1727
+ sidebarProps = {},
1728
+ hero,
1729
+ maxWidth = 1280,
1730
+ basePath = "/blog",
1731
+ className,
1732
+ currentCategory,
1733
+ children
1734
+ }) {
1735
+ const hasSidebar = showSidebar && layout !== "full-width";
1736
+ return /* @__PURE__ */ jsxs("div", { className, children: [
1737
+ hero && /* @__PURE__ */ jsx(
1738
+ "section",
1739
+ {
1740
+ style: {
1741
+ padding: "60px 20px",
1742
+ backgroundColor: hero.backgroundColor || "var(--sk-primary)",
1743
+ backgroundImage: hero.backgroundImage ? `url(${hero.backgroundImage})` : void 0,
1744
+ backgroundSize: "cover",
1745
+ backgroundPosition: "center",
1746
+ color: "var(--sk-bg)",
1747
+ textAlign: "center"
1748
+ },
1749
+ children: /* @__PURE__ */ jsxs("div", { style: { maxWidth, margin: "0 auto" }, children: [
1750
+ hero.title && /* @__PURE__ */ jsx(
1751
+ "h1",
1752
+ {
1753
+ style: {
1754
+ fontSize: "clamp(32px, 5vw, 48px)",
1755
+ fontWeight: 700,
1756
+ marginBottom: 16
1757
+ },
1758
+ children: hero.title
1759
+ }
1760
+ ),
1761
+ hero.subtitle && /* @__PURE__ */ jsx(
1762
+ "p",
1763
+ {
1764
+ style: {
1765
+ fontSize: "clamp(16px, 2vw, 20px)",
1766
+ opacity: 0.9,
1767
+ maxWidth: 600,
1768
+ margin: "0 auto"
1769
+ },
1770
+ children: hero.subtitle
1771
+ }
1772
+ )
1773
+ ] })
1774
+ }
1775
+ ),
1776
+ /* @__PURE__ */ jsx(
1777
+ "div",
1778
+ {
1779
+ style: {
1780
+ maxWidth,
1781
+ margin: "0 auto",
1782
+ padding: "40px 20px"
1783
+ },
1784
+ children: /* @__PURE__ */ jsxs(
1785
+ "div",
1786
+ {
1787
+ style: {
1788
+ display: hasSidebar ? "grid" : "block",
1789
+ gridTemplateColumns: hasSidebar ? layout === "sidebar-left" ? "300px 1fr" : "1fr 300px" : void 0,
1790
+ gap: 48
1791
+ },
1792
+ children: [
1793
+ hasSidebar && layout === "sidebar-left" && /* @__PURE__ */ jsx(
1794
+ BlogSidebar,
1795
+ {
1796
+ apiUrl,
1797
+ apiKey,
1798
+ basePath,
1799
+ currentCategory,
1800
+ ...sidebarProps
1801
+ }
1802
+ ),
1803
+ /* @__PURE__ */ jsx("main", { style: { minWidth: 0 }, children }),
1804
+ hasSidebar && layout === "sidebar-right" && /* @__PURE__ */ jsx(
1805
+ BlogSidebar,
1806
+ {
1807
+ apiUrl,
1808
+ apiKey,
1809
+ basePath,
1810
+ currentCategory,
1811
+ ...sidebarProps
1812
+ }
1813
+ )
1814
+ ]
1815
+ }
1816
+ )
1817
+ }
1818
+ )
1819
+ ] });
1820
+ }
1821
+ async function BlogPage({ listComponent, ...layoutProps }) {
1822
+ return /* @__PURE__ */ jsx(BlogLayout, { ...layoutProps, children: listComponent });
1823
+ }
1824
+ async function BlogPostPage({ postComponent, ...layoutProps }) {
1825
+ return /* @__PURE__ */ jsx(BlogLayout, { ...layoutProps, showSidebar: false, layout: "full-width", children: /* @__PURE__ */ jsx("div", { style: { maxWidth: 800, margin: "0 auto" }, children: postComponent }) });
1826
+ }
1827
+ async function CategoryPage({
1828
+ category,
1829
+ categoryName,
1830
+ listComponent,
1831
+ hero,
1832
+ ...layoutProps
1833
+ }) {
1834
+ const categoryHero = hero || {
1835
+ title: categoryName || category,
1836
+ subtitle: `Browse all posts in ${categoryName || category}`,
1837
+ backgroundColor: "var(--sk-primary)"
1838
+ };
1839
+ return /* @__PURE__ */ jsx(BlogLayout, { ...layoutProps, hero: categoryHero, currentCategory: category, children: listComponent });
1840
+ }
1841
+ async function fetchRelatedPosts2(apiUrl, apiKey, currentPostId, limit) {
1842
+ try {
1843
+ const response = await fetch(`${apiUrl}/public/blog/related`, {
1844
+ method: "POST",
1845
+ headers: {
1846
+ "Content-Type": "application/json",
1847
+ "x-api-key": apiKey
1848
+ },
1849
+ // The controller reads snake_case `current_post_id` and looks the post
1850
+ // up by id. camelCase here meant the id arrived as undefined, the
1851
+ // lookup matched nothing, and this rendered "no related posts" as a
1852
+ // clean 200 — the silent sibling of the 404 path bug fixed above.
1853
+ body: JSON.stringify({
1854
+ current_post_id: currentPostId,
1855
+ limit
1856
+ })
1857
+ });
1858
+ if (!response.ok) {
1859
+ console.error("Failed to fetch related posts:", response.statusText);
1860
+ return [];
1861
+ }
1862
+ const data = await response.json();
1863
+ return data.posts || [];
1864
+ } catch (error) {
1865
+ console.error("Failed to fetch related posts:", error);
1866
+ return [];
1867
+ }
1868
+ }
1869
+ async function RelatedPosts({
1870
+ apiUrl = process.env.SONOR_API_URL || "https://api.sonor.io",
1871
+ apiKey = process.env.SONOR_API_KEY || "",
1872
+ currentPostId,
1873
+ limit = 3,
1874
+ className,
1875
+ renderItem
1876
+ }) {
1877
+ if (!apiKey) {
1878
+ console.warn("[Blog] No API key configured for RelatedPosts");
1879
+ return null;
1880
+ }
1881
+ const posts = await fetchRelatedPosts2(apiUrl, apiKey, currentPostId, limit);
1882
+ if (posts.length === 0) return null;
1883
+ return /* @__PURE__ */ jsxs("section", { className, children: [
1884
+ /* @__PURE__ */ jsx("h3", { style: { marginBottom: 16 }, children: "Related Posts" }),
1885
+ /* @__PURE__ */ jsx("div", { style: { display: "grid", gap: 16 }, children: posts.map(
1886
+ (post) => renderItem ? renderItem(post) : /* @__PURE__ */ jsxs("article", { style: { borderBottom: "1px solid var(--sk-border)", paddingBottom: 16 }, children: [
1887
+ post.featured_image && /* @__PURE__ */ jsx(
1888
+ "img",
1889
+ {
1890
+ src: post.featured_image,
1891
+ alt: post.title,
1892
+ style: {
1893
+ width: "100%",
1894
+ height: 120,
1895
+ objectFit: "cover",
1896
+ borderRadius: 8,
1897
+ marginBottom: 8
1898
+ }
1899
+ }
1900
+ ),
1901
+ /* @__PURE__ */ jsx("a", { href: `/blog/${post.slug}`, style: { textDecoration: "none" }, children: /* @__PURE__ */ jsx("h4", { style: { margin: 0, color: "inherit" }, children: post.title }) }),
1902
+ post.excerpt && /* @__PURE__ */ jsx("p", { style: { margin: "4px 0 0", fontSize: 14, color: "var(--sk-text-secondary)" }, children: post.excerpt })
1903
+ ] }, post.id)
1904
+ ) })
1905
+ ] });
1906
+ }
1445
1907
 
1446
- export { BlogList, BlogPost, ClusterNavigation, ServiceCallout, ServiceCallouts, addExternalLinkTargets, normalizeSiteHost, resolveBlogSiteUrl };
1447
- //# sourceMappingURL=chunk-JJS63TDR.mjs.map
1448
- //# sourceMappingURL=chunk-JJS63TDR.mjs.map
1908
+ export { BlogLayout, BlogList, BlogPage, BlogPost, BlogPostPage, BlogSidebar, CategoryPage, ClusterNavigation, RelatedPosts, ServiceCallout, ServiceCallouts, addExternalLinkTargets, getAuthorSocialLinks, normalizeSiteHost, readingTimeMinutes, resolveBlogSiteUrl };
1909
+ //# sourceMappingURL=chunk-A3VGZAZQ.mjs.map
1910
+ //# sourceMappingURL=chunk-A3VGZAZQ.mjs.map