@sonordev/site-kit 5.0.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/agent-manifest.json +8 -5
  2. package/dist/AnalyticsProvider-2LCSA6G3.mjs +10 -0
  3. package/dist/{AnalyticsProvider-KCLRFOX6.mjs.map → AnalyticsProvider-2LCSA6G3.mjs.map} +1 -1
  4. package/dist/AnalyticsProvider-V2U3TQMH.js +31 -0
  5. package/dist/{AnalyticsProvider-TXM3DRLI.js.map → AnalyticsProvider-V2U3TQMH.js.map} +1 -1
  6. package/dist/{BlogViewTracker-J6LRGUHU.js → BlogViewTracker-COTPD7WL.js} +6 -6
  7. package/dist/{BlogViewTracker-J6LRGUHU.js.map → BlogViewTracker-COTPD7WL.js.map} +1 -1
  8. package/dist/{BlogViewTracker-PZWAWB3O.mjs → BlogViewTracker-HG25ONRP.mjs} +5 -5
  9. package/dist/{BlogViewTracker-PZWAWB3O.mjs.map → BlogViewTracker-HG25ONRP.mjs.map} +1 -1
  10. package/dist/ChatWidget-4QUJYFXU.js +20 -0
  11. package/dist/{ChatWidget-LD54Z2PQ.js.map → ChatWidget-4QUJYFXU.js.map} +1 -1
  12. package/dist/ChatWidget-RWO7R7EJ.mjs +11 -0
  13. package/dist/{ChatWidget-PMDPSZXG.mjs.map → ChatWidget-RWO7R7EJ.mjs.map} +1 -1
  14. package/dist/EngageWidget-LF4AC4QN.mjs +9 -0
  15. package/dist/{EngageWidget-4CBFRN4Y.mjs.map → EngageWidget-LF4AC4QN.mjs.map} +1 -1
  16. package/dist/EngageWidget-RSOXB3YM.js +18 -0
  17. package/dist/{EngageWidget-BF5NMQ5A.js.map → EngageWidget-RSOXB3YM.js.map} +1 -1
  18. package/dist/{FileField-VXADIOMN.js → FileField-S2GUM3QB.js} +6 -6
  19. package/dist/{FileField-VXADIOMN.js.map → FileField-S2GUM3QB.js.map} +1 -1
  20. package/dist/{FileField-FFRHS3XP.mjs → FileField-YJ7DZXC3.mjs} +5 -5
  21. package/dist/{FileField-FFRHS3XP.mjs.map → FileField-YJ7DZXC3.mjs.map} +1 -1
  22. package/dist/{FormSpotlight-JG4ZHS56.js → FormSpotlight-7WAXLXZA.js} +15 -15
  23. package/dist/{FormSpotlight-JG4ZHS56.js.map → FormSpotlight-7WAXLXZA.js.map} +1 -1
  24. package/dist/{FormSpotlight-KE46EDP5.mjs → FormSpotlight-HLH5LQKI.mjs} +3 -3
  25. package/dist/{FormSpotlight-KE46EDP5.mjs.map → FormSpotlight-HLH5LQKI.mjs.map} +1 -1
  26. package/dist/{FormStage-5Z53Z2WY.js → FormStage-LEZYERJB.js} +13 -13
  27. package/dist/{FormStage-5Z53Z2WY.js.map → FormStage-LEZYERJB.js.map} +1 -1
  28. package/dist/{FormStage-PZKWEXZE.mjs → FormStage-Q5JW75AF.mjs} +3 -3
  29. package/dist/{FormStage-PZKWEXZE.mjs.map → FormStage-Q5JW75AF.mjs.map} +1 -1
  30. package/dist/ManagedForm-H4SEFSAF.js +23 -0
  31. package/dist/{ManagedForm-E4WHMARH.js.map → ManagedForm-H4SEFSAF.js.map} +1 -1
  32. package/dist/ManagedForm-U3NFIVEC.mjs +14 -0
  33. package/dist/{ManagedForm-VU2TKV6J.mjs.map → ManagedForm-U3NFIVEC.mjs.map} +1 -1
  34. package/dist/{ManagedNewsletterForm-PG4EX3W6.js → ManagedNewsletterForm-KT2NGUNW.js} +8 -8
  35. package/dist/{ManagedNewsletterForm-PG4EX3W6.js.map → ManagedNewsletterForm-KT2NGUNW.js.map} +1 -1
  36. package/dist/{ManagedNewsletterForm-6DET3VGZ.mjs → ManagedNewsletterForm-YKYW7B6P.mjs} +7 -7
  37. package/dist/{ManagedNewsletterForm-6DET3VGZ.mjs.map → ManagedNewsletterForm-YKYW7B6P.mjs.map} +1 -1
  38. package/dist/{SignalCore-RZVTLUC2.mjs → SignalCore-2BH5PUGS.mjs} +5 -5
  39. package/dist/{SignalCore-RZVTLUC2.mjs.map → SignalCore-2BH5PUGS.mjs.map} +1 -1
  40. package/dist/{SignalCore-TCUVXVMN.js → SignalCore-JM4ODFL2.js} +11 -11
  41. package/dist/{SignalCore-TCUVXVMN.js.map → SignalCore-JM4ODFL2.js.map} +1 -1
  42. package/dist/SitemapSync-5CXS2JGB.mjs +8 -0
  43. package/dist/{SitemapSync-T75NAFB3.mjs.map → SitemapSync-5CXS2JGB.mjs.map} +1 -1
  44. package/dist/SitemapSync-J4UMJRTO.js +17 -0
  45. package/dist/{SitemapSync-AJU4DM3G.js.map → SitemapSync-J4UMJRTO.js.map} +1 -1
  46. package/dist/analytics/index.js +9 -9
  47. package/dist/analytics/index.mjs +4 -4
  48. package/dist/blog/index.d.ts +9 -5
  49. package/dist/blog/index.d.ts.map +1 -1
  50. package/dist/blog/index.js +20 -20
  51. package/dist/blog/index.mjs +3 -3
  52. package/dist/blog/server-ui.js +14 -14
  53. package/dist/blog/server-ui.mjs +2 -2
  54. package/dist/{chunk-6QQFEJIP.js → chunk-2EJX56YJ.js} +8 -8
  55. package/dist/{chunk-6QQFEJIP.js.map → chunk-2EJX56YJ.js.map} +1 -1
  56. package/dist/{chunk-SXPINIJG.mjs → chunk-2XHEUWHV.mjs} +4 -4
  57. package/dist/{chunk-SXPINIJG.mjs.map → chunk-2XHEUWHV.mjs.map} +1 -1
  58. package/dist/{chunk-7T4VMXKD.js → chunk-44ZTBQH4.js} +3 -3
  59. package/dist/{chunk-7T4VMXKD.js.map → chunk-44ZTBQH4.js.map} +1 -1
  60. package/dist/chunk-4SQ6PROR.mjs +6 -0
  61. package/dist/{chunk-JPTJGLKS.mjs.map → chunk-4SQ6PROR.mjs.map} +1 -1
  62. package/dist/{chunk-PPCTL4B5.mjs → chunk-4TU246Q4.mjs} +10 -3
  63. package/dist/chunk-4TU246Q4.mjs.map +1 -0
  64. package/dist/{chunk-YSZB2DRX.mjs → chunk-5G2ZRQMO.mjs} +3 -3
  65. package/dist/{chunk-YSZB2DRX.mjs.map → chunk-5G2ZRQMO.mjs.map} +1 -1
  66. package/dist/{chunk-FTBABL3T.mjs → chunk-5W56B52Z.mjs} +3 -3
  67. package/dist/{chunk-FTBABL3T.mjs.map → chunk-5W56B52Z.mjs.map} +1 -1
  68. package/dist/{chunk-XPAHKYX7.mjs → chunk-6YKNDQYJ.mjs} +3 -3
  69. package/dist/{chunk-XPAHKYX7.mjs.map → chunk-6YKNDQYJ.mjs.map} +1 -1
  70. package/dist/{chunk-UV6KQUSL.mjs → chunk-A3VGZAZQ.mjs} +3 -3
  71. package/dist/{chunk-UV6KQUSL.mjs.map → chunk-A3VGZAZQ.mjs.map} +1 -1
  72. package/dist/{chunk-JY3KZDEM.js → chunk-ACLBRIYD.js} +3 -3
  73. package/dist/{chunk-JY3KZDEM.js.map → chunk-ACLBRIYD.js.map} +1 -1
  74. package/dist/{chunk-MGPHBVOK.js → chunk-ACWGG4VW.js} +9 -9
  75. package/dist/{chunk-MGPHBVOK.js.map → chunk-ACWGG4VW.js.map} +1 -1
  76. package/dist/{chunk-J4JXAFSW.mjs → chunk-ADBLBGCQ.mjs} +3 -3
  77. package/dist/{chunk-J4JXAFSW.mjs.map → chunk-ADBLBGCQ.mjs.map} +1 -1
  78. package/dist/{chunk-4UHO6DPJ.mjs → chunk-ADOGOLYO.mjs} +4 -4
  79. package/dist/{chunk-4UHO6DPJ.mjs.map → chunk-ADOGOLYO.mjs.map} +1 -1
  80. package/dist/{chunk-IX5RAZWX.js → chunk-BGBJSMXT.js} +6 -6
  81. package/dist/{chunk-IX5RAZWX.js.map → chunk-BGBJSMXT.js.map} +1 -1
  82. package/dist/{chunk-YVE65W47.mjs → chunk-BUDV7QHH.mjs} +4 -4
  83. package/dist/{chunk-YVE65W47.mjs.map → chunk-BUDV7QHH.mjs.map} +1 -1
  84. package/dist/{chunk-3SMG4EXR.mjs → chunk-BVLGJ2CZ.mjs} +3 -3
  85. package/dist/{chunk-3SMG4EXR.mjs.map → chunk-BVLGJ2CZ.mjs.map} +1 -1
  86. package/dist/{chunk-OGPS3DKE.js → chunk-CBMHJPR7.js} +5 -5
  87. package/dist/{chunk-OGPS3DKE.js.map → chunk-CBMHJPR7.js.map} +1 -1
  88. package/dist/{chunk-VACFVPNF.js → chunk-CGQO7MFO.js} +14 -14
  89. package/dist/{chunk-VACFVPNF.js.map → chunk-CGQO7MFO.js.map} +1 -1
  90. package/dist/{chunk-FQ3JQV3M.js → chunk-CKPFETIO.js} +4 -4
  91. package/dist/{chunk-FQ3JQV3M.js.map → chunk-CKPFETIO.js.map} +1 -1
  92. package/dist/{chunk-MVJQ4ZA2.mjs → chunk-CYQB5GLU.mjs} +4 -4
  93. package/dist/{chunk-MVJQ4ZA2.mjs.map → chunk-CYQB5GLU.mjs.map} +1 -1
  94. package/dist/{chunk-GCZMDY2T.js → chunk-DKRXPXOR.js} +3 -3
  95. package/dist/{chunk-GCZMDY2T.js.map → chunk-DKRXPXOR.js.map} +1 -1
  96. package/dist/{chunk-PZE5L2FK.mjs → chunk-DTNNZJYM.mjs} +4 -4
  97. package/dist/{chunk-PZE5L2FK.mjs.map → chunk-DTNNZJYM.mjs.map} +1 -1
  98. package/dist/{chunk-HCN2US4M.js → chunk-E3GHVAMK.js} +18 -18
  99. package/dist/{chunk-HCN2US4M.js.map → chunk-E3GHVAMK.js.map} +1 -1
  100. package/dist/{chunk-5JNLZRLX.mjs → chunk-EKTMXHBI.mjs} +3 -3
  101. package/dist/{chunk-5JNLZRLX.mjs.map → chunk-EKTMXHBI.mjs.map} +1 -1
  102. package/dist/{chunk-LLKXPJSE.js → chunk-EZLK2OQL.js} +7 -7
  103. package/dist/{chunk-LLKXPJSE.js.map → chunk-EZLK2OQL.js.map} +1 -1
  104. package/dist/{chunk-BQY3FJ3R.js → chunk-FMOOQKZU.js} +8 -8
  105. package/dist/{chunk-BQY3FJ3R.js.map → chunk-FMOOQKZU.js.map} +1 -1
  106. package/dist/{chunk-QI2H5KK6.mjs → chunk-FZISCIJV.mjs} +4 -4
  107. package/dist/{chunk-QI2H5KK6.mjs.map → chunk-FZISCIJV.mjs.map} +1 -1
  108. package/dist/{chunk-62ODUWUX.js → chunk-GYAH4KFC.js} +4 -4
  109. package/dist/{chunk-62ODUWUX.js.map → chunk-GYAH4KFC.js.map} +1 -1
  110. package/dist/{chunk-JIUVBSQZ.js → chunk-GZVSGQKT.js} +3 -3
  111. package/dist/{chunk-JIUVBSQZ.js.map → chunk-GZVSGQKT.js.map} +1 -1
  112. package/dist/{chunk-3FZ76VI5.js → chunk-HPIY7AR3.js} +14 -14
  113. package/dist/{chunk-3FZ76VI5.js.map → chunk-HPIY7AR3.js.map} +1 -1
  114. package/dist/{chunk-5OHHYGD6.js → chunk-IQLYFQKZ.js} +15 -15
  115. package/dist/{chunk-5OHHYGD6.js.map → chunk-IQLYFQKZ.js.map} +1 -1
  116. package/dist/{chunk-DX6D7HDI.js → chunk-JEI3CSY4.js} +4 -4
  117. package/dist/{chunk-DX6D7HDI.js.map → chunk-JEI3CSY4.js.map} +1 -1
  118. package/dist/{chunk-LZY374FB.js → chunk-MCXHQHIX.js} +4 -4
  119. package/dist/{chunk-LZY374FB.js.map → chunk-MCXHQHIX.js.map} +1 -1
  120. package/dist/{chunk-FCKL5CF3.mjs → chunk-NIJVVW4G.mjs} +3 -3
  121. package/dist/{chunk-FCKL5CF3.mjs.map → chunk-NIJVVW4G.mjs.map} +1 -1
  122. package/dist/{chunk-YGRHEEPX.mjs → chunk-NSTY7ZZA.mjs} +7 -7
  123. package/dist/{chunk-YGRHEEPX.mjs.map → chunk-NSTY7ZZA.mjs.map} +1 -1
  124. package/dist/{chunk-HEUCDF3O.mjs → chunk-OAJVITNO.mjs} +3 -3
  125. package/dist/{chunk-HEUCDF3O.mjs.map → chunk-OAJVITNO.mjs.map} +1 -1
  126. package/dist/{chunk-SW6KWUNI.mjs → chunk-OTHKWMDB.mjs} +3 -3
  127. package/dist/{chunk-SW6KWUNI.mjs.map → chunk-OTHKWMDB.mjs.map} +1 -1
  128. package/dist/{chunk-EISVUD75.mjs → chunk-ROJ25QM3.mjs} +3 -3
  129. package/dist/{chunk-EISVUD75.mjs.map → chunk-ROJ25QM3.mjs.map} +1 -1
  130. package/dist/{chunk-FDWDXMJL.mjs → chunk-SXNKLHOX.mjs} +3 -3
  131. package/dist/{chunk-FDWDXMJL.mjs.map → chunk-SXNKLHOX.mjs.map} +1 -1
  132. package/dist/{chunk-MPO6TRLS.js → chunk-TAM2D54C.js} +14 -14
  133. package/dist/{chunk-MPO6TRLS.js.map → chunk-TAM2D54C.js.map} +1 -1
  134. package/dist/{chunk-MWXBRCM2.mjs → chunk-TECD4AP7.mjs} +3 -3
  135. package/dist/{chunk-MWXBRCM2.mjs.map → chunk-TECD4AP7.mjs.map} +1 -1
  136. package/dist/{chunk-AXYKBQVI.mjs → chunk-UMWVTIIZ.mjs} +8 -8
  137. package/dist/{chunk-AXYKBQVI.mjs.map → chunk-UMWVTIIZ.mjs.map} +1 -1
  138. package/dist/{chunk-5JQLLF2T.js → chunk-VCNPTLK2.js} +12 -12
  139. package/dist/{chunk-5JQLLF2T.js.map → chunk-VCNPTLK2.js.map} +1 -1
  140. package/dist/{chunk-4D2G5ZNP.js → chunk-VIIGOCX4.js} +15 -15
  141. package/dist/{chunk-4D2G5ZNP.js.map → chunk-VIIGOCX4.js.map} +1 -1
  142. package/dist/{chunk-QH3WVTEK.mjs → chunk-VWVUYL5J.mjs} +4 -4
  143. package/dist/{chunk-QH3WVTEK.mjs.map → chunk-VWVUYL5J.mjs.map} +1 -1
  144. package/dist/{chunk-KWH6RAVY.js → chunk-WMNRTCYY.js} +11 -11
  145. package/dist/{chunk-KWH6RAVY.js.map → chunk-WMNRTCYY.js.map} +1 -1
  146. package/dist/{chunk-N3RWPAR5.js → chunk-WZMM57R2.js} +5 -5
  147. package/dist/{chunk-N3RWPAR5.js.map → chunk-WZMM57R2.js.map} +1 -1
  148. package/dist/chunk-YPEX4RDE.js +8 -0
  149. package/dist/{chunk-S65JSRWW.js.map → chunk-YPEX4RDE.js.map} +1 -1
  150. package/dist/{chunk-UABMMR7U.js → chunk-Z33JXJTJ.js} +10 -3
  151. package/dist/chunk-Z33JXJTJ.js.map +1 -0
  152. package/dist/{chunk-UFURXSAI.mjs → chunk-ZFZMN4LT.mjs} +3 -3
  153. package/dist/{chunk-UFURXSAI.mjs.map → chunk-ZFZMN4LT.mjs.map} +1 -1
  154. package/dist/cli/index.js +3 -3
  155. package/dist/cli/index.mjs +1 -1
  156. package/dist/client/index.js +4 -4
  157. package/dist/client/index.mjs +3 -3
  158. package/dist/commerce/index.js +56 -56
  159. package/dist/commerce/index.mjs +5 -5
  160. package/dist/commerce/server-result.test.d.ts +2 -0
  161. package/dist/commerce/server-result.test.d.ts.map +1 -0
  162. package/dist/commerce/server.d.ts +51 -0
  163. package/dist/commerce/server.d.ts.map +1 -1
  164. package/dist/commerce/server.js +57 -24
  165. package/dist/commerce/server.js.map +1 -1
  166. package/dist/commerce/server.mjs +54 -25
  167. package/dist/commerce/server.mjs.map +1 -1
  168. package/dist/engage/index.js +10 -10
  169. package/dist/engage/index.mjs +7 -7
  170. package/dist/fleet/index.js +8 -8
  171. package/dist/fleet/index.mjs +4 -4
  172. package/dist/forms/index.js +16 -16
  173. package/dist/forms/index.mjs +9 -9
  174. package/dist/forms/server.js +10 -10
  175. package/dist/forms/server.mjs +8 -8
  176. package/dist/forms/static.js +7 -7
  177. package/dist/forms/static.mjs +6 -6
  178. package/dist/images/index.js +11 -11
  179. package/dist/images/index.mjs +4 -4
  180. package/dist/index.js +63 -63
  181. package/dist/index.mjs +9 -9
  182. package/dist/layout/client.js +8 -8
  183. package/dist/layout/client.mjs +7 -7
  184. package/dist/layout/index.js +10 -10
  185. package/dist/layout/index.mjs +8 -8
  186. package/dist/llms/generateLLMsTxt.d.ts.map +1 -1
  187. package/dist/llms/humanize-industry.d.ts +9 -0
  188. package/dist/llms/humanize-industry.d.ts.map +1 -0
  189. package/dist/llms/humanize-industry.test.d.ts +2 -0
  190. package/dist/llms/humanize-industry.test.d.ts.map +1 -0
  191. package/dist/llms/index.js +12 -12
  192. package/dist/llms/index.mjs +2 -2
  193. package/dist/maps/index.js +5 -5
  194. package/dist/maps/index.mjs +3 -3
  195. package/dist/search/index.js +4 -4
  196. package/dist/search/index.mjs +3 -3
  197. package/dist/seo/client.js +5 -5
  198. package/dist/seo/client.mjs +4 -4
  199. package/dist/seo/index.js +5 -5
  200. package/dist/seo/index.mjs +4 -4
  201. package/dist/server/index.js +3 -3
  202. package/dist/server/index.mjs +2 -2
  203. package/dist/shared/version.d.ts +1 -1
  204. package/dist/signal/index.js +11 -11
  205. package/dist/signal/index.mjs +2 -2
  206. package/dist/sitemap/index.js +2 -2
  207. package/dist/sitemap/index.mjs +1 -1
  208. package/dist/sync/index.js +16 -16
  209. package/dist/sync/index.mjs +4 -4
  210. package/package.json +1 -1
  211. package/dist/AnalyticsProvider-KCLRFOX6.mjs +0 -10
  212. package/dist/AnalyticsProvider-TXM3DRLI.js +0 -31
  213. package/dist/ChatWidget-LD54Z2PQ.js +0 -20
  214. package/dist/ChatWidget-PMDPSZXG.mjs +0 -11
  215. package/dist/EngageWidget-4CBFRN4Y.mjs +0 -9
  216. package/dist/EngageWidget-BF5NMQ5A.js +0 -18
  217. package/dist/ManagedForm-E4WHMARH.js +0 -23
  218. package/dist/ManagedForm-VU2TKV6J.mjs +0 -14
  219. package/dist/SitemapSync-AJU4DM3G.js +0 -17
  220. package/dist/SitemapSync-T75NAFB3.mjs +0 -8
  221. package/dist/chunk-JPTJGLKS.mjs +0 -6
  222. package/dist/chunk-PPCTL4B5.mjs.map +0 -1
  223. package/dist/chunk-S65JSRWW.js +0 -8
  224. package/dist/chunk-UABMMR7U.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/signal/SignalCore.tsx"],"names":["useState","useRef","getOrCreateVisitorId","getOrCreateSessionId","useEffect","useCallback","sonorFetch","getFreshCredential","isSiteToken"],"mappings":"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","file":"SignalCore-TCUVXVMN.js","sourcesContent":["/**\n * @sonordev/site-kit/signal - SignalCore\n *\n * The heavy half of SignalBridge: config fetching, SSE streaming, experiment\n * assignment, event queue/flush, and behavioral tracking. Mounted by the\n * SignalBridge shell as a CHILDLESS lazy sibling — it never wraps page\n * content, so the signal machinery stays out of the server-render path and\n * off the critical hydration chunk. It reports state up to the shell via\n * `onState` and registers its imperative API via `onRegister`.\n */\n\n'use client'\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\n// Single source of truth for visitor/session IDs (storage keys _sk_vid/_sk_sid)\n// — shared with Analytics and Engage. Do NOT re-fork ID logic into this module.\nimport { getOrCreateVisitorId, getOrCreateSessionId } from '../shared/identity'\n// Canonical client transport — the same wrapper Analytics/Forms/Engage route\n// through (see shared/sonorFetch header). It gives every request a per-attempt\n// AbortSignal timeout, so a hung API aborts cleanly instead of being left to log\n// net::ERR_TIMED_OUT — the console error that fails Lighthouse best-practices.\n// It also sets x-api-key from the `apiKey` option, so callers drop the header.\nimport { sonorFetch } from '../shared/sonorFetch'\nimport { getFreshCredential, isSiteToken } from '../shared/siteToken'\nimport type {\n SignalConfig,\n SignalEvent,\n SignalOutcome,\n ExperimentAssignment,\n} from './types'\n\n// ============================================\n// Shell ↔ core contract\n// ============================================\n\nexport interface SignalCoreApi {\n trackEvent: (event: Partial<SignalEvent>) => void\n trackOutcome: (outcome: SignalOutcome) => void\n getExperiment: (experimentId: string) => ExperimentAssignment | null\n refreshConfig: () => Promise<void>\n}\n\nexport interface SignalCoreState {\n config: SignalConfig | null\n loading: boolean\n error: Error | null\n}\n\nexport interface SignalCoreProps {\n enabled: boolean\n realtime: boolean\n experiments: boolean\n behaviorTracking: boolean\n externalVisitorId?: string\n externalSessionId?: string\n pageMetadataRef?: React.RefObject<Record<string, unknown> | null>\n /** Called with the imperative API on mount, and with null on unmount. */\n onRegister: (api: SignalCoreApi | null) => void\n /** Called whenever config/loading/error change, so the shell can re-render consumers. */\n onState: (state: SignalCoreState) => void\n}\n\n// ============================================\n// Utility Functions\n// ============================================\n\nfunction getApiConfig() {\n const apiUrl = typeof window !== 'undefined'\n ? (window as any).__SITE_KIT_API_URL__ || 'https://api.sonor.io'\n : 'https://api.sonor.io'\n const apiKey = typeof window !== 'undefined'\n ? (window as any).__SITE_KIT_API_KEY__\n : undefined\n return { apiUrl, apiKey }\n}\n\n// A visitor's console must stay clean (Lighthouse \"errors logged to the console\"\n// best-practice) — Signal's diagnostics only surface when the site opts into\n// debug via SiteKitClientProviders' __SITE_KIT_DEBUG__ global, mirroring how\n// AnalyticsProvider gates every one of its logs behind its `debug` prop.\nfunction isDebug(): boolean {\n return typeof window !== 'undefined' && !!(window as any).__SITE_KIT_DEBUG__\n}\n\nfunction getDeviceType(): 'desktop' | 'mobile' | 'tablet' {\n if (typeof window === 'undefined') return 'desktop'\n const ua = navigator.userAgent\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\nfunction getBrowser(): string {\n if (typeof window === 'undefined') return 'unknown'\n const ua = navigator.userAgent\n if (ua.includes('Firefox')) return 'Firefox'\n if (ua.includes('Edg')) return 'Edge'\n if (ua.includes('Chrome')) return 'Chrome'\n if (ua.includes('Safari')) return 'Safari'\n return 'Other'\n}\n\nfunction getOS(): string {\n if (typeof window === 'undefined') return 'unknown'\n const ua = navigator.userAgent\n if (ua.includes('Windows')) return 'Windows'\n if (ua.includes('Mac')) return 'macOS'\n if (ua.includes('iPhone') || ua.includes('iPad')) return 'iOS'\n if (ua.includes('Android')) return 'Android'\n if (ua.includes('Linux')) return 'Linux'\n return 'Other'\n}\n\n// ============================================\n// SignalCore Component (childless)\n// ============================================\n\nexport function SignalCore({\n enabled,\n realtime,\n experiments,\n behaviorTracking,\n externalVisitorId,\n externalSessionId,\n pageMetadataRef,\n onRegister,\n onState,\n}: SignalCoreProps) {\n const [config, setConfig] = useState<SignalConfig | null>(null)\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<Error | null>(null)\n\n // Refs for SSE and tracking\n const eventSourceRef = useRef<EventSource | null>(null)\n const eventQueueRef = useRef<Partial<SignalEvent>[]>([])\n const flushTimeoutRef = useRef<NodeJS.Timeout | null>(null)\n const assignmentsRef = useRef<Map<string, ExperimentAssignment>>(new Map())\n\n // Behavioral tracking state\n const pageLoadTimeRef = useRef<number>(Date.now())\n const scrollDepthRef = useRef<number>(0)\n const clickCountRef = useRef<number>(0)\n\n const { apiUrl, apiKey } = getApiConfig()\n\n // Use external IDs from shared identity, fall back to the shared generators\n const resolvedVisitorId = externalVisitorId || getOrCreateVisitorId()\n const resolvedSessionId = externalSessionId || getOrCreateSessionId()\n\n // Mirror state up to the shell so context consumers re-render\n useEffect(() => {\n onState({ config, loading, error })\n }, [config, loading, error, onState])\n\n // ============================================\n // Experiment Assignment\n // ============================================\n\n const loadExperimentAssignment = useCallback(async (experimentId: string): Promise<ExperimentAssignment | null> => {\n // Check localStorage first\n const storageKey = `_signal_exp_${experimentId}`\n const stored = localStorage.getItem(storageKey)\n\n if (stored) {\n try {\n const assignment = JSON.parse(stored) as ExperimentAssignment\n if (assignment.expires > Date.now()) {\n assignmentsRef.current.set(experimentId, assignment)\n return assignment\n }\n } catch {\n // Invalid stored data, continue to fetch\n }\n }\n\n // Fetch from API — idempotent read, so the transport's default retries apply.\n try {\n const response = await sonorFetch(\n `${apiUrl}/api/public/signal/experiment/${experimentId}`,\n {\n headers: {\n 'x-visitor-id': resolvedVisitorId,\n },\n },\n { apiKey },\n )\n\n if (!response.ok) return null\n\n const assignment = await response.json() as ExperimentAssignment\n\n // Store assignment\n localStorage.setItem(storageKey, JSON.stringify(assignment))\n assignmentsRef.current.set(experimentId, assignment)\n\n return assignment\n } catch (err) {\n if (isDebug()) console.error('[Signal] Experiment assignment error:', err)\n return null\n }\n }, [apiUrl, apiKey])\n\n const getExperiment = useCallback((experimentId: string): ExperimentAssignment | null => {\n return assignmentsRef.current.get(experimentId) || null\n }, [])\n\n // ============================================\n // Config Fetching\n // ============================================\n\n const fetchConfig = useCallback(async () => {\n if (!apiKey || !enabled) {\n setLoading(false)\n return\n }\n\n try {\n const response = await sonorFetch(\n `${apiUrl}/api/public/signal/config`,\n {\n headers: {\n 'x-visitor-id': resolvedVisitorId,\n },\n },\n { apiKey },\n )\n\n if (!response.ok) {\n throw new Error(`Failed to fetch Signal config: ${response.statusText}`)\n }\n\n const data = await response.json()\n setConfig(data.config)\n setError(null)\n\n // Load experiment assignments\n if (experiments && data.config?.experiments) {\n for (const exp of data.config.experiments) {\n if (exp.status === 'running') {\n await loadExperimentAssignment(exp.id)\n }\n }\n }\n } catch (err) {\n if (isDebug()) console.error('[Signal] Config fetch error:', err)\n setError(err as Error)\n } finally {\n setLoading(false)\n }\n }, [apiUrl, apiKey, enabled, experiments, resolvedVisitorId, loadExperimentAssignment])\n\n // ============================================\n // SSE Real-time Updates\n // ============================================\n\n const connectSSE = useCallback(() => {\n if (!apiKey || !enabled || !realtime) return\n\n // Close existing connection\n if (eventSourceRef.current) {\n eventSourceRef.current.close()\n eventSourceRef.current = null\n }\n\n // EventSource cannot send headers, so the credential rides in the URL —\n // which server/CDN access logs capture. Per the transport contract in\n // sonorFetch.ts, the raw API key NEVER goes in a URL: only the\n // short-lived minted site token may (bounded exposure, unforgeable HMAC).\n // Raw-key mode (2.x layouts, mint-failure fallback) skips the stream —\n // config still loads via POST, only live push is lost.\n void (async () => {\n const credential = await getFreshCredential(apiKey)\n if (!credential || !isSiteToken(credential)) {\n if (isDebug()) {\n console.warn('[Signal] Realtime stream disabled: requires site-token mode (raw keys never go in URLs)')\n }\n return\n }\n if (eventSourceRef.current) return\n\n const url = `${apiUrl}/api/public/signal/stream?token=${encodeURIComponent(credential)}`\n connectEventSource(url)\n })()\n\n function connectEventSource(url: string) {\n const eventSource = new EventSource(url)\n\n eventSource.addEventListener('config_update', (e) => {\n try {\n const { config: newConfig, version } = JSON.parse(e.data)\n setConfig(prev => {\n if (prev?.version !== version) {\n if (isDebug()) console.log('[Signal] Config updated to version:', version)\n return newConfig\n }\n return prev\n })\n } catch (err) {\n if (isDebug()) console.error('[Signal] SSE parse error:', err)\n }\n })\n\n eventSource.addEventListener('experiment_update', (e) => {\n try {\n const { experiment_id, action } = JSON.parse(e.data)\n if (action === 'started' || action === 'updated') {\n loadExperimentAssignment(experiment_id)\n } else if (action === 'stopped') {\n assignmentsRef.current.delete(experiment_id)\n }\n } catch (err) {\n if (isDebug()) console.error('[Signal] Experiment update error:', err)\n }\n })\n\n eventSource.onerror = () => {\n if (isDebug()) console.warn('[Signal] SSE connection error, reconnecting...')\n eventSource.close()\n if (eventSourceRef.current === eventSource) {\n eventSourceRef.current = null\n }\n // Reconnect after 5 seconds (re-mints the token if it expired)\n setTimeout(connectSSE, 5000)\n }\n\n eventSourceRef.current = eventSource\n }\n }, [apiUrl, apiKey, enabled, realtime, loadExperimentAssignment])\n\n // ============================================\n // Event Tracking\n // ============================================\n\n const flushEvents = useCallback(async () => {\n if (eventQueueRef.current.length === 0) return\n\n const events = [...eventQueueRef.current]\n eventQueueRef.current = []\n\n try {\n // retries: 0 — fire-and-forget tracking; a retried flush after a lost\n // response would double-count events. The transport still aborts a hung\n // request at its timeout (no net::ERR_TIMED_OUT).\n await sonorFetch(\n `${apiUrl}/api/public/signal/events`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n visitor_id: resolvedVisitorId,\n session_id: resolvedSessionId,\n events,\n }),\n },\n { apiKey, retries: 0 },\n )\n } catch (err) {\n // Re-queue failed events\n eventQueueRef.current = [...events, ...eventQueueRef.current]\n if (isDebug()) console.error('[Signal] Event flush error:', err)\n }\n }, [apiUrl, apiKey])\n\n const trackEvent = useCallback((event: Partial<SignalEvent>) => {\n if (!enabled || !apiKey) return\n\n // Enrich event with context\n const enrichedEvent: Partial<SignalEvent> = {\n ...event,\n page_url: window.location.href,\n page_path: window.location.pathname,\n referrer: document.referrer,\n device_type: getDeviceType(),\n browser: getBrowser(),\n os: getOS(),\n viewport_width: window.innerWidth,\n viewport_height: window.innerHeight,\n time_on_page: Date.now() - pageLoadTimeRef.current,\n scroll_depth: scrollDepthRef.current,\n click_count: clickCountRef.current,\n experiments: Array.from(assignmentsRef.current.values()).map(a => ({\n experiment_id: a.experiment_id,\n variant_key: a.variant_key,\n })),\n // Merge page metadata from Analytics if available\n page_metadata: pageMetadataRef?.current ?? undefined,\n timestamp: new Date().toISOString(),\n }\n\n eventQueueRef.current.push(enrichedEvent)\n\n // Debounce flush\n if (flushTimeoutRef.current) {\n clearTimeout(flushTimeoutRef.current)\n }\n flushTimeoutRef.current = setTimeout(flushEvents, 1000)\n }, [enabled, apiKey, flushEvents])\n\n // ============================================\n // Outcome Tracking\n // ============================================\n\n const trackOutcome = useCallback(async (outcome: SignalOutcome) => {\n if (!enabled || !apiKey) return\n\n try {\n // retries: 0 — fire-and-forget conversion signal; never double-fire on a\n // lost response. Still aborts a hung request at the transport timeout.\n await sonorFetch(\n `${apiUrl}/api/public/signal/outcome`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...outcome,\n visitor_id: resolvedVisitorId,\n session_id: resolvedSessionId,\n experiments: Array.from(assignmentsRef.current.keys()),\n page_url: window.location.href,\n timestamp: new Date().toISOString(),\n }),\n },\n { apiKey, retries: 0 },\n )\n } catch (err) {\n if (isDebug()) console.error('[Signal] Outcome tracking error:', err)\n }\n }, [apiUrl, apiKey, enabled])\n\n // ============================================\n // Behavioral Tracking\n // ============================================\n\n useEffect(() => {\n if (!behaviorTracking || typeof window === 'undefined') return\n\n // Track scroll depth\n const handleScroll = () => {\n const scrollTop = window.scrollY\n const docHeight = document.documentElement.scrollHeight - window.innerHeight\n const depth = docHeight > 0 ? Math.round((scrollTop / docHeight) * 100) : 0\n scrollDepthRef.current = Math.max(scrollDepthRef.current, depth)\n }\n\n // Track clicks\n const handleClick = () => {\n clickCountRef.current++\n }\n\n window.addEventListener('scroll', handleScroll, { passive: true })\n window.addEventListener('click', handleClick)\n\n // Flush on visibility change or page hide.\n // `pagehide` (not `beforeunload`): fires on iOS Safari, bfcache-safe.\n const handleVisibilityChange = () => {\n if (document.visibilityState === 'hidden') {\n flushEvents()\n }\n }\n\n document.addEventListener('visibilitychange', handleVisibilityChange)\n window.addEventListener('pagehide', flushEvents)\n\n return () => {\n window.removeEventListener('scroll', handleScroll)\n window.removeEventListener('click', handleClick)\n document.removeEventListener('visibilitychange', handleVisibilityChange)\n window.removeEventListener('pagehide', flushEvents)\n }\n }, [behaviorTracking, flushEvents])\n\n // ============================================\n // Initialization + shell registration\n // ============================================\n\n useEffect(() => {\n fetchConfig()\n }, [fetchConfig])\n\n useEffect(() => {\n if (config && realtime) {\n connectSSE()\n }\n\n return () => {\n if (eventSourceRef.current) {\n eventSourceRef.current.close()\n }\n }\n }, [config, realtime, connectSSE])\n\n // Hand the imperative API to the shell; buffered calls drain on register.\n useEffect(() => {\n onRegister({\n trackEvent,\n trackOutcome: (outcome: SignalOutcome) => { void trackOutcome(outcome) },\n getExperiment,\n refreshConfig: fetchConfig,\n })\n return () => onRegister(null)\n }, [onRegister, trackEvent, trackOutcome, getExperiment, fetchConfig])\n\n return null\n}\n"]}
