@sonordev/site-kit 5.8.2 → 6.0.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 (545) hide show
  1. package/README.md +11 -11
  2. package/agent-manifest.json +22 -11
  3. package/dist/{AnalyticsProvider-LUEUDZZC.mjs → AnalyticsProvider-6QVM2B6O.mjs} +6 -6
  4. package/dist/{AnalyticsProvider-LUEUDZZC.mjs.map → AnalyticsProvider-6QVM2B6O.mjs.map} +1 -1
  5. package/dist/{AnalyticsProvider-4JV3OFCG.js → AnalyticsProvider-AZQXLRWN.js} +10 -10
  6. package/dist/{AnalyticsProvider-4JV3OFCG.js.map → AnalyticsProvider-AZQXLRWN.js.map} +1 -1
  7. package/dist/ArticleFaqSection-3KZ24MFS.js +13 -0
  8. package/dist/ArticleFaqSection-3KZ24MFS.js.map +1 -0
  9. package/dist/ArticleFaqSection-XZPXJVH4.mjs +11 -0
  10. package/dist/ArticleFaqSection-XZPXJVH4.mjs.map +1 -0
  11. package/dist/{BlogViewTracker-YQMTEGYZ.mjs → ArticleViewTracker-AEWJMXQQ.mjs} +13 -13
  12. package/dist/ArticleViewTracker-AEWJMXQQ.mjs.map +1 -0
  13. package/dist/{BlogViewTracker-32C4SCHA.js → ArticleViewTracker-CFBTQ46B.js} +16 -16
  14. package/dist/ArticleViewTracker-CFBTQ46B.js.map +1 -0
  15. package/dist/ChatWidget-6626OPXO.mjs +15 -0
  16. package/dist/{ChatWidget-IRTAMRQS.mjs.map → ChatWidget-6626OPXO.mjs.map} +1 -1
  17. package/dist/ChatWidget-U24AYLXF.js +24 -0
  18. package/dist/{ChatWidget-KCXQXNUF.js.map → ChatWidget-U24AYLXF.js.map} +1 -1
  19. package/dist/EngageWidget-TR47W2ZI.mjs +12 -0
  20. package/dist/{EngageWidget-7AIUJRXV.mjs.map → EngageWidget-TR47W2ZI.mjs.map} +1 -1
  21. package/dist/EngageWidget-XUTDFRF3.js +21 -0
  22. package/dist/{EngageWidget-EUUZHQOU.js.map → EngageWidget-XUTDFRF3.js.map} +1 -1
  23. package/dist/{FileField-XJYJO5HE.mjs → FileField-DNNC5IPS.mjs} +5 -5
  24. package/dist/{FileField-XJYJO5HE.mjs.map → FileField-DNNC5IPS.mjs.map} +1 -1
  25. package/dist/{FileField-SNI5XCHQ.js → FileField-R4RQG77G.js} +6 -6
  26. package/dist/{FileField-SNI5XCHQ.js.map → FileField-R4RQG77G.js.map} +1 -1
  27. package/dist/{FormSpotlight-S64G4CMM.js → FormSpotlight-7ILRAD3W.js} +9 -9
  28. package/dist/{FormSpotlight-S64G4CMM.js.map → FormSpotlight-7ILRAD3W.js.map} +1 -1
  29. package/dist/{FormSpotlight-BCXI4A4R.mjs → FormSpotlight-MXY4I46H.mjs} +3 -3
  30. package/dist/{FormSpotlight-BCXI4A4R.mjs.map → FormSpotlight-MXY4I46H.mjs.map} +1 -1
  31. package/dist/{FormStage-PX5TVY25.js → FormStage-CVD3I3SE.js} +9 -9
  32. package/dist/{FormStage-PX5TVY25.js.map → FormStage-CVD3I3SE.js.map} +1 -1
  33. package/dist/{FormStage-RHARCSPS.mjs → FormStage-FDJGRGEU.mjs} +3 -3
  34. package/dist/{FormStage-RHARCSPS.mjs.map → FormStage-FDJGRGEU.mjs.map} +1 -1
  35. package/dist/ManagedForm-5675CLWS.mjs +16 -0
  36. package/dist/{ManagedForm-7IDXBQS6.mjs.map → ManagedForm-5675CLWS.mjs.map} +1 -1
  37. package/dist/ManagedForm-KYIK54SL.js +25 -0
  38. package/dist/{ManagedForm-RI2TSUZD.js.map → ManagedForm-KYIK54SL.js.map} +1 -1
  39. package/dist/{ManagedNewsletterForm-UXBJ5OJB.mjs → ManagedNewsletterForm-DFLDGNQU.mjs} +11 -11
  40. package/dist/ManagedNewsletterForm-DFLDGNQU.mjs.map +1 -0
  41. package/dist/{ManagedNewsletterForm-IAGIHBNT.js → ManagedNewsletterForm-IH3MRJOD.js} +13 -13
  42. package/dist/ManagedNewsletterForm-IH3MRJOD.js.map +1 -0
  43. package/dist/{SignalCore-Q2BQMPCJ.js → SignalCore-6LYIZFXK.js} +11 -11
  44. package/dist/{SignalCore-Q2BQMPCJ.js.map → SignalCore-6LYIZFXK.js.map} +1 -1
  45. package/dist/{SignalCore-37WGILFY.mjs → SignalCore-ZH3R6XD3.mjs} +5 -5
  46. package/dist/{SignalCore-37WGILFY.mjs.map → SignalCore-ZH3R6XD3.mjs.map} +1 -1
  47. package/dist/SitemapSync-PKBXWVI6.mjs +9 -0
  48. package/dist/{SitemapSync-YIAI7PMT.mjs.map → SitemapSync-PKBXWVI6.mjs.map} +1 -1
  49. package/dist/SitemapSync-PZ76V5MX.js +18 -0
  50. package/dist/{SitemapSync-DWEL7HTB.js.map → SitemapSync-PZ76V5MX.js.map} +1 -1
  51. package/dist/analytics/index.js +9 -9
  52. package/dist/analytics/index.mjs +4 -4
  53. package/dist/{blog-styles-7AKRUMV7.mjs → article-styles-DACUAOVT.mjs} +124 -124
  54. package/dist/article-styles-DACUAOVT.mjs.map +1 -0
  55. package/dist/{blog-styles-6EY3BS5Y.js → article-styles-JHHTNHOK.js} +125 -125
  56. package/dist/article-styles-JHHTNHOK.js.map +1 -0
  57. package/dist/article-tables-EWXG4LNP.js +17 -0
  58. package/dist/article-tables-EWXG4LNP.js.map +1 -0
  59. package/dist/article-tables-OGE52LNT.mjs +4 -0
  60. package/dist/article-tables-OGE52LNT.mjs.map +1 -0
  61. package/dist/{blog/BlogPost.d.ts → articles/Article.d.ts} +18 -16
  62. package/dist/articles/Article.d.ts.map +1 -0
  63. package/dist/{blog/BlogFAQ.d.ts → articles/ArticleFAQ.d.ts} +6 -6
  64. package/dist/articles/ArticleFAQ.d.ts.map +1 -0
  65. package/dist/articles/ArticleFaqSection.d.ts +3 -0
  66. package/dist/articles/ArticleFaqSection.d.ts.map +1 -0
  67. package/dist/{blog/BlogList.d.ts → articles/ArticleList.d.ts} +16 -16
  68. package/dist/articles/ArticleList.d.ts.map +1 -0
  69. package/dist/{blog/BlogViewTracker.d.ts → articles/ArticleViewTracker.d.ts} +4 -4
  70. package/dist/articles/ArticleViewTracker.d.ts.map +1 -0
  71. package/dist/{blog → articles}/AuthorCard.d.ts +3 -3
  72. package/dist/articles/AuthorCard.d.ts.map +1 -0
  73. package/dist/{blog → articles}/AuthorPage.d.ts +1 -1
  74. package/dist/articles/AuthorPage.d.ts.map +1 -0
  75. package/dist/{blog → articles}/ClusterLandingPage.d.ts +6 -6
  76. package/dist/articles/ClusterLandingPage.d.ts.map +1 -0
  77. package/dist/{blog → articles}/ClusterNavigation.d.ts +5 -5
  78. package/dist/articles/ClusterNavigation.d.ts.map +1 -0
  79. package/dist/{blog → articles}/ManagedNewsletterForm.d.ts +1 -1
  80. package/dist/articles/ManagedNewsletterForm.d.ts.map +1 -0
  81. package/dist/{blog → articles}/NewsletterShell.d.ts +1 -1
  82. package/dist/articles/NewsletterShell.d.ts.map +1 -0
  83. package/dist/{blog → articles}/NewsletterWidget.d.ts +4 -4
  84. package/dist/articles/NewsletterWidget.d.ts.map +1 -0
  85. package/dist/{blog/BlogLayout.d.ts → articles/PublicationLayout.d.ts} +18 -18
  86. package/dist/articles/PublicationLayout.d.ts.map +1 -0
  87. package/dist/{blog/BlogSidebar.d.ts → articles/PublicationSidebar.d.ts} +8 -8
  88. package/dist/articles/PublicationSidebar.d.ts.map +1 -0
  89. package/dist/{blog → articles}/RelatedPosts.d.ts +6 -6
  90. package/dist/articles/RelatedPosts.d.ts.map +1 -0
  91. package/dist/{blog → articles}/ServiceCallout.d.ts +4 -4
  92. package/dist/articles/ServiceCallout.d.ts.map +1 -0
  93. package/dist/{blog → articles}/TableOfContents.d.ts +1 -1
  94. package/dist/articles/TableOfContents.d.ts.map +1 -0
  95. package/dist/{blog/blog-styles.d.ts → articles/article-styles.d.ts} +5 -5
  96. package/dist/articles/article-styles.d.ts.map +1 -0
  97. package/dist/{blog/blog-tables.d.ts → articles/article-tables.d.ts} +4 -4
  98. package/dist/articles/article-tables.d.ts.map +1 -0
  99. package/dist/articles/artwork.d.ts +14 -0
  100. package/dist/articles/artwork.d.ts.map +1 -0
  101. package/dist/{blog → articles}/author-schema.d.ts +6 -5
  102. package/dist/articles/author-schema.d.ts.map +1 -0
  103. package/dist/{blog → articles}/author-social.d.ts +2 -2
  104. package/dist/articles/author-social.d.ts.map +1 -0
  105. package/dist/{blog → articles}/excerpt.d.ts +2 -2
  106. package/dist/articles/excerpt.d.ts.map +1 -0
  107. package/dist/{blog → articles}/index.d.ts +26 -31
  108. package/dist/articles/index.d.ts.map +1 -0
  109. package/dist/{blog → articles}/index.js +39 -73
  110. package/dist/articles/index.js.map +1 -0
  111. package/dist/{blog → articles}/index.mjs +16 -17
  112. package/dist/articles/index.mjs.map +1 -0
  113. package/dist/articles/news-sitemap.d.ts +47 -0
  114. package/dist/articles/news-sitemap.d.ts.map +1 -0
  115. package/dist/{blog/processBlogHtml.d.ts → articles/processArticleHtml.d.ts} +4 -4
  116. package/dist/articles/processArticleHtml.d.ts.map +1 -0
  117. package/dist/articles/public-reads.d.ts +27 -0
  118. package/dist/articles/public-reads.d.ts.map +1 -0
  119. package/dist/{blog → articles}/reading-time.d.ts +2 -2
  120. package/dist/articles/reading-time.d.ts.map +1 -0
  121. package/dist/{blog → articles}/routes.d.ts +16 -12
  122. package/dist/articles/routes.d.ts.map +1 -0
  123. package/dist/{blog → articles}/server-core.d.ts +94 -81
  124. package/dist/articles/server-core.d.ts.map +1 -0
  125. package/dist/articles/server-ui.d.ts +29 -0
  126. package/dist/articles/server-ui.d.ts.map +1 -0
  127. package/dist/{chunk-KPWK23G7.js → articles/server-ui.js} +378 -499
  128. package/dist/articles/server-ui.js.map +1 -0
  129. package/dist/{chunk-RA4DCRMR.mjs → articles/server-ui.mjs} +328 -474
  130. package/dist/articles/server-ui.mjs.map +1 -0
  131. package/dist/{blog → articles}/server.d.ts +94 -81
  132. package/dist/articles/server.d.ts.map +1 -0
  133. package/dist/articles/server.js +236 -0
  134. package/dist/articles/server.mjs +11 -0
  135. package/dist/{blog → articles}/types.d.ts +34 -34
  136. package/dist/articles/types.d.ts.map +1 -0
  137. package/dist/articles/widget-styles.d.ts +9 -0
  138. package/dist/articles/widget-styles.d.ts.map +1 -0
  139. package/dist/brand/extract-brand-profile.d.ts +1 -1
  140. package/dist/{chunk-DTWR7VRQ.js → chunk-254IW4FC.js} +9 -9
  141. package/dist/{chunk-DTWR7VRQ.js.map → chunk-254IW4FC.js.map} +1 -1
  142. package/dist/chunk-2KRAY5NC.mjs +6 -0
  143. package/dist/{chunk-TAPCWMBV.mjs.map → chunk-2KRAY5NC.mjs.map} +1 -1
  144. package/dist/{chunk-X6NPTILR.mjs → chunk-2WEBUZNP.mjs} +3 -3
  145. package/dist/{chunk-X6NPTILR.mjs.map → chunk-2WEBUZNP.mjs.map} +1 -1
  146. package/dist/{chunk-3EXBBFXX.mjs → chunk-2YSB4FIC.mjs} +4 -4
  147. package/dist/{chunk-3EXBBFXX.mjs.map → chunk-2YSB4FIC.mjs.map} +1 -1
  148. package/dist/{chunk-GDH42JAS.js → chunk-3GHPFLEH.js} +15 -15
  149. package/dist/{chunk-GDH42JAS.js.map → chunk-3GHPFLEH.js.map} +1 -1
  150. package/dist/{chunk-QWXTQC3N.js → chunk-3LCJJ6Y6.js} +3 -3
  151. package/dist/{chunk-QWXTQC3N.js.map → chunk-3LCJJ6Y6.js.map} +1 -1
  152. package/dist/{chunk-YVQNOB3Q.mjs → chunk-3OCXVTN5.mjs} +3 -3
  153. package/dist/{chunk-YVQNOB3Q.mjs.map → chunk-3OCXVTN5.mjs.map} +1 -1
  154. package/dist/chunk-3T2CVHFO.mjs +453 -0
  155. package/dist/chunk-3T2CVHFO.mjs.map +1 -0
  156. package/dist/{chunk-ZDXY44FH.js → chunk-3U5SVB4W.js} +4 -4
  157. package/dist/{chunk-ZDXY44FH.js.map → chunk-3U5SVB4W.js.map} +1 -1
  158. package/dist/{chunk-I3ND4XYW.js → chunk-4BEGKFMN.js} +8 -8
  159. package/dist/{chunk-I3ND4XYW.js.map → chunk-4BEGKFMN.js.map} +1 -1
  160. package/dist/{chunk-YFX3Q56O.mjs → chunk-4KAMU5HD.mjs} +3 -3
  161. package/dist/chunk-4KAMU5HD.mjs.map +1 -0
  162. package/dist/{chunk-ZPLN537Q.mjs → chunk-4WCA2HM6.mjs} +2 -2
  163. package/dist/chunk-4WCA2HM6.mjs.map +1 -0
  164. package/dist/{chunk-PXWYMOZY.js → chunk-5DSUPTBU.js} +13 -13
  165. package/dist/{chunk-PXWYMOZY.js.map → chunk-5DSUPTBU.js.map} +1 -1
  166. package/dist/{chunk-GHECYDSZ.mjs → chunk-5F2FIM5A.mjs} +16 -15
  167. package/dist/chunk-5F2FIM5A.mjs.map +1 -0
  168. package/dist/{chunk-Y5QZPUL3.mjs → chunk-5YVQWLSQ.mjs} +5 -5
  169. package/dist/chunk-5YVQWLSQ.mjs.map +1 -0
  170. package/dist/chunk-6DCAMW62.mjs +55 -0
  171. package/dist/chunk-6DCAMW62.mjs.map +1 -0
  172. package/dist/{chunk-Q2NBD54V.js → chunk-7THQ4UW3.js} +2 -2
  173. package/dist/chunk-7THQ4UW3.js.map +1 -0
  174. package/dist/{chunk-6FTC6EYD.mjs → chunk-7TKSRUQU.mjs} +7 -7
  175. package/dist/{chunk-6FTC6EYD.mjs.map → chunk-7TKSRUQU.mjs.map} +1 -1
  176. package/dist/{chunk-4TLFZ6NR.mjs → chunk-AS2HUIDW.mjs} +3 -3
  177. package/dist/chunk-AS2HUIDW.mjs.map +1 -0
  178. package/dist/{chunk-YN7QHLWF.js → chunk-BBBJHYPH.js} +5 -5
  179. package/dist/chunk-BBBJHYPH.js.map +1 -0
  180. package/dist/{chunk-3Y7IKQDD.js → chunk-BZG34WHF.js} +14 -14
  181. package/dist/{chunk-3Y7IKQDD.js.map → chunk-BZG34WHF.js.map} +1 -1
  182. package/dist/{chunk-4LYW6PMU.mjs → chunk-C2CTLLIO.mjs} +3 -3
  183. package/dist/chunk-C2CTLLIO.mjs.map +1 -0
  184. package/dist/{chunk-O237KKCX.mjs → chunk-C5VITBN7.mjs} +5 -5
  185. package/dist/chunk-C5VITBN7.mjs.map +1 -0
  186. package/dist/{chunk-75A4KY4X.mjs → chunk-CFRJ2MK5.mjs} +2 -2
  187. package/dist/chunk-CFRJ2MK5.mjs.map +1 -0
  188. package/dist/{chunk-G2WC3CXW.js → chunk-CLO3K7PF.js} +2 -2
  189. package/dist/chunk-CLO3K7PF.js.map +1 -0
  190. package/dist/{chunk-ALVQOG4M.mjs → chunk-CSSNZGTU.mjs} +4 -4
  191. package/dist/{chunk-ALVQOG4M.mjs.map → chunk-CSSNZGTU.mjs.map} +1 -1
  192. package/dist/{chunk-U6O5NG56.js → chunk-CZGGUPPQ.js} +15 -15
  193. package/dist/{chunk-U6O5NG56.js.map → chunk-CZGGUPPQ.js.map} +1 -1
  194. package/dist/{chunk-U5WMGUDV.js → chunk-D47W5DE4.js} +4 -4
  195. package/dist/{chunk-U5WMGUDV.js.map → chunk-D47W5DE4.js.map} +1 -1
  196. package/dist/{chunk-AK6JZ3OE.mjs → chunk-EDLNMGQC.mjs} +3 -3
  197. package/dist/{chunk-DO6ATNLN.js.map → chunk-EDLNMGQC.mjs.map} +1 -1
  198. package/dist/chunk-EL74YDNX.js +8 -0
  199. package/dist/{chunk-TJVZEDE3.js.map → chunk-EL74YDNX.js.map} +1 -1
  200. package/dist/{chunk-HX6ZG3PP.js → chunk-EMHSHAVW.js} +3 -3
  201. package/dist/chunk-EMHSHAVW.js.map +1 -0
  202. package/dist/{chunk-7TC3GRXQ.js → chunk-G6KQ3C3W.js} +25 -23
  203. package/dist/chunk-G6KQ3C3W.js.map +1 -0
  204. package/dist/{chunk-4PXUMDHL.mjs → chunk-GQ3SDRL6.mjs} +4 -4
  205. package/dist/{chunk-4PXUMDHL.mjs.map → chunk-GQ3SDRL6.mjs.map} +1 -1
  206. package/dist/{chunk-73EBIAF3.js → chunk-HFCQGSD2.js} +18 -18
  207. package/dist/{chunk-73EBIAF3.js.map → chunk-HFCQGSD2.js.map} +1 -1
  208. package/dist/{chunk-XZO5I4RS.mjs → chunk-HIZJD7TU.mjs} +3 -3
  209. package/dist/{chunk-XZO5I4RS.mjs.map → chunk-HIZJD7TU.mjs.map} +1 -1
  210. package/dist/{chunk-AUTJQGZ2.mjs → chunk-HOOVYWTO.mjs} +4 -4
  211. package/dist/{chunk-AUTJQGZ2.mjs.map → chunk-HOOVYWTO.mjs.map} +1 -1
  212. package/dist/{chunk-LUF22UGR.js → chunk-HX5JPNMN.js} +8 -8
  213. package/dist/{chunk-LUF22UGR.js.map → chunk-HX5JPNMN.js.map} +1 -1
  214. package/dist/chunk-HXHRS3PX.mjs +349 -0
  215. package/dist/chunk-HXHRS3PX.mjs.map +1 -0
  216. package/dist/{chunk-XBX2K3GA.js → chunk-IBJOGXQI.js} +4 -4
  217. package/dist/{chunk-XBX2K3GA.js.map → chunk-IBJOGXQI.js.map} +1 -1
  218. package/dist/{chunk-NHX6YJ7G.mjs → chunk-JMNBU2RG.mjs} +9 -9
  219. package/dist/{chunk-NHX6YJ7G.mjs.map → chunk-JMNBU2RG.mjs.map} +1 -1
  220. package/dist/{chunk-R7GHP3FY.js → chunk-JONWE26J.js} +3 -3
  221. package/dist/chunk-JONWE26J.js.map +1 -0
  222. package/dist/{chunk-HOJ4J4X2.mjs → chunk-JSXLTZUP.mjs} +6 -6
  223. package/dist/{chunk-HOJ4J4X2.mjs.map → chunk-JSXLTZUP.mjs.map} +1 -1
  224. package/dist/{chunk-5BZNVKNK.mjs → chunk-JXCMCASE.mjs} +3 -3
  225. package/dist/{chunk-5BZNVKNK.mjs.map → chunk-JXCMCASE.mjs.map} +1 -1
  226. package/dist/{chunk-F2ZFMPW4.js → chunk-KA4NNWOK.js} +10 -10
  227. package/dist/{chunk-F2ZFMPW4.js.map → chunk-KA4NNWOK.js.map} +1 -1
  228. package/dist/{chunk-K4TCEAUX.js → chunk-KR7ATPAN.js} +5 -5
  229. package/dist/chunk-KR7ATPAN.js.map +1 -0
  230. package/dist/{chunk-JLVCWC6A.mjs → chunk-KZVSB5WE.mjs} +2 -2
  231. package/dist/chunk-KZVSB5WE.mjs.map +1 -0
  232. package/dist/chunk-LWCAZDY2.js +355 -0
  233. package/dist/chunk-LWCAZDY2.js.map +1 -0
  234. package/dist/{chunk-D7CF3OPZ.js → chunk-MCG4BSRW.js} +5 -5
  235. package/dist/{chunk-D7CF3OPZ.js.map → chunk-MCG4BSRW.js.map} +1 -1
  236. package/dist/{chunk-OBNMSO66.js → chunk-MIYGP34I.js} +14 -14
  237. package/dist/{chunk-OBNMSO66.js.map → chunk-MIYGP34I.js.map} +1 -1
  238. package/dist/{chunk-PXK4WNSU.js → chunk-MS2EE6LT.js} +10 -10
  239. package/dist/{chunk-PXK4WNSU.js.map → chunk-MS2EE6LT.js.map} +1 -1
  240. package/dist/{chunk-JR2FT6T5.js → chunk-N6CB7MK7.js} +6 -6
  241. package/dist/{chunk-JR2FT6T5.js.map → chunk-N6CB7MK7.js.map} +1 -1
  242. package/dist/{chunk-LMEUYRRR.js → chunk-NAA5J2JM.js} +233 -120
  243. package/dist/chunk-NAA5J2JM.js.map +1 -0
  244. package/dist/{chunk-OE7CTIOU.mjs → chunk-NE6QGHFT.mjs} +4 -4
  245. package/dist/{chunk-OE7CTIOU.mjs.map → chunk-NE6QGHFT.mjs.map} +1 -1
  246. package/dist/{chunk-SCVSPTXJ.mjs → chunk-NR52QHOD.mjs} +3 -3
  247. package/dist/{chunk-SCVSPTXJ.mjs.map → chunk-NR52QHOD.mjs.map} +1 -1
  248. package/dist/{chunk-GQF6QAQS.js → chunk-OGNX6JT4.js} +5 -5
  249. package/dist/chunk-OGNX6JT4.js.map +1 -0
  250. package/dist/{chunk-FVW6FT6L.js → chunk-OSU4QA5M.js} +8 -8
  251. package/dist/{chunk-FVW6FT6L.js.map → chunk-OSU4QA5M.js.map} +1 -1
  252. package/dist/{chunk-RI25UGHE.mjs → chunk-PJYTYM5G.mjs} +3 -3
  253. package/dist/{chunk-RI25UGHE.mjs.map → chunk-PJYTYM5G.mjs.map} +1 -1
  254. package/dist/{chunk-DO6ATNLN.js → chunk-PRAHDLKT.js} +5 -5
  255. package/dist/chunk-PRAHDLKT.js.map +1 -0
  256. package/dist/{chunk-RQOKQC7J.mjs → chunk-QEM2F2DC.mjs} +3 -3
  257. package/dist/{chunk-RQOKQC7J.mjs.map → chunk-QEM2F2DC.mjs.map} +1 -1
  258. package/dist/{chunk-3Z3TOPND.js → chunk-QOCLSJIU.js} +3 -3
  259. package/dist/{chunk-3Z3TOPND.js.map → chunk-QOCLSJIU.js.map} +1 -1
  260. package/dist/{chunk-AHKVOYFO.mjs → chunk-QVBAAPNT.mjs} +3 -3
  261. package/dist/{chunk-AHKVOYFO.mjs.map → chunk-QVBAAPNT.mjs.map} +1 -1
  262. package/dist/{chunk-FWFJZV52.mjs → chunk-RC4L4DV2.mjs} +4 -4
  263. package/dist/{chunk-FWFJZV52.mjs.map → chunk-RC4L4DV2.mjs.map} +1 -1
  264. package/dist/{chunk-ZVI7MBVF.mjs → chunk-RDPI27TS.mjs} +12 -10
  265. package/dist/chunk-RDPI27TS.mjs.map +1 -0
  266. package/dist/{chunk-OEW2LFOV.js → chunk-RLUNEEGM.js} +4 -4
  267. package/dist/{chunk-OEW2LFOV.js.map → chunk-RLUNEEGM.js.map} +1 -1
  268. package/dist/{chunk-TCVOGK6U.mjs → chunk-RPCODOWG.mjs} +3 -3
  269. package/dist/{chunk-TCVOGK6U.mjs.map → chunk-RPCODOWG.mjs.map} +1 -1
  270. package/dist/{chunk-QK54SZPF.mjs → chunk-RZGVNDO6.mjs} +4 -4
  271. package/dist/{chunk-QK54SZPF.mjs.map → chunk-RZGVNDO6.mjs.map} +1 -1
  272. package/dist/{chunk-GKVEWOYN.js → chunk-SCRB5DZM.js} +8 -8
  273. package/dist/{chunk-GKVEWOYN.js.map → chunk-SCRB5DZM.js.map} +1 -1
  274. package/dist/{chunk-YQTE32QK.js → chunk-SG7CWD2R.js} +17 -16
  275. package/dist/chunk-SG7CWD2R.js.map +1 -0
  276. package/dist/chunk-TBXWJJGT.js +468 -0
  277. package/dist/chunk-TBXWJJGT.js.map +1 -0
  278. package/dist/{chunk-SJPI34DL.mjs → chunk-TCCGP3FT.mjs} +3 -3
  279. package/dist/{chunk-SJPI34DL.mjs.map → chunk-TCCGP3FT.mjs.map} +1 -1
  280. package/dist/{chunk-7BI2RVQD.js → chunk-TCZHRSWY.js} +4 -4
  281. package/dist/{chunk-7BI2RVQD.js.map → chunk-TCZHRSWY.js.map} +1 -1
  282. package/dist/{chunk-M45AL7EA.js → chunk-TST2IKYO.js} +14 -14
  283. package/dist/{chunk-M45AL7EA.js.map → chunk-TST2IKYO.js.map} +1 -1
  284. package/dist/{chunk-U2V542EO.mjs → chunk-UHYRVALN.mjs} +2 -2
  285. package/dist/{chunk-U2V542EO.mjs.map → chunk-UHYRVALN.mjs.map} +1 -1
  286. package/dist/{chunk-4L7OHRWB.mjs → chunk-UO6KTHBQ.mjs} +4 -4
  287. package/dist/{chunk-4L7OHRWB.mjs.map → chunk-UO6KTHBQ.mjs.map} +1 -1
  288. package/dist/{chunk-H5NBFNND.js → chunk-UZKXOZHR.js} +2 -2
  289. package/dist/chunk-UZKXOZHR.js.map +1 -0
  290. package/dist/{chunk-ZTY4YS7Q.js → chunk-VINLIMAX.js} +3 -3
  291. package/dist/{chunk-ZTY4YS7Q.js.map → chunk-VINLIMAX.js.map} +1 -1
  292. package/dist/{chunk-YC2CKOX6.js → chunk-WDEGGHTB.js} +12 -12
  293. package/dist/{chunk-YC2CKOX6.js.map → chunk-WDEGGHTB.js.map} +1 -1
  294. package/dist/{chunk-OX2GTNMB.mjs → chunk-WV5YQL3W.mjs} +3 -3
  295. package/dist/{chunk-OX2GTNMB.mjs.map → chunk-WV5YQL3W.mjs.map} +1 -1
  296. package/dist/{chunk-3EY5E35M.mjs → chunk-X3MY4PL7.mjs} +210 -107
  297. package/dist/chunk-X3MY4PL7.mjs.map +1 -0
  298. package/dist/{chunk-7SLYI62M.mjs → chunk-XKXZ4OW4.mjs} +4 -4
  299. package/dist/{chunk-7SLYI62M.mjs.map → chunk-XKXZ4OW4.mjs.map} +1 -1
  300. package/dist/{chunk-FX232N4P.mjs → chunk-XSBKR3VF.mjs} +5 -5
  301. package/dist/{chunk-FX232N4P.mjs.map → chunk-XSBKR3VF.mjs.map} +1 -1
  302. package/dist/{chunk-SEP5D4MI.js → chunk-Y2CP5J6Q.js} +2 -2
  303. package/dist/{chunk-SEP5D4MI.js.map → chunk-Y2CP5J6Q.js.map} +1 -1
  304. package/dist/{chunk-HQ2EPU5R.js → chunk-YGDQVZEL.js} +7 -7
  305. package/dist/{chunk-HQ2EPU5R.js.map → chunk-YGDQVZEL.js.map} +1 -1
  306. package/dist/{chunk-KV7XXLJV.mjs → chunk-YPGUV6BT.mjs} +3 -3
  307. package/dist/{chunk-KV7XXLJV.mjs.map → chunk-YPGUV6BT.mjs.map} +1 -1
  308. package/dist/chunk-YRCR7WY3.js +65 -0
  309. package/dist/chunk-YRCR7WY3.js.map +1 -0
  310. package/dist/{chunk-NM567VXC.mjs → chunk-YWLBQ3L5.mjs} +4 -4
  311. package/dist/{chunk-NM567VXC.mjs.map → chunk-YWLBQ3L5.mjs.map} +1 -1
  312. package/dist/{chunk-3HGHWDCY.js → chunk-YYEBFQGS.js} +4 -4
  313. package/dist/{chunk-3HGHWDCY.js.map → chunk-YYEBFQGS.js.map} +1 -1
  314. package/dist/chunk-ZL35JCDA.mjs +61 -0
  315. package/dist/chunk-ZL35JCDA.mjs.map +1 -0
  316. package/dist/chunk-ZR43XFUM.js +60 -0
  317. package/dist/chunk-ZR43XFUM.js.map +1 -0
  318. package/dist/{chunk-EZ5DX7ED.mjs → chunk-ZR4TYCQW.mjs} +3 -3
  319. package/dist/{chunk-EZ5DX7ED.mjs.map → chunk-ZR4TYCQW.mjs.map} +1 -1
  320. package/dist/cli/commands/setup.d.ts +2 -2
  321. package/dist/cli/commands/sync.d.ts +2 -2
  322. package/dist/cli/commands/sync.d.ts.map +1 -1
  323. package/dist/cli/index.js +76 -76
  324. package/dist/cli/index.mjs +29 -29
  325. package/dist/client/index.js +5 -5
  326. package/dist/client/index.mjs +4 -4
  327. package/dist/commerce/index.js +57 -57
  328. package/dist/commerce/index.mjs +5 -5
  329. package/dist/commerce/server.d.ts +1 -1
  330. package/dist/commerce/server.js +7 -7
  331. package/dist/commerce/server.js.map +1 -1
  332. package/dist/commerce/server.mjs +7 -7
  333. package/dist/commerce/server.mjs.map +1 -1
  334. package/dist/discover-LPN55L5B.js +21 -0
  335. package/dist/{discover-NGEPXZOD.js.map → discover-LPN55L5B.js.map} +1 -1
  336. package/dist/discover-QGA6QFSR.mjs +4 -0
  337. package/dist/{discover-CYXYKHZ2.mjs.map → discover-QGA6QFSR.mjs.map} +1 -1
  338. package/dist/engage/index.js +13 -13
  339. package/dist/engage/index.mjs +7 -7
  340. package/dist/fleet/contract.d.ts +1 -1
  341. package/dist/fleet/contract.js +12 -12
  342. package/dist/fleet/contract.mjs +1 -1
  343. package/dist/fleet/index.js +20 -20
  344. package/dist/fleet/index.mjs +5 -5
  345. package/dist/forms/index.js +21 -21
  346. package/dist/forms/index.mjs +10 -10
  347. package/dist/forms/server.js +10 -10
  348. package/dist/forms/server.mjs +8 -8
  349. package/dist/forms/static.js +7 -7
  350. package/dist/forms/static.mjs +6 -6
  351. package/dist/images/index.js +11 -11
  352. package/dist/images/index.mjs +4 -4
  353. package/dist/index.d.ts +2 -2
  354. package/dist/index.d.ts.map +1 -1
  355. package/dist/index.js +70 -70
  356. package/dist/index.mjs +12 -12
  357. package/dist/layout/client.js +10 -10
  358. package/dist/layout/client.mjs +9 -9
  359. package/dist/layout/index.js +12 -12
  360. package/dist/layout/index.mjs +10 -10
  361. package/dist/llms/SpeakableSchema.d.ts +1 -1
  362. package/dist/llms/SpeakableSchema.d.ts.map +1 -1
  363. package/dist/llms/client.d.ts +18 -0
  364. package/dist/llms/client.d.ts.map +1 -0
  365. package/dist/llms/client.js +66 -0
  366. package/dist/llms/client.js.map +1 -0
  367. package/dist/llms/client.mjs +5 -0
  368. package/dist/llms/client.mjs.map +1 -0
  369. package/dist/llms/generateLLMsTxt.d.ts.map +1 -1
  370. package/dist/llms/index.js +75 -478
  371. package/dist/llms/index.js.map +1 -1
  372. package/dist/llms/index.mjs +10 -455
  373. package/dist/llms/index.mjs.map +1 -1
  374. package/dist/llms/types.d.ts +7 -0
  375. package/dist/llms/types.d.ts.map +1 -1
  376. package/dist/maps/index.js +5 -5
  377. package/dist/maps/index.mjs +3 -3
  378. package/dist/og/index.js +7 -7
  379. package/dist/og/index.mjs +2 -2
  380. package/dist/og/route.d.ts +6 -6
  381. package/dist/og/route.js.map +1 -1
  382. package/dist/og/route.mjs.map +1 -1
  383. package/dist/og/wiring.d.ts +4 -4
  384. package/dist/og/wiring.d.ts.map +1 -1
  385. package/dist/proxy/index.js +5 -5
  386. package/dist/proxy/index.mjs +3 -3
  387. package/dist/redirects/index.js +10 -10
  388. package/dist/redirects/index.mjs +3 -3
  389. package/dist/redirects/not-found.js +7 -7
  390. package/dist/redirects/not-found.mjs +3 -3
  391. package/dist/robots/indexnow.d.ts +17 -0
  392. package/dist/robots/indexnow.d.ts.map +1 -0
  393. package/dist/robots/indexnow.js +39 -0
  394. package/dist/robots/indexnow.js.map +1 -0
  395. package/dist/robots/indexnow.mjs +34 -0
  396. package/dist/robots/indexnow.mjs.map +1 -0
  397. package/dist/search/contract.d.ts +1 -1
  398. package/dist/search/contract.js +3 -3
  399. package/dist/search/contract.mjs +1 -1
  400. package/dist/search/index.js +7 -7
  401. package/dist/search/index.mjs +5 -5
  402. package/dist/seo/ManagedSchema.d.ts.map +1 -1
  403. package/dist/seo/client.js +6 -6
  404. package/dist/seo/client.mjs +5 -5
  405. package/dist/seo/index.js +58 -50
  406. package/dist/seo/index.js.map +1 -1
  407. package/dist/seo/index.mjs +23 -15
  408. package/dist/seo/index.mjs.map +1 -1
  409. package/dist/seo/register-sitemap-cli.js +12 -12
  410. package/dist/seo/register-sitemap-cli.mjs +5 -5
  411. package/dist/seo/server.js +21 -21
  412. package/dist/seo/server.mjs +5 -5
  413. package/dist/server/index.js +3 -3
  414. package/dist/server/index.mjs +2 -2
  415. package/dist/{server-api-A2EFCTZX.mjs → server-api-7F5P6CSH.mjs} +6 -6
  416. package/dist/{server-api-A2EFCTZX.mjs.map → server-api-7F5P6CSH.mjs.map} +1 -1
  417. package/dist/{server-api-IWTZ7C3O.js → server-api-OC5JNK6R.js} +24 -24
  418. package/dist/{server-api-IWTZ7C3O.js.map → server-api-OC5JNK6R.js.map} +1 -1
  419. package/dist/shared/build-entries.d.ts +15 -7
  420. package/dist/shared/build-entries.d.ts.map +1 -1
  421. package/dist/shared/version.d.ts +1 -1
  422. package/dist/signal/index.js +11 -11
  423. package/dist/signal/index.mjs +2 -2
  424. package/dist/sitemap/discover.d.ts +1 -1
  425. package/dist/sitemap/index.d.ts +7 -1
  426. package/dist/sitemap/index.d.ts.map +1 -1
  427. package/dist/sitemap/index.js +47 -30
  428. package/dist/sitemap/index.js.map +1 -1
  429. package/dist/sitemap/index.mjs +26 -9
  430. package/dist/sitemap/index.mjs.map +1 -1
  431. package/dist/sitemap/shared.d.ts +1 -1
  432. package/dist/sitemap/shared.d.ts.map +1 -1
  433. package/dist/sites/site-param.d.ts +2 -2
  434. package/dist/sync/index.js +17 -17
  435. package/dist/sync/index.mjs +4 -4
  436. package/dist/types.d.ts +1 -1
  437. package/dist/types.d.ts.map +1 -1
  438. package/dist/writeLLMsTxt-ATADOUVZ.js +20 -0
  439. package/dist/writeLLMsTxt-QJFXBHZF.mjs +11 -0
  440. package/package.json +25 -14
  441. package/dist/BlogPostFaqSection-P3GXVQPA.mjs +0 -11
  442. package/dist/BlogPostFaqSection-P3GXVQPA.mjs.map +0 -1
  443. package/dist/BlogPostFaqSection-YG5J4B4U.js +0 -13
  444. package/dist/BlogPostFaqSection-YG5J4B4U.js.map +0 -1
  445. package/dist/BlogViewTracker-32C4SCHA.js.map +0 -1
  446. package/dist/BlogViewTracker-YQMTEGYZ.mjs.map +0 -1
  447. package/dist/ChatWidget-IRTAMRQS.mjs +0 -15
  448. package/dist/ChatWidget-KCXQXNUF.js +0 -24
  449. package/dist/EngageWidget-7AIUJRXV.mjs +0 -12
  450. package/dist/EngageWidget-EUUZHQOU.js +0 -21
  451. package/dist/ManagedForm-7IDXBQS6.mjs +0 -16
  452. package/dist/ManagedForm-RI2TSUZD.js +0 -25
  453. package/dist/ManagedNewsletterForm-IAGIHBNT.js.map +0 -1
  454. package/dist/ManagedNewsletterForm-UXBJ5OJB.mjs.map +0 -1
  455. package/dist/SitemapSync-DWEL7HTB.js +0 -18
  456. package/dist/SitemapSync-YIAI7PMT.mjs +0 -9
  457. package/dist/blog/AuthorCard.d.ts.map +0 -1
  458. package/dist/blog/AuthorPage.d.ts.map +0 -1
  459. package/dist/blog/BlogFAQ.d.ts.map +0 -1
  460. package/dist/blog/BlogLayout.d.ts.map +0 -1
  461. package/dist/blog/BlogList.d.ts.map +0 -1
  462. package/dist/blog/BlogPost.d.ts.map +0 -1
  463. package/dist/blog/BlogPostFaqSection.d.ts +0 -3
  464. package/dist/blog/BlogPostFaqSection.d.ts.map +0 -1
  465. package/dist/blog/BlogSidebar.d.ts.map +0 -1
  466. package/dist/blog/BlogViewTracker.d.ts.map +0 -1
  467. package/dist/blog/ClusterLandingPage.d.ts.map +0 -1
  468. package/dist/blog/ClusterNavigation.d.ts.map +0 -1
  469. package/dist/blog/ManagedNewsletterForm.d.ts.map +0 -1
  470. package/dist/blog/NewsletterShell.d.ts.map +0 -1
  471. package/dist/blog/NewsletterWidget.d.ts.map +0 -1
  472. package/dist/blog/RelatedPosts.d.ts.map +0 -1
  473. package/dist/blog/ServiceCallout.d.ts.map +0 -1
  474. package/dist/blog/TableOfContents.d.ts.map +0 -1
  475. package/dist/blog/artwork.d.ts +0 -14
  476. package/dist/blog/artwork.d.ts.map +0 -1
  477. package/dist/blog/author-schema.d.ts.map +0 -1
  478. package/dist/blog/author-social.d.ts.map +0 -1
  479. package/dist/blog/blog-styles.d.ts.map +0 -1
  480. package/dist/blog/blog-tables.d.ts.map +0 -1
  481. package/dist/blog/excerpt.d.ts.map +0 -1
  482. package/dist/blog/index.d.ts.map +0 -1
  483. package/dist/blog/index.js.map +0 -1
  484. package/dist/blog/index.mjs.map +0 -1
  485. package/dist/blog/processBlogHtml.d.ts.map +0 -1
  486. package/dist/blog/public-reads.d.ts +0 -27
  487. package/dist/blog/public-reads.d.ts.map +0 -1
  488. package/dist/blog/reading-time.d.ts.map +0 -1
  489. package/dist/blog/routes.d.ts.map +0 -1
  490. package/dist/blog/server-core.d.ts.map +0 -1
  491. package/dist/blog/server-ui.d.ts +0 -29
  492. package/dist/blog/server-ui.d.ts.map +0 -1
  493. package/dist/blog/server-ui.js +0 -267
  494. package/dist/blog/server-ui.js.map +0 -1
  495. package/dist/blog/server-ui.mjs +0 -203
  496. package/dist/blog/server-ui.mjs.map +0 -1
  497. package/dist/blog/server.d.ts.map +0 -1
  498. package/dist/blog/server.js +0 -207
  499. package/dist/blog/server.mjs +0 -10
  500. package/dist/blog/types.d.ts.map +0 -1
  501. package/dist/blog/widget-styles.d.ts +0 -9
  502. package/dist/blog/widget-styles.d.ts.map +0 -1
  503. package/dist/blog-styles-6EY3BS5Y.js.map +0 -1
  504. package/dist/blog-styles-7AKRUMV7.mjs.map +0 -1
  505. package/dist/blog-tables-DWDEWA3S.js +0 -17
  506. package/dist/blog-tables-DWDEWA3S.js.map +0 -1
  507. package/dist/blog-tables-QGIHOESZ.mjs +0 -4
  508. package/dist/blog-tables-QGIHOESZ.mjs.map +0 -1
  509. package/dist/chunk-3EY5E35M.mjs.map +0 -1
  510. package/dist/chunk-4LYW6PMU.mjs.map +0 -1
  511. package/dist/chunk-4TLFZ6NR.mjs.map +0 -1
  512. package/dist/chunk-5B4J3IBX.mjs +0 -164
  513. package/dist/chunk-5B4J3IBX.mjs.map +0 -1
  514. package/dist/chunk-75A4KY4X.mjs.map +0 -1
  515. package/dist/chunk-7TC3GRXQ.js.map +0 -1
  516. package/dist/chunk-AK6JZ3OE.mjs.map +0 -1
  517. package/dist/chunk-FHPW7XVH.js +0 -175
  518. package/dist/chunk-FHPW7XVH.js.map +0 -1
  519. package/dist/chunk-G2WC3CXW.js.map +0 -1
  520. package/dist/chunk-GHECYDSZ.mjs.map +0 -1
  521. package/dist/chunk-GQF6QAQS.js.map +0 -1
  522. package/dist/chunk-H5NBFNND.js.map +0 -1
  523. package/dist/chunk-HX6ZG3PP.js.map +0 -1
  524. package/dist/chunk-JLVCWC6A.mjs.map +0 -1
  525. package/dist/chunk-K4TCEAUX.js.map +0 -1
  526. package/dist/chunk-KPWK23G7.js.map +0 -1
  527. package/dist/chunk-LMEUYRRR.js.map +0 -1
  528. package/dist/chunk-O237KKCX.mjs.map +0 -1
  529. package/dist/chunk-Q2NBD54V.js.map +0 -1
  530. package/dist/chunk-R7GHP3FY.js.map +0 -1
  531. package/dist/chunk-RA4DCRMR.mjs.map +0 -1
  532. package/dist/chunk-TAPCWMBV.mjs +0 -6
  533. package/dist/chunk-TJVZEDE3.js +0 -8
  534. package/dist/chunk-Y5QZPUL3.mjs.map +0 -1
  535. package/dist/chunk-YFX3Q56O.mjs.map +0 -1
  536. package/dist/chunk-YN7QHLWF.js.map +0 -1
  537. package/dist/chunk-YQTE32QK.js.map +0 -1
  538. package/dist/chunk-ZPLN537Q.mjs.map +0 -1
  539. package/dist/chunk-ZVI7MBVF.mjs.map +0 -1
  540. package/dist/discover-CYXYKHZ2.mjs +0 -4
  541. package/dist/discover-NGEPXZOD.js +0 -21
  542. package/dist/writeLLMsTxt-CQ7A4AAL.js +0 -19
  543. package/dist/writeLLMsTxt-NX5MSPYX.mjs +0 -10
  544. /package/dist/{blog → articles}/server.js.map +0 -0
  545. /package/dist/{blog → articles}/server.mjs.map +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @sonordev/site-kit
