@sonordev/site-kit 5.3.2 → 5.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (411) hide show
  1. package/AGENTS.md +16 -6
  2. package/README.md +26 -7
  3. package/agent-manifest.json +11 -10
  4. package/dist/AnalyticsProvider-KFXAH4GR.mjs +11 -0
  5. package/dist/{AnalyticsProvider-2XK54UZW.mjs.map → AnalyticsProvider-KFXAH4GR.mjs.map} +1 -1
  6. package/dist/AnalyticsProvider-WDDW3IJW.js +32 -0
  7. package/dist/{AnalyticsProvider-PM7SOGOS.js.map → AnalyticsProvider-WDDW3IJW.js.map} +1 -1
  8. package/dist/{BlogViewTracker-3BIUF5TI.js → BlogViewTracker-D4DIEP4Q.js} +6 -6
  9. package/dist/{BlogViewTracker-3BIUF5TI.js.map → BlogViewTracker-D4DIEP4Q.js.map} +1 -1
  10. package/dist/{BlogViewTracker-KFUDRDQK.mjs → BlogViewTracker-ZVEGGH3Y.mjs} +5 -5
  11. package/dist/{BlogViewTracker-KFUDRDQK.mjs.map → BlogViewTracker-ZVEGGH3Y.mjs.map} +1 -1
  12. package/dist/ChatWidget-2ZYPYIMQ.js +22 -0
  13. package/dist/{ChatWidget-7BYSGNO2.js.map → ChatWidget-2ZYPYIMQ.js.map} +1 -1
  14. package/dist/ChatWidget-FYCCLMQE.mjs +13 -0
  15. package/dist/{ChatWidget-4PHZHGG5.mjs.map → ChatWidget-FYCCLMQE.mjs.map} +1 -1
  16. package/dist/EngageWidget-6HUZYOY7.mjs +11 -0
  17. package/dist/{EngageWidget-D6M6QWEC.mjs.map → EngageWidget-6HUZYOY7.mjs.map} +1 -1
  18. package/dist/EngageWidget-MYQTBBW6.js +20 -0
  19. package/dist/{EngageWidget-Q4ITKTMJ.js.map → EngageWidget-MYQTBBW6.js.map} +1 -1
  20. package/dist/{FileField-YBBIJOCK.js → FileField-JK2S24XU.js} +6 -6
  21. package/dist/{FileField-YBBIJOCK.js.map → FileField-JK2S24XU.js.map} +1 -1
  22. package/dist/{FileField-PQQDX4IR.mjs → FileField-OZZHWGPA.mjs} +5 -5
  23. package/dist/{FileField-PQQDX4IR.mjs.map → FileField-OZZHWGPA.mjs.map} +1 -1
  24. package/dist/{FormSpotlight-WUN24F3P.js → FormSpotlight-5AXFQU5M.js} +15 -15
  25. package/dist/{FormSpotlight-WUN24F3P.js.map → FormSpotlight-5AXFQU5M.js.map} +1 -1
  26. package/dist/{FormSpotlight-7TIIWFTP.mjs → FormSpotlight-XV42L72H.mjs} +3 -3
  27. package/dist/{FormSpotlight-7TIIWFTP.mjs.map → FormSpotlight-XV42L72H.mjs.map} +1 -1
  28. package/dist/{FormStage-CM7OVLUT.js → FormStage-HATUHNRV.js} +13 -13
  29. package/dist/{FormStage-CM7OVLUT.js.map → FormStage-HATUHNRV.js.map} +1 -1
  30. package/dist/{FormStage-TFN2GIBO.mjs → FormStage-RUK675HV.mjs} +3 -3
  31. package/dist/{FormStage-TFN2GIBO.mjs.map → FormStage-RUK675HV.mjs.map} +1 -1
  32. package/dist/ManagedForm-JWEXJEXK.js +23 -0
  33. package/dist/{ManagedForm-N63YGVNY.js.map → ManagedForm-JWEXJEXK.js.map} +1 -1
  34. package/dist/ManagedForm-OA3MNGXT.mjs +14 -0
  35. package/dist/{ManagedForm-ZUXLHEQU.mjs.map → ManagedForm-OA3MNGXT.mjs.map} +1 -1
  36. package/dist/{ManagedNewsletterForm-PIVJTU5L.js → ManagedNewsletterForm-AAHH63KT.js} +8 -8
  37. package/dist/{ManagedNewsletterForm-PIVJTU5L.js.map → ManagedNewsletterForm-AAHH63KT.js.map} +1 -1
  38. package/dist/{ManagedNewsletterForm-4AVKTZ2A.mjs → ManagedNewsletterForm-HZKTNWLW.mjs} +7 -7
  39. package/dist/{ManagedNewsletterForm-4AVKTZ2A.mjs.map → ManagedNewsletterForm-HZKTNWLW.mjs.map} +1 -1
  40. package/dist/{SignalCore-LT4NCPOR.mjs → SignalCore-X3GDGBZD.mjs} +5 -5
  41. package/dist/{SignalCore-LT4NCPOR.mjs.map → SignalCore-X3GDGBZD.mjs.map} +1 -1
  42. package/dist/{SignalCore-2M5TISM7.js → SignalCore-YSNZYBKJ.js} +11 -11
  43. package/dist/{SignalCore-2M5TISM7.js.map → SignalCore-YSNZYBKJ.js.map} +1 -1
  44. package/dist/SitemapSync-2PTDBH5E.mjs +9 -0
  45. package/dist/{SitemapSync-G3OLECFI.mjs.map → SitemapSync-2PTDBH5E.mjs.map} +1 -1
  46. package/dist/SitemapSync-3SFAI546.js +18 -0
  47. package/dist/{SitemapSync-7OBOJG2L.js.map → SitemapSync-3SFAI546.js.map} +1 -1
  48. package/dist/analytics/dispatch.d.ts +4 -4
  49. package/dist/analytics/index.js +15 -15
  50. package/dist/analytics/index.mjs +6 -6
  51. package/dist/{api-NTHZ6PAW.mjs → api-D745LGGU.mjs} +3 -3
  52. package/dist/api-D745LGGU.mjs.map +1 -0
  53. package/dist/{api-N5OLQXYN.js → api-XR5APCH3.js} +3 -3
  54. package/dist/api-XR5APCH3.js.map +1 -0
  55. package/dist/blog/AuthorPage.d.ts +1 -1
  56. package/dist/blog/AuthorPage.d.ts.map +1 -1
  57. package/dist/blog/BlogLayout.d.ts +3 -1
  58. package/dist/blog/BlogLayout.d.ts.map +1 -1
  59. package/dist/blog/BlogList.d.ts +3 -1
  60. package/dist/blog/BlogList.d.ts.map +1 -1
  61. package/dist/blog/BlogPost.d.ts +3 -1
  62. package/dist/blog/BlogPost.d.ts.map +1 -1
  63. package/dist/blog/BlogSidebar.d.ts +3 -1
  64. package/dist/blog/BlogSidebar.d.ts.map +1 -1
  65. package/dist/blog/ClusterLandingPage.d.ts +3 -1
  66. package/dist/blog/ClusterLandingPage.d.ts.map +1 -1
  67. package/dist/blog/ClusterNavigation.d.ts +3 -1
  68. package/dist/blog/ClusterNavigation.d.ts.map +1 -1
  69. package/dist/blog/RelatedPosts.d.ts +4 -1
  70. package/dist/blog/RelatedPosts.d.ts.map +1 -1
  71. package/dist/blog/artwork-components.test.d.ts +2 -0
  72. package/dist/blog/artwork-components.test.d.ts.map +1 -0
  73. package/dist/blog/artwork.d.ts +14 -0
  74. package/dist/blog/artwork.d.ts.map +1 -0
  75. package/dist/blog/artwork.test.d.ts +2 -0
  76. package/dist/blog/artwork.test.d.ts.map +1 -0
  77. package/dist/blog/blog-styles.d.ts.map +1 -1
  78. package/dist/blog/blog-tables.d.ts +13 -0
  79. package/dist/blog/blog-tables.d.ts.map +1 -0
  80. package/dist/blog/blog-tables.test.d.ts +2 -0
  81. package/dist/blog/blog-tables.test.d.ts.map +1 -0
  82. package/dist/blog/index.d.ts +3 -0
  83. package/dist/blog/index.d.ts.map +1 -1
  84. package/dist/blog/index.js +52 -30
  85. package/dist/blog/index.js.map +1 -1
  86. package/dist/blog/index.mjs +15 -12
  87. package/dist/blog/index.mjs.map +1 -1
  88. package/dist/blog/publication-render.test.d.ts +2 -0
  89. package/dist/blog/publication-render.test.d.ts.map +1 -0
  90. package/dist/blog/publication-routes.test.d.ts +2 -0
  91. package/dist/blog/publication-routes.test.d.ts.map +1 -0
  92. package/dist/blog/routes.d.ts +40 -0
  93. package/dist/blog/routes.d.ts.map +1 -0
  94. package/dist/blog/server-core.d.ts +28 -21
  95. package/dist/blog/server-core.d.ts.map +1 -1
  96. package/dist/blog/server-ui.d.ts +4 -0
  97. package/dist/blog/server-ui.d.ts.map +1 -1
  98. package/dist/blog/server-ui.js +49 -28
  99. package/dist/blog/server-ui.js.map +1 -1
  100. package/dist/blog/server-ui.mjs +9 -15
  101. package/dist/blog/server-ui.mjs.map +1 -1
  102. package/dist/blog/server.d.ts +28 -21
  103. package/dist/blog/server.d.ts.map +1 -1
  104. package/dist/blog/server.js +71 -42
  105. package/dist/blog/server.mjs +3 -2
  106. package/dist/blog/types.d.ts +8 -1
  107. package/dist/blog/types.d.ts.map +1 -1
  108. package/dist/blog-styles-6EY3BS5Y.js +595 -0
  109. package/dist/blog-styles-6EY3BS5Y.js.map +1 -0
  110. package/dist/blog-styles-7AKRUMV7.mjs +592 -0
  111. package/dist/blog-styles-7AKRUMV7.mjs.map +1 -0
  112. package/dist/blog-tables-DWDEWA3S.js +17 -0
  113. package/dist/blog-tables-DWDEWA3S.js.map +1 -0
  114. package/dist/blog-tables-QGIHOESZ.mjs +4 -0
  115. package/dist/blog-tables-QGIHOESZ.mjs.map +1 -0
  116. package/dist/{chunk-OIJ435IZ.js → chunk-2CMSWJWC.js} +18 -18
  117. package/dist/{chunk-OIJ435IZ.js.map → chunk-2CMSWJWC.js.map} +1 -1
  118. package/dist/{chunk-K37JPEQW.js → chunk-2OU4KBUN.js} +26 -23
  119. package/dist/chunk-2OU4KBUN.js.map +1 -0
  120. package/dist/{chunk-JSLYNYTB.mjs → chunk-3B6CXGAK.mjs} +3 -3
  121. package/dist/{chunk-JSLYNYTB.mjs.map → chunk-3B6CXGAK.mjs.map} +1 -1
  122. package/dist/{chunk-HMFFAUCD.js → chunk-3DWIYCQX.js} +2 -2
  123. package/dist/chunk-3DWIYCQX.js.map +1 -0
  124. package/dist/{chunk-3EPMDPWI.js → chunk-3SDMJMN2.js} +5 -5
  125. package/dist/{chunk-3EPMDPWI.js.map → chunk-3SDMJMN2.js.map} +1 -1
  126. package/dist/chunk-4B4S56WJ.mjs +110 -0
  127. package/dist/chunk-4B4S56WJ.mjs.map +1 -0
  128. package/dist/chunk-4U5NCKQY.mjs +39 -0
  129. package/dist/chunk-4U5NCKQY.mjs.map +1 -0
  130. package/dist/{chunk-CQUA2AUA.mjs → chunk-4XGACM7D.mjs} +3 -3
  131. package/dist/{chunk-CQUA2AUA.mjs.map → chunk-4XGACM7D.mjs.map} +1 -1
  132. package/dist/{chunk-AVM4OZHR.mjs → chunk-5TGAUWNO.mjs} +3 -3
  133. package/dist/{chunk-AVM4OZHR.mjs.map → chunk-5TGAUWNO.mjs.map} +1 -1
  134. package/dist/{chunk-RO55G3OA.mjs → chunk-64BOVMXG.mjs} +3 -3
  135. package/dist/{chunk-RO55G3OA.mjs.map → chunk-64BOVMXG.mjs.map} +1 -1
  136. package/dist/{chunk-JBGRXICL.js → chunk-746RKQHA.js} +75 -70
  137. package/dist/chunk-746RKQHA.js.map +1 -0
  138. package/dist/{chunk-N3C323NY.mjs → chunk-7PPNXORV.mjs} +3 -3
  139. package/dist/{chunk-N3C323NY.mjs.map → chunk-7PPNXORV.mjs.map} +1 -1
  140. package/dist/{chunk-DYKFC7WY.js → chunk-A3F5GRNJ.js} +8 -8
  141. package/dist/{chunk-DYKFC7WY.js.map → chunk-A3F5GRNJ.js.map} +1 -1
  142. package/dist/{chunk-4TU246Q4.mjs → chunk-AEARU24Q.mjs} +40 -26
  143. package/dist/chunk-AEARU24Q.mjs.map +1 -0
  144. package/dist/{chunk-5BZDHZCN.js → chunk-BNOQXDPJ.js} +4 -4
  145. package/dist/{chunk-5BZDHZCN.js.map → chunk-BNOQXDPJ.js.map} +1 -1
  146. package/dist/{chunk-XQZTOWS3.js → chunk-CT5REGAK.js} +15 -15
  147. package/dist/{chunk-XQZTOWS3.js.map → chunk-CT5REGAK.js.map} +1 -1
  148. package/dist/{chunk-KOP3DPIR.mjs → chunk-DRLHQQBH.mjs} +4 -4
  149. package/dist/{chunk-KOP3DPIR.mjs.map → chunk-DRLHQQBH.mjs.map} +1 -1
  150. package/dist/{chunk-Y7SRO7MJ.mjs → chunk-DYULWKDC.mjs} +4 -4
  151. package/dist/{chunk-Y7SRO7MJ.mjs.map → chunk-DYULWKDC.mjs.map} +1 -1
  152. package/dist/{chunk-DHXQBTXE.mjs → chunk-EEQYKMGH.mjs} +75 -70
  153. package/dist/chunk-EEQYKMGH.mjs.map +1 -0
  154. package/dist/chunk-ESP5RMB7.js +42 -0
  155. package/dist/chunk-ESP5RMB7.js.map +1 -0
  156. package/dist/{chunk-4DE2KJ7R.js → chunk-FF5N5D3D.js} +8 -8
  157. package/dist/{chunk-4DE2KJ7R.js.map → chunk-FF5N5D3D.js.map} +1 -1
  158. package/dist/{chunk-757HXAYX.js → chunk-FYVLQ3OU.js} +3 -3
  159. package/dist/{chunk-757HXAYX.js.map → chunk-FYVLQ3OU.js.map} +1 -1
  160. package/dist/{chunk-OC6PU7U2.mjs → chunk-G5HUI4BO.mjs} +3 -3
  161. package/dist/{chunk-OC6PU7U2.mjs.map → chunk-G5HUI4BO.mjs.map} +1 -1
  162. package/dist/chunk-G6WF4G3E.js +43 -0
  163. package/dist/chunk-G6WF4G3E.js.map +1 -0
  164. package/dist/chunk-GHECYDSZ.mjs +134 -0
  165. package/dist/chunk-GHECYDSZ.mjs.map +1 -0
  166. package/dist/{chunk-JTO3K5B7.mjs → chunk-HBI67P7Y.mjs} +4 -4
  167. package/dist/{chunk-JTO3K5B7.mjs.map → chunk-HBI67P7Y.mjs.map} +1 -1
  168. package/dist/{chunk-FFJVQWKO.js → chunk-HFJQMIFM.js} +4 -4
  169. package/dist/{chunk-FFJVQWKO.js.map → chunk-HFJQMIFM.js.map} +1 -1
  170. package/dist/{chunk-A3NNUKFA.js → chunk-HX3BRMOX.js} +96 -644
  171. package/dist/chunk-HX3BRMOX.js.map +1 -0
  172. package/dist/{chunk-3TXX5KIN.js → chunk-JNRHTZL4.js} +2 -2
  173. package/dist/{chunk-3TXX5KIN.js.map → chunk-JNRHTZL4.js.map} +1 -1
  174. package/dist/{chunk-R3LYTIVN.js → chunk-KAUUGRYB.js} +5 -5
  175. package/dist/{chunk-R3LYTIVN.js.map → chunk-KAUUGRYB.js.map} +1 -1
  176. package/dist/{chunk-L2LJQIM3.js → chunk-KPKQKFT4.js} +11 -11
  177. package/dist/chunk-KPKQKFT4.js.map +1 -0
  178. package/dist/chunk-LC7AM4J5.js +118 -0
  179. package/dist/chunk-LC7AM4J5.js.map +1 -0
  180. package/dist/{chunk-GFNXWS3I.js → chunk-MCJF2KJ6.js} +5 -5
  181. package/dist/{chunk-GFNXWS3I.js.map → chunk-MCJF2KJ6.js.map} +1 -1
  182. package/dist/{chunk-Z7K5AMCE.js → chunk-MNYM2XU4.js} +4 -4
  183. package/dist/{chunk-Z7K5AMCE.js.map → chunk-MNYM2XU4.js.map} +1 -1
  184. package/dist/{chunk-6QABCGM6.mjs → chunk-MU7IEPDG.mjs} +4 -4
  185. package/dist/chunk-MU7IEPDG.mjs.map +1 -0
  186. package/dist/chunk-NSWO43XW.mjs +39 -0
  187. package/dist/chunk-NSWO43XW.mjs.map +1 -0
  188. package/dist/{chunk-Z33JXJTJ.js → chunk-NZSFOZJV.js} +40 -26
  189. package/dist/chunk-NZSFOZJV.js.map +1 -0
  190. package/dist/{chunk-ZKR5AJV5.mjs → chunk-OFSA7LUH.mjs} +4 -4
  191. package/dist/{chunk-ZKR5AJV5.mjs.map → chunk-OFSA7LUH.mjs.map} +1 -1
  192. package/dist/{chunk-M7FWXEXC.js → chunk-PIPLBBDH.js} +8 -8
  193. package/dist/{chunk-M7FWXEXC.js.map → chunk-PIPLBBDH.js.map} +1 -1
  194. package/dist/{chunk-FDVE56JS.js → chunk-Q26VZNM2.js} +3 -3
  195. package/dist/{chunk-FDVE56JS.js.map → chunk-Q26VZNM2.js.map} +1 -1
  196. package/dist/{chunk-6AZTRTCG.js → chunk-QEGUI2Q2.js} +15 -15
  197. package/dist/{chunk-6AZTRTCG.js.map → chunk-QEGUI2Q2.js.map} +1 -1
  198. package/dist/{chunk-GPNBBUEN.js → chunk-QFNSM77X.js} +3 -3
  199. package/dist/{chunk-GPNBBUEN.js.map → chunk-QFNSM77X.js.map} +1 -1
  200. package/dist/{chunk-QZ54OCWD.mjs → chunk-R4MX6EOM.mjs} +7 -7
  201. package/dist/{chunk-QZ54OCWD.mjs.map → chunk-R4MX6EOM.mjs.map} +1 -1
  202. package/dist/{chunk-67CHHDBL.mjs → chunk-RMMHWSPP.mjs} +96 -644
  203. package/dist/chunk-RMMHWSPP.mjs.map +1 -0
  204. package/dist/{chunk-B4BFQSSS.mjs → chunk-RU54J2PY.mjs} +4 -4
  205. package/dist/chunk-RU54J2PY.mjs.map +1 -0
  206. package/dist/{chunk-AXAIUCSF.mjs → chunk-RZUZMUTN.mjs} +9 -8
  207. package/dist/chunk-RZUZMUTN.mjs.map +1 -0
  208. package/dist/{chunk-NSLYY62T.mjs → chunk-S6FEC6UT.mjs} +9 -5
  209. package/dist/chunk-S6FEC6UT.mjs.map +1 -0
  210. package/dist/{chunk-3DPXOZAU.mjs → chunk-SHLWA6JY.mjs} +2 -2
  211. package/dist/chunk-SHLWA6JY.mjs.map +1 -0
  212. package/dist/{chunk-E33HJMRP.js → chunk-SQVYLIIN.js} +11 -7
  213. package/dist/chunk-SQVYLIIN.js.map +1 -0
  214. package/dist/chunk-SUZ3ZLB2.js +8 -0
  215. package/dist/{chunk-D37M7MIH.js.map → chunk-SUZ3ZLB2.js.map} +1 -1
  216. package/dist/{chunk-DZDWBQKA.mjs → chunk-TALEV3IH.mjs} +3 -3
  217. package/dist/{chunk-DZDWBQKA.mjs.map → chunk-TALEV3IH.mjs.map} +1 -1
  218. package/dist/{chunk-UOTXSWKZ.mjs → chunk-TP7H6BSK.mjs} +2 -2
  219. package/dist/{chunk-UOTXSWKZ.mjs.map → chunk-TP7H6BSK.mjs.map} +1 -1
  220. package/dist/{chunk-XW5KNCWJ.mjs → chunk-TX2QQ7IX.mjs} +3 -3
  221. package/dist/{chunk-XW5KNCWJ.mjs.map → chunk-TX2QQ7IX.mjs.map} +1 -1
  222. package/dist/{chunk-PEEQMI7U.js → chunk-UNPEMSLK.js} +12 -11
  223. package/dist/chunk-UNPEMSLK.js.map +1 -0
  224. package/dist/{chunk-42F5EK24.mjs → chunk-UZL2QU2V.mjs} +16 -13
  225. package/dist/chunk-UZL2QU2V.mjs.map +1 -0
  226. package/dist/{chunk-6VG65AIA.mjs → chunk-V6NOM7PJ.mjs} +3 -3
  227. package/dist/{chunk-6VG65AIA.mjs.map → chunk-V6NOM7PJ.mjs.map} +1 -1
  228. package/dist/{chunk-W23TMUKB.js → chunk-VAS3LH5W.js} +418 -98
  229. package/dist/chunk-VAS3LH5W.js.map +1 -0
  230. package/dist/{chunk-TS3N3LGZ.mjs → chunk-VYHRAICF.mjs} +4 -4
  231. package/dist/{chunk-TS3N3LGZ.mjs.map → chunk-VYHRAICF.mjs.map} +1 -1
  232. package/dist/{chunk-G3YUSRCL.js → chunk-W5NVW23S.js} +4 -4
  233. package/dist/{chunk-G3YUSRCL.js.map → chunk-W5NVW23S.js.map} +1 -1
  234. package/dist/chunk-WDBCXRTT.mjs +6 -0
  235. package/dist/{chunk-OUERH2T4.mjs.map → chunk-WDBCXRTT.mjs.map} +1 -1
  236. package/dist/{chunk-ZOJ3TLO5.mjs → chunk-WIZRCI6J.mjs} +3 -3
  237. package/dist/{chunk-ZOJ3TLO5.mjs.map → chunk-WIZRCI6J.mjs.map} +1 -1
  238. package/dist/{chunk-HDQTZAGE.mjs → chunk-X2XFLYZ3.mjs} +3 -3
  239. package/dist/{chunk-HDQTZAGE.mjs.map → chunk-X2XFLYZ3.mjs.map} +1 -1
  240. package/dist/{chunk-HVFXFPUJ.mjs → chunk-XQYC4KMH.mjs} +413 -94
  241. package/dist/chunk-XQYC4KMH.mjs.map +1 -0
  242. package/dist/{chunk-KPFPSOYS.js → chunk-YNC5D3FT.js} +12 -12
  243. package/dist/{chunk-KPFPSOYS.js.map → chunk-YNC5D3FT.js.map} +1 -1
  244. package/dist/chunk-YQTE32QK.js +137 -0
  245. package/dist/chunk-YQTE32QK.js.map +1 -0
  246. package/dist/{chunk-PZXKFHPO.js → chunk-YYAFHIY7.js} +15 -15
  247. package/dist/chunk-YYAFHIY7.js.map +1 -0
  248. package/dist/{chunk-MANX6422.js → chunk-Z6S4MWSR.js} +7 -7
  249. package/dist/{chunk-MANX6422.js.map → chunk-Z6S4MWSR.js.map} +1 -1
  250. package/dist/{chunk-DVH3JHZ3.mjs → chunk-ZRQFG3L6.mjs} +5 -5
  251. package/dist/{chunk-DVH3JHZ3.mjs.map → chunk-ZRQFG3L6.mjs.map} +1 -1
  252. package/dist/cli/agent/checks.d.ts.map +1 -1
  253. package/dist/cli/agent/ssr-bailout.d.ts +27 -0
  254. package/dist/cli/agent/ssr-bailout.d.ts.map +1 -0
  255. package/dist/cli/agent/ssr-bailout.test.d.ts +2 -0
  256. package/dist/cli/agent/ssr-bailout.test.d.ts.map +1 -0
  257. package/dist/cli/codemod/transforms.d.ts.map +1 -1
  258. package/dist/cli/index.js +38 -51
  259. package/dist/cli/index.js.map +1 -1
  260. package/dist/cli/index.mjs +36 -49
  261. package/dist/cli/index.mjs.map +1 -1
  262. package/dist/cli/migrator/index.d.ts.map +1 -1
  263. package/dist/client/index.d.ts +1 -0
  264. package/dist/client/index.d.ts.map +1 -1
  265. package/dist/client/index.js +20 -7
  266. package/dist/client/index.js.map +1 -1
  267. package/dist/client/index.mjs +5 -4
  268. package/dist/client/index.mjs.map +1 -1
  269. package/dist/cms/index.js.map +1 -1
  270. package/dist/cms/index.mjs.map +1 -1
  271. package/dist/cms/sanity-image.d.ts +1 -1
  272. package/dist/commerce/index.js +58 -58
  273. package/dist/commerce/index.mjs +7 -7
  274. package/dist/engage/ChatWidget.d.ts.map +1 -1
  275. package/dist/engage/EngageWidget.d.ts +3 -4
  276. package/dist/engage/EngageWidget.d.ts.map +1 -1
  277. package/dist/engage/chat-launcher.test.d.ts +2 -0
  278. package/dist/engage/chat-launcher.test.d.ts.map +1 -0
  279. package/dist/engage/index.js +12 -10
  280. package/dist/engage/index.js.map +1 -1
  281. package/dist/engage/index.mjs +9 -7
  282. package/dist/engage/index.mjs.map +1 -1
  283. package/dist/engage/launcher-placement.d.ts +56 -0
  284. package/dist/engage/launcher-placement.d.ts.map +1 -0
  285. package/dist/engage/launcher-placement.test.d.ts +2 -0
  286. package/dist/engage/launcher-placement.test.d.ts.map +1 -0
  287. package/dist/engage/types.d.ts +41 -7
  288. package/dist/engage/types.d.ts.map +1 -1
  289. package/dist/fleet/index.js +8 -8
  290. package/dist/fleet/index.mjs +4 -4
  291. package/dist/forms/index.js +16 -16
  292. package/dist/forms/index.mjs +9 -9
  293. package/dist/forms/server.js +10 -10
  294. package/dist/forms/server.mjs +8 -8
  295. package/dist/forms/static.js +7 -7
  296. package/dist/forms/static.mjs +6 -6
  297. package/dist/images/ManagedImage.d.ts.map +1 -1
  298. package/dist/images/index.js +11 -11
  299. package/dist/images/index.mjs +4 -4
  300. package/dist/index.js +65 -65
  301. package/dist/index.mjs +11 -11
  302. package/dist/layout/SiteKitClientProviders.d.ts.map +1 -1
  303. package/dist/layout/client.d.ts.map +1 -1
  304. package/dist/layout/client.js +8 -8
  305. package/dist/layout/client.mjs +7 -7
  306. package/dist/layout/index.js +10 -10
  307. package/dist/layout/index.mjs +8 -8
  308. package/dist/layout/types.d.ts +7 -3
  309. package/dist/layout/types.d.ts.map +1 -1
  310. package/dist/llms/generateLLMsTxt.d.ts.map +1 -1
  311. package/dist/llms/index.js +12 -12
  312. package/dist/llms/index.mjs +2 -2
  313. package/dist/llms/types.d.ts +7 -1
  314. package/dist/llms/types.d.ts.map +1 -1
  315. package/dist/maps/index.js +5 -5
  316. package/dist/maps/index.mjs +3 -3
  317. package/dist/mcp/WebMcpTools.d.ts +5 -2
  318. package/dist/mcp/WebMcpTools.d.ts.map +1 -1
  319. package/dist/mcp/client.js.map +1 -1
  320. package/dist/mcp/client.mjs.map +1 -1
  321. package/dist/search/index.js +4 -4
  322. package/dist/search/index.mjs +3 -3
  323. package/dist/seo/LocationPageContent.d.ts +6 -5
  324. package/dist/seo/LocationPageContent.d.ts.map +1 -1
  325. package/dist/seo/api.d.ts +4 -5
  326. package/dist/seo/api.d.ts.map +1 -1
  327. package/dist/seo/client.js +5 -5
  328. package/dist/seo/client.mjs +4 -4
  329. package/dist/seo/index.js +42 -42
  330. package/dist/seo/index.js.map +1 -1
  331. package/dist/seo/index.mjs +8 -8
  332. package/dist/seo/index.mjs.map +1 -1
  333. package/dist/seo/routing.d.ts +9 -23
  334. package/dist/seo/routing.d.ts.map +1 -1
  335. package/dist/seo/server-api.d.ts +11 -5
  336. package/dist/seo/server-api.d.ts.map +1 -1
  337. package/dist/seo/server.js +18 -18
  338. package/dist/seo/server.mjs +2 -2
  339. package/dist/server/index.js +3 -3
  340. package/dist/server/index.mjs +2 -2
  341. package/dist/{server-api-HW4PL2L2.mjs → server-api-RG3ZL3DV.mjs} +3 -3
  342. package/dist/{server-api-HW4PL2L2.mjs.map → server-api-RG3ZL3DV.mjs.map} +1 -1
  343. package/dist/{server-api-DB2SIUP4.js → server-api-RYJQAUGO.js} +21 -21
  344. package/dist/{server-api-DB2SIUP4.js.map → server-api-RYJQAUGO.js.map} +1 -1
  345. package/dist/shared/version.d.ts +1 -1
  346. package/dist/shared/visual-viewport-gap.d.ts +52 -0
  347. package/dist/shared/visual-viewport-gap.d.ts.map +1 -0
  348. package/dist/shared/visual-viewport-gap.test.d.ts +2 -0
  349. package/dist/shared/visual-viewport-gap.test.d.ts.map +1 -0
  350. package/dist/signal/index.js +11 -11
  351. package/dist/signal/index.mjs +2 -2
  352. package/dist/sitemap/index.js +2 -2
  353. package/dist/sitemap/index.mjs +1 -1
  354. package/dist/sync/BookingWidget.d.ts +0 -23
  355. package/dist/sync/BookingWidget.d.ts.map +1 -1
  356. package/dist/sync/MeetingFormatStep.d.ts +13 -0
  357. package/dist/sync/MeetingFormatStep.d.ts.map +1 -0
  358. package/dist/sync/api.d.ts +9 -10
  359. package/dist/sync/api.d.ts.map +1 -1
  360. package/dist/sync/booking-flow.d.ts +7 -0
  361. package/dist/sync/booking-flow.d.ts.map +1 -0
  362. package/dist/sync/booking-flow.test.d.ts +2 -0
  363. package/dist/sync/booking-flow.test.d.ts.map +1 -0
  364. package/dist/sync/index.d.ts +2 -2
  365. package/dist/sync/index.d.ts.map +1 -1
  366. package/dist/sync/index.js +20 -16
  367. package/dist/sync/index.mjs +4 -4
  368. package/dist/sync/types.d.ts +34 -0
  369. package/dist/sync/types.d.ts.map +1 -1
  370. package/dist/types.d.ts +9 -0
  371. package/dist/types.d.ts.map +1 -1
  372. package/package.json +1 -1
  373. package/skills/site-kit/SKILL.md +8 -3
  374. package/dist/AnalyticsProvider-2XK54UZW.mjs +0 -11
  375. package/dist/AnalyticsProvider-PM7SOGOS.js +0 -32
  376. package/dist/ChatWidget-4PHZHGG5.mjs +0 -11
  377. package/dist/ChatWidget-7BYSGNO2.js +0 -20
  378. package/dist/EngageWidget-D6M6QWEC.mjs +0 -9
  379. package/dist/EngageWidget-Q4ITKTMJ.js +0 -18
  380. package/dist/ManagedForm-N63YGVNY.js +0 -23
  381. package/dist/ManagedForm-ZUXLHEQU.mjs +0 -14
  382. package/dist/SitemapSync-7OBOJG2L.js +0 -18
  383. package/dist/SitemapSync-G3OLECFI.mjs +0 -9
  384. package/dist/api-N5OLQXYN.js.map +0 -1
  385. package/dist/api-NTHZ6PAW.mjs.map +0 -1
  386. package/dist/chunk-3DPXOZAU.mjs.map +0 -1
  387. package/dist/chunk-42F5EK24.mjs.map +0 -1
  388. package/dist/chunk-4TU246Q4.mjs.map +0 -1
  389. package/dist/chunk-67CHHDBL.mjs.map +0 -1
  390. package/dist/chunk-6QABCGM6.mjs.map +0 -1
  391. package/dist/chunk-A3NNUKFA.js.map +0 -1
  392. package/dist/chunk-AXAIUCSF.mjs.map +0 -1
  393. package/dist/chunk-B4BFQSSS.mjs.map +0 -1
  394. package/dist/chunk-CGCYZJYX.mjs +0 -41
  395. package/dist/chunk-CGCYZJYX.mjs.map +0 -1
  396. package/dist/chunk-D37M7MIH.js +0 -8
  397. package/dist/chunk-DHXQBTXE.mjs.map +0 -1
  398. package/dist/chunk-E33HJMRP.js.map +0 -1
  399. package/dist/chunk-HMFFAUCD.js.map +0 -1
  400. package/dist/chunk-HVFXFPUJ.mjs.map +0 -1
  401. package/dist/chunk-JBGRXICL.js.map +0 -1
  402. package/dist/chunk-K37JPEQW.js.map +0 -1
  403. package/dist/chunk-L2LJQIM3.js.map +0 -1
  404. package/dist/chunk-NSLYY62T.mjs.map +0 -1
  405. package/dist/chunk-OUERH2T4.mjs +0 -6
  406. package/dist/chunk-PEEQMI7U.js.map +0 -1
  407. package/dist/chunk-PZXKFHPO.js.map +0 -1
  408. package/dist/chunk-TPL2IHFI.js +0 -43
  409. package/dist/chunk-TPL2IHFI.js.map +0 -1
  410. package/dist/chunk-W23TMUKB.js.map +0 -1
  411. package/dist/chunk-Z33JXJTJ.js.map +0 -1