1
+ {"version":3,"sources":["../src/signal/SignalCore.tsx"],"names":["useState","useRef","getOrCreateVisitorId","getOrCreateSessionId","useEffect","useCallback","sonorFetch","getFreshCredential","isSiteToken"],"mappings":"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","file":"SignalCore-JM4ODFL2.js","sourcesContent":["/**\n * @sonordev/site-kit/signal - SignalCore\n *\n * The heavy half of SignalBridge: config fetching, SSE streaming, experiment\n * assignment, event queue/flush, and behavioral tracking. Mounted by the\n * SignalBridge shell as a CHILDLESS lazy sibling — it never wraps page\n * content, so the signal machinery stays out of the server-render path and\n * off the critical hydration chunk. It reports state up to the shell via\n * `onState` and registers its imperative API via `onRegister`.\n */\n\n'use client'\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\n// Single source of truth for visitor/session IDs (storage keys _sk_vid/_sk_sid)\n// — shared with Analytics and Engage. Do NOT re-fork ID logic into this module.\nimport { getOrCreateVisitorId, getOrCreateSessionId } from '../shared/identity'\n// Canonical client transport — the same wrapper Analytics/Forms/Engage route\n// through (see shared/sonorFetch header). It gives every request a per-attempt\n// AbortSignal timeout, so a hung API aborts cleanly instead of being left to log\n// net::ERR_TIMED_OUT — the console error that fails Lighthouse best-practices.\n// It also sets x-api-key from the `apiKey` option, so callers drop the header.\nimport { sonorFetch } from '../shared/sonorFetch'\nimport { getFreshCredential, isSiteToken } from '../shared/siteToken'\nimport type {\n SignalConfig,\n SignalEvent,\n SignalOutcome,\n ExperimentAssignment,\n} from './types'\n\n// ============================================\n// Shell ↔ core contract\n// ============================================\n\nexport interface SignalCoreApi {\n trackEvent: (event: Partial<SignalEvent>) => void\n trackOutcome: (outcome: SignalOutcome) => void\n getExperiment: (experimentId: string) => ExperimentAssignment | null\n refreshConfig: () => Promise<void>\n}\n\nexport interface SignalCoreState {\n config: SignalConfig | null\n loading: boolean\n error: Error | null\n}\n\nexport interface SignalCoreProps {\n enabled: boolean\n realtime: boolean\n experiments: boolean\n behaviorTracking: boolean\n externalVisitorId?: string\n externalSessionId?: string\n pageMetadataRef?: React.RefObject<Record<string, unknown> | null>\n /** Called with the imperative API on mount, and with null on unmount. */\n onRegister: (api: SignalCoreApi | null) => void\n /** Called whenever config/loading/error change, so the shell can re-render consumers. */\n onState: (state: SignalCoreState) => void\n}\n\n// ============================================\n// Utility Functions\n// ============================================\n\nfunction getApiConfig() {\n const apiUrl = typeof window !== 'undefined'\n ? (window as any).__SITE_KIT_API_URL__ || 'https://api.sonor.io'\n : 'https://api.sonor.io'\n const apiKey = typeof window !== 'undefined'\n ? (window as any).__SITE_KIT_API_KEY__\n : undefined\n return { apiUrl, apiKey }\n}\n\n// A visitor's console must stay clean (Lighthouse \"errors logged to the console\"\n// best-practice) — Signal's diagnostics only surface when the site opts into\n// debug via SiteKitClientProviders' __SITE_KIT_DEBUG__ global, mirroring how\n// AnalyticsProvider gates every one of its logs behind its `debug` prop.\nfunction isDebug(): boolean {\n return typeof window !== 'undefined' && !!(window as any).__SITE_KIT_DEBUG__\n}\n\nfunction getDeviceType(): 'desktop' | 'mobile' | 'tablet' {\n if (typeof window === 'undefined') return 'desktop'\n const ua = navigator.userAgent\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\nfunction getBrowser(): string {\n if (typeof window === 'undefined') return 'unknown'\n const ua = navigator.userAgent\n if (ua.includes('Firefox')) return 'Firefox'\n if (ua.includes('Edg')) return 'Edge'\n if (ua.includes('Chrome')) return 'Chrome'\n if (ua.includes('Safari')) return 'Safari'\n return 'Other'\n}\n\nfunction getOS(): string {\n if (typeof window === 'undefined') return 'unknown'\n const ua = navigator.userAgent\n if (ua.includes('Windows')) return 'Windows'\n if (ua.includes('Mac')) return 'macOS'\n if (ua.includes('iPhone') || ua.includes('iPad')) return 'iOS'\n if (ua.includes('Android')) return 'Android'\n if (ua.includes('Linux')) return 'Linux'\n return 'Other'\n}\n\n// ============================================\n// SignalCore Component (childless)\n// ============================================\n\nexport function SignalCore({\n enabled,\n realtime,\n experiments,\n behaviorTracking,\n externalVisitorId,\n externalSessionId,\n pageMetadataRef,\n onRegister,\n onState,\n}: SignalCoreProps) {\n const [config, setConfig] = useState<SignalConfig | null>(null)\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<Error | null>(null)\n\n // Refs for SSE and tracking\n const eventSourceRef = useRef<EventSource | null>(null)\n const eventQueueRef = useRef<Partial<SignalEvent>[]>([])\n const flushTimeoutRef = useRef<NodeJS.Timeout | null>(null)\n const assignmentsRef = useRef<Map<string, ExperimentAssignment>>(new Map())\n\n // Behavioral tracking state\n const pageLoadTimeRef = useRef<number>(Date.now())\n const scrollDepthRef = useRef<number>(0)\n const clickCountRef = useRef<number>(0)\n\n const { apiUrl, apiKey } = getApiConfig()\n\n // Use external IDs from shared identity, fall back to the shared generators\n const resolvedVisitorId = externalVisitorId || getOrCreateVisitorId()\n const resolvedSessionId = externalSessionId || getOrCreateSessionId()\n\n // Mirror state up to the shell so context consumers re-render\n useEffect(() => {\n onState({ config, loading, error })\n }, [config, loading, error, onState])\n\n // ============================================\n // Experiment Assignment\n // ============================================\n\n const loadExperimentAssignment = useCallback(async (experimentId: string): Promise<ExperimentAssignment | null> => {\n // Check localStorage first\n const storageKey = `_signal_exp_${experimentId}`\n const stored = localStorage.getItem(storageKey)\n\n if (stored) {\n try {\n const assignment = JSON.parse(stored) as ExperimentAssignment\n if (assignment.expires > Date.now()) {\n assignmentsRef.current.set(experimentId, assignment)\n return assignment\n }\n } catch {\n // Invalid stored data, continue to fetch\n }\n }\n\n // Fetch from API — idempotent read, so the transport's default retries apply.\n try {\n const response = await sonorFetch(\n `${apiUrl}/api/public/signal/experiment/${experimentId}`,\n {\n headers: {\n 'x-visitor-id': resolvedVisitorId,\n },\n },\n { apiKey },\n )\n\n if (!response.ok) return null\n\n const assignment = await response.json() as ExperimentAssignment\n\n // Store assignment\n localStorage.setItem(storageKey, JSON.stringify(assignment))\n assignmentsRef.current.set(experimentId, assignment)\n\n return assignment\n } catch (err) {\n if (isDebug()) console.error('[Signal] Experiment assignment error:', err)\n return null\n }\n }, [apiUrl, apiKey])\n\n const getExperiment = useCallback((experimentId: string): ExperimentAssignment | null => {\n return assignmentsRef.current.get(experimentId) || null\n }, [])\n\n // ============================================\n // Config Fetching\n // ============================================\n\n const fetchConfig = useCallback(async () => {\n if (!apiKey || !enabled) {\n setLoading(false)\n return\n }\n\n try {\n const response = await sonorFetch(\n `${apiUrl}/api/public/signal/config`,\n {\n headers: {\n 'x-visitor-id': resolvedVisitorId,\n },\n },\n { apiKey },\n )\n\n if (!response.ok) {\n throw new Error(`Failed to fetch Signal config: ${response.statusText}`)\n }\n\n const data = await response.json()\n setConfig(data.config)\n setError(null)\n\n // Load experiment assignments\n if (experiments && data.config?.experiments) {\n for (const exp of data.config.experiments) {\n if (exp.status === 'running') {\n await loadExperimentAssignment(exp.id)\n }\n }\n }\n } catch (err) {\n if (isDebug()) console.error('[Signal] Config fetch error:', err)\n setError(err as Error)\n } finally {\n setLoading(false)\n }\n }, [apiUrl, apiKey, enabled, experiments, resolvedVisitorId, loadExperimentAssignment])\n\n // ============================================\n // SSE Real-time Updates\n // ============================================\n\n const connectSSE = useCallback(() => {\n if (!apiKey || !enabled || !realtime) return\n\n // Close existing connection\n if (eventSourceRef.current) {\n eventSourceRef.current.close()\n eventSourceRef.current = null\n }\n\n // EventSource cannot send headers, so the credential rides in the URL —\n // which server/CDN access logs capture. Per the transport contract in\n // sonorFetch.ts, the raw API key NEVER goes in a URL: only the\n // short-lived minted site token may (bounded exposure, unforgeable HMAC).\n // Raw-key mode (2.x layouts, mint-failure fallback) skips the stream —\n // config still loads via POST, only live push is lost.\n void (async () => {\n const credential = await getFreshCredential(apiKey)\n if (!credential || !isSiteToken(credential)) {\n if (isDebug()) {\n console.warn('[Signal] Realtime stream disabled: requires site-token mode (raw keys never go in URLs)')\n }\n return\n }\n if (eventSourceRef.current) return\n\n const url = `${apiUrl}/api/public/signal/stream?token=${encodeURIComponent(credential)}`\n connectEventSource(url)\n })()\n\n function connectEventSource(url: string) {\n const eventSource = new EventSource(url)\n\n eventSource.addEventListener('config_update', (e) => {\n try {\n const { config: newConfig, version } = JSON.parse(e.data)\n setConfig(prev => {\n if (prev?.version !== version) {\n if (isDebug()) console.log('[Signal] Config updated to version:', version)\n return newConfig\n }\n return prev\n })\n } catch (err) {\n if (isDebug()) console.error('[Signal] SSE parse error:', err)\n }\n })\n\n eventSource.addEventListener('experiment_update', (e) => {\n try {\n const { experiment_id, action } = JSON.parse(e.data)\n if (action === 'started' || action === 'updated') {\n loadExperimentAssignment(experiment_id)\n } else if (action === 'stopped') {\n assignmentsRef.current.delete(experiment_id)\n }\n } catch (err) {\n if (isDebug()) console.error('[Signal] Experiment update error:', err)\n }\n })\n\n eventSource.onerror = () => {\n if (isDebug()) console.warn('[Signal] SSE connection error, reconnecting...')\n eventSource.close()\n if (eventSourceRef.current === eventSource) {\n eventSourceRef.current = null\n }\n // Reconnect after 5 seconds (re-mints the token if it expired)\n setTimeout(connectSSE, 5000)\n }\n\n eventSourceRef.current = eventSource\n }\n }, [apiUrl, apiKey, enabled, realtime, loadExperimentAssignment])\n\n // ============================================\n // Event Tracking\n // ============================================\n\n const flushEvents = useCallback(async () => {\n if (eventQueueRef.current.length === 0) return\n\n const events = [...eventQueueRef.current]\n eventQueueRef.current = []\n\n try {\n // retries: 0 — fire-and-forget tracking; a retried flush after a lost\n // response would double-count events. The transport still aborts a hung\n // request at its timeout (no net::ERR_TIMED_OUT).\n await sonorFetch(\n `${apiUrl}/api/public/signal/events`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n visitor_id: resolvedVisitorId,\n session_id: resolvedSessionId,\n events,\n }),\n },\n { apiKey, retries: 0 },\n )\n } catch (err) {\n // Re-queue failed events\n eventQueueRef.current = [...events, ...eventQueueRef.current]\n if (isDebug()) console.error('[Signal] Event flush error:', err)\n }\n }, [apiUrl, apiKey])\n\n const trackEvent = useCallback((event: Partial<SignalEvent>) => {\n if (!enabled || !apiKey) return\n\n // Enrich event with context\n const enrichedEvent: Partial<SignalEvent> = {\n ...event,\n page_url: window.location.href,\n page_path: window.location.pathname,\n referrer: document.referrer,\n device_type: getDeviceType(),\n browser: getBrowser(),\n os: getOS(),\n viewport_width: window.innerWidth,\n viewport_height: window.innerHeight,\n time_on_page: Date.now() - pageLoadTimeRef.current,\n scroll_depth: scrollDepthRef.current,\n click_count: clickCountRef.current,\n experiments: Array.from(assignmentsRef.current.values()).map(a => ({\n experiment_id: a.experiment_id,\n variant_key: a.variant_key,\n })),\n // Merge page metadata from Analytics if available\n page_metadata: pageMetadataRef?.current ?? undefined,\n timestamp: new Date().toISOString(),\n }\n\n eventQueueRef.current.push(enrichedEvent)\n\n // Debounce flush\n if (flushTimeoutRef.current) {\n clearTimeout(flushTimeoutRef.current)\n }\n flushTimeoutRef.current = setTimeout(flushEvents, 1000)\n }, [enabled, apiKey, flushEvents])\n\n // ============================================\n // Outcome Tracking\n // ============================================\n\n const trackOutcome = useCallback(async (outcome: SignalOutcome) => {\n if (!enabled || !apiKey) return\n\n try {\n // retries: 0 — fire-and-forget conversion signal; never double-fire on a\n // lost response. Still aborts a hung request at the transport timeout.\n await sonorFetch(\n `${apiUrl}/api/public/signal/outcome`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...outcome,\n visitor_id: resolvedVisitorId,\n session_id: resolvedSessionId,\n experiments: Array.from(assignmentsRef.current.keys()),\n page_url: window.location.href,\n timestamp: new Date().toISOString(),\n }),\n },\n { apiKey, retries: 0 },\n )\n } catch (err) {\n if (isDebug()) console.error('[Signal] Outcome tracking error:', err)\n }\n }, [apiUrl, apiKey, enabled])\n\n // ============================================\n // Behavioral Tracking\n // ============================================\n\n useEffect(() => {\n if (!behaviorTracking || typeof window === 'undefined') return\n\n // Track scroll depth\n const handleScroll = () => {\n const scrollTop = window.scrollY\n const docHeight = document.documentElement.scrollHeight - window.innerHeight\n const depth = docHeight > 0 ? Math.round((scrollTop / docHeight) * 100) : 0\n scrollDepthRef.current = Math.max(scrollDepthRef.current, depth)\n }\n\n // Track clicks\n const handleClick = () => {\n clickCountRef.current++\n }\n\n window.addEventListener('scroll', handleScroll, { passive: true })\n window.addEventListener('click', handleClick)\n\n // Flush on visibility change or page hide.\n // `pagehide` (not `beforeunload`): fires on iOS Safari, bfcache-safe.\n const handleVisibilityChange = () => {\n if (document.visibilityState === 'hidden') {\n flushEvents()\n }\n }\n\n document.addEventListener('visibilitychange', handleVisibilityChange)\n window.addEventListener('pagehide', flushEvents)\n\n return () => {\n window.removeEventListener('scroll', handleScroll)\n window.removeEventListener('click', handleClick)\n document.removeEventListener('visibilitychange', handleVisibilityChange)\n window.removeEventListener('pagehide', flushEvents)\n }\n }, [behaviorTracking, flushEvents])\n\n // ============================================\n // Initialization + shell registration\n // ============================================\n\n useEffect(() => {\n fetchConfig()\n }, [fetchConfig])\n\n useEffect(() => {\n if (config && realtime) {\n connectSSE()\n }\n\n return () => {\n if (eventSourceRef.current) {\n eventSourceRef.current.close()\n }\n }\n }, [config, realtime, connectSSE])\n\n // Hand the imperative API to the shell; buffered calls drain on register.\n useEffect(() => {\n onRegister({\n trackEvent,\n trackOutcome: (outcome: SignalOutcome) => { void trackOutcome(outcome) },\n getExperiment,\n refreshConfig: fetchConfig,\n })\n return () => onRegister(null)\n }, [onRegister, trackEvent, trackOutcome, getExperiment, fetchConfig])\n\n return null\n}\n"]}
@@ -0,0 +1,8 @@
1
+ export { SitemapSync } from './chunk-ADBLBGCQ.mjs';
2
+ import './chunk-QJU6HBSK.mjs';
3
+ import './chunk-ADOGOLYO.mjs';
4
+ import './chunk-SXNKLHOX.mjs';
5
+ import './chunk-4SQ6PROR.mjs';
6
+ import './chunk-BEXTDHO4.mjs';
7
+ //# sourceMappingURL=SitemapSync-5CXS2JGB.mjs.map
8
+ //# sourceMappingURL=SitemapSync-5CXS2JGB.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"SitemapSync-T75NAFB3.mjs"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"SitemapSync-5CXS2JGB.mjs"}
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ var chunkCBMHJPR7_js = require('./chunk-CBMHJPR7.js');
4
+ require('./chunk-JEOKDUPQ.js');
5
+ require('./chunk-VIIGOCX4.js');
6
+ require('./chunk-CKPFETIO.js');
7
+ require('./chunk-YPEX4RDE.js');
8
+ require('./chunk-SNAQBZPT.js');
9
+
10
+
11
+
12
+ Object.defineProperty(exports, "SitemapSync", {
13
+ enumerable: true,
14
+ get: function () { return chunkCBMHJPR7_js.SitemapSync; }
15
+ });
16
+ //# sourceMappingURL=SitemapSync-J4UMJRTO.js.map
17
+ //# sourceMappingURL=SitemapSync-J4UMJRTO.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"SitemapSync-AJU4DM3G.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"SitemapSync-J4UMJRTO.js"}
@@ -2,13 +2,13 @@
2
2
  'use strict';
