@sonordev/site-kit 6.3.6 → 6.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (291) hide show
  1. package/agent-manifest.json +8 -2
  2. package/dist/AnalyticsProvider-44PDLORZ.js +34 -0
  3. package/dist/{AnalyticsProvider-L3GWK5PO.js.map → AnalyticsProvider-44PDLORZ.js.map} +1 -1
  4. package/dist/AnalyticsProvider-F6KHEAOX.mjs +13 -0
  5. package/dist/{AnalyticsProvider-XDVJTAPN.mjs.map → AnalyticsProvider-F6KHEAOX.mjs.map} +1 -1
  6. package/dist/{ArticleViewTracker-YMGW6ZXB.js → ArticleViewTracker-MGNVIHZ4.js} +6 -6
  7. package/dist/{ArticleViewTracker-YMGW6ZXB.js.map → ArticleViewTracker-MGNVIHZ4.js.map} +1 -1
  8. package/dist/{ArticleViewTracker-7AJJTGFY.mjs → ArticleViewTracker-NI4UNSY7.mjs} +5 -5
  9. package/dist/{ArticleViewTracker-7AJJTGFY.mjs.map → ArticleViewTracker-NI4UNSY7.mjs.map} +1 -1
  10. package/dist/{ChatWidget-MR64ZLOG.mjs → ChatWidget-XSALHDDW.mjs} +7 -7
  11. package/dist/{ChatWidget-MR64ZLOG.mjs.map → ChatWidget-XSALHDDW.mjs.map} +1 -1
  12. package/dist/{ChatWidget-IAYEXLNX.js → ChatWidget-YBXJRR2Z.js} +10 -10
  13. package/dist/{ChatWidget-IAYEXLNX.js.map → ChatWidget-YBXJRR2Z.js.map} +1 -1
  14. package/dist/EngageWidget-DUEXPVOY.mjs +13 -0
  15. package/dist/{EngageWidget-RANSIKC3.mjs.map → EngageWidget-DUEXPVOY.mjs.map} +1 -1
  16. package/dist/EngageWidget-MDCRS3BN.js +22 -0
  17. package/dist/{EngageWidget-BF7DH4GO.js.map → EngageWidget-MDCRS3BN.js.map} +1 -1
  18. package/dist/{FileField-VRKATE4G.js → FileField-AXU6KBSV.js} +6 -6
  19. package/dist/{FileField-VRKATE4G.js.map → FileField-AXU6KBSV.js.map} +1 -1
  20. package/dist/{FileField-7ZNQ5BID.mjs → FileField-UTLGR5ZN.mjs} +5 -5
  21. package/dist/{FileField-7ZNQ5BID.mjs.map → FileField-UTLGR5ZN.mjs.map} +1 -1
  22. package/dist/{FormSpotlight-QNH7XGYS.mjs → FormSpotlight-NWLCZMOT.mjs} +3 -3
  23. package/dist/{FormSpotlight-QNH7XGYS.mjs.map → FormSpotlight-NWLCZMOT.mjs.map} +1 -1
  24. package/dist/{FormSpotlight-VQJ2QWIU.js → FormSpotlight-RR5KJDIH.js} +9 -9
  25. package/dist/{FormSpotlight-VQJ2QWIU.js.map → FormSpotlight-RR5KJDIH.js.map} +1 -1
  26. package/dist/{FormStage-3JIN6X6O.js → FormStage-GFNX4GLU.js} +9 -9
  27. package/dist/{FormStage-3JIN6X6O.js.map → FormStage-GFNX4GLU.js.map} +1 -1
  28. package/dist/{FormStage-XB4JNFCH.mjs → FormStage-V4XKLI6J.mjs} +3 -3
  29. package/dist/{FormStage-XB4JNFCH.mjs.map → FormStage-V4XKLI6J.mjs.map} +1 -1
  30. package/dist/ManagedForm-4AD3LWSC.js +25 -0
  31. package/dist/{ManagedForm-Q5UFMUBE.js.map → ManagedForm-4AD3LWSC.js.map} +1 -1
  32. package/dist/ManagedForm-4IWPG6AZ.mjs +16 -0
  33. package/dist/{ManagedForm-E6F4FLVY.mjs.map → ManagedForm-4IWPG6AZ.mjs.map} +1 -1
  34. package/dist/{ManagedNewsletterForm-OEEC3GVY.mjs → ManagedNewsletterForm-ARSY2VHC.mjs} +6 -6
  35. package/dist/{ManagedNewsletterForm-OEEC3GVY.mjs.map → ManagedNewsletterForm-ARSY2VHC.mjs.map} +1 -1
  36. package/dist/{ManagedNewsletterForm-UTNOJ5T4.js → ManagedNewsletterForm-HJZNUABY.js} +7 -7
  37. package/dist/{ManagedNewsletterForm-UTNOJ5T4.js.map → ManagedNewsletterForm-HJZNUABY.js.map} +1 -1
  38. package/dist/{SignalCore-PWN5X6FF.mjs → SignalCore-N2LKG4XN.mjs} +5 -5
  39. package/dist/{SignalCore-PWN5X6FF.mjs.map → SignalCore-N2LKG4XN.mjs.map} +1 -1
  40. package/dist/{SignalCore-4AUWHMYK.js → SignalCore-P2JUY2BO.js} +11 -11
  41. package/dist/{SignalCore-4AUWHMYK.js.map → SignalCore-P2JUY2BO.js.map} +1 -1
  42. package/dist/SitemapSync-KFY4PJ7G.js +19 -0
  43. package/dist/{SitemapSync-DHJ25PSH.js.map → SitemapSync-KFY4PJ7G.js.map} +1 -1
  44. package/dist/SitemapSync-UYDL7T4M.mjs +10 -0
  45. package/dist/{SitemapSync-ZA2MNM63.mjs.map → SitemapSync-UYDL7T4M.mjs.map} +1 -1
  46. package/dist/analytics/index.js +14 -13
  47. package/dist/analytics/index.mjs +6 -5
  48. package/dist/articles/AuthorPage.d.ts +1 -1
  49. package/dist/articles/AuthorPage.d.ts.map +1 -1
  50. package/dist/articles/author-schema.d.ts +59 -13
  51. package/dist/articles/author-schema.d.ts.map +1 -1
  52. package/dist/articles/index.js +24 -23
  53. package/dist/articles/index.js.map +1 -1
  54. package/dist/articles/index.mjs +12 -11
  55. package/dist/articles/index.mjs.map +1 -1
  56. package/dist/articles/routes.d.ts +9 -0
  57. package/dist/articles/routes.d.ts.map +1 -1
  58. package/dist/articles/server-core.d.ts +5 -2
  59. package/dist/articles/server-core.d.ts.map +1 -1
  60. package/dist/articles/server-ui.js +45 -45
  61. package/dist/articles/server-ui.mjs +8 -8
  62. package/dist/articles/server.d.ts +5 -2
  63. package/dist/articles/server.d.ts.map +1 -1
  64. package/dist/articles/server.js +72 -56
  65. package/dist/articles/server.mjs +3 -3
  66. package/dist/articles/types.d.ts +23 -0
  67. package/dist/articles/types.d.ts.map +1 -1
  68. package/dist/{chunk-UAOQVHZW.js → chunk-34XL7TVH.js} +4 -4
  69. package/dist/{chunk-UAOQVHZW.js.map → chunk-34XL7TVH.js.map} +1 -1
  70. package/dist/chunk-3AOKYAZ2.js +135 -0
  71. package/dist/chunk-3AOKYAZ2.js.map +1 -0
  72. package/dist/{chunk-BJKA3XRS.mjs → chunk-3BLKKF67.mjs} +4 -4
  73. package/dist/{chunk-BJKA3XRS.mjs.map → chunk-3BLKKF67.mjs.map} +1 -1
  74. package/dist/{chunk-3J5L5DIK.js → chunk-3EAS4PAT.js} +3 -3
  75. package/dist/{chunk-3J5L5DIK.js.map → chunk-3EAS4PAT.js.map} +1 -1
  76. package/dist/{chunk-SB4CJX2X.mjs → chunk-42LLFAJQ.mjs} +3 -3
  77. package/dist/{chunk-SB4CJX2X.mjs.map → chunk-42LLFAJQ.mjs.map} +1 -1
  78. package/dist/{chunk-ZR43XFUM.js → chunk-55J2KE7D.js} +3 -3
  79. package/dist/chunk-55J2KE7D.js.map +1 -0
  80. package/dist/{chunk-VGBUC2JP.js → chunk-5ZMTEK7U.js} +10 -10
  81. package/dist/{chunk-VGBUC2JP.js.map → chunk-5ZMTEK7U.js.map} +1 -1
  82. package/dist/{chunk-6DCAMW62.mjs → chunk-6C47333H.mjs} +3 -3
  83. package/dist/chunk-6C47333H.mjs.map +1 -0
  84. package/dist/{chunk-E7EV2AHT.js → chunk-6OQYRVMI.js} +9 -9
  85. package/dist/{chunk-E7EV2AHT.js.map → chunk-6OQYRVMI.js.map} +1 -1
  86. package/dist/{chunk-UJIKP35G.mjs → chunk-7F66Y4MA.mjs} +4 -4
  87. package/dist/{chunk-UJIKP35G.mjs.map → chunk-7F66Y4MA.mjs.map} +1 -1
  88. package/dist/{chunk-6MOGGEY3.mjs → chunk-A2HL22BO.mjs} +3 -3
  89. package/dist/{chunk-6MOGGEY3.mjs.map → chunk-A2HL22BO.mjs.map} +1 -1
  90. package/dist/{chunk-7NFSSPGM.js → chunk-AL4Z6VYF.js} +8 -8
  91. package/dist/{chunk-7NFSSPGM.js.map → chunk-AL4Z6VYF.js.map} +1 -1
  92. package/dist/{chunk-W46QIVBM.mjs → chunk-B6QPCAEG.mjs} +3 -3
  93. package/dist/{chunk-W46QIVBM.mjs.map → chunk-B6QPCAEG.mjs.map} +1 -1
  94. package/dist/{chunk-EB33U2WT.js → chunk-BHZHWXER.js} +131 -71
  95. package/dist/chunk-BHZHWXER.js.map +1 -0
  96. package/dist/{chunk-R26FAQWF.mjs → chunk-BNKBRLJK.mjs} +3 -3
  97. package/dist/{chunk-R26FAQWF.mjs.map → chunk-BNKBRLJK.mjs.map} +1 -1
  98. package/dist/{chunk-A6UYV475.mjs → chunk-CABEVWKJ.mjs} +4 -24
  99. package/dist/chunk-CABEVWKJ.mjs.map +1 -0
  100. package/dist/{chunk-LWCAZDY2.js → chunk-CDRQYJUT.js} +4 -4
  101. package/dist/{chunk-LWCAZDY2.js.map → chunk-CDRQYJUT.js.map} +1 -1
  102. package/dist/{chunk-SAOUAIRS.js → chunk-CM4AVKXR.js} +14 -14
  103. package/dist/{chunk-SAOUAIRS.js.map → chunk-CM4AVKXR.js.map} +1 -1
  104. package/dist/{chunk-KMONA7CT.mjs → chunk-D3WJMSTB.mjs} +3 -3
  105. package/dist/{chunk-KMONA7CT.mjs.map → chunk-D3WJMSTB.mjs.map} +1 -1
  106. package/dist/{chunk-3Q3Y6OQE.mjs → chunk-DWZGW77V.mjs} +4 -4
  107. package/dist/{chunk-3Q3Y6OQE.mjs.map → chunk-DWZGW77V.mjs.map} +1 -1
  108. package/dist/{chunk-L6BQIDSZ.mjs → chunk-FPVYKSXE.mjs} +13 -10
  109. package/dist/chunk-FPVYKSXE.mjs.map +1 -0
  110. package/dist/{chunk-5XDOBM5S.js → chunk-G2KGHIAP.js} +3 -3
  111. package/dist/{chunk-5XDOBM5S.js.map → chunk-G2KGHIAP.js.map} +1 -1
  112. package/dist/chunk-GFSQMK35.mjs +127 -0
  113. package/dist/chunk-GFSQMK35.mjs.map +1 -0
  114. package/dist/chunk-GIGUDKLS.mjs +6 -0
  115. package/dist/{chunk-3V6DIQI7.mjs.map → chunk-GIGUDKLS.mjs.map} +1 -1
  116. package/dist/{chunk-BJ4T65OK.mjs → chunk-H4TSADY3.mjs} +3 -3
  117. package/dist/{chunk-BJ4T65OK.mjs.map → chunk-H4TSADY3.mjs.map} +1 -1
  118. package/dist/{chunk-J4C3JAJF.js → chunk-IO65ROAO.js} +15 -15
  119. package/dist/{chunk-J4C3JAJF.js.map → chunk-IO65ROAO.js.map} +1 -1
  120. package/dist/chunk-JCDX37BY.js +58 -0
  121. package/dist/chunk-JCDX37BY.js.map +1 -0
  122. package/dist/{chunk-5J4FKRGH.mjs → chunk-MDQLON5R.mjs} +5 -5
  123. package/dist/{chunk-5J4FKRGH.mjs.map → chunk-MDQLON5R.mjs.map} +1 -1
  124. package/dist/{chunk-3POB4JKR.js → chunk-MHKD34B4.js} +15 -15
  125. package/dist/{chunk-3POB4JKR.js.map → chunk-MHKD34B4.js.map} +1 -1
  126. package/dist/chunk-MXJOKOFK.mjs +51 -0
  127. package/dist/chunk-MXJOKOFK.mjs.map +1 -0
  128. package/dist/{chunk-5RNAUYWE.js → chunk-NH2P27MA.js} +4 -27
  129. package/dist/chunk-NH2P27MA.js.map +1 -0
  130. package/dist/{chunk-5DZVQW35.mjs → chunk-OFBEBMXN.mjs} +4 -4
  131. package/dist/{chunk-5DZVQW35.mjs.map → chunk-OFBEBMXN.mjs.map} +1 -1
  132. package/dist/{chunk-G3L26XQ7.js → chunk-OIPG3EGM.js} +5 -5
  133. package/dist/{chunk-G3L26XQ7.js.map → chunk-OIPG3EGM.js.map} +1 -1
  134. package/dist/{chunk-2UZULHI4.js → chunk-OY3PDIB3.js} +10 -10
  135. package/dist/{chunk-2UZULHI4.js.map → chunk-OY3PDIB3.js.map} +1 -1
  136. package/dist/{chunk-SNXJXPB6.js → chunk-PFDRQJKJ.js} +13 -13
  137. package/dist/{chunk-SNXJXPB6.js.map → chunk-PFDRQJKJ.js.map} +1 -1
  138. package/dist/{chunk-CXYGKK4U.mjs → chunk-PGYOBEPL.mjs} +3 -3
  139. package/dist/{chunk-CXYGKK4U.mjs.map → chunk-PGYOBEPL.mjs.map} +1 -1
  140. package/dist/{chunk-TE3YNZVH.js → chunk-PIPGH7GA.js} +4 -4
  141. package/dist/{chunk-TE3YNZVH.js.map → chunk-PIPGH7GA.js.map} +1 -1
  142. package/dist/chunk-PURI56RE.js +8 -0
  143. package/dist/{chunk-6SBRD5KT.js.map → chunk-PURI56RE.js.map} +1 -1
  144. package/dist/{chunk-X3MY4PL7.mjs → chunk-QAQTDHHT.mjs} +10 -14
  145. package/dist/chunk-QAQTDHHT.mjs.map +1 -0
  146. package/dist/{chunk-PMWF5CRL.js → chunk-QCS7NWMA.js} +15 -12
  147. package/dist/chunk-QCS7NWMA.js.map +1 -0
  148. package/dist/{chunk-HXHRS3PX.mjs → chunk-RCB6HEHM.mjs} +3 -3
  149. package/dist/{chunk-HXHRS3PX.mjs.map → chunk-RCB6HEHM.mjs.map} +1 -1
  150. package/dist/{chunk-ANYCUTS5.js → chunk-RMDH2HMW.js} +3 -3
  151. package/dist/{chunk-ANYCUTS5.js.map → chunk-RMDH2HMW.js.map} +1 -1
  152. package/dist/{chunk-NAA5J2JM.js → chunk-RQROZLH3.js} +47 -51
  153. package/dist/chunk-RQROZLH3.js.map +1 -0
  154. package/dist/{chunk-X5J3PYZJ.js → chunk-SUGBIEYQ.js} +9 -9
  155. package/dist/{chunk-X5J3PYZJ.js.map → chunk-SUGBIEYQ.js.map} +1 -1
  156. package/dist/{chunk-LFF32POH.mjs → chunk-SVCKJ5KH.mjs} +4 -4
  157. package/dist/{chunk-LFF32POH.mjs.map → chunk-SVCKJ5KH.mjs.map} +1 -1
  158. package/dist/{chunk-YKZ3EVAQ.mjs → chunk-THO4NS6Z.mjs} +3 -3
  159. package/dist/{chunk-YKZ3EVAQ.mjs.map → chunk-THO4NS6Z.mjs.map} +1 -1
  160. package/dist/{chunk-K6ZQVDP4.mjs → chunk-TPEPAHU5.mjs} +3 -3
  161. package/dist/{chunk-K6ZQVDP4.mjs.map → chunk-TPEPAHU5.mjs.map} +1 -1
  162. package/dist/{chunk-FRUBUQOH.js → chunk-U577ITSA.js} +5 -5
  163. package/dist/{chunk-FRUBUQOH.js.map → chunk-U577ITSA.js.map} +1 -1
  164. package/dist/{chunk-B2NO5QVY.mjs → chunk-UCQDE5UH.mjs} +3 -3
  165. package/dist/{chunk-B2NO5QVY.mjs.map → chunk-UCQDE5UH.mjs.map} +1 -1
  166. package/dist/{chunk-KB7SIIVY.mjs → chunk-VA2O5OSV.mjs} +3 -3
  167. package/dist/{chunk-KB7SIIVY.mjs.map → chunk-VA2O5OSV.mjs.map} +1 -1
  168. package/dist/{chunk-6I5O5CTL.mjs → chunk-VJTKIKZY.mjs} +128 -68
  169. package/dist/chunk-VJTKIKZY.mjs.map +1 -0
  170. package/dist/{chunk-OLVCGOXZ.js → chunk-VUAGR6VL.js} +12 -12
  171. package/dist/{chunk-OLVCGOXZ.js.map → chunk-VUAGR6VL.js.map} +1 -1
  172. package/dist/{chunk-PQICWWQW.mjs → chunk-XEOIGCUE.mjs} +5 -5
  173. package/dist/{chunk-PQICWWQW.mjs.map → chunk-XEOIGCUE.mjs.map} +1 -1
  174. package/dist/chunk-YMZNEDFP.js +39 -0
  175. package/dist/chunk-YMZNEDFP.js.map +1 -0
  176. package/dist/chunk-Z2URIOKG.mjs +36 -0
  177. package/dist/chunk-Z2URIOKG.mjs.map +1 -0
  178. package/dist/{chunk-2MEMK5XC.js → chunk-ZXC56JS3.js} +14 -14
  179. package/dist/{chunk-2MEMK5XC.js.map → chunk-ZXC56JS3.js.map} +1 -1
  180. package/dist/cli/index.js +3 -3
  181. package/dist/cli/index.mjs +1 -1
  182. package/dist/client/index.js +4 -4
  183. package/dist/client/index.mjs +3 -3
  184. package/dist/commerce/index.js +59 -58
  185. package/dist/commerce/index.mjs +7 -6
  186. package/dist/engage/DesignRenderer.d.ts.map +1 -1
  187. package/dist/engage/EngageWidget.d.ts.map +1 -1
  188. package/dist/engage/element-rules.d.ts +39 -0
  189. package/dist/engage/element-rules.d.ts.map +1 -0
  190. package/dist/engage/index.js +11 -10
  191. package/dist/engage/index.js.map +1 -1
  192. package/dist/engage/index.mjs +8 -7
  193. package/dist/engage/index.mjs.map +1 -1
  194. package/dist/fleet/index.js +10 -9
  195. package/dist/fleet/index.mjs +6 -5
  196. package/dist/forms/index.js +13 -13
  197. package/dist/forms/index.mjs +7 -7
  198. package/dist/forms/server.js +2 -2
  199. package/dist/forms/server.mjs +1 -1
  200. package/dist/images/index.js +11 -11
  201. package/dist/images/index.mjs +4 -4
  202. package/dist/index.js +65 -64
  203. package/dist/index.js.map +1 -1
  204. package/dist/index.mjs +11 -10
  205. package/dist/index.mjs.map +1 -1
  206. package/dist/layout/SiteKitClientProviders.d.ts.map +1 -1
  207. package/dist/layout/client.d.ts.map +1 -1
  208. package/dist/layout/client.js +10 -9
  209. package/dist/layout/client.mjs +9 -8
  210. package/dist/layout/index.js +12 -11
  211. package/dist/layout/index.js.map +1 -1
  212. package/dist/layout/index.mjs +10 -9
  213. package/dist/layout/index.mjs.map +1 -1
  214. package/dist/layout/types.d.ts +6 -0
  215. package/dist/layout/types.d.ts.map +1 -1
  216. package/dist/llms/index.d.ts +2 -0
  217. package/dist/llms/index.d.ts.map +1 -1
  218. package/dist/llms/index.js +129 -14
  219. package/dist/llms/index.js.map +1 -1
  220. package/dist/llms/index.mjs +115 -5
  221. package/dist/llms/index.mjs.map +1 -1
  222. package/dist/llms/revalidate.d.ts +3 -0
  223. package/dist/llms/revalidate.d.ts.map +1 -1
  224. package/dist/llms/seo-revalidate.d.ts +105 -0
  225. package/dist/llms/seo-revalidate.d.ts.map +1 -0
  226. package/dist/maps/index.js +5 -5
  227. package/dist/maps/index.mjs +3 -3
  228. package/dist/mcp/transport.d.ts +166 -0
  229. package/dist/mcp/transport.d.ts.map +1 -0
  230. package/dist/mcp/transport.js +137 -0
  231. package/dist/mcp/transport.js.map +1 -0
  232. package/dist/mcp/transport.mjs +123 -0
  233. package/dist/mcp/transport.mjs.map +1 -0
  234. package/dist/portfolio/contract.d.ts +93 -0
  235. package/dist/portfolio/contract.d.ts.map +1 -1
  236. package/dist/portfolio/contract.js +94 -1
  237. package/dist/portfolio/contract.js.map +1 -1
  238. package/dist/portfolio/contract.mjs +79 -2
  239. package/dist/portfolio/contract.mjs.map +1 -1
  240. package/dist/search/index.js +4 -4
  241. package/dist/search/index.mjs +3 -3
  242. package/dist/seo/client.js +7 -6
  243. package/dist/seo/client.mjs +6 -5
  244. package/dist/seo/index.js +7 -6
  245. package/dist/seo/index.js.map +1 -1
  246. package/dist/seo/index.mjs +6 -5
  247. package/dist/seo/index.mjs.map +1 -1
  248. package/dist/seo/register-sitemap-cli.js +1 -1
  249. package/dist/seo/register-sitemap-cli.mjs +1 -1
  250. package/dist/server/index.js +3 -3
  251. package/dist/server/index.mjs +2 -2
  252. package/dist/shared/build-entries.d.ts +7 -0
  253. package/dist/shared/build-entries.d.ts.map +1 -1
  254. package/dist/shared/frame.d.ts +15 -0
  255. package/dist/shared/frame.d.ts.map +1 -1
  256. package/dist/shared/request-guards.d.ts +27 -0
  257. package/dist/shared/request-guards.d.ts.map +1 -0
  258. package/dist/shared/version.d.ts +1 -1
  259. package/dist/signal/index.js +11 -11
  260. package/dist/signal/index.mjs +2 -2
  261. package/dist/sitemap/index.js +3 -3
  262. package/dist/sitemap/index.mjs +2 -2
  263. package/dist/sync/index.js +17 -17
  264. package/dist/sync/index.mjs +4 -4
  265. package/dist/{writeLLMsTxt-LYYC3ZSN.mjs → writeLLMsTxt-IYJILIU3.mjs} +3 -3
  266. package/dist/{writeLLMsTxt-XHLHJ5XY.js → writeLLMsTxt-SQG4B63X.js} +4 -4
  267. package/package.json +24 -21
  268. package/dist/AnalyticsProvider-L3GWK5PO.js +0 -33
  269. package/dist/AnalyticsProvider-XDVJTAPN.mjs +0 -12
  270. package/dist/EngageWidget-BF7DH4GO.js +0 -21
  271. package/dist/EngageWidget-RANSIKC3.mjs +0 -12
  272. package/dist/ManagedForm-E6F4FLVY.mjs +0 -16
  273. package/dist/ManagedForm-Q5UFMUBE.js +0 -25
  274. package/dist/SitemapSync-DHJ25PSH.js +0 -18
  275. package/dist/SitemapSync-ZA2MNM63.mjs +0 -9
  276. package/dist/chunk-3V6DIQI7.mjs +0 -6
  277. package/dist/chunk-5RNAUYWE.js.map +0 -1
  278. package/dist/chunk-6DCAMW62.mjs.map +0 -1
  279. package/dist/chunk-6I5O5CTL.mjs.map +0 -1
  280. package/dist/chunk-6SBRD5KT.js +0 -8
  281. package/dist/chunk-A6UYV475.mjs.map +0 -1
  282. package/dist/chunk-EB33U2WT.js.map +0 -1
  283. package/dist/chunk-L6BQIDSZ.mjs.map +0 -1
  284. package/dist/chunk-NAA5J2JM.js.map +0 -1
  285. package/dist/chunk-PMWF5CRL.js.map +0 -1
  286. package/dist/chunk-X3MY4PL7.mjs.map +0 -1
  287. package/dist/chunk-YRCR7WY3.js +0 -65
  288. package/dist/chunk-YRCR7WY3.js.map +0 -1
  289. package/dist/chunk-ZL35JCDA.mjs +0 -61
  290. package/dist/chunk-ZL35JCDA.mjs.map +0 -1
  291. package/dist/chunk-ZR43XFUM.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/engage/element-rules.ts","../src/engage/DesignRenderer.tsx","../src/engage/EngageWidget.tsx"],"names":["useState","jsx","createElement","jsxs","React","dynamic","resolveAnalyticsTarget","DEFAULT_ENGAGE_Z_INDEX","usePathname","useEffect","getOrCreateVisitorId","sonorFetch","useCallback","ReactDOM","Fragment","useRef"],"mappings":"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","file":"chunk-BHZHWXER.js","sourcesContent":["/**\n * @sonordev/site-kit/engage - the rules EngageWidget applies to popups,\n * banners and toasts, as pure functions (the package's tests have no DOM).\n *\n * Sonor validates every popup before it's published (sonor-api\n * popups/popup-contract.ts), so these are the second check: a link the kit\n * would follow or an image it would load must be safe here too, whatever the\n * API sent.\n */\n\nimport type { EngageElement } from './types'\n\n// Browsers strip tabs and newlines before parsing a URL, so \"java\\tscript:\"\n// runs as javascript:. A URL carrying any control character or space is\n// refused outright rather than cleaned.\nfunction hasControlOrSpace(value: string): boolean {\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i)\n if (code <= 0x20 || (code >= 0x7f && code <= 0x9f)) return true\n }\n return false\n}\n\nfunction isSitePath(value: string): boolean {\n return value.startsWith('/') && !value.startsWith('//') && !value.startsWith('/\\\\')\n}\n\n/**\n * A URL a popup's button or link may send a visitor to: a path on this site,\n * an anchor, http(s), mailto or tel. Anything else (javascript:, data:,\n * protocol-relative) is undefined, and the kit doesn't navigate.\n */\nexport function safeActionUrl(raw: unknown): string | undefined {\n if (typeof raw !== 'string') return undefined\n const value = raw.trim()\n if (!value || hasControlOrSpace(value)) return undefined\n if (value.startsWith('#') || isSitePath(value)) return value\n const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(value)?.[1]?.toLowerCase()\n return scheme && ['http', 'https', 'mailto', 'tel'].includes(scheme) ? value : undefined\n}\n\n/** An image a popup may load: http(s) or a path on this site. */\nexport function safeImageSrc(raw: unknown): string | undefined {\n if (typeof raw !== 'string') return undefined\n const value = raw.trim()\n if (!value || hasControlOrSpace(value)) return undefined\n if (isSitePath(value)) return value\n return /^https?:\\/\\//i.test(value) ? value : undefined\n}\n\n/** Exact path, or a prefix ending in `*`. The grammar Sonor stores page patterns in. */\nexport function matchPath(pathname: string, pattern: string): boolean {\n if (pattern.endsWith('*')) return pathname.startsWith(pattern.slice(0, -1))\n return pathname === pattern\n}\n\nexport type DeviceType = 'desktop' | 'mobile' | 'tablet'\n\nexport function deviceFromUserAgent(ua: string): DeviceType {\n if (/tablet|ipad|playbook|silk/i.test(ua)) return 'tablet'\n if (/mobile|iphone|ipod|android|blackberry|opera mini|iemobile/i.test(ua)) return 'mobile'\n return 'desktop'\n}\n\n/** The storage key that remembers a visitor saw (closed or clicked) an element. */\nexport function seenKey(elementId: string): string {\n return `_engage_${elementId}`\n}\n\ninterface SeenStore {\n local: Pick<Storage, 'getItem'> | null\n session: Pick<Storage, 'getItem'> | null\n}\n\n/** Whether an element's targeting and frequency cap allow it on this page, for this visitor. */\nexport function isEligible(\n element: EngageElement,\n pathname: string,\n device: DeviceType,\n store: SeenStore,\n now: number = Date.now(),\n): boolean {\n const pages = element.targeting?.pages\n if (pages) {\n if (pages.exclude?.some((p) => matchPath(pathname, p))) return false\n if (pages.include && !pages.include.some((p) => matchPath(pathname, p))) return false\n }\n if (element.targeting?.devices && !element.targeting.devices.includes(device)) return false\n\n const frequency = element.trigger?.frequency\n if (frequency) {\n const key = seenKey(element.id)\n if (frequency.type === 'once') {\n if (store.local?.getItem(key)) return false\n } else if (frequency.type === 'once-per-session') {\n if (store.session?.getItem(key)) return false\n } else if (frequency.type === 'every-n-days' && frequency.days) {\n const last = store.local?.getItem(key)\n if (last && now - parseInt(last, 10) < frequency.days * 86_400_000) return false\n }\n }\n return true\n}\n\n/**\n * The active list after `id` asks to show. A popup (the kind centred over a\n * dimmed page) waits while another is open, so two never stack; banners and\n * toasts show alongside. Elements arrive from Sonor highest priority first, so\n * the first popup to trigger is the one that wins a tie.\n */\nexport function activateElement(active: string[], id: string, elements: EngageElement[]): string[] {\n if (active.includes(id)) return active\n const typeOf = (elementId: string) => elements.find((e) => e.id === elementId)?.type\n if (typeOf(id) === 'popup' && active.some((other) => typeOf(other) === 'popup')) return active\n return [...active, id]\n}\n","/**\n * @sonordev/site-kit/engage - Design Renderer\n * \n * Renders design_json from Engage Studio as React components.\n * This is the runtime renderer that converts the visual builder's\n * JSON structure into actual React elements.\n */\n\n'use client'\n\nimport React, { createElement, CSSProperties, MouseEvent, useState } from 'react'\nimport { safeActionUrl, safeImageSrc } from './element-rules'\n\n// ============================================\n// Types\n// ============================================\n\nexport interface DesignNode {\n id: string\n type: string\n name: string\n children?: DesignNode[]\n props?: Record<string, any>\n style?: CSSProperties\n}\n\nexport interface DesignDocument {\n id: string\n type: string\n name: string\n children: DesignNode[]\n style?: CSSProperties\n props?: Record<string, any>\n}\n\nexport interface DesignRendererProps {\n design: DesignDocument\n onClose?: () => void\n onAction?: (action: ActionConfig, node: DesignNode) => void\n context?: EngageContext\n}\n\nexport interface ActionConfig {\n action: string\n url?: string\n newTab?: boolean\n target?: string\n text?: string\n productId?: string\n formId?: string\n}\n\nexport interface EngageContext {\n // Site-Kit context data that can be bound to elements\n user?: {\n name?: string\n email?: string\n isLoggedIn?: boolean\n }\n cart?: {\n itemCount?: number\n total?: number\n }\n page?: {\n url?: string\n title?: string\n }\n // Custom data from the page\n [key: string]: any\n}\n\n// ============================================\n// Action Handlers\n// ============================================\n\nfunction handleAction(\n action: ActionConfig,\n node: DesignNode,\n onClose?: () => void,\n onAction?: (action: ActionConfig, node: DesignNode) => void,\n): void {\n if (!action?.action || action.action === 'none') return\n\n // Let parent handle custom actions\n if (onAction) {\n onAction(action, node)\n }\n\n switch (action.action) {\n case 'link': {\n // Only a site path, anchor, http(s), mailto or tel: a design is data\n // from the API, and a javascript: URL here would run on the site.\n const url = safeActionUrl(action.url)\n if (url) {\n if (action.newTab) {\n window.open(url, '_blank', 'noopener,noreferrer')\n } else {\n window.location.href = url\n }\n }\n break\n }\n\n case 'scroll':\n if (action.target) {\n const element = document.querySelector(action.target)\n element?.scrollIntoView({ behavior: 'smooth' })\n }\n break\n\n case 'close':\n onClose?.()\n break\n\n case 'copy':\n if (action.text) {\n navigator.clipboard.writeText(action.text).catch(console.error)\n }\n break\n\n case 'share':\n if (navigator.share) {\n navigator.share({\n title: document.title,\n url: window.location.href,\n }).catch(console.error)\n }\n break\n\n case 'download': {\n const url = safeActionUrl(action.url)\n if (url) {\n const a = document.createElement('a')\n a.href = url\n a.download = ''\n a.click()\n }\n break\n }\n\n // Commerce actions - these should be handled by onAction callback\n case 'add_to_cart':\n case 'checkout':\n case 'book':\n case 'submit_form':\n case 'open_form':\n // Handled by parent via onAction\n break\n }\n}\n\n// ============================================\n// Animation Styles\n// ============================================\n\nconst animationKeyframes = `\n@keyframes engageFadeIn { from { opacity: 0; } to { opacity: 1; } }\n@keyframes engageFadeInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }\n@keyframes engageFadeInDown { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } }\n@keyframes engageSlideInLeft { from { opacity: 0; transform: translateX(-20px); } to { opacity: 1; transform: translateX(0); } }\n@keyframes engageSlideInRight { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: translateX(0); } }\n@keyframes engageSlideInUp { from { opacity: 0; transform: translateY(100%); } to { opacity: 1; transform: translateY(0); } }\n@keyframes engageScaleIn { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: scale(1); } }\n@keyframes engageBounceIn { 0% { opacity: 0; transform: scale(0.3); } 50% { transform: scale(1.05); } 70% { transform: scale(0.9); } 100% { opacity: 1; transform: scale(1); } }\n`\n\nfunction getAnimationStyle(animation?: string, delay?: number, duration?: number): CSSProperties {\n if (!animation || animation === 'none') return {}\n \n const animationMap: Record<string, string> = {\n fadeIn: 'engageFadeIn',\n fadeInUp: 'engageFadeInUp',\n fadeInDown: 'engageFadeInDown',\n slideInLeft: 'engageSlideInLeft',\n slideInRight: 'engageSlideInRight',\n slideInUp: 'engageSlideInUp',\n scaleIn: 'engageScaleIn',\n bounceIn: 'engageBounceIn',\n }\n \n const animationName = animationMap[animation]\n if (!animationName) return {}\n \n return {\n animation: `${animationName} ${duration || 300}ms ease-out ${delay || 0}ms forwards`,\n opacity: 0, // Start invisible, animation will show it\n }\n}\n\n// ============================================\n// Node Renderer\n// ============================================\n\ninterface NodeRendererProps {\n node: DesignNode\n onClose?: () => void\n onAction?: (action: ActionConfig, node: DesignNode) => void\n context?: EngageContext\n}\n\nfunction NodeRenderer({ node, onClose, onAction, context }: NodeRendererProps): React.ReactElement | null {\n const [isHovered, setIsHovered] = useState(false)\n const { type, props = {}, style = {}, children } = node\n\n // Build styles with hover effects\n const computedStyle: CSSProperties = { ...style }\n \n // Apply animation\n if (props.animation) {\n Object.assign(computedStyle, getAnimationStyle(\n props.animation,\n props.animationDelay,\n props.animationDuration\n ))\n }\n \n // Apply hover effects\n if (isHovered) {\n if (props.hoverScale && props.hoverScale !== 'none') {\n computedStyle.transform = `scale(${props.hoverScale})`\n computedStyle.transition = 'transform 0.2s ease'\n }\n if (props.hoverShadow && props.hoverShadow !== 'none') {\n const shadowMap: Record<string, string> = {\n sm: '0 1px 2px 0 rgb(0 0 0 / 0.05)',\n md: '0 4px 6px -1px rgb(0 0 0 / 0.1)',\n lg: '0 10px 15px -3px rgb(0 0 0 / 0.1)',\n }\n computedStyle.boxShadow = shadowMap[props.hoverShadow]\n }\n }\n\n // Event handlers\n const eventHandlers: Record<string, (e: MouseEvent) => void> = {\n onMouseEnter: () => setIsHovered(true),\n onMouseLeave: () => setIsHovered(false),\n }\n \n // Click handler\n if (props.onClick) {\n eventHandlers.onClick = (e: MouseEvent) => {\n e.preventDefault()\n handleAction(props.onClick, node, onClose, onAction)\n }\n computedStyle.cursor = 'pointer'\n }\n\n // Render children recursively\n const renderedChildren = children?.map((child) => (\n <NodeRenderer\n key={child.id}\n node={child}\n onClose={onClose}\n onAction={onAction}\n context={context}\n />\n ))\n\n // Render based on type\n switch (type) {\n case 'Container':\n case 'Box':\n case 'Section':\n return (\n <div style={computedStyle} {...eventHandlers}>\n {renderedChildren}\n </div>\n )\n\n case 'Text':\n return (\n <p style={computedStyle} {...eventHandlers}>\n {resolveText(props.text, context)}\n </p>\n )\n\n case 'Heading':\n const HeadingTag = `h${props.level || 2}` as keyof React.JSX.IntrinsicElements\n return createElement(\n HeadingTag,\n { style: computedStyle, ...eventHandlers },\n resolveText(props.text, context)\n )\n\n case 'Button':\n case 'BookingButton':\n case 'BuyNow':\n case 'AddToCart':\n case 'EventRSVP':\n return (\n <button\n style={computedStyle}\n {...eventHandlers}\n type=\"button\"\n aria-label={typeof props.ariaLabel === 'string' ? props.ariaLabel : undefined}\n >\n {resolveText(props.text || props.label, context) || 'Button'}\n </button>\n )\n\n case 'Image':\n return (\n <img\n src={safeImageSrc(props.src)}\n alt={props.alt || ''}\n style={computedStyle}\n {...eventHandlers}\n />\n )\n\n case 'Link':\n return (\n <a\n href={safeActionUrl(props.href) ?? '#'}\n target={props.newTab ? '_blank' : undefined}\n rel={props.newTab ? 'noopener noreferrer' : undefined}\n style={computedStyle}\n {...eventHandlers}\n >\n {resolveText(props.text, context) || renderedChildren}\n </a>\n )\n\n case 'Input':\n return (\n <input\n type={props.inputType || 'text'}\n placeholder={props.placeholder}\n style={computedStyle}\n {...eventHandlers}\n />\n )\n\n case 'Divider':\n return <hr style={{ border: 'none', borderTop: '1px solid var(--sk-border, #e5e7eb)', ...computedStyle }} />\n\n case 'Spacer':\n return <div style={{ ...computedStyle, width: props.width, height: props.height }} />\n\n case 'Icon':\n // Simple emoji/text icon rendering\n return (\n <span style={computedStyle} {...eventHandlers}>\n {props.icon || '★'}\n </span>\n )\n\n case 'FormEmbed':\n // For form embeds, we need to render the form from Forms module\n // This would integrate with the ManagedForm component\n return (\n <div \n style={computedStyle} \n data-engage-form={props.form_id}\n {...eventHandlers}\n >\n {/* ManagedForm would be rendered here by the parent */}\n <div style={{ padding: '16px', background: 'var(--sk-bg-elevated, #f5f5f5)', borderRadius: '8px', textAlign: 'center' }}>\n Form: {props.form_id || 'Not configured'}\n </div>\n </div>\n )\n\n case 'ProductCard':\n case 'EventCard':\n // Product/event cards need data binding from Commerce\n return (\n <div \n style={computedStyle} \n data-engage-offering={props.offering_id}\n {...eventHandlers}\n >\n {renderedChildren}\n </div>\n )\n\n default:\n // Unknown type - render as div with children\n console.warn(`[DesignRenderer] Unknown node type: ${type}`)\n return (\n <div style={computedStyle} {...eventHandlers}>\n {renderedChildren}\n </div>\n )\n }\n}\n\n// ============================================\n// Text Resolution (Data Bindings)\n// ============================================\n\nfunction resolveText(text: string | undefined, context?: EngageContext): string {\n if (!text) return ''\n if (!context) return text\n \n // Replace {{variable}} patterns with context values\n return text.replace(/\\{\\{(\\w+(?:\\.\\w+)*)\\}\\}/g, (match, path) => {\n const value = getNestedValue(context, path)\n return value !== undefined ? String(value) : match\n })\n}\n\nfunction getNestedValue(obj: Record<string, any>, path: string): any {\n return path.split('.').reduce((acc, key) => acc?.[key], obj)\n}\n\n// ============================================\n// Main Component\n// ============================================\n\nexport function DesignRenderer({\n design,\n onClose,\n onAction,\n context,\n}: DesignRendererProps): React.ReactElement {\n // Inject animation keyframes\n React.useEffect(() => {\n if (typeof document === 'undefined') return\n \n const styleId = 'engage-design-renderer-animations'\n if (!document.getElementById(styleId)) {\n const styleSheet = document.createElement('style')\n styleSheet.id = styleId\n styleSheet.textContent = animationKeyframes\n document.head.appendChild(styleSheet)\n }\n }, [])\n\n // Render the root container\n const rootStyle: CSSProperties = {\n ...design.style,\n }\n\n return (\n <div style={rootStyle} data-engage-design={design.id}>\n {design.children?.map((node) => (\n <NodeRenderer\n key={node.id}\n node={node}\n onClose={onClose}\n onAction={onAction}\n context={context}\n />\n ))}\n </div>\n )\n}\n\nexport default DesignRenderer\n","/**\n * @sonordev/site-kit/engage - Engage Widget\n * \n * Loads and renders engagement widgets (popups, nudges, bars, chat) via Portal API\n * Supports both legacy config-based rendering and new design_json from Engage Studio\n */\n\n'use client'\n\nimport React, { useEffect, useRef, useState, useCallback } from 'react'\nimport ReactDOM from 'react-dom'\nimport dynamic from 'next/dynamic'\nimport { usePathname } from 'next/navigation'\nimport type { ChatLauncherPlacement, EngageElement } from './types'\nimport { DEFAULT_ENGAGE_Z_INDEX } from './launcher-placement'\nimport { getOrCreateVisitorId } from '../shared/identity'\nimport { resolveAnalyticsTarget, type AnalyticsGateOptions } from '../shared/reporting-gate'\nimport { sonorFetch } from '../shared/sonorFetch'\nimport { DesignRenderer, type ActionConfig, type DesignDocument } from './DesignRenderer'\nimport { activateElement, deviceFromUserAgent, isEligible, safeActionUrl, seenKey, type DeviceType } from './element-rules'\n\n// ChatWidget pulls react-markdown (and lazily socket.io) — keep it out of the\n// engage chunk entirely and only download it when the idle-gated `chatReady`\n// flips and the widget actually renders.\n//\n// react-markdown cannot be made an optional peer dependency: bundlers resolve\n// even a DYNAMIC import at build time, so a site without it installed fails\n// with \"Module not found\" before any runtime fallback can catch it. Verified\n// against Next 16 / Turbopack, 2026-08-14. See CHANGELOG 4.0.3.\nconst LazyChatWidget = dynamic(\n () => import('./ChatWidget').then(m => ({ default: m.ChatWidget })),\n { ssr: false },\n)\n\ninterface EngageWidgetProps extends ChatLauncherPlacement, AnalyticsGateOptions {\n apiUrl?: string\n apiKey?: string\n projectId?: string\n chatEnabled?: boolean\n debug?: boolean\n}\n\n// Gate before mounting any effects, element telemetry, or the chat transport.\n// Standalone use and SiteKitLayout share the analytics send decision.\nexport function EngageWidget(props: EngageWidgetProps) {\n const target = resolveAnalyticsTarget(props)\n if (!target) return null\n return <AllowedEngageWidget {...props} {...target} />\n}\n\nfunction AllowedEngageWidget({\n apiUrl: propApiUrl,\n apiKey: propApiKey,\n projectId: propProjectId,\n position = 'bottom-right',\n offsetBottom,\n zIndex = DEFAULT_ENGAGE_Z_INDEX,\n chatEnabled = true,\n debug = false,\n}: EngageWidgetProps & { apiUrl: string; apiKey: string }) {\n const pathname = usePathname()\n const [elements, setElements] = useState<EngageElement[]>([])\n const [activeElements, setActiveElements] = useState<string[]>([])\n const [dismissedElements, setDismissedElements] = useState<Set<string>>(new Set())\n const [chatReady, setChatReady] = useState(false)\n \n // Load elements from API (GET /engage/widget/elements)\n useEffect(() => {\n async function loadElements() {\n const apiUrl = propApiUrl\n const apiKey = propApiKey\n \n if (!apiKey) {\n if (debug) console.warn('[Engage] No API key configured')\n return\n }\n \n // Shared identity (_sk_vid) — same visitor ID as Analytics & Signal\n const visitorId = getOrCreateVisitorId()\n const url = typeof window !== 'undefined' ? window.location.href : ''\n \n try {\n const response = await sonorFetch(\n `${apiUrl.replace(/\\/$/, '')}/engage/widget/elements?url=${encodeURIComponent(url)}&visitorId=${encodeURIComponent(visitorId)}&deviceType=${getDeviceType()}`,\n {},\n { apiKey },\n )\n \n if (!response.ok) {\n if (debug) console.error('[Engage] Error loading elements:', response.statusText)\n return\n }\n \n const json = await response.json()\n const elementsList = json.data?.elements ?? json.elements ?? []\n if (debug) console.log('[Engage] Loaded elements:', elementsList)\n setElements(elementsList)\n } catch (error) {\n if (debug) console.error('[Engage] Error loading elements:', error)\n }\n }\n \n loadElements()\n }, [propApiUrl, propApiKey, debug])\n\n // Defer ChatWidget until the browser is idle (reduces main-thread blocking)\n useEffect(() => {\n if (!chatEnabled) return\n const id =\n typeof requestIdleCallback !== 'undefined'\n ? requestIdleCallback(() => setChatReady(true), { timeout: 3000 })\n : setTimeout(() => setChatReady(true), 1)\n return () => {\n typeof cancelIdleCallback !== 'undefined' ? cancelIdleCallback(id as number) : clearTimeout(id)\n }\n }, [chatEnabled])\n \n // Check targeting and trigger for each element. Runs again on every\n // client-side navigation (pathname), so a popup targeted at one page shows\n // there and leaves when the visitor moves on.\n useEffect(() => {\n if (!elements.length) return\n\n const store = { local: storageOrNull('local'), session: storageOrNull('session') }\n const device = getDeviceType()\n const eligible = elements.filter(\n element => !dismissedElements.has(element.id) && isEligible(element, pathname, device, store),\n )\n\n if (debug) console.log('[Engage] Eligible elements:', eligible)\n\n // Anything showing that doesn't belong on this page any more goes away.\n const eligibleIds = new Set(eligible.map(e => e.id))\n setActiveElements(prev => {\n const kept = prev.filter(id => eligibleIds.has(id))\n return kept.length === prev.length ? prev : kept\n })\n\n // activateElement dedupes (this effect re-runs when dismissedElements\n // changes, so a still-eligible immediate element would otherwise be pushed\n // twice) and keeps to one centred popup at a time. A popup that waited\n // gets its turn when the open one is closed: that re-runs this effect.\n const activate = (id: string) => {\n setActiveElements(prev => activateElement(prev, id, elements))\n }\n\n // Every timer/listener registered here is torn down on cleanup — the old\n // version leaked delay timeouts and exit-intent/scroll listeners on each\n // effect re-run and on unmount.\n const cleanups: Array<() => void> = []\n\n eligible.forEach(element => {\n const trigger = element.trigger\n\n if (trigger?.type === 'immediate' || !trigger?.type) {\n activate(element.id)\n } else if (trigger?.type === 'delay' && trigger.delay) {\n const timer = setTimeout(() => activate(element.id), trigger.delay * 1000)\n cleanups.push(() => clearTimeout(timer))\n } else if (trigger?.type === 'exit-intent') {\n const handleMouseLeave = (e: MouseEvent) => {\n if (e.clientY < 10) {\n activate(element.id)\n document.removeEventListener('mouseleave', handleMouseLeave)\n }\n }\n document.addEventListener('mouseleave', handleMouseLeave)\n cleanups.push(() => document.removeEventListener('mouseleave', handleMouseLeave))\n } else if (trigger?.type === 'scroll' && trigger.scrollPercentage) {\n const handleScroll = () => {\n const scrollPercent = (window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100\n if (scrollPercent >= (trigger.scrollPercentage || 50)) {\n activate(element.id)\n window.removeEventListener('scroll', handleScroll)\n }\n }\n window.addEventListener('scroll', handleScroll, { passive: true })\n cleanups.push(() => window.removeEventListener('scroll', handleScroll))\n }\n })\n\n return () => {\n cleanups.forEach(fn => fn())\n }\n }, [elements, pathname, dismissedElements, debug])\n \n // Remember the visitor saw an element, for its frequency cap. Closing it\n // and clicking its button both count: without the second, a \"once\" popup\n // came back on the page its own button led to.\n const recordSeen = useCallback((elementId: string) => {\n const element = elements.find(e => e.id === elementId)\n if (!element?.trigger?.frequency) return\n try {\n if (element.trigger.frequency.type === 'once-per-session') {\n sessionStorage.setItem(seenKey(elementId), 'true')\n } else {\n localStorage.setItem(seenKey(elementId), Date.now().toString())\n }\n } catch {\n // Storage blocked (private mode): the popup may show again. Nothing else breaks.\n }\n }, [elements])\n\n const handleDismiss = useCallback((elementId: string) => {\n setDismissedElements(prev => new Set([...prev, elementId]))\n setActiveElements(prev => prev.filter(id => id !== elementId))\n recordSeen(elementId)\n }, [recordSeen])\n\n // Render active elements + chat widget\n // Use portal to document.body so widgets always land inside <body>,\n // even when SiteKitLayout wraps <body> (common in root layouts)\n if (typeof document === 'undefined') return null\n\n return ReactDOM.createPortal(\n <>\n {activeElements.map(elementId => {\n const element = elements.find(e => e.id === elementId)\n if (!element) return null\n\n return (\n <EngageElementRenderer\n key={element.id}\n element={element}\n onDismiss={() => handleDismiss(element.id)}\n onEngaged={() => recordSeen(element.id)}\n zIndex={zIndex}\n apiUrl={propApiUrl}\n apiKey={propApiKey}\n />\n )\n })}\n\n {/* Chat Widget - deferred until idle; chunk downloads on first render */}\n {chatEnabled && chatReady && (\n <LazyChatWidget\n projectId={propProjectId ?? undefined}\n config={{\n position,\n offsetBottom,\n zIndex,\n buttonColor: '#2563eb', // Default blue-600 (AA on white), overridden by --sk-primary CSS var or API brand_primary\n }}\n />\n )}\n </>,\n document.body,\n )\n}\n\n// ============================================\n// Action Handler + Tracking\n// ============================================\n\nfunction trackEngageEvent(\n apiUrl: string,\n apiKey: string | undefined,\n endpoint: 'impression' | 'click',\n data: Record<string, unknown>\n) {\n if (!apiKey) return\n const visitorId = typeof localStorage !== 'undefined'\n ? localStorage.getItem('_sk_vid')\n : null\n sonorFetch(`${apiUrl.replace(/\\/$/, '')}/engage/widget/${endpoint}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ ...data, visitorId, pageUrl: window.location.href }),\n keepalive: true,\n }, { apiKey, retries: 0 }).catch(() => {})\n}\n\nfunction handleEngageAction(\n action: ActionConfig,\n _node: unknown,\n element: EngageElement,\n apiUrl: string,\n apiKey: string | undefined\n) {\n // Track click\n trackEngageEvent(apiUrl, apiKey, 'click', {\n elementId: element.id,\n action: action.action,\n })\n\n switch (action.action) {\n case 'navigate': {\n const url = safeActionUrl(action.url)\n if (url) window.location.href = url\n break\n }\n case 'open-url': {\n const url = safeActionUrl(action.url)\n if (url) window.open(url, '_blank', 'noopener,noreferrer')\n break\n }\n case 'submit-form':\n case 'submit_form':\n window.dispatchEvent(new CustomEvent('engage:submit-form', {\n detail: { formId: action.formId || action.url, elementId: element.id },\n }))\n break\n case 'track-conversion':\n window.dispatchEvent(new CustomEvent('engage:conversion', {\n detail: { action, elementId: element.id },\n }))\n break\n default:\n window.dispatchEvent(new CustomEvent('engage:action', {\n detail: { action, elementId: element.id },\n }))\n break\n }\n}\n\n// Helper components\nfunction EngageElementRenderer({\n element,\n onDismiss,\n onEngaged,\n zIndex,\n apiUrl,\n apiKey,\n}: {\n element: EngageElement\n onDismiss: () => void\n /** The visitor acted on it (its button, not its close). */\n onEngaged: () => void\n zIndex: number\n apiUrl: string\n apiKey: string | undefined\n}) {\n // Impression tracking via IntersectionObserver\n const containerRef = useRef<HTMLDivElement>(null)\n const impressionTrackedRef = useRef(false)\n\n useEffect(() => {\n const el = containerRef.current\n if (!el || impressionTrackedRef.current) return\n\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting && !impressionTrackedRef.current) {\n impressionTrackedRef.current = true\n trackEngageEvent(apiUrl, apiKey, 'impression', { elementId: element.id })\n observer.disconnect()\n }\n },\n { threshold: 0.5 }\n )\n observer.observe(el)\n return () => observer.disconnect()\n }, [apiUrl, apiKey, element.id])\n\n const onAction = useCallback(\n (action: ActionConfig, node: unknown) => {\n if (action.action !== 'close') onEngaged()\n handleEngageAction(action, node, element, apiUrl, apiKey)\n },\n [element, apiUrl, apiKey, onEngaged]\n )\n\n // If element has design_json from Engage Studio, use DesignRenderer\n if (element.design_json) {\n // Wrap in appropriate container based on element type\n if (element.type === 'popup') {\n return (\n <div\n ref={containerRef}\n data-engage-element={element.id}\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: 'rgba(0,0,0,0.5)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex,\n }}\n onClick={onDismiss}\n >\n <div onClick={e => e.stopPropagation()}>\n <DesignRenderer\n design={element.design_json}\n onClose={onDismiss}\n onAction={onAction}\n />\n </div>\n </div>\n )\n }\n\n if (element.type === 'bar') {\n return (\n <div\n ref={containerRef}\n data-engage-element={element.id}\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n zIndex,\n }}\n >\n <DesignRenderer\n design={element.design_json}\n onClose={onDismiss}\n onAction={onAction}\n />\n </div>\n )\n }\n\n if (element.type === 'nudge' || element.type === 'slide-in') {\n const position = element.config?.position || 'bottom-right'\n const positionStyles: Record<string, React.CSSProperties> = {\n 'bottom-right': { bottom: 20, right: 20 },\n 'bottom-left': { bottom: 20, left: 20 },\n 'top-right': { top: 20, right: 20 },\n 'top-left': { top: 20, left: 20 },\n }\n\n return (\n <div\n ref={containerRef}\n data-engage-element={element.id}\n style={{\n position: 'fixed',\n zIndex,\n ...positionStyles[position],\n }}\n >\n <DesignRenderer\n design={element.design_json}\n onClose={onDismiss}\n onAction={onAction}\n />\n </div>\n )\n }\n\n // Default: render design_json directly\n return (\n <div ref={containerRef} data-engage-element={element.id}>\n <DesignRenderer\n design={element.design_json}\n onClose={onDismiss}\n onAction={onAction}\n />\n </div>\n )\n }\n\n // Legacy: Simple popup rendering for elements without design_json\n if (element.type === 'popup') {\n return (\n <div\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: 'rgba(0,0,0,0.5)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex,\n }}\n onClick={onDismiss}\n >\n <div\n style={{\n backgroundColor: 'var(--sk-bg, #ffffff)',\n padding: 24,\n borderRadius: 8,\n maxWidth: 500,\n width: '90%',\n }}\n onClick={e => e.stopPropagation()}\n >\n <button\n onClick={onDismiss}\n style={{\n position: 'absolute',\n top: 8,\n right: 8,\n background: 'none',\n border: 'none',\n fontSize: 24,\n cursor: 'pointer',\n }}\n >\n ×\n </button>\n {element.config?.title && <h2>{element.config.title}</h2>}\n {element.config?.message && <p>{element.config.message}</p>}\n </div>\n </div>\n )\n }\n \n // Bar/banner rendering\n if (element.type === 'bar') {\n return (\n <div\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n backgroundColor: element.config?.backgroundColor || 'var(--sk-primary, #2563eb)',\n color: element.config?.textColor || 'var(--sk-bg, #ffffff)',\n padding: '12px 24px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 16,\n zIndex,\n }}\n >\n <span>{element.config?.message}</span>\n <button\n onClick={onDismiss}\n style={{\n background: 'none',\n border: 'none',\n color: 'inherit',\n fontSize: 20,\n cursor: 'pointer',\n }}\n >\n ×\n </button>\n </div>\n )\n }\n \n return null\n}\n\n// Utilities\nfunction getDeviceType(): DeviceType {\n if (typeof navigator === 'undefined') return 'desktop'\n return deviceFromUserAgent(navigator.userAgent)\n}\n\nfunction storageOrNull(kind: 'local' | 'session'): Storage | null {\n try {\n return kind === 'local' ? window.localStorage : window.sessionStorage\n } catch {\n return null\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { useSignalExperiment, useSignalEvent } from './chunk-6MOGGEY3.mjs';
