@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
@@ -684,10 +684,14 @@ function subtractDaysFromIso(isoString, dayCount) {
684
684
  return addDaysToIso(isoString, -dayCount);
685
685
  }
686
686
  var init_date_math = __esmMin((() => {}));
687
+ var init_html_entities = __esmMin((() => {}));
687
688
  var init_duration$1 = __esmMin((() => {}));
688
689
  var init_demo_capability_policy = __esmMin((() => {
689
690
  init_src$2();
690
- })), init_demo_claim_access = __esmMin((() => {})), init_demo_lifecycle_status = __esmMin((() => {}));
691
+ })), init_demo_claim_access = __esmMin((() => {}));
692
+ var init_demo_lifecycle_status = __esmMin((() => {})), init_demo_warm_pool_target = __esmMin((() => {
693
+ init_result$1();
694
+ }));
691
695
  var init_demo_runtime = __esmMin((() => {}));
692
696
  var init_collections = __esmMin((() => {}));
693
697
  //#endregion
@@ -707,6 +711,19 @@ function parseCurrencyCode(value) {
707
711
  function resolveCurrencyLocale(currencyCode, override) {
708
712
  return override ?? CURRENCY_LOCALE_BY_CODE[currencyCode] ?? "en";
709
713
  }
714
+ function fractionDigitsFor(decimals, exactFormatter) {
715
+ switch (decimals) {
716
+ case "exact": return {};
717
+ case "auto": return {
718
+ minimumFractionDigits: 0,
719
+ maximumFractionDigits: exactFormatter.resolvedOptions().maximumFractionDigits
720
+ };
721
+ case "whole": return {
722
+ minimumFractionDigits: 0,
723
+ maximumFractionDigits: 0
724
+ };
725
+ }
726
+ }
710
727
  /**
711
728
  * The single currency-amount formatter for the product: minor units in,
712
729
  * localized string out.
@@ -717,6 +734,13 @@ function resolveCurrencyLocale(currencyCode, override) {
717
734
  * own `Intl.NumberFormat`.
718
735
  */
719
736
  function formatCurrencyAmount(amountCents, currency, options) {
737
+ return formatCurrencyMajorUnits(amountCents / 100, currency, options);
738
+ }
739
+ /**
740
+ * `formatCurrencyAmount` for an amount already in MAJOR units (29.99 = £29.99),
741
+ * such as a registrar price. Prefer minor units everywhere else.
742
+ */
743
+ function formatCurrencyMajorUnits(amount, currency, options) {
720
744
  const currencyCode = currency.toUpperCase();
721
745
  const locale = resolveCurrencyLocale(currencyCode, options?.locale);
722
746
  try {
@@ -724,17 +748,13 @@ function formatCurrencyAmount(amountCents, currency, options) {
724
748
  style: "currency",
725
749
  currency: currencyCode
726
750
  });
727
- const fractionDigits = options?.decimals === "auto" ? {
728
- minimumFractionDigits: 0,
729
- maximumFractionDigits: exactFormatter.resolvedOptions().maximumFractionDigits
730
- } : {};
731
751
  return new Intl.NumberFormat(locale, {
732
752
  style: "currency",
733
753
  currency: currencyCode,
734
- ...fractionDigits
735
- }).format(amountCents / 100);
754
+ ...fractionDigitsFor(options?.decimals ?? "exact", exactFormatter)
755
+ }).format(amount);
736
756
  } catch {
737
- return `${(amountCents / 100).toFixed(2)} ${currencyCode}`;
757
+ return `${amount.toFixed(2)} ${currencyCode}`;
738
758
  }
739
759
  }
740
760
  var CURRENCY_CODE_INPUT_PATTERN, CURRENCY_LOCALE_BY_CODE;
@@ -1018,7 +1038,7 @@ function parseEventPageSurfaceDestinationMode(value) {
1018
1038
  return value === "cms-managed" || value === "system-managed" ? value : void 0;
1019
1039
  }