3
3
 
4
4
  var chunkEDZWNCSE_js = require('../chunk-EDZWNCSE.js');
5
- var chunk3FZ76VI5_js = require('../chunk-3FZ76VI5.js');
5
+ var chunkHPIY7AR3_js = require('../chunk-HPIY7AR3.js');
6
6
  var chunkHMFFAUCD_js = require('../chunk-HMFFAUCD.js');
7
7
  require('../chunk-RC4WWQXR.js');
8
8
  require('../chunk-VJMPIRSD.js');
9
- require('../chunk-4D2G5ZNP.js');
10
- require('../chunk-FQ3JQV3M.js');
11
- require('../chunk-S65JSRWW.js');
9
+ require('../chunk-VIIGOCX4.js');
10
+ require('../chunk-CKPFETIO.js');
11
+ require('../chunk-YPEX4RDE.js');
12
12
  require('../chunk-SNAQBZPT.js');
13
13
 
14
14
 
@@ -23,23 +23,23 @@ Object.defineProperty(exports, "useContactTracking", {
23
23
  });
24
24
  Object.defineProperty(exports, "AnalyticsProvider", {
25
25
  enumerable: true,
26
- get: function () { return chunk3FZ76VI5_js.AnalyticsProvider; }
26
+ get: function () { return chunkHPIY7AR3_js.AnalyticsProvider; }
27
27
  });
28
28
  Object.defineProperty(exports, "WebVitals", {
29
29
  enumerable: true,
30
- get: function () { return chunk3FZ76VI5_js.WebVitals; }
30
+ get: function () { return chunkHPIY7AR3_js.WebVitals; }
31
31
  });
32
32
  Object.defineProperty(exports, "useAnalytics", {
33
33
  enumerable: true,
34
- get: function () { return chunk3FZ76VI5_js.useAnalytics; }
34
+ get: function () { return chunkHPIY7AR3_js.useAnalytics; }
35
35
  });
36
36
  Object.defineProperty(exports, "useAnalyticsOptional", {
37
37
  enumerable: true,
38
- get: function () { return chunk3FZ76VI5_js.useAnalyticsOptional; }
38
+ get: function () { return chunkHPIY7AR3_js.useAnalyticsOptional; }
39
39
  });
40
40
  Object.defineProperty(exports, "useTrackEvent", {
41
41
  enumerable: true,
42
- get: function () { return chunk3FZ76VI5_js.useTrackEvent; }
42
+ get: function () { return chunkHPIY7AR3_js.useTrackEvent; }
43
43
  });
44
44
  Object.defineProperty(exports, "trackConversion", {
45
45
  enumerable: true,
@@ -1,12 +1,12 @@
1
1
  'use client';
2
2
  export { ContactTracking, useContactTracking } from '../chunk-26JXNW7B.mjs';
3
- export { AnalyticsProvider, WebVitals, useAnalytics, useAnalyticsOptional, useTrackEvent } from '../chunk-HEUCDF3O.mjs';
3
+ export { AnalyticsProvider, WebVitals, useAnalytics, useAnalyticsOptional, useTrackEvent } from '../chunk-OAJVITNO.mjs';
4
4
  export { trackConversion, trackEvent } from '../chunk-3DPXOZAU.mjs';
5
5
  import '../chunk-ZZQAGCSI.mjs';
6
6
  import '../chunk-6EDVCUAG.mjs';
7
- import '../chunk-4UHO6DPJ.mjs';
8
- import '../chunk-FDWDXMJL.mjs';
9
- import '../chunk-JPTJGLKS.mjs';
7
+ import '../chunk-ADOGOLYO.mjs';
8
+ import '../chunk-SXNKLHOX.mjs';
9
+ import '../chunk-4SQ6PROR.mjs';
10
10
  import '../chunk-BEXTDHO4.mjs';
11
11
  //# sourceMappingURL=index.mjs.map
12
12
  //# sourceMappingURL=index.mjs.map
@@ -1,14 +1,18 @@
1
1
  /**
2
2
  * @sonordev/site-kit/blog
3
3
  *
4
- * Complete blog integration for Portal-managed content.
5
- * Create posts in the Portal, automatically embedded in your site.
4
+ * Complete blog integration for Sonor-managed content.
5
+ * Create posts in the Sonor dashboard, automatically embedded in your site.
6
+ *
7
+ * Async server components (BlogLayout, BlogList, BlogPost, BlogSidebar,
8
+ * RelatedPosts, the *Page helpers) come from `blog/server-ui`. This entry is
9
+ * 'use client'-stamped, so importing them from here hands Next an async
10
+ * component across a client boundary and the route 500s in production.
6
11
  *
7
12
  * @example
8
13
  * ```tsx
9
- * // Blog index page (BlogList from server-ui avoids Next RSC + shared client chunks)
10
- * import { BlogList } from '@sonordev/site-kit/blog/server-ui'
11
- * import { BlogLayout } from '@sonordev/site-kit/blog'
14
+ * // Blog index page both from server-ui; this barrel is for client components only
15
+ * import { BlogList, BlogLayout } from '@sonordev/site-kit/blog/server-ui'
12
16
  *
13
17
  * export default function BlogPage() {
14
18
  * return (
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/blog/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,YAAY,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAErE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,YAAY,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAErE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAE/D,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC/E,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAExG,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAClE,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAEjE;;;;;;;;;;;;;;;GAeG;AACH,YAAY,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAGnE,cAAc,SAAS,CAAA;AAGvB,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/blog/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,YAAY,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAErE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,YAAY,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAErE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAE/D,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC/E,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAExG,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAClE,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAEjE;;;;;;;;;;;;;;;GAeG;AACH,YAAY,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAGnE,cAAc,SAAS,CAAA;AAGvB,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,mBAAmB,CAAA"}
@@ -3,7 +3,7 @@
3
3
 
4
4
  var chunkGQF6QAQS_js = require('../chunk-GQF6QAQS.js');
5
5
  var chunkDO6ATNLN_js = require('../chunk-DO6ATNLN.js');
6
- var chunkGCZMDY2T_js = require('../chunk-GCZMDY2T.js');
6
+ var chunkDKRXPXOR_js = require('../chunk-DKRXPXOR.js');
7
7
  require('../chunk-HX6ZG3PP.js');
8
8
  var chunkTPL2IHFI_js = require('../chunk-TPL2IHFI.js');
9
9
  var chunkJ7QI3GDX_js = require('../chunk-J7QI3GDX.js');
@@ -15,7 +15,7 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
15
15
 
16
16
  var React__default = /*#__PURE__*/_interopDefault(React);
17
17
 
18
- var ManagedNewsletterForm = React__default.default.lazy(() => import('../ManagedNewsletterForm-PG4EX3W6.js'));
18
+ var ManagedNewsletterForm = React__default.default.lazy(() => import('../ManagedNewsletterForm-KT2NGUNW.js'));
19
19
  function NewsletterWidget({
20
20
  title = "Subscribe to Our Newsletter",
21
21
  description = "Get the latest posts delivered straight to your inbox.",
@@ -206,7 +206,7 @@ function AuthorCard({ author, showBio = true, showSocial = true, showTrustBlock
206
206
  author.company ? ` at ${author.company}` : ""
207
207
  ] }),
208
208
  showBio && author.bio && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: "4px 0", color: "var(--sk-text-secondary)", fontSize: 14 }, children: author.bio }),
209
- showSocial && chunkGCZMDY2T_js.getAuthorSocialLinks(author).length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", gap: 12, marginTop: 8 }, children: chunkGCZMDY2T_js.getAuthorSocialLinks(author).map((link) => /* @__PURE__ */ jsxRuntime.jsx("a", { href: link.href, target: "_blank", rel: "noopener noreferrer", children: link.label }, link.label)) })
209
+ showSocial && chunkDKRXPXOR_js.getAuthorSocialLinks(author).length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", gap: 12, marginTop: 8 }, children: chunkDKRXPXOR_js.getAuthorSocialLinks(author).map((link) => /* @__PURE__ */ jsxRuntime.jsx("a", { href: link.href, target: "_blank", rel: "noopener noreferrer", children: link.label }, link.label)) })
210
210
  ] })
211
211
  ] }),
212
212
  showTrustBlock && /* @__PURE__ */ jsxRuntime.jsx(TrustBlock, { author })
@@ -267,7 +267,7 @@ function AuthorHero({ author }) {
267
267
  );
268
268
  }
269
269
  function SocialLinks({ author }) {
270
- const links = chunkGCZMDY2T_js.getAuthorSocialLinks(author);
270
+ const links = chunkDKRXPXOR_js.getAuthorSocialLinks(author);
271
271
  if (links.length === 0) return null;
272
272
  return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", gap: 16, marginTop: 16 }, children: links.map((link) => /* @__PURE__ */ jsxRuntime.jsx(
273
273
  "a",
@@ -322,8 +322,8 @@ function PostCard({ post, basePath }) {
322
322
  date && /* @__PURE__ */ jsxRuntime.jsx("time", { style: { fontSize: 12, color: "var(--sk-text-tertiary, #6b7280)", marginBottom: 6 }, children: date }),
323
323
  /* @__PURE__ */ jsxRuntime.jsx("a", { href, style: { textDecoration: "none", color: "inherit" }, children: /* @__PURE__ */ jsxRuntime.jsx("h3", { style: { margin: "0 0 8px", fontSize: 18, fontWeight: 600, lineHeight: 1.3, color: "var(--sk-text-primary, #111827)" }, children: post.title }) }),
324
324
  post.excerpt && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontSize: 14, lineHeight: 1.6, color: "var(--sk-text-secondary, #4b5563)", flex: 1 }, children: post.excerpt }),
325
- chunkGCZMDY2T_js.readingTimeMinutes(post) && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: 12, color: "var(--sk-text-tertiary, #6b7280)", marginTop: 12 }, children: [
326
- chunkGCZMDY2T_js.readingTimeMinutes(post),
325
+ chunkDKRXPXOR_js.readingTimeMinutes(post) && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: 12, color: "var(--sk-text-tertiary, #6b7280)", marginTop: 12 }, children: [
326
+ chunkDKRXPXOR_js.readingTimeMinutes(post),
327
327
  " min read"
328
328
  ] })
329
329
  ] })
@@ -455,59 +455,59 @@ Object.defineProperty(exports, "BlogFAQ", {
455
455
  });
456
456
  Object.defineProperty(exports, "BlogLayout", {
457
457
  enumerable: true,
458
- get: function () { return chunkGCZMDY2T_js.BlogLayout; }
458
+ get: function () { return chunkDKRXPXOR_js.BlogLayout; }
459
459
  });
460
460
  Object.defineProperty(exports, "BlogList", {
461
461
  enumerable: true,
462
- get: function () { return chunkGCZMDY2T_js.BlogList; }
462
+ get: function () { return chunkDKRXPXOR_js.BlogList; }
463
463
  });
464
464
  Object.defineProperty(exports, "BlogPage", {
465
465
  enumerable: true,
466
- get: function () { return chunkGCZMDY2T_js.BlogPage; }
466
+ get: function () { return chunkDKRXPXOR_js.BlogPage; }
467
467
  });
468
468
  Object.defineProperty(exports, "BlogPost", {
469
469
  enumerable: true,
470
- get: function () { return chunkGCZMDY2T_js.BlogPost; }
470
+ get: function () { return chunkDKRXPXOR_js.BlogPost; }
471
471
  });
472
472
  Object.defineProperty(exports, "BlogPostPage", {
473
473
  enumerable: true,
474
- get: function () { return chunkGCZMDY2T_js.BlogPostPage; }
474
+ get: function () { return chunkDKRXPXOR_js.BlogPostPage; }
475
475
  });
476
476
  Object.defineProperty(exports, "BlogSidebar", {
477
477
  enumerable: true,
478
- get: function () { return chunkGCZMDY2T_js.BlogSidebar; }
478
+ get: function () { return chunkDKRXPXOR_js.BlogSidebar; }
479
479
  });
480
480
  Object.defineProperty(exports, "CategoryPage", {
481
481
  enumerable: true,
482
- get: function () { return chunkGCZMDY2T_js.CategoryPage; }
482
+ get: function () { return chunkDKRXPXOR_js.CategoryPage; }
483
483
  });
484
484
  Object.defineProperty(exports, "ClusterNavigation", {
485
485
  enumerable: true,
486
- get: function () { return chunkGCZMDY2T_js.ClusterNavigation; }
486
+ get: function () { return chunkDKRXPXOR_js.ClusterNavigation; }
487
487
  });
488
488
  Object.defineProperty(exports, "RelatedPosts", {
489
489
  enumerable: true,
490
- get: function () { return chunkGCZMDY2T_js.RelatedPosts; }
490
+ get: function () { return chunkDKRXPXOR_js.RelatedPosts; }
491
491
  });
492
492
  Object.defineProperty(exports, "ServiceCallout", {
493
493
  enumerable: true,
494
- get: function () { return chunkGCZMDY2T_js.ServiceCallout; }
494
+ get: function () { return chunkDKRXPXOR_js.ServiceCallout; }
495
495
  });
496
496
  Object.defineProperty(exports, "ServiceCallouts", {
497
497
  enumerable: true,
498
- get: function () { return chunkGCZMDY2T_js.ServiceCallouts; }
498
+ get: function () { return chunkDKRXPXOR_js.ServiceCallouts; }
499
499
  });
500
500
  Object.defineProperty(exports, "addExternalLinkTargets", {
501
501
  enumerable: true,
502
- get: function () { return chunkGCZMDY2T_js.addExternalLinkTargets; }
502
+ get: function () { return chunkDKRXPXOR_js.addExternalLinkTargets; }
503
503
  });
504
504
  Object.defineProperty(exports, "normalizeSiteHost", {
505
505
  enumerable: true,
506
- get: function () { return chunkGCZMDY2T_js.normalizeSiteHost; }
506
+ get: function () { return chunkDKRXPXOR_js.normalizeSiteHost; }
507
507
  });
508
508
  Object.defineProperty(exports, "resolveBlogSiteUrl", {
509
509
  enumerable: true,
510
- get: function () { return chunkGCZMDY2T_js.resolveBlogSiteUrl; }
510
+ get: function () { return chunkDKRXPXOR_js.resolveBlogSiteUrl; }
511
511
  });
512
512
  exports.AuthorCard = AuthorCard;
513
513
  exports.AuthorPage = AuthorPage;
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
  export { BlogFAQ } from '../chunk-O237KKCX.mjs';
3
3
  import { NewsletterShell } from '../chunk-AK6JZ3OE.mjs';
4
- import { getAuthorSocialLinks, readingTimeMinutes } from '../chunk-UV6KQUSL.mjs';
5
- export { BlogLayout, BlogList, BlogPage, BlogPost, BlogPostPage, BlogSidebar, CategoryPage, ClusterNavigation, RelatedPosts, ServiceCallout, ServiceCallouts, addExternalLinkTargets, normalizeSiteHost, resolveBlogSiteUrl } from '../chunk-UV6KQUSL.mjs';
4
+ import { getAuthorSocialLinks, readingTimeMinutes } from '../chunk-A3VGZAZQ.mjs';
5
+ export { BlogLayout, BlogList, BlogPage, BlogPost, BlogPostPage, BlogSidebar, CategoryPage, ClusterNavigation, RelatedPosts, ServiceCallout, ServiceCallouts, addExternalLinkTargets, normalizeSiteHost, resolveBlogSiteUrl } from '../chunk-A3VGZAZQ.mjs';
6
6
  import '../chunk-YFX3Q56O.mjs';
7
7
  import { generateAuthorSchema } from '../chunk-CGCYZJYX.mjs';
8
8
  import { safeJsonLd } from '../chunk-662YHKWW.mjs';
@@ -10,7 +10,7 @@ import '../chunk-BEXTDHO4.mjs';
10
10
  import React, { useState, Suspense, useEffect } from 'react';
11
11
  import { jsx, jsxs } from 'react/jsx-runtime';
12
12
 
13
- var ManagedNewsletterForm = React.lazy(() => import('../ManagedNewsletterForm-6DET3VGZ.mjs'));
13
+ var ManagedNewsletterForm = React.lazy(() => import('../ManagedNewsletterForm-YKYW7B6P.mjs'));
14
14
  function NewsletterWidget({
15
15
  title = "Subscribe to Our Newsletter",
16
16
  description = "Get the latest posts delivered straight to your inbox.",
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkGCZMDY2T_js = require('../chunk-GCZMDY2T.js');
3
+ var chunkDKRXPXOR_js = require('../chunk-DKRXPXOR.js');
4
4
  require('../chunk-HX6ZG3PP.js');
5
5
  var chunkJBGRXICL_js = require('../chunk-JBGRXICL.js');
6
6
  require('../chunk-TPL2IHFI.js');
@@ -159,8 +159,8 @@ async function ClusterLandingPage({
159
159
  /* @__PURE__ */ jsxRuntime.jsx("h2", { className: unstyled ? "" : "sk-cluster-pillar-title", children: pillar.title }),
160
160
  pillar.excerpt && /* @__PURE__ */ jsxRuntime.jsx("p", { className: unstyled ? "" : "sk-cluster-pillar-excerpt", children: pillar.excerpt }),
161
161
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: unstyled ? "" : "sk-cluster-pillar-meta", children: [
162
- chunkGCZMDY2T_js.readingTimeMinutes(pillar) && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
163
- chunkGCZMDY2T_js.readingTimeMinutes(pillar),
162
+ chunkDKRXPXOR_js.readingTimeMinutes(pillar) && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
163
+ chunkDKRXPXOR_js.readingTimeMinutes(pillar),
164
164
  " min read"
165
165
  ] }),
166
166
  pillar.word_count && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
@@ -184,8 +184,8 @@ async function ClusterLandingPage({
184
184
  /* @__PURE__ */ jsxRuntime.jsx("h3", { className: unstyled ? "" : "sk-cluster-support-title", children: post.title }),
185
185
  post.excerpt && /* @__PURE__ */ jsxRuntime.jsx("p", { className: unstyled ? "" : "sk-cluster-support-excerpt", children: post.excerpt }),
186
186
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: unstyled ? "" : "sk-cluster-support-meta", children: [
187
- chunkGCZMDY2T_js.readingTimeMinutes(post) && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
188
- chunkGCZMDY2T_js.readingTimeMinutes(post),
187
+ chunkDKRXPXOR_js.readingTimeMinutes(post) && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
188
+ chunkDKRXPXOR_js.readingTimeMinutes(post),
189
189
  " min read"
190
190
  ] }),
191
191
  post.relationship_to_pillar && /* @__PURE__ */ jsxRuntime.jsx("span", { children: post.relationship_to_pillar })
@@ -201,39 +201,39 @@ async function ClusterLandingPage({
201
201
 
202
202
  Object.defineProperty(exports, "BlogLayout", {
203
203
  enumerable: true,
204
- get: function () { return chunkGCZMDY2T_js.BlogLayout; }
204
+ get: function () { return chunkDKRXPXOR_js.BlogLayout; }
205
205
  });
206
206
  Object.defineProperty(exports, "BlogList", {
207
207
  enumerable: true,
208
- get: function () { return chunkGCZMDY2T_js.BlogList; }
208
+ get: function () { return chunkDKRXPXOR_js.BlogList; }
209
209
  });
210
210
  Object.defineProperty(exports, "BlogPage", {
211
211
  enumerable: true,
212
- get: function () { return chunkGCZMDY2T_js.BlogPage; }
212
+ get: function () { return chunkDKRXPXOR_js.BlogPage; }
213
213
  });
214
214
  Object.defineProperty(exports, "BlogPost", {
215
215
  enumerable: true,
216
- get: function () { return chunkGCZMDY2T_js.BlogPost; }
216
+ get: function () { return chunkDKRXPXOR_js.BlogPost; }
217
217
  });
218
218
  Object.defineProperty(exports, "BlogPostPage", {
219
219
  enumerable: true,
220
- get: function () { return chunkGCZMDY2T_js.BlogPostPage; }
220
+ get: function () { return chunkDKRXPXOR_js.BlogPostPage; }
221
221
  });
222
222
  Object.defineProperty(exports, "BlogSidebar", {
223
223
  enumerable: true,
224
- get: function () { return chunkGCZMDY2T_js.BlogSidebar; }
224
+ get: function () { return chunkDKRXPXOR_js.BlogSidebar; }
225
225
  });
226
226
  Object.defineProperty(exports, "CategoryPage", {
227
227
  enumerable: true,
228
- get: function () { return chunkGCZMDY2T_js.CategoryPage; }
228
+ get: function () { return chunkDKRXPXOR_js.CategoryPage; }
229
229
  });
230
230
  Object.defineProperty(exports, "ClusterNavigation", {
231
231
  enumerable: true,
232
- get: function () { return chunkGCZMDY2T_js.ClusterNavigation; }
232
+ get: function () { return chunkDKRXPXOR_js.ClusterNavigation; }
233
233
  });
234
234
  Object.defineProperty(exports, "RelatedPosts", {
235
235
  enumerable: true,
236
- get: function () { return chunkGCZMDY2T_js.RelatedPosts; }
236
+ get: function () { return chunkDKRXPXOR_js.RelatedPosts; }
237
237
  });
238
238
  exports.ClusterLandingPage = ClusterLandingPage;
239
239
  //# sourceMappingURL=server-ui.js.map
@@ -1,5 +1,5 @@
1
- import { readingTimeMinutes } from '../chunk-UV6KQUSL.mjs';
2
- export { BlogLayout, BlogList, BlogPage, BlogPost, BlogPostPage, BlogSidebar, CategoryPage, ClusterNavigation, RelatedPosts } from '../chunk-UV6KQUSL.mjs';
1
+ import { readingTimeMinutes } from '../chunk-A3VGZAZQ.mjs';
2
+ export { BlogLayout, BlogList, BlogPage, BlogPost, BlogPostPage, BlogSidebar, CategoryPage, ClusterNavigation, RelatedPosts } from '../chunk-A3VGZAZQ.mjs';
3
3
  import '../chunk-YFX3Q56O.mjs';
4
4
  import { getTopicCluster } from '../chunk-DHXQBTXE.mjs';
5
5
  import '../chunk-CGCYZJYX.mjs';
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunkJIUVBSQZ_js = require('./chunk-JIUVBSQZ.js');
4
+ var chunkGZVSGQKT_js = require('./chunk-GZVSGQKT.js');
5
5
  var React = require('react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
 
@@ -16,8 +16,8 @@ function SignalExperiment({
16
16
  trackImpression = true,
17
17
  children
18
18
  }) {
19
- const { assignment, variant, isControl } = chunkJIUVBSQZ_js.useSignalExperiment(experimentId);
20
- const trackEvent = chunkJIUVBSQZ_js.useSignalEvent();
19
+ const { assignment, variant, isControl } = chunkGZVSGQKT_js.useSignalExperiment(experimentId);
20
+ const trackEvent = chunkGZVSGQKT_js.useSignalEvent();
21
21
  React.useEffect(() => {
22
22
  if (trackImpression && variant) {
23
23
  trackEvent({
@@ -44,7 +44,7 @@ function SignalExperiment({
44
44
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: variants.control || null });
45
45
  }
46
46
  function useExperimentVariant(experimentId) {
47
- return chunkJIUVBSQZ_js.useSignalExperiment(experimentId);
47
+ return chunkGZVSGQKT_js.useSignalExperiment(experimentId);
48
48
  }
49
49
  function ExperimentConversion({
50
50
  experimentId,
@@ -52,8 +52,8 @@ function ExperimentConversion({
52
52
  value,
53
53
  children
54
54
  }) {
55
- const trackEvent = chunkJIUVBSQZ_js.useSignalEvent();
56
- const { variant } = chunkJIUVBSQZ_js.useSignalExperiment(experimentId);
55
+ const trackEvent = chunkGZVSGQKT_js.useSignalEvent();
56
+ const { variant } = chunkGZVSGQKT_js.useSignalExperiment(experimentId);
57
57
  const handleInteraction = () => {
58
58
  trackEvent({
59
59
  event_type: "experiment",
@@ -79,5 +79,5 @@ function ExperimentConversion({
79
79
  exports.ExperimentConversion = ExperimentConversion;
80
80
  exports.SignalExperiment = SignalExperiment;
81
81
  exports.useExperimentVariant = useExperimentVariant;
82
- //# sourceMappingURL=chunk-6QQFEJIP.js.map
83
- //# sourceMappingURL=chunk-6QQFEJIP.js.map
82
+ //# sourceMappingURL=chunk-2EJX56YJ.js.map
83
+ //# sourceMappingURL=chunk-2EJX56YJ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/signal/SignalExperiment.tsx"],"names":["useSignalExperiment","useSignalEvent","useEffect","jsx","Fragment","React"],"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,GAAIA,qCAAoB,YAAY,CAAA;AAC3E,EAAA,MAAM,aAAaC,+BAAA,EAAe;AAGlC,EAAAC,eAAA,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,uBAAOC,cAAA,CAAAC,mBAAA,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,6DAAU,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,EACpB;AAGA,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,6DAAU,QAAA,EAAA,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,uBAAOD,cAAA,CAAAC,mBAAA,EAAA,EAAG,QAAA,EAAA,QAAA,CAAS,OAAA,IAAW,IAAA,EAAK,CAAA;AACrC;AAYO,SAAS,qBAAqB,YAAA,EAAsB;AACzD,EAAA,OAAOJ,qCAAoB,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,aAAaC,+BAAA,EAAe;AAClC,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAID,oCAAA,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,OAAOK,sBAAA,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-6QQFEJIP.js","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":["useSignalExperiment","useSignalEvent","useEffect","jsx","Fragment","React"],"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,GAAIA,qCAAoB,YAAY,CAAA;AAC3E,EAAA,MAAM,aAAaC,+BAAA,EAAe;AAGlC,EAAAC,eAAA,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,uBAAOC,cAAA,CAAAC,mBAAA,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,6DAAU,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,EACpB;AAGA,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,6DAAU,QAAA,EAAA,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,uBAAOD,cAAA,CAAAC,mBAAA,EAAA,EAAG,QAAA,EAAA,QAAA,CAAS,OAAA,IAAW,IAAA,EAAK,CAAA;AACrC;AAYO,SAAS,qBAAqB,YAAA,EAAsB;AACzD,EAAA,OAAOJ,qCAAoB,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,aAAaC,+BAAA,EAAe;AAClC,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAID,oCAAA,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,OAAOK,sBAAA,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-2EJX56YJ.js","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,6 +1,6 @@
1
1
  'use client';
2
- import { useForm } from './chunk-YVE65W47.mjs';
3
- import { sonorFetch } from './chunk-4UHO6DPJ.mjs';
2
+ import { useForm } from './chunk-BUDV7QHH.mjs';
3
+ import { sonorFetch } from './chunk-ADOGOLYO.mjs';
4
4
  import { useState, useRef, useEffect, useCallback } from 'react';
5
5
  import ReactMarkdown from 'react-markdown';
6
6
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -1605,5 +1605,5 @@ function ChatWidget({ projectId: propProjectId, config, apiUrl: propApiUrl, sign
1605
1605
  }
1606
1606
 
1607
1607
  export { ChatWidget };
1608
- //# sourceMappingURL=chunk-SXPINIJG.mjs.map
1609
- //# sourceMappingURL=chunk-SXPINIJG.mjs.map
1608
+ //# sourceMappingURL=chunk-2XHEUWHV.mjs.map
1609
+ //# sourceMappingURL=chunk-2XHEUWHV.mjs.map