@sonordev/site-kit 6.0.1 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/README.md +11 -0
  2. package/agent-manifest.json +8 -1
  3. package/dist/{AnalyticsProvider-YU6QANW5.mjs → AnalyticsProvider-PO6SSJG2.mjs} +6 -6
  4. package/dist/{AnalyticsProvider-YU6QANW5.mjs.map → AnalyticsProvider-PO6SSJG2.mjs.map} +1 -1
  5. package/dist/{AnalyticsProvider-4RLYTVWO.js → AnalyticsProvider-V6G45QG7.js} +10 -10
  6. package/dist/{AnalyticsProvider-4RLYTVWO.js.map → AnalyticsProvider-V6G45QG7.js.map} +1 -1
  7. package/dist/{ArticleViewTracker-LI44SA4T.mjs → ArticleViewTracker-CML36HJZ.mjs} +5 -5
  8. package/dist/{ArticleViewTracker-LI44SA4T.mjs.map → ArticleViewTracker-CML36HJZ.mjs.map} +1 -1
  9. package/dist/{ArticleViewTracker-OQB2VT73.js → ArticleViewTracker-FE2YWHX4.js} +6 -6
  10. package/dist/{ArticleViewTracker-OQB2VT73.js.map → ArticleViewTracker-FE2YWHX4.js.map} +1 -1
  11. package/dist/ChatWidget-GVNDKGUU.mjs +16 -0
  12. package/dist/{ChatWidget-56SW5ITH.mjs.map → ChatWidget-GVNDKGUU.mjs.map} +1 -1
  13. package/dist/ChatWidget-YL34KOZM.js +25 -0
  14. package/dist/{ChatWidget-HR3OC3WA.js.map → ChatWidget-YL34KOZM.js.map} +1 -1
  15. package/dist/EngageWidget-465O5XUV.mjs +12 -0
  16. package/dist/{EngageWidget-L4X35N2B.mjs.map → EngageWidget-465O5XUV.mjs.map} +1 -1
  17. package/dist/EngageWidget-IQRKRYPG.js +21 -0
  18. package/dist/{EngageWidget-HXGI3ZKG.js.map → EngageWidget-IQRKRYPG.js.map} +1 -1
  19. package/dist/{FileField-N2P6E2PN.js → FileField-F3PFKMIF.js} +6 -6
  20. package/dist/{FileField-N2P6E2PN.js.map → FileField-F3PFKMIF.js.map} +1 -1
  21. package/dist/{FileField-GSTLU42O.mjs → FileField-FWKSBFRX.mjs} +5 -5
  22. package/dist/{FileField-GSTLU42O.mjs.map → FileField-FWKSBFRX.mjs.map} +1 -1
  23. package/dist/{FormSpotlight-QLXOS5LN.js → FormSpotlight-DJQ3P3EX.js} +9 -9
  24. package/dist/{FormSpotlight-QLXOS5LN.js.map → FormSpotlight-DJQ3P3EX.js.map} +1 -1
  25. package/dist/{FormSpotlight-UFATQTN3.mjs → FormSpotlight-K4LP2DMP.mjs} +3 -3
  26. package/dist/{FormSpotlight-UFATQTN3.mjs.map → FormSpotlight-K4LP2DMP.mjs.map} +1 -1
  27. package/dist/{FormStage-4HYDMCYU.js → FormStage-QMGZ3MOT.js} +9 -9
  28. package/dist/{FormStage-4HYDMCYU.js.map → FormStage-QMGZ3MOT.js.map} +1 -1
  29. package/dist/{FormStage-SYOKD5TJ.mjs → FormStage-YKVTHPKV.mjs} +3 -3
  30. package/dist/{FormStage-SYOKD5TJ.mjs.map → FormStage-YKVTHPKV.mjs.map} +1 -1
  31. package/dist/ManagedForm-MLPETHSQ.js +25 -0
  32. package/dist/{ManagedForm-TUSGW5EH.js.map → ManagedForm-MLPETHSQ.js.map} +1 -1
  33. package/dist/ManagedForm-P3L34ALG.mjs +16 -0
  34. package/dist/{ManagedForm-3TDSIRCM.mjs.map → ManagedForm-P3L34ALG.mjs.map} +1 -1
  35. package/dist/{ManagedNewsletterForm-CNGCBA2N.mjs → ManagedNewsletterForm-C5YQH7MP.mjs} +7 -7
  36. package/dist/{ManagedNewsletterForm-CNGCBA2N.mjs.map → ManagedNewsletterForm-C5YQH7MP.mjs.map} +1 -1
  37. package/dist/{ManagedNewsletterForm-XJEPVJRM.js → ManagedNewsletterForm-R4LLZBRQ.js} +8 -8
  38. package/dist/{ManagedNewsletterForm-XJEPVJRM.js.map → ManagedNewsletterForm-R4LLZBRQ.js.map} +1 -1
  39. package/dist/{SignalCore-ARRVP6F7.mjs → SignalCore-BNYNS6P7.mjs} +5 -5
  40. package/dist/{SignalCore-ARRVP6F7.mjs.map → SignalCore-BNYNS6P7.mjs.map} +1 -1
  41. package/dist/{SignalCore-AXK6RCR4.js → SignalCore-CLELIKFI.js} +11 -11
  42. package/dist/{SignalCore-AXK6RCR4.js.map → SignalCore-CLELIKFI.js.map} +1 -1
  43. package/dist/SitemapSync-P7XWL6VV.js +18 -0
  44. package/dist/{SitemapSync-GAGREAX6.js.map → SitemapSync-P7XWL6VV.js.map} +1 -1
  45. package/dist/SitemapSync-SIKJCK7N.mjs +9 -0
  46. package/dist/{SitemapSync-42VKJUOU.mjs.map → SitemapSync-SIKJCK7N.mjs.map} +1 -1
  47. package/dist/analytics/index.js +9 -9
  48. package/dist/analytics/index.mjs +4 -4
  49. package/dist/articles/index.js +2 -2
  50. package/dist/articles/index.mjs +2 -2
  51. package/dist/articles/server-ui.js +1 -1
  52. package/dist/articles/server-ui.mjs +1 -1
  53. package/dist/{chunk-UILVPI2R.js → chunk-36NE4PSS.js} +3 -3
  54. package/dist/{chunk-UILVPI2R.js.map → chunk-36NE4PSS.js.map} +1 -1
  55. package/dist/{chunk-L63DFM4R.mjs → chunk-3DXJHMQM.mjs} +3 -3
  56. package/dist/{chunk-L63DFM4R.mjs.map → chunk-3DXJHMQM.mjs.map} +1 -1
  57. package/dist/{chunk-NYNL6UQV.mjs → chunk-4EJI4IOX.mjs} +63 -50
  58. package/dist/chunk-4EJI4IOX.mjs.map +1 -0
  59. package/dist/{chunk-6URNNS3V.mjs → chunk-6OSHL7H5.mjs} +4 -4
  60. package/dist/{chunk-6URNNS3V.mjs.map → chunk-6OSHL7H5.mjs.map} +1 -1
  61. package/dist/chunk-ACKFL6WA.mjs +6 -0
  62. package/dist/{chunk-7MAHP735.mjs.map → chunk-ACKFL6WA.mjs.map} +1 -1
  63. package/dist/{chunk-4NBJDP6Y.js → chunk-AQUWWATH.js} +4 -4
  64. package/dist/{chunk-4NBJDP6Y.js.map → chunk-AQUWWATH.js.map} +1 -1
  65. package/dist/{chunk-QXPGIOU7.mjs → chunk-BDSNEB3O.mjs} +3 -3
  66. package/dist/{chunk-QXPGIOU7.mjs.map → chunk-BDSNEB3O.mjs.map} +1 -1
  67. package/dist/{chunk-ZRWIMNQF.js → chunk-BGOPF6J2.js} +3 -3
  68. package/dist/{chunk-ZRWIMNQF.js.map → chunk-BGOPF6J2.js.map} +1 -1
  69. package/dist/chunk-BZR6RUIN.mjs +128 -0
  70. package/dist/chunk-BZR6RUIN.mjs.map +1 -0
  71. package/dist/{chunk-XLFTZV34.mjs → chunk-CJX2MC62.mjs} +3 -3
  72. package/dist/{chunk-XLFTZV34.mjs.map → chunk-CJX2MC62.mjs.map} +1 -1
  73. package/dist/{chunk-AQMQOH7V.js → chunk-DQXEYUTD.js} +3 -3
  74. package/dist/{chunk-AQMQOH7V.js.map → chunk-DQXEYUTD.js.map} +1 -1
  75. package/dist/{chunk-PKZMNDZJ.js → chunk-DXBSBWSS.js} +5 -5
  76. package/dist/{chunk-PKZMNDZJ.js.map → chunk-DXBSBWSS.js.map} +1 -1
  77. package/dist/{chunk-NVWUXCUQ.mjs → chunk-ESAPT5JT.mjs} +3 -3
  78. package/dist/{chunk-NVWUXCUQ.mjs.map → chunk-ESAPT5JT.mjs.map} +1 -1
  79. package/dist/{chunk-QP56JXMH.mjs → chunk-F6BYWNHU.mjs} +3 -3
  80. package/dist/{chunk-QP56JXMH.mjs.map → chunk-F6BYWNHU.mjs.map} +1 -1
  81. package/dist/{chunk-NNQG25M2.mjs → chunk-FQAZBJJO.mjs} +3 -3
  82. package/dist/{chunk-NNQG25M2.mjs.map → chunk-FQAZBJJO.mjs.map} +1 -1
  83. package/dist/{chunk-RX4TVHSN.mjs → chunk-H5FCJBAN.mjs} +3 -3
  84. package/dist/{chunk-RX4TVHSN.mjs.map → chunk-H5FCJBAN.mjs.map} +1 -1
  85. package/dist/{chunk-6ZOMIPU5.js → chunk-I4RU3RCS.js} +8 -8
  86. package/dist/{chunk-6ZOMIPU5.js.map → chunk-I4RU3RCS.js.map} +1 -1
  87. package/dist/{chunk-GCZHKHEH.js → chunk-IDJY2JWU.js} +5 -5
  88. package/dist/{chunk-GCZHKHEH.js.map → chunk-IDJY2JWU.js.map} +1 -1
  89. package/dist/{chunk-6YEPFH3Q.js → chunk-ITVQV7DK.js} +10 -10
  90. package/dist/{chunk-6YEPFH3Q.js.map → chunk-ITVQV7DK.js.map} +1 -1
  91. package/dist/chunk-IWSN4DGG.js +132 -0
  92. package/dist/chunk-IWSN4DGG.js.map +1 -0
  93. package/dist/{chunk-P2HOVWJW.js → chunk-K4LLYQFZ.js} +14 -14
  94. package/dist/{chunk-P2HOVWJW.js.map → chunk-K4LLYQFZ.js.map} +1 -1
  95. package/dist/{chunk-XWKY46NU.js → chunk-KDNB6BYH.js} +11 -11
  96. package/dist/{chunk-XWKY46NU.js.map → chunk-KDNB6BYH.js.map} +1 -1
  97. package/dist/{chunk-U6F6AN23.mjs → chunk-KKTSAT7I.mjs} +4 -4
  98. package/dist/{chunk-U6F6AN23.mjs.map → chunk-KKTSAT7I.mjs.map} +1 -1
  99. package/dist/{chunk-BMH2D2EP.mjs → chunk-L3GAEBJU.mjs} +3 -3
  100. package/dist/{chunk-BMH2D2EP.mjs.map → chunk-L3GAEBJU.mjs.map} +1 -1
  101. package/dist/{chunk-TC3JSQUS.js → chunk-LF44SJPP.js} +4 -4
  102. package/dist/{chunk-TC3JSQUS.js.map → chunk-LF44SJPP.js.map} +1 -1
  103. package/dist/{chunk-QD4BNYMM.js → chunk-MZK5APTV.js} +18 -18
  104. package/dist/{chunk-QD4BNYMM.js.map → chunk-MZK5APTV.js.map} +1 -1
  105. package/dist/chunk-NBOBOYMT.js +52 -0
  106. package/dist/chunk-NBOBOYMT.js.map +1 -0
  107. package/dist/{chunk-ZYJYBE5G.js → chunk-NDVKIDMN.js} +4 -4
  108. package/dist/{chunk-ZYJYBE5G.js.map → chunk-NDVKIDMN.js.map} +1 -1
  109. package/dist/{chunk-IDOHDP7D.mjs → chunk-NMKUYGKK.mjs} +4 -4
  110. package/dist/{chunk-IDOHDP7D.mjs.map → chunk-NMKUYGKK.mjs.map} +1 -1
  111. package/dist/chunk-OBKS3CPP.mjs +50 -0
  112. package/dist/chunk-OBKS3CPP.mjs.map +1 -0
  113. package/dist/{chunk-WLCPBZOS.mjs → chunk-OF4V7CSP.mjs} +3 -3
  114. package/dist/{chunk-WLCPBZOS.mjs.map → chunk-OF4V7CSP.mjs.map} +1 -1
  115. package/dist/{chunk-LCYODFNY.mjs → chunk-OQWAJBYA.mjs} +3 -3
  116. package/dist/{chunk-LCYODFNY.mjs.map → chunk-OQWAJBYA.mjs.map} +1 -1
  117. package/dist/chunk-OXA4ZSX2.js +8 -0
  118. package/dist/{chunk-F3EAAAZ3.js.map → chunk-OXA4ZSX2.js.map} +1 -1
  119. package/dist/{chunk-QJ3SMLND.mjs → chunk-QC6VQ2IW.mjs} +3 -3
  120. package/dist/{chunk-QJ3SMLND.mjs.map → chunk-QC6VQ2IW.mjs.map} +1 -1
  121. package/dist/{chunk-UCBBZXJI.js → chunk-QF3XTEXV.js} +4 -4
  122. package/dist/{chunk-UCBBZXJI.js.map → chunk-QF3XTEXV.js.map} +1 -1
  123. package/dist/{chunk-SU42KCQD.mjs → chunk-RGCUND5Q.mjs} +4 -4
  124. package/dist/{chunk-SU42KCQD.mjs.map → chunk-RGCUND5Q.mjs.map} +1 -1
  125. package/dist/{chunk-BWSYPQ5E.js → chunk-RVFOUPK4.js} +6 -6
  126. package/dist/{chunk-BWSYPQ5E.js.map → chunk-RVFOUPK4.js.map} +1 -1
  127. package/dist/{chunk-ULSFOC3J.js → chunk-SDGS2R5O.js} +12 -12
  128. package/dist/{chunk-ULSFOC3J.js.map → chunk-SDGS2R5O.js.map} +1 -1
  129. package/dist/{chunk-BIU234TJ.mjs → chunk-TA3TQTDA.mjs} +8 -8
  130. package/dist/{chunk-BIU234TJ.mjs.map → chunk-TA3TQTDA.mjs.map} +1 -1
  131. package/dist/{chunk-R6UE6MC5.js → chunk-TMNFPVK5.js} +7 -7
  132. package/dist/{chunk-R6UE6MC5.js.map → chunk-TMNFPVK5.js.map} +1 -1
  133. package/dist/{chunk-4VCR6TXK.js → chunk-VK74LC4H.js} +5 -5
  134. package/dist/{chunk-4VCR6TXK.js.map → chunk-VK74LC4H.js.map} +1 -1
  135. package/dist/{chunk-GJCQVVO3.mjs → chunk-XGELGOF6.mjs} +7 -7
  136. package/dist/{chunk-GJCQVVO3.mjs.map → chunk-XGELGOF6.mjs.map} +1 -1
  137. package/dist/{chunk-LZPICBND.js → chunk-XKJLJLQ4.js} +74 -61
  138. package/dist/chunk-XKJLJLQ4.js.map +1 -0
  139. package/dist/{chunk-YTJKVWHY.mjs → chunk-XOYQKFKI.mjs} +4 -4
  140. package/dist/{chunk-YTJKVWHY.mjs.map → chunk-XOYQKFKI.mjs.map} +1 -1
  141. package/dist/{chunk-NVOYCK2S.js → chunk-Y53BIB7A.js} +14 -14
  142. package/dist/{chunk-NVOYCK2S.js.map → chunk-Y53BIB7A.js.map} +1 -1
  143. package/dist/{chunk-GKPVGVHY.mjs → chunk-YKNXBWPZ.mjs} +3 -3
  144. package/dist/{chunk-GKPVGVHY.mjs.map → chunk-YKNXBWPZ.mjs.map} +1 -1
  145. package/dist/{chunk-KUHMHKG5.mjs → chunk-YP5WAFTI.mjs} +4 -4
  146. package/dist/{chunk-KUHMHKG5.mjs.map → chunk-YP5WAFTI.mjs.map} +1 -1
  147. package/dist/{chunk-FKFVN3GT.js → chunk-YS7Y2PQG.js} +8 -8
  148. package/dist/{chunk-FKFVN3GT.js.map → chunk-YS7Y2PQG.js.map} +1 -1
  149. package/dist/{chunk-5ABTBPPK.js → chunk-ZQJGCQHC.js} +15 -15
  150. package/dist/{chunk-5ABTBPPK.js.map → chunk-ZQJGCQHC.js.map} +1 -1
  151. package/dist/{chunk-LFASEDBO.mjs → chunk-ZQSJK65K.mjs} +3 -3
  152. package/dist/{chunk-LFASEDBO.mjs.map → chunk-ZQSJK65K.mjs.map} +1 -1
  153. package/dist/cli/index.js +3 -3
  154. package/dist/cli/index.mjs +1 -1
  155. package/dist/client/index.js +4 -4
  156. package/dist/client/index.mjs +3 -3
  157. package/dist/commerce/index.js +57 -57
  158. package/dist/commerce/index.mjs +5 -5
  159. package/dist/cta-bar/CtaBar.d.ts +71 -0
  160. package/dist/cta-bar/CtaBar.d.ts.map +1 -0
  161. package/dist/cta-bar/CtaBarBehavior.d.ts +46 -0
  162. package/dist/cta-bar/CtaBarBehavior.d.ts.map +1 -0
  163. package/dist/cta-bar/client.d.ts +46 -0
  164. package/dist/cta-bar/client.d.ts.map +1 -0
  165. package/dist/cta-bar/client.js +23 -0
  166. package/dist/cta-bar/client.js.map +1 -0
  167. package/dist/cta-bar/client.mjs +6 -0
  168. package/dist/cta-bar/client.mjs.map +1 -0
  169. package/dist/cta-bar/index.d.ts +12 -0
  170. package/dist/cta-bar/index.d.ts.map +1 -0
  171. package/dist/cta-bar/index.js +230 -0
  172. package/dist/cta-bar/index.js.map +1 -0
  173. package/dist/cta-bar/index.mjs +224 -0
  174. package/dist/cta-bar/index.mjs.map +1 -0
  175. package/dist/cta-bar/styles.d.ts +46 -0
  176. package/dist/cta-bar/styles.d.ts.map +1 -0
  177. package/dist/engage/ChatWidget.d.ts.map +1 -1
  178. package/dist/engage/EchoUiActions.d.ts.map +1 -1
  179. package/dist/engage/index.js +14 -13
  180. package/dist/engage/index.js.map +1 -1
  181. package/dist/engage/index.mjs +8 -7
  182. package/dist/engage/index.mjs.map +1 -1
  183. package/dist/fleet/index.js +8 -8
  184. package/dist/fleet/index.mjs +4 -4
  185. package/dist/forms/index.js +22 -22
  186. package/dist/forms/index.mjs +9 -9
  187. package/dist/forms/server.js +10 -10
  188. package/dist/forms/server.mjs +8 -8
  189. package/dist/forms/static.js +7 -7
  190. package/dist/forms/static.mjs +6 -6
  191. package/dist/images/index.js +11 -11
  192. package/dist/images/index.mjs +4 -4
  193. package/dist/index.js +63 -63
  194. package/dist/index.mjs +9 -9
  195. package/dist/layout/client.js +8 -8
  196. package/dist/layout/client.mjs +7 -7
  197. package/dist/layout/index.js +10 -10
  198. package/dist/layout/index.mjs +8 -8
  199. package/dist/maps/index.js +5 -5
  200. package/dist/maps/index.mjs +3 -3
  201. package/dist/search/index.js +4 -4
  202. package/dist/search/index.mjs +3 -3
  203. package/dist/seo/client.js +5 -5
  204. package/dist/seo/client.mjs +4 -4
  205. package/dist/seo/index.js +5 -5
  206. package/dist/seo/index.mjs +4 -4
  207. package/dist/server/index.js +3 -3
  208. package/dist/server/index.mjs +2 -2
  209. package/dist/shared/build-entries.d.ts +4 -1
  210. package/dist/shared/build-entries.d.ts.map +1 -1
  211. package/dist/shared/glass.d.ts +51 -0
  212. package/dist/shared/glass.d.ts.map +1 -0
  213. package/dist/shared/version.d.ts +1 -1
  214. package/dist/signal/index.js +11 -11
  215. package/dist/signal/index.mjs +2 -2
  216. package/dist/sync/index.js +17 -17
  217. package/dist/sync/index.mjs +4 -4
  218. package/package.json +6 -1
  219. package/skills/site-kit/SKILL.md +6 -0
  220. package/dist/ChatWidget-56SW5ITH.mjs +0 -15
  221. package/dist/ChatWidget-HR3OC3WA.js +0 -24
  222. package/dist/EngageWidget-HXGI3ZKG.js +0 -21
  223. package/dist/EngageWidget-L4X35N2B.mjs +0 -12
  224. package/dist/ManagedForm-3TDSIRCM.mjs +0 -16
  225. package/dist/ManagedForm-TUSGW5EH.js +0 -25
  226. package/dist/SitemapSync-42VKJUOU.mjs +0 -9
  227. package/dist/SitemapSync-GAGREAX6.js +0 -18
  228. package/dist/chunk-7MAHP735.mjs +0 -6
  229. package/dist/chunk-F3EAAAZ3.js +0 -8
  230. package/dist/chunk-LZPICBND.js.map +0 -1
  231. package/dist/chunk-NYNL6UQV.mjs.map +0 -1
