@riverbankcms/sdk 0.147.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 (381) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/{PreviewEditorSidebar-DtpB3_sS.mjs → PreviewEditorSidebar-DvEPG3Z2.mjs} +202 -143
  3. package/dist/{PreviewEditorUI-DxTLgaHo.mjs → PreviewEditorUI-D6eb6fkx.mjs} +68 -60
  4. package/dist/{PreviewQueryProvider-Dd4dxOiU.mjs → PreviewQueryProvider-5znTyJuz.mjs} +1 -1
  5. package/dist/{SdkPreviewModeRuntime-DMMNCngt.mjs → SdkPreviewModeRuntime-DJ6utQ_R.mjs} +1191 -513
  6. package/dist/{SiteChromeCustomizeContext-DQXZXiqS.mjs → SiteChromeCustomizeContext-CFJYh6vo.mjs} +201798 -197304
  7. package/dist/_dts/ai/src/contracts/proposals.d.ts +0 -33
  8. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +0 -3
  9. package/dist/_dts/api/src/accessAdmin.d.ts +0 -4
  10. package/dist/_dts/api/src/accountApi.d.ts +1 -1
  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 +0 -2
  25. package/dist/_dts/api/src/bookingOperations.d.ts +4 -4
  26. package/dist/_dts/api/src/bookingRecords.d.ts +1 -0
  27. package/dist/_dts/api/src/bookings.d.ts +7 -7
  28. package/dist/_dts/api/src/calendar.d.ts +9 -9
  29. package/dist/_dts/api/src/commercePortalEndpoints.d.ts +7 -6
  30. package/dist/_dts/api/src/common/envelope.d.ts +2 -2
  31. package/dist/_dts/api/src/content-editor.d.ts +2 -2
  32. package/dist/_dts/api/src/contentEntries.d.ts +17 -48
  33. package/dist/_dts/api/src/contentRuntime.d.ts +51 -37
  34. package/dist/_dts/api/src/contentTypes.d.ts +11 -11
  35. package/dist/_dts/api/src/contentVersionHistoryClient.d.ts +6 -6
  36. package/dist/_dts/api/src/documentLifecycle.d.ts +67 -0
  37. package/dist/_dts/api/src/domains.d.ts +16 -16
  38. package/dist/_dts/api/src/editLeaseEndpoints.d.ts +72 -0
  39. package/dist/_dts/api/src/emailSettings.d.ts +4 -4
  40. package/dist/_dts/api/src/endpoints.d.ts +133 -41
  41. package/dist/_dts/api/src/eventEmailTemplates.d.ts +2 -2
  42. package/dist/_dts/api/src/eventManagementContracts.d.ts +25 -0
  43. package/dist/_dts/api/src/eventManagementEndpointDefinitions.d.ts +0 -8
  44. package/dist/_dts/api/src/eventPageWords.d.ts +7 -12
  45. package/dist/_dts/api/src/footerSettings.d.ts +6 -6
  46. package/dist/_dts/api/src/index.d.ts +6 -5
  47. package/dist/_dts/api/src/indexCoreTypes.d.ts +1 -0
  48. package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -1
  49. package/dist/_dts/api/src/navigation.d.ts +5 -5
  50. package/dist/_dts/api/src/pageSurfaceEditorEndpoints.d.ts +55 -0
  51. package/dist/_dts/api/src/pageSurfaceEndpoints.d.ts +28 -7
  52. package/dist/_dts/api/src/pages.d.ts +7 -7
  53. package/dist/_dts/api/src/performance.d.ts +1 -1
  54. package/dist/_dts/api/src/public/index.d.ts +1 -1
  55. package/dist/_dts/api/src/publicAppointmentBookingContracts.d.ts +2 -0
  56. package/dist/_dts/api/src/publicExperience/commerceEndpoints.d.ts +4 -0
  57. package/dist/_dts/api/src/redirects.d.ts +3 -3
  58. package/dist/_dts/api/src/request.d.ts +10 -1
  59. package/dist/_dts/api/src/resources.d.ts +4 -4
  60. package/dist/_dts/api/src/routes.d.ts +8 -3
  61. package/dist/_dts/api/src/sdk-event-upsert.d.ts +0 -1
  62. package/dist/_dts/api/src/sdkBlockUpsertContracts.d.ts +21 -0
  63. package/dist/_dts/api/src/sdkContracts.d.ts +5 -28
  64. package/dist/_dts/api/src/sdkEventEndpointDefinitions.d.ts +1 -1
  65. package/dist/_dts/api/src/sdkEventOccurrenceRequestContracts.d.ts +43 -0
  66. package/dist/_dts/api/src/sdkManagedEventContracts.d.ts +4 -2
  67. package/dist/_dts/api/src/sdkPullEventContracts.d.ts +8 -1
  68. package/dist/_dts/api/src/seo.d.ts +4 -4
  69. package/dist/_dts/api/src/services.d.ts +4 -4
  70. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +15 -8
  71. package/dist/_dts/api/src/siteMembers.d.ts +10 -10
  72. package/dist/_dts/api/src/siteOnboarding.d.ts +14 -0
  73. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +7 -3
  74. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +5 -12
  75. package/dist/_dts/api/src/siteRuntimeEntry.d.ts +31 -0
  76. package/dist/_dts/billing/src/checkout/platform.d.ts +77 -0
  77. package/dist/_dts/billing/src/components/index.d.ts +25 -40
  78. package/dist/_dts/billing/src/membership/index.d.ts +1 -3
  79. package/dist/_dts/billing/src/plans/entitlements.d.ts +80 -0
  80. package/dist/_dts/billing/src/plans/registry.d.ts +16 -16
  81. package/dist/_dts/billing/src/plans/standing.d.ts +9 -2
  82. package/dist/_dts/billing/src/plans/types.d.ts +5 -15
  83. package/dist/_dts/billing/src/site-arrangements.d.ts +2 -2
  84. package/dist/_dts/billing/src/subscriptions/standingEvidence.d.ts +2 -4
  85. package/dist/_dts/billing/src/subscriptions/store.d.ts +17 -11
  86. package/dist/_dts/block-form/src/backend/store-backend.d.ts +6 -7
  87. package/dist/_dts/block-form/src/backend/types.d.ts +7 -0
  88. package/dist/_dts/block-form/src/widgets/FieldFrame.d.ts +3 -1
  89. package/dist/_dts/blocks/src/client/events.d.ts +3 -0
  90. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +16 -4
  91. package/dist/_dts/blocks/src/pageRenderAdmission.d.ts +4 -13
  92. package/dist/_dts/blocks/src/pageRendererContracts.d.ts +2 -0
  93. package/dist/_dts/blocks/src/portal/types.d.ts +0 -2
  94. package/dist/_dts/blocks/src/system/blocks/contact-newsletter.d.ts +2 -1
  95. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +3 -1
  96. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +4 -4
  97. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +6 -1
  98. package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +2 -2
  99. package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
  100. package/dist/_dts/blocks/src/system/runtime/api/types/appointments.d.ts +2 -0
  101. package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +6 -0
  102. package/dist/_dts/blocks/src/system/runtime/api/types/portal.d.ts +6 -0
  103. package/dist/_dts/blocks/src/system/runtime/api/types/shop.d.ts +4 -0
  104. package/dist/_dts/blocks/src/system/runtime/components/booking/SuccessMessage.d.ts +4 -1
  105. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +24 -6
  106. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +12 -3
  107. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.d.ts +3 -0
  108. package/dist/_dts/blocks/src/system/runtime/hooks/usePaymentVerification.d.ts +2 -1
  109. package/dist/_dts/blocks/src/system/runtime/hooks/usePolling.d.ts +7 -48
  110. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.checkout-return-context.d.ts +7 -0
  111. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.completion.d.ts +3 -1
  112. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +4 -0
  113. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.interactive.d.ts +9 -0
  114. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.payment-confirmation.d.ts +13 -0
  115. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.state.d.ts +15 -1
  116. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.submit-actions.d.ts +8 -0
  117. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.submit-handler.d.ts +1 -0
  118. package/dist/_dts/blocks/src/system/runtime/nodes/booking-runtime-sources.d.ts +1 -0
  119. package/dist/_dts/blocks/src/system/runtime/nodes/checkout.server.d.ts +2 -1
  120. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationSurface.d.ts +2 -1
  121. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationWizard.d.ts +5 -0
  122. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/SuccessStep.d.ts +4 -1
  123. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +2 -0
  124. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +2 -5
  125. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +9 -5
  126. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventListing.interactive.d.ts +6 -0
  127. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/dates.d.ts +37 -3
  128. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventCard.client.d.ts +1 -1
  129. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventCard.d.ts +16 -1
  130. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCardPresentations.d.ts +13 -0
  131. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +5 -5
  132. package/dist/_dts/blocks/src/system/runtime/nodes/shared/MagicLinkForm.d.ts +1 -14
  133. package/dist/_dts/blocks/src/system/runtime/nodes/shared/MagicLinkForm.state.d.ts +12 -0
  134. package/dist/_dts/blocks/src/system/runtime/nodes/shop.interactive.d.ts +13 -0
  135. package/dist/_dts/blocks/src/system/runtime/shared/components/DemoBookingPortalAccess.d.ts +22 -0
  136. package/dist/_dts/blocks/src/system/runtime/shared/components/DemoPortalSignInLink.d.ts +4 -0
  137. package/dist/_dts/blocks/src/system/runtime/shared/components/index.d.ts +1 -0
  138. package/dist/_dts/blocks/src/system/runtime/shared/utils/demoBookingPassStorage.d.ts +10 -0
  139. package/dist/_dts/blocks/src/system/runtime/shared/utils/demoPortalMagicLink.d.ts +29 -0
  140. package/dist/_dts/commerce/src/purchase/event-registration-errors.d.ts +4 -0
  141. package/dist/_dts/content-editor/src/components/ContentFieldsForm.d.ts +2 -7
  142. package/dist/_dts/content-editor/src/controller/EditLeaseController.d.ts +39 -0
  143. package/dist/_dts/content-editor/src/controller/EditorWriteGate.d.ts +38 -0
  144. package/dist/_dts/content-editor/src/controller/EntryControllerProvider.d.ts +25 -61
  145. package/dist/_dts/content-editor/src/controller/LinkedEntryLeaseBanner.d.ts +7 -0
  146. package/dist/_dts/content-editor/src/controller/LinkedEntryLeaseControllers.d.ts +14 -0
  147. package/dist/_dts/content-editor/src/controller/deriveEditorUnpublishedState.d.ts +6 -0
  148. package/dist/_dts/content-editor/src/controller/documentValueBaseline.d.ts +25 -0
  149. package/dist/_dts/content-editor/src/controller/editLeaseLossSignal.d.ts +6 -0
  150. package/dist/_dts/content-editor/src/controller/editLeaseNotice.d.ts +28 -0
  151. package/dist/_dts/content-editor/src/controller/editorClientId.d.ts +2 -0
  152. package/dist/_dts/content-editor/src/controller/editorEditability.d.ts +38 -0
  153. package/dist/_dts/content-editor/src/controller/editorLeaseParticipation.d.ts +34 -0
  154. package/dist/_dts/content-editor/src/controller/normalizedMetadataBaseline.d.ts +29 -0
  155. package/dist/_dts/content-editor/src/controller/pageSurfaceDocumentBaselines.d.ts +14 -0
  156. package/dist/_dts/content-editor/src/controller/pageSurfaceLifecycle.d.ts +11 -0
  157. package/dist/_dts/content-editor/src/controller/planDocumentBaselineRefresh.d.ts +19 -0
  158. package/dist/_dts/content-editor/src/controller/readDocumentLeaseBaselines.d.ts +19 -0
  159. package/dist/_dts/content-editor/src/controller/refreshDocumentLeaseBaseline.d.ts +12 -0
  160. package/dist/_dts/content-editor/src/controller/refreshLinkedEntry.d.ts +17 -0
  161. package/dist/_dts/content-editor/src/controller/replayRestoredEditorEffects.d.ts +2 -3
  162. package/dist/_dts/content-editor/src/controller/routeWrites.d.ts +26 -0
  163. package/dist/_dts/content-editor/src/controller/useAutosaveTriggers.d.ts +16 -17
  164. package/dist/_dts/content-editor/src/controller/useBlockedPublishPlan.d.ts +6 -2
  165. package/dist/_dts/content-editor/src/controller/useBlocksList.d.ts +3 -3
  166. package/dist/_dts/content-editor/src/controller/useEntryValueAutosaves.d.ts +21 -0
  167. package/dist/_dts/content-editor/src/controller/useInitialEditorUiStore.d.ts +24 -0
  168. package/dist/_dts/content-editor/src/controller/useServerBaselineReconciliation.d.ts +17 -0
  169. package/dist/_dts/content-editor/src/footerComposerPanelTypes.d.ts +1 -1
  170. package/dist/_dts/content-editor/src/hooks/applyBlockedPublishPlan.d.ts +5 -1
  171. package/dist/_dts/content-editor/src/hooks/blockDraftLifecycle.d.ts +8 -47
  172. package/dist/_dts/content-editor/src/hooks/editLeaseMachine.d.ts +120 -0
  173. package/dist/_dts/content-editor/src/hooks/publishability.d.ts +6 -10
  174. package/dist/_dts/content-editor/src/hooks/useAutosaveStatus.d.ts +3 -0
  175. package/dist/_dts/content-editor/src/hooks/useBlockAutosave.d.ts +5 -15
  176. package/dist/_dts/content-editor/src/hooks/useDebouncedLatestSave.d.ts +7 -5
  177. package/dist/_dts/content-editor/src/hooks/useEditLease.d.ts +28 -0
  178. package/dist/_dts/content-editor/src/hooks/useEntryActions.d.ts +25 -39
  179. package/dist/_dts/content-editor/src/hooks/useEntryMutations.d.ts +17 -19
  180. package/dist/_dts/content-editor/src/hooks/useLinkedEntryAutosave.d.ts +5 -8
  181. package/dist/_dts/content-editor/src/hooks/useValueAutosave.d.ts +64 -0
  182. package/dist/_dts/content-editor/src/hooks/validateBlocksForPublish.d.ts +0 -7
  183. package/dist/_dts/content-editor/src/index.d.ts +26 -7
  184. package/dist/_dts/content-editor/src/linkedEntries/domain.d.ts +12 -0
  185. package/dist/_dts/content-editor/src/linkedEntries/owner.d.ts +9 -0
  186. package/dist/_dts/content-editor/src/liveDrafts/draftProjection.d.ts +66 -0
  187. package/dist/_dts/content-editor/src/liveDrafts/linkedSaveHandovers.d.ts +37 -0
  188. package/dist/_dts/content-editor/src/liveDrafts/remoteDraftOverlay.d.ts +113 -0
  189. package/dist/_dts/content-editor/src/liveDrafts/useLiveDrafts.d.ts +32 -0
  190. package/dist/_dts/content-editor/src/liveDrafts/useRetentionTicks.d.ts +7 -0
  191. package/dist/_dts/content-editor/src/primitives/shared/activePreviewField.d.ts +6 -0
  192. package/dist/_dts/content-editor/src/primitives/shared/storeBinding.d.ts +1 -0
  193. package/dist/_dts/content-editor/src/services/contentEntryServices.d.ts +96 -19
  194. package/dist/_dts/content-editor/src/services/editorApiClient.d.ts +13 -0
  195. package/dist/_dts/content-editor/src/services/index.d.ts +2 -0
  196. package/dist/_dts/content-editor/src/services/pageSurfaceEditorServices.d.ts +23 -0
  197. package/dist/_dts/content-editor/src/sync/flushValues.d.ts +13 -0
  198. package/dist/_dts/content-editor/src/sync/lifecycleFailure.d.ts +51 -0
  199. package/dist/_dts/content-editor/src/sync/runLifecycle.d.ts +64 -0
  200. package/dist/_dts/content-editor/src/sync/schedulerValues.d.ts +27 -0
  201. package/dist/_dts/content-editor/src/sync/sendPlanning.d.ts +104 -0
  202. package/dist/_dts/content-editor/src/sync/valueSync.d.ts +114 -0
  203. package/dist/_dts/content-editor/src/ui/blockCollection.d.ts +8 -0
  204. package/dist/_dts/content-editor/src/ui/documentLifecycle.d.ts +18 -0
  205. package/dist/_dts/content-editor/src/ui/editorLeaseUiState.d.ts +7 -0
  206. package/dist/_dts/content-editor/src/ui/editorRefresh.d.ts +82 -0
  207. package/dist/_dts/content-editor/src/ui/editorSnapshot.d.ts +102 -127
  208. package/dist/_dts/content-editor/src/ui/editorTransactionState.d.ts +1 -1
  209. package/dist/_dts/content-editor/src/ui/editorUiStore.d.ts +126 -72
  210. package/dist/_dts/content-editor/src/ui/editorValueSnapshot.d.ts +18 -0
  211. package/dist/_dts/content-editor/src/ui/serverBlockAdmission.d.ts +26 -0
  212. package/dist/_dts/content-editor/src/ui/stores/autosaveStore.d.ts +16 -27
  213. package/dist/_dts/content-editor/src/ui/stores/blockVersionsStore.d.ts +24 -0
  214. package/dist/_dts/content-editor/src/ui/stores/linkedEntryLeaseStore.d.ts +54 -0
  215. package/dist/_dts/content-editor/src/ui/stores/linkedSaveHandoversStore.d.ts +11 -0
  216. package/dist/_dts/content-editor/src/ui/stores/remoteDraftsStore.d.ts +10 -0
  217. package/dist/_dts/content-editor/src/ui/stores/types.d.ts +63 -3
  218. package/dist/_dts/content-editor/src/useFooterComposerState.d.ts +2 -2
  219. package/dist/_dts/content-editor/src/useFooterNavigationLayout.d.ts +1 -1
  220. package/dist/_dts/content-model/src/content-types/builtin-schemas.d.ts +4 -4
  221. package/dist/_dts/content-model/src/content-types/builtins.d.ts +4 -4
  222. package/dist/_dts/content-model/src/definitions/shared.d.ts +11 -2
  223. package/dist/_dts/content-model/src/entry-slots/index.d.ts +1 -0
  224. package/dist/_dts/content-model/src/entry-slots/serializeAllowedBlocks.d.ts +2 -0
  225. package/dist/_dts/content-model/src/metadataConfig.d.ts +10 -38
  226. package/dist/_dts/content-model/src/templates/defaults.d.ts +0 -1
  227. package/dist/_dts/content-model/src/types.d.ts +0 -1
  228. package/dist/_dts/core/src/block-content-identity.d.ts +49 -1
  229. package/dist/_dts/core/src/branded.d.ts +12 -0
  230. package/dist/_dts/core/src/currency-format.d.ts +8 -2
  231. package/dist/_dts/core/src/demo-lifecycle-status.d.ts +2 -2
  232. package/dist/_dts/core/src/demo-warm-pool-target.d.ts +8 -0
  233. package/dist/_dts/core/src/edit-lease.d.ts +55 -0
  234. package/dist/_dts/core/src/editor-state.d.ts +38 -13
  235. package/dist/_dts/core/src/editor-value-sync.d.ts +79 -0
  236. package/dist/_dts/core/src/html-entities.d.ts +6 -0
  237. package/dist/_dts/core/src/index.d.ts +4 -0
  238. package/dist/_dts/core/src/uuid.d.ts +7 -5
  239. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +159 -153
  240. package/dist/_dts/editor/src/EditorProvider.d.ts +5 -0
  241. package/dist/_dts/editor/src/chrome/EditorChrome.d.ts +14 -0
  242. package/dist/_dts/editor/src/chrome/EditorStatusBar.d.ts +1 -0
  243. package/dist/_dts/editor/src/chrome/statusBarPresentation.d.ts +0 -1
  244. package/dist/_dts/editor/src/index.d.ts +1 -1
  245. package/dist/_dts/editor-blocks/src/BlockEditor.d.ts +10 -9
  246. package/dist/_dts/editor-blocks/src/BlockForm.d.ts +1 -1
  247. package/dist/_dts/editor-blocks/src/block-editor/BlockCard.d.ts +1 -1
  248. package/dist/_dts/editor-blocks/src/block-editor/BlockCardFrame.d.ts +1 -1
  249. package/dist/_dts/editor-blocks/src/block-editor/BlockSettingsModal.d.ts +1 -1
  250. package/dist/_dts/editor-blocks/src/block-editor/applyExtendedFieldDefaults.d.ts +3 -4
  251. package/dist/_dts/editor-blocks/src/block-editor/blockDraftBaselineSeed.d.ts +4 -8
  252. package/dist/_dts/editor-blocks/src/block-editor/editorBlockItem.d.ts +23 -0
  253. package/dist/_dts/editor-blocks/src/block-editor/generatedIconApplyCoordination.d.ts +2 -7
  254. package/dist/_dts/editor-blocks/src/block-editor/hooks/applyBlockStructureChange.d.ts +4 -0
  255. package/dist/_dts/editor-blocks/src/block-editor/hooks/buildInsertBlockHistoryCommand.d.ts +14 -5
  256. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockBaselineSync.d.ts +21 -19
  257. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockCreation.d.ts +2 -10
  258. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockDuplication.d.ts +8 -16
  259. package/dist/_dts/editor-blocks/src/block-editor/owner.d.ts +6 -16
  260. package/dist/_dts/editor-blocks/src/block-editor/types.d.ts +37 -9
  261. package/dist/_dts/editor-blocks/src/index.d.ts +2 -1
  262. package/dist/_dts/editor-blocks/src/widgets/entry-picker/loaders.d.ts +1 -1
  263. package/dist/_dts/editor-blocks/src/widgets/link/loaders.d.ts +1 -1
  264. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/loaders.d.ts +1 -1
  265. package/dist/_dts/editor-blocks/src/widgets/reference/loaders.d.ts +1 -1
  266. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/loaders.d.ts +3 -2
  267. package/dist/_dts/media-core/src/fileStorage.d.ts +4 -0
  268. package/dist/_dts/media-editor/src/context.d.ts +1 -1
  269. package/dist/_dts/media-editor/src/createMediaEditorProvider.d.ts +1 -2
  270. package/dist/_dts/media-editor/src/provider.d.ts +3 -2
  271. package/dist/_dts/media-react/src/hooks/internal/classification.d.ts +1 -1
  272. package/dist/_dts/media-react/src/hooks/useApiMediaUploader.d.ts +3 -1
  273. package/dist/_dts/preview-next/src/client/blocks/composer/mergeDrafts.d.ts +8 -3
  274. package/dist/_dts/preview-next/src/client/blocks/composer/types.d.ts +6 -3
  275. package/dist/_dts/preview-next/src/client/blocks/linkedEntryRenderOverlay.d.ts +22 -2
  276. package/dist/_dts/preview-next/src/client/blocks/previewProjection/entryFieldRebinding.d.ts +13 -0
  277. package/dist/_dts/preview-next/src/client/blocks/previewProjection/index.d.ts +2 -1
  278. package/dist/_dts/preview-next/src/client/blocks/previewProjection/types.d.ts +11 -1
  279. package/dist/_dts/preview-next/src/client/blocks/renderPrecedence.d.ts +17 -0
  280. package/dist/_dts/preview-next/src/client/blocks/useLinkedSaveHandoverRetention.d.ts +20 -0
  281. package/dist/_dts/preview-next/src/client/index.d.ts +1 -1
  282. package/dist/_dts/preview-next/src/client/preview/EntryEditorPanel.d.ts +2 -1
  283. package/dist/_dts/preview-next/src/client/preview/EntrySlotBlockEditorPanel.d.ts +2 -1
  284. package/dist/_dts/preview-next/src/client/preview/PreviewAccessBanners.d.ts +7 -0
  285. package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +2 -1
  286. package/dist/_dts/preview-next/src/client/preview/PreviewEntryControllerProvider.d.ts +24 -14
  287. package/dist/_dts/preview-next/src/client/preview/PreviewLeaseEditingMode.d.ts +2 -0
  288. package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +9 -2
  289. package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +1 -0
  290. package/dist/_dts/preview-next/src/client/preview/previewCustomizeAutosave.d.ts +5 -0
  291. package/dist/_dts/preview-next/src/client/preview/previewCustomizeWorkflowState.d.ts +3 -4
  292. package/dist/_dts/preview-next/src/client/preview/sdkConfig.d.ts +1 -0
  293. package/dist/_dts/preview-next/src/client/preview/usePreviewCustomizeWorkflowState.d.ts +4 -0
  294. package/dist/_dts/realtime/src/client.d.ts +3 -0
  295. package/dist/_dts/realtime/src/draftChannel.d.ts +91 -0
  296. package/dist/_dts/realtime/src/drafts.d.ts +210 -0
  297. package/dist/_dts/realtime/src/index.d.ts +3 -0
  298. package/dist/_dts/realtime/src/leaseChangeSubscriptions.d.ts +8 -0
  299. package/dist/_dts/realtime/src/types.d.ts +113 -0
  300. package/dist/_dts/realtime/src/useDraftChannel.d.ts +34 -0
  301. package/dist/_dts/realtime/src/useSiteRealtimeReload.d.ts +27 -0
  302. package/dist/_dts/sdk/src/public-api/contracts.d.ts +6 -55
  303. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +1 -0
  304. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +1 -0
  305. package/dist/_dts/sdk/src/rendering/helpers/pageRuntimeSupport.d.ts +2 -0
  306. package/dist/_dts/sdk/src/version.d.ts +1 -1
  307. package/dist/_dts/surfaces/src/index.d.ts +1 -0
  308. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +2 -2
  309. package/dist/client/{BookingMailingListNote-1n4Ch_u_.mjs → BookingMailingListNote-CzRt2dF_.mjs} +98 -96
  310. package/dist/client/DemoBookingPortalAccess-mxqwap3f.mjs +344 -0
  311. package/dist/client/{EventCombined.client-C0pgma9y.mjs → EventCombined.client-CDb11igO.mjs} +6 -6
  312. package/dist/client/{EventListing.client-4fhLOvHP.mjs → EventListing.client-EgYhzKPa.mjs} +2 -2
  313. package/dist/client/{LeafletStaticMap-DScC4F3w.mjs → LeafletStaticMap-gtmtaA2b.mjs} +1 -1
  314. package/dist/client/{TerminalPanel-B5ZUsYhe.mjs → TerminalPanel-DvNUP5ot.mjs} +1 -1
  315. package/dist/client/{ThemedButton-DoVIV1Ao.mjs → ThemedButton-C7CeUJjW.mjs} +1 -1
  316. package/dist/client/{accordion-CoT5g7zo.mjs → accordion-kjvt49rA.mjs} +1 -1
  317. package/dist/client/{bookingForm-BWxB46xD.mjs → bookingForm-pbRZordh.mjs} +212 -62
  318. package/dist/client/bookings.mjs +616 -225
  319. package/dist/client/{carousel-DtNYWFd3.mjs → carousel-f4Zbmicv.mjs} +1 -1
  320. package/dist/client/{cart-z4qZih1Y.mjs → cart-DO20An50.mjs} +3 -3
  321. package/dist/client/{checkout-DpL7euFH.mjs → checkout-Du5amDR_.mjs} +3 -3
  322. package/dist/client/{checkoutUrls-BEfR7kVu.mjs → checkoutUrls-CXhko2Rv.mjs} +1 -1
  323. package/dist/client/client.mjs +1753 -823
  324. package/dist/client/{context-C8TinPJc.mjs → context-eW97E945.mjs} +4 -3
  325. package/dist/client/{dates-vwwxTeB0.mjs → dates-jPCirRea.mjs} +56 -11
  326. package/dist/client/{eventCalendar-DIbHfJXO.mjs → eventCalendar-C2M-iE4j.mjs} +9 -9
  327. package/dist/client/{eventCombined-DoGMJ6cg.mjs → eventCombined-W6ns3LHg.mjs} +4 -4
  328. package/dist/client/{eventDetails-BjN9v6a1.mjs → eventDetails-CR-GT0f0.mjs} +4 -4
  329. package/dist/client/{eventListing-DajjWgOv.mjs → eventListing-BK8AfYZz.mjs} +4 -4
  330. package/dist/client/{eventRegistration-DMq9gMA-.mjs → eventRegistration-BJSd4KUu.mjs} +369 -242
  331. package/dist/client/{form-Qf6qTbos.mjs → form-BvpfbQaT.mjs} +3 -3
  332. package/dist/client/{headerSection-D7qJrqFX.mjs → headerSection-I5sUQ8x-.mjs} +3 -3
  333. package/dist/client/hooks.mjs +254 -53
  334. package/dist/client/{locationMap-CCF9-t_0.mjs → locationMap-BLvwf9_f.mjs} +3 -3
  335. package/dist/client/{media-CwBGetqC.mjs → media-Cl38iOMI.mjs} +10 -3
  336. package/dist/client/{newsletterForm-DzCLSP4S.mjs → newsletterForm-DrQ2weE8.mjs} +3 -3
  337. package/dist/client/{pricing-Cgxv2KLC.mjs → pricing-BES87mrR.mjs} +1 -1
  338. package/dist/client/{productDetail-ru9w5GHx.mjs → productDetail-Url9jcc5.mjs} +3 -3
  339. package/dist/client/{productList-zaapKSl-.mjs → productList-DE7ngEZJ.mjs} +3 -3
  340. package/dist/client/{propsDecoder-CwvvNOHx.mjs → propsDecoder-D1OtGXDV.mjs} +89 -17
  341. package/dist/client/rendering/client.mjs +1445 -658
  342. package/dist/client/rendering/islands.mjs +18 -18
  343. package/dist/client/rendering.mjs +2478 -1515
  344. package/dist/client/{routeIslandApiConfig-BwVFo0Y4.mjs → routeIslandApiConfig-BG9Y-SHg.mjs} +1 -1
  345. package/dist/client/{shop-mktkXvbV.mjs → shop-CJkuySJ3.mjs} +126 -79
  346. package/dist/client/{shop-commerce-De7gEnkA.mjs → shop-commerce-4rKj5n9h.mjs} +25 -13
  347. package/dist/client/{shop-commerce-store-B3MCxIBW.mjs → shop-commerce-store-Bxm75Pg6.mjs} +1 -1
  348. package/dist/client/{shopShared-TqExh235.mjs → shopShared-DpoQDWfz.mjs} +4 -4
  349. package/dist/client/{useEventFilters-n_OjkIjX.mjs → useEventFilters-D8HliSqR.mjs} +32 -17
  350. package/dist/preview-next/before-render.mjs +192 -83
  351. package/dist/preview-next/client/runtime.mjs +4 -4
  352. package/dist/preview-next/keepAlive.mjs +192 -83
  353. package/dist/preview-next/middleware.mjs +192 -83
  354. package/dist/{previewAuthStore-C_EHQ5XA.mjs → previewAuthStore-BXXF3hhW.mjs} +194 -83
  355. package/dist/{sdk-runtime-BIkJg5y1.mjs → sdk-runtime-C2a05WjL.mjs} +2 -2
  356. package/dist/{separator-C9qDP95Z.mjs → separator-CuNhBAhS.mjs} +1 -1
  357. package/dist/server/components.mjs +1720 -1392
  358. package/dist/server/config-validation.mjs +221 -37
  359. package/dist/server/config.mjs +221 -37
  360. package/dist/server/data.mjs +221 -37
  361. package/dist/server/index.mjs +195 -84
  362. package/dist/server/next.mjs +490 -196
  363. package/dist/server/page-converter.mjs +53 -14
  364. package/dist/server/prebuild.mjs +1 -1
  365. package/dist/server/rendering/server.mjs +1427 -1098
  366. package/dist/server/rendering.mjs +2693 -2365
  367. package/dist/server/routing.mjs +291 -55
  368. package/dist/server/server.mjs +281 -114
  369. package/package.json +1 -1
  370. package/dist/_dts/billing/src/plans/display.d.ts +0 -15
  371. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.mailing-list-note.d.ts +0 -3
  372. package/dist/_dts/content-editor/src/controller/buildBlockPublishedBaselines.d.ts +0 -4
  373. package/dist/_dts/content-editor/src/controller/buildPublishSuccessTransition.d.ts +0 -16
  374. package/dist/_dts/content-editor/src/controller/driver.d.ts +0 -14
  375. package/dist/_dts/content-editor/src/controller/seedDraftBaselinesFromBlocks.d.ts +0 -7
  376. package/dist/_dts/content-editor/src/controller/useEntrySyncHelpers.d.ts +0 -29
  377. package/dist/_dts/content-editor/src/hooks/autosaveScopePlanning.d.ts +0 -26
  378. package/dist/_dts/content-editor/src/hooks/useSimpleAutosave.d.ts +0 -64
  379. package/dist/_dts/content-editor/src/hooks/useStoreAutosave.d.ts +0 -48
  380. package/dist/_dts/content-editor/src/types.d.ts +0 -44
  381. package/dist/client/DiscountCodeDisclosure-CKJtz0mY.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