@@ -1,8 +1,83 @@
1
1
  'use client';
2
- import { sonorFetch } from './chunk-ZKR5AJV5.mjs';
3
- import { useState, useRef, useMemo, useEffect, useCallback } from 'react';
2
+ import { sonorFetch } from './chunk-OFSA7LUH.mjs';
3
+ import { useState, useRef, useMemo, useCallback, useEffect, useId } from 'react';
4
4
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
5
 
6
+ function MeetingFormatStep({ options, busy, format, address, onFormatChange, onAddressChange, onContinue, onBack }) {
7
+ const id = useId();
8
+ const choices = [
9
+ { value: "virtual", label: "Virtual", description: "Meet online with a Google Meet link." },
10
+ { value: "office", label: "Come to us", description: "Meet in person at our office." },
11
+ { value: "client_location", label: "We come to you", description: `We can meet at your location within about ${options.travel_radius_miles} miles of our office.` }
12
+ ];
13
+ return /* @__PURE__ */ jsxs("form", { onSubmit: (e) => {
14
+ e.preventDefault();
15
+ if (format) onContinue(format, format === "client_location" ? address : void 0);
16
+ }, className: "bw-step sk-meeting-step", children: [
17
+ onBack && /* @__PURE__ */ jsx("button", { type: "button", className: "bw-back sk-meeting-change", onClick: onBack, disabled: busy, children: "\u2190 Change service" }),
18
+ /* @__PURE__ */ jsx("h2", { className: "bw-heading", children: "How would you like to meet?" }),
19
+ /* @__PURE__ */ jsxs("fieldset", { disabled: busy, className: "sk-meeting-choices", children: [
20
+ /* @__PURE__ */ jsx("legend", { className: "sk-meeting-legend", children: "Meeting format" }),
21
+ choices.map((choice) => /* @__PURE__ */ jsxs("label", { className: `sk-meeting-choice ${format === choice.value ? "sk-meeting-selected" : ""}`, children: [
22
+ /* @__PURE__ */ jsx("input", { type: "radio", name: `${id}-format`, value: choice.value, checked: format === choice.value, onChange: () => onFormatChange(choice.value), required: true }),
23
+ /* @__PURE__ */ jsxs("span", { children: [
24
+ /* @__PURE__ */ jsx("strong", { children: choice.label }),
25
+ /* @__PURE__ */ jsx("span", { children: choice.description })
26
+ ] })
27
+ ] }, choice.value))
28
+ ] }),
29
+ format === "office" && /* @__PURE__ */ jsxs("div", { className: "sk-meeting-address", children: [
30
+ /* @__PURE__ */ jsx("p", { children: options.office_address }),
31
+ /* @__PURE__ */ jsx("p", { children: options.office_instructions }),
32
+ /* @__PURE__ */ jsx("a", { href: `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(options.office_address)}`, target: "_blank", rel: "noopener noreferrer", children: "Get directions" })
33
+ ] }),
34
+ format === "client_location" && /* @__PURE__ */ jsxs("fieldset", { disabled: busy, className: "bw-form sk-meeting-fields", children: [
35
+ /* @__PURE__ */ jsx("legend", { children: "Your meeting address" }),
36
+ [
37
+ ["street", "Street address", "street-address"],
38
+ ["unit", "Suite or unit (optional)", "address-line2"],
39
+ ["city", "City", "address-level2"],
40
+ ["region", "State or region", "address-level1"],
41
+ ["postalCode", "Postal code", "postal-code"],
42
+ ["country", "Country", "country-name"]
43
+ ].map(([key, label, autocomplete]) => /* @__PURE__ */ jsxs("div", { className: "bw-field", children: [
44
+ /* @__PURE__ */ jsx("label", { htmlFor: `${id}-${key}`, children: label }),
45
+ /* @__PURE__ */ jsx(
46
+ "input",
47
+ {
48
+ id: `${id}-${key}`,
49
+ value: address[key],
50
+ required: key !== "unit",
51
+ maxLength: 200,
52
+ autoComplete: autocomplete,
53
+ onChange: (e) => onAddressChange({ ...address, [key]: e.target.value })
54
+ }
55
+ )
56
+ ] }, key)),
57
+ /* @__PURE__ */ jsxs("div", { className: "bw-field", children: [
58
+ /* @__PURE__ */ jsx("label", { htmlFor: `${id}-notes`, children: "Parking or access notes (optional)" }),
59
+ /* @__PURE__ */ jsx("textarea", { id: `${id}-notes`, value: address.notes, maxLength: 2e3, onChange: (e) => onAddressChange({ ...address, notes: e.target.value }) })
60
+ ] }),
61
+ options.travel_review_required && /* @__PURE__ */ jsx("p", { children: "We\u2019ll reserve your requested time and confirm after checking travel arrangements." })
62
+ ] }),
63
+ /* @__PURE__ */ jsx("button", { className: "bw-submit", type: "submit", disabled: !format || busy, children: busy ? "Checking meeting details\u2026" : "Choose a time" }),
64
+ /* @__PURE__ */ jsx("style", { children: `
65
+ .sk-meeting-choices { border: 0; padding: 0; margin: 20px 0; display: grid; gap: 10px; }
66
+ .sk-meeting-legend { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
67
+ .sk-meeting-choice { display: flex; align-items: flex-start; gap: 12px; padding: 16px; border: 1px solid var(--sk-border); border-radius: var(--sk-radius); cursor: pointer; background: var(--sk-surface); }
68
+ .sk-meeting-choice input { margin-top: 4px; accent-color: var(--sk-primary); }
69
+ .sk-meeting-choice strong { display: block; color: var(--sk-text-primary); }
70
+ .sk-meeting-choice span span { display: block; margin-top: 4px; font-size: 14px; color: var(--sk-text-secondary); }
71
+ .sk-meeting-selected { border-color: var(--sk-primary); background: var(--sk-primary-light); }
72
+ .sk-meeting-address { padding: 16px; background: var(--sk-surface); border-radius: var(--sk-radius); margin-bottom: 16px; white-space: pre-wrap; }
73
+ .sk-meeting-address a { display: inline-block; margin-top: 8px; color: var(--sk-primary); }
74
+ .sk-meeting-fields { border: 0; padding: 0; margin-bottom: 20px; }
75
+ .sk-meeting-fields legend { margin-bottom: 12px; font-weight: 600; }
76
+ .sk-meeting-step .bw-submit { width: 100%; }
77
+ ` })
78
+ ] });
79
+ }
80
+
6
81
  // src/sync/api.ts
