@riverbankcms/sdk 0.146.0 → 0.148.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 (466) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/{PreviewEditorSidebar-kg2r2Fyi.mjs → PreviewEditorSidebar-DvEPG3Z2.mjs} +249 -172
  3. package/dist/{PreviewEditorUI-sWMLp5dT.mjs → PreviewEditorUI-D6eb6fkx.mjs} +68 -60
  4. package/dist/{PreviewQueryProvider-Cg51xq1w.mjs → PreviewQueryProvider-5znTyJuz.mjs} +1 -1
  5. package/dist/{SdkPreviewModeRuntime-h2ti3Hch.mjs → SdkPreviewModeRuntime-DJ6utQ_R.mjs} +1180 -475
  6. package/dist/{SiteChromeCustomizeContext-DEACFH9m.mjs → SiteChromeCustomizeContext-CFJYh6vo.mjs} +199078 -193767
  7. package/dist/_dts/ai/src/contracts/proposals.d.ts +198 -33
  8. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +18 -3
  9. package/dist/_dts/api/src/accessAdmin.d.ts +0 -4
  10. package/dist/_dts/api/src/accountApi.d.ts +6 -6
  11. package/dist/_dts/api/src/admin.d.ts +22 -22
  12. package/dist/_dts/api/src/aiPatch.d.ts +2 -2
  13. package/dist/_dts/api/src/aiPlayground.d.ts +1 -0
  14. package/dist/_dts/api/src/analytics.d.ts +2 -2
  15. package/dist/_dts/api/src/apiEndpointTypes.d.ts +2 -0
  16. package/dist/_dts/api/src/appointmentSetup.d.ts +2 -2
  17. package/dist/_dts/api/src/auth.d.ts +10 -10
  18. package/dist/_dts/api/src/availability.d.ts +6 -6
  19. package/dist/_dts/api/src/billing.d.ts +42 -15
  20. package/dist/_dts/api/src/billingEndpointDefinitions.d.ts +8 -0
  21. package/dist/_dts/api/src/billingEndpointTypes.d.ts +15 -6
  22. package/dist/_dts/api/src/blocks.d.ts +15 -14
  23. package/dist/_dts/api/src/blocksKeys.d.ts +2 -0
  24. package/dist/_dts/api/src/bookingConfig.d.ts +16 -2
  25. package/dist/_dts/api/src/bookingManagementEndpoints.d.ts +4 -13
  26. package/dist/_dts/api/src/bookingOperations.d.ts +6 -48
  27. package/dist/_dts/api/src/bookingPeople.d.ts +92 -0
  28. package/dist/_dts/api/src/bookingPeopleEndpointDefinitions.d.ts +38 -0
  29. package/dist/_dts/api/src/bookingRecords.d.ts +12 -49
  30. package/dist/_dts/api/src/bookingSettingsSections.d.ts +1 -1
  31. package/dist/_dts/api/src/bookings.d.ts +8 -7
  32. package/dist/_dts/api/src/calendar.d.ts +9 -9
  33. package/dist/_dts/api/src/commercePortalEndpoints.d.ts +7 -6
  34. package/dist/_dts/api/src/common/envelope.d.ts +2 -2
  35. package/dist/_dts/api/src/content-editor.d.ts +2 -2
  36. package/dist/_dts/api/src/contentEntries.d.ts +17 -48
  37. package/dist/_dts/api/src/contentRuntime.d.ts +51 -37
  38. package/dist/_dts/api/src/contentTypes.d.ts +11 -11
  39. package/dist/_dts/api/src/contentVersionHistoryClient.d.ts +6 -6
  40. package/dist/_dts/api/src/documentLifecycle.d.ts +67 -0
  41. package/dist/_dts/api/src/domains.d.ts +16 -16
  42. package/dist/_dts/api/src/editLeaseEndpoints.d.ts +72 -0
  43. package/dist/_dts/api/src/emailSettings.d.ts +4 -4
  44. package/dist/_dts/api/src/endpoints.d.ts +725 -607
  45. package/dist/_dts/api/src/eventEmailTemplates.d.ts +2 -2
  46. package/dist/_dts/api/src/eventManagementContracts.d.ts +48 -8
  47. package/dist/_dts/api/src/eventManagementEndpointDefinitions.d.ts +1 -9
  48. package/dist/_dts/api/src/eventPageWords.d.ts +7 -12
  49. package/dist/_dts/api/src/footerSettings.d.ts +6 -6
  50. package/dist/_dts/api/src/index.d.ts +8 -6
  51. package/dist/_dts/api/src/indexCoreTypes.d.ts +2 -1
  52. package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -1
  53. package/dist/_dts/api/src/launchReadiness.d.ts +1 -6
  54. package/dist/_dts/api/src/mailingListIntegration.d.ts +6 -0
  55. package/dist/_dts/api/src/navigation/dashboardBookingsNav.d.ts +1 -1
  56. package/dist/_dts/api/src/navigation.d.ts +5 -5
  57. package/dist/_dts/api/src/newsletterEndpointDefinitions.d.ts +15 -0
  58. package/dist/_dts/api/src/occurrenceScheduling.d.ts +19 -0
  59. package/dist/_dts/api/src/pageSurfaceEditorEndpoints.d.ts +55 -0
  60. package/dist/_dts/api/src/pageSurfaceEndpoints.d.ts +28 -7
  61. package/dist/_dts/api/src/pages.d.ts +7 -7
  62. package/dist/_dts/api/src/performance.d.ts +1 -1
  63. package/dist/_dts/api/src/public/index.d.ts +1 -1
  64. package/dist/_dts/api/src/publicAppointmentBookingContracts.d.ts +50 -0
  65. package/dist/_dts/api/src/publicExperience/commerceEndpoints.d.ts +4 -0
  66. package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +7 -0
  67. package/dist/_dts/api/src/redirects.d.ts +3 -3
  68. package/dist/_dts/api/src/request.d.ts +10 -1
  69. package/dist/_dts/api/src/resources.d.ts +4 -4
  70. package/dist/_dts/api/src/routes.d.ts +8 -3
  71. package/dist/_dts/api/src/sdk-event-upsert.d.ts +15 -1
  72. package/dist/_dts/api/src/sdkBlockUpsertContracts.d.ts +21 -0
  73. package/dist/_dts/api/src/sdkContracts.d.ts +5 -28
  74. package/dist/_dts/api/src/sdkCourseBooking.d.ts +4 -4
  75. package/dist/_dts/api/src/sdkEventEndpointDefinitions.d.ts +1 -1
  76. package/dist/_dts/api/src/sdkEventOccurrenceRequestContracts.d.ts +43 -0
  77. package/dist/_dts/api/src/sdkManagedEventContracts.d.ts +4 -2
  78. package/dist/_dts/api/src/sdkPullEventContracts.d.ts +8 -1
  79. package/dist/_dts/api/src/seo.d.ts +4 -4
  80. package/dist/_dts/api/src/services.d.ts +4 -4
  81. package/dist/_dts/api/src/siteLifecycleEndpoints.d.ts +61 -0
  82. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +19 -25
  83. package/dist/_dts/api/src/siteMembers.d.ts +10 -10
  84. package/dist/_dts/api/src/siteOnboarding.d.ts +16 -14
  85. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +7 -3
  86. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +5 -12
  87. package/dist/_dts/api/src/siteRuntimeEntry.d.ts +31 -0
  88. package/dist/_dts/billing/src/checkout/platform.d.ts +77 -0
  89. package/dist/_dts/billing/src/components/index.d.ts +25 -40
  90. package/dist/_dts/billing/src/membership/index.d.ts +1 -3
  91. package/dist/_dts/billing/src/plans/entitlements.d.ts +80 -0
  92. package/dist/_dts/billing/src/plans/registry.d.ts +16 -16
  93. package/dist/_dts/billing/src/plans/standing.d.ts +9 -2
  94. package/dist/_dts/billing/src/plans/types.d.ts +5 -15
  95. package/dist/_dts/billing/src/site-arrangements.d.ts +2 -2
  96. package/dist/_dts/billing/src/subscriptions/standingEvidence.d.ts +2 -4
  97. package/dist/_dts/billing/src/subscriptions/store.d.ts +17 -11
  98. package/dist/_dts/block-form/src/backend/store-backend.d.ts +6 -7
  99. package/dist/_dts/block-form/src/backend/types.d.ts +7 -0
  100. package/dist/_dts/block-form/src/widgets/FieldFrame.d.ts +3 -1
  101. package/dist/_dts/blocks/src/PageRenderer.d.ts +3 -4
  102. package/dist/_dts/blocks/src/client/events.d.ts +3 -0
  103. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +24 -4
  104. package/dist/_dts/blocks/src/index.d.ts +1 -1
  105. package/dist/_dts/blocks/src/pageRenderAdmission.d.ts +18 -9
  106. package/dist/_dts/blocks/src/pageRendererContracts.d.ts +4 -0
  107. package/dist/_dts/blocks/src/portal/types.d.ts +0 -2
  108. package/dist/_dts/blocks/src/system/blocks/contact-newsletter.d.ts +2 -1
  109. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +3 -1
  110. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +4 -4
  111. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +6 -1
  112. package/dist/_dts/blocks/src/system/blocks/newsletter-signup.d.ts +4 -1
  113. package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +2 -2
  114. package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
  115. package/dist/_dts/blocks/src/system/runtime/api/types/appointments.d.ts +6 -0
  116. package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +18 -0
  117. package/dist/_dts/blocks/src/system/runtime/api/types/portal.d.ts +6 -0
  118. package/dist/_dts/blocks/src/system/runtime/api/types/shop.d.ts +4 -0
  119. package/dist/_dts/blocks/src/system/runtime/components/booking/SuccessMessage.d.ts +4 -1
  120. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +36 -6
  121. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +18 -3
  122. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.d.ts +11 -0
  123. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessEventRegistrationFlow.d.ts +2 -0
  124. package/dist/_dts/blocks/src/system/runtime/hooks/usePaymentVerification.d.ts +2 -1
  125. package/dist/_dts/blocks/src/system/runtime/hooks/usePolling.d.ts +7 -48
  126. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.checkout-return-context.d.ts +7 -0
  127. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.completion.d.ts +11 -0
  128. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +13 -0
  129. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.interactive.d.ts +28 -0
  130. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.mailing-list-choice.d.ts +5 -0
  131. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.mailing-list-state.d.ts +9 -0
  132. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.payment-confirmation.d.ts +13 -0
  133. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.reserved-fields.d.ts +1 -1
  134. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.server.d.ts +1 -1
  135. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.state.d.ts +17 -1
  136. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.submit-actions.d.ts +8 -0
  137. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.submit-handler.d.ts +9 -0
  138. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.submit-success.d.ts +9 -0
  139. package/dist/_dts/blocks/src/system/runtime/nodes/booking-runtime-sources.d.ts +4 -0
  140. package/dist/_dts/blocks/src/system/runtime/nodes/checkout.server.d.ts +2 -1
  141. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/AttendeeDetailsStep.d.ts +3 -0
  142. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationSurface.d.ts +2 -1
  143. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationWizard.d.ts +5 -0
  144. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/SuccessStep.d.ts +7 -1
  145. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +3 -0
  146. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/sessionStorage.d.ts +2 -0
  147. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +8 -0
  148. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +5 -5
  149. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +8 -0
  150. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +18 -5
  151. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventListing.interactive.d.ts +6 -0
  152. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/dates.d.ts +37 -3
  153. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventCard.client.d.ts +1 -1
  154. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventCard.d.ts +16 -1
  155. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCardPresentations.d.ts +13 -0
  156. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +5 -5
  157. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.block-submission.d.ts +2 -4
  158. package/dist/_dts/blocks/src/system/runtime/nodes/shared/MagicLinkForm.d.ts +1 -14
  159. package/dist/_dts/blocks/src/system/runtime/nodes/shared/MagicLinkForm.state.d.ts +12 -0
  160. package/dist/_dts/blocks/src/system/runtime/nodes/shop.interactive.d.ts +13 -0
  161. package/dist/_dts/blocks/src/system/runtime/resolver.d.ts +2 -0
  162. package/dist/_dts/blocks/src/system/runtime/shared/components/BookingMailingListNote.d.ts +6 -0
  163. package/dist/_dts/blocks/src/system/runtime/shared/components/DemoBookingPortalAccess.d.ts +22 -0
  164. package/dist/_dts/blocks/src/system/runtime/shared/components/DemoPortalSignInLink.d.ts +4 -0
  165. package/dist/_dts/blocks/src/system/runtime/shared/components/index.d.ts +1 -0
  166. package/dist/_dts/blocks/src/system/runtime/shared/mailingListSignupCopy.d.ts +6 -0
  167. package/dist/_dts/blocks/src/system/runtime/shared/types.d.ts +1 -0
  168. package/dist/_dts/blocks/src/system/runtime/shared/utils/demoBookingPassStorage.d.ts +10 -0
  169. package/dist/_dts/blocks/src/system/runtime/shared/utils/demoPortalMagicLink.d.ts +29 -0
  170. package/dist/_dts/blocks/src/system/transforms/registry/_utils/surfaceForegroundStyles.d.ts +3 -2
  171. package/dist/_dts/blocks/src/system/transforms/registry/core.d.ts +2 -0
  172. package/dist/_dts/blocks/src/system/transforms/registry/layout.d.ts +1 -3
  173. package/dist/_dts/commerce/src/purchase/event-registration-errors.d.ts +4 -0
  174. package/dist/_dts/content-editor/src/components/ContentFieldsForm.d.ts +2 -7
  175. package/dist/_dts/content-editor/src/controller/EditLeaseController.d.ts +39 -0
  176. package/dist/_dts/content-editor/src/controller/EditorWriteGate.d.ts +38 -0
  177. package/dist/_dts/content-editor/src/controller/EntryControllerProvider.d.ts +25 -61
  178. package/dist/_dts/content-editor/src/controller/LinkedEntryLeaseBanner.d.ts +7 -0
  179. package/dist/_dts/content-editor/src/controller/LinkedEntryLeaseControllers.d.ts +14 -0
  180. package/dist/_dts/content-editor/src/controller/deriveEditorUnpublishedState.d.ts +6 -0
  181. package/dist/_dts/content-editor/src/controller/documentValueBaseline.d.ts +25 -0
  182. package/dist/_dts/content-editor/src/controller/editLeaseLossSignal.d.ts +6 -0
  183. package/dist/_dts/content-editor/src/controller/editLeaseNotice.d.ts +28 -0
  184. package/dist/_dts/content-editor/src/controller/editorClientId.d.ts +2 -0
  185. package/dist/_dts/content-editor/src/controller/editorEditability.d.ts +38 -0
  186. package/dist/_dts/content-editor/src/controller/editorLeaseParticipation.d.ts +34 -0
  187. package/dist/_dts/content-editor/src/controller/normalizedMetadataBaseline.d.ts +29 -0
  188. package/dist/_dts/content-editor/src/controller/pageSurfaceDocumentBaselines.d.ts +14 -0
  189. package/dist/_dts/content-editor/src/controller/pageSurfaceLifecycle.d.ts +11 -0
  190. package/dist/_dts/content-editor/src/controller/planDocumentBaselineRefresh.d.ts +19 -0
  191. package/dist/_dts/content-editor/src/controller/readDocumentLeaseBaselines.d.ts +19 -0
  192. package/dist/_dts/content-editor/src/controller/refreshDocumentLeaseBaseline.d.ts +12 -0
  193. package/dist/_dts/content-editor/src/controller/refreshLinkedEntry.d.ts +17 -0
  194. package/dist/_dts/content-editor/src/controller/replayRestoredEditorEffects.d.ts +2 -3
  195. package/dist/_dts/content-editor/src/controller/routeWrites.d.ts +26 -0
  196. package/dist/_dts/content-editor/src/controller/useAutosaveTriggers.d.ts +16 -17
  197. package/dist/_dts/content-editor/src/controller/useBlockedPublishPlan.d.ts +6 -2
  198. package/dist/_dts/content-editor/src/controller/useBlocksList.d.ts +3 -3
  199. package/dist/_dts/content-editor/src/controller/useEntryValueAutosaves.d.ts +21 -0
  200. package/dist/_dts/content-editor/src/controller/useInitialEditorUiStore.d.ts +24 -0
  201. package/dist/_dts/content-editor/src/controller/useServerBaselineReconciliation.d.ts +17 -0
  202. package/dist/_dts/content-editor/src/footerComposerPanelTypes.d.ts +1 -1
  203. package/dist/_dts/content-editor/src/hooks/applyBlockedPublishPlan.d.ts +5 -1
  204. package/dist/_dts/content-editor/src/hooks/blockDraftLifecycle.d.ts +8 -47
  205. package/dist/_dts/content-editor/src/hooks/editLeaseMachine.d.ts +120 -0
  206. package/dist/_dts/content-editor/src/hooks/publishability.d.ts +6 -10
  207. package/dist/_dts/content-editor/src/hooks/useAutosaveStatus.d.ts +3 -0
  208. package/dist/_dts/content-editor/src/hooks/useBlockAutosave.d.ts +5 -15
  209. package/dist/_dts/content-editor/src/hooks/useDebouncedLatestSave.d.ts +7 -5
  210. package/dist/_dts/content-editor/src/hooks/useEditLease.d.ts +28 -0
  211. package/dist/_dts/content-editor/src/hooks/useEntryActions.d.ts +25 -39
  212. package/dist/_dts/content-editor/src/hooks/useEntryMutations.d.ts +17 -19
  213. package/dist/_dts/content-editor/src/hooks/useLinkedEntryAutosave.d.ts +5 -8
  214. package/dist/_dts/content-editor/src/hooks/useValueAutosave.d.ts +64 -0
  215. package/dist/_dts/content-editor/src/hooks/validateBlocksForPublish.d.ts +0 -7
  216. package/dist/_dts/content-editor/src/index.d.ts +26 -7
  217. package/dist/_dts/content-editor/src/linkedEntries/domain.d.ts +12 -0
  218. package/dist/_dts/content-editor/src/linkedEntries/owner.d.ts +9 -0
  219. package/dist/_dts/content-editor/src/liveDrafts/draftProjection.d.ts +66 -0
  220. package/dist/_dts/content-editor/src/liveDrafts/linkedSaveHandovers.d.ts +37 -0
  221. package/dist/_dts/content-editor/src/liveDrafts/remoteDraftOverlay.d.ts +113 -0
  222. package/dist/_dts/content-editor/src/liveDrafts/useLiveDrafts.d.ts +32 -0
  223. package/dist/_dts/content-editor/src/liveDrafts/useRetentionTicks.d.ts +7 -0
  224. package/dist/_dts/content-editor/src/primitives/shared/activePreviewField.d.ts +6 -0
  225. package/dist/_dts/content-editor/src/primitives/shared/storeBinding.d.ts +1 -0
  226. package/dist/_dts/content-editor/src/services/contentEntryServices.d.ts +96 -19
  227. package/dist/_dts/content-editor/src/services/editorApiClient.d.ts +13 -0
  228. package/dist/_dts/content-editor/src/services/index.d.ts +2 -0
  229. package/dist/_dts/content-editor/src/services/pageSurfaceEditorServices.d.ts +23 -0
  230. package/dist/_dts/content-editor/src/sync/flushValues.d.ts +13 -0
  231. package/dist/_dts/content-editor/src/sync/lifecycleFailure.d.ts +51 -0
  232. package/dist/_dts/content-editor/src/sync/runLifecycle.d.ts +64 -0
  233. package/dist/_dts/content-editor/src/sync/schedulerValues.d.ts +27 -0
  234. package/dist/_dts/content-editor/src/sync/sendPlanning.d.ts +104 -0
  235. package/dist/_dts/content-editor/src/sync/valueSync.d.ts +114 -0
  236. package/dist/_dts/content-editor/src/ui/blockCollection.d.ts +8 -0
  237. package/dist/_dts/content-editor/src/ui/documentLifecycle.d.ts +18 -0
  238. package/dist/_dts/content-editor/src/ui/editorLeaseUiState.d.ts +7 -0
  239. package/dist/_dts/content-editor/src/ui/editorRefresh.d.ts +82 -0
  240. package/dist/_dts/content-editor/src/ui/editorSnapshot.d.ts +102 -127
  241. package/dist/_dts/content-editor/src/ui/editorTransactionState.d.ts +1 -1
  242. package/dist/_dts/content-editor/src/ui/editorUiStore.d.ts +126 -72
  243. package/dist/_dts/content-editor/src/ui/editorValueSnapshot.d.ts +18 -0
  244. package/dist/_dts/content-editor/src/ui/serverBlockAdmission.d.ts +26 -0
  245. package/dist/_dts/content-editor/src/ui/stores/autosaveStore.d.ts +16 -27
  246. package/dist/_dts/content-editor/src/ui/stores/blockVersionsStore.d.ts +24 -0
  247. package/dist/_dts/content-editor/src/ui/stores/linkedEntryLeaseStore.d.ts +54 -0
  248. package/dist/_dts/content-editor/src/ui/stores/linkedSaveHandoversStore.d.ts +11 -0
  249. package/dist/_dts/content-editor/src/ui/stores/remoteDraftsStore.d.ts +10 -0
  250. package/dist/_dts/content-editor/src/ui/stores/types.d.ts +63 -3
  251. package/dist/_dts/content-editor/src/useFooterComposerState.d.ts +2 -2
  252. package/dist/_dts/content-editor/src/useFooterNavigationLayout.d.ts +1 -1
  253. package/dist/_dts/content-model/src/content-types/builtin-schemas.d.ts +4 -4
  254. package/dist/_dts/content-model/src/content-types/builtins.d.ts +4 -4
  255. package/dist/_dts/content-model/src/definitions/shared.d.ts +11 -2
  256. package/dist/_dts/content-model/src/entry-slots/index.d.ts +1 -0
  257. package/dist/_dts/content-model/src/entry-slots/serializeAllowedBlocks.d.ts +2 -0
  258. package/dist/_dts/content-model/src/metadataConfig.d.ts +10 -38
  259. package/dist/_dts/content-model/src/templates/defaults.d.ts +0 -1
  260. package/dist/_dts/content-model/src/types.d.ts +0 -1
  261. package/dist/_dts/core/src/block-content-identity.d.ts +49 -1
  262. package/dist/_dts/core/src/branded.d.ts +12 -0
  263. package/dist/_dts/core/src/currency-format.d.ts +8 -2
  264. package/dist/_dts/core/src/demo-lifecycle-status.d.ts +2 -2
  265. package/dist/_dts/core/src/demo-warm-pool-target.d.ts +8 -0
  266. package/dist/_dts/core/src/edit-lease.d.ts +55 -0
  267. package/dist/_dts/core/src/editor-state.d.ts +38 -13
  268. package/dist/_dts/core/src/editor-value-sync.d.ts +79 -0
  269. package/dist/_dts/core/src/html-entities.d.ts +6 -0
  270. package/dist/_dts/core/src/index.d.ts +5 -1
  271. package/dist/_dts/core/src/mailing-list-runtime.d.ts +15 -0
  272. package/dist/_dts/core/src/mailing-list-setup.d.ts +2 -0
  273. package/dist/_dts/core/src/mailing-list-submission.d.ts +6 -0
  274. package/dist/_dts/core/src/navigation-portal-labels.d.ts +9 -0
  275. package/dist/_dts/core/src/participants.d.ts +0 -38
  276. package/dist/_dts/core/src/uuid.d.ts +7 -5
  277. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +261 -175
  278. package/dist/_dts/editor/src/EditorProvider.d.ts +5 -0
  279. package/dist/_dts/editor/src/chrome/EditorChrome.d.ts +14 -0
  280. package/dist/_dts/editor/src/chrome/EditorStatusBar.d.ts +1 -0
  281. package/dist/_dts/editor/src/chrome/statusBarPresentation.d.ts +0 -1
  282. package/dist/_dts/editor/src/index.d.ts +1 -1
  283. package/dist/_dts/editor-blocks/src/BlockEditor.d.ts +10 -9
  284. package/dist/_dts/editor-blocks/src/BlockForm.d.ts +1 -1
  285. package/dist/_dts/editor-blocks/src/block-editor/BlockCard.d.ts +1 -1
  286. package/dist/_dts/editor-blocks/src/block-editor/BlockCardFrame.d.ts +1 -1
  287. package/dist/_dts/editor-blocks/src/block-editor/BlockSettingsModal.d.ts +1 -1
  288. package/dist/_dts/editor-blocks/src/block-editor/actionPresentation.d.ts +1 -0
  289. package/dist/_dts/editor-blocks/src/block-editor/applyExtendedFieldDefaults.d.ts +3 -4
  290. package/dist/_dts/editor-blocks/src/block-editor/blockDraftBaselineSeed.d.ts +4 -8
  291. package/dist/_dts/editor-blocks/src/block-editor/editorBlockItem.d.ts +23 -0
  292. package/dist/_dts/editor-blocks/src/block-editor/generatedIconApplyCoordination.d.ts +2 -7
  293. package/dist/_dts/editor-blocks/src/block-editor/hooks/applyBlockStructureChange.d.ts +4 -0
  294. package/dist/_dts/editor-blocks/src/block-editor/hooks/buildInsertBlockHistoryCommand.d.ts +14 -5
  295. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockBaselineSync.d.ts +21 -19
  296. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockCreation.d.ts +2 -10
  297. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockDuplication.d.ts +8 -16
  298. package/dist/_dts/editor-blocks/src/block-editor/owner.d.ts +6 -16
  299. package/dist/_dts/editor-blocks/src/block-editor/types.d.ts +37 -9
  300. package/dist/_dts/editor-blocks/src/index.d.ts +2 -1
  301. package/dist/_dts/editor-blocks/src/widgets/entry-picker/loaders.d.ts +1 -1
  302. package/dist/_dts/editor-blocks/src/widgets/link/loaders.d.ts +1 -1
  303. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/loaders.d.ts +1 -1
  304. package/dist/_dts/editor-blocks/src/widgets/reference/loaders.d.ts +1 -1
  305. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/loaders.d.ts +3 -2
  306. package/dist/_dts/media-core/src/fileStorage.d.ts +4 -0
  307. package/dist/_dts/media-editor/src/context.d.ts +1 -1
  308. package/dist/_dts/media-editor/src/createMediaEditorProvider.d.ts +1 -2
  309. package/dist/_dts/media-editor/src/provider.d.ts +3 -2
  310. package/dist/_dts/media-react/src/hooks/internal/classification.d.ts +1 -1
  311. package/dist/_dts/media-react/src/hooks/useApiMediaUploader.d.ts +3 -1
  312. package/dist/_dts/preview-next/src/client/blocks/EditablePageRenderer.d.ts +7 -1
  313. package/dist/_dts/preview-next/src/client/blocks/composer/mergeDrafts.d.ts +8 -3
  314. package/dist/_dts/preview-next/src/client/blocks/composer/types.d.ts +10 -6
  315. package/dist/_dts/preview-next/src/client/blocks/linkedEntryRenderOverlay.d.ts +22 -2
  316. package/dist/_dts/preview-next/src/client/blocks/previewProjection/entryFieldRebinding.d.ts +13 -0
  317. package/dist/_dts/preview-next/src/client/blocks/previewProjection/index.d.ts +2 -1
  318. package/dist/_dts/preview-next/src/client/blocks/previewProjection/types.d.ts +11 -1
  319. package/dist/_dts/preview-next/src/client/blocks/renderPrecedence.d.ts +17 -0
  320. package/dist/_dts/preview-next/src/client/blocks/useLinkedSaveHandoverRetention.d.ts +20 -0
  321. package/dist/_dts/preview-next/src/client/index.d.ts +1 -1
  322. package/dist/_dts/preview-next/src/client/preview/EntryEditorPanel.d.ts +2 -1
  323. package/dist/_dts/preview-next/src/client/preview/EntrySlotBlockEditorPanel.d.ts +2 -1
  324. package/dist/_dts/preview-next/src/client/preview/PreviewAccessBanners.d.ts +7 -0
  325. package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +2 -1
  326. package/dist/_dts/preview-next/src/client/preview/PreviewEntryControllerProvider.d.ts +24 -14
  327. package/dist/_dts/preview-next/src/client/preview/PreviewLeaseEditingMode.d.ts +2 -0
  328. package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +9 -2
  329. package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +1 -0
  330. package/dist/_dts/preview-next/src/client/preview/previewCustomizeAutosave.d.ts +5 -0
  331. package/dist/_dts/preview-next/src/client/preview/previewCustomizeWorkflowState.d.ts +3 -4
  332. package/dist/_dts/preview-next/src/client/preview/sdkConfig.d.ts +1 -0
  333. package/dist/_dts/preview-next/src/client/preview/usePreviewCustomizeWorkflowState.d.ts +4 -0
  334. package/dist/_dts/realtime/src/client.d.ts +3 -0
  335. package/dist/_dts/realtime/src/draftChannel.d.ts +91 -0
  336. package/dist/_dts/realtime/src/drafts.d.ts +210 -0
  337. package/dist/_dts/realtime/src/index.d.ts +3 -0
  338. package/dist/_dts/realtime/src/leaseChangeSubscriptions.d.ts +8 -0
  339. package/dist/_dts/realtime/src/types.d.ts +113 -0
  340. package/dist/_dts/realtime/src/useDraftChannel.d.ts +34 -0
  341. package/dist/_dts/realtime/src/useSiteRealtimeReload.d.ts +27 -0
  342. package/dist/_dts/sdk/src/public-api/contracts.d.ts +6 -55
  343. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +2 -0
  344. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +2 -0
  345. package/dist/_dts/sdk/src/rendering/helpers/loadPage.d.ts +1 -1
  346. package/dist/_dts/sdk/src/rendering/helpers/pageRuntimeSupport.d.ts +4 -2
  347. package/dist/_dts/sdk/src/version.d.ts +1 -1
  348. package/dist/_dts/surfaces/src/index.d.ts +1 -0
  349. package/dist/_dts/theme-core/src/buttons/effects/types.d.ts +1 -1
  350. package/dist/_dts/theme-core/src/footer/effectiveNavLinkStyle.d.ts +13 -0
  351. package/dist/_dts/theme-core/src/footer/index.d.ts +1 -0
  352. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  353. package/dist/_dts/theme-core/src/header/effectiveNavLinkStyle.d.ts +17 -0
  354. package/dist/_dts/theme-core/src/header/generateHeaderLogoStyles.d.ts +15 -0
  355. package/dist/_dts/theme-core/src/header/generateHeaderNavLinkStyles.d.ts +4 -0
  356. package/dist/_dts/theme-core/src/header/index.d.ts +3 -0
  357. package/dist/_dts/theme-core/src/header/legacyNavLinkStyle.d.ts +1 -1
  358. package/dist/_dts/theme-core/src/header/openingForegroundProjection.d.ts +7 -0
  359. package/dist/_dts/theme-core/src/header/rootPaint.d.ts +4 -0
  360. package/dist/_dts/theme-core/src/navigation/effectPolicy.d.ts +38 -0
  361. package/dist/_dts/theme-core/src/navigation/generateNavLinkCSS.d.ts +4 -0
  362. package/dist/_dts/theme-core/src/navigation/types.d.ts +4 -0
  363. package/dist/_dts/theme-core/src/site-styles/accessibleSurfaces.d.ts +1 -1
  364. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +2 -2
  365. package/dist/_dts/theme-core/src/surfaces/foregroundContract.d.ts +7 -0
  366. package/dist/_dts/theme-core/src/surfaces/foregroundInteraction.d.ts +29 -22
  367. package/dist/_dts/theme-core/src/surfaces/foregroundRoles.d.ts +10 -2
  368. package/dist/_dts/theme-core/src/surfaces/resolveSurfaceForeground.d.ts +9 -0
  369. package/dist/_dts/theme-core/src/utils/cssDeclarations.d.ts +2 -0
  370. package/dist/_dts/ui/src/badge.d.ts +2 -1
  371. package/dist/_dts/ui/src/button.d.ts +1 -1
  372. package/dist/_dts/ui/src/combobox-keys.d.ts +23 -0
  373. package/dist/_dts/ui/src/combobox-rows.d.ts +34 -0
  374. package/dist/_dts/ui/src/combobox.d.ts +26 -1
  375. package/dist/_dts/ui/src/date-picker.d.ts +5 -8
  376. package/dist/_dts/ui/src/editor-item-card.d.ts +1 -0
  377. package/dist/_dts/ui/src/field-trigger.d.ts +39 -0
  378. package/dist/_dts/ui/src/fieldControl.d.ts +27 -0
  379. package/dist/_dts/ui/src/index.d.ts +4 -1
  380. package/dist/_dts/ui/src/native-select.d.ts +8 -0
  381. package/dist/_dts/ui/src/popover.d.ts +7 -1
  382. package/dist/_dts/ui/src/segmented-control.d.ts +4 -0
  383. package/dist/_dts/ui/src/surface.d.ts +1 -1
  384. package/dist/client/{BookingConsentAgreement-BQKL045f.mjs → BookingMailingListNote-CzRt2dF_.mjs} +110 -97
  385. package/dist/client/{CheckboxChoice--W2n6yKs.mjs → CheckboxChoice-B33MqoUo.mjs} +1 -1
  386. package/dist/client/DemoBookingPortalAccess-mxqwap3f.mjs +344 -0
  387. package/dist/client/{EventCombined.client-BdRjVbhH.mjs → EventCombined.client-CDb11igO.mjs} +7 -7
  388. package/dist/client/{EventListing.client-DBxC6xOU.mjs → EventListing.client-EgYhzKPa.mjs} +2 -2
  389. package/dist/client/{LeafletStaticMap-mHEJKrTs.mjs → LeafletStaticMap-gtmtaA2b.mjs} +1 -1
  390. package/dist/client/{scrollToBlock-BNgaEUpo.mjs → TerminalPanel-DvNUP5ot.mjs} +77 -77
  391. package/dist/client/{ThemedButton-CE5KYT6z.mjs → ThemedButton-C7CeUJjW.mjs} +2 -2
  392. package/dist/client/{accordion-BEQNSptH.mjs → accordion-kjvt49rA.mjs} +1 -1
  393. package/dist/client/{bookingForm-AMr-s5vw.mjs → bookingForm-pbRZordh.mjs} +411 -141
  394. package/dist/client/bookings.mjs +966 -396
  395. package/dist/client/{carousel-Bbt_QgJy.mjs → carousel-f4Zbmicv.mjs} +2 -2
  396. package/dist/client/{carousel.client-jahpU9Vz.mjs → carousel.client-A2lG-9od.mjs} +1 -1
  397. package/dist/client/{cart-CnWi30zJ.mjs → cart-DO20An50.mjs} +3 -3
  398. package/dist/client/{checkout-f3nkWgd4.mjs → checkout-Du5amDR_.mjs} +3 -3
  399. package/dist/client/{checkoutUrls-CW3-78uu.mjs → checkoutUrls-CXhko2Rv.mjs} +1 -1
  400. package/dist/client/client.mjs +3837 -2202
  401. package/dist/client/{colorStyles-CuJBiS-1.mjs → colorStyles-j5U9v5JA.mjs} +5 -1
  402. package/dist/client/{context-Bc8T6pCe.mjs → context-eW97E945.mjs} +4 -3
  403. package/dist/client/{dates-DUsCEzLb.mjs → dates-jPCirRea.mjs} +56 -11
  404. package/dist/client/{eventCalendar-CKwgXui5.mjs → eventCalendar-C2M-iE4j.mjs} +10 -10
  405. package/dist/client/{eventCombined-CBAOSTGR.mjs → eventCombined-W6ns3LHg.mjs} +4 -4
  406. package/dist/client/{eventDetails-Dh-_WiBD.mjs → eventDetails-CR-GT0f0.mjs} +4 -4
  407. package/dist/client/{eventListing-CA3frIH5.mjs → eventListing-BK8AfYZz.mjs} +4 -4
  408. package/dist/client/{eventRegistration-BHtsgdcg.mjs → eventRegistration-BJSd4KUu.mjs} +461 -266
  409. package/dist/client/{form-C2h3YAcg.mjs → form-BvpfbQaT.mjs} +5 -5
  410. package/dist/client/{headerSection-lwMuMTH9.mjs → headerSection-I5sUQ8x-.mjs} +3 -3
  411. package/dist/client/hooks.mjs +909 -163
  412. package/dist/client/{locationMap-DJ2bLODV.mjs → locationMap-BLvwf9_f.mjs} +4 -4
  413. package/dist/client/{FieldValidationMessage-AYanWFb-.mjs → mailingListSignupCopy-DZSHZrm6.mjs} +14 -1
  414. package/dist/client/{media-BtJ37tzS.mjs → media-Cl38iOMI.mjs} +11 -4
  415. package/dist/client/{newsletterForm-8Pu5K32g.mjs → newsletterForm-DrQ2weE8.mjs} +6 -6
  416. package/dist/client/{pricing-HHx3IgBz.mjs → pricing-BES87mrR.mjs} +1 -1
  417. package/dist/client/{productDetail-C_1odnAf.mjs → productDetail-Url9jcc5.mjs} +3 -3
  418. package/dist/client/{productList-CtCv-Nmx.mjs → productList-DE7ngEZJ.mjs} +3 -3
  419. package/dist/client/{propsDecoder-Dcgsncxb.mjs → propsDecoder-D1OtGXDV.mjs} +140 -22
  420. package/dist/client/rendering/client.mjs +2366 -997
  421. package/dist/client/rendering/islands.mjs +19 -19
  422. package/dist/client/rendering.mjs +4607 -2884
  423. package/dist/client/{routeIslandApiConfig-CWLP7wu3.mjs → routeIslandApiConfig-BG9Y-SHg.mjs} +1 -1
  424. package/dist/client/{shop-DQXrQ8kJ.mjs → shop-CJkuySJ3.mjs} +126 -79
  425. package/dist/client/{shop-commerce-B88zmWWo.mjs → shop-commerce-4rKj5n9h.mjs} +26 -14
  426. package/dist/client/{shop-commerce-store-DtSfkKuX.mjs → shop-commerce-store-Bxm75Pg6.mjs} +1 -1
  427. package/dist/client/{shopShared-cuaONpkJ.mjs → shopShared-DpoQDWfz.mjs} +5 -5
  428. package/dist/client/{useEventFilters-Bukew6Gb.mjs → useEventFilters-D8HliSqR.mjs} +33 -18
  429. package/dist/preview-next/before-render.mjs +314 -133
  430. package/dist/preview-next/client/runtime.mjs +4 -4
  431. package/dist/preview-next/editor-base.css +53 -2
  432. package/dist/preview-next/editor-chrome.css +7 -4
  433. package/dist/preview-next/keepAlive.mjs +314 -133
  434. package/dist/preview-next/middleware.mjs +314 -133
  435. package/dist/{previewAuthStore-h5IgbSp4.mjs → previewAuthStore-BXXF3hhW.mjs} +316 -133
  436. package/dist/{sdk-runtime-DTc1uIXn.mjs → sdk-runtime-C2a05WjL.mjs} +2 -2
  437. package/dist/{separator-BpHS1KZK.mjs → separator-CuNhBAhS.mjs} +1 -1
  438. package/dist/server/components.mjs +6888 -6157
  439. package/dist/server/config-validation.mjs +931 -199
  440. package/dist/server/config.mjs +931 -199
  441. package/dist/server/data.mjs +929 -198
  442. package/dist/server/index.mjs +317 -134
  443. package/dist/server/navigation.mjs +13 -2
  444. package/dist/server/next.mjs +5003 -4340
  445. package/dist/server/page-converter.mjs +160 -78
  446. package/dist/server/prebuild.mjs +1 -1
  447. package/dist/server/rendering/server.mjs +6421 -5687
  448. package/dist/server/rendering.mjs +7683 -6933
  449. package/dist/server/routing.mjs +1035 -338
  450. package/dist/server/server.mjs +946 -256
  451. package/dist/server/theme-bridge.mjs +66 -17
  452. package/dist/server/theme.mjs +5 -1
  453. package/dist/styles/index.css +32 -4
  454. package/package.json +1 -1
  455. package/dist/_dts/billing/src/plans/display.d.ts +0 -15
  456. package/dist/_dts/content-editor/src/controller/buildBlockPublishedBaselines.d.ts +0 -4
  457. package/dist/_dts/content-editor/src/controller/buildPublishSuccessTransition.d.ts +0 -16
  458. package/dist/_dts/content-editor/src/controller/driver.d.ts +0 -14
  459. package/dist/_dts/content-editor/src/controller/seedDraftBaselinesFromBlocks.d.ts +0 -7
  460. package/dist/_dts/content-editor/src/controller/useEntrySyncHelpers.d.ts +0 -29
  461. package/dist/_dts/content-editor/src/hooks/autosaveScopePlanning.d.ts +0 -26
  462. package/dist/_dts/content-editor/src/hooks/useSimpleAutosave.d.ts +0 -64
  463. package/dist/_dts/content-editor/src/hooks/useStoreAutosave.d.ts +0 -48
  464. package/dist/_dts/content-editor/src/types.d.ts +0 -44
  465. package/dist/_dts/core/src/participant-identity.d.ts +0 -135
  466. package/dist/client/DiscountCodeDisclosure-CsOtjFY7.mjs +0 -137