1020
1040
  function parseEventPageSurfaceSubject(value) {
1021
- if (!isRecord$30(value)) return err$2({ kind: "notObject" });
1041
+ if (!isRecord$32(value)) return err$2({ kind: "notObject" });
1022
1042
  switch (value.kind) {
1023
1043
  case "eventSeries": {
1024
1044
  const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
@@ -1073,7 +1093,7 @@ function parseEventSeriesIdList(values) {
1073
1093
  }
1074
1094
  return ok$2(parsed);
1075
1095
  }
1076
- function isRecord$30(value) {
1096
+ function isRecord$32(value) {
1077
1097
  return typeof value === "object" && value !== null && !Array.isArray(value);
1078
1098
  }
1079
1099
  var init_event_page_surface_subject = __esmMin((() => {
@@ -1627,7 +1647,15 @@ var init_try_async = __esmMin((() => {
1627
1647
  init_result$1();
1628
1648
  }));
1629
1649
  var init_narrow_result = __esmMin((() => {}));
1630
- var init_editor_state = __esmMin((() => {})), init_block_content_identity = __esmMin((() => {}));
1650
+ var init_editor_state = __esmMin((() => {}));
1651
+ var init_editor_value_sync = __esmMin((() => {
1652
+ init_assert_never();
1653
+ }));
1654
+ var init_edit_lease = __esmMin((() => {
1655
+ init_branded();
1656
+ })), init_block_content_identity = __esmMin((() => {
1657
+ init_branded();
1658
+ }));
1631
1659
  var init_sensitive_collection = __esmMin((() => {}));
1632
1660
  //#endregion
1633
1661
  //#region ../core/src/assertNever.ts
@@ -1646,7 +1674,7 @@ var init_public_profile = __esmMin((() => {
1646
1674
  var init_public_experience = __esmMin((() => {}));
1647
1675
  //#endregion
1648
1676
  //#region ../core/src/rich-text.ts
1649
- function isRecord$28(value) {
1677
+ function isRecord$30(value) {
1650
1678
  return typeof value === "object" && value !== null && !Array.isArray(value);
1651
1679
  }
1652
1680
  function hasOnlyKeys(value, allowed) {
@@ -1657,10 +1685,10 @@ function isDenseArrayOf(value, predicate) {
1657
1685
  return true;
1658
1686
  }
1659
1687
  function isTipTapMark(value) {
1660
- return isRecord$28(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$28(value.attrs));
1688
+ return isRecord$30(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$30(value.attrs));
1661
1689
  }
1662
1690
  function isTipTapNode(value) {
1663
- if (!isRecord$28(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$28(value.attrs) || value.marks !== void 0 && (!Array.isArray(value.marks) || !isDenseArrayOf(value.marks, isTipTapMark)) || value.content !== void 0 && (!Array.isArray(value.content) || !isDenseArrayOf(value.content, isTipTapNode))) return false;
1691
+ if (!isRecord$30(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$30(value.attrs) || value.marks !== void 0 && (!Array.isArray(value.marks) || !isDenseArrayOf(value.marks, isTipTapMark)) || value.content !== void 0 && (!Array.isArray(value.content) || !isDenseArrayOf(value.content, isTipTapNode))) return false;
1664
1692
  if (value.type === "text") return typeof value.text === "string" && value.text.length > 0 && value.content === void 0;
1665
1693
  return value.text === void 0;
1666
1694
  }
@@ -1705,10 +1733,10 @@ var init_mailing_list_identifiers = __esmMin((() => {
1705
1733
  //#endregion
1706
1734
  //#region ../core/src/mailing-list-targeting-parser.ts
1707
1735
  function parseMailingListPlacementTargeting(value) {
1708
- if (!isRecord$27(value)) return targetingError("shape");
1736
+ if (!isRecord$29(value)) return targetingError("shape");
1709
1737
  if (value.mode === "default") return ok$2({ mode: "default" });
1710
1738
  if (value.mode !== "custom") return targetingError("mode");
1711
- if (!isRecord$27(value.selection)) return targetingError("selection");
1739
+ if (!isRecord$29(value.selection)) return targetingError("selection");
1712
1740
  switch (value.provider) {
1713
1741
  case "native": return parseNativeTargeting(value.selection);
1714
1742
  case "brevo": return parseBrevoTargeting(value.selection);
@@ -1717,7 +1745,7 @@ function parseMailingListPlacementTargeting(value) {
1717
1745
  }
1718
1746
  }
1719
1747
  function parseMailingListVisitorSelection(value) {
1720
- if (!isRecord$27(value)) return visitorSelectionError$1("shape");
1748
+ if (!isRecord$29(value)) return visitorSelectionError$1("shape");
1721
1749
  switch (value.provider) {
1722
1750
  case "native": {
1723
1751
  const topicIds = parseVisitorIds(value.topicIds, parseNewsletterListId);
@@ -1850,7 +1878,7 @@ function parseVisitorIds(value, parseId) {
1850
1878
  }
1851
1879
  return parsed;
1852
1880
  }
1853
- function isRecord$27(value) {
1881
+ function isRecord$29(value) {
1854
1882
  return typeof value === "object" && value !== null && !Array.isArray(value);
1855
1883
  }
1856
1884
  function targetingError(field) {
@@ -1907,7 +1935,7 @@ var init_mailing_list_setup = __esmMin((() => {
1907
1935
  //#endregion
1908
1936
  //#region ../core/src/mailing-list-setup-parser.ts
1909
1937
  function parseMailingListGlobalForm(value) {
1910
- if (!isRecord$23(value)) return formError("shape");
1938
+ if (!isRecord$25(value)) return formError("shape");
1911
1939
  const fields = parseGlobalFields(value.fields);
1912
1940
  if (fields === null) return formError("fields");
1913
1941
  if (typeof value.includeOptionalPhone !== "boolean") return formError("includeOptionalPhone");
@@ -1926,7 +1954,7 @@ function parseMailingListGlobalForm(value) {
1926
1954
  });
1927
1955
  }
1928
1956
  function parseGlobalFields(value) {
1929
- if (!isRecord$23(value) || typeof value.preset !== "string") return null;
1957
+ if (!isRecord$25(value) || typeof value.preset !== "string") return null;
1930
1958
  switch (value.preset) {
1931
1959
  case "emailOnly": return { preset: "emailOnly" };
1932
1960
  case "emailName": return isRequirement(value.name) ? {
@@ -1963,7 +1991,7 @@ function parseOptionalString(value) {
1963
1991
  function isRequirement(value) {
1964
1992
  return value === "required" || value === "optional";
1965
1993
  }
1966
- function isRecord$23(value) {
1994
+ function isRecord$25(value) {
1967
1995
  return typeof value === "object" && value !== null && !Array.isArray(value);
1968
1996
  }
1969
1997
  function formError(field) {
@@ -2021,7 +2049,7 @@ var init_mailing_list_targeting = __esmMin((() => {
2021
2049
  //#endregion
2022
2050
  //#region ../core/src/mailing-list-runtime.ts
2023
2051
  function parseMailingListRuntimeContext(value) {
2024
- if (!isRecord$22(value)) return invalidRuntimeContext();
2052
+ if (!isRecord$24(value)) return invalidRuntimeContext();
2025
2053
  if (value.tag === "not_configured") return ok$2({ tag: "not_configured" });
2026
2054
  if (value.tag !== "configured") return invalidRuntimeContext();
2027
2055
  return parseConfiguredRuntimeContext(value);
@@ -2049,7 +2077,7 @@ function parseBookingSignupOffer(value) {
2049
2077
  tag: "unavailable",
2050
2078
  reason: "disabled"
2051
2079
  };
2052
- if (!isRecord$22(value)) return null;
2080
+ if (!isRecord$24(value)) return null;
2053
2081
  if (value.tag === "offered") return { tag: "offered" };
2054
2082
  if (value.tag === "unavailable" && (value.reason === "disabled" || value.reason === "fields" || value.reason === "destination")) return {
2055
2083
  tag: "unavailable",
@@ -2058,7 +2086,7 @@ function parseBookingSignupOffer(value) {
2058
2086
  return null;
2059
2087
  }
2060
2088
  function parseRuntimeProvider(value) {
2061
- if (!isRecord$22(value)) return null;
2089
+ if (!isRecord$24(value)) return null;
2062
2090
  switch (value.provider) {
2063
2091
  case "native": return parseNativeRuntimeProvider(value);
2064
2092
  case "brevo": return parseBrevoRuntimeProvider(value);
@@ -2090,7 +2118,7 @@ function parseMailchimpRuntimeProvider(value) {
2090
2118
  if (defaultAudienceId === null) return null;
2091
2119
  const audiences = [];
2092
2120
  for (const audience of value.audiences) {
2093
- if (!isRecord$22(audience)) return null;
2121
+ if (!isRecord$24(audience)) return null;
2094
2122
  const id = parseMailchimpAudienceId(audience.id);
2095
2123
  const name = parseName(audience.name);
2096
2124
  if (id === null || name === null || !Array.isArray(audience.interests)) return null;
@@ -2111,7 +2139,7 @@ function parseMailchimpRuntimeProvider(value) {
2111
2139
  function parseMailchimpInterests(value) {
2112
2140
  const interests = [];
2113
2141
  for (const interest of value) {
2114
- if (!isRecord$22(interest)) return null;
2142
+ if (!isRecord$24(interest)) return null;
2115
2143
  const id = parseMailchimpInterestId(interest.id);
2116
2144
  const name = parseName(interest.name);
2117
2145
  const categoryName = parseName(interest.categoryName);
@@ -2128,7 +2156,7 @@ function parseNamedItems(value, parseId) {
2128
2156
  if (!Array.isArray(value)) return null;
2129
2157
  const items = [];
2130
2158
  for (const item of value) {
2131
- if (!isRecord$22(item)) return null;
2159
+ if (!isRecord$24(item)) return null;
2132
2160
  const id = parseId(item.id);
2133
2161
  const name = parseName(item.name);
2134
2162
  if (id === null || name === null) return null;
@@ -2144,7 +2172,7 @@ function parseName(value) {
2144
2172
  const name = value.trim();
2145
2173
  return name.length > 0 ? name : null;
2146
2174
  }
2147
- function isRecord$22(value) {
2175
+ function isRecord$24(value) {
2148
2176
  return typeof value === "object" && value !== null && !Array.isArray(value);
2149
2177
  }
2150
2178
  function invalidRuntimeContext() {
@@ -2194,6 +2222,14 @@ var init_csv_render = __esmMin((() => {
2194
2222
  }));
2195
2223
  var init_csv_types = __esmMin((() => {})), init_email_format = __esmMin((() => {}));
2196
2224
  var init_slug = __esmMin((() => {}));
2225
+ function generateUuidV4(cryptoSource = globalThis.crypto) {
2226
+ if (typeof cryptoSource.randomUUID === "function") return cryptoSource.randomUUID();
2227
+ const bytes = cryptoSource.getRandomValues(/* @__PURE__ */ new Uint8Array(16));
2228
+ bytes[6] = (bytes[6] ?? 0) & 15 | 64;
2229
+ bytes[8] = (bytes[8] ?? 0) & 63 | 128;
2230
+ const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0"));
2231
+ 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("")}`;
2232
+ }
2197
2233
  var init_uuid = __esmMin((() => {}));
2198
2234
  function sortStableJsonValue(value) {
2199
2235
  if (value === null) return null;
@@ -2560,10 +2596,12 @@ var init_event_catalogue = __esmMin((() => {
2560
2596
  var init_src$2 = __esmMin((() => {
2561
2597
  init_branded();
2562
2598
  init_date_math();
2599
+ init_html_entities();
2563
2600
  init_duration$1();
2564
2601
  init_demo_capability_policy();
2565
2602
  init_demo_claim_access();
2566
2603
  init_demo_lifecycle_status();
2604
+ init_demo_warm_pool_target();
2567
2605
  init_demo_runtime();
2568
2606
  init_collections();
2569
2607
  init_event_booking_offer();
@@ -2590,6 +2628,8 @@ var init_src$2 = __esmMin((() => {
2590
2628
  init_narrow_result();
2591
2629
  init_non_empty_array();
2592
2630
  init_editor_state();
2631
+ init_editor_value_sync();
2632
+ init_edit_lease();
2593
2633
  init_block_content_identity();
2594
2634
  init_sensitive_collection();
2595
2635
  init_assertNever$1();
@@ -2687,9 +2727,13 @@ var init_fileStorage = __esmMin((() => {
2687
2727
  FILE_STORAGE_BUCKETS = {
2688
2728
  publicSite: unsafeAsStorageBucketName("media"),
2689
2729
  privateSite: unsafeAsStorageBucketName("site-files-private"),
2690
- temporary: unsafeAsStorageBucketName("temp-uploads")
2730
+ temporary: unsafeAsStorageBucketName("temp-uploads"),
2731
+ siteAssets: unsafeAsStorageBucketName("site-assets"),
2732
+ siteFonts: unsafeAsStorageBucketName("site-fonts"),
2733
+ bookingRequirementDocuments: unsafeAsStorageBucketName("booking-requirement-documents")
2691
2734
  };
2692
- FILE_STORAGE_BUCKETS.publicSite, unsafeAsStorageBucketName("site-assets"), unsafeAsStorageBucketName("site-fonts");
2735
+ FILE_STORAGE_BUCKETS.publicSite, FILE_STORAGE_BUCKETS.siteAssets, FILE_STORAGE_BUCKETS.siteFonts;
2736
+ FILE_STORAGE_BUCKETS.publicSite, FILE_STORAGE_BUCKETS.privateSite, FILE_STORAGE_BUCKETS.temporary, FILE_STORAGE_BUCKETS.siteAssets, FILE_STORAGE_BUCKETS.siteFonts, FILE_STORAGE_BUCKETS.bookingRequirementDocuments;
2693
2737
  PRIVATE_SITE_FILE_BUCKET_MIME_TYPES = [
2694
2738
  "application/pdf",
2695
2739
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
@@ -2764,11 +2808,11 @@ var init_storagePathDomain = __esmMin((() => {}));
2764
2808
  var init_fileAssetLegacyProjection = __esmMin((() => {}));
2765
2809
  //#endregion
2766
2810
  //#region ../media-core/src/typeGuards.ts
2767
- function isRecord$20(value) {
2811
+ function isRecord$22(value) {
2768
2812
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2769
2813
  }
2770
2814
  function asRecord$1(value) {
2771
- return isRecord$20(value) ? value : void 0;
2815
+ return isRecord$22(value) ? value : void 0;
2772
2816
  }
2773
2817
  var init_typeGuards$1 = __esmMin((() => {}));
2774
2818
  function isFileJsonObject(value) {
@@ -2778,7 +2822,7 @@ function isFileJsonValue(value) {
2778
2822
  if (value === null || typeof value === "string" || typeof value === "boolean") return true;
2779
2823
  if (typeof value === "number") return Number.isFinite(value);
2780
2824
  if (Array.isArray(value)) return value.every(isFileJsonValue);
2781
- return isRecord$20(value) && isFileJsonObject(value);
2825
+ return isRecord$22(value) && isFileJsonObject(value);
2782
2826
  }
2783
2827
  var init_filePersistence = __esmMin((() => {
2784
2828
  init_src$2();
@@ -3086,7 +3130,7 @@ function isCmsMediaObjectType(value) {
3086
3130
  return typeof value === "string" && CMS_MEDIA_OBJECT_TYPES.includes(value);
3087
3131
  }
3088
3132
  function isCmsMediaObject(value) {
3089
- if (!isRecord$20(value)) return false;
3133
+ if (!isRecord$22(value)) return false;
3090
3134
  const type = value.type;
3091
3135
  if (!isCmsMediaObjectType(type)) return false;
3092
3136
  if ("attrs" in value) return false;
@@ -3097,7 +3141,7 @@ function collectMediaObjects(value, out, location = "") {
3097
3141
  value.forEach((item, index) => collectMediaObjects(item, out, `${location}[${index}]`));
3098
3142
  return;
3099
3143
  }
3100
- if (!isRecord$20(value)) return;
3144
+ if (!isRecord$22(value)) return;
3101
3145
  if (isCmsMediaObject(value)) out.push({
3102
3146
  obj: value,
3103
3147
  location
@@ -3131,8 +3175,8 @@ function walkAndCollectImageAttrs(value, out, location = "") {
3131
3175
  value.forEach((item, index) => walkAndCollectImageAttrs(item, out, `${location}[${index}]`));
3132
3176
  return;
3133
3177
  }
3134
- if (!isRecord$20(value)) return;
3135
- if (value.type === "image" && isRecord$20(value.attrs)) out.push({
3178
+ if (!isRecord$22(value)) return;
3179
+ if (value.type === "image" && isRecord$22(value.attrs)) out.push({
3136
3180
  attrs: value.attrs,
3137
3181
  location: location ? `${location}.attrs` : "attrs"
3138
3182
  });
@@ -3192,7 +3236,7 @@ function mediaIdentifierOrFallback(current, fallback) {
3192
3236
  var init_renderableMediaAsset = __esmMin((() => {}));
3193
3237
  //#endregion
3194
3238
  //#region ../media-core/src/contentMediaAudit.ts
3195
- function isRecord$19(value) {
3239
+ function isRecord$21(value) {
3196
3240
  return typeof value === "object" && value !== null && !Array.isArray(value);
3197
3241
  }
3198
3242
  function summarizeContentMediaValue(value) {
@@ -3203,7 +3247,7 @@ function summarizeContentMediaValue(value) {
3203
3247
  }
3204
3248
  if (value === null) return "null";
3205
3249
  if (Array.isArray(value)) return `array(${value.length})`;
3206
- if (isRecord$19(value)) return `object(${Object.keys(value).sort().join(",")})`;
3250
+ if (isRecord$21(value)) return `object(${Object.keys(value).sort().join(",")})`;
3207
3251
  return typeof value;
3208
3252
  }
3209
3253
  function auditMediaValue(context, path, allowedMediaTypes, value) {
@@ -3227,9 +3271,9 @@ function auditMediaValue(context, path, allowedMediaTypes, value) {
3227
3271
  allowedMediaTypes
3228
3272
  }];
3229
3273
  }
3230
- const hasValidIdentifier = isRecord$19(value) && typeof value.identifier === "string" && value.identifier.trim().length > 0;
3231
- const hasValidExplicitType = isRecord$19(value) && (!("type" in value) || typeof value.type === "string" && allowedMediaTypes.includes(value.type));
3232
- const hasRetiredEnvironmentField = isRecord$19(value) && ("assetId" in value || "storagePath" in value || "storageBucket" in value || "src" in value || "mimeType" in value || looksLikeUuid(value.id));
3274
+ const hasValidIdentifier = isRecord$21(value) && typeof value.identifier === "string" && value.identifier.trim().length > 0;
3275
+ const hasValidExplicitType = isRecord$21(value) && (!("type" in value) || typeof value.type === "string" && allowedMediaTypes.includes(value.type));
3276
+ const hasRetiredEnvironmentField = isRecord$21(value) && ("assetId" in value || "storagePath" in value || "storageBucket" in value || "src" in value || "mimeType" in value || looksLikeUuid(value.id));
3233
3277
  if (hasValidIdentifier && hasValidExplicitType && !hasRetiredEnvironmentField) return [];
3234
3278
  return [{
3235
3279
  tag: "malformed-object",
@@ -3240,7 +3284,7 @@ function auditMediaValue(context, path, allowedMediaTypes, value) {
3240
3284
  }];
3241
3285
  }
3242
3286
  function auditFields(context, fields, value, parentPath) {
3243
- if (!isRecord$19(value)) return [];
3287
+ if (!isRecord$21(value)) return [];
3244
3288
  const findings = [];
3245
3289
  for (const field of fields) {
3246
3290
  if (!(field.id in value)) continue;
@@ -3257,7 +3301,7 @@ function auditFields(context, fields, value, parentPath) {
3257
3301
  if (!Array.isArray(fieldValue)) break;
3258
3302
  for (const [index, item] of fieldValue.entries()) {
3259
3303
  const itemPath = [...fieldPath, index];
3260
- if (!isRecord$19(item)) {
3304
+ if (!isRecord$21(item)) {
3261
3305
  findings.push({
3262
3306
  tag: "missing-schema",
3263
3307
  context,
@@ -3291,7 +3335,7 @@ var init_contentMediaAudit = __esmMin((() => {
3291
3335
  }));
3292
3336
  //#endregion
3293
3337
  //#region ../media-core/src/contentMediaAuditFieldAdapter.ts
3294
- function isRecord$18(value) {
3338
+ function isRecord$20(value) {
3295
3339
  return typeof value === "object" && value !== null && !Array.isArray(value);
3296
3340
  }
3297
3341
  function unknownArray(value) {
@@ -3300,7 +3344,7 @@ function unknownArray(value) {
3300
3344
  function fieldsArray(value) {
3301
3345
  const directFields = unknownArray(value);
3302
3346
  if (directFields) return directFields;
3303
- if (!isRecord$18(value)) return null;
3347
+ if (!isRecord$20(value)) return null;
3304
3348
  return unknownArray(value.fields);
3305
3349
  }
3306
3350
  function nestedFields(field) {
@@ -3365,7 +3409,7 @@ function mergeFields(fields) {
3365
3409
  }
3366
3410
  function adaptFields(rawFields, flattenRepeaterGroups = false, defaultFileKinds = ["document"]) {
3367
3411
  return mergeFields(rawFields.flatMap((rawField) => {
3368
- if (!isRecord$18(rawField)) return [];
3412
+ if (!isRecord$20(rawField)) return [];
3369
3413
  const { id, type } = rawField;
3370
3414
  if (typeof id !== "string" || !id || typeof type !== "string") return [];
3371
3415
  if (type === "media" || type === "file") return [{
@@ -3373,7 +3417,7 @@ function adaptFields(rawFields, flattenRepeaterGroups = false, defaultFileKinds
3373
3417
  id,
3374
3418
  allowedMediaTypes: allowedMediaTypes(rawField, type, defaultFileKinds)
3375
3419
  }];
3376
- if (flattenRepeaterGroups && type === "group" && isRecord$18(rawField.ui) && rawField.ui.flattenInRepeater === true) return adaptFields(nestedFields(rawField), false, defaultFileKinds);
3420
+ if (flattenRepeaterGroups && type === "group" && isRecord$20(rawField.ui) && rawField.ui.flattenInRepeater === true) return adaptFields(nestedFields(rawField), false, defaultFileKinds);
3377
3421
  if (type === "group" || type === "modal") return [{
3378
3422
  kind: "object",
3379
3423
  id,
@@ -3382,14 +3426,14 @@ function adaptFields(rawFields, flattenRepeaterGroups = false, defaultFileKinds
3382
3426
  if (type === "tabGroup") return [{
3383
3427
  kind: "object",
3384
3428
  id,
3385
- fields: adaptFields((unknownArray(rawField.tabs) ?? []).flatMap((tab) => isRecord$18(tab) ? unknownArray(tab.fields) ?? [] : []), false, defaultFileKinds)
3429
+ fields: adaptFields((unknownArray(rawField.tabs) ?? []).flatMap((tab) => isRecord$20(tab) ? unknownArray(tab.fields) ?? [] : []), false, defaultFileKinds)
3386
3430
  }];
3387
3431
  if (type !== "repeater") return [];
3388
- if (isRecord$18(rawField.itemTypes)) return [{
3432
+ if (isRecord$20(rawField.itemTypes)) return [{
3389
3433
  kind: "repeater",
3390
3434
  id,
3391
3435
  mode: "variants",
3392
- variants: Object.entries(rawField.itemTypes).flatMap(([typeId, itemType]) => isRecord$18(itemType) && Array.isArray(itemType.fields) ? [{
3436
+ variants: Object.entries(rawField.itemTypes).flatMap(([typeId, itemType]) => isRecord$20(itemType) && Array.isArray(itemType.fields) ? [{
3393
3437
  typeId,
3394
3438
  fields: adaptFields(itemType.fields, true, defaultFileKinds)
3395
3439
  }] : []),
@@ -8177,7 +8221,7 @@ var init_interactionPalette = __esmMin((() => {
8177
8221
  //#endregion
8178
8222
  //#region ../theme-core/src/boxBackgroundSchema.ts
8179
8223
  function normalizeAuthoringOpacity(value) {
8180
- if (!isRecord$17(value)) return value;
8224
+ if (!isRecord$19(value)) return value;
8181
8225
  return {
8182
8226
  ...value,
8183
8227
  opacity: normalizeOpacity(value.opacity)
@@ -8186,7 +8230,7 @@ function normalizeAuthoringOpacity(value) {
8186
8230
  function normalizeOpacity(value) {
8187
8231
  return typeof value === "number" && value > 1 && value <= 100 ? value / 100 : value;
8188
8232
  }
8189
- function isRecord$17(value) {
8233
+ function isRecord$19(value) {
8190
8234
  return typeof value === "object" && value !== null && !Array.isArray(value);
8191
8235
  }
8192
8236
  var boxBackgroundOverlaySchema, commonSchema, mediaPresentationSchema, boxBackgroundSchema;
@@ -9005,7 +9049,7 @@ var init_media$1 = __esmMin((() => {
9005
9049
  /**
9006
9050
  * Strict record guard: excludes null, primitives, and arrays.
9007
9051
  */
9008
- function isRecord$16(value) {
9052
+ function isRecord$18(value) {
9009
9053
  return typeof value === "object" && value !== null && !Array.isArray(value);
9010
9054
  }
9011
9055
  var init_typeGuards = __esmMin((() => {}));
@@ -9374,7 +9418,6 @@ var init_schemas = __esmMin((() => {
9374
9418
  description: z.string().nullable(),
9375
9419
  content: z.object({ body: RichTextDocSchema.nullable().optional() }).optional(),
9376
9420
  presentation: z.object({
9377
- cardTitleOverride: z.string().nullable().optional(),
9378
9421
  summary: z.string().nullable().optional(),
9379
9422
  image: mediaSchema.nullable().optional()
9380
9423
  }).optional(),
@@ -9407,6 +9450,7 @@ var init_schemas = __esmMin((() => {
9407
9450
  "archived"
9408
9451
  ]).optional(),
9409
9452
  timeZone: z.string(),
9453
+ siteTimeZone: z.string().optional(),
9410
9454
  pricing: publicEventPricingSchema,
9411
9455
  paymentTerms: blockBookingPaymentTermsSchema,
9412
9456
  cancellationPolicy: z.object({ refunds: z.object({
@@ -10112,7 +10156,7 @@ function encodePublicProductCategorySelector(selector) {
10112
10156
  };
10113
10157
  }
10114
10158
  }
10115
- function isRecord$15(value) {
10159
+ function isRecord$17(value) {
10116
10160
  return typeof value === "object" && value !== null;
10117
10161
  }
10118
10162
  function isJsonResponseContentType(contentType) {
@@ -10136,15 +10180,15 @@ async function parseJsonBody(response) {
10136
10180
  }
10137
10181
  }
10138
10182
  function isFieldError(value) {
10139
- return isRecord$15(value) && !Array.isArray(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
10183
+ return isRecord$17(value) && !Array.isArray(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
10140
10184
  }
10141
10185
  function fieldErrorsFromUnknown(value) {
10142
10186
  if (!Array.isArray(value)) return void 0;
10143
10187
  return value.every(isFieldError) ? value : void 0;
10144
10188
  }
10145
10189
  function getBlockApiErrorDetails(data) {
10146
- if (!isRecord$15(data)) return {};
10147
- const nestedError = isRecord$15(data.error) ? data.error : void 0;
10190
+ if (!isRecord$17(data)) return {};
10191
+ const nestedError = isRecord$17(data.error) ? data.error : void 0;
10148
10192
  const message = typeof nestedError?.message === "string" ? nestedError.message : typeof data.message === "string" ? data.message : void 0;
10149
10193
  const code = typeof nestedError?.code === "string" ? nestedError.code : typeof data.code === "string" ? data.code : void 0;
10150
10194
  const fieldErrors = fieldErrorsFromUnknown(nestedError?.fieldErrors) ?? fieldErrorsFromUnknown(data.fieldErrors);
@@ -10713,10 +10757,11 @@ function createBlockApi(config) {
10713
10757
  },
10714
10758
  async sendMagicLink(data) {
10715
10759
  const sid = requireSiteId();
10716
- await request(PORTAL.sendMagicLink, { body: {
10760
+ return request(PORTAL.sendMagicLink, { body: {
10717
10761
  siteId: sid,
10718
10762
  email: data.email,
10719
- redirectUrl: data.redirectUrl
10763
+ redirectUrl: data.redirectUrl,
10764
+ demoBookingPass: data.demoBookingPass
10720
10765
  } });
10721
10766
  },
10722
10767
  async logout() {
@@ -11158,11 +11203,11 @@ var UnsafePathSegmentError = class extends Error {
11158
11203
  function assertSafePathSegments(segments) {
11159
11204
  for (const segment of segments) if (typeof segment === "string" && UNSAFE_PATH_SEGMENTS.has(segment)) throw new UnsafePathSegmentError(segment);
11160
11205
  }
11161
- function isRecord$14(value) {
11206
+ function isRecord$16(value) {
11162
11207
  return typeof value === "object" && value !== null && !Array.isArray(value);
11163
11208
  }
11164
11209
  function isPathContainer(value) {
11165
- return Array.isArray(value) || isRecord$14(value);
11210
+ return Array.isArray(value) || isRecord$16(value);
11166
11211
  }
11167
11212
  function getContainerValue(container, segment) {
11168
11213
  if (typeof segment === "number") return Array.isArray(container) ? container[segment] : void 0;
@@ -14149,7 +14194,7 @@ function parseSiteIconStyleGuideVersionId(value) {
14149
14194
  //#region ../blocks/src/system/icons/value.ts
14150
14195
  init_semantic();
14151
14196
  const NO_BLOCK_ICON_VALUE = { kind: "none" };
14152
- function isRecord$13(value) {
14197
+ function isRecord$15(value) {
14153
14198
  return typeof value === "object" && value !== null && !Array.isArray(value);
14154
14199
  }
14155
14200
  function parseBlockIconValue(value) {
@@ -14157,7 +14202,7 @@ function parseBlockIconValue(value) {
14157
14202
  kind: "semantic",
14158
14203
  iconId: value
14159
14204
  };
14160
- if (!isRecord$13(value)) return NO_BLOCK_ICON_VALUE;
14205
+ if (!isRecord$15(value)) return NO_BLOCK_ICON_VALUE;
14161
14206
  switch (value.kind) {
14162
14207
  case "none": return NO_BLOCK_ICON_VALUE;
14163
14208
  case "semantic": return isSemanticIconId(value.iconId) ? {
@@ -14230,7 +14275,7 @@ function buildGeneratedBlockIconRenderAssetLookupFromUnknown(value) {
14230
14275
  if (!Array.isArray(value)) return { kind: "invalid_asset_list" };
14231
14276
  const inputs = [];
14232
14277
  for (const [index, item] of value.entries()) {
14233
- if (!isRecord$13(item)) return {
14278
+ if (!isRecord$15(item)) return {
14234
14279
  kind: "invalid_asset_entry",
14235
14280
  index,
14236
14281
  reason: "not_object"
@@ -14350,11 +14395,11 @@ function resolveFeatureCardGeneratedIconSizePx(value) {
14350
14395
  const parsed = parseFeatureCardGeneratedIconSizePx(value);
14351
14396
  return parsed.ok ? parsed.value : unsafeAsFeatureCardGeneratedIconSizePx(FEATURE_CARD_GENERATED_ICON_SIZE_PX.default);
14352
14397
  }
14353
- function isRecord$12(value) {
14398
+ function isRecord$14(value) {
14354
14399
  return typeof value === "object" && value !== null && !Array.isArray(value);
14355
14400
  }
14356
14401
  function toPlainTextFromTipTap(value) {
14357
- if (!isRecord$12(value)) return "";
14402
+ if (!isRecord$14(value)) return "";
14358
14403
  if (typeof value.text === "string") return value.text;
14359
14404
  const content = value.content;
14360
14405
  if (!Array.isArray(content)) return "";
@@ -16091,7 +16136,7 @@ function successSubmissionFeedback(message) {
16091
16136
  message
16092
16137
  };
16093
16138
  }
16094
- function isRecord$10(value) {
16139
+ function isRecord$12(value) {
16095
16140
  return typeof value === "object" && value !== null && !Array.isArray(value);
16096
16141
  }
16097
16142
  function deepEqualJsonValue(left, right) {
@@ -16101,8 +16146,8 @@ function deepEqualJsonValue(left, right) {
16101
16146
  if (left.length !== right.length) return false;
16102
16147
  return left.every((item, index) => deepEqualJsonValue(item, right[index]));
16103
16148
  }
16104
- if (isRecord$10(left) || isRecord$10(right)) {
16105
- if (!isRecord$10(left) || !isRecord$10(right)) return false;
16149
+ if (isRecord$12(left) || isRecord$12(right)) {
16150
+ if (!isRecord$12(left) || !isRecord$12(right)) return false;
16106
16151
  const leftKeys = Object.keys(left).sort();
16107
16152
  if (!deepEqualJsonValue(leftKeys, Object.keys(right).sort())) return false;
16108
16153
  return leftKeys.every((key) => deepEqualJsonValue(left[key], right[key]));
@@ -16207,7 +16252,7 @@ function resolveAppointmentCheckoutVerificationState(input) {
16207
16252
  tag: "timeout",
16208
16253
  sessionId: input.config.sessionId,
16209
16254
  appointmentId,
16210
- message: "Could not verify your appointment payment. If you were charged, please contact support."
16255
+ message: "We’re still confirming your payment. This can take a minute – you can check again, and you won’t be charged twice."
16211
16256
  };
16212
16257
  if (input.pollingStatus === "failed") {
16213
16258
  if (paymentStatus === "refunded") return {
@@ -16271,7 +16316,7 @@ function deriveBookingFormViewState(input) {
16271
16316
  message: input.verificationState.message
16272
16317
  };
16273
16318
  case "timeout": return {
16274
- kind: "error",
16319
+ kind: "timeout",
16275
16320
  message: input.verificationState.message
16276
16321
  };
16277
16322
  case "confirmed": return {
@@ -16285,12 +16330,12 @@ function resolveBookingSiteId(siteId, form) {
16285
16330
  return siteId || form?.siteId || "";
16286
16331
  }
16287
16332
  function normalizeBookingFormConfig(form) {
16288
- if (!isRecord$9(form)) return null;
16333
+ if (!isRecord$11(form)) return null;
16289
16334
  const id = readNonEmptyString(form.id);
16290
16335
  const name = readNonEmptyString(form.name);
16291
16336
  if (!id || !name) return null;
16292
- const schemaSource = isRecord$9(form.schema) ? form.schema : isRecord$9(form.schemaJson) ? form.schemaJson : null;
16293
- const settingsSource = isRecord$9(form.settings) ? form.settings : isRecord$9(form.settingsJson) ? form.settingsJson : null;
16337
+ const schemaSource = isRecord$11(form.schema) ? form.schema : isRecord$11(form.schemaJson) ? form.schemaJson : null;
16338
+ const settingsSource = isRecord$11(form.settings) ? form.settings : isRecord$11(form.settingsJson) ? form.settingsJson : null;
16294
16339
  return {
16295
16340
  id,
16296
16341
  name,
@@ -16310,8 +16355,8 @@ function normalizeBookingServices(services) {
16310
16355
  };
16311
16356
  if (!services) return [];
16312
16357
  if (Array.isArray(services)) return services.filter(isBookingFormService).map(normalizeService);
16313
- if (isRecord$9(services) && "services" in services) return Array.isArray(services.services) ? services.services.filter(isBookingFormService).map(normalizeService) : [];
16314
- return isRecord$9(services) ? Object.values(services).filter(isBookingFormService).map(normalizeService) : [];
16358
+ if (isRecord$11(services) && "services" in services) return Array.isArray(services.services) ? services.services.filter(isBookingFormService).map(normalizeService) : [];
16359
+ return isRecord$11(services) ? Object.values(services).filter(isBookingFormService).map(normalizeService) : [];
16315
16360
  }
16316
16361
  function normalizeBookingSchema(value) {
16317
16362
  if (!value) return void 0;
@@ -16322,7 +16367,7 @@ function normalizeBookingSchema(value) {
16322
16367
  };
16323
16368
  }
16324
16369
  function readBookingFormField(value) {
16325
- if (!isRecord$9(value)) return null;
16370
+ if (!isRecord$11(value)) return null;
16326
16371
  const id = readNonEmptyString(value.id);
16327
16372
  const label = readNonEmptyString(value.label);
16328
16373
  const type = readBookingFieldType(value.type);
@@ -16365,7 +16410,7 @@ function readBookingFieldOptions(value) {
16365
16410
  return options.length > 0 ? options : void 0;
16366
16411
  }
16367
16412
  function readBookingFieldOption(value) {
16368
- if (!isRecord$9(value)) return null;
16413
+ if (!isRecord$11(value)) return null;
16369
16414
  const optionValue = readNonEmptyString(value.value);
16370
16415
  const label = readNonEmptyString(value.label);
16371
16416
  return optionValue && label ? {
@@ -16385,7 +16430,7 @@ function normalizeBookingSettings(value) {
16385
16430
  };
16386
16431
  }
16387
16432
  function isBookingFormService(value) {
16388
- return isRecord$9(value) && typeof value.id === "string" && typeof value.siteId === "string" && typeof value.title === "string" && (value.consent === void 0 || blockBookingConsentSchema.safeParse(value.consent).success);
16433
+ return isRecord$11(value) && typeof value.id === "string" && typeof value.siteId === "string" && typeof value.title === "string" && (value.consent === void 0 || blockBookingConsentSchema.safeParse(value.consent).success);
16389
16434
  }
16390
16435
  function collectBookingCustomFields(data) {
16391
16436
  const customFields = {};
@@ -16435,7 +16480,7 @@ function readStringArray(value) {
16435
16480
  const strings = value.filter((item) => typeof item === "string");
16436
16481
  return strings.length > 0 ? strings : void 0;
16437
16482
  }
16438
- function isRecord$9(value) {
16483
+ function isRecord$11(value) {
16439
16484
  return typeof value === "object" && value !== null;
16440
16485
  }
16441
16486
  function getBookingServicePaymentSelectionMode(service) {
@@ -16629,23 +16674,70 @@ function formatBookingSubmissionPreparationError(error) {
16629
16674
  default: return assertNever$11(error);
16630
16675
  }
16631
16676
  }
16632
- function getBookingSuccessMessage(successMessage) {
16633
- return successMessage?.trim() || "Your appointment has been booked! Check your email for confirmation.";
16677
+ function getBookingSuccessCopy(successMessage) {
16678
+ const customMessage = successMessage?.trim();
16679
+ return customMessage && customMessage !== DEFAULT_BOOKING_SUCCESS_MESSAGE ? { message: customMessage } : DEFAULT_BOOKING_SUCCESS_COPY;
16680
+ }
16681
+ function getRegistrationSuccessCopy(result, fallback) {
16682
+ const isWaitlist = result?.status === "waitlist";
16683
+ const isInfo = result?.variant === "info";
16684
+ const includesEmailSentence = !isWaitlist && !isInfo;
16685
+ const responseMessage = result?.message;
16686
+ const trimmedResponseMessage = responseMessage?.trim();
16687
+ if ((isWaitlist || isInfo) && trimmedResponseMessage) {
16688
+ const emailFollowupMessage = result?.emailFollowupMessage;
16689
+ return {
16690
+ message: responseMessage ?? "",
16691
+ ...emailFollowupMessage?.trim() ? { defaultEmailSentence: emailFollowupMessage } : {}
16692
+ };
16693
+ }
16694
+ if (trimmedResponseMessage === DEFAULT_REGISTRATION_SUCCESS_MESSAGE) return includesEmailSentence ? DEFAULT_REGISTRATION_SUCCESS_COPY : { message: DEFAULT_REGISTRATION_SUCCESS_COPY.message };
16695
+ if (trimmedResponseMessage) return includesEmailSentence ? registrationCopyWithEmail(trimmedResponseMessage) : { message: trimmedResponseMessage };
16696
+ const fallbackMessage = fallback?.trim();
16697
+ if (fallbackMessage && fallbackMessage !== DEFAULT_REGISTRATION_SUCCESS_MESSAGE) return { message: fallbackMessage };
16698
+ return includesEmailSentence ? DEFAULT_REGISTRATION_SUCCESS_COPY : { message: DEFAULT_REGISTRATION_SUCCESS_COPY.message };
16699
+ }
16700
+ function registrationCopyWithEmail(message) {
16701
+ return {
16702
+ message,
16703
+ defaultEmailSentence: DEFAULT_REGISTRATION_EMAIL_SENTENCE
16704
+ };
16634
16705
  }
16706
+ function getShopSuccessCopy(outcome) {
16707
+ switch (outcome) {
16708
+ case "success": return {
16709
+ message: "",
16710
+ defaultEmailSentence: "Check your email for confirmation."
16711
+ };
16712
+ case "cancelled": return { message: "You can try again whenever you’re ready." };
16713
+ }
16714
+ }
16715
+ var DEFAULT_BOOKING_SUCCESS_COPY, DEFAULT_BOOKING_SUCCESS_MESSAGE, DEFAULT_REGISTRATION_SUCCESS_COPY, DEFAULT_REGISTRATION_SUCCESS_MESSAGE, DEFAULT_REGISTRATION_EMAIL_SENTENCE;
16635
16716
  var init_booking_form_state = __esmMin((() => {
16636
16717
  init_dist$1();
16637
16718
  init_src$2();
16638
16719
  init_bookingConsent();
16639
16720
  init_booking_form_reserved_fields();
16640
16721
  init_booking_form_consent();
16722
+ DEFAULT_BOOKING_SUCCESS_COPY = {
16723
+ message: "Your booking has been confirmed.",
16724
+ defaultEmailSentence: "Check your email for details."
16725
+ };
16726
+ DEFAULT_BOOKING_SUCCESS_MESSAGE = "Your booking has been confirmed. Check your email for details.";
16727
+ DEFAULT_REGISTRATION_SUCCESS_COPY = {
16728
+ message: "Thank you for registering!",
16729
+ defaultEmailSentence: "Check your email for confirmation details."
16730
+ };
16731
+ DEFAULT_REGISTRATION_SUCCESS_MESSAGE = "Thank you for registering! Check your email for confirmation details.";
16732
+ DEFAULT_REGISTRATION_EMAIL_SENTENCE = "Check your email for confirmation details.";
16641
16733
  }));
16642
16734
  //#endregion
16643
16735
  //#region ../blocks/src/system/runtime/nodes/booking-form.service-categories.ts
16644
- function isRecord$8(value) {
16736
+ function isRecord$10(value) {
16645
16737
  return typeof value === "object" && value !== null && !Array.isArray(value);
16646
16738
  }
16647
16739
  function readCategory(value) {
16648
- if (!isRecord$8(value)) return [];
16740
+ if (!isRecord$10(value)) return [];
16649
16741
  const { id, name, description } = value;
16650
16742
  if (typeof id !== "string" || id.trim() === "" || typeof name !== "string") return [];
16651
16743
  return [{
@@ -16661,7 +16753,7 @@ function readCategory(value) {
16661
16753
  * it.
16662
16754
  */
16663
16755
  function normalizeBookingServiceCategories(services) {
16664
- if (!isRecord$8(services) || !Array.isArray(services.categories)) return [];
16756
+ if (!isRecord$10(services) || !Array.isArray(services.categories)) return [];
16665
16757
  return services.categories.flatMap(readCategory);
16666
16758
  }
16667
16759
  var init_booking_form_service_categories = __esmMin((() => {}));
@@ -16810,6 +16902,7 @@ var init_booking_form_interactive = __esmMin((() => {
16810
16902
  return parsed.ok ? parsed.value : void 0;
16811
16903
  });
16812
16904
  bookingSourceSchema = z.object({
16905
+ demoEmailSuppressed: z.boolean().optional(),
16813
16906
  mailingList: bookingMailingListContextSchema.optional(),
16814
16907
  siteName: z.string().optional(),
16815
16908
  siteId: z.string().optional(),
@@ -16840,6 +16933,7 @@ var init_booking_form_interactive = __esmMin((() => {
16840
16933
  message: z.string().nullable()
16841
16934
  });
16842
16935
  bookingHydrationSchema = z.object({
16936
+ demoEmailSuppressed: z.boolean().optional(),
16843
16937
  mailingList: bookingMailingListContextSchema.optional(),
16844
16938
  siteName: z.string().optional(),
16845
16939
  formId: z.string().nullable(),
@@ -16878,6 +16972,7 @@ var init_booking_form_interactive = __esmMin((() => {
16878
16972
  return {
16879
16973
  display: buildBookingFormDisplay(source, form),
16880
16974
  hydration: {
16975
+ demoEmailSuppressed: source.demoEmailSuppressed,
16881
16976
  mailingList: source.mailingList,
16882
16977
  siteName: source.siteName,
16883
16978
  formId: form?.id ?? source.formId ?? null,
@@ -17645,11 +17740,11 @@ var init_bookability = __esmMin((() => {
17645
17740
  }));
17646
17741
  //#endregion
17647
17742
  //#region ../blocks/src/system/runtime/nodes/events/domain/destination.ts
17648
- function isRecord$7(value) {
17743
+ function isRecord$9(value) {
17649
17744
  return typeof value === "object" && value !== null && !Array.isArray(value);
17650
17745
  }
17651
17746
  function isRuntimeEventDestination(value) {
17652
- if (!isRecord$7(value) || typeof value.kind !== "string") return false;
17747
+ if (!isRecord$9(value) || typeof value.kind !== "string") return false;
17653
17748
  if (value.kind === "native") return (value.mode === "cms-managed" || value.mode === "system-managed") && typeof value.path === "string";
17654
17749
  return value.kind === "external" && typeof value.url === "string" && typeof value.label === "string";
17655
17750
  }
@@ -17740,6 +17835,44 @@ var init_cta = __esmMin((() => {
17740
17835
  }));
17741
17836
  //#endregion
17742
17837
  //#region ../blocks/src/system/runtime/nodes/events/domain/dates.ts
17838
+ /**
17839
+ * The English locale a site's public dates are written in, read from the
17840
+ * site's own time zone (Will, 2026-09-26: "date style from site time zone").
17841
+ *
17842
+ * Sites don't store a locale, and every public word around a date is English,
17843
+ * so the only open question is which English conventions to follow: day or
17844
+ * month first, and a 24 or 12-hour clock. The site's time zone is the one
17845
+ * fact every site carries about where it is. It is the site's, never an
17846
+ * event's: a venue left at UTC must not turn a UK site's dates American.
17847
+ * Anywhere this can't place (UTC, the Americas, Asia) keeps US English, which
17848
+ * is what these helpers wrote before sites were placed at all.
17849
+ */
17850
+ function eventDateLocale(siteTimeZone) {
17851
+ if (!siteTimeZone) return "en-US";
17852
+ if (siteTimeZone === "Europe/Dublin") return "en-IE";
17853
+ if (siteTimeZone.startsWith("Europe/")) return "en-GB";
17854
+ if (siteTimeZone.startsWith("Australia/")) return "en-AU";
17855
+ if (siteTimeZone === "Pacific/Auckland" || siteTimeZone === "Pacific/Chatham") return "en-NZ";
17856
+ return "en-US";
17857
+ }
17858
+ /**
17859
+ * Formatting options for an event's dates: the times in the event's own zone,
17860
+ * written in its site's locale. A record from an older server that doesn't
17861
+ * name the site's zone falls back to the event's.
17862
+ */
17863
+ function eventDateOptions(place) {
17864
+ return {
17865
+ timeZone: place.timeZone ?? null,
17866
+ locale: eventDateLocale(place.siteTimeZone ?? place.timeZone)
17867
+ };
17868
+ }
17869
+ /**
17870
+ * Start and end times as cards write them, in the site's locale:
17871
+ * "10:00 to 16:00" in the UK, "10:00 AM to 4:00 PM" in the US.
17872
+ */
17873
+ function formatEventTimeRange$1(times, options) {
17874
+ return `${formatTime$2(times.startsAt, options)} to ${formatTime$2(times.endsAt, options)}`;
17875
+ }
17743
17876
  /** Use the event timezone when present, otherwise the calendar/site timezone. */
17744
17877
  function resolveEventTimeZone(event, calendarTimeZone) {
17745
17878
  return event.timeZone || calendarTimeZone;
@@ -17761,18 +17894,25 @@ function formatDate$2(isoTimestamp, options) {
17761
17894
  });
17762
17895
  }
17763
17896
  /**
17764
- * Format time for display.
17765
- * Returns: "10:00 AM"
17897
+ * Whether the locale reads a 24-hour clock, where hours are written with two
17898
+ * digits ("09:00"), as the dashboard writes them.
17899
+ */
17900
+ function usesTwentyFourHourClock(locale) {
17901
+ return new Intl.DateTimeFormat(locale, { hour: "numeric" }).resolvedOptions().hour12 === false;
17902
+ }
17903
+ /**
17904
+ * Format time for display, on the locale's own clock.
17905
+ * Returns: "9:00 AM" (en-US) or "09:00" (en-GB)
17766
17906
  */
17767
17907
  function formatTime$2(isoTimestamp, options) {
17908
+ const locale = options?.locale ?? "en-US";
17768
17909
  return formatBookingTime(toScheduledBookingDateTime({
17769
17910
  startsAt: isoTimestamp,
17770
17911
  timeZone: toBookingTimeZone(options?.timeZone ?? "UTC"),
17771
- locale: options?.locale ?? "en-US"
17912
+ locale
17772
17913
  }), {
17773
- hour: "numeric",
17774
- minute: "2-digit",
17775
- hour12: true
17914
+ hour: usesTwentyFourHourClock(locale) ? "2-digit" : "numeric",
17915
+ minute: "2-digit"
17776
17916
  });
17777
17917
  }
17778
17918
  function formatEventDateParts(args) {
@@ -17804,7 +17944,7 @@ function formatEventCompactDateRail(isoTimestamp, options) {
17804
17944
  locale: options?.locale ?? "en-US"
17805
17945
  });
17806
17946
  const weekday = formatBookingDate(dateTime, { weekday: "short" }).toLocaleUpperCase(options?.locale ?? "en-US");
17807
- const month = formatBookingDate(dateTime, { month: "short" }).toLocaleUpperCase(options?.locale ?? "en-US");
17947
+ const month = formatBookingDate(dateTime, { month: "short" }).slice(0, 3).toLocaleUpperCase(options?.locale ?? "en-US");
17808
17948
  return {
17809
17949
  weekday,
17810
17950
  day: formatBookingDate(dateTime, { day: "numeric" }),
@@ -17824,7 +17964,7 @@ function formatEventCompactDateRail(isoTimestamp, options) {
17824
17964
  * keep the fact panel on the same date and timezone rules as event rows.
17825
17965
  */
17826
17966
  function formatEventNextDateFact(event) {
17827
- const rail = formatEventCompactDateRail(event.startsAt, { timeZone: event.timeZone });
17967
+ const rail = formatEventCompactDateRail(event.startsAt, eventDateOptions(event));
17828
17968
  return {
17829
17969
  dateTime: event.startsAt,
17830
17970
  value: `${rail.weekday} ${rail.day} ${rail.month}`,
@@ -18723,6 +18863,13 @@ function CalendarIcon({ className, size = 16, strokeWidth = 2 }) {
18723
18863
  var init_EventCardIcons = __esmMin((() => {}));
18724
18864
  //#endregion
18725
18865
  //#region ../blocks/src/system/runtime/nodes/events/shared/EventCard.tsx
18866
+ /** The category's badge, when the event has a category. */
18867
+ function eventCardCategoryBadge(category) {
18868
+ return category ? {
18869
+ label: category.name,
18870
+ style: getCategoryBadgeStyle(category.color ?? null)
18871
+ } : null;
18872
+ }
18726
18873
  function EventCardMedia(props) {
18727
18874
  if (props.dateFact) return /* @__PURE__ */ jsxs("div", {
18728
18875
  className: "card-media event-card-media event-card-date-fallback",
@@ -18747,7 +18894,8 @@ function EventCardMedia(props) {
18747
18894
  /* @__PURE__ */ jsx(MediaNodeServer, {
18748
18895
  value: props.image,
18749
18896
  className: "event-card-image",
18750
- size: ImagePresets.card
18897
+ size: ImagePresets.card,
18898
+ imageResolveContext: props.imageResolveContext
18751
18899
  }),
18752
18900
  props.categoryBadge && /* @__PURE__ */ jsx("span", {
18753
18901
  className: "event-category-badge event-category-badge--overlay",
@@ -18862,6 +19010,17 @@ function resolveEventCardOptions(props) {
18862
19010
  headingLevel: props.headingLevel ?? 3
18863
19011
  };
18864
19012
  }
19013
+ /**
19014
+ * The card's date and times, written the way the event's place writes them
19015
+ * ("Friday, 16 October 2026" and "10:00 to 16:00" in the UK).
19016
+ */
19017
+ function formatEventCardWhen(event) {
19018
+ const options = eventDateOptions(event);
19019
+ return {
19020
+ formattedDate: formatDate$2(event.startsAt, options),
19021
+ formattedTime: formatEventTimeRange$1(event, options)
19022
+ };
19023
+ }
18865
19024
  function resolveEventCardDateFact(props) {
18866
19025
  if (!props.showImage || props.image || props.presentation !== "catalogue") return null;
18867
19026
  return formatEventNextDateFact(props.event);
@@ -18906,24 +19065,19 @@ var init_EventCard = __esmMin((() => {
18906
19065
  init_EventCardIcons();
18907
19066
  init_domain();
18908
19067
  init_ThemedButton();
18909
- EventCard = ({ event, cardRole = "default", buttonVariant = "primary", buttonText, showVenue = true, showMap = true, mapSlot, allowMap = true, showCapacity = true, showImage = true, showCategory = true, showSummary = true, orientation = "vertical", presentation, headingLevel }) => {
19068
+ EventCard = ({ event, cardRole = "default", buttonVariant = "primary", buttonText, showVenue = true, showMap = true, mapSlot, allowMap = true, showCapacity = true, showImage = true, showCategory = true, showSummary = true, orientation = "vertical", presentation, headingLevel, imageResolveContext }) => {
18910
19069
  const { presentation: cardPresentation, presentationClass, headingLevel: cardHeadingLevel } = resolveEventCardOptions({
18911
19070
  presentation,
18912
19071
  headingLevel
18913
19072
  });
18914
- const timeZone = event.timeZone ?? null;
18915
- const formattedDate = formatDate$2(event.startsAt, { timeZone });
18916
- const formattedTime = `${formatTime$2(event.startsAt, { timeZone })} - ${formatTime$2(event.endsAt, { timeZone })}`;
19073
+ const { formattedDate, formattedTime } = formatEventCardWhen(event);
18917
19074
  const cta = resolveEventCta(event, buttonText);
18918
19075
  const cardClass = boxStyleClassNames({ role: cardRole }, { baseClass: "event-card" });
18919
19076
  const title = event.title;
18920
19077
  const summary = event.presentation?.summary ?? event.description;
18921
19078
  const image = event.presentation?.image ?? null;
18922
19079
  const category = event.eventCategory;
18923
- const categoryBadge = category && showCategory ? {
18924
- label: category.name,
18925
- style: getCategoryBadgeStyle(category.color ?? null)
18926
- } : null;
19080
+ const categoryBadge = showCategory ? eventCardCategoryBadge(category) : null;
18927
19081
  const hasImage = Boolean(showImage && image);
18928
19082
  const dateFact = resolveEventCardDateFact({
18929
19083
  event,
@@ -18942,7 +19096,8 @@ var init_EventCard = __esmMin((() => {
18942
19096
  categoryId: category?.id,
18943
19097
  dateFact,
18944
19098
  hasImage,
18945
- image
19099
+ image,
19100
+ imageResolveContext
18946
19101
  }), /* @__PURE__ */ jsx(EventCardContent, {
18947
19102
  allowMap,
18948
19103
  buttonVariant,
@@ -20927,10 +21082,40 @@ var init_EventCombined_interactive = __esmMin((() => {
20927
21082
  });
20928
21083
  }));
20929
21084
  //#endregion
21085
+ //#region ../blocks/src/system/runtime/nodes/events/shared/eventCardPresentations.ts
21086
+ /** A booking page's catalogue card: one per series, "See dates" for dated events. */
21087
+ function catalogueEventCardProps(event, buttonVariant = "primary") {
21088
+ return {
21089
+ presentation: "catalogue",
21090
+ headingLevel: 4,
21091
+ buttonVariant,
21092
+ buttonText: event.bookingScope === "single_occurrence" ? "See dates" : void 0,
21093
+ showMap: false,
21094
+ allowMap: false,
21095
+ showCategory: false,
21096
+ orientation: "vertical"
21097
+ };
21098
+ }
21099
+ /** An events listing's card, from the listing's display settings. */
21100
+ function listingEventCardProps(display) {
21101
+ return {
21102
+ cardRole: display.cardRole,
21103
+ buttonVariant: display.buttonVariant,
21104
+ buttonText: display.buttonText,
21105
+ showVenue: display.showVenue,
21106
+ showMap: display.showMap,
21107
+ allowMap: false,
21108
+ showCapacity: display.showCapacity,
21109
+ orientation: display.orientation
21110
+ };
21111
+ }
21112
+ var init_eventCardPresentations = __esmMin((() => {}));
21113
+ //#endregion
20930
21114
  //#region ../blocks/src/system/runtime/nodes/events/shared/renderEventListItem.tsx
20931
21115
  init_EventCombined_interactive();
20932
21116
  init_EventCard();
20933
21117
  init_EventCompactRow();
21118
+ init_eventCardPresentations();
20934
21119
  /**
20935
21120
  * Shared SSR render function for event list items.
20936
21121
  * Selects between EventCard and EventCompactRow based on the display's listLayout.
@@ -20946,14 +21131,7 @@ function renderEventListItem(event, display) {
20946
21131
  }, event.occurrenceId || event.id);
20947
21132
  return /* @__PURE__ */ jsx(EventCard, {
20948
21133
  event,
20949
- cardRole: display.cardRole,
20950
- buttonVariant: display.buttonVariant,
20951
- buttonText: display.buttonText,
20952
- showVenue: display.showVenue,
20953
- showMap: display.showMap,
20954
- allowMap: false,
20955
- showCapacity: display.showCapacity,
20956
- orientation: display.orientation
21134
+ ...listingEventCardProps(display)
20957
21135
  }, event.occurrenceId || event.id);
20958
21136
  }
20959
21137
  //#endregion
@@ -21299,6 +21477,7 @@ function matchesGroup(group, event) {
21299
21477
  //#endregion
21300
21478
  //#region ../blocks/src/system/runtime/nodes/offerings-preview-catalogue.tsx
21301
21479
  init_shared$3();
21480
+ init_eventCardPresentations();
21302
21481
  init_domain();
21303
21482
  function OfferingsCatalogue(props) {
21304
21483
  const state = buildOfferingsCatalogueState({
@@ -21340,14 +21519,7 @@ function OfferingsCatalogue(props) {
21340
21519
  style: { gridTemplateColumns: "repeat(auto-fill, minmax(min(100%, 18rem), 1fr))" },
21341
21520
  children: events.map((event) => /* @__PURE__ */ jsx(EventCard, {
21342
21521
  event,
21343
- presentation: "catalogue",
21344
- headingLevel: 4,
21345
- buttonVariant: props.buttonVariant ?? "primary",
21346
- buttonText: event.bookingScope === "single_occurrence" ? "See dates" : void 0,
21347
- showMap: false,
21348
- allowMap: false,
21349
- showCategory: false,
21350
- orientation: "vertical"
21522
+ ...catalogueEventCardProps(event, props.buttonVariant ?? "primary")
21351
21523
  }, event.seriesId))
21352
21524
  })]
21353
21525
  }, group.sourceKey))
@@ -21653,45 +21825,73 @@ function FeaturedOfferingSummary({ item }) {
21653
21825
  }
21654
21826
  function featuredSummaryDetails(item) {
21655
21827
  switch (item.kind) {
21656
- case "event": return formatFeaturedSummary(deriveEventScheduleSummary(item.event), item.event.venue?.name ?? null);
21828
+ case "event": return formatFeaturedSummary(deriveEventScheduleSummary(item.event), {
21829
+ venue: item.event.venue?.name ?? null,
21830
+ siteTimeZone: item.event.siteTimeZone
21831
+ });
21657
21832
  case "run": {
21658
21833
  const schedule = derivePreviewRunSchedule(item.run.run.sessions);
21659
- return schedule.kind === "scheduled" ? formatFeaturedSummary(schedule.summary, item.run.representative.venue?.name ?? null) : null;
21834
+ return schedule.kind === "scheduled" ? formatFeaturedSummary(schedule.summary, {
21835
+ venue: item.run.representative.venue?.name ?? null,
21836
+ siteTimeZone: item.run.representative.siteTimeZone
21837
+ }) : null;
21660
21838
  }
21661
21839
  default: return assertNever$22(item, "Unhandled offerings preview item");
21662
21840
  }
21663
21841
  }
21664
- function formatFeaturedSummary(summary, venue) {
21842
+ function formatFeaturedSummary(summary, place) {
21665
21843
  switch (summary.kind) {
21666
- case "single-occurrence": return detailsFromOccurrences(summary.occurrence, null, venue, null, null);
21667
- case "multi-day-span": return detailsFromOccurrences(summary.occurrence, summary.occurrence, venue, null, null, true);
21668
- case "fixed-recurring-run": return detailsFromOccurrences(summary.first, summary.last, venue, summary.recurrenceLabel, null);
21669
- case "irregular-multi-session-run": return detailsFromOccurrences(summary.first, summary.last, venue, null, `${summary.sessionCount} dates`);
21844
+ case "single-occurrence": return detailsFromOccurrences({
21845
+ first: summary.occurrence,
21846
+ last: null,
21847
+ place
21848
+ });
21849
+ case "multi-day-span": return detailsFromOccurrences({
21850
+ first: summary.occurrence,
21851
+ last: summary.occurrence,
21852
+ place,
21853
+ spanUsesEndDate: true
21854
+ });
21855
+ case "fixed-recurring-run": return detailsFromOccurrences({
21856
+ first: summary.first,
21857
+ last: summary.last,
21858
+ place,
21859
+ recurrence: summary.recurrenceLabel
21860
+ });
21861
+ case "irregular-multi-session-run": return detailsFromOccurrences({
21862
+ first: summary.first,
21863
+ last: summary.last,
21864
+ place,
21865
+ sessionCount: `${summary.sessionCount} dates`
21866
+ });
21670
21867
  default: return assertNever$22(summary, "Unhandled offerings preview schedule summary");
21671
21868
  }
21672
21869
  }
21673
- function detailsFromOccurrences(first, last, venue, recurrence, sessionCount, spanUsesEndDate = false) {
21674
- const endDateTime = spanUsesEndDate ? first.endsAt : last?.startsAt ?? first.startsAt;
21870
+ function detailsFromOccurrences(input) {
21871
+ const { first, last, place } = input;
21872
+ const endDateTime = input.spanUsesEndDate ? first.endsAt : last?.startsAt ?? first.startsAt;
21873
+ const options = eventDateOptions({
21874
+ timeZone: first.timeZone,
21875
+ siteTimeZone: place.siteTimeZone
21876
+ });
21877
+ const summaryDate = (isoTimestamp, timeZone) => formatSummaryDate(isoTimestamp, {
21878
+ timeZone,
21879
+ locale: options.locale
21880
+ });
21675
21881
  return {
21676
- startDate: formatSummaryDate(first.startsAt, first.timeZone),
21882
+ startDate: summaryDate(first.startsAt, first.timeZone),
21677
21883
  startDateTime: first.startsAt,
21678
- endDate: last ? formatSummaryDate(endDateTime, last.timeZone) : null,
21884
+ endDate: last ? summaryDate(endDateTime, last.timeZone) : null,
21679
21885
  endDateTime,
21680
- timeRange: `${formatTime$2(first.startsAt, {
21681
- timeZone: first.timeZone,
21682
- locale: "en-GB"
21683
- })} – ${formatTime$2(first.endsAt, {
21684
- timeZone: first.timeZone,
21685
- locale: "en-GB"
21686
- })}`,
21687
- recurrence,
21688
- sessionCount,
21689
- venue
21690
- };
21691
- }
21692
- function formatSummaryDate(isoTimestamp, timeZone) {
21693
- return new Intl.DateTimeFormat("en-GB", {
21694
- timeZone,
21886
+ timeRange: formatEventTimeRange$1(first, options),
21887
+ recurrence: input.recurrence ?? null,
21888
+ sessionCount: input.sessionCount ?? null,
21889
+ venue: place.venue
21890
+ };
21891
+ }
21892
+ function formatSummaryDate(isoTimestamp, options) {
21893
+ return new Intl.DateTimeFormat(options.locale, {
21894
+ timeZone: options.timeZone,
21695
21895
  weekday: "long",
21696
21896
  day: "numeric",
21697
21897
  month: "long",
@@ -21738,9 +21938,12 @@ function WholeSeriesRunCompactRow({ group, path, now }) {
21738
21938
  path
21739
21939
  });
21740
21940
  const { sessionCount: sessionsCount, firstSession } = schedule;
21741
- const timeZone = firstSession.timeZone;
21742
- const dateRail = formatEventCompactDateRail(firstSession.startsAt, { timeZone });
21743
- const timeRange = `${formatTime$2(firstSession.startsAt, { timeZone })} - ${formatTime$2(firstSession.endsAt, { timeZone })}`;
21941
+ const options = eventDateOptions({
21942
+ timeZone: firstSession.timeZone,
21943
+ siteTimeZone: group.representative.siteTimeZone
21944
+ });
21945
+ const dateRail = formatEventCompactDateRail(firstSession.startsAt, options);
21946
+ const timeRange = formatEventTimeRange$1(firstSession, options);
21744
21947
  const price = formatEventPriceDisplay(group.representative.pricing);
21745
21948
  const statusLabel = resolveWholeSeriesBookingPhase(group.run, now).kind === "open" ? null : "Registration closed";
21746
21949
  return /* @__PURE__ */ jsxs("article", {
@@ -21820,9 +22023,12 @@ function WholeSeriesRunFeatureCard({ group, now, path, buttonVariant, buttonText
21820
22023
  path
21821
22024
  });
21822
22025
  const { firstSession } = schedule;
21823
- const timeZone = firstSession.timeZone;
21824
- const formattedDate = formatEventCompactDateRail(firstSession.startsAt, { timeZone }).label;
21825
- const timeRange = `${formatTime$2(firstSession.startsAt, { timeZone })} - ${formatTime$2(firstSession.endsAt, { timeZone })}`;
22026
+ const options = eventDateOptions({
22027
+ timeZone: firstSession.timeZone,
22028
+ siteTimeZone: group.representative.siteTimeZone
22029
+ });
22030
+ const formattedDate = formatEventCompactDateRail(firstSession.startsAt, options).label;
22031
+ const timeRange = formatEventTimeRange$1(firstSession, options);
21826
22032
  const price = formatEventPriceDisplay(group.representative.pricing);
21827
22033
  const statusLabel = resolveWholeSeriesBookingPhase(group.run, now).kind === "open" ? null : "Registration closed";
21828
22034
  const description = group.representative.description;
@@ -33898,6 +34104,7 @@ var init_shop_interactive = __esmMin((() => {
33898
34104
  memberships: z.array(publicMembershipProductSchema).nullable().optional(),
33899
34105
  products: z.array(publicProductSchema).nullable().optional(),
33900
34106
  siteId: z.string().optional(),
34107
+ demoEmailSuppressed: z.boolean().optional(),
33901
34108
  apiBaseUrl: z.string().optional(),
33902
34109
  readAuthority: browserReadAuthoritySchema.optional(),
33903
34110
  stage: previewStageSchema.optional()
@@ -34017,7 +34224,8 @@ var init_shop_interactive = __esmMin((() => {
34017
34224
  passesMembershipsHydrationSchema = z.object({
34018
34225
  memberships: z.array(publicMembershipProductSchema),
34019
34226
  passPurchaseMode: z.enum(["add_to_cart", "buy_now"]),
34020
- buttonVariant: blockButtonRoleSchema
34227
+ buttonVariant: blockButtonRoleSchema,
34228
+ demoEmailSuppressed: z.boolean().optional()
34021
34229
  });
34022
34230
  productListHydrationSchema = z.object({
34023
34231
  products: z.array(publicProductSchema),
@@ -34039,7 +34247,8 @@ var init_shop_interactive = __esmMin((() => {
34039
34247
  });
34040
34248
  checkoutHydrationSchema = z.object({
34041
34249
  emptyStateText: z.string(),
34042
- submitButtonText: z.string()
34250
+ submitButtonText: z.string(),
34251
+ demoEmailSuppressed: z.boolean().optional()
34043
34252
  });
34044
34253
  passesMembershipsRenderSchema = z.object({
34045
34254
  display: passesMembershipsDisplaySchema,
@@ -34096,7 +34305,8 @@ var init_shop_interactive = __esmMin((() => {
34096
34305
  hydration: {
34097
34306
  memberships: source.showMemberships === false ? [] : source.memberships ?? [],
34098
34307
  passPurchaseMode,
34099
- buttonVariant: source.buttonVariant ?? "primary"
34308
+ buttonVariant: source.buttonVariant ?? "primary",
34309
+ demoEmailSuppressed: source.demoEmailSuppressed
34100
34310
  }
34101
34311
  };
34102
34312
  }
@@ -34189,7 +34399,8 @@ var init_shop_interactive = __esmMin((() => {
34189
34399
  }),
34190
34400
  hydration: {
34191
34401
  emptyStateText: source.emptyStateText ?? "Add something to your cart to continue.",
34192
- submitButtonText: source.submitButtonText ?? "Checkout"
34402
+ submitButtonText: source.submitButtonText ?? "Checkout",
34403
+ demoEmailSuppressed: source.demoEmailSuppressed
34193
34404
  }
34194
34405
  })
34195
34406
  });
@@ -34400,6 +34611,10 @@ const checkoutBlockDefinition = {
34400
34611
  baseClass: "",
34401
34612
  spacing: "spacious",
34402
34613
  children: sectionContainer([checkout(withApiBindings({
34614
+ demoEmailSuppressed: { $bind: {
34615
+ from: "$root.demoEmailSuppressed",
34616
+ fallback: false
34617
+ } },
34403
34618
  readAuthority: { $bind: { from: "$root.readAuthority" } },
34404
34619
  mode: "checkout",
34405
34620
  heading: { $bind: {
@@ -34987,13 +35202,13 @@ function buildEventRegistrationShellBodyText(stepLabels) {
34987
35202
  return "Preparing dates, tickets, and booking details.";
34988
35203
  }
34989
35204
  function normalizeEventRegistrationEventInput(value) {
34990
- if (!isRecord$4(value)) return value;
35205
+ if (!isRecord$6(value)) return value;
34991
35206
  return {
34992
35207
  ...value,
34993
35208
  destination: resolveRuntimeEventDestination(value)
34994
35209
  };
34995
35210
  }
34996
- function isRecord$4(value) {
35211
+ function isRecord$6(value) {
34997
35212
  return typeof value === "object" && value !== null && !Array.isArray(value);
34998
35213
  }
34999
35214
  function buildEventRegistrationInteractiveIslandProps(props) {
@@ -35042,6 +35257,7 @@ var init_event_registration_interactive = __esmMin((() => {
35042
35257
  ];
35043
35258
  eventRegistrationPublicEventSchema = z.preprocess(normalizeEventRegistrationEventInput, publicEventSchema);
35044
35259
  eventRegistrationHydrationSchemaShape = {
35260
+ demoEmailSuppressed: z.boolean().optional(),
35045
35261
  occurrenceContext: occurrenceContextSchema.optional(),
35046
35262
  subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
35047
35263
  maxTickets: z.string().optional(),
@@ -35137,6 +35353,7 @@ var init_event_registration_interactive = __esmMin((() => {
35137
35353
  ...eventSource,
35138
35354
  events: [...scopedSourceEvents]
35139
35355
  } : eventSource,
35356
+ demoEmailSuppressed: source.demoEmailSuppressed,
35140
35357
  maxTickets: source.maxTickets ?? void 0,
35141
35358
  showVenue: source.showVenue,
35142
35359
  showCapacity: source.showCapacity,
@@ -35282,8 +35499,8 @@ const eventRegistrationBlockDefinition = {
35282
35499
  description: "Message shown after successful registration",
35283
35500
  required: false,
35284
35501
  multiline: true,
35285
- defaultValue: "Thank you for registering! Check your email for confirmation details.",
35286
- maxLength: 500
35502
+ maxLength: 500,
35503
+ ui: { placeholder: "Thank you for registering! Check your email for confirmation details." }
35287
35504
  },
35288
35505
  {
35289
35506
  id: "buttonText",
@@ -35304,6 +35521,10 @@ const eventRegistrationBlockDefinition = {
35304
35521
  text({ as: "h2" }, bind("content.heading"), when("content.heading")),
35305
35522
  richText({ className: "rb-prose rb-max-w-none" }, bind("content.description"), when("content.description")),
35306
35523
  eventRegistration(withApiBindings({
35524
+ demoEmailSuppressed: { $bind: {
35525
+ from: "$root.demoEmailSuppressed",
35526
+ fallback: false
35527
+ } },
35307
35528
  readAuthority: { $bind: { from: "$root.readAuthority" } },
35308
35529
  occurrenceContext: { $bind: { from: "$root.occurrenceContext" } },
35309
35530
  subject: { $bind: { from: "$root.subject" } },
@@ -36942,6 +37163,7 @@ var init_EventListing_interactive = __esmMin((() => {
36942
37163
  init_islands();
36943
37164
  init_runtime();
36944
37165
  init_shared$3();
37166
+ init_eventCardPresentations();
36945
37167
  init_contract_schemas();
36946
37168
  init_listOptions();
36947
37169
  init_eventCollectionContract();
@@ -38514,6 +38736,10 @@ const shopBlockDefinition = {
38514
38736
  spacing: "spacious",
38515
38737
  children: sectionContainer([shop(withApiBindings({
38516
38738
  readAuthority: { $bind: { from: "$root.readAuthority" } },
38739
+ demoEmailSuppressed: { $bind: {
38740
+ from: "$root.demoEmailSuppressed",
38741
+ fallback: false
38742
+ } },
38517
38743
  mode: "passes-memberships",
38518
38744
  showPasses: { $bind: {
38519
38745
  from: "content.showPasses",
@@ -39011,11 +39237,12 @@ function CartSSR({ blockId, siteId, apiBaseUrl, stage, children, ...rest }) {
39011
39237
  //#endregion
39012
39238
  //#region ../blocks/src/system/runtime/nodes/checkout.server.tsx
39013
39239
  init_shop_interactive();
39014
- function CheckoutSSR({ blockId, siteId, apiBaseUrl, stage, children, ...rest }) {
39240
+ function CheckoutSSR({ blockId, siteId, apiBaseUrl, stage, demoEmailSuppressed, children, ...rest }) {
39015
39241
  const islandProps = buildCheckoutInteractiveIslandProps({
39016
39242
  siteId,
39017
39243
  apiBaseUrl,
39018
39244
  stage,
39245
+ demoEmailSuppressed,
39019
39246
  ...rest
39020
39247
  });
39021
39248
  return /* @__PURE__ */ jsxs("div", {
@@ -43348,6 +43575,35 @@ var init_src = __esmMin((() => {
43348
43575
  init_dist();
43349
43576
  }));
43350
43577
  //#endregion
43578
+ //#region ../blocks/src/system/runtime/nodes/booking-form.payment-confirmation.ts
43579
+ function bookingServiceRequiresPaymentBeforeBooking(input) {
43580
+ switch (getBookingServicePaymentSelectionMode(input.service)) {
43581
+ case "implicit_upfront":
43582
+ case "implicit_instalment_plan":
43583
+ case "implicit_flexible_balance": return true;
43584
+ case "choice_required": return input.selectedCollectionOptionKind !== void 0 && input.selectedCollectionOptionKind !== "deferred_manual";
43585
+ case "implicit_deferred_manual":
43586
+ case "pending_stripe_setup":
43587
+ case "unsupported": return false;
43588
+ }
43589
+ }
43590
+ function resolveBookingPaymentConfirmationSummary(input) {
43591
+ const service = input.service;
43592
+ if (!service || input.hasSelectedAppointmentPackage || !Number.isFinite(input.priceAmount) || input.priceAmount <= 0 || !service.durationMinutes || !bookingServiceRequiresPaymentBeforeBooking({
43593
+ service,
43594
+ selectedCollectionOptionKind: input.selectedCollectionOptionKind
43595
+ })) return null;
43596
+ return {
43597
+ serviceTitle: service.title,
43598
+ durationMinutes: service.durationMinutes,
43599
+ priceAmount: input.priceAmount,
43600
+ priceCurrency: service.priceCurrency ?? service.pricing?.currency ?? "USD"
43601
+ };
43602
+ }
43603
+ var init_booking_form_payment_confirmation = __esmMin((() => {
43604
+ init_booking_form_state();
43605
+ }));
43606
+ //#endregion
43351
43607
  //#region ../blocks/src/system/runtime/hooks/useSelectedAppointmentConsentForm.ts
43352
43608
  function useSelectedAppointmentConsentForm(form, selectedService) {
43353
43609
  return useMemo(() => projectSelectedAppointmentConsentIntoForm(form, resolveSelectedAppointmentConsent(selectedService)), [form, selectedService]);
@@ -43888,6 +44144,75 @@ var init_useBookingSubmission_state = __esmMin((() => {
43888
44144
  };
43889
44145
  }));
43890
44146
  //#endregion
44147
+ //#region ../blocks/src/system/runtime/shared/utils/demoBookingPassStorage.ts
44148
+ function normalizeDemoBookingEmail(email) {
44149
+ return email.trim().toLowerCase();
44150
+ }
44151
+ function storeDemoBookingPass(email, pass) {
44152
+ try {
44153
+ const normalizedEmail = normalizeDemoBookingEmail(email);
44154
+ if (!normalizedEmail || !pass) return;
44155
+ const current = readStoredDemoBookingPasses();
44156
+ const updated = [{
44157
+ email: normalizedEmail,
44158
+ pass
44159
+ }, ...current.filter((entry) => entry.email !== normalizedEmail)].slice(0, MAX_STORED_PASSES);
44160
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify(updated));
44161
+ } catch {}
44162
+ }
44163
+ function storeDemoBookingPassIfAvailable(email, pass) {
44164
+ if (email && pass) storeDemoBookingPass(email, pass);
44165
+ }
44166
+ function getDemoBookingPass(email) {
44167
+ try {
44168
+ const normalizedEmail = normalizeDemoBookingEmail(email);
44169
+ return readStoredDemoBookingPasses().find((entry) => entry.email === normalizedEmail)?.pass ?? null;
44170
+ } catch {
44171
+ return null;
44172
+ }
44173
+ }
44174
+ function storeDemoBookingCheckoutReturn(email, pass) {
44175
+ const normalizedEmail = normalizeDemoBookingEmail(email);
44176
+ if (!normalizedEmail) return;
44177
+ storeDemoBookingPassIfAvailable(normalizedEmail, pass);
44178
+ try {
44179
+ window.sessionStorage.setItem(CHECKOUT_RETURN_EMAIL_KEY, normalizedEmail);
44180
+ } catch {}
44181
+ }
44182
+ function readDemoBookingCheckoutReturnEmail() {
44183
+ try {
44184
+ const email = window.sessionStorage.getItem(CHECKOUT_RETURN_EMAIL_KEY);
44185
+ window.sessionStorage.removeItem(CHECKOUT_RETURN_EMAIL_KEY);
44186
+ return email ? normalizeDemoBookingEmail(email) : null;
44187
+ } catch {
44188
+ return null;
44189
+ }
44190
+ }
44191
+ function readStoredDemoBookingPasses() {
44192
+ try {
44193
+ const raw = window.localStorage.getItem(STORAGE_KEY);
44194
+ if (!raw) return [];
44195
+ const parsed = JSON.parse(raw);
44196
+ return Array.isArray(parsed) ? parsed.filter(isStoredDemoBookingPass) : [];
44197
+ } catch {
44198
+ return [];
44199
+ }
44200
+ }
44201
+ function isStoredDemoBookingPass(value) {
44202
+ if (!isRecord$5(value)) return false;
44203
+ const record = value;
44204
+ return typeof record.email === "string" && record.email.length > 0 && typeof record.pass === "string" && record.pass.length > 0;
44205
+ }
44206
+ function isRecord$5(value) {
44207
+ return typeof value === "object" && value !== null && !Array.isArray(value);
44208
+ }
44209
+ var STORAGE_KEY, CHECKOUT_RETURN_EMAIL_KEY, MAX_STORED_PASSES;
44210
+ var init_demoBookingPassStorage = __esmMin((() => {
44211
+ STORAGE_KEY = "riverbank:demo-booking-passes:v1";
44212
+ CHECKOUT_RETURN_EMAIL_KEY = "riverbank:demo-booking-checkout-email:v1";
44213
+ MAX_STORED_PASSES = 10;
44214
+ }));
44215
+ //#endregion
43891
44216
  //#region ../blocks/src/system/runtime/hooks/useBookingSubmission.ts
43892
44217
  /**
43893
44218
  * Hook for submitting appointment bookings
@@ -43947,6 +44272,7 @@ function useBookingSubmission(_siteId) {
43947
44272
  successUrl: data.successUrl,
43948
44273
  cancelUrl: data.cancelUrl
43949
44274
  });
44275
+ storeDemoBookingPassIfAvailable(response.customer.email, response.demoBookingPass);
43950
44276
  dispatch({
43951
44277
  type: "submission-succeeded",
43952
44278
  message: response.type === "checkout_redirect" ? "Redirecting to secure checkout..." : "Booking submitted successfully."
@@ -43977,6 +44303,7 @@ var init_useBookingSubmission = __esmMin((() => {
43977
44303
  init_dist$1();
43978
44304
  init_api$1();
43979
44305
  init_useBookingSubmission_state();
44306
+ init_demoBookingPassStorage();
43980
44307
  }));
43981
44308
  //#endregion
43982
44309
  //#region ../blocks/src/system/runtime/nodes/booking-form.submit-success.ts
@@ -43990,15 +44317,18 @@ function completeBookingSubmission(input) {
43990
44317
  kind: "checkout_redirect",
43991
44318
  checkoutUrl: data.checkoutUrl,
43992
44319
  sessionId: data.sessionId,
44320
+ customerEmail: data.customer.email,
44321
+ ...data.demoBookingPass ? { demoBookingPass: data.demoBookingPass } : {},
43993
44322
  ...data.mailingListSignupNote ? { mailingListSignupNote: data.mailingListSignupNote } : {}
43994
44323
  }
43995
44324
  };
43996
44325
  }
44326
+ const successCopy = getBookingSuccessCopy(input.successMessage);
43997
44327
  input.dispatch({
43998
44328
  type: "feedback-set",
43999
44329
  feedback: {
44000
44330
  kind: "success",
44001
- message: getBookingSuccessMessage(input.successMessage),
44331
+ message: successCopy.defaultEmailSentence ? `${successCopy.message} ${successCopy.defaultEmailSentence}`.trim() : successCopy.message,
44002
44332
  resourceName: data.appointment.resourceName
44003
44333
  }
44004
44334
  });
@@ -44008,6 +44338,8 @@ function completeBookingSubmission(input) {
44008
44338
  kind: "booked",
44009
44339
  appointmentId: data.appointment.id,
44010
44340
  resourceName: data.appointment.resourceName,
44341
+ customerEmail: data.customer.email,
44342
+ ...data.demoBookingPass ? { demoBookingPass: data.demoBookingPass } : {},
44011
44343
  ...data.mailingListSignupNote ? { mailingListSignupNote: data.mailingListSignupNote } : {}
44012
44344
  }
44013
44345
  };
@@ -45703,6 +46035,12 @@ function useHeadlessBookingFlow(options) {
45703
46035
  selectedService,
45704
46036
  state.selectedSlot?.startAt
45705
46037
  ]);
46038
+ const paymentConfirmationSummary = resolveBookingPaymentConfirmationSummary({
46039
+ service: selectedService,
46040
+ priceAmount: selectedAppointmentPriceAmount,
46041
+ selectedCollectionOptionKind: state.selectedCollectionOptionKind,
46042
+ hasSelectedAppointmentPackage: Boolean(state.selectedAppointmentPackageId)
46043
+ });
45706
46044
  const appointmentPackageItems = appointmentPackages.tag === "loaded" ? appointmentPackages.value : [];
45707
46045
  const selectedAppointmentPackage = appointmentPackageItems.find((appointmentPackage) => appointmentPackage.customerPassId === state.selectedAppointmentPackageId) ?? null;
45708
46046
  const spamProtectionEnabled = options.spamProtectionEnabled ?? isSpamProtectionEnabled();
@@ -45732,7 +46070,8 @@ function useHeadlessBookingFlow(options) {
45732
46070
  selectedSlidingAmount,
45733
46071
  slidingScale: selectedServiceSlidingScale,
45734
46072
  appointmentPackages: appointmentPackagesModel,
45735
- errorMessage: paymentResolution.errorMessage ?? "This service cannot be booked right now."
46073
+ errorMessage: paymentResolution.errorMessage ?? "This service cannot be booked right now.",
46074
+ confirmationSummary: null
45736
46075
  } : {
45737
46076
  kind: "ok",
45738
46077
  mode: paymentResolution.mode,
@@ -45742,7 +46081,8 @@ function useHeadlessBookingFlow(options) {
45742
46081
  selectedSlidingAmountInput: state.selectedSlidingAmountInput,
45743
46082
  selectedSlidingAmount,
45744
46083
  slidingScale: selectedServiceSlidingScale,
45745
- appointmentPackages: appointmentPackagesModel
46084
+ appointmentPackages: appointmentPackagesModel,
46085
+ confirmationSummary: paymentConfirmationSummary
45746
46086
  };
45747
46087
  return {
45748
46088
  mailingList,
@@ -45842,6 +46182,7 @@ var init_useHeadlessBookingFlow = __esmMin((() => {
45842
46182
  init_src$2();
45843
46183
  init_api$1();
45844
46184
  init_booking_form_state();
46185
+ init_booking_form_payment_confirmation();
45845
46186
  init_useSelectedAppointmentConsentForm();
45846
46187
  init_useAvailableDates();
45847
46188
  init_useAvailableSlots();
@@ -45921,65 +46262,22 @@ var init_usePolling_state = __esmMin((() => {
45921
46262
  * Provides a reusable polling mechanism with configurable intervals,
45922
46263
  * max attempts, and completion detection. Used by usePaymentVerification
45923
46264
  * and other hooks that need to poll for status changes.
45924
- *
45925
- * @example
45926
- * ```tsx
45927
- * const polling = usePolling(shouldPoll ? {
45928
- * pollFn: () => api.getStatus(id),
45929
- * isComplete: (result) => result.status === 'done',
45930
- * } : null);
45931
- *
45932
- * useEffect(() => {
45933
- * if (polling.status === 'completed') {
45934
- * handleSuccess(polling.result);
45935
- * }
45936
- * }, [polling.status]);
45937
- * ```
45938
- */
45939
- /**
45940
- * Generic hook for polling an async operation until completion.
45941
- *
45942
- * Pass config to start polling, or null to stop/idle.
45943
- * The hook handles cleanup on unmount and config changes.
45944
- *
45945
- * **IMPORTANT: Config identity stability**
45946
- *
45947
- * The config object is used as an effect dependency. If config identity
45948
- * changes on every render (e.g., inline objects), polling will restart
45949
- * continuously, causing infinite request loops.
45950
- *
45951
- * Always memoize the config object:
45952
- *
45953
- * @example
45954
- * ```tsx
45955
- * // BAD - inline object creates new identity every render
45956
- * usePolling({
45957
- * pollFn: () => api.getStatus(id),
45958
- * isComplete: (result) => result.status === 'done',
45959
- * });
45960
- *
45961
- * // GOOD - memoized config, stable identity
45962
- * const pollConfig = useMemo(() => shouldPoll ? {
45963
- * pollFn: () => api.getStatus(id),
45964
- * isComplete: (result) => result.status === 'done',
45965
- * } : null, [shouldPoll, api, id]);
45966
- *
45967
- * usePolling(pollConfig);
45968
- * ```
45969
- *
45970
- * @param config - Configuration for polling, or null to stop
45971
- * @returns Polling result with status, data, and retry function
45972
46265
  */
45973
- function usePolling(config) {
45974
- const [state, dispatch] = useReducer(pollingReducer, void 0, createInitialPollingState);
45975
- const attemptsRef = useRef(0);
45976
- const timeoutRef = useRef(null);
45977
- const isPollingRef = useRef(false);
45978
- const isActiveRef = useRef(false);
45979
- const generationRef = useRef(0);
45980
- const configRef = useRef(config);
45981
- configRef.current = config;
45982
- const cleanup = useCallback(() => {
46266
+ function usePollingRuntime(config) {
46267
+ const runtime = {
46268
+ configRef: useRef(config),
46269
+ attemptsRef: useRef(0),
46270
+ timeoutRef: useRef(null),
46271
+ isPollingRef: useRef(false),
46272
+ isActiveRef: useRef(false),
46273
+ generationRef: useRef(0)
46274
+ };
46275
+ runtime.configRef.current = config;
46276
+ return runtime;
46277
+ }
46278
+ function usePollingCleanup(runtime) {
46279
+ const { isActiveRef, generationRef, timeoutRef, isPollingRef } = runtime;
46280
+ return useCallback(() => {
45983
46281
  isActiveRef.current = false;
45984
46282
  generationRef.current += 1;
45985
46283
  if (timeoutRef.current) {
@@ -45987,16 +46285,27 @@ function usePolling(config) {
45987
46285
  timeoutRef.current = null;
45988
46286
  }
45989
46287
  isPollingRef.current = false;
45990
- }, []);
45991
- const resetState = useCallback(() => {
46288
+ }, [
46289
+ generationRef,
46290
+ isActiveRef,
46291
+ isPollingRef,
46292
+ timeoutRef
46293
+ ]);
46294
+ }
46295
+ function usePollingReset(runtime, dispatch) {
46296
+ const { attemptsRef } = runtime;
46297
+ return useCallback(() => {
45992
46298
  dispatch({ type: "polling-reset" });
45993
46299
  attemptsRef.current = 0;
45994
- }, []);
45995
- const poll = useCallback(async () => {
45996
- const cfg = configRef.current;
45997
- if (!cfg) return true;
46300
+ }, [attemptsRef, dispatch]);
46301
+ }
46302
+ function usePollingRequest(runtime, dispatch, cleanup) {
46303
+ const { configRef, attemptsRef, isPollingRef, isActiveRef, generationRef } = runtime;
46304
+ return useCallback(async () => {
46305
+ const config = configRef.current;
46306
+ if (!config) return true;
45998
46307
  if (isPollingRef.current) return false;
45999
- const maxAttempts = cfg.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
46308
+ const maxAttempts = config.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
46000
46309
  if (attemptsRef.current >= maxAttempts) {
46001
46310
  dispatch({ type: "polling-timed-out" });
46002
46311
  cleanup();
@@ -46006,81 +46315,115 @@ function usePolling(config) {
46006
46315
  attemptsRef.current += 1;
46007
46316
  const generation = generationRef.current;
46008
46317
  try {
46009
- const data = await cfg.pollFn();
46010
- if (generation !== generationRef.current || !isActiveRef.current) {
46011
- isPollingRef.current = false;
46012
- return true;
46013
- }
46014
- if (cfg.isFailed?.(data)) {
46318
+ const result = await config.pollFn();
46319
+ if (generation !== generationRef.current || !isActiveRef.current) return true;
46320
+ if (config.isFailed?.(result)) {
46015
46321
  dispatch({
46016
46322
  type: "polling-failed",
46017
- result: data
46323
+ result
46018
46324
  });
46019
46325
  cleanup();
46020
46326
  return true;
46021
46327
  }
46022
- if (cfg.isComplete(data)) {
46328
+ if (config.isComplete(result)) {
46023
46329
  dispatch({
46024
46330
  type: "polling-completed",
46025
- result: data
46331
+ result
46026
46332
  });
46027
46333
  cleanup();
46028
46334
  return true;
46029
46335
  }
46030
46336
  dispatch({
46031
46337
  type: "polling-progressed",
46032
- result: data
46338
+ result
46033
46339
  });
46034
46340
  isPollingRef.current = false;
46035
46341
  return false;
46036
- } catch (err) {
46037
- if (generation !== generationRef.current || !isActiveRef.current) {
46038
- isPollingRef.current = false;
46039
- return true;
46040
- }
46041
- if (err instanceof Error) dispatch({
46342
+ } catch (error) {
46343
+ if (generation !== generationRef.current || !isActiveRef.current) return true;
46344
+ if (error instanceof Error) dispatch({
46042
46345
  type: "polling-request-failed",
46043
- error: err
46346
+ error
46044
46347
  });
46045
46348
  isPollingRef.current = false;
46046
46349
  return false;
46047
46350
  }
46048
- }, [cleanup]);
46049
- const schedulePoll = useCallback(() => {
46351
+ }, [
46352
+ attemptsRef,
46353
+ cleanup,
46354
+ configRef,
46355
+ dispatch,
46356
+ generationRef,
46357
+ isActiveRef,
46358
+ isPollingRef
46359
+ ]);
46360
+ }
46361
+ function usePollingScheduler(runtime, poll) {
46362
+ const { attemptsRef, configRef, isActiveRef, timeoutRef } = runtime;
46363
+ return useCallback(() => {
46050
46364
  if (!isActiveRef.current) return;
46051
- const pollInterval = configRef.current?.interval ?? DEFAULT_POLL_INTERVAL;
46052
46365
  const doPoll = async () => {
46053
- if (!await poll() && isActiveRef.current) timeoutRef.current = setTimeout(doPoll, pollInterval);
46366
+ if (!await poll() && isActiveRef.current) {
46367
+ const configuredInterval = configRef.current?.interval;
46368
+ const interval = typeof configuredInterval === "function" ? configuredInterval(attemptsRef.current) : configuredInterval ?? DEFAULT_POLL_INTERVAL;
46369
+ timeoutRef.current = setTimeout(doPoll, interval);
46370
+ }
46054
46371
  };
46055
46372
  doPoll();
46056
- }, [poll]);
46373
+ }, [
46374
+ attemptsRef,
46375
+ configRef,
46376
+ isActiveRef,
46377
+ poll,
46378
+ timeoutRef
46379
+ ]);
46380
+ }
46381
+ function usePollingCycle(config, runtime, dispatch) {
46382
+ const cleanup = usePollingCleanup(runtime);
46383
+ const resetState = usePollingReset(runtime, dispatch);
46384
+ const schedulePoll = usePollingScheduler(runtime, usePollingRequest(runtime, dispatch, cleanup));
46385
+ const pollingEnabled = config !== null;
46057
46386
  useEffect(() => {
46058
- if (!config) {
46387
+ if (!pollingEnabled) {
46059
46388
  cleanup();
46060
46389
  dispatch({ type: "polling-went-idle" });
46061
46390
  return;
46062
46391
  }
46063
46392
  resetState();
46064
- isActiveRef.current = true;
46393
+ runtime.isActiveRef.current = true;
46065
46394
  schedulePoll();
46066
46395
  return cleanup;
46067
46396
  }, [
46068
- config,
46069
46397
  cleanup,
46398
+ dispatch,
46399
+ pollingEnabled,
46070
46400
  resetState,
46401
+ config?.restartKey ?? null,
46402
+ runtime.isActiveRef,
46071
46403
  schedulePoll
46072
46404
  ]);
46073
- const retry = useCallback(() => {
46074
- if (!configRef.current) return;
46405
+ return useCallback(() => {
46406
+ if (!runtime.configRef.current) return;
46075
46407
  cleanup();
46076
46408
  resetState();
46077
- isActiveRef.current = true;
46409
+ runtime.isActiveRef.current = true;
46078
46410
  schedulePoll();
46079
46411
  }, [
46080
46412
  cleanup,
46081
46413
  resetState,
46414
+ runtime.configRef,
46415
+ runtime.isActiveRef,
46082
46416
  schedulePoll
46083
46417
  ]);
46418
+ }
46419
+ /**
46420
+ * Polls until the operation completes, fails, times out, or becomes disabled.
46421
+ * Config objects may be rebuilt across renders; change restartKey to begin a
46422
+ * new operation and reset its attempt budget.
46423
+ */
46424
+ function usePolling(config) {
46425
+ const [state, dispatch] = useReducer(pollingReducer, void 0, createInitialPollingState);
46426
+ const retry = usePollingCycle(config, usePollingRuntime(config), dispatch);
46084
46427
  return {
46085
46428
  status: config ? state.tag : "idle",
46086
46429
  result: config ? state.result : null,
@@ -46096,21 +46439,33 @@ var init_usePolling = __esmMin((() => {
46096
46439
  }));
46097
46440
  //#endregion
46098
46441
  //#region ../blocks/src/system/runtime/hooks/useAppointmentCheckoutVerification.ts
46442
+ function resolveAppointmentCheckoutPollInterval(attempt) {
46443
+ return Math.min(1e3 * 2 ** (attempt - 1), 4e3);
46444
+ }
46099
46445
  function useAppointmentCheckoutVerification(config) {
46100
46446
  return useAppointmentCheckoutVerificationWithDeps(config, appointmentCheckoutVerificationDeps);
46101
46447
  }
46102
46448
  function useAppointmentCheckoutVerificationWithDeps(config, deps) {
46103
46449
  const api = deps.useBlockApi();
46450
+ const sessionId = config?.sessionId ?? null;
46451
+ const maxAttempts = config?.maxAttempts;
46452
+ const pollInterval = config?.pollInterval;
46104
46453
  const pollingConfig = useMemo(() => {
46105
- if (!config) return null;
46454
+ if (sessionId === null) return null;
46106
46455
  return {
46107
- pollFn: () => api.getAppointmentBookingStatus({ sessionId: config.sessionId }),
46456
+ restartKey: sessionId,
46457
+ pollFn: () => api.getAppointmentBookingStatus({ sessionId }),
46108
46458
  isComplete: (result) => (result.paymentStatus === "completed" || result.paymentStatus === "not_required") && result.appointmentStatus === "confirmed",
46109
46459
  isFailed: (result) => result.paymentStatus === "failed" || result.paymentStatus === "cancelled" || result.paymentStatus === "refunded" || result.appointmentStatus === "cancelled",
46110
- maxAttempts: config.maxAttempts,
46111
- interval: config.pollInterval
46460
+ maxAttempts: maxAttempts ?? APPOINTMENT_CHECKOUT_MAX_ATTEMPTS,
46461
+ interval: pollInterval ?? resolveAppointmentCheckoutPollInterval
46112
46462
  };
46113
- }, [api, config]);
46463
+ }, [
46464
+ api,
46465
+ sessionId,
46466
+ maxAttempts,
46467
+ pollInterval
46468
+ ]);
46114
46469
  const polling = deps.usePolling(pollingConfig);
46115
46470
  return {
46116
46471
  state: resolveAppointmentCheckoutVerificationState({
@@ -46122,11 +46477,12 @@ function useAppointmentCheckoutVerificationWithDeps(config, deps) {
46122
46477
  retry: polling.retry
46123
46478
  };
46124
46479
  }
46125
- var appointmentCheckoutVerificationDeps;
46480
+ var APPOINTMENT_CHECKOUT_MAX_ATTEMPTS, appointmentCheckoutVerificationDeps;
46126
46481
  var init_useAppointmentCheckoutVerification = __esmMin((() => {
46127
46482
  init_api$1();
46128
46483
  init_booking_form_state();
46129
46484
  init_usePolling();
46485
+ APPOINTMENT_CHECKOUT_MAX_ATTEMPTS = 12;
46130
46486
  appointmentCheckoutVerificationDeps = {
46131
46487
  useBlockApi,
46132
46488
  usePolling
@@ -46650,6 +47006,76 @@ var init_booking_form_service_choices = __esmMin((() => {
46650
47006
  init_CheckIcon$1();
46651
47007
  }));
46652
47008
  //#endregion
47009
+ //#region ../blocks/src/system/runtime/nodes/booking-form.submit-actions.tsx
47010
+ function resolvePrimaryActionLabel(isLastStep, requiresPayment) {
47011
+ if (!isLastStep) return "Continue";
47012
+ return requiresPayment ? "Continue to payment" : "Complete";
47013
+ }
47014
+ function formatBookingConfirmationDateTime(booking) {
47015
+ const startAt = booking.currentStep?.id === "datetime-selection" ? booking.availability.selectedSlot?.startAt : void 0;
47016
+ return startAt ? new Intl.DateTimeFormat(void 0, {
47017
+ dateStyle: "medium",
47018
+ timeStyle: "short",
47019
+ timeZone: booking.availability.timezone
47020
+ }).format(new Date(startAt)) : null;
47021
+ }
47022
+ function BookingPaymentConfirmationText({ booking, summary }) {
47023
+ if (!summary) return null;
47024
+ const dateTime = formatBookingConfirmationDateTime(booking);
47025
+ return /* @__PURE__ */ jsxs("p", {
47026
+ className: "ab-text rb-on-surface--muted",
47027
+ children: [
47028
+ summary.serviceTitle,
47029
+ " · ",
47030
+ summary.durationMinutes,
47031
+ " min ·",
47032
+ " ",
47033
+ formatCurrencyAmount(summary.priceAmount, summary.priceCurrency, { decimals: "auto" }),
47034
+ dateTime ? ` · ${dateTime}` : ""
47035
+ ]
47036
+ });
47037
+ }
47038
+ function BookingFormSubmitActions({ booking, onSubmit }) {
47039
+ const currentStepIndex = booking.currentStep?.visibleIndex ?? 0;
47040
+ const isFirstStep = currentStepIndex === 0;
47041
+ const isLastStep = currentStepIndex === booking.steps.length - 1;
47042
+ const isSubmitting = booking.status.tag === "submitting";
47043
+ const paymentSummary = isLastStep && booking.payment.kind === "ok" ? booking.payment.confirmationSummary : null;
47044
+ const handlePrimaryAction = async () => {
47045
+ if ((await booking.actions.next()).ok && isLastStep) await onSubmit();
47046
+ };
47047
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(BookingPaymentConfirmationText, {
47048
+ booking,
47049
+ summary: paymentSummary
47050
+ }), /* @__PURE__ */ jsxs("div", {
47051
+ className: "rb-wizard-actions",
47052
+ children: [!isFirstStep ? /* @__PURE__ */ jsx(ThemedButton, {
47053
+ type: "button",
47054
+ onClick: booking.actions.back,
47055
+ variant: "outline",
47056
+ size: "md",
47057
+ label: "Back"
47058
+ }) : null, /* @__PURE__ */ jsx(ThemedButton, {
47059
+ type: "button",
47060
+ onClick: () => {
47061
+ handlePrimaryAction();
47062
+ },
47063
+ disabled: isSubmitting,
47064
+ variant: "primary",
47065
+ size: "md",
47066
+ label: resolvePrimaryActionLabel(isLastStep, Boolean(paymentSummary)),
47067
+ pending: isSubmitting ? {
47068
+ label: "Submitting...",
47069
+ srLabel: "Submitting"
47070
+ } : void 0
47071
+ })]
47072
+ })] });
47073
+ }
47074
+ var init_booking_form_submit_actions = __esmMin((() => {
47075
+ init_src$2();
47076
+ init_ThemedButton();
47077
+ }));
47078
+ //#endregion
46653
47079
  //#region ../blocks/src/system/runtime/nodes/booking-form.default-ui.tsx
46654
47080
  function formatBookingAmount(amount, currency) {
46655
47081
  return formatCurrencyAmount(amount, currency, { decimals: "auto" });
@@ -46658,13 +47084,6 @@ function HeadlessBookingDefaultForm({ booking, onSubmit }) {
46658
47084
  const currentStep = booking.currentStep;
46659
47085
  const errorSummaryId = React.useId();
46660
47086
  const currentStepIndex = currentStep?.visibleIndex ?? 0;
46661
- const isFirstStep = currentStepIndex === 0;
46662
- const isLastStep = currentStepIndex === booking.steps.length - 1;
46663
- const isSubmitting = booking.status.tag === "submitting";
46664
- const handlePrimaryAction = async () => {
46665
- if (!(await booking.actions.next()).ok) return;
46666
- if (isLastStep) await onSubmit();
46667
- };
46668
47087
  if (!currentStep) return /* @__PURE__ */ jsx("div", {
46669
47088
  className: "rb-text-center rb-py-12",
46670
47089
  children: /* @__PURE__ */ jsx("p", {
@@ -46692,28 +47111,9 @@ function HeadlessBookingDefaultForm({ booking, onSubmit }) {
46692
47111
  errors: currentStep.errors,
46693
47112
  id: errorSummaryId
46694
47113
  }),
46695
- /* @__PURE__ */ jsxs("div", {
46696
- className: "rb-wizard-actions",
46697
- children: [!isFirstStep ? /* @__PURE__ */ jsx(ThemedButton, {
46698
- type: "button",
46699
- onClick: booking.actions.back,
46700
- variant: "outline",
46701
- size: "md",
46702
- label: "Back"
46703
- }) : null, /* @__PURE__ */ jsx(ThemedButton, {
46704
- type: "button",
46705
- onClick: () => {
46706
- handlePrimaryAction();
46707
- },
46708
- disabled: isSubmitting,
46709
- variant: "primary",
46710
- size: "md",
46711
- label: isLastStep ? "Complete" : "Continue",
46712
- pending: isSubmitting ? {
46713
- label: "Submitting...",
46714
- srLabel: "Submitting"
46715
- } : void 0
46716
- })]
47114
+ /* @__PURE__ */ jsx(BookingFormSubmitActions, {
47115
+ booking,
47116
+ onSubmit
46717
47117
  }),
46718
47118
  /* @__PURE__ */ jsx(DefaultBookingDiscount, { booking }),
46719
47119
  /* @__PURE__ */ jsx(DefaultBookingFeedback, { booking }),
@@ -47336,6 +47736,7 @@ var init_booking_form_default_ui = __esmMin((() => {
47336
47736
  init_booking_form_mailing_list_choice();
47337
47737
  init_CheckboxChoice();
47338
47738
  init_booking_form_service_choices();
47739
+ init_booking_form_submit_actions();
47339
47740
  }));
47340
47741
  //#endregion
47341
47742
  //#region ../blocks/src/system/runtime/shared/utils/checkoutUrls.ts
@@ -47579,6 +47980,23 @@ var init_ActionRow = __esmMin((() => {
47579
47980
  };
47580
47981
  }));
47581
47982
  //#endregion
47983
+ //#region ../blocks/src/system/runtime/shared/components/DemoPortalSignInLink.tsx
47984
+ function DemoPortalSignInLink(props) {
47985
+ return /* @__PURE__ */ jsxs("div", { children: [
47986
+ /* @__PURE__ */ jsx("h3", { children: "Your sign-in link" }),
47987
+ /* @__PURE__ */ jsx("p", { children: "In the demo we don’t send emails, so here’s the link we’d have sent you." }),
47988
+ /* @__PURE__ */ jsx(ThemedButtonLink, {
47989
+ variant: "default",
47990
+ size: "md",
47991
+ label: "Sign in to the portal",
47992
+ href: props.url
47993
+ })
47994
+ ] });
47995
+ }
47996
+ var init_DemoPortalSignInLink = __esmMin((() => {
47997
+ init_ThemedButton();
47998
+ }));
47999
+ //#endregion
47582
48000
  //#region ../blocks/src/system/runtime/shared/components/LoggedInAsUser.tsx
47583
48001
  /**
47584
48002
  * Displays the logged-in user's email with an optional logout link.
@@ -47869,6 +48287,7 @@ var init_components = __esmMin((() => {
47869
48287
  init_ActionRow();
47870
48288
  init_FieldValidationMessage();
47871
48289
  init_FeedbackMessage();
48290
+ init_DemoPortalSignInLink();
47872
48291
  init_LoggedInAsUser();
47873
48292
  init_StateIcon();
47874
48293
  init_MembershipHero$1();
@@ -47887,6 +48306,158 @@ var init_shared = __esmMin((() => {
47887
48306
  init_components();
47888
48307
  }));
47889
48308
  //#endregion
48309
+ //#region ../blocks/src/system/runtime/shared/utils/demoPortalMagicLink.ts
48310
+ function buildPortalCallbackUrl(origin, redirectTo) {
48311
+ const url = new URL("/api/portal/callback", origin);
48312
+ url.searchParams.set("redirect_to", redirectTo);
48313
+ return url.toString();
48314
+ }
48315
+ async function requestDemoPortalMagicLink(input) {
48316
+ const email = normalizeDemoBookingEmail(input.email);
48317
+ const pass = getDemoBookingPass(email);
48318
+ const request = {
48319
+ email,
48320
+ redirectUrl: input.redirectUrl,
48321
+ ...pass ? { demoBookingPass: pass } : {}
48322
+ };
48323
+ try {
48324
+ const response = await input.send(request);
48325
+ if ("kind" in response) return {
48326
+ kind: "refused",
48327
+ message: response.message
48328
+ };
48329
+ return "demoSignInUrl" in response ? {
48330
+ kind: "demo_sign_in",
48331
+ url: response.demoSignInUrl
48332
+ } : { kind: "email_sent" };
48333
+ } catch (error) {
48334
+ if (error instanceof BlockApiError && error.tag === "demo_email_not_booked_here") return {
48335
+ kind: "refused",
48336
+ message: error.message
48337
+ };
48338
+ throw error;
48339
+ }
48340
+ }
48341
+ var CUSTOMER_PORTAL_PATH;
48342
+ var init_demoPortalMagicLink = __esmMin((() => {
48343
+ init_client$1();
48344
+ init_demoBookingPassStorage();
48345
+ CUSTOMER_PORTAL_PATH = "/portal";
48346
+ }));
48347
+ //#endregion
48348
+ //#region ../blocks/src/system/runtime/shared/components/DemoBookingPortalAccess.tsx
48349
+ function BookingConfirmation(props) {
48350
+ const content = renderConfirmationMessage((props.demoEmailSuppressed ? [props.copy.message] : [props.copy.message, props.copy.defaultEmailSentence ?? ""]).filter((part) => part.trim().length > 0).join(" "), props.messagePresentation);
48351
+ if (!props.demoEmailSuppressed) return content;
48352
+ return /* @__PURE__ */ jsxs(Fragment, { children: [content, /* @__PURE__ */ jsx(DemoBookingPortalAccess, {
48353
+ email: props.email,
48354
+ noteClassName: props.noteClassName,
48355
+ showConfirmationNote: props.showConfirmationNote
48356
+ })] });
48357
+ }
48358
+ function DemoBookingPortalAccess(props) {
48359
+ const { state, openPortal } = useDemoBookingPortalAccess(props.email);
48360
+ return /* @__PURE__ */ jsxs("div", {
48361
+ className: "rb-mt-4 rb-flex rb-flex-col rb-items-start rb-gap-3",
48362
+ "data-testid": "demo-booking-portal-access",
48363
+ children: [
48364
+ props.showConfirmationNote === false ? null : /* @__PURE__ */ jsx("p", {
48365
+ className: props.noteClassName ?? "ab-text",
48366
+ children: SUPPRESSED_CONFIRMATION_NOTE
48367
+ }),
48368
+ /* @__PURE__ */ jsx(ThemedButton, {
48369
+ type: "button",
48370
+ variant: "default",
48371
+ size: "md",
48372
+ label: state.tag === "opening" ? "Opening…" : "Open the customer portal",
48373
+ disabled: state.tag === "opening",
48374
+ onClick: openPortal
48375
+ }),
48376
+ state.tag === "refused" ? /* @__PURE__ */ jsx("p", {
48377
+ role: "alert",
48378
+ children: state.message
48379
+ }) : null,
48380
+ state.tag === "error" ? /* @__PURE__ */ jsx("p", {
48381
+ role: "alert",
48382
+ children: state.message
48383
+ }) : null
48384
+ ]
48385
+ });
48386
+ }
48387
+ function renderConfirmationMessage(message, presentation) {
48388
+ if (!message) return null;
48389
+ switch (presentation.kind) {
48390
+ case "paragraph": return /* @__PURE__ */ jsx("p", {
48391
+ className: presentation.className,
48392
+ children: message
48393
+ });
48394
+ case "plain": return message;
48395
+ }
48396
+ }
48397
+ function useDemoBookingPortalAccess(email) {
48398
+ const api = useBlockApi();
48399
+ const [state, setState] = React.useState({ tag: "idle" });
48400
+ const openPortal = async () => {
48401
+ if (state.tag === "opening") return;
48402
+ if (!email) {
48403
+ setState({
48404
+ tag: "error",
48405
+ message: "We couldn’t open the customer portal. Please try again."
48406
+ });
48407
+ return;
48408
+ }
48409
+ setState({ tag: "opening" });
48410
+ try {
48411
+ const result = await requestDemoPortalMagicLink({
48412
+ email,
48413
+ redirectUrl: buildPortalCallbackUrl(window.location.origin, CUSTOMER_PORTAL_PATH),
48414
+ send: (request) => api.sendMagicLink(request)
48415
+ });
48416
+ switch (result.kind) {
48417
+ case "demo_sign_in":
48418
+ window.location.assign(result.url);
48419
+ return;
48420
+ case "refused":
48421
+ setState({
48422
+ tag: "refused",
48423
+ message: result.message
48424
+ });
48425
+ return;
48426
+ case "email_sent":
48427
+ setState({ tag: "idle" });
48428
+ return;
48429
+ }
48430
+ } catch (error) {
48431
+ setState(handlePortalAccessError(error));
48432
+ }
48433
+ };
48434
+ return {
48435
+ state,
48436
+ openPortal
48437
+ };
48438
+ }
48439
+ function handlePortalAccessError(error) {
48440
+ if (error instanceof BlockApiError && error.tag === "demo_email_not_booked_here") return {
48441
+ tag: "refused",
48442
+ message: error.message
48443
+ };
48444
+ return error instanceof BlockApiError ? {
48445
+ tag: "error",
48446
+ message: error.message
48447
+ } : {
48448
+ tag: "error",
48449
+ message: "We couldn’t open the customer portal. Please try again."
48450
+ };
48451
+ }
48452
+ var SUPPRESSED_CONFIRMATION_NOTE;
48453
+ var init_DemoBookingPortalAccess = __esmMin((() => {
48454
+ init_api$1();
48455
+ init_client$1();
48456
+ init_demoPortalMagicLink();
48457
+ init_ThemedButton();
48458
+ 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.";
48459
+ }));
48460
+ //#endregion
47890
48461
  //#region ../blocks/src/system/runtime/components/booking/SuccessMessage.tsx
47891
48462
  /**
47892
48463
  * SuccessMessage Component
@@ -47900,7 +48471,8 @@ var init_SuccessMessage = __esmMin((() => {
47900
48471
  init_CheckIcon$1();
47901
48472
  init_StateIcon();
47902
48473
  init_TerminalPanel();
47903
- SuccessMessage = ({ message, resourceName, className }) => {
48474
+ init_DemoBookingPortalAccess();
48475
+ SuccessMessage = ({ copy, resourceName, className, demoEmailSuppressed = false, customerEmail = null }) => {
47904
48476
  return /* @__PURE__ */ jsx(TerminalPanel, {
47905
48477
  tone: "success",
47906
48478
  title: "Booking confirmed",
@@ -47908,9 +48480,15 @@ var init_SuccessMessage = __esmMin((() => {
47908
48480
  variant: "success",
47909
48481
  children: /* @__PURE__ */ jsx(CheckIcon, { strokeWidth: 3 })
47910
48482
  }),
47911
- body: /* @__PURE__ */ jsx("p", {
47912
- className: "ab-text",
47913
- children: message
48483
+ body: /* @__PURE__ */ jsx(BookingConfirmation, {
48484
+ demoEmailSuppressed,
48485
+ email: customerEmail,
48486
+ copy,
48487
+ messagePresentation: {
48488
+ kind: "paragraph",
48489
+ className: "ab-text"
48490
+ },
48491
+ noteClassName: "ab-text"
47914
48492
  }),
47915
48493
  secondaryBody: resourceName ? /* @__PURE__ */ jsxs("p", {
47916
48494
  className: "ab-text rb-on-surface--muted",
@@ -47953,32 +48531,56 @@ var init_BookingMailingListNote = __esmMin((() => {
47953
48531
  init_mailingListSignupCopy();
47954
48532
  }));
47955
48533
  //#endregion
47956
- //#region ../blocks/src/system/runtime/nodes/booking-form.mailing-list-note.ts
48534
+ //#region ../blocks/src/system/runtime/nodes/booking-form.checkout-return-context.ts
47957
48535
  function storageKey$1(sessionId) {
47958
48536
  return `riverbank:booking:mailing-list:${sessionId}`;
47959
48537
  }
47960
- function saveAppointmentMailingListNote(sessionId, note) {
47961
- if (!note) return;
48538
+ function saveAppointmentCheckoutReturnContext(sessionId, context) {
48539
+ if (!context.customerEmail && !context.mailingListNote) return;
47962
48540
  try {
47963
- window.sessionStorage.setItem(storageKey$1(sessionId), note);
48541
+ window.sessionStorage.setItem(storageKey$1(sessionId), JSON.stringify(context));
47964
48542
  } catch {}
47965
48543
  }
47966
- function readAppointmentMailingListNote(sessionId) {
48544
+ function readAppointmentCheckoutReturnContext(sessionId) {
47967
48545
  try {
47968
48546
  const stored = window.sessionStorage.getItem(storageKey$1(sessionId));
47969
- return stored === "confirmation_required" || stored === "not_confirmed" ? stored : null;
48547
+ if (!stored) return null;
48548
+ return parseContext(stored);
47970
48549
  } catch {
47971
48550
  return null;
47972
48551
  }
47973
48552
  }
47974
- var init_booking_form_mailing_list_note = __esmMin((() => {}));
48553
+ function parseContext(value) {
48554
+ try {
48555
+ const parsed = JSON.parse(value);
48556
+ return isContext(parsed) ? parsed : null;
48557
+ } catch {
48558
+ return value === "confirmation_required" || value === "not_confirmed" ? {
48559
+ customerEmail: null,
48560
+ mailingListNote: value
48561
+ } : null;
48562
+ }
48563
+ }
48564
+ function isContext(value) {
48565
+ if (!isRecord$3(value)) return false;
48566
+ return (typeof value.customerEmail === "string" || value.customerEmail === null) && (value.mailingListNote === null || value.mailingListNote === "confirmation_required" || value.mailingListNote === "not_confirmed");
48567
+ }
48568
+ function isRecord$3(value) {
48569
+ return typeof value === "object" && value !== null && !Array.isArray(value);
48570
+ }
48571
+ var init_booking_form_checkout_return_context = __esmMin((() => {}));
47975
48572
  //#endregion
47976
48573
  //#region ../blocks/src/system/runtime/nodes/booking-form.completion.tsx
47977
- function BookingFormCompletion({ resourceName, successMessage, redirectState, localNote }) {
47978
- const note = redirectState.kind === "success" ? readAppointmentMailingListNote(redirectState.sessionId) : localNote;
48574
+ function BookingFormCompletion({ resourceName, successMessage, redirectState, localNote, customerEmail, demoEmailSuppressed = false }) {
48575
+ const returnContext = redirectState.kind === "success" ? readAppointmentCheckoutReturnContext(redirectState.sessionId) : null;
48576
+ const note = redirectState.kind === "success" ? returnContext?.mailingListNote ?? null : localNote;
48577
+ const confirmedEmail = returnContext?.customerEmail ?? customerEmail;
48578
+ const successCopy = getBookingSuccessCopy(successMessage);
47979
48579
  return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SuccessMessage, {
47980
- message: getBookingSuccessMessage(successMessage),
47981
- resourceName
48580
+ copy: successCopy,
48581
+ resourceName,
48582
+ demoEmailSuppressed,
48583
+ customerEmail: confirmedEmail
47982
48584
  }), note ? /* @__PURE__ */ jsx(BookingMailingListNote, {
47983
48585
  note,
47984
48586
  context: "booking",
@@ -47989,7 +48591,7 @@ var init_booking_form_completion = __esmMin((() => {
47989
48591
  init_SuccessMessage();
47990
48592
  init_BookingMailingListNote();
47991
48593
  init_booking_form_state();
47992
- init_booking_form_mailing_list_note();
48594
+ init_booking_form_checkout_return_context();
47993
48595
  }));
47994
48596
  //#endregion
47995
48597
  //#region ../blocks/src/system/runtime/nodes/booking-form.submit-handler.ts
@@ -48008,17 +48610,23 @@ function createBookingFormSubmitHandler(input) {
48008
48610
  cancelUrl: appendRebookFlag(cancelUrl, input.isPortalRebook)
48009
48611
  });
48010
48612
  if (!result.ok) return;
48613
+ storeDemoBookingPassIfAvailable(result.outcome.customerEmail, result.outcome.demoBookingPass);
48011
48614
  if (result.outcome.kind === "checkout_redirect") {
48012
- saveAppointmentMailingListNote(result.outcome.sessionId, result.outcome.mailingListSignupNote);
48615
+ saveAppointmentCheckoutReturnContext(result.outcome.sessionId, {
48616
+ customerEmail: result.outcome.customerEmail,
48617
+ mailingListNote: result.outcome.mailingListSignupNote ?? null
48618
+ });
48013
48619
  window.location.href = result.outcome.checkoutUrl;
48014
48620
  return;
48015
48621
  }
48016
48622
  input.setLocalMailingListNote(result.outcome.mailingListSignupNote ?? null);
48623
+ input.setLocalCustomerEmail(result.outcome.customerEmail);
48017
48624
  };
48018
48625
  }
48019
48626
  var init_booking_form_submit_handler = __esmMin((() => {
48020
48627
  init_shared();
48021
- init_booking_form_mailing_list_note();
48628
+ init_booking_form_checkout_return_context();
48629
+ init_demoBookingPassStorage();
48022
48630
  }));
48023
48631
  //#endregion
48024
48632
  //#region ../blocks/src/system/runtime/nodes/booking-form.client.tsx
@@ -48058,6 +48666,7 @@ var init_booking_form_client = __esmMin((() => {
48058
48666
  init_booking_form_interactive();
48059
48667
  init_shared();
48060
48668
  init_FeedbackMessage();
48669
+ init_ThemedButton();
48061
48670
  init_booking_form_completion();
48062
48671
  init_booking_form_submit_handler();
48063
48672
  init_date_formatting();
@@ -48075,6 +48684,7 @@ var init_booking_form_client = __esmMin((() => {
48075
48684
  const hasLoggedRebookCompletionRef = useRef(false);
48076
48685
  const [redirectState] = useState(() => getBookingRedirectStateFromLocation(getBookingRedirectLocationSnapshot()));
48077
48686
  const [localMailingListNote, setLocalMailingListNote] = useState(null);
48687
+ const [localCustomerEmail, setLocalCustomerEmail] = useState(null);
48078
48688
  const showSpamProtection = render.hydration.spamProtectionEnabled ?? isSpamProtectionEnabled();
48079
48689
  const api = useBlockApi();
48080
48690
  const hasPortalAuth = api.config.auth.type === "bearer" || api.config.authOverrides?.portal?.type === "bearer";
@@ -48157,7 +48767,8 @@ var init_booking_form_client = __esmMin((() => {
48157
48767
  booking,
48158
48768
  bookingAnchorId,
48159
48769
  isPortalRebook,
48160
- setLocalMailingListNote
48770
+ setLocalMailingListNote,
48771
+ setLocalCustomerEmail
48161
48772
  });
48162
48773
  if (viewState.kind === "success") return /* @__PURE__ */ jsx(BookingSurface, {
48163
48774
  id: bookingAnchorId,
@@ -48166,7 +48777,9 @@ var init_booking_form_client = __esmMin((() => {
48166
48777
  successMessage: render.display.successMessage,
48167
48778
  resourceName: viewState.resourceName,
48168
48779
  redirectState,
48169
- localNote: localMailingListNote
48780
+ localNote: localMailingListNote,
48781
+ customerEmail: localCustomerEmail,
48782
+ demoEmailSuppressed: render.hydration.demoEmailSuppressed
48170
48783
  })
48171
48784
  });
48172
48785
  if (viewState.kind === "verifying") return /* @__PURE__ */ jsx(BookingSurface, {
@@ -48182,6 +48795,25 @@ var init_booking_form_client = __esmMin((() => {
48182
48795
  })
48183
48796
  })
48184
48797
  });
48798
+ if (viewState.kind === "timeout") return /* @__PURE__ */ jsxs(BookingSurface, {
48799
+ id: bookingAnchorId,
48800
+ className: render.display.className,
48801
+ children: [/* @__PURE__ */ jsx(FeedbackMessage, {
48802
+ tone: "info",
48803
+ className: "alert alert-info",
48804
+ role: "status",
48805
+ children: /* @__PURE__ */ jsx("p", {
48806
+ className: "ab-text",
48807
+ children: viewState.message
48808
+ })
48809
+ }), /* @__PURE__ */ jsx(ThemedButton, {
48810
+ type: "button",
48811
+ variant: "primary",
48812
+ size: "md",
48813
+ label: "Check again",
48814
+ onClick: verification.retry
48815
+ })]
48816
+ });
48185
48817
  return /* @__PURE__ */ jsxs(BookingSurface, {
48186
48818
  id: bookingAnchorId,
48187
48819
  className: render.display.className,
@@ -48864,7 +49496,7 @@ function recoverRegistrationError(action, handlers) {
48864
49496
  switch (action) {
48865
49497
  case "none": return;
48866
49498
  case "portal":
48867
- window.location.assign("/portal");
49499
+ window.location.assign(CUSTOMER_PORTAL_PATH);
48868
49500
  return;
48869
49501
  case "event":
48870
49502
  window.location.assign(window.location.pathname);
@@ -48889,7 +49521,9 @@ function recoverRegistrationError(action, handlers) {
48889
49521
  return;
48890
49522
  }
48891
49523
  }
48892
- var init_registrationErrorRecovery = __esmMin((() => {}));
49524
+ var init_registrationErrorRecovery = __esmMin((() => {
49525
+ init_demoPortalMagicLink();
49526
+ }));
48893
49527
  //#endregion
48894
49528
  //#region ../blocks/src/system/runtime/nodes/event-registration/validation.ts
48895
49529
  function createInitialRegistrationFormData() {
@@ -49709,6 +50343,10 @@ var init_event_registration_errors = __esmMin((() => {
49709
50343
  message: "The payment options for this event have changed. Please check the latest options before continuing.",
49710
50344
  action: "payment-options"
49711
50345
  },
50346
+ verificationFailed: {
50347
+ message: "We couldn’t confirm this request came from a person. Please refresh the page and try again.",
50348
+ action: "none"
50349
+ },
49712
50350
  idempotencyConflict: {
49713
50351
  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.",
49714
50352
  action: "portal"
@@ -49942,36 +50580,50 @@ var init_useWaitlistClaim = __esmMin((() => {
49942
50580
  }));
49943
50581
  //#endregion
49944
50582
  //#region ../blocks/src/system/runtime/hooks/usePaymentVerification.ts
49945
- /**
49946
- * Hook for polling payment status after Stripe redirects.
49947
- *
49948
- * Built on top of the generic usePolling hook, this provides
49949
- * a specialized interface for verifying event registration payments.
49950
- *
49951
- * @example
49952
- * ```tsx
49953
- * const verification = usePaymentVerification(
49954
- * step === 'verifying-payment' && attendeeId
49955
- * ? { transactionId: attendeeId }
49956
- * : null
49957
- * );
49958
- *
49959
- * useEffect(() => {
49960
- * if (verification.status === 'completed') {
49961
- * setStep('success');
49962
- * } else if (verification.status === 'failed') {
49963
- * setStep('payment-failed');
49964
- * } else if (verification.status === 'timeout') {
49965
- * setStep('verifying-timeout');
49966
- * }
49967
- * }, [verification.status]);
49968
- * ```
49969
- */
50583
+ function resolvePaymentPollingTarget(config) {
50584
+ const reference = config.reference;
50585
+ return reference.scope === "occurrence" ? {
50586
+ key: `occurrence:${reference.attendeeId}`,
50587
+ reference
50588
+ } : {
50589
+ key: `wholeSeries:${reference.registrationId}`,
50590
+ reference
50591
+ };
50592
+ }
50593
+ function createPaymentPollingConfig(api, settings) {
50594
+ if (settings === null) return null;
50595
+ const target = resolvePaymentPollingTarget(settings);
50596
+ return {
50597
+ restartKey: target.key,
50598
+ pollFn: () => api.getEventRegistrationStatus(target.reference),
50599
+ isComplete: (result) => result.paymentStatus === "completed" || result.paymentStatus === "not_required",
50600
+ isFailed: (result) => result.paymentStatus === "failed" || result.paymentStatus === "refunded",
50601
+ maxAttempts: settings.maxAttempts,
50602
+ interval: settings.pollInterval
50603
+ };
50604
+ }
50605
+ function getPaymentVerificationError(polling, paymentStatus) {
50606
+ if (polling.status === "timeout") return "Could not verify payment. If you were charged, please contact support.";
50607
+ if (polling.status === "failed" && paymentStatus !== null) return paymentStatus === "refunded" ? "Payment was refunded. Please contact support." : "Payment was declined. Please try again.";
50608
+ return polling.error?.message ?? null;
50609
+ }
50610
+ function mapPaymentVerificationResult(polling) {
50611
+ const paymentStatus = polling.result?.paymentStatus ?? null;
50612
+ return {
50613
+ status: polling.status,
50614
+ paymentStatus,
50615
+ attendeeStatus: polling.result?.attendeeStatus ?? null,
50616
+ waitlistPosition: polling.result?.waitlistPosition ?? null,
50617
+ error: getPaymentVerificationError(polling, paymentStatus),
50618
+ retry: polling.retry
50619
+ };
50620
+ }
49970
50621
  /**
49971
50622
  * Hook for polling payment status after Stripe redirects.
49972
50623
  *
49973
50624
  * Pass config to start polling, or null to stop/idle.
49974
- * The hook handles cleanup on unmount and config changes.
50625
+ * The hook handles cleanup on unmount and starts a new cycle when the status
50626
+ * reference changes.
49975
50627
  *
49976
50628
  * @param config - Configuration for polling, or null to stop
49977
50629
  * @returns Verification result with status, data, and retry function
@@ -49980,30 +50632,7 @@ function usePaymentVerification(config) {
49980
50632
  return usePaymentVerificationWithDeps(config, paymentVerificationDeps);
49981
50633
  }
49982
50634
  function usePaymentVerificationWithDeps(config, deps) {
49983
- const api = deps.useBlockApi();
49984
- const polling = usePolling(useMemo(() => {
49985
- if (!config) return null;
49986
- return {
49987
- pollFn: () => api.getEventRegistrationStatus(config.reference),
49988
- isComplete: (result) => result.paymentStatus === "completed" || result.paymentStatus === "not_required",
49989
- isFailed: (result) => result.paymentStatus === "failed" || result.paymentStatus === "refunded",
49990
- maxAttempts: config.maxAttempts,
49991
- interval: config.pollInterval
49992
- };
49993
- }, [api, config]));
49994
- const paymentStatus = polling.result?.paymentStatus ?? null;
49995
- let errorMessage = null;
49996
- if (polling.status === "timeout") errorMessage = "Could not verify payment. If you were charged, please contact support.";
49997
- else if (polling.status === "failed" && paymentStatus) errorMessage = paymentStatus === "refunded" ? "Payment was refunded. Please contact support." : "Payment was declined. Please try again.";
49998
- else if (polling.error) errorMessage = polling.error.message;
49999
- return {
50000
- status: polling.status,
50001
- paymentStatus,
50002
- attendeeStatus: polling.result?.attendeeStatus ?? null,
50003
- waitlistPosition: polling.result?.waitlistPosition ?? null,
50004
- error: errorMessage,
50005
- retry: polling.retry
50006
- };
50635
+ return mapPaymentVerificationResult(usePolling(createPaymentPollingConfig(deps.useBlockApi(), config)));
50007
50636
  }
50008
50637
  var paymentVerificationDeps;
50009
50638
  var init_usePaymentVerification = __esmMin((() => {
@@ -50394,17 +51023,6 @@ var init_registrationErrorPresentation = __esmMin((() => {
50394
51023
  function wantsMailingListSignup(options) {
50395
51024
  return options.mailingListSignup !== null && options.formData.mailingListOptIn === true;
50396
51025
  }
50397
- function createClientCommandId(cryptoSource = {
50398
- randomUUID: globalThis.crypto.randomUUID?.bind(globalThis.crypto),
50399
- getRandomValues: (bytes) => globalThis.crypto.getRandomValues(bytes)
50400
- }) {
50401
- if (cryptoSource.randomUUID) return cryptoSource.randomUUID();
50402
- const bytes = cryptoSource.getRandomValues(/* @__PURE__ */ new Uint8Array(16));
50403
- bytes[6] = (bytes[6] ?? 0) & 15 | 64;
50404
- bytes[8] = (bytes[8] ?? 0) & 63 | 128;
50405
- const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0"));
50406
- 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("")}`;
50407
- }
50408
51026
  function useEventRegistrationSubmit(options) {
50409
51027
  return useEventRegistrationSubmitWithDeps(options, eventRegistrationSubmitDeps);
50410
51028
  }
@@ -50483,6 +51101,7 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
50483
51101
  };
50484
51102
  }
50485
51103
  async function completeRegistrationSubmission(options, deps, prepared, result, submitOptions) {
51104
+ if (result.demoBookingPass) storeDemoBookingPass(options.formData.email, result.demoBookingPass);
50486
51105
  switch (result.kind) {
50487
51106
  case "paymentStatusRequired":
50488
51107
  options.setPaymentStatusRecovery({
@@ -50505,6 +51124,7 @@ async function completeRegistrationSubmission(options, deps, prepared, result, s
50505
51124
  status: "waitlist",
50506
51125
  title: "Added to waitlist",
50507
51126
  message: result.waitlist.message,
51127
+ emailFollowupMessage: result.waitlist.emailFollowupMessage,
50508
51128
  mailingListSignupNote: result.mailingListSignupNote
50509
51129
  });
50510
51130
  break;
@@ -50633,15 +51253,18 @@ function buildRegistrationRequest(options, prepared, method, passId, membershipI
50633
51253
  guests: prepared.guestsPayload
50634
51254
  };
50635
51255
  }
50636
- var eventRegistrationSubmitDeps;
51256
+ var createClientCommandId, eventRegistrationSubmitDeps;
50637
51257
  var init_useEventRegistrationSubmit = __esmMin((() => {
51258
+ init_src$2();
50638
51259
  init_client$1();
50639
51260
  init_shared();
50640
51261
  init_registrationErrorPresentation();
50641
51262
  init_constants();
50642
51263
  init_registrationDerivations();
50643
51264
  init_sessionStorage();
51265
+ init_demoBookingPassStorage();
50644
51266
  init_ticketSelectionLines();
51267
+ createClientCommandId = generateUuidV4;
50645
51268
  eventRegistrationSubmitDeps = {
50646
51269
  savePendingRegistration,
50647
51270
  createClientCommandId
@@ -51687,6 +52310,108 @@ var init_useEventCheckoutHandoffRestore = __esmMin((() => {
51687
52310
  };
51688
52311
  }));
51689
52312
  //#endregion
52313
+ //#region ../blocks/src/system/runtime/nodes/event-registration/EventRegistrationBookingLayer.tsx
52314
+ function BookingEntry(props) {
52315
+ const base = props.variant === "teaser" ? "er-booking-teaser" : "er-booking-bar";
52316
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
52317
+ className: `${base}__info`,
52318
+ children: [
52319
+ /* @__PURE__ */ jsx("span", {
52320
+ className: `${base}__title`,
52321
+ children: "Book this event"
52322
+ }),
52323
+ props.summary && /* @__PURE__ */ jsx("span", {
52324
+ className: `${base}__meta`,
52325
+ children: props.summary
52326
+ }),
52327
+ props.variant === "teaser" && props.ticketCurrency && props.ticketTypes.length > 0 ? /* @__PURE__ */ jsx("div", {
52328
+ className: "er-booking-teaser__tickets",
52329
+ children: props.ticketTypes.map((ticketType) => /* @__PURE__ */ jsxs("div", {
52330
+ className: "er-booking-teaser__ticket",
52331
+ children: [/* @__PURE__ */ jsx("span", {
52332
+ className: "er-booking-teaser__ticket-name",
52333
+ children: ticketType.name
52334
+ }), /* @__PURE__ */ jsx("strong", { children: props.formatTicketPrice(ticketType) })]
52335
+ }, ticketType.pricingOptionId))
52336
+ }) : null
52337
+ ]
52338
+ }), /* @__PURE__ */ jsx(ThemedButton, {
52339
+ type: "button",
52340
+ variant: props.buttonVariant,
52341
+ size: "md",
52342
+ extraClassName: `${base}__cta`,
52343
+ label: "Book now",
52344
+ onClick: props.onOpen
52345
+ })] });
52346
+ }
52347
+ function EventRegistrationBookingLayer(props) {
52348
+ const entryProps = {
52349
+ summary: [props.priceLabel, props.availabilityLabel].filter(Boolean).join(" · "),
52350
+ ticketTypes: props.ticketTypes,
52351
+ ticketCurrency: props.ticketCurrency,
52352
+ buttonVariant: props.buttonVariant,
52353
+ formatTicketPrice: props.formatTicketPrice,
52354
+ onOpen: props.onOpen
52355
+ };
52356
+ const floatingBar = !props.overlayOpen && props.isWizardStep ? /* @__PURE__ */ jsx("div", {
52357
+ className: "er-booking-bar",
52358
+ children: /* @__PURE__ */ jsx("div", {
52359
+ className: "er-booking-bar__inner",
52360
+ children: /* @__PURE__ */ jsx(BookingEntry, {
52361
+ ...entryProps,
52362
+ variant: "bar"
52363
+ })
52364
+ })
52365
+ }) : null;
52366
+ const floatingLayer = props.portalRoot ? createPortal(/* @__PURE__ */ jsx("div", {
52367
+ className: props.registrationRootClassName,
52368
+ "data-block": "event-registration",
52369
+ children: floatingBar
52370
+ }), props.portalRoot) : floatingBar;
52371
+ const overlayLayer = props.overlayOpen ? /* @__PURE__ */ jsx(ModalShell, {
52372
+ title: "Book this event",
52373
+ titleId: "event-registration-booking-title",
52374
+ onClose: props.onClose,
52375
+ portal: props.portalRoot != null,
52376
+ portalRoot: props.portalRoot,
52377
+ portalWrapperClassName: props.registrationRootClassName,
52378
+ portalWrapperProps: { "data-block": "event-registration" },
52379
+ overlayClassName: "er-booking-overlay",
52380
+ modalClassName: "er-booking-overlay__panel",
52381
+ renderHeader: ({ closeButtonRef, onClose, title, titleId }) => /* @__PURE__ */ jsxs("div", {
52382
+ className: "er-booking-overlay__header",
52383
+ children: [/* @__PURE__ */ jsx("h2", {
52384
+ className: "er-booking-overlay__title",
52385
+ id: titleId,
52386
+ children: title
52387
+ }), /* @__PURE__ */ jsx("button", {
52388
+ ref: closeButtonRef,
52389
+ type: "button",
52390
+ className: "er-booking-overlay__close",
52391
+ onClick: onClose,
52392
+ "aria-label": "Close booking",
52393
+ children: "×"
52394
+ })]
52395
+ }),
52396
+ children: props.overlaySurface
52397
+ }) : null;
52398
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
52399
+ props.isWizardStep && /* @__PURE__ */ jsx("div", {
52400
+ className: "er-booking-teaser",
52401
+ children: /* @__PURE__ */ jsx(BookingEntry, {
52402
+ ...entryProps,
52403
+ variant: "teaser"
52404
+ })
52405
+ }),
52406
+ floatingLayer,
52407
+ overlayLayer
52408
+ ] });
52409
+ }
52410
+ var init_EventRegistrationBookingLayer = __esmMin((() => {
52411
+ init_ModalShell();
52412
+ init_ThemedButton();
52413
+ }));
52414
+ //#endregion
51690
52415
  //#region ../blocks/src/system/runtime/nodes/shared/MagicLinkForm.state.ts
51691
52416
  function magicLinkSubmissionReducer(state, action) {
51692
52417
  switch (action.type) {
@@ -51696,6 +52421,14 @@ function magicLinkSubmissionReducer(state, action) {
51696
52421
  case "submit-succeeded":
51697
52422
  if (state.tag !== "submitting") return state;
51698
52423
  return { tag: "success" };
52424
+ case "submit-demo-link": return state.tag === "submitting" ? {
52425
+ tag: "demo_link",
52426
+ url: action.url
52427
+ } : state;
52428
+ case "submit-demo-refused": return state.tag === "submitting" ? {
52429
+ tag: "demo_refused",
52430
+ message: action.message
52431
+ } : state;
51699
52432
  case "submit-failed":
51700
52433
  if (state.tag !== "submitting") return state;
51701
52434
  return {
@@ -51719,114 +52452,175 @@ var init_MagicLinkForm_state = __esmMin((() => {
51719
52452
  }));
51720
52453
  //#endregion
51721
52454
  //#region ../blocks/src/system/runtime/nodes/shared/MagicLinkForm.tsx
51722
- function MagicLinkButton(props) {
51723
- return props.themed ? /* @__PURE__ */ jsx(ThemedButton, {
51724
- type: props.type,
51725
- variant: props.variant,
51726
- size: "md",
51727
- label: props.label,
51728
- disabled: props.disabled,
51729
- onClick: props.onClick
51730
- }) : /* @__PURE__ */ jsx("button", {
51731
- type: props.type,
51732
- className: props.className,
51733
- disabled: props.disabled,
51734
- onClick: props.onClick,
51735
- children: props.label
51736
- });
51737
- }
51738
- /**
51739
- * Reusable magic link login form.
51740
- * Used by Customer Portal and Event Registration blocks.
51741
- */
51742
- function MagicLinkForm({ initialEmail = "", title, subtitle, buttonText = "Send login link", successMessage = "Check your email for a login link to sign in.", onSuccess, classPrefix = "er", compact = false }) {
52455
+ function MagicLinkForm(props) {
51743
52456
  const api = useBlockApi();
51744
- const [email, setEmail] = useState(initialEmail);
51745
- const [submissionState, dispatchSubmission] = useReducer(magicLinkSubmissionReducer, initialMagicLinkSubmissionState);
51746
- const loading = isMagicLinkSubmitting(submissionState);
51747
- const error = getMagicLinkError(submissionState);
51748
- const handleSubmit = async (e) => {
51749
- e.preventDefault();
51750
- const normalizedEmail = email.trim().toLowerCase();
51751
- if (!normalizedEmail || loading) return;
51752
- dispatchSubmission({ type: "submit-started" });
51753
- try {
51754
- const redirectTo = `${window.location.pathname}${window.location.search}${window.location.hash}`;
51755
- await api.sendMagicLink({
51756
- email: normalizedEmail,
51757
- redirectUrl: `${window.location.origin}/api/portal/callback?redirect_to=${encodeURIComponent(redirectTo)}`
51758
- });
51759
- dispatchSubmission({ type: "submit-succeeded" });
51760
- onSuccess?.();
51761
- } catch (err) {
51762
- console.error("Magic link error:", err);
51763
- dispatchSubmission({
51764
- type: "submit-failed",
51765
- message: getMagicLinkErrorMessage(err)
51766
- });
51767
- }
51768
- };
51769
- const handleReset = () => {
51770
- setEmail("");
51771
- dispatchSubmission({ type: "reset" });
52457
+ const [email, setEmail] = useState(props.initialEmail ?? "");
52458
+ const [state, dispatch] = useReducer(magicLinkSubmissionReducer, initialMagicLinkSubmissionState);
52459
+ const loading = isMagicLinkSubmitting(state);
52460
+ const handleSubmit = (event) => {
52461
+ submitMagicLink({
52462
+ event,
52463
+ email,
52464
+ loading,
52465
+ api,
52466
+ dispatch,
52467
+ onSuccess: props.onSuccess
52468
+ });
51772
52469
  };
51773
- if (submissionState.tag === "success") return /* @__PURE__ */ jsxs("div", {
51774
- className: `${classPrefix}-magic-link-success`,
51775
- children: [/* @__PURE__ */ jsx("p", {
51776
- className: `${classPrefix}-portal-auth-text ${classPrefix}-portal-auth-text--success`,
51777
- children: successMessage
51778
- }), !compact && /* @__PURE__ */ jsx(MagicLinkButton, {
51779
- themed: classPrefix === "cp",
51780
- type: "button",
51781
- variant: "secondary",
51782
- className: `${classPrefix}-modal-btn ${classPrefix}-modal-btn--secondary`,
51783
- label: "Try a different email",
51784
- onClick: handleReset
51785
- })]
52470
+ if (state.tag === "success" || state.tag === "demo_link") return /* @__PURE__ */ jsx(MagicLinkSuccess, {
52471
+ state,
52472
+ classPrefix: props.classPrefix ?? "er",
52473
+ compact: props.compact ?? false,
52474
+ successMessage: props.successMessage ?? "Check your email for a login link to sign in.",
52475
+ onReset: () => {
52476
+ setEmail("");
52477
+ dispatch({ type: "reset" });
52478
+ }
51786
52479
  });
52480
+ return /* @__PURE__ */ jsx(MagicLinkFormView, {
52481
+ classPrefix: props.classPrefix ?? "er",
52482
+ compact: props.compact ?? false,
52483
+ email,
52484
+ error: getMagicLinkError(state),
52485
+ loading,
52486
+ title: props.title,
52487
+ subtitle: props.subtitle,
52488
+ buttonText: props.buttonText ?? "Send login link",
52489
+ state,
52490
+ onEmailChange: setEmail,
52491
+ onSubmit: handleSubmit
52492
+ });
52493
+ }
52494
+ function MagicLinkFormView(props) {
52495
+ const classPrefix = props.classPrefix;
51787
52496
  return /* @__PURE__ */ jsxs("form", {
51788
- onSubmit: handleSubmit,
52497
+ onSubmit: props.onSubmit,
51789
52498
  className: `${classPrefix}-magic-link-form`,
51790
52499
  children: [
51791
- title && /* @__PURE__ */ jsx("h3", {
52500
+ props.title ? /* @__PURE__ */ jsx("h3", {
51792
52501
  className: `${classPrefix}-magic-link-title`,
51793
- children: title
51794
- }),
51795
- subtitle && /* @__PURE__ */ jsx("p", {
52502
+ children: props.title
52503
+ }) : null,
52504
+ props.subtitle ? /* @__PURE__ */ jsx("p", {
51796
52505
  className: `${classPrefix}-portal-auth-text`,
51797
- children: subtitle
51798
- }),
52506
+ children: props.subtitle
52507
+ }) : null,
51799
52508
  /* @__PURE__ */ jsx("input", {
51800
52509
  type: "email",
51801
52510
  className: classPrefix === "cp" ? "cp-input" : `${classPrefix}-form__input`,
51802
52511
  placeholder: "your@email.com",
51803
- value: email,
51804
- onChange: (e) => setEmail(e.target.value),
51805
- autoFocus: !compact,
52512
+ value: props.email,
52513
+ onChange: (event) => props.onEmailChange(event.target.value),
52514
+ autoFocus: !props.compact,
51806
52515
  required: true,
51807
- disabled: loading
52516
+ disabled: props.loading
51808
52517
  }),
51809
- error && /* @__PURE__ */ jsx("p", {
51810
- className: `${classPrefix}-portal-auth-text ${classPrefix}-portal-auth-text--error`,
51811
- children: error
52518
+ /* @__PURE__ */ jsx(MagicLinkFormFeedback, {
52519
+ classPrefix,
52520
+ error: props.error,
52521
+ state: props.state
51812
52522
  }),
51813
52523
  /* @__PURE__ */ jsx(MagicLinkButton, {
51814
52524
  themed: classPrefix === "cp",
51815
52525
  type: "submit",
51816
52526
  variant: "primary",
51817
52527
  className: `${classPrefix}-modal-btn`,
51818
- label: loading ? "Sending..." : buttonText,
51819
- disabled: !email.trim() || loading
52528
+ label: props.loading ? "Sending..." : props.buttonText,
52529
+ disabled: !props.email.trim() || props.loading
51820
52530
  })
51821
52531
  ]
51822
52532
  });
51823
52533
  }
52534
+ function MagicLinkFormFeedback(props) {
52535
+ if (!props.error && props.state.tag !== "demo_refused") return null;
52536
+ return /* @__PURE__ */ jsxs(Fragment, { children: [props.error ? /* @__PURE__ */ jsx("p", {
52537
+ className: `${props.classPrefix}-portal-auth-text ${props.classPrefix}-portal-auth-text--error`,
52538
+ children: props.error
52539
+ }) : null, props.state.tag === "demo_refused" ? /* @__PURE__ */ jsx("p", {
52540
+ role: "alert",
52541
+ className: `${props.classPrefix}-portal-auth-text ${props.classPrefix}-portal-auth-text--error`,
52542
+ children: props.state.message
52543
+ }) : null] });
52544
+ }
52545
+ function MagicLinkSuccess(props) {
52546
+ return /* @__PURE__ */ jsxs("div", {
52547
+ className: `${props.classPrefix}-magic-link-success`,
52548
+ children: [props.state.tag === "success" ? /* @__PURE__ */ jsx("p", {
52549
+ className: `${props.classPrefix}-portal-auth-text ${props.classPrefix}-portal-auth-text--success`,
52550
+ children: props.successMessage
52551
+ }) : /* @__PURE__ */ jsx(DemoPortalSignInLink, { url: props.state.url }), !props.compact ? /* @__PURE__ */ jsx(MagicLinkButton, {
52552
+ themed: props.classPrefix === "cp",
52553
+ type: "button",
52554
+ variant: "secondary",
52555
+ className: `${props.classPrefix}-modal-btn ${props.classPrefix}-modal-btn--secondary`,
52556
+ label: "Try a different email",
52557
+ onClick: props.onReset
52558
+ }) : null]
52559
+ });
52560
+ }
52561
+ function MagicLinkButton(props) {
52562
+ return props.themed ? /* @__PURE__ */ jsx(ThemedButton, {
52563
+ type: props.type,
52564
+ variant: props.variant,
52565
+ size: "md",
52566
+ label: props.label,
52567
+ disabled: props.disabled,
52568
+ onClick: props.onClick
52569
+ }) : /* @__PURE__ */ jsx("button", {
52570
+ type: props.type,
52571
+ className: props.className,
52572
+ disabled: props.disabled,
52573
+ onClick: props.onClick,
52574
+ children: props.label
52575
+ });
52576
+ }
52577
+ async function submitMagicLink(input) {
52578
+ input.event.preventDefault();
52579
+ const email = input.email.trim().toLowerCase();
52580
+ if (!email || input.loading) return;
52581
+ input.dispatch({ type: "submit-started" });
52582
+ try {
52583
+ const result = await requestDemoPortalMagicLink({
52584
+ email,
52585
+ redirectUrl: getMagicLinkRedirectUrl(),
52586
+ send: (request) => input.api.sendMagicLink(request)
52587
+ });
52588
+ input.dispatch(magicLinkActionForResult(result));
52589
+ if (result.kind === "email_sent") input.onSuccess?.();
52590
+ } catch (error) {
52591
+ console.error("Magic link error:", error);
52592
+ input.dispatch({
52593
+ type: "submit-failed",
52594
+ message: getMagicLinkErrorMessage(error)
52595
+ });
52596
+ }
52597
+ }
52598
+ function magicLinkActionForResult(result) {
52599
+ switch (result.kind) {
52600
+ case "email_sent": return { type: "submit-succeeded" };
52601
+ case "demo_sign_in": return {
52602
+ type: "submit-demo-link",
52603
+ url: result.url
52604
+ };
52605
+ case "refused": return {
52606
+ type: "submit-demo-refused",
52607
+ message: result.message
52608
+ };
52609
+ }
52610
+ }
52611
+ function getMagicLinkRedirectUrl() {
52612
+ const redirectTo = `${window.location.pathname}${window.location.search}${window.location.hash}`;
52613
+ return buildPortalCallbackUrl(window.location.origin, redirectTo);
52614
+ }
51824
52615
  function getMagicLinkErrorMessage(error) {
51825
- return error instanceof Error ? error.message : "Failed to send. Please try again.";
52616
+ return error instanceof BlockApiError ? error.message : "We couldn’t send the sign-in link. Please try again.";
51826
52617
  }
51827
52618
  var init_MagicLinkForm = __esmMin((() => {
51828
52619
  init_ThemedButton();
52620
+ init_DemoPortalSignInLink();
51829
52621
  init_api$1();
52622
+ init_client$1();
52623
+ init_demoPortalMagicLink();
51830
52624
  init_MagicLinkForm_state();
51831
52625
  }));
51832
52626
  //#endregion
@@ -52141,19 +52935,19 @@ function isExistingRegistrationBlocking$1(wizard) {
52141
52935
  }
52142
52936
  function resolveTicketSelectionContinueLabel(input) {
52143
52937
  if (input.isCheckingExistingRegistration) return "Checking registration...";
52938
+ if (input.ticketTypeSelectionBlocked) return "Choose a ticket";
52144
52939
  if (input.registrationOptionsPending) return "Checking availability...";
52145
52940
  if (input.registrationOptionsFailed) return "Availability unavailable";
52146
52941
  if (input.hasExistingRegistration) return resolveExistingRegistrationLabel(input.wizard);
52147
- if (input.ticketTypeSelectionBlocked) return "Choose a ticket";
52148
52942
  return "Continue";
52149
52943
  }
52150
52944
  function SelectTicketsActions(props) {
52151
52945
  const { wizard } = props;
52152
- const registrationOptionsPending = wizard.registrationOptionsState.tag === "idle" || wizard.registrationOptionsState.tag === "loading";
52946
+ const ticketTypeSelectionBlocked = wizard.ticketTypeSelectionRequired && !wizard.hasValidTicketSelection;
52947
+ const registrationOptionsPending = !ticketTypeSelectionBlocked && ["idle", "loading"].includes(wizard.registrationOptionsState.tag);
52153
52948
  const registrationOptionsFailed = wizard.registrationOptionsState.tag === "failed";
52154
52949
  const isCheckingExistingRegistration = wizard.portalAuthState === "authenticated" && wizard.existingRegistrationLoading;
52155
52950
  const hasExistingRegistration = isExistingRegistrationBlocking$1(wizard);
52156
- const ticketTypeSelectionBlocked = wizard.ticketTypeSelectionRequired && !wizard.hasValidTicketSelection;
52157
52951
  const isContinueDisabled = registrationOptionsPending || registrationOptionsFailed || isCheckingExistingRegistration || hasExistingRegistration || ticketTypeSelectionBlocked;
52158
52952
  const continueLabel = resolveTicketSelectionContinueLabel({
52159
52953
  wizard,
@@ -108007,8 +108801,9 @@ var SuccessStep;
108007
108801
  var init_SuccessStep = __esmMin((() => {
108008
108802
  init_shared();
108009
108803
  init_BookingMailingListNote();
108010
- SuccessStep = ({ title, message, variant = "success", mailingListSignupNote, context = "booking" }) => {
108011
- return /* @__PURE__ */ jsx(TerminalPanel, {
108804
+ init_DemoBookingPortalAccess();
108805
+ SuccessStep = ({ title, copy, variant = "success", mailingListSignupNote, context = "booking", demoEmailSuppressed = false, customerEmail }) => {
108806
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(TerminalPanel, {
108012
108807
  tone: variant === "info" ? "info" : "success",
108013
108808
  className: "er-center",
108014
108809
  iconClassName: "er-icon",
@@ -108048,12 +108843,18 @@ var init_SuccessStep = __esmMin((() => {
108048
108843
  })
108049
108844
  }),
108050
108845
  title: title ?? (variant === "info" ? "Already Registered" : "Registration Confirmed!"),
108051
- body: message,
108846
+ body: /* @__PURE__ */ jsx(BookingConfirmation, {
108847
+ demoEmailSuppressed,
108848
+ email: customerEmail,
108849
+ copy,
108850
+ messagePresentation: { kind: "plain" },
108851
+ noteClassName: "er-text--muted"
108852
+ }),
108052
108853
  secondaryBody: mailingListSignupNote ? /* @__PURE__ */ jsx(BookingMailingListNote, {
108053
108854
  note: mailingListSignupNote,
108054
108855
  context
108055
108856
  }) : void 0
108056
- });
108857
+ }) });
108057
108858
  };
108058
108859
  }));
108059
108860
  //#endregion
@@ -108550,7 +109351,8 @@ function EventRegistrationTerminalState(props) {
108550
109351
  }) : null;
108551
109352
  case "success": return /* @__PURE__ */ jsx(EventRegistrationSuccess, {
108552
109353
  wizard,
108553
- fallbackMessage: props.successMessage
109354
+ fallbackMessage: props.successMessage,
109355
+ demoEmailSuppressed: props.demoEmailSuppressed
108554
109356
  });
108555
109357
  case "error": return /* @__PURE__ */ jsx(ErrorStep, {
108556
109358
  message: wizard.errorMessage,
@@ -108567,12 +109369,15 @@ function EventRegistrationTerminalState(props) {
108567
109369
  function EventRegistrationSuccess(props) {
108568
109370
  const result = props.wizard.registrationResult;
108569
109371
  if (!result) return null;
109372
+ const copy = getRegistrationSuccessCopy(result, props.fallbackMessage);
108570
109373
  return /* @__PURE__ */ jsx(SuccessStep, {
108571
109374
  title: result.title,
108572
109375
  variant: result.variant,
108573
- message: result.message ?? props.fallbackMessage,
109376
+ copy,
108574
109377
  mailingListSignupNote: result.mailingListSignupNote,
108575
- context: result.status === "waitlist" ? "waitlist" : "booking"
109378
+ context: result.status === "waitlist" ? "waitlist" : "booking",
109379
+ demoEmailSuppressed: props.demoEmailSuppressed,
109380
+ customerEmail: props.wizard.formData.email
108576
109381
  });
108577
109382
  }
108578
109383
  function EventRegistrationSurface(props) {
@@ -108620,11 +109425,13 @@ function EventRegistrationSurface(props) {
108620
109425
  }), /* @__PURE__ */ jsx(EventRegistrationTerminalState, {
108621
109426
  wizard,
108622
109427
  supportEmail: props.supportEmail,
108623
- successMessage: props.successMessage
109428
+ successMessage: props.successMessage,
109429
+ demoEmailSuppressed: props.demoEmailSuppressed
108624
109430
  })]
108625
109431
  });
108626
109432
  }
108627
109433
  var init_EventRegistrationSurface = __esmMin((() => {
109434
+ init_booking_form_state();
108628
109435
  init_MagicLinkForm();
108629
109436
  init_spinner$1();
108630
109437
  init_ErrorStep();
@@ -108639,109 +109446,17 @@ var init_EventRegistrationSurface = __esmMin((() => {
108639
109446
  init_VerifyingTimeoutStep();
108640
109447
  }));
108641
109448
  //#endregion
108642
- //#region ../blocks/src/system/runtime/nodes/event-registration/EventRegistrationBookingLayer.tsx
108643
- function BookingEntry(props) {
108644
- const base = props.variant === "teaser" ? "er-booking-teaser" : "er-booking-bar";
108645
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
108646
- className: `${base}__info`,
108647
- children: [
108648
- /* @__PURE__ */ jsx("span", {
108649
- className: `${base}__title`,
108650
- children: "Book this event"
108651
- }),
108652
- props.summary && /* @__PURE__ */ jsx("span", {
108653
- className: `${base}__meta`,
108654
- children: props.summary
108655
- }),
108656
- props.variant === "teaser" && props.ticketCurrency && props.ticketTypes.length > 0 ? /* @__PURE__ */ jsx("div", {
108657
- className: "er-booking-teaser__tickets",
108658
- children: props.ticketTypes.map((ticketType) => /* @__PURE__ */ jsxs("div", {
108659
- className: "er-booking-teaser__ticket",
108660
- children: [/* @__PURE__ */ jsx("span", {
108661
- className: "er-booking-teaser__ticket-name",
108662
- children: ticketType.name
108663
- }), /* @__PURE__ */ jsx("strong", { children: props.formatTicketPrice(ticketType) })]
108664
- }, ticketType.pricingOptionId))
108665
- }) : null
108666
- ]
108667
- }), /* @__PURE__ */ jsx(ThemedButton, {
108668
- type: "button",
108669
- variant: props.buttonVariant,
108670
- size: "md",
108671
- extraClassName: `${base}__cta`,
108672
- label: "Book now",
108673
- onClick: props.onOpen
108674
- })] });
108675
- }
108676
- function EventRegistrationBookingLayer(props) {
108677
- const entryProps = {
108678
- summary: [props.priceLabel, props.availabilityLabel].filter(Boolean).join(" · "),
108679
- ticketTypes: props.ticketTypes,
108680
- ticketCurrency: props.ticketCurrency,
108681
- buttonVariant: props.buttonVariant,
108682
- formatTicketPrice: props.formatTicketPrice,
108683
- onOpen: props.onOpen
108684
- };
108685
- const floatingBar = !props.overlayOpen && props.isWizardStep ? /* @__PURE__ */ jsx("div", {
108686
- className: "er-booking-bar",
108687
- children: /* @__PURE__ */ jsx("div", {
108688
- className: "er-booking-bar__inner",
108689
- children: /* @__PURE__ */ jsx(BookingEntry, {
108690
- ...entryProps,
108691
- variant: "bar"
108692
- })
108693
- })
108694
- }) : null;
108695
- const floatingLayer = props.portalRoot ? createPortal(/* @__PURE__ */ jsx("div", {
108696
- className: props.registrationRootClassName,
108697
- "data-block": "event-registration",
108698
- children: floatingBar
108699
- }), props.portalRoot) : floatingBar;
108700
- const overlayLayer = props.overlayOpen ? /* @__PURE__ */ jsx(ModalShell, {
108701
- title: "Book this event",
108702
- titleId: "event-registration-booking-title",
108703
- onClose: props.onClose,
108704
- portal: props.portalRoot != null,
108705
- portalRoot: props.portalRoot,
108706
- portalWrapperClassName: props.registrationRootClassName,
108707
- portalWrapperProps: { "data-block": "event-registration" },
108708
- overlayClassName: "er-booking-overlay",
108709
- modalClassName: "er-booking-overlay__panel",
108710
- renderHeader: ({ closeButtonRef, onClose, title, titleId }) => /* @__PURE__ */ jsxs("div", {
108711
- className: "er-booking-overlay__header",
108712
- children: [/* @__PURE__ */ jsx("h2", {
108713
- className: "er-booking-overlay__title",
108714
- id: titleId,
108715
- children: title
108716
- }), /* @__PURE__ */ jsx("button", {
108717
- ref: closeButtonRef,
108718
- type: "button",
108719
- className: "er-booking-overlay__close",
108720
- onClick: onClose,
108721
- "aria-label": "Close booking",
108722
- children: "×"
108723
- })]
108724
- }),
108725
- children: props.overlaySurface
108726
- }) : null;
108727
- return /* @__PURE__ */ jsxs(Fragment, { children: [
108728
- props.isWizardStep && /* @__PURE__ */ jsx("div", {
108729
- className: "er-booking-teaser",
108730
- children: /* @__PURE__ */ jsx(BookingEntry, {
108731
- ...entryProps,
108732
- variant: "teaser"
108733
- })
108734
- }),
108735
- floatingLayer,
108736
- overlayLayer
108737
- ] });
108738
- }
108739
- var init_EventRegistrationBookingLayer = __esmMin((() => {
108740
- init_ModalShell();
108741
- init_ThemedButton();
108742
- }));
108743
- //#endregion
108744
109449
  //#region ../blocks/src/system/runtime/nodes/event-registration/EventRegistrationWizard.tsx
109450
+ function getPortalAuthCopy(waitlistClaimRequiresPortalLogin, loginMessage, demoEmailSuppressed) {
109451
+ const defaultCopy = waitlistClaimRequiresPortalLogin ? {
109452
+ ...EVENT_PORTAL_AUTH_COPY["waitlist-claim"],
109453
+ description: loginMessage ?? "Log in to continue with your waitlist claim."
109454
+ } : EVENT_PORTAL_AUTH_COPY.membership;
109455
+ return demoEmailSuppressed && !waitlistClaimRequiresPortalLogin ? {
109456
+ ...defaultCopy,
109457
+ buttonText: "Get a sign-in link →"
109458
+ } : defaultCopy;
109459
+ }
108745
109460
  function getActiveTicketTypes(event) {
108746
109461
  return event?.pricing.kind === "tiered" ? event.pricing.options.filter((ticketType) => ticketType.isActive).sort((left, right) => left.sortOrder - right.sortOrder).map(({ id, ...ticketType }) => ({
108747
109462
  ...ticketType,
@@ -108789,11 +109504,18 @@ function useConfiguredEventRegistrationWizard(props) {
108789
109504
  });
108790
109505
  }
108791
109506
  function EventRegistrationWizard(props) {
108792
- const { occurrenceContext, subject, events, showVenue = true, showCapacity = true, successMessage = "Thank you for registering! Check your email for confirmation details.", buttonText = "Complete Registration", buttonVariant = "primary", className, spamProtectionEnabled, supportEmail } = props;
109507
+ const wizard = useConfiguredEventRegistrationWizard(props);
109508
+ return /* @__PURE__ */ jsx(EventRegistrationWizardView, {
109509
+ ...props,
109510
+ wizard
109511
+ });
109512
+ }
109513
+ function EventRegistrationWizardView(viewProps) {
109514
+ const { wizard, ...props } = viewProps;
109515
+ const { showVenue = true, showCapacity = true, successMessage, buttonText = "Complete Registration", buttonVariant = "primary", className, spamProtectionEnabled, supportEmail } = props;
108793
109516
  const showSpamProtection = spamProtectionEnabled ?? isSpamProtectionEnabled();
108794
109517
  const registrationRootClassName = `event-registration ${className || ""}`;
108795
109518
  const registrationRootRef = React.useRef(null);
108796
- const wizard = useConfiguredEventRegistrationWizard(props);
108797
109519
  useEventCheckoutHandoffRestore(wizard.step === "redirecting");
108798
109520
  const [bookingOverlayOpen, setBookingOverlayOpen] = useState(false);
108799
109521
  const [floatingPortalRoot, setFloatingPortalRoot] = useState(null);
@@ -108859,10 +109581,7 @@ function EventRegistrationWizard(props) {
108859
109581
  const summaryPriceLabel = summaryEvent ? formatEventPriceDisplay(summaryEvent.pricing) : null;
108860
109582
  const summaryAvailabilityLabel = getAvailabilityLabel(summaryEvent, wizard.selectedAttendanceMode);
108861
109583
  const waitlistClaimRequiresPortalLogin = wizard.waitlistClaim.requiresPortalLogin && wizard.portalAuthState !== "authenticated" && wizard.portalAuthState !== "checking";
108862
- const portalAuthCopy = waitlistClaimRequiresPortalLogin ? {
108863
- ...EVENT_PORTAL_AUTH_COPY["waitlist-claim"],
108864
- description: wizard.waitlistClaim.loginMessage ?? "Log in to continue with your waitlist claim."
108865
- } : EVENT_PORTAL_AUTH_COPY.membership;
109584
+ const portalAuthCopy = getPortalAuthCopy(waitlistClaimRequiresPortalLogin, wizard.waitlistClaim.loginMessage, props.demoEmailSuppressed);
108866
109585
  const showPortalAuthPrompt = waitlistClaimRequiresPortalLogin || wizard.step === "select-tickets" && wizard.portalAuthState !== "authenticated" && wizard.portalAuthState !== "checking" && summaryEventPricingType !== "free";
108867
109586
  const renderRegistrationSurface = (variant) => /* @__PURE__ */ jsx(EventRegistrationSurface, {
108868
109587
  variant,
@@ -108879,7 +109598,8 @@ function EventRegistrationWizard(props) {
108879
109598
  buttonText,
108880
109599
  buttonVariant,
108881
109600
  supportEmail,
108882
- successMessage
109601
+ successMessage,
109602
+ demoEmailSuppressed: props.demoEmailSuppressed
108883
109603
  });
108884
109604
  const isEmbedded = (className ?? "").includes("event-registration--embedded");
108885
109605
  const overlayEnabled = props.overlayEnabled === true;
@@ -108927,8 +109647,8 @@ var init_EventRegistrationWizard = __esmMin((() => {
108927
109647
  init_themePortalRoot();
108928
109648
  init_constants();
108929
109649
  init_useEventCheckoutHandoffRestore();
108930
- init_EventRegistrationSurface();
108931
109650
  init_EventRegistrationBookingLayer();
109651
+ init_EventRegistrationSurface();
108932
109652
  EVENT_PORTAL_AUTH_COPY = {
108933
109653
  membership: {
108934
109654
  title: "Already have an account?",
@@ -109236,7 +109956,7 @@ var init_event_registration_client = __esmMin((() => {
109236
109956
  * Loads Leaflet CSS/JS from CDN to avoid bundling in the blocks package.
109237
109957
  */
109238
109958
  function isLeafletApi(value) {
109239
- if (!isRecord$16(value)) return false;
109959
+ if (!isRecord$18(value)) return false;
109240
109960
  return typeof value.map === "function" && typeof value.tileLayer === "function" && typeof value.marker === "function";
109241
109961
  }
109242
109962
  function loadLeaflet() {
@@ -109979,6 +110699,109 @@ var init_useDiscountApply = __esmMin((() => {
109979
110699
  }));
109980
110700
  //#endregion
109981
110701
  //#region ../blocks/src/system/runtime/nodes/shop.client.tsx
110702
+ function ShopCheckoutReturnNotice(props) {
110703
+ const succeeded = props.notice.kind === "success";
110704
+ const copy = getShopSuccessCopy(succeeded ? "success" : "cancelled");
110705
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(TerminalPanel, {
110706
+ tone: succeeded ? "success" : "warning",
110707
+ className: "shop__return",
110708
+ titleClassName: "shop__return-title",
110709
+ bodyClassName: "shop__return-text",
110710
+ icon: /* @__PURE__ */ jsx(StateIcon, {
110711
+ variant: succeeded ? "success" : "warning",
110712
+ children: succeeded ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CrossIcon, {})
110713
+ }),
110714
+ title: succeeded ? "Payment successful" : "Payment cancelled",
110715
+ body: /* @__PURE__ */ jsx(BookingConfirmation, {
110716
+ demoEmailSuppressed: succeeded && props.demoEmailSuppressed,
110717
+ email: props.email,
110718
+ copy,
110719
+ messagePresentation: { kind: "plain" },
110720
+ noteClassName: "shop__return-text"
110721
+ }),
110722
+ actions: /* @__PURE__ */ jsx(ThemedButton, {
110723
+ type: "button",
110724
+ variant: "secondary",
110725
+ size: "sm",
110726
+ extraClassName: "shop__return-dismiss",
110727
+ label: "Dismiss",
110728
+ onClick: props.onDismiss
110729
+ })
110730
+ }) });
110731
+ }
110732
+ function handleShopCheckoutResult(input) {
110733
+ switch (input.result.type) {
110734
+ case "duplicate_membership_warning":
110735
+ input.dispatch({
110736
+ type: "submitDuplicateWarning",
110737
+ warning: input.result
110738
+ });
110739
+ return;
110740
+ case "bypassed":
110741
+ if (input.result.demoBookingPass) storeDemoBookingCheckoutReturn(input.checkout.form.email, input.result.demoBookingPass);
110742
+ window.location.href = input.successUrl;
110743
+ return;
110744
+ case "redirect":
110745
+ if (input.result.demoBookingPass) storeDemoBookingCheckoutReturn(input.checkout.form.email, input.result.demoBookingPass);
110746
+ window.location.href = input.result.checkoutUrl;
110747
+ return;
110748
+ default: return assertNever$22(input.result);
110749
+ }
110750
+ }
110751
+ function buildDirectShopCheckoutPlan(input) {
110752
+ const successUrl = new URL(input.currentUrl);
110753
+ successUrl.searchParams.set("checkout", "success");
110754
+ successUrl.searchParams.set("product", input.checkout.item.product.id);
110755
+ const cancelUrl = new URL(input.currentUrl);
110756
+ cancelUrl.searchParams.set("checkout", "cancelled");
110757
+ const form = {
110758
+ ...input.checkout.form,
110759
+ discountCode: input.manualCodeEntryAllowed ? getAppliedDiscountCode(input.discountApply) ?? "" : ""
110760
+ };
110761
+ return {
110762
+ successUrl: successUrl.toString(),
110763
+ command: planDirectShopCheckoutRequest({
110764
+ productType: input.checkout.item.productType,
110765
+ productId: input.checkout.item.product.id,
110766
+ form,
110767
+ successUrl: successUrl.toString(),
110768
+ cancelUrl: cancelUrl.toString(),
110769
+ confirmDuplicate: input.confirmDuplicate
110770
+ })
110771
+ };
110772
+ }
110773
+ async function submitDirectShopCheckout(input) {
110774
+ const checkout = input.checkout;
110775
+ if (!checkout) return;
110776
+ input.dispatch({ type: "submitStarted" });
110777
+ try {
110778
+ const attempt = buildDirectShopCheckoutPlan({
110779
+ checkout,
110780
+ currentUrl: window.location.href,
110781
+ confirmDuplicate: input.confirmDuplicate,
110782
+ discountApply: input.discountApply,
110783
+ manualCodeEntryAllowed: input.manualCodeEntryAllowed
110784
+ });
110785
+ if (!attempt.command.ok) {
110786
+ input.dispatch({
110787
+ type: "submitFailed",
110788
+ error: attempt.command.error.message
110789
+ });
110790
+ return;
110791
+ }
110792
+ handleShopCheckoutResult({
110793
+ result: await input.api.createShopCheckout(attempt.command.value),
110794
+ checkout,
110795
+ successUrl: attempt.successUrl,
110796
+ dispatch: input.dispatch
110797
+ });
110798
+ } catch (error) {
110799
+ input.dispatch({
110800
+ type: "submitFailed",
110801
+ error: error instanceof Error ? error.message : "An error occurred"
110802
+ });
110803
+ }
110804
+ }
109982
110805
  function ShopClient(props) {
109983
110806
  return /* @__PURE__ */ jsx(PassesMembershipsController, { render: props.render });
109984
110807
  }
@@ -110028,6 +110851,7 @@ function PassesMembershipsController({ render }) {
110028
110851
  const [discountApply, dispatchDiscountApply] = React.useReducer(discountApplyReducer, initialDiscountApplyState);
110029
110852
  const passAddFeedback = useTransientShopAddFeedback();
110030
110853
  const [modalPortalRoot, setModalPortalRoot] = useState(null);
110854
+ const [checkoutReturnEmail, setCheckoutReturnEmail] = useState(null);
110031
110855
  const shopRootRef = useRef(null);
110032
110856
  const emailInputRef = useRef(null);
110033
110857
  const focusedCheckoutKeyRef = useRef(null);
@@ -110122,6 +110946,7 @@ function PassesMembershipsController({ render }) {
110122
110946
  if (!checkoutStatus) return;
110123
110947
  scrollToBlock(SHOP_ANCHOR_ID);
110124
110948
  if (checkoutStatus === "success") {
110949
+ setCheckoutReturnEmail(readDemoBookingCheckoutReturnEmail());
110125
110950
  dispatch({
110126
110951
  type: "setReturnNotice",
110127
110952
  notice: { kind: "success" }
@@ -110133,58 +110958,14 @@ function PassesMembershipsController({ render }) {
110133
110958
  notice: { kind: "cancelled" }
110134
110959
  });
110135
110960
  }, []);
110136
- const submitCheckout = useCallback(async (confirmDuplicate = false) => {
110137
- if (!checkout) return;
110138
- dispatch({ type: "submitStarted" });
110139
- try {
110140
- const currentUrl = window.location.href;
110141
- const successUrl = new URL(currentUrl);
110142
- successUrl.searchParams.set("checkout", "success");
110143
- successUrl.searchParams.set("product", checkout.item.product.id);
110144
- const cancelUrl = new URL(currentUrl);
110145
- cancelUrl.searchParams.set("checkout", "cancelled");
110146
- const form = {
110147
- ...checkout.form,
110148
- discountCode: discountUi.manualCodeEntryAllowed ? getAppliedDiscountCode(discountApply) ?? "" : ""
110149
- };
110150
- const command = planDirectShopCheckoutRequest({
110151
- productType: checkout.item.productType,
110152
- productId: checkout.item.product.id,
110153
- form,
110154
- successUrl: successUrl.toString(),
110155
- cancelUrl: cancelUrl.toString(),
110156
- confirmDuplicate
110157
- });
110158
- if (!command.ok) {
110159
- dispatch({
110160
- type: "submitFailed",
110161
- error: command.error.message
110162
- });
110163
- return;
110164
- }
110165
- const result = await api.createShopCheckout(command.value);
110166
- switch (result.type) {
110167
- case "duplicate_membership_warning":
110168
- dispatch({
110169
- type: "submitDuplicateWarning",
110170
- warning: result
110171
- });
110172
- return;
110173
- case "bypassed":
110174
- window.location.href = successUrl.toString();
110175
- return;
110176
- case "redirect":
110177
- window.location.href = result.checkoutUrl;
110178
- return;
110179
- default: return assertNever$22(result);
110180
- }
110181
- } catch (submitError) {
110182
- dispatch({
110183
- type: "submitFailed",
110184
- error: submitError instanceof Error ? submitError.message : "An error occurred"
110185
- });
110186
- }
110187
- }, [
110961
+ const submitCheckout = useCallback((confirmDuplicate = false) => submitDirectShopCheckout({
110962
+ checkout,
110963
+ confirmDuplicate,
110964
+ api,
110965
+ discountApply,
110966
+ manualCodeEntryAllowed: discountUi.manualCodeEntryAllowed,
110967
+ dispatch
110968
+ }), [
110188
110969
  api,
110189
110970
  checkout,
110190
110971
  discountApply,
@@ -110211,26 +110992,12 @@ function PassesMembershipsController({ render }) {
110211
110992
  ref: shopRootRef,
110212
110993
  children: /* @__PURE__ */ jsx(PassesMembershipsSectionView, {
110213
110994
  display,
110214
- beforeContent: /* @__PURE__ */ jsx(Fragment, { children: state.returnNotice ? /* @__PURE__ */ jsx(TerminalPanel, {
110215
- tone: state.returnNotice.kind === "success" ? "success" : "warning",
110216
- className: "shop__return",
110217
- titleClassName: "shop__return-title",
110218
- bodyClassName: "shop__return-text",
110219
- icon: /* @__PURE__ */ jsx(StateIcon, {
110220
- variant: state.returnNotice.kind === "success" ? "success" : "warning",
110221
- children: state.returnNotice.kind === "success" ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CrossIcon, {})
110222
- }),
110223
- title: state.returnNotice.kind === "success" ? "Payment successful" : "Payment cancelled",
110224
- body: state.returnNotice.kind === "success" ? "Check your email for confirmation." : "You can try again whenever you’re ready.",
110225
- actions: /* @__PURE__ */ jsx(ThemedButton, {
110226
- type: "button",
110227
- variant: "secondary",
110228
- size: "sm",
110229
- extraClassName: "shop__return-dismiss",
110230
- label: "Dismiss",
110231
- onClick: () => dispatch({ type: "clearReturnNotice" })
110232
- })
110233
- }) : null }),
110995
+ beforeContent: state.returnNotice ? /* @__PURE__ */ jsx(ShopCheckoutReturnNotice, {
110996
+ notice: state.returnNotice,
110997
+ demoEmailSuppressed: hydration.demoEmailSuppressed === true,
110998
+ email: checkoutReturnEmail,
110999
+ onDismiss: () => dispatch({ type: "clearReturnNotice" })
111000
+ }) : null,
110234
111001
  passCards: display.passes.map((passDisplay) => {
110235
111002
  return /* @__PURE__ */ jsx(PassProductCard, {
110236
111003
  display: passDisplay,
@@ -110450,6 +111217,9 @@ var init_shop_client = __esmMin((() => {
110450
111217
  init_shop_checkout_form();
110451
111218
  init_DiscountCodeDisclosure();
110452
111219
  init_useDiscountApply();
111220
+ init_DemoBookingPortalAccess();
111221
+ init_booking_form_state();
111222
+ init_demoBookingPassStorage();
110453
111223
  SHOP_ANCHOR_ID = "shop";
110454
111224
  }));
110455
111225
  //#endregion
@@ -112528,14 +113298,26 @@ function CartController(props) {
112528
113298
  })] })
112529
113299
  });
112530
113300
  }
113301
+ function ShopCheckoutNoticeView(props) {
113302
+ if (!props.notice) return null;
113303
+ const succeeded = props.notice === "success";
113304
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(FeedbackMessage, {
113305
+ tone: succeeded ? "success" : "warning",
113306
+ className: "rb-mb-4 rb-rounded-xl rb-border rb-p-4",
113307
+ role: "status",
113308
+ children: succeeded ? "Payment successful." : "Checkout cancelled."
113309
+ }), succeeded && props.demoEmailSuppressed ? /* @__PURE__ */ jsx(DemoBookingPortalAccess, { email: props.email }) : null] });
113310
+ }
112531
113311
  function CheckoutController(props) {
112532
113312
  const api = useBlockApi();
112533
113313
  const cart = useCommerceCart(api.config.siteId);
112534
113314
  const [state, dispatch] = React$1.useReducer(shopCheckoutReducer, initialShopCheckoutState);
113315
+ const [checkoutReturnEmail, setCheckoutReturnEmail] = React$1.useState(null);
112535
113316
  const [discountApply, dispatchDiscountApply] = React$1.useReducer(discountApplyReducer, initialDiscountApplyState);
112536
113317
  React$1.useEffect(() => {
112537
113318
  const checkout = consumeSearchParam("checkout");
112538
113319
  if (checkout === "success") {
113320
+ setCheckoutReturnEmail(readDemoBookingCheckoutReturnEmail());
112539
113321
  cart.clear();
112540
113322
  dispatch({
112541
113323
  type: "setNotice",
@@ -112595,6 +113377,7 @@ function CheckoutController(props) {
112595
113377
  return;
112596
113378
  }
112597
113379
  const result = await api.createUnifiedCheckout(command.value);
113380
+ if (result.demoBookingPass) storeDemoBookingCheckoutReturn(state.form.email, result.demoBookingPass);
112598
113381
  if (result.type === "redirect") {
112599
113382
  window.location.href = result.checkoutUrl;
112600
113383
  return;
@@ -112613,12 +113396,11 @@ function CheckoutController(props) {
112613
113396
  };
112614
113397
  return /* @__PURE__ */ jsx(CheckoutShellView, {
112615
113398
  display,
112616
- notice: state.notice ? /* @__PURE__ */ jsx(FeedbackMessage, {
112617
- tone: state.notice === "success" ? "success" : "warning",
112618
- className: "rb-mb-4 rb-rounded-xl rb-border rb-p-4",
112619
- role: "status",
112620
- children: state.notice === "success" ? "Payment successful." : "Checkout cancelled."
112621
- }) : null,
113399
+ notice: /* @__PURE__ */ jsx(ShopCheckoutNoticeView, {
113400
+ notice: state.notice,
113401
+ demoEmailSuppressed: props.render.hydration.demoEmailSuppressed === true,
113402
+ email: checkoutReturnEmail
113403
+ }),
112622
113404
  body: /* @__PURE__ */ jsxs("form", {
112623
113405
  className: "rb-flex rb-flex-col rb-gap-4",
112624
113406
  onSubmit: handleSubmit,
@@ -112716,6 +113498,8 @@ var init_shop_commerce = __esmMin((() => {
112716
113498
  init_display();
112717
113499
  init_view$1();
112718
113500
  init_shop_commerce_store();
113501
+ init_DemoBookingPortalAccess();
113502
+ init_demoBookingPassStorage();
112719
113503
  init_shop_commerce_shared();
112720
113504
  init_shop_add_feedback();
112721
113505
  init_shop_checkout_state();
@@ -119839,6 +120623,9 @@ var init_events = __esmMin((() => {
119839
120623
  init_EventCalendar_client();
119840
120624
  init_EventCombined_client();
119841
120625
  init_EventListing_client();
120626
+ init_EventCard_client();
120627
+ init_eventCardPresentations();
120628
+ init_EventListing_interactive();
119842
120629
  }));
119843
120630
  //#endregion
119844
120631
  //#region src/rendering/islands/enhancers/eventRegistration.tsx