@@ -3168,6 +3184,16 @@ function resolveBookingSignupOffer(context, siteName) {
3168
3184
  const name = siteName?.trim() ?? "";
3169
3185
  return context?.tag === "configured" && context.bookingSignup.tag === "offered" ? { siteName: name.length > 0 ? name : "this site" } : null;
3170
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
+ }
3171
3197
  function sessionStartMs(session) {
3172
3198
  return Date.parse(session.startsAt);
3173
3199
  }
@@ -7023,7 +7049,7 @@ const boxBackgroundSchema = z.discriminatedUnion("type", [
7023
7049
  })
7024
7050
  ]);
7025
7051
  function normalizeAuthoringOpacity(value) {
7026
- if (!isRecord$6(value)) return value;
7052
+ if (!isRecord$8(value)) return value;
7027
7053
  return {
7028
7054
  ...value,
7029
7055
  opacity: normalizeOpacity(value.opacity)
@@ -7032,7 +7058,7 @@ function normalizeAuthoringOpacity(value) {
7032
7058
  function normalizeOpacity(value) {
7033
7059
  return typeof value === "number" && value > 1 && value <= 100 ? value / 100 : value;
7034
7060
  }
7035
- function isRecord$6(value) {
7061
+ function isRecord$8(value) {
7036
7062
  return typeof value === "object" && value !== null && !Array.isArray(value);
7037
7063
  }
7038
7064
  //#endregion
@@ -8156,7 +8182,6 @@ const publicEventBaseSchema = z.object({
8156
8182
  description: z.string().nullable(),
8157
8183
  content: z.object({ body: RichTextDocSchema.nullable().optional() }).optional(),
8158
8184
  presentation: z.object({
8159
- cardTitleOverride: z.string().nullable().optional(),
8160
8185
  summary: z.string().nullable().optional(),
8161
8186
  image: mediaSchema.nullable().optional()
8162
8187
  }).optional(),
@@ -8189,6 +8214,7 @@ const publicEventBaseSchema = z.object({
8189
8214
  "archived"
8190
8215
  ]).optional(),
8191
8216
  timeZone: z.string(),
8217
+ siteTimeZone: z.string().optional(),
8192
8218
  pricing: publicEventPricingSchema,
8193
8219
  paymentTerms: blockBookingPaymentTermsSchema,
8194
8220
  cancellationPolicy: z.object({ refunds: z.object({
@@ -8716,7 +8742,7 @@ var BlockApiError = class extends Error {
8716
8742
  this.name = "BlockApiError";
8717
8743
  }
8718
8744
  };
8719
- function isRecord$5(value) {
8745
+ function isRecord$7(value) {
8720
8746
  return typeof value === "object" && value !== null;
8721
8747
  }
8722
8748
  function isJsonResponseContentType(contentType) {
@@ -8740,15 +8766,15 @@ async function parseJsonBody(response) {
8740
8766
  }
8741
8767
  }
8742
8768
  function isFieldError(value) {
8743
- 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";
8744
8770
  }
8745
8771
  function fieldErrorsFromUnknown(value) {
8746
8772
  if (!Array.isArray(value)) return void 0;
8747
8773
  return value.every(isFieldError) ? value : void 0;
8748
8774
  }
8749
8775
  function getBlockApiErrorDetails(data) {
8750
- if (!isRecord$5(data)) return {};
8751
- 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;
8752
8778
  const message = typeof nestedError?.message === "string" ? nestedError.message : typeof data.message === "string" ? data.message : void 0;
8753
8779
  const code = typeof nestedError?.code === "string" ? nestedError.code : typeof data.code === "string" ? data.code : void 0;
8754
8780
  const fieldErrors = fieldErrorsFromUnknown(nestedError?.fieldErrors) ?? fieldErrorsFromUnknown(data.fieldErrors);
@@ -9317,10 +9343,11 @@ function createBlockApi(config) {
9317
9343
  },
9318
9344
  async sendMagicLink(data) {
9319
9345
  const sid = requireSiteId();
9320
- await request(PORTAL.sendMagicLink, { body: {
9346
+ return request(PORTAL.sendMagicLink, { body: {
9321
9347
  siteId: sid,
9322
9348
  email: data.email,
9323
- redirectUrl: data.redirectUrl
9349
+ redirectUrl: data.redirectUrl,
9350
+ demoBookingPass: data.demoBookingPass
9324
9351
  } });
9325
9352
  },
9326
9353
  async logout() {
@@ -9543,7 +9570,7 @@ function resolveAppointmentCheckoutVerificationState(input) {
9543
9570
  tag: "timeout",
9544
9571
  sessionId: input.config.sessionId,
9545
9572
  appointmentId,
9546
- 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."
9547
9574
  };
9548
9575
  if (input.pollingStatus === "failed") {
9549
9576
  if (paymentStatus === "refunded") return {
@@ -9607,7 +9634,7 @@ function deriveBookingFormViewState(input) {
9607
9634
  message: input.verificationState.message
9608
9635
  };
9609
9636
  case "timeout": return {
9610
- kind: "error",
9637
+ kind: "timeout",
9611
9638
  message: input.verificationState.message
9612
9639
  };
9613
9640
  case "confirmed": return {
@@ -9621,12 +9648,12 @@ function resolveBookingSiteId(siteId, form) {
9621
9648
  return siteId || form?.siteId || "";
9622
9649
  }
9623
9650
  function normalizeBookingFormConfig(form) {
9624
- if (!isRecord$4(form)) return null;
9651
+ if (!isRecord$6(form)) return null;
9625
9652
  const id = readNonEmptyString(form.id);
9626
9653
  const name = readNonEmptyString(form.name);
9627
9654
  if (!id || !name) return null;
9628
- const schemaSource = isRecord$4(form.schema) ? form.schema : isRecord$4(form.schemaJson) ? form.schemaJson : null;
9629
- 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;
9630
9657
  return {
9631
9658
  id,
9632
9659
  name,
@@ -9646,8 +9673,8 @@ function normalizeBookingServices(services) {
9646
9673
  };
9647
9674
  if (!services) return [];
9648
9675
  if (Array.isArray(services)) return services.filter(isBookingFormService).map(normalizeService);
9649
- if (isRecord$4(services) && "services" in services) return Array.isArray(services.services) ? services.services.filter(isBookingFormService).map(normalizeService) : [];
9650
- 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) : [];
9651
9678
  }
9652
9679
  function normalizeBookingSchema(value) {
9653
9680
  if (!value) return void 0;
@@ -9658,7 +9685,7 @@ function normalizeBookingSchema(value) {
9658
9685
  };
9659
9686
  }
9660
9687
  function readBookingFormField(value) {
9661
- if (!isRecord$4(value)) return null;
9688
+ if (!isRecord$6(value)) return null;
9662
9689
  const id = readNonEmptyString(value.id);
9663
9690
  const label = readNonEmptyString(value.label);
9664
9691
  const type = readBookingFieldType(value.type);
@@ -9701,7 +9728,7 @@ function readBookingFieldOptions(value) {
9701
9728
  return options.length > 0 ? options : void 0;
9702
9729
  }
9703
9730
  function readBookingFieldOption(value) {
9704
- if (!isRecord$4(value)) return null;
9731
+ if (!isRecord$6(value)) return null;
9705
9732
  const optionValue = readNonEmptyString(value.value);
9706
9733
  const label = readNonEmptyString(value.label);
9707
9734
  return optionValue && label ? {
@@ -9721,7 +9748,7 @@ function normalizeBookingSettings(value) {
9721
9748
  };
9722
9749
  }
9723
9750
  function isBookingFormService(value) {
9724
- 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);
9725
9752
  }
9726
9753
  function collectBookingCustomFields(data) {
9727
9754
  const customFields = {};
@@ -9771,7 +9798,7 @@ function readStringArray(value) {
9771
9798
  const strings = value.filter((item) => typeof item === "string");
9772
9799
  return strings.length > 0 ? strings : void 0;
9773
9800
  }
9774
- function isRecord$4(value) {
9801
+ function isRecord$6(value) {
9775
9802
  return typeof value === "object" && value !== null;
9776
9803
  }
9777
9804
  function getBookingServicePaymentSelectionMode(service) {
@@ -9965,8 +9992,40 @@ function formatBookingSubmissionPreparationError(error) {
9965
9992
  default: return assertNever(error);
9966
9993
  }
9967
9994
  }
9968
- function getBookingSuccessMessage(successMessage) {
9969
- 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
+ };
9970
10029
  }
9971
10030
  //#endregion
9972
10031
  //#region ../blocks/src/system/runtime/hooks/useSelectedAppointmentConsentForm.ts
@@ -10487,6 +10546,54 @@ function selectIsSubmitting(state) {
10487
10546
  return state.status.tag === "submitting";
10488
10547
  }
10489
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
10490
10597
  //#region ../blocks/src/system/runtime/hooks/useBookingSubmission.ts
10491
10598
  /**
10492
10599
  * Custom hook for submitting appointment bookings
@@ -10552,6 +10659,7 @@ function useBookingSubmission(_siteId) {
10552
10659
  successUrl: data.successUrl,
10553
10660
  cancelUrl: data.cancelUrl
10554
10661
  });
10662
+ storeDemoBookingPassIfAvailable(response.customer.email, response.demoBookingPass);
10555
10663
  dispatch({
10556
10664
  type: "submission-succeeded",
10557
10665
  message: response.type === "checkout_redirect" ? "Redirecting to secure checkout..." : "Booking submitted successfully."
@@ -10590,15 +10698,18 @@ function completeBookingSubmission(input) {
10590
10698
  kind: "checkout_redirect",
10591
10699
  checkoutUrl: data.checkoutUrl,
10592
10700
  sessionId: data.sessionId,
10701
+ customerEmail: data.customer.email,
10702
+ ...data.demoBookingPass ? { demoBookingPass: data.demoBookingPass } : {},
10593
10703
  ...data.mailingListSignupNote ? { mailingListSignupNote: data.mailingListSignupNote } : {}
10594
10704
  }
10595
10705
  };
10596
10706
  }
10707
+ const successCopy = getBookingSuccessCopy(input.successMessage);
10597
10708
  input.dispatch({
10598
10709
  type: "feedback-set",
10599
10710
  feedback: {
10600
10711
  kind: "success",
10601
- message: getBookingSuccessMessage(input.successMessage),
10712
+ message: successCopy.defaultEmailSentence ? `${successCopy.message} ${successCopy.defaultEmailSentence}`.trim() : successCopy.message,
10602
10713
  resourceName: data.appointment.resourceName
10603
10714
  }
10604
10715
  });
@@ -10608,6 +10719,8 @@ function completeBookingSubmission(input) {
10608
10719
  kind: "booked",
10609
10720
  appointmentId: data.appointment.id,
10610
10721
  resourceName: data.appointment.resourceName,
10722
+ customerEmail: data.customer.email,
10723
+ ...data.demoBookingPass ? { demoBookingPass: data.demoBookingPass } : {},
10611
10724
  ...data.mailingListSignupNote ? { mailingListSignupNote: data.mailingListSignupNote } : {}
10612
10725
  }
10613
10726
  };
@@ -11071,11 +11184,11 @@ function formatScheduleDate(isoString, locale) {
11071
11184
  }
11072
11185
  //#endregion
11073
11186
  //#region ../blocks/src/system/runtime/nodes/booking-form.service-categories.ts
11074
- function isRecord$3(value) {
11187
+ function isRecord$4(value) {
11075
11188
  return typeof value === "object" && value !== null && !Array.isArray(value);
11076
11189
  }
11077
11190
  function readCategory(value) {
11078
- if (!isRecord$3(value)) return [];
11191
+ if (!isRecord$4(value)) return [];
11079
11192
  const { id, name, description } = value;
11080
11193
  if (typeof id !== "string" || id.trim() === "" || typeof name !== "string") return [];
11081
11194
  return [{
@@ -11091,7 +11204,7 @@ function readCategory(value) {
11091
11204
  * it.
11092
11205
  */
11093
11206
  function normalizeBookingServiceCategories(services) {
11094
- if (!isRecord$3(services) || !Array.isArray(services.categories)) return [];
11207
+ if (!isRecord$4(services) || !Array.isArray(services.categories)) return [];
11095
11208
  return services.categories.flatMap(readCategory);
11096
11209
  }
11097
11210
  /**
@@ -11099,7 +11212,7 @@ function normalizeBookingServiceCategories(services) {
11099
11212
  * its loader data (`data.services`).
11100
11213
  */
11101
11214
  function readOverrideServiceCategories(data) {
11102
- return isRecord$3(data) ? normalizeBookingServiceCategories(data.services) : [];
11215
+ return isRecord$4(data) ? normalizeBookingServiceCategories(data.services) : [];
11103
11216
  }
11104
11217
  //#endregion
11105
11218
  //#region ../blocks/src/system/runtime/nodes/booking-form.validationErrors.ts
@@ -11865,7 +11978,7 @@ function isBlankFieldValue(value) {
11865
11978
  return false;
11866
11979
  }
11867
11980
  function readAppointmentBookingOverrideData(value) {
11868
- if (!isRecord$2(value)) return null;
11981
+ if (!isRecord$3(value)) return null;
11869
11982
  const services = normalizeBookingServices(value.services);
11870
11983
  return {
11871
11984
  form: normalizeBookingFormConfig(value.form),
@@ -11880,7 +11993,7 @@ function createOverrideInputError(reason, message, warnInDev = false) {
11880
11993
  message
11881
11994
  };
11882
11995
  }
11883
- function isRecord$2(value) {
11996
+ function isRecord$3(value) {
11884
11997
  return typeof value === "object" && value !== null;
11885
11998
  }
11886
11999
  //#endregion
@@ -12383,6 +12496,12 @@ function useHeadlessBookingFlow(options) {
12383
12496
  selectedService,
12384
12497
  state.selectedSlot?.startAt
12385
12498
  ]);
12499
+ const paymentConfirmationSummary = resolveBookingPaymentConfirmationSummary({
12500
+ service: selectedService,
12501
+ priceAmount: selectedAppointmentPriceAmount,
12502
+ selectedCollectionOptionKind: state.selectedCollectionOptionKind,
12503
+ hasSelectedAppointmentPackage: Boolean(state.selectedAppointmentPackageId)
12504
+ });
12386
12505
  const appointmentPackageItems = appointmentPackages.tag === "loaded" ? appointmentPackages.value : [];
12387
12506
  const selectedAppointmentPackage = appointmentPackageItems.find((appointmentPackage) => appointmentPackage.customerPassId === state.selectedAppointmentPackageId) ?? null;
12388
12507
  const spamProtectionEnabled = options.spamProtectionEnabled ?? isSpamProtectionEnabled();
@@ -12412,7 +12531,8 @@ function useHeadlessBookingFlow(options) {
12412
12531
  selectedSlidingAmount,
12413
12532
  slidingScale: selectedServiceSlidingScale,
12414
12533
  appointmentPackages: appointmentPackagesModel,
12415
- errorMessage: paymentResolution.errorMessage ?? "This service cannot be booked right now."
12534
+ errorMessage: paymentResolution.errorMessage ?? "This service cannot be booked right now.",
12535
+ confirmationSummary: null
12416
12536
  } : {
12417
12537
  kind: "ok",
12418
12538
  mode: paymentResolution.mode,
@@ -12422,7 +12542,8 @@ function useHeadlessBookingFlow(options) {
12422
12542
  selectedSlidingAmountInput: state.selectedSlidingAmountInput,
12423
12543
  selectedSlidingAmount,
12424
12544
  slidingScale: selectedServiceSlidingScale,
12425
- appointmentPackages: appointmentPackagesModel
12545
+ appointmentPackages: appointmentPackagesModel,
12546
+ confirmationSummary: paymentConfirmationSummary
12426
12547
  };
12427
12548
  return {
12428
12549
  mailingList,
@@ -12580,67 +12701,24 @@ function pollingReducer(state, action) {
12580
12701
  * Provides a reusable polling mechanism with configurable intervals,
12581
12702
  * max attempts, and completion detection. Used by usePaymentVerification
12582
12703
  * and other hooks that need to poll for status changes.
12583
- *
12584
- * @example
12585
- * ```tsx
12586
- * const polling = usePolling(shouldPoll ? {
12587
- * pollFn: () => api.getStatus(id),
12588
- * isComplete: (result) => result.status === 'done',
12589
- * } : null);
12590
- *
12591
- * useEffect(() => {
12592
- * if (polling.status === 'completed') {
12593
- * handleSuccess(polling.result);
12594
- * }
12595
- * }, [polling.status]);
12596
- * ```
12597
12704
  */
12598
12705
  const DEFAULT_MAX_ATTEMPTS = 10;
12599
12706
  const DEFAULT_POLL_INTERVAL = 1e3;
12600
- /**
12601
- * Generic hook for polling an async operation until completion.
12602
- *
12603
- * Pass config to start polling, or null to stop/idle.
12604
- * The hook handles cleanup on unmount and config changes.
12605
- *
12606
- * **IMPORTANT: Config identity stability**
12607
- *
12608
- * The config object is used as an effect dependency. If config identity
12609
- * changes on every render (e.g., inline objects), polling will restart
12610
- * continuously, causing infinite request loops.
12611
- *
12612
- * Always memoize the config object:
12613
- *
12614
- * @example
12615
- * ```tsx
12616
- * // BAD - inline object creates new identity every render
12617
- * usePolling({
12618
- * pollFn: () => api.getStatus(id),
12619
- * isComplete: (result) => result.status === 'done',
12620
- * });
12621
- *
12622
- * // GOOD - memoized config, stable identity
12623
- * const pollConfig = useMemo(() => shouldPoll ? {
12624
- * pollFn: () => api.getStatus(id),
12625
- * isComplete: (result) => result.status === 'done',
12626
- * } : null, [shouldPoll, api, id]);
12627
- *
12628
- * usePolling(pollConfig);
12629
- * ```
12630
- *
12631
- * @param config - Configuration for polling, or null to stop
12632
- * @returns Polling result with status, data, and retry function
12633
- */
12634
- function usePolling(config) {
12635
- const [state, dispatch] = useReducer(pollingReducer, void 0, createInitialPollingState);
12636
- const attemptsRef = useRef(0);
12637
- const timeoutRef = useRef(null);
12638
- const isPollingRef = useRef(false);
12639
- const isActiveRef = useRef(false);
12640
- const generationRef = useRef(0);
12641
- const configRef = useRef(config);
12642
- configRef.current = config;
12643
- 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(() => {
12644
12722
  isActiveRef.current = false;
12645
12723
  generationRef.current += 1;
12646
12724
  if (timeoutRef.current) {
@@ -12648,16 +12726,27 @@ function usePolling(config) {
12648
12726
  timeoutRef.current = null;
12649
12727
  }
12650
12728
  isPollingRef.current = false;
12651
- }, []);
12652
- const resetState = useCallback(() => {
12729
+ }, [
12730
+ generationRef,
12731
+ isActiveRef,
12732
+ isPollingRef,
12733
+ timeoutRef
12734
+ ]);
12735
+ }
12736
+ function usePollingReset(runtime, dispatch) {
12737
+ const { attemptsRef } = runtime;
12738
+ return useCallback(() => {
12653
12739
  dispatch({ type: "polling-reset" });
12654
12740
  attemptsRef.current = 0;
12655
- }, []);
12656
- const poll = useCallback(async () => {
12657
- const cfg = configRef.current;
12658
- if (!cfg) return true;
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;
12659
12748
  if (isPollingRef.current) return false;
12660
- const maxAttempts = cfg.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
12749
+ const maxAttempts = config.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
12661
12750
  if (attemptsRef.current >= maxAttempts) {
12662
12751
  dispatch({ type: "polling-timed-out" });
12663
12752
  cleanup();
@@ -12667,81 +12756,115 @@ function usePolling(config) {
12667
12756
  attemptsRef.current += 1;
12668
12757
  const generation = generationRef.current;
12669
12758
  try {
12670
- const data = await cfg.pollFn();
12671
- if (generation !== generationRef.current || !isActiveRef.current) {
12672
- isPollingRef.current = false;
12673
- return true;
12674
- }
12675
- if (cfg.isFailed?.(data)) {
12759
+ const result = await config.pollFn();
12760
+ if (generation !== generationRef.current || !isActiveRef.current) return true;
12761
+ if (config.isFailed?.(result)) {
12676
12762
  dispatch({
12677
12763
  type: "polling-failed",
12678
- result: data
12764
+ result
12679
12765
  });
12680
12766
  cleanup();
12681
12767
  return true;
12682
12768
  }
12683
- if (cfg.isComplete(data)) {
12769
+ if (config.isComplete(result)) {
12684
12770
  dispatch({
12685
12771
  type: "polling-completed",
12686
- result: data
12772
+ result
12687
12773
  });
12688
12774
  cleanup();
12689
12775
  return true;
12690
12776
  }
12691
12777
  dispatch({
12692
12778
  type: "polling-progressed",
12693
- result: data
12779
+ result
12694
12780
  });
12695
12781
  isPollingRef.current = false;
12696
12782
  return false;
12697
- } catch (err) {
12698
- if (generation !== generationRef.current || !isActiveRef.current) {
12699
- isPollingRef.current = false;
12700
- return true;
12701
- }
12702
- if (err instanceof Error) dispatch({
12783
+ } catch (error) {
12784
+ if (generation !== generationRef.current || !isActiveRef.current) return true;
12785
+ if (error instanceof Error) dispatch({
12703
12786
  type: "polling-request-failed",
12704
- error: err
12787
+ error
12705
12788
  });
12706
12789
  isPollingRef.current = false;
12707
12790
  return false;
12708
12791
  }
12709
- }, [cleanup]);
12710
- 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(() => {
12711
12805
  if (!isActiveRef.current) return;
12712
- const pollInterval = configRef.current?.interval ?? DEFAULT_POLL_INTERVAL;
12713
12806
  const doPoll = async () => {
12714
- 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
+ }
12715
12812
  };
12716
12813
  doPoll();
12717
- }, [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;
12718
12827
  useEffect(() => {
12719
- if (!config) {
12828
+ if (!pollingEnabled) {
12720
12829
  cleanup();
12721
12830
  dispatch({ type: "polling-went-idle" });
12722
12831
  return;
12723
12832
  }
12724
12833
  resetState();
12725
- isActiveRef.current = true;
12834
+ runtime.isActiveRef.current = true;
12726
12835
  schedulePoll();
12727
12836
  return cleanup;
12728
12837
  }, [
12729
- config,
12730
12838
  cleanup,
12839
+ dispatch,
12840
+ pollingEnabled,
12731
12841
  resetState,
12842
+ config?.restartKey ?? null,
12843
+ runtime.isActiveRef,
12732
12844
  schedulePoll
12733
12845
  ]);
12734
- const retry = useCallback(() => {
12735
- if (!configRef.current) return;
12846
+ return useCallback(() => {
12847
+ if (!runtime.configRef.current) return;
12736
12848
  cleanup();
12737
12849
  resetState();
12738
- isActiveRef.current = true;
12850
+ runtime.isActiveRef.current = true;
12739
12851
  schedulePoll();
12740
12852
  }, [
12741
12853
  cleanup,
12742
12854
  resetState,
12855
+ runtime.configRef,
12856
+ runtime.isActiveRef,
12743
12857
  schedulePoll
12744
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);
12745
12868
  return {
12746
12869
  status: config ? state.tag : "idle",
12747
12870
  result: config ? state.result : null,
@@ -12751,6 +12874,10 @@ function usePolling(config) {
12751
12874
  }
12752
12875
  //#endregion
12753
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
+ }
12754
12881
  const appointmentCheckoutVerificationDeps = {
12755
12882
  useBlockApi,
12756
12883
  usePolling
@@ -12760,16 +12887,25 @@ function useAppointmentCheckoutVerification(config) {
12760
12887
  }
12761
12888
  function useAppointmentCheckoutVerificationWithDeps(config, deps) {
12762
12889
  const api = deps.useBlockApi();
12890
+ const sessionId = config?.sessionId ?? null;
12891
+ const maxAttempts = config?.maxAttempts;
12892
+ const pollInterval = config?.pollInterval;
12763
12893
  const pollingConfig = useMemo(() => {
12764
- if (!config) return null;
12894
+ if (sessionId === null) return null;
12765
12895
  return {
12766
- pollFn: () => api.getAppointmentBookingStatus({ sessionId: config.sessionId }),
12896
+ restartKey: sessionId,
12897
+ pollFn: () => api.getAppointmentBookingStatus({ sessionId }),
12767
12898
  isComplete: (result) => (result.paymentStatus === "completed" || result.paymentStatus === "not_required") && result.appointmentStatus === "confirmed",
12768
12899
  isFailed: (result) => result.paymentStatus === "failed" || result.paymentStatus === "cancelled" || result.paymentStatus === "refunded" || result.appointmentStatus === "cancelled",
12769
- maxAttempts: config.maxAttempts,
12770
- interval: config.pollInterval
12900
+ maxAttempts: maxAttempts ?? APPOINTMENT_CHECKOUT_MAX_ATTEMPTS,
12901
+ interval: pollInterval ?? resolveAppointmentCheckoutPollInterval
12771
12902
  };
12772
- }, [api, config]);
12903
+ }, [
12904
+ api,
12905
+ sessionId,
12906
+ maxAttempts,
12907
+ pollInterval
12908
+ ]);
12773
12909
  const polling = deps.usePolling(pollingConfig);
12774
12910
  return {
12775
12911
  state: resolveAppointmentCheckoutVerificationState({
@@ -13381,11 +13517,18 @@ function isReservedPathSegment(value) {
13381
13517
  function isUnsafePathSegment(segment) {
13382
13518
  return segment.trim().length === 0 || segment !== segment.trim() || isReservedPathSegment(segment) || containsUnsafePathSegmentCharacter(segment);
13383
13519
  }
13384
- ({
13520
+ //#endregion
13521
+ //#region ../media-core/src/fileStorage.ts
13522
+ const FILE_STORAGE_BUCKETS = {
13385
13523
  publicSite: unsafeAsStorageBucketName("media"),
13386
13524
  privateSite: unsafeAsStorageBucketName("site-files-private"),
13387
- temporary: unsafeAsStorageBucketName("temp-uploads")
13388
- }).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;
13389
13532
  function parseStoragePath(value) {
13390
13533
  return joinStoragePathSegments(value.split("/"));
13391
13534
  }
@@ -14211,6 +14354,72 @@ function ServiceChoiceGrid({ booking, choices }) {
14211
14354
  });
14212
14355
  }
14213
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
14214
14423
  //#region ../blocks/src/system/runtime/nodes/booking-form.default-ui.tsx
14215
14424
  function formatBookingAmount(amount, currency) {
14216
14425
  return formatCurrencyAmount(amount, currency, { decimals: "auto" });
@@ -14219,13 +14428,6 @@ function HeadlessBookingDefaultForm({ booking, onSubmit }) {
14219
14428
  const currentStep = booking.currentStep;
14220
14429
  const errorSummaryId = React.useId();
14221
14430
  const currentStepIndex = currentStep?.visibleIndex ?? 0;
14222
- const isFirstStep = currentStepIndex === 0;
14223
- const isLastStep = currentStepIndex === booking.steps.length - 1;
14224
- const isSubmitting = booking.status.tag === "submitting";
14225
- const handlePrimaryAction = async () => {
14226
- if (!(await booking.actions.next()).ok) return;
14227
- if (isLastStep) await onSubmit();
14228
- };
14229
14431
  if (!currentStep) return /* @__PURE__ */ jsx("div", {
14230
14432
  className: "rb-text-center rb-py-12",
14231
14433
  children: /* @__PURE__ */ jsx("p", {
@@ -14253,28 +14455,9 @@ function HeadlessBookingDefaultForm({ booking, onSubmit }) {
14253
14455
  errors: currentStep.errors,
14254
14456
  id: errorSummaryId
14255
14457
  }),
14256
- /* @__PURE__ */ jsxs("div", {
14257
- className: "rb-wizard-actions",
14258
- children: [!isFirstStep ? /* @__PURE__ */ jsx(ThemedButton, {
14259
- type: "button",
14260
- onClick: booking.actions.back,
14261
- variant: "outline",
14262
- size: "md",
14263
- label: "Back"
14264
- }) : null, /* @__PURE__ */ jsx(ThemedButton, {
14265
- type: "button",
14266
- onClick: () => {
14267
- handlePrimaryAction();
14268
- },
14269
- disabled: isSubmitting,
14270
- variant: "primary",
14271
- size: "md",
14272
- label: isLastStep ? "Complete" : "Continue",
14273
- pending: isSubmitting ? {
14274
- label: "Submitting...",
14275
- srLabel: "Submitting"
14276
- } : void 0
14277
- })]
14458
+ /* @__PURE__ */ jsx(BookingFormSubmitActions, {
14459
+ booking,
14460
+ onSubmit
14278
14461
  }),
14279
14462
  /* @__PURE__ */ jsx(DefaultBookingDiscount, { booking }),
14280
14463
  /* @__PURE__ */ jsx(DefaultBookingFeedback, { booking }),
@@ -15004,8 +15187,148 @@ function TerminalPanel({ tone, title, titleAs: Title = "h3", body, secondaryBody
15004
15187
  });
15005
15188
  }
15006
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
15007
15330
  //#region ../blocks/src/system/runtime/components/booking/SuccessMessage.tsx
15008
- const SuccessMessage = ({ message, resourceName, className }) => {
15331
+ const SuccessMessage = ({ copy, resourceName, className, demoEmailSuppressed = false, customerEmail = null }) => {
15009
15332
  return /* @__PURE__ */ jsx(TerminalPanel, {
15010
15333
  tone: "success",
15011
15334
  title: "Booking confirmed",
@@ -15013,9 +15336,15 @@ const SuccessMessage = ({ message, resourceName, className }) => {
15013
15336
  variant: "success",
15014
15337
  children: /* @__PURE__ */ jsx(CheckIcon, { strokeWidth: 3 })
15015
15338
  }),
15016
- body: /* @__PURE__ */ jsx("p", {
15017
- className: "ab-text",
15018
- children: message
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"
15019
15348
  }),
15020
15349
  secondaryBody: resourceName ? /* @__PURE__ */ jsxs("p", {
15021
15350
  className: "ab-text rb-on-surface--muted",
@@ -15051,31 +15380,54 @@ function BookingMailingListNote(props) {
15051
15380
  });
15052
15381
  }
15053
15382
  //#endregion
15054
- //#region ../blocks/src/system/runtime/nodes/booking-form.mailing-list-note.ts
15383
+ //#region ../blocks/src/system/runtime/nodes/booking-form.checkout-return-context.ts
15055
15384
  function storageKey(sessionId) {
15056
15385
  return `riverbank:booking:mailing-list:${sessionId}`;
15057
15386
  }
15058
- function saveAppointmentMailingListNote(sessionId, note) {
15059
- if (!note) return;
15387
+ function saveAppointmentCheckoutReturnContext(sessionId, context) {
15388
+ if (!context.customerEmail && !context.mailingListNote) return;
15060
15389
  try {
15061
- window.sessionStorage.setItem(storageKey(sessionId), note);
15390
+ window.sessionStorage.setItem(storageKey(sessionId), JSON.stringify(context));
15062
15391
  } catch {}
15063
15392
  }
15064
- function readAppointmentMailingListNote(sessionId) {
15393
+ function readAppointmentCheckoutReturnContext(sessionId) {
15065
15394
  try {
15066
15395
  const stored = window.sessionStorage.getItem(storageKey(sessionId));
15067
- return stored === "confirmation_required" || stored === "not_confirmed" ? stored : null;
15396
+ if (!stored) return null;
15397
+ return parseContext(stored);
15068
15398
  } catch {
15069
15399
  return null;
15070
15400
  }
15071
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
+ }
15072
15420
  //#endregion
15073
15421
  //#region ../blocks/src/system/runtime/nodes/booking-form.completion.tsx
15074
- function BookingFormCompletion({ resourceName, successMessage, redirectState, localNote }) {
15075
- const note = redirectState.kind === "success" ? readAppointmentMailingListNote(redirectState.sessionId) : localNote;
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;
15076
15426
  return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SuccessMessage, {
15077
- message: getBookingSuccessMessage(successMessage),
15078
- resourceName
15427
+ copy: getBookingSuccessCopy(successMessage),
15428
+ resourceName,
15429
+ demoEmailSuppressed,
15430
+ customerEmail: confirmedEmail
15079
15431
  }), note ? /* @__PURE__ */ jsx(BookingMailingListNote, {
15080
15432
  note,
15081
15433
  context: "booking",
@@ -15099,12 +15451,17 @@ function createBookingFormSubmitHandler(input) {
15099
15451
  cancelUrl: appendRebookFlag(cancelUrl, input.isPortalRebook)
15100
15452
  });
15101
15453
  if (!result.ok) return;
15454
+ storeDemoBookingPassIfAvailable(result.outcome.customerEmail, result.outcome.demoBookingPass);
15102
15455
  if (result.outcome.kind === "checkout_redirect") {
15103
- saveAppointmentMailingListNote(result.outcome.sessionId, result.outcome.mailingListSignupNote);
15456
+ saveAppointmentCheckoutReturnContext(result.outcome.sessionId, {
15457
+ customerEmail: result.outcome.customerEmail,
15458
+ mailingListNote: result.outcome.mailingListSignupNote ?? null
15459
+ });
15104
15460
  window.location.href = result.outcome.checkoutUrl;
15105
15461
  return;
15106
15462
  }
15107
15463
  input.setLocalMailingListNote(result.outcome.mailingListSignupNote ?? null);
15464
+ input.setLocalCustomerEmail(result.outcome.customerEmail);
15108
15465
  };
15109
15466
  }
15110
15467
  //#endregion
@@ -15144,6 +15501,7 @@ const BookingFormClient$1 = ({ siteId: siteIdProp, render }) => {
15144
15501
  const hasLoggedRebookCompletionRef = useRef(false);
15145
15502
  const [redirectState] = useState(() => getBookingRedirectStateFromLocation(getBookingRedirectLocationSnapshot()));
15146
15503
  const [localMailingListNote, setLocalMailingListNote] = useState(null);
15504
+ const [localCustomerEmail, setLocalCustomerEmail] = useState(null);
15147
15505
  const showSpamProtection = render.hydration.spamProtectionEnabled ?? isSpamProtectionEnabled();
15148
15506
  const api = useBlockApi();
15149
15507
  const hasPortalAuth = api.config.auth.type === "bearer" || api.config.authOverrides?.portal?.type === "bearer";
@@ -15226,7 +15584,8 @@ const BookingFormClient$1 = ({ siteId: siteIdProp, render }) => {
15226
15584
  booking,
15227
15585
  bookingAnchorId,
15228
15586
  isPortalRebook,
15229
- setLocalMailingListNote
15587
+ setLocalMailingListNote,
15588
+ setLocalCustomerEmail
15230
15589
  });
15231
15590
  if (viewState.kind === "success") return /* @__PURE__ */ jsx(BookingSurface, {
15232
15591
  id: bookingAnchorId,
@@ -15235,7 +15594,9 @@ const BookingFormClient$1 = ({ siteId: siteIdProp, render }) => {
15235
15594
  successMessage: render.display.successMessage,
15236
15595
  resourceName: viewState.resourceName,
15237
15596
  redirectState,
15238
- localNote: localMailingListNote
15597
+ localNote: localMailingListNote,
15598
+ customerEmail: localCustomerEmail,
15599
+ demoEmailSuppressed: render.hydration.demoEmailSuppressed
15239
15600
  })
15240
15601
  });
15241
15602
  if (viewState.kind === "verifying") return /* @__PURE__ */ jsx(BookingSurface, {
@@ -15251,6 +15612,25 @@ const BookingFormClient$1 = ({ siteId: siteIdProp, render }) => {
15251
15612
  })
15252
15613
  })
15253
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
+ });
15254
15634
  return /* @__PURE__ */ jsxs(BookingSurface, {
15255
15635
  id: bookingAnchorId,
15256
15636
  className: render.display.className,
@@ -15311,7 +15691,7 @@ function recoverRegistrationError(action, handlers) {
15311
15691
  switch (action) {
15312
15692
  case "none": return;
15313
15693
  case "portal":
15314
- window.location.assign("/portal");
15694
+ window.location.assign(CUSTOMER_PORTAL_PATH);
15315
15695
  return;
15316
15696
  case "event":
15317
15697
  window.location.assign(window.location.pathname);
@@ -15976,6 +16356,10 @@ const eventRegistrationErrors = {
15976
16356
  message: "The payment options for this event have changed. Please check the latest options before continuing.",
15977
16357
  action: "payment-options"
15978
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
+ },
15979
16363
  idempotencyConflict: {
15980
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.",
15981
16365
  action: "portal"
@@ -16163,11 +16547,50 @@ function useResolvedWaitlistClaim(deps, credential) {
16163
16547
  * ```
16164
16548
  */
16165
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
+ }
16166
16588
  /**
16167
16589
  * Hook for polling payment status after Stripe redirects.
16168
16590
  *
16169
16591
  * Pass config to start polling, or null to stop/idle.
16170
- * 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.
16171
16594
  *
16172
16595
  * @param config - Configuration for polling, or null to stop
16173
16596
  * @returns Verification result with status, data, and retry function
@@ -16176,30 +16599,7 @@ function usePaymentVerification(config) {
16176
16599
  return usePaymentVerificationWithDeps(config, paymentVerificationDeps);
16177
16600
  }
16178
16601
  function usePaymentVerificationWithDeps(config, deps) {
16179
- const api = deps.useBlockApi();
16180
- const polling = usePolling(useMemo(() => {
16181
- if (!config) return null;
16182
- return {
16183
- pollFn: () => api.getEventRegistrationStatus(config.reference),
16184
- isComplete: (result) => result.paymentStatus === "completed" || result.paymentStatus === "not_required",
16185
- isFailed: (result) => result.paymentStatus === "failed" || result.paymentStatus === "refunded",
16186
- maxAttempts: config.maxAttempts,
16187
- interval: config.pollInterval
16188
- };
16189
- }, [api, config]));
16190
- const paymentStatus = polling.result?.paymentStatus ?? null;
16191
- let errorMessage = null;
16192
- if (polling.status === "timeout") errorMessage = "Could not verify payment. If you were charged, please contact support.";
16193
- else if (polling.status === "failed" && paymentStatus) errorMessage = paymentStatus === "refunded" ? "Payment was refunded. Please contact support." : "Payment was declined. Please try again.";
16194
- else if (polling.error) errorMessage = polling.error.message;
16195
- return {
16196
- status: polling.status,
16197
- paymentStatus,
16198
- attendeeStatus: polling.result?.attendeeStatus ?? null,
16199
- waitlistPosition: polling.result?.waitlistPosition ?? null,
16200
- error: errorMessage,
16201
- retry: polling.retry
16202
- };
16602
+ return mapPaymentVerificationResult(usePolling(createPaymentPollingConfig(deps.useBlockApi(), config)));
16203
16603
  }
16204
16604
  //#endregion
16205
16605
  //#region ../blocks/src/system/runtime/nodes/event-registration/constants.ts
@@ -16572,20 +16972,9 @@ function registrationErrorPresentation(error) {
16572
16972
  function wantsMailingListSignup(options) {
16573
16973
  return options.mailingListSignup !== null && options.formData.mailingListOptIn === true;
16574
16974
  }
16575
- function createClientCommandId(cryptoSource = {
16576
- randomUUID: globalThis.crypto.randomUUID?.bind(globalThis.crypto),
16577
- getRandomValues: (bytes) => globalThis.crypto.getRandomValues(bytes)
16578
- }) {
16579
- if (cryptoSource.randomUUID) return cryptoSource.randomUUID();
16580
- const bytes = cryptoSource.getRandomValues(/* @__PURE__ */ new Uint8Array(16));
16581
- bytes[6] = (bytes[6] ?? 0) & 15 | 64;
16582
- bytes[8] = (bytes[8] ?? 0) & 63 | 128;
16583
- const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0"));
16584
- 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("")}`;
16585
- }
16586
16975
  const eventRegistrationSubmitDeps = {
16587
16976
  savePendingRegistration,
16588
- createClientCommandId
16977
+ createClientCommandId: generateUuidV4
16589
16978
  };
16590
16979
  function useEventRegistrationSubmit(options) {
16591
16980
  return useEventRegistrationSubmitWithDeps(options, eventRegistrationSubmitDeps);
@@ -16665,6 +17054,7 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
16665
17054
  };
16666
17055
  }
16667
17056
  async function completeRegistrationSubmission(options, deps, prepared, result, submitOptions) {
17057
+ if (result.demoBookingPass) storeDemoBookingPass(options.formData.email, result.demoBookingPass);
16668
17058
  switch (result.kind) {
16669
17059
  case "paymentStatusRequired":
16670
17060
  options.setPaymentStatusRecovery({
@@ -16687,6 +17077,7 @@ async function completeRegistrationSubmission(options, deps, prepared, result, s
16687
17077
  status: "waitlist",
16688
17078
  title: "Added to waitlist",
16689
17079
  message: result.waitlist.message,
17080
+ emailFollowupMessage: result.waitlist.emailFollowupMessage,
16690
17081
  mailingListSignupNote: result.mailingListSignupNote
16691
17082
  });
16692
17083
  break;