@sonordev/site-kit 5.5.0 → 5.7.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 (392) hide show
  1. package/agent-manifest.json +11 -3
  2. package/dist/AnalyticsProvider-EWF7JN2X.mjs +11 -0
  3. package/dist/{AnalyticsProvider-KFXAH4GR.mjs.map → AnalyticsProvider-EWF7JN2X.mjs.map} +1 -1
  4. package/dist/AnalyticsProvider-GJFG7YXA.js +32 -0
  5. package/dist/{AnalyticsProvider-WDDW3IJW.js.map → AnalyticsProvider-GJFG7YXA.js.map} +1 -1
  6. package/dist/{BlogViewTracker-D4DIEP4Q.js → BlogViewTracker-2D3IJPJK.js} +6 -6
  7. package/dist/{BlogViewTracker-D4DIEP4Q.js.map → BlogViewTracker-2D3IJPJK.js.map} +1 -1
  8. package/dist/{BlogViewTracker-ZVEGGH3Y.mjs → BlogViewTracker-CKYG6MYU.mjs} +5 -5
  9. package/dist/{BlogViewTracker-ZVEGGH3Y.mjs.map → BlogViewTracker-CKYG6MYU.mjs.map} +1 -1
  10. package/dist/ChatWidget-AWP6GBVW.js +22 -0
  11. package/dist/{ChatWidget-2ZYPYIMQ.js.map → ChatWidget-AWP6GBVW.js.map} +1 -1
  12. package/dist/ChatWidget-Z5QXDZP3.mjs +13 -0
  13. package/dist/{ChatWidget-FYCCLMQE.mjs.map → ChatWidget-Z5QXDZP3.mjs.map} +1 -1
  14. package/dist/EngageWidget-BKEY5TPO.mjs +12 -0
  15. package/dist/{EngageWidget-6HUZYOY7.mjs.map → EngageWidget-BKEY5TPO.mjs.map} +1 -1
  16. package/dist/EngageWidget-VT4DYXVO.js +21 -0
  17. package/dist/{EngageWidget-MYQTBBW6.js.map → EngageWidget-VT4DYXVO.js.map} +1 -1
  18. package/dist/{FileField-JK2S24XU.js → FileField-62ZWZMQK.js} +6 -6
  19. package/dist/{FileField-JK2S24XU.js.map → FileField-62ZWZMQK.js.map} +1 -1
  20. package/dist/{FileField-OZZHWGPA.mjs → FileField-JJN5QKDL.mjs} +5 -5
  21. package/dist/{FileField-OZZHWGPA.mjs.map → FileField-JJN5QKDL.mjs.map} +1 -1
  22. package/dist/{FormSpotlight-XV42L72H.mjs → FormSpotlight-OTFB6QM5.mjs} +3 -3
  23. package/dist/{FormSpotlight-XV42L72H.mjs.map → FormSpotlight-OTFB6QM5.mjs.map} +1 -1
  24. package/dist/{FormSpotlight-5AXFQU5M.js → FormSpotlight-URS4XRS7.js} +15 -15
  25. package/dist/{FormSpotlight-5AXFQU5M.js.map → FormSpotlight-URS4XRS7.js.map} +1 -1
  26. package/dist/{FormStage-HATUHNRV.js → FormStage-FVKMIV73.js} +13 -13
  27. package/dist/{FormStage-HATUHNRV.js.map → FormStage-FVKMIV73.js.map} +1 -1
  28. package/dist/{FormStage-RUK675HV.mjs → FormStage-VPGOCMAV.mjs} +3 -3
  29. package/dist/{FormStage-RUK675HV.mjs.map → FormStage-VPGOCMAV.mjs.map} +1 -1
  30. package/dist/ManagedForm-CXVDJMHN.mjs +14 -0
  31. package/dist/{ManagedForm-OA3MNGXT.mjs.map → ManagedForm-CXVDJMHN.mjs.map} +1 -1
  32. package/dist/ManagedForm-FGNTDGED.js +23 -0
  33. package/dist/{ManagedForm-JWEXJEXK.js.map → ManagedForm-FGNTDGED.js.map} +1 -1
  34. package/dist/{ManagedNewsletterForm-AAHH63KT.js → ManagedNewsletterForm-3O5L44AZ.js} +8 -8
  35. package/dist/{ManagedNewsletterForm-AAHH63KT.js.map → ManagedNewsletterForm-3O5L44AZ.js.map} +1 -1
  36. package/dist/{ManagedNewsletterForm-HZKTNWLW.mjs → ManagedNewsletterForm-SQYB4BZU.mjs} +7 -7
  37. package/dist/{ManagedNewsletterForm-HZKTNWLW.mjs.map → ManagedNewsletterForm-SQYB4BZU.mjs.map} +1 -1
  38. package/dist/{SignalCore-X3GDGBZD.mjs → SignalCore-M2PKKIGH.mjs} +5 -5
  39. package/dist/{SignalCore-X3GDGBZD.mjs.map → SignalCore-M2PKKIGH.mjs.map} +1 -1
  40. package/dist/{SignalCore-YSNZYBKJ.js → SignalCore-RFBOBNLQ.js} +11 -11
  41. package/dist/{SignalCore-YSNZYBKJ.js.map → SignalCore-RFBOBNLQ.js.map} +1 -1
  42. package/dist/SitemapSync-4OVMIIGC.mjs +9 -0
  43. package/dist/{SitemapSync-2PTDBH5E.mjs.map → SitemapSync-4OVMIIGC.mjs.map} +1 -1
  44. package/dist/SitemapSync-RK3SQ4M2.js +18 -0
  45. package/dist/{SitemapSync-3SFAI546.js.map → SitemapSync-RK3SQ4M2.js.map} +1 -1
  46. package/dist/SitemapSync.d.ts +3 -2
  47. package/dist/SitemapSync.d.ts.map +1 -1
  48. package/dist/analytics/AnalyticsProvider.d.ts +3 -1
  49. package/dist/analytics/AnalyticsProvider.d.ts.map +1 -1
  50. package/dist/analytics/WebVitals.d.ts +3 -1
  51. package/dist/analytics/WebVitals.d.ts.map +1 -1
  52. package/dist/analytics/index.js +13 -13
  53. package/dist/analytics/index.mjs +5 -5
  54. package/dist/analytics/send-gate.d.ts +8 -37
  55. package/dist/analytics/send-gate.d.ts.map +1 -1
  56. package/dist/blog/index.js +20 -20
  57. package/dist/blog/index.mjs +3 -3
  58. package/dist/blog/metadata-images.test.d.ts +2 -0
  59. package/dist/blog/metadata-images.test.d.ts.map +1 -0
  60. package/dist/blog/server-core.d.ts +31 -6
  61. package/dist/blog/server-core.d.ts.map +1 -1
  62. package/dist/blog/server-ui.js +16 -16
  63. package/dist/blog/server-ui.mjs +3 -3
  64. package/dist/blog/server.d.ts +31 -6
  65. package/dist/blog/server.d.ts.map +1 -1
  66. package/dist/blog/server.js +40 -40
  67. package/dist/blog/server.mjs +1 -1
  68. package/dist/blog/static-params.test.d.ts +2 -0
  69. package/dist/blog/static-params.test.d.ts.map +1 -0
  70. package/dist/{chunk-KAUUGRYB.js → chunk-2N27LCZH.js} +26 -32
  71. package/dist/chunk-2N27LCZH.js.map +1 -0
  72. package/dist/{chunk-R4MX6EOM.mjs → chunk-3CLP35TT.mjs} +7 -7
  73. package/dist/{chunk-R4MX6EOM.mjs.map → chunk-3CLP35TT.mjs.map} +1 -1
  74. package/dist/{chunk-SQVYLIIN.js → chunk-3S5JN6KL.js} +16 -19
  75. package/dist/chunk-3S5JN6KL.js.map +1 -0
  76. package/dist/chunk-3UC6JETG.js +32 -0
  77. package/dist/chunk-3UC6JETG.js.map +1 -0
  78. package/dist/{chunk-CT5REGAK.js → chunk-3YQILJKJ.js} +14 -14
  79. package/dist/{chunk-CT5REGAK.js.map → chunk-3YQILJKJ.js.map} +1 -1
  80. package/dist/{chunk-3B6CXGAK.mjs → chunk-47XQWV4S.mjs} +3 -3
  81. package/dist/{chunk-3B6CXGAK.mjs.map → chunk-47XQWV4S.mjs.map} +1 -1
  82. package/dist/{chunk-RZUZMUTN.mjs → chunk-4A5V73SR.mjs} +21 -9
  83. package/dist/chunk-4A5V73SR.mjs.map +1 -0
  84. package/dist/{chunk-FYVLQ3OU.js → chunk-4UVM7E2W.js} +3 -3
  85. package/dist/{chunk-FYVLQ3OU.js.map → chunk-4UVM7E2W.js.map} +1 -1
  86. package/dist/{chunk-HFJQMIFM.js → chunk-4WBTM6YE.js} +4 -4
  87. package/dist/{chunk-HFJQMIFM.js.map → chunk-4WBTM6YE.js.map} +1 -1
  88. package/dist/{chunk-XQYC4KMH.mjs → chunk-57AFHENV.mjs} +48 -42
  89. package/dist/chunk-57AFHENV.mjs.map +1 -0
  90. package/dist/chunk-5RNAUYWE.js +50 -0
  91. package/dist/chunk-5RNAUYWE.js.map +1 -0
  92. package/dist/chunk-5TXXTYXL.js +8 -0
  93. package/dist/{chunk-SUZ3ZLB2.js.map → chunk-5TXXTYXL.js.map} +1 -1
  94. package/dist/{chunk-RU54J2PY.mjs → chunk-6FC5Q4KU.mjs} +3 -3
  95. package/dist/{chunk-RU54J2PY.mjs.map → chunk-6FC5Q4KU.mjs.map} +1 -1
  96. package/dist/{chunk-ZRQFG3L6.mjs → chunk-7ZX6TO6C.mjs} +4 -4
  97. package/dist/{chunk-ZRQFG3L6.mjs.map → chunk-7ZX6TO6C.mjs.map} +1 -1
  98. package/dist/chunk-A6UYV475.mjs +45 -0
  99. package/dist/chunk-A6UYV475.mjs.map +1 -0
  100. package/dist/{chunk-4XGACM7D.mjs → chunk-ABZGEHTC.mjs} +3 -3
  101. package/dist/{chunk-4XGACM7D.mjs.map → chunk-ABZGEHTC.mjs.map} +1 -1
  102. package/dist/chunk-AWK57R5S.mjs +29 -0
  103. package/dist/chunk-AWK57R5S.mjs.map +1 -0
  104. package/dist/{chunk-EEQYKMGH.mjs → chunk-BFJOZ3MU.mjs} +23 -17
  105. package/dist/chunk-BFJOZ3MU.mjs.map +1 -0
  106. package/dist/{chunk-HX3BRMOX.js → chunk-BFM5PEFV.js} +3 -3
  107. package/dist/{chunk-HX3BRMOX.js.map → chunk-BFM5PEFV.js.map} +1 -1
  108. package/dist/{chunk-VYHRAICF.mjs → chunk-BQGEVMIR.mjs} +4 -4
  109. package/dist/{chunk-VYHRAICF.mjs.map → chunk-BQGEVMIR.mjs.map} +1 -1
  110. package/dist/{chunk-S6FEC6UT.mjs → chunk-BUJWXSYZ.mjs} +14 -17
  111. package/dist/chunk-BUJWXSYZ.mjs.map +1 -0
  112. package/dist/{chunk-VAS3LH5W.js → chunk-C4PZ2R3B.js} +55 -49
  113. package/dist/chunk-C4PZ2R3B.js.map +1 -0
  114. package/dist/{chunk-MU7IEPDG.mjs → chunk-C563AHZZ.mjs} +3 -3
  115. package/dist/{chunk-MU7IEPDG.mjs.map → chunk-C563AHZZ.mjs.map} +1 -1
  116. package/dist/{chunk-746RKQHA.js → chunk-CPY74A4F.js} +23 -17
  117. package/dist/chunk-CPY74A4F.js.map +1 -0
  118. package/dist/{chunk-UNPEMSLK.js → chunk-D553G64G.js} +24 -12
  119. package/dist/chunk-D553G64G.js.map +1 -0
  120. package/dist/{chunk-KPKQKFT4.js → chunk-DOB37PV4.js} +3 -3
  121. package/dist/{chunk-KPKQKFT4.js.map → chunk-DOB37PV4.js.map} +1 -1
  122. package/dist/{chunk-2OU4KBUN.js → chunk-ELQ4SRRR.js} +15 -15
  123. package/dist/{chunk-2OU4KBUN.js.map → chunk-ELQ4SRRR.js.map} +1 -1
  124. package/dist/{chunk-Q26VZNM2.js → chunk-F3AKYZOH.js} +3 -3
  125. package/dist/{chunk-Q26VZNM2.js.map → chunk-F3AKYZOH.js.map} +1 -1
  126. package/dist/{chunk-X2XFLYZ3.mjs → chunk-FBDHKYNF.mjs} +3 -3
  127. package/dist/{chunk-X2XFLYZ3.mjs.map → chunk-FBDHKYNF.mjs.map} +1 -1
  128. package/dist/{chunk-BNOQXDPJ.js → chunk-FEWWGEQF.js} +4 -4
  129. package/dist/{chunk-BNOQXDPJ.js.map → chunk-FEWWGEQF.js.map} +1 -1
  130. package/dist/{chunk-NZSFOZJV.js → chunk-FO4KGPGF.js} +2 -2
  131. package/dist/{chunk-NZSFOZJV.js.map → chunk-FO4KGPGF.js.map} +1 -1
  132. package/dist/{chunk-QEGUI2Q2.js → chunk-H65OX263.js} +15 -15
  133. package/dist/{chunk-QEGUI2Q2.js.map → chunk-H65OX263.js.map} +1 -1
  134. package/dist/{chunk-46BMNWE6.js → chunk-H6YVT3BL.js} +2 -2
  135. package/dist/{chunk-46BMNWE6.js.map → chunk-H6YVT3BL.js.map} +1 -1
  136. package/dist/{chunk-TX2QQ7IX.mjs → chunk-HBN4A2N4.mjs} +3 -3
  137. package/dist/{chunk-TX2QQ7IX.mjs.map → chunk-HBN4A2N4.mjs.map} +1 -1
  138. package/dist/{chunk-AJQI3WTN.mjs → chunk-ILNCUSXW.mjs} +2 -2
  139. package/dist/{chunk-AJQI3WTN.mjs.map → chunk-ILNCUSXW.mjs.map} +1 -1
  140. package/dist/{chunk-RMMHWSPP.mjs → chunk-JNAXDFC4.mjs} +3 -3
  141. package/dist/{chunk-RMMHWSPP.mjs.map → chunk-JNAXDFC4.mjs.map} +1 -1
  142. package/dist/{chunk-TALEV3IH.mjs → chunk-JQ7M6CVL.mjs} +3 -3
  143. package/dist/{chunk-TALEV3IH.mjs.map → chunk-JQ7M6CVL.mjs.map} +1 -1
  144. package/dist/{chunk-2CMSWJWC.js → chunk-JTCQJKJE.js} +18 -18
  145. package/dist/{chunk-2CMSWJWC.js.map → chunk-JTCQJKJE.js.map} +1 -1
  146. package/dist/{chunk-7PPNXORV.mjs → chunk-JTF4DFUF.mjs} +25 -31
  147. package/dist/chunk-JTF4DFUF.mjs.map +1 -0
  148. package/dist/{chunk-MCJF2KJ6.js → chunk-KXGD4E7G.js} +5 -5
  149. package/dist/{chunk-MCJF2KJ6.js.map → chunk-KXGD4E7G.js.map} +1 -1
  150. package/dist/chunk-L4V6TKMJ.mjs +94 -0
  151. package/dist/chunk-L4V6TKMJ.mjs.map +1 -0
  152. package/dist/{chunk-W5NVW23S.js → chunk-L7ACQ6PC.js} +4 -4
  153. package/dist/{chunk-W5NVW23S.js.map → chunk-L7ACQ6PC.js.map} +1 -1
  154. package/dist/{chunk-WIZRCI6J.mjs → chunk-M5GY2AI3.mjs} +3 -3
  155. package/dist/{chunk-WIZRCI6J.mjs.map → chunk-M5GY2AI3.mjs.map} +1 -1
  156. package/dist/{chunk-HBI67P7Y.mjs → chunk-MW2M6O7A.mjs} +18 -14
  157. package/dist/chunk-MW2M6O7A.mjs.map +1 -0
  158. package/dist/{chunk-A3F5GRNJ.js → chunk-NOU3JQJK.js} +8 -8
  159. package/dist/{chunk-A3F5GRNJ.js.map → chunk-NOU3JQJK.js.map} +1 -1
  160. package/dist/{chunk-DYULWKDC.mjs → chunk-O2VJZOR2.mjs} +14 -33
  161. package/dist/chunk-O2VJZOR2.mjs.map +1 -0
  162. package/dist/{chunk-FF5N5D3D.js → chunk-OYOO2OO5.js} +8 -8
  163. package/dist/{chunk-FF5N5D3D.js.map → chunk-OYOO2OO5.js.map} +1 -1
  164. package/dist/chunk-P4TB4ROG.js +110 -0
  165. package/dist/chunk-P4TB4ROG.js.map +1 -0
  166. package/dist/{chunk-V6NOM7PJ.mjs → chunk-Q7347KP6.mjs} +3 -3
  167. package/dist/{chunk-V6NOM7PJ.mjs.map → chunk-Q7347KP6.mjs.map} +1 -1
  168. package/dist/chunk-QRBPT6Z6.mjs +6 -0
  169. package/dist/{chunk-WDBCXRTT.mjs.map → chunk-QRBPT6Z6.mjs.map} +1 -1
  170. package/dist/{chunk-G5HUI4BO.mjs → chunk-R2SXXFXZ.mjs} +3 -3
  171. package/dist/{chunk-G5HUI4BO.mjs.map → chunk-R2SXXFXZ.mjs.map} +1 -1
  172. package/dist/{chunk-PIPLBBDH.js → chunk-RCSTDJUH.js} +22 -41
  173. package/dist/chunk-RCSTDJUH.js.map +1 -0
  174. package/dist/{chunk-Z6S4MWSR.js → chunk-RNAGCAIB.js} +21 -17
  175. package/dist/chunk-RNAGCAIB.js.map +1 -0
  176. package/dist/{chunk-AEARU24Q.mjs → chunk-RVRN5U7W.mjs} +2 -2
  177. package/dist/{chunk-AEARU24Q.mjs.map → chunk-RVRN5U7W.mjs.map} +1 -1
  178. package/dist/{chunk-DRLHQQBH.mjs → chunk-TDJKGN5Q.mjs} +4 -4
  179. package/dist/{chunk-DRLHQQBH.mjs.map → chunk-TDJKGN5Q.mjs.map} +1 -1
  180. package/dist/{chunk-MNYM2XU4.js → chunk-TSZIACRC.js} +4 -4
  181. package/dist/{chunk-MNYM2XU4.js.map → chunk-TSZIACRC.js.map} +1 -1
  182. package/dist/{chunk-UZL2QU2V.mjs → chunk-UQ5YULFU.mjs} +4 -4
  183. package/dist/{chunk-UZL2QU2V.mjs.map → chunk-UQ5YULFU.mjs.map} +1 -1
  184. package/dist/{chunk-5TGAUWNO.mjs → chunk-V5THCFPG.mjs} +3 -3
  185. package/dist/{chunk-5TGAUWNO.mjs.map → chunk-V5THCFPG.mjs.map} +1 -1
  186. package/dist/{chunk-YNC5D3FT.js → chunk-VFGEY6FJ.js} +12 -12
  187. package/dist/{chunk-YNC5D3FT.js.map → chunk-VFGEY6FJ.js.map} +1 -1
  188. package/dist/{chunk-OFSA7LUH.mjs → chunk-XLPU3TEE.mjs} +4 -4
  189. package/dist/{chunk-OFSA7LUH.mjs.map → chunk-XLPU3TEE.mjs.map} +1 -1
  190. package/dist/{chunk-YYAFHIY7.js → chunk-YKUEFRZI.js} +14 -14
  191. package/dist/{chunk-YYAFHIY7.js.map → chunk-YKUEFRZI.js.map} +1 -1
  192. package/dist/{chunk-QFNSM77X.js → chunk-YYDZ2TYR.js} +3 -3
  193. package/dist/{chunk-QFNSM77X.js.map → chunk-YYDZ2TYR.js.map} +1 -1
  194. package/dist/cli/agent/checks.d.ts.map +1 -1
  195. package/dist/cli/api/{uptrade.d.ts → sonor.d.ts} +3 -2
  196. package/dist/cli/api/sonor.d.ts.map +1 -0
  197. package/dist/cli/commands/api-routes.d.ts.map +1 -1
  198. package/dist/cli/commands/config-regression.test.d.ts +2 -0
  199. package/dist/cli/commands/config-regression.test.d.ts.map +1 -0
  200. package/dist/cli/commands/faqs.d.ts.map +1 -1
  201. package/dist/cli/commands/geo.d.ts +4 -0
  202. package/dist/cli/commands/geo.d.ts.map +1 -1
  203. package/dist/cli/commands/geo.test.d.ts +2 -0
  204. package/dist/cli/commands/geo.test.d.ts.map +1 -0
  205. package/dist/cli/commands/images.d.ts.map +1 -1
  206. package/dist/cli/commands/locations.d.ts.map +1 -1
  207. package/dist/cli/commands/migrate.d.ts.map +1 -1
  208. package/dist/cli/commands/og.d.ts +10 -1
  209. package/dist/cli/commands/og.d.ts.map +1 -1
  210. package/dist/cli/commands/scaffold.d.ts +1 -2
  211. package/dist/cli/commands/scaffold.d.ts.map +1 -1
  212. package/dist/cli/commands/setup.d.ts.map +1 -1
  213. package/dist/cli/commands/sync.d.ts.map +1 -1
  214. package/dist/cli/config.d.ts +31 -0
  215. package/dist/cli/config.d.ts.map +1 -0
  216. package/dist/cli/config.test.d.ts +2 -0
  217. package/dist/cli/config.test.d.ts.map +1 -0
  218. package/dist/cli/generators/index.d.ts +5 -0
  219. package/dist/cli/generators/index.d.ts.map +1 -1
  220. package/dist/cli/generators/index.test.d.ts +2 -0
  221. package/dist/cli/generators/index.test.d.ts.map +1 -0
  222. package/dist/cli/index.js +717 -634
  223. package/dist/cli/index.js.map +1 -1
  224. package/dist/cli/index.mjs +708 -625
  225. package/dist/cli/index.mjs.map +1 -1
  226. package/dist/cli/migrator/index.d.ts +1 -0
  227. package/dist/cli/migrator/index.d.ts.map +1 -1
  228. package/dist/cli/state.d.ts +7 -0
  229. package/dist/cli/state.d.ts.map +1 -0
  230. package/dist/cli/state.test.d.ts +2 -0
  231. package/dist/cli/state.test.d.ts.map +1 -0
  232. package/dist/client/index.js +4 -4
  233. package/dist/client/index.mjs +3 -3
  234. package/dist/commerce/index.js +57 -57
  235. package/dist/commerce/index.mjs +6 -6
  236. package/dist/discover-FGTKWOL3.mjs +4 -0
  237. package/dist/{discover-BEJRYNFF.mjs.map → discover-FGTKWOL3.mjs.map} +1 -1
  238. package/dist/discover-NJZPWTDL.js +21 -0
  239. package/dist/{discover-WVDYDUJX.js.map → discover-NJZPWTDL.js.map} +1 -1
  240. package/dist/engage/EngageWidget.d.ts +3 -2
  241. package/dist/engage/EngageWidget.d.ts.map +1 -1
  242. package/dist/engage/index.js +11 -10
  243. package/dist/engage/index.js.map +1 -1
  244. package/dist/engage/index.mjs +8 -7
  245. package/dist/engage/index.mjs.map +1 -1
  246. package/dist/fleet/FleetHeartbeat.d.ts +3 -2
  247. package/dist/fleet/FleetHeartbeat.d.ts.map +1 -1
  248. package/dist/fleet/heartbeat.d.ts +3 -2
  249. package/dist/fleet/heartbeat.d.ts.map +1 -1
  250. package/dist/fleet/heartbeat.test.d.ts +2 -0
  251. package/dist/fleet/heartbeat.test.d.ts.map +1 -0
  252. package/dist/fleet/index.js +9 -8
  253. package/dist/fleet/index.mjs +5 -4
  254. package/dist/forms/index.js +16 -16
  255. package/dist/forms/index.mjs +9 -9
  256. package/dist/forms/server.js +10 -10
  257. package/dist/forms/server.mjs +8 -8
  258. package/dist/forms/static.js +7 -7
  259. package/dist/forms/static.mjs +6 -6
  260. package/dist/images/index.js +11 -11
  261. package/dist/images/index.mjs +4 -4
  262. package/dist/index.js +69 -69
  263. package/dist/index.mjs +11 -11
  264. package/dist/layout/SiteKitClientProviders.d.ts.map +1 -1
  265. package/dist/layout/client.d.ts.map +1 -1
  266. package/dist/layout/client.js +9 -8
  267. package/dist/layout/client.mjs +8 -7
  268. package/dist/layout/index.js +11 -10
  269. package/dist/layout/index.js.map +1 -1
  270. package/dist/layout/index.mjs +9 -8
  271. package/dist/layout/index.mjs.map +1 -1
  272. package/dist/layout/types.d.ts +2 -0
  273. package/dist/layout/types.d.ts.map +1 -1
  274. package/dist/llms/aiRobots.d.ts +4 -1
  275. package/dist/llms/aiRobots.d.ts.map +1 -1
  276. package/dist/llms/handlers.d.ts +20 -2
  277. package/dist/llms/handlers.d.ts.map +1 -1
  278. package/dist/llms/index.js +25 -18
  279. package/dist/llms/index.js.map +1 -1
  280. package/dist/llms/index.mjs +15 -8
  281. package/dist/llms/index.mjs.map +1 -1
  282. package/dist/llms/wiring.d.ts +81 -0
  283. package/dist/llms/wiring.d.ts.map +1 -0
  284. package/dist/llms/wiring.test.d.ts +2 -0
  285. package/dist/llms/wiring.test.d.ts.map +1 -0
  286. package/dist/maps/index.js +5 -5
  287. package/dist/maps/index.mjs +3 -3
  288. package/dist/og/wiring.d.ts +5 -1
  289. package/dist/og/wiring.d.ts.map +1 -1
  290. package/dist/proxy/index.d.ts +16 -11
  291. package/dist/proxy/index.d.ts.map +1 -1
  292. package/dist/proxy/index.js +3 -3
  293. package/dist/proxy/index.js.map +1 -1
  294. package/dist/proxy/index.mjs +1 -1
  295. package/dist/proxy/index.mjs.map +1 -1
  296. package/dist/redirects/index.d.ts +1 -1
  297. package/dist/redirects/index.js +8 -8
  298. package/dist/redirects/index.mjs +1 -1
  299. package/dist/redirects/not-found.d.ts +14 -29
  300. package/dist/redirects/not-found.d.ts.map +1 -1
  301. package/dist/redirects/not-found.js +12 -5
  302. package/dist/redirects/not-found.js.map +1 -1
  303. package/dist/redirects/not-found.mjs +8 -1
  304. package/dist/redirects/not-found.mjs.map +1 -1
  305. package/dist/robots/index.d.ts +5 -1
  306. package/dist/robots/index.d.ts.map +1 -1
  307. package/dist/robots/index.js +7 -1
  308. package/dist/robots/index.js.map +1 -1
  309. package/dist/robots/index.mjs +4 -1
  310. package/dist/robots/index.mjs.map +1 -1
  311. package/dist/robots/index.test.d.ts +2 -0
  312. package/dist/robots/index.test.d.ts.map +1 -0
  313. package/dist/robots/next-internals.d.ts +22 -0
  314. package/dist/robots/next-internals.d.ts.map +1 -0
  315. package/dist/search/index.js +4 -4
  316. package/dist/search/index.mjs +3 -3
  317. package/dist/seo/client.js +6 -6
  318. package/dist/seo/client.mjs +5 -5
  319. package/dist/seo/index.js +15 -15
  320. package/dist/seo/index.mjs +7 -7
  321. package/dist/seo/register-sitemap-cli.js +4 -4
  322. package/dist/seo/register-sitemap-cli.mjs +1 -1
  323. package/dist/seo/server.js +5 -5
  324. package/dist/seo/server.mjs +1 -1
  325. package/dist/server/index.js +3 -3
  326. package/dist/server/index.mjs +2 -2
  327. package/dist/shared/next-files.d.ts +35 -0
  328. package/dist/shared/next-files.d.ts.map +1 -0
  329. package/dist/shared/next-files.test.d.ts +2 -0
  330. package/dist/shared/next-files.test.d.ts.map +1 -0
  331. package/dist/shared/reporting-gate.d.ts +43 -0
  332. package/dist/shared/reporting-gate.d.ts.map +1 -0
  333. package/dist/shared/version.d.ts +1 -1
  334. package/dist/signal/index.js +11 -11
  335. package/dist/signal/index.mjs +2 -2
  336. package/dist/sitemap/discover.d.ts.map +1 -1
  337. package/dist/sitemap/index.d.ts +6 -1
  338. package/dist/sitemap/index.d.ts.map +1 -1
  339. package/dist/sitemap/index.js +5 -12
  340. package/dist/sitemap/index.js.map +1 -1
  341. package/dist/sitemap/index.mjs +4 -11
  342. package/dist/sitemap/index.mjs.map +1 -1
  343. package/dist/sync/AddToCalendar.d.ts +19 -0
  344. package/dist/sync/AddToCalendar.d.ts.map +1 -0
  345. package/dist/sync/BookingWidget.d.ts.map +1 -1
  346. package/dist/sync/add-to-calendar.test.d.ts +2 -0
  347. package/dist/sync/add-to-calendar.test.d.ts.map +1 -0
  348. package/dist/sync/api-errors.test.d.ts +2 -0
  349. package/dist/sync/api-errors.test.d.ts.map +1 -0
  350. package/dist/sync/api.d.ts.map +1 -1
  351. package/dist/sync/index.js +17 -17
  352. package/dist/sync/index.mjs +4 -4
  353. package/dist/sync/types.d.ts +14 -0
  354. package/dist/sync/types.d.ts.map +1 -1
  355. package/package.json +22 -24
  356. package/dist/AnalyticsProvider-KFXAH4GR.mjs +0 -11
  357. package/dist/AnalyticsProvider-WDDW3IJW.js +0 -32
  358. package/dist/ChatWidget-2ZYPYIMQ.js +0 -22
  359. package/dist/ChatWidget-FYCCLMQE.mjs +0 -13
  360. package/dist/EngageWidget-6HUZYOY7.mjs +0 -11
  361. package/dist/EngageWidget-MYQTBBW6.js +0 -20
  362. package/dist/ManagedForm-JWEXJEXK.js +0 -23
  363. package/dist/ManagedForm-OA3MNGXT.mjs +0 -14
  364. package/dist/SitemapSync-2PTDBH5E.mjs +0 -9
  365. package/dist/SitemapSync-3SFAI546.js +0 -18
  366. package/dist/chunk-746RKQHA.js.map +0 -1
  367. package/dist/chunk-7PPNXORV.mjs.map +0 -1
  368. package/dist/chunk-DYULWKDC.mjs.map +0 -1
  369. package/dist/chunk-EEQYKMGH.mjs.map +0 -1
  370. package/dist/chunk-HBI67P7Y.mjs.map +0 -1
  371. package/dist/chunk-KAUUGRYB.js.map +0 -1
  372. package/dist/chunk-LOS5D6B3.js +0 -72
  373. package/dist/chunk-LOS5D6B3.js.map +0 -1
  374. package/dist/chunk-NVSWTDWU.mjs +0 -25
  375. package/dist/chunk-NVSWTDWU.mjs.map +0 -1
  376. package/dist/chunk-OL2QBWAU.js +0 -29
  377. package/dist/chunk-OL2QBWAU.js.map +0 -1
  378. package/dist/chunk-PIPLBBDH.js.map +0 -1
  379. package/dist/chunk-RZUZMUTN.mjs.map +0 -1
  380. package/dist/chunk-S6FEC6UT.mjs.map +0 -1
  381. package/dist/chunk-SQVYLIIN.js.map +0 -1
  382. package/dist/chunk-SUZ3ZLB2.js +0 -8
  383. package/dist/chunk-UNPEMSLK.js.map +0 -1
  384. package/dist/chunk-VAS3LH5W.js.map +0 -1
  385. package/dist/chunk-WDBCXRTT.mjs +0 -6
  386. package/dist/chunk-XIJ4F6IE.mjs +0 -63
  387. package/dist/chunk-XIJ4F6IE.mjs.map +0 -1
  388. package/dist/chunk-XQYC4KMH.mjs.map +0 -1
  389. package/dist/chunk-Z6S4MWSR.js.map +0 -1
  390. package/dist/cli/api/uptrade.d.ts.map +0 -1
  391. package/dist/discover-BEJRYNFF.mjs +0 -4
  392. package/dist/discover-WVDYDUJX.js +0 -21