@@ -2563,6 +2563,19 @@ const CURRENCY_LOCALE_BY_CODE = {
2563
2563
  function resolveCurrencyLocale(currencyCode, override) {
2564
2564
  return override ?? CURRENCY_LOCALE_BY_CODE[currencyCode] ?? "en";
2565
2565
  }
2566
+ function fractionDigitsFor(decimals, exactFormatter) {
2567
+ switch (decimals) {
2568
+ case "exact": return {};
2569
+ case "auto": return {
2570
+ minimumFractionDigits: 0,
2571
+ maximumFractionDigits: exactFormatter.resolvedOptions().maximumFractionDigits
2572
+ };
2573
+ case "whole": return {
2574
+ minimumFractionDigits: 0,
2575
+ maximumFractionDigits: 0
2576
+ };
2577
+ }
2578
+ }
2566
2579
  /**
2567
2580
  * The single currency-amount formatter for the product: minor units in,
2568
2581
  * localized string out.
@@ -2573,6 +2586,13 @@ function resolveCurrencyLocale(currencyCode, override) {
2573
2586
  * own `Intl.NumberFormat`.
2574
2587
  */
2575
2588
  function formatCurrencyAmount(amountCents, currency, options) {
2589
+ return formatCurrencyMajorUnits(amountCents / 100, currency, options);
2590
+ }
2591
+ /**
2592
+ * `formatCurrencyAmount` for an amount already in MAJOR units (29.99 = £29.99),
2593
+ * such as a registrar price. Prefer minor units everywhere else.
2594
+ */
2595
+ function formatCurrencyMajorUnits(amount, currency, options) {
2576
2596
  const currencyCode = currency.toUpperCase();
2577
2597
  const locale = resolveCurrencyLocale(currencyCode, options?.locale);
2578
2598
  try {
@@ -2580,17 +2600,13 @@ function formatCurrencyAmount(amountCents, currency, options) {
2580
2600
  style: "currency",
2581
2601
  currency: currencyCode
2582
2602
  });
2583
- const fractionDigits = options?.decimals === "auto" ? {
2584
- minimumFractionDigits: 0,
2585
- maximumFractionDigits: exactFormatter.resolvedOptions().maximumFractionDigits
2586
- } : {};
2587
2603
  return new Intl.NumberFormat(locale, {
2588
2604
  style: "currency",
2589
2605
  currency: currencyCode,
2590
- ...fractionDigits
2591
- }).format(amountCents / 100);
2606
+ ...fractionDigitsFor(options?.decimals ?? "exact", exactFormatter)
2607
+ }).format(amount);
2592
2608
  } catch {
2593
- return `${(amountCents / 100).toFixed(2)} ${currencyCode}`;
2609
+ return `${amount.toFixed(2)} ${currencyCode}`;
2594
2610
  }
2595
2611
  }
2596
2612
  //#endregion
@@ -2786,7 +2802,7 @@ function parseEventPageSurfaceDestinationMode(value) {
2786
2802
  return value === "cms-managed" || value === "system-managed" ? value : void 0;
2787
2803
  }
2788
2804
  function parseEventPageSurfaceSubject(value) {
2789
- if (!isRecord$7(value)) return err$1({ kind: "notObject" });
2805
+ if (!isRecord$9(value)) return err$1({ kind: "notObject" });
2790
2806
  switch (value.kind) {
2791
2807
  case "eventSeries": {
2792
2808
  const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
@@ -2841,7 +2857,7 @@ function parseEventSeriesIdList(values) {
2841
2857
  }
2842
2858
  return ok$1(parsed);
2843
2859
  }
2844
- function isRecord$7(value) {
2860
+ function isRecord$9(value) {
2845
2861
  return typeof value === "object" && value !== null && !Array.isArray(value);
2846
2862
  }
2847
2863
  //#endregion
@@ -3162,6 +3178,22 @@ function layoutServicesByCategory(categories, services, options) {
3162
3178
  other
3163
3179
  };
3164
3180
  }
3181
+ //#endregion
3182
+ //#region ../core/src/mailing-list-runtime.ts
3183
+ function resolveBookingSignupOffer(context, siteName) {
3184
+ const name = siteName?.trim() ?? "";
3185
+ return context?.tag === "configured" && context.bookingSignup.tag === "offered" ? { siteName: name.length > 0 ? name : "this site" } : null;
3186
+ }
3187
+ //#endregion
3188
+ //#region ../core/src/uuid.ts
3189
+ function generateUuidV4(cryptoSource = globalThis.crypto) {
3190
+ if (typeof cryptoSource.randomUUID === "function") return cryptoSource.randomUUID();
3191
+ const bytes = cryptoSource.getRandomValues(/* @__PURE__ */ new Uint8Array(16));
3192
+ bytes[6] = (bytes[6] ?? 0) & 15 | 64;
3193
+ bytes[8] = (bytes[8] ?? 0) & 63 | 128;
3194
+ const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0"));
3195
+ return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10).join("")}`;
3196
+ }
3165
3197
  function sessionStartMs(session) {
3166
3198
  return Date.parse(session.startsAt);
3167
3199
  }
@@ -7017,7 +7049,7 @@ const boxBackgroundSchema = z.discriminatedUnion("type", [
7017
7049
  })
7018
7050
  ]);
7019
7051
  function normalizeAuthoringOpacity(value) {
7020
- if (!isRecord$6(value)) return value;
7052
+ if (!isRecord$8(value)) return value;
7021
7053
  return {
7022
7054
  ...value,
7023
7055
  opacity: normalizeOpacity(value.opacity)
@@ -7026,7 +7058,7 @@ function normalizeAuthoringOpacity(value) {
7026
7058
  function normalizeOpacity(value) {
7027
7059
  return typeof value === "number" && value > 1 && value <= 100 ? value / 100 : value;
7028
7060
  }
7029
- function isRecord$6(value) {
7061
+ function isRecord$8(value) {
7030
7062
  return typeof value === "object" && value !== null && !Array.isArray(value);
7031
7063
  }
7032
7064
  //#endregion
@@ -8150,7 +8182,6 @@ const publicEventBaseSchema = z.object({
8150
8182
  description: z.string().nullable(),
8151
8183
  content: z.object({ body: RichTextDocSchema.nullable().optional() }).optional(),
8152
8184
  presentation: z.object({
8153
- cardTitleOverride: z.string().nullable().optional(),
8154
8185
  summary: z.string().nullable().optional(),
8155
8186
  image: mediaSchema.nullable().optional()
8156
8187
  }).optional(),
@@ -8183,6 +8214,7 @@ const publicEventBaseSchema = z.object({
8183
8214
  "archived"
8184
8215
  ]).optional(),
8185
8216
  timeZone: z.string(),
8217
+ siteTimeZone: z.string().optional(),
8186
8218
  pricing: publicEventPricingSchema,
8187
8219
  paymentTerms: blockBookingPaymentTermsSchema,
8188
8220
  cancellationPolicy: z.object({ refunds: z.object({
@@ -8710,7 +8742,7 @@ var BlockApiError = class extends Error {
8710
8742
  this.name = "BlockApiError";
8711
8743
  }
8712
8744
  };
8713
- function isRecord$5(value) {
8745
+ function isRecord$7(value) {
8714
8746
  return typeof value === "object" && value !== null;
8715
8747
  }
8716
8748
  function isJsonResponseContentType(contentType) {
@@ -8734,15 +8766,15 @@ async function parseJsonBody(response) {
8734
8766
  }
8735
8767
  }
8736
8768
  function isFieldError(value) {
8737
- return isRecord$5(value) && !Array.isArray(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
8769
+ return isRecord$7(value) && !Array.isArray(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
8738
8770
  }
8739
8771
  function fieldErrorsFromUnknown(value) {
8740
8772
  if (!Array.isArray(value)) return void 0;
8741
8773
  return value.every(isFieldError) ? value : void 0;
8742
8774
  }
8743
8775
  function getBlockApiErrorDetails(data) {
8744
- if (!isRecord$5(data)) return {};
8745
- const nestedError = isRecord$5(data.error) ? data.error : void 0;
8776
+ if (!isRecord$7(data)) return {};
8777
+ const nestedError = isRecord$7(data.error) ? data.error : void 0;
8746
8778
  const message = typeof nestedError?.message === "string" ? nestedError.message : typeof data.message === "string" ? data.message : void 0;
8747
8779
  const code = typeof nestedError?.code === "string" ? nestedError.code : typeof data.code === "string" ? data.code : void 0;
8748
8780
  const fieldErrors = fieldErrorsFromUnknown(nestedError?.fieldErrors) ?? fieldErrorsFromUnknown(data.fieldErrors);
@@ -9311,10 +9343,11 @@ function createBlockApi(config) {
9311
9343
  },
9312
9344
  async sendMagicLink(data) {
9313
9345
  const sid = requireSiteId();
9314
- await request(PORTAL.sendMagicLink, { body: {
9346
+ return request(PORTAL.sendMagicLink, { body: {
9315
9347
  siteId: sid,
9316
9348
  email: data.email,
9317
- redirectUrl: data.redirectUrl
9349
+ redirectUrl: data.redirectUrl,
9350
+ demoBookingPass: data.demoBookingPass
9318
9351
  } });
9319
9352
  },
9320
9353
  async logout() {
@@ -9389,105 +9422,6 @@ function useBlockApi() {
9389
9422
  if (!client) throw new Error("useBlockApi must be used within a BlockApiProvider. Make sure your component is wrapped with <BlockApiProvider>.");
9390
9423
  return client;
9391
9424
  }
9392
- //#endregion
9393
- //#region ../blocks/src/system/runtime/shared/components/CheckIcon.tsx
9394
- function CheckIcon({ className, strokeWidth = 2 }) {
9395
- return /* @__PURE__ */ jsx("svg", {
9396
- fill: "none",
9397
- strokeLinecap: "round",
9398
- strokeLinejoin: "round",
9399
- strokeWidth,
9400
- viewBox: "0 0 24 24",
9401
- stroke: "currentColor",
9402
- className,
9403
- width: "1em",
9404
- height: "1em",
9405
- "aria-hidden": "true",
9406
- children: /* @__PURE__ */ jsx("path", { d: "M5 13l4 4L19 7" })
9407
- });
9408
- }
9409
- //#endregion
9410
- //#region ../blocks/src/system/runtime/shared/components/StateIcon.tsx
9411
- /**
9412
- * Circular icon wrapper for terminal state screens (success, error, waitlist, etc.).
9413
- *
9414
- * Layout is provided by shared `rb-state-icon` CSS; color variants are
9415
- * block-scoped by the owning registration surface.
9416
- */
9417
- function StateIcon({ variant, children }) {
9418
- return /* @__PURE__ */ jsx("div", {
9419
- className: `rb-state-icon rb-state-icon--${variant}`,
9420
- "aria-hidden": "true",
9421
- children
9422
- });
9423
- }
9424
- //#endregion
9425
- //#region ../blocks/src/system/runtime/shared/components/TerminalPanel.tsx
9426
- function joinClasses$1(...parts) {
9427
- return parts.filter((part) => typeof part === "string" && part.length > 0).join(" ");
9428
- }
9429
- function TerminalPanel({ tone, title, titleAs: Title = "h3", body, secondaryBody, icon, actions, className, titleClassName, bodyClassName, secondaryBodyClassName, iconClassName, actionsClassName, role, live }) {
9430
- const resolvedRole = role ?? (tone === "error" ? "alert" : "status");
9431
- const resolvedLive = live ?? (resolvedRole === "alert" ? "assertive" : "polite");
9432
- return /* @__PURE__ */ jsxs("div", {
9433
- className,
9434
- "data-terminal-panel": true,
9435
- "data-terminal-tone": tone,
9436
- role: resolvedRole,
9437
- "aria-live": resolvedLive === "off" ? void 0 : resolvedLive,
9438
- children: [
9439
- icon ? /* @__PURE__ */ jsx("div", {
9440
- className: joinClasses$1(iconClassName),
9441
- "data-terminal-icon": true,
9442
- children: icon
9443
- }) : null,
9444
- /* @__PURE__ */ jsx(Title, {
9445
- className: joinClasses$1(titleClassName),
9446
- "data-terminal-title": true,
9447
- children: title
9448
- }),
9449
- body ? /* @__PURE__ */ jsx("div", {
9450
- className: joinClasses$1(bodyClassName),
9451
- "data-terminal-body": true,
9452
- children: body
9453
- }) : null,
9454
- actions ? /* @__PURE__ */ jsx("div", {
9455
- className: joinClasses$1(actionsClassName),
9456
- "data-terminal-actions": true,
9457
- children: actions
9458
- }) : null,
9459
- secondaryBody ? /* @__PURE__ */ jsx("div", {
9460
- className: joinClasses$1(secondaryBodyClassName),
9461
- "data-terminal-secondary-body": true,
9462
- children: secondaryBody
9463
- }) : null
9464
- ]
9465
- });
9466
- }
9467
- //#endregion
9468
- //#region ../blocks/src/system/runtime/components/booking/SuccessMessage.tsx
9469
- const SuccessMessage = ({ message, resourceName, className }) => {
9470
- return /* @__PURE__ */ jsx(TerminalPanel, {
9471
- tone: "success",
9472
- title: "Booking confirmed",
9473
- icon: /* @__PURE__ */ jsx(StateIcon, {
9474
- variant: "success",
9475
- children: /* @__PURE__ */ jsx(CheckIcon, { strokeWidth: 3 })
9476
- }),
9477
- body: /* @__PURE__ */ jsx("p", {
9478
- className: "ab-text",
9479
- children: message
9480
- }),
9481
- secondaryBody: resourceName ? /* @__PURE__ */ jsxs("p", {
9482
- className: "ab-text rb-on-surface--muted",
9483
- children: ["Practitioner: ", resourceName]
9484
- }) : null,
9485
- className: ["ab-center", className ?? ""].join(" ").trim(),
9486
- titleClassName: "ab-terminal-title",
9487
- role: "alert",
9488
- live: "polite"
9489
- });
9490
- };
9491
9425
  new TextEncoder();
9492
9426
  //#endregion
9493
9427
  //#region ../altcha/src/index.ts
@@ -9571,7 +9505,8 @@ const BOOKING_FORM_DATA_RESERVED_KEY_VALUES = [
9571
9505
  "discountCode",
9572
9506
  "selectedSlidingAmountInput",
9573
9507
  "selectedCollectionOptionKind",
9574
- "selectedAppointmentPackageId"
9508
+ "selectedAppointmentPackageId",
9509
+ "mailingListOptIn"
9575
9510
  ];
9576
9511
  const BOOKING_FORM_DATA_RESERVED_KEYS = new Set(BOOKING_FORM_DATA_RESERVED_KEY_VALUES);
9577
9512
  //#endregion
@@ -9635,7 +9570,7 @@ function resolveAppointmentCheckoutVerificationState(input) {
9635
9570
  tag: "timeout",
9636
9571
  sessionId: input.config.sessionId,
9637
9572
  appointmentId,
9638
- message: "Could not verify your appointment payment. If you were charged, please contact support."
9573
+ message: "We’re still confirming your payment. This can take a minute – you can check again, and you won’t be charged twice."
9639
9574
  };
9640
9575
  if (input.pollingStatus === "failed") {
9641
9576
  if (paymentStatus === "refunded") return {
@@ -9699,7 +9634,7 @@ function deriveBookingFormViewState(input) {
9699
9634
  message: input.verificationState.message
9700
9635
  };
9701
9636
  case "timeout": return {
9702
- kind: "error",
9637
+ kind: "timeout",
9703
9638
  message: input.verificationState.message
9704
9639
  };
9705
9640
  case "confirmed": return {
@@ -9713,12 +9648,12 @@ function resolveBookingSiteId(siteId, form) {
9713
9648
  return siteId || form?.siteId || "";
9714
9649
  }
9715
9650
  function normalizeBookingFormConfig(form) {
9716
- if (!isRecord$4(form)) return null;
9651
+ if (!isRecord$6(form)) return null;
9717
9652
  const id = readNonEmptyString(form.id);
9718
9653
  const name = readNonEmptyString(form.name);
9719
9654
  if (!id || !name) return null;
9720
- const schemaSource = isRecord$4(form.schema) ? form.schema : isRecord$4(form.schemaJson) ? form.schemaJson : null;
9721
- const settingsSource = isRecord$4(form.settings) ? form.settings : isRecord$4(form.settingsJson) ? form.settingsJson : null;
9655
+ const schemaSource = isRecord$6(form.schema) ? form.schema : isRecord$6(form.schemaJson) ? form.schemaJson : null;
9656
+ const settingsSource = isRecord$6(form.settings) ? form.settings : isRecord$6(form.settingsJson) ? form.settingsJson : null;
9722
9657
  return {
9723
9658
  id,
9724
9659
  name,
@@ -9738,8 +9673,8 @@ function normalizeBookingServices(services) {
9738
9673
  };
9739
9674
  if (!services) return [];
9740
9675
  if (Array.isArray(services)) return services.filter(isBookingFormService).map(normalizeService);
9741
- if (isRecord$4(services) && "services" in services) return Array.isArray(services.services) ? services.services.filter(isBookingFormService).map(normalizeService) : [];
9742
- return isRecord$4(services) ? Object.values(services).filter(isBookingFormService).map(normalizeService) : [];
9676
+ if (isRecord$6(services) && "services" in services) return Array.isArray(services.services) ? services.services.filter(isBookingFormService).map(normalizeService) : [];
9677
+ return isRecord$6(services) ? Object.values(services).filter(isBookingFormService).map(normalizeService) : [];
9743
9678
  }
9744
9679
  function normalizeBookingSchema(value) {
9745
9680
  if (!value) return void 0;
@@ -9750,7 +9685,7 @@ function normalizeBookingSchema(value) {
9750
9685
  };
9751
9686
  }
9752
9687
  function readBookingFormField(value) {
9753
- if (!isRecord$4(value)) return null;
9688
+ if (!isRecord$6(value)) return null;
9754
9689
  const id = readNonEmptyString(value.id);
9755
9690
  const label = readNonEmptyString(value.label);
9756
9691
  const type = readBookingFieldType(value.type);
@@ -9793,7 +9728,7 @@ function readBookingFieldOptions(value) {
9793
9728
  return options.length > 0 ? options : void 0;
9794
9729
  }
9795
9730
  function readBookingFieldOption(value) {
9796
- if (!isRecord$4(value)) return null;
9731
+ if (!isRecord$6(value)) return null;
9797
9732
  const optionValue = readNonEmptyString(value.value);
9798
9733
  const label = readNonEmptyString(value.label);
9799
9734
  return optionValue && label ? {
@@ -9813,7 +9748,7 @@ function normalizeBookingSettings(value) {
9813
9748
  };
9814
9749
  }
9815
9750
  function isBookingFormService(value) {
9816
- return isRecord$4(value) && typeof value.id === "string" && typeof value.siteId === "string" && typeof value.title === "string" && (value.consent === void 0 || blockBookingConsentSchema.safeParse(value.consent).success);
9751
+ return isRecord$6(value) && typeof value.id === "string" && typeof value.siteId === "string" && typeof value.title === "string" && (value.consent === void 0 || blockBookingConsentSchema.safeParse(value.consent).success);
9817
9752
  }
9818
9753
  function collectBookingCustomFields(data) {
9819
9754
  const customFields = {};
@@ -9863,7 +9798,7 @@ function readStringArray(value) {
9863
9798
  const strings = value.filter((item) => typeof item === "string");
9864
9799
  return strings.length > 0 ? strings : void 0;
9865
9800
  }
9866
- function isRecord$4(value) {
9801
+ function isRecord$6(value) {
9867
9802
  return typeof value === "object" && value !== null;
9868
9803
  }
9869
9804
  function getBookingServicePaymentSelectionMode(service) {
@@ -9991,6 +9926,7 @@ function prepareBookingSubmission(input) {
9991
9926
  startAt: selectedSlot,
9992
9927
  endAt: endDate.toISOString(),
9993
9928
  customFields: collectBookingCustomFields(input.data),
9929
+ ...selectedMailingListOptIn(input.data),
9994
9930
  timezone: toBookingTimeZone(input.viewerTimeZone ?? null)
9995
9931
  };
9996
9932
  if (customerPassId) return {
@@ -10041,6 +9977,9 @@ function prepareBookingSubmission(input) {
10041
9977
  }
10042
9978
  };
10043
9979
  }
9980
+ function selectedMailingListOptIn(data) {
9981
+ return data.mailingListOptIn === true ? { mailingListOptIn: true } : {};
9982
+ }
10044
9983
  function formatBookingSubmissionPreparationError(error) {
10045
9984
  switch (error.tag) {
10046
9985
  case "missing-required-booking-information": return "Missing required booking information";
@@ -10053,8 +9992,40 @@ function formatBookingSubmissionPreparationError(error) {
10053
9992
  default: return assertNever(error);
10054
9993
  }
10055
9994
  }
10056
- function getBookingSuccessMessage(successMessage) {
10057
- return successMessage?.trim() || "Your appointment has been booked! Check your email for confirmation.";
9995
+ const DEFAULT_BOOKING_SUCCESS_COPY = {
9996
+ message: "Your booking has been confirmed.",
9997
+ defaultEmailSentence: "Check your email for details."
9998
+ };
9999
+ const DEFAULT_BOOKING_SUCCESS_MESSAGE = "Your booking has been confirmed. Check your email for details.";
10000
+ function getBookingSuccessCopy(successMessage) {
10001
+ const customMessage = successMessage?.trim();
10002
+ return customMessage && customMessage !== DEFAULT_BOOKING_SUCCESS_MESSAGE ? { message: customMessage } : DEFAULT_BOOKING_SUCCESS_COPY;
10003
+ }
10004
+ //#endregion
10005
+ //#region ../blocks/src/system/runtime/nodes/booking-form.payment-confirmation.ts
10006
+ function bookingServiceRequiresPaymentBeforeBooking(input) {
10007
+ switch (getBookingServicePaymentSelectionMode(input.service)) {
10008
+ case "implicit_upfront":
10009
+ case "implicit_instalment_plan":
10010
+ case "implicit_flexible_balance": return true;
10011
+ case "choice_required": return input.selectedCollectionOptionKind !== void 0 && input.selectedCollectionOptionKind !== "deferred_manual";
10012
+ case "implicit_deferred_manual":
10013
+ case "pending_stripe_setup":
10014
+ case "unsupported": return false;
10015
+ }
10016
+ }
10017
+ function resolveBookingPaymentConfirmationSummary(input) {
10018
+ const service = input.service;
10019
+ if (!service || input.hasSelectedAppointmentPackage || !Number.isFinite(input.priceAmount) || input.priceAmount <= 0 || !service.durationMinutes || !bookingServiceRequiresPaymentBeforeBooking({
10020
+ service,
10021
+ selectedCollectionOptionKind: input.selectedCollectionOptionKind
10022
+ })) return null;
10023
+ return {
10024
+ serviceTitle: service.title,
10025
+ durationMinutes: service.durationMinutes,
10026
+ priceAmount: input.priceAmount,
10027
+ priceCurrency: service.priceCurrency ?? service.pricing?.currency ?? "USD"
10028
+ };
10058
10029
  }
10059
10030
  //#endregion
10060
10031
  //#region ../blocks/src/system/runtime/hooks/useSelectedAppointmentConsentForm.ts
@@ -10575,6 +10546,54 @@ function selectIsSubmitting(state) {
10575
10546
  return state.status.tag === "submitting";
10576
10547
  }
10577
10548
  //#endregion
10549
+ //#region ../blocks/src/system/runtime/shared/utils/demoBookingPassStorage.ts
10550
+ const STORAGE_KEY = "riverbank:demo-booking-passes:v1";
10551
+ const MAX_STORED_PASSES = 10;
10552
+ function normalizeDemoBookingEmail(email) {
10553
+ return email.trim().toLowerCase();
10554
+ }
10555
+ function storeDemoBookingPass(email, pass) {
10556
+ try {
10557
+ const normalizedEmail = normalizeDemoBookingEmail(email);
10558
+ if (!normalizedEmail || !pass) return;
10559
+ const current = readStoredDemoBookingPasses();
10560
+ const updated = [{
10561
+ email: normalizedEmail,
10562
+ pass
10563
+ }, ...current.filter((entry) => entry.email !== normalizedEmail)].slice(0, MAX_STORED_PASSES);
10564
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify(updated));
10565
+ } catch {}
10566
+ }
10567
+ function storeDemoBookingPassIfAvailable(email, pass) {
10568
+ if (email && pass) storeDemoBookingPass(email, pass);
10569
+ }
10570
+ function getDemoBookingPass(email) {
10571
+ try {
10572
+ const normalizedEmail = normalizeDemoBookingEmail(email);
10573
+ return readStoredDemoBookingPasses().find((entry) => entry.email === normalizedEmail)?.pass ?? null;
10574
+ } catch {
10575
+ return null;
10576
+ }
10577
+ }
10578
+ function readStoredDemoBookingPasses() {
10579
+ try {
10580
+ const raw = window.localStorage.getItem(STORAGE_KEY);
10581
+ if (!raw) return [];
10582
+ const parsed = JSON.parse(raw);
10583
+ return Array.isArray(parsed) ? parsed.filter(isStoredDemoBookingPass) : [];
10584
+ } catch {
10585
+ return [];
10586
+ }
10587
+ }
10588
+ function isStoredDemoBookingPass(value) {
10589
+ if (!isRecord$5(value)) return false;
10590
+ const record = value;
10591
+ return typeof record.email === "string" && record.email.length > 0 && typeof record.pass === "string" && record.pass.length > 0;
10592
+ }
10593
+ function isRecord$5(value) {
10594
+ return typeof value === "object" && value !== null && !Array.isArray(value);
10595
+ }
10596
+ //#endregion
10578
10597
  //#region ../blocks/src/system/runtime/hooks/useBookingSubmission.ts
10579
10598
  /**
10580
10599
  * Custom hook for submitting appointment bookings
@@ -10621,6 +10640,7 @@ function useBookingSubmission(_siteId) {
10621
10640
  startAt: data.startAt,
10622
10641
  endAt: data.endAt,
10623
10642
  customFields: data.customFields,
10643
+ mailingListOptIn: data.mailingListOptIn,
10624
10644
  timezone: data.timezone,
10625
10645
  customerPassId: data.customerPassId
10626
10646
  }) : await api.submitBooking({
@@ -10630,6 +10650,7 @@ function useBookingSubmission(_siteId) {
10630
10650
  startAt: data.startAt,
10631
10651
  endAt: data.endAt,
10632
10652
  customFields: data.customFields,
10653
+ mailingListOptIn: data.mailingListOptIn,
10633
10654
  timezone: data.timezone,
10634
10655
  discountCode: data.discountCode,
10635
10656
  selectedSlidingAmount: data.selectedSlidingAmount,
@@ -10638,6 +10659,7 @@ function useBookingSubmission(_siteId) {
10638
10659
  successUrl: data.successUrl,
10639
10660
  cancelUrl: data.cancelUrl
10640
10661
  });
10662
+ storeDemoBookingPassIfAvailable(response.customer.email, response.demoBookingPass);
10641
10663
  dispatch({
10642
10664
  type: "submission-succeeded",
10643
10665
  message: response.type === "checkout_redirect" ? "Redirecting to secure checkout..." : "Booking submitted successfully."
@@ -10665,6 +10687,45 @@ function useBookingSubmission(_siteId) {
10665
10687
  };
10666
10688
  }
10667
10689
  //#endregion
10690
+ //#region ../blocks/src/system/runtime/nodes/booking-form.submit-success.ts
10691
+ function completeBookingSubmission(input) {
10692
+ const { data } = input;
10693
+ if (data.type === "checkout_redirect") {
10694
+ if (input.redirect === "auto" && typeof window !== "undefined") input.navigateToCheckout(data.checkoutUrl);
10695
+ return {
10696
+ ok: true,
10697
+ outcome: {
10698
+ kind: "checkout_redirect",
10699
+ checkoutUrl: data.checkoutUrl,
10700
+ sessionId: data.sessionId,
10701
+ customerEmail: data.customer.email,
10702
+ ...data.demoBookingPass ? { demoBookingPass: data.demoBookingPass } : {},
10703
+ ...data.mailingListSignupNote ? { mailingListSignupNote: data.mailingListSignupNote } : {}
10704
+ }
10705
+ };
10706
+ }
10707
+ const successCopy = getBookingSuccessCopy(input.successMessage);
10708
+ input.dispatch({
10709
+ type: "feedback-set",
10710
+ feedback: {
10711
+ kind: "success",
10712
+ message: successCopy.defaultEmailSentence ? `${successCopy.message} ${successCopy.defaultEmailSentence}`.trim() : successCopy.message,
10713
+ resourceName: data.appointment.resourceName
10714
+ }
10715
+ });
10716
+ return {
10717
+ ok: true,
10718
+ outcome: {
10719
+ kind: "booked",
10720
+ appointmentId: data.appointment.id,
10721
+ resourceName: data.appointment.resourceName,
10722
+ customerEmail: data.customer.email,
10723
+ ...data.demoBookingPass ? { demoBookingPass: data.demoBookingPass } : {},
10724
+ ...data.mailingListSignupNote ? { mailingListSignupNote: data.mailingListSignupNote } : {}
10725
+ }
10726
+ };
10727
+ }
10728
+ //#endregion
10668
10729
  //#region ../blocks/src/system/runtime/api/types/discounts.ts
10669
10730
  function discountAvailabilityHasDiscounts(availability) {
10670
10731
  return availability.type !== "none";
@@ -11123,11 +11184,11 @@ function formatScheduleDate(isoString, locale) {
11123
11184
  }
11124
11185
  //#endregion
11125
11186
  //#region ../blocks/src/system/runtime/nodes/booking-form.service-categories.ts
11126
- function isRecord$3(value) {
11187
+ function isRecord$4(value) {
11127
11188
  return typeof value === "object" && value !== null && !Array.isArray(value);
11128
11189
  }
11129
11190
  function readCategory(value) {
11130
- if (!isRecord$3(value)) return [];
11191
+ if (!isRecord$4(value)) return [];
11131
11192
  const { id, name, description } = value;
11132
11193
  if (typeof id !== "string" || id.trim() === "" || typeof name !== "string") return [];
11133
11194
  return [{
@@ -11143,7 +11204,7 @@ function readCategory(value) {
11143
11204
  * it.
11144
11205
  */
11145
11206
  function normalizeBookingServiceCategories(services) {
11146
- if (!isRecord$3(services) || !Array.isArray(services.categories)) return [];
11207
+ if (!isRecord$4(services) || !Array.isArray(services.categories)) return [];
11147
11208
  return services.categories.flatMap(readCategory);
11148
11209
  }
11149
11210
  /**
@@ -11151,7 +11212,7 @@ function normalizeBookingServiceCategories(services) {
11151
11212
  * its loader data (`data.services`).
11152
11213
  */
11153
11214
  function readOverrideServiceCategories(data) {
11154
- return isRecord$3(data) ? normalizeBookingServiceCategories(data.services) : [];
11215
+ return isRecord$4(data) ? normalizeBookingServiceCategories(data.services) : [];
11155
11216
  }
11156
11217
  //#endregion
11157
11218
  //#region ../blocks/src/system/runtime/nodes/booking-form.validationErrors.ts
@@ -11195,6 +11256,40 @@ function clearBookingFieldError(errors, fieldId) {
11195
11256
  };
11196
11257
  }
11197
11258
  //#endregion
11259
+ //#region ../blocks/src/system/runtime/nodes/booking-form.mailing-list-state.ts
11260
+ function bookingFormDataWithEligibleOptIn(data, eligible) {
11261
+ return {
11262
+ ...data,
11263
+ mailingListOptIn: eligible && data.mailingListOptIn === true
11264
+ };
11265
+ }
11266
+ function isBookingContactEvent(event) {
11267
+ return event.type === "field-updated" || event.type === "field-touched" || event.type === "mailing-list-opt-in-set";
11268
+ }
11269
+ function applyBookingContactEvent(state, event) {
11270
+ switch (event.type) {
11271
+ case "field-updated": return {
11272
+ ...state,
11273
+ fieldValues: {
11274
+ ...state.fieldValues,
11275
+ [event.fieldId]: event.value
11276
+ },
11277
+ validationErrors: clearBookingFieldError(clearBookingFormError(state.validationErrors), event.fieldId)
11278
+ };
11279
+ case "field-touched": return {
11280
+ ...state,
11281
+ touchedFields: {
11282
+ ...state.touchedFields,
11283
+ [event.fieldId]: true
11284
+ }
11285
+ };
11286
+ case "mailing-list-opt-in-set": return {
11287
+ ...state,
11288
+ mailingListOptIn: event.checked
11289
+ };
11290
+ }
11291
+ }
11292
+ //#endregion
11198
11293
  //#region ../blocks/src/system/runtime/nodes/booking-form.field-values.ts
11199
11294
  function collectInitialBookingFieldValues(initialData) {
11200
11295
  const values = {};
@@ -11220,6 +11315,7 @@ function createInitialBookingFlowReducerState(input) {
11220
11315
  selectedDate: toOptionalString(initialData.selectedDate),
11221
11316
  selectedSlot: null,
11222
11317
  fieldValues: collectInitialBookingFieldValues(initialData),
11318
+ mailingListOptIn: initialData.mailingListOptIn === true,
11223
11319
  touchedFields: {},
11224
11320
  attemptedStepIds: {},
11225
11321
  discountCode: toOptionalString(initialData.discountCode) ?? "",
@@ -11272,6 +11368,7 @@ function applyAvailabilitySelectionInvalidation(state, invalidation) {
11272
11368
  };
11273
11369
  }
11274
11370
  function bookingFlowReducer(state, event) {
11371
+ if (isBookingContactEvent(event)) return applyBookingContactEvent(state, event);
11275
11372
  switch (event.type) {
11276
11373
  case "service-selected": return applyBookingServiceSelection(state, event.serviceId);
11277
11374
  case "resource-selected": return {
@@ -11294,21 +11391,6 @@ function bookingFlowReducer(state, event) {
11294
11391
  feedback: clearAvailabilityFeedback(state.feedback),
11295
11392
  validationErrors: clearBookingFormError(state.validationErrors)
11296
11393
  };
11297
- case "field-updated": return {
11298
- ...state,
11299
- fieldValues: {
11300
- ...state.fieldValues,
11301
- [event.fieldId]: event.value
11302
- },
11303
- validationErrors: clearBookingFieldError(clearBookingFormError(state.validationErrors), event.fieldId)
11304
- };
11305
- case "field-touched": return {
11306
- ...state,
11307
- touchedFields: {
11308
- ...state.touchedFields,
11309
- [event.fieldId]: true
11310
- }
11311
- };
11312
11394
  case "step-advance-attempted": return state.attemptedStepIds[event.stepId] ? state : {
11313
11395
  ...state,
11314
11396
  attemptedStepIds: {
@@ -11446,6 +11528,7 @@ function deriveBookingSlotDisplayOptions(input) {
11446
11528
  function toBookingFormData(state) {
11447
11529
  return {
11448
11530
  ...state.fieldValues,
11531
+ mailingListOptIn: state.mailingListOptIn,
11449
11532
  serviceId: state.selectedServiceId,
11450
11533
  resourceId: state.selectedResourceId ?? state.selectedSlot?.resourceId,
11451
11534
  selectedDate: state.selectedDate,
@@ -11708,10 +11791,7 @@ function buildBookingSubmitPlan(input) {
11708
11791
  };
11709
11792
  const prepared = prepareBookingSubmission({
11710
11793
  formId: input.formId,
11711
- data: toBookingFormData({
11712
- ...input.state,
11713
- altchaSolution: input.altchaSolution ?? input.state.altchaSolution
11714
- }),
11794
+ data: bookingFormDataWithEligibleOptIn(toBookingFormData(input.state), Boolean(input.mailingListEligible)),
11715
11795
  services: input.services,
11716
11796
  defaultServiceId: input.defaultServiceId,
11717
11797
  defaultResourceId: input.defaultResourceId,
@@ -11898,7 +11978,7 @@ function isBlankFieldValue(value) {
11898
11978
  return false;
11899
11979
  }
11900
11980
  function readAppointmentBookingOverrideData(value) {
11901
- if (!isRecord$2(value)) return null;
11981
+ if (!isRecord$3(value)) return null;
11902
11982
  const services = normalizeBookingServices(value.services);
11903
11983
  return {
11904
11984
  form: normalizeBookingFormConfig(value.form),
@@ -11913,7 +11993,7 @@ function createOverrideInputError(reason, message, warnInDev = false) {
11913
11993
  message
11914
11994
  };
11915
11995
  }
11916
- function isRecord$2(value) {
11996
+ function isRecord$3(value) {
11917
11997
  return typeof value === "object" && value !== null;
11918
11998
  }
11919
11999
  //#endregion
@@ -11966,6 +12046,8 @@ function useHeadlessBookingFlow(options) {
11966
12046
  const canLoadAppointmentPackages = Boolean(options.enableAppointmentPackages && hasPortalBearerAuth && selectedService && !selectedServiceSlidingScale && (selectedService.priceAmount ?? 0) > 0);
11967
12047
  const appointmentPackagesUnavailableReason = !options.enableAppointmentPackages ? "disabled" : !selectedService || selectedServiceSlidingScale || (selectedService.priceAmount ?? 0) <= 0 ? "missing-priced-service" : !hasPortalBearerAuth ? "missing-portal-auth" : null;
11968
12048
  const data = useMemo(() => toBookingFormData(state), [state]);
12049
+ const mailingList = resolveBookingSignupOffer(options.mailingList, options.siteName);
12050
+ const mailingListEligible = mailingList !== null;
11969
12051
  const availabilityDatesQuery = useMemo(() => buildBookingAvailabilityQuery({
11970
12052
  serviceId: selectedServiceId,
11971
12053
  resourceId: selectedResourceId,
@@ -12226,7 +12308,8 @@ function useHeadlessBookingFlow(options) {
12226
12308
  viewerTimeZone: latest.viewerTimeZone,
12227
12309
  redirect: submitOptions?.redirect ?? "manual",
12228
12310
  successUrl: submitOptions?.successUrl,
12229
- cancelUrl: submitOptions?.cancelUrl
12311
+ cancelUrl: submitOptions?.cancelUrl,
12312
+ mailingListEligible
12230
12313
  });
12231
12314
  if (!plan.ok) {
12232
12315
  dispatch({
@@ -12259,37 +12342,18 @@ function useHeadlessBookingFlow(options) {
12259
12342
  message: result.error
12260
12343
  };
12261
12344
  }
12262
- if (result.data.type === "checkout_redirect") {
12263
- if (plan.redirect === "auto" && typeof window !== "undefined") latest.navigateToCheckout(result.data.checkoutUrl);
12264
- return {
12265
- ok: true,
12266
- outcome: {
12267
- kind: "checkout_redirect",
12268
- checkoutUrl: result.data.checkoutUrl
12269
- }
12270
- };
12271
- }
12272
- dispatch({
12273
- type: "feedback-set",
12274
- feedback: {
12275
- kind: "success",
12276
- message: getBookingSuccessMessage(latest.successMessage),
12277
- resourceName: result.data.appointment.resourceName
12278
- }
12345
+ return completeBookingSubmission({
12346
+ data: result.data,
12347
+ redirect: plan.redirect,
12348
+ successMessage: latest.successMessage,
12349
+ navigateToCheckout: latest.navigateToCheckout,
12350
+ dispatch
12279
12351
  });
12280
- return {
12281
- ok: true,
12282
- outcome: {
12283
- kind: "booked",
12284
- appointmentId: result.data.appointment.id,
12285
- resourceName: result.data.appointment.resourceName
12286
- }
12287
- };
12288
12352
  } finally {
12289
12353
  submittingRef.current = false;
12290
12354
  dispatch({ type: "submission-finished" });
12291
12355
  }
12292
- }, [latestRef]);
12356
+ }, [latestRef, mailingListEligible]);
12293
12357
  const actions = useMemo(() => ({
12294
12358
  selectService: (serviceId) => dispatch({
12295
12359
  type: "service-selected",
@@ -12312,6 +12376,10 @@ function useHeadlessBookingFlow(options) {
12312
12376
  fieldId: unsafeAsBookingFieldId(fieldId),
12313
12377
  value
12314
12378
  }),
12379
+ setMailingListOptIn: (checked) => dispatch({
12380
+ type: "mailing-list-opt-in-set",
12381
+ checked
12382
+ }),
12315
12383
  markFieldTouched: (fieldId) => dispatch({
12316
12384
  type: "field-touched",
12317
12385
  fieldId: unsafeAsBookingFieldId(fieldId)
@@ -12428,6 +12496,12 @@ function useHeadlessBookingFlow(options) {
12428
12496
  selectedService,
12429
12497
  state.selectedSlot?.startAt
12430
12498
  ]);
12499
+ const paymentConfirmationSummary = resolveBookingPaymentConfirmationSummary({
12500
+ service: selectedService,
12501
+ priceAmount: selectedAppointmentPriceAmount,
12502
+ selectedCollectionOptionKind: state.selectedCollectionOptionKind,
12503
+ hasSelectedAppointmentPackage: Boolean(state.selectedAppointmentPackageId)
12504
+ });
12431
12505
  const appointmentPackageItems = appointmentPackages.tag === "loaded" ? appointmentPackages.value : [];
12432
12506
  const selectedAppointmentPackage = appointmentPackageItems.find((appointmentPackage) => appointmentPackage.customerPassId === state.selectedAppointmentPackageId) ?? null;
12433
12507
  const spamProtectionEnabled = options.spamProtectionEnabled ?? isSpamProtectionEnabled();
@@ -12457,7 +12531,8 @@ function useHeadlessBookingFlow(options) {
12457
12531
  selectedSlidingAmount,
12458
12532
  slidingScale: selectedServiceSlidingScale,
12459
12533
  appointmentPackages: appointmentPackagesModel,
12460
- errorMessage: paymentResolution.errorMessage ?? "This service cannot be booked right now."
12534
+ errorMessage: paymentResolution.errorMessage ?? "This service cannot be booked right now.",
12535
+ confirmationSummary: null
12461
12536
  } : {
12462
12537
  kind: "ok",
12463
12538
  mode: paymentResolution.mode,
@@ -12467,9 +12542,12 @@ function useHeadlessBookingFlow(options) {
12467
12542
  selectedSlidingAmountInput: state.selectedSlidingAmountInput,
12468
12543
  selectedSlidingAmount,
12469
12544
  slidingScale: selectedServiceSlidingScale,
12470
- appointmentPackages: appointmentPackagesModel
12545
+ appointmentPackages: appointmentPackagesModel,
12546
+ confirmationSummary: paymentConfirmationSummary
12471
12547
  };
12472
12548
  return {
12549
+ mailingList,
12550
+ mailingListOptIn: state.mailingListOptIn,
12473
12551
  status,
12474
12552
  view,
12475
12553
  steps: stepState.steps,
@@ -12623,67 +12701,24 @@ function pollingReducer(state, action) {
12623
12701
  * Provides a reusable polling mechanism with configurable intervals,
12624
12702
  * max attempts, and completion detection. Used by usePaymentVerification
12625
12703
  * and other hooks that need to poll for status changes.
12626
- *
12627
- * @example
12628
- * ```tsx
12629
- * const polling = usePolling(shouldPoll ? {
12630
- * pollFn: () => api.getStatus(id),
12631
- * isComplete: (result) => result.status === 'done',
12632
- * } : null);
12633
- *
12634
- * useEffect(() => {
12635
- * if (polling.status === 'completed') {
12636
- * handleSuccess(polling.result);
12637
- * }
12638
- * }, [polling.status]);
12639
- * ```
12640
12704
  */
12641
12705
  const DEFAULT_MAX_ATTEMPTS = 10;
12642
12706
  const DEFAULT_POLL_INTERVAL = 1e3;
12643
- /**
12644
- * Generic hook for polling an async operation until completion.
12645
- *
12646
- * Pass config to start polling, or null to stop/idle.
12647
- * The hook handles cleanup on unmount and config changes.
12648
- *
12649
- * **IMPORTANT: Config identity stability**
12650
- *
12651
- * The config object is used as an effect dependency. If config identity
12652
- * changes on every render (e.g., inline objects), polling will restart
12653
- * continuously, causing infinite request loops.
12654
- *
12655
- * Always memoize the config object:
12656
- *
12657
- * @example
12658
- * ```tsx
12659
- * // BAD - inline object creates new identity every render
12660
- * usePolling({
12661
- * pollFn: () => api.getStatus(id),
12662
- * isComplete: (result) => result.status === 'done',
12663
- * });
12664
- *
12665
- * // GOOD - memoized config, stable identity
12666
- * const pollConfig = useMemo(() => shouldPoll ? {
12667
- * pollFn: () => api.getStatus(id),
12668
- * isComplete: (result) => result.status === 'done',
12669
- * } : null, [shouldPoll, api, id]);
12670
- *
12671
- * usePolling(pollConfig);
12672
- * ```
12673
- *
12674
- * @param config - Configuration for polling, or null to stop
12675
- * @returns Polling result with status, data, and retry function
12676
- */
12677
- function usePolling(config) {
12678
- const [state, dispatch] = useReducer(pollingReducer, void 0, createInitialPollingState);
12679
- const attemptsRef = useRef(0);
12680
- const timeoutRef = useRef(null);
12681
- const isPollingRef = useRef(false);
12682
- const isActiveRef = useRef(false);
12683
- const generationRef = useRef(0);
12684
- const configRef = useRef(config);
12685
- configRef.current = config;
12686
- const cleanup = useCallback(() => {
12707
+ function usePollingRuntime(config) {
12708
+ const runtime = {
12709
+ configRef: useRef(config),
12710
+ attemptsRef: useRef(0),
12711
+ timeoutRef: useRef(null),
12712
+ isPollingRef: useRef(false),
12713
+ isActiveRef: useRef(false),
12714
+ generationRef: useRef(0)
12715
+ };
12716
+ runtime.configRef.current = config;
12717
+ return runtime;
12718
+ }
12719
+ function usePollingCleanup(runtime) {
12720
+ const { isActiveRef, generationRef, timeoutRef, isPollingRef } = runtime;
12721
+ return useCallback(() => {
12687
12722
  isActiveRef.current = false;
12688
12723
  generationRef.current += 1;
12689
12724
  if (timeoutRef.current) {
@@ -12691,16 +12726,27 @@ function usePolling(config) {
12691
12726
  timeoutRef.current = null;
12692
12727
  }
12693
12728
  isPollingRef.current = false;
12694
- }, []);
12695
- const resetState = useCallback(() => {
12696
- dispatch({ type: "polling-reset" });
12697
- attemptsRef.current = 0;
12698
- }, []);
12699
- const poll = useCallback(async () => {
12700
- const cfg = configRef.current;
12701
- if (!cfg) return true;
12729
+ }, [
12730
+ generationRef,
12731
+ isActiveRef,
12732
+ isPollingRef,
12733
+ timeoutRef
12734
+ ]);
12735
+ }
12736
+ function usePollingReset(runtime, dispatch) {
12737
+ const { attemptsRef } = runtime;
12738
+ return useCallback(() => {
12739
+ dispatch({ type: "polling-reset" });
12740
+ attemptsRef.current = 0;
12741
+ }, [attemptsRef, dispatch]);
12742
+ }
12743
+ function usePollingRequest(runtime, dispatch, cleanup) {
12744
+ const { configRef, attemptsRef, isPollingRef, isActiveRef, generationRef } = runtime;
12745
+ return useCallback(async () => {
12746
+ const config = configRef.current;
12747
+ if (!config) return true;
12702
12748
  if (isPollingRef.current) return false;
12703
- const maxAttempts = cfg.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
12749
+ const maxAttempts = config.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
12704
12750
  if (attemptsRef.current >= maxAttempts) {
12705
12751
  dispatch({ type: "polling-timed-out" });
12706
12752
  cleanup();
@@ -12710,81 +12756,115 @@ function usePolling(config) {
12710
12756
  attemptsRef.current += 1;
12711
12757
  const generation = generationRef.current;
12712
12758
  try {
12713
- const data = await cfg.pollFn();
12714
- if (generation !== generationRef.current || !isActiveRef.current) {
12715
- isPollingRef.current = false;
12716
- return true;
12717
- }
12718
- if (cfg.isFailed?.(data)) {
12759
+ const result = await config.pollFn();
12760
+ if (generation !== generationRef.current || !isActiveRef.current) return true;
12761
+ if (config.isFailed?.(result)) {
12719
12762
  dispatch({
12720
12763
  type: "polling-failed",
12721
- result: data
12764
+ result
12722
12765
  });
12723
12766
  cleanup();
12724
12767
  return true;
12725
12768
  }
12726
- if (cfg.isComplete(data)) {
12769
+ if (config.isComplete(result)) {
12727
12770
  dispatch({
12728
12771
  type: "polling-completed",
12729
- result: data
12772
+ result
12730
12773
  });
12731
12774
  cleanup();
12732
12775
  return true;
12733
12776
  }
12734
12777
  dispatch({
12735
12778
  type: "polling-progressed",
12736
- result: data
12779
+ result
12737
12780
  });
12738
12781
  isPollingRef.current = false;
12739
12782
  return false;
12740
- } catch (err) {
12741
- if (generation !== generationRef.current || !isActiveRef.current) {
12742
- isPollingRef.current = false;
12743
- return true;
12744
- }
12745
- if (err instanceof Error) dispatch({
12783
+ } catch (error) {
12784
+ if (generation !== generationRef.current || !isActiveRef.current) return true;
12785
+ if (error instanceof Error) dispatch({
12746
12786
  type: "polling-request-failed",
12747
- error: err
12787
+ error
12748
12788
  });
12749
12789
  isPollingRef.current = false;
12750
12790
  return false;
12751
12791
  }
12752
- }, [cleanup]);
12753
- const schedulePoll = useCallback(() => {
12792
+ }, [
12793
+ attemptsRef,
12794
+ cleanup,
12795
+ configRef,
12796
+ dispatch,
12797
+ generationRef,
12798
+ isActiveRef,
12799
+ isPollingRef
12800
+ ]);
12801
+ }
12802
+ function usePollingScheduler(runtime, poll) {
12803
+ const { attemptsRef, configRef, isActiveRef, timeoutRef } = runtime;
12804
+ return useCallback(() => {
12754
12805
  if (!isActiveRef.current) return;
12755
- const pollInterval = configRef.current?.interval ?? DEFAULT_POLL_INTERVAL;
12756
12806
  const doPoll = async () => {
12757
- if (!await poll() && isActiveRef.current) timeoutRef.current = setTimeout(doPoll, pollInterval);
12807
+ if (!await poll() && isActiveRef.current) {
12808
+ const configuredInterval = configRef.current?.interval;
12809
+ const interval = typeof configuredInterval === "function" ? configuredInterval(attemptsRef.current) : configuredInterval ?? DEFAULT_POLL_INTERVAL;
12810
+ timeoutRef.current = setTimeout(doPoll, interval);
12811
+ }
12758
12812
  };
12759
12813
  doPoll();
12760
- }, [poll]);
12814
+ }, [
12815
+ attemptsRef,
12816
+ configRef,
12817
+ isActiveRef,
12818
+ poll,
12819
+ timeoutRef
12820
+ ]);
12821
+ }
12822
+ function usePollingCycle(config, runtime, dispatch) {
12823
+ const cleanup = usePollingCleanup(runtime);
12824
+ const resetState = usePollingReset(runtime, dispatch);
12825
+ const schedulePoll = usePollingScheduler(runtime, usePollingRequest(runtime, dispatch, cleanup));
12826
+ const pollingEnabled = config !== null;
12761
12827
  useEffect(() => {
12762
- if (!config) {
12828
+ if (!pollingEnabled) {
12763
12829
  cleanup();
12764
12830
  dispatch({ type: "polling-went-idle" });
12765
12831
  return;
12766
12832
  }
12767
12833
  resetState();
12768
- isActiveRef.current = true;
12834
+ runtime.isActiveRef.current = true;
12769
12835
  schedulePoll();
12770
12836
  return cleanup;
12771
12837
  }, [
12772
- config,
12773
12838
  cleanup,
12839
+ dispatch,
12840
+ pollingEnabled,
12774
12841
  resetState,
12842
+ config?.restartKey ?? null,
12843
+ runtime.isActiveRef,
12775
12844
  schedulePoll
12776
12845
  ]);
12777
- const retry = useCallback(() => {
12778
- if (!configRef.current) return;
12846
+ return useCallback(() => {
12847
+ if (!runtime.configRef.current) return;
12779
12848
  cleanup();
12780
12849
  resetState();
12781
- isActiveRef.current = true;
12850
+ runtime.isActiveRef.current = true;
12782
12851
  schedulePoll();
12783
12852
  }, [
12784
12853
  cleanup,
12785
12854
  resetState,
12855
+ runtime.configRef,
12856
+ runtime.isActiveRef,
12786
12857
  schedulePoll
12787
12858
  ]);
12859
+ }
12860
+ /**
12861
+ * Polls until the operation completes, fails, times out, or becomes disabled.
12862
+ * Config objects may be rebuilt across renders; change restartKey to begin a
12863
+ * new operation and reset its attempt budget.
12864
+ */
12865
+ function usePolling(config) {
12866
+ const [state, dispatch] = useReducer(pollingReducer, void 0, createInitialPollingState);
12867
+ const retry = usePollingCycle(config, usePollingRuntime(config), dispatch);
12788
12868
  return {
12789
12869
  status: config ? state.tag : "idle",
12790
12870
  result: config ? state.result : null,
@@ -12794,6 +12874,10 @@ function usePolling(config) {
12794
12874
  }
12795
12875
  //#endregion
12796
12876
  //#region ../blocks/src/system/runtime/hooks/useAppointmentCheckoutVerification.ts
12877
+ const APPOINTMENT_CHECKOUT_MAX_ATTEMPTS = 12;
12878
+ function resolveAppointmentCheckoutPollInterval(attempt) {
12879
+ return Math.min(1e3 * 2 ** (attempt - 1), 4e3);
12880
+ }
12797
12881
  const appointmentCheckoutVerificationDeps = {
12798
12882
  useBlockApi,
12799
12883
  usePolling
@@ -12803,16 +12887,25 @@ function useAppointmentCheckoutVerification(config) {
12803
12887
  }
12804
12888
  function useAppointmentCheckoutVerificationWithDeps(config, deps) {
12805
12889
  const api = deps.useBlockApi();
12890
+ const sessionId = config?.sessionId ?? null;
12891
+ const maxAttempts = config?.maxAttempts;
12892
+ const pollInterval = config?.pollInterval;
12806
12893
  const pollingConfig = useMemo(() => {
12807
- if (!config) return null;
12894
+ if (sessionId === null) return null;
12808
12895
  return {
12809
- pollFn: () => api.getAppointmentBookingStatus({ sessionId: config.sessionId }),
12896
+ restartKey: sessionId,
12897
+ pollFn: () => api.getAppointmentBookingStatus({ sessionId }),
12810
12898
  isComplete: (result) => (result.paymentStatus === "completed" || result.paymentStatus === "not_required") && result.appointmentStatus === "confirmed",
12811
12899
  isFailed: (result) => result.paymentStatus === "failed" || result.paymentStatus === "cancelled" || result.paymentStatus === "refunded" || result.appointmentStatus === "cancelled",
12812
- maxAttempts: config.maxAttempts,
12813
- interval: config.pollInterval
12900
+ maxAttempts: maxAttempts ?? APPOINTMENT_CHECKOUT_MAX_ATTEMPTS,
12901
+ interval: pollInterval ?? resolveAppointmentCheckoutPollInterval
12814
12902
  };
12815
- }, [api, config]);
12903
+ }, [
12904
+ api,
12905
+ sessionId,
12906
+ maxAttempts,
12907
+ pollInterval
12908
+ ]);
12816
12909
  const polling = deps.usePolling(pollingConfig);
12817
12910
  return {
12818
12911
  state: resolveAppointmentCheckoutVerificationState({
@@ -12934,7 +13027,7 @@ function ThemedButton({ variant, size, extraClassName, screenReaderSuffix, label
12934
13027
  }
12935
13028
  //#endregion
12936
13029
  //#region ../blocks/src/system/runtime/shared/components/FeedbackMessage.tsx
12937
- function joinClasses(...parts) {
13030
+ function joinClasses$1(...parts) {
12938
13031
  return parts.filter((part) => typeof part === "string" && part.length > 0).join(" ");
12939
13032
  }
12940
13033
  /**
@@ -12953,17 +13046,17 @@ function FeedbackMessage({ tone, treatment = "panel", children, className, id, t
12953
13046
  const shouldWrapBody = Boolean(title || bodyClassName) || treatment === "field-note";
12954
13047
  return /* @__PURE__ */ jsxs("div", {
12955
13048
  id,
12956
- className: joinClasses(className, treatmentClass(treatment)) || void 0,
13049
+ className: joinClasses$1(className, treatmentClass(treatment)) || void 0,
12957
13050
  "data-feedback-tone": tone,
12958
13051
  "data-feedback-treatment": treatment,
12959
13052
  role,
12960
13053
  "aria-live": resolvedLive === "off" ? void 0 : resolvedLive,
12961
13054
  children: [title ? /* @__PURE__ */ jsx("p", {
12962
- className: joinClasses(titleClassName),
13055
+ className: joinClasses$1(titleClassName),
12963
13056
  "data-feedback-title": true,
12964
13057
  children: title
12965
13058
  }) : null, shouldWrapBody ? /* @__PURE__ */ jsx("div", {
12966
- className: joinClasses(bodyClassName),
13059
+ className: joinClasses$1(bodyClassName),
12967
13060
  "data-feedback-body": true,
12968
13061
  children
12969
13062
  }) : children]
@@ -13145,6 +13238,23 @@ const TimeSlotSelector = ({ value, onChange, slots, isLoading, timezone, require
13145
13238
  });
13146
13239
  };
13147
13240
  //#endregion
13241
+ //#region ../blocks/src/system/runtime/shared/components/CheckIcon.tsx
13242
+ function CheckIcon({ className, strokeWidth = 2 }) {
13243
+ return /* @__PURE__ */ jsx("svg", {
13244
+ fill: "none",
13245
+ strokeLinecap: "round",
13246
+ strokeLinejoin: "round",
13247
+ strokeWidth,
13248
+ viewBox: "0 0 24 24",
13249
+ stroke: "currentColor",
13250
+ className,
13251
+ width: "1em",
13252
+ height: "1em",
13253
+ "aria-hidden": "true",
13254
+ children: /* @__PURE__ */ jsx("path", { d: "M5 13l4 4L19 7" })
13255
+ });
13256
+ }
13257
+ //#endregion
13148
13258
  //#region ../blocks/src/system/runtime/shared/components/StepIndicator.tsx
13149
13259
  /**
13150
13260
  * Shared step indicator component for registration wizards.
@@ -13407,11 +13517,18 @@ function isReservedPathSegment(value) {
13407
13517
  function isUnsafePathSegment(segment) {
13408
13518
  return segment.trim().length === 0 || segment !== segment.trim() || isReservedPathSegment(segment) || containsUnsafePathSegmentCharacter(segment);
13409
13519
  }
13410
- ({
13520
+ //#endregion
13521
+ //#region ../media-core/src/fileStorage.ts
13522
+ const FILE_STORAGE_BUCKETS = {
13411
13523
  publicSite: unsafeAsStorageBucketName("media"),
13412
13524
  privateSite: unsafeAsStorageBucketName("site-files-private"),
13413
- temporary: unsafeAsStorageBucketName("temp-uploads")
13414
- }).publicSite;
13525
+ temporary: unsafeAsStorageBucketName("temp-uploads"),
13526
+ siteAssets: unsafeAsStorageBucketName("site-assets"),
13527
+ siteFonts: unsafeAsStorageBucketName("site-fonts"),
13528
+ bookingRequirementDocuments: unsafeAsStorageBucketName("booking-requirement-documents")
13529
+ };
13530
+ FILE_STORAGE_BUCKETS.publicSite, FILE_STORAGE_BUCKETS.siteAssets, FILE_STORAGE_BUCKETS.siteFonts;
13531
+ FILE_STORAGE_BUCKETS.publicSite, FILE_STORAGE_BUCKETS.privateSite, FILE_STORAGE_BUCKETS.temporary, FILE_STORAGE_BUCKETS.siteAssets, FILE_STORAGE_BUCKETS.siteFonts, FILE_STORAGE_BUCKETS.bookingRequirementDocuments;
13415
13532
  function parseStoragePath(value) {
13416
13533
  return joinStoragePathSegments(value.split("/"));
13417
13534
  }
@@ -14128,6 +14245,25 @@ function CheckboxChoice({ label, presentation = "row", className, ...inputProps
14128
14245
  });
14129
14246
  }
14130
14247
  //#endregion
14248
+ //#region ../blocks/src/system/runtime/nodes/booking-form.mailing-list-choice.tsx
14249
+ function BookingMailingListChoice({ booking }) {
14250
+ const id = React.useId();
14251
+ if (!booking.mailingList) return null;
14252
+ return /* @__PURE__ */ jsxs("div", {
14253
+ className: "rb-space-y-2",
14254
+ children: [/* @__PURE__ */ jsx(CheckboxChoice, {
14255
+ id,
14256
+ name: "mailingListOptIn",
14257
+ checked: booking.mailingListOptIn,
14258
+ onChange: (event) => booking.actions.setMailingListOptIn(event.target.checked),
14259
+ label: `Email me news and updates from ${booking.mailingList.siteName}.`
14260
+ }), /* @__PURE__ */ jsx("p", {
14261
+ className: "rb-caption status-muted",
14262
+ children: "Optional. You can unsubscribe at any time."
14263
+ })]
14264
+ });
14265
+ }
14266
+ //#endregion
14131
14267
  //#region ../blocks/src/system/runtime/nodes/booking-form.service-choices.tsx
14132
14268
  function optionCardClassName(isSelected) {
14133
14269
  return `rb-option-card${isSelected ? " rb-option-card--selected" : ""}`;
@@ -14218,6 +14354,72 @@ function ServiceChoiceGrid({ booking, choices }) {
14218
14354
  });
14219
14355
  }
14220
14356
  //#endregion
14357
+ //#region ../blocks/src/system/runtime/nodes/booking-form.submit-actions.tsx
14358
+ function resolvePrimaryActionLabel(isLastStep, requiresPayment) {
14359
+ if (!isLastStep) return "Continue";
14360
+ return requiresPayment ? "Continue to payment" : "Complete";
14361
+ }
14362
+ function formatBookingConfirmationDateTime(booking) {
14363
+ const startAt = booking.currentStep?.id === "datetime-selection" ? booking.availability.selectedSlot?.startAt : void 0;
14364
+ return startAt ? new Intl.DateTimeFormat(void 0, {
14365
+ dateStyle: "medium",
14366
+ timeStyle: "short",
14367
+ timeZone: booking.availability.timezone
14368
+ }).format(new Date(startAt)) : null;
14369
+ }
14370
+ function BookingPaymentConfirmationText({ booking, summary }) {
14371
+ if (!summary) return null;
14372
+ const dateTime = formatBookingConfirmationDateTime(booking);
14373
+ return /* @__PURE__ */ jsxs("p", {
14374
+ className: "ab-text rb-on-surface--muted",
14375
+ children: [
14376
+ summary.serviceTitle,
14377
+ " · ",
14378
+ summary.durationMinutes,
14379
+ " min ·",
14380
+ " ",
14381
+ formatCurrencyAmount(summary.priceAmount, summary.priceCurrency, { decimals: "auto" }),
14382
+ dateTime ? ` · ${dateTime}` : ""
14383
+ ]
14384
+ });
14385
+ }
14386
+ function BookingFormSubmitActions({ booking, onSubmit }) {
14387
+ const currentStepIndex = booking.currentStep?.visibleIndex ?? 0;
14388
+ const isFirstStep = currentStepIndex === 0;
14389
+ const isLastStep = currentStepIndex === booking.steps.length - 1;
14390
+ const isSubmitting = booking.status.tag === "submitting";
14391
+ const paymentSummary = isLastStep && booking.payment.kind === "ok" ? booking.payment.confirmationSummary : null;
14392
+ const handlePrimaryAction = async () => {
14393
+ if ((await booking.actions.next()).ok && isLastStep) await onSubmit();
14394
+ };
14395
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(BookingPaymentConfirmationText, {
14396
+ booking,
14397
+ summary: paymentSummary
14398
+ }), /* @__PURE__ */ jsxs("div", {
14399
+ className: "rb-wizard-actions",
14400
+ children: [!isFirstStep ? /* @__PURE__ */ jsx(ThemedButton, {
14401
+ type: "button",
14402
+ onClick: booking.actions.back,
14403
+ variant: "outline",
14404
+ size: "md",
14405
+ label: "Back"
14406
+ }) : null, /* @__PURE__ */ jsx(ThemedButton, {
14407
+ type: "button",
14408
+ onClick: () => {
14409
+ handlePrimaryAction();
14410
+ },
14411
+ disabled: isSubmitting,
14412
+ variant: "primary",
14413
+ size: "md",
14414
+ label: resolvePrimaryActionLabel(isLastStep, Boolean(paymentSummary)),
14415
+ pending: isSubmitting ? {
14416
+ label: "Submitting...",
14417
+ srLabel: "Submitting"
14418
+ } : void 0
14419
+ })]
14420
+ })] });
14421
+ }
14422
+ //#endregion
14221
14423
  //#region ../blocks/src/system/runtime/nodes/booking-form.default-ui.tsx
14222
14424
  function formatBookingAmount(amount, currency) {
14223
14425
  return formatCurrencyAmount(amount, currency, { decimals: "auto" });
@@ -14226,13 +14428,6 @@ function HeadlessBookingDefaultForm({ booking, onSubmit }) {
14226
14428
  const currentStep = booking.currentStep;
14227
14429
  const errorSummaryId = React.useId();
14228
14430
  const currentStepIndex = currentStep?.visibleIndex ?? 0;
14229
- const isFirstStep = currentStepIndex === 0;
14230
- const isLastStep = currentStepIndex === booking.steps.length - 1;
14231
- const isSubmitting = booking.status.tag === "submitting";
14232
- const handlePrimaryAction = async () => {
14233
- if (!(await booking.actions.next()).ok) return;
14234
- if (isLastStep) await onSubmit();
14235
- };
14236
14431
  if (!currentStep) return /* @__PURE__ */ jsx("div", {
14237
14432
  className: "rb-text-center rb-py-12",
14238
14433
  children: /* @__PURE__ */ jsx("p", {
@@ -14260,28 +14455,9 @@ function HeadlessBookingDefaultForm({ booking, onSubmit }) {
14260
14455
  errors: currentStep.errors,
14261
14456
  id: errorSummaryId
14262
14457
  }),
14263
- /* @__PURE__ */ jsxs("div", {
14264
- className: "rb-wizard-actions",
14265
- children: [!isFirstStep ? /* @__PURE__ */ jsx(ThemedButton, {
14266
- type: "button",
14267
- onClick: booking.actions.back,
14268
- variant: "outline",
14269
- size: "md",
14270
- label: "Back"
14271
- }) : null, /* @__PURE__ */ jsx(ThemedButton, {
14272
- type: "button",
14273
- onClick: () => {
14274
- handlePrimaryAction();
14275
- },
14276
- disabled: isSubmitting,
14277
- variant: "primary",
14278
- size: "md",
14279
- label: isLastStep ? "Complete" : "Continue",
14280
- pending: isSubmitting ? {
14281
- label: "Submitting...",
14282
- srLabel: "Submitting"
14283
- } : void 0
14284
- })]
14458
+ /* @__PURE__ */ jsx(BookingFormSubmitActions, {
14459
+ booking,
14460
+ onSubmit
14285
14461
  }),
14286
14462
  /* @__PURE__ */ jsx(DefaultBookingDiscount, { booking }),
14287
14463
  /* @__PURE__ */ jsx(DefaultBookingFeedback, { booking }),
@@ -14607,12 +14783,17 @@ function PaymentOptionContent({ description, helperText, id, summaryRows, title
14607
14783
  });
14608
14784
  }
14609
14785
  function DefaultDynamicFields({ booking, fields }) {
14786
+ const lastContactIndex = fields.reduce((last, field, index) => [
14787
+ "name",
14788
+ "email",
14789
+ "phone"
14790
+ ].includes(field.id) ? index : last, -1);
14610
14791
  return /* @__PURE__ */ jsx("div", {
14611
14792
  className: "rb-space-y-6",
14612
- children: fields.map((field) => /* @__PURE__ */ jsx(DefaultDynamicField, {
14793
+ children: fields.map((field, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [/* @__PURE__ */ jsx(DefaultDynamicField, {
14613
14794
  booking,
14614
14795
  field
14615
- }, field.id))
14796
+ }), index === lastContactIndex && booking.mailingList ? /* @__PURE__ */ jsx(BookingMailingListChoice, { booking }) : null] }, field.id))
14616
14797
  });
14617
14798
  }
14618
14799
  function DefaultDynamicField({ booking, field }) {
@@ -14948,9 +15129,343 @@ function consumeSearchParams(paramNames) {
14948
15129
  return values;
14949
15130
  }
14950
15131
  //#endregion
15132
+ //#region ../blocks/src/system/runtime/shared/components/StateIcon.tsx
15133
+ /**
15134
+ * Circular icon wrapper for terminal state screens (success, error, waitlist, etc.).
15135
+ *
15136
+ * Layout is provided by shared `rb-state-icon` CSS; color variants are
15137
+ * block-scoped by the owning registration surface.
15138
+ */
15139
+ function StateIcon({ variant, children }) {
15140
+ return /* @__PURE__ */ jsx("div", {
15141
+ className: `rb-state-icon rb-state-icon--${variant}`,
15142
+ "aria-hidden": "true",
15143
+ children
15144
+ });
15145
+ }
15146
+ //#endregion
15147
+ //#region ../blocks/src/system/runtime/shared/components/TerminalPanel.tsx
15148
+ function joinClasses(...parts) {
15149
+ return parts.filter((part) => typeof part === "string" && part.length > 0).join(" ");
15150
+ }
15151
+ function TerminalPanel({ tone, title, titleAs: Title = "h3", body, secondaryBody, icon, actions, className, titleClassName, bodyClassName, secondaryBodyClassName, iconClassName, actionsClassName, role, live }) {
15152
+ const resolvedRole = role ?? (tone === "error" ? "alert" : "status");
15153
+ const resolvedLive = live ?? (resolvedRole === "alert" ? "assertive" : "polite");
15154
+ return /* @__PURE__ */ jsxs("div", {
15155
+ className,
15156
+ "data-terminal-panel": true,
15157
+ "data-terminal-tone": tone,
15158
+ role: resolvedRole,
15159
+ "aria-live": resolvedLive === "off" ? void 0 : resolvedLive,
15160
+ children: [
15161
+ icon ? /* @__PURE__ */ jsx("div", {
15162
+ className: joinClasses(iconClassName),
15163
+ "data-terminal-icon": true,
15164
+ children: icon
15165
+ }) : null,
15166
+ /* @__PURE__ */ jsx(Title, {
15167
+ className: joinClasses(titleClassName),
15168
+ "data-terminal-title": true,
15169
+ children: title
15170
+ }),
15171
+ body ? /* @__PURE__ */ jsx("div", {
15172
+ className: joinClasses(bodyClassName),
15173
+ "data-terminal-body": true,
15174
+ children: body
15175
+ }) : null,
15176
+ actions ? /* @__PURE__ */ jsx("div", {
15177
+ className: joinClasses(actionsClassName),
15178
+ "data-terminal-actions": true,
15179
+ children: actions
15180
+ }) : null,
15181
+ secondaryBody ? /* @__PURE__ */ jsx("div", {
15182
+ className: joinClasses(secondaryBodyClassName),
15183
+ "data-terminal-secondary-body": true,
15184
+ children: secondaryBody
15185
+ }) : null
15186
+ ]
15187
+ });
15188
+ }
15189
+ //#endregion
15190
+ //#region ../blocks/src/system/runtime/shared/utils/demoPortalMagicLink.ts
15191
+ const CUSTOMER_PORTAL_PATH = "/portal";
15192
+ function buildPortalCallbackUrl(origin, redirectTo) {
15193
+ const url = new URL("/api/portal/callback", origin);
15194
+ url.searchParams.set("redirect_to", redirectTo);
15195
+ return url.toString();
15196
+ }
15197
+ async function requestDemoPortalMagicLink(input) {
15198
+ const email = normalizeDemoBookingEmail(input.email);
15199
+ const pass = getDemoBookingPass(email);
15200
+ const request = {
15201
+ email,
15202
+ redirectUrl: input.redirectUrl,
15203
+ ...pass ? { demoBookingPass: pass } : {}
15204
+ };
15205
+ try {
15206
+ const response = await input.send(request);
15207
+ if ("kind" in response) return {
15208
+ kind: "refused",
15209
+ message: response.message
15210
+ };
15211
+ return "demoSignInUrl" in response ? {
15212
+ kind: "demo_sign_in",
15213
+ url: response.demoSignInUrl
15214
+ } : { kind: "email_sent" };
15215
+ } catch (error) {
15216
+ if (error instanceof BlockApiError && error.tag === "demo_email_not_booked_here") return {
15217
+ kind: "refused",
15218
+ message: error.message
15219
+ };
15220
+ throw error;
15221
+ }
15222
+ }
15223
+ //#endregion
15224
+ //#region ../blocks/src/system/runtime/shared/components/DemoBookingPortalAccess.tsx
15225
+ const SUPPRESSED_CONFIRMATION_NOTE = "This is a demo, so we haven’t sent a confirmation email. You can still see your booking in the customer portal.";
15226
+ function BookingConfirmation(props) {
15227
+ const content = renderConfirmationMessage((props.demoEmailSuppressed ? [props.copy.message] : [props.copy.message, props.copy.defaultEmailSentence ?? ""]).filter((part) => part.trim().length > 0).join(" "), props.messagePresentation);
15228
+ if (!props.demoEmailSuppressed) return content;
15229
+ return /* @__PURE__ */ jsxs(Fragment, { children: [content, /* @__PURE__ */ jsx(DemoBookingPortalAccess, {
15230
+ email: props.email,
15231
+ noteClassName: props.noteClassName,
15232
+ showConfirmationNote: props.showConfirmationNote
15233
+ })] });
15234
+ }
15235
+ function DemoBookingPortalAccess(props) {
15236
+ const { state, openPortal } = useDemoBookingPortalAccess(props.email);
15237
+ return /* @__PURE__ */ jsxs("div", {
15238
+ className: "rb-mt-4 rb-flex rb-flex-col rb-items-start rb-gap-3",
15239
+ "data-testid": "demo-booking-portal-access",
15240
+ children: [
15241
+ props.showConfirmationNote === false ? null : /* @__PURE__ */ jsx("p", {
15242
+ className: props.noteClassName ?? "ab-text",
15243
+ children: SUPPRESSED_CONFIRMATION_NOTE
15244
+ }),
15245
+ /* @__PURE__ */ jsx(ThemedButton, {
15246
+ type: "button",
15247
+ variant: "default",
15248
+ size: "md",
15249
+ label: state.tag === "opening" ? "Opening…" : "Open the customer portal",
15250
+ disabled: state.tag === "opening",
15251
+ onClick: openPortal
15252
+ }),
15253
+ state.tag === "refused" ? /* @__PURE__ */ jsx("p", {
15254
+ role: "alert",
15255
+ children: state.message
15256
+ }) : null,
15257
+ state.tag === "error" ? /* @__PURE__ */ jsx("p", {
15258
+ role: "alert",
15259
+ children: state.message
15260
+ }) : null
15261
+ ]
15262
+ });
15263
+ }
15264
+ function renderConfirmationMessage(message, presentation) {
15265
+ if (!message) return null;
15266
+ switch (presentation.kind) {
15267
+ case "paragraph": return /* @__PURE__ */ jsx("p", {
15268
+ className: presentation.className,
15269
+ children: message
15270
+ });
15271
+ case "plain": return message;
15272
+ }
15273
+ }
15274
+ function useDemoBookingPortalAccess(email) {
15275
+ const api = useBlockApi();
15276
+ const [state, setState] = React.useState({ tag: "idle" });
15277
+ const openPortal = async () => {
15278
+ if (state.tag === "opening") return;
15279
+ if (!email) {
15280
+ setState({
15281
+ tag: "error",
15282
+ message: "We couldn’t open the customer portal. Please try again."
15283
+ });
15284
+ return;
15285
+ }
15286
+ setState({ tag: "opening" });
15287
+ try {
15288
+ const result = await requestDemoPortalMagicLink({
15289
+ email,
15290
+ redirectUrl: buildPortalCallbackUrl(window.location.origin, CUSTOMER_PORTAL_PATH),
15291
+ send: (request) => api.sendMagicLink(request)
15292
+ });
15293
+ switch (result.kind) {
15294
+ case "demo_sign_in":
15295
+ window.location.assign(result.url);
15296
+ return;
15297
+ case "refused":
15298
+ setState({
15299
+ tag: "refused",
15300
+ message: result.message
15301
+ });
15302
+ return;
15303
+ case "email_sent":
15304
+ setState({ tag: "idle" });
15305
+ return;
15306
+ }
15307
+ } catch (error) {
15308
+ setState(handlePortalAccessError(error));
15309
+ }
15310
+ };
15311
+ return {
15312
+ state,
15313
+ openPortal
15314
+ };
15315
+ }
15316
+ function handlePortalAccessError(error) {
15317
+ if (error instanceof BlockApiError && error.tag === "demo_email_not_booked_here") return {
15318
+ tag: "refused",
15319
+ message: error.message
15320
+ };
15321
+ return error instanceof BlockApiError ? {
15322
+ tag: "error",
15323
+ message: error.message
15324
+ } : {
15325
+ tag: "error",
15326
+ message: "We couldn’t open the customer portal. Please try again."
15327
+ };
15328
+ }
15329
+ //#endregion
15330
+ //#region ../blocks/src/system/runtime/components/booking/SuccessMessage.tsx
15331
+ const SuccessMessage = ({ copy, resourceName, className, demoEmailSuppressed = false, customerEmail = null }) => {
15332
+ return /* @__PURE__ */ jsx(TerminalPanel, {
15333
+ tone: "success",
15334
+ title: "Booking confirmed",
15335
+ icon: /* @__PURE__ */ jsx(StateIcon, {
15336
+ variant: "success",
15337
+ children: /* @__PURE__ */ jsx(CheckIcon, { strokeWidth: 3 })
15338
+ }),
15339
+ body: /* @__PURE__ */ jsx(BookingConfirmation, {
15340
+ demoEmailSuppressed,
15341
+ email: customerEmail,
15342
+ copy,
15343
+ messagePresentation: {
15344
+ kind: "paragraph",
15345
+ className: "ab-text"
15346
+ },
15347
+ noteClassName: "ab-text"
15348
+ }),
15349
+ secondaryBody: resourceName ? /* @__PURE__ */ jsxs("p", {
15350
+ className: "ab-text rb-on-surface--muted",
15351
+ children: ["Practitioner: ", resourceName]
15352
+ }) : null,
15353
+ className: ["ab-center", className ?? ""].join(" ").trim(),
15354
+ titleClassName: "ab-terminal-title",
15355
+ role: "alert",
15356
+ live: "polite"
15357
+ });
15358
+ };
15359
+ //#endregion
15360
+ //#region ../blocks/src/system/runtime/shared/mailingListSignupCopy.ts
15361
+ const MAILING_LIST_CONFIRMATION_MESSAGE = "Please check your inbox to confirm your signup.";
15362
+ function getBookingMailingListNoteCopy(note, context) {
15363
+ if (note === "confirmation_required") return {
15364
+ title: MAILING_LIST_CONFIRMATION_MESSAGE,
15365
+ detail: context === "booking" ? "This is separate from your booking confirmation." : null
15366
+ };
15367
+ return {
15368
+ title: "We couldn’t confirm your mailing-list signup.",
15369
+ detail: context === "booking" ? "This does not affect your booking." : null
15370
+ };
15371
+ }
15372
+ //#endregion
15373
+ //#region ../blocks/src/system/runtime/shared/components/BookingMailingListNote.tsx
15374
+ function BookingMailingListNote(props) {
15375
+ const copy = getBookingMailingListNoteCopy(props.note, props.context);
15376
+ return /* @__PURE__ */ jsxs("div", {
15377
+ role: "status",
15378
+ className: props.className,
15379
+ children: [/* @__PURE__ */ jsx("p", { children: copy.title }), copy.detail ? /* @__PURE__ */ jsx("p", { children: copy.detail }) : null]
15380
+ });
15381
+ }
15382
+ //#endregion
15383
+ //#region ../blocks/src/system/runtime/nodes/booking-form.checkout-return-context.ts
15384
+ function storageKey(sessionId) {
15385
+ return `riverbank:booking:mailing-list:${sessionId}`;
15386
+ }
15387
+ function saveAppointmentCheckoutReturnContext(sessionId, context) {
15388
+ if (!context.customerEmail && !context.mailingListNote) return;
15389
+ try {
15390
+ window.sessionStorage.setItem(storageKey(sessionId), JSON.stringify(context));
15391
+ } catch {}
15392
+ }
15393
+ function readAppointmentCheckoutReturnContext(sessionId) {
15394
+ try {
15395
+ const stored = window.sessionStorage.getItem(storageKey(sessionId));
15396
+ if (!stored) return null;
15397
+ return parseContext(stored);
15398
+ } catch {
15399
+ return null;
15400
+ }
15401
+ }
15402
+ function parseContext(value) {
15403
+ try {
15404
+ const parsed = JSON.parse(value);
15405
+ return isContext(parsed) ? parsed : null;
15406
+ } catch {
15407
+ return value === "confirmation_required" || value === "not_confirmed" ? {
15408
+ customerEmail: null,
15409
+ mailingListNote: value
15410
+ } : null;
15411
+ }
15412
+ }
15413
+ function isContext(value) {
15414
+ if (!isRecord$2(value)) return false;
15415
+ return (typeof value.customerEmail === "string" || value.customerEmail === null) && (value.mailingListNote === null || value.mailingListNote === "confirmation_required" || value.mailingListNote === "not_confirmed");
15416
+ }
15417
+ function isRecord$2(value) {
15418
+ return typeof value === "object" && value !== null && !Array.isArray(value);
15419
+ }
15420
+ //#endregion
15421
+ //#region ../blocks/src/system/runtime/nodes/booking-form.completion.tsx
15422
+ function BookingFormCompletion({ resourceName, successMessage, redirectState, localNote, customerEmail, demoEmailSuppressed = false }) {
15423
+ const returnContext = redirectState.kind === "success" ? readAppointmentCheckoutReturnContext(redirectState.sessionId) : null;
15424
+ const note = redirectState.kind === "success" ? returnContext?.mailingListNote ?? null : localNote;
15425
+ const confirmedEmail = returnContext?.customerEmail ?? customerEmail;
15426
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SuccessMessage, {
15427
+ copy: getBookingSuccessCopy(successMessage),
15428
+ resourceName,
15429
+ demoEmailSuppressed,
15430
+ customerEmail: confirmedEmail
15431
+ }), note ? /* @__PURE__ */ jsx(BookingMailingListNote, {
15432
+ note,
15433
+ context: "booking",
15434
+ className: "rb-mt-4"
15435
+ }) : null] });
15436
+ }
15437
+ //#endregion
15438
+ //#region ../blocks/src/system/runtime/nodes/booking-form.submit-handler.ts
15439
+ function appendRebookFlag(url, enabled) {
15440
+ if (!enabled) return url;
15441
+ const nextUrl = new URL(url);
15442
+ nextUrl.searchParams.set("rebook", "1");
15443
+ return nextUrl.toString();
15444
+ }
15445
+ function createBookingFormSubmitHandler(input) {
15446
+ return async () => {
15447
+ const { successUrl, cancelUrl } = buildCheckoutReturnUrls("booking", input.bookingAnchorId);
15448
+ const result = await input.booking.actions.submit({
15449
+ redirect: "manual",
15450
+ successUrl: appendRebookFlag(successUrl, input.isPortalRebook),
15451
+ cancelUrl: appendRebookFlag(cancelUrl, input.isPortalRebook)
15452
+ });
15453
+ if (!result.ok) return;
15454
+ storeDemoBookingPassIfAvailable(result.outcome.customerEmail, result.outcome.demoBookingPass);
15455
+ if (result.outcome.kind === "checkout_redirect") {
15456
+ saveAppointmentCheckoutReturnContext(result.outcome.sessionId, {
15457
+ customerEmail: result.outcome.customerEmail,
15458
+ mailingListNote: result.outcome.mailingListSignupNote ?? null
15459
+ });
15460
+ window.location.href = result.outcome.checkoutUrl;
15461
+ return;
15462
+ }
15463
+ input.setLocalMailingListNote(result.outcome.mailingListSignupNote ?? null);
15464
+ input.setLocalCustomerEmail(result.outcome.customerEmail);
15465
+ };
15466
+ }
15467
+ //#endregion
14951
15468
  //#region ../blocks/src/system/runtime/nodes/booking-form.client.tsx
14952
- const PORTAL_REBOOK_QUERY_PARAM = "rebook";
14953
- const PORTAL_REBOOK_QUERY_VALUE = "1";
14954
15469
  const REBOOK_COMPLETION_MODE_VERIFIED_CHECKOUT = "verified_checkout";
14955
15470
  const REBOOK_COMPLETION_MODE_BYPASSED = "bypassed";
14956
15471
  function getBookingRedirectLocationSnapshot() {
@@ -14963,12 +15478,6 @@ function getBookingRedirectLocationSnapshot() {
14963
15478
  hash: window.location.hash
14964
15479
  };
14965
15480
  }
14966
- function appendRebookFlag(url, enabled) {
14967
- if (!enabled) return url;
14968
- const nextUrl = new URL(url);
14969
- nextUrl.searchParams.set(PORTAL_REBOOK_QUERY_PARAM, PORTAL_REBOOK_QUERY_VALUE);
14970
- return nextUrl.toString();
14971
- }
14972
15481
  /**
14973
15482
  * Themed surface container for every booking view state (wizard, success,
14974
15483
  * verifying). Styled by the shared registration-surface layer.
@@ -14991,12 +15500,17 @@ const BookingFormClient$1 = ({ siteId: siteIdProp, render }) => {
14991
15500
  const isPortalRebook = render.hydration.rebookContext?.kind === "portal_rebook";
14992
15501
  const hasLoggedRebookCompletionRef = useRef(false);
14993
15502
  const [redirectState] = useState(() => getBookingRedirectStateFromLocation(getBookingRedirectLocationSnapshot()));
15503
+ const [localMailingListNote, setLocalMailingListNote] = useState(null);
15504
+ const [localCustomerEmail, setLocalCustomerEmail] = useState(null);
14994
15505
  const showSpamProtection = render.hydration.spamProtectionEnabled ?? isSpamProtectionEnabled();
14995
15506
  const api = useBlockApi();
14996
15507
  const hasPortalAuth = api.config.auth.type === "bearer" || api.config.authOverrides?.portal?.type === "bearer";
15508
+ const formId = render.hydration.formId ?? form?.id ?? "booking-form";
14997
15509
  const booking = useHeadlessBookingFlow({
15510
+ mailingList: render.hydration.mailingList,
15511
+ siteName: render.hydration.siteName,
14998
15512
  siteId,
14999
- formId: render.hydration.formId ?? form?.id ?? "booking-form",
15513
+ formId,
15000
15514
  form,
15001
15515
  services,
15002
15516
  serviceCategories: render.hydration.serviceCategories,
@@ -15066,22 +15580,23 @@ const BookingFormClient$1 = ({ siteId: siteIdProp, render }) => {
15066
15580
  children: render.display.message ?? "Booking form not found. Please check your configuration."
15067
15581
  })
15068
15582
  });
15069
- const handleComplete = async () => {
15070
- const { successUrl, cancelUrl } = buildCheckoutReturnUrls("booking", bookingAnchorId);
15071
- const result = await booking.actions.submit({
15072
- redirect: "manual",
15073
- successUrl: appendRebookFlag(successUrl, isPortalRebook),
15074
- cancelUrl: appendRebookFlag(cancelUrl, isPortalRebook)
15075
- });
15076
- if (!result.ok) return;
15077
- if (result.outcome.kind === "checkout_redirect") window.location.href = result.outcome.checkoutUrl;
15078
- };
15583
+ const handleComplete = createBookingFormSubmitHandler({
15584
+ booking,
15585
+ bookingAnchorId,
15586
+ isPortalRebook,
15587
+ setLocalMailingListNote,
15588
+ setLocalCustomerEmail
15589
+ });
15079
15590
  if (viewState.kind === "success") return /* @__PURE__ */ jsx(BookingSurface, {
15080
15591
  id: bookingAnchorId,
15081
15592
  className: render.display.className,
15082
- children: /* @__PURE__ */ jsx(SuccessMessage, {
15083
- message: getBookingSuccessMessage(render.display.successMessage),
15084
- resourceName: viewState.resourceName
15593
+ children: /* @__PURE__ */ jsx(BookingFormCompletion, {
15594
+ successMessage: render.display.successMessage,
15595
+ resourceName: viewState.resourceName,
15596
+ redirectState,
15597
+ localNote: localMailingListNote,
15598
+ customerEmail: localCustomerEmail,
15599
+ demoEmailSuppressed: render.hydration.demoEmailSuppressed
15085
15600
  })
15086
15601
  });
15087
15602
  if (viewState.kind === "verifying") return /* @__PURE__ */ jsx(BookingSurface, {
@@ -15097,6 +15612,25 @@ const BookingFormClient$1 = ({ siteId: siteIdProp, render }) => {
15097
15612
  })
15098
15613
  })
15099
15614
  });
15615
+ if (viewState.kind === "timeout") return /* @__PURE__ */ jsxs(BookingSurface, {
15616
+ id: bookingAnchorId,
15617
+ className: render.display.className,
15618
+ children: [/* @__PURE__ */ jsx(FeedbackMessage, {
15619
+ tone: "info",
15620
+ className: "alert alert-info",
15621
+ role: "status",
15622
+ children: /* @__PURE__ */ jsx("p", {
15623
+ className: "ab-text",
15624
+ children: viewState.message
15625
+ })
15626
+ }), /* @__PURE__ */ jsx(ThemedButton, {
15627
+ type: "button",
15628
+ variant: "primary",
15629
+ size: "md",
15630
+ label: "Check again",
15631
+ onClick: verification.retry
15632
+ })]
15633
+ });
15100
15634
  return /* @__PURE__ */ jsxs(BookingSurface, {
15101
15635
  id: bookingAnchorId,
15102
15636
  className: render.display.className,
@@ -15157,7 +15691,7 @@ function recoverRegistrationError(action, handlers) {
15157
15691
  switch (action) {
15158
15692
  case "none": return;
15159
15693
  case "portal":
15160
- window.location.assign("/portal");
15694
+ window.location.assign(CUSTOMER_PORTAL_PATH);
15161
15695
  return;
15162
15696
  case "event":
15163
15697
  window.location.assign(window.location.pathname);
@@ -15190,7 +15724,8 @@ function createInitialRegistrationFormData() {
15190
15724
  email: "",
15191
15725
  phone: "",
15192
15726
  notes: "",
15193
- consentAccepted: false
15727
+ consentAccepted: false,
15728
+ mailingListOptIn: false
15194
15729
  };
15195
15730
  }
15196
15731
  function validateFormData(formData, requiresConsent = false) {
@@ -15821,6 +16356,10 @@ const eventRegistrationErrors = {
15821
16356
  message: "The payment options for this event have changed. Please check the latest options before continuing.",
15822
16357
  action: "payment-options"
15823
16358
  },
16359
+ verificationFailed: {
16360
+ message: "We couldn’t confirm this request came from a person. Please refresh the page and try again.",
16361
+ action: "none"
16362
+ },
15824
16363
  idempotencyConflict: {
15825
16364
  message: "You’ve already started booking this event. Please finish in the other tab if it’s still open, or check your booking status before starting again.",
15826
16365
  action: "portal"
@@ -16008,11 +16547,50 @@ function useResolvedWaitlistClaim(deps, credential) {
16008
16547
  * ```
16009
16548
  */
16010
16549
  const paymentVerificationDeps = { useBlockApi };
16550
+ function resolvePaymentPollingTarget(config) {
16551
+ const reference = config.reference;
16552
+ return reference.scope === "occurrence" ? {
16553
+ key: `occurrence:${reference.attendeeId}`,
16554
+ reference
16555
+ } : {
16556
+ key: `wholeSeries:${reference.registrationId}`,
16557
+ reference
16558
+ };
16559
+ }
16560
+ function createPaymentPollingConfig(api, settings) {
16561
+ if (settings === null) return null;
16562
+ const target = resolvePaymentPollingTarget(settings);
16563
+ return {
16564
+ restartKey: target.key,
16565
+ pollFn: () => api.getEventRegistrationStatus(target.reference),
16566
+ isComplete: (result) => result.paymentStatus === "completed" || result.paymentStatus === "not_required",
16567
+ isFailed: (result) => result.paymentStatus === "failed" || result.paymentStatus === "refunded",
16568
+ maxAttempts: settings.maxAttempts,
16569
+ interval: settings.pollInterval
16570
+ };
16571
+ }
16572
+ function getPaymentVerificationError(polling, paymentStatus) {
16573
+ if (polling.status === "timeout") return "Could not verify payment. If you were charged, please contact support.";
16574
+ if (polling.status === "failed" && paymentStatus !== null) return paymentStatus === "refunded" ? "Payment was refunded. Please contact support." : "Payment was declined. Please try again.";
16575
+ return polling.error?.message ?? null;
16576
+ }
16577
+ function mapPaymentVerificationResult(polling) {
16578
+ const paymentStatus = polling.result?.paymentStatus ?? null;
16579
+ return {
16580
+ status: polling.status,
16581
+ paymentStatus,
16582
+ attendeeStatus: polling.result?.attendeeStatus ?? null,
16583
+ waitlistPosition: polling.result?.waitlistPosition ?? null,
16584
+ error: getPaymentVerificationError(polling, paymentStatus),
16585
+ retry: polling.retry
16586
+ };
16587
+ }
16011
16588
  /**
16012
16589
  * Hook for polling payment status after Stripe redirects.
16013
16590
  *
16014
16591
  * Pass config to start polling, or null to stop/idle.
16015
- * The hook handles cleanup on unmount and config changes.
16592
+ * The hook handles cleanup on unmount and starts a new cycle when the status
16593
+ * reference changes.
16016
16594
  *
16017
16595
  * @param config - Configuration for polling, or null to stop
16018
16596
  * @returns Verification result with status, data, and retry function
@@ -16021,30 +16599,7 @@ function usePaymentVerification(config) {
16021
16599
  return usePaymentVerificationWithDeps(config, paymentVerificationDeps);
16022
16600
  }
16023
16601
  function usePaymentVerificationWithDeps(config, deps) {
16024
- const api = deps.useBlockApi();
16025
- const polling = usePolling(useMemo(() => {
16026
- if (!config) return null;
16027
- return {
16028
- pollFn: () => api.getEventRegistrationStatus(config.reference),
16029
- isComplete: (result) => result.paymentStatus === "completed" || result.paymentStatus === "not_required",
16030
- isFailed: (result) => result.paymentStatus === "failed" || result.paymentStatus === "refunded",
16031
- maxAttempts: config.maxAttempts,
16032
- interval: config.pollInterval
16033
- };
16034
- }, [api, config]));
16035
- const paymentStatus = polling.result?.paymentStatus ?? null;
16036
- let errorMessage = null;
16037
- if (polling.status === "timeout") errorMessage = "Could not verify payment. If you were charged, please contact support.";
16038
- else if (polling.status === "failed" && paymentStatus) errorMessage = paymentStatus === "refunded" ? "Payment was refunded. Please contact support." : "Payment was declined. Please try again.";
16039
- else if (polling.error) errorMessage = polling.error.message;
16040
- return {
16041
- status: polling.status,
16042
- paymentStatus,
16043
- attendeeStatus: polling.result?.attendeeStatus ?? null,
16044
- waitlistPosition: polling.result?.waitlistPosition ?? null,
16045
- error: errorMessage,
16046
- retry: polling.retry
16047
- };
16602
+ return mapPaymentVerificationResult(usePolling(createPaymentPollingConfig(deps.useBlockApi(), config)));
16048
16603
  }
16049
16604
  //#endregion
16050
16605
  //#region ../blocks/src/system/runtime/nodes/event-registration/constants.ts
@@ -16314,7 +16869,10 @@ async function handleCheckoutReturn(options, deps, returnContextRef) {
16314
16869
  }
16315
16870
  const { checkoutAttemptId } = command;
16316
16871
  const pending = deps.getPendingRegistration(siteId, checkoutAttemptId);
16317
- returnContextRef.current = { checkoutAttemptId };
16872
+ returnContextRef.current = {
16873
+ checkoutAttemptId,
16874
+ mailingListSignupNote: pending?.mailingListSignupNote
16875
+ };
16318
16876
  if (pending) restorePendingPresentation(options, pending);
16319
16877
  options.setStep("verifying-payment");
16320
16878
  try {
@@ -16335,7 +16893,10 @@ function completeVerifiedRegistration(options, deps, returnContext) {
16335
16893
  const siteId = options.api.config.siteId;
16336
16894
  const checkoutAttemptId = returnContext?.checkoutAttemptId;
16337
16895
  if (siteId && checkoutAttemptId) deps.clearPendingRegistration(siteId, checkoutAttemptId);
16338
- options.setRegistrationResult({ status: "confirmed" });
16896
+ options.setRegistrationResult({
16897
+ status: "confirmed",
16898
+ mailingListSignupNote: returnContext?.mailingListSignupNote
16899
+ });
16339
16900
  options.setStep("success");
16340
16901
  }
16341
16902
  function useEventRegistrationStripeReturnWithDeps(options, deps) {
@@ -16408,20 +16969,12 @@ function registrationErrorPresentation(error) {
16408
16969
  }
16409
16970
  //#endregion
16410
16971
  //#region ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.ts
16411
- function createClientCommandId(cryptoSource = {
16412
- randomUUID: globalThis.crypto.randomUUID?.bind(globalThis.crypto),
16413
- getRandomValues: (bytes) => globalThis.crypto.getRandomValues(bytes)
16414
- }) {
16415
- if (cryptoSource.randomUUID) return cryptoSource.randomUUID();
16416
- const bytes = cryptoSource.getRandomValues(/* @__PURE__ */ new Uint8Array(16));
16417
- bytes[6] = (bytes[6] ?? 0) & 15 | 64;
16418
- bytes[8] = (bytes[8] ?? 0) & 63 | 128;
16419
- const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0"));
16420
- return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10).join("")}`;
16972
+ function wantsMailingListSignup(options) {
16973
+ return options.mailingListSignup !== null && options.formData.mailingListOptIn === true;
16421
16974
  }
16422
16975
  const eventRegistrationSubmitDeps = {
16423
16976
  savePendingRegistration,
16424
- createClientCommandId
16977
+ createClientCommandId: generateUuidV4
16425
16978
  };
16426
16979
  function useEventRegistrationSubmit(options) {
16427
16980
  return useEventRegistrationSubmitWithDeps(options, eventRegistrationSubmitDeps);
@@ -16501,11 +17054,13 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
16501
17054
  };
16502
17055
  }
16503
17056
  async function completeRegistrationSubmission(options, deps, prepared, result, submitOptions) {
17057
+ if (result.demoBookingPass) storeDemoBookingPass(options.formData.email, result.demoBookingPass);
16504
17058
  switch (result.kind) {
16505
17059
  case "paymentStatusRequired":
16506
17060
  options.setPaymentStatusRecovery({
16507
17061
  kind: "ready",
16508
- subject: result.subject
17062
+ subject: result.subject,
17063
+ mailingListSignupNote: result.mailingListSignupNote
16509
17064
  });
16510
17065
  options.setStep("payment-status");
16511
17066
  return {
@@ -16514,14 +17069,16 @@ async function completeRegistrationSubmission(options, deps, prepared, result, s
16514
17069
  };
16515
17070
  case "checkoutRequired":
16516
17071
  options.setPendingRegistrationReference(result.reference);
16517
- savePendingCheckout(options, deps, prepared, result.submissionId, result.reference);
17072
+ savePendingCheckout(options, deps, prepared, result.submissionId, result.reference, result.mailingListSignupNote);
16518
17073
  options.setStep("redirecting");
16519
17074
  return redirectToCheckout(result.checkoutUrl, submitOptions);
16520
17075
  case "waitlisted":
16521
17076
  options.setRegistrationResult({
16522
17077
  status: "waitlist",
16523
17078
  title: "Added to waitlist",
16524
- message: result.waitlist.message
17079
+ message: result.waitlist.message,
17080
+ emailFollowupMessage: result.waitlist.emailFollowupMessage,
17081
+ mailingListSignupNote: result.mailingListSignupNote
16525
17082
  });
16526
17083
  break;
16527
17084
  case "bookingComplete":
@@ -16529,7 +17086,8 @@ async function completeRegistrationSubmission(options, deps, prepared, result, s
16529
17086
  options.setPendingRegistrationReference(result.reference);
16530
17087
  options.setRegistrationResult({
16531
17088
  status: "confirmed",
16532
- message: result.summary.paymentMethod === "pass" ? result.summary.message : void 0
17089
+ message: result.summary.paymentMethod === "pass" ? result.summary.message : void 0,
17090
+ mailingListSignupNote: result.mailingListSignupNote
16533
17091
  });
16534
17092
  break;
16535
17093
  }
@@ -16588,7 +17146,7 @@ function resolveSelectionSnapshot(method, passId, membershipId, bundleProductId,
16588
17146
  if (method === "free") return { method };
16589
17147
  throw new Error("Choose an available payment option.");
16590
17148
  }
16591
- function savePendingCheckout(options, deps, prepared, checkoutAttemptId, reference) {
17149
+ function savePendingCheckout(options, deps, prepared, checkoutAttemptId, reference, mailingListSignupNote) {
16592
17150
  const siteId = options.api.config.siteId;
16593
17151
  if (!siteId) return;
16594
17152
  deps.savePendingRegistration(siteId, checkoutAttemptId, {
@@ -16597,7 +17155,8 @@ function savePendingCheckout(options, deps, prepared, checkoutAttemptId, referen
16597
17155
  ticketSelections: prepared.ticketSelections,
16598
17156
  selectedEventId: options.registrationTarget?.selectedEventId ?? null,
16599
17157
  selectedAttendanceMode: options.selectedAttendanceMode,
16600
- paymentSelection: prepared.selectionSnapshot
17158
+ paymentSelection: prepared.selectionSnapshot,
17159
+ mailingListSignupNote
16601
17160
  });
16602
17161
  }
16603
17162
  function redirectToCheckout(checkoutUrl, submitOptions) {
@@ -16611,7 +17170,7 @@ function redirectToCheckout(checkoutUrl, submitOptions) {
16611
17170
  };
16612
17171
  }
16613
17172
  function registrationRequestIntentKey(request) {
16614
- const { registrationCommandId: _command, altchaSolution: _proof, checkout, ...intent } = request;
17173
+ const { registrationCommandId: _command, altchaSolution: _proof, mailingListOptIn: _marketingConsent, checkout, ...intent } = request;
16615
17174
  return JSON.stringify({
16616
17175
  ...intent,
16617
17176
  checkout: checkout ? {
@@ -16636,6 +17195,7 @@ function buildRegistrationRequest(options, prepared, method, passId, membershipI
16636
17195
  phone: options.formData.phone.trim() || void 0,
16637
17196
  notes: options.formData.notes.trim() || void 0,
16638
17197
  consentAccepted: options.formData.consentAccepted,
17198
+ mailingListOptIn: wantsMailingListSignup(options),
16639
17199
  altchaSolution: options.altchaSolution,
16640
17200
  paymentMethod: method,
16641
17201
  customerPassId: method === "pass" ? passId : void 0,
@@ -17629,13 +18189,17 @@ function isCheckableRecovery(state) {
17629
18189
  function assistanceRequired(recovery) {
17630
18190
  return {
17631
18191
  kind: "assistanceRequired",
17632
- subject: recovery.subject
18192
+ subject: recovery.subject,
18193
+ mailingListSignupNote: recovery.mailingListSignupNote
17633
18194
  };
17634
18195
  }
17635
18196
  function applyStatusOutcome(outcome, recovery, setters, setRecovery) {
17636
18197
  if (outcome.kind === "resolved") {
17637
18198
  setters.setPendingRegistrationReference(outcome.reference);
17638
- setters.setRegistrationResult({ status: "confirmed" });
18199
+ setters.setRegistrationResult({
18200
+ status: "confirmed",
18201
+ mailingListSignupNote: recovery.mailingListSignupNote
18202
+ });
17639
18203
  setRecovery(null);
17640
18204
  setters.setStep("success");
17641
18205
  return;
@@ -17764,6 +18328,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
17764
18328
  const paymentSelection = flowState.paymentSelection;
17765
18329
  const [selectedEvent, setSelectedEvent] = useState(preSelectedEvent ?? null);
17766
18330
  const [formData, setFormData] = useState(createInitialRegistrationFormData);
18331
+ const mailingListSignup = resolveBookingSignupOffer(options.mailingList, options.siteName);
17767
18332
  const [errors, setErrors] = useState({});
17768
18333
  const [guests, setGuests] = useState([]);
17769
18334
  const [guestErrors, setGuestErrors] = useState({});
@@ -18210,6 +18775,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
18210
18775
  ticketSelections,
18211
18776
  selectedSlidingAmount,
18212
18777
  formData,
18778
+ mailingListSignup,
18213
18779
  altchaSolution,
18214
18780
  requireGuestDetails,
18215
18781
  guests,
@@ -18306,6 +18872,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
18306
18872
  hasValidTicketSelection,
18307
18873
  eventRequiresPayment,
18308
18874
  formData,
18875
+ mailingListSignup,
18309
18876
  setFormData,
18310
18877
  errors,
18311
18878
  guests,
@@ -18517,7 +19084,8 @@ function useEventRegistrationControllerWithDeps(options, deps) {
18517
19084
  },
18518
19085
  attendee: {
18519
19086
  values: wizard.formData,
18520
- errors: wizard.errors
19087
+ errors: wizard.errors,
19088
+ mailingListSignup: wizard.mailingListSignup
18521
19089
  },
18522
19090
  guests: {
18523
19091
  required: wizard.requireGuestDetails,
@@ -18615,7 +19183,9 @@ function useEventRegistrationWizardControllerWithDeps(options, deps) {
18615
19183
  occurrenceContext: options.occurrenceContext ?? null,
18616
19184
  subject: options.subject ?? null,
18617
19185
  events: [...options.events ?? []],
18618
- maxTicketsNum
19186
+ maxTicketsNum,
19187
+ mailingList: options.mailingList,
19188
+ siteName: options.siteName
18619
19189
  }) };
18620
19190
  }
18621
19191
  function resolveExistingRegistrationState(wizard) {