@@ -3,7 +3,7 @@
3
3
 
4
4
  var chunkJONWE26J_js = require('./chunk-JONWE26J.js');
5
5
  var chunk5RNAUYWE_js = require('./chunk-5RNAUYWE.js');
6
- var chunk5ABTBPPK_js = require('./chunk-5ABTBPPK.js');
6
+ var chunkZQJGCQHC_js = require('./chunk-ZQJGCQHC.js');
7
7
  var react = require('react');
8
8
 
9
9
  var SYNC_STAMP_KEY = "_sk_sitemap_synced_at";
@@ -47,7 +47,7 @@ function storeSyncedHash(hash) {
47
47
  }
48
48
  async function parseSitemap(sitemapUrl, debug) {
49
49
  try {
50
- const response = await chunk5ABTBPPK_js.sonorFetch(sitemapUrl);
50
+ const response = await chunkZQJGCQHC_js.sonorFetch(sitemapUrl);
51
51
  if (!response.ok) {
52
52
  if (debug) console.warn("[SitemapSync] Failed to fetch sitemap:", response.status);
53
53
  return [];
@@ -97,7 +97,7 @@ async function syncToPortal(entries, apiUrl, apiKey, site, debug, mode = "additi
97
97
  try {
98
98
  const target = chunk5RNAUYWE_js.resolveAnalyticsTarget({ ...gate, apiUrl, apiKey });
99
99
  if (!target) return { success: false, created: 0, updated: 0 };
100
- const response = await chunk5ABTBPPK_js.sonorFetch(`${target.apiUrl}/api/public/seo/register-sitemap`, {
100
+ const response = await chunkZQJGCQHC_js.sonorFetch(`${target.apiUrl}/api/public/seo/register-sitemap`, {
101
101
  method: "POST",
102
102
  headers: { "Content-Type": "application/json" },
103
103
  body: JSON.stringify({
@@ -191,5 +191,5 @@ function SitemapSync({
191
191
  }
192
192
 
193
193
  exports.SitemapSync = SitemapSync;
194
- //# sourceMappingURL=chunk-4VCR6TXK.js.map
195
- //# sourceMappingURL=chunk-4VCR6TXK.js.map
194
+ //# sourceMappingURL=chunk-VK74LC4H.js.map
195
+ //# sourceMappingURL=chunk-VK74LC4H.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/SitemapSync.tsx"],"names":["sonorFetch","locToPath","isMalformedSitemapPath","resolveAnalyticsTarget","inferPageType","useRef","useEffect"],"mappings":"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","file":"chunk-4VCR6TXK.js","sourcesContent":["/**\n * SitemapSync - Automatically sync sitemap.xml to Portal API\n *\n * Client-only component. Lives at package root so the main entry does not\n * pull in seo/ (and server-only code). For use in SiteKitLayout and\n * from @sonordev/site-kit/seo.\n *\n * @example\n * ```tsx\n * import { SitemapSync } from '@sonordev/site-kit'\n * // or\n * import { SitemapSync } from '@sonordev/site-kit/seo'\n * ```\n */\n\n'use client'\n\nimport { useEffect, useRef } from 'react'\nimport { sonorFetch } from './shared/sonorFetch'\nimport { resolveAnalyticsTarget, type AnalyticsGateOptions } from './shared/reporting-gate'\n// Single source of truth for page-type inference + path normalization, shared\n// with createSitemap (build) and the register-sitemap CLI. Pure string logic,\n// safe in the browser.\nimport { inferPageType, locToPath, isMalformedSitemapPath } from './sitemap/shared'\n\ninterface SitemapSyncProps extends AnalyticsGateOptions {\n /** Custom sitemap URL (defaults to /sitemap.xml) */\n sitemapUrl?: string\n /** How often to re-sync in minutes (0 = only on mount, default: 60) */\n syncInterval?: number\n /** Enable debug logging */\n debug?: boolean\n /**\n * Sync mode:\n * - 'additive' (default for runtime): adds/updates pages but never deletes existing ones\n * - 'full-replace': replaces the entire page set (use only for build-time sync via createSitemap)\n */\n mode?: 'additive' | 'full-replace'\n}\n\ninterface SitemapEntry {\n path: string\n lastmod?: string\n changefreq?: string\n priority?: number\n pageType?: string\n}\n\n/**\n * Per-browser-session sync throttle. Build-time sync (createSitemap) is the\n * canonical source of truth; runtime SitemapSync is only a safety net — so\n * re-registering the sitemap on every full page load of every visitor is pure\n * waste (fetch + DOMParser on the visitor's main thread, plus a write per\n * pageview against the API). Stamp the last successful sync in sessionStorage\n * and skip while inside the throttle window.\n */\nconst SYNC_STAMP_KEY = '_sk_sitemap_synced_at'\nconst SYNC_HASH_KEY = '_sk_sitemap_hash'\n\nfunction isRecentlySynced(throttleMinutes: number): boolean {\n try {\n const stamp = sessionStorage.getItem(SYNC_STAMP_KEY)\n if (!stamp) return false\n const elapsed = Date.now() - parseInt(stamp, 10)\n return elapsed >= 0 && elapsed < throttleMinutes * 60 * 1000\n } catch {\n return false // storage unavailable (private mode) — sync as before\n }\n}\n\nfunction stampSynced(): void {\n try {\n sessionStorage.setItem(SYNC_STAMP_KEY, Date.now().toString())\n } catch {\n /* storage unavailable — throttle simply won't apply */\n }\n}\n\n/**\n * Content-hash guard (localStorage, so it survives across sessions): the\n * sitemap of a static site only changes at deploy, so once ONE sync of a given\n * sitemap succeeded from this browser, re-POSTing the identical entry set is\n * pure API load. Hash the parsed entries; skip the POST when unchanged.\n * Keyed by sitemap URL so multiple SitemapSync instances don't collide.\n */\nfunction hashEntries(sitemapUrl: string, entries: SitemapEntry[]): string {\n const text = entries\n .map(e => `${e.path}|${e.lastmod ?? ''}|${e.changefreq ?? ''}|${e.priority ?? ''}`)\n .join('\\n')\n let hash = 0\n for (let i = 0; i < text.length; i++) {\n hash = ((hash << 5) - hash + text.charCodeAt(i)) | 0\n }\n return `${sitemapUrl}:${entries.length}:${hash.toString(16)}`\n}\n\nfunction isAlreadySyncedHash(hash: string): boolean {\n try {\n return localStorage.getItem(SYNC_HASH_KEY) === hash\n } catch {\n return false\n }\n}\n\nfunction storeSyncedHash(hash: string): void {\n try {\n localStorage.setItem(SYNC_HASH_KEY, hash)\n } catch {\n /* storage unavailable — guard simply won't apply */\n }\n}\n\nasync function parseSitemap(sitemapUrl: string, debug: boolean): Promise<SitemapEntry[]> {\n try {\n const response = await sonorFetch(sitemapUrl)\n if (!response.ok) {\n if (debug) console.warn('[SitemapSync] Failed to fetch sitemap:', response.status)\n return []\n }\n\n const text = await response.text()\n const parser = new DOMParser()\n const doc = parser.parseFromString(text, 'application/xml')\n\n const parseError = doc.querySelector('parsererror')\n if (parseError) {\n if (debug) console.warn('[SitemapSync] Sitemap parse error:', parseError.textContent)\n return []\n }\n\n const urls = doc.querySelectorAll('url')\n const entries: SitemapEntry[] = []\n\n urls.forEach(url => {\n const loc = url.querySelector('loc')?.textContent?.trim()\n if (!loc) return\n\n const path = locToPath(loc)\n\n // Reject malformed paths (embedded domains, double protocols, etc.)\n if (isMalformedSitemapPath(path)) {\n if (debug) console.warn(`[SitemapSync] Skipping malformed path: ${path}`)\n return\n }\n\n const lastmod = url.querySelector('lastmod')?.textContent || undefined\n const changefreq = url.querySelector('changefreq')?.textContent || undefined\n const priorityStr = url.querySelector('priority')?.textContent\n const priority = priorityStr ? parseFloat(priorityStr) : undefined\n\n entries.push({ path, lastmod, changefreq, priority })\n })\n\n if (debug) {\n console.log(`[SitemapSync] Parsed ${entries.length} entries from sitemap`)\n }\n\n return entries\n } catch (error) {\n if (debug) console.error('[SitemapSync] Error parsing sitemap:', error)\n return []\n }\n}\n\nasync function syncToPortal(\n entries: SitemapEntry[],\n apiUrl: string,\n apiKey: string,\n site: string,\n debug: boolean,\n mode: 'additive' | 'full-replace' = 'additive',\n gate: AnalyticsGateOptions = {},\n): Promise<{ success: boolean; created: number; updated: number }> {\n if (!apiKey) {\n if (debug) console.warn('[SitemapSync] No API key configured')\n return { success: false, created: 0, updated: 0 }\n }\n\n if (entries.length === 0) {\n if (debug) console.log('[SitemapSync] No entries to sync')\n return { success: true, created: 0, updated: 0 }\n }\n\n try {\n // Registration is idempotent in both modes (same payload → same final\n // state), so retrying a timed-out attempt is safe.\n const target = resolveAnalyticsTarget({ ...gate, apiUrl, apiKey })\n if (!target) return { success: false, created: 0, updated: 0 }\n const response = await sonorFetch(`${target.apiUrl}/api/public/seo/register-sitemap`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n entries: entries.map(e => ({\n path: e.path,\n priority: e.priority,\n changefreq: e.changefreq,\n pageType: inferPageType(e.path),\n })),\n mode,\n // Sub-site host — tagged on every seo_pages row so the dashboard\n // can scope the page tree to one microsite. Resolved by\n // SiteKitClientProviders (see __SITE_KIT_SITE__).\n ...(site ? { site } : {}),\n }),\n }, { apiKey: target.apiKey, retries: 2 })\n\n if (!response?.ok) {\n if (debug) console.error('[SitemapSync] API error:', response?.status, response?.statusText)\n return { success: false, created: 0, updated: 0 }\n }\n\n const result = await response.json()\n\n if (debug) {\n console.log(`[SitemapSync] Synced: ${result.created} created, ${result.updated} updated`)\n }\n\n return {\n success: true,\n created: result.created || 0,\n updated: result.updated || 0,\n }\n } catch (error) {\n if (debug) console.error('[SitemapSync] Sync error:', error)\n return { success: false, created: 0, updated: 0 }\n }\n}\n\nexport function SitemapSync({\n sitemapUrl = '/sitemap.xml',\n syncInterval = 60,\n debug = false,\n mode = 'additive',\n apiUrl: propApiUrl,\n apiKey: propApiKey,\n allowInFrame = false,\n allowLocalhost = false,\n}: SitemapSyncProps) {\n const hasSyncedRef = useRef(false)\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null)\n\n useEffect(() => {\n // Build-time sync via createSitemap is the canonical source of truth, but\n // it can fail during ISR revalidation (app/ dir unavailable on serverless).\n // Runtime SitemapSync in additive mode is a safe fallback — it adds/updates\n // pages that may be missing without ever deleting existing ones.\n // Full-replace is never safe at runtime — always force additive.\n const effectiveMode: 'additive' | 'full-replace' = 'additive'\n\n // Throttle window: reuse syncInterval when periodic syncing is on,\n // otherwise default to 60 minutes for the on-mount sync.\n const throttleMinutes = syncInterval > 0 ? syncInterval : 60\n\n const doSync = async () => {\n const gate = { apiUrl: propApiUrl, apiKey: propApiKey, allowInFrame, allowLocalhost, debug }\n const target = resolveAnalyticsTarget(gate)\n if (!target) return\n const { apiUrl, apiKey } = target\n const site = (window as any).__SITE_KIT_SITE__ || window.location.host || ''\n\n if (isRecentlySynced(throttleMinutes)) {\n if (debug) console.log('[SitemapSync] Skipped — synced within the last', throttleMinutes, 'min this session')\n return\n }\n\n if (debug) console.log('[SitemapSync] Starting sitemap sync...', site ? `(site: ${site})` : '')\n\n const entries = await parseSitemap(sitemapUrl, debug)\n\n if (entries.length > 0) {\n const hash = hashEntries(sitemapUrl, entries)\n if (isAlreadySyncedHash(hash)) {\n // This exact sitemap already synced from this browser — the server\n // state can't be improved by re-POSTing it. Stamp the session so we\n // don't even re-fetch/parse for the rest of the throttle window.\n stampSynced()\n if (debug) console.log('[SitemapSync] Skipped POST — sitemap unchanged since last successful sync')\n return\n }\n const result = await syncToPortal(entries, apiUrl, apiKey, site, debug, effectiveMode, gate)\n if (result.success) {\n stampSynced()\n storeSyncedHash(hash)\n }\n }\n }\n\n if (!resolveAnalyticsTarget({ apiUrl: propApiUrl, apiKey: propApiKey, allowInFrame, allowLocalhost, debug })) return\n\n if (!hasSyncedRef.current) {\n hasSyncedRef.current = true\n doSync()\n }\n\n if (syncInterval > 0) {\n intervalRef.current = setInterval(doSync, syncInterval * 60 * 1000)\n }\n\n return () => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current)\n }\n }\n }, [sitemapUrl, syncInterval, debug, mode, propApiUrl, propApiKey, allowInFrame, allowLocalhost])\n\n return null\n}\n"]}
1
+ {"version":3,"sources":["../src/SitemapSync.tsx"],"names":["sonorFetch","locToPath","isMalformedSitemapPath","resolveAnalyticsTarget","inferPageType","useRef","useEffect"],"mappings":"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","file":"chunk-VK74LC4H.js","sourcesContent":["/**\n * SitemapSync - Automatically sync sitemap.xml to Portal API\n *\n * Client-only component. Lives at package root so the main entry does not\n * pull in seo/ (and server-only code). For use in SiteKitLayout and\n * from @sonordev/site-kit/seo.\n *\n * @example\n * ```tsx\n * import { SitemapSync } from '@sonordev/site-kit'\n * // or\n * import { SitemapSync } from '@sonordev/site-kit/seo'\n * ```\n */\n\n'use client'\n\nimport { useEffect, useRef } from 'react'\nimport { sonorFetch } from './shared/sonorFetch'\nimport { resolveAnalyticsTarget, type AnalyticsGateOptions } from './shared/reporting-gate'\n// Single source of truth for page-type inference + path normalization, shared\n// with createSitemap (build) and the register-sitemap CLI. Pure string logic,\n// safe in the browser.\nimport { inferPageType, locToPath, isMalformedSitemapPath } from './sitemap/shared'\n\ninterface SitemapSyncProps extends AnalyticsGateOptions {\n /** Custom sitemap URL (defaults to /sitemap.xml) */\n sitemapUrl?: string\n /** How often to re-sync in minutes (0 = only on mount, default: 60) */\n syncInterval?: number\n /** Enable debug logging */\n debug?: boolean\n /**\n * Sync mode:\n * - 'additive' (default for runtime): adds/updates pages but never deletes existing ones\n * - 'full-replace': replaces the entire page set (use only for build-time sync via createSitemap)\n */\n mode?: 'additive' | 'full-replace'\n}\n\ninterface SitemapEntry {\n path: string\n lastmod?: string\n changefreq?: string\n priority?: number\n pageType?: string\n}\n\n/**\n * Per-browser-session sync throttle. Build-time sync (createSitemap) is the\n * canonical source of truth; runtime SitemapSync is only a safety net — so\n * re-registering the sitemap on every full page load of every visitor is pure\n * waste (fetch + DOMParser on the visitor's main thread, plus a write per\n * pageview against the API). Stamp the last successful sync in sessionStorage\n * and skip while inside the throttle window.\n */\nconst SYNC_STAMP_KEY = '_sk_sitemap_synced_at'\nconst SYNC_HASH_KEY = '_sk_sitemap_hash'\n\nfunction isRecentlySynced(throttleMinutes: number): boolean {\n try {\n const stamp = sessionStorage.getItem(SYNC_STAMP_KEY)\n if (!stamp) return false\n const elapsed = Date.now() - parseInt(stamp, 10)\n return elapsed >= 0 && elapsed < throttleMinutes * 60 * 1000\n } catch {\n return false // storage unavailable (private mode) — sync as before\n }\n}\n\nfunction stampSynced(): void {\n try {\n sessionStorage.setItem(SYNC_STAMP_KEY, Date.now().toString())\n } catch {\n /* storage unavailable — throttle simply won't apply */\n }\n}\n\n/**\n * Content-hash guard (localStorage, so it survives across sessions): the\n * sitemap of a static site only changes at deploy, so once ONE sync of a given\n * sitemap succeeded from this browser, re-POSTing the identical entry set is\n * pure API load. Hash the parsed entries; skip the POST when unchanged.\n * Keyed by sitemap URL so multiple SitemapSync instances don't collide.\n */\nfunction hashEntries(sitemapUrl: string, entries: SitemapEntry[]): string {\n const text = entries\n .map(e => `${e.path}|${e.lastmod ?? ''}|${e.changefreq ?? ''}|${e.priority ?? ''}`)\n .join('\\n')\n let hash = 0\n for (let i = 0; i < text.length; i++) {\n hash = ((hash << 5) - hash + text.charCodeAt(i)) | 0\n }\n return `${sitemapUrl}:${entries.length}:${hash.toString(16)}`\n}\n\nfunction isAlreadySyncedHash(hash: string): boolean {\n try {\n return localStorage.getItem(SYNC_HASH_KEY) === hash\n } catch {\n return false\n }\n}\n\nfunction storeSyncedHash(hash: string): void {\n try {\n localStorage.setItem(SYNC_HASH_KEY, hash)\n } catch {\n /* storage unavailable — guard simply won't apply */\n }\n}\n\nasync function parseSitemap(sitemapUrl: string, debug: boolean): Promise<SitemapEntry[]> {\n try {\n const response = await sonorFetch(sitemapUrl)\n if (!response.ok) {\n if (debug) console.warn('[SitemapSync] Failed to fetch sitemap:', response.status)\n return []\n }\n\n const text = await response.text()\n const parser = new DOMParser()\n const doc = parser.parseFromString(text, 'application/xml')\n\n const parseError = doc.querySelector('parsererror')\n if (parseError) {\n if (debug) console.warn('[SitemapSync] Sitemap parse error:', parseError.textContent)\n return []\n }\n\n const urls = doc.querySelectorAll('url')\n const entries: SitemapEntry[] = []\n\n urls.forEach(url => {\n const loc = url.querySelector('loc')?.textContent?.trim()\n if (!loc) return\n\n const path = locToPath(loc)\n\n // Reject malformed paths (embedded domains, double protocols, etc.)\n if (isMalformedSitemapPath(path)) {\n if (debug) console.warn(`[SitemapSync] Skipping malformed path: ${path}`)\n return\n }\n\n const lastmod = url.querySelector('lastmod')?.textContent || undefined\n const changefreq = url.querySelector('changefreq')?.textContent || undefined\n const priorityStr = url.querySelector('priority')?.textContent\n const priority = priorityStr ? parseFloat(priorityStr) : undefined\n\n entries.push({ path, lastmod, changefreq, priority })\n })\n\n if (debug) {\n console.log(`[SitemapSync] Parsed ${entries.length} entries from sitemap`)\n }\n\n return entries\n } catch (error) {\n if (debug) console.error('[SitemapSync] Error parsing sitemap:', error)\n return []\n }\n}\n\nasync function syncToPortal(\n entries: SitemapEntry[],\n apiUrl: string,\n apiKey: string,\n site: string,\n debug: boolean,\n mode: 'additive' | 'full-replace' = 'additive',\n gate: AnalyticsGateOptions = {},\n): Promise<{ success: boolean; created: number; updated: number }> {\n if (!apiKey) {\n if (debug) console.warn('[SitemapSync] No API key configured')\n return { success: false, created: 0, updated: 0 }\n }\n\n if (entries.length === 0) {\n if (debug) console.log('[SitemapSync] No entries to sync')\n return { success: true, created: 0, updated: 0 }\n }\n\n try {\n // Registration is idempotent in both modes (same payload → same final\n // state), so retrying a timed-out attempt is safe.\n const target = resolveAnalyticsTarget({ ...gate, apiUrl, apiKey })\n if (!target) return { success: false, created: 0, updated: 0 }\n const response = await sonorFetch(`${target.apiUrl}/api/public/seo/register-sitemap`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n entries: entries.map(e => ({\n path: e.path,\n priority: e.priority,\n changefreq: e.changefreq,\n pageType: inferPageType(e.path),\n })),\n mode,\n // Sub-site host — tagged on every seo_pages row so the dashboard\n // can scope the page tree to one microsite. Resolved by\n // SiteKitClientProviders (see __SITE_KIT_SITE__).\n ...(site ? { site } : {}),\n }),\n }, { apiKey: target.apiKey, retries: 2 })\n\n if (!response?.ok) {\n if (debug) console.error('[SitemapSync] API error:', response?.status, response?.statusText)\n return { success: false, created: 0, updated: 0 }\n }\n\n const result = await response.json()\n\n if (debug) {\n console.log(`[SitemapSync] Synced: ${result.created} created, ${result.updated} updated`)\n }\n\n return {\n success: true,\n created: result.created || 0,\n updated: result.updated || 0,\n }\n } catch (error) {\n if (debug) console.error('[SitemapSync] Sync error:', error)\n return { success: false, created: 0, updated: 0 }\n }\n}\n\nexport function SitemapSync({\n sitemapUrl = '/sitemap.xml',\n syncInterval = 60,\n debug = false,\n mode = 'additive',\n apiUrl: propApiUrl,\n apiKey: propApiKey,\n allowInFrame = false,\n allowLocalhost = false,\n}: SitemapSyncProps) {\n const hasSyncedRef = useRef(false)\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null)\n\n useEffect(() => {\n // Build-time sync via createSitemap is the canonical source of truth, but\n // it can fail during ISR revalidation (app/ dir unavailable on serverless).\n // Runtime SitemapSync in additive mode is a safe fallback — it adds/updates\n // pages that may be missing without ever deleting existing ones.\n // Full-replace is never safe at runtime — always force additive.\n const effectiveMode: 'additive' | 'full-replace' = 'additive'\n\n // Throttle window: reuse syncInterval when periodic syncing is on,\n // otherwise default to 60 minutes for the on-mount sync.\n const throttleMinutes = syncInterval > 0 ? syncInterval : 60\n\n const doSync = async () => {\n const gate = { apiUrl: propApiUrl, apiKey: propApiKey, allowInFrame, allowLocalhost, debug }\n const target = resolveAnalyticsTarget(gate)\n if (!target) return\n const { apiUrl, apiKey } = target\n const site = (window as any).__SITE_KIT_SITE__ || window.location.host || ''\n\n if (isRecentlySynced(throttleMinutes)) {\n if (debug) console.log('[SitemapSync] Skipped — synced within the last', throttleMinutes, 'min this session')\n return\n }\n\n if (debug) console.log('[SitemapSync] Starting sitemap sync...', site ? `(site: ${site})` : '')\n\n const entries = await parseSitemap(sitemapUrl, debug)\n\n if (entries.length > 0) {\n const hash = hashEntries(sitemapUrl, entries)\n if (isAlreadySyncedHash(hash)) {\n // This exact sitemap already synced from this browser — the server\n // state can't be improved by re-POSTing it. Stamp the session so we\n // don't even re-fetch/parse for the rest of the throttle window.\n stampSynced()\n if (debug) console.log('[SitemapSync] Skipped POST — sitemap unchanged since last successful sync')\n return\n }\n const result = await syncToPortal(entries, apiUrl, apiKey, site, debug, effectiveMode, gate)\n if (result.success) {\n stampSynced()\n storeSyncedHash(hash)\n }\n }\n }\n\n if (!resolveAnalyticsTarget({ apiUrl: propApiUrl, apiKey: propApiKey, allowInFrame, allowLocalhost, debug })) return\n\n if (!hasSyncedRef.current) {\n hasSyncedRef.current = true\n doSync()\n }\n\n if (syncInterval > 0) {\n intervalRef.current = setInterval(doSync, syncInterval * 60 * 1000)\n }\n\n return () => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current)\n }\n }\n }, [sitemapUrl, syncInterval, debug, mode, propApiUrl, propApiKey, allowInFrame, allowLocalhost])\n\n return null\n}\n"]}
@@ -1,10 +1,10 @@
1
1
  'use client';
2
- import { countStageViews, countStageQuestions, useFieldControls } from './chunk-QP56JXMH.mjs';
3
- import { HoneypotField, NativeFallbackFields, nativeFormProps } from './chunk-WLCPBZOS.mjs';
2
+ import { countStageViews, countStageQuestions, useFieldControls } from './chunk-F6BYWNHU.mjs';
3
+ import { HoneypotField, NativeFallbackFields, nativeFormProps } from './chunk-OF4V7CSP.mjs';
4
4
  import { DelightStyles, FormMomentum, FormField } from './chunk-VJV7WUR2.mjs';
5
- import { useFormTracking, useForm } from './chunk-KUHMHKG5.mjs';
5
+ import { useFormTracking, useForm } from './chunk-YP5WAFTI.mjs';
6
6
  import { isFieldVisible, validateField, isFieldComplete, isDisplayOnly } from './chunk-QRHVMTHF.mjs';
7
- import { submitForm, DEFAULT_FORM_SUCCESS_MESSAGE } from './chunk-LCYODFNY.mjs';
7
+ import { submitForm, DEFAULT_FORM_SUCCESS_MESSAGE } from './chunk-OQWAJBYA.mjs';
8
8
  import { DEFAULT_HONEYPOT_FIELD } from './chunk-TMVKRQGJ.mjs';
9
9
  import { useState, useRef, useMemo, useEffect, useCallback } from 'react';
10
10
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
@@ -63,7 +63,7 @@ function FormClient({
63
63
  return;
64
64
  }
65
65
  let cancelled = false;
66
- const load = resolvedExperience === "stage" ? import('./FormStage-SYOKD5TJ.mjs').then((m) => m.FormStage) : import('./FormSpotlight-UFATQTN3.mjs').then((m) => m.FormSpotlight);
66
+ const load = resolvedExperience === "stage" ? import('./FormStage-YKVTHPKV.mjs').then((m) => m.FormStage) : import('./FormSpotlight-K4LP2DMP.mjs').then((m) => m.FormSpotlight);
67
67
  load.then((Component) => {
68
68
  if (!cancelled) setExperience(() => Component);
69
69
  }).catch((err) => {
@@ -479,5 +479,5 @@ function ManagedForm({
479
479
  }
480
480
 
481
481
  export { FormClient, ManagedForm };
482
- //# sourceMappingURL=chunk-GJCQVVO3.mjs.map
483
- //# sourceMappingURL=chunk-GJCQVVO3.mjs.map
482
+ //# sourceMappingURL=chunk-XGELGOF6.mjs.map
483
+ //# sourceMappingURL=chunk-XGELGOF6.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/forms/FormClient.tsx","../src/forms/ManagedForm.tsx"],"names":["currentStepConfig","isFieldVisible","validateField","jsx"],"mappings":"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","file":"chunk-GJCQVVO3.mjs","sourcesContent":["/**\n * @sonordev/site-kit/forms - Form Client Component\n * \n * Handles form state, validation, and submission\n */\n\n'use client'\n\nimport React, { useState, useCallback, useMemo, useRef, useEffect } from 'react'\nimport { useFormTracking } from './useFormTracking'\nimport * as fieldRules from './field-rules'\nimport { FormField } from './FormField'\nimport { submitForm, DEFAULT_HONEYPOT_FIELD } from './submitForm'\nimport type { \n ManagedFormConfig, \n FormField as FormFieldType, \n FormRenderProps,\n FormSubmission,\n} from './types'\nimport { DEFAULT_FORM_SUCCESS_MESSAGE } from './defaultSuccessMessage'\nimport { DelightStyles, FormMomentum } from './delight'\nimport { HoneypotField } from './HoneypotField'\nimport { useFieldControls } from './field-controls'\nimport { nativeFormProps, NativeFallbackFields } from './native-fallback'\nimport { countStageViews, countStageQuestions } from './experience-plan'\nimport type { ExperienceRenderProps, FormExperience } from './types'\n\ninterface FormClientProps {\n config: ManagedFormConfig\n className?: string\n onSuccess?: (submission: FormSubmission) => void\n onError?: (error: Error) => void\n customRender?: (props: FormRenderProps) => React.ReactNode\n /**\n * Pre-fill field values by slug. For context the page already has and the\n * visitor should not retype: an email captured earlier in a conversation,\n * the service they were reading about, an estimate the assistant just\n * produced. Applied ON TOP of each field's configured default_value.\n *\n * Unknown slugs are ignored, so a stale key cannot break the form.\n */\n defaultValues?: Record<string, unknown>\n /**\n * Which rendering the form gets. Defaults to the form's `layout` config\n * (`layout: 'stage'` in Sonor flips a form to stage with no site deploy),\n * else 'classic'. customRender always wins over this.\n */\n experience?: FormExperience\n /** Absolute page URL for the no-JS 303 to land on (see native-fallback). */\n nativeReturnTo?: string\n}\n\nexport function FormClient({\n config,\n className,\n onSuccess,\n onError,\n customRender,\n experience,\n nativeReturnTo,\n defaultValues,\n}: FormClientProps) {\n // Seed default_value fields once (lazy initializer — config is stable for\n // the life of this mount; ManagedForm only renders us once it has a form).\n const [values, setValues] = useState<Record<string, unknown>>(() => {\n const defaults: Record<string, unknown> = {}\n for (const field of config.fields || []) {\n if (field.default_value !== undefined && field.default_value !== null) {\n defaults[field.slug] = field.default_value\n }\n }\n // Caller-supplied values win over the form's configured defaults — they\n // are per-visitor context (what Echo already knows about this person,\n // the service they were reading about) rather than form configuration.\n return { ...defaults, ...(defaultValues || {}) }\n })\n const [errors, setErrors] = useState<Record<string, string>>({})\n const [step, setStep] = useState(1)\n // Direction of the last step change, so the transition slides the way the\n // user is travelling ('forward' on Next, 'back' on Back).\n const [stepDirection, setStepDirection] = useState<'forward' | 'back'>('forward')\n const [isSubmitting, setIsSubmitting] = useState(false)\n const [isComplete, setIsComplete] = useState(false)\n const [submitError, setSubmitError] = useState<string | null>(null)\n const [honeypotValue, setHoneypotValue] = useState('')\n // Fields the user has interacted with — the valid tick only appears after\n // real input (never on pristine fields), so it reads as earned feedback.\n const [touched, setTouched] = useState<Record<string, boolean>>({})\n const honeypotFieldName = config.honeypot_field || DEFAULT_HONEYPOT_FIELD\n\n // Anti-bot: record when form first rendered (bots submit in < 3 seconds)\n const formLoadedAt = useRef(Date.now())\n // Synchronous guard against a concurrent double-submit (Enter + click, etc.).\n const isSubmittingRef = useRef(false)\n\n // Resolve the experience: explicit prop > form config > SPOTLIGHT.\n //\n // Spotlight is the 4.0 default: every managed form converses back unless it\n // opts out. Opting out is `experience=\"classic\"` on the component or\n // `layout: 'classic'` in Sonor (forms are data, so either side can decide\n // with no deploy from the other). customRender always wins, and a form with\n // no answerable fields has nothing to perform, so it falls back to classic.\n const stageBeatCount = useMemo(() => countStageViews(config), [config])\n const questionCount = useMemo(() => countStageQuestions(config), [config])\n const requested: FormExperience =\n experience ??\n (config.layout === 'stage'\n ? 'stage'\n : config.layout === 'classic'\n ? 'classic'\n : 'spotlight')\n const resolvedExperience: FormExperience =\n !customRender && questionCount > 0 && requested !== 'classic'\n ? requested\n : 'classic'\n\n // Date/file controls are fetched only when the form actually has such a\n // field — most forms have neither, and the date picker alone was ~5 KB\n // gzipped in every forms bundle. Until a chunk lands (and for SSR/no-JS),\n // FormField renders the native control, which submits the same value.\n const fieldControls = useFieldControls(config.fields)\n\n // The celebration is fetched as soon as the user starts submitting, so the\n // chunk arrives during the network round-trip and the payoff still feels\n // instant — without putting its markup and CSS in every form's bundle.\n const [Celebration, setCelebration] =\n useState<React.ComponentType<{ message: string; className?: string }> | null>(null)\n useEffect(() => {\n if (!isSubmitting && !isComplete) return\n let cancelled = false\n import('./FormCelebration')\n .then((m) => {\n if (!cancelled) setCelebration(() => m.FormCelebration)\n })\n .catch(() => {\n // Stays null — the plain confirmation message renders instead.\n })\n return () => {\n cancelled = true\n }\n }, [isSubmitting, isComplete])\n\n // Experience components load on demand, so a classic form (the fleet\n // default) never downloads stage/spotlight code or their stylesheets.\n // Until the chunk lands — and for SSR and no-JS — the CLASSIC form renders:\n // a complete, working, submittable form. The experience is progressive\n // enhancement layered on top, never a prerequisite for capturing the lead.\n const [Experience, setExperience] =\n useState<React.ComponentType<ExperienceRenderProps> | null>(null)\n useEffect(() => {\n if (resolvedExperience === 'classic') {\n setExperience(null)\n return\n }\n let cancelled = false\n const load =\n resolvedExperience === 'stage'\n ? import('./FormStage').then((m) => m.FormStage)\n : import('./FormSpotlight').then((m) => m.FormSpotlight)\n load\n .then((Component) => {\n // setState with a component value needs the updater form, or React\n // would call it as a lazy initializer.\n if (!cancelled) setExperience(() => Component)\n })\n .catch((err) => {\n // Chunk failed (offline, cache miss, CDN hiccup): stay on classic.\n console.error('[Forms] Experience failed to load; using classic form:', err)\n })\n return () => {\n cancelled = true\n }\n }, [resolvedExperience])\n \n // Get fields for current step\n const currentFields = useMemo(() => {\n if (!config.is_multi_step) {\n return config.fields || []\n }\n \n const currentStepConfig = config.steps?.find(s => s.step_number === step)\n if (!currentStepConfig) return config.fields || []\n \n return (config.fields || []).filter(f => f.step_id === currentStepConfig.id)\n }, [config, step])\n \n // Visibility, validation and completeness all come from field-rules.ts,\n // shared with useForm. These wrappers only bind the current values.\n const isFieldVisible = useCallback(\n (field: FormFieldType): boolean => fieldRules.isFieldVisible(field, values),\n [values],\n )\n\n const validateField = useCallback(\n (field: FormFieldType): string | null => fieldRules.validateField(field, values, isFieldVisible),\n [values, isFieldVisible],\n )\n\n // Delight: per-field validity for the tick + fields-completed momentum.\n const fieldIsComplete = useCallback(\n (field: FormFieldType): boolean => fieldRules.isFieldComplete(field, values, isFieldVisible),\n [values, isFieldVisible],\n )\n\n const momentum = useMemo(() => {\n const measurable = (config.fields || []).filter(\n f => f.is_required && isFieldVisible(f) && !fieldRules.isDisplayOnly(f),\n )\n return { done: measurable.filter(fieldIsComplete).length, total: measurable.length }\n }, [config, isFieldVisible, fieldIsComplete])\n\n const fieldBySlug = useMemo(\n () => new Map((config.fields || []).map((f) => [f.slug, f] as const)),\n [config.fields],\n )\n\n const {\n trackStepChange,\n trackComplete,\n trackFieldFocus,\n trackFieldBlur,\n trackFieldChange,\n } = useFormTracking({\n formId: config.id,\n // Alternate experiences report their unit (beat / field index) as the\n // step — form_analytics becomes a drop-off funnel with zero API changes.\n totalSteps:\n resolvedExperience === 'stage'\n ? stageBeatCount\n : resolvedExperience === 'spotlight'\n ? questionCount\n : config.total_steps,\n // Same verdict as the valid tick and the momentum count.\n isFieldComplete: (slug) => {\n const field = fieldBySlug.get(slug)\n return field ? fieldIsComplete(field) : false\n },\n })\n\n // Validate current step\n const validateStep = useCallback((): boolean => {\n const newErrors: Record<string, string> = {}\n \n for (const field of currentFields) {\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 }, [currentFields, 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. Returns the first\n // step containing an error so the user can be taken straight to it.\n const validateAll = useCallback((): { ok: boolean; firstErrorStep: number | null } => {\n const allFields = config.fields || []\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 if (Object.keys(newErrors).length === 0) return { ok: true, firstErrorStep: null }\n\n let firstErrorStep: number | null = null\n if (config.is_multi_step && config.steps) {\n const ordered = [...config.steps].sort((a, b) => a.step_number - b.step_number)\n for (const s of ordered) {\n if (allFields.some((f) => f.step_id === s.id && newErrors[f.slug])) {\n firstErrorStep = s.step_number\n break\n }\n }\n }\n return { ok: false, firstErrorStep }\n }, [config, validateField])\n\n // Collect values for currently-visible fields only, so a value typed into a\n // field that later became conditionally hidden is never submitted.\n const buildVisibleValues = useCallback((): Record<string, unknown> => {\n const out: Record<string, unknown> = {}\n for (const field of config.fields || []) {\n if (!isFieldVisible(field)) continue\n if (field.slug in values) out[field.slug] = values[field.slug]\n }\n return out\n }, [config, values, isFieldVisible])\n\n // Set field value\n const setFieldValue = useCallback((key: string, value: unknown) => {\n setTouched(prev => (prev[key] ? prev : { ...prev, [key]: true }))\n setValues(prev => ({ ...prev, [key]: value }))\n trackFieldChange(key)\n // Clear error when field changes\n if (errors[key]) {\n setErrors(prev => {\n const next = { ...prev }\n delete next[key]\n return next\n })\n }\n }, [errors, trackFieldChange])\n \n // Step navigation\n const nextStep = useCallback((): boolean => {\n if (!validateStep()) return false\n \n if (step < config.total_steps) {\n const newStep = step + 1\n setStepDirection('forward')\n setStep(newStep)\n trackStepChange(newStep)\n return true\n }\n return false\n }, [step, config.total_steps, validateStep, trackStepChange])\n\n const prevStep = useCallback(() => {\n if (step > 1) {\n const newStep = step - 1\n setStepDirection('back')\n setStep(newStep)\n trackStepChange(newStep)\n }\n }, [step, trackStepChange])\n\n const goToStep = useCallback((targetStep: number) => {\n if (targetStep >= 1 && targetStep <= config.total_steps) {\n setStepDirection(targetStep < step ? 'back' : 'forward')\n setStep(targetStep)\n trackStepChange(targetStep)\n }\n }, [step, config.total_steps, trackStepChange])\n \n // Submit form\n const submit = useCallback(async () => {\n // Re-entrancy guard — refs update synchronously, so this blocks a second\n // submit fired in the same tick (Enter key + button click, or a double-tap).\n if (isSubmittingRef.current) return\n\n const { ok, firstErrorStep } = validateAll()\n if (!ok) {\n if (firstErrorStep != null) {\n setStepDirection('back')\n setStep(firstErrorStep)\n }\n return\n }\n\n isSubmittingRef.current = true\n setIsSubmitting(true)\n setSubmitError(null)\n\n try {\n const data = await submitForm({\n config,\n values: buildVisibleValues(),\n honeypotValue: config.honeypot_enabled ? honeypotValue : '',\n formLoadedAt: formLoadedAt.current,\n })\n\n trackComplete()\n setIsComplete(true)\n onSuccess?.(data as FormSubmission)\n\n if (config.redirect_url) {\n window.location.href = config.redirect_url\n }\n } catch (error) {\n console.error('[Forms] 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 }, [config, honeypotValue, validateAll, buildVisibleValues, trackComplete, onSuccess, onError])\n \n // Progress percentage\n const progress = useMemo(() => {\n return Math.round((step / config.total_steps) * 100)\n }, [step, config.total_steps])\n\n // Title/description the admin gave the current step, used as the step's\n // conversational heading. Absent for single-step forms.\n const currentStepConfig = useMemo(\n () => config.steps?.find((s) => s.step_number === step),\n [config.steps, step],\n )\n\n // Move focus to the new step's panel so keyboard and screen-reader users land\n // on the fields they just navigated to instead of staying on a button that\n // has moved. Skipped on first render so the form never steals focus on load.\n const stepPanelRef = useRef<HTMLDivElement | null>(null)\n const hasNavigatedRef = useRef(false)\n useEffect(() => {\n if (!config.is_multi_step) return\n if (!hasNavigatedRef.current) {\n hasNavigatedRef.current = true\n return\n }\n stepPanelRef.current?.focus()\n }, [step, config.is_multi_step])\n\n\n // Render props for custom rendering\n const renderProps: FormRenderProps = {\n config,\n fields: currentFields,\n step,\n totalSteps: config.total_steps,\n values,\n errors,\n isSubmitting,\n progress,\n nextStep,\n prevStep,\n goToStep,\n submit,\n setFieldValue,\n isFieldVisible,\n trackFieldFocus,\n trackFieldBlur,\n }\n \n // Show success message (fallback when API returns empty / null success_message)\n if (isComplete) {\n const raw = config.success_message\n const message =\n typeof raw === 'string' && raw.trim().length > 0\n ? raw.trim()\n : DEFAULT_FORM_SUCCESS_MESSAGE\n // The payoff moment — celebration, not a receipt. Sites theme it via\n // --sk-primary + data-sk-part; reduced-motion users get the static check.\n // Loaded lazily (it only ever renders AFTER a submit round-trip, so the\n // chunk fetch is free), but the confirmation itself never depends on\n // that chunk: until it lands, and if it never lands, the plain message\n // below is shown. A user must always be told their submission worked.\n if (Celebration) return <Celebration message={message} className={className} />\n return (\n <div className={className} data-sk-part=\"celebration-fallback\" role=\"status\">\n <p>{message}</p>\n </div>\n )\n }\n \n // Custom render\n if (customRender) {\n return <>{customRender(renderProps)}</>\n }\n\n // Alternate experiences — render BRANCHES, not customRenders: this\n // FormClient still owns values/errors/honeypot/submit, so spam defense and\n // validation are identical to classic.\n if (resolvedExperience !== 'classic' && Experience) {\n const bundle: ExperienceRenderProps = {\n config,\n values,\n errors,\n touched,\n isSubmitting,\n submitError,\n momentum,\n className,\n setFieldValue,\n validateField,\n isFieldVisible,\n fieldIsComplete,\n applyFieldError: (slug, message) =>\n setErrors((prev) => ({ ...prev, [slug]: message })),\n submit,\n trackStepChange,\n trackFieldFocus,\n trackFieldBlur,\n honeypot: config.honeypot_enabled ? (\n <HoneypotField\n name={honeypotFieldName}\n value={honeypotValue}\n onChange={setHoneypotValue}\n />\n ) : null,\n }\n return (\n <>\n <DelightStyles />\n <Experience {...bundle} />\n </>\n )\n }\n\n // Default render\n return (\n <form data-sk-state={isSubmitting ? 'submitting' : 'idle'}\n // Ready = every required field validates AND the submit button (not\n // \"Next\") is what's showing — the wake-up glow means \"press start\".\n data-sk-ready={\n momentum.total > 0 && momentum.done >= momentum.total && step >= config.total_steps\n ? 'true'\n : undefined\n }\n className={`sk-form ${className || ''}`}\n // No-JS floor: real action/method so the browser can POST without the\n // bundle. With JS the preventDefault below always wins.\n {...nativeFormProps(config)}\n onSubmit={(e) => {\n e.preventDefault()\n if (step < config.total_steps) {\n nextStep()\n } else {\n submit()\n }\n }}\n >\n <DelightStyles />\n <FormMomentum done={momentum.done} total={momentum.total} />\n {/* Step indicator for multi-step */}\n {config.is_multi_step && (\n <div className=\"sk-form__progress\">\n <div className=\"sk-form__progress-header\">\n <span className=\"sk-form__progress-step\">\n Step {step} of {config.total_steps}\n </span>\n {/* The percentage readout is opt-in — \"Step 2 of 4\" already gives\n the user their position, and a bare number reads as pressure. */}\n {config.show_progress && (\n <span className=\"sk-form__progress-percent\">{progress}%</span>\n )}\n </div>\n <div\n className=\"sk-form__progress-track\"\n role=\"progressbar\"\n aria-valuemin={1}\n aria-valuemax={config.total_steps}\n aria-valuenow={step}\n aria-valuetext={`Step ${step} of ${config.total_steps}`}\n >\n <div className=\"sk-form__progress-bar\" style={{ width: `${progress}%` }} />\n </div>\n <ol className=\"sk-form__progress-dots\" aria-hidden=\"true\">\n {Array.from({ length: config.total_steps }, (_, i) => i + 1).map((n) => (\n <li\n key={n}\n className={\n 'sk-form__progress-dot' +\n (n === step ? ' sk-form__progress-dot--current' : '') +\n (n < step ? ' sk-form__progress-dot--done' : '')\n }\n />\n ))}\n </ol>\n </div>\n )}\n\n {/* Fields — keyed by step so each step animates in on navigation */}\n <div\n key={step}\n ref={stepPanelRef}\n tabIndex={-1}\n className={\n 'sk-form__step' +\n (config.is_multi_step ? ` sk-form__step--${stepDirection}` : '')\n }\n >\n {config.is_multi_step && (currentStepConfig?.title || currentStepConfig?.description) && (\n <div className=\"sk-form__step-intro\">\n {currentStepConfig.title && (\n <h3 className=\"sk-form__step-title\">{currentStepConfig.title}</h3>\n )}\n {currentStepConfig.description && (\n <p className=\"sk-form__step-description\">{currentStepConfig.description}</p>\n )}\n </div>\n )}\n\n <div className=\"sk-form__fields\">\n {currentFields.map((field) => {\n if (!isFieldVisible(field)) return null\n\n return (\n <div key={field.id} className={`sk-form__field-wrapper sk-form__field-wrapper--${field.width || 'full'}`}>\n <FormField\n field={field}\n value={values[field.slug]}\n error={errors[field.slug]}\n showValid={!!touched[field.slug] && !errors[field.slug] && fieldIsComplete(field)}\n onChange={(value) => setFieldValue(field.slug, value)}\n onFocus={() => trackFieldFocus(field.slug)}\n onBlur={() => trackFieldBlur(field.slug)}\n controls={fieldControls}\n />\n </div>\n )\n })}\n </div>\n </div>\n\n {/* Navigation buttons */}\n <div\n className=\"sk-form__actions\"\n style={{ justifyContent: step > 1 ? 'space-between' : 'flex-end' }}\n >\n {step > 1 && (\n <button type=\"button\" className=\"sk-form__btn sk-form__btn--back\" onClick={prevStep}>\n Back\n </button>\n )}\n <button type=\"submit\" className=\"sk-form__btn sk-form__btn--submit\" disabled={isSubmitting}>\n {isSubmitting\n ? 'Submitting...'\n : step < config.total_steps\n ? 'Next'\n : config.submit_button_text\n }\n </button>\n </div>\n\n {submitError && (\n <p\n className=\"sk-form__submit-error\"\n role=\"alert\"\n style={{ color: 'var(--sk-error, #dc2626)', fontSize: 14, marginTop: 12 }}\n >\n {submitError}\n </p>\n )}\n\n {/* Honeypot field — shared single source of truth with the stage\n experience (HoneypotField.tsx holds the invariants). */}\n {config.honeypot_enabled && (\n <HoneypotField\n name={honeypotFieldName}\n value={honeypotValue}\n onChange={setHoneypotValue}\n />\n )}\n\n {/* No-JS control fields (_sk_token auth + _sk_return destination). */}\n <NativeFallbackFields config={config} returnTo={nativeReturnTo} />\n </form>\n )\n}\n","/**\n * @sonordev/site-kit/forms - Managed Form Component\n * \n * Fetches form config from Portal API and renders fields with validation\n */\n\n'use client'\n\nimport type { ManagedFormProps } from './types'\nimport { useForm } from './useForm'\nimport { FormClient } from './FormClient'\n\n// ============================================\n// Main Component (Client Component)\n// ============================================\n\nexport function ManagedForm({\n formId,\n projectId,\n className,\n onSuccess,\n onError,\n initialConfig,\n experience,\n nativeReturnTo,\n defaultValues,\n children,\n}: ManagedFormProps) {\n const {\n form,\n isLoading,\n fetchError,\n } = useForm(formId, {\n projectId,\n onSuccess,\n onError,\n initialForm: initialConfig,\n // FormClient below owns this form's tracking — it renders the fields,\n // drives step navigation and runs the submit, so it is the only thing that\n // can report a real funnel. useForm is used here purely to FETCH the\n // config; we never call its submit, so its analytics row could only ever\n // open and abandon, never complete.\n //\n // Leaving this on is the double-count bug fixed in 4.2.2: two\n // trackers per form, two form_analytics rows per page load, every\n // start -> submission rate reported at half its true value.\n trackAnalytics: false,\n })\n \n if (isLoading) {\n return (\n <div className={className}>\n <p style={{ color: '#6b7280' }}>Loading form...</p>\n </div>\n )\n }\n \n if (fetchError || !form) {\n return (\n <div className={className}>\n <p style={{ color: 'var(--sk-error, #dc2626)' }}>\n {fetchError?.message || 'Form not found or inactive.'}\n </p>\n </div>\n )\n }\n \n // Pass to client component for interactivity\n return (\n <FormClient\n config={form}\n className={className}\n onSuccess={onSuccess}\n onError={onError}\n customRender={children}\n experience={experience}\n nativeReturnTo={nativeReturnTo}\n defaultValues={defaultValues}\n />\n )\n}\n\n"]}
1
+ {"version":3,"sources":["../src/forms/FormClient.tsx","../src/forms/ManagedForm.tsx"],"names":["currentStepConfig","isFieldVisible","validateField","jsx"],"mappings":"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","file":"chunk-XGELGOF6.mjs","sourcesContent":["/**\n * @sonordev/site-kit/forms - Form Client Component\n * \n * Handles form state, validation, and submission\n */\n\n'use client'\n\nimport React, { useState, useCallback, useMemo, useRef, useEffect } from 'react'\nimport { useFormTracking } from './useFormTracking'\nimport * as fieldRules from './field-rules'\nimport { FormField } from './FormField'\nimport { submitForm, DEFAULT_HONEYPOT_FIELD } from './submitForm'\nimport type { \n ManagedFormConfig, \n FormField as FormFieldType, \n FormRenderProps,\n FormSubmission,\n} from './types'\nimport { DEFAULT_FORM_SUCCESS_MESSAGE } from './defaultSuccessMessage'\nimport { DelightStyles, FormMomentum } from './delight'\nimport { HoneypotField } from './HoneypotField'\nimport { useFieldControls } from './field-controls'\nimport { nativeFormProps, NativeFallbackFields } from './native-fallback'\nimport { countStageViews, countStageQuestions } from './experience-plan'\nimport type { ExperienceRenderProps, FormExperience } from './types'\n\ninterface FormClientProps {\n config: ManagedFormConfig\n className?: string\n onSuccess?: (submission: FormSubmission) => void\n onError?: (error: Error) => void\n customRender?: (props: FormRenderProps) => React.ReactNode\n /**\n * Pre-fill field values by slug. For context the page already has and the\n * visitor should not retype: an email captured earlier in a conversation,\n * the service they were reading about, an estimate the assistant just\n * produced. Applied ON TOP of each field's configured default_value.\n *\n * Unknown slugs are ignored, so a stale key cannot break the form.\n */\n defaultValues?: Record<string, unknown>\n /**\n * Which rendering the form gets. Defaults to the form's `layout` config\n * (`layout: 'stage'` in Sonor flips a form to stage with no site deploy),\n * else 'classic'. customRender always wins over this.\n */\n experience?: FormExperience\n /** Absolute page URL for the no-JS 303 to land on (see native-fallback). */\n nativeReturnTo?: string\n}\n\nexport function FormClient({\n config,\n className,\n onSuccess,\n onError,\n customRender,\n experience,\n nativeReturnTo,\n defaultValues,\n}: FormClientProps) {\n // Seed default_value fields once (lazy initializer — config is stable for\n // the life of this mount; ManagedForm only renders us once it has a form).\n const [values, setValues] = useState<Record<string, unknown>>(() => {\n const defaults: Record<string, unknown> = {}\n for (const field of config.fields || []) {\n if (field.default_value !== undefined && field.default_value !== null) {\n defaults[field.slug] = field.default_value\n }\n }\n // Caller-supplied values win over the form's configured defaults — they\n // are per-visitor context (what Echo already knows about this person,\n // the service they were reading about) rather than form configuration.\n return { ...defaults, ...(defaultValues || {}) }\n })\n const [errors, setErrors] = useState<Record<string, string>>({})\n const [step, setStep] = useState(1)\n // Direction of the last step change, so the transition slides the way the\n // user is travelling ('forward' on Next, 'back' on Back).\n const [stepDirection, setStepDirection] = useState<'forward' | 'back'>('forward')\n const [isSubmitting, setIsSubmitting] = useState(false)\n const [isComplete, setIsComplete] = useState(false)\n const [submitError, setSubmitError] = useState<string | null>(null)\n const [honeypotValue, setHoneypotValue] = useState('')\n // Fields the user has interacted with — the valid tick only appears after\n // real input (never on pristine fields), so it reads as earned feedback.\n const [touched, setTouched] = useState<Record<string, boolean>>({})\n const honeypotFieldName = config.honeypot_field || DEFAULT_HONEYPOT_FIELD\n\n // Anti-bot: record when form first rendered (bots submit in < 3 seconds)\n const formLoadedAt = useRef(Date.now())\n // Synchronous guard against a concurrent double-submit (Enter + click, etc.).\n const isSubmittingRef = useRef(false)\n\n // Resolve the experience: explicit prop > form config > SPOTLIGHT.\n //\n // Spotlight is the 4.0 default: every managed form converses back unless it\n // opts out. Opting out is `experience=\"classic\"` on the component or\n // `layout: 'classic'` in Sonor (forms are data, so either side can decide\n // with no deploy from the other). customRender always wins, and a form with\n // no answerable fields has nothing to perform, so it falls back to classic.\n const stageBeatCount = useMemo(() => countStageViews(config), [config])\n const questionCount = useMemo(() => countStageQuestions(config), [config])\n const requested: FormExperience =\n experience ??\n (config.layout === 'stage'\n ? 'stage'\n : config.layout === 'classic'\n ? 'classic'\n : 'spotlight')\n const resolvedExperience: FormExperience =\n !customRender && questionCount > 0 && requested !== 'classic'\n ? requested\n : 'classic'\n\n // Date/file controls are fetched only when the form actually has such a\n // field — most forms have neither, and the date picker alone was ~5 KB\n // gzipped in every forms bundle. Until a chunk lands (and for SSR/no-JS),\n // FormField renders the native control, which submits the same value.\n const fieldControls = useFieldControls(config.fields)\n\n // The celebration is fetched as soon as the user starts submitting, so the\n // chunk arrives during the network round-trip and the payoff still feels\n // instant — without putting its markup and CSS in every form's bundle.\n const [Celebration, setCelebration] =\n useState<React.ComponentType<{ message: string; className?: string }> | null>(null)\n useEffect(() => {\n if (!isSubmitting && !isComplete) return\n let cancelled = false\n import('./FormCelebration')\n .then((m) => {\n if (!cancelled) setCelebration(() => m.FormCelebration)\n })\n .catch(() => {\n // Stays null — the plain confirmation message renders instead.\n })\n return () => {\n cancelled = true\n }\n }, [isSubmitting, isComplete])\n\n // Experience components load on demand, so a classic form (the fleet\n // default) never downloads stage/spotlight code or their stylesheets.\n // Until the chunk lands — and for SSR and no-JS — the CLASSIC form renders:\n // a complete, working, submittable form. The experience is progressive\n // enhancement layered on top, never a prerequisite for capturing the lead.\n const [Experience, setExperience] =\n useState<React.ComponentType<ExperienceRenderProps> | null>(null)\n useEffect(() => {\n if (resolvedExperience === 'classic') {\n setExperience(null)\n return\n }\n let cancelled = false\n const load =\n resolvedExperience === 'stage'\n ? import('./FormStage').then((m) => m.FormStage)\n : import('./FormSpotlight').then((m) => m.FormSpotlight)\n load\n .then((Component) => {\n // setState with a component value needs the updater form, or React\n // would call it as a lazy initializer.\n if (!cancelled) setExperience(() => Component)\n })\n .catch((err) => {\n // Chunk failed (offline, cache miss, CDN hiccup): stay on classic.\n console.error('[Forms] Experience failed to load; using classic form:', err)\n })\n return () => {\n cancelled = true\n }\n }, [resolvedExperience])\n \n // Get fields for current step\n const currentFields = useMemo(() => {\n if (!config.is_multi_step) {\n return config.fields || []\n }\n \n const currentStepConfig = config.steps?.find(s => s.step_number === step)\n if (!currentStepConfig) return config.fields || []\n \n return (config.fields || []).filter(f => f.step_id === currentStepConfig.id)\n }, [config, step])\n \n // Visibility, validation and completeness all come from field-rules.ts,\n // shared with useForm. These wrappers only bind the current values.\n const isFieldVisible = useCallback(\n (field: FormFieldType): boolean => fieldRules.isFieldVisible(field, values),\n [values],\n )\n\n const validateField = useCallback(\n (field: FormFieldType): string | null => fieldRules.validateField(field, values, isFieldVisible),\n [values, isFieldVisible],\n )\n\n // Delight: per-field validity for the tick + fields-completed momentum.\n const fieldIsComplete = useCallback(\n (field: FormFieldType): boolean => fieldRules.isFieldComplete(field, values, isFieldVisible),\n [values, isFieldVisible],\n )\n\n const momentum = useMemo(() => {\n const measurable = (config.fields || []).filter(\n f => f.is_required && isFieldVisible(f) && !fieldRules.isDisplayOnly(f),\n )\n return { done: measurable.filter(fieldIsComplete).length, total: measurable.length }\n }, [config, isFieldVisible, fieldIsComplete])\n\n const fieldBySlug = useMemo(\n () => new Map((config.fields || []).map((f) => [f.slug, f] as const)),\n [config.fields],\n )\n\n const {\n trackStepChange,\n trackComplete,\n trackFieldFocus,\n trackFieldBlur,\n trackFieldChange,\n } = useFormTracking({\n formId: config.id,\n // Alternate experiences report their unit (beat / field index) as the\n // step — form_analytics becomes a drop-off funnel with zero API changes.\n totalSteps:\n resolvedExperience === 'stage'\n ? stageBeatCount\n : resolvedExperience === 'spotlight'\n ? questionCount\n : config.total_steps,\n // Same verdict as the valid tick and the momentum count.\n isFieldComplete: (slug) => {\n const field = fieldBySlug.get(slug)\n return field ? fieldIsComplete(field) : false\n },\n })\n\n // Validate current step\n const validateStep = useCallback((): boolean => {\n const newErrors: Record<string, string> = {}\n \n for (const field of currentFields) {\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 }, [currentFields, 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. Returns the first\n // step containing an error so the user can be taken straight to it.\n const validateAll = useCallback((): { ok: boolean; firstErrorStep: number | null } => {\n const allFields = config.fields || []\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 if (Object.keys(newErrors).length === 0) return { ok: true, firstErrorStep: null }\n\n let firstErrorStep: number | null = null\n if (config.is_multi_step && config.steps) {\n const ordered = [...config.steps].sort((a, b) => a.step_number - b.step_number)\n for (const s of ordered) {\n if (allFields.some((f) => f.step_id === s.id && newErrors[f.slug])) {\n firstErrorStep = s.step_number\n break\n }\n }\n }\n return { ok: false, firstErrorStep }\n }, [config, validateField])\n\n // Collect values for currently-visible fields only, so a value typed into a\n // field that later became conditionally hidden is never submitted.\n const buildVisibleValues = useCallback((): Record<string, unknown> => {\n const out: Record<string, unknown> = {}\n for (const field of config.fields || []) {\n if (!isFieldVisible(field)) continue\n if (field.slug in values) out[field.slug] = values[field.slug]\n }\n return out\n }, [config, values, isFieldVisible])\n\n // Set field value\n const setFieldValue = useCallback((key: string, value: unknown) => {\n setTouched(prev => (prev[key] ? prev : { ...prev, [key]: true }))\n setValues(prev => ({ ...prev, [key]: value }))\n trackFieldChange(key)\n // Clear error when field changes\n if (errors[key]) {\n setErrors(prev => {\n const next = { ...prev }\n delete next[key]\n return next\n })\n }\n }, [errors, trackFieldChange])\n \n // Step navigation\n const nextStep = useCallback((): boolean => {\n if (!validateStep()) return false\n \n if (step < config.total_steps) {\n const newStep = step + 1\n setStepDirection('forward')\n setStep(newStep)\n trackStepChange(newStep)\n return true\n }\n return false\n }, [step, config.total_steps, validateStep, trackStepChange])\n\n const prevStep = useCallback(() => {\n if (step > 1) {\n const newStep = step - 1\n setStepDirection('back')\n setStep(newStep)\n trackStepChange(newStep)\n }\n }, [step, trackStepChange])\n\n const goToStep = useCallback((targetStep: number) => {\n if (targetStep >= 1 && targetStep <= config.total_steps) {\n setStepDirection(targetStep < step ? 'back' : 'forward')\n setStep(targetStep)\n trackStepChange(targetStep)\n }\n }, [step, config.total_steps, trackStepChange])\n \n // Submit form\n const submit = useCallback(async () => {\n // Re-entrancy guard — refs update synchronously, so this blocks a second\n // submit fired in the same tick (Enter key + button click, or a double-tap).\n if (isSubmittingRef.current) return\n\n const { ok, firstErrorStep } = validateAll()\n if (!ok) {\n if (firstErrorStep != null) {\n setStepDirection('back')\n setStep(firstErrorStep)\n }\n return\n }\n\n isSubmittingRef.current = true\n setIsSubmitting(true)\n setSubmitError(null)\n\n try {\n const data = await submitForm({\n config,\n values: buildVisibleValues(),\n honeypotValue: config.honeypot_enabled ? honeypotValue : '',\n formLoadedAt: formLoadedAt.current,\n })\n\n trackComplete()\n setIsComplete(true)\n onSuccess?.(data as FormSubmission)\n\n if (config.redirect_url) {\n window.location.href = config.redirect_url\n }\n } catch (error) {\n console.error('[Forms] 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 }, [config, honeypotValue, validateAll, buildVisibleValues, trackComplete, onSuccess, onError])\n \n // Progress percentage\n const progress = useMemo(() => {\n return Math.round((step / config.total_steps) * 100)\n }, [step, config.total_steps])\n\n // Title/description the admin gave the current step, used as the step's\n // conversational heading. Absent for single-step forms.\n const currentStepConfig = useMemo(\n () => config.steps?.find((s) => s.step_number === step),\n [config.steps, step],\n )\n\n // Move focus to the new step's panel so keyboard and screen-reader users land\n // on the fields they just navigated to instead of staying on a button that\n // has moved. Skipped on first render so the form never steals focus on load.\n const stepPanelRef = useRef<HTMLDivElement | null>(null)\n const hasNavigatedRef = useRef(false)\n useEffect(() => {\n if (!config.is_multi_step) return\n if (!hasNavigatedRef.current) {\n hasNavigatedRef.current = true\n return\n }\n stepPanelRef.current?.focus()\n }, [step, config.is_multi_step])\n\n\n // Render props for custom rendering\n const renderProps: FormRenderProps = {\n config,\n fields: currentFields,\n step,\n totalSteps: config.total_steps,\n values,\n errors,\n isSubmitting,\n progress,\n nextStep,\n prevStep,\n goToStep,\n submit,\n setFieldValue,\n isFieldVisible,\n trackFieldFocus,\n trackFieldBlur,\n }\n \n // Show success message (fallback when API returns empty / null success_message)\n if (isComplete) {\n const raw = config.success_message\n const message =\n typeof raw === 'string' && raw.trim().length > 0\n ? raw.trim()\n : DEFAULT_FORM_SUCCESS_MESSAGE\n // The payoff moment — celebration, not a receipt. Sites theme it via\n // --sk-primary + data-sk-part; reduced-motion users get the static check.\n // Loaded lazily (it only ever renders AFTER a submit round-trip, so the\n // chunk fetch is free), but the confirmation itself never depends on\n // that chunk: until it lands, and if it never lands, the plain message\n // below is shown. A user must always be told their submission worked.\n if (Celebration) return <Celebration message={message} className={className} />\n return (\n <div className={className} data-sk-part=\"celebration-fallback\" role=\"status\">\n <p>{message}</p>\n </div>\n )\n }\n \n // Custom render\n if (customRender) {\n return <>{customRender(renderProps)}</>\n }\n\n // Alternate experiences — render BRANCHES, not customRenders: this\n // FormClient still owns values/errors/honeypot/submit, so spam defense and\n // validation are identical to classic.\n if (resolvedExperience !== 'classic' && Experience) {\n const bundle: ExperienceRenderProps = {\n config,\n values,\n errors,\n touched,\n isSubmitting,\n submitError,\n momentum,\n className,\n setFieldValue,\n validateField,\n isFieldVisible,\n fieldIsComplete,\n applyFieldError: (slug, message) =>\n setErrors((prev) => ({ ...prev, [slug]: message })),\n submit,\n trackStepChange,\n trackFieldFocus,\n trackFieldBlur,\n honeypot: config.honeypot_enabled ? (\n <HoneypotField\n name={honeypotFieldName}\n value={honeypotValue}\n onChange={setHoneypotValue}\n />\n ) : null,\n }\n return (\n <>\n <DelightStyles />\n <Experience {...bundle} />\n </>\n )\n }\n\n // Default render\n return (\n <form data-sk-state={isSubmitting ? 'submitting' : 'idle'}\n // Ready = every required field validates AND the submit button (not\n // \"Next\") is what's showing — the wake-up glow means \"press start\".\n data-sk-ready={\n momentum.total > 0 && momentum.done >= momentum.total && step >= config.total_steps\n ? 'true'\n : undefined\n }\n className={`sk-form ${className || ''}`}\n // No-JS floor: real action/method so the browser can POST without the\n // bundle. With JS the preventDefault below always wins.\n {...nativeFormProps(config)}\n onSubmit={(e) => {\n e.preventDefault()\n if (step < config.total_steps) {\n nextStep()\n } else {\n submit()\n }\n }}\n >\n <DelightStyles />\n <FormMomentum done={momentum.done} total={momentum.total} />\n {/* Step indicator for multi-step */}\n {config.is_multi_step && (\n <div className=\"sk-form__progress\">\n <div className=\"sk-form__progress-header\">\n <span className=\"sk-form__progress-step\">\n Step {step} of {config.total_steps}\n </span>\n {/* The percentage readout is opt-in — \"Step 2 of 4\" already gives\n the user their position, and a bare number reads as pressure. */}\n {config.show_progress && (\n <span className=\"sk-form__progress-percent\">{progress}%</span>\n )}\n </div>\n <div\n className=\"sk-form__progress-track\"\n role=\"progressbar\"\n aria-valuemin={1}\n aria-valuemax={config.total_steps}\n aria-valuenow={step}\n aria-valuetext={`Step ${step} of ${config.total_steps}`}\n >\n <div className=\"sk-form__progress-bar\" style={{ width: `${progress}%` }} />\n </div>\n <ol className=\"sk-form__progress-dots\" aria-hidden=\"true\">\n {Array.from({ length: config.total_steps }, (_, i) => i + 1).map((n) => (\n <li\n key={n}\n className={\n 'sk-form__progress-dot' +\n (n === step ? ' sk-form__progress-dot--current' : '') +\n (n < step ? ' sk-form__progress-dot--done' : '')\n }\n />\n ))}\n </ol>\n </div>\n )}\n\n {/* Fields — keyed by step so each step animates in on navigation */}\n <div\n key={step}\n ref={stepPanelRef}\n tabIndex={-1}\n className={\n 'sk-form__step' +\n (config.is_multi_step ? ` sk-form__step--${stepDirection}` : '')\n }\n >\n {config.is_multi_step && (currentStepConfig?.title || currentStepConfig?.description) && (\n <div className=\"sk-form__step-intro\">\n {currentStepConfig.title && (\n <h3 className=\"sk-form__step-title\">{currentStepConfig.title}</h3>\n )}\n {currentStepConfig.description && (\n <p className=\"sk-form__step-description\">{currentStepConfig.description}</p>\n )}\n </div>\n )}\n\n <div className=\"sk-form__fields\">\n {currentFields.map((field) => {\n if (!isFieldVisible(field)) return null\n\n return (\n <div key={field.id} className={`sk-form__field-wrapper sk-form__field-wrapper--${field.width || 'full'}`}>\n <FormField\n field={field}\n value={values[field.slug]}\n error={errors[field.slug]}\n showValid={!!touched[field.slug] && !errors[field.slug] && fieldIsComplete(field)}\n onChange={(value) => setFieldValue(field.slug, value)}\n onFocus={() => trackFieldFocus(field.slug)}\n onBlur={() => trackFieldBlur(field.slug)}\n controls={fieldControls}\n />\n </div>\n )\n })}\n </div>\n </div>\n\n {/* Navigation buttons */}\n <div\n className=\"sk-form__actions\"\n style={{ justifyContent: step > 1 ? 'space-between' : 'flex-end' }}\n >\n {step > 1 && (\n <button type=\"button\" className=\"sk-form__btn sk-form__btn--back\" onClick={prevStep}>\n Back\n </button>\n )}\n <button type=\"submit\" className=\"sk-form__btn sk-form__btn--submit\" disabled={isSubmitting}>\n {isSubmitting\n ? 'Submitting...'\n : step < config.total_steps\n ? 'Next'\n : config.submit_button_text\n }\n </button>\n </div>\n\n {submitError && (\n <p\n className=\"sk-form__submit-error\"\n role=\"alert\"\n style={{ color: 'var(--sk-error, #dc2626)', fontSize: 14, marginTop: 12 }}\n >\n {submitError}\n </p>\n )}\n\n {/* Honeypot field — shared single source of truth with the stage\n experience (HoneypotField.tsx holds the invariants). */}\n {config.honeypot_enabled && (\n <HoneypotField\n name={honeypotFieldName}\n value={honeypotValue}\n onChange={setHoneypotValue}\n />\n )}\n\n {/* No-JS control fields (_sk_token auth + _sk_return destination). */}\n <NativeFallbackFields config={config} returnTo={nativeReturnTo} />\n </form>\n )\n}\n","/**\n * @sonordev/site-kit/forms - Managed Form Component\n * \n * Fetches form config from Portal API and renders fields with validation\n */\n\n'use client'\n\nimport type { ManagedFormProps } from './types'\nimport { useForm } from './useForm'\nimport { FormClient } from './FormClient'\n\n// ============================================\n// Main Component (Client Component)\n// ============================================\n\nexport function ManagedForm({\n formId,\n projectId,\n className,\n onSuccess,\n onError,\n initialConfig,\n experience,\n nativeReturnTo,\n defaultValues,\n children,\n}: ManagedFormProps) {\n const {\n form,\n isLoading,\n fetchError,\n } = useForm(formId, {\n projectId,\n onSuccess,\n onError,\n initialForm: initialConfig,\n // FormClient below owns this form's tracking — it renders the fields,\n // drives step navigation and runs the submit, so it is the only thing that\n // can report a real funnel. useForm is used here purely to FETCH the\n // config; we never call its submit, so its analytics row could only ever\n // open and abandon, never complete.\n //\n // Leaving this on is the double-count bug fixed in 4.2.2: two\n // trackers per form, two form_analytics rows per page load, every\n // start -> submission rate reported at half its true value.\n trackAnalytics: false,\n })\n \n if (isLoading) {\n return (\n <div className={className}>\n <p style={{ color: '#6b7280' }}>Loading form...</p>\n </div>\n )\n }\n \n if (fetchError || !form) {\n return (\n <div className={className}>\n <p style={{ color: 'var(--sk-error, #dc2626)' }}>\n {fetchError?.message || 'Form not found or inactive.'}\n </p>\n </div>\n )\n }\n \n // Pass to client component for interactivity\n return (\n <FormClient\n config={form}\n className={className}\n onSuccess={onSuccess}\n onError={onError}\n customRender={children}\n experience={experience}\n nativeReturnTo={nativeReturnTo}\n defaultValues={defaultValues}\n />\n )\n}\n\n"]}