2
2
 
3
- All-in-one integration kit for [Sonor](https://sonor.io)-powered Next.js sites. One package, one env var, every module: SEO, Analytics, Forms, Blog, Commerce, Engage, GEO/AEO, Booking, Reputation, A/B Testing, and more — all managed from the Sonor dashboard at [app.sonor.io](https://app.sonor.io).
3
+ All-in-one integration kit for [Sonor](https://sonor.io)-powered Next.js sites. One package, one env var, every module: SEO, Analytics, Forms, Articles, Commerce, Engage, GEO/AEO, Booking, Reputation, A/B Testing, and more — all managed from the Sonor dashboard at [app.sonor.io](https://app.sonor.io).
4
4
 
5
5
  ## Install
6
6
 
@@ -12,13 +12,13 @@ npm install @sonordev/site-kit
12
12
 
13
13
  The 5.4.0 release adds meeting-format selection with recoverable reservations,
14
14
  separate article artwork and share cards, accessible themed article tables, and
15
- shared publication routing. Pass one `routing` object to blog components and the
15
+ shared publication routing. Pass one `routing` object to article components and the
16
16
  same options to metadata, sitemap, feed, and schema helpers:
17
17
 
18
18
  ```tsx
19
19
  const routing = { basePath: '/theforge', includeCategoryInPath: true }
20
- // <BlogPost slug="build-first" routing={routing} />
21
- // generateBlogPostMetadata('build-first', { siteUrl, ...routing })
20
+ // <Article slug="build-first" routing={routing} />
21
+ // generateArticleMetadata('build-first', { siteUrl, ...routing })
22
22
  ```
23
23
 
24
24
  Deploy compatible Sonor booking services and migrations, upgrade and deploy
@@ -106,7 +106,7 @@ Every module has its own README in `src/<module>/README.md` with full API docs,
106
106
 
107
107
  | Module | Import | Purpose | Docs |
108
108
  |--------|--------|---------|------|
109
- | **Blog** | `@sonordev/site-kit/blog` | Portal-managed blog with SSG, topic clusters, E-E-A-T | [README](src/blog/README.md) |
109
+ | **Articles** | `@sonordev/site-kit/articles` | Portal-managed article with SSG, topic clusters, E-E-A-T | [README](src/article/README.md) |
110
110
  | **Images** | `@sonordev/site-kit/images` | Managed image slots with dev-mode editing | [README](src/images/README.md) |
111
111
  | **Reputation** | `@sonordev/site-kit/reputation` | Reviews, testimonials, rating stats | [README](src/reputation/README.md) |
112
112
 
@@ -189,9 +189,9 @@ import { AnalyticsProvider, useAnalytics, WebVitals } from '@sonordev/site-kit/a
189
189
  // Forms
190
190
  import { ManagedForm, useForm, formsApi, field } from '@sonordev/site-kit/forms'
191
191
 
192
- // Blog (server components — keeps server-only data helpers out of client bundles)
193
- import { BlogPost, BlogList, ClusterLandingPage } from '@sonordev/site-kit/blog/server-ui'
194
- import { getBlogPost, generateBlogStaticParams } from '@sonordev/site-kit/blog/server'
192
+ // Articles (server components — keeps server-only data helpers out of client bundles)
193
+ import { Article, ArticleList, ClusterLandingPage } from '@sonordev/site-kit/articles/server-ui'
194
+ import { getArticle, generateArticleStaticParams } from '@sonordev/site-kit/articles/server'
195
195
 
196
196
  // Commerce
197
197
  import { OfferingCard, ProductPage, EventCalendar } from '@sonordev/site-kit/commerce'
@@ -284,7 +284,7 @@ Fully typed. All types are exported from their respective module paths:
284
284
  ```ts
285
285
  import type { LLMsDataResponse, GenerateLLMSTxtOptions } from '@sonordev/site-kit/llms'
286
286
  import type { ManagedFormConfig, UseFormReturn } from '@sonordev/site-kit/forms'
287
- import type { BlogPost, TopicCluster } from '@sonordev/site-kit/blog'
287
+ import type { Article, TopicCluster } from '@sonordev/site-kit/articles'
288
288
  import type { CommerceOffering, SizeChart } from '@sonordev/site-kit/commerce'
289
289
  import type { SiteKitLayoutProps } from '@sonordev/site-kit/layout'
290
290
  ```
@@ -293,9 +293,9 @@ import type { SiteKitLayoutProps } from '@sonordev/site-kit/layout'
293
293
 
294
294
  ## Architecture Note
295
295
 
296
- `@sonordev/site-kit` is the client bridge between Next.js marketing sites and the Sonor platform. All persistent data (forms, blog posts, SEO config, analytics) lives in the Portal API — site-kit fetches, renders, and tracks.
296
+ `@sonordev/site-kit` is the client bridge between Next.js marketing sites and the Sonor platform. All persistent data (forms, articles, SEO config, analytics) lives in the Portal API — site-kit fetches, renders, and tracks.
297
297
 
298
- - **Server components** (SEO, Blog, Images): Import directly, RSC-compatible, no provider needed
298
+ - **Server components** (SEO, Articles, Images): Import directly, RSC-compatible, no provider needed
299
299
  - **Client modules** (Analytics, Engage, Signal): Lazy-loaded via `SiteKitLayout`, tree-shaken
300
300
  - **Build-time** (Sitemap, llms.txt): Run during `next build`, sync to Portal
301
301
  - **Middleware** (Redirects, Security, AI Discovery): Runs on every request edge
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@sonordev/site-kit",
4
- "version": "5.8.2",
4
+ "version": "6.0.0",
5
5
  "description": "Machine-readable manifest for coding agents integrating a site with Sonor. See AGENTS.md (shipped) and docs/SITE-KIT-AGENT-NATIVE.md.",
6
6
  "env": {
7
7
  "required": [
@@ -151,23 +151,23 @@
151
151
  "side": "unknown"
152
152
  },
153
153
  {
154
- "name": "blog",
155
- "import": "@sonordev/site-kit/blog",
154
+ "name": "articles",
155
+ "import": "@sonordev/site-kit/articles",
156
156
  "side": "client",
157
- "purpose": "Client-only blog pieces: TableOfContents, BlogFAQ, AuthorCard, ServiceCallout, NewsletterWidget, ClusterNavigation.",
158
- "caution": "Stamped 'use client' at build time. BlogLayout, BlogList, BlogPost, BlogSidebar, RelatedPosts, ClusterLandingPage and the *Page helpers are async server components — import them from @sonordev/site-kit/blog/server-ui. Importing them from this barrel hands Next an async component across a client boundary and the route 500s in production."
157
+ "purpose": "Client-only article pieces: TableOfContents, ArticleFAQ, AuthorCard, AuthorPage, ServiceCallout, NewsletterWidget, ClusterNavigation, ArticleViewTracker. Types for every article component.",
158
+ "caution": "Stamped 'use client' at build time. It exports no async server components: Article, ArticleList, PublicationLayout, PublicationPage, ArticlePage, CategoryPage, PublicationSidebar, RelatedPosts and ClusterLandingPage come from @sonordev/site-kit/articles/server-ui."
159
159
  },
160
160
  {
161
- "name": "blog/server",
162
- "import": "@sonordev/site-kit/blog/server",
161
+ "name": "articles/server",
162
+ "import": "@sonordev/site-kit/articles/server",
163
163
  "side": "server",
164
- "purpose": "Server-only blog data, SSG, metadata, schema, RSS and Atom. Shared publication routing supports basePath, includeCategoryInPath and custom postPath/categoryPath; resolveBlogArtwork separates article art from full cards; wrapBlogTables supplies accessible article tables."
164
+ "purpose": "Server-only article data, SSG, metadata, schema, RSS/Atom feeds (20 newest by default), article sitemap with images, and a Google News sitemap. Shared publication routing supports basePath, includeCategoryInPath and custom postPath/categoryPath; resolveArticleArtwork separates article art from full cards; wrapArticleTables supplies accessible article tables."
165
165
  },
166
166
  {
167
- "name": "blog/server-ui",
168
- "import": "@sonordev/site-kit/blog/server-ui",
167
+ "name": "articles/server-ui",
168
+ "import": "@sonordev/site-kit/articles/server-ui",
169
169
  "side": "server",
170
- "purpose": "RSC-safe blog UI: BlogPost, BlogList, BlogLayout, BlogSidebar, RelatedPosts, ClusterLandingPage, ClusterNavigation, and page helpers. Pass a shared routing object for custom publication paths. Article art, complete generated cards and themed table scrolling are handled by default."
170
+ "purpose": "RSC-safe article UI: Article, ArticleList, PublicationLayout, PublicationSidebar, RelatedPosts, ClusterLandingPage, ClusterNavigation, and page helpers. Pass a shared routing object (basePath defaults to /articles) so a site keeps its own publication path. Article art, complete generated cards and themed table scrolling are handled by default."
171
171
  },
172
172
  {
173
173
  "name": "commerce",
@@ -238,6 +238,11 @@
238
238
  "side": "server",
239
239
  "purpose": "AI visibility / llms.txt generation (Node only)."
240
240
  },
241
+ {
242
+ "name": "llms/client",
243
+ "import": "@sonordev/site-kit/llms/client",
244
+ "side": "unknown"
245
+ },
241
246
  {
242
247
  "name": "llms/contract",
243
248
  "import": "@sonordev/site-kit/llms/contract",
@@ -301,6 +306,12 @@
301
306
  "side": "server",
302
307
  "purpose": "robots.txt generator (createRobots). Also re-exports the AI crawler helpers from ./llms: buildAiCrawlerRules, createRobotsTxtHandler, AI_RETRIEVAL_CRAWLERS, AI_TRAINING_CRAWLERS."
303
308
  },
309
+ {
310
+ "name": "robots/indexnow",
311
+ "import": "@sonordev/site-kit/robots/indexnow",
312
+ "side": "server",
313
+ "purpose": "GET handler for app/indexnow.txt: serves the project's IndexNow key so Sonor can submit new, edited and removed articles to Bing, Yandex, Seznam and Naver."
314
+ },
304
315
  {
305
316
  "name": "site-config",
306
317
  "import": "@sonordev/site-kit/site-config",
@@ -1,12 +1,12 @@
1
- export { AnalyticsProvider, useAnalytics, useAnalyticsOptional, useTrackEvent } from './chunk-X6NPTILR.mjs';
1
+ export { AnalyticsProvider, useAnalytics, useAnalyticsOptional, useTrackEvent } from './chunk-2WEBUZNP.mjs';
2
2
  import './chunk-SHLWA6JY.mjs';
3
3
  import './chunk-ZZQAGCSI.mjs';
4
4
  import './chunk-5SANRSX3.mjs';
5
5
  import './chunk-6EDVCUAG.mjs';
6
6
  import './chunk-A6UYV475.mjs';
7
- import './chunk-3EXBBFXX.mjs';
8
- import './chunk-SCVSPTXJ.mjs';
9
- import './chunk-TAPCWMBV.mjs';
7
+ import './chunk-2YSB4FIC.mjs';
8
+ import './chunk-NR52QHOD.mjs';
9
+ import './chunk-2KRAY5NC.mjs';
10
10
  import './chunk-BEXTDHO4.mjs';
11
- //# sourceMappingURL=AnalyticsProvider-LUEUDZZC.mjs.map
12
- //# sourceMappingURL=AnalyticsProvider-LUEUDZZC.mjs.map
11
+ //# sourceMappingURL=AnalyticsProvider-6QVM2B6O.mjs.map
12
+ //# sourceMappingURL=AnalyticsProvider-6QVM2B6O.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"AnalyticsProvider-LUEUDZZC.mjs"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"AnalyticsProvider-6QVM2B6O.mjs"}
@@ -1,33 +1,33 @@
1
1
  'use strict';
2
2
 
3
- var chunkD7CF3OPZ_js = require('./chunk-D7CF3OPZ.js');
3
+ var chunkMCG4BSRW_js = require('./chunk-MCG4BSRW.js');
4
4
  require('./chunk-3DWIYCQX.js');
5
5
  require('./chunk-RC4WWQXR.js');
6
6
  require('./chunk-P4Y75QSU.js');
7
7
  require('./chunk-VJMPIRSD.js');
8
8
  require('./chunk-5RNAUYWE.js');
9
- require('./chunk-GDH42JAS.js');
10
- require('./chunk-7BI2RVQD.js');
11
- require('./chunk-TJVZEDE3.js');
9
+ require('./chunk-3GHPFLEH.js');
10
+ require('./chunk-TCZHRSWY.js');
11
+ require('./chunk-EL74YDNX.js');
12
12
  require('./chunk-SNAQBZPT.js');
13
13
 
14
14
 
15
15
 
16
16
  Object.defineProperty(exports, "AnalyticsProvider", {
17
17
  enumerable: true,
18
- get: function () { return chunkD7CF3OPZ_js.AnalyticsProvider; }
18
+ get: function () { return chunkMCG4BSRW_js.AnalyticsProvider; }
19
19
  });
20
20
  Object.defineProperty(exports, "useAnalytics", {
21
21
  enumerable: true,
22
- get: function () { return chunkD7CF3OPZ_js.useAnalytics; }
22
+ get: function () { return chunkMCG4BSRW_js.useAnalytics; }
23
23
  });
24
24
  Object.defineProperty(exports, "useAnalyticsOptional", {
25
25
  enumerable: true,
26
- get: function () { return chunkD7CF3OPZ_js.useAnalyticsOptional; }
26
+ get: function () { return chunkMCG4BSRW_js.useAnalyticsOptional; }
27
27
  });
28
28
  Object.defineProperty(exports, "useTrackEvent", {
29
29
  enumerable: true,
30
- get: function () { return chunkD7CF3OPZ_js.useTrackEvent; }
30
+ get: function () { return chunkMCG4BSRW_js.useTrackEvent; }
31
31
  });
32
- //# sourceMappingURL=AnalyticsProvider-4JV3OFCG.js.map
33
- //# sourceMappingURL=AnalyticsProvider-4JV3OFCG.js.map
32
+ //# sourceMappingURL=AnalyticsProvider-AZQXLRWN.js.map
33
+ //# sourceMappingURL=AnalyticsProvider-AZQXLRWN.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"AnalyticsProvider-4JV3OFCG.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"AnalyticsProvider-AZQXLRWN.js"}
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ var chunkOGNX6JT4_js = require('./chunk-OGNX6JT4.js');
4
+ require('./chunk-SNAQBZPT.js');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ function ArticleFaqSection(props) {
8
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkOGNX6JT4_js.ArticleFAQ, { ...props });
9
+ }
10
+
11
+ exports.ArticleFaqSection = ArticleFaqSection;
12
+ //# sourceMappingURL=ArticleFaqSection-3KZ24MFS.js.map
13
+ //# sourceMappingURL=ArticleFaqSection-3KZ24MFS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/articles/ArticleFaqSection.tsx"],"names":["jsx","ArticleFAQ"],"mappings":";;;;;;AAWO,SAAS,kBAAkB,KAAA,EAAwB;AACxD,EAAA,uBAAOA,cAAA,CAACC,2BAAA,EAAA,EAAY,GAAG,KAAA,EAAO,CAAA;AAChC","file":"ArticleFaqSection-3KZ24MFS.js","sourcesContent":["'use client'\n\n/**\n * Client boundary for FAQ accordion inside {@link Article}.\n * Keeps `Article.tsx` free of bundled hook code so the prebuilt `server-ui`\n * chunk stays a Server Component and supports render-prop `children`.\n */\n\nimport { ArticleFAQ } from './ArticleFAQ'\nimport type { ArticleFAQProps } from './ArticleFAQ'\n\nexport function ArticleFaqSection(props: ArticleFAQProps) {\n return <ArticleFAQ {...props} />\n}\n"]}
@@ -0,0 +1,11 @@
1
+ import { ArticleFAQ } from './chunk-C5VITBN7.mjs';
2
+ import './chunk-BEXTDHO4.mjs';
3
+ import { jsx } from 'react/jsx-runtime';
4
+
5
+ function ArticleFaqSection(props) {
6
+ return /* @__PURE__ */ jsx(ArticleFAQ, { ...props });
7
+ }
8
+
9
+ export { ArticleFaqSection };
10
+ //# sourceMappingURL=ArticleFaqSection-XZPXJVH4.mjs.map
11
+ //# sourceMappingURL=ArticleFaqSection-XZPXJVH4.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/articles/ArticleFaqSection.tsx"],"names":[],"mappings":";;;;AAWO,SAAS,kBAAkB,KAAA,EAAwB;AACxD,EAAA,uBAAO,GAAA,CAAC,UAAA,EAAA,EAAY,GAAG,KAAA,EAAO,CAAA;AAChC","file":"ArticleFaqSection-XZPXJVH4.mjs","sourcesContent":["'use client'\n\n/**\n * Client boundary for FAQ accordion inside {@link Article}.\n * Keeps `Article.tsx` free of bundled hook code so the prebuilt `server-ui`\n * chunk stays a Server Component and supports render-prop `children`.\n */\n\nimport { ArticleFAQ } from './ArticleFAQ'\nimport type { ArticleFAQProps } from './ArticleFAQ'\n\nexport function ArticleFaqSection(props: ArticleFAQProps) {\n return <ArticleFAQ {...props} />\n}\n"]}
@@ -1,16 +1,16 @@
1
1
  'use client';
2
2
  import { useDeferredActivation } from './chunk-ZVBLXXNJ.mjs';
3
- import { withSiteBody } from './chunk-4TLFZ6NR.mjs';
4
- import './chunk-JLVCWC6A.mjs';
3
+ import { withSiteBody } from './chunk-AS2HUIDW.mjs';
4
+ import './chunk-KZVSB5WE.mjs';
5
5
  import './chunk-ZN4HBK5C.mjs';
6
- import { sonorFetch } from './chunk-3EXBBFXX.mjs';
7
- import './chunk-SCVSPTXJ.mjs';
8
- import './chunk-TAPCWMBV.mjs';
6
+ import { sonorFetch } from './chunk-2YSB4FIC.mjs';
7
+ import './chunk-NR52QHOD.mjs';
8
+ import './chunk-2KRAY5NC.mjs';
9
9
  import './chunk-BEXTDHO4.mjs';
10
10
  import { useEffect } from 'react';
11
11
 
12
- var SESSION_KEY_PREFIX = "__sonor_blog_viewed__:";
13
- function trackBlogView(slug, site) {
12
+ var SESSION_KEY_PREFIX = "__sonor_article_viewed__:";
13
+ function trackArticleView(slug, site) {
14
14
  if (!slug || typeof window === "undefined") return;
15
15
  const w = window;
16
16
  const baseUrl = w.__SITE_KIT_API_URL__;
@@ -21,7 +21,7 @@ function trackBlogView(slug, site) {
21
21
  } catch {
22
22
  }
23
23
  void sonorFetch(
24
- `${baseUrl}/public/blog/view`,
24
+ `${baseUrl}/public/articles/view`,
25
25
  {
26
26
  method: "POST",
27
27
  headers: { "Content-Type": "application/json" },
@@ -38,14 +38,14 @@ function trackBlogView(slug, site) {
38
38
  }).catch(() => {
39
39
  });
40
40
  }
41
- function BlogViewTracker({ slug, site }) {
41
+ function ArticleViewTracker({ slug, site }) {
42
42
  const ready = useDeferredActivation(true);
43
43
  useEffect(() => {
44
- if (ready) trackBlogView(slug, site);
44
+ if (ready) trackArticleView(slug, site);
45
45
  }, [ready, slug, site]);
46
46
  return null;
47
47
  }
48
48
 
49
- export { BlogViewTracker, trackBlogView };
50
- //# sourceMappingURL=BlogViewTracker-YQMTEGYZ.mjs.map
51
- //# sourceMappingURL=BlogViewTracker-YQMTEGYZ.mjs.map
49
+ export { ArticleViewTracker, trackArticleView };
50
+ //# sourceMappingURL=ArticleViewTracker-AEWJMXQQ.mjs.map
51
+ //# sourceMappingURL=ArticleViewTracker-AEWJMXQQ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/articles/ArticleViewTracker.tsx"],"names":[],"mappings":";;;;;;;;;;AAoBA,IAAM,kBAAA,GAAqB,2BAAA;AAgBpB,SAAS,gBAAA,CAAiB,MAAc,IAAA,EAAqB;AAClE,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,MAAA,KAAW,WAAA,EAAa;AAI5C,EAAA,MAAM,CAAA,GAAI,MAAA;AAKV,EAAA,MAAM,UAAU,CAAA,CAAE,oBAAA;AAClB,EAAA,IAAI,CAAC,OAAA,IAAW,CAAC,CAAA,CAAE,oBAAA,EAAsB;AAKzC,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,kBAAkB,CAAA,EAAG,IAAI,CAAA,CAAA;AACxC,EAAA,IAAI;AACF,IAAA,IAAI,cAAA,CAAe,OAAA,CAAQ,GAAG,CAAA,EAAG;AAAA,EACnC,CAAA,CAAA,MAAQ;AAAA,EAER;AAIA,EAAA,KAAK,UAAA;AAAA,IACH,GAAG,OAAO,CAAA,qBAAA,CAAA;AAAA,IACV;AAAA,MACE,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,MAC9C,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,YAAA,CAAa,EAAE,MAAK,EAAG,IAAA,IAAQ,CAAA,CAAE,iBAAiB,CAAC;AAAA,KAC1E;AAAA,IACA,EAAE,SAAS,CAAA;AAAE,GACf,CACG,IAAA,CAAK,CAAC,GAAA,KAAQ;AACb,IAAA,IAAI,IAAI,EAAA,EAAI;AACV,MAAA,IAAI;AACF,QAAA,cAAA,CAAe,OAAA,CAAQ,KAAK,GAAG,CAAA;AAAA,MACjC,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,CAAC,CAAA,CACA,KAAA,CAAM,MAAM;AAAA,EAEb,CAAC,CAAA;AACL;AAEO,SAAS,kBAAA,CAAmB,EAAE,IAAA,EAAM,IAAA,EAAK,EAA4B;AAC1E,EAAA,MAAM,KAAA,GAAQ,sBAAsB,IAAI,CAAA;AAExC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,KAAA,EAAO,gBAAA,CAAiB,IAAA,EAAM,IAAI,CAAA;AAAA,EACxC,CAAA,EAAG,CAAC,KAAA,EAAO,IAAA,EAAM,IAAI,CAAC,CAAA;AAEtB,EAAA,OAAO,IAAA;AACT","file":"ArticleViewTracker-AEWJMXQQ.mjs","sourcesContent":["'use client'\n\n/**\n * @sonordev/site-kit article — reader-side view tracking\n *\n * Counts actual readers by POSTing to /public/articles/view once per post per\n * browser session. This replaces the server-side increment that rode\n * GET posts/:slug — under ISR that GET fires on REVALIDATION, not on reads,\n * so view_count was measuring cache churn instead of people.\n *\n * Childless by design (renders null, never wraps children) and gated behind\n * the same idle deferral SiteKitLayout uses, so it stays out of the critical\n * hydration window.\n */\n\nimport { useEffect } from 'react'\nimport { useDeferredActivation } from '../shared/defer'\nimport { sonorFetch } from '../shared/sonorFetch'\nimport { withSiteBody } from '../sites/site-param'\n\nconst SESSION_KEY_PREFIX = '__sonor_article_viewed__:'\n\nexport interface ArticleViewTrackerProps {\n slug: string\n /**\n * Sub-site host the view counts toward. Omit to use the host SiteKitLayout\n * published (`__SITE_KIT_SITE__`, the same one analytics tags page views\n * with), then NEXT_PUBLIC_SITE_URL, then `window.location.host`.\n */\n site?: string\n}\n\n/**\n * The effect body, exported for tests (the package's vitest runs in node, so\n * the component's mount path can't be exercised directly).\n */\nexport function trackArticleView(slug: string, site?: string): void {\n if (!slug || typeof window === 'undefined') return\n\n // SiteKitLayout globals; the credential is the minted st1. token, never\n // the raw key. Without SiteKitLayout the globals are absent — no-op.\n const w = window as Window & {\n __SITE_KIT_API_URL__?: string\n __SITE_KIT_API_KEY__?: string\n __SITE_KIT_SITE__?: string\n }\n const baseUrl = w.__SITE_KIT_API_URL__\n if (!baseUrl || !w.__SITE_KIT_API_KEY__) return\n\n // One view per post per session. sessionStorage can throw (private\n // windows, storage-blocked browsers) — treat a throw as \"not yet viewed\"\n // and skip writing rather than skip counting.\n const key = `${SESSION_KEY_PREFIX}${slug}`\n try {\n if (sessionStorage.getItem(key)) return\n } catch {\n /* unreadable storage — count the view, skip dedupe */\n }\n\n // retries: 0 — the increment is not idempotent, so a retried request\n // would double-count.\n void sonorFetch(\n `${baseUrl}/public/articles/view`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(withSiteBody({ slug }, site || w.__SITE_KIT_SITE__)),\n },\n { retries: 0 }\n )\n .then((res) => {\n if (res.ok) {\n try {\n sessionStorage.setItem(key, '1')\n } catch {\n /* storage write blocked — worst case is a re-count next mount */\n }\n }\n })\n .catch(() => {\n /* view tracking is best-effort; never surface errors */\n })\n}\n\nexport function ArticleViewTracker({ slug, site }: ArticleViewTrackerProps) {\n const ready = useDeferredActivation(true)\n\n useEffect(() => {\n if (ready) trackArticleView(slug, site)\n }, [ready, slug, site])\n\n return null\n}\n"]}
@@ -2,17 +2,17 @@
2
2
  'use strict';
3
3
 
4
4
  var chunkHGNSJXWT_js = require('./chunk-HGNSJXWT.js');
5
- var chunkYN7QHLWF_js = require('./chunk-YN7QHLWF.js');
6
- require('./chunk-H5NBFNND.js');
5
+ var chunkBBBJHYPH_js = require('./chunk-BBBJHYPH.js');
6
+ require('./chunk-UZKXOZHR.js');
7
7
  require('./chunk-SWIKKSKL.js');
8
- var chunkGDH42JAS_js = require('./chunk-GDH42JAS.js');
9
- require('./chunk-7BI2RVQD.js');
10
- require('./chunk-TJVZEDE3.js');
8
+ var chunk3GHPFLEH_js = require('./chunk-3GHPFLEH.js');
9
+ require('./chunk-TCZHRSWY.js');
10
+ require('./chunk-EL74YDNX.js');
11
11
  require('./chunk-SNAQBZPT.js');
12
12
  var react = require('react');
13
13
 
14
- var SESSION_KEY_PREFIX = "__sonor_blog_viewed__:";
15
- function trackBlogView(slug, site) {
14
+ var SESSION_KEY_PREFIX = "__sonor_article_viewed__:";
15
+ function trackArticleView(slug, site) {
16
16
  if (!slug || typeof window === "undefined") return;
17
17
  const w = window;
18
18
  const baseUrl = w.__SITE_KIT_API_URL__;
@@ -22,12 +22,12 @@ function trackBlogView(slug, site) {
22
22
  if (sessionStorage.getItem(key)) return;
23
23
  } catch {
24
24
  }
25
- void chunkGDH42JAS_js.sonorFetch(
26
- `${baseUrl}/public/blog/view`,
25
+ void chunk3GHPFLEH_js.sonorFetch(
26
+ `${baseUrl}/public/articles/view`,
27
27
  {
28
28
  method: "POST",
29
29
  headers: { "Content-Type": "application/json" },
30
- body: JSON.stringify(chunkYN7QHLWF_js.withSiteBody({ slug }, site || w.__SITE_KIT_SITE__))
30
+ body: JSON.stringify(chunkBBBJHYPH_js.withSiteBody({ slug }, site || w.__SITE_KIT_SITE__))
31
31
  },
32
32
  { retries: 0 }
33
33
  ).then((res) => {
@@ -40,15 +40,15 @@ function trackBlogView(slug, site) {
40
40
  }).catch(() => {
41
41
  });
42
42
  }
43
- function BlogViewTracker({ slug, site }) {
43
+ function ArticleViewTracker({ slug, site }) {
44
44
  const ready = chunkHGNSJXWT_js.useDeferredActivation(true);
45
45
  react.useEffect(() => {
46
- if (ready) trackBlogView(slug, site);
46
+ if (ready) trackArticleView(slug, site);
47
47
  }, [ready, slug, site]);
48
48
  return null;
49
49
  }
50
50
 
51
- exports.BlogViewTracker = BlogViewTracker;
52
- exports.trackBlogView = trackBlogView;
53
- //# sourceMappingURL=BlogViewTracker-32C4SCHA.js.map
54
- //# sourceMappingURL=BlogViewTracker-32C4SCHA.js.map
51
+ exports.ArticleViewTracker = ArticleViewTracker;
52
+ exports.trackArticleView = trackArticleView;
53
+ //# sourceMappingURL=ArticleViewTracker-CFBTQ46B.js.map
54
+ //# sourceMappingURL=ArticleViewTracker-CFBTQ46B.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/articles/ArticleViewTracker.tsx"],"names":["sonorFetch","withSiteBody","useDeferredActivation","useEffect"],"mappings":";;;;;;;;;;;;AAoBA,IAAM,kBAAA,GAAqB,2BAAA;AAgBpB,SAAS,gBAAA,CAAiB,MAAc,IAAA,EAAqB;AAClE,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,MAAA,KAAW,WAAA,EAAa;AAI5C,EAAA,MAAM,CAAA,GAAI,MAAA;AAKV,EAAA,MAAM,UAAU,CAAA,CAAE,oBAAA;AAClB,EAAA,IAAI,CAAC,OAAA,IAAW,CAAC,CAAA,CAAE,oBAAA,EAAsB;AAKzC,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,kBAAkB,CAAA,EAAG,IAAI,CAAA,CAAA;AACxC,EAAA,IAAI;AACF,IAAA,IAAI,cAAA,CAAe,OAAA,CAAQ,GAAG,CAAA,EAAG;AAAA,EACnC,CAAA,CAAA,MAAQ;AAAA,EAER;AAIA,EAAA,KAAKA,2BAAA;AAAA,IACH,GAAG,OAAO,CAAA,qBAAA,CAAA;AAAA,IACV;AAAA,MACE,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,MAC9C,IAAA,EAAM,IAAA,CAAK,SAAA,CAAUC,6BAAA,CAAa,EAAE,MAAK,EAAG,IAAA,IAAQ,CAAA,CAAE,iBAAiB,CAAC;AAAA,KAC1E;AAAA,IACA,EAAE,SAAS,CAAA;AAAE,GACf,CACG,IAAA,CAAK,CAAC,GAAA,KAAQ;AACb,IAAA,IAAI,IAAI,EAAA,EAAI;AACV,MAAA,IAAI;AACF,QAAA,cAAA,CAAe,OAAA,CAAQ,KAAK,GAAG,CAAA;AAAA,MACjC,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,CAAC,CAAA,CACA,KAAA,CAAM,MAAM;AAAA,EAEb,CAAC,CAAA;AACL;AAEO,SAAS,kBAAA,CAAmB,EAAE,IAAA,EAAM,IAAA,EAAK,EAA4B;AAC1E,EAAA,MAAM,KAAA,GAAQC,uCAAsB,IAAI,CAAA;AAExC,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,KAAA,EAAO,gBAAA,CAAiB,IAAA,EAAM,IAAI,CAAA;AAAA,EACxC,CAAA,EAAG,CAAC,KAAA,EAAO,IAAA,EAAM,IAAI,CAAC,CAAA;AAEtB,EAAA,OAAO,IAAA;AACT","file":"ArticleViewTracker-CFBTQ46B.js","sourcesContent":["'use client'\n\n/**\n * @sonordev/site-kit article — reader-side view tracking\n *\n * Counts actual readers by POSTing to /public/articles/view once per post per\n * browser session. This replaces the server-side increment that rode\n * GET posts/:slug — under ISR that GET fires on REVALIDATION, not on reads,\n * so view_count was measuring cache churn instead of people.\n *\n * Childless by design (renders null, never wraps children) and gated behind\n * the same idle deferral SiteKitLayout uses, so it stays out of the critical\n * hydration window.\n */\n\nimport { useEffect } from 'react'\nimport { useDeferredActivation } from '../shared/defer'\nimport { sonorFetch } from '../shared/sonorFetch'\nimport { withSiteBody } from '../sites/site-param'\n\nconst SESSION_KEY_PREFIX = '__sonor_article_viewed__:'\n\nexport interface ArticleViewTrackerProps {\n slug: string\n /**\n * Sub-site host the view counts toward. Omit to use the host SiteKitLayout\n * published (`__SITE_KIT_SITE__`, the same one analytics tags page views\n * with), then NEXT_PUBLIC_SITE_URL, then `window.location.host`.\n */\n site?: string\n}\n\n/**\n * The effect body, exported for tests (the package's vitest runs in node, so\n * the component's mount path can't be exercised directly).\n */\nexport function trackArticleView(slug: string, site?: string): void {\n if (!slug || typeof window === 'undefined') return\n\n // SiteKitLayout globals; the credential is the minted st1. token, never\n // the raw key. Without SiteKitLayout the globals are absent — no-op.\n const w = window as Window & {\n __SITE_KIT_API_URL__?: string\n __SITE_KIT_API_KEY__?: string\n __SITE_KIT_SITE__?: string\n }\n const baseUrl = w.__SITE_KIT_API_URL__\n if (!baseUrl || !w.__SITE_KIT_API_KEY__) return\n\n // One view per post per session. sessionStorage can throw (private\n // windows, storage-blocked browsers) — treat a throw as \"not yet viewed\"\n // and skip writing rather than skip counting.\n const key = `${SESSION_KEY_PREFIX}${slug}`\n try {\n if (sessionStorage.getItem(key)) return\n } catch {\n /* unreadable storage — count the view, skip dedupe */\n }\n\n // retries: 0 — the increment is not idempotent, so a retried request\n // would double-count.\n void sonorFetch(\n `${baseUrl}/public/articles/view`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(withSiteBody({ slug }, site || w.__SITE_KIT_SITE__)),\n },\n { retries: 0 }\n )\n .then((res) => {\n if (res.ok) {\n try {\n sessionStorage.setItem(key, '1')\n } catch {\n /* storage write blocked — worst case is a re-count next mount */\n }\n }\n })\n .catch(() => {\n /* view tracking is best-effort; never surface errors */\n })\n}\n\nexport function ArticleViewTracker({ slug, site }: ArticleViewTrackerProps) {\n const ready = useDeferredActivation(true)\n\n useEffect(() => {\n if (ready) trackArticleView(slug, site)\n }, [ready, slug, site])\n\n return null\n}\n"]}
@@ -0,0 +1,15 @@
1
+ export { ChatWidget } from './chunk-XKXZ4OW4.mjs';
2
+ import './chunk-4U5NCKQY.mjs';
3
+ import './chunk-NSWO43XW.mjs';
4
+ import './chunk-HOOVYWTO.mjs';
5
+ import './chunk-QRHVMTHF.mjs';
6
+ import './chunk-ZR4TYCQW.mjs';
7
+ import './chunk-TMVKRQGJ.mjs';
8
+ import './chunk-5SANRSX3.mjs';
9
+ import './chunk-6EDVCUAG.mjs';
10
+ import './chunk-2YSB4FIC.mjs';
11
+ import './chunk-NR52QHOD.mjs';
12
+ import './chunk-2KRAY5NC.mjs';
13
+ import './chunk-BEXTDHO4.mjs';
14
+ //# sourceMappingURL=ChatWidget-6626OPXO.mjs.map
15
+ //# sourceMappingURL=ChatWidget-6626OPXO.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"ChatWidget-IRTAMRQS.mjs"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"ChatWidget-6626OPXO.mjs"}
@@ -0,0 +1,24 @@
1
+ 'use strict';
2
+
3
+ var chunkCZGGUPPQ_js = require('./chunk-CZGGUPPQ.js');
4
+ require('./chunk-ESP5RMB7.js');
5
+ require('./chunk-G6WF4G3E.js');
6
+ require('./chunk-WDEGGHTB.js');
7
+ require('./chunk-5XFFUP6D.js');
8
+ require('./chunk-YYEBFQGS.js');
9
+ require('./chunk-KHPJ3CEL.js');
10
+ require('./chunk-P4Y75QSU.js');
11
+ require('./chunk-VJMPIRSD.js');
12
+ require('./chunk-3GHPFLEH.js');
13
+ require('./chunk-TCZHRSWY.js');
14
+ require('./chunk-EL74YDNX.js');
15
+ require('./chunk-SNAQBZPT.js');
16
+
17
+
18
+
19
+ Object.defineProperty(exports, "ChatWidget", {
20
+ enumerable: true,
21
+ get: function () { return chunkCZGGUPPQ_js.ChatWidget; }
22
+ });
23
+ //# sourceMappingURL=ChatWidget-U24AYLXF.js.map
24
+ //# sourceMappingURL=ChatWidget-U24AYLXF.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"ChatWidget-KCXQXNUF.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"ChatWidget-U24AYLXF.js"}
@@ -0,0 +1,12 @@
1
+ export { EngageWidget } from './chunk-YWLBQ3L5.mjs';
2
+ import './chunk-4U5NCKQY.mjs';
3
+ import './chunk-NSWO43XW.mjs';
4
+ import './chunk-ZZQAGCSI.mjs';
5
+ import './chunk-6EDVCUAG.mjs';
6
+ import './chunk-A6UYV475.mjs';
7
+ import './chunk-2YSB4FIC.mjs';
8
+ import './chunk-NR52QHOD.mjs';
9
+ import './chunk-2KRAY5NC.mjs';
10
+ import './chunk-BEXTDHO4.mjs';
11
+ //# sourceMappingURL=EngageWidget-TR47W2ZI.mjs.map
12
+ //# sourceMappingURL=EngageWidget-TR47W2ZI.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"EngageWidget-7AIUJRXV.mjs"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"EngageWidget-TR47W2ZI.mjs"}
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ var chunkN6CB7MK7_js = require('./chunk-N6CB7MK7.js');
4
+ require('./chunk-ESP5RMB7.js');
5
+ require('./chunk-G6WF4G3E.js');
6
+ require('./chunk-RC4WWQXR.js');
7
+ require('./chunk-VJMPIRSD.js');
8
+ require('./chunk-5RNAUYWE.js');
9
+ require('./chunk-3GHPFLEH.js');
10
+ require('./chunk-TCZHRSWY.js');
11
+ require('./chunk-EL74YDNX.js');
12
+ require('./chunk-SNAQBZPT.js');
13
+
14
+
15
+
16
+ Object.defineProperty(exports, "EngageWidget", {
17
+ enumerable: true,
18
+ get: function () { return chunkN6CB7MK7_js.EngageWidget; }
19
+ });
20
+ //# sourceMappingURL=EngageWidget-XUTDFRF3.js.map
21
+ //# sourceMappingURL=EngageWidget-XUTDFRF3.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"EngageWidget-EUUZHQOU.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"EngageWidget-XUTDFRF3.js"}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
- import { sonorFetch } from './chunk-3EXBBFXX.mjs';
3
- import './chunk-SCVSPTXJ.mjs';
4
- import './chunk-TAPCWMBV.mjs';
2
+ import { sonorFetch } from './chunk-2YSB4FIC.mjs';
3
+ import './chunk-NR52QHOD.mjs';
4
+ import './chunk-2KRAY5NC.mjs';
5
5
  import './chunk-BEXTDHO4.mjs';
6
6
  import React from 'react';
7
7
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
@@ -81,5 +81,5 @@ async function uploadFormFile(file) {
81
81
  }
82
82
 
83
83
  export { FileField };
84
- //# sourceMappingURL=FileField-XJYJO5HE.mjs.map
85
- //# sourceMappingURL=FileField-XJYJO5HE.mjs.map
84
+ //# sourceMappingURL=FileField-DNNC5IPS.mjs.map
85
+ //# sourceMappingURL=FileField-DNNC5IPS.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/forms/FileField.tsx"],"names":[],"mappings":"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","file":"FileField-XJYJO5HE.mjs","sourcesContent":["'use client'\n\n/**\n * File upload field — the one field type that cannot render on the server.\n *\n * It holds upload state and reads the browser-published credential globals, so\n * it lives here rather than in FormField.tsx. Pulling it out is what lets\n * FormField drop its `'use client'` directive and render inside a Server\n * Component (see StaticForm.tsx); a form WITHOUT a file field now ships no\n * field-rendering JavaScript at all.\n *\n * Uploads the chosen file to the Sonor API, which stores it and returns a\n * public URL — that URL becomes the field value, so large files never touch\n * the JSON submission body. The value stays empty until the upload succeeds,\n * so a required file field correctly blocks submission until the upload\n * completes (rather than submitting a useless bare filename).\n *\n * Note: forms containing a file field are NOT native-POST eligible (see\n * native-fallback.tsx) — a form-encoded POST cannot run this upload — so the\n * server shell renders a plain disabled-looking file input and the real\n * control arrives with the enhancement.\n */\n\nimport React from 'react'\nimport type { FormField as FormFieldType } from './types'\nimport { sonorFetch } from '../shared/sonorFetch'\n\nexport interface FileFieldProps {\n field: FormFieldType\n inputId: string\n classPrefix: string\n baseInputStyle: React.CSSProperties\n onChange: (value: unknown) => void\n}\n\nexport function FileField({\n field,\n inputId,\n classPrefix,\n baseInputStyle,\n onChange,\n}: FileFieldProps) {\n const [status, setStatus] = React.useState<'idle' | 'uploading' | 'error'>('idle')\n const [fileName, setFileName] = React.useState('')\n\n const handleFile = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0]\n if (!file) return\n setFileName(file.name)\n setStatus('uploading')\n onChange('') // clear any prior URL until this upload completes\n try {\n const url = await uploadFormFile(file)\n onChange(url)\n setStatus('idle')\n } catch (err) {\n console.error('[Forms] File upload failed:', err)\n onChange('')\n setStatus('error')\n }\n }\n\n return (\n <>\n <input\n id={inputId}\n className={`${classPrefix}__input ${classPrefix}__input--file`}\n type=\"file\"\n name={field.slug}\n required={field.is_required}\n disabled={status === 'uploading'}\n onChange={handleFile}\n style={baseInputStyle}\n />\n {status === 'uploading' && (\n <p style={{ color: 'var(--sk-text-tertiary, #6b7280)', fontSize: 14, marginTop: 4 }}>\n Uploading {fileName}…\n </p>\n )}\n {status === 'error' && (\n <p role=\"alert\" style={{ color: 'var(--sk-error, #dc2626)', fontSize: 14, marginTop: 4 }}>\n Upload failed. Please choose the file again.\n </p>\n )}\n </>\n )\n}\n\n/** Upload a single file to the Sonor API and return its stored public URL. */\nasync function uploadFormFile(file: File): Promise<string> {\n const apiUrl =\n typeof window !== 'undefined'\n ? (window as any).__SITE_KIT_API_URL__ || 'https://api.sonor.io'\n : 'https://api.sonor.io'\n const apiKey =\n typeof window !== 'undefined' ? (window as any).__SITE_KIT_API_KEY__ : undefined\n if (!apiKey) {\n throw new Error('API key is required to upload files.')\n }\n\n const body = new FormData()\n body.append('file', file)\n\n // No Content-Type header — the browser sets the multipart boundary itself.\n const response = await sonorFetch(\n `${apiUrl}/api/public/forms/upload`,\n {\n method: 'POST',\n headers: { Authorization: `Bearer ${apiKey}` },\n body,\n },\n { retries: 1, timeoutMs: 60000 },\n )\n\n if (!response.ok) {\n throw new Error(`Upload failed (${response.status})`)\n }\n const data = (await response.json().catch(() => null)) as { url?: string } | null\n if (!data?.url) {\n throw new Error('Upload did not return a URL.')\n }\n return data.url\n}\n"]}
1
+ {"version":3,"sources":["../src/forms/FileField.tsx"],"names":[],"mappings":"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","file":"FileField-DNNC5IPS.mjs","sourcesContent":["'use client'\n\n/**\n * File upload field — the one field type that cannot render on the server.\n *\n * It holds upload state and reads the browser-published credential globals, so\n * it lives here rather than in FormField.tsx. Pulling it out is what lets\n * FormField drop its `'use client'` directive and render inside a Server\n * Component (see StaticForm.tsx); a form WITHOUT a file field now ships no\n * field-rendering JavaScript at all.\n *\n * Uploads the chosen file to the Sonor API, which stores it and returns a\n * public URL — that URL becomes the field value, so large files never touch\n * the JSON submission body. The value stays empty until the upload succeeds,\n * so a required file field correctly blocks submission until the upload\n * completes (rather than submitting a useless bare filename).\n *\n * Note: forms containing a file field are NOT native-POST eligible (see\n * native-fallback.tsx) — a form-encoded POST cannot run this upload — so the\n * server shell renders a plain disabled-looking file input and the real\n * control arrives with the enhancement.\n */\n\nimport React from 'react'\nimport type { FormField as FormFieldType } from './types'\nimport { sonorFetch } from '../shared/sonorFetch'\n\nexport interface FileFieldProps {\n field: FormFieldType\n inputId: string\n classPrefix: string\n baseInputStyle: React.CSSProperties\n onChange: (value: unknown) => void\n}\n\nexport function FileField({\n field,\n inputId,\n classPrefix,\n baseInputStyle,\n onChange,\n}: FileFieldProps) {\n const [status, setStatus] = React.useState<'idle' | 'uploading' | 'error'>('idle')\n const [fileName, setFileName] = React.useState('')\n\n const handleFile = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0]\n if (!file) return\n setFileName(file.name)\n setStatus('uploading')\n onChange('') // clear any prior URL until this upload completes\n try {\n const url = await uploadFormFile(file)\n onChange(url)\n setStatus('idle')\n } catch (err) {\n console.error('[Forms] File upload failed:', err)\n onChange('')\n setStatus('error')\n }\n }\n\n return (\n <>\n <input\n id={inputId}\n className={`${classPrefix}__input ${classPrefix}__input--file`}\n type=\"file\"\n name={field.slug}\n required={field.is_required}\n disabled={status === 'uploading'}\n onChange={handleFile}\n style={baseInputStyle}\n />\n {status === 'uploading' && (\n <p style={{ color: 'var(--sk-text-tertiary, #6b7280)', fontSize: 14, marginTop: 4 }}>\n Uploading {fileName}…\n </p>\n )}\n {status === 'error' && (\n <p role=\"alert\" style={{ color: 'var(--sk-error, #dc2626)', fontSize: 14, marginTop: 4 }}>\n Upload failed. Please choose the file again.\n </p>\n )}\n </>\n )\n}\n\n/** Upload a single file to the Sonor API and return its stored public URL. */\nasync function uploadFormFile(file: File): Promise<string> {\n const apiUrl =\n typeof window !== 'undefined'\n ? (window as any).__SITE_KIT_API_URL__ || 'https://api.sonor.io'\n : 'https://api.sonor.io'\n const apiKey =\n typeof window !== 'undefined' ? (window as any).__SITE_KIT_API_KEY__ : undefined\n if (!apiKey) {\n throw new Error('API key is required to upload files.')\n }\n\n const body = new FormData()\n body.append('file', file)\n\n // No Content-Type header — the browser sets the multipart boundary itself.\n const response = await sonorFetch(\n `${apiUrl}/api/public/forms/upload`,\n {\n method: 'POST',\n headers: { Authorization: `Bearer ${apiKey}` },\n body,\n },\n { retries: 1, timeoutMs: 60000 },\n )\n\n if (!response.ok) {\n throw new Error(`Upload failed (${response.status})`)\n }\n const data = (await response.json().catch(() => null)) as { url?: string } | null\n if (!data?.url) {\n throw new Error('Upload did not return a URL.')\n }\n return data.url\n}\n"]}
@@ -1,9 +1,9 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunkGDH42JAS_js = require('./chunk-GDH42JAS.js');
5
- require('./chunk-7BI2RVQD.js');
6
- require('./chunk-TJVZEDE3.js');
4
+ var chunk3GHPFLEH_js = require('./chunk-3GHPFLEH.js');
5
+ require('./chunk-TCZHRSWY.js');
6
+ require('./chunk-EL74YDNX.js');
7
7
  require('./chunk-SNAQBZPT.js');
8
8
  var React = require('react');
9
9
  var jsxRuntime = require('react/jsx-runtime');
@@ -67,7 +67,7 @@ async function uploadFormFile(file) {
67
67
  }
68
68
  const body = new FormData();
69
69
  body.append("file", file);
70
- const response = await chunkGDH42JAS_js.sonorFetch(
70
+ const response = await chunk3GHPFLEH_js.sonorFetch(
71
71
  `${apiUrl}/api/public/forms/upload`,
72
72
  {
73
73
  method: "POST",
@@ -87,5 +87,5 @@ async function uploadFormFile(file) {
87
87
  }
88
88
 
89
89
  exports.FileField = FileField;
90
- //# sourceMappingURL=FileField-SNI5XCHQ.js.map
91
- //# sourceMappingURL=FileField-SNI5XCHQ.js.map
90
+ //# sourceMappingURL=FileField-R4RQG77G.js.map
91
+ //# sourceMappingURL=FileField-R4RQG77G.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/forms/FileField.tsx"],"names":["React","jsxs","Fragment","jsx","sonorFetch"],"mappings":"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","file":"FileField-SNI5XCHQ.js","sourcesContent":["'use client'\n\n/**\n * File upload field — the one field type that cannot render on the server.\n *\n * It holds upload state and reads the browser-published credential globals, so\n * it lives here rather than in FormField.tsx. Pulling it out is what lets\n * FormField drop its `'use client'` directive and render inside a Server\n * Component (see StaticForm.tsx); a form WITHOUT a file field now ships no\n * field-rendering JavaScript at all.\n *\n * Uploads the chosen file to the Sonor API, which stores it and returns a\n * public URL — that URL becomes the field value, so large files never touch\n * the JSON submission body. The value stays empty until the upload succeeds,\n * so a required file field correctly blocks submission until the upload\n * completes (rather than submitting a useless bare filename).\n *\n * Note: forms containing a file field are NOT native-POST eligible (see\n * native-fallback.tsx) — a form-encoded POST cannot run this upload — so the\n * server shell renders a plain disabled-looking file input and the real\n * control arrives with the enhancement.\n */\n\nimport React from 'react'\nimport type { FormField as FormFieldType } from './types'\nimport { sonorFetch } from '../shared/sonorFetch'\n\nexport interface FileFieldProps {\n field: FormFieldType\n inputId: string\n classPrefix: string\n baseInputStyle: React.CSSProperties\n onChange: (value: unknown) => void\n}\n\nexport function FileField({\n field,\n inputId,\n classPrefix,\n baseInputStyle,\n onChange,\n}: FileFieldProps) {\n const [status, setStatus] = React.useState<'idle' | 'uploading' | 'error'>('idle')\n const [fileName, setFileName] = React.useState('')\n\n const handleFile = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0]\n if (!file) return\n setFileName(file.name)\n setStatus('uploading')\n onChange('') // clear any prior URL until this upload completes\n try {\n const url = await uploadFormFile(file)\n onChange(url)\n setStatus('idle')\n } catch (err) {\n console.error('[Forms] File upload failed:', err)\n onChange('')\n setStatus('error')\n }\n }\n\n return (\n <>\n <input\n id={inputId}\n className={`${classPrefix}__input ${classPrefix}__input--file`}\n type=\"file\"\n name={field.slug}\n required={field.is_required}\n disabled={status === 'uploading'}\n onChange={handleFile}\n style={baseInputStyle}\n />\n {status === 'uploading' && (\n <p style={{ color: 'var(--sk-text-tertiary, #6b7280)', fontSize: 14, marginTop: 4 }}>\n Uploading {fileName}…\n </p>\n )}\n {status === 'error' && (\n <p role=\"alert\" style={{ color: 'var(--sk-error, #dc2626)', fontSize: 14, marginTop: 4 }}>\n Upload failed. Please choose the file again.\n </p>\n )}\n </>\n )\n}\n\n/** Upload a single file to the Sonor API and return its stored public URL. */\nasync function uploadFormFile(file: File): Promise<string> {\n const apiUrl =\n typeof window !== 'undefined'\n ? (window as any).__SITE_KIT_API_URL__ || 'https://api.sonor.io'\n : 'https://api.sonor.io'\n const apiKey =\n typeof window !== 'undefined' ? (window as any).__SITE_KIT_API_KEY__ : undefined\n if (!apiKey) {\n throw new Error('API key is required to upload files.')\n }\n\n const body = new FormData()\n body.append('file', file)\n\n // No Content-Type header — the browser sets the multipart boundary itself.\n const response = await sonorFetch(\n `${apiUrl}/api/public/forms/upload`,\n {\n method: 'POST',\n headers: { Authorization: `Bearer ${apiKey}` },\n body,\n },\n { retries: 1, timeoutMs: 60000 },\n )\n\n if (!response.ok) {\n throw new Error(`Upload failed (${response.status})`)\n }\n const data = (await response.json().catch(() => null)) as { url?: string } | null\n if (!data?.url) {\n throw new Error('Upload did not return a URL.')\n }\n return data.url\n}\n"]}
1
+ {"version":3,"sources":["../src/forms/FileField.tsx"],"names":["React","jsxs","Fragment","jsx","sonorFetch"],"mappings":"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","file":"FileField-R4RQG77G.js","sourcesContent":["'use client'\n\n/**\n * File upload field — the one field type that cannot render on the server.\n *\n * It holds upload state and reads the browser-published credential globals, so\n * it lives here rather than in FormField.tsx. Pulling it out is what lets\n * FormField drop its `'use client'` directive and render inside a Server\n * Component (see StaticForm.tsx); a form WITHOUT a file field now ships no\n * field-rendering JavaScript at all.\n *\n * Uploads the chosen file to the Sonor API, which stores it and returns a\n * public URL — that URL becomes the field value, so large files never touch\n * the JSON submission body. The value stays empty until the upload succeeds,\n * so a required file field correctly blocks submission until the upload\n * completes (rather than submitting a useless bare filename).\n *\n * Note: forms containing a file field are NOT native-POST eligible (see\n * native-fallback.tsx) — a form-encoded POST cannot run this upload — so the\n * server shell renders a plain disabled-looking file input and the real\n * control arrives with the enhancement.\n */\n\nimport React from 'react'\nimport type { FormField as FormFieldType } from './types'\nimport { sonorFetch } from '../shared/sonorFetch'\n\nexport interface FileFieldProps {\n field: FormFieldType\n inputId: string\n classPrefix: string\n baseInputStyle: React.CSSProperties\n onChange: (value: unknown) => void\n}\n\nexport function FileField({\n field,\n inputId,\n classPrefix,\n baseInputStyle,\n onChange,\n}: FileFieldProps) {\n const [status, setStatus] = React.useState<'idle' | 'uploading' | 'error'>('idle')\n const [fileName, setFileName] = React.useState('')\n\n const handleFile = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0]\n if (!file) return\n setFileName(file.name)\n setStatus('uploading')\n onChange('') // clear any prior URL until this upload completes\n try {\n const url = await uploadFormFile(file)\n onChange(url)\n setStatus('idle')\n } catch (err) {\n console.error('[Forms] File upload failed:', err)\n onChange('')\n setStatus('error')\n }\n }\n\n return (\n <>\n <input\n id={inputId}\n className={`${classPrefix}__input ${classPrefix}__input--file`}\n type=\"file\"\n name={field.slug}\n required={field.is_required}\n disabled={status === 'uploading'}\n onChange={handleFile}\n style={baseInputStyle}\n />\n {status === 'uploading' && (\n <p style={{ color: 'var(--sk-text-tertiary, #6b7280)', fontSize: 14, marginTop: 4 }}>\n Uploading {fileName}…\n </p>\n )}\n {status === 'error' && (\n <p role=\"alert\" style={{ color: 'var(--sk-error, #dc2626)', fontSize: 14, marginTop: 4 }}>\n Upload failed. Please choose the file again.\n </p>\n )}\n </>\n )\n}\n\n/** Upload a single file to the Sonor API and return its stored public URL. */\nasync function uploadFormFile(file: File): Promise<string> {\n const apiUrl =\n typeof window !== 'undefined'\n ? (window as any).__SITE_KIT_API_URL__ || 'https://api.sonor.io'\n : 'https://api.sonor.io'\n const apiKey =\n typeof window !== 'undefined' ? (window as any).__SITE_KIT_API_KEY__ : undefined\n if (!apiKey) {\n throw new Error('API key is required to upload files.')\n }\n\n const body = new FormData()\n body.append('file', file)\n\n // No Content-Type header — the browser sets the multipart boundary itself.\n const response = await sonorFetch(\n `${apiUrl}/api/public/forms/upload`,\n {\n method: 'POST',\n headers: { Authorization: `Bearer ${apiKey}` },\n body,\n },\n { retries: 1, timeoutMs: 60000 },\n )\n\n if (!response.ok) {\n throw new Error(`Upload failed (${response.status})`)\n }\n const data = (await response.json().catch(() => null)) as { url?: string } | null\n if (!data?.url) {\n throw new Error('Upload did not return a URL.')\n }\n return data.url\n}\n"]}