2
+ import { useSignalExperiment, useSignalEvent } from './chunk-A2HL22BO.mjs';
3
3
  import React, { useEffect } from 'react';
4
4
  import { jsx, Fragment } from 'react/jsx-runtime';
5
5
 
@@ -71,5 +71,5 @@ function ExperimentConversion({
71
71
  }
72
72
 
73
73
  export { ExperimentConversion, SignalExperiment, useExperimentVariant };
74
- //# sourceMappingURL=chunk-R26FAQWF.mjs.map
75
- //# sourceMappingURL=chunk-R26FAQWF.mjs.map
74
+ //# sourceMappingURL=chunk-BNKBRLJK.mjs.map
75
+ //# sourceMappingURL=chunk-BNKBRLJK.mjs.map
@@ -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-R26FAQWF.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-BNKBRLJK.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,24 +1,4 @@
1
- // src/shared/frame.ts
2
- function isFramed() {
3
- if (typeof window === "undefined") return false;
4
- try {
5
- return window.self !== window.top;
6
- } catch {
7
- return true;
8
- }
9
- }
10
- function isTopFrameSameOrigin() {
11
- if (typeof window === "undefined") return false;
12
- try {
13
- return typeof window.top?.location?.href === "string";
14
- } catch {
15
- return false;
16
- }
17
- }
18
- function isCrossOriginFrame() {
19
- if (!isFramed()) return false;
20
- return !isTopFrameSameOrigin();
21
- }
1
+ import { isCrossOriginFrame } from './chunk-MXJOKOFK.mjs';
22
2
 
23
3
  // src/shared/reporting-gate.ts
24
4
  var announcedSuppression = false;
@@ -40,6 +20,6 @@ function resolveAnalyticsTarget(options = {}) {
40
20
  return { apiUrl, apiKey };
41
21
  }
42
22
 
43
- export { isCrossOriginFrame, isFramed, isTopFrameSameOrigin, resolveAnalyticsTarget };
44
- //# sourceMappingURL=chunk-A6UYV475.mjs.map
45
- //# sourceMappingURL=chunk-A6UYV475.mjs.map
23
+ export { resolveAnalyticsTarget };
24
+ //# sourceMappingURL=chunk-CABEVWKJ.mjs.map
25
+ //# sourceMappingURL=chunk-CABEVWKJ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/reporting-gate.ts"],"names":[],"mappings":";;;AA4CA,IAAI,oBAAA,GAAuB,KAAA;AAepB,SAAS,sBAAA,CACd,OAAA,GAAgC,EAAC,EACT;AACxB,EAAA,MAAM,MAAA,GAAS,OAAO,MAAA,KAAW,WAAA,GAAc,MAAA,GAAY,MAAA;AAI3D,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,IAAU,MAAA,EAAQ,oBAAA,IAAwB,sBAAA;AACjE,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,IAAU,MAAA,EAAQ,oBAAA;AAEzC,EAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AAKpB,EAAA,MAAM,QAAA,GAAA,CAAY,QAAQ,QAAA,EAAU,QAAA,IAAY,IAAI,WAAA,EAAY,CAAE,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA;AACpF,EAAA,MAAM,KAAA,GAAQ,QAAA,KAAa,WAAA,IAAe,QAAA,CAAS,QAAA,CAAS,YAAY,CAAA,IACtE,QAAA,KAAa,WAAA,IAAe,QAAA,KAAa,OAAA,IAAW,QAAA,KAAa,SACjE,QAAA,KAAa,SAAA;AACf,EAAA,MAAM,KAAA,GAAQ,KAAA,IAAS,OAAA,CAAQ,cAAA,KAAmB,IAAA,GAAO,gBAAA,GACrD,CAAC,OAAA,CAAQ,YAAA,IAAgB,kBAAA,EAAmB,GAAI,cAAA,GAAiB,IAAA;AACrE,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,IAAI,OAAA,CAAQ,KAAA,IAAS,CAAC,oBAAA,EAAsB;AAC1C,MAAA,oBAAA,GAAuB,IAAA;AACvB,MAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,+CAAA,EAAkD,KAAK,CAAA,sBAAA,CAAwB,CAAA;AAAA,IAC9F;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,OAAO,EAAE,QAAQ,MAAA,EAAO;AAC1B","file":"chunk-CABEVWKJ.mjs","sourcesContent":["/**\n * Single source of truth for client reporting eligibility and credentials.\n * Analytics, fleet, SitemapSync and Engage all resolve through this gate.\n * Kept separate from transport wrappers so non-analytics modules stay lean.\n */\n\nimport { isCrossOriginFrame } from './frame'\n\n/** Resolved destination for an analytics send. */\nexport interface AnalyticsTarget {\n apiUrl: string\n apiKey: string\n}\n\nexport interface AnalyticsGateOptions {\n /** `apiUrl` prop, when the caller was given one. Falls back to the window global. */\n apiUrl?: string\n /** `apiKey` prop, when the caller was given one. Falls back to the window global. */\n apiKey?: string\n /**\n * Opt back in to reporting from inside a cross-origin frame. For a site\n * deliberately distributed as an embed (a widget, a partner-hosted\n * booking or menu page) the frame IS the product, and its traffic is real.\n * Explicit per-site config only — see AnalyticsConfig.allowInFrame. There\n * is deliberately no window global or env var for this: a silent switch\n * that turns cross-tenant tracking back on is the failure mode, not the\n * feature.\n */\n allowInFrame?: boolean\n /** Explicitly allow reporting from local browser hosts. Default false. */\n allowLocalhost?: boolean\n /** Emit the one-time diagnostic when a send is suppressed. */\n debug?: boolean\n}\n\n// Re-exported so analytics consumers have one import for the whole decision.\nexport { isCrossOriginFrame, isFramed, isTopFrameSameOrigin } from './frame'\n\n/**\n * One `console.info` per document, not one per event. A framed page fires\n * page view + journey + vitals + a click's worth of heatmap rows; logging\n * each suppression would turn a correct decision into console spam (and\n * Lighthouse best-practices noise) in someone else's page.\n */\nlet announcedSuppression = false\n\n/** Test seam — resets the once-per-document log latch. */\nexport function __resetSendGate(): void {\n announcedSuppression = false\n}\n\n/**\n * Resolve where an analytics call should go, or `null` if it must not happen.\n *\n * Returning `null` is the ONLY \"do not send\" signal in this module. Callers\n * that set up listeners or scrape the DOM should resolve first and bail on\n * `null`, so a blocked document never even attaches a scroll or click\n * listener — the guard saves the work, not just the request.\n */\nexport function resolveAnalyticsTarget(\n options: AnalyticsGateOptions = {},\n): AnalyticsTarget | null {\n const config = typeof window === 'undefined' ? undefined : window as Window & {\n __SITE_KIT_API_URL__?: string\n __SITE_KIT_API_KEY__?: string\n }\n const apiUrl = options.apiUrl || config?.__SITE_KIT_API_URL__ || 'https://api.sonor.io'\n const apiKey = options.apiKey || config?.__SITE_KIT_API_KEY__\n\n if (!apiKey) return null\n\n // Single source of truth for browser reporting: use the actual document\n // hostname, NEVER analytics.site or NEXT_PUBLIC_SITE_URL (often production\n // domains even when next start is being verified on localhost).\n const hostname = (config?.location?.hostname || '').toLowerCase().replace(/\\.+$/, '')\n const local = hostname === 'localhost' || hostname.endsWith('.localhost') ||\n hostname === '127.0.0.1' || hostname === '[::1]' || hostname === '::1' ||\n hostname === '0.0.0.0'\n const optIn = local && options.allowLocalhost !== true ? 'allowLocalhost'\n : !options.allowInFrame && isCrossOriginFrame() ? 'allowInFrame' : null\n if (optIn) {\n if (options.debug && !announcedSuppression) {\n announcedSuppression = true\n console.info(`[Site-kit] Reporting suppressed. Set analytics.${optIn} to explicitly opt in.`)\n }\n return null\n }\n\n return { apiUrl, apiKey }\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkZR43XFUM_js = require('./chunk-ZR43XFUM.js');
3
+ var chunk55J2KE7D_js = require('./chunk-55J2KE7D.js');
4
4
  var chunkJONWE26J_js = require('./chunk-JONWE26J.js');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
 
@@ -304,7 +304,7 @@ function ClusterNavigation({
304
304
  if (!hasPillarLink && !hasSiblings) return null;
305
305
  const trailingSlash = chunkJONWE26J_js.resolveTrailingSlash(trailingSlashProp);
306
306
  const articleUrl = (article) => {
307
- const path = chunkZR43XFUM_js.createPublicationRoutes({ basePath, category, includeCategoryInPath: !routing, ...routing }).post(article);
307
+ const path = chunk55J2KE7D_js.createPublicationRoutes({ basePath, category, includeCategoryInPath: !routing, ...routing }).post(article);
308
308
  return trailingSlash ? chunkJONWE26J_js.applyTrailingSlash(path, true) : path;
309
309
  };
310
310
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -351,5 +351,5 @@ exports.ServiceCallout = ServiceCallout;
351
351
  exports.ServiceCallouts = ServiceCallouts;
352
352
  exports.getAuthorSocialLinks = getAuthorSocialLinks;
353
353
  exports.readingTimeMinutes = readingTimeMinutes;
354
- //# sourceMappingURL=chunk-LWCAZDY2.js.map
355
- //# sourceMappingURL=chunk-LWCAZDY2.js.map
354
+ //# sourceMappingURL=chunk-CDRQYJUT.js.map
355
+ //# sourceMappingURL=chunk-CDRQYJUT.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/articles/ServiceCallout.tsx","../src/articles/ClusterNavigation.tsx","../src/articles/author-social.ts","../src/articles/reading-time.ts"],"names":["jsxs","jsx","Fragment","resolveTrailingSlash","createPublicationRoutes","applyTrailingSlash"],"mappings":"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","file":"chunk-LWCAZDY2.js","sourcesContent":["/**\n * @sonordev/site-kit/articles - Service Callout / CTA Component\n *\n * Renders a promotional call-to-action section within articles.\n * Automatically generated by Signal AI during article creation, linking\n * article content to the business's relevant services.\n *\n * Two variants:\n * - 'featured' (default): Full-width gradient banner with button\n * - 'inline': Compact card with icon accent\n *\n * Uses site-kit brand tokens (--sk-primary, --sk-bg, etc.) for theming.\n * Supports full Tailwind override via `styles` prop.\n *\n * @example\n * ```tsx\n * <ServiceCallout\n * title=\"Ready to build your MVP?\"\n * description=\"Our team specializes in lean SaaS builds.\"\n * cta=\"Get Started\"\n * url=\"/services/application-development\"\n * />\n * ```\n */\n\nimport React from 'react'\n\nexport interface ServiceCalloutProps {\n title: string\n description?: string\n cta?: string\n url: string\n variant?: 'featured' | 'inline'\n /** Override default styles with Tailwind classes */\n styles?: {\n wrapper?: string\n title?: string\n description?: string\n button?: string\n }\n /** Strip all default styles (BYO Tailwind) */\n unstyled?: boolean\n}\n\n// Default inline styles using CSS custom properties for brand theming\nconst defaults = {\n featured: {\n wrapper: {\n display: 'flex',\n flexWrap: 'wrap' as const,\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '1.5rem',\n padding: '2rem 2.5rem',\n margin: '3rem 0',\n borderRadius: '1rem',\n background: 'linear-gradient(135deg, color-mix(in srgb, var(--sk-primary, #2563eb) 8%, transparent), color-mix(in srgb, var(--sk-primary, #2563eb) 15%, transparent))',\n border: '1px solid color-mix(in srgb, var(--sk-primary, #2563eb) 25%, transparent)',\n },\n title: {\n fontSize: '1.25rem',\n fontWeight: 700,\n color: 'var(--sk-text-primary, #0f172a)',\n margin: 0,\n },\n description: {\n fontSize: '0.9375rem',\n color: 'var(--sk-text-secondary, #475569)',\n marginTop: '0.5rem',\n maxWidth: '40rem',\n },\n button: {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '0.5rem',\n padding: '0.75rem 1.75rem',\n borderRadius: '0.5rem',\n fontWeight: 600,\n fontSize: '0.9375rem',\n color: '#ffffff',\n background: 'var(--sk-primary, #2563eb)',\n textDecoration: 'none',\n transition: 'transform 0.15s, box-shadow 0.15s',\n whiteSpace: 'nowrap' as const,\n },\n },\n inline: {\n wrapper: {\n display: 'flex',\n gap: '1rem',\n padding: '1.25rem 1.5rem',\n margin: '2rem 0',\n borderRadius: '0.75rem',\n background: 'var(--sk-bg-elevated, #f8fafc)',\n border: '1px solid color-mix(in srgb, var(--sk-primary, #2563eb) 20%, var(--sk-surface-border, #e2e8f0))',\n },\n icon: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '2.5rem',\n height: '2.5rem',\n borderRadius: '0.625rem',\n background: 'var(--sk-primary, #2563eb)',\n color: '#ffffff',\n flexShrink: 0,\n fontSize: '1.125rem',\n },\n title: {\n fontSize: '1rem',\n fontWeight: 600,\n color: 'var(--sk-text-primary, #0f172a)',\n margin: 0,\n },\n description: {\n fontSize: '0.875rem',\n color: 'var(--sk-text-secondary, #475569)',\n marginTop: '0.25rem',\n },\n link: {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '0.25rem',\n marginTop: '0.5rem',\n fontSize: '0.875rem',\n fontWeight: 600,\n color: 'var(--sk-primary, #2563eb)',\n textDecoration: 'none',\n },\n },\n}\n\nexport function ServiceCallout({\n title,\n description,\n cta = 'Learn More',\n url,\n variant = 'featured',\n styles,\n unstyled = false,\n}: ServiceCalloutProps) {\n if (variant === 'inline') {\n return (\n <aside\n className={styles?.wrapper}\n style={unstyled ? undefined : defaults.inline.wrapper}\n role=\"complementary\"\n aria-label=\"Related service\"\n >\n <div style={unstyled ? undefined : defaults.inline.icon}>→</div>\n <div>\n <h4\n className={styles?.title}\n style={unstyled ? undefined : defaults.inline.title}\n >\n {title}\n </h4>\n {description && (\n <p\n className={styles?.description}\n style={unstyled ? undefined : defaults.inline.description}\n >\n {description}\n </p>\n )}\n <a\n href={url}\n className={styles?.button}\n style={unstyled ? undefined : defaults.inline.link}\n >\n {cta} →\n </a>\n </div>\n </aside>\n )\n }\n\n // Featured variant (default)\n return (\n <section\n className={styles?.wrapper}\n style={unstyled ? undefined : defaults.featured.wrapper}\n role=\"complementary\"\n aria-label=\"Call to action\"\n >\n <div>\n <h3\n className={styles?.title}\n style={unstyled ? undefined : defaults.featured.title}\n >\n {title}\n </h3>\n {description && (\n <p\n className={styles?.description}\n style={unstyled ? undefined : defaults.featured.description}\n >\n {description}\n </p>\n )}\n </div>\n <a\n href={url}\n className={styles?.button}\n style={unstyled ? undefined : defaults.featured.button}\n >\n {cta} →\n </a>\n </section>\n )\n}\n\n/**\n * Renders all service callouts for an article.\n * First callout uses 'featured' variant, subsequent use 'inline'.\n */\nexport function ServiceCallouts({\n callouts,\n styles,\n unstyled,\n}: {\n callouts: Array<{ title: string; description?: string; cta?: string; url: string }>\n styles?: ServiceCalloutProps['styles']\n unstyled?: boolean\n}) {\n if (!callouts || callouts.length === 0) return null\n\n return (\n <>\n {callouts.map((callout, i) => (\n <ServiceCallout\n key={callout.url + i}\n {...callout}\n variant={i === 0 ? 'featured' : 'inline'}\n styles={styles}\n unstyled={unstyled}\n />\n ))}\n </>\n )\n}\n","/**\n * @sonordev/site-kit/articles - Cluster Navigation Component\n *\n * Renders cluster context on article pages:\n * - \"Full Guide\" pillar backlink (on support articles only)\n * - Sibling article list with article_type badges\n *\n * Adapts to light/dark themes automatically using the same --sk-* variables\n * as the rest of site-kit, with currentColor-based fallbacks.\n */\n\nimport React from 'react'\nimport type { ClusterNavigation as ClusterNavigationType } from './types'\nimport { createPublicationRoutes, type PublicationRoutingOptions } from './routes'\nimport { applyTrailingSlash, resolveTrailingSlash } from '../sitemap/shared'\n\n// ============================================================================\n// CSS\n// ============================================================================\n\nconst clusterNavCss = `\n.sk-cluster-nav {\n --_cn-primary: var(--sk-primary, currentColor);\n --_cn-bg: var(--sk-bg-elevated, color-mix(in srgb, currentColor 6%, transparent));\n --_cn-border: var(--sk-surface-border, color-mix(in srgb, currentColor 12%, transparent));\n --_cn-text: var(--sk-text-primary, inherit);\n --_cn-text2: var(--sk-text-secondary, color-mix(in srgb, currentColor 70%, transparent));\n --_cn-text3: var(--sk-text-tertiary, color-mix(in srgb, currentColor 45%, transparent));\n\n margin: 2rem 0;\n padding: 1.5rem;\n border-radius: 0.75rem;\n background: var(--_cn-bg);\n border: 1px solid var(--_cn-border);\n color: var(--_cn-text);\n}\n\n.sk-cluster-pillar-link {\n margin-bottom: 1.25rem;\n padding-bottom: 1.25rem;\n border-bottom: 1px solid var(--_cn-border);\n}\n.sk-cluster-pillar-link-label {\n font-size: 0.6875rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--_cn-text3);\n margin: 0 0 0.375rem 0;\n}\n.sk-cluster-pillar-link a {\n font-size: 0.9375rem;\n font-weight: 600;\n color: var(--_cn-primary);\n text-decoration: none;\n transition: opacity 0.15s;\n}\n.sk-cluster-pillar-link a:hover { opacity: 0.8; }\n\n.sk-cluster-siblings-title {\n font-size: 0.6875rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--_cn-text3);\n margin: 0 0 0.75rem 0;\n}\n.sk-cluster-siblings-list {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n.sk-cluster-siblings-item {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n.sk-cluster-siblings-item a {\n font-size: 0.875rem;\n color: var(--_cn-text2);\n text-decoration: none;\n transition: color 0.15s;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.sk-cluster-siblings-item a:hover { color: var(--_cn-primary); }\n.sk-cluster-type-badge {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n padding: 0.125rem 0.4rem;\n border-radius: 9999px;\n font-size: 0.625rem;\n font-weight: 500;\n text-transform: capitalize;\n background: color-mix(in srgb, var(--_cn-primary) 10%, transparent);\n color: var(--_cn-primary);\n border: 1px solid color-mix(in srgb, var(--_cn-primary) 20%, transparent);\n}\n`\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport interface ClusterNavigationProps {\n /** Cluster navigation data */\n navigation: ClusterNavigationType\n /** Base path for article URLs (default: /article) */\n basePath?: string\n routing?: PublicationRoutingOptions\n /**\n * Fallback category slug for URL building (optional). Each linked article's\n * OWN category takes precedence when present — applying one category to\n * every sibling produced wrong-category URLs (duplicate content / redirect\n * chains) on category-segmented sites whenever a cluster spans categories.\n */\n category?: string\n /**\n * Append a trailing slash to article URLs. Defaults to the site's\n * next.config `trailingSlash`, so it rarely needs setting.\n */\n trailingSlash?: boolean\n /** Disable default styles */\n unstyled?: boolean\n /** Custom class name */\n className?: string\n}\n\nexport function ClusterNavigation({\n navigation,\n basePath,\n routing,\n category,\n trailingSlash: trailingSlashProp,\n unstyled = false,\n className,\n}: ClusterNavigationProps) {\n if (!navigation) return null\n\n const siblings = (navigation.siblings || []).filter(\n s => s.article_type !== 'pillar'\n )\n\n const hasPillarLink = !navigation.is_pillar && navigation.pillar\n const hasSiblings = siblings.length > 0\n\n if (!hasPillarLink && !hasSiblings) return null\n\n const trailingSlash = resolveTrailingSlash(trailingSlashProp)\n const articleUrl = (article: { slug: string; category?: string }) => {\n // Preserve the existing category-aware default; explicit routing can opt out.\n const path = createPublicationRoutes({ basePath, category, includeCategoryInPath: !routing, ...routing }).post(article)\n return trailingSlash ? applyTrailingSlash(path, true) : path\n }\n\n return (\n <>\n {!unstyled && <style dangerouslySetInnerHTML={{ __html: clusterNavCss }} />}\n\n <nav className={`${unstyled ? '' : 'sk-cluster-nav'} ${className || ''}`}>\n {hasPillarLink && navigation.pillar && (\n <div className={unstyled ? '' : 'sk-cluster-pillar-link'}>\n <p className={unstyled ? '' : 'sk-cluster-pillar-link-label'}>Full Guide</p>\n <a href={articleUrl(navigation.pillar)}>\n {navigation.pillar.title}\n </a>\n </div>\n )}\n\n {hasSiblings && (\n <div>\n <p className={unstyled ? '' : 'sk-cluster-siblings-title'}>\n {navigation.is_pillar ? 'Deep Dives' : 'More in This Series'}\n </p>\n <ul className={unstyled ? '' : 'sk-cluster-siblings-list'}>\n {siblings.map((sibling) => (\n <li key={sibling.slug} className={unstyled ? '' : 'sk-cluster-siblings-item'}>\n <span className={unstyled ? '' : 'sk-cluster-type-badge'}>\n {sibling.article_type}\n </span>\n <a href={articleUrl(sibling)}>{sibling.title}</a>\n </li>\n ))}\n </ul>\n </div>\n )}\n </nav>\n </>\n )\n}\n","import type { ArticleAuthor } from './types'\n\nexport interface AuthorSocialLink {\n label: string\n href: string\n}\n\nconst withPrefix = (value: string, base: string): string =>\n value.startsWith('http') ? value : `${base}${value}`\n\n/**\n * Single source of truth for author social display.\n *\n * The real blog_authors columns are linkedin_url / twitter_url / website_url\n * (E-E-A-T fields); `social_links` / `website` are the legacy shape that no\n * API response ever carried. Real columns win; legacy handles get their host\n * prefixed unless they are already full URLs.\n */\nexport function getAuthorSocialLinks(\n author: Pick<\n ArticleAuthor,\n 'linkedin_url' | 'twitter_url' | 'website_url' | 'website' | 'social_links'\n >\n): AuthorSocialLink[] {\n const links: AuthorSocialLink[] = []\n\n const linkedin = author.linkedin_url || author.social_links?.linkedin\n if (linkedin) links.push({ label: 'LinkedIn', href: withPrefix(linkedin, 'https://linkedin.com/in/') })\n\n const twitter = author.twitter_url\n ? author.twitter_url\n : author.social_links?.twitter\n ? withPrefix(author.social_links.twitter, 'https://twitter.com/')\n : null\n if (twitter) links.push({ label: 'Twitter', href: twitter })\n\n const website = author.website_url || author.website\n if (website) links.push({ label: 'Website', href: website })\n\n const github = author.social_links?.github\n if (github) links.push({ label: 'GitHub', href: withPrefix(github, 'https://github.com/') })\n\n return links\n}\n","import type { Article } from './types'\n\n/**\n * Single source of truth for reading-time display.\n *\n * The DB/API column is `reading_time` (blog_posts) — `reading_time_minutes`\n * never existed server-side and exists on the type only for callers that\n * pre-map their own data. Every \"X min read\" chip resolves through here.\n */\nexport function readingTimeMinutes(\n post: Pick<Article, 'reading_time' | 'reading_time_minutes'>\n): number | null {\n const value = post.reading_time_minutes ?? post.reading_time\n return typeof value === 'number' && value > 0 ? value : null\n}\n"]}
1
+ {"version":3,"sources":["../src/articles/ServiceCallout.tsx","../src/articles/ClusterNavigation.tsx","../src/articles/author-social.ts","../src/articles/reading-time.ts"],"names":["jsxs","jsx","Fragment","resolveTrailingSlash","createPublicationRoutes","applyTrailingSlash"],"mappings":";;;;;;AA6CA,IAAM,QAAA,GAAW;AAAA,EACf,QAAA,EAAU;AAAA,IACR,OAAA,EAAS;AAAA,MACP,OAAA,EAAS,MAAA;AAAA,MACT,QAAA,EAAU,MAAA;AAAA,MACV,UAAA,EAAY,QAAA;AAAA,MACZ,cAAA,EAAgB,eAAA;AAAA,MAChB,GAAA,EAAK,QAAA;AAAA,MACL,OAAA,EAAS,aAAA;AAAA,MACT,MAAA,EAAQ,QAAA;AAAA,MACR,YAAA,EAAc,MAAA;AAAA,MACd,UAAA,EAAY,0JAAA;AAAA,MACZ,MAAA,EAAQ;AAAA,KACV;AAAA,IACA,KAAA,EAAO;AAAA,MACL,QAAA,EAAU,SAAA;AAAA,MACV,UAAA,EAAY,GAAA;AAAA,MACZ,KAAA,EAAO,iCAAA;AAAA,MACP,MAAA,EAAQ;AAAA,KACV;AAAA,IACA,WAAA,EAAa;AAAA,MACX,QAAA,EAAU,WAAA;AAAA,MACV,KAAA,EAAO,mCAAA;AAAA,MACP,SAAA,EAAW,QAAA;AAAA,MACX,QAAA,EAAU;AAAA,KACZ;AAAA,IACA,MAAA,EAAQ;AAAA,MACN,OAAA,EAAS,aAAA;AAAA,MACT,UAAA,EAAY,QAAA;AAAA,MACZ,GAAA,EAAK,QAAA;AAAA,MACL,OAAA,EAAS,iBAAA;AAAA,MACT,YAAA,EAAc,QAAA;AAAA,MACd,UAAA,EAAY,GAAA;AAAA,MACZ,QAAA,EAAU,WAAA;AAAA,MACV,KAAA,EAAO,SAAA;AAAA,MACP,UAAA,EAAY,4BAAA;AAAA,MACZ,cAAA,EAAgB,MAAA;AAAA,MAChB,UAAA,EAAY,mCAAA;AAAA,MACZ,UAAA,EAAY;AAAA;AACd,GACF;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,OAAA,EAAS;AAAA,MACP,OAAA,EAAS,MAAA;AAAA,MACT,GAAA,EAAK,MAAA;AAAA,MACL,OAAA,EAAS,gBAAA;AAAA,MACT,MAAA,EAAQ,QAAA;AAAA,MACR,YAAA,EAAc,SAAA;AAAA,MACd,UAAA,EAAY,gCAAA;AAAA,MACZ,MAAA,EAAQ;AAAA,KACV;AAAA,IACA,IAAA,EAAM;AAAA,MACJ,OAAA,EAAS,MAAA;AAAA,MACT,UAAA,EAAY,QAAA;AAAA,MACZ,cAAA,EAAgB,QAAA;AAAA,MAChB,KAAA,EAAO,QAAA;AAAA,MACP,MAAA,EAAQ,QAAA;AAAA,MACR,YAAA,EAAc,UAAA;AAAA,MACd,UAAA,EAAY,4BAAA;AAAA,MACZ,KAAA,EAAO,SAAA;AAAA,MACP,UAAA,EAAY,CAAA;AAAA,MACZ,QAAA,EAAU;AAAA,KACZ;AAAA,IACA,KAAA,EAAO;AAAA,MACL,QAAA,EAAU,MAAA;AAAA,MACV,UAAA,EAAY,GAAA;AAAA,MACZ,KAAA,EAAO,iCAAA;AAAA,MACP,MAAA,EAAQ;AAAA,KACV;AAAA,IACA,WAAA,EAAa;AAAA,MACX,QAAA,EAAU,UAAA;AAAA,MACV,KAAA,EAAO,mCAAA;AAAA,MACP,SAAA,EAAW;AAAA,KACb;AAAA,IACA,IAAA,EAAM;AAAA,MACJ,OAAA,EAAS,aAAA;AAAA,MACT,UAAA,EAAY,QAAA;AAAA,MACZ,GAAA,EAAK,SAAA;AAAA,MACL,SAAA,EAAW,QAAA;AAAA,MACX,QAAA,EAAU,UAAA;AAAA,MACV,UAAA,EAAY,GAAA;AAAA,MACZ,KAAA,EAAO,4BAAA;AAAA,MACP,cAAA,EAAgB;AAAA;AAClB;AAEJ,CAAA;AAEO,SAAS,cAAA,CAAe;AAAA,EAC7B,KAAA;AAAA,EACA,WAAA;AAAA,EACA,GAAA,GAAM,YAAA;AAAA,EACN,GAAA;AAAA,EACA,OAAA,GAAU,UAAA;AAAA,EACV,MAAA;AAAA,EACA,QAAA,GAAW;AACb,CAAA,EAAwB;AACtB,EAAA,IAAI,YAAY,QAAA,EAAU;AACxB,IAAA,uBACEA,eAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,WAAW,MAAA,EAAQ,OAAA;AAAA,QACnB,KAAA,EAAO,QAAA,GAAW,MAAA,GAAY,QAAA,CAAS,MAAA,CAAO,OAAA;AAAA,QAC9C,IAAA,EAAK,eAAA;AAAA,QACL,YAAA,EAAW,iBAAA;AAAA,QAEX,QAAA,EAAA;AAAA,0BAAAC,cAAA,CAAC,SAAI,KAAA,EAAO,QAAA,GAAW,SAAY,QAAA,CAAS,MAAA,CAAO,MAAM,QAAA,EAAA,QAAA,EAAC,CAAA;AAAA,0CACzD,KAAA,EAAA,EACC,QAAA,EAAA;AAAA,4BAAAA,cAAA;AAAA,cAAC,IAAA;AAAA,cAAA;AAAA,gBACC,WAAW,MAAA,EAAQ,KAAA;AAAA,gBACnB,KAAA,EAAO,QAAA,GAAW,MAAA,GAAY,QAAA,CAAS,MAAA,CAAO,KAAA;AAAA,gBAE7C,QAAA,EAAA;AAAA;AAAA,aACH;AAAA,YACC,WAAA,oBACCA,cAAA;AAAA,cAAC,GAAA;AAAA,cAAA;AAAA,gBACC,WAAW,MAAA,EAAQ,WAAA;AAAA,gBACnB,KAAA,EAAO,QAAA,GAAW,MAAA,GAAY,QAAA,CAAS,MAAA,CAAO,WAAA;AAAA,gBAE7C,QAAA,EAAA;AAAA;AAAA,aACH;AAAA,4BAEFD,eAAA;AAAA,cAAC,GAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAM,GAAA;AAAA,gBACN,WAAW,MAAA,EAAQ,MAAA;AAAA,gBACnB,KAAA,EAAO,QAAA,GAAW,MAAA,GAAY,QAAA,CAAS,MAAA,CAAO,IAAA;AAAA,gBAE7C,QAAA,EAAA;AAAA,kBAAA,GAAA;AAAA,kBAAI;AAAA;AAAA;AAAA;AACP,WAAA,EACF;AAAA;AAAA;AAAA,KACF;AAAA,EAEJ;AAGA,EAAA,uBACEA,eAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,WAAW,MAAA,EAAQ,OAAA;AAAA,MACnB,KAAA,EAAO,QAAA,GAAW,MAAA,GAAY,QAAA,CAAS,QAAA,CAAS,OAAA;AAAA,MAChD,IAAA,EAAK,eAAA;AAAA,MACL,YAAA,EAAW,gBAAA;AAAA,MAEX,QAAA,EAAA;AAAA,wBAAAA,eAAA,CAAC,KAAA,EAAA,EACC,QAAA,EAAA;AAAA,0BAAAC,cAAA;AAAA,YAAC,IAAA;AAAA,YAAA;AAAA,cACC,WAAW,MAAA,EAAQ,KAAA;AAAA,cACnB,KAAA,EAAO,QAAA,GAAW,MAAA,GAAY,QAAA,CAAS,QAAA,CAAS,KAAA;AAAA,cAE/C,QAAA,EAAA;AAAA;AAAA,WACH;AAAA,UACC,WAAA,oBACCA,cAAA;AAAA,YAAC,GAAA;AAAA,YAAA;AAAA,cACC,WAAW,MAAA,EAAQ,WAAA;AAAA,cACnB,KAAA,EAAO,QAAA,GAAW,MAAA,GAAY,QAAA,CAAS,QAAA,CAAS,WAAA;AAAA,cAE/C,QAAA,EAAA;AAAA;AAAA;AACH,SAAA,EAEJ,CAAA;AAAA,wBACAD,eAAA;AAAA,UAAC,GAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAM,GAAA;AAAA,YACN,WAAW,MAAA,EAAQ,MAAA;AAAA,YACnB,KAAA,EAAO,QAAA,GAAW,MAAA,GAAY,QAAA,CAAS,QAAA,CAAS,MAAA;AAAA,YAE/C,QAAA,EAAA;AAAA,cAAA,GAAA;AAAA,cAAI;AAAA;AAAA;AAAA;AACP;AAAA;AAAA,GACF;AAEJ;AAMO,SAAS,eAAA,CAAgB;AAAA,EAC9B,QAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAIG;AACD,EAAA,IAAI,CAAC,QAAA,IAAY,QAAA,CAAS,MAAA,KAAW,GAAG,OAAO,IAAA;AAE/C,EAAA,uBACEC,cAAA,CAAAC,mBAAA,EAAA,EACG,QAAA,EAAA,QAAA,CAAS,GAAA,CAAI,CAAC,SAAS,CAAA,qBACtBD,cAAA;AAAA,IAAC,cAAA;AAAA,IAAA;AAAA,MAEE,GAAG,OAAA;AAAA,MACJ,OAAA,EAAS,CAAA,KAAM,CAAA,GAAI,UAAA,GAAa,QAAA;AAAA,MAChC,MAAA;AAAA,MACA;AAAA,KAAA;AAAA,IAJK,QAAQ,GAAA,GAAM;AAAA,GAMtB,CAAA,EACH,CAAA;AAEJ;AC5NA,IAAM,aAAA,GAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAiHf,SAAS,iBAAA,CAAkB;AAAA,EAChC,UAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,aAAA,EAAe,iBAAA;AAAA,EACf,QAAA,GAAW,KAAA;AAAA,EACX;AACF,CAAA,EAA2B;AACzB,EAAA,IAAI,CAAC,YAAY,OAAO,IAAA;AAExB,EAAA,MAAM,QAAA,GAAA,CAAY,UAAA,CAAW,QAAA,IAAY,EAAC,EAAG,MAAA;AAAA,IAC3C,CAAA,CAAA,KAAK,EAAE,YAAA,KAAiB;AAAA,GAC1B;AAEA,EAAA,MAAM,aAAA,GAAgB,CAAC,UAAA,CAAW,SAAA,IAAa,UAAA,CAAW,MAAA;AAC1D,EAAA,MAAM,WAAA,GAAc,SAAS,MAAA,GAAS,CAAA;AAEtC,EAAA,IAAI,CAAC,aAAA,IAAiB,CAAC,WAAA,EAAa,OAAO,IAAA;AAE3C,EAAA,MAAM,aAAA,GAAgBE,sCAAqB,iBAAiB,CAAA;AAC5D,EAAA,MAAM,UAAA,GAAa,CAAC,OAAA,KAAiD;AAEnE,IAAA,MAAM,IAAA,GAAOC,wCAAA,CAAwB,EAAE,QAAA,EAAU,QAAA,EAAU,qBAAA,EAAuB,CAAC,OAAA,EAAS,GAAG,OAAA,EAAS,CAAA,CAAE,KAAK,OAAO,CAAA;AACtH,IAAA,OAAO,aAAA,GAAgBC,mCAAA,CAAmB,IAAA,EAAM,IAAI,CAAA,GAAI,IAAA;AAAA,EAC1D,CAAA;AAEA,EAAA,uBACEL,eAAAA,CAAAE,mBAAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,CAAC,QAAA,oBAAYD,cAAAA,CAAC,OAAA,EAAA,EAAM,yBAAyB,EAAE,MAAA,EAAQ,eAAc,EAAG,CAAA;AAAA,oBAEzED,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,CAAA,EAAG,QAAA,GAAW,EAAA,GAAK,gBAAgB,CAAA,CAAA,EAAI,SAAA,IAAa,EAAE,CAAA,CAAA,EACnE,QAAA,EAAA;AAAA,MAAA,aAAA,IAAiB,UAAA,CAAW,0BAC3BA,eAAAA,CAAC,SAAI,SAAA,EAAW,QAAA,GAAW,KAAK,wBAAA,EAC9B,QAAA,EAAA;AAAA,wBAAAC,eAAC,GAAA,EAAA,EAAE,SAAA,EAAW,QAAA,GAAW,EAAA,GAAK,gCAAgC,QAAA,EAAA,YAAA,EAAU,CAAA;AAAA,wBACxEA,cAAAA,CAAC,GAAA,EAAA,EAAE,IAAA,EAAM,UAAA,CAAW,WAAW,MAAM,CAAA,EAClC,QAAA,EAAA,UAAA,CAAW,MAAA,CAAO,KAAA,EACrB;AAAA,OAAA,EACF,CAAA;AAAA,MAGD,WAAA,oBACCD,eAAAA,CAAC,KAAA,EAAA,EACC,QAAA,EAAA;AAAA,wBAAAC,cAAAA,CAAC,OAAE,SAAA,EAAW,QAAA,GAAW,KAAK,2BAAA,EAC3B,QAAA,EAAA,UAAA,CAAW,SAAA,GAAY,YAAA,GAAe,qBAAA,EACzC,CAAA;AAAA,wBACAA,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAW,QAAA,GAAW,KAAK,0BAAA,EAC5B,QAAA,EAAA,QAAA,CAAS,GAAA,CAAI,CAAC,4BACbD,eAAAA,CAAC,QAAsB,SAAA,EAAW,QAAA,GAAW,KAAK,0BAAA,EAChD,QAAA,EAAA;AAAA,0BAAAC,eAAC,MAAA,EAAA,EAAK,SAAA,EAAW,WAAW,EAAA,GAAK,uBAAA,EAC9B,kBAAQ,YAAA,EACX,CAAA;AAAA,0BACAA,eAAC,GAAA,EAAA,EAAE,IAAA,EAAM,WAAW,OAAO,CAAA,EAAI,kBAAQ,KAAA,EAAM;AAAA,SAAA,EAAA,EAJtC,OAAA,CAAQ,IAKjB,CACD,CAAA,EACH;AAAA,OAAA,EACF;AAAA,KAAA,EAEJ;AAAA,GAAA,EACF,CAAA;AAEJ;;;AC3LA,IAAM,UAAA,GAAa,CAAC,KAAA,EAAe,IAAA,KACjC,KAAA,CAAM,UAAA,CAAW,MAAM,CAAA,GAAI,KAAA,GAAQ,CAAA,EAAG,IAAI,CAAA,EAAG,KAAK,CAAA,CAAA;AAU7C,SAAS,qBACd,MAAA,EAIoB;AACpB,EAAA,MAAM,QAA4B,EAAC;AAEnC,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,YAAA,IAAgB,MAAA,CAAO,YAAA,EAAc,QAAA;AAC7D,EAAA,IAAI,QAAA,EAAU,KAAA,CAAM,IAAA,CAAK,EAAE,KAAA,EAAO,UAAA,EAAY,IAAA,EAAM,UAAA,CAAW,QAAA,EAAU,0BAA0B,CAAA,EAAG,CAAA;AAEtG,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,WAAA,GACnB,MAAA,CAAO,WAAA,GACP,MAAA,CAAO,YAAA,EAAc,OAAA,GACnB,UAAA,CAAW,MAAA,CAAO,YAAA,CAAa,OAAA,EAAS,sBAAsB,CAAA,GAC9D,IAAA;AACN,EAAA,IAAI,OAAA,QAAe,IAAA,CAAK,EAAE,OAAO,SAAA,EAAW,IAAA,EAAM,SAAS,CAAA;AAE3D,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,WAAA,IAAe,MAAA,CAAO,OAAA;AAC7C,EAAA,IAAI,OAAA,QAAe,IAAA,CAAK,EAAE,OAAO,SAAA,EAAW,IAAA,EAAM,SAAS,CAAA;AAE3D,EAAA,MAAM,MAAA,GAAS,OAAO,YAAA,EAAc,MAAA;AACpC,EAAA,IAAI,MAAA,EAAQ,KAAA,CAAM,IAAA,CAAK,EAAE,KAAA,EAAO,QAAA,EAAU,IAAA,EAAM,UAAA,CAAW,MAAA,EAAQ,qBAAqB,CAAA,EAAG,CAAA;AAE3F,EAAA,OAAO,KAAA;AACT;;;AClCO,SAAS,mBACd,IAAA,EACe;AACf,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,oBAAA,IAAwB,IAAA,CAAK,YAAA;AAChD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,GAAQ,IAAI,KAAA,GAAQ,IAAA;AAC1D","file":"chunk-CDRQYJUT.js","sourcesContent":["/**\n * @sonordev/site-kit/articles - Service Callout / CTA Component\n *\n * Renders a promotional call-to-action section within articles.\n * Automatically generated by Signal AI during article creation, linking\n * article content to the business's relevant services.\n *\n * Two variants:\n * - 'featured' (default): Full-width gradient banner with button\n * - 'inline': Compact card with icon accent\n *\n * Uses site-kit brand tokens (--sk-primary, --sk-bg, etc.) for theming.\n * Supports full Tailwind override via `styles` prop.\n *\n * @example\n * ```tsx\n * <ServiceCallout\n * title=\"Ready to build your MVP?\"\n * description=\"Our team specializes in lean SaaS builds.\"\n * cta=\"Get Started\"\n * url=\"/services/application-development\"\n * />\n * ```\n */\n\nimport React from 'react'\n\nexport interface ServiceCalloutProps {\n title: string\n description?: string\n cta?: string\n url: string\n variant?: 'featured' | 'inline'\n /** Override default styles with Tailwind classes */\n styles?: {\n wrapper?: string\n title?: string\n description?: string\n button?: string\n }\n /** Strip all default styles (BYO Tailwind) */\n unstyled?: boolean\n}\n\n// Default inline styles using CSS custom properties for brand theming\nconst defaults = {\n featured: {\n wrapper: {\n display: 'flex',\n flexWrap: 'wrap' as const,\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '1.5rem',\n padding: '2rem 2.5rem',\n margin: '3rem 0',\n borderRadius: '1rem',\n background: 'linear-gradient(135deg, color-mix(in srgb, var(--sk-primary, #2563eb) 8%, transparent), color-mix(in srgb, var(--sk-primary, #2563eb) 15%, transparent))',\n border: '1px solid color-mix(in srgb, var(--sk-primary, #2563eb) 25%, transparent)',\n },\n title: {\n fontSize: '1.25rem',\n fontWeight: 700,\n color: 'var(--sk-text-primary, #0f172a)',\n margin: 0,\n },\n description: {\n fontSize: '0.9375rem',\n color: 'var(--sk-text-secondary, #475569)',\n marginTop: '0.5rem',\n maxWidth: '40rem',\n },\n button: {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '0.5rem',\n padding: '0.75rem 1.75rem',\n borderRadius: '0.5rem',\n fontWeight: 600,\n fontSize: '0.9375rem',\n color: '#ffffff',\n background: 'var(--sk-primary, #2563eb)',\n textDecoration: 'none',\n transition: 'transform 0.15s, box-shadow 0.15s',\n whiteSpace: 'nowrap' as const,\n },\n },\n inline: {\n wrapper: {\n display: 'flex',\n gap: '1rem',\n padding: '1.25rem 1.5rem',\n margin: '2rem 0',\n borderRadius: '0.75rem',\n background: 'var(--sk-bg-elevated, #f8fafc)',\n border: '1px solid color-mix(in srgb, var(--sk-primary, #2563eb) 20%, var(--sk-surface-border, #e2e8f0))',\n },\n icon: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '2.5rem',\n height: '2.5rem',\n borderRadius: '0.625rem',\n background: 'var(--sk-primary, #2563eb)',\n color: '#ffffff',\n flexShrink: 0,\n fontSize: '1.125rem',\n },\n title: {\n fontSize: '1rem',\n fontWeight: 600,\n color: 'var(--sk-text-primary, #0f172a)',\n margin: 0,\n },\n description: {\n fontSize: '0.875rem',\n color: 'var(--sk-text-secondary, #475569)',\n marginTop: '0.25rem',\n },\n link: {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '0.25rem',\n marginTop: '0.5rem',\n fontSize: '0.875rem',\n fontWeight: 600,\n color: 'var(--sk-primary, #2563eb)',\n textDecoration: 'none',\n },\n },\n}\n\nexport function ServiceCallout({\n title,\n description,\n cta = 'Learn More',\n url,\n variant = 'featured',\n styles,\n unstyled = false,\n}: ServiceCalloutProps) {\n if (variant === 'inline') {\n return (\n <aside\n className={styles?.wrapper}\n style={unstyled ? undefined : defaults.inline.wrapper}\n role=\"complementary\"\n aria-label=\"Related service\"\n >\n <div style={unstyled ? undefined : defaults.inline.icon}>→</div>\n <div>\n <h4\n className={styles?.title}\n style={unstyled ? undefined : defaults.inline.title}\n >\n {title}\n </h4>\n {description && (\n <p\n className={styles?.description}\n style={unstyled ? undefined : defaults.inline.description}\n >\n {description}\n </p>\n )}\n <a\n href={url}\n className={styles?.button}\n style={unstyled ? undefined : defaults.inline.link}\n >\n {cta} →\n </a>\n </div>\n </aside>\n )\n }\n\n // Featured variant (default)\n return (\n <section\n className={styles?.wrapper}\n style={unstyled ? undefined : defaults.featured.wrapper}\n role=\"complementary\"\n aria-label=\"Call to action\"\n >\n <div>\n <h3\n className={styles?.title}\n style={unstyled ? undefined : defaults.featured.title}\n >\n {title}\n </h3>\n {description && (\n <p\n className={styles?.description}\n style={unstyled ? undefined : defaults.featured.description}\n >\n {description}\n </p>\n )}\n </div>\n <a\n href={url}\n className={styles?.button}\n style={unstyled ? undefined : defaults.featured.button}\n >\n {cta} →\n </a>\n </section>\n )\n}\n\n/**\n * Renders all service callouts for an article.\n * First callout uses 'featured' variant, subsequent use 'inline'.\n */\nexport function ServiceCallouts({\n callouts,\n styles,\n unstyled,\n}: {\n callouts: Array<{ title: string; description?: string; cta?: string; url: string }>\n styles?: ServiceCalloutProps['styles']\n unstyled?: boolean\n}) {\n if (!callouts || callouts.length === 0) return null\n\n return (\n <>\n {callouts.map((callout, i) => (\n <ServiceCallout\n key={callout.url + i}\n {...callout}\n variant={i === 0 ? 'featured' : 'inline'}\n styles={styles}\n unstyled={unstyled}\n />\n ))}\n </>\n )\n}\n","/**\n * @sonordev/site-kit/articles - Cluster Navigation Component\n *\n * Renders cluster context on article pages:\n * - \"Full Guide\" pillar backlink (on support articles only)\n * - Sibling article list with article_type badges\n *\n * Adapts to light/dark themes automatically using the same --sk-* variables\n * as the rest of site-kit, with currentColor-based fallbacks.\n */\n\nimport React from 'react'\nimport type { ClusterNavigation as ClusterNavigationType } from './types'\nimport { createPublicationRoutes, type PublicationRoutingOptions } from './routes'\nimport { applyTrailingSlash, resolveTrailingSlash } from '../sitemap/shared'\n\n// ============================================================================\n// CSS\n// ============================================================================\n\nconst clusterNavCss = `\n.sk-cluster-nav {\n --_cn-primary: var(--sk-primary, currentColor);\n --_cn-bg: var(--sk-bg-elevated, color-mix(in srgb, currentColor 6%, transparent));\n --_cn-border: var(--sk-surface-border, color-mix(in srgb, currentColor 12%, transparent));\n --_cn-text: var(--sk-text-primary, inherit);\n --_cn-text2: var(--sk-text-secondary, color-mix(in srgb, currentColor 70%, transparent));\n --_cn-text3: var(--sk-text-tertiary, color-mix(in srgb, currentColor 45%, transparent));\n\n margin: 2rem 0;\n padding: 1.5rem;\n border-radius: 0.75rem;\n background: var(--_cn-bg);\n border: 1px solid var(--_cn-border);\n color: var(--_cn-text);\n}\n\n.sk-cluster-pillar-link {\n margin-bottom: 1.25rem;\n padding-bottom: 1.25rem;\n border-bottom: 1px solid var(--_cn-border);\n}\n.sk-cluster-pillar-link-label {\n font-size: 0.6875rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--_cn-text3);\n margin: 0 0 0.375rem 0;\n}\n.sk-cluster-pillar-link a {\n font-size: 0.9375rem;\n font-weight: 600;\n color: var(--_cn-primary);\n text-decoration: none;\n transition: opacity 0.15s;\n}\n.sk-cluster-pillar-link a:hover { opacity: 0.8; }\n\n.sk-cluster-siblings-title {\n font-size: 0.6875rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--_cn-text3);\n margin: 0 0 0.75rem 0;\n}\n.sk-cluster-siblings-list {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n.sk-cluster-siblings-item {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n.sk-cluster-siblings-item a {\n font-size: 0.875rem;\n color: var(--_cn-text2);\n text-decoration: none;\n transition: color 0.15s;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.sk-cluster-siblings-item a:hover { color: var(--_cn-primary); }\n.sk-cluster-type-badge {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n padding: 0.125rem 0.4rem;\n border-radius: 9999px;\n font-size: 0.625rem;\n font-weight: 500;\n text-transform: capitalize;\n background: color-mix(in srgb, var(--_cn-primary) 10%, transparent);\n color: var(--_cn-primary);\n border: 1px solid color-mix(in srgb, var(--_cn-primary) 20%, transparent);\n}\n`\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport interface ClusterNavigationProps {\n /** Cluster navigation data */\n navigation: ClusterNavigationType\n /** Base path for article URLs (default: /article) */\n basePath?: string\n routing?: PublicationRoutingOptions\n /**\n * Fallback category slug for URL building (optional). Each linked article's\n * OWN category takes precedence when present — applying one category to\n * every sibling produced wrong-category URLs (duplicate content / redirect\n * chains) on category-segmented sites whenever a cluster spans categories.\n */\n category?: string\n /**\n * Append a trailing slash to article URLs. Defaults to the site's\n * next.config `trailingSlash`, so it rarely needs setting.\n */\n trailingSlash?: boolean\n /** Disable default styles */\n unstyled?: boolean\n /** Custom class name */\n className?: string\n}\n\nexport function ClusterNavigation({\n navigation,\n basePath,\n routing,\n category,\n trailingSlash: trailingSlashProp,\n unstyled = false,\n className,\n}: ClusterNavigationProps) {\n if (!navigation) return null\n\n const siblings = (navigation.siblings || []).filter(\n s => s.article_type !== 'pillar'\n )\n\n const hasPillarLink = !navigation.is_pillar && navigation.pillar\n const hasSiblings = siblings.length > 0\n\n if (!hasPillarLink && !hasSiblings) return null\n\n const trailingSlash = resolveTrailingSlash(trailingSlashProp)\n const articleUrl = (article: { slug: string; category?: string }) => {\n // Preserve the existing category-aware default; explicit routing can opt out.\n const path = createPublicationRoutes({ basePath, category, includeCategoryInPath: !routing, ...routing }).post(article)\n return trailingSlash ? applyTrailingSlash(path, true) : path\n }\n\n return (\n <>\n {!unstyled && <style dangerouslySetInnerHTML={{ __html: clusterNavCss }} />}\n\n <nav className={`${unstyled ? '' : 'sk-cluster-nav'} ${className || ''}`}>\n {hasPillarLink && navigation.pillar && (\n <div className={unstyled ? '' : 'sk-cluster-pillar-link'}>\n <p className={unstyled ? '' : 'sk-cluster-pillar-link-label'}>Full Guide</p>\n <a href={articleUrl(navigation.pillar)}>\n {navigation.pillar.title}\n </a>\n </div>\n )}\n\n {hasSiblings && (\n <div>\n <p className={unstyled ? '' : 'sk-cluster-siblings-title'}>\n {navigation.is_pillar ? 'Deep Dives' : 'More in This Series'}\n </p>\n <ul className={unstyled ? '' : 'sk-cluster-siblings-list'}>\n {siblings.map((sibling) => (\n <li key={sibling.slug} className={unstyled ? '' : 'sk-cluster-siblings-item'}>\n <span className={unstyled ? '' : 'sk-cluster-type-badge'}>\n {sibling.article_type}\n </span>\n <a href={articleUrl(sibling)}>{sibling.title}</a>\n </li>\n ))}\n </ul>\n </div>\n )}\n </nav>\n </>\n )\n}\n","import type { ArticleAuthor } from './types'\n\nexport interface AuthorSocialLink {\n label: string\n href: string\n}\n\nconst withPrefix = (value: string, base: string): string =>\n value.startsWith('http') ? value : `${base}${value}`\n\n/**\n * Single source of truth for author social display.\n *\n * The real blog_authors columns are linkedin_url / twitter_url / website_url\n * (E-E-A-T fields); `social_links` / `website` are the legacy shape that no\n * API response ever carried. Real columns win; legacy handles get their host\n * prefixed unless they are already full URLs.\n */\nexport function getAuthorSocialLinks(\n author: Pick<\n ArticleAuthor,\n 'linkedin_url' | 'twitter_url' | 'website_url' | 'website' | 'social_links'\n >\n): AuthorSocialLink[] {\n const links: AuthorSocialLink[] = []\n\n const linkedin = author.linkedin_url || author.social_links?.linkedin\n if (linkedin) links.push({ label: 'LinkedIn', href: withPrefix(linkedin, 'https://linkedin.com/in/') })\n\n const twitter = author.twitter_url\n ? author.twitter_url\n : author.social_links?.twitter\n ? withPrefix(author.social_links.twitter, 'https://twitter.com/')\n : null\n if (twitter) links.push({ label: 'Twitter', href: twitter })\n\n const website = author.website_url || author.website\n if (website) links.push({ label: 'Website', href: website })\n\n const github = author.social_links?.github\n if (github) links.push({ label: 'GitHub', href: withPrefix(github, 'https://github.com/') })\n\n return links\n}\n","import type { Article } from './types'\n\n/**\n * Single source of truth for reading-time display.\n *\n * The DB/API column is `reading_time` (blog_posts) — `reading_time_minutes`\n * never existed server-side and exists on the type only for callers that\n * pre-map their own data. Every \"X min read\" chip resolves through here.\n */\nexport function readingTimeMinutes(\n post: Pick<Article, 'reading_time' | 'reading_time_minutes'>\n): number | null {\n const value = post.reading_time_minutes ?? post.reading_time\n return typeof value === 'number' && value > 0 ? value : null\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunkJ4C3JAJF_js = require('./chunk-J4C3JAJF.js');
4
+ var chunkIO65ROAO_js = require('./chunk-IO65ROAO.js');
5
5
  var react = require('react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
 
@@ -40,7 +40,7 @@ function ManagedImage({
40
40
  }
41
41
  try {
42
42
  const params = new URLSearchParams({ page_path: currentPath });
43
- const res = await chunkJ4C3JAJF_js.sonorFetch(
43
+ const res = await chunkIO65ROAO_js.sonorFetch(
44
44
  `${apiUrl}/public/images/slot/${encodeURIComponent(slotId)}?${params}`,
45
45
  { headers: { "Content-Type": "application/json" } },
46
46
  { apiKey }
@@ -214,7 +214,7 @@ function ImagePickerModal({
214
214
  const params = new URLSearchParams();
215
215
  if (currentFolder) params.set("folder", currentFolder);
216
216
  if (search) params.set("search", search);
217
- const res = await chunkJ4C3JAJF_js.sonorFetch(
217
+ const res = await chunkIO65ROAO_js.sonorFetch(
218
218
  `${config.apiUrl}/public/images/files?${params}`,
219
219
  { headers: { "Content-Type": "application/json" } },
220
220
  { apiKey: config.apiKey }
@@ -236,7 +236,7 @@ function ImagePickerModal({
236
236
  const handleSelectFile = async (file) => {
237
237
  if (!config?.apiKey || !config?.apiUrl) return;
238
238
  try {
239
- const res = await chunkJ4C3JAJF_js.sonorFetch(
239
+ const res = await chunkIO65ROAO_js.sonorFetch(
240
240
  `${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}`,
241
241
  {
242
242
  method: "POST",
@@ -267,7 +267,7 @@ function ImagePickerModal({
267
267
  formData.append("page_path", pagePath);
268
268
  formData.append("folder", currentFolder || "Website/Images");
269
269
  if (altText) formData.append("alt_text", altText);
270
- const res = await chunkJ4C3JAJF_js.sonorFetch(`${config.apiUrl}/public/images/upload`, {
270
+ const res = await chunkIO65ROAO_js.sonorFetch(`${config.apiUrl}/public/images/upload`, {
271
271
  method: "POST",
272
272
  body: formData
273
273
  }, { apiKey: config.apiKey, retries: 0, timeoutMs: 6e4 });
@@ -284,7 +284,7 @@ function ImagePickerModal({
284
284
  if (!config?.apiKey || !config?.apiUrl) return;
285
285
  try {
286
286
  const params = new URLSearchParams({ page_path: pagePath });
287
- await chunkJ4C3JAJF_js.sonorFetch(
287
+ await chunkIO65ROAO_js.sonorFetch(
288
288
  `${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}?${params}`,
289
289
  { method: "DELETE" },
290
290
  { apiKey: config.apiKey, retries: 0 }
@@ -428,7 +428,7 @@ function ImagePickerModal({
428
428
  async function fetchManagedImage(config, slotId, pagePath) {
429
429
  const params = new URLSearchParams();
430
430
  if (pagePath) params.set("page_path", pagePath);
431
- const res = await chunkJ4C3JAJF_js.sonorFetch(
431
+ const res = await chunkIO65ROAO_js.sonorFetch(
432
432
  `${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}?${params}`,
433
433
  { headers: { "Content-Type": "application/json" } },
434
434
  { apiKey: config.apiKey }
@@ -443,7 +443,7 @@ async function fetchManagedImages(config, options) {
443
443
  if (options?.pagePath) params.set("page_path", options.pagePath);
444
444
  if (options?.category) params.set("category", options.category);
445
445
  if (options?.includePlaceholders) params.set("include_placeholders", "true");
446
- const res = await chunkJ4C3JAJF_js.sonorFetch(
446
+ const res = await chunkIO65ROAO_js.sonorFetch(
447
447
  `${config.apiUrl}/public/images?${params}`,
448
448
  { headers: { "Content-Type": "application/json" } },
449
449
  { apiKey: config.apiKey }
@@ -457,7 +457,7 @@ async function listImageFiles(config, options) {
457
457
  const params = new URLSearchParams();
458
458
  if (options?.folder) params.set("folder", options.folder);
459
459
  if (options?.search) params.set("search", options.search);
460
- const res = await chunkJ4C3JAJF_js.sonorFetch(
460
+ const res = await chunkIO65ROAO_js.sonorFetch(
461
461
  `${config.apiUrl}/public/images/files?${params}`,
462
462
  { headers: { "Content-Type": "application/json" } },
463
463
  { apiKey: config.apiKey }
@@ -474,7 +474,7 @@ async function uploadImage(config, file, options) {
474
474
  if (options?.pagePath) formData.append("page_path", options.pagePath);
475
475
  if (options?.folder) formData.append("folder", options.folder);
476
476
  if (options?.altText) formData.append("alt_text", options.altText);
477
- const res = await chunkJ4C3JAJF_js.sonorFetch(`${config.apiUrl}/public/images/upload`, {
477
+ const res = await chunkIO65ROAO_js.sonorFetch(`${config.apiUrl}/public/images/upload`, {
478
478
  method: "POST",
479
479
  body: formData
480
480
  }, { apiKey: config.apiKey, retries: 0, timeoutMs: 6e4 });
@@ -484,7 +484,7 @@ async function uploadImage(config, file, options) {
484
484
  return res.json();
485
485
  }
486
486
  async function assignImageToSlot(config, slotId, options) {
487
- const res = await chunkJ4C3JAJF_js.sonorFetch(
487
+ const res = await chunkIO65ROAO_js.sonorFetch(
488
488
  `${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}`,
489
489
  {
490
490
  method: "POST",
@@ -511,7 +511,7 @@ async function assignImageToSlot(config, slotId, options) {
511
511
  async function clearImageSlot(config, slotId, pagePath) {
512
512
  const params = new URLSearchParams();
513
513
  if (pagePath) params.set("page_path", pagePath);
514
- const res = await chunkJ4C3JAJF_js.sonorFetch(
514
+ const res = await chunkIO65ROAO_js.sonorFetch(
515
515
  `${config.apiUrl}/public/images/slot/${encodeURIComponent(slotId)}?${params}`,
516
516
  { method: "DELETE" },
517
517
  { apiKey: config.apiKey, retries: 0 }
@@ -529,5 +529,5 @@ exports.fetchManagedImage = fetchManagedImage;
529
529
  exports.fetchManagedImages = fetchManagedImages;
530
530
  exports.listImageFiles = listImageFiles;
531
531
  exports.uploadImage = uploadImage;
532
- //# sourceMappingURL=chunk-SAOUAIRS.js.map
533
- //# sourceMappingURL=chunk-SAOUAIRS.js.map
532
+ //# sourceMappingURL=chunk-CM4AVKXR.js.map
533
+ //# sourceMappingURL=chunk-CM4AVKXR.js.map