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