7
82
  var DEFAULT_API_URL = "https://api.sonor.io";
8
83
  function getApiConfig() {
@@ -42,13 +117,14 @@ async function fetchBookingTypeDetails(typeSlug, orgSlug, apiUrl, apiKey) {
42
117
  }
43
118
  return response.json();
44
119
  }
45
- async function fetchAvailability(typeSlug, date, orgSlug, apiUrl, apiKey, timezone, hostId) {
120
+ async function fetchAvailability(typeSlug, date, orgSlug, apiUrl, apiKey, timezone, hostId, meetingToken) {
46
121
  const cfg = getApiConfig();
47
122
  const url = apiUrl || cfg.apiUrl;
48
123
  const key = apiKey || cfg.apiKey;
49
124
  const params = new URLSearchParams({ date });
50
125
  if (timezone) params.append("timezone", timezone);
51
126
  if (hostId) params.append("hostId", hostId);
127
+ if (meetingToken) params.append("meetingToken", meetingToken);
52
128
  const endpoint = key ? `${url}/sync/widget/availability/${typeSlug}?${params}` : `${url}/sync/public/${orgSlug}/availability/${typeSlug}?${params}`;
53
129
  const response = await sonorFetch(endpoint, { headers: buildHeaders() }, { apiKey: key, retries: 0 });
54
130
  if (!response.ok) {
@@ -68,6 +144,11 @@ async function fetchAvailability(typeSlug, date, orgSlug, apiUrl, apiKey, timezo
68
144
  available: slot.available !== false
69
145
  }));
70
146
  }
147
+ async function bookingRequestError(response, fallback) {
148
+ const body = await response.json().catch(() => ({}));
149
+ const message = Array.isArray(body.message) ? body.message.join(". ") : body.message;
150
+ return new Error(typeof message === "string" && message.trim() ? message : fallback);
151
+ }
71
152
  async function createSlotHold(holdData, apiUrl, apiKey) {
72
153
  const cfg = getApiConfig();
73
154
  const url = apiUrl || cfg.apiUrl;
@@ -79,7 +160,7 @@ async function createSlotHold(holdData, apiUrl, apiKey) {
79
160
  body: JSON.stringify(holdData)
80
161
  }, { apiKey: key, retries: 0 });
81
162
  if (!response.ok) {
82
- throw new Error(`Failed to hold slot: ${response.statusText}`);
163
+ throw await bookingRequestError(response, "We couldn\u2019t reserve that time. Please choose another time.");
83
164
  }
84
165
  return response.json();
85
166
  }
@@ -104,12 +185,11 @@ async function createBooking(bookingData, apiUrl, apiKey) {
104
185
  body: JSON.stringify(bookingData)
105
186
  }, { apiKey: key, retries: 0 });
106
187
  if (!response.ok) {
107
- const errorData = await response.json().catch(() => ({}));
108
- throw new Error(errorData.message || `Failed to create booking: ${response.statusText}`);
188
+ throw await bookingRequestError(response, "We couldn\u2019t complete your booking. Please try again.");
109
189
  }
110
190
  return response.json();
111
191
  }
112
- async function fetchAvailableDates(typeSlug, startDate, endDate, orgSlug, apiUrl, apiKey, timezone) {
192
+ async function fetchAvailableDates(typeSlug, startDate, endDate, orgSlug, apiUrl, apiKey, timezone, meetingToken) {
113
193
  const availableDates = [];
114
194
  const start = new Date(startDate);
115
195
  const end = new Date(endDate);
@@ -117,7 +197,7 @@ async function fetchAvailableDates(typeSlug, startDate, endDate, orgSlug, apiUrl
117
197
  while (current <= end) {
118
198
  const dateStr = current.toISOString().split("T")[0];
119
199
  try {
120
- const slots = await fetchAvailability(typeSlug, dateStr, orgSlug, apiUrl, apiKey, timezone);
200
+ const slots = await fetchAvailability(typeSlug, dateStr, orgSlug, apiUrl, apiKey, timezone, void 0, meetingToken);
121
201
  if (slots.some((s) => s.available)) {
122
202
  availableDates.push(dateStr);
123
203
  }
@@ -164,6 +244,33 @@ function formatDuration(minutes) {
164
244
  }
165
245
  return `${hours}h ${mins}m`;
166
246
  }
247
+ async function prepareMeeting(bookingType, format, address, orgSlug, apiUrl, apiKey) {
248
+ const cfg = getApiConfig();
249
+ const url = apiUrl || cfg.apiUrl;
250
+ const key = apiKey || cfg.apiKey;
251
+ const endpoint = key ? `${url}/sync/widget/meeting` : `${url}/sync/public/${orgSlug}/meeting`;
252
+ const response = await sonorFetch(endpoint, {
253
+ method: "POST",
254
+ headers: buildHeaders(true),
255
+ body: JSON.stringify({ bookingType, format, address })
256
+ }, { apiKey: key, retries: 0 });
257
+ if (!response.ok) {
258
+ throw await bookingRequestError(response, "We couldn\u2019t check your meeting details. Please try again.");
259
+ }
260
+ return response.json();
261
+ }
262
+
263
+ // src/sync/booking-flow.ts
264
+ function expiredBookingContext(meeting, hold, now = Date.now()) {
265
+ if (hold) return Date.parse(hold.expiresAt) <= now ? "hold" : null;
266
+ return meeting && Date.parse(meeting.expiresAt) <= now ? "meeting" : null;
267
+ }
268
+ function bookingRecoveryFromError(error) {
269
+ const message = error instanceof Error ? error.message : "";
270
+ if (/meeting details expired|choose how you.d like to meet first/i.test(message)) return "meeting";
271
+ if (/time reservation expired|invalid slot hold|meeting details changed/i.test(message)) return "hold";
272
+ return null;
273
+ }
167
274
  var DEFAULT_API_URL2 = "https://api.sonor.io";
168
275
  var DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
169
276
  var MONTHS = [
@@ -275,6 +382,17 @@ function BookingWidget({
275
382
  const [guestInfo, setGuestInfo] = useState({ name: "", email: "" });
276
383
  const [bookingResult, setBookingResult] = useState(null);
277
384
  const [submitting, setSubmitting] = useState(false);
385
+ const [meeting, setMeeting] = useState(null);
386
+ const [meetingFormat, setMeetingFormat] = useState(null);
387
+ const [meetingAddress, setMeetingAddress] = useState({ street: "", city: "", region: "", postalCode: "", country: "United States", unit: "", notes: "" });
388
+ const [recovery, setRecovery] = useState(null);
389
+ const [sessionId] = useState(() => `bw-${Date.now()}-${Math.random().toString(36).slice(2)}`);
390
+ const requestRef = useRef(0);
391
+ const busyRef = useRef(false);
392
+ const bookingInFlightRef = useRef(false);
393
+ const holdRef = useRef(null);
394
+ const onErrorRef = useRef(onError);
395
+ onErrorRef.current = onError;
278
396
  const [autoProbing, setAutoProbing] = useState(false);
279
397
  const probeRef = useRef(0);
280
398
  const prefetchedRef = useRef(null);
@@ -299,26 +417,79 @@ function BookingWidget({
299
417
  d.setDate(d.getDate() + daysToShow);
300
418
  return d;
301
419
  }, [today, daysToShow]);
420
+ const setActiveHold = useCallback((value) => {
421
+ holdRef.current = value;
422
+ setHold(value);
423
+ }, []);
424
+ const resetScheduling = useCallback((nextStep, clearMeeting = false) => {
425
+ ++requestRef.current;
426
+ const previous = holdRef.current;
427
+ setActiveHold(null);
428
+ if (previous) releaseSlotHold(previous.holdId, apiUrl, apiKey).catch(() => {
429
+ });
430
+ setSelectedDate(null);
431
+ setSelectedSlot(null);
432
+ setConfirmedSlot(false);
433
+ setSlots([]);
434
+ setSlotsLoading(false);
435
+ prefetchedRef.current = null;
436
+ if (clearMeeting) setMeeting(null);
437
+ setRecovery(null);
438
+ setError(null);
439
+ setStep(nextStep);
440
+ }, [apiUrl, apiKey, setActiveHold]);
441
+ const reportRequestError = useCallback((err) => {
442
+ setRecovery(bookingRecoveryFromError(err));
443
+ setError(err.message);
444
+ onErrorRef.current?.(err);
445
+ }, []);
446
+ useEffect(() => () => {
447
+ ++requestRef.current;
448
+ if (holdRef.current && !bookingInFlightRef.current) {
449
+ releaseSlotHold(holdRef.current.holdId, apiUrl, apiKey).catch(() => {
450
+ });
451
+ }
452
+ holdRef.current = null;
453
+ }, [apiUrl, apiKey]);
302
454
  useEffect(() => {
455
+ let cancelled = false;
456
+ ++requestRef.current;
457
+ busyRef.current = false;
458
+ bookingInFlightRef.current = false;
459
+ resetScheduling(bookingTypeSlug ? "datetime" : "type", true);
460
+ setSelectedType(null);
461
+ setMeetingFormat(null);
462
+ setBookingResult(null);
463
+ setSubmitting(false);
303
464
  if (bookingTypeSlug) {
304
465
  setLoading(true);
305
466
  fetchBookingTypeDetails(bookingTypeSlug, orgSlug, apiUrl, apiKey).then((type) => {
306
- setSelectedType(type);
307
- setStep("datetime");
467
+ if (!cancelled) {
468
+ setSelectedType(type);
469
+ setStep(type.meeting_options ? "format" : "datetime");
470
+ }
308
471
  }).catch((err) => {
309
- setError(err.message);
310
- onError?.(err);
311
- }).finally(() => setLoading(false));
472
+ if (!cancelled) reportRequestError(err);
473
+ }).finally(() => {
474
+ if (!cancelled) setLoading(false);
475
+ });
312
476
  } else {
313
477
  setLoading(true);
314
- fetchBookingTypes(orgSlug, apiUrl, apiKey).then((types) => setBookingTypes(types.filter((t) => t.is_active))).catch((err) => {
315
- setError(err.message);
316
- onError?.(err);
317
- }).finally(() => setLoading(false));
478
+ fetchBookingTypes(orgSlug, apiUrl, apiKey).then((types) => {
479
+ if (!cancelled) setBookingTypes(types.filter((t) => t.is_active));
480
+ }).catch((err) => {
481
+ if (!cancelled) reportRequestError(err);
482
+ }).finally(() => {
483
+ if (!cancelled) setLoading(false);
484
+ });
318
485
  }
319
- }, [orgSlug, apiKey, bookingTypeSlug, apiUrl, onError]);
486
+ return () => {
487
+ cancelled = true;
488
+ ++requestRef.current;
489
+ };
490
+ }, [orgSlug, apiKey, bookingTypeSlug, apiUrl, resetScheduling, reportRequestError]);
320
491
  useEffect(() => {
321
- if (!selectedDate || !selectedType) return;
492
+ if (!selectedDate || !selectedType || selectedType.meeting_options && !meeting) return;
322
493
  const dateStr = toLocalDateStr(selectedDate);
323
494
  setSelectedSlot(null);
324
495
  setConfirmedSlot(false);
@@ -329,15 +500,22 @@ function BookingWidget({
329
500
  setSlotsLoading(false);
330
501
  return;
331
502
  }
503
+ let cancelled = false;
332
504
  setSlotsLoading(true);
333
505
  setSlots([]);
334
- fetchAvailability(selectedType.slug, dateStr, orgSlug, apiUrl, apiKey, timezone).then((s) => setSlots(s.filter((slot) => slot.available))).catch((err) => {
335
- setError(err.message);
336
- onError?.(err);
337
- }).finally(() => setSlotsLoading(false));
338
- }, [selectedDate, selectedType, orgSlug, apiKey, apiUrl, timezone, onError]);
506
+ fetchAvailability(selectedType.slug, dateStr, orgSlug, apiUrl, apiKey, timezone, void 0, meeting?.meetingToken).then((s) => {
507
+ if (!cancelled) setSlots(s.filter((slot) => slot.available));
508
+ }).catch((err) => {
509
+ if (!cancelled) reportRequestError(err);
510
+ }).finally(() => {
511
+ if (!cancelled) setSlotsLoading(false);
512
+ });
513
+ return () => {
514
+ cancelled = true;
515
+ };
516
+ }, [selectedDate, selectedType, orgSlug, apiKey, apiUrl, timezone, reportRequestError, meeting]);
339
517
  useEffect(() => {
340
- if (!autoSelectFirstDay || !selectedType || selectedDate) return;
518
+ if (!autoSelectFirstDay || !selectedType || selectedDate || step !== "datetime" || recovery || selectedType.meeting_options && !meeting) return;
341
519
  const probeId = ++probeRef.current;
342
520
  let cancelled = false;
343
521
  const PROBE_DAYS = 14;
@@ -350,7 +528,7 @@ function BookingWidget({
350
528
  d.setDate(d.getDate() + i);
351
529
  if (d > maxDate) break;
352
530
  const dateStr = toLocalDateStr(d);
353
- const s = await fetchAvailability(selectedType.slug, dateStr, orgSlug, apiUrl, apiKey, timezone);
531
+ const s = await fetchAvailability(selectedType.slug, dateStr, orgSlug, apiUrl, apiKey, timezone, void 0, meeting?.meetingToken);
354
532
  if (cancelled || probeRef.current !== probeId) return;
355
533
  const open = s.filter((slot) => slot.available);
356
534
  if (open.length > 0) {
@@ -360,7 +538,8 @@ function BookingWidget({
360
538
  return;
361
539
  }
362
540
  }
363
- } catch {
541
+ } catch (err) {
542
+ if (!cancelled && bookingRecoveryFromError(err)) reportRequestError(err);
364
543
  } finally {
365
544
  if (!cancelled && probeRef.current === probeId) setAutoProbing(false);
366
545
  }
@@ -369,46 +548,92 @@ function BookingWidget({
369
548
  cancelled = true;
370
549
  setAutoProbing(false);
371
550
  };
372
- }, [autoSelectFirstDay, selectedType, selectedDate, orgSlug, apiKey, apiUrl, timezone, today, maxDate]);
551
+ }, [autoSelectFirstDay, selectedType, selectedDate, orgSlug, apiKey, apiUrl, timezone, today, maxDate, step, meeting, recovery, reportRequestError]);
552
+ useEffect(() => {
553
+ if (step !== "datetime" && step !== "form" || loading || submitting) return;
554
+ const expiry = hold?.expiresAt || meeting?.expiresAt;
555
+ if (!expiry || !Number.isFinite(Date.parse(expiry))) return;
556
+ const checkExpiry = () => {
557
+ const expired = expiredBookingContext(meeting, hold);
558
+ if (!busyRef.current && expired) setRecovery(expired);
559
+ };
560
+ const timer = setTimeout(checkExpiry, Math.max(0, Date.parse(expiry) - Date.now()));
561
+ window.addEventListener("focus", checkExpiry);
562
+ return () => {
563
+ clearTimeout(timer);
564
+ window.removeEventListener("focus", checkExpiry);
565
+ };
566
+ }, [meeting, hold, step, loading, submitting]);
373
567
  const handleSlotSelect = useCallback((slot) => {
568
+ if (busyRef.current) return;
374
569
  setSelectedSlot(slot);
375
570
  setConfirmedSlot(false);
376
571
  }, []);
377
572
  const handleSlotConfirm = useCallback(async () => {
378
- if (!selectedType || !selectedSlot) return;
379
- if (hold) await releaseSlotHold(hold.holdId, apiUrl, apiKey).catch(() => {
380
- });
573
+ if (!selectedType || !selectedSlot || busyRef.current || recovery) return;
574
+ const expired = expiredBookingContext(meeting, null);
575
+ if (expired) {
576
+ setRecovery(expired);
577
+ return;
578
+ }
579
+ const requestId = ++requestRef.current;
580
+ busyRef.current = true;
381
581
  setLoading(true);
582
+ setError(null);
382
583
  try {
584
+ const previous = holdRef.current;
585
+ setActiveHold(null);
586
+ if (previous) await releaseSlotHold(previous.holdId, apiUrl, apiKey).catch(() => {
587
+ });
588
+ if (requestId !== requestRef.current) return;
383
589
  const newHold = await createSlotHold(
384
590
  {
591
+ meetingToken: meeting?.meetingToken,
592
+ org: apiKey ? void 0 : orgSlug,
385
593
  bookingType: selectedType.slug,
386
594
  slotStart: selectedSlot.start,
387
595
  slotEnd: selectedSlot.end,
388
596
  hostId: selectedSlot.hostId || "",
389
- sessionId: `bw-${Date.now()}`
597
+ sessionId
390
598
  },
391
599
  apiUrl,
392
600
  apiKey
393
601
  );
394
- setHold(newHold);
602
+ if (requestId !== requestRef.current) {
603
+ await releaseSlotHold(newHold.holdId, apiUrl, apiKey).catch(() => {
604
+ });
605
+ return;
606
+ }
607
+ setActiveHold(newHold);
395
608
  setConfirmedSlot(true);
396
609
  setStep("form");
397
610
  } catch (err) {
398
- setError(err.message);
399
- onError?.(err);
611
+ if (requestId === requestRef.current) reportRequestError(err);
400
612
  } finally {
401
- setLoading(false);
613
+ if (requestId === requestRef.current) {
614
+ busyRef.current = false;
615
+ setLoading(false);
616
+ }
402
617
  }
403
- }, [selectedType, selectedSlot, hold, timezone, apiUrl, apiKey, onError]);
618
+ }, [selectedType, selectedSlot, apiUrl, apiKey, meeting, sessionId, orgSlug, recovery, setActiveHold, reportRequestError]);
404
619
  const handleBookingSubmit = useCallback(async (e) => {
405
620
  e.preventDefault();
406
- if (!selectedType || !selectedSlot) return;
621
+ if (!selectedType || !selectedSlot || busyRef.current || recovery) return;
622
+ const expired = expiredBookingContext(meeting, hold);
623
+ if (expired) {
624
+ setRecovery(expired);
625
+ return;
626
+ }
627
+ const requestId = ++requestRef.current;
628
+ busyRef.current = true;
629
+ bookingInFlightRef.current = true;
407
630
  setSubmitting(true);
408
631
  setError(null);
409
632
  try {
410
633
  const result = await createBooking(
411
634
  {
635
+ meetingToken: meeting?.meetingToken,
636
+ org: apiKey ? void 0 : orgSlug,
412
637
  bookingType: selectedType.slug,
413
638
  scheduledAt: selectedSlot.start,
414
639
  hostId: selectedSlot.hostId || "",
@@ -419,31 +644,82 @@ function BookingWidget({
419
644
  source: "main-site",
420
645
  timezone,
421
646
  holdId: hold?.holdId,
422
- sessionId: `bw-${Date.now()}`,
647
+ sessionId,
423
648
  sourceUrl: typeof window !== "undefined" ? window.location.href : void 0
424
649
  },
425
650
  apiUrl,
426
651
  apiKey
427
652
  );
653
+ if (requestId !== requestRef.current) return;
654
+ setActiveHold(null);
428
655
  setBookingResult(result);
429
656
  setStep("success");
430
657
  onBookingComplete?.(result);
431
658
  } catch (err) {
432
- setError(err.message);
433
- onError?.(err);
659
+ if (requestId === requestRef.current) reportRequestError(err);
660
+ else if (hold) releaseSlotHold(hold.holdId, apiUrl, apiKey).catch(() => {
661
+ });
434
662
  } finally {
435
- setSubmitting(false);
663
+ if (requestId === requestRef.current) {
664
+ busyRef.current = false;
665
+ bookingInFlightRef.current = false;
666
+ setSubmitting(false);
667
+ }
436
668
  }
437
- }, [selectedType, selectedSlot, guestInfo, timezone, hold, apiUrl, apiKey, onBookingComplete, onError]);
438
- useEffect(() => {
439
- return () => {
440
- if (hold) releaseSlotHold(hold.holdId, apiUrl, apiKey).catch(() => {
441
- });
442
- };
443
- }, [hold, apiUrl, apiKey]);
669
+ }, [selectedType, selectedSlot, guestInfo, timezone, hold, apiUrl, apiKey, onBookingComplete, meeting, sessionId, orgSlug, recovery, setActiveHold, reportRequestError]);
670
+ const chooseFormat = async (format, address) => {
671
+ if (!selectedType || busyRef.current) return;
672
+ const requestId = ++requestRef.current;
673
+ busyRef.current = true;
674
+ setLoading(true);
675
+ setError(null);
676
+ try {
677
+ const prepared = await prepareMeeting(selectedType.slug, format, address, orgSlug, apiUrl, apiKey);
678
+ if (requestId !== requestRef.current) return;
679
+ setMeeting(prepared);
680
+ setRecovery(null);
681
+ setSelectedDate(null);
682
+ setSelectedSlot(null);
683
+ prefetchedRef.current = null;
684
+ setStep("datetime");
685
+ } catch (err) {
686
+ if (requestId === requestRef.current) reportRequestError(err);
687
+ } finally {
688
+ if (requestId === requestRef.current) {
689
+ busyRef.current = false;
690
+ setLoading(false);
691
+ }
692
+ }
693
+ };
694
+ const changeFormat = () => {
695
+ if (!busyRef.current) resetScheduling("format", true);
696
+ };
697
+ const changeService = () => {
698
+ if (busyRef.current) return;
699
+ resetScheduling("type", true);
700
+ setSelectedType(null);
701
+ setMeetingFormat(null);
702
+ };
703
+ const recoverReservation = () => {
704
+ if (busyRef.current) return;
705
+ const needsMeeting = recovery === "meeting" || expiredBookingContext(meeting, null) === "meeting";
706
+ resetScheduling(needsMeeting ? "format" : "datetime", needsMeeting);
707
+ };
708
+ const displayType = selectedType ? {
709
+ ...selectedType,
710
+ ...meeting ? { location_type: meeting.location_type, location_details: meeting.location_details, location_instructions: meeting.location_instructions } : {},
711
+ ...bookingResult ? {
712
+ location_type: bookingResult.booking.location_type || selectedType.location_type,
713
+ location_details: bookingResult.booking.location_details,
714
+ location_instructions: bookingResult.booking.location_instructions,
715
+ video_link: bookingResult.booking.video_link
716
+ } : {}
717
+ } : null;
718
+ const isPending = bookingResult?.booking.status === "pending";
444
719
  const canGoPrev = viewMonth.getFullYear() > today.getFullYear() || viewMonth.getMonth() > today.getMonth();
445
720
  const canGoNext = viewMonth < maxDate;
446
721
  const goMonth = (dir) => {
722
+ if (busyRef.current) return;
447
723
  setViewMonth((prev) => new Date(prev.getFullYear(), prev.getMonth() + dir, 1));
448
724
  };
449
725
  const groupedSlots = useMemo(() => {
@@ -478,10 +754,17 @@ function BookingWidget({
478
754
  "--sk-input-focus-ring": styles.primaryColor ? `color-mix(in srgb, ${styles.primaryColor} 12%, ${styles.backgroundColor || "white"})` : "#e8f1ff"
479
755
  };
480
756
  return /* @__PURE__ */ jsxs("div", { className: `bw-root ${className}`, style: cssVars, children: [
481
- error && /* @__PURE__ */ jsxs("div", { className: "bw-error", role: "alert", children: [
757
+ error && !recovery && /* @__PURE__ */ jsxs("div", { className: "bw-error", role: "alert", children: [
482
758
  /* @__PURE__ */ jsx("span", { children: error }),
483
759
  /* @__PURE__ */ jsx("button", { onClick: () => setError(null), "aria-label": "Dismiss error", children: "\xD7" })
484
760
  ] }),
761
+ recovery && /* @__PURE__ */ jsxs("div", { className: "sk-booking-recovery", role: "alert", children: [
762
+ /* @__PURE__ */ jsxs("p", { children: [
763
+ recovery === "meeting" ? "Your meeting details need to be checked again." : "Your time reservation expired. Choose a time to continue.",
764
+ " Your entered details are saved."
765
+ ] }),
766
+ /* @__PURE__ */ jsx("button", { type: "button", className: "bw-submit", onClick: recoverReservation, disabled: loading || submitting, children: recovery === "meeting" ? "Review meeting details" : "Choose another time" })
767
+ ] }),
485
768
  step === "type" && !hideTypeSelector && /* @__PURE__ */ jsxs("div", { className: "bw-step bw-fade-in", children: [
486
769
  /* @__PURE__ */ jsx("h2", { className: "bw-heading", children: "Select a Service" }),
487
770
  loading ? /* @__PURE__ */ jsxs("div", { className: "bw-loading", children: [
@@ -492,8 +775,10 @@ function BookingWidget({
492
775
  {
493
776
  className: "bw-type-card",
494
777
  onClick: () => {
495
- setSelectedType(type);
496
- setStep("datetime");
778
+ if (!busyRef.current) {
779
+ resetScheduling(type.meeting_options ? "format" : "datetime", true);
780
+ setSelectedType(type);
781
+ }
497
782
  },
498
783
  children: [
499
784
  /* @__PURE__ */ jsx("span", { className: "bw-type-name", children: type.name }),
@@ -510,12 +795,23 @@ function BookingWidget({
510
795
  type.id
511
796
  )) })
512
797
  ] }),
798
+ step === "format" && selectedType?.meeting_options && /* @__PURE__ */ jsx(
799
+ MeetingFormatStep,
800
+ {
801
+ options: selectedType.meeting_options,
802
+ busy: loading,
803
+ format: meetingFormat,
804
+ address: meetingAddress,
805
+ onFormatChange: setMeetingFormat,
806
+ onAddressChange: setMeetingAddress,
807
+ onContinue: chooseFormat,
808
+ onBack: !bookingTypeSlug && !hideTypeSelector ? changeService : void 0
809
+ }
810
+ ),
811
+ selectedType?.meeting_options && (step === "datetime" || step === "form") && /* @__PURE__ */ jsx("button", { type: "button", className: "bw-back sk-meeting-change", onClick: changeFormat, disabled: loading || submitting, children: "\u2190 Change meeting format" }),
513
812
  step === "datetime" && selectedType && /* @__PURE__ */ jsxs("div", { className: "bw-step bw-fade-in", children: [
514
813
  /* @__PURE__ */ jsxs("div", { className: "bw-info-header", children: [
515
- !bookingTypeSlug && /* @__PURE__ */ jsx("button", { className: "bw-back", onClick: () => {
516
- setSelectedType(null);
517
- setStep("type");
518
- }, children: /* @__PURE__ */ jsx(ArrowLeftIcon, {}) }),
814
+ !bookingTypeSlug && !hideTypeSelector && /* @__PURE__ */ jsx("button", { className: "bw-back", onClick: changeService, disabled: loading, "aria-label": "Change service", children: /* @__PURE__ */ jsx(ArrowLeftIcon, {}) }),
519
815
  /* @__PURE__ */ jsxs("div", { children: [
520
816
  /* @__PURE__ */ jsx("h2", { className: "bw-heading", children: selectedType.name }),
521
817
  /* @__PURE__ */ jsxs("div", { className: "bw-meta-row", children: [
@@ -529,34 +825,36 @@ function BookingWidget({
529
825
  " ",
530
826
  shortTz
531
827
  ] }),
532
- /* @__PURE__ */ jsx(LocationBadge, { type: selectedType })
828
+ /* @__PURE__ */ jsx(LocationBadge, { type: displayType })
533
829
  ] })
534
830
  ] })
535
831
  ] }),
536
832
  /* @__PURE__ */ jsxs("div", { className: "bw-datetime-layout", children: [
537
833
  /* @__PURE__ */ jsxs("div", { className: "bw-calendar", children: [
538
834
  /* @__PURE__ */ jsxs("div", { className: "bw-cal-header", children: [
539
- /* @__PURE__ */ jsx("button", { className: "bw-cal-nav", onClick: () => goMonth(-1), disabled: !canGoPrev, "aria-label": "Previous month", children: /* @__PURE__ */ jsx(ChevronLeft, {}) }),
835
+ /* @__PURE__ */ jsx("button", { className: "bw-cal-nav", onClick: () => goMonth(-1), disabled: !canGoPrev || loading || !!recovery, "aria-label": "Previous month", children: /* @__PURE__ */ jsx(ChevronLeft, {}) }),
540
836
  /* @__PURE__ */ jsxs("span", { className: "bw-cal-title", children: [
541
837
  MONTHS[viewMonth.getMonth()],
542
838
  " ",
543
839
  viewMonth.getFullYear()
544
840
  ] }),
545
- /* @__PURE__ */ jsx("button", { className: "bw-cal-nav", onClick: () => goMonth(1), disabled: !canGoNext, "aria-label": "Next month", children: /* @__PURE__ */ jsx(ChevronRight, {}) })
841
+ /* @__PURE__ */ jsx("button", { className: "bw-cal-nav", onClick: () => goMonth(1), disabled: !canGoNext || loading || !!recovery, "aria-label": "Next month", children: /* @__PURE__ */ jsx(ChevronRight, {}) })
546
842
  ] }),
547
843
  /* @__PURE__ */ jsx("div", { className: "bw-cal-weekdays", children: DAYS.map((d) => /* @__PURE__ */ jsx("span", { className: "bw-cal-wd", children: d }, d)) }),
548
844
  /* @__PURE__ */ jsx("div", { className: "bw-cal-grid", children: days.map((date, i) => {
549
845
  if (!date) return /* @__PURE__ */ jsx("span", { className: "bw-cal-empty" }, `e-${i}`);
550
846
  const past = isBeforeDay(date, today);
551
847
  const future = date > maxDate;
552
- const disabled = past || future;
848
+ const disabled = past || future || loading || !!recovery;
553
849
  const sel = selectedDate && isSameDay(date, selectedDate);
554
850
  const isToday = isSameDay(date, today);
555
851
  return /* @__PURE__ */ jsx(
556
852
  "button",
557
853
  {
558
854
  className: `bw-cal-day${sel ? " selected" : ""}${isToday ? " today" : ""}${disabled ? " disabled" : ""}`,
559
- onClick: () => !disabled && setSelectedDate(date),
855
+ onClick: () => {
856
+ if (!disabled && !busyRef.current) setSelectedDate(date);
857
+ },
560
858
  disabled,
561
859
  "aria-label": date.toLocaleDateString("en-US", { weekday: "long", month: "long", day: "numeric" }),
562
860
  "aria-pressed": sel || void 0,
@@ -579,15 +877,15 @@ function BookingWidget({
579
877
  /* @__PURE__ */ jsx("p", { className: "bw-times-date", children: selectedDate.toLocaleDateString("en-US", { weekday: "long", month: "short", day: "numeric" }) }),
580
878
  groupedSlots.morning.length > 0 && /* @__PURE__ */ jsxs("div", { className: "bw-time-group", children: [
581
879
  /* @__PURE__ */ jsx("span", { className: "bw-time-label", children: "Morning" }),
582
- groupedSlots.morning.map((slot) => /* @__PURE__ */ jsx(TimeButton, { slot, selected: selectedSlot?.start === slot.start, confirmed: confirmedSlot && selectedSlot?.start === slot.start, onClick: () => handleSlotSelect(slot), onConfirm: handleSlotConfirm, timezone, loading }, slot.start))
880
+ groupedSlots.morning.map((slot) => /* @__PURE__ */ jsx(TimeButton, { slot, selected: selectedSlot?.start === slot.start, confirmed: confirmedSlot && selectedSlot?.start === slot.start, onClick: () => handleSlotSelect(slot), onConfirm: handleSlotConfirm, timezone, loading: loading || !!recovery }, slot.start))
583
881
  ] }),
584
882
  groupedSlots.afternoon.length > 0 && /* @__PURE__ */ jsxs("div", { className: "bw-time-group", children: [
585
883
  /* @__PURE__ */ jsx("span", { className: "bw-time-label", children: "Afternoon" }),
586
- groupedSlots.afternoon.map((slot) => /* @__PURE__ */ jsx(TimeButton, { slot, selected: selectedSlot?.start === slot.start, confirmed: confirmedSlot && selectedSlot?.start === slot.start, onClick: () => handleSlotSelect(slot), onConfirm: handleSlotConfirm, timezone, loading }, slot.start))
884
+ groupedSlots.afternoon.map((slot) => /* @__PURE__ */ jsx(TimeButton, { slot, selected: selectedSlot?.start === slot.start, confirmed: confirmedSlot && selectedSlot?.start === slot.start, onClick: () => handleSlotSelect(slot), onConfirm: handleSlotConfirm, timezone, loading: loading || !!recovery }, slot.start))
587
885
  ] }),
588
886
  groupedSlots.evening.length > 0 && /* @__PURE__ */ jsxs("div", { className: "bw-time-group", children: [
589
887
  /* @__PURE__ */ jsx("span", { className: "bw-time-label", children: "Evening" }),
590
- groupedSlots.evening.map((slot) => /* @__PURE__ */ jsx(TimeButton, { slot, selected: selectedSlot?.start === slot.start, confirmed: confirmedSlot && selectedSlot?.start === slot.start, onClick: () => handleSlotSelect(slot), onConfirm: handleSlotConfirm, timezone, loading }, slot.start))
888
+ groupedSlots.evening.map((slot) => /* @__PURE__ */ jsx(TimeButton, { slot, selected: selectedSlot?.start === slot.start, confirmed: confirmedSlot && selectedSlot?.start === slot.start, onClick: () => handleSlotSelect(slot), onConfirm: handleSlotConfirm, timezone, loading: loading || !!recovery }, slot.start))
591
889
  ] }),
592
890
  (groupedSlots.afternoon.length > 0 || groupedSlots.evening.length > 0) && /* @__PURE__ */ jsx("p", { className: "bw-times-scroll-hint", children: "Scroll for more times" })
593
891
  ] }) })
@@ -595,7 +893,7 @@ function BookingWidget({
595
893
  ] }),
596
894
  step === "form" && selectedType && selectedSlot && /* @__PURE__ */ jsxs("div", { className: "bw-step bw-fade-in", children: [
597
895
  /* @__PURE__ */ jsxs("div", { className: "bw-info-header", children: [
598
- /* @__PURE__ */ jsx("button", { className: "bw-back", onClick: () => setStep("datetime"), children: /* @__PURE__ */ jsx(ArrowLeftIcon, {}) }),
896
+ /* @__PURE__ */ jsx("button", { className: "bw-back", onClick: recoverReservation, disabled: submitting, "aria-label": "Choose another time", children: /* @__PURE__ */ jsx(ArrowLeftIcon, {}) }),
599
897
  /* @__PURE__ */ jsxs("div", { children: [
600
898
  /* @__PURE__ */ jsx("h2", { className: "bw-heading", children: "Your Details" }),
601
899
  /* @__PURE__ */ jsxs("div", { className: "bw-meta-row", children: [
@@ -609,14 +907,16 @@ function BookingWidget({
609
907
  " \xB7 ",
610
908
  formatTime(selectedSlot.start, timezone)
611
909
  ] }),
612
- /* @__PURE__ */ jsx(LocationBadge, { type: selectedType })
910
+ /* @__PURE__ */ jsx(LocationBadge, { type: displayType })
613
911
  ] })
614
912
  ] })
615
913
  ] }),
616
- hold && /* @__PURE__ */ jsxs("div", { className: "bw-hold-notice", children: [
914
+ hold && !recovery && /* @__PURE__ */ jsxs("div", { className: "bw-hold-notice", children: [
617
915
  /* @__PURE__ */ jsx(SpinnerIcon, {}),
618
916
  " Slot held for you. Complete your details to confirm."
619
917
  ] }),
918
+ /* @__PURE__ */ jsx(LocationRow, { type: displayType, meetingFormat: meeting?.format }),
919
+ meeting?.requires_review && /* @__PURE__ */ jsx("p", { children: "We\u2019ll confirm your visit after reviewing travel arrangements." }),
620
920
  /* @__PURE__ */ jsxs("form", { onSubmit: handleBookingSubmit, className: "bw-form", children: [
621
921
  /* @__PURE__ */ jsxs("div", { className: "bw-field", children: [
622
922
  /* @__PURE__ */ jsxs("label", { htmlFor: "bw-name", children: [
@@ -629,6 +929,7 @@ function BookingWidget({
629
929
  id: "bw-name",
630
930
  type: "text",
631
931
  required: true,
932
+ readOnly: submitting,
632
933
  value: guestInfo.name,
633
934
  onChange: (e) => setGuestInfo((p) => ({ ...p, name: e.target.value })),
634
935
  placeholder: "Jane Smith",
@@ -647,6 +948,7 @@ function BookingWidget({
647
948
  id: "bw-email",
648
949
  type: "email",
649
950
  required: true,
951
+ readOnly: submitting,
650
952
  value: guestInfo.email,
651
953
  onChange: (e) => setGuestInfo((p) => ({ ...p, email: e.target.value })),
652
954
  placeholder: "jane@example.com",
@@ -655,10 +957,15 @@ function BookingWidget({
655
957
  )
656
958
  ] }),
657
959
  /* @__PURE__ */ jsxs("div", { className: "bw-field", children: [
658
- /* @__PURE__ */ jsx("label", { htmlFor: "bw-phone", children: "Phone" }),
960
+ /* @__PURE__ */ jsxs("label", { htmlFor: "bw-phone", children: [
961
+ "Phone ",
962
+ meeting?.format === "client_location" && /* @__PURE__ */ jsx("span", { className: "bw-req", children: "*" })
963
+ ] }),
659
964
  /* @__PURE__ */ jsx(
660
965
  "input",
661
966
  {
967
+ required: meeting?.format === "client_location",
968
+ readOnly: submitting,
662
969
  id: "bw-phone",
663
970
  type: "tel",
664
971
  value: guestInfo.phone || "",
@@ -674,6 +981,7 @@ function BookingWidget({
674
981
  "textarea",
675
982
  {
676
983
  id: "bw-notes",
984
+ readOnly: submitting,
677
985
  value: guestInfo.notes || "",
678
986
  onChange: (e) => setGuestInfo((p) => ({ ...p, notes: e.target.value })),
679
987
  placeholder: "Anything you'd like us to know...",
@@ -681,15 +989,15 @@ function BookingWidget({
681
989
  }
682
990
  )
683
991
  ] }),
684
- /* @__PURE__ */ jsx("button", { type: "submit", className: "bw-submit", disabled: submitting || !guestInfo.name || !guestInfo.email, children: submitting ? /* @__PURE__ */ jsxs(Fragment, { children: [
992
+ /* @__PURE__ */ jsx("button", { type: "submit", className: "bw-submit", disabled: submitting || !!recovery || !guestInfo.name || !guestInfo.email, children: submitting ? /* @__PURE__ */ jsxs(Fragment, { children: [
685
993
  /* @__PURE__ */ jsx(SpinnerIcon, {}),
686
994
  " Confirming..."
687
- ] }) : "Confirm Booking" })
995
+ ] }) : meeting?.requires_review ? "Request meeting" : "Confirm booking" })
688
996
  ] })
689
997
  ] }),
690
998
  step === "success" && bookingResult && /* @__PURE__ */ jsxs("div", { className: "bw-step bw-fade-in bw-success", children: [
691
999
  /* @__PURE__ */ jsx("div", { className: "bw-success-icon", children: /* @__PURE__ */ jsx(CheckCircleIcon, {}) }),
692
- /* @__PURE__ */ jsx("h2", { className: "bw-heading", children: "You\u2019re Booked!" }),
1000
+ /* @__PURE__ */ jsx("h2", { className: "bw-heading", children: isPending ? "Meeting request received" : "You\u2019re booked!" }),
693
1001
  /* @__PURE__ */ jsxs("div", { className: "bw-details-card", children: [
694
1002
  /* @__PURE__ */ jsxs("div", { className: "bw-detail-row", children: [
695
1003
  /* @__PURE__ */ jsx("span", { className: "bw-detail-label", children: "When" }),
@@ -710,26 +1018,28 @@ function BookingWidget({
710
1018
  /* @__PURE__ */ jsx("span", { className: "bw-detail-label", children: "With" }),
711
1019
  /* @__PURE__ */ jsx("span", { className: "bw-detail-value", children: bookingResult.booking.hostName })
712
1020
  ] }),
713
- /* @__PURE__ */ jsx(LocationRow, { type: selectedType })
1021
+ /* @__PURE__ */ jsx(LocationRow, { type: displayType, meetingFormat: meeting?.format })
714
1022
  ] }),
715
1023
  /* @__PURE__ */ jsxs("p", { className: "bw-email-notice", children: [
716
- "We\u2019ve emailed your confirmation to ",
1024
+ isPending ? "We\u2019ll send your confirmation to " : "Your meeting details will arrive at ",
717
1025
  /* @__PURE__ */ jsx("strong", { children: guestInfo.email }),
718
- " with everything you need."
1026
+ "."
719
1027
  ] }),
720
- /* @__PURE__ */ jsx("p", { className: "bw-cal-links-label", children: "Add to your calendar" }),
721
- /* @__PURE__ */ jsxs("div", { className: "bw-cal-links", children: [
722
- /* @__PURE__ */ jsxs("a", { href: bookingResult.calendarLinks.google, target: "_blank", rel: "noopener noreferrer", className: "bw-cal-link", children: [
723
- /* @__PURE__ */ jsx(CalendarPlusIcon, {}),
724
- " Google"
725
- ] }),
726
- /* @__PURE__ */ jsxs("a", { href: bookingResult.calendarLinks.outlook, target: "_blank", rel: "noopener noreferrer", className: "bw-cal-link", children: [
727
- /* @__PURE__ */ jsx(CalendarPlusIcon, {}),
728
- " Outlook"
729
- ] }),
730
- /* @__PURE__ */ jsxs("a", { href: bookingResult.calendarLinks.ics, download: true, className: "bw-cal-link", children: [
731
- /* @__PURE__ */ jsx(CalendarPlusIcon, {}),
732
- " iCal"
1028
+ !isPending && /* @__PURE__ */ jsxs(Fragment, { children: [
1029
+ /* @__PURE__ */ jsx("p", { className: "bw-cal-links-label", children: "Add to your calendar" }),
1030
+ /* @__PURE__ */ jsxs("div", { className: "bw-cal-links", children: [
1031
+ /* @__PURE__ */ jsxs("a", { href: bookingResult.calendarLinks.google, target: "_blank", rel: "noopener noreferrer", className: "bw-cal-link", children: [
1032
+ /* @__PURE__ */ jsx(CalendarPlusIcon, {}),
1033
+ " Google"
1034
+ ] }),
1035
+ /* @__PURE__ */ jsxs("a", { href: bookingResult.calendarLinks.outlook, target: "_blank", rel: "noopener noreferrer", className: "bw-cal-link", children: [
1036
+ /* @__PURE__ */ jsx(CalendarPlusIcon, {}),
1037
+ " Outlook"
1038
+ ] }),
1039
+ /* @__PURE__ */ jsxs("a", { href: bookingResult.calendarLinks.ics, download: true, className: "bw-cal-link", children: [
1040
+ /* @__PURE__ */ jsx(CalendarPlusIcon, {}),
1041
+ " iCal"
1042
+ ] })
733
1043
  ] })
734
1044
  ] }),
735
1045
  (bookingResult.rescheduleUrl || bookingResult.cancelUrl) && /* @__PURE__ */ jsxs("p", { className: "bw-manage-links", children: [
@@ -768,7 +1078,7 @@ function getLocationDisplay(type) {
768
1078
  return { kind: "custom", label: details || "See details" };
769
1079
  case "virtual":
770
1080
  default:
771
- return { kind: "virtual", label: "Video call" };
1081
+ return { kind: "virtual", label: "Video call", detail: type.video_link };
772
1082
  }
773
1083
  }
774
1084
  function LocationBadge({ type }) {
@@ -780,7 +1090,7 @@ function LocationBadge({ type }) {
780
1090
  loc.label
781
1091
  ] });
782
1092
  }
783
- function LocationRow({ type }) {
1093
+ function LocationRow({ type, meetingFormat }) {
784
1094
  const loc = getLocationDisplay(type);
785
1095
  if (!loc) return null;
786
1096
  return /* @__PURE__ */ jsxs("div", { className: "bw-detail-row", children: [
@@ -789,9 +1099,13 @@ function LocationRow({ type }) {
789
1099
  loc.label,
790
1100
  loc.detail ? /* @__PURE__ */ jsxs(Fragment, { children: [
791
1101
  /* @__PURE__ */ jsx("br", {}),
792
- loc.detail
1102
+ loc.kind === "virtual" ? /* @__PURE__ */ jsx("a", { href: loc.detail, target: "_blank", rel: "noopener noreferrer", children: "Join Google Meet" }) : loc.detail
793
1103
  ] }) : null,
794
- loc.mapUrl ? /* @__PURE__ */ jsxs(Fragment, { children: [
1104
+ type?.location_instructions && /* @__PURE__ */ jsxs(Fragment, { children: [
1105
+ /* @__PURE__ */ jsx("br", {}),
1106
+ /* @__PURE__ */ jsx("span", { style: { whiteSpace: "pre-wrap" }, children: type.location_instructions })
1107
+ ] }),
1108
+ loc.mapUrl && meetingFormat !== "client_location" ? /* @__PURE__ */ jsxs(Fragment, { children: [
795
1109
  /* @__PURE__ */ jsx("br", {}),
796
1110
  /* @__PURE__ */ jsx("a", { href: loc.mapUrl, target: "_blank", rel: "noopener noreferrer", className: "bw-where-link", children: "Get directions \u2192" })
797
1111
  ] }) : null,
@@ -871,6 +1185,10 @@ var WIDGET_CSS = `
871
1185
  padding: 10px 14px; border-radius: var(--sk-radius); margin-bottom: 16px; font-size: 0.875rem;
872
1186
  }
873
1187
  .bw-error button { background: none; border: none; color: inherit; cursor: pointer; font-size: 1.25rem; line-height: 1; padding: 0; }
1188
+ .sk-booking-recovery { padding: 16px; margin-bottom: 16px; border: 1px solid var(--sk-border); border-radius: var(--sk-radius); background: var(--sk-surface); color: var(--sk-text-primary); }
1189
+ .sk-booking-recovery p { margin: 0 0 12px; font-size: 0.875rem; }
1190
+ .sk-booking-recovery .bw-submit { width: auto; }
1191
+ .bw-back:disabled { cursor: wait; opacity: 0.55; }
874
1192
 
875
1193
  /* \u2500\u2500 Headings \u2500\u2500 */
876
1194
  .bw-heading { font-size: 1.125rem; font-weight: 600; margin: 0; letter-spacing: -0.01em; }
@@ -892,6 +1210,7 @@ var WIDGET_CSS = `
892
1210
  background: var(--sk-bg); cursor: pointer; color: var(--sk-text-secondary); flex-shrink: 0; margin-top: 1px;
893
1211
  transition: all 0.15s;
894
1212
  }
1213
+ .bw-back.sk-meeting-change { width: auto; height: auto; min-height: 36px; padding: 8px 12px; border-radius: var(--sk-radius); margin-bottom: 12px; font-size: 0.8125rem; }
895
1214
  .bw-back:hover { background: var(--sk-surface); border-color: var(--sk-border); }
896
1215
 
897
1216
  /* \u2500\u2500 Loading \u2500\u2500 */
@@ -1086,6 +1405,6 @@ var WIDGET_CSS = `
1086
1405
  .bw-manage-links a { color: var(--sk-primary, #14B8A6); text-decoration: none; font-weight: 500; }
1087
1406
  `;
1088
1407
 
1089
- export { BookingWidget, createBooking, createSlotHold, detectTimezone, fetchAvailability, fetchAvailableDates, fetchBookingTypeDetails, fetchBookingTypes, formatDate, formatDuration, formatTime, releaseSlotHold };
1090
- //# sourceMappingURL=chunk-HVFXFPUJ.mjs.map
1091
- //# sourceMappingURL=chunk-HVFXFPUJ.mjs.map
1408
+ export { BookingWidget, createBooking, createSlotHold, detectTimezone, fetchAvailability, fetchAvailableDates, fetchBookingTypeDetails, fetchBookingTypes, formatDate, formatDuration, formatTime, prepareMeeting, releaseSlotHold };
1409
+ //# sourceMappingURL=chunk-XQYC4KMH.mjs.map
1410
+ //# sourceMappingURL=chunk-XQYC4KMH.mjs.map