@@ -1,5 +1,5 @@
1
1
  import { resolveSiteHost } from './chunk-GZJE23Y5.mjs';
2
- import { configureSiteCredential, currentCredential } from './chunk-4XGACM7D.mjs';
2
+ import { configureSiteCredential, currentCredential } from './chunk-ABZGEHTC.mjs';
3
3
 
4
4
  // src/shared/publishCredential.ts
5
5
  function publishSiteCredential({
@@ -19,5 +19,5 @@ function publishSiteCredential({
19
19
  }
20
20
 
21
21
  export { publishSiteCredential };
22
- //# sourceMappingURL=chunk-5TGAUWNO.mjs.map
23
- //# sourceMappingURL=chunk-5TGAUWNO.mjs.map
22
+ //# sourceMappingURL=chunk-V5THCFPG.mjs.map
23
+ //# sourceMappingURL=chunk-V5THCFPG.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared/publishCredential.ts"],"names":[],"mappings":";;;;AAkEO,SAAS,qBAAA,CAAsB;AAAA,EACpC,MAAA;AAAA,EACA,MAAA,GAAS,sBAAA;AAAA,EACT,IAAA;AAAA,EACA,KAAA,GAAQ,KAAA;AAAA,EACR;AACF,CAAA,EAAuC;AACrC,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAKnC,EAAA,uBAAA,CAAwB,EAAE,UAAA,EAAY,MAAA,EAAQ,MAAA,EAAQ,CAAA;AACrD,EAAC,OAAe,oBAAA,GAAuB,MAAA;AACvC,EAAC,MAAA,CAAe,oBAAA,GAAuB,iBAAA,CAAkB,MAAM,CAAA;AAC/D,EAAC,OAAe,kBAAA,GAAqB,KAAA;AACrC,EAAC,MAAA,CAAe,iBAAA,GAAoB,IAAA,IAAQ,eAAA,EAAgB;AAG7D,EAAA,IAAI,cAAA,EAAiB,MAAA,CAAe,uBAAA,GAA0B,cAAA;AAChE","file":"chunk-5TGAUWNO.mjs","sourcesContent":["/**\n * @sonordev/site-kit shared — Client credential + window-global publishing\n *\n * SINGLE SOURCE OF TRUTH for seeding the browser-side token manager and the\n * `window.__SITE_KIT_*` globals that every client module reads. Used by:\n *\n * - `SiteKitClientProviders` (core `SiteKitLayout`)\n * - `SiteKitCredential` (`@sonordev/site-kit/client`) — the public component\n * for layouts that are NOT core `SiteKitLayout`, e.g.\n * `@sonordev/agency-site-kit`'s `AgencySiteKitLayout`.\n *\n * Do not re-fork this. Before it existed, agency sites hand-rolled their own\n * \"set the globals on mount\" component (upforge's `UptradeSiteKitInit`), and\n * because those copies had no access to the token manager they published the\n * RAW `sonor_` key into the client bundle — the exact exposure the mint exists\n * to prevent. Any layout that puts a credential on `window` goes through here.\n *\n * Client-safe: no `server-only` guard, SSR-safe (every write is window-gated).\n * The minting half is server-only and lives in `../server/mint-site-token`.\n */\n// Leaf modules, NOT '../sites/contract' — see sites/normalize.ts. Importing the\n// full contract here shipped its JSON schema to every browser that loads a\n// credential-publishing entry.\nimport { resolveSiteHost } from '../sites/resolve'\nimport { configureSiteCredential, currentCredential } from './siteToken'\n\n/**\n * Re-exported so the client-side callers below and every existing importer keep\n * a single name for this. The implementation lives in `../sites/resolve` — the\n * ONE resolver shared by the browser (this file) and the build-time sitemap /\n * llms.txt path, so both tag the same host.\n */\nexport { resolveSiteHost }\n\nexport interface PublishSiteCredentialOptions {\n /**\n * The credential the layout minted server-side. In 3.2+ this is a short-lived\n * `st1.` token that `sonorFetch` refreshes transparently. A raw `sonor_` key\n * still works (2.x kit, or the mint-failed fallback) but should never be\n * routed here from a client component — it would ship the secret to the\n * browser.\n */\n apiKey?: string\n apiUrl?: string\n /** Pre-resolved sub-site host. Omit to resolve via `resolveSiteHost`. */\n site?: string\n debug?: boolean\n /**\n * Referrer-restricted Google Maps BROWSER key for client map components.\n * Resolved server-side by SiteKitLayout (NEXT_PUBLIC_GOOGLE_MAPS_API_KEY /\n * GOOGLE_MAPS_BROWSER_KEY) because maps/api.ts runs client-side, where a bare\n * process.env read is dead code unless the app's bundler happens to inline it.\n * Never route a server secret here.\n */\n mapsBrowserKey?: string\n}\n\n/**\n * Seed the token manager and publish the `window.__SITE_KIT_*` globals.\n *\n * Called during RENDER, not in an effect: client modules read these globals in\n * their own mount effects, and effects run child-first, so an effect-based\n * publish would land after the modules that need it.\n *\n * No-op on the server.\n */\nexport function publishSiteCredential({\n apiKey,\n apiUrl = 'https://api.sonor.io',\n site,\n debug = false,\n mapsBrowserKey,\n}: PublishSiteCredentialOptions): void {\n if (typeof window === 'undefined') return\n\n // Seed the client token manager. The window global is set to the freshest\n // token held — a prior page this session may already have refreshed past the\n // seed the layout injected. In raw-key mode this is a passthrough.\n configureSiteCredential({ credential: apiKey, apiUrl })\n ;(window as any).__SITE_KIT_API_URL__ = apiUrl\n ;(window as any).__SITE_KIT_API_KEY__ = currentCredential(apiKey)\n ;(window as any).__SITE_KIT_DEBUG__ = debug\n ;(window as any).__SITE_KIT_SITE__ = site ?? resolveSiteHost()\n // maps/api.ts falls back to this global when the Sonor platform hasn't\n // provisioned a browser key. Don't clobber a value another layout already set.\n if (mapsBrowserKey) (window as any).__GOOGLE_MAPS_API_KEY__ = mapsBrowserKey\n}\n"]}
1
+ {"version":3,"sources":["../src/shared/publishCredential.ts"],"names":[],"mappings":";;;;AAkEO,SAAS,qBAAA,CAAsB;AAAA,EACpC,MAAA;AAAA,EACA,MAAA,GAAS,sBAAA;AAAA,EACT,IAAA;AAAA,EACA,KAAA,GAAQ,KAAA;AAAA,EACR;AACF,CAAA,EAAuC;AACrC,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAKnC,EAAA,uBAAA,CAAwB,EAAE,UAAA,EAAY,MAAA,EAAQ,MAAA,EAAQ,CAAA;AACrD,EAAC,OAAe,oBAAA,GAAuB,MAAA;AACvC,EAAC,MAAA,CAAe,oBAAA,GAAuB,iBAAA,CAAkB,MAAM,CAAA;AAC/D,EAAC,OAAe,kBAAA,GAAqB,KAAA;AACrC,EAAC,MAAA,CAAe,iBAAA,GAAoB,IAAA,IAAQ,eAAA,EAAgB;AAG7D,EAAA,IAAI,cAAA,EAAiB,MAAA,CAAe,uBAAA,GAA0B,cAAA;AAChE","file":"chunk-V5THCFPG.mjs","sourcesContent":["/**\n * @sonordev/site-kit shared — Client credential + window-global publishing\n *\n * SINGLE SOURCE OF TRUTH for seeding the browser-side token manager and the\n * `window.__SITE_KIT_*` globals that every client module reads. Used by:\n *\n * - `SiteKitClientProviders` (core `SiteKitLayout`)\n * - `SiteKitCredential` (`@sonordev/site-kit/client`) — the public component\n * for layouts that are NOT core `SiteKitLayout`, e.g.\n * `@sonordev/agency-site-kit`'s `AgencySiteKitLayout`.\n *\n * Do not re-fork this. Before it existed, agency sites hand-rolled their own\n * \"set the globals on mount\" component (upforge's `UptradeSiteKitInit`), and\n * because those copies had no access to the token manager they published the\n * RAW `sonor_` key into the client bundle — the exact exposure the mint exists\n * to prevent. Any layout that puts a credential on `window` goes through here.\n *\n * Client-safe: no `server-only` guard, SSR-safe (every write is window-gated).\n * The minting half is server-only and lives in `../server/mint-site-token`.\n */\n// Leaf modules, NOT '../sites/contract' — see sites/normalize.ts. Importing the\n// full contract here shipped its JSON schema to every browser that loads a\n// credential-publishing entry.\nimport { resolveSiteHost } from '../sites/resolve'\nimport { configureSiteCredential, currentCredential } from './siteToken'\n\n/**\n * Re-exported so the client-side callers below and every existing importer keep\n * a single name for this. The implementation lives in `../sites/resolve` — the\n * ONE resolver shared by the browser (this file) and the build-time sitemap /\n * llms.txt path, so both tag the same host.\n */\nexport { resolveSiteHost }\n\nexport interface PublishSiteCredentialOptions {\n /**\n * The credential the layout minted server-side. In 3.2+ this is a short-lived\n * `st1.` token that `sonorFetch` refreshes transparently. A raw `sonor_` key\n * still works (2.x kit, or the mint-failed fallback) but should never be\n * routed here from a client component — it would ship the secret to the\n * browser.\n */\n apiKey?: string\n apiUrl?: string\n /** Pre-resolved sub-site host. Omit to resolve via `resolveSiteHost`. */\n site?: string\n debug?: boolean\n /**\n * Referrer-restricted Google Maps BROWSER key for client map components.\n * Resolved server-side by SiteKitLayout (NEXT_PUBLIC_GOOGLE_MAPS_API_KEY /\n * GOOGLE_MAPS_BROWSER_KEY) because maps/api.ts runs client-side, where a bare\n * process.env read is dead code unless the app's bundler happens to inline it.\n * Never route a server secret here.\n */\n mapsBrowserKey?: string\n}\n\n/**\n * Seed the token manager and publish the `window.__SITE_KIT_*` globals.\n *\n * Called during RENDER, not in an effect: client modules read these globals in\n * their own mount effects, and effects run child-first, so an effect-based\n * publish would land after the modules that need it.\n *\n * No-op on the server.\n */\nexport function publishSiteCredential({\n apiKey,\n apiUrl = 'https://api.sonor.io',\n site,\n debug = false,\n mapsBrowserKey,\n}: PublishSiteCredentialOptions): void {\n if (typeof window === 'undefined') return\n\n // Seed the client token manager. The window global is set to the freshest\n // token held — a prior page this session may already have refreshed past the\n // seed the layout injected. In raw-key mode this is a passthrough.\n configureSiteCredential({ credential: apiKey, apiUrl })\n ;(window as any).__SITE_KIT_API_URL__ = apiUrl\n ;(window as any).__SITE_KIT_API_KEY__ = currentCredential(apiKey)\n ;(window as any).__SITE_KIT_DEBUG__ = debug\n ;(window as any).__SITE_KIT_SITE__ = site ?? resolveSiteHost()\n // maps/api.ts falls back to this global when the Sonor platform hasn't\n // provisioned a browser key. Don't clobber a value another layout already set.\n if (mapsBrowserKey) (window as any).__GOOGLE_MAPS_API_KEY__ = mapsBrowserKey\n}\n"]}
@@ -1,9 +1,9 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunkBNOQXDPJ_js = require('./chunk-BNOQXDPJ.js');
4
+ var chunkFEWWGEQF_js = require('./chunk-FEWWGEQF.js');
5
5
  var chunkVJMPIRSD_js = require('./chunk-VJMPIRSD.js');
6
- var chunkQEGUI2Q2_js = require('./chunk-QEGUI2Q2.js');
6
+ var chunkH65OX263_js = require('./chunk-H65OX263.js');
7
7
  var react = require('react');
8
8
 
9
9
  // src/forms/tracking-session.ts
@@ -75,7 +75,7 @@ function useFormTracking({
75
75
  return null;
76
76
  }
77
77
  try {
78
- const response = await chunkQEGUI2Q2_js.sonorFetch(
78
+ const response = await chunkH65OX263_js.sonorFetch(
79
79
  `${apiUrl}/api/public/forms/analytics/start`,
80
80
  {
81
81
  method: "POST",
@@ -118,7 +118,7 @@ function useFormTracking({
118
118
  const currentStepTime = Math.floor((now - stepStartTimeRef.current) / 1e3);
119
119
  stepTimesRef.current[currentStepRef.current] = currentStepTime;
120
120
  session.abandonSent = true;
121
- chunkQEGUI2Q2_js.sonorBeacon(
121
+ chunkH65OX263_js.sonorBeacon(
122
122
  `${apiUrl}/api/public/forms/analytics/abandon`,
123
123
  {
124
124
  analyticsId: analyticsIdRef.current,
@@ -164,7 +164,7 @@ function useFormTracking({
164
164
  const analyticsId = await resolveAnalyticsId();
165
165
  if (!analyticsId) return;
166
166
  try {
167
- const response = await chunkQEGUI2Q2_js.sonorFetch(
167
+ const response = await chunkH65OX263_js.sonorFetch(
168
168
  `${apiUrl}/api/public/forms/analytics/step`,
169
169
  {
170
170
  method: "POST",
@@ -202,7 +202,7 @@ function useFormTracking({
202
202
  const session = sessionRef.current;
203
203
  if (session) session.abandonSent = true;
204
204
  try {
205
- const response = await chunkQEGUI2Q2_js.sonorFetch(
205
+ const response = await chunkH65OX263_js.sonorFetch(
206
206
  `${apiUrl}/api/public/forms/analytics/complete`,
207
207
  {
208
208
  method: "POST",
@@ -249,7 +249,7 @@ function useForm(formIdOrSlug, options = {}) {
249
249
  } = options;
250
250
  const projectId = optionsProjectId || (typeof window !== "undefined" ? window.__SITE_KIT_PROJECT_ID__ : void 0);
251
251
  const [form, setForm] = react.useState(
252
- () => initialForm ? chunkBNOQXDPJ_js.normalizeFormConfig(initialForm) : null
252
+ () => initialForm ? chunkFEWWGEQF_js.normalizeFormConfig(initialForm) : null
253
253
  );
254
254
  const [isLoading, setIsLoading] = react.useState(!initialForm);
255
255
  const [fetchError, setFetchError] = react.useState(null);
@@ -310,7 +310,7 @@ function useForm(formIdOrSlug, options = {}) {
310
310
  formIdOrSlug
311
311
  })
312
312
  };
313
- const response = await chunkQEGUI2Q2_js.sonorFetch(url, init, { apiKey, retries: 3, timeoutMs: 15e3 });
313
+ const response = await chunkH65OX263_js.sonorFetch(url, init, { apiKey, retries: 3, timeoutMs: 15e3 });
314
314
  if (!response.ok) {
315
315
  throw new Error(`Failed to fetch form: ${response.statusText}`);
316
316
  }
@@ -320,7 +320,7 @@ function useForm(formIdOrSlug, options = {}) {
320
320
  ;
321
321
  window.__SITE_KIT_RECAPTCHA_SITE_KEY__ = data.recaptcha_site_key;
322
322
  }
323
- setForm(chunkBNOQXDPJ_js.normalizeFormConfig(data));
323
+ setForm(chunkFEWWGEQF_js.normalizeFormConfig(data));
324
324
  const defaults = {};
325
325
  for (const field of data.fields || []) {
326
326
  if (field.default_value !== void 0 && field.default_value !== null) {
@@ -489,7 +489,7 @@ function useForm(formIdOrSlug, options = {}) {
489
489
  setIsSubmitting(true);
490
490
  setSubmitError(null);
491
491
  try {
492
- const data = await chunkBNOQXDPJ_js.submitForm({
492
+ const data = await chunkFEWWGEQF_js.submitForm({
493
493
  config: form,
494
494
  values: buildVisibleValues(),
495
495
  honeypotValue: "",
@@ -553,5 +553,5 @@ function useForm(formIdOrSlug, options = {}) {
553
553
 
554
554
  exports.useForm = useForm;
555
555
  exports.useFormTracking = useFormTracking;
556
- //# sourceMappingURL=chunk-YNC5D3FT.js.map
557
- //# sourceMappingURL=chunk-YNC5D3FT.js.map
556
+ //# sourceMappingURL=chunk-VFGEY6FJ.js.map
557
+ //# sourceMappingURL=chunk-VFGEY6FJ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/forms/tracking-session.ts","../src/forms/useFormTracking.ts","../src/forms/useForm.ts"],"names":["uuid","useRef","useEffect","sonorFetch","sonorBeacon","useCallback","useState","normalizeFormConfig","useMemo","submitForm"],"mappings":"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","file":"chunk-YNC5D3FT.js","sourcesContent":["/**\n * @sonordev/site-kit/forms - Form tracking session registry\n *\n * SINGLE SOURCE OF TRUTH for a form's `form_analytics` row: one\n * `/analytics/start` per formId per page load, shared by every tracker\n * mounted for that form. Do NOT re-fork start logic into a caller.\n *\n * The lesson from the double-count bug fixed in 4.2.2: `ManagedForm` called\n * `useForm` (which tracks) AND rendered `FormClient` (which also tracks). Two\n * independent hook instances each minted their own session uuid and POSTed\n * their own start, so a single page load wrote TWO `form_analytics` rows —\n * present in every release up to and including 4.2.1. That halved every reported\n * start -> submission conversion rate, and because each instance registered its\n * own `beforeunload` it wrote two abandonment rows per visit as well. The\n * signature in the data was unmistakable: paired rows where exactly one ever\n * completed (only FormClient's instance owns submit) but BOTH abandoned.\n *\n * Trackers SHARE the resulting analytics row id, so whichever component owns\n * submission can still complete the row no matter which one opened it. That\n * sharing is what makes this safe as a guard rather than a gamble on which\n * instance mounts first.\n */\n\n// Single source of truth for v4 UUIDs — crypto.randomUUID throws on plain HTTP\n// and older Safari. Do NOT re-fork ID generation here.\nimport { uuid } from '../shared/uuid'\n\nexport interface TrackingSession {\n /** The uuid reported to the API as this form visit's session. */\n readonly sessionId: string\n readonly startedAt: number\n /** Resolves to the analytics row id, or null when the start POST failed. */\n readonly analyticsId: Promise<string | null>\n /**\n * Abandonment belongs to the ROW, not to a tracker. Every mounted tracker\n * registers its own `beforeunload`; only the first beacon may fire, or one\n * visit reports abandonment as many times as it has trackers.\n */\n abandonSent: boolean\n /** @internal */\n refCount: number\n /** @internal */\n releaseTimer: ReturnType<typeof setTimeout> | null\n}\n\n/**\n * How long a session outlives its last unmount before a fresh start POST is\n * allowed. Covers React StrictMode's dev-mode mount -> unmount -> mount and the\n * FormEnhancer static -> interactive swap; both remount a form within the same\n * page load and would otherwise mint a second row for one visit.\n */\nexport const SESSION_GRACE_MS = 2000\n\nconst activeSessions = new Map<string, TrackingSession>()\n\n/**\n * Join the tracking session for `formId`, opening one if none is live.\n *\n * `start` is invoked at most once per session and must resolve to the analytics\n * row id (or null when the POST failed). Callers MUST pair this with\n * {@link releaseTrackingSession} on unmount.\n */\nexport function acquireTrackingSession(\n formId: string,\n start: (sessionId: string) => Promise<string | null>,\n): TrackingSession {\n const existing = activeSessions.get(formId)\n if (existing) {\n // A tracker rejoined inside the grace window — cancel the pending teardown\n // rather than letting it delete a session that is live again.\n if (existing.releaseTimer) {\n clearTimeout(existing.releaseTimer)\n existing.releaseTimer = null\n }\n existing.refCount++\n return existing\n }\n\n const sessionId = uuid()\n const session: TrackingSession = {\n sessionId,\n startedAt: Date.now(),\n // Assigned below — declared here so the object shape is complete first.\n analyticsId: null as unknown as Promise<string | null>,\n abandonSent: false,\n refCount: 1,\n releaseTimer: null,\n }\n\n // Register BEFORE invoking `start`, so a tracker mounting later in the same\n // commit joins this session instead of racing it to a second row. React runs\n // effects synchronously within a commit, so this check-then-set cannot be\n // interleaved — but only if nothing awaits in between.\n activeSessions.set(formId, session)\n ;(session as { analyticsId: Promise<string | null> }).analyticsId = start(sessionId)\n\n return session\n}\n\n/**\n * Leave the tracking session. The last tracker out schedules teardown after\n * {@link SESSION_GRACE_MS} rather than deleting immediately, so a remount\n * within the same page load reuses the row instead of opening another.\n */\nexport function releaseTrackingSession(formId: string, session: TrackingSession): void {\n session.refCount--\n if (session.refCount > 0) return\n if (session.releaseTimer) return\n\n session.releaseTimer = setTimeout(() => {\n session.releaseTimer = null\n // Re-check both conditions: a tracker may have rejoined, or the entry may\n // already have been replaced by a later session for the same form.\n if (session.refCount <= 0 && activeSessions.get(formId) === session) {\n activeSessions.delete(formId)\n }\n }, SESSION_GRACE_MS)\n\n // Never hold the process open for a teardown timer (SSR/test environments).\n ;(session.releaseTimer as { unref?: () => void })?.unref?.()\n}\n\n/** Test-only: drop all live sessions so cases start from a clean registry. */\nexport function __resetTrackingSessions(): void {\n for (const session of activeSessions.values()) {\n if (session.releaseTimer) clearTimeout(session.releaseTimer)\n }\n activeSessions.clear()\n}\n","/**\n * @sonordev/site-kit/forms - Form Tracking Hook\n *\n * Tracks form analytics including step progress and abandonment.\n *\n * The `form_analytics` row is owned by the shared session registry, not by this\n * hook — see `tracking-session.ts`. Every tracker mounted for the same form\n * joins ONE session and shares its analytics row id, so composing two trackers\n * over a single form (as ManagedForm once did) can no longer double-count.\n */\n\n'use client'\n\nimport { useEffect, useRef, useCallback } from 'react'\nimport { sonorFetch, sonorBeacon } from '../shared/sonorFetch'\nimport {\n acquireTrackingSession,\n releaseTrackingSession,\n type TrackingSession,\n} from './tracking-session'\n\ninterface UseFormTrackingOptions {\n formId: string\n totalSteps: number\n enabled?: boolean\n debug?: boolean\n}\n\ninterface FormTrackingReturn {\n trackStepChange: (step: number) => void\n trackComplete: () => void\n sessionId: string\n}\n\nexport function useFormTracking({\n formId,\n totalSteps,\n enabled = true,\n debug = false,\n}: UseFormTrackingOptions): FormTrackingReturn {\n const sessionRef = useRef<TrackingSession | null>(null)\n const sessionIdRef = useRef<string>('')\n const startTimeRef = useRef<number>(0)\n const stepStartTimeRef = useRef<number>(0)\n const stepTimesRef = useRef<Record<number, number>>({})\n const currentStepRef = useRef<number>(1)\n const maxStepRef = useRef<number>(1)\n const analyticsIdRef = useRef<string | null>(null)\n\n // Initialize tracking\n useEffect(() => {\n if (!enabled) return\n if (!formId) {\n if (debug) console.warn('[Forms] Tracking skipped: formId is empty')\n return\n }\n\n // Record form start. Invoked at most once per session by the registry —\n // a second tracker for this form joins the existing session instead.\n const startTracking = async (sessionId: string): Promise<string | null> => {\n const apiUrl = (window as any).__SITE_KIT_API_URL__\n const apiKey = (window as any).__SITE_KIT_API_KEY__\n\n if (!apiUrl || !apiKey) {\n if (debug) console.error('[Forms] Missing API URL or API key')\n return null\n }\n\n try {\n const response = await sonorFetch(\n `${apiUrl}/api/public/forms/analytics/start`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n formId,\n sessionId,\n deviceType: getDeviceType(),\n }),\n },\n { apiKey, retries: 0 },\n )\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n }\n\n const data = await response.json()\n if (debug) console.log('[Forms] Started tracking:', data.id)\n return data.id ?? null\n } catch (error) {\n if (debug) console.error('[Forms] Error starting tracking:', error)\n return null\n }\n }\n\n const session = acquireTrackingSession(formId, startTracking)\n sessionRef.current = session\n sessionIdRef.current = session.sessionId\n startTimeRef.current = session.startedAt\n stepStartTimeRef.current = Date.now()\n\n let joined = true\n void session.analyticsId.then((id) => {\n if (joined) analyticsIdRef.current = id\n })\n\n // Handle abandonment on page leave\n const handleBeforeUnload = () => {\n if (!analyticsIdRef.current) return\n // One abandonment per ROW. Without this, every tracker sharing the\n // session reports the same visit as abandoned.\n if (session.abandonSent) return\n\n const apiUrl = (window as any).__SITE_KIT_API_URL__\n const apiKey = (window as any).__SITE_KIT_API_KEY__\n\n if (!apiUrl || !apiKey) return\n\n const now = Date.now()\n const currentStepTime = Math.floor((now - stepStartTimeRef.current) / 1000)\n stepTimesRef.current[currentStepRef.current] = currentStepTime\n\n session.abandonSent = true\n\n // Fire-and-forget via sonorBeacon: keepalive fetch keeps the credential in\n // the x-api-key header (raw sendBeacon can't set headers), so abandonment\n // authenticates on 3.2+ token sites and uses the freshest minted token.\n sonorBeacon(\n `${apiUrl}/api/public/forms/analytics/abandon`,\n {\n analyticsId: analyticsIdRef.current,\n step: currentStepRef.current,\n maxStep: maxStepRef.current,\n stepTimes: stepTimesRef.current,\n totalTimeSeconds: Math.floor((now - startTimeRef.current) / 1000),\n },\n apiKey,\n )\n\n if (debug) console.log('[Forms] Abandonment tracked')\n }\n\n window.addEventListener('beforeunload', handleBeforeUnload)\n\n return () => {\n joined = false\n window.removeEventListener('beforeunload', handleBeforeUnload)\n releaseTrackingSession(formId, session)\n sessionRef.current = null\n }\n }, [formId, enabled, debug])\n\n /**\n * The analytics row id, waiting on the start POST if it is still in flight.\n * A fast submit used to race the start and silently drop the completion,\n * which understated conversions the same way double-starting overstated them.\n */\n const resolveAnalyticsId = useCallback(async (): Promise<string | null> => {\n if (analyticsIdRef.current) return analyticsIdRef.current\n const session = sessionRef.current\n if (!session) return null\n const id = await session.analyticsId\n if (id) analyticsIdRef.current = id\n return id\n }, [])\n\n // Track step changes\n const trackStepChange = useCallback(async (step: number) => {\n if (!enabled) return\n\n const apiUrl = (window as any).__SITE_KIT_API_URL__\n const apiKey = (window as any).__SITE_KIT_API_KEY__\n\n if (!apiUrl || !apiKey) {\n if (debug) console.error('[Forms] Missing API URL or API key')\n return\n }\n\n const now = Date.now()\n\n // Record time spent on previous step\n const prevStepTime = Math.floor((now - stepStartTimeRef.current) / 1000)\n stepTimesRef.current[currentStepRef.current] = prevStepTime\n\n // Update refs\n currentStepRef.current = step\n maxStepRef.current = Math.max(maxStepRef.current, step)\n stepStartTimeRef.current = now\n\n const analyticsId = await resolveAnalyticsId()\n if (!analyticsId) return\n\n // Update database\n try {\n const response = await sonorFetch(\n `${apiUrl}/api/public/forms/analytics/step`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n analyticsId,\n step,\n maxStep: maxStepRef.current,\n stepTimes: stepTimesRef.current,\n }),\n },\n { apiKey, retries: 0 },\n )\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n }\n\n if (debug) console.log('[Forms] Step changed to:', step)\n } catch (error) {\n if (debug) console.error('[Forms] Error updating step:', error)\n }\n }, [enabled, debug, resolveAnalyticsId])\n\n // Track completion\n const trackComplete = useCallback(async () => {\n if (!enabled) return\n\n const apiUrl = (window as any).__SITE_KIT_API_URL__\n const apiKey = (window as any).__SITE_KIT_API_KEY__\n\n if (!apiUrl || !apiKey) {\n if (debug) console.error('[Forms] Missing API URL or API key')\n return\n }\n\n const now = Date.now()\n\n // Record time for final step\n const finalStepTime = Math.floor((now - stepStartTimeRef.current) / 1000)\n stepTimesRef.current[currentStepRef.current] = finalStepTime\n\n const analyticsId = await resolveAnalyticsId()\n if (!analyticsId) return\n\n // A completed row must never also be reported as abandoned when the\n // success screen is later closed.\n const session = sessionRef.current\n if (session) session.abandonSent = true\n\n try {\n // Complete form analytics tracking\n // Note: A database trigger will automatically log this as a conversion\n // in analytics_conversions when completed_at is set\n const response = await sonorFetch(\n `${apiUrl}/api/public/forms/analytics/complete`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n analyticsId,\n totalSteps,\n stepTimes: stepTimesRef.current,\n totalTimeSeconds: Math.floor((now - startTimeRef.current) / 1000),\n }),\n },\n { apiKey, retries: 0 },\n )\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n }\n\n if (debug) console.log('[Forms] Form completed')\n\n // No client-side conversion POST: the Sonor API records the canonical\n // form_submission conversion (analytics_conversions + session flag)\n // when the submission lands at /api/public/forms/submit. The old POST\n // here sent this hook's form-tracking uuid as `sessionId`, which\n // matched no analytics session and double-counted the conversion.\n } catch (error) {\n if (debug) console.error('[Forms] Error completing tracking:', error)\n }\n }, [enabled, totalSteps, formId, debug, resolveAnalyticsId])\n\n return {\n trackStepChange,\n trackComplete,\n sessionId: sessionIdRef.current,\n }\n}\n\n// Helper\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","/**\n * @sonordev/site-kit/forms - useForm Hook\n * \n * Headless hook for complete control over form rendering.\n * Fetches form config from API, handles validation, state, and submission.\n * \n * @example\n * ```tsx\n * const { form, fields, values, errors, setFieldValue, submit, isSubmitting } = useForm('contact-form')\n * \n * return (\n * <form onSubmit={(e) => { e.preventDefault(); submit() }}>\n * {fields.map(field => (\n * <MyCustomInput\n * key={field.slug}\n * label={field.label}\n * value={values[field.slug]}\n * error={errors[field.slug]}\n * onChange={(val) => setFieldValue(field.slug, val)}\n * />\n * ))}\n * <button type=\"submit\" disabled={isSubmitting}>Submit</button>\n * </form>\n * )\n * ```\n */\n\n'use client'\n\nimport { useState, useEffect, useCallback, useMemo, useRef } from 'react'\nimport { useFormTracking } from './useFormTracking'\n// Shared with StaticForm — the server shell and this client path MUST agree\n// on field order, step count and success copy or the enhancement swap jumps.\nimport { normalizeFormConfig } from './normalize-config'\nimport { sonorFetch } from '../shared/sonorFetch'\nimport { submitForm } from './submitForm'\nimport type { \n ManagedFormConfig, \n FormField, \n FormSubmission \n} from './types'\nimport { DEFAULT_FORM_SUCCESS_MESSAGE } from './defaultSuccessMessage'\n\n// ============================================\n// Types\n// ============================================\n\nexport interface UseFormOptions {\n /** Project ID (defaults to SiteKitLayout config) */\n projectId?: string\n /** Callback when form submits successfully */\n onSuccess?: (submission: FormSubmission) => void\n /** Callback when submission fails */\n onError?: (error: Error) => void\n /** Initial values to prefill */\n initialValues?: Record<string, unknown>\n /** Auto-redirect after success (override form config) */\n redirectUrl?: string | false\n /**\n * Server-fetched form payload (from `getFormConfig` in\n * `@sonordev/site-kit/forms/server`). When provided, the fields render on\n * the first client render — no config fetch, no \"Loading form...\" flash.\n * Accepts the RAW API payload; normalized here exactly like a client fetch.\n */\n initialForm?: Record<string, unknown> | null\n /**\n * Report this form's funnel to Sonor (`form_analytics`). Defaults to true —\n * a headless `useForm` consumer renders and submits the form itself, so this\n * hook is the only thing that can track it.\n *\n * `ManagedForm` passes FALSE: it delegates rendering, step navigation and\n * submission to `FormClient`, which tracks that path. Exactly one component\n * may own a form's tracking — two owners was the double-count bug fixed\n * in 4.2.2.\n */\n trackAnalytics?: boolean\n}\n\n\nexport interface UseFormReturn {\n /** Form configuration (null while loading) */\n form: ManagedFormConfig | null\n /** Loading state */\n isLoading: boolean\n /** Error fetching form */\n fetchError: Error | null\n /** Human-readable error from the last submit attempt (null when none) */\n submitError: string | null\n\n /** All form fields */\n allFields: FormField[]\n /** Fields for current step (multi-step) or all fields (single step) */\n fields: FormField[]\n /** Visible fields only (respecting conditional logic) */\n visibleFields: FormField[]\n \n /** Current form values */\n values: Record<string, unknown>\n /** Current validation errors */\n errors: Record<string, string>\n \n /** Set a single field value */\n setFieldValue: (key: string, value: unknown) => void\n /** Set multiple field values at once */\n setValues: (values: Record<string, unknown>) => void\n /** Clear all errors */\n clearErrors: () => void\n \n /** Multi-step state */\n step: number\n totalSteps: number\n isMultiStep: boolean\n progress: number\n \n /** Multi-step navigation */\n nextStep: () => boolean\n prevStep: () => void\n goToStep: (step: number) => void\n canGoNext: boolean\n canGoPrev: boolean\n isLastStep: boolean\n \n /** Validate current step */\n validate: () => boolean\n /** Validate a single field */\n validateField: (field: FormField) => string | null\n /** Check if a field is visible (conditional logic) */\n isFieldVisible: (field: FormField) => boolean\n \n /** Submit the form */\n submit: () => Promise<void>\n /** Submission state */\n isSubmitting: boolean\n isComplete: boolean\n /** Reset form to initial state */\n reset: () => void\n}\n\n// ============================================\n// Hook\n// ============================================\n\nexport function useForm(\n formIdOrSlug: string,\n options: UseFormOptions = {}\n): UseFormReturn {\n const {\n projectId: optionsProjectId,\n onSuccess,\n onError,\n initialValues = {},\n redirectUrl,\n initialForm,\n trackAnalytics = true,\n } = options\n\n // Get projectId from window globals if not provided\n const projectId = optionsProjectId ||\n (typeof window !== 'undefined' ? (window as any).__SITE_KIT_PROJECT_ID__ : undefined)\n\n // State — a server-provided config renders fields on the very first pass\n // (lazy initializer, so normalization runs once, and SSR + hydration agree).\n const [form, setForm] = useState<ManagedFormConfig | null>(() =>\n initialForm ? normalizeFormConfig(initialForm) : null,\n )\n const [isLoading, setIsLoading] = useState(!initialForm)\n const [fetchError, setFetchError] = useState<Error | null>(null)\n const [values, setValuesState] = useState<Record<string, unknown>>(() => {\n if (!initialForm) return initialValues\n const defaults: Record<string, unknown> = {}\n for (const field of (initialForm as any).fields || []) {\n if (field.default_value !== undefined && field.default_value !== null) {\n defaults[field.slug] = field.default_value\n }\n }\n return { ...defaults, ...initialValues }\n })\n const [errors, setErrors] = useState<Record<string, string>>({})\n const [step, setStep] = useState(1)\n const [isSubmitting, setIsSubmitting] = useState(false)\n const [isComplete, setIsComplete] = useState(false)\n const [submitError, setSubmitError] = useState<string | null>(null)\n\n // Synchronous re-entrancy guard + anti-bot timing.\n const isSubmittingRef = useRef(false)\n const formLoadedAt = useRef(Date.now())\n\n const totalSteps = form?.total_steps || 1\n const isMultiStep = (form?.is_multi_step) || false\n \n const { trackStepChange, trackComplete } = useFormTracking({\n formId: form?.id || '',\n totalSteps,\n enabled: trackAnalytics,\n })\n \n // Fetch form config (project is derived from API key on the backend; projectId is optional)\n useEffect(() => {\n // Server already provided the config — the recaptcha site key still needs\n // publishing to the window global, then there is nothing to fetch. Only\n // honored when it matches the requested form, so a slug change after\n // mount still refetches instead of pinning the stale config.\n const initialMatches =\n initialForm &&\n ((initialForm as any).slug === formIdOrSlug || (initialForm as any).id === formIdOrSlug)\n if (initialMatches) {\n const siteKey = (initialForm as any).recaptcha_site_key\n if (typeof window !== 'undefined' && siteKey) {\n ;(window as any).__SITE_KIT_RECAPTCHA_SITE_KEY__ = siteKey\n }\n return\n }\n\n const apiUrl = typeof window !== 'undefined'\n ? (window as any).__SITE_KIT_API_URL__ || 'https://api.sonor.io'\n : 'https://api.sonor.io'\n\n async function fetchForm() {\n try {\n setIsLoading(true)\n setFetchError(null)\n\n // The provider sets __SITE_KIT_API_KEY__ during its render; if this\n // hook's effect happens to run first, poll briefly for it rather than\n // failing permanently and wedging the form on \"API key is required\".\n const readApiKey = (): string | undefined =>\n typeof window !== 'undefined' ? (window as any).__SITE_KIT_API_KEY__ : undefined\n let apiKey = readApiKey()\n for (let i = 0; i < 15 && !apiKey; i++) {\n await new Promise((r) => setTimeout(r, 100))\n apiKey = readApiKey()\n }\n if (!apiKey) {\n throw new Error('API key is required. Provide it via SiteKitLayout or set SONOR_API_KEY.')\n }\n\n const url = `${apiUrl}/api/public/forms/config`\n const init: RequestInit = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n formIdOrSlug: formIdOrSlug,\n }),\n }\n\n // Pass the credential via options.apiKey, NOT an Authorization header.\n // extractApiKey() server-side prefers Authorization: Bearer over x-api-key,\n // so a hand-set Bearer pins the stale build-time seed and defeats\n // sonorFetch's refresh — the seed 401s and the refresh-retry keeps\n // re-sending the same dead Bearer. Letting sonorFetch own x-api-key means\n // the server sees the FRESH token.\n const response = await sonorFetch(url, init, { apiKey, retries: 3, timeoutMs: 15000 })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch form: ${response.statusText}`)\n }\n \n const data = await response.json()\n if (!data) throw new Error('Form not found')\n\n if (typeof window !== 'undefined' && data.recaptcha_site_key) {\n ;(window as any).__SITE_KIT_RECAPTCHA_SITE_KEY__ = data.recaptcha_site_key\n }\n\n setForm(normalizeFormConfig(data))\n \n // Set default values from field configs\n const defaults: Record<string, unknown> = {}\n for (const field of data.fields || []) {\n if (field.default_value !== undefined && field.default_value !== null) {\n defaults[field.slug] = field.default_value\n }\n }\n setValuesState({ ...defaults, ...initialValues })\n \n } catch (err) {\n setFetchError(err as Error)\n } finally {\n setIsLoading(false)\n }\n }\n \n fetchForm()\n // initialForm intentionally captured once — server config for THIS render\n // of THIS form; a changed slug refetches, a re-created object must not.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [formIdOrSlug, projectId])\n \n // All fields\n const allFields = useMemo(() => form?.fields || [], [form])\n \n // Fields for current step\n const fields = useMemo(() => {\n if (!isMultiStep) return allFields\n \n const currentStepConfig = form?.steps?.find(s => s.step_number === step)\n if (!currentStepConfig) return allFields\n \n return allFields.filter(f => f.step_id === currentStepConfig.id)\n }, [form, step, allFields, isMultiStep])\n \n // Check if field is visible (conditional logic)\n const isFieldVisible = useCallback((field: FormField): boolean => {\n if (!field.conditional?.show_when) return true\n \n const { field: condField, operator, value } = field.conditional.show_when\n const fieldValue = values[condField]\n \n switch (operator) {\n case 'equals':\n return fieldValue === value\n case 'not_equals':\n return fieldValue !== value\n case 'contains':\n return String(fieldValue || '').includes(String(value))\n case 'not_contains':\n return !String(fieldValue || '').includes(String(value))\n case 'is_empty':\n return !fieldValue || fieldValue === ''\n case 'not_empty':\n return !!fieldValue && fieldValue !== ''\n case 'greater_than':\n return Number(fieldValue) > Number(value)\n case 'less_than':\n return Number(fieldValue) < Number(value)\n default:\n return true\n }\n }, [values])\n \n // Visible fields only\n const visibleFields = useMemo(() => {\n return fields.filter(isFieldVisible)\n }, [fields, isFieldVisible])\n \n // Validate a single field\n const validateField = useCallback((field: FormField): string | null => {\n if (!isFieldVisible(field)) return null\n // Skip display-only field types\n if (['heading', 'section_header', 'paragraph', 'hidden'].includes(field.field_type)) return null\n\n const value = values[field.slug]\n const rules = field.validation || {}\n \n // Required check\n if (field.is_required && (!value || value === '')) {\n return rules.custom_error || `${field.label} is required`\n }\n \n if (!value) return null\n \n const strValue = String(value)\n \n // Length checks\n if (rules.min_length && strValue.length < rules.min_length) {\n return `${field.label} must be at least ${rules.min_length} characters`\n }\n if (rules.max_length && strValue.length > rules.max_length) {\n return `${field.label} must be no more than ${rules.max_length} characters`\n }\n \n // Numeric checks\n if (rules.min !== undefined && Number(value) < rules.min) {\n return `${field.label} must be at least ${rules.min}`\n }\n if (rules.max !== undefined && Number(value) > rules.max) {\n return `${field.label} must be no more than ${rules.max}`\n }\n \n // Pattern check — guard against an invalid admin-entered pattern.\n if (rules.pattern) {\n try {\n if (!new RegExp(rules.pattern).test(strValue)) {\n return rules.custom_error || `${field.label} is invalid`\n }\n } catch {\n // Malformed pattern — skip rather than crashing the form.\n }\n }\n \n // Email check\n if (field.field_type === 'email' && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(strValue)) {\n return 'Please enter a valid email address'\n }\n \n // Phone check\n if (field.field_type === 'phone' && !/^[\\d\\s\\-\\+\\(\\)]+$/.test(strValue)) {\n return 'Please enter a valid phone number'\n }\n \n return null\n }, [values, isFieldVisible])\n \n // Validate current step\n const validate = useCallback((): boolean => {\n const newErrors: Record<string, string> = {}\n \n for (const field of fields) {\n const error = validateField(field)\n if (error) {\n newErrors[field.slug] = error\n }\n }\n \n setErrors(newErrors)\n return Object.keys(newErrors).length === 0\n }, [fields, validateField])\n\n // Validate EVERY field across all steps — used on final submit so a required\n // field left empty on an earlier step cannot slip through.\n const validateAll = useCallback((): boolean => {\n const newErrors: Record<string, string> = {}\n for (const field of allFields) {\n const error = validateField(field)\n if (error) newErrors[field.slug] = error\n }\n setErrors(newErrors)\n return Object.keys(newErrors).length === 0\n }, [allFields, validateField])\n\n // Visible field values only — never submit a value from a conditionally-hidden field.\n const buildVisibleValues = useCallback((): Record<string, unknown> => {\n const out: Record<string, unknown> = {}\n for (const field of allFields) {\n if (!isFieldVisible(field)) continue\n if (field.slug in values) out[field.slug] = values[field.slug]\n }\n return out\n }, [allFields, values, isFieldVisible])\n\n // Set single field value\n const setFieldValue = useCallback((key: string, value: unknown) => {\n setValuesState(prev => ({ ...prev, [key]: value }))\n // Clear error when field changes\n setErrors(prev => {\n if (prev[key]) {\n const next = { ...prev }\n delete next[key]\n return next\n }\n return prev\n })\n }, [])\n \n // Set multiple values\n const setValues = useCallback((newValues: Record<string, unknown>) => {\n setValuesState(prev => ({ ...prev, ...newValues }))\n }, [])\n \n // Clear all errors\n const clearErrors = useCallback(() => {\n setErrors({})\n }, [])\n \n // Step navigation\n const canGoNext = step < totalSteps\n const canGoPrev = step > 1\n const isLastStep = step === totalSteps\n const progress = Math.round((step / totalSteps) * 100)\n \n const nextStep = useCallback((): boolean => {\n if (!validate()) return false\n \n if (step < totalSteps) {\n const newStep = step + 1\n setStep(newStep)\n trackStepChange(newStep)\n return true\n }\n return false\n }, [step, totalSteps, validate, trackStepChange])\n \n const prevStep = useCallback(() => {\n if (step > 1) {\n const newStep = step - 1\n setStep(newStep)\n trackStepChange(newStep)\n }\n }, [step, trackStepChange])\n \n const goToStep = useCallback((targetStep: number) => {\n if (targetStep >= 1 && targetStep <= totalSteps) {\n setStep(targetStep)\n trackStepChange(targetStep)\n }\n }, [totalSteps, trackStepChange])\n \n // Submit form\n const submit = useCallback(async () => {\n if (!form) return\n // Re-entrancy guard — blocks a concurrent double-submit in the same tick.\n if (isSubmittingRef.current) return\n if (!validateAll()) return\n\n isSubmittingRef.current = true\n setIsSubmitting(true)\n setSubmitError(null)\n\n try {\n const data = await submitForm({\n config: form,\n values: buildVisibleValues(),\n honeypotValue: '',\n formLoadedAt: formLoadedAt.current,\n })\n\n trackComplete()\n setIsComplete(true)\n onSuccess?.(data as FormSubmission)\n\n const finalRedirect = redirectUrl !== false\n ? (redirectUrl || form.redirect_url)\n : undefined\n if (finalRedirect) {\n window.location.href = finalRedirect\n }\n } catch (error) {\n console.error('[useForm] Submission error:', error)\n setSubmitError('Something went wrong sending your submission. Please try again.')\n onError?.(error as Error)\n } finally {\n isSubmittingRef.current = false\n setIsSubmitting(false)\n }\n }, [form, validateAll, buildVisibleValues, trackComplete, onSuccess, onError, redirectUrl])\n \n // Reset form\n const reset = useCallback(() => {\n setValuesState(initialValues)\n setErrors({})\n setStep(1)\n setIsComplete(false)\n setSubmitError(null)\n }, [initialValues])\n \n return {\n form,\n isLoading,\n fetchError,\n submitError,\n\n allFields,\n fields,\n visibleFields,\n \n values,\n errors,\n setFieldValue,\n setValues,\n clearErrors,\n \n step,\n totalSteps,\n isMultiStep,\n progress,\n \n nextStep,\n prevStep,\n goToStep,\n canGoNext,\n canGoPrev,\n isLastStep,\n \n validate,\n validateField,\n isFieldVisible,\n \n submit,\n isSubmitting,\n isComplete,\n reset,\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/forms/tracking-session.ts","../src/forms/useFormTracking.ts","../src/forms/useForm.ts"],"names":["uuid","useRef","useEffect","sonorFetch","sonorBeacon","useCallback","useState","normalizeFormConfig","useMemo","submitForm"],"mappings":"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","file":"chunk-VFGEY6FJ.js","sourcesContent":["/**\n * @sonordev/site-kit/forms - Form tracking session registry\n *\n * SINGLE SOURCE OF TRUTH for a form's `form_analytics` row: one\n * `/analytics/start` per formId per page load, shared by every tracker\n * mounted for that form. Do NOT re-fork start logic into a caller.\n *\n * The lesson from the double-count bug fixed in 4.2.2: `ManagedForm` called\n * `useForm` (which tracks) AND rendered `FormClient` (which also tracks). Two\n * independent hook instances each minted their own session uuid and POSTed\n * their own start, so a single page load wrote TWO `form_analytics` rows —\n * present in every release up to and including 4.2.1. That halved every reported\n * start -> submission conversion rate, and because each instance registered its\n * own `beforeunload` it wrote two abandonment rows per visit as well. The\n * signature in the data was unmistakable: paired rows where exactly one ever\n * completed (only FormClient's instance owns submit) but BOTH abandoned.\n *\n * Trackers SHARE the resulting analytics row id, so whichever component owns\n * submission can still complete the row no matter which one opened it. That\n * sharing is what makes this safe as a guard rather than a gamble on which\n * instance mounts first.\n */\n\n// Single source of truth for v4 UUIDs — crypto.randomUUID throws on plain HTTP\n// and older Safari. Do NOT re-fork ID generation here.\nimport { uuid } from '../shared/uuid'\n\nexport interface TrackingSession {\n /** The uuid reported to the API as this form visit's session. */\n readonly sessionId: string\n readonly startedAt: number\n /** Resolves to the analytics row id, or null when the start POST failed. */\n readonly analyticsId: Promise<string | null>\n /**\n * Abandonment belongs to the ROW, not to a tracker. Every mounted tracker\n * registers its own `beforeunload`; only the first beacon may fire, or one\n * visit reports abandonment as many times as it has trackers.\n */\n abandonSent: boolean\n /** @internal */\n refCount: number\n /** @internal */\n releaseTimer: ReturnType<typeof setTimeout> | null\n}\n\n/**\n * How long a session outlives its last unmount before a fresh start POST is\n * allowed. Covers React StrictMode's dev-mode mount -> unmount -> mount and the\n * FormEnhancer static -> interactive swap; both remount a form within the same\n * page load and would otherwise mint a second row for one visit.\n */\nexport const SESSION_GRACE_MS = 2000\n\nconst activeSessions = new Map<string, TrackingSession>()\n\n/**\n * Join the tracking session for `formId`, opening one if none is live.\n *\n * `start` is invoked at most once per session and must resolve to the analytics\n * row id (or null when the POST failed). Callers MUST pair this with\n * {@link releaseTrackingSession} on unmount.\n */\nexport function acquireTrackingSession(\n formId: string,\n start: (sessionId: string) => Promise<string | null>,\n): TrackingSession {\n const existing = activeSessions.get(formId)\n if (existing) {\n // A tracker rejoined inside the grace window — cancel the pending teardown\n // rather than letting it delete a session that is live again.\n if (existing.releaseTimer) {\n clearTimeout(existing.releaseTimer)\n existing.releaseTimer = null\n }\n existing.refCount++\n return existing\n }\n\n const sessionId = uuid()\n const session: TrackingSession = {\n sessionId,\n startedAt: Date.now(),\n // Assigned below — declared here so the object shape is complete first.\n analyticsId: null as unknown as Promise<string | null>,\n abandonSent: false,\n refCount: 1,\n releaseTimer: null,\n }\n\n // Register BEFORE invoking `start`, so a tracker mounting later in the same\n // commit joins this session instead of racing it to a second row. React runs\n // effects synchronously within a commit, so this check-then-set cannot be\n // interleaved — but only if nothing awaits in between.\n activeSessions.set(formId, session)\n ;(session as { analyticsId: Promise<string | null> }).analyticsId = start(sessionId)\n\n return session\n}\n\n/**\n * Leave the tracking session. The last tracker out schedules teardown after\n * {@link SESSION_GRACE_MS} rather than deleting immediately, so a remount\n * within the same page load reuses the row instead of opening another.\n */\nexport function releaseTrackingSession(formId: string, session: TrackingSession): void {\n session.refCount--\n if (session.refCount > 0) return\n if (session.releaseTimer) return\n\n session.releaseTimer = setTimeout(() => {\n session.releaseTimer = null\n // Re-check both conditions: a tracker may have rejoined, or the entry may\n // already have been replaced by a later session for the same form.\n if (session.refCount <= 0 && activeSessions.get(formId) === session) {\n activeSessions.delete(formId)\n }\n }, SESSION_GRACE_MS)\n\n // Never hold the process open for a teardown timer (SSR/test environments).\n ;(session.releaseTimer as { unref?: () => void })?.unref?.()\n}\n\n/** Test-only: drop all live sessions so cases start from a clean registry. */\nexport function __resetTrackingSessions(): void {\n for (const session of activeSessions.values()) {\n if (session.releaseTimer) clearTimeout(session.releaseTimer)\n }\n activeSessions.clear()\n}\n","/**\n * @sonordev/site-kit/forms - Form Tracking Hook\n *\n * Tracks form analytics including step progress and abandonment.\n *\n * The `form_analytics` row is owned by the shared session registry, not by this\n * hook — see `tracking-session.ts`. Every tracker mounted for the same form\n * joins ONE session and shares its analytics row id, so composing two trackers\n * over a single form (as ManagedForm once did) can no longer double-count.\n */\n\n'use client'\n\nimport { useEffect, useRef, useCallback } from 'react'\nimport { sonorFetch, sonorBeacon } from '../shared/sonorFetch'\nimport {\n acquireTrackingSession,\n releaseTrackingSession,\n type TrackingSession,\n} from './tracking-session'\n\ninterface UseFormTrackingOptions {\n formId: string\n totalSteps: number\n enabled?: boolean\n debug?: boolean\n}\n\ninterface FormTrackingReturn {\n trackStepChange: (step: number) => void\n trackComplete: () => void\n sessionId: string\n}\n\nexport function useFormTracking({\n formId,\n totalSteps,\n enabled = true,\n debug = false,\n}: UseFormTrackingOptions): FormTrackingReturn {\n const sessionRef = useRef<TrackingSession | null>(null)\n const sessionIdRef = useRef<string>('')\n const startTimeRef = useRef<number>(0)\n const stepStartTimeRef = useRef<number>(0)\n const stepTimesRef = useRef<Record<number, number>>({})\n const currentStepRef = useRef<number>(1)\n const maxStepRef = useRef<number>(1)\n const analyticsIdRef = useRef<string | null>(null)\n\n // Initialize tracking\n useEffect(() => {\n if (!enabled) return\n if (!formId) {\n if (debug) console.warn('[Forms] Tracking skipped: formId is empty')\n return\n }\n\n // Record form start. Invoked at most once per session by the registry —\n // a second tracker for this form joins the existing session instead.\n const startTracking = async (sessionId: string): Promise<string | null> => {\n const apiUrl = (window as any).__SITE_KIT_API_URL__\n const apiKey = (window as any).__SITE_KIT_API_KEY__\n\n if (!apiUrl || !apiKey) {\n if (debug) console.error('[Forms] Missing API URL or API key')\n return null\n }\n\n try {\n const response = await sonorFetch(\n `${apiUrl}/api/public/forms/analytics/start`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n formId,\n sessionId,\n deviceType: getDeviceType(),\n }),\n },\n { apiKey, retries: 0 },\n )\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n }\n\n const data = await response.json()\n if (debug) console.log('[Forms] Started tracking:', data.id)\n return data.id ?? null\n } catch (error) {\n if (debug) console.error('[Forms] Error starting tracking:', error)\n return null\n }\n }\n\n const session = acquireTrackingSession(formId, startTracking)\n sessionRef.current = session\n sessionIdRef.current = session.sessionId\n startTimeRef.current = session.startedAt\n stepStartTimeRef.current = Date.now()\n\n let joined = true\n void session.analyticsId.then((id) => {\n if (joined) analyticsIdRef.current = id\n })\n\n // Handle abandonment on page leave\n const handleBeforeUnload = () => {\n if (!analyticsIdRef.current) return\n // One abandonment per ROW. Without this, every tracker sharing the\n // session reports the same visit as abandoned.\n if (session.abandonSent) return\n\n const apiUrl = (window as any).__SITE_KIT_API_URL__\n const apiKey = (window as any).__SITE_KIT_API_KEY__\n\n if (!apiUrl || !apiKey) return\n\n const now = Date.now()\n const currentStepTime = Math.floor((now - stepStartTimeRef.current) / 1000)\n stepTimesRef.current[currentStepRef.current] = currentStepTime\n\n session.abandonSent = true\n\n // Fire-and-forget via sonorBeacon: keepalive fetch keeps the credential in\n // the x-api-key header (raw sendBeacon can't set headers), so abandonment\n // authenticates on 3.2+ token sites and uses the freshest minted token.\n sonorBeacon(\n `${apiUrl}/api/public/forms/analytics/abandon`,\n {\n analyticsId: analyticsIdRef.current,\n step: currentStepRef.current,\n maxStep: maxStepRef.current,\n stepTimes: stepTimesRef.current,\n totalTimeSeconds: Math.floor((now - startTimeRef.current) / 1000),\n },\n apiKey,\n )\n\n if (debug) console.log('[Forms] Abandonment tracked')\n }\n\n window.addEventListener('beforeunload', handleBeforeUnload)\n\n return () => {\n joined = false\n window.removeEventListener('beforeunload', handleBeforeUnload)\n releaseTrackingSession(formId, session)\n sessionRef.current = null\n }\n }, [formId, enabled, debug])\n\n /**\n * The analytics row id, waiting on the start POST if it is still in flight.\n * A fast submit used to race the start and silently drop the completion,\n * which understated conversions the same way double-starting overstated them.\n */\n const resolveAnalyticsId = useCallback(async (): Promise<string | null> => {\n if (analyticsIdRef.current) return analyticsIdRef.current\n const session = sessionRef.current\n if (!session) return null\n const id = await session.analyticsId\n if (id) analyticsIdRef.current = id\n return id\n }, [])\n\n // Track step changes\n const trackStepChange = useCallback(async (step: number) => {\n if (!enabled) return\n\n const apiUrl = (window as any).__SITE_KIT_API_URL__\n const apiKey = (window as any).__SITE_KIT_API_KEY__\n\n if (!apiUrl || !apiKey) {\n if (debug) console.error('[Forms] Missing API URL or API key')\n return\n }\n\n const now = Date.now()\n\n // Record time spent on previous step\n const prevStepTime = Math.floor((now - stepStartTimeRef.current) / 1000)\n stepTimesRef.current[currentStepRef.current] = prevStepTime\n\n // Update refs\n currentStepRef.current = step\n maxStepRef.current = Math.max(maxStepRef.current, step)\n stepStartTimeRef.current = now\n\n const analyticsId = await resolveAnalyticsId()\n if (!analyticsId) return\n\n // Update database\n try {\n const response = await sonorFetch(\n `${apiUrl}/api/public/forms/analytics/step`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n analyticsId,\n step,\n maxStep: maxStepRef.current,\n stepTimes: stepTimesRef.current,\n }),\n },\n { apiKey, retries: 0 },\n )\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n }\n\n if (debug) console.log('[Forms] Step changed to:', step)\n } catch (error) {\n if (debug) console.error('[Forms] Error updating step:', error)\n }\n }, [enabled, debug, resolveAnalyticsId])\n\n // Track completion\n const trackComplete = useCallback(async () => {\n if (!enabled) return\n\n const apiUrl = (window as any).__SITE_KIT_API_URL__\n const apiKey = (window as any).__SITE_KIT_API_KEY__\n\n if (!apiUrl || !apiKey) {\n if (debug) console.error('[Forms] Missing API URL or API key')\n return\n }\n\n const now = Date.now()\n\n // Record time for final step\n const finalStepTime = Math.floor((now - stepStartTimeRef.current) / 1000)\n stepTimesRef.current[currentStepRef.current] = finalStepTime\n\n const analyticsId = await resolveAnalyticsId()\n if (!analyticsId) return\n\n // A completed row must never also be reported as abandoned when the\n // success screen is later closed.\n const session = sessionRef.current\n if (session) session.abandonSent = true\n\n try {\n // Complete form analytics tracking\n // Note: A database trigger will automatically log this as a conversion\n // in analytics_conversions when completed_at is set\n const response = await sonorFetch(\n `${apiUrl}/api/public/forms/analytics/complete`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n analyticsId,\n totalSteps,\n stepTimes: stepTimesRef.current,\n totalTimeSeconds: Math.floor((now - startTimeRef.current) / 1000),\n }),\n },\n { apiKey, retries: 0 },\n )\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n }\n\n if (debug) console.log('[Forms] Form completed')\n\n // No client-side conversion POST: the Sonor API records the canonical\n // form_submission conversion (analytics_conversions + session flag)\n // when the submission lands at /api/public/forms/submit. The old POST\n // here sent this hook's form-tracking uuid as `sessionId`, which\n // matched no analytics session and double-counted the conversion.\n } catch (error) {\n if (debug) console.error('[Forms] Error completing tracking:', error)\n }\n }, [enabled, totalSteps, formId, debug, resolveAnalyticsId])\n\n return {\n trackStepChange,\n trackComplete,\n sessionId: sessionIdRef.current,\n }\n}\n\n// Helper\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","/**\n * @sonordev/site-kit/forms - useForm Hook\n * \n * Headless hook for complete control over form rendering.\n * Fetches form config from API, handles validation, state, and submission.\n * \n * @example\n * ```tsx\n * const { form, fields, values, errors, setFieldValue, submit, isSubmitting } = useForm('contact-form')\n * \n * return (\n * <form onSubmit={(e) => { e.preventDefault(); submit() }}>\n * {fields.map(field => (\n * <MyCustomInput\n * key={field.slug}\n * label={field.label}\n * value={values[field.slug]}\n * error={errors[field.slug]}\n * onChange={(val) => setFieldValue(field.slug, val)}\n * />\n * ))}\n * <button type=\"submit\" disabled={isSubmitting}>Submit</button>\n * </form>\n * )\n * ```\n */\n\n'use client'\n\nimport { useState, useEffect, useCallback, useMemo, useRef } from 'react'\nimport { useFormTracking } from './useFormTracking'\n// Shared with StaticForm — the server shell and this client path MUST agree\n// on field order, step count and success copy or the enhancement swap jumps.\nimport { normalizeFormConfig } from './normalize-config'\nimport { sonorFetch } from '../shared/sonorFetch'\nimport { submitForm } from './submitForm'\nimport type { \n ManagedFormConfig, \n FormField, \n FormSubmission \n} from './types'\nimport { DEFAULT_FORM_SUCCESS_MESSAGE } from './defaultSuccessMessage'\n\n// ============================================\n// Types\n// ============================================\n\nexport interface UseFormOptions {\n /** Project ID (defaults to SiteKitLayout config) */\n projectId?: string\n /** Callback when form submits successfully */\n onSuccess?: (submission: FormSubmission) => void\n /** Callback when submission fails */\n onError?: (error: Error) => void\n /** Initial values to prefill */\n initialValues?: Record<string, unknown>\n /** Auto-redirect after success (override form config) */\n redirectUrl?: string | false\n /**\n * Server-fetched form payload (from `getFormConfig` in\n * `@sonordev/site-kit/forms/server`). When provided, the fields render on\n * the first client render — no config fetch, no \"Loading form...\" flash.\n * Accepts the RAW API payload; normalized here exactly like a client fetch.\n */\n initialForm?: Record<string, unknown> | null\n /**\n * Report this form's funnel to Sonor (`form_analytics`). Defaults to true —\n * a headless `useForm` consumer renders and submits the form itself, so this\n * hook is the only thing that can track it.\n *\n * `ManagedForm` passes FALSE: it delegates rendering, step navigation and\n * submission to `FormClient`, which tracks that path. Exactly one component\n * may own a form's tracking — two owners was the double-count bug fixed\n * in 4.2.2.\n */\n trackAnalytics?: boolean\n}\n\n\nexport interface UseFormReturn {\n /** Form configuration (null while loading) */\n form: ManagedFormConfig | null\n /** Loading state */\n isLoading: boolean\n /** Error fetching form */\n fetchError: Error | null\n /** Human-readable error from the last submit attempt (null when none) */\n submitError: string | null\n\n /** All form fields */\n allFields: FormField[]\n /** Fields for current step (multi-step) or all fields (single step) */\n fields: FormField[]\n /** Visible fields only (respecting conditional logic) */\n visibleFields: FormField[]\n \n /** Current form values */\n values: Record<string, unknown>\n /** Current validation errors */\n errors: Record<string, string>\n \n /** Set a single field value */\n setFieldValue: (key: string, value: unknown) => void\n /** Set multiple field values at once */\n setValues: (values: Record<string, unknown>) => void\n /** Clear all errors */\n clearErrors: () => void\n \n /** Multi-step state */\n step: number\n totalSteps: number\n isMultiStep: boolean\n progress: number\n \n /** Multi-step navigation */\n nextStep: () => boolean\n prevStep: () => void\n goToStep: (step: number) => void\n canGoNext: boolean\n canGoPrev: boolean\n isLastStep: boolean\n \n /** Validate current step */\n validate: () => boolean\n /** Validate a single field */\n validateField: (field: FormField) => string | null\n /** Check if a field is visible (conditional logic) */\n isFieldVisible: (field: FormField) => boolean\n \n /** Submit the form */\n submit: () => Promise<void>\n /** Submission state */\n isSubmitting: boolean\n isComplete: boolean\n /** Reset form to initial state */\n reset: () => void\n}\n\n// ============================================\n// Hook\n// ============================================\n\nexport function useForm(\n formIdOrSlug: string,\n options: UseFormOptions = {}\n): UseFormReturn {\n const {\n projectId: optionsProjectId,\n onSuccess,\n onError,\n initialValues = {},\n redirectUrl,\n initialForm,\n trackAnalytics = true,\n } = options\n\n // Get projectId from window globals if not provided\n const projectId = optionsProjectId ||\n (typeof window !== 'undefined' ? (window as any).__SITE_KIT_PROJECT_ID__ : undefined)\n\n // State — a server-provided config renders fields on the very first pass\n // (lazy initializer, so normalization runs once, and SSR + hydration agree).\n const [form, setForm] = useState<ManagedFormConfig | null>(() =>\n initialForm ? normalizeFormConfig(initialForm) : null,\n )\n const [isLoading, setIsLoading] = useState(!initialForm)\n const [fetchError, setFetchError] = useState<Error | null>(null)\n const [values, setValuesState] = useState<Record<string, unknown>>(() => {\n if (!initialForm) return initialValues\n const defaults: Record<string, unknown> = {}\n for (const field of (initialForm as any).fields || []) {\n if (field.default_value !== undefined && field.default_value !== null) {\n defaults[field.slug] = field.default_value\n }\n }\n return { ...defaults, ...initialValues }\n })\n const [errors, setErrors] = useState<Record<string, string>>({})\n const [step, setStep] = useState(1)\n const [isSubmitting, setIsSubmitting] = useState(false)\n const [isComplete, setIsComplete] = useState(false)\n const [submitError, setSubmitError] = useState<string | null>(null)\n\n // Synchronous re-entrancy guard + anti-bot timing.\n const isSubmittingRef = useRef(false)\n const formLoadedAt = useRef(Date.now())\n\n const totalSteps = form?.total_steps || 1\n const isMultiStep = (form?.is_multi_step) || false\n \n const { trackStepChange, trackComplete } = useFormTracking({\n formId: form?.id || '',\n totalSteps,\n enabled: trackAnalytics,\n })\n \n // Fetch form config (project is derived from API key on the backend; projectId is optional)\n useEffect(() => {\n // Server already provided the config — the recaptcha site key still needs\n // publishing to the window global, then there is nothing to fetch. Only\n // honored when it matches the requested form, so a slug change after\n // mount still refetches instead of pinning the stale config.\n const initialMatches =\n initialForm &&\n ((initialForm as any).slug === formIdOrSlug || (initialForm as any).id === formIdOrSlug)\n if (initialMatches) {\n const siteKey = (initialForm as any).recaptcha_site_key\n if (typeof window !== 'undefined' && siteKey) {\n ;(window as any).__SITE_KIT_RECAPTCHA_SITE_KEY__ = siteKey\n }\n return\n }\n\n const apiUrl = typeof window !== 'undefined'\n ? (window as any).__SITE_KIT_API_URL__ || 'https://api.sonor.io'\n : 'https://api.sonor.io'\n\n async function fetchForm() {\n try {\n setIsLoading(true)\n setFetchError(null)\n\n // The provider sets __SITE_KIT_API_KEY__ during its render; if this\n // hook's effect happens to run first, poll briefly for it rather than\n // failing permanently and wedging the form on \"API key is required\".\n const readApiKey = (): string | undefined =>\n typeof window !== 'undefined' ? (window as any).__SITE_KIT_API_KEY__ : undefined\n let apiKey = readApiKey()\n for (let i = 0; i < 15 && !apiKey; i++) {\n await new Promise((r) => setTimeout(r, 100))\n apiKey = readApiKey()\n }\n if (!apiKey) {\n throw new Error('API key is required. Provide it via SiteKitLayout or set SONOR_API_KEY.')\n }\n\n const url = `${apiUrl}/api/public/forms/config`\n const init: RequestInit = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n formIdOrSlug: formIdOrSlug,\n }),\n }\n\n // Pass the credential via options.apiKey, NOT an Authorization header.\n // extractApiKey() server-side prefers Authorization: Bearer over x-api-key,\n // so a hand-set Bearer pins the stale build-time seed and defeats\n // sonorFetch's refresh — the seed 401s and the refresh-retry keeps\n // re-sending the same dead Bearer. Letting sonorFetch own x-api-key means\n // the server sees the FRESH token.\n const response = await sonorFetch(url, init, { apiKey, retries: 3, timeoutMs: 15000 })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch form: ${response.statusText}`)\n }\n \n const data = await response.json()\n if (!data) throw new Error('Form not found')\n\n if (typeof window !== 'undefined' && data.recaptcha_site_key) {\n ;(window as any).__SITE_KIT_RECAPTCHA_SITE_KEY__ = data.recaptcha_site_key\n }\n\n setForm(normalizeFormConfig(data))\n \n // Set default values from field configs\n const defaults: Record<string, unknown> = {}\n for (const field of data.fields || []) {\n if (field.default_value !== undefined && field.default_value !== null) {\n defaults[field.slug] = field.default_value\n }\n }\n setValuesState({ ...defaults, ...initialValues })\n \n } catch (err) {\n setFetchError(err as Error)\n } finally {\n setIsLoading(false)\n }\n }\n \n fetchForm()\n // initialForm intentionally captured once — server config for THIS render\n // of THIS form; a changed slug refetches, a re-created object must not.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [formIdOrSlug, projectId])\n \n // All fields\n const allFields = useMemo(() => form?.fields || [], [form])\n \n // Fields for current step\n const fields = useMemo(() => {\n if (!isMultiStep) return allFields\n \n const currentStepConfig = form?.steps?.find(s => s.step_number === step)\n if (!currentStepConfig) return allFields\n \n return allFields.filter(f => f.step_id === currentStepConfig.id)\n }, [form, step, allFields, isMultiStep])\n \n // Check if field is visible (conditional logic)\n const isFieldVisible = useCallback((field: FormField): boolean => {\n if (!field.conditional?.show_when) return true\n \n const { field: condField, operator, value } = field.conditional.show_when\n const fieldValue = values[condField]\n \n switch (operator) {\n case 'equals':\n return fieldValue === value\n case 'not_equals':\n return fieldValue !== value\n case 'contains':\n return String(fieldValue || '').includes(String(value))\n case 'not_contains':\n return !String(fieldValue || '').includes(String(value))\n case 'is_empty':\n return !fieldValue || fieldValue === ''\n case 'not_empty':\n return !!fieldValue && fieldValue !== ''\n case 'greater_than':\n return Number(fieldValue) > Number(value)\n case 'less_than':\n return Number(fieldValue) < Number(value)\n default:\n return true\n }\n }, [values])\n \n // Visible fields only\n const visibleFields = useMemo(() => {\n return fields.filter(isFieldVisible)\n }, [fields, isFieldVisible])\n \n // Validate a single field\n const validateField = useCallback((field: FormField): string | null => {\n if (!isFieldVisible(field)) return null\n // Skip display-only field types\n if (['heading', 'section_header', 'paragraph', 'hidden'].includes(field.field_type)) return null\n\n const value = values[field.slug]\n const rules = field.validation || {}\n \n // Required check\n if (field.is_required && (!value || value === '')) {\n return rules.custom_error || `${field.label} is required`\n }\n \n if (!value) return null\n \n const strValue = String(value)\n \n // Length checks\n if (rules.min_length && strValue.length < rules.min_length) {\n return `${field.label} must be at least ${rules.min_length} characters`\n }\n if (rules.max_length && strValue.length > rules.max_length) {\n return `${field.label} must be no more than ${rules.max_length} characters`\n }\n \n // Numeric checks\n if (rules.min !== undefined && Number(value) < rules.min) {\n return `${field.label} must be at least ${rules.min}`\n }\n if (rules.max !== undefined && Number(value) > rules.max) {\n return `${field.label} must be no more than ${rules.max}`\n }\n \n // Pattern check — guard against an invalid admin-entered pattern.\n if (rules.pattern) {\n try {\n if (!new RegExp(rules.pattern).test(strValue)) {\n return rules.custom_error || `${field.label} is invalid`\n }\n } catch {\n // Malformed pattern — skip rather than crashing the form.\n }\n }\n \n // Email check\n if (field.field_type === 'email' && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(strValue)) {\n return 'Please enter a valid email address'\n }\n \n // Phone check\n if (field.field_type === 'phone' && !/^[\\d\\s\\-\\+\\(\\)]+$/.test(strValue)) {\n return 'Please enter a valid phone number'\n }\n \n return null\n }, [values, isFieldVisible])\n \n // Validate current step\n const validate = useCallback((): boolean => {\n const newErrors: Record<string, string> = {}\n \n for (const field of fields) {\n const error = validateField(field)\n if (error) {\n newErrors[field.slug] = error\n }\n }\n \n setErrors(newErrors)\n return Object.keys(newErrors).length === 0\n }, [fields, validateField])\n\n // Validate EVERY field across all steps — used on final submit so a required\n // field left empty on an earlier step cannot slip through.\n const validateAll = useCallback((): boolean => {\n const newErrors: Record<string, string> = {}\n for (const field of allFields) {\n const error = validateField(field)\n if (error) newErrors[field.slug] = error\n }\n setErrors(newErrors)\n return Object.keys(newErrors).length === 0\n }, [allFields, validateField])\n\n // Visible field values only — never submit a value from a conditionally-hidden field.\n const buildVisibleValues = useCallback((): Record<string, unknown> => {\n const out: Record<string, unknown> = {}\n for (const field of allFields) {\n if (!isFieldVisible(field)) continue\n if (field.slug in values) out[field.slug] = values[field.slug]\n }\n return out\n }, [allFields, values, isFieldVisible])\n\n // Set single field value\n const setFieldValue = useCallback((key: string, value: unknown) => {\n setValuesState(prev => ({ ...prev, [key]: value }))\n // Clear error when field changes\n setErrors(prev => {\n if (prev[key]) {\n const next = { ...prev }\n delete next[key]\n return next\n }\n return prev\n })\n }, [])\n \n // Set multiple values\n const setValues = useCallback((newValues: Record<string, unknown>) => {\n setValuesState(prev => ({ ...prev, ...newValues }))\n }, [])\n \n // Clear all errors\n const clearErrors = useCallback(() => {\n setErrors({})\n }, [])\n \n // Step navigation\n const canGoNext = step < totalSteps\n const canGoPrev = step > 1\n const isLastStep = step === totalSteps\n const progress = Math.round((step / totalSteps) * 100)\n \n const nextStep = useCallback((): boolean => {\n if (!validate()) return false\n \n if (step < totalSteps) {\n const newStep = step + 1\n setStep(newStep)\n trackStepChange(newStep)\n return true\n }\n return false\n }, [step, totalSteps, validate, trackStepChange])\n \n const prevStep = useCallback(() => {\n if (step > 1) {\n const newStep = step - 1\n setStep(newStep)\n trackStepChange(newStep)\n }\n }, [step, trackStepChange])\n \n const goToStep = useCallback((targetStep: number) => {\n if (targetStep >= 1 && targetStep <= totalSteps) {\n setStep(targetStep)\n trackStepChange(targetStep)\n }\n }, [totalSteps, trackStepChange])\n \n // Submit form\n const submit = useCallback(async () => {\n if (!form) return\n // Re-entrancy guard — blocks a concurrent double-submit in the same tick.\n if (isSubmittingRef.current) return\n if (!validateAll()) return\n\n isSubmittingRef.current = true\n setIsSubmitting(true)\n setSubmitError(null)\n\n try {\n const data = await submitForm({\n config: form,\n values: buildVisibleValues(),\n honeypotValue: '',\n formLoadedAt: formLoadedAt.current,\n })\n\n trackComplete()\n setIsComplete(true)\n onSuccess?.(data as FormSubmission)\n\n const finalRedirect = redirectUrl !== false\n ? (redirectUrl || form.redirect_url)\n : undefined\n if (finalRedirect) {\n window.location.href = finalRedirect\n }\n } catch (error) {\n console.error('[useForm] Submission error:', error)\n setSubmitError('Something went wrong sending your submission. Please try again.')\n onError?.(error as Error)\n } finally {\n isSubmittingRef.current = false\n setIsSubmitting(false)\n }\n }, [form, validateAll, buildVisibleValues, trackComplete, onSuccess, onError, redirectUrl])\n \n // Reset form\n const reset = useCallback(() => {\n setValuesState(initialValues)\n setErrors({})\n setStep(1)\n setIsComplete(false)\n setSubmitError(null)\n }, [initialValues])\n \n return {\n form,\n isLoading,\n fetchError,\n submitError,\n\n allFields,\n fields,\n visibleFields,\n \n values,\n errors,\n setFieldValue,\n setValues,\n clearErrors,\n \n step,\n totalSteps,\n isMultiStep,\n progress,\n \n nextStep,\n prevStep,\n goToStep,\n canGoNext,\n canGoPrev,\n isLastStep,\n \n validate,\n validateField,\n isFieldVisible,\n \n submit,\n isSubmitting,\n isComplete,\n reset,\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { isTokenMode, getFreshCredential, isSiteToken, refreshSiteToken, currentCredential, credentialBreakerId } from './chunk-4XGACM7D.mjs';
2
- import { SITE_KIT_VERSION } from './chunk-WDBCXRTT.mjs';
1
+ import { isTokenMode, getFreshCredential, isSiteToken, refreshSiteToken, currentCredential, credentialBreakerId } from './chunk-ABZGEHTC.mjs';
2
+ import { SITE_KIT_VERSION } from './chunk-QRBPT6Z6.mjs';
3
3
 
4
4
  // src/shared/fetchWithRetry.ts
5
5
  function backoffDelay(attempt, response) {
@@ -127,5 +127,5 @@ function sonorBeacon(url, payload, apiKey) {
127
127
  }
128
128
 
129
129
  export { sonorBeacon, sonorFetch };
130
- //# sourceMappingURL=chunk-OFSA7LUH.mjs.map
131
- //# sourceMappingURL=chunk-OFSA7LUH.mjs.map
130
+ //# sourceMappingURL=chunk-XLPU3TEE.mjs.map
131
+ //# sourceMappingURL=chunk-XLPU3TEE.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared/fetchWithRetry.ts","../src/shared/sonorFetch.ts"],"names":[],"mappings":"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","file":"chunk-OFSA7LUH.mjs","sourcesContent":["/**\n * @sonordev/site-kit shared - Resilient fetch\n *\n * Single source of truth for client-side resilient fetch (forms, SitemapSync).\n * Adds a per-attempt timeout and retries transient failures (network errors,\n * request timeouts, HTTP 429, and 5xx) with exponential backoff.\n *\n * A form submission must survive a brief API blip — a deploy, a cold start, a\n * dropped packet. A single un-retried fetch turning into \"Something went wrong\"\n * is how leads get lost. The explicit abort also matters on its own: a request\n * left to hang until the browser's own network timeout logs a console error\n * (net::ERR_TIMED_OUT) that fails Lighthouse best-practices; an aborted fetch\n * logs nothing.\n */\n\nexport interface FetchRetryOptions {\n /** Number of retries AFTER the first attempt (default 2 → up to 3 tries total). */\n retries?: number\n /** Per-attempt timeout in milliseconds (default 15000). */\n timeoutMs?: number\n}\n\nfunction backoffDelay(attempt: number, response?: Response): number {\n // Honor a Retry-After header on 429 responses when present.\n if (response?.status === 429) {\n const header = response.headers.get('retry-after')\n const seconds = header ? parseInt(header, 10) : NaN\n if (!Number.isNaN(seconds) && seconds > 0) return Math.min(seconds * 1000, 10000)\n }\n // Exponential backoff: 500ms, 1s, 2s, ... capped at 8s.\n return Math.min(8000, 500 * 2 ** attempt)\n}\n\n/**\n * fetch() with a timeout and automatic retries for transient failures.\n *\n * Non-transient responses (2xx, 3xx, and 4xx other than 429) are returned to\n * the caller as-is — only 429/5xx and thrown network/timeout errors are retried.\n * If every attempt fails with a thrown error, the last error is re-thrown.\n */\nexport async function fetchWithRetry(\n url: string,\n init: RequestInit,\n options: FetchRetryOptions = {},\n): Promise<Response> {\n const retries = options.retries ?? 2\n const timeoutMs = options.timeoutMs ?? 15000\n let lastError: unknown\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), timeoutMs)\n try {\n const response = await fetch(url, { ...init, signal: controller.signal })\n clearTimeout(timer)\n\n if ((response.status === 429 || response.status >= 500) && attempt < retries) {\n await new Promise((resolve) => setTimeout(resolve, backoffDelay(attempt, response)))\n continue\n }\n return response\n } catch (error) {\n clearTimeout(timer)\n lastError = error\n // Network failure or timeout (AbortController) — retry while attempts remain.\n if (attempt < retries) {\n await new Promise((resolve) => setTimeout(resolve, backoffDelay(attempt)))\n continue\n }\n }\n }\n\n throw lastError instanceof Error\n ? lastError\n : new Error('Network request failed after multiple attempts. Please try again.')\n}\n","/**\n * @sonordev/site-kit shared - Canonical client transport\n *\n * Single source of truth for how site-kit talks to Sonor from the browser.\n * Every client-side module (analytics, forms, commerce, engage, maps, images,\n * SitemapSync) routes through here instead of bare fetch(), which gives the\n * whole kit, in one place:\n *\n * - per-attempt timeout + retry with backoff (via fetchWithRetry) — a hung\n * request left to the browser's own network timeout logs a console error\n * (net::ERR_TIMED_OUT) that fails Lighthouse best-practices\n * - the x-sitekit-version header on every request, so the platform can see\n * which kit version each site actually runs from live traffic\n * - CREDENTIAL LIFECYCLE: sites on 3.2+ ship a short-lived minted token instead\n * of the raw key. This transport resolves the freshest token (refreshing a\n * stale seed transparently), and on a 401/403 for a token it refreshes once\n * and retries before giving up. A raw key (2.x kit, or the mint-failed\n * fallback) is a pure passthrough — legacy behavior is unchanged.\n * - an auth circuit breaker: after a 401/403 the credential is paused for a few\n * minutes and ONE friendly console.info is emitted — a site on a stale or\n * canceled key must not spam the API or the visitor's console. Keyed by the\n * project (from the token) so it survives token rotation.\n * - sonorBeacon for unload-time telemetry that keeps the credential in headers;\n * navigator.sendBeacon can't set headers and forced the key into the URL,\n * where server and CDN access logs capture it\n *\n * Non-idempotent endpoints (checkout, payment intents, uploads) must pass\n * { retries: 0 } — they still get the timeout, but never an automatic retry.\n */\nimport { fetchWithRetry, type FetchRetryOptions } from './fetchWithRetry'\nimport { SITE_KIT_VERSION } from './version'\nimport {\n credentialBreakerId,\n currentCredential,\n getFreshCredential,\n isSiteToken,\n isTokenMode,\n refreshSiteToken,\n} from './siteToken'\n\nexport interface SonorFetchOptions extends FetchRetryOptions {\n /** Project credential — the minted token (3.2+) or raw key. Sent as x-api-key. */\n apiKey?: string\n}\n\n/** How long a credential stays paused after an auth failure. */\nconst AUTH_BREAK_MS = 5 * 60_000\n\n// breaker id → epoch ms until which requests are paused. Shared on window for\n// the same reason as the token state (see siteToken.ts): duplicated module\n// copies must trip and observe ONE breaker, not one each. Never applies on the\n// server, so a per-module Map there is fine.\nconst BREAKER_STATE_KEY = '__SONOR_AUTH_BREAKER__'\nconst pausedKeys: Map<string, number> = (() => {\n if (typeof window === 'undefined') return new Map()\n const w = window as unknown as Record<string, Map<string, number> | undefined>\n return (w[BREAKER_STATE_KEY] ??= new Map())\n})()\nlet warnedThisPage = false\n\n/** True when a previous 401/403 has paused this credential (browser only). */\nexport function isAuthPaused(credential?: string): boolean {\n if (typeof window === 'undefined') return false\n const id = credentialBreakerId(credential)\n const until = pausedKeys.get(id)\n if (!until) return false\n if (Date.now() >= until) {\n pausedKeys.delete(id)\n return false\n }\n return true\n}\n\nfunction tripBreaker(credential?: string): void {\n pausedKeys.set(credentialBreakerId(credential), Date.now() + AUTH_BREAK_MS)\n if (!warnedThisPage) {\n warnedThisPage = true\n // info, not error: a visitor's console must stay clean (Lighthouse\n // errors-in-console), and copy never names env vars or key formats.\n console.info(\n \"[Sonor] This site couldn't authenticate with Sonor, so data features are paused for a few minutes. If this keeps happening, the site is likely running an outdated API key.\",\n )\n }\n}\n\nexport async function sonorFetch(\n url: string,\n init: RequestInit = {},\n options: SonorFetchOptions = {},\n): Promise<Response> {\n // Resolve the credential to send. In token mode this may transparently refresh\n // a stale seed before the first request; in raw-key mode it's a passthrough.\n let credential = options.apiKey\n if (credential !== undefined || isTokenMode()) {\n credential = await getFreshCredential(options.apiKey)\n }\n\n const headers = new Headers(init.headers || {})\n headers.set('x-sitekit-version', SITE_KIT_VERSION)\n if (credential) {\n if (isTokenMode()) {\n // Token mode: `credential` is the freshest token (refreshed just above if\n // the seed was stale). It MUST override any x-api-key a caller hand-set — a\n // stale build-time seed passed as a header would otherwise pin the request\n // and defeat refresh entirely. Also drop a caller-set Authorization:\n // extractApiKey() server-side prefers `Authorization: Bearer` over\n // x-api-key, so a stale Bearer seed would win even once we set a fresh\n // x-api-key. This is the single place the client credential is chosen — do\n // not re-attach it as a header at call sites.\n headers.set('x-api-key', credential)\n headers.delete('authorization')\n } else if (!headers.has('x-api-key')) {\n // Raw-key mode: legacy passthrough — respect a caller-supplied header.\n headers.set('x-api-key', credential)\n }\n }\n\n if (isAuthPaused(credential)) {\n // Synthetic response keeps every caller's !response.ok path working\n // without a network round trip while the breaker is open.\n return new Response(null, { status: 401, statusText: 'sonor-auth-paused' })\n }\n\n let response = await fetchWithRetry(url, { ...init, headers }, options)\n\n // A token can rotate or expire mid-session. On the first auth failure, try ONE\n // refresh + retry before tripping the breaker — only for token credentials\n // (raw keys have nothing to refresh).\n if (\n (response.status === 401 || response.status === 403) &&\n typeof window !== 'undefined' &&\n isSiteToken(credential)\n ) {\n const refreshed = await refreshSiteToken()\n if (refreshed && refreshed !== credential) {\n const retryHeaders = new Headers(init.headers || {})\n retryHeaders.set('x-sitekit-version', SITE_KIT_VERSION)\n retryHeaders.set('x-api-key', refreshed)\n // Same reason as the initial request: a caller-set stale Bearer would win\n // over our fresh x-api-key server-side, so strip it on the retry too.\n retryHeaders.delete('authorization')\n credential = refreshed\n response = await fetchWithRetry(url, { ...init, headers: retryHeaders }, options)\n }\n }\n\n if (\n (response.status === 401 || response.status === 403) &&\n typeof window !== 'undefined' &&\n credential\n ) {\n tripBreaker(credential)\n }\n\n return response\n}\n\n/**\n * Fire-and-forget telemetry that survives page unload.\n *\n * Uses fetch({ keepalive: true }) so auth travels in headers. Falls back to\n * navigator.sendBeacon (no auth headers possible — the server may reject it,\n * but we never put the key in the URL) only when keepalive fetch is missing.\n *\n * Cannot await a refresh at unload time, so it sends the freshest token already\n * held (currentCredential) rather than the possibly-stale seed the caller passed.\n */\nexport function sonorBeacon(url: string, payload: unknown, apiKey?: string): void {\n const credential = currentCredential(apiKey)\n const body = typeof payload === 'string' ? payload : JSON.stringify(payload)\n try {\n void fetch(url, {\n method: 'POST',\n keepalive: true,\n headers: {\n 'Content-Type': 'application/json',\n 'x-sitekit-version': SITE_KIT_VERSION,\n ...(credential ? { 'x-api-key': credential } : {}),\n },\n body,\n }).catch(() => {\n /* page is closing — best effort */\n })\n } catch {\n try {\n if (typeof navigator !== 'undefined' && navigator.sendBeacon) {\n navigator.sendBeacon(url, new Blob([body], { type: 'application/json' }))\n }\n } catch {\n /* nothing left to try */\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/shared/fetchWithRetry.ts","../src/shared/sonorFetch.ts"],"names":[],"mappings":"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","file":"chunk-XLPU3TEE.mjs","sourcesContent":["/**\n * @sonordev/site-kit shared - Resilient fetch\n *\n * Single source of truth for client-side resilient fetch (forms, SitemapSync).\n * Adds a per-attempt timeout and retries transient failures (network errors,\n * request timeouts, HTTP 429, and 5xx) with exponential backoff.\n *\n * A form submission must survive a brief API blip — a deploy, a cold start, a\n * dropped packet. A single un-retried fetch turning into \"Something went wrong\"\n * is how leads get lost. The explicit abort also matters on its own: a request\n * left to hang until the browser's own network timeout logs a console error\n * (net::ERR_TIMED_OUT) that fails Lighthouse best-practices; an aborted fetch\n * logs nothing.\n */\n\nexport interface FetchRetryOptions {\n /** Number of retries AFTER the first attempt (default 2 → up to 3 tries total). */\n retries?: number\n /** Per-attempt timeout in milliseconds (default 15000). */\n timeoutMs?: number\n}\n\nfunction backoffDelay(attempt: number, response?: Response): number {\n // Honor a Retry-After header on 429 responses when present.\n if (response?.status === 429) {\n const header = response.headers.get('retry-after')\n const seconds = header ? parseInt(header, 10) : NaN\n if (!Number.isNaN(seconds) && seconds > 0) return Math.min(seconds * 1000, 10000)\n }\n // Exponential backoff: 500ms, 1s, 2s, ... capped at 8s.\n return Math.min(8000, 500 * 2 ** attempt)\n}\n\n/**\n * fetch() with a timeout and automatic retries for transient failures.\n *\n * Non-transient responses (2xx, 3xx, and 4xx other than 429) are returned to\n * the caller as-is — only 429/5xx and thrown network/timeout errors are retried.\n * If every attempt fails with a thrown error, the last error is re-thrown.\n */\nexport async function fetchWithRetry(\n url: string,\n init: RequestInit,\n options: FetchRetryOptions = {},\n): Promise<Response> {\n const retries = options.retries ?? 2\n const timeoutMs = options.timeoutMs ?? 15000\n let lastError: unknown\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), timeoutMs)\n try {\n const response = await fetch(url, { ...init, signal: controller.signal })\n clearTimeout(timer)\n\n if ((response.status === 429 || response.status >= 500) && attempt < retries) {\n await new Promise((resolve) => setTimeout(resolve, backoffDelay(attempt, response)))\n continue\n }\n return response\n } catch (error) {\n clearTimeout(timer)\n lastError = error\n // Network failure or timeout (AbortController) — retry while attempts remain.\n if (attempt < retries) {\n await new Promise((resolve) => setTimeout(resolve, backoffDelay(attempt)))\n continue\n }\n }\n }\n\n throw lastError instanceof Error\n ? lastError\n : new Error('Network request failed after multiple attempts. Please try again.')\n}\n","/**\n * @sonordev/site-kit shared - Canonical client transport\n *\n * Single source of truth for how site-kit talks to Sonor from the browser.\n * Every client-side module (analytics, forms, commerce, engage, maps, images,\n * SitemapSync) routes through here instead of bare fetch(), which gives the\n * whole kit, in one place:\n *\n * - per-attempt timeout + retry with backoff (via fetchWithRetry) — a hung\n * request left to the browser's own network timeout logs a console error\n * (net::ERR_TIMED_OUT) that fails Lighthouse best-practices\n * - the x-sitekit-version header on every request, so the platform can see\n * which kit version each site actually runs from live traffic\n * - CREDENTIAL LIFECYCLE: sites on 3.2+ ship a short-lived minted token instead\n * of the raw key. This transport resolves the freshest token (refreshing a\n * stale seed transparently), and on a 401/403 for a token it refreshes once\n * and retries before giving up. A raw key (2.x kit, or the mint-failed\n * fallback) is a pure passthrough — legacy behavior is unchanged.\n * - an auth circuit breaker: after a 401/403 the credential is paused for a few\n * minutes and ONE friendly console.info is emitted — a site on a stale or\n * canceled key must not spam the API or the visitor's console. Keyed by the\n * project (from the token) so it survives token rotation.\n * - sonorBeacon for unload-time telemetry that keeps the credential in headers;\n * navigator.sendBeacon can't set headers and forced the key into the URL,\n * where server and CDN access logs capture it\n *\n * Non-idempotent endpoints (checkout, payment intents, uploads) must pass\n * { retries: 0 } — they still get the timeout, but never an automatic retry.\n */\nimport { fetchWithRetry, type FetchRetryOptions } from './fetchWithRetry'\nimport { SITE_KIT_VERSION } from './version'\nimport {\n credentialBreakerId,\n currentCredential,\n getFreshCredential,\n isSiteToken,\n isTokenMode,\n refreshSiteToken,\n} from './siteToken'\n\nexport interface SonorFetchOptions extends FetchRetryOptions {\n /** Project credential — the minted token (3.2+) or raw key. Sent as x-api-key. */\n apiKey?: string\n}\n\n/** How long a credential stays paused after an auth failure. */\nconst AUTH_BREAK_MS = 5 * 60_000\n\n// breaker id → epoch ms until which requests are paused. Shared on window for\n// the same reason as the token state (see siteToken.ts): duplicated module\n// copies must trip and observe ONE breaker, not one each. Never applies on the\n// server, so a per-module Map there is fine.\nconst BREAKER_STATE_KEY = '__SONOR_AUTH_BREAKER__'\nconst pausedKeys: Map<string, number> = (() => {\n if (typeof window === 'undefined') return new Map()\n const w = window as unknown as Record<string, Map<string, number> | undefined>\n return (w[BREAKER_STATE_KEY] ??= new Map())\n})()\nlet warnedThisPage = false\n\n/** True when a previous 401/403 has paused this credential (browser only). */\nexport function isAuthPaused(credential?: string): boolean {\n if (typeof window === 'undefined') return false\n const id = credentialBreakerId(credential)\n const until = pausedKeys.get(id)\n if (!until) return false\n if (Date.now() >= until) {\n pausedKeys.delete(id)\n return false\n }\n return true\n}\n\nfunction tripBreaker(credential?: string): void {\n pausedKeys.set(credentialBreakerId(credential), Date.now() + AUTH_BREAK_MS)\n if (!warnedThisPage) {\n warnedThisPage = true\n // info, not error: a visitor's console must stay clean (Lighthouse\n // errors-in-console), and copy never names env vars or key formats.\n console.info(\n \"[Sonor] This site couldn't authenticate with Sonor, so data features are paused for a few minutes. If this keeps happening, the site is likely running an outdated API key.\",\n )\n }\n}\n\nexport async function sonorFetch(\n url: string,\n init: RequestInit = {},\n options: SonorFetchOptions = {},\n): Promise<Response> {\n // Resolve the credential to send. In token mode this may transparently refresh\n // a stale seed before the first request; in raw-key mode it's a passthrough.\n let credential = options.apiKey\n if (credential !== undefined || isTokenMode()) {\n credential = await getFreshCredential(options.apiKey)\n }\n\n const headers = new Headers(init.headers || {})\n headers.set('x-sitekit-version', SITE_KIT_VERSION)\n if (credential) {\n if (isTokenMode()) {\n // Token mode: `credential` is the freshest token (refreshed just above if\n // the seed was stale). It MUST override any x-api-key a caller hand-set — a\n // stale build-time seed passed as a header would otherwise pin the request\n // and defeat refresh entirely. Also drop a caller-set Authorization:\n // extractApiKey() server-side prefers `Authorization: Bearer` over\n // x-api-key, so a stale Bearer seed would win even once we set a fresh\n // x-api-key. This is the single place the client credential is chosen — do\n // not re-attach it as a header at call sites.\n headers.set('x-api-key', credential)\n headers.delete('authorization')\n } else if (!headers.has('x-api-key')) {\n // Raw-key mode: legacy passthrough — respect a caller-supplied header.\n headers.set('x-api-key', credential)\n }\n }\n\n if (isAuthPaused(credential)) {\n // Synthetic response keeps every caller's !response.ok path working\n // without a network round trip while the breaker is open.\n return new Response(null, { status: 401, statusText: 'sonor-auth-paused' })\n }\n\n let response = await fetchWithRetry(url, { ...init, headers }, options)\n\n // A token can rotate or expire mid-session. On the first auth failure, try ONE\n // refresh + retry before tripping the breaker — only for token credentials\n // (raw keys have nothing to refresh).\n if (\n (response.status === 401 || response.status === 403) &&\n typeof window !== 'undefined' &&\n isSiteToken(credential)\n ) {\n const refreshed = await refreshSiteToken()\n if (refreshed && refreshed !== credential) {\n const retryHeaders = new Headers(init.headers || {})\n retryHeaders.set('x-sitekit-version', SITE_KIT_VERSION)\n retryHeaders.set('x-api-key', refreshed)\n // Same reason as the initial request: a caller-set stale Bearer would win\n // over our fresh x-api-key server-side, so strip it on the retry too.\n retryHeaders.delete('authorization')\n credential = refreshed\n response = await fetchWithRetry(url, { ...init, headers: retryHeaders }, options)\n }\n }\n\n if (\n (response.status === 401 || response.status === 403) &&\n typeof window !== 'undefined' &&\n credential\n ) {\n tripBreaker(credential)\n }\n\n return response\n}\n\n/**\n * Fire-and-forget telemetry that survives page unload.\n *\n * Uses fetch({ keepalive: true }) so auth travels in headers. Falls back to\n * navigator.sendBeacon (no auth headers possible — the server may reject it,\n * but we never put the key in the URL) only when keepalive fetch is missing.\n *\n * Cannot await a refresh at unload time, so it sends the freshest token already\n * held (currentCredential) rather than the possibly-stale seed the caller passed.\n */\nexport function sonorBeacon(url: string, payload: unknown, apiKey?: string): void {\n const credential = currentCredential(apiKey)\n const body = typeof payload === 'string' ? payload : JSON.stringify(payload)\n try {\n void fetch(url, {\n method: 'POST',\n keepalive: true,\n headers: {\n 'Content-Type': 'application/json',\n 'x-sitekit-version': SITE_KIT_VERSION,\n ...(credential ? { 'x-api-key': credential } : {}),\n },\n body,\n }).catch(() => {\n /* page is closing — best effort */\n })\n } catch {\n try {\n if (typeof navigator !== 'undefined' && navigator.sendBeacon) {\n navigator.sendBeacon(url, new Blob([body], { type: 'application/json' }))\n }\n } catch {\n /* nothing left to try */\n }\n }\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunkQEGUI2Q2_js = require('./chunk-QEGUI2Q2.js');
4
+ var chunkH65OX263_js = require('./chunk-H65OX263.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 chunkQEGUI2Q2_js.sonorFetch(
43
+ const res = await chunkH65OX263_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 chunkQEGUI2Q2_js.sonorFetch(
217
+ const res = await chunkH65OX263_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 chunkQEGUI2Q2_js.sonorFetch(
239
+ const res = await chunkH65OX263_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 chunkQEGUI2Q2_js.sonorFetch(`${config.apiUrl}/public/images/upload`, {
270
+ const res = await chunkH65OX263_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 chunkQEGUI2Q2_js.sonorFetch(
287
+ await chunkH65OX263_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 chunkQEGUI2Q2_js.sonorFetch(
431
+ const res = await chunkH65OX263_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 chunkQEGUI2Q2_js.sonorFetch(
446
+ const res = await chunkH65OX263_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 chunkQEGUI2Q2_js.sonorFetch(
460
+ const res = await chunkH65OX263_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 chunkQEGUI2Q2_js.sonorFetch(`${config.apiUrl}/public/images/upload`, {
477
+ const res = await chunkH65OX263_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 chunkQEGUI2Q2_js.sonorFetch(
487
+ const res = await chunkH65OX263_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 chunkQEGUI2Q2_js.sonorFetch(
514
+ const res = await chunkH65OX263_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-YYAFHIY7.js.map
533
- //# sourceMappingURL=chunk-YYAFHIY7.js.map
532
+ //# sourceMappingURL=chunk-YKUEFRZI.js.map
533
+ //# sourceMappingURL=chunk-YKUEFRZI.js.map