@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
@@ -606,10 +606,14 @@ function subtractDaysFromIso(isoString, dayCount) {
606
606
  return addDaysToIso(isoString, -dayCount);
607
607
  }
608
608
  var init_date_math = __esmMin((() => {}));
609
+ var init_html_entities = __esmMin((() => {}));
609
610
  var init_duration$1 = __esmMin((() => {}));
610
611
  var init_demo_capability_policy = __esmMin((() => {
611
612
  init_src$2();
612
- })), init_demo_claim_access = __esmMin((() => {})), init_demo_lifecycle_status = __esmMin((() => {}));
613
+ })), init_demo_claim_access = __esmMin((() => {}));
614
+ var init_demo_lifecycle_status = __esmMin((() => {})), init_demo_warm_pool_target = __esmMin((() => {
615
+ init_result$1();
616
+ }));
613
617
  var init_demo_runtime = __esmMin((() => {}));
614
618
  var init_collections = __esmMin((() => {}));
615
619
  //#endregion
@@ -629,6 +633,19 @@ function parseCurrencyCode(value) {
629
633
  function resolveCurrencyLocale(currencyCode, override) {
630
634
  return override ?? CURRENCY_LOCALE_BY_CODE[currencyCode] ?? "en";
631
635
  }
636
+ function fractionDigitsFor(decimals, exactFormatter) {
637
+ switch (decimals) {
638
+ case "exact": return {};
639
+ case "auto": return {
640
+ minimumFractionDigits: 0,
641
+ maximumFractionDigits: exactFormatter.resolvedOptions().maximumFractionDigits
642
+ };
643
+ case "whole": return {
644
+ minimumFractionDigits: 0,
645
+ maximumFractionDigits: 0
646
+ };
647
+ }
648
+ }
632
649
  /**
633
650
  * The single currency-amount formatter for the product: minor units in,
634
651
  * localized string out.
@@ -639,6 +656,13 @@ function resolveCurrencyLocale(currencyCode, override) {
639
656
  * own `Intl.NumberFormat`.
640
657
  */
641
658
  function formatCurrencyAmount(amountCents, currency, options) {
659
+ return formatCurrencyMajorUnits(amountCents / 100, currency, options);
660
+ }
661
+ /**
662
+ * `formatCurrencyAmount` for an amount already in MAJOR units (29.99 = £29.99),
663
+ * such as a registrar price. Prefer minor units everywhere else.
664
+ */
665
+ function formatCurrencyMajorUnits(amount, currency, options) {
642
666
  const currencyCode = currency.toUpperCase();
643
667
  const locale = resolveCurrencyLocale(currencyCode, options?.locale);
644
668
  try {
@@ -646,17 +670,13 @@ function formatCurrencyAmount(amountCents, currency, options) {
646
670
  style: "currency",
647
671
  currency: currencyCode
648
672
  });
649
- const fractionDigits = options?.decimals === "auto" ? {
650
- minimumFractionDigits: 0,
651
- maximumFractionDigits: exactFormatter.resolvedOptions().maximumFractionDigits
652
- } : {};
653
673
  return new Intl.NumberFormat(locale, {
654
674
  style: "currency",
655
675
  currency: currencyCode,
656
- ...fractionDigits
657
- }).format(amountCents / 100);
676
+ ...fractionDigitsFor(options?.decimals ?? "exact", exactFormatter)
677
+ }).format(amount);
658
678
  } catch {
659
- return `${(amountCents / 100).toFixed(2)} ${currencyCode}`;
679
+ return `${amount.toFixed(2)} ${currencyCode}`;
660
680
  }
661
681
  }
662
682
  var CURRENCY_CODE_INPUT_PATTERN, CURRENCY_LOCALE_BY_CODE;
@@ -940,7 +960,7 @@ function parseEventPageSurfaceDestinationMode(value) {
940
960
  return value === "cms-managed" || value === "system-managed" ? value : void 0;
941
961
  }
942
962
  function parseEventPageSurfaceSubject(value) {
943
- if (!isRecord$41(value)) return err$2({ kind: "notObject" });
963
+ if (!isRecord$43(value)) return err$2({ kind: "notObject" });
944
964
  switch (value.kind) {
945
965
  case "eventSeries": {
946
966
  const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
@@ -995,7 +1015,7 @@ function parseEventSeriesIdList(values) {
995
1015
  }
996
1016
  return ok$2(parsed);
997
1017
  }
998
- function isRecord$41(value) {
1018
+ function isRecord$43(value) {
999
1019
  return typeof value === "object" && value !== null && !Array.isArray(value);
1000
1020
  }
1001
1021
  var init_event_page_surface_subject = __esmMin((() => {
@@ -1549,7 +1569,36 @@ var init_try_async = __esmMin((() => {
1549
1569
  init_result$1();
1550
1570
  }));
1551
1571
  var init_narrow_result = __esmMin((() => {}));
1552
- var init_editor_state = __esmMin((() => {})), init_block_content_identity = __esmMin((() => {}));
1572
+ var init_editor_state = __esmMin((() => {}));
1573
+ var init_editor_value_sync = __esmMin((() => {
1574
+ init_assert_never();
1575
+ }));
1576
+ var init_edit_lease = __esmMin((() => {
1577
+ init_branded();
1578
+ }));
1579
+ //#endregion
1580
+ //#region ../core/src/block-content-identity.ts
1581
+ function readContentVersionId(value) {
1582
+ const parsed = parseContentVersionId(value);
1583
+ return parsed.ok ? parsed.value : null;
1584
+ }
1585
+ /** The one pairing of a published id with its content. */
1586
+ function readPublishedBlockPlacement(id, content) {
1587
+ if (id == null && content == null) return null;
1588
+ const versionId = readContentVersionId(id);
1589
+ return versionId !== null && content != null ? {
1590
+ kind: "published",
1591
+ id: versionId,
1592
+ content
1593
+ } : {
1594
+ kind: "incomplete",
1595
+ id: id ?? null,
1596
+ content: content ?? null
1597
+ };
1598
+ }
1599
+ var init_block_content_identity = __esmMin((() => {
1600
+ init_branded();
1601
+ }));
1553
1602
  var init_sensitive_collection = __esmMin((() => {}));
1554
1603
  //#endregion
1555
1604
  //#region ../core/src/assertNever.ts
@@ -1568,7 +1617,7 @@ var init_public_profile = __esmMin((() => {
1568
1617
  var init_public_experience = __esmMin((() => {}));
1569
1618
  //#endregion
1570
1619
  //#region ../core/src/rich-text.ts
1571
- function isRecord$39(value) {
1620
+ function isRecord$41(value) {
1572
1621
  return typeof value === "object" && value !== null && !Array.isArray(value);
1573
1622
  }
1574
1623
  function hasOnlyKeys(value, allowed) {
@@ -1579,10 +1628,10 @@ function isDenseArrayOf(value, predicate) {
1579
1628
  return true;
1580
1629
  }
1581
1630
  function isTipTapMark(value) {
1582
- return isRecord$39(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$39(value.attrs));
1631
+ return isRecord$41(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$41(value.attrs));
1583
1632
  }
1584
1633
  function isTipTapNode(value) {
1585
- if (!isRecord$39(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$39(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;
1634
+ if (!isRecord$41(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$41(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;
1586
1635
  if (value.type === "text") return typeof value.text === "string" && value.text.length > 0 && value.content === void 0;
1587
1636
  return value.text === void 0;
1588
1637
  }
@@ -1633,10 +1682,10 @@ var init_mailing_list_identifiers = __esmMin((() => {
1633
1682
  //#endregion
1634
1683
  //#region ../core/src/mailing-list-targeting-parser.ts
1635
1684
  function parseMailingListPlacementTargeting(value) {
1636
- if (!isRecord$38(value)) return targetingError("shape");
1685
+ if (!isRecord$40(value)) return targetingError("shape");
1637
1686
  if (value.mode === "default") return ok$2({ mode: "default" });
1638
1687
  if (value.mode !== "custom") return targetingError("mode");
1639
- if (!isRecord$38(value.selection)) return targetingError("selection");
1688
+ if (!isRecord$40(value.selection)) return targetingError("selection");
1640
1689
  switch (value.provider) {
1641
1690
  case "native": return parseNativeTargeting(value.selection);
1642
1691
  case "brevo": return parseBrevoTargeting(value.selection);
@@ -1645,7 +1694,7 @@ function parseMailingListPlacementTargeting(value) {
1645
1694
  }
1646
1695
  }
1647
1696
  function parseMailingListVisitorSelection(value) {
1648
- if (!isRecord$38(value)) return visitorSelectionError$1("shape");
1697
+ if (!isRecord$40(value)) return visitorSelectionError$1("shape");
1649
1698
  switch (value.provider) {
1650
1699
  case "native": {
1651
1700
  const topicIds = parseVisitorIds(value.topicIds, parseNewsletterListId);
@@ -1778,7 +1827,7 @@ function parseVisitorIds(value, parseId) {
1778
1827
  }
1779
1828
  return parsed;
1780
1829
  }
1781
- function isRecord$38(value) {
1830
+ function isRecord$40(value) {
1782
1831
  return typeof value === "object" && value !== null && !Array.isArray(value);
1783
1832
  }
1784
1833
  function targetingError(field) {
@@ -1829,11 +1878,11 @@ var init_footer_navigation_layout = __esmMin((() => {}));
1829
1878
  var init_footer_composition_types = __esmMin((() => {}));
1830
1879
  //#endregion
1831
1880
  //#region ../core/src/mailing-list-setup.ts
1832
- function isRecord$35(value) {
1881
+ function isRecord$37(value) {
1833
1882
  return typeof value === "object" && value !== null && !Array.isArray(value);
1834
1883
  }
1835
1884
  function parseMailingListProviderScope(value) {
1836
- if (!isRecord$35(value)) return err$2("invalid_mailing_list_provider_scope");
1885
+ if (!isRecord$37(value)) return err$2("invalid_mailing_list_provider_scope");
1837
1886
  if (value.provider === "native") return ok$2({ provider: "native" });
1838
1887
  if (value.provider === "brevo") {
1839
1888
  const accountId = parseBrevoAccountId(value.accountId);
@@ -1860,7 +1909,7 @@ var init_mailing_list_setup = __esmMin((() => {
1860
1909
  //#endregion
1861
1910
  //#region ../core/src/mailing-list-setup-parser.ts
1862
1911
  function parseMailingListGlobalForm(value) {
1863
- if (!isRecord$34(value)) return formError("shape");
1912
+ if (!isRecord$36(value)) return formError("shape");
1864
1913
  const fields = parseGlobalFields(value.fields);
1865
1914
  if (fields === null) return formError("fields");
1866
1915
  if (typeof value.includeOptionalPhone !== "boolean") return formError("includeOptionalPhone");
@@ -1879,7 +1928,7 @@ function parseMailingListGlobalForm(value) {
1879
1928
  });
1880
1929
  }
1881
1930
  function parseGlobalFields(value) {
1882
- if (!isRecord$34(value) || typeof value.preset !== "string") return null;
1931
+ if (!isRecord$36(value) || typeof value.preset !== "string") return null;
1883
1932
  switch (value.preset) {
1884
1933
  case "emailOnly": return { preset: "emailOnly" };
1885
1934
  case "emailName": return isRequirement(value.name) ? {
@@ -1916,7 +1965,7 @@ function parseOptionalString(value) {
1916
1965
  function isRequirement(value) {
1917
1966
  return value === "required" || value === "optional";
1918
1967
  }
1919
- function isRecord$34(value) {
1968
+ function isRecord$36(value) {
1920
1969
  return typeof value === "object" && value !== null && !Array.isArray(value);
1921
1970
  }
1922
1971
  function formError(field) {
@@ -1995,7 +2044,7 @@ var init_mailing_list_targeting = __esmMin((() => {
1995
2044
  //#endregion
1996
2045
  //#region ../core/src/mailing-list-runtime.ts
1997
2046
  function parseMailingListRuntimeContext(value) {
1998
- if (!isRecord$33(value)) return invalidRuntimeContext();
2047
+ if (!isRecord$35(value)) return invalidRuntimeContext();
1999
2048
  if (value.tag === "not_configured") return ok$2({ tag: "not_configured" });
2000
2049
  if (value.tag !== "configured") return invalidRuntimeContext();
2001
2050
  return parseConfiguredRuntimeContext(value);
@@ -2023,7 +2072,7 @@ function parseBookingSignupOffer(value) {
2023
2072
  tag: "unavailable",
2024
2073
  reason: "disabled"
2025
2074
  };
2026
- if (!isRecord$33(value)) return null;
2075
+ if (!isRecord$35(value)) return null;
2027
2076
  if (value.tag === "offered") return { tag: "offered" };
2028
2077
  if (value.tag === "unavailable" && (value.reason === "disabled" || value.reason === "fields" || value.reason === "destination")) return {
2029
2078
  tag: "unavailable",
@@ -2032,7 +2081,7 @@ function parseBookingSignupOffer(value) {
2032
2081
  return null;
2033
2082
  }
2034
2083
  function parseRuntimeProvider(value) {
2035
- if (!isRecord$33(value)) return null;
2084
+ if (!isRecord$35(value)) return null;
2036
2085
  switch (value.provider) {
2037
2086
  case "native": return parseNativeRuntimeProvider(value);
2038
2087
  case "brevo": return parseBrevoRuntimeProvider(value);
@@ -2064,7 +2113,7 @@ function parseMailchimpRuntimeProvider(value) {
2064
2113
  if (defaultAudienceId === null) return null;
2065
2114
  const audiences = [];
2066
2115
  for (const audience of value.audiences) {
2067
- if (!isRecord$33(audience)) return null;
2116
+ if (!isRecord$35(audience)) return null;
2068
2117
  const id = parseMailchimpAudienceId$1(audience.id);
2069
2118
  const name = parseName(audience.name);
2070
2119
  if (id === null || name === null || !Array.isArray(audience.interests)) return null;
@@ -2085,7 +2134,7 @@ function parseMailchimpRuntimeProvider(value) {
2085
2134
  function parseMailchimpInterests(value) {
2086
2135
  const interests = [];
2087
2136
  for (const interest of value) {
2088
- if (!isRecord$33(interest)) return null;
2137
+ if (!isRecord$35(interest)) return null;
2089
2138
  const id = parseMailchimpInterestId(interest.id);
2090
2139
  const name = parseName(interest.name);
2091
2140
  const categoryName = parseName(interest.categoryName);
@@ -2102,7 +2151,7 @@ function parseNamedItems(value, parseId) {
2102
2151
  if (!Array.isArray(value)) return null;
2103
2152
  const items = [];
2104
2153
  for (const item of value) {
2105
- if (!isRecord$33(item)) return null;
2154
+ if (!isRecord$35(item)) return null;
2106
2155
  const id = parseId(item.id);
2107
2156
  const name = parseName(item.name);
2108
2157
  if (id === null || name === null) return null;
@@ -2118,7 +2167,7 @@ function parseName(value) {
2118
2167
  const name = value.trim();
2119
2168
  return name.length > 0 ? name : null;
2120
2169
  }
2121
- function isRecord$33(value) {
2170
+ function isRecord$35(value) {
2122
2171
  return typeof value === "object" && value !== null && !Array.isArray(value);
2123
2172
  }
2124
2173
  function invalidRuntimeContext() {
@@ -2177,6 +2226,14 @@ var init_csv_render = __esmMin((() => {
2177
2226
  }));
2178
2227
  var init_csv_types = __esmMin((() => {})), init_email_format = __esmMin((() => {}));
2179
2228
  var init_slug = __esmMin((() => {}));
2229
+ function generateUuidV4(cryptoSource = globalThis.crypto) {
2230
+ if (typeof cryptoSource.randomUUID === "function") return cryptoSource.randomUUID();
2231
+ const bytes = cryptoSource.getRandomValues(/* @__PURE__ */ new Uint8Array(16));
2232
+ bytes[6] = (bytes[6] ?? 0) & 15 | 64;
2233
+ bytes[8] = (bytes[8] ?? 0) & 63 | 128;
2234
+ const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0"));
2235
+ 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("")}`;
2236
+ }
2180
2237
  var init_uuid = __esmMin((() => {}));
2181
2238
  function sortStableJsonValue(value) {
2182
2239
  if (value === null) return null;
@@ -2696,10 +2753,12 @@ var init_event_catalogue = __esmMin((() => {
2696
2753
  var init_src$2 = __esmMin((() => {
2697
2754
  init_branded();
2698
2755
  init_date_math();
2756
+ init_html_entities();
2699
2757
  init_duration$1();
2700
2758
  init_demo_capability_policy();
2701
2759
  init_demo_claim_access();
2702
2760
  init_demo_lifecycle_status();
2761
+ init_demo_warm_pool_target();
2703
2762
  init_demo_runtime();
2704
2763
  init_collections();
2705
2764
  init_event_booking_offer();
@@ -2726,6 +2785,8 @@ var init_src$2 = __esmMin((() => {
2726
2785
  init_narrow_result();
2727
2786
  init_non_empty_array();
2728
2787
  init_editor_state();
2788
+ init_editor_value_sync();
2789
+ init_edit_lease();
2729
2790
  init_block_content_identity();
2730
2791
  init_sensitive_collection();
2731
2792
  init_assertNever$1();
@@ -2823,9 +2884,13 @@ var init_fileStorage = __esmMin((() => {
2823
2884
  FILE_STORAGE_BUCKETS = {
2824
2885
  publicSite: unsafeAsStorageBucketName("media"),
2825
2886
  privateSite: unsafeAsStorageBucketName("site-files-private"),
2826
- temporary: unsafeAsStorageBucketName("temp-uploads")
2887
+ temporary: unsafeAsStorageBucketName("temp-uploads"),
2888
+ siteAssets: unsafeAsStorageBucketName("site-assets"),
2889
+ siteFonts: unsafeAsStorageBucketName("site-fonts"),
2890
+ bookingRequirementDocuments: unsafeAsStorageBucketName("booking-requirement-documents")
2827
2891
  };
2828
- FILE_STORAGE_BUCKETS.publicSite, unsafeAsStorageBucketName("site-assets"), unsafeAsStorageBucketName("site-fonts");
2892
+ FILE_STORAGE_BUCKETS.publicSite, FILE_STORAGE_BUCKETS.siteAssets, FILE_STORAGE_BUCKETS.siteFonts;
2893
+ FILE_STORAGE_BUCKETS.publicSite, FILE_STORAGE_BUCKETS.privateSite, FILE_STORAGE_BUCKETS.temporary, FILE_STORAGE_BUCKETS.siteAssets, FILE_STORAGE_BUCKETS.siteFonts, FILE_STORAGE_BUCKETS.bookingRequirementDocuments;
2829
2894
  PRIVATE_SITE_FILE_BUCKET_MIME_TYPES = [
2830
2895
  "application/pdf",
2831
2896
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
@@ -2900,11 +2965,11 @@ var init_storagePathDomain = __esmMin((() => {}));
2900
2965
  var init_fileAssetLegacyProjection = __esmMin((() => {}));
2901
2966
  //#endregion
2902
2967
  //#region ../media-core/src/typeGuards.ts
2903
- function isRecord$31(value) {
2968
+ function isRecord$33(value) {
2904
2969
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2905
2970
  }
2906
2971
  function asRecord$3(value) {
2907
- return isRecord$31(value) ? value : void 0;
2972
+ return isRecord$33(value) ? value : void 0;
2908
2973
  }
2909
2974
  var init_typeGuards$1 = __esmMin((() => {}));
2910
2975
  function isFileJsonObject(value) {
@@ -2914,7 +2979,7 @@ function isFileJsonValue(value) {
2914
2979
  if (value === null || typeof value === "string" || typeof value === "boolean") return true;
2915
2980
  if (typeof value === "number") return Number.isFinite(value);
2916
2981
  if (Array.isArray(value)) return value.every(isFileJsonValue);
2917
- return isRecord$31(value) && isFileJsonObject(value);
2982
+ return isRecord$33(value) && isFileJsonObject(value);
2918
2983
  }
2919
2984
  var init_filePersistence = __esmMin((() => {
2920
2985
  init_src$2();
@@ -3280,7 +3345,7 @@ function isCmsMediaObjectType(value) {
3280
3345
  return typeof value === "string" && CMS_MEDIA_OBJECT_TYPES.includes(value);
3281
3346
  }
3282
3347
  function isCmsMediaObject(value) {
3283
- if (!isRecord$31(value)) return false;
3348
+ if (!isRecord$33(value)) return false;
3284
3349
  const type = value.type;
3285
3350
  if (!isCmsMediaObjectType(type)) return false;
3286
3351
  if ("attrs" in value) return false;
@@ -3291,7 +3356,7 @@ function collectMediaObjects(value, out, location = "") {
3291
3356
  value.forEach((item, index) => collectMediaObjects(item, out, `${location}[${index}]`));
3292
3357
  return;
3293
3358
  }
3294
- if (!isRecord$31(value)) return;
3359
+ if (!isRecord$33(value)) return;
3295
3360
  if (isCmsMediaObject(value)) out.push({
3296
3361
  obj: value,
3297
3362
  location
@@ -3337,8 +3402,8 @@ function walkAndCollectImageAttrs(value, out, location = "") {
3337
3402
  value.forEach((item, index) => walkAndCollectImageAttrs(item, out, `${location}[${index}]`));
3338
3403
  return;
3339
3404
  }
3340
- if (!isRecord$31(value)) return;
3341
- if (value.type === "image" && isRecord$31(value.attrs)) out.push({
3405
+ if (!isRecord$33(value)) return;
3406
+ if (value.type === "image" && isRecord$33(value.attrs)) out.push({
3342
3407
  attrs: value.attrs,
3343
3408
  location: location ? `${location}.attrs` : "attrs"
3344
3409
  });
@@ -3398,7 +3463,7 @@ function mediaIdentifierOrFallback(current, fallback) {
3398
3463
  var init_renderableMediaAsset = __esmMin((() => {}));
3399
3464
  //#endregion
3400
3465
  //#region ../media-core/src/contentMediaAudit.ts
3401
- function isRecord$30(value) {
3466
+ function isRecord$32(value) {
3402
3467
  return typeof value === "object" && value !== null && !Array.isArray(value);
3403
3468
  }
3404
3469
  function summarizeContentMediaValue(value) {
@@ -3409,7 +3474,7 @@ function summarizeContentMediaValue(value) {
3409
3474
  }
3410
3475
  if (value === null) return "null";
3411
3476
  if (Array.isArray(value)) return `array(${value.length})`;
3412
- if (isRecord$30(value)) return `object(${Object.keys(value).sort().join(",")})`;
3477
+ if (isRecord$32(value)) return `object(${Object.keys(value).sort().join(",")})`;
3413
3478
  return typeof value;
3414
3479
  }
3415
3480
  function auditMediaValue(context, path, allowedMediaTypes, value) {
@@ -3433,9 +3498,9 @@ function auditMediaValue(context, path, allowedMediaTypes, value) {
3433
3498
  allowedMediaTypes
3434
3499
  }];
3435
3500
  }
3436
- const hasValidIdentifier = isRecord$30(value) && typeof value.identifier === "string" && value.identifier.trim().length > 0;
3437
- const hasValidExplicitType = isRecord$30(value) && (!("type" in value) || typeof value.type === "string" && allowedMediaTypes.includes(value.type));
3438
- const hasRetiredEnvironmentField = isRecord$30(value) && ("assetId" in value || "storagePath" in value || "storageBucket" in value || "src" in value || "mimeType" in value || looksLikeUuid(value.id));
3501
+ const hasValidIdentifier = isRecord$32(value) && typeof value.identifier === "string" && value.identifier.trim().length > 0;
3502
+ const hasValidExplicitType = isRecord$32(value) && (!("type" in value) || typeof value.type === "string" && allowedMediaTypes.includes(value.type));
3503
+ const hasRetiredEnvironmentField = isRecord$32(value) && ("assetId" in value || "storagePath" in value || "storageBucket" in value || "src" in value || "mimeType" in value || looksLikeUuid(value.id));
3439
3504
  if (hasValidIdentifier && hasValidExplicitType && !hasRetiredEnvironmentField) return [];
3440
3505
  return [{
3441
3506
  tag: "malformed-object",
@@ -3446,7 +3511,7 @@ function auditMediaValue(context, path, allowedMediaTypes, value) {
3446
3511
  }];
3447
3512
  }
3448
3513
  function auditFields(context, fields, value, parentPath) {
3449
- if (!isRecord$30(value)) return [];
3514
+ if (!isRecord$32(value)) return [];
3450
3515
  const findings = [];
3451
3516
  for (const field of fields) {
3452
3517
  if (!(field.id in value)) continue;
@@ -3463,7 +3528,7 @@ function auditFields(context, fields, value, parentPath) {
3463
3528
  if (!Array.isArray(fieldValue)) break;
3464
3529
  for (const [index, item] of fieldValue.entries()) {
3465
3530
  const itemPath = [...fieldPath, index];
3466
- if (!isRecord$30(item)) {
3531
+ if (!isRecord$32(item)) {
3467
3532
  findings.push({
3468
3533
  tag: "missing-schema",
3469
3534
  context,
@@ -3497,7 +3562,7 @@ var init_contentMediaAudit = __esmMin((() => {
3497
3562
  }));
3498
3563
  //#endregion
3499
3564
  //#region ../media-core/src/contentMediaAuditFieldAdapter.ts
3500
- function isRecord$29(value) {
3565
+ function isRecord$31(value) {
3501
3566
  return typeof value === "object" && value !== null && !Array.isArray(value);
3502
3567
  }
3503
3568
  function unknownArray(value) {
@@ -3506,7 +3571,7 @@ function unknownArray(value) {
3506
3571
  function fieldsArray(value) {
3507
3572
  const directFields = unknownArray(value);
3508
3573
  if (directFields) return directFields;
3509
- if (!isRecord$29(value)) return null;
3574
+ if (!isRecord$31(value)) return null;
3510
3575
  return unknownArray(value.fields);
3511
3576
  }
3512
3577
  function nestedFields(field) {
@@ -3571,7 +3636,7 @@ function mergeFields(fields) {
3571
3636
  }
3572
3637
  function adaptFields(rawFields, flattenRepeaterGroups = false, defaultFileKinds = ["document"]) {
3573
3638
  return mergeFields(rawFields.flatMap((rawField) => {
3574
- if (!isRecord$29(rawField)) return [];
3639
+ if (!isRecord$31(rawField)) return [];
3575
3640
  const { id, type } = rawField;
3576
3641
  if (typeof id !== "string" || !id || typeof type !== "string") return [];
3577
3642
  if (type === "media" || type === "file") return [{
@@ -3579,7 +3644,7 @@ function adaptFields(rawFields, flattenRepeaterGroups = false, defaultFileKinds
3579
3644
  id,
3580
3645
  allowedMediaTypes: allowedMediaTypes(rawField, type, defaultFileKinds)
3581
3646
  }];
3582
- if (flattenRepeaterGroups && type === "group" && isRecord$29(rawField.ui) && rawField.ui.flattenInRepeater === true) return adaptFields(nestedFields(rawField), false, defaultFileKinds);
3647
+ if (flattenRepeaterGroups && type === "group" && isRecord$31(rawField.ui) && rawField.ui.flattenInRepeater === true) return adaptFields(nestedFields(rawField), false, defaultFileKinds);
3583
3648
  if (type === "group" || type === "modal") return [{
3584
3649
  kind: "object",
3585
3650
  id,
@@ -3588,14 +3653,14 @@ function adaptFields(rawFields, flattenRepeaterGroups = false, defaultFileKinds
3588
3653
  if (type === "tabGroup") return [{
3589
3654
  kind: "object",
3590
3655
  id,
3591
- fields: adaptFields((unknownArray(rawField.tabs) ?? []).flatMap((tab) => isRecord$29(tab) ? unknownArray(tab.fields) ?? [] : []), false, defaultFileKinds)
3656
+ fields: adaptFields((unknownArray(rawField.tabs) ?? []).flatMap((tab) => isRecord$31(tab) ? unknownArray(tab.fields) ?? [] : []), false, defaultFileKinds)
3592
3657
  }];
3593
3658
  if (type !== "repeater") return [];
3594
- if (isRecord$29(rawField.itemTypes)) return [{
3659
+ if (isRecord$31(rawField.itemTypes)) return [{
3595
3660
  kind: "repeater",
3596
3661
  id,
3597
3662
  mode: "variants",
3598
- variants: Object.entries(rawField.itemTypes).flatMap(([typeId, itemType]) => isRecord$29(itemType) && Array.isArray(itemType.fields) ? [{
3663
+ variants: Object.entries(rawField.itemTypes).flatMap(([typeId, itemType]) => isRecord$31(itemType) && Array.isArray(itemType.fields) ? [{
3599
3664
  typeId,
3600
3665
  fields: adaptFields(itemType.fields, true, defaultFileKinds)
3601
3666
  }] : []),
@@ -12713,7 +12778,7 @@ var init_interactionPalette = __esmMin((() => {
12713
12778
  //#endregion
12714
12779
  //#region ../theme-core/src/boxBackgroundSchema.ts
12715
12780
  function normalizeAuthoringOpacity(value) {
12716
- if (!isRecord$28(value)) return value;
12781
+ if (!isRecord$30(value)) return value;
12717
12782
  return {
12718
12783
  ...value,
12719
12784
  opacity: normalizeOpacity(value.opacity)
@@ -12722,7 +12787,7 @@ function normalizeAuthoringOpacity(value) {
12722
12787
  function normalizeOpacity(value) {
12723
12788
  return typeof value === "number" && value > 1 && value <= 100 ? value / 100 : value;
12724
12789
  }
12725
- function isRecord$28(value) {
12790
+ function isRecord$30(value) {
12726
12791
  return typeof value === "object" && value !== null && !Array.isArray(value);
12727
12792
  }
12728
12793
  var boxBackgroundOverlaySchema, commonSchema, mediaPresentationSchema, boxBackgroundSchema;
@@ -13541,7 +13606,7 @@ var init_media$1 = __esmMin((() => {
13541
13606
  /**
13542
13607
  * Strict record guard: excludes null, primitives, and arrays.
13543
13608
  */
13544
- function isRecord$27(value) {
13609
+ function isRecord$29(value) {
13545
13610
  return typeof value === "object" && value !== null && !Array.isArray(value);
13546
13611
  }
13547
13612
  /**
@@ -13932,7 +13997,6 @@ var init_schemas = __esmMin((() => {
13932
13997
  description: z$1.string().nullable(),
13933
13998
  content: z$1.object({ body: RichTextDocSchema.nullable().optional() }).optional(),
13934
13999
  presentation: z$1.object({
13935
- cardTitleOverride: z$1.string().nullable().optional(),
13936
14000
  summary: z$1.string().nullable().optional(),
13937
14001
  image: mediaSchema.nullable().optional()
13938
14002
  }).optional(),
@@ -13965,6 +14029,7 @@ var init_schemas = __esmMin((() => {
13965
14029
  "archived"
13966
14030
  ]).optional(),
13967
14031
  timeZone: z$1.string(),
14032
+ siteTimeZone: z$1.string().optional(),
13968
14033
  pricing: publicEventPricingSchema,
13969
14034
  paymentTerms: blockBookingPaymentTermsSchema,
13970
14035
  cancellationPolicy: z$1.object({ refunds: z$1.object({
@@ -30046,7 +30111,7 @@ function successSubmissionFeedback(message) {
30046
30111
  message
30047
30112
  };
30048
30113
  }
30049
- function isRecord$25(value) {
30114
+ function isRecord$27(value) {
30050
30115
  return typeof value === "object" && value !== null && !Array.isArray(value);
30051
30116
  }
30052
30117
  function deepEqualJsonValue(left, right) {
@@ -30056,8 +30121,8 @@ function deepEqualJsonValue(left, right) {
30056
30121
  if (left.length !== right.length) return false;
30057
30122
  return left.every((item, index) => deepEqualJsonValue(item, right[index]));
30058
30123
  }
30059
- if (isRecord$25(left) || isRecord$25(right)) {
30060
- if (!isRecord$25(left) || !isRecord$25(right)) return false;
30124
+ if (isRecord$27(left) || isRecord$27(right)) {
30125
+ if (!isRecord$27(left) || !isRecord$27(right)) return false;
30061
30126
  const leftKeys = Object.keys(left).sort();
30062
30127
  if (!deepEqualJsonValue(leftKeys, Object.keys(right).sort())) return false;
30063
30128
  return leftKeys.every((key) => deepEqualJsonValue(left[key], right[key]));
@@ -30162,7 +30227,7 @@ function resolveAppointmentCheckoutVerificationState(input) {
30162
30227
  tag: "timeout",
30163
30228
  sessionId: input.config.sessionId,
30164
30229
  appointmentId,
30165
- message: "Could not verify your appointment payment. If you were charged, please contact support."
30230
+ message: "We’re still confirming your payment. This can take a minute – you can check again, and you won’t be charged twice."
30166
30231
  };
30167
30232
  if (input.pollingStatus === "failed") {
30168
30233
  if (paymentStatus === "refunded") return {
@@ -30226,7 +30291,7 @@ function deriveBookingFormViewState(input) {
30226
30291
  message: input.verificationState.message
30227
30292
  };
30228
30293
  case "timeout": return {
30229
- kind: "error",
30294
+ kind: "timeout",
30230
30295
  message: input.verificationState.message
30231
30296
  };
30232
30297
  case "confirmed": return {
@@ -30240,12 +30305,12 @@ function resolveBookingSiteId(siteId, form) {
30240
30305
  return siteId || form?.siteId || "";
30241
30306
  }
30242
30307
  function normalizeBookingFormConfig(form) {
30243
- if (!isRecord$24(form)) return null;
30308
+ if (!isRecord$26(form)) return null;
30244
30309
  const id = readNonEmptyString(form.id);
30245
30310
  const name = readNonEmptyString(form.name);
30246
30311
  if (!id || !name) return null;
30247
- const schemaSource = isRecord$24(form.schema) ? form.schema : isRecord$24(form.schemaJson) ? form.schemaJson : null;
30248
- const settingsSource = isRecord$24(form.settings) ? form.settings : isRecord$24(form.settingsJson) ? form.settingsJson : null;
30312
+ const schemaSource = isRecord$26(form.schema) ? form.schema : isRecord$26(form.schemaJson) ? form.schemaJson : null;
30313
+ const settingsSource = isRecord$26(form.settings) ? form.settings : isRecord$26(form.settingsJson) ? form.settingsJson : null;
30249
30314
  return {
30250
30315
  id,
30251
30316
  name,
@@ -30265,8 +30330,8 @@ function normalizeBookingServices(services) {
30265
30330
  };
30266
30331
  if (!services) return [];
30267
30332
  if (Array.isArray(services)) return services.filter(isBookingFormService).map(normalizeService);
30268
- if (isRecord$24(services) && "services" in services) return Array.isArray(services.services) ? services.services.filter(isBookingFormService).map(normalizeService) : [];
30269
- return isRecord$24(services) ? Object.values(services).filter(isBookingFormService).map(normalizeService) : [];
30333
+ if (isRecord$26(services) && "services" in services) return Array.isArray(services.services) ? services.services.filter(isBookingFormService).map(normalizeService) : [];
30334
+ return isRecord$26(services) ? Object.values(services).filter(isBookingFormService).map(normalizeService) : [];
30270
30335
  }
30271
30336
  function normalizeBookingSchema(value) {
30272
30337
  if (!value) return void 0;
@@ -30277,7 +30342,7 @@ function normalizeBookingSchema(value) {
30277
30342
  };
30278
30343
  }
30279
30344
  function readBookingFormField(value) {
30280
- if (!isRecord$24(value)) return null;
30345
+ if (!isRecord$26(value)) return null;
30281
30346
  const id = readNonEmptyString(value.id);
30282
30347
  const label = readNonEmptyString(value.label);
30283
30348
  const type = readBookingFieldType(value.type);
@@ -30320,7 +30385,7 @@ function readBookingFieldOptions(value) {
30320
30385
  return options.length > 0 ? options : void 0;
30321
30386
  }
30322
30387
  function readBookingFieldOption(value) {
30323
- if (!isRecord$24(value)) return null;
30388
+ if (!isRecord$26(value)) return null;
30324
30389
  const optionValue = readNonEmptyString(value.value);
30325
30390
  const label = readNonEmptyString(value.label);
30326
30391
  return optionValue && label ? {
@@ -30340,7 +30405,7 @@ function normalizeBookingSettings(value) {
30340
30405
  };
30341
30406
  }
30342
30407
  function isBookingFormService(value) {
30343
- return isRecord$24(value) && typeof value.id === "string" && typeof value.siteId === "string" && typeof value.title === "string" && (value.consent === void 0 || blockBookingConsentSchema.safeParse(value.consent).success);
30408
+ return isRecord$26(value) && typeof value.id === "string" && typeof value.siteId === "string" && typeof value.title === "string" && (value.consent === void 0 || blockBookingConsentSchema.safeParse(value.consent).success);
30344
30409
  }
30345
30410
  function collectBookingCustomFields(data) {
30346
30411
  const customFields = {};
@@ -30390,7 +30455,7 @@ function readStringArray(value) {
30390
30455
  const strings = value.filter((item) => typeof item === "string");
30391
30456
  return strings.length > 0 ? strings : void 0;
30392
30457
  }
30393
- function isRecord$24(value) {
30458
+ function isRecord$26(value) {
30394
30459
  return typeof value === "object" && value !== null;
30395
30460
  }
30396
30461
  function getBookingServicePaymentSelectionMode(service) {
@@ -30584,23 +30649,70 @@ function formatBookingSubmissionPreparationError(error) {
30584
30649
  default: return assertNever$11(error);
30585
30650
  }
30586
30651
  }
30587
- function getBookingSuccessMessage(successMessage) {
30588
- return successMessage?.trim() || "Your appointment has been booked! Check your email for confirmation.";
30652
+ function getBookingSuccessCopy(successMessage) {
30653
+ const customMessage = successMessage?.trim();
30654
+ return customMessage && customMessage !== DEFAULT_BOOKING_SUCCESS_MESSAGE ? { message: customMessage } : DEFAULT_BOOKING_SUCCESS_COPY;
30655
+ }
30656
+ function getRegistrationSuccessCopy(result, fallback) {
30657
+ const isWaitlist = result?.status === "waitlist";
30658
+ const isInfo = result?.variant === "info";
30659
+ const includesEmailSentence = !isWaitlist && !isInfo;
30660
+ const responseMessage = result?.message;
30661
+ const trimmedResponseMessage = responseMessage?.trim();
30662
+ if ((isWaitlist || isInfo) && trimmedResponseMessage) {
30663
+ const emailFollowupMessage = result?.emailFollowupMessage;
30664
+ return {
30665
+ message: responseMessage ?? "",
30666
+ ...emailFollowupMessage?.trim() ? { defaultEmailSentence: emailFollowupMessage } : {}
30667
+ };
30668
+ }
30669
+ if (trimmedResponseMessage === DEFAULT_REGISTRATION_SUCCESS_MESSAGE) return includesEmailSentence ? DEFAULT_REGISTRATION_SUCCESS_COPY : { message: DEFAULT_REGISTRATION_SUCCESS_COPY.message };
30670
+ if (trimmedResponseMessage) return includesEmailSentence ? registrationCopyWithEmail(trimmedResponseMessage) : { message: trimmedResponseMessage };
30671
+ const fallbackMessage = fallback?.trim();
30672
+ if (fallbackMessage && fallbackMessage !== DEFAULT_REGISTRATION_SUCCESS_MESSAGE) return { message: fallbackMessage };
30673
+ return includesEmailSentence ? DEFAULT_REGISTRATION_SUCCESS_COPY : { message: DEFAULT_REGISTRATION_SUCCESS_COPY.message };
30674
+ }
30675
+ function registrationCopyWithEmail(message) {
30676
+ return {
30677
+ message,
30678
+ defaultEmailSentence: DEFAULT_REGISTRATION_EMAIL_SENTENCE
30679
+ };
30680
+ }
30681
+ function getShopSuccessCopy(outcome) {
30682
+ switch (outcome) {
30683
+ case "success": return {
30684
+ message: "",
30685
+ defaultEmailSentence: "Check your email for confirmation."
30686
+ };
30687
+ case "cancelled": return { message: "You can try again whenever you’re ready." };
30688
+ }
30589
30689
  }
30690
+ var DEFAULT_BOOKING_SUCCESS_COPY, DEFAULT_BOOKING_SUCCESS_MESSAGE, DEFAULT_REGISTRATION_SUCCESS_COPY, DEFAULT_REGISTRATION_SUCCESS_MESSAGE, DEFAULT_REGISTRATION_EMAIL_SENTENCE;
30590
30691
  var init_booking_form_state = __esmMin((() => {
30591
30692
  init_dist$1();
30592
30693
  init_src$2();
30593
30694
  init_bookingConsent();
30594
30695
  init_booking_form_reserved_fields();
30595
30696
  init_booking_form_consent();
30697
+ DEFAULT_BOOKING_SUCCESS_COPY = {
30698
+ message: "Your booking has been confirmed.",
30699
+ defaultEmailSentence: "Check your email for details."
30700
+ };
30701
+ DEFAULT_BOOKING_SUCCESS_MESSAGE = "Your booking has been confirmed. Check your email for details.";
30702
+ DEFAULT_REGISTRATION_SUCCESS_COPY = {
30703
+ message: "Thank you for registering!",
30704
+ defaultEmailSentence: "Check your email for confirmation details."
30705
+ };
30706
+ DEFAULT_REGISTRATION_SUCCESS_MESSAGE = "Thank you for registering! Check your email for confirmation details.";
30707
+ DEFAULT_REGISTRATION_EMAIL_SENTENCE = "Check your email for confirmation details.";
30596
30708
  }));
30597
30709
  //#endregion
30598
30710
  //#region ../blocks/src/system/runtime/nodes/booking-form.service-categories.ts
30599
- function isRecord$23(value) {
30711
+ function isRecord$25(value) {
30600
30712
  return typeof value === "object" && value !== null && !Array.isArray(value);
30601
30713
  }
30602
30714
  function readCategory(value) {
30603
- if (!isRecord$23(value)) return [];
30715
+ if (!isRecord$25(value)) return [];
30604
30716
  const { id, name, description } = value;
30605
30717
  if (typeof id !== "string" || id.trim() === "" || typeof name !== "string") return [];
30606
30718
  return [{
@@ -30616,7 +30728,7 @@ function readCategory(value) {
30616
30728
  * it.
30617
30729
  */
30618
30730
  function normalizeBookingServiceCategories(services) {
30619
- if (!isRecord$23(services) || !Array.isArray(services.categories)) return [];
30731
+ if (!isRecord$25(services) || !Array.isArray(services.categories)) return [];
30620
30732
  return services.categories.flatMap(readCategory);
30621
30733
  }
30622
30734
  var init_booking_form_service_categories = __esmMin((() => {}));
@@ -30778,6 +30890,7 @@ var init_booking_form_interactive = __esmMin((() => {
30778
30890
  return parsed.ok ? parsed.value : void 0;
30779
30891
  });
30780
30892
  bookingSourceSchema = z$1.object({
30893
+ demoEmailSuppressed: z$1.boolean().optional(),
30781
30894
  mailingList: bookingMailingListContextSchema.optional(),
30782
30895
  siteName: z$1.string().optional(),
30783
30896
  siteId: z$1.string().optional(),
@@ -30808,6 +30921,7 @@ var init_booking_form_interactive = __esmMin((() => {
30808
30921
  message: z$1.string().nullable()
30809
30922
  });
30810
30923
  bookingHydrationSchema = z$1.object({
30924
+ demoEmailSuppressed: z$1.boolean().optional(),
30811
30925
  mailingList: bookingMailingListContextSchema.optional(),
30812
30926
  siteName: z$1.string().optional(),
30813
30927
  formId: z$1.string().nullable(),
@@ -30846,6 +30960,7 @@ var init_booking_form_interactive = __esmMin((() => {
30846
30960
  return {
30847
30961
  display: buildBookingFormDisplay(source, form),
30848
30962
  hydration: {
30963
+ demoEmailSuppressed: source.demoEmailSuppressed,
30849
30964
  mailingList: source.mailingList,
30850
30965
  siteName: source.siteName,
30851
30966
  formId: form?.id ?? source.formId ?? null,
@@ -31200,11 +31315,11 @@ var init_bookability = __esmMin((() => {
31200
31315
  }));
31201
31316
  //#endregion
31202
31317
  //#region ../blocks/src/system/runtime/nodes/events/domain/destination.ts
31203
- function isRecord$22(value) {
31318
+ function isRecord$24(value) {
31204
31319
  return typeof value === "object" && value !== null && !Array.isArray(value);
31205
31320
  }
31206
31321
  function isRuntimeEventDestination(value) {
31207
- if (!isRecord$22(value) || typeof value.kind !== "string") return false;
31322
+ if (!isRecord$24(value) || typeof value.kind !== "string") return false;
31208
31323
  if (value.kind === "native") return (value.mode === "cms-managed" || value.mode === "system-managed") && typeof value.path === "string";
31209
31324
  return value.kind === "external" && typeof value.url === "string" && typeof value.label === "string";
31210
31325
  }
@@ -31295,6 +31410,44 @@ var init_cta$1 = __esmMin((() => {
31295
31410
  }));
31296
31411
  //#endregion
31297
31412
  //#region ../blocks/src/system/runtime/nodes/events/domain/dates.ts
31413
+ /**
31414
+ * The English locale a site's public dates are written in, read from the
31415
+ * site's own time zone (Will, 2026-09-26: "date style from site time zone").
31416
+ *
31417
+ * Sites don't store a locale, and every public word around a date is English,
31418
+ * so the only open question is which English conventions to follow: day or
31419
+ * month first, and a 24 or 12-hour clock. The site's time zone is the one
31420
+ * fact every site carries about where it is. It is the site's, never an
31421
+ * event's: a venue left at UTC must not turn a UK site's dates American.
31422
+ * Anywhere this can't place (UTC, the Americas, Asia) keeps US English, which
31423
+ * is what these helpers wrote before sites were placed at all.
31424
+ */
31425
+ function eventDateLocale(siteTimeZone) {
31426
+ if (!siteTimeZone) return "en-US";
31427
+ if (siteTimeZone === "Europe/Dublin") return "en-IE";
31428
+ if (siteTimeZone.startsWith("Europe/")) return "en-GB";
31429
+ if (siteTimeZone.startsWith("Australia/")) return "en-AU";
31430
+ if (siteTimeZone === "Pacific/Auckland" || siteTimeZone === "Pacific/Chatham") return "en-NZ";
31431
+ return "en-US";
31432
+ }
31433
+ /**
31434
+ * Formatting options for an event's dates: the times in the event's own zone,
31435
+ * written in its site's locale. A record from an older server that doesn't
31436
+ * name the site's zone falls back to the event's.
31437
+ */
31438
+ function eventDateOptions(place) {
31439
+ return {
31440
+ timeZone: place.timeZone ?? null,
31441
+ locale: eventDateLocale(place.siteTimeZone ?? place.timeZone)
31442
+ };
31443
+ }
31444
+ /**
31445
+ * Start and end times as cards write them, in the site's locale:
31446
+ * "10:00 to 16:00" in the UK, "10:00 AM to 4:00 PM" in the US.
31447
+ */
31448
+ function formatEventTimeRange$1(times, options) {
31449
+ return `${formatTime$2(times.startsAt, options)} to ${formatTime$2(times.endsAt, options)}`;
31450
+ }
31298
31451
  /** Use the event timezone when present, otherwise the calendar/site timezone. */
31299
31452
  function resolveEventTimeZone(event, calendarTimeZone) {
31300
31453
  return event.timeZone || calendarTimeZone;
@@ -31316,18 +31469,25 @@ function formatDate$2(isoTimestamp, options) {
31316
31469
  });
31317
31470
  }
31318
31471
  /**
31319
- * Format time for display.
31320
- * Returns: "10:00 AM"
31472
+ * Whether the locale reads a 24-hour clock, where hours are written with two
31473
+ * digits ("09:00"), as the dashboard writes them.
31474
+ */
31475
+ function usesTwentyFourHourClock(locale) {
31476
+ return new Intl.DateTimeFormat(locale, { hour: "numeric" }).resolvedOptions().hour12 === false;
31477
+ }
31478
+ /**
31479
+ * Format time for display, on the locale's own clock.
31480
+ * Returns: "9:00 AM" (en-US) or "09:00" (en-GB)
31321
31481
  */
31322
31482
  function formatTime$2(isoTimestamp, options) {
31483
+ const locale = options?.locale ?? "en-US";
31323
31484
  return formatBookingTime(toScheduledBookingDateTime({
31324
31485
  startsAt: isoTimestamp,
31325
31486
  timeZone: toBookingTimeZone(options?.timeZone ?? "UTC"),
31326
- locale: options?.locale ?? "en-US"
31487
+ locale
31327
31488
  }), {
31328
- hour: "numeric",
31329
- minute: "2-digit",
31330
- hour12: true
31489
+ hour: usesTwentyFourHourClock(locale) ? "2-digit" : "numeric",
31490
+ minute: "2-digit"
31331
31491
  });
31332
31492
  }
31333
31493
  function formatEventDateParts(args) {
@@ -31359,7 +31519,7 @@ function formatEventCompactDateRail(isoTimestamp, options) {
31359
31519
  locale: options?.locale ?? "en-US"
31360
31520
  });
31361
31521
  const weekday = formatBookingDate(dateTime, { weekday: "short" }).toLocaleUpperCase(options?.locale ?? "en-US");
31362
- const month = formatBookingDate(dateTime, { month: "short" }).toLocaleUpperCase(options?.locale ?? "en-US");
31522
+ const month = formatBookingDate(dateTime, { month: "short" }).slice(0, 3).toLocaleUpperCase(options?.locale ?? "en-US");
31363
31523
  return {
31364
31524
  weekday,
31365
31525
  day: formatBookingDate(dateTime, { day: "numeric" }),
@@ -31379,7 +31539,7 @@ function formatEventCompactDateRail(isoTimestamp, options) {
31379
31539
  * keep the fact panel on the same date and timezone rules as event rows.
31380
31540
  */
31381
31541
  function formatEventNextDateFact(event) {
31382
- const rail = formatEventCompactDateRail(event.startsAt, { timeZone: event.timeZone });
31542
+ const rail = formatEventCompactDateRail(event.startsAt, eventDateOptions(event));
31383
31543
  return {
31384
31544
  dateTime: event.startsAt,
31385
31545
  value: `${rail.weekday} ${rail.day} ${rail.month}`,
@@ -34225,6 +34385,13 @@ var init_ThemedButton = __esmMin((() => {
34225
34385
  }));
34226
34386
  //#endregion
34227
34387
  //#region ../blocks/src/system/runtime/nodes/events/shared/EventCard.tsx
34388
+ /** The category's badge, when the event has a category. */
34389
+ function eventCardCategoryBadge(category) {
34390
+ return category ? {
34391
+ label: category.name,
34392
+ style: getCategoryBadgeStyle(category.color ?? null)
34393
+ } : null;
34394
+ }
34228
34395
  function EventCardMedia(props) {
34229
34396
  if (props.dateFact) return /* @__PURE__ */ jsxs("div", {
34230
34397
  className: "card-media event-card-media event-card-date-fallback",
@@ -34249,7 +34416,8 @@ function EventCardMedia(props) {
34249
34416
  /* @__PURE__ */ jsx(MediaNodeServer, {
34250
34417
  value: props.image,
34251
34418
  className: "event-card-image",
34252
- size: ImagePresets.card
34419
+ size: ImagePresets.card,
34420
+ imageResolveContext: props.imageResolveContext
34253
34421
  }),
34254
34422
  props.categoryBadge && /* @__PURE__ */ jsx("span", {
34255
34423
  className: "event-category-badge event-category-badge--overlay",
@@ -34364,6 +34532,17 @@ function resolveEventCardOptions(props) {
34364
34532
  headingLevel: props.headingLevel ?? 3
34365
34533
  };
34366
34534
  }
34535
+ /**
34536
+ * The card's date and times, written the way the event's place writes them
34537
+ * ("Friday, 16 October 2026" and "10:00 to 16:00" in the UK).
34538
+ */
34539
+ function formatEventCardWhen(event) {
34540
+ const options = eventDateOptions(event);
34541
+ return {
34542
+ formattedDate: formatDate$2(event.startsAt, options),
34543
+ formattedTime: formatEventTimeRange$1(event, options)
34544
+ };
34545
+ }
34367
34546
  function resolveEventCardDateFact(props) {
34368
34547
  if (!props.showImage || props.image || props.presentation !== "catalogue") return null;
34369
34548
  return formatEventNextDateFact(props.event);
@@ -34409,24 +34588,19 @@ var init_EventCard = __esmMin((() => {
34409
34588
  init_EventCardIcons();
34410
34589
  init_domain();
34411
34590
  init_ThemedButton();
34412
- 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 }) => {
34591
+ 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 }) => {
34413
34592
  const { presentation: cardPresentation, presentationClass, headingLevel: cardHeadingLevel } = resolveEventCardOptions({
34414
34593
  presentation,
34415
34594
  headingLevel
34416
34595
  });
34417
- const timeZone = event.timeZone ?? null;
34418
- const formattedDate = formatDate$2(event.startsAt, { timeZone });
34419
- const formattedTime = `${formatTime$2(event.startsAt, { timeZone })} - ${formatTime$2(event.endsAt, { timeZone })}`;
34596
+ const { formattedDate, formattedTime } = formatEventCardWhen(event);
34420
34597
  const cta = resolveEventCta(event, buttonText);
34421
34598
  const cardClass = boxStyleClassNames({ role: cardRole }, { baseClass: "event-card" });
34422
34599
  const title = event.title;
34423
34600
  const summary = event.presentation?.summary ?? event.description;
34424
34601
  const image = event.presentation?.image ?? null;
34425
34602
  const category = event.eventCategory;
34426
- const categoryBadge = category && showCategory ? {
34427
- label: category.name,
34428
- style: getCategoryBadgeStyle(category.color ?? null)
34429
- } : null;
34603
+ const categoryBadge = showCategory ? eventCardCategoryBadge(category) : null;
34430
34604
  const hasImage = Boolean(showImage && image);
34431
34605
  const dateFact = resolveEventCardDateFact({
34432
34606
  event,
@@ -34445,7 +34619,8 @@ var init_EventCard = __esmMin((() => {
34445
34619
  categoryId: category?.id,
34446
34620
  dateFact,
34447
34621
  hasImage,
34448
- image
34622
+ image,
34623
+ imageResolveContext
34449
34624
  }), /* @__PURE__ */ jsx(EventCardContent, {
34450
34625
  allowMap,
34451
34626
  buttonVariant,
@@ -34787,6 +34962,35 @@ var init_shared$2 = __esmMin((() => {
34787
34962
  init_OfferingTitle();
34788
34963
  }));
34789
34964
  //#endregion
34965
+ //#region ../blocks/src/system/runtime/nodes/events/shared/eventCardPresentations.ts
34966
+ /** A booking page's catalogue card: one per series, "See dates" for dated events. */
34967
+ function catalogueEventCardProps(event, buttonVariant = "primary") {
34968
+ return {
34969
+ presentation: "catalogue",
34970
+ headingLevel: 4,
34971
+ buttonVariant,
34972
+ buttonText: event.bookingScope === "single_occurrence" ? "See dates" : void 0,
34973
+ showMap: false,
34974
+ allowMap: false,
34975
+ showCategory: false,
34976
+ orientation: "vertical"
34977
+ };
34978
+ }
34979
+ /** An events listing's card, from the listing's display settings. */
34980
+ function listingEventCardProps(display) {
34981
+ return {
34982
+ cardRole: display.cardRole,
34983
+ buttonVariant: display.buttonVariant,
34984
+ buttonText: display.buttonText,
34985
+ showVenue: display.showVenue,
34986
+ showMap: display.showMap,
34987
+ allowMap: false,
34988
+ showCapacity: display.showCapacity,
34989
+ orientation: display.orientation
34990
+ };
34991
+ }
34992
+ var init_eventCardPresentations = __esmMin((() => {}));
34993
+ //#endregion
34790
34994
  //#region ../blocks/src/system/runtime/nodes/shared/contract-schemas.ts
34791
34995
  var previewStageSchema, registrationButtonVariantSchema, eventButtonVariantSchema, eventLayoutSchema, eventCalendarDisplayModeSchema, eventCalendarDefaultViewSchema, columnOptionSchema, weekStartSchema, filterAutoShowSchema, calendarTabViewsSchema;
34792
34996
  var init_contract_schemas = __esmMin((() => {
@@ -35161,6 +35365,7 @@ var init_EventListing_interactive = __esmMin((() => {
35161
35365
  init_islands();
35162
35366
  init_runtime();
35163
35367
  init_shared$2();
35368
+ init_eventCardPresentations();
35164
35369
  init_contract_schemas();
35165
35370
  init_listOptions();
35166
35371
  init_eventCollectionContract();
@@ -35816,13 +36021,13 @@ function buildEventRegistrationShellBodyText(stepLabels) {
35816
36021
  return "Preparing dates, tickets, and booking details.";
35817
36022
  }
35818
36023
  function normalizeEventRegistrationEventInput(value) {
35819
- if (!isRecord$21(value)) return value;
36024
+ if (!isRecord$23(value)) return value;
35820
36025
  return {
35821
36026
  ...value,
35822
36027
  destination: resolveRuntimeEventDestination(value)
35823
36028
  };
35824
36029
  }
35825
- function isRecord$21(value) {
36030
+ function isRecord$23(value) {
35826
36031
  return typeof value === "object" && value !== null && !Array.isArray(value);
35827
36032
  }
35828
36033
  function buildEventRegistrationInteractiveIslandProps(props) {
@@ -35871,6 +36076,7 @@ var init_event_registration_interactive = __esmMin((() => {
35871
36076
  ];
35872
36077
  eventRegistrationPublicEventSchema = z$1.preprocess(normalizeEventRegistrationEventInput, publicEventSchema);
35873
36078
  eventRegistrationHydrationSchemaShape = {
36079
+ demoEmailSuppressed: z$1.boolean().optional(),
35874
36080
  occurrenceContext: occurrenceContextSchema.optional(),
35875
36081
  subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
35876
36082
  maxTickets: z$1.string().optional(),
@@ -35966,6 +36172,7 @@ var init_event_registration_interactive = __esmMin((() => {
35966
36172
  ...eventSource,
35967
36173
  events: [...scopedSourceEvents]
35968
36174
  } : eventSource,
36175
+ demoEmailSuppressed: source.demoEmailSuppressed,
35969
36176
  maxTickets: source.maxTickets ?? void 0,
35970
36177
  showVenue: source.showVenue,
35971
36178
  showCapacity: source.showCapacity,
@@ -37312,6 +37519,7 @@ var init_shop_interactive = __esmMin((() => {
37312
37519
  memberships: z$1.array(publicMembershipProductSchema).nullable().optional(),
37313
37520
  products: z$1.array(publicProductSchema).nullable().optional(),
37314
37521
  siteId: z$1.string().optional(),
37522
+ demoEmailSuppressed: z$1.boolean().optional(),
37315
37523
  apiBaseUrl: z$1.string().optional(),
37316
37524
  readAuthority: browserReadAuthoritySchema.optional(),
37317
37525
  stage: previewStageSchema.optional()
@@ -37431,7 +37639,8 @@ var init_shop_interactive = __esmMin((() => {
37431
37639
  passesMembershipsHydrationSchema = z$1.object({
37432
37640
  memberships: z$1.array(publicMembershipProductSchema),
37433
37641
  passPurchaseMode: z$1.enum(["add_to_cart", "buy_now"]),
37434
- buttonVariant: blockButtonRoleSchema
37642
+ buttonVariant: blockButtonRoleSchema,
37643
+ demoEmailSuppressed: z$1.boolean().optional()
37435
37644
  });
37436
37645
  productListHydrationSchema = z$1.object({
37437
37646
  products: z$1.array(publicProductSchema),
@@ -37453,7 +37662,8 @@ var init_shop_interactive = __esmMin((() => {
37453
37662
  });
37454
37663
  checkoutHydrationSchema = z$1.object({
37455
37664
  emptyStateText: z$1.string(),
37456
- submitButtonText: z$1.string()
37665
+ submitButtonText: z$1.string(),
37666
+ demoEmailSuppressed: z$1.boolean().optional()
37457
37667
  });
37458
37668
  passesMembershipsRenderSchema = z$1.object({
37459
37669
  display: passesMembershipsDisplaySchema,
@@ -37510,7 +37720,8 @@ var init_shop_interactive = __esmMin((() => {
37510
37720
  hydration: {
37511
37721
  memberships: source.showMemberships === false ? [] : source.memberships ?? [],
37512
37722
  passPurchaseMode,
37513
- buttonVariant: source.buttonVariant ?? "primary"
37723
+ buttonVariant: source.buttonVariant ?? "primary",
37724
+ demoEmailSuppressed: source.demoEmailSuppressed
37514
37725
  }
37515
37726
  };
37516
37727
  }
@@ -37603,7 +37814,8 @@ var init_shop_interactive = __esmMin((() => {
37603
37814
  }),
37604
37815
  hydration: {
37605
37816
  emptyStateText: source.emptyStateText ?? "Add something to your cart to continue.",
37606
- submitButtonText: source.submitButtonText ?? "Checkout"
37817
+ submitButtonText: source.submitButtonText ?? "Checkout",
37818
+ demoEmailSuppressed: source.demoEmailSuppressed
37607
37819
  }
37608
37820
  })
37609
37821
  });
@@ -39272,6 +39484,7 @@ const SDK_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
39272
39484
  responseKind: "json",
39273
39485
  errors: [
39274
39486
  "resource:not_found",
39487
+ "validation:invalid_input",
39275
39488
  "resource:conflict",
39276
39489
  "server:internal_error"
39277
39490
  ]
@@ -39728,28 +39941,6 @@ const EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
39728
39941
  "resource:conflict",
39729
39942
  "server:internal_error"
39730
39943
  ]
39731
- },
39732
- /**
39733
- * The Content tab's one write: the short introduction, image and
39734
- * description of an event's page, published without its layout.
39735
- */
39736
- saveEventPageWords: {
39737
- path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/words",
39738
- method: "PUT",
39739
- tags: [
39740
- TAG_TEMPLATES.siteCollection,
39741
- TAG_TEMPLATES.siteRoutableContent,
39742
- TAG_TEMPLATES.pageSurfaceById
39743
- ],
39744
- auth: "user",
39745
- responseKind: "json",
39746
- errors: [
39747
- "auth:forbidden",
39748
- "validation:invalid_input",
39749
- "resource:not_found",
39750
- "resource:conflict",
39751
- "server:internal_error"
39752
- ]
39753
39944
  }
39754
39945
  });
39755
39946
  //#endregion
@@ -40175,6 +40366,15 @@ const BILLING_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
40175
40366
  auth: "user",
40176
40367
  responseKind: "json"
40177
40368
  },
40369
+ /** Continue on Free from the onboarding card page; only the attempt's owner. */
40370
+ continueOnboardingOnFree: {
40371
+ path: "/onboarding/attempts/{attemptToken}/plan/free",
40372
+ method: "POST",
40373
+ tags: ["billing"],
40374
+ auth: "user",
40375
+ errors: [],
40376
+ responseKind: "json"
40377
+ },
40178
40378
  createBillingPortalSession: {
40179
40379
  path: "/billing/portal/session",
40180
40380
  method: "POST",
@@ -40184,6 +40384,161 @@ const BILLING_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
40184
40384
  }
40185
40385
  });
40186
40386
  //#endregion
40387
+ //#region ../api/src/editLeaseEndpoints.ts
40388
+ const path = "/sites/{siteId}/edit-leases/{nodeType}/{nodeId}";
40389
+ const lifecycleErrors = [
40390
+ "auth:lease_required",
40391
+ "auth:forbidden",
40392
+ "resource:not_found",
40393
+ "validation:invalid_input",
40394
+ "server:internal_error"
40395
+ ];
40396
+ const EDIT_LEASE_ENDPOINT_DEFINITIONS = {
40397
+ readEditLease: {
40398
+ path,
40399
+ method: "GET",
40400
+ editLease: "lifecycle",
40401
+ errors: lifecycleErrors,
40402
+ auth: "user",
40403
+ responseKind: "json"
40404
+ },
40405
+ acquireEditLease: {
40406
+ path,
40407
+ method: "POST",
40408
+ editLease: "lifecycle",
40409
+ errors: lifecycleErrors,
40410
+ auth: "user",
40411
+ responseKind: "json"
40412
+ },
40413
+ takeOverEditLease: {
40414
+ path,
40415
+ method: "PUT",
40416
+ editLease: "lifecycle",
40417
+ errors: lifecycleErrors,
40418
+ auth: "user",
40419
+ responseKind: "json"
40420
+ },
40421
+ heartbeatEditLease: {
40422
+ path,
40423
+ method: "PATCH",
40424
+ editLease: "lifecycle",
40425
+ errors: [...lifecycleErrors, "auth:lease_lost"],
40426
+ auth: "user",
40427
+ responseKind: "json"
40428
+ },
40429
+ releaseEditLease: {
40430
+ path,
40431
+ method: "DELETE",
40432
+ editLease: "lifecycle",
40433
+ errors: lifecycleErrors,
40434
+ auth: "user",
40435
+ responseKind: "json"
40436
+ }
40437
+ };
40438
+ //#endregion
40439
+ //#region ../api/src/pageSurfaceEditorEndpoints.ts
40440
+ const surfaceTags = [TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById];
40441
+ const PAGE_SURFACE_EDITOR_ENDPOINT_DEFINITIONS = {
40442
+ getPageSurfaceEditorDocument: {
40443
+ path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/content",
40444
+ method: "GET",
40445
+ errors: [
40446
+ "auth:forbidden",
40447
+ "validation:invalid_input",
40448
+ "resource:not_found",
40449
+ "resource:conflict",
40450
+ "server:internal_error"
40451
+ ],
40452
+ tags: surfaceTags,
40453
+ auth: "user",
40454
+ responseKind: "json"
40455
+ },
40456
+ updatePageSurfaceDraftContent: {
40457
+ editLease: "managed",
40458
+ path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/content",
40459
+ method: "PUT",
40460
+ errors: [
40461
+ "validation:invalid_input",
40462
+ "resource:not_found",
40463
+ "resource:conflict",
40464
+ "server:internal_error"
40465
+ ],
40466
+ tags: surfaceTags,
40467
+ auth: "user",
40468
+ responseKind: "json"
40469
+ },
40470
+ discardPageSurfaceDraftContent: {
40471
+ editLease: "managed",
40472
+ path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/content/draft",
40473
+ method: "DELETE",
40474
+ errors: [
40475
+ "validation:invalid_input",
40476
+ "resource:not_found",
40477
+ "resource:conflict",
40478
+ "server:internal_error"
40479
+ ],
40480
+ tags: surfaceTags,
40481
+ auth: "user",
40482
+ responseKind: "json"
40483
+ },
40484
+ updatePageSurfaceRouteMetadata: {
40485
+ editLease: "managed",
40486
+ path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/metadata",
40487
+ method: "PATCH",
40488
+ errors: [
40489
+ "validation:invalid_input",
40490
+ "resource:not_found",
40491
+ "resource:conflict",
40492
+ "server:internal_error"
40493
+ ],
40494
+ tags: [
40495
+ TAG_TEMPLATES.siteCollection,
40496
+ TAG_TEMPLATES.siteRoutableContent,
40497
+ TAG_TEMPLATES.pageSurfaceById
40498
+ ],
40499
+ auth: "user",
40500
+ responseKind: "json"
40501
+ },
40502
+ publishPageSurface: {
40503
+ editLease: "managed",
40504
+ path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/publication",
40505
+ method: "POST",
40506
+ errors: [
40507
+ "auth:forbidden",
40508
+ "validation:invalid_input",
40509
+ "resource:not_found",
40510
+ "resource:conflict",
40511
+ "server:internal_error"
40512
+ ],
40513
+ tags: [
40514
+ TAG_TEMPLATES.siteCollection,
40515
+ TAG_TEMPLATES.siteRoutableContent,
40516
+ TAG_TEMPLATES.pageSurfaceById
40517
+ ],
40518
+ auth: "user",
40519
+ responseKind: "json"
40520
+ },
40521
+ saveEventContentTab: {
40522
+ editLease: "managed",
40523
+ path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/event-content",
40524
+ method: "PUT",
40525
+ errors: [
40526
+ "auth:forbidden",
40527
+ "validation:invalid_input",
40528
+ "resource:not_found",
40529
+ "resource:conflict",
40530
+ "server:internal_error"
40531
+ ],
40532
+ tags: [
40533
+ TAG_TEMPLATES.siteCollection,
40534
+ TAG_TEMPLATES.siteRoutableContent,
40535
+ TAG_TEMPLATES.pageSurfaceById
40536
+ ],
40537
+ auth: "user",
40538
+ responseKind: "json"
40539
+ }
40540
+ };
40541
+ //#endregion
40187
40542
  //#region ../api/src/bookingPeopleEndpointDefinitions.ts
40188
40543
  /**
40189
40544
  * People endpoints (#1356): the People list, its CSV export, and deleting a
@@ -40276,6 +40631,8 @@ const API_ENDPOINTS$1 = {
40276
40631
  ...GIFTING_ENDPOINT_DEFINITIONS,
40277
40632
  ...PUBLIC_READ_ENDPOINT_DEFINITIONS,
40278
40633
  ...BILLING_ENDPOINT_DEFINITIONS,
40634
+ ...EDIT_LEASE_ENDPOINT_DEFINITIONS,
40635
+ ...PAGE_SURFACE_EDITOR_ENDPOINT_DEFINITIONS,
40279
40636
  ...SITE_MANAGEMENT_ENDPOINT_DEFINITIONS,
40280
40637
  aiContentUpdateChat: {
40281
40638
  path: "/ai/content-update-chat",
@@ -40297,6 +40654,7 @@ const API_ENDPOINTS$1 = {
40297
40654
  responseKind: "json"
40298
40655
  },
40299
40656
  aiDesignerPageOpsApply: {
40657
+ editLease: "managed",
40300
40658
  path: "/sites/{siteId}/ai/designer/page/apply",
40301
40659
  method: "POST",
40302
40660
  tags: [TAG_TEMPLATES.siteCollection],
@@ -41131,6 +41489,7 @@ const API_ENDPOINTS$1 = {
41131
41489
  responseKind: "json"
41132
41490
  },
41133
41491
  restoreContentEntryVersion: {
41492
+ editLease: "managed",
41134
41493
  path: "/sites/{siteId}/content/{type}/{entryId}/versions/{versionId}/restore",
41135
41494
  method: "POST",
41136
41495
  errors: [
@@ -41148,6 +41507,7 @@ const API_ENDPOINTS$1 = {
41148
41507
  responseKind: "json"
41149
41508
  },
41150
41509
  updateContentEntryContent: {
41510
+ editLease: "managed",
41151
41511
  path: "/sites/{siteId}/content/{type}/{entryId}/content",
41152
41512
  method: "PUT",
41153
41513
  tags: [
@@ -41164,67 +41524,6 @@ const API_ENDPOINTS$1 = {
41164
41524
  ],
41165
41525
  responseKind: "json"
41166
41526
  },
41167
- updatePageSurfaceDraftContent: {
41168
- path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/content",
41169
- method: "PUT",
41170
- errors: [
41171
- "validation:invalid_input",
41172
- "resource:not_found",
41173
- "resource:conflict",
41174
- "server:internal_error"
41175
- ],
41176
- tags: [TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById],
41177
- auth: "user",
41178
- responseKind: "json"
41179
- },
41180
- discardPageSurfaceDraftContent: {
41181
- path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/content/draft",
41182
- method: "DELETE",
41183
- errors: [
41184
- "validation:invalid_input",
41185
- "resource:not_found",
41186
- "resource:conflict",
41187
- "server:internal_error"
41188
- ],
41189
- tags: [TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById],
41190
- auth: "user",
41191
- responseKind: "json"
41192
- },
41193
- updatePageSurfaceRouteMetadata: {
41194
- path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/metadata",
41195
- method: "PATCH",
41196
- errors: [
41197
- "validation:invalid_input",
41198
- "resource:not_found",
41199
- "resource:conflict",
41200
- "server:internal_error"
41201
- ],
41202
- tags: [
41203
- TAG_TEMPLATES.siteCollection,
41204
- TAG_TEMPLATES.siteRoutableContent,
41205
- TAG_TEMPLATES.pageSurfaceById
41206
- ],
41207
- auth: "user",
41208
- responseKind: "json"
41209
- },
41210
- publishPageSurface: {
41211
- path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/publication",
41212
- method: "POST",
41213
- errors: [
41214
- "auth:forbidden",
41215
- "validation:invalid_input",
41216
- "resource:not_found",
41217
- "resource:conflict",
41218
- "server:internal_error"
41219
- ],
41220
- tags: [
41221
- TAG_TEMPLATES.siteCollection,
41222
- TAG_TEMPLATES.siteRoutableContent,
41223
- TAG_TEMPLATES.pageSurfaceById
41224
- ],
41225
- auth: "user",
41226
- responseKind: "json"
41227
- },
41228
41527
  runSdkWorkflow: {
41229
41528
  path: "/sites/{siteId}/content/{type}/{entryId}/workflows/{workflowId}/run",
41230
41529
  method: "POST",
@@ -41261,6 +41560,7 @@ const API_ENDPOINTS$1 = {
41261
41560
  responseKind: "json"
41262
41561
  },
41263
41562
  updateRouteMetadata: {
41563
+ editLease: "managed",
41264
41564
  path: "/sites/{siteId}/routes/{routeId}/metadata",
41265
41565
  method: "PATCH",
41266
41566
  tags: [
@@ -41278,6 +41578,7 @@ const API_ENDPOINTS$1 = {
41278
41578
  responseKind: "json"
41279
41579
  },
41280
41580
  publishContentEntry: {
41581
+ editLease: "managed",
41281
41582
  path: "/sites/{siteId}/content/{type}/{entryId}/publish",
41282
41583
  method: "POST",
41283
41584
  tags: [
@@ -41289,6 +41590,7 @@ const API_ENDPOINTS$1 = {
41289
41590
  responseKind: "json"
41290
41591
  },
41291
41592
  scheduleContentEntry: {
41593
+ editLease: "managed",
41292
41594
  path: "/sites/{siteId}/content/{type}/{entryId}/schedule",
41293
41595
  method: "POST",
41294
41596
  tags: [
@@ -41306,6 +41608,7 @@ const API_ENDPOINTS$1 = {
41306
41608
  responseKind: "json"
41307
41609
  },
41308
41610
  cancelScheduledContentEntry: {
41611
+ editLease: "managed",
41309
41612
  path: "/sites/{siteId}/content/{type}/{entryId}/schedule",
41310
41613
  method: "DELETE",
41311
41614
  tags: [
@@ -41323,6 +41626,7 @@ const API_ENDPOINTS$1 = {
41323
41626
  responseKind: "json"
41324
41627
  },
41325
41628
  discardContentEntry: {
41629
+ editLease: "managed",
41326
41630
  path: "/sites/{siteId}/content/{type}/{entryId}/discard",
41327
41631
  method: "POST",
41328
41632
  tags: [
@@ -41341,6 +41645,7 @@ const API_ENDPOINTS$1 = {
41341
41645
  responseKind: "json"
41342
41646
  },
41343
41647
  unpublishContentEntry: {
41648
+ editLease: "managed",
41344
41649
  path: "/sites/{siteId}/content/{type}/{entryId}/unpublish",
41345
41650
  method: "POST",
41346
41651
  tags: [
@@ -41382,6 +41687,7 @@ const API_ENDPOINTS$1 = {
41382
41687
  responseKind: "json"
41383
41688
  },
41384
41689
  deleteContentEntry: {
41690
+ editLease: "managed",
41385
41691
  path: "/sites/{siteId}/content/{type}/{entryId}",
41386
41692
  method: "DELETE",
41387
41693
  tags: [
@@ -42591,6 +42897,7 @@ const API_ENDPOINTS$1 = {
42591
42897
  responseKind: "json"
42592
42898
  },
42593
42899
  saveBlockContent: {
42900
+ editLease: "owner-derived",
42594
42901
  path: "/blocks/{blockId}/content",
42595
42902
  method: "POST",
42596
42903
  tags: [
@@ -42628,6 +42935,7 @@ const API_ENDPOINTS$1 = {
42628
42935
  errors: ["resource:not_found", "resource:conflict"]
42629
42936
  },
42630
42937
  createEntrySlotBlock: {
42938
+ editLease: "managed",
42631
42939
  path: "/sites/{siteId}/content/{type}/{entryId}/slots/{slotKey}/blocks",
42632
42940
  method: "POST",
42633
42941
  tags: [
@@ -42645,6 +42953,7 @@ const API_ENDPOINTS$1 = {
42645
42953
  ]
42646
42954
  },
42647
42955
  reorderEntrySlotBlocks: {
42956
+ editLease: "managed",
42648
42957
  path: "/sites/{siteId}/content/{type}/{entryId}/slots/{slotKey}/blocks/reorder",
42649
42958
  method: "POST",
42650
42959
  tags: [
@@ -42662,6 +42971,7 @@ const API_ENDPOINTS$1 = {
42662
42971
  ]
42663
42972
  },
42664
42973
  deleteEntrySlotBlock: {
42974
+ editLease: "managed",
42665
42975
  path: "/sites/{siteId}/content/{type}/{entryId}/slots/{slotKey}/blocks/{blockId}",
42666
42976
  method: "DELETE",
42667
42977
  tags: [
@@ -42692,6 +43002,7 @@ const API_ENDPOINTS$1 = {
42692
43002
  ]
42693
43003
  },
42694
43004
  createPageSurfaceSlotBlock: {
43005
+ editLease: "managed",
42695
43006
  path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/slots/{slotKey}/blocks",
42696
43007
  method: "POST",
42697
43008
  tags: [
@@ -42710,6 +43021,7 @@ const API_ENDPOINTS$1 = {
42710
43021
  ]
42711
43022
  },
42712
43023
  reorderPageSurfaceSlotBlocks: {
43024
+ editLease: "managed",
42713
43025
  path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/slots/{slotKey}/blocks/reorder",
42714
43026
  method: "POST",
42715
43027
  tags: [
@@ -42728,6 +43040,7 @@ const API_ENDPOINTS$1 = {
42728
43040
  ]
42729
43041
  },
42730
43042
  deletePageSurfaceSlotBlock: {
43043
+ editLease: "managed",
42731
43044
  path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/slots/{slotKey}/blocks/{blockId}",
42732
43045
  method: "DELETE",
42733
43046
  tags: [
@@ -42745,6 +43058,7 @@ const API_ENDPOINTS$1 = {
42745
43058
  ]
42746
43059
  },
42747
43060
  createBlock: {
43061
+ editLease: "managed",
42748
43062
  path: "/sites/{siteId}/pages/{pageId}/blocks",
42749
43063
  method: "POST",
42750
43064
  tags: [
@@ -42756,6 +43070,7 @@ const API_ENDPOINTS$1 = {
42756
43070
  responseKind: "json"
42757
43071
  },
42758
43072
  reorderBlocks: {
43073
+ editLease: "managed",
42759
43074
  path: "/sites/{siteId}/pages/{pageId}/blocks/reorder",
42760
43075
  method: "POST",
42761
43076
  tags: [
@@ -42767,6 +43082,7 @@ const API_ENDPOINTS$1 = {
42767
43082
  responseKind: "json"
42768
43083
  },
42769
43084
  deleteBlock: {
43085
+ editLease: "managed",
42770
43086
  path: "/sites/{siteId}/pages/{pageId}/blocks/{blockId}",
42771
43087
  method: "DELETE",
42772
43088
  tags: [
@@ -42812,6 +43128,7 @@ const API_ENDPOINTS$1 = {
42812
43128
  responseKind: "json"
42813
43129
  },
42814
43130
  publishPageDraft: {
43131
+ editLease: "managed",
42815
43132
  path: "/sites/{siteId}/pages/{pageId}/publish",
42816
43133
  method: "POST",
42817
43134
  tags: [TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById],
@@ -42819,6 +43136,7 @@ const API_ENDPOINTS$1 = {
42819
43136
  responseKind: "json"
42820
43137
  },
42821
43138
  discardPageDraft: {
43139
+ editLease: "managed",
42822
43140
  path: "/sites/{siteId}/pages/{pageId}/discard",
42823
43141
  method: "POST",
42824
43142
  tags: [TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById],
@@ -42834,6 +43152,7 @@ const API_ENDPOINTS$1 = {
42834
43152
  errors: ["resource:not_found", "server:internal_error"]
42835
43153
  },
42836
43154
  savePageDesignState: {
43155
+ editLease: "managed",
42837
43156
  path: "/sites/{siteId}/pages/{pageId}/design-state",
42838
43157
  method: "POST",
42839
43158
  tags: [TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById],
@@ -42863,6 +43182,7 @@ const API_ENDPOINTS$1 = {
42863
43182
  responseKind: "json"
42864
43183
  },
42865
43184
  restorePageVersion: {
43185
+ editLease: "managed",
42866
43186
  path: "/sites/{siteId}/pages/{pageId}/versions/{versionId}/restore",
42867
43187
  method: "POST",
42868
43188
  errors: [
@@ -42876,6 +43196,7 @@ const API_ENDPOINTS$1 = {
42876
43196
  responseKind: "json"
42877
43197
  },
42878
43198
  applyPageDesignEditorAction: {
43199
+ editLease: "managed",
42879
43200
  path: "/sites/{siteId}/pages/{pageId}/design/actions",
42880
43201
  method: "POST",
42881
43202
  tags: [TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById],
@@ -45641,6 +45962,8 @@ const API_ERROR_CODE_SET = /* @__PURE__ */ new Set([
45641
45962
  "auth:sudo_required",
45642
45963
  "auth:insufficient_permissions",
45643
45964
  "auth:impersonation_restricted",
45965
+ "auth:lease_required",
45966
+ "auth:lease_lost",
45644
45967
  "validation:invalid_input",
45645
45968
  "validation:missing_field",
45646
45969
  "validation:invalid_format",
@@ -45670,20 +45993,20 @@ function isApiError(result) {
45670
45993
  function isApiSuccess(result) {
45671
45994
  return result.success === true;
45672
45995
  }
45673
- function isRecord$20(value) {
45996
+ function isRecord$22(value) {
45674
45997
  return typeof value === "object" && value !== null && !Array.isArray(value);
45675
45998
  }
45676
45999
  function isFieldError$1(value) {
45677
- return isRecord$20(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
46000
+ return isRecord$22(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
45678
46001
  }
45679
46002
  function fieldErrorsFromUnknown$1(value) {
45680
46003
  if (!Array.isArray(value)) return null;
45681
46004
  return value.every(isFieldError$1) ? value : null;
45682
46005
  }
45683
46006
  function extractEnvelopeErrorObject(body) {
45684
- if (!isRecord$20(body)) return null;
46007
+ if (!isRecord$22(body)) return null;
45685
46008
  const error = body.error;
45686
- if (!isRecord$20(error)) return null;
46009
+ if (!isRecord$22(error)) return null;
45687
46010
  if ("success" in body && body.success !== false) return null;
45688
46011
  return error;
45689
46012
  }
@@ -46095,7 +46418,7 @@ function internalNavigationLinkToLocalLink(item) {
46095
46418
  init_src$2();
46096
46419
  const LINKED_CONTENT_ENTRY_META_KEY = "__rbLinkedContentEntry";
46097
46420
  function coerceLinkedContentEntriesPayload(payload) {
46098
- if (!isRecord$19(payload)) return payload;
46421
+ if (!isRecord$21(payload)) return payload;
46099
46422
  const response = payload;
46100
46423
  if (!Array.isArray(response.entries)) return payload;
46101
46424
  const contentType = parsePublicContentTypeMeta(response.contentType);
@@ -46103,16 +46426,16 @@ function coerceLinkedContentEntriesPayload(payload) {
46103
46426
  return response.entries.map((entry) => enrichLinkedContentEntry(entry, contentType));
46104
46427
  }
46105
46428
  function getLinkedContentEntryMeta(value) {
46106
- if (!isRecord$19(value)) return null;
46429
+ if (!isRecord$21(value)) return null;
46107
46430
  const candidate = value[LINKED_CONTENT_ENTRY_META_KEY];
46108
46431
  return isLinkedContentEntryMeta(candidate) ? candidate : null;
46109
46432
  }
46110
46433
  function buildLinkedContentEditTarget(input) {
46111
46434
  const { entry, sourceBlockId, sourceBlockKind, itemIndex } = input;
46112
- if (!isRecord$19(entry)) return null;
46435
+ if (!isRecord$21(entry)) return null;
46113
46436
  const meta = getLinkedContentEntryMeta(entry);
46114
46437
  if (!meta || meta.support.kind !== "supported") return null;
46115
- const content = isRecord$19(entry.content) ? entry.content : {};
46438
+ const content = isRecord$21(entry.content) ? entry.content : {};
46116
46439
  return {
46117
46440
  kind: "linked-content-entry",
46118
46441
  entryId: meta.entryId,
@@ -46176,12 +46499,12 @@ function resolveLinkedEntryInlineFieldEligibility(input) {
46176
46499
  };
46177
46500
  }
46178
46501
  function enrichLinkedContentEntry(entry, contentType) {
46179
- if (!isRecord$19(entry)) return entry;
46502
+ if (!isRecord$21(entry)) return entry;
46180
46503
  const entryId = typeof entry.id === "string" ? entry.id : null;
46181
46504
  if (!entryId) return entry;
46182
46505
  const title = typeof entry.title === "string" && entry.title.trim().length > 0 ? entry.title : entryId;
46183
46506
  const optimisticHash = typeof entry.optimisticHash === "string" && entry.optimisticHash.length > 0 ? entry.optimisticHash : null;
46184
- const content = isRecord$19(entry.content) ? entry.content : {};
46507
+ const content = isRecord$21(entry.content) ? entry.content : {};
46185
46508
  const meta = {
46186
46509
  kind: "linked-content-entry",
46187
46510
  entryId,
@@ -46277,7 +46600,7 @@ function capitalize(value) {
46277
46600
  return value.charAt(0).toUpperCase() + value.slice(1).toLowerCase();
46278
46601
  }
46279
46602
  function parsePublicContentTypeMeta(value) {
46280
- if (!isRecord$19(value)) return null;
46603
+ if (!isRecord$21(value)) return null;
46281
46604
  if (typeof value.key !== "string" || value.key.trim().length === 0) return null;
46282
46605
  return {
46283
46606
  key: value.key,
@@ -46287,7 +46610,7 @@ function parsePublicContentTypeMeta(value) {
46287
46610
  };
46288
46611
  }
46289
46612
  function parsePublicContentTypeLinkedEntryEditing(value) {
46290
- if (!isRecord$19(value) || typeof value.kind !== "string") return null;
46613
+ if (!isRecord$21(value) || typeof value.kind !== "string") return null;
46291
46614
  switch (value.kind) {
46292
46615
  case "generic": return { kind: "generic" };
46293
46616
  case "unsupported-domain-backed": return {
@@ -46298,7 +46621,7 @@ function parsePublicContentTypeLinkedEntryEditing(value) {
46298
46621
  }
46299
46622
  }
46300
46623
  function parsePublicContentTypeFieldMeta(value) {
46301
- if (!isRecord$19(value)) return [];
46624
+ if (!isRecord$21(value)) return [];
46302
46625
  if (typeof value.id !== "string" || typeof value.type !== "string") return [];
46303
46626
  return [{
46304
46627
  id: value.id,
@@ -46313,14 +46636,14 @@ function parseStringArray(value) {
46313
46636
  return value.filter((item) => typeof item === "string");
46314
46637
  }
46315
46638
  function isLinkedContentEntryMeta(value) {
46316
- if (!isRecord$19(value)) return false;
46639
+ if (!isRecord$21(value)) return false;
46317
46640
  if (value.kind !== "linked-content-entry") return false;
46318
46641
  if (typeof value.entryId !== "string") return false;
46319
46642
  if (typeof value.contentTypeKey !== "string") return false;
46320
46643
  if (typeof value.contentTypeLabel !== "string") return false;
46321
46644
  if (typeof value.title !== "string") return false;
46322
46645
  if (!(value.optimisticHash === null || typeof value.optimisticHash === "string")) return false;
46323
- if (!isRecord$19(value.contentType)) return false;
46646
+ if (!isRecord$21(value.contentType)) return false;
46324
46647
  if (!isLinkedEntryFieldSourceArray(value.fieldSources)) return false;
46325
46648
  return isLinkedContentEditSupport(value.support);
46326
46649
  }
@@ -46328,7 +46651,7 @@ function isLinkedEntryFieldSourceArray(value) {
46328
46651
  return Array.isArray(value) && value.every(isLinkedEntryFieldSource);
46329
46652
  }
46330
46653
  function isLinkedEntryFieldSource(value) {
46331
- if (!isRecord$19(value)) return false;
46654
+ if (!isRecord$21(value)) return false;
46332
46655
  if (typeof value.displayPath !== "string") return false;
46333
46656
  switch (value.kind) {
46334
46657
  case "content-field": return typeof value.fieldPath === "string" && (value.fieldType === "text" || value.fieldType === "richText");
@@ -46349,7 +46672,7 @@ function isLinkedEntryInlineFieldReadOnlyReason(value) {
46349
46672
  }
46350
46673
  }
46351
46674
  function isLinkedContentEditSupport(value) {
46352
- if (!isRecord$19(value) || typeof value.kind !== "string") return false;
46675
+ if (!isRecord$21(value) || typeof value.kind !== "string") return false;
46353
46676
  switch (value.kind) {
46354
46677
  case "supported": return true;
46355
46678
  case "unsupported-domain-backed":
@@ -46358,7 +46681,7 @@ function isLinkedContentEditSupport(value) {
46358
46681
  default: return false;
46359
46682
  }
46360
46683
  }
46361
- function isRecord$19(value) {
46684
+ function isRecord$21(value) {
46362
46685
  return typeof value === "object" && value !== null && !Array.isArray(value);
46363
46686
  }
46364
46687
  const inlineTextMarkSchema = z$1.discriminatedUnion("kind", [
@@ -48011,16 +48334,16 @@ const interpolateRichTextTokensOptionsSchema = z$1.object({ tokens: z$1.array(su
48011
48334
  const richTextTokenPattern = /\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/g;
48012
48335
  function getSiteName(context) {
48013
48336
  const viewModel = context.viewModel;
48014
- if (!isRecord$27(viewModel)) return null;
48337
+ if (!isRecord$29(viewModel)) return null;
48015
48338
  const site = viewModel.site;
48016
- if (isRecord$27(site) && typeof site.title === "string") {
48339
+ if (isRecord$29(site) && typeof site.title === "string") {
48017
48340
  const title = site.title.trim();
48018
48341
  return title.length > 0 ? title : null;
48019
48342
  }
48020
48343
  const root = viewModel.$root;
48021
- if (isRecord$27(root)) {
48344
+ if (isRecord$29(root)) {
48022
48345
  const rootSite = root.site;
48023
- if (isRecord$27(rootSite) && typeof rootSite.title === "string") {
48346
+ if (isRecord$29(rootSite) && typeof rootSite.title === "string") {
48024
48347
  const title = rootSite.title.trim();
48025
48348
  if (title.length > 0) return title;
48026
48349
  }
@@ -48042,7 +48365,7 @@ function replaceTokenText(input, allowedTokens, tokenValues) {
48042
48365
  });
48043
48366
  }
48044
48367
  function visitRichTextNode(node, allowedTokens, tokenValues) {
48045
- if (!isRecord$27(node)) return node;
48368
+ if (!isRecord$29(node)) return node;
48046
48369
  let changed = false;
48047
48370
  const nextNode = { ...node };
48048
48371
  if (nextNode.type === "text" && typeof nextNode.text === "string") {
@@ -48063,7 +48386,7 @@ function visitRichTextNode(node, allowedTokens, tokenValues) {
48063
48386
  return changed ? nextNode : node;
48064
48387
  }
48065
48388
  function interpolateRichTextTokens(value, options, context) {
48066
- if (!isRecord$27(value)) return value;
48389
+ if (!isRecord$29(value)) return value;
48067
48390
  return visitRichTextNode(value, new Set(options.tokens), {
48068
48391
  year: String((/* @__PURE__ */ new Date()).getFullYear()),
48069
48392
  site_name: getSiteName(context)
@@ -48252,11 +48575,11 @@ var UnsafePathSegmentError = class extends Error {
48252
48575
  function assertSafePathSegments(segments) {
48253
48576
  for (const segment of segments) if (typeof segment === "string" && UNSAFE_PATH_SEGMENTS.has(segment)) throw new UnsafePathSegmentError(segment);
48254
48577
  }
48255
- function isRecord$18(value) {
48578
+ function isRecord$20(value) {
48256
48579
  return typeof value === "object" && value !== null && !Array.isArray(value);
48257
48580
  }
48258
48581
  function isPathContainer(value) {
48259
- return Array.isArray(value) || isRecord$18(value);
48582
+ return Array.isArray(value) || isRecord$20(value);
48260
48583
  }
48261
48584
  function getContainerValue(container, segment) {
48262
48585
  if (typeof segment === "number") return Array.isArray(container) ? container[segment] : void 0;
@@ -48646,7 +48969,7 @@ function parseSiteIconStyleGuideVersionId(value) {
48646
48969
  //#region ../blocks/src/system/icons/value.ts
48647
48970
  init_semantic();
48648
48971
  const NO_BLOCK_ICON_VALUE = { kind: "none" };
48649
- function isRecord$17(value) {
48972
+ function isRecord$19(value) {
48650
48973
  return typeof value === "object" && value !== null && !Array.isArray(value);
48651
48974
  }
48652
48975
  function parseBlockIconValue(value) {
@@ -48654,7 +48977,7 @@ function parseBlockIconValue(value) {
48654
48977
  kind: "semantic",
48655
48978
  iconId: value
48656
48979
  };
48657
- if (!isRecord$17(value)) return NO_BLOCK_ICON_VALUE;
48980
+ if (!isRecord$19(value)) return NO_BLOCK_ICON_VALUE;
48658
48981
  switch (value.kind) {
48659
48982
  case "none": return NO_BLOCK_ICON_VALUE;
48660
48983
  case "semantic": return isSemanticIconId(value.iconId) ? {
@@ -48727,7 +49050,7 @@ function buildGeneratedBlockIconRenderAssetLookupFromUnknown(value) {
48727
49050
  if (!Array.isArray(value)) return { kind: "invalid_asset_list" };
48728
49051
  const inputs = [];
48729
49052
  for (const [index, item] of value.entries()) {
48730
- if (!isRecord$17(item)) return {
49053
+ if (!isRecord$19(item)) return {
48731
49054
  kind: "invalid_asset_entry",
48732
49055
  index,
48733
49056
  reason: "not_object"
@@ -48847,11 +49170,11 @@ function resolveFeatureCardGeneratedIconSizePx(value) {
48847
49170
  const parsed = parseFeatureCardGeneratedIconSizePx(value);
48848
49171
  return parsed.ok ? parsed.value : unsafeAsFeatureCardGeneratedIconSizePx(FEATURE_CARD_GENERATED_ICON_SIZE_PX.default);
48849
49172
  }
48850
- function isRecord$16(value) {
49173
+ function isRecord$18(value) {
48851
49174
  return typeof value === "object" && value !== null && !Array.isArray(value);
48852
49175
  }
48853
49176
  function toPlainTextFromTipTap(value) {
48854
- if (!isRecord$16(value)) return "";
49177
+ if (!isRecord$18(value)) return "";
48855
49178
  if (typeof value.text === "string") return value.text;
48856
49179
  const content = value.content;
48857
49180
  if (!Array.isArray(content)) return "";
@@ -51069,6 +51392,7 @@ const EventSpotlight = ({ events, layout = "grid", columns = "3", cardRole = "de
51069
51392
  //#region ../blocks/src/system/runtime/nodes/events/shared/renderEventListItem.tsx
51070
51393
  init_EventCard();
51071
51394
  init_EventCompactRow();
51395
+ init_eventCardPresentations();
51072
51396
  /**
51073
51397
  * Shared SSR render function for event list items.
51074
51398
  * Selects between EventCard and EventCompactRow based on the display's listLayout.
@@ -51084,14 +51408,7 @@ function renderEventListItem(event, display) {
51084
51408
  }, event.occurrenceId || event.id);
51085
51409
  return /* @__PURE__ */ jsx(EventCard, {
51086
51410
  event,
51087
- cardRole: display.cardRole,
51088
- buttonVariant: display.buttonVariant,
51089
- buttonText: display.buttonText,
51090
- showVenue: display.showVenue,
51091
- showMap: display.showMap,
51092
- allowMap: false,
51093
- showCapacity: display.showCapacity,
51094
- orientation: display.orientation
51411
+ ...listingEventCardProps(display)
51095
51412
  }, event.occurrenceId || event.id);
51096
51413
  }
51097
51414
  //#endregion
@@ -51279,7 +51596,7 @@ function inferLegacyOfferingsPreviewGroupOrder(overrides) {
51279
51596
  return keys.length >= 2 ? keys : [];
51280
51597
  }
51281
51598
  function normalizeOfferingsPreviewContentForWrite(value) {
51282
- if (!isRecord$14(value)) return null;
51599
+ if (!isRecord$16(value)) return null;
51283
51600
  const groupOrderValue = value.groupOrder;
51284
51601
  if (Array.isArray(groupOrderValue)) {
51285
51602
  const normalized = normalizeOfferingsPreviewGroupOrder(groupOrderValue);
@@ -51292,7 +51609,7 @@ function normalizeOfferingsPreviewContentForWrite(value) {
51292
51609
  ...value,
51293
51610
  groupOrder: []
51294
51611
  };
51295
- const legacyOrder = inferLegacyOfferingsPreviewGroupOrder(Array.isArray(value.groupOverrides) ? value.groupOverrides.filter(isRecord$14) : []);
51612
+ const legacyOrder = inferLegacyOfferingsPreviewGroupOrder(Array.isArray(value.groupOverrides) ? value.groupOverrides.filter(isRecord$16) : []);
51296
51613
  return legacyOrder.length > 0 ? {
51297
51614
  ...value,
51298
51615
  groupOrder: legacyOrder
@@ -51357,7 +51674,7 @@ function uniqueOfferingsPreviewSourceKeys(values) {
51357
51674
  }
51358
51675
  return keys;
51359
51676
  }
51360
- function isRecord$14(value) {
51677
+ function isRecord$16(value) {
51361
51678
  return typeof value === "object" && value !== null && !Array.isArray(value);
51362
51679
  }
51363
51680
  function mergeOrderedKeysWithDefaults(orderedKeys, defaultKeys) {
@@ -51464,6 +51781,7 @@ function matchesGroup(group, event) {
51464
51781
  //#endregion
51465
51782
  //#region ../blocks/src/system/runtime/nodes/offerings-preview-catalogue.tsx
51466
51783
  init_shared$2();
51784
+ init_eventCardPresentations();
51467
51785
  init_domain();
51468
51786
  function OfferingsCatalogue(props) {
51469
51787
  const state = buildOfferingsCatalogueState({
@@ -51505,14 +51823,7 @@ function OfferingsCatalogue(props) {
51505
51823
  style: { gridTemplateColumns: "repeat(auto-fill, minmax(min(100%, 18rem), 1fr))" },
51506
51824
  children: events.map((event) => /* @__PURE__ */ jsx(EventCard, {
51507
51825
  event,
51508
- presentation: "catalogue",
51509
- headingLevel: 4,
51510
- buttonVariant: props.buttonVariant ?? "primary",
51511
- buttonText: event.bookingScope === "single_occurrence" ? "See dates" : void 0,
51512
- showMap: false,
51513
- allowMap: false,
51514
- showCategory: false,
51515
- orientation: "vertical"
51826
+ ...catalogueEventCardProps(event, props.buttonVariant ?? "primary")
51516
51827
  }, event.seriesId))
51517
51828
  })]
51518
51829
  }, group.sourceKey))
@@ -51810,45 +52121,73 @@ function FeaturedOfferingSummary({ item }) {
51810
52121
  }
51811
52122
  function featuredSummaryDetails(item) {
51812
52123
  switch (item.kind) {
51813
- case "event": return formatFeaturedSummary(deriveEventScheduleSummary(item.event), item.event.venue?.name ?? null);
52124
+ case "event": return formatFeaturedSummary(deriveEventScheduleSummary(item.event), {
52125
+ venue: item.event.venue?.name ?? null,
52126
+ siteTimeZone: item.event.siteTimeZone
52127
+ });
51814
52128
  case "run": {
51815
52129
  const schedule = derivePreviewRunSchedule(item.run.run.sessions);
51816
- return schedule.kind === "scheduled" ? formatFeaturedSummary(schedule.summary, item.run.representative.venue?.name ?? null) : null;
52130
+ return schedule.kind === "scheduled" ? formatFeaturedSummary(schedule.summary, {
52131
+ venue: item.run.representative.venue?.name ?? null,
52132
+ siteTimeZone: item.run.representative.siteTimeZone
52133
+ }) : null;
51817
52134
  }
51818
52135
  default: return assertNever$20(item, "Unhandled offerings preview item");
51819
52136
  }
51820
52137
  }
51821
- function formatFeaturedSummary(summary, venue) {
52138
+ function formatFeaturedSummary(summary, place) {
51822
52139
  switch (summary.kind) {
51823
- case "single-occurrence": return detailsFromOccurrences(summary.occurrence, null, venue, null, null);
51824
- case "multi-day-span": return detailsFromOccurrences(summary.occurrence, summary.occurrence, venue, null, null, true);
51825
- case "fixed-recurring-run": return detailsFromOccurrences(summary.first, summary.last, venue, summary.recurrenceLabel, null);
51826
- case "irregular-multi-session-run": return detailsFromOccurrences(summary.first, summary.last, venue, null, `${summary.sessionCount} dates`);
52140
+ case "single-occurrence": return detailsFromOccurrences({
52141
+ first: summary.occurrence,
52142
+ last: null,
52143
+ place
52144
+ });
52145
+ case "multi-day-span": return detailsFromOccurrences({
52146
+ first: summary.occurrence,
52147
+ last: summary.occurrence,
52148
+ place,
52149
+ spanUsesEndDate: true
52150
+ });
52151
+ case "fixed-recurring-run": return detailsFromOccurrences({
52152
+ first: summary.first,
52153
+ last: summary.last,
52154
+ place,
52155
+ recurrence: summary.recurrenceLabel
52156
+ });
52157
+ case "irregular-multi-session-run": return detailsFromOccurrences({
52158
+ first: summary.first,
52159
+ last: summary.last,
52160
+ place,
52161
+ sessionCount: `${summary.sessionCount} dates`
52162
+ });
51827
52163
  default: return assertNever$20(summary, "Unhandled offerings preview schedule summary");
51828
52164
  }
51829
52165
  }
51830
- function detailsFromOccurrences(first, last, venue, recurrence, sessionCount, spanUsesEndDate = false) {
51831
- const endDateTime = spanUsesEndDate ? first.endsAt : last?.startsAt ?? first.startsAt;
52166
+ function detailsFromOccurrences(input) {
52167
+ const { first, last, place } = input;
52168
+ const endDateTime = input.spanUsesEndDate ? first.endsAt : last?.startsAt ?? first.startsAt;
52169
+ const options = eventDateOptions({
52170
+ timeZone: first.timeZone,
52171
+ siteTimeZone: place.siteTimeZone
52172
+ });
52173
+ const summaryDate = (isoTimestamp, timeZone) => formatSummaryDate(isoTimestamp, {
52174
+ timeZone,
52175
+ locale: options.locale
52176
+ });
51832
52177
  return {
51833
- startDate: formatSummaryDate(first.startsAt, first.timeZone),
52178
+ startDate: summaryDate(first.startsAt, first.timeZone),
51834
52179
  startDateTime: first.startsAt,
51835
- endDate: last ? formatSummaryDate(endDateTime, last.timeZone) : null,
52180
+ endDate: last ? summaryDate(endDateTime, last.timeZone) : null,
51836
52181
  endDateTime,
51837
- timeRange: `${formatTime$2(first.startsAt, {
51838
- timeZone: first.timeZone,
51839
- locale: "en-GB"
51840
- })} – ${formatTime$2(first.endsAt, {
51841
- timeZone: first.timeZone,
51842
- locale: "en-GB"
51843
- })}`,
51844
- recurrence,
51845
- sessionCount,
51846
- venue
51847
- };
51848
- }
51849
- function formatSummaryDate(isoTimestamp, timeZone) {
51850
- return new Intl.DateTimeFormat("en-GB", {
51851
- timeZone,
52182
+ timeRange: formatEventTimeRange$1(first, options),
52183
+ recurrence: input.recurrence ?? null,
52184
+ sessionCount: input.sessionCount ?? null,
52185
+ venue: place.venue
52186
+ };
52187
+ }
52188
+ function formatSummaryDate(isoTimestamp, options) {
52189
+ return new Intl.DateTimeFormat(options.locale, {
52190
+ timeZone: options.timeZone,
51852
52191
  weekday: "long",
51853
52192
  day: "numeric",
51854
52193
  month: "long",
@@ -51895,9 +52234,12 @@ function WholeSeriesRunCompactRow({ group, path, now }) {
51895
52234
  path
51896
52235
  });
51897
52236
  const { sessionCount: sessionsCount, firstSession } = schedule;
51898
- const timeZone = firstSession.timeZone;
51899
- const dateRail = formatEventCompactDateRail(firstSession.startsAt, { timeZone });
51900
- const timeRange = `${formatTime$2(firstSession.startsAt, { timeZone })} - ${formatTime$2(firstSession.endsAt, { timeZone })}`;
52237
+ const options = eventDateOptions({
52238
+ timeZone: firstSession.timeZone,
52239
+ siteTimeZone: group.representative.siteTimeZone
52240
+ });
52241
+ const dateRail = formatEventCompactDateRail(firstSession.startsAt, options);
52242
+ const timeRange = formatEventTimeRange$1(firstSession, options);
51901
52243
  const price = formatEventPriceDisplay(group.representative.pricing);
51902
52244
  const statusLabel = resolveWholeSeriesBookingPhase(group.run, now).kind === "open" ? null : "Registration closed";
51903
52245
  return /* @__PURE__ */ jsxs("article", {
@@ -51977,9 +52319,12 @@ function WholeSeriesRunFeatureCard({ group, now, path, buttonVariant, buttonText
51977
52319
  path
51978
52320
  });
51979
52321
  const { firstSession } = schedule;
51980
- const timeZone = firstSession.timeZone;
51981
- const formattedDate = formatEventCompactDateRail(firstSession.startsAt, { timeZone }).label;
51982
- const timeRange = `${formatTime$2(firstSession.startsAt, { timeZone })} - ${formatTime$2(firstSession.endsAt, { timeZone })}`;
52322
+ const options = eventDateOptions({
52323
+ timeZone: firstSession.timeZone,
52324
+ siteTimeZone: group.representative.siteTimeZone
52325
+ });
52326
+ const formattedDate = formatEventCompactDateRail(firstSession.startsAt, options).label;
52327
+ const timeRange = formatEventTimeRange$1(firstSession, options);
51983
52328
  const price = formatEventPriceDisplay(group.representative.pricing);
51984
52329
  const statusLabel = resolveWholeSeriesBookingPhase(group.run, now).kind === "open" ? null : "Registration closed";
51985
52330
  const description = group.representative.description;
@@ -52457,6 +52802,10 @@ const checkoutBlockDefinition = {
52457
52802
  baseClass: "",
52458
52803
  spacing: "spacious",
52459
52804
  children: sectionContainer([checkout(withApiBindings({
52805
+ demoEmailSuppressed: { $bind: {
52806
+ from: "$root.demoEmailSuppressed",
52807
+ fallback: false
52808
+ } },
52460
52809
  readAuthority: { $bind: { from: "$root.readAuthority" } },
52461
52810
  mode: "checkout",
52462
52811
  heading: { $bind: {
@@ -52733,8 +53082,8 @@ const eventRegistrationBlockDefinition = {
52733
53082
  description: "Message shown after successful registration",
52734
53083
  required: false,
52735
53084
  multiline: true,
52736
- defaultValue: "Thank you for registering! Check your email for confirmation details.",
52737
- maxLength: 500
53085
+ maxLength: 500,
53086
+ ui: { placeholder: "Thank you for registering! Check your email for confirmation details." }
52738
53087
  },
52739
53088
  {
52740
53089
  id: "buttonText",
@@ -52755,6 +53104,10 @@ const eventRegistrationBlockDefinition = {
52755
53104
  text({ as: "h2" }, bind("content.heading"), when("content.heading")),
52756
53105
  richText({ className: "rb-prose rb-max-w-none" }, bind("content.description"), when("content.description")),
52757
53106
  eventRegistration(withApiBindings({
53107
+ demoEmailSuppressed: { $bind: {
53108
+ from: "$root.demoEmailSuppressed",
53109
+ fallback: false
53110
+ } },
52758
53111
  readAuthority: { $bind: { from: "$root.readAuthority" } },
52759
53112
  occurrenceContext: { $bind: { from: "$root.occurrenceContext" } },
52760
53113
  subject: { $bind: { from: "$root.subject" } },
@@ -55108,6 +55461,10 @@ const shopBlockDefinition = {
55108
55461
  spacing: "spacious",
55109
55462
  children: sectionContainer([shop(withApiBindings({
55110
55463
  readAuthority: { $bind: { from: "$root.readAuthority" } },
55464
+ demoEmailSuppressed: { $bind: {
55465
+ from: "$root.demoEmailSuppressed",
55466
+ fallback: false
55467
+ } },
55111
55468
  mode: "passes-memberships",
55112
55469
  showPasses: { $bind: {
55113
55470
  from: "content.showPasses",
@@ -55605,11 +55962,12 @@ function CartSSR({ blockId, siteId, apiBaseUrl, stage, children, ...rest }) {
55605
55962
  //#endregion
55606
55963
  //#region ../blocks/src/system/runtime/nodes/checkout.server.tsx
55607
55964
  init_shop_interactive();
55608
- function CheckoutSSR({ blockId, siteId, apiBaseUrl, stage, children, ...rest }) {
55965
+ function CheckoutSSR({ blockId, siteId, apiBaseUrl, stage, demoEmailSuppressed, children, ...rest }) {
55609
55966
  const islandProps = buildCheckoutInteractiveIslandProps({
55610
55967
  siteId,
55611
55968
  apiBaseUrl,
55612
55969
  stage,
55970
+ demoEmailSuppressed,
55613
55971
  ...rest
55614
55972
  });
55615
55973
  return /* @__PURE__ */ jsxs("div", {
@@ -57594,14 +57952,14 @@ function isDecoratedHeadingBlockKind(blockKind) {
57594
57952
  return blockKind === "block.intro" || blockKind === "block.feature-cards" || blockKind === "block.testimonials" || blockKind === "block.faq";
57595
57953
  }
57596
57954
  function readVariant(blockContent) {
57597
- if (!isRecord$13(blockContent)) return void 0;
57955
+ if (!isRecord$15(blockContent)) return void 0;
57598
57956
  const variant = blockContent.variant;
57599
57957
  return typeof variant === "string" ? variant : void 0;
57600
57958
  }
57601
57959
  function isFaqDecoratedVariant(variant) {
57602
57960
  return variant === "default" || variant === "question-columns";
57603
57961
  }
57604
- function isRecord$13(value) {
57962
+ function isRecord$15(value) {
57605
57963
  return typeof value === "object" && value !== null && !Array.isArray(value);
57606
57964
  }
57607
57965
  function buildHeadingDecorationWrapperClassName(className) {
@@ -58581,11 +58939,11 @@ function readTreatment(kind, value) {
58581
58939
  };
58582
58940
  }
58583
58941
  function readBlockComposition(value) {
58584
- if (!isRecord$12(value) || typeof value.kind !== "string") return null;
58942
+ if (!isRecord$14(value) || typeof value.kind !== "string") return null;
58585
58943
  if (!isCompositionKind(value.kind)) return null;
58586
58944
  return readTreatment(value.kind, value.treatment);
58587
58945
  }
58588
- function isRecord$12(value) {
58946
+ function isRecord$14(value) {
58589
58947
  return typeof value === "object" && value !== null && !Array.isArray(value);
58590
58948
  }
58591
58949
  //#endregion
@@ -61874,6 +62232,7 @@ function buildPageRendererRootRuntime(dataContext) {
61874
62232
  const { siteId = null, siteName, pageId = null, pathname = null, bookingTimeZone, previewStage = "published", apiBaseUrl = null, portalToken = null, readAuthority, bookingOfferingPresets = [], appointmentServicePathPrefix = null, mailingList = { tag: "not_configured" }, eventRegistrationOverlayEnabled = false, loaderFailures = {} } = dataContext ?? {};
61875
62233
  return {
61876
62234
  siteId,
62235
+ demoEmailSuppressed: resolveDemoEmailSuppression(dataContext),
61877
62236
  siteName,
61878
62237
  pageId,
61879
62238
  pathname,
@@ -61889,6 +62248,9 @@ function buildPageRendererRootRuntime(dataContext) {
61889
62248
  loaderFailures
61890
62249
  };
61891
62250
  }
62251
+ function resolveDemoEmailSuppression(dataContext) {
62252
+ return dataContext?.demoEmailSuppressed === true;
62253
+ }
61892
62254
  //#endregion
61893
62255
  //#region ../blocks/src/pageRenderAudience.tsx
61894
62256
  init_colorStyles();
@@ -66498,6 +66860,10 @@ const bookingDescription = richText({}, bind("content.description"), when("conte
66498
66860
  * that hydration never rewrites.
66499
66861
  */
66500
66862
  const bookingWizard = bookingForm(withApiBindings({
66863
+ demoEmailSuppressed: { $bind: {
66864
+ from: "$root.demoEmailSuppressed",
66865
+ fallback: false
66866
+ } },
66501
66867
  portalToken: { $bind: {
66502
66868
  from: "$root.portalToken",
66503
66869
  fallback: null
@@ -68025,7 +68391,7 @@ function isOfferingsPreviewItemLimit(value) {
68025
68391
  return value === "1" || value === "2" || value === "3" || value === "4" || value === "5" || value === "6" || value === null;
68026
68392
  }
68027
68393
  function normalizeOfferingsPreviewGroupOverride(value) {
68028
- if (!isRecord$10(value)) return [];
68394
+ if (!isRecord$12(value)) return [];
68029
68395
  const override = {};
68030
68396
  if (isOfferingsPreviewSourceKey(value.sourceKey) || value.sourceKey === null) override.sourceKey = value.sourceKey;
68031
68397
  if (typeof value.title === "string" || value.title === null) override.title = value.title;
@@ -68048,7 +68414,7 @@ function normalizeSectionStylesContent(value) {
68048
68414
  }
68049
68415
  function normalizeBoxStylesContent(value) {
68050
68416
  if (value === null) return null;
68051
- if (!isRecord$10(value)) return void 0;
68417
+ if (!isRecord$12(value)) return void 0;
68052
68418
  const { background: _background, ...rest } = value;
68053
68419
  const background = parseBackgroundContent(value.background);
68054
68420
  return {
@@ -68056,7 +68422,7 @@ function normalizeBoxStylesContent(value) {
68056
68422
  ...background ? { background } : {}
68057
68423
  };
68058
68424
  }
68059
- function isRecord$10(value) {
68425
+ function isRecord$12(value) {
68060
68426
  return typeof value === "object" && value !== null && !Array.isArray(value);
68061
68427
  }
68062
68428
  //#endregion
@@ -71220,11 +71586,11 @@ init_repeaterGrid();
71220
71586
  //#endregion
71221
71587
  //#region ../blocks/src/system/media/constrainedVideoMedia.ts
71222
71588
  init_src$1();
71223
- function isRecord$9(value) {
71589
+ function isRecord$11(value) {
71224
71590
  return typeof value === "object" && value !== null && !Array.isArray(value);
71225
71591
  }
71226
71592
  function valueAtField(current, fieldId) {
71227
- return isRecord$9(current) ? current[fieldId] : void 0;
71593
+ return isRecord$11(current) ? current[fieldId] : void 0;
71228
71594
  }
71229
71595
  function collectConstrainedVideoMediaValues(options) {
71230
71596
  const { blockKind, fields, currentValue, parentPath = [] } = options;
@@ -71235,7 +71601,7 @@ function collectConstrainedVideoMediaValues(options) {
71235
71601
  const fieldValue = valueAtField(currentValue, field.id);
71236
71602
  switch (field.type) {
71237
71603
  case "media": {
71238
- if (!isRecord$9(fieldValue) || fieldValue.type !== "video") break;
71604
+ if (!isRecord$11(fieldValue) || fieldValue.type !== "video") break;
71239
71605
  const policy = deriveVideoSlotPolicy(resolveVideoSelectionIntentForMediaField({
71240
71606
  fieldPath,
71241
71607
  mediaKinds: field.mediaKinds
@@ -71632,7 +71998,7 @@ function hydrateResolvedBookingConsentValue(value, context) {
71632
71998
  const hydratedItems = value.map((item) => hydrateResolvedBookingConsentValue(item, context));
71633
71999
  return hydratedItems.every((item, index) => item === value[index]) ? value : hydratedItems;
71634
72000
  }
71635
- if (!isRecord$27(value)) return value;
72001
+ if (!isRecord$29(value)) return value;
71636
72002
  if (isBookingConsentCarrier(value)) {
71637
72003
  const agreement = hydrateValue(value.agreement, context);
71638
72004
  return agreement === value.agreement ? value : {
@@ -71652,7 +72018,7 @@ function hydrateValue(value, context) {
71652
72018
  const resolvedItems = value.map((item) => hydrateValue(item, context));
71653
72019
  return resolvedItems.every((item, index) => item === value[index]) ? value : resolvedItems;
71654
72020
  }
71655
- if (isRecord$27(value)) {
72021
+ if (isRecord$29(value)) {
71656
72022
  if (isInternalLink$1(value)) return hydrateInternalLink(value, context.routes);
71657
72023
  if (isPageLink$1(value)) return hydratePageLink(value, context);
71658
72024
  if (isEntryLink$1(value)) return hydrateEntryLink(value, context);
@@ -71718,7 +72084,7 @@ function hydrateEntryLink(link, context) {
71718
72084
  init_typeGuards();
71719
72085
  function resolveBlockData(blockId, dataLoaders, dataContext, routes) {
71720
72086
  const raw = blockId ? dataContext?.resolvedData?.[blockId] : void 0;
71721
- if (isRecord$27(raw)) return routes ? hydrateResolvedBookingConsentLinks(raw, routes, dataContext?.pagesByIdentifier, dataContext?.entriesByIdentifier) : raw;
72087
+ if (isRecord$29(raw)) return routes ? hydrateResolvedBookingConsentLinks(raw, routes, dataContext?.pagesByIdentifier, dataContext?.entriesByIdentifier) : raw;
71722
72088
  return dataLoaders && typeof dataLoaders === "object" && Object.keys(dataLoaders).length > 0 ? {} : void 0;
71723
72089
  }
71724
72090
  //#endregion
@@ -71733,15 +72099,17 @@ function planNewsletterBlockSubmission(placement) {
71733
72099
  sourceRef
71734
72100
  } : { tag: "unavailable" };
71735
72101
  }
71736
- if (placement.publishedPlacement && "kind" in placement.publishedPlacement) return { tag: "unpublished-settings" };
71737
- if (placement.publishedPlacement) return planNewsletterPreviewSubmission({
71738
- blockId: placement.blockId,
71739
- publishedContentId: placement.publishedPlacement.id,
71740
- renderedContent: placement.renderedContent,
71741
- publishedContent: placement.publishedPlacement.content
71742
- });
71743
- if (placement.stage === "preview") return { tag: "unpublished-form" };
71744
- return { tag: "unavailable" };
72102
+ const published = placement.publishedPlacement;
72103
+ if (published === null) return placement.stage === "preview" ? { tag: "unpublished-form" } : { tag: "unavailable" };
72104
+ switch (published.kind) {
72105
+ case "incomplete": return { tag: "unpublished-settings" };
72106
+ case "published": return planNewsletterPreviewSubmission({
72107
+ blockId: placement.blockId,
72108
+ publishedContentId: published.id,
72109
+ renderedContent: placement.renderedContent,
72110
+ publishedContent: published.content
72111
+ });
72112
+ }
71745
72113
  }
71746
72114
  /** Decide whether the visible draft can safely cite the published placement. */
71747
72115
  function planNewsletterPreviewSubmission(placement) {
@@ -71988,19 +72356,7 @@ function createBlockErrorBoundary() {
71988
72356
  const BlockErrorBoundary = createBlockErrorBoundary();
71989
72357
  //#endregion
71990
72358
  //#region ../blocks/src/pageRenderAdmission.ts
71991
- /** Pair a published version with the content it authorises at the render boundary. */
71992
- function readPublishedBlockPlacement(id, content) {
71993
- if (id == null && content == null) return null;
71994
- if (id == null || content == null) return {
71995
- kind: "incomplete",
71996
- id: id ?? null,
71997
- content: content ?? null
71998
- };
71999
- return {
72000
- id,
72001
- content
72002
- };
72003
- }
72359
+ init_src$2();
72004
72360
  function toPresentationPage(page) {
72005
72361
  if (!page) return null;
72006
72362
  return {
@@ -88867,7 +89223,7 @@ init_src$2();
88867
89223
  const APPOINTMENT_SERVICE_VISIBILITY_VALUES = ["public", "unlisted"];
88868
89224
  //#endregion
88869
89225
  //#region ../api/src/utils/isRecord.ts
88870
- function isRecord$6(value) {
89226
+ function isRecord$8(value) {
88871
89227
  return typeof value === "object" && value !== null && !Array.isArray(value);
88872
89228
  }
88873
89229
  //#endregion
@@ -89124,7 +89480,7 @@ function sanitizeMarks(marks) {
89124
89480
  if (!Array.isArray(marks) || marks.length === 0) return;
89125
89481
  const sanitized = marks.flatMap((mark) => {
89126
89482
  if (mark.type === "bold" || mark.type === "strong" || mark.type === "italic" || mark.type === "em") return [{ type: mark.type }];
89127
- if (mark.type === "link" && isRecord$6(mark.attrs) && typeof mark.attrs.href === "string") {
89483
+ if (mark.type === "link" && isRecord$8(mark.attrs) && typeof mark.attrs.href === "string") {
89128
89484
  const attrs = { href: mark.attrs.href };
89129
89485
  if (typeof mark.attrs.target === "string" && mark.attrs.target.trim().length > 0) attrs.target = mark.attrs.target;
89130
89486
  if (typeof mark.attrs.rel === "string" && mark.attrs.rel.trim().length > 0) attrs.rel = mark.attrs.rel;
@@ -89149,7 +89505,7 @@ function collectText(node) {
89149
89505
  }
89150
89506
  function stableSerialize(value) {
89151
89507
  if (Array.isArray(value)) return `[${value.map(stableSerialize).join(",")}]`;
89152
- if (isRecord$6(value)) return `{${Object.entries(value).filter(([, entryValue]) => entryValue !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, entryValue]) => `${JSON.stringify(key)}:${stableSerialize(entryValue)}`).join(",")}}`;
89508
+ if (isRecord$8(value)) return `{${Object.entries(value).filter(([, entryValue]) => entryValue !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, entryValue]) => `${JSON.stringify(key)}:${stableSerialize(entryValue)}`).join(",")}}`;
89153
89509
  return JSON.stringify(value);
89154
89510
  }
89155
89511
  //#endregion
@@ -89332,7 +89688,7 @@ function collectCartLinkStats(items, depth = 0) {
89332
89688
  return result;
89333
89689
  }
89334
89690
  function isNavigationMenuValidationItem(value) {
89335
- if (!isRecord$6(value)) return false;
89691
+ if (!isRecord$8(value)) return false;
89336
89692
  return typeof value.label === "string";
89337
89693
  }
89338
89694
  //#endregion
@@ -89353,7 +89709,7 @@ function normalizeIdList(value) {
89353
89709
  return result.length > 0 ? result : null;
89354
89710
  }
89355
89711
  function extractNavVisibilityConfig(raw) {
89356
- if (!isRecord$6(raw)) return null;
89712
+ if (!isRecord$8(raw)) return null;
89357
89713
  const modeRaw = raw.mode;
89358
89714
  const mode = modeRaw === "augment" || modeRaw === "restrict" ? modeRaw : null;
89359
89715
  const allowIds = normalizeIdList(raw.allowIds);
@@ -89366,7 +89722,7 @@ function extractNavVisibilityConfig(raw) {
89366
89722
  };
89367
89723
  }
89368
89724
  function asRecord(value) {
89369
- return isRecord$6(value) ? value : null;
89725
+ return isRecord$8(value) ? value : null;
89370
89726
  }
89371
89727
  /**
89372
89728
  * Check if a raw config object has any nav visibility values defined.
@@ -89481,7 +89837,7 @@ const ENTRY_REF_KEYS = [
89481
89837
  "entryId",
89482
89838
  "slug"
89483
89839
  ];
89484
- function isRecord$5(value) {
89840
+ function isRecord$7(value) {
89485
89841
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
89486
89842
  }
89487
89843
  function extractManualEntryRef(item) {
@@ -89489,7 +89845,7 @@ function extractManualEntryRef(item) {
89489
89845
  const trimmed = item.trim();
89490
89846
  return trimmed.length > 0 ? trimmed : null;
89491
89847
  }
89492
- if (!isRecord$5(item)) return null;
89848
+ if (!isRecord$7(item)) return null;
89493
89849
  for (const key of ENTRY_REF_KEYS) {
89494
89850
  const raw = item[key];
89495
89851
  if (typeof raw === "string" && raw.trim().length > 0) return raw.trim();
@@ -89822,11 +90178,19 @@ function readBlockContentId(value, name) {
89822
90178
  function readTransportedBlockIdentity(block, kind, stage) {
89823
90179
  return {
89824
90180
  draftContentId: readBlockContentId(block.draftContentId, "draft content id"),
89825
- publishedPlacement: stage === "preview" ? readPublishedBlockPlacement(readBlockContentId(block.publishedContentId, "published content id"), sanitizeNullableSdkRuntimeBlockContent(kind, readNestedContentRecord(block.publishedContent))) : null
90181
+ publishedPlacement: stage === "preview" ? readSdkPreviewPublishedPlacement(block, kind) : null
89826
90182
  };
89827
90183
  }
90184
+ /** Pair SDK preview publication data whether it is transported or already admitted. */
90185
+ function readSdkPreviewPublishedPlacement(block, kind) {
90186
+ if (block.publishedPlacement !== void 0 && block.publishedPlacement !== null) {
90187
+ if (!isRecord$6(block.publishedPlacement)) throw new Error("Invalid published placement in page");
90188
+ return readPublishedBlockPlacement(readBlockContentId(block.publishedPlacement.id, "published content id"), sanitizeNullableSdkRuntimeBlockContent(kind, readContentRecord(block.publishedPlacement.content) ?? null));
90189
+ }
90190
+ return readPublishedBlockPlacement(readBlockContentId(block.publishedContentId, "published content id"), sanitizeNullableSdkRuntimeBlockContent(kind, readSdkPublishedContentRecord(block.publishedContent)));
90191
+ }
89828
90192
  function convertPageResponseBlock(block, stage) {
89829
- if (!isRecord$4(block)) throw new Error("Invalid block format in page API response");
90193
+ if (!isRecord$6(block)) throw new Error("Invalid block format in page API response");
89830
90194
  const header = readTransportedBlockHeader(block);
89831
90195
  const admission = readInvalidBlockAdmission(block.admission);
89832
90196
  return {
@@ -89850,7 +90214,7 @@ function readTransportedBlockHeader(block) {
89850
90214
  };
89851
90215
  }
89852
90216
  function readInvalidBlockAdmission(value) {
89853
- if (!isRecord$4(value) || value.kind !== "invalid" || !isRecord$4(value.error)) return null;
90217
+ if (!isRecord$6(value) || value.kind !== "invalid" || !isRecord$6(value.error)) return null;
89854
90218
  if (value.error.kind !== "invalid_manifest_content" && value.error.kind !== "manifest_unavailable") return null;
89855
90219
  return value;
89856
90220
  }
@@ -89923,20 +90287,24 @@ function invalidRenderableBlock(block, error) {
89923
90287
  }
89924
90288
  };
89925
90289
  }
89926
- function isRecord$4(value) {
90290
+ function isRecord$6(value) {
89927
90291
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
89928
90292
  }
89929
90293
  function readContentRecord(value) {
89930
- return isRecord$4(value) ? value : void 0;
90294
+ return isRecord$6(value) ? value : void 0;
89931
90295
  }
89932
90296
  function readNestedContentRecord(value) {
89933
- if (!isRecord$4(value)) return null;
90297
+ if (!isRecord$6(value)) return null;
89934
90298
  return readContentRecord(value.data) ?? null;
89935
90299
  }
90300
+ function readSdkPublishedContentRecord(value) {
90301
+ if (!isRecord$6(value)) return null;
90302
+ return "data" in value ? readContentRecord(value.data) ?? null : value;
90303
+ }
89936
90304
  function sanitizeSdkRuntimeBlockContent(blockKind, content) {
89937
90305
  if (blockKind !== "block.newsletter-signup") return content;
89938
90306
  const sanitized = sanitizeNewsletterSignupPublicContent(content);
89939
- return isRecord$4(sanitized) ? sanitized : {};
90307
+ return isRecord$6(sanitized) ? sanitized : {};
89940
90308
  }
89941
90309
  function sanitizeNullableSdkRuntimeBlockContent(blockKind, content) {
89942
90310
  return content ? sanitizeSdkRuntimeBlockContent(blockKind, content) : null;
@@ -91730,7 +92098,7 @@ var init_embla_carousel_autoplay_esm = __esmMin((() => {
91730
92098
  function isObject$1(subject) {
91731
92099
  return Object.prototype.toString.call(subject) === "[object Object]";
91732
92100
  }
91733
- function isRecord$3(subject) {
92101
+ function isRecord$5(subject) {
91734
92102
  return isObject$1(subject) || Array.isArray(subject);
91735
92103
  }
91736
92104
  function canUseDOM() {
@@ -91745,7 +92113,7 @@ function areOptionsEqual(optionsA, optionsB) {
91745
92113
  const valueA = optionsA[key];
91746
92114
  const valueB = optionsB[key];
91747
92115
  if (typeof valueA === "function") return `${valueA}` === `${valueB}`;
91748
- if (!isRecord$3(valueA) || !isRecord$3(valueB)) return valueA === valueB;
92116
+ if (!isRecord$5(valueA) || !isRecord$5(valueB)) return valueA === valueB;
91749
92117
  return areOptionsEqual(valueA, valueB);
91750
92118
  });
91751
92119
  }
@@ -148273,7 +148641,7 @@ function encodePublicProductCategorySelector(selector) {
148273
148641
  };
148274
148642
  }
148275
148643
  }
148276
- function isRecord$2(value) {
148644
+ function isRecord$4(value) {
148277
148645
  return typeof value === "object" && value !== null;
148278
148646
  }
148279
148647
  function isJsonResponseContentType(contentType) {
@@ -148297,15 +148665,15 @@ async function parseJsonBody(response) {
148297
148665
  }
148298
148666
  }
148299
148667
  function isFieldError(value) {
148300
- return isRecord$2(value) && !Array.isArray(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
148668
+ return isRecord$4(value) && !Array.isArray(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
148301
148669
  }
148302
148670
  function fieldErrorsFromUnknown(value) {
148303
148671
  if (!Array.isArray(value)) return void 0;
148304
148672
  return value.every(isFieldError) ? value : void 0;
148305
148673
  }
148306
148674
  function getBlockApiErrorDetails(data) {
148307
- if (!isRecord$2(data)) return {};
148308
- const nestedError = isRecord$2(data.error) ? data.error : void 0;
148675
+ if (!isRecord$4(data)) return {};
148676
+ const nestedError = isRecord$4(data.error) ? data.error : void 0;
148309
148677
  const message = typeof nestedError?.message === "string" ? nestedError.message : typeof data.message === "string" ? data.message : void 0;
148310
148678
  const code = typeof nestedError?.code === "string" ? nestedError.code : typeof data.code === "string" ? data.code : void 0;
148311
148679
  const fieldErrors = fieldErrorsFromUnknown(nestedError?.fieldErrors) ?? fieldErrorsFromUnknown(data.fieldErrors);
@@ -148874,10 +149242,11 @@ function createBlockApi(config) {
148874
149242
  },
148875
149243
  async sendMagicLink(data) {
148876
149244
  const sid = requireSiteId();
148877
- await request(PORTAL.sendMagicLink, { body: {
149245
+ return request(PORTAL.sendMagicLink, { body: {
148878
149246
  siteId: sid,
148879
149247
  email: data.email,
148880
- redirectUrl: data.redirectUrl
149248
+ redirectUrl: data.redirectUrl,
149249
+ demoBookingPass: data.demoBookingPass
148881
149250
  } });
148882
149251
  },
148883
149252
  async logout() {
@@ -151719,6 +152088,35 @@ var init_form = __esmMin((() => {
151719
152088
  };
151720
152089
  }));
151721
152090
  //#endregion
152091
+ //#region ../blocks/src/system/runtime/nodes/booking-form.payment-confirmation.ts
152092
+ function bookingServiceRequiresPaymentBeforeBooking(input) {
152093
+ switch (getBookingServicePaymentSelectionMode(input.service)) {
152094
+ case "implicit_upfront":
152095
+ case "implicit_instalment_plan":
152096
+ case "implicit_flexible_balance": return true;
152097
+ case "choice_required": return input.selectedCollectionOptionKind !== void 0 && input.selectedCollectionOptionKind !== "deferred_manual";
152098
+ case "implicit_deferred_manual":
152099
+ case "pending_stripe_setup":
152100
+ case "unsupported": return false;
152101
+ }
152102
+ }
152103
+ function resolveBookingPaymentConfirmationSummary(input) {
152104
+ const service = input.service;
152105
+ if (!service || input.hasSelectedAppointmentPackage || !Number.isFinite(input.priceAmount) || input.priceAmount <= 0 || !service.durationMinutes || !bookingServiceRequiresPaymentBeforeBooking({
152106
+ service,
152107
+ selectedCollectionOptionKind: input.selectedCollectionOptionKind
152108
+ })) return null;
152109
+ return {
152110
+ serviceTitle: service.title,
152111
+ durationMinutes: service.durationMinutes,
152112
+ priceAmount: input.priceAmount,
152113
+ priceCurrency: service.priceCurrency ?? service.pricing?.currency ?? "USD"
152114
+ };
152115
+ }
152116
+ var init_booking_form_payment_confirmation = __esmMin((() => {
152117
+ init_booking_form_state();
152118
+ }));
152119
+ //#endregion
151722
152120
  //#region ../blocks/src/system/runtime/hooks/useSelectedAppointmentConsentForm.ts
151723
152121
  function useSelectedAppointmentConsentForm(form, selectedService) {
151724
152122
  return useMemo(() => projectSelectedAppointmentConsentIntoForm(form, resolveSelectedAppointmentConsent(selectedService)), [form, selectedService]);
@@ -152260,6 +152658,75 @@ var init_useBookingSubmission_state = __esmMin((() => {
152260
152658
  };
152261
152659
  }));
152262
152660
  //#endregion
152661
+ //#region ../blocks/src/system/runtime/shared/utils/demoBookingPassStorage.ts
152662
+ function normalizeDemoBookingEmail(email) {
152663
+ return email.trim().toLowerCase();
152664
+ }
152665
+ function storeDemoBookingPass(email, pass) {
152666
+ try {
152667
+ const normalizedEmail = normalizeDemoBookingEmail(email);
152668
+ if (!normalizedEmail || !pass) return;
152669
+ const current = readStoredDemoBookingPasses();
152670
+ const updated = [{
152671
+ email: normalizedEmail,
152672
+ pass
152673
+ }, ...current.filter((entry) => entry.email !== normalizedEmail)].slice(0, MAX_STORED_PASSES);
152674
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify(updated));
152675
+ } catch {}
152676
+ }
152677
+ function storeDemoBookingPassIfAvailable(email, pass) {
152678
+ if (email && pass) storeDemoBookingPass(email, pass);
152679
+ }
152680
+ function getDemoBookingPass(email) {
152681
+ try {
152682
+ const normalizedEmail = normalizeDemoBookingEmail(email);
152683
+ return readStoredDemoBookingPasses().find((entry) => entry.email === normalizedEmail)?.pass ?? null;
152684
+ } catch {
152685
+ return null;
152686
+ }
152687
+ }
152688
+ function storeDemoBookingCheckoutReturn(email, pass) {
152689
+ const normalizedEmail = normalizeDemoBookingEmail(email);
152690
+ if (!normalizedEmail) return;
152691
+ storeDemoBookingPassIfAvailable(normalizedEmail, pass);
152692
+ try {
152693
+ window.sessionStorage.setItem(CHECKOUT_RETURN_EMAIL_KEY, normalizedEmail);
152694
+ } catch {}
152695
+ }
152696
+ function readDemoBookingCheckoutReturnEmail() {
152697
+ try {
152698
+ const email = window.sessionStorage.getItem(CHECKOUT_RETURN_EMAIL_KEY);
152699
+ window.sessionStorage.removeItem(CHECKOUT_RETURN_EMAIL_KEY);
152700
+ return email ? normalizeDemoBookingEmail(email) : null;
152701
+ } catch {
152702
+ return null;
152703
+ }
152704
+ }
152705
+ function readStoredDemoBookingPasses() {
152706
+ try {
152707
+ const raw = window.localStorage.getItem(STORAGE_KEY);
152708
+ if (!raw) return [];
152709
+ const parsed = JSON.parse(raw);
152710
+ return Array.isArray(parsed) ? parsed.filter(isStoredDemoBookingPass) : [];
152711
+ } catch {
152712
+ return [];
152713
+ }
152714
+ }
152715
+ function isStoredDemoBookingPass(value) {
152716
+ if (!isRecord$3(value)) return false;
152717
+ const record = value;
152718
+ return typeof record.email === "string" && record.email.length > 0 && typeof record.pass === "string" && record.pass.length > 0;
152719
+ }
152720
+ function isRecord$3(value) {
152721
+ return typeof value === "object" && value !== null && !Array.isArray(value);
152722
+ }
152723
+ var STORAGE_KEY, CHECKOUT_RETURN_EMAIL_KEY, MAX_STORED_PASSES;
152724
+ var init_demoBookingPassStorage = __esmMin((() => {
152725
+ STORAGE_KEY = "riverbank:demo-booking-passes:v1";
152726
+ CHECKOUT_RETURN_EMAIL_KEY = "riverbank:demo-booking-checkout-email:v1";
152727
+ MAX_STORED_PASSES = 10;
152728
+ }));
152729
+ //#endregion
152263
152730
  //#region ../blocks/src/system/runtime/hooks/useBookingSubmission.ts
152264
152731
  /**
152265
152732
  * Hook for submitting appointment bookings
@@ -152319,6 +152786,7 @@ function useBookingSubmission(_siteId) {
152319
152786
  successUrl: data.successUrl,
152320
152787
  cancelUrl: data.cancelUrl
152321
152788
  });
152789
+ storeDemoBookingPassIfAvailable(response.customer.email, response.demoBookingPass);
152322
152790
  dispatch({
152323
152791
  type: "submission-succeeded",
152324
152792
  message: response.type === "checkout_redirect" ? "Redirecting to secure checkout..." : "Booking submitted successfully."
@@ -152349,6 +152817,7 @@ var init_useBookingSubmission = __esmMin((() => {
152349
152817
  init_dist$1();
152350
152818
  init_api$1();
152351
152819
  init_useBookingSubmission_state();
152820
+ init_demoBookingPassStorage();
152352
152821
  }));
152353
152822
  //#endregion
152354
152823
  //#region ../blocks/src/system/runtime/nodes/booking-form.submit-success.ts
@@ -152362,15 +152831,18 @@ function completeBookingSubmission(input) {
152362
152831
  kind: "checkout_redirect",
152363
152832
  checkoutUrl: data.checkoutUrl,
152364
152833
  sessionId: data.sessionId,
152834
+ customerEmail: data.customer.email,
152835
+ ...data.demoBookingPass ? { demoBookingPass: data.demoBookingPass } : {},
152365
152836
  ...data.mailingListSignupNote ? { mailingListSignupNote: data.mailingListSignupNote } : {}
152366
152837
  }
152367
152838
  };
152368
152839
  }
152840
+ const successCopy = getBookingSuccessCopy(input.successMessage);
152369
152841
  input.dispatch({
152370
152842
  type: "feedback-set",
152371
152843
  feedback: {
152372
152844
  kind: "success",
152373
- message: getBookingSuccessMessage(input.successMessage),
152845
+ message: successCopy.defaultEmailSentence ? `${successCopy.message} ${successCopy.defaultEmailSentence}`.trim() : successCopy.message,
152374
152846
  resourceName: data.appointment.resourceName
152375
152847
  }
152376
152848
  });
@@ -152380,6 +152852,8 @@ function completeBookingSubmission(input) {
152380
152852
  kind: "booked",
152381
152853
  appointmentId: data.appointment.id,
152382
152854
  resourceName: data.appointment.resourceName,
152855
+ customerEmail: data.customer.email,
152856
+ ...data.demoBookingPass ? { demoBookingPass: data.demoBookingPass } : {},
152383
152857
  ...data.mailingListSignupNote ? { mailingListSignupNote: data.mailingListSignupNote } : {}
152384
152858
  }
152385
152859
  };
@@ -154075,6 +154549,12 @@ function useHeadlessBookingFlow(options) {
154075
154549
  selectedService,
154076
154550
  state.selectedSlot?.startAt
154077
154551
  ]);
154552
+ const paymentConfirmationSummary = resolveBookingPaymentConfirmationSummary({
154553
+ service: selectedService,
154554
+ priceAmount: selectedAppointmentPriceAmount,
154555
+ selectedCollectionOptionKind: state.selectedCollectionOptionKind,
154556
+ hasSelectedAppointmentPackage: Boolean(state.selectedAppointmentPackageId)
154557
+ });
154078
154558
  const appointmentPackageItems = appointmentPackages.tag === "loaded" ? appointmentPackages.value : [];
154079
154559
  const selectedAppointmentPackage = appointmentPackageItems.find((appointmentPackage) => appointmentPackage.customerPassId === state.selectedAppointmentPackageId) ?? null;
154080
154560
  const spamProtectionEnabled = options.spamProtectionEnabled ?? isSpamProtectionEnabled();
@@ -154104,7 +154584,8 @@ function useHeadlessBookingFlow(options) {
154104
154584
  selectedSlidingAmount,
154105
154585
  slidingScale: selectedServiceSlidingScale,
154106
154586
  appointmentPackages: appointmentPackagesModel,
154107
- errorMessage: paymentResolution.errorMessage ?? "This service cannot be booked right now."
154587
+ errorMessage: paymentResolution.errorMessage ?? "This service cannot be booked right now.",
154588
+ confirmationSummary: null
154108
154589
  } : {
154109
154590
  kind: "ok",
154110
154591
  mode: paymentResolution.mode,
@@ -154114,7 +154595,8 @@ function useHeadlessBookingFlow(options) {
154114
154595
  selectedSlidingAmountInput: state.selectedSlidingAmountInput,
154115
154596
  selectedSlidingAmount,
154116
154597
  slidingScale: selectedServiceSlidingScale,
154117
- appointmentPackages: appointmentPackagesModel
154598
+ appointmentPackages: appointmentPackagesModel,
154599
+ confirmationSummary: paymentConfirmationSummary
154118
154600
  };
154119
154601
  return {
154120
154602
  mailingList,
@@ -154214,6 +154696,7 @@ var init_useHeadlessBookingFlow = __esmMin((() => {
154214
154696
  init_src$2();
154215
154697
  init_api$1();
154216
154698
  init_booking_form_state();
154699
+ init_booking_form_payment_confirmation();
154217
154700
  init_useSelectedAppointmentConsentForm();
154218
154701
  init_useAvailableDates();
154219
154702
  init_useAvailableSlots();
@@ -154293,65 +154776,22 @@ var init_usePolling_state = __esmMin((() => {
154293
154776
  * Provides a reusable polling mechanism with configurable intervals,
154294
154777
  * max attempts, and completion detection. Used by usePaymentVerification
154295
154778
  * and other hooks that need to poll for status changes.
154296
- *
154297
- * @example
154298
- * ```tsx
154299
- * const polling = usePolling(shouldPoll ? {
154300
- * pollFn: () => api.getStatus(id),
154301
- * isComplete: (result) => result.status === 'done',
154302
- * } : null);
154303
- *
154304
- * useEffect(() => {
154305
- * if (polling.status === 'completed') {
154306
- * handleSuccess(polling.result);
154307
- * }
154308
- * }, [polling.status]);
154309
- * ```
154310
154779
  */
154311
- /**
154312
- * Generic hook for polling an async operation until completion.
154313
- *
154314
- * Pass config to start polling, or null to stop/idle.
154315
- * The hook handles cleanup on unmount and config changes.
154316
- *
154317
- * **IMPORTANT: Config identity stability**
154318
- *
154319
- * The config object is used as an effect dependency. If config identity
154320
- * changes on every render (e.g., inline objects), polling will restart
154321
- * continuously, causing infinite request loops.
154322
- *
154323
- * Always memoize the config object:
154324
- *
154325
- * @example
154326
- * ```tsx
154327
- * // BAD - inline object creates new identity every render
154328
- * usePolling({
154329
- * pollFn: () => api.getStatus(id),
154330
- * isComplete: (result) => result.status === 'done',
154331
- * });
154332
- *
154333
- * // GOOD - memoized config, stable identity
154334
- * const pollConfig = useMemo(() => shouldPoll ? {
154335
- * pollFn: () => api.getStatus(id),
154336
- * isComplete: (result) => result.status === 'done',
154337
- * } : null, [shouldPoll, api, id]);
154338
- *
154339
- * usePolling(pollConfig);
154340
- * ```
154341
- *
154342
- * @param config - Configuration for polling, or null to stop
154343
- * @returns Polling result with status, data, and retry function
154344
- */
154345
- function usePolling(config) {
154346
- const [state, dispatch] = useReducer(pollingReducer, void 0, createInitialPollingState);
154347
- const attemptsRef = useRef(0);
154348
- const timeoutRef = useRef(null);
154349
- const isPollingRef = useRef(false);
154350
- const isActiveRef = useRef(false);
154351
- const generationRef = useRef(0);
154352
- const configRef = useRef(config);
154353
- configRef.current = config;
154354
- const cleanup = useCallback(() => {
154780
+ function usePollingRuntime(config) {
154781
+ const runtime = {
154782
+ configRef: useRef(config),
154783
+ attemptsRef: useRef(0),
154784
+ timeoutRef: useRef(null),
154785
+ isPollingRef: useRef(false),
154786
+ isActiveRef: useRef(false),
154787
+ generationRef: useRef(0)
154788
+ };
154789
+ runtime.configRef.current = config;
154790
+ return runtime;
154791
+ }
154792
+ function usePollingCleanup(runtime) {
154793
+ const { isActiveRef, generationRef, timeoutRef, isPollingRef } = runtime;
154794
+ return useCallback(() => {
154355
154795
  isActiveRef.current = false;
154356
154796
  generationRef.current += 1;
154357
154797
  if (timeoutRef.current) {
@@ -154359,16 +154799,27 @@ function usePolling(config) {
154359
154799
  timeoutRef.current = null;
154360
154800
  }
154361
154801
  isPollingRef.current = false;
154362
- }, []);
154363
- const resetState = useCallback(() => {
154802
+ }, [
154803
+ generationRef,
154804
+ isActiveRef,
154805
+ isPollingRef,
154806
+ timeoutRef
154807
+ ]);
154808
+ }
154809
+ function usePollingReset(runtime, dispatch) {
154810
+ const { attemptsRef } = runtime;
154811
+ return useCallback(() => {
154364
154812
  dispatch({ type: "polling-reset" });
154365
154813
  attemptsRef.current = 0;
154366
- }, []);
154367
- const poll = useCallback(async () => {
154368
- const cfg = configRef.current;
154369
- if (!cfg) return true;
154814
+ }, [attemptsRef, dispatch]);
154815
+ }
154816
+ function usePollingRequest(runtime, dispatch, cleanup) {
154817
+ const { configRef, attemptsRef, isPollingRef, isActiveRef, generationRef } = runtime;
154818
+ return useCallback(async () => {
154819
+ const config = configRef.current;
154820
+ if (!config) return true;
154370
154821
  if (isPollingRef.current) return false;
154371
- const maxAttempts = cfg.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
154822
+ const maxAttempts = config.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
154372
154823
  if (attemptsRef.current >= maxAttempts) {
154373
154824
  dispatch({ type: "polling-timed-out" });
154374
154825
  cleanup();
@@ -154378,81 +154829,115 @@ function usePolling(config) {
154378
154829
  attemptsRef.current += 1;
154379
154830
  const generation = generationRef.current;
154380
154831
  try {
154381
- const data = await cfg.pollFn();
154382
- if (generation !== generationRef.current || !isActiveRef.current) {
154383
- isPollingRef.current = false;
154384
- return true;
154385
- }
154386
- if (cfg.isFailed?.(data)) {
154832
+ const result = await config.pollFn();
154833
+ if (generation !== generationRef.current || !isActiveRef.current) return true;
154834
+ if (config.isFailed?.(result)) {
154387
154835
  dispatch({
154388
154836
  type: "polling-failed",
154389
- result: data
154837
+ result
154390
154838
  });
154391
154839
  cleanup();
154392
154840
  return true;
154393
154841
  }
154394
- if (cfg.isComplete(data)) {
154842
+ if (config.isComplete(result)) {
154395
154843
  dispatch({
154396
154844
  type: "polling-completed",
154397
- result: data
154845
+ result
154398
154846
  });
154399
154847
  cleanup();
154400
154848
  return true;
154401
154849
  }
154402
154850
  dispatch({
154403
154851
  type: "polling-progressed",
154404
- result: data
154852
+ result
154405
154853
  });
154406
154854
  isPollingRef.current = false;
154407
154855
  return false;
154408
- } catch (err) {
154409
- if (generation !== generationRef.current || !isActiveRef.current) {
154410
- isPollingRef.current = false;
154411
- return true;
154412
- }
154413
- if (err instanceof Error) dispatch({
154856
+ } catch (error) {
154857
+ if (generation !== generationRef.current || !isActiveRef.current) return true;
154858
+ if (error instanceof Error) dispatch({
154414
154859
  type: "polling-request-failed",
154415
- error: err
154860
+ error
154416
154861
  });
154417
154862
  isPollingRef.current = false;
154418
154863
  return false;
154419
154864
  }
154420
- }, [cleanup]);
154421
- const schedulePoll = useCallback(() => {
154865
+ }, [
154866
+ attemptsRef,
154867
+ cleanup,
154868
+ configRef,
154869
+ dispatch,
154870
+ generationRef,
154871
+ isActiveRef,
154872
+ isPollingRef
154873
+ ]);
154874
+ }
154875
+ function usePollingScheduler(runtime, poll) {
154876
+ const { attemptsRef, configRef, isActiveRef, timeoutRef } = runtime;
154877
+ return useCallback(() => {
154422
154878
  if (!isActiveRef.current) return;
154423
- const pollInterval = configRef.current?.interval ?? DEFAULT_POLL_INTERVAL;
154424
154879
  const doPoll = async () => {
154425
- if (!await poll() && isActiveRef.current) timeoutRef.current = setTimeout(doPoll, pollInterval);
154880
+ if (!await poll() && isActiveRef.current) {
154881
+ const configuredInterval = configRef.current?.interval;
154882
+ const interval = typeof configuredInterval === "function" ? configuredInterval(attemptsRef.current) : configuredInterval ?? DEFAULT_POLL_INTERVAL;
154883
+ timeoutRef.current = setTimeout(doPoll, interval);
154884
+ }
154426
154885
  };
154427
154886
  doPoll();
154428
- }, [poll]);
154887
+ }, [
154888
+ attemptsRef,
154889
+ configRef,
154890
+ isActiveRef,
154891
+ poll,
154892
+ timeoutRef
154893
+ ]);
154894
+ }
154895
+ function usePollingCycle(config, runtime, dispatch) {
154896
+ const cleanup = usePollingCleanup(runtime);
154897
+ const resetState = usePollingReset(runtime, dispatch);
154898
+ const schedulePoll = usePollingScheduler(runtime, usePollingRequest(runtime, dispatch, cleanup));
154899
+ const pollingEnabled = config !== null;
154429
154900
  useEffect(() => {
154430
- if (!config) {
154901
+ if (!pollingEnabled) {
154431
154902
  cleanup();
154432
154903
  dispatch({ type: "polling-went-idle" });
154433
154904
  return;
154434
154905
  }
154435
154906
  resetState();
154436
- isActiveRef.current = true;
154907
+ runtime.isActiveRef.current = true;
154437
154908
  schedulePoll();
154438
154909
  return cleanup;
154439
154910
  }, [
154440
- config,
154441
154911
  cleanup,
154912
+ dispatch,
154913
+ pollingEnabled,
154442
154914
  resetState,
154915
+ config?.restartKey ?? null,
154916
+ runtime.isActiveRef,
154443
154917
  schedulePoll
154444
154918
  ]);
154445
- const retry = useCallback(() => {
154446
- if (!configRef.current) return;
154919
+ return useCallback(() => {
154920
+ if (!runtime.configRef.current) return;
154447
154921
  cleanup();
154448
154922
  resetState();
154449
- isActiveRef.current = true;
154923
+ runtime.isActiveRef.current = true;
154450
154924
  schedulePoll();
154451
154925
  }, [
154452
154926
  cleanup,
154453
154927
  resetState,
154928
+ runtime.configRef,
154929
+ runtime.isActiveRef,
154454
154930
  schedulePoll
154455
154931
  ]);
154932
+ }
154933
+ /**
154934
+ * Polls until the operation completes, fails, times out, or becomes disabled.
154935
+ * Config objects may be rebuilt across renders; change restartKey to begin a
154936
+ * new operation and reset its attempt budget.
154937
+ */
154938
+ function usePolling(config) {
154939
+ const [state, dispatch] = useReducer(pollingReducer, void 0, createInitialPollingState);
154940
+ const retry = usePollingCycle(config, usePollingRuntime(config), dispatch);
154456
154941
  return {
154457
154942
  status: config ? state.tag : "idle",
154458
154943
  result: config ? state.result : null,
@@ -154468,21 +154953,33 @@ var init_usePolling = __esmMin((() => {
154468
154953
  }));
154469
154954
  //#endregion
154470
154955
  //#region ../blocks/src/system/runtime/hooks/useAppointmentCheckoutVerification.ts
154956
+ function resolveAppointmentCheckoutPollInterval(attempt) {
154957
+ return Math.min(1e3 * 2 ** (attempt - 1), 4e3);
154958
+ }
154471
154959
  function useAppointmentCheckoutVerification(config) {
154472
154960
  return useAppointmentCheckoutVerificationWithDeps(config, appointmentCheckoutVerificationDeps);
154473
154961
  }
154474
154962
  function useAppointmentCheckoutVerificationWithDeps(config, deps) {
154475
154963
  const api = deps.useBlockApi();
154964
+ const sessionId = config?.sessionId ?? null;
154965
+ const maxAttempts = config?.maxAttempts;
154966
+ const pollInterval = config?.pollInterval;
154476
154967
  const pollingConfig = useMemo(() => {
154477
- if (!config) return null;
154968
+ if (sessionId === null) return null;
154478
154969
  return {
154479
- pollFn: () => api.getAppointmentBookingStatus({ sessionId: config.sessionId }),
154970
+ restartKey: sessionId,
154971
+ pollFn: () => api.getAppointmentBookingStatus({ sessionId }),
154480
154972
  isComplete: (result) => (result.paymentStatus === "completed" || result.paymentStatus === "not_required") && result.appointmentStatus === "confirmed",
154481
154973
  isFailed: (result) => result.paymentStatus === "failed" || result.paymentStatus === "cancelled" || result.paymentStatus === "refunded" || result.appointmentStatus === "cancelled",
154482
- maxAttempts: config.maxAttempts,
154483
- interval: config.pollInterval
154974
+ maxAttempts: maxAttempts ?? APPOINTMENT_CHECKOUT_MAX_ATTEMPTS,
154975
+ interval: pollInterval ?? resolveAppointmentCheckoutPollInterval
154484
154976
  };
154485
- }, [api, config]);
154977
+ }, [
154978
+ api,
154979
+ sessionId,
154980
+ maxAttempts,
154981
+ pollInterval
154982
+ ]);
154486
154983
  const polling = deps.usePolling(pollingConfig);
154487
154984
  return {
154488
154985
  state: resolveAppointmentCheckoutVerificationState({
@@ -154494,11 +154991,12 @@ function useAppointmentCheckoutVerificationWithDeps(config, deps) {
154494
154991
  retry: polling.retry
154495
154992
  };
154496
154993
  }
154497
- var appointmentCheckoutVerificationDeps;
154994
+ var APPOINTMENT_CHECKOUT_MAX_ATTEMPTS, appointmentCheckoutVerificationDeps;
154498
154995
  var init_useAppointmentCheckoutVerification = __esmMin((() => {
154499
154996
  init_api$1();
154500
154997
  init_booking_form_state();
154501
154998
  init_usePolling();
154999
+ APPOINTMENT_CHECKOUT_MAX_ATTEMPTS = 12;
154502
155000
  appointmentCheckoutVerificationDeps = {
154503
155001
  useBlockApi,
154504
155002
  usePolling
@@ -155022,6 +155520,76 @@ var init_booking_form_service_choices = __esmMin((() => {
155022
155520
  init_CheckIcon$1();
155023
155521
  }));
155024
155522
  //#endregion
155523
+ //#region ../blocks/src/system/runtime/nodes/booking-form.submit-actions.tsx
155524
+ function resolvePrimaryActionLabel(isLastStep, requiresPayment) {
155525
+ if (!isLastStep) return "Continue";
155526
+ return requiresPayment ? "Continue to payment" : "Complete";
155527
+ }
155528
+ function formatBookingConfirmationDateTime(booking) {
155529
+ const startAt = booking.currentStep?.id === "datetime-selection" ? booking.availability.selectedSlot?.startAt : void 0;
155530
+ return startAt ? new Intl.DateTimeFormat(void 0, {
155531
+ dateStyle: "medium",
155532
+ timeStyle: "short",
155533
+ timeZone: booking.availability.timezone
155534
+ }).format(new Date(startAt)) : null;
155535
+ }
155536
+ function BookingPaymentConfirmationText({ booking, summary }) {
155537
+ if (!summary) return null;
155538
+ const dateTime = formatBookingConfirmationDateTime(booking);
155539
+ return /* @__PURE__ */ jsxs("p", {
155540
+ className: "ab-text rb-on-surface--muted",
155541
+ children: [
155542
+ summary.serviceTitle,
155543
+ " · ",
155544
+ summary.durationMinutes,
155545
+ " min ·",
155546
+ " ",
155547
+ formatCurrencyAmount(summary.priceAmount, summary.priceCurrency, { decimals: "auto" }),
155548
+ dateTime ? ` · ${dateTime}` : ""
155549
+ ]
155550
+ });
155551
+ }
155552
+ function BookingFormSubmitActions({ booking, onSubmit }) {
155553
+ const currentStepIndex = booking.currentStep?.visibleIndex ?? 0;
155554
+ const isFirstStep = currentStepIndex === 0;
155555
+ const isLastStep = currentStepIndex === booking.steps.length - 1;
155556
+ const isSubmitting = booking.status.tag === "submitting";
155557
+ const paymentSummary = isLastStep && booking.payment.kind === "ok" ? booking.payment.confirmationSummary : null;
155558
+ const handlePrimaryAction = async () => {
155559
+ if ((await booking.actions.next()).ok && isLastStep) await onSubmit();
155560
+ };
155561
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(BookingPaymentConfirmationText, {
155562
+ booking,
155563
+ summary: paymentSummary
155564
+ }), /* @__PURE__ */ jsxs("div", {
155565
+ className: "rb-wizard-actions",
155566
+ children: [!isFirstStep ? /* @__PURE__ */ jsx(ThemedButton, {
155567
+ type: "button",
155568
+ onClick: booking.actions.back,
155569
+ variant: "outline",
155570
+ size: "md",
155571
+ label: "Back"
155572
+ }) : null, /* @__PURE__ */ jsx(ThemedButton, {
155573
+ type: "button",
155574
+ onClick: () => {
155575
+ handlePrimaryAction();
155576
+ },
155577
+ disabled: isSubmitting,
155578
+ variant: "primary",
155579
+ size: "md",
155580
+ label: resolvePrimaryActionLabel(isLastStep, Boolean(paymentSummary)),
155581
+ pending: isSubmitting ? {
155582
+ label: "Submitting...",
155583
+ srLabel: "Submitting"
155584
+ } : void 0
155585
+ })]
155586
+ })] });
155587
+ }
155588
+ var init_booking_form_submit_actions = __esmMin((() => {
155589
+ init_src$2();
155590
+ init_ThemedButton();
155591
+ }));
155592
+ //#endregion
155025
155593
  //#region ../blocks/src/system/runtime/nodes/booking-form.default-ui.tsx
155026
155594
  function formatBookingAmount(amount, currency) {
155027
155595
  return formatCurrencyAmount(amount, currency, { decimals: "auto" });
@@ -155030,13 +155598,6 @@ function HeadlessBookingDefaultForm({ booking, onSubmit }) {
155030
155598
  const currentStep = booking.currentStep;
155031
155599
  const errorSummaryId = React.useId();
155032
155600
  const currentStepIndex = currentStep?.visibleIndex ?? 0;
155033
- const isFirstStep = currentStepIndex === 0;
155034
- const isLastStep = currentStepIndex === booking.steps.length - 1;
155035
- const isSubmitting = booking.status.tag === "submitting";
155036
- const handlePrimaryAction = async () => {
155037
- if (!(await booking.actions.next()).ok) return;
155038
- if (isLastStep) await onSubmit();
155039
- };
155040
155601
  if (!currentStep) return /* @__PURE__ */ jsx("div", {
155041
155602
  className: "rb-text-center rb-py-12",
155042
155603
  children: /* @__PURE__ */ jsx("p", {
@@ -155064,28 +155625,9 @@ function HeadlessBookingDefaultForm({ booking, onSubmit }) {
155064
155625
  errors: currentStep.errors,
155065
155626
  id: errorSummaryId
155066
155627
  }),
155067
- /* @__PURE__ */ jsxs("div", {
155068
- className: "rb-wizard-actions",
155069
- children: [!isFirstStep ? /* @__PURE__ */ jsx(ThemedButton, {
155070
- type: "button",
155071
- onClick: booking.actions.back,
155072
- variant: "outline",
155073
- size: "md",
155074
- label: "Back"
155075
- }) : null, /* @__PURE__ */ jsx(ThemedButton, {
155076
- type: "button",
155077
- onClick: () => {
155078
- handlePrimaryAction();
155079
- },
155080
- disabled: isSubmitting,
155081
- variant: "primary",
155082
- size: "md",
155083
- label: isLastStep ? "Complete" : "Continue",
155084
- pending: isSubmitting ? {
155085
- label: "Submitting...",
155086
- srLabel: "Submitting"
155087
- } : void 0
155088
- })]
155628
+ /* @__PURE__ */ jsx(BookingFormSubmitActions, {
155629
+ booking,
155630
+ onSubmit
155089
155631
  }),
155090
155632
  /* @__PURE__ */ jsx(DefaultBookingDiscount, { booking }),
155091
155633
  /* @__PURE__ */ jsx(DefaultBookingFeedback, { booking }),
@@ -155708,6 +156250,7 @@ var init_booking_form_default_ui = __esmMin((() => {
155708
156250
  init_booking_form_mailing_list_choice();
155709
156251
  init_CheckboxChoice();
155710
156252
  init_booking_form_service_choices();
156253
+ init_booking_form_submit_actions();
155711
156254
  }));
155712
156255
  //#endregion
155713
156256
  //#region ../blocks/src/system/runtime/shared/utils/checkoutUrls.ts
@@ -155930,6 +156473,23 @@ var init_ActionRow = __esmMin((() => {
155930
156473
  };
155931
156474
  }));
155932
156475
  //#endregion
156476
+ //#region ../blocks/src/system/runtime/shared/components/DemoPortalSignInLink.tsx
156477
+ function DemoPortalSignInLink(props) {
156478
+ return /* @__PURE__ */ jsxs("div", { children: [
156479
+ /* @__PURE__ */ jsx("h3", { children: "Your sign-in link" }),
156480
+ /* @__PURE__ */ jsx("p", { children: "In the demo we don’t send emails, so here’s the link we’d have sent you." }),
156481
+ /* @__PURE__ */ jsx(ThemedButtonLink, {
156482
+ variant: "default",
156483
+ size: "md",
156484
+ label: "Sign in to the portal",
156485
+ href: props.url
156486
+ })
156487
+ ] });
156488
+ }
156489
+ var init_DemoPortalSignInLink = __esmMin((() => {
156490
+ init_ThemedButton();
156491
+ }));
156492
+ //#endregion
155933
156493
  //#region ../blocks/src/system/runtime/shared/components/LoggedInAsUser.tsx
155934
156494
  /**
155935
156495
  * Displays the logged-in user's email with an optional logout link.
@@ -156116,6 +156676,7 @@ var init_components = __esmMin((() => {
156116
156676
  init_ActionRow();
156117
156677
  init_FieldValidationMessage();
156118
156678
  init_FeedbackMessage();
156679
+ init_DemoPortalSignInLink();
156119
156680
  init_LoggedInAsUser();
156120
156681
  init_StateIcon();
156121
156682
  init_MembershipHero$1();
@@ -156134,6 +156695,158 @@ var init_shared = __esmMin((() => {
156134
156695
  init_components();
156135
156696
  }));
156136
156697
  //#endregion
156698
+ //#region ../blocks/src/system/runtime/shared/utils/demoPortalMagicLink.ts
156699
+ function buildPortalCallbackUrl(origin, redirectTo) {
156700
+ const url = new URL("/api/portal/callback", origin);
156701
+ url.searchParams.set("redirect_to", redirectTo);
156702
+ return url.toString();
156703
+ }
156704
+ async function requestDemoPortalMagicLink(input) {
156705
+ const email = normalizeDemoBookingEmail(input.email);
156706
+ const pass = getDemoBookingPass(email);
156707
+ const request = {
156708
+ email,
156709
+ redirectUrl: input.redirectUrl,
156710
+ ...pass ? { demoBookingPass: pass } : {}
156711
+ };
156712
+ try {
156713
+ const response = await input.send(request);
156714
+ if ("kind" in response) return {
156715
+ kind: "refused",
156716
+ message: response.message
156717
+ };
156718
+ return "demoSignInUrl" in response ? {
156719
+ kind: "demo_sign_in",
156720
+ url: response.demoSignInUrl
156721
+ } : { kind: "email_sent" };
156722
+ } catch (error) {
156723
+ if (error instanceof BlockApiError && error.tag === "demo_email_not_booked_here") return {
156724
+ kind: "refused",
156725
+ message: error.message
156726
+ };
156727
+ throw error;
156728
+ }
156729
+ }
156730
+ var CUSTOMER_PORTAL_PATH;
156731
+ var init_demoPortalMagicLink = __esmMin((() => {
156732
+ init_client$1();
156733
+ init_demoBookingPassStorage();
156734
+ CUSTOMER_PORTAL_PATH = "/portal";
156735
+ }));
156736
+ //#endregion
156737
+ //#region ../blocks/src/system/runtime/shared/components/DemoBookingPortalAccess.tsx
156738
+ function BookingConfirmation(props) {
156739
+ const content = renderConfirmationMessage((props.demoEmailSuppressed ? [props.copy.message] : [props.copy.message, props.copy.defaultEmailSentence ?? ""]).filter((part) => part.trim().length > 0).join(" "), props.messagePresentation);
156740
+ if (!props.demoEmailSuppressed) return content;
156741
+ return /* @__PURE__ */ jsxs(Fragment, { children: [content, /* @__PURE__ */ jsx(DemoBookingPortalAccess, {
156742
+ email: props.email,
156743
+ noteClassName: props.noteClassName,
156744
+ showConfirmationNote: props.showConfirmationNote
156745
+ })] });
156746
+ }
156747
+ function DemoBookingPortalAccess(props) {
156748
+ const { state, openPortal } = useDemoBookingPortalAccess(props.email);
156749
+ return /* @__PURE__ */ jsxs("div", {
156750
+ className: "rb-mt-4 rb-flex rb-flex-col rb-items-start rb-gap-3",
156751
+ "data-testid": "demo-booking-portal-access",
156752
+ children: [
156753
+ props.showConfirmationNote === false ? null : /* @__PURE__ */ jsx("p", {
156754
+ className: props.noteClassName ?? "ab-text",
156755
+ children: SUPPRESSED_CONFIRMATION_NOTE
156756
+ }),
156757
+ /* @__PURE__ */ jsx(ThemedButton, {
156758
+ type: "button",
156759
+ variant: "default",
156760
+ size: "md",
156761
+ label: state.tag === "opening" ? "Opening…" : "Open the customer portal",
156762
+ disabled: state.tag === "opening",
156763
+ onClick: openPortal
156764
+ }),
156765
+ state.tag === "refused" ? /* @__PURE__ */ jsx("p", {
156766
+ role: "alert",
156767
+ children: state.message
156768
+ }) : null,
156769
+ state.tag === "error" ? /* @__PURE__ */ jsx("p", {
156770
+ role: "alert",
156771
+ children: state.message
156772
+ }) : null
156773
+ ]
156774
+ });
156775
+ }
156776
+ function renderConfirmationMessage(message, presentation) {
156777
+ if (!message) return null;
156778
+ switch (presentation.kind) {
156779
+ case "paragraph": return /* @__PURE__ */ jsx("p", {
156780
+ className: presentation.className,
156781
+ children: message
156782
+ });
156783
+ case "plain": return message;
156784
+ }
156785
+ }
156786
+ function useDemoBookingPortalAccess(email) {
156787
+ const api = useBlockApi();
156788
+ const [state, setState] = React.useState({ tag: "idle" });
156789
+ const openPortal = async () => {
156790
+ if (state.tag === "opening") return;
156791
+ if (!email) {
156792
+ setState({
156793
+ tag: "error",
156794
+ message: "We couldn’t open the customer portal. Please try again."
156795
+ });
156796
+ return;
156797
+ }
156798
+ setState({ tag: "opening" });
156799
+ try {
156800
+ const result = await requestDemoPortalMagicLink({
156801
+ email,
156802
+ redirectUrl: buildPortalCallbackUrl(window.location.origin, CUSTOMER_PORTAL_PATH),
156803
+ send: (request) => api.sendMagicLink(request)
156804
+ });
156805
+ switch (result.kind) {
156806
+ case "demo_sign_in":
156807
+ window.location.assign(result.url);
156808
+ return;
156809
+ case "refused":
156810
+ setState({
156811
+ tag: "refused",
156812
+ message: result.message
156813
+ });
156814
+ return;
156815
+ case "email_sent":
156816
+ setState({ tag: "idle" });
156817
+ return;
156818
+ }
156819
+ } catch (error) {
156820
+ setState(handlePortalAccessError(error));
156821
+ }
156822
+ };
156823
+ return {
156824
+ state,
156825
+ openPortal
156826
+ };
156827
+ }
156828
+ function handlePortalAccessError(error) {
156829
+ if (error instanceof BlockApiError && error.tag === "demo_email_not_booked_here") return {
156830
+ tag: "refused",
156831
+ message: error.message
156832
+ };
156833
+ return error instanceof BlockApiError ? {
156834
+ tag: "error",
156835
+ message: error.message
156836
+ } : {
156837
+ tag: "error",
156838
+ message: "We couldn’t open the customer portal. Please try again."
156839
+ };
156840
+ }
156841
+ var SUPPRESSED_CONFIRMATION_NOTE;
156842
+ var init_DemoBookingPortalAccess = __esmMin((() => {
156843
+ init_api$1();
156844
+ init_client$1();
156845
+ init_demoPortalMagicLink();
156846
+ init_ThemedButton();
156847
+ 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.";
156848
+ }));
156849
+ //#endregion
156137
156850
  //#region ../blocks/src/system/runtime/components/booking/SuccessMessage.tsx
156138
156851
  /**
156139
156852
  * SuccessMessage Component
@@ -156147,7 +156860,8 @@ var init_SuccessMessage = __esmMin((() => {
156147
156860
  init_CheckIcon$1();
156148
156861
  init_StateIcon();
156149
156862
  init_TerminalPanel();
156150
- SuccessMessage = ({ message, resourceName, className }) => {
156863
+ init_DemoBookingPortalAccess();
156864
+ SuccessMessage = ({ copy, resourceName, className, demoEmailSuppressed = false, customerEmail = null }) => {
156151
156865
  return /* @__PURE__ */ jsx(TerminalPanel, {
156152
156866
  tone: "success",
156153
156867
  title: "Booking confirmed",
@@ -156155,9 +156869,15 @@ var init_SuccessMessage = __esmMin((() => {
156155
156869
  variant: "success",
156156
156870
  children: /* @__PURE__ */ jsx(CheckIcon, { strokeWidth: 3 })
156157
156871
  }),
156158
- body: /* @__PURE__ */ jsx("p", {
156159
- className: "ab-text",
156160
- children: message
156872
+ body: /* @__PURE__ */ jsx(BookingConfirmation, {
156873
+ demoEmailSuppressed,
156874
+ email: customerEmail,
156875
+ copy,
156876
+ messagePresentation: {
156877
+ kind: "paragraph",
156878
+ className: "ab-text"
156879
+ },
156880
+ noteClassName: "ab-text"
156161
156881
  }),
156162
156882
  secondaryBody: resourceName ? /* @__PURE__ */ jsxs("p", {
156163
156883
  className: "ab-text rb-on-surface--muted",
@@ -156200,32 +156920,56 @@ var init_BookingMailingListNote = __esmMin((() => {
156200
156920
  init_mailingListSignupCopy();
156201
156921
  }));
156202
156922
  //#endregion
156203
- //#region ../blocks/src/system/runtime/nodes/booking-form.mailing-list-note.ts
156923
+ //#region ../blocks/src/system/runtime/nodes/booking-form.checkout-return-context.ts
156204
156924
  function storageKey(sessionId) {
156205
156925
  return `riverbank:booking:mailing-list:${sessionId}`;
156206
156926
  }
156207
- function saveAppointmentMailingListNote(sessionId, note) {
156208
- if (!note) return;
156927
+ function saveAppointmentCheckoutReturnContext(sessionId, context) {
156928
+ if (!context.customerEmail && !context.mailingListNote) return;
156209
156929
  try {
156210
- window.sessionStorage.setItem(storageKey(sessionId), note);
156930
+ window.sessionStorage.setItem(storageKey(sessionId), JSON.stringify(context));
156211
156931
  } catch {}
156212
156932
  }
156213
- function readAppointmentMailingListNote(sessionId) {
156933
+ function readAppointmentCheckoutReturnContext(sessionId) {
156214
156934
  try {
156215
156935
  const stored = window.sessionStorage.getItem(storageKey(sessionId));
156216
- return stored === "confirmation_required" || stored === "not_confirmed" ? stored : null;
156936
+ if (!stored) return null;
156937
+ return parseContext(stored);
156217
156938
  } catch {
156218
156939
  return null;
156219
156940
  }
156220
156941
  }
156221
- var init_booking_form_mailing_list_note = __esmMin((() => {}));
156942
+ function parseContext(value) {
156943
+ try {
156944
+ const parsed = JSON.parse(value);
156945
+ return isContext(parsed) ? parsed : null;
156946
+ } catch {
156947
+ return value === "confirmation_required" || value === "not_confirmed" ? {
156948
+ customerEmail: null,
156949
+ mailingListNote: value
156950
+ } : null;
156951
+ }
156952
+ }
156953
+ function isContext(value) {
156954
+ if (!isRecord$1(value)) return false;
156955
+ return (typeof value.customerEmail === "string" || value.customerEmail === null) && (value.mailingListNote === null || value.mailingListNote === "confirmation_required" || value.mailingListNote === "not_confirmed");
156956
+ }
156957
+ function isRecord$1(value) {
156958
+ return typeof value === "object" && value !== null && !Array.isArray(value);
156959
+ }
156960
+ var init_booking_form_checkout_return_context = __esmMin((() => {}));
156222
156961
  //#endregion
156223
156962
  //#region ../blocks/src/system/runtime/nodes/booking-form.completion.tsx
156224
- function BookingFormCompletion({ resourceName, successMessage, redirectState, localNote }) {
156225
- const note = redirectState.kind === "success" ? readAppointmentMailingListNote(redirectState.sessionId) : localNote;
156963
+ function BookingFormCompletion({ resourceName, successMessage, redirectState, localNote, customerEmail, demoEmailSuppressed = false }) {
156964
+ const returnContext = redirectState.kind === "success" ? readAppointmentCheckoutReturnContext(redirectState.sessionId) : null;
156965
+ const note = redirectState.kind === "success" ? returnContext?.mailingListNote ?? null : localNote;
156966
+ const confirmedEmail = returnContext?.customerEmail ?? customerEmail;
156967
+ const successCopy = getBookingSuccessCopy(successMessage);
156226
156968
  return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SuccessMessage, {
156227
- message: getBookingSuccessMessage(successMessage),
156228
- resourceName
156969
+ copy: successCopy,
156970
+ resourceName,
156971
+ demoEmailSuppressed,
156972
+ customerEmail: confirmedEmail
156229
156973
  }), note ? /* @__PURE__ */ jsx(BookingMailingListNote, {
156230
156974
  note,
156231
156975
  context: "booking",
@@ -156236,7 +156980,7 @@ var init_booking_form_completion = __esmMin((() => {
156236
156980
  init_SuccessMessage();
156237
156981
  init_BookingMailingListNote();
156238
156982
  init_booking_form_state();
156239
- init_booking_form_mailing_list_note();
156983
+ init_booking_form_checkout_return_context();
156240
156984
  }));
156241
156985
  //#endregion
156242
156986
  //#region ../blocks/src/system/runtime/nodes/booking-form.submit-handler.ts
@@ -156255,17 +156999,23 @@ function createBookingFormSubmitHandler(input) {
156255
156999
  cancelUrl: appendRebookFlag(cancelUrl, input.isPortalRebook)
156256
157000
  });
156257
157001
  if (!result.ok) return;
157002
+ storeDemoBookingPassIfAvailable(result.outcome.customerEmail, result.outcome.demoBookingPass);
156258
157003
  if (result.outcome.kind === "checkout_redirect") {
156259
- saveAppointmentMailingListNote(result.outcome.sessionId, result.outcome.mailingListSignupNote);
157004
+ saveAppointmentCheckoutReturnContext(result.outcome.sessionId, {
157005
+ customerEmail: result.outcome.customerEmail,
157006
+ mailingListNote: result.outcome.mailingListSignupNote ?? null
157007
+ });
156260
157008
  window.location.href = result.outcome.checkoutUrl;
156261
157009
  return;
156262
157010
  }
156263
157011
  input.setLocalMailingListNote(result.outcome.mailingListSignupNote ?? null);
157012
+ input.setLocalCustomerEmail(result.outcome.customerEmail);
156264
157013
  };
156265
157014
  }
156266
157015
  var init_booking_form_submit_handler = __esmMin((() => {
156267
157016
  init_shared();
156268
- init_booking_form_mailing_list_note();
157017
+ init_booking_form_checkout_return_context();
157018
+ init_demoBookingPassStorage();
156269
157019
  }));
156270
157020
  //#endregion
156271
157021
  //#region ../blocks/src/system/runtime/nodes/booking-form.client.tsx
@@ -156302,6 +157052,7 @@ var init_booking_form_client = __esmMin((() => {
156302
157052
  init_booking_form_interactive();
156303
157053
  init_shared();
156304
157054
  init_FeedbackMessage();
157055
+ init_ThemedButton();
156305
157056
  init_booking_form_completion();
156306
157057
  init_booking_form_submit_handler();
156307
157058
  init_date_formatting();
@@ -156319,6 +157070,7 @@ var init_booking_form_client = __esmMin((() => {
156319
157070
  const hasLoggedRebookCompletionRef = useRef(false);
156320
157071
  const [redirectState] = useState(() => getBookingRedirectStateFromLocation(getBookingRedirectLocationSnapshot()));
156321
157072
  const [localMailingListNote, setLocalMailingListNote] = useState(null);
157073
+ const [localCustomerEmail, setLocalCustomerEmail] = useState(null);
156322
157074
  const showSpamProtection = render.hydration.spamProtectionEnabled ?? isSpamProtectionEnabled();
156323
157075
  const api = useBlockApi();
156324
157076
  const hasPortalAuth = api.config.auth.type === "bearer" || api.config.authOverrides?.portal?.type === "bearer";
@@ -156401,7 +157153,8 @@ var init_booking_form_client = __esmMin((() => {
156401
157153
  booking,
156402
157154
  bookingAnchorId,
156403
157155
  isPortalRebook,
156404
- setLocalMailingListNote
157156
+ setLocalMailingListNote,
157157
+ setLocalCustomerEmail
156405
157158
  });
156406
157159
  if (viewState.kind === "success") return /* @__PURE__ */ jsx(BookingSurface, {
156407
157160
  id: bookingAnchorId,
@@ -156410,7 +157163,9 @@ var init_booking_form_client = __esmMin((() => {
156410
157163
  successMessage: render.display.successMessage,
156411
157164
  resourceName: viewState.resourceName,
156412
157165
  redirectState,
156413
- localNote: localMailingListNote
157166
+ localNote: localMailingListNote,
157167
+ customerEmail: localCustomerEmail,
157168
+ demoEmailSuppressed: render.hydration.demoEmailSuppressed
156414
157169
  })
156415
157170
  });
156416
157171
  if (viewState.kind === "verifying") return /* @__PURE__ */ jsx(BookingSurface, {
@@ -156426,6 +157181,25 @@ var init_booking_form_client = __esmMin((() => {
156426
157181
  })
156427
157182
  })
156428
157183
  });
157184
+ if (viewState.kind === "timeout") return /* @__PURE__ */ jsxs(BookingSurface, {
157185
+ id: bookingAnchorId,
157186
+ className: render.display.className,
157187
+ children: [/* @__PURE__ */ jsx(FeedbackMessage, {
157188
+ tone: "info",
157189
+ className: "alert alert-info",
157190
+ role: "status",
157191
+ children: /* @__PURE__ */ jsx("p", {
157192
+ className: "ab-text",
157193
+ children: viewState.message
157194
+ })
157195
+ }), /* @__PURE__ */ jsx(ThemedButton, {
157196
+ type: "button",
157197
+ variant: "primary",
157198
+ size: "md",
157199
+ label: "Check again",
157200
+ onClick: verification.retry
157201
+ })]
157202
+ });
156429
157203
  return /* @__PURE__ */ jsxs(BookingSurface, {
156430
157204
  id: bookingAnchorId,
156431
157205
  className: render.display.className,
@@ -157176,7 +157950,7 @@ function recoverRegistrationError(action, handlers) {
157176
157950
  switch (action) {
157177
157951
  case "none": return;
157178
157952
  case "portal":
157179
- window.location.assign("/portal");
157953
+ window.location.assign(CUSTOMER_PORTAL_PATH);
157180
157954
  return;
157181
157955
  case "event":
157182
157956
  window.location.assign(window.location.pathname);
@@ -157201,7 +157975,9 @@ function recoverRegistrationError(action, handlers) {
157201
157975
  return;
157202
157976
  }
157203
157977
  }
157204
- var init_registrationErrorRecovery = __esmMin((() => {}));
157978
+ var init_registrationErrorRecovery = __esmMin((() => {
157979
+ init_demoPortalMagicLink();
157980
+ }));
157205
157981
  //#endregion
157206
157982
  //#region ../blocks/src/system/runtime/nodes/event-registration/validation.ts
157207
157983
  function createInitialRegistrationFormData() {
@@ -158021,6 +158797,10 @@ var init_event_registration_errors = __esmMin((() => {
158021
158797
  message: "The payment options for this event have changed. Please check the latest options before continuing.",
158022
158798
  action: "payment-options"
158023
158799
  },
158800
+ verificationFailed: {
158801
+ message: "We couldn’t confirm this request came from a person. Please refresh the page and try again.",
158802
+ action: "none"
158803
+ },
158024
158804
  idempotencyConflict: {
158025
158805
  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.",
158026
158806
  action: "portal"
@@ -158254,36 +159034,50 @@ var init_useWaitlistClaim = __esmMin((() => {
158254
159034
  }));
158255
159035
  //#endregion
158256
159036
  //#region ../blocks/src/system/runtime/hooks/usePaymentVerification.ts
158257
- /**
158258
- * Hook for polling payment status after Stripe redirects.
158259
- *
158260
- * Built on top of the generic usePolling hook, this provides
158261
- * a specialized interface for verifying event registration payments.
158262
- *
158263
- * @example
158264
- * ```tsx
158265
- * const verification = usePaymentVerification(
158266
- * step === 'verifying-payment' && attendeeId
158267
- * ? { transactionId: attendeeId }
158268
- * : null
158269
- * );
158270
- *
158271
- * useEffect(() => {
158272
- * if (verification.status === 'completed') {
158273
- * setStep('success');
158274
- * } else if (verification.status === 'failed') {
158275
- * setStep('payment-failed');
158276
- * } else if (verification.status === 'timeout') {
158277
- * setStep('verifying-timeout');
158278
- * }
158279
- * }, [verification.status]);
158280
- * ```
158281
- */
159037
+ function resolvePaymentPollingTarget(config) {
159038
+ const reference = config.reference;
159039
+ return reference.scope === "occurrence" ? {
159040
+ key: `occurrence:${reference.attendeeId}`,
159041
+ reference
159042
+ } : {
159043
+ key: `wholeSeries:${reference.registrationId}`,
159044
+ reference
159045
+ };
159046
+ }
159047
+ function createPaymentPollingConfig(api, settings) {
159048
+ if (settings === null) return null;
159049
+ const target = resolvePaymentPollingTarget(settings);
159050
+ return {
159051
+ restartKey: target.key,
159052
+ pollFn: () => api.getEventRegistrationStatus(target.reference),
159053
+ isComplete: (result) => result.paymentStatus === "completed" || result.paymentStatus === "not_required",
159054
+ isFailed: (result) => result.paymentStatus === "failed" || result.paymentStatus === "refunded",
159055
+ maxAttempts: settings.maxAttempts,
159056
+ interval: settings.pollInterval
159057
+ };
159058
+ }
159059
+ function getPaymentVerificationError(polling, paymentStatus) {
159060
+ if (polling.status === "timeout") return "Could not verify payment. If you were charged, please contact support.";
159061
+ if (polling.status === "failed" && paymentStatus !== null) return paymentStatus === "refunded" ? "Payment was refunded. Please contact support." : "Payment was declined. Please try again.";
159062
+ return polling.error?.message ?? null;
159063
+ }
159064
+ function mapPaymentVerificationResult(polling) {
159065
+ const paymentStatus = polling.result?.paymentStatus ?? null;
159066
+ return {
159067
+ status: polling.status,
159068
+ paymentStatus,
159069
+ attendeeStatus: polling.result?.attendeeStatus ?? null,
159070
+ waitlistPosition: polling.result?.waitlistPosition ?? null,
159071
+ error: getPaymentVerificationError(polling, paymentStatus),
159072
+ retry: polling.retry
159073
+ };
159074
+ }
158282
159075
  /**
158283
159076
  * Hook for polling payment status after Stripe redirects.
158284
159077
  *
158285
159078
  * Pass config to start polling, or null to stop/idle.
158286
- * The hook handles cleanup on unmount and config changes.
159079
+ * The hook handles cleanup on unmount and starts a new cycle when the status
159080
+ * reference changes.
158287
159081
  *
158288
159082
  * @param config - Configuration for polling, or null to stop
158289
159083
  * @returns Verification result with status, data, and retry function
@@ -158292,30 +159086,7 @@ function usePaymentVerification(config) {
158292
159086
  return usePaymentVerificationWithDeps(config, paymentVerificationDeps);
158293
159087
  }
158294
159088
  function usePaymentVerificationWithDeps(config, deps) {
158295
- const api = deps.useBlockApi();
158296
- const polling = usePolling(useMemo(() => {
158297
- if (!config) return null;
158298
- return {
158299
- pollFn: () => api.getEventRegistrationStatus(config.reference),
158300
- isComplete: (result) => result.paymentStatus === "completed" || result.paymentStatus === "not_required",
158301
- isFailed: (result) => result.paymentStatus === "failed" || result.paymentStatus === "refunded",
158302
- maxAttempts: config.maxAttempts,
158303
- interval: config.pollInterval
158304
- };
158305
- }, [api, config]));
158306
- const paymentStatus = polling.result?.paymentStatus ?? null;
158307
- let errorMessage = null;
158308
- if (polling.status === "timeout") errorMessage = "Could not verify payment. If you were charged, please contact support.";
158309
- else if (polling.status === "failed" && paymentStatus) errorMessage = paymentStatus === "refunded" ? "Payment was refunded. Please contact support." : "Payment was declined. Please try again.";
158310
- else if (polling.error) errorMessage = polling.error.message;
158311
- return {
158312
- status: polling.status,
158313
- paymentStatus,
158314
- attendeeStatus: polling.result?.attendeeStatus ?? null,
158315
- waitlistPosition: polling.result?.waitlistPosition ?? null,
158316
- error: errorMessage,
158317
- retry: polling.retry
158318
- };
159089
+ return mapPaymentVerificationResult(usePolling(createPaymentPollingConfig(deps.useBlockApi(), config)));
158319
159090
  }
158320
159091
  var paymentVerificationDeps;
158321
159092
  var init_usePaymentVerification = __esmMin((() => {
@@ -158706,17 +159477,6 @@ var init_registrationErrorPresentation = __esmMin((() => {
158706
159477
  function wantsMailingListSignup(options) {
158707
159478
  return options.mailingListSignup !== null && options.formData.mailingListOptIn === true;
158708
159479
  }
158709
- function createClientCommandId(cryptoSource = {
158710
- randomUUID: globalThis.crypto.randomUUID?.bind(globalThis.crypto),
158711
- getRandomValues: (bytes) => globalThis.crypto.getRandomValues(bytes)
158712
- }) {
158713
- if (cryptoSource.randomUUID) return cryptoSource.randomUUID();
158714
- const bytes = cryptoSource.getRandomValues(/* @__PURE__ */ new Uint8Array(16));
158715
- bytes[6] = (bytes[6] ?? 0) & 15 | 64;
158716
- bytes[8] = (bytes[8] ?? 0) & 63 | 128;
158717
- const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0"));
158718
- 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("")}`;
158719
- }
158720
159480
  function useEventRegistrationSubmit(options) {
158721
159481
  return useEventRegistrationSubmitWithDeps(options, eventRegistrationSubmitDeps);
158722
159482
  }
@@ -158795,6 +159555,7 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
158795
159555
  };
158796
159556
  }
158797
159557
  async function completeRegistrationSubmission(options, deps, prepared, result, submitOptions) {
159558
+ if (result.demoBookingPass) storeDemoBookingPass(options.formData.email, result.demoBookingPass);
158798
159559
  switch (result.kind) {
158799
159560
  case "paymentStatusRequired":
158800
159561
  options.setPaymentStatusRecovery({
@@ -158817,6 +159578,7 @@ async function completeRegistrationSubmission(options, deps, prepared, result, s
158817
159578
  status: "waitlist",
158818
159579
  title: "Added to waitlist",
158819
159580
  message: result.waitlist.message,
159581
+ emailFollowupMessage: result.waitlist.emailFollowupMessage,
158820
159582
  mailingListSignupNote: result.mailingListSignupNote
158821
159583
  });
158822
159584
  break;
@@ -158945,15 +159707,18 @@ function buildRegistrationRequest(options, prepared, method, passId, membershipI
158945
159707
  guests: prepared.guestsPayload
158946
159708
  };
158947
159709
  }
158948
- var eventRegistrationSubmitDeps;
159710
+ var createClientCommandId, eventRegistrationSubmitDeps;
158949
159711
  var init_useEventRegistrationSubmit = __esmMin((() => {
159712
+ init_src$2();
158950
159713
  init_client$1();
158951
159714
  init_shared();
158952
159715
  init_registrationErrorPresentation();
158953
159716
  init_constants();
158954
159717
  init_registrationDerivations();
158955
159718
  init_sessionStorage();
159719
+ init_demoBookingPassStorage();
158956
159720
  init_ticketSelectionLines();
159721
+ createClientCommandId = generateUuidV4;
158957
159722
  eventRegistrationSubmitDeps = {
158958
159723
  savePendingRegistration,
158959
159724
  createClientCommandId
@@ -159999,6 +160764,108 @@ var init_useEventCheckoutHandoffRestore = __esmMin((() => {
159999
160764
  };
160000
160765
  }));
160001
160766
  //#endregion
160767
+ //#region ../blocks/src/system/runtime/nodes/event-registration/EventRegistrationBookingLayer.tsx
160768
+ function BookingEntry(props) {
160769
+ const base = props.variant === "teaser" ? "er-booking-teaser" : "er-booking-bar";
160770
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
160771
+ className: `${base}__info`,
160772
+ children: [
160773
+ /* @__PURE__ */ jsx("span", {
160774
+ className: `${base}__title`,
160775
+ children: "Book this event"
160776
+ }),
160777
+ props.summary && /* @__PURE__ */ jsx("span", {
160778
+ className: `${base}__meta`,
160779
+ children: props.summary
160780
+ }),
160781
+ props.variant === "teaser" && props.ticketCurrency && props.ticketTypes.length > 0 ? /* @__PURE__ */ jsx("div", {
160782
+ className: "er-booking-teaser__tickets",
160783
+ children: props.ticketTypes.map((ticketType) => /* @__PURE__ */ jsxs("div", {
160784
+ className: "er-booking-teaser__ticket",
160785
+ children: [/* @__PURE__ */ jsx("span", {
160786
+ className: "er-booking-teaser__ticket-name",
160787
+ children: ticketType.name
160788
+ }), /* @__PURE__ */ jsx("strong", { children: props.formatTicketPrice(ticketType) })]
160789
+ }, ticketType.pricingOptionId))
160790
+ }) : null
160791
+ ]
160792
+ }), /* @__PURE__ */ jsx(ThemedButton, {
160793
+ type: "button",
160794
+ variant: props.buttonVariant,
160795
+ size: "md",
160796
+ extraClassName: `${base}__cta`,
160797
+ label: "Book now",
160798
+ onClick: props.onOpen
160799
+ })] });
160800
+ }
160801
+ function EventRegistrationBookingLayer(props) {
160802
+ const entryProps = {
160803
+ summary: [props.priceLabel, props.availabilityLabel].filter(Boolean).join(" · "),
160804
+ ticketTypes: props.ticketTypes,
160805
+ ticketCurrency: props.ticketCurrency,
160806
+ buttonVariant: props.buttonVariant,
160807
+ formatTicketPrice: props.formatTicketPrice,
160808
+ onOpen: props.onOpen
160809
+ };
160810
+ const floatingBar = !props.overlayOpen && props.isWizardStep ? /* @__PURE__ */ jsx("div", {
160811
+ className: "er-booking-bar",
160812
+ children: /* @__PURE__ */ jsx("div", {
160813
+ className: "er-booking-bar__inner",
160814
+ children: /* @__PURE__ */ jsx(BookingEntry, {
160815
+ ...entryProps,
160816
+ variant: "bar"
160817
+ })
160818
+ })
160819
+ }) : null;
160820
+ const floatingLayer = props.portalRoot ? createPortal(/* @__PURE__ */ jsx("div", {
160821
+ className: props.registrationRootClassName,
160822
+ "data-block": "event-registration",
160823
+ children: floatingBar
160824
+ }), props.portalRoot) : floatingBar;
160825
+ const overlayLayer = props.overlayOpen ? /* @__PURE__ */ jsx(ModalShell, {
160826
+ title: "Book this event",
160827
+ titleId: "event-registration-booking-title",
160828
+ onClose: props.onClose,
160829
+ portal: props.portalRoot != null,
160830
+ portalRoot: props.portalRoot,
160831
+ portalWrapperClassName: props.registrationRootClassName,
160832
+ portalWrapperProps: { "data-block": "event-registration" },
160833
+ overlayClassName: "er-booking-overlay",
160834
+ modalClassName: "er-booking-overlay__panel",
160835
+ renderHeader: ({ closeButtonRef, onClose, title, titleId }) => /* @__PURE__ */ jsxs("div", {
160836
+ className: "er-booking-overlay__header",
160837
+ children: [/* @__PURE__ */ jsx("h2", {
160838
+ className: "er-booking-overlay__title",
160839
+ id: titleId,
160840
+ children: title
160841
+ }), /* @__PURE__ */ jsx("button", {
160842
+ ref: closeButtonRef,
160843
+ type: "button",
160844
+ className: "er-booking-overlay__close",
160845
+ onClick: onClose,
160846
+ "aria-label": "Close booking",
160847
+ children: "×"
160848
+ })]
160849
+ }),
160850
+ children: props.overlaySurface
160851
+ }) : null;
160852
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
160853
+ props.isWizardStep && /* @__PURE__ */ jsx("div", {
160854
+ className: "er-booking-teaser",
160855
+ children: /* @__PURE__ */ jsx(BookingEntry, {
160856
+ ...entryProps,
160857
+ variant: "teaser"
160858
+ })
160859
+ }),
160860
+ floatingLayer,
160861
+ overlayLayer
160862
+ ] });
160863
+ }
160864
+ var init_EventRegistrationBookingLayer = __esmMin((() => {
160865
+ init_ModalShell();
160866
+ init_ThemedButton();
160867
+ }));
160868
+ //#endregion
160002
160869
  //#region ../blocks/src/system/runtime/nodes/shared/MagicLinkForm.state.ts
160003
160870
  function magicLinkSubmissionReducer(state, action) {
160004
160871
  switch (action.type) {
@@ -160008,6 +160875,14 @@ function magicLinkSubmissionReducer(state, action) {
160008
160875
  case "submit-succeeded":
160009
160876
  if (state.tag !== "submitting") return state;
160010
160877
  return { tag: "success" };
160878
+ case "submit-demo-link": return state.tag === "submitting" ? {
160879
+ tag: "demo_link",
160880
+ url: action.url
160881
+ } : state;
160882
+ case "submit-demo-refused": return state.tag === "submitting" ? {
160883
+ tag: "demo_refused",
160884
+ message: action.message
160885
+ } : state;
160011
160886
  case "submit-failed":
160012
160887
  if (state.tag !== "submitting") return state;
160013
160888
  return {
@@ -160031,114 +160906,175 @@ var init_MagicLinkForm_state = __esmMin((() => {
160031
160906
  }));
160032
160907
  //#endregion
160033
160908
  //#region ../blocks/src/system/runtime/nodes/shared/MagicLinkForm.tsx
160034
- function MagicLinkButton(props) {
160035
- return props.themed ? /* @__PURE__ */ jsx(ThemedButton, {
160036
- type: props.type,
160037
- variant: props.variant,
160038
- size: "md",
160039
- label: props.label,
160040
- disabled: props.disabled,
160041
- onClick: props.onClick
160042
- }) : /* @__PURE__ */ jsx("button", {
160043
- type: props.type,
160044
- className: props.className,
160045
- disabled: props.disabled,
160046
- onClick: props.onClick,
160047
- children: props.label
160048
- });
160049
- }
160050
- /**
160051
- * Reusable magic link login form.
160052
- * Used by Customer Portal and Event Registration blocks.
160053
- */
160054
- 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 }) {
160909
+ function MagicLinkForm(props) {
160055
160910
  const api = useBlockApi();
160056
- const [email, setEmail] = useState(initialEmail);
160057
- const [submissionState, dispatchSubmission] = useReducer(magicLinkSubmissionReducer, initialMagicLinkSubmissionState);
160058
- const loading = isMagicLinkSubmitting(submissionState);
160059
- const error = getMagicLinkError(submissionState);
160060
- const handleSubmit = async (e) => {
160061
- e.preventDefault();
160062
- const normalizedEmail = email.trim().toLowerCase();
160063
- if (!normalizedEmail || loading) return;
160064
- dispatchSubmission({ type: "submit-started" });
160065
- try {
160066
- const redirectTo = `${window.location.pathname}${window.location.search}${window.location.hash}`;
160067
- await api.sendMagicLink({
160068
- email: normalizedEmail,
160069
- redirectUrl: `${window.location.origin}/api/portal/callback?redirect_to=${encodeURIComponent(redirectTo)}`
160070
- });
160071
- dispatchSubmission({ type: "submit-succeeded" });
160072
- onSuccess?.();
160073
- } catch (err) {
160074
- console.error("Magic link error:", err);
160075
- dispatchSubmission({
160076
- type: "submit-failed",
160077
- message: getMagicLinkErrorMessage(err)
160078
- });
160079
- }
160080
- };
160081
- const handleReset = () => {
160082
- setEmail("");
160083
- dispatchSubmission({ type: "reset" });
160911
+ const [email, setEmail] = useState(props.initialEmail ?? "");
160912
+ const [state, dispatch] = useReducer(magicLinkSubmissionReducer, initialMagicLinkSubmissionState);
160913
+ const loading = isMagicLinkSubmitting(state);
160914
+ const handleSubmit = (event) => {
160915
+ submitMagicLink({
160916
+ event,
160917
+ email,
160918
+ loading,
160919
+ api,
160920
+ dispatch,
160921
+ onSuccess: props.onSuccess
160922
+ });
160084
160923
  };
160085
- if (submissionState.tag === "success") return /* @__PURE__ */ jsxs("div", {
160086
- className: `${classPrefix}-magic-link-success`,
160087
- children: [/* @__PURE__ */ jsx("p", {
160088
- className: `${classPrefix}-portal-auth-text ${classPrefix}-portal-auth-text--success`,
160089
- children: successMessage
160090
- }), !compact && /* @__PURE__ */ jsx(MagicLinkButton, {
160091
- themed: classPrefix === "cp",
160092
- type: "button",
160093
- variant: "secondary",
160094
- className: `${classPrefix}-modal-btn ${classPrefix}-modal-btn--secondary`,
160095
- label: "Try a different email",
160096
- onClick: handleReset
160097
- })]
160924
+ if (state.tag === "success" || state.tag === "demo_link") return /* @__PURE__ */ jsx(MagicLinkSuccess, {
160925
+ state,
160926
+ classPrefix: props.classPrefix ?? "er",
160927
+ compact: props.compact ?? false,
160928
+ successMessage: props.successMessage ?? "Check your email for a login link to sign in.",
160929
+ onReset: () => {
160930
+ setEmail("");
160931
+ dispatch({ type: "reset" });
160932
+ }
160098
160933
  });
160934
+ return /* @__PURE__ */ jsx(MagicLinkFormView, {
160935
+ classPrefix: props.classPrefix ?? "er",
160936
+ compact: props.compact ?? false,
160937
+ email,
160938
+ error: getMagicLinkError(state),
160939
+ loading,
160940
+ title: props.title,
160941
+ subtitle: props.subtitle,
160942
+ buttonText: props.buttonText ?? "Send login link",
160943
+ state,
160944
+ onEmailChange: setEmail,
160945
+ onSubmit: handleSubmit
160946
+ });
160947
+ }
160948
+ function MagicLinkFormView(props) {
160949
+ const classPrefix = props.classPrefix;
160099
160950
  return /* @__PURE__ */ jsxs("form", {
160100
- onSubmit: handleSubmit,
160951
+ onSubmit: props.onSubmit,
160101
160952
  className: `${classPrefix}-magic-link-form`,
160102
160953
  children: [
160103
- title && /* @__PURE__ */ jsx("h3", {
160954
+ props.title ? /* @__PURE__ */ jsx("h3", {
160104
160955
  className: `${classPrefix}-magic-link-title`,
160105
- children: title
160106
- }),
160107
- subtitle && /* @__PURE__ */ jsx("p", {
160956
+ children: props.title
160957
+ }) : null,
160958
+ props.subtitle ? /* @__PURE__ */ jsx("p", {
160108
160959
  className: `${classPrefix}-portal-auth-text`,
160109
- children: subtitle
160110
- }),
160960
+ children: props.subtitle
160961
+ }) : null,
160111
160962
  /* @__PURE__ */ jsx("input", {
160112
160963
  type: "email",
160113
160964
  className: classPrefix === "cp" ? "cp-input" : `${classPrefix}-form__input`,
160114
160965
  placeholder: "your@email.com",
160115
- value: email,
160116
- onChange: (e) => setEmail(e.target.value),
160117
- autoFocus: !compact,
160966
+ value: props.email,
160967
+ onChange: (event) => props.onEmailChange(event.target.value),
160968
+ autoFocus: !props.compact,
160118
160969
  required: true,
160119
- disabled: loading
160970
+ disabled: props.loading
160120
160971
  }),
160121
- error && /* @__PURE__ */ jsx("p", {
160122
- className: `${classPrefix}-portal-auth-text ${classPrefix}-portal-auth-text--error`,
160123
- children: error
160972
+ /* @__PURE__ */ jsx(MagicLinkFormFeedback, {
160973
+ classPrefix,
160974
+ error: props.error,
160975
+ state: props.state
160124
160976
  }),
160125
160977
  /* @__PURE__ */ jsx(MagicLinkButton, {
160126
160978
  themed: classPrefix === "cp",
160127
160979
  type: "submit",
160128
160980
  variant: "primary",
160129
160981
  className: `${classPrefix}-modal-btn`,
160130
- label: loading ? "Sending..." : buttonText,
160131
- disabled: !email.trim() || loading
160982
+ label: props.loading ? "Sending..." : props.buttonText,
160983
+ disabled: !props.email.trim() || props.loading
160132
160984
  })
160133
160985
  ]
160134
160986
  });
160135
160987
  }
160988
+ function MagicLinkFormFeedback(props) {
160989
+ if (!props.error && props.state.tag !== "demo_refused") return null;
160990
+ return /* @__PURE__ */ jsxs(Fragment, { children: [props.error ? /* @__PURE__ */ jsx("p", {
160991
+ className: `${props.classPrefix}-portal-auth-text ${props.classPrefix}-portal-auth-text--error`,
160992
+ children: props.error
160993
+ }) : null, props.state.tag === "demo_refused" ? /* @__PURE__ */ jsx("p", {
160994
+ role: "alert",
160995
+ className: `${props.classPrefix}-portal-auth-text ${props.classPrefix}-portal-auth-text--error`,
160996
+ children: props.state.message
160997
+ }) : null] });
160998
+ }
160999
+ function MagicLinkSuccess(props) {
161000
+ return /* @__PURE__ */ jsxs("div", {
161001
+ className: `${props.classPrefix}-magic-link-success`,
161002
+ children: [props.state.tag === "success" ? /* @__PURE__ */ jsx("p", {
161003
+ className: `${props.classPrefix}-portal-auth-text ${props.classPrefix}-portal-auth-text--success`,
161004
+ children: props.successMessage
161005
+ }) : /* @__PURE__ */ jsx(DemoPortalSignInLink, { url: props.state.url }), !props.compact ? /* @__PURE__ */ jsx(MagicLinkButton, {
161006
+ themed: props.classPrefix === "cp",
161007
+ type: "button",
161008
+ variant: "secondary",
161009
+ className: `${props.classPrefix}-modal-btn ${props.classPrefix}-modal-btn--secondary`,
161010
+ label: "Try a different email",
161011
+ onClick: props.onReset
161012
+ }) : null]
161013
+ });
161014
+ }
161015
+ function MagicLinkButton(props) {
161016
+ return props.themed ? /* @__PURE__ */ jsx(ThemedButton, {
161017
+ type: props.type,
161018
+ variant: props.variant,
161019
+ size: "md",
161020
+ label: props.label,
161021
+ disabled: props.disabled,
161022
+ onClick: props.onClick
161023
+ }) : /* @__PURE__ */ jsx("button", {
161024
+ type: props.type,
161025
+ className: props.className,
161026
+ disabled: props.disabled,
161027
+ onClick: props.onClick,
161028
+ children: props.label
161029
+ });
161030
+ }
161031
+ async function submitMagicLink(input) {
161032
+ input.event.preventDefault();
161033
+ const email = input.email.trim().toLowerCase();
161034
+ if (!email || input.loading) return;
161035
+ input.dispatch({ type: "submit-started" });
161036
+ try {
161037
+ const result = await requestDemoPortalMagicLink({
161038
+ email,
161039
+ redirectUrl: getMagicLinkRedirectUrl(),
161040
+ send: (request) => input.api.sendMagicLink(request)
161041
+ });
161042
+ input.dispatch(magicLinkActionForResult(result));
161043
+ if (result.kind === "email_sent") input.onSuccess?.();
161044
+ } catch (error) {
161045
+ console.error("Magic link error:", error);
161046
+ input.dispatch({
161047
+ type: "submit-failed",
161048
+ message: getMagicLinkErrorMessage(error)
161049
+ });
161050
+ }
161051
+ }
161052
+ function magicLinkActionForResult(result) {
161053
+ switch (result.kind) {
161054
+ case "email_sent": return { type: "submit-succeeded" };
161055
+ case "demo_sign_in": return {
161056
+ type: "submit-demo-link",
161057
+ url: result.url
161058
+ };
161059
+ case "refused": return {
161060
+ type: "submit-demo-refused",
161061
+ message: result.message
161062
+ };
161063
+ }
161064
+ }
161065
+ function getMagicLinkRedirectUrl() {
161066
+ const redirectTo = `${window.location.pathname}${window.location.search}${window.location.hash}`;
161067
+ return buildPortalCallbackUrl(window.location.origin, redirectTo);
161068
+ }
160136
161069
  function getMagicLinkErrorMessage(error) {
160137
- return error instanceof Error ? error.message : "Failed to send. Please try again.";
161070
+ return error instanceof BlockApiError ? error.message : "We couldn’t send the sign-in link. Please try again.";
160138
161071
  }
160139
161072
  var init_MagicLinkForm = __esmMin((() => {
160140
161073
  init_ThemedButton();
161074
+ init_DemoPortalSignInLink();
160141
161075
  init_api$1();
161076
+ init_client$1();
161077
+ init_demoPortalMagicLink();
160142
161078
  init_MagicLinkForm_state();
160143
161079
  }));
160144
161080
  //#endregion
@@ -160453,19 +161389,19 @@ function isExistingRegistrationBlocking$1(wizard) {
160453
161389
  }
160454
161390
  function resolveTicketSelectionContinueLabel(input) {
160455
161391
  if (input.isCheckingExistingRegistration) return "Checking registration...";
161392
+ if (input.ticketTypeSelectionBlocked) return "Choose a ticket";
160456
161393
  if (input.registrationOptionsPending) return "Checking availability...";
160457
161394
  if (input.registrationOptionsFailed) return "Availability unavailable";
160458
161395
  if (input.hasExistingRegistration) return resolveExistingRegistrationLabel(input.wizard);
160459
- if (input.ticketTypeSelectionBlocked) return "Choose a ticket";
160460
161396
  return "Continue";
160461
161397
  }
160462
161398
  function SelectTicketsActions(props) {
160463
161399
  const { wizard } = props;
160464
- const registrationOptionsPending = wizard.registrationOptionsState.tag === "idle" || wizard.registrationOptionsState.tag === "loading";
161400
+ const ticketTypeSelectionBlocked = wizard.ticketTypeSelectionRequired && !wizard.hasValidTicketSelection;
161401
+ const registrationOptionsPending = !ticketTypeSelectionBlocked && ["idle", "loading"].includes(wizard.registrationOptionsState.tag);
160465
161402
  const registrationOptionsFailed = wizard.registrationOptionsState.tag === "failed";
160466
161403
  const isCheckingExistingRegistration = wizard.portalAuthState === "authenticated" && wizard.existingRegistrationLoading;
160467
161404
  const hasExistingRegistration = isExistingRegistrationBlocking$1(wizard);
160468
- const ticketTypeSelectionBlocked = wizard.ticketTypeSelectionRequired && !wizard.hasValidTicketSelection;
160469
161405
  const isContinueDisabled = registrationOptionsPending || registrationOptionsFailed || isCheckingExistingRegistration || hasExistingRegistration || ticketTypeSelectionBlocked;
160470
161406
  const continueLabel = resolveTicketSelectionContinueLabel({
160471
161407
  wizard,
@@ -161962,8 +162898,9 @@ var SuccessStep;
161962
162898
  var init_SuccessStep = __esmMin((() => {
161963
162899
  init_shared();
161964
162900
  init_BookingMailingListNote();
161965
- SuccessStep = ({ title, message, variant = "success", mailingListSignupNote, context = "booking" }) => {
161966
- return /* @__PURE__ */ jsx(TerminalPanel, {
162901
+ init_DemoBookingPortalAccess();
162902
+ SuccessStep = ({ title, copy, variant = "success", mailingListSignupNote, context = "booking", demoEmailSuppressed = false, customerEmail }) => {
162903
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(TerminalPanel, {
161967
162904
  tone: variant === "info" ? "info" : "success",
161968
162905
  className: "er-center",
161969
162906
  iconClassName: "er-icon",
@@ -162003,12 +162940,18 @@ var init_SuccessStep = __esmMin((() => {
162003
162940
  })
162004
162941
  }),
162005
162942
  title: title ?? (variant === "info" ? "Already Registered" : "Registration Confirmed!"),
162006
- body: message,
162943
+ body: /* @__PURE__ */ jsx(BookingConfirmation, {
162944
+ demoEmailSuppressed,
162945
+ email: customerEmail,
162946
+ copy,
162947
+ messagePresentation: { kind: "plain" },
162948
+ noteClassName: "er-text--muted"
162949
+ }),
162007
162950
  secondaryBody: mailingListSignupNote ? /* @__PURE__ */ jsx(BookingMailingListNote, {
162008
162951
  note: mailingListSignupNote,
162009
162952
  context
162010
162953
  }) : void 0
162011
- });
162954
+ }) });
162012
162955
  };
162013
162956
  }));
162014
162957
  //#endregion
@@ -162505,7 +163448,8 @@ function EventRegistrationTerminalState(props) {
162505
163448
  }) : null;
162506
163449
  case "success": return /* @__PURE__ */ jsx(EventRegistrationSuccess, {
162507
163450
  wizard,
162508
- fallbackMessage: props.successMessage
163451
+ fallbackMessage: props.successMessage,
163452
+ demoEmailSuppressed: props.demoEmailSuppressed
162509
163453
  });
162510
163454
  case "error": return /* @__PURE__ */ jsx(ErrorStep, {
162511
163455
  message: wizard.errorMessage,
@@ -162522,12 +163466,15 @@ function EventRegistrationTerminalState(props) {
162522
163466
  function EventRegistrationSuccess(props) {
162523
163467
  const result = props.wizard.registrationResult;
162524
163468
  if (!result) return null;
163469
+ const copy = getRegistrationSuccessCopy(result, props.fallbackMessage);
162525
163470
  return /* @__PURE__ */ jsx(SuccessStep, {
162526
163471
  title: result.title,
162527
163472
  variant: result.variant,
162528
- message: result.message ?? props.fallbackMessage,
163473
+ copy,
162529
163474
  mailingListSignupNote: result.mailingListSignupNote,
162530
- context: result.status === "waitlist" ? "waitlist" : "booking"
163475
+ context: result.status === "waitlist" ? "waitlist" : "booking",
163476
+ demoEmailSuppressed: props.demoEmailSuppressed,
163477
+ customerEmail: props.wizard.formData.email
162531
163478
  });
162532
163479
  }
162533
163480
  function EventRegistrationSurface(props) {
@@ -162575,11 +163522,13 @@ function EventRegistrationSurface(props) {
162575
163522
  }), /* @__PURE__ */ jsx(EventRegistrationTerminalState, {
162576
163523
  wizard,
162577
163524
  supportEmail: props.supportEmail,
162578
- successMessage: props.successMessage
163525
+ successMessage: props.successMessage,
163526
+ demoEmailSuppressed: props.demoEmailSuppressed
162579
163527
  })]
162580
163528
  });
162581
163529
  }
162582
163530
  var init_EventRegistrationSurface = __esmMin((() => {
163531
+ init_booking_form_state();
162583
163532
  init_MagicLinkForm();
162584
163533
  init_spinner();
162585
163534
  init_ErrorStep();
@@ -162594,109 +163543,17 @@ var init_EventRegistrationSurface = __esmMin((() => {
162594
163543
  init_VerifyingTimeoutStep();
162595
163544
  }));
162596
163545
  //#endregion
162597
- //#region ../blocks/src/system/runtime/nodes/event-registration/EventRegistrationBookingLayer.tsx
162598
- function BookingEntry(props) {
162599
- const base = props.variant === "teaser" ? "er-booking-teaser" : "er-booking-bar";
162600
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
162601
- className: `${base}__info`,
162602
- children: [
162603
- /* @__PURE__ */ jsx("span", {
162604
- className: `${base}__title`,
162605
- children: "Book this event"
162606
- }),
162607
- props.summary && /* @__PURE__ */ jsx("span", {
162608
- className: `${base}__meta`,
162609
- children: props.summary
162610
- }),
162611
- props.variant === "teaser" && props.ticketCurrency && props.ticketTypes.length > 0 ? /* @__PURE__ */ jsx("div", {
162612
- className: "er-booking-teaser__tickets",
162613
- children: props.ticketTypes.map((ticketType) => /* @__PURE__ */ jsxs("div", {
162614
- className: "er-booking-teaser__ticket",
162615
- children: [/* @__PURE__ */ jsx("span", {
162616
- className: "er-booking-teaser__ticket-name",
162617
- children: ticketType.name
162618
- }), /* @__PURE__ */ jsx("strong", { children: props.formatTicketPrice(ticketType) })]
162619
- }, ticketType.pricingOptionId))
162620
- }) : null
162621
- ]
162622
- }), /* @__PURE__ */ jsx(ThemedButton, {
162623
- type: "button",
162624
- variant: props.buttonVariant,
162625
- size: "md",
162626
- extraClassName: `${base}__cta`,
162627
- label: "Book now",
162628
- onClick: props.onOpen
162629
- })] });
162630
- }
162631
- function EventRegistrationBookingLayer(props) {
162632
- const entryProps = {
162633
- summary: [props.priceLabel, props.availabilityLabel].filter(Boolean).join(" · "),
162634
- ticketTypes: props.ticketTypes,
162635
- ticketCurrency: props.ticketCurrency,
162636
- buttonVariant: props.buttonVariant,
162637
- formatTicketPrice: props.formatTicketPrice,
162638
- onOpen: props.onOpen
162639
- };
162640
- const floatingBar = !props.overlayOpen && props.isWizardStep ? /* @__PURE__ */ jsx("div", {
162641
- className: "er-booking-bar",
162642
- children: /* @__PURE__ */ jsx("div", {
162643
- className: "er-booking-bar__inner",
162644
- children: /* @__PURE__ */ jsx(BookingEntry, {
162645
- ...entryProps,
162646
- variant: "bar"
162647
- })
162648
- })
162649
- }) : null;
162650
- const floatingLayer = props.portalRoot ? createPortal(/* @__PURE__ */ jsx("div", {
162651
- className: props.registrationRootClassName,
162652
- "data-block": "event-registration",
162653
- children: floatingBar
162654
- }), props.portalRoot) : floatingBar;
162655
- const overlayLayer = props.overlayOpen ? /* @__PURE__ */ jsx(ModalShell, {
162656
- title: "Book this event",
162657
- titleId: "event-registration-booking-title",
162658
- onClose: props.onClose,
162659
- portal: props.portalRoot != null,
162660
- portalRoot: props.portalRoot,
162661
- portalWrapperClassName: props.registrationRootClassName,
162662
- portalWrapperProps: { "data-block": "event-registration" },
162663
- overlayClassName: "er-booking-overlay",
162664
- modalClassName: "er-booking-overlay__panel",
162665
- renderHeader: ({ closeButtonRef, onClose, title, titleId }) => /* @__PURE__ */ jsxs("div", {
162666
- className: "er-booking-overlay__header",
162667
- children: [/* @__PURE__ */ jsx("h2", {
162668
- className: "er-booking-overlay__title",
162669
- id: titleId,
162670
- children: title
162671
- }), /* @__PURE__ */ jsx("button", {
162672
- ref: closeButtonRef,
162673
- type: "button",
162674
- className: "er-booking-overlay__close",
162675
- onClick: onClose,
162676
- "aria-label": "Close booking",
162677
- children: "×"
162678
- })]
162679
- }),
162680
- children: props.overlaySurface
162681
- }) : null;
162682
- return /* @__PURE__ */ jsxs(Fragment, { children: [
162683
- props.isWizardStep && /* @__PURE__ */ jsx("div", {
162684
- className: "er-booking-teaser",
162685
- children: /* @__PURE__ */ jsx(BookingEntry, {
162686
- ...entryProps,
162687
- variant: "teaser"
162688
- })
162689
- }),
162690
- floatingLayer,
162691
- overlayLayer
162692
- ] });
162693
- }
162694
- var init_EventRegistrationBookingLayer = __esmMin((() => {
162695
- init_ModalShell();
162696
- init_ThemedButton();
162697
- }));
162698
- //#endregion
162699
163546
  //#region ../blocks/src/system/runtime/nodes/event-registration/EventRegistrationWizard.tsx
163547
+ function getPortalAuthCopy(waitlistClaimRequiresPortalLogin, loginMessage, demoEmailSuppressed) {
163548
+ const defaultCopy = waitlistClaimRequiresPortalLogin ? {
163549
+ ...EVENT_PORTAL_AUTH_COPY["waitlist-claim"],
163550
+ description: loginMessage ?? "Log in to continue with your waitlist claim."
163551
+ } : EVENT_PORTAL_AUTH_COPY.membership;
163552
+ return demoEmailSuppressed && !waitlistClaimRequiresPortalLogin ? {
163553
+ ...defaultCopy,
163554
+ buttonText: "Get a sign-in link →"
163555
+ } : defaultCopy;
163556
+ }
162700
163557
  function getActiveTicketTypes(event) {
162701
163558
  return event?.pricing.kind === "tiered" ? event.pricing.options.filter((ticketType) => ticketType.isActive).sort((left, right) => left.sortOrder - right.sortOrder).map(({ id, ...ticketType }) => ({
162702
163559
  ...ticketType,
@@ -162744,11 +163601,18 @@ function useConfiguredEventRegistrationWizard(props) {
162744
163601
  });
162745
163602
  }
162746
163603
  function EventRegistrationWizard(props) {
162747
- 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;
163604
+ const wizard = useConfiguredEventRegistrationWizard(props);
163605
+ return /* @__PURE__ */ jsx(EventRegistrationWizardView, {
163606
+ ...props,
163607
+ wizard
163608
+ });
163609
+ }
163610
+ function EventRegistrationWizardView(viewProps) {
163611
+ const { wizard, ...props } = viewProps;
163612
+ const { showVenue = true, showCapacity = true, successMessage, buttonText = "Complete Registration", buttonVariant = "primary", className, spamProtectionEnabled, supportEmail } = props;
162748
163613
  const showSpamProtection = spamProtectionEnabled ?? isSpamProtectionEnabled();
162749
163614
  const registrationRootClassName = `event-registration ${className || ""}`;
162750
163615
  const registrationRootRef = React.useRef(null);
162751
- const wizard = useConfiguredEventRegistrationWizard(props);
162752
163616
  useEventCheckoutHandoffRestore(wizard.step === "redirecting");
162753
163617
  const [bookingOverlayOpen, setBookingOverlayOpen] = useState(false);
162754
163618
  const [floatingPortalRoot, setFloatingPortalRoot] = useState(null);
@@ -162814,10 +163678,7 @@ function EventRegistrationWizard(props) {
162814
163678
  const summaryPriceLabel = summaryEvent ? formatEventPriceDisplay(summaryEvent.pricing) : null;
162815
163679
  const summaryAvailabilityLabel = getAvailabilityLabel(summaryEvent, wizard.selectedAttendanceMode);
162816
163680
  const waitlistClaimRequiresPortalLogin = wizard.waitlistClaim.requiresPortalLogin && wizard.portalAuthState !== "authenticated" && wizard.portalAuthState !== "checking";
162817
- const portalAuthCopy = waitlistClaimRequiresPortalLogin ? {
162818
- ...EVENT_PORTAL_AUTH_COPY["waitlist-claim"],
162819
- description: wizard.waitlistClaim.loginMessage ?? "Log in to continue with your waitlist claim."
162820
- } : EVENT_PORTAL_AUTH_COPY.membership;
163681
+ const portalAuthCopy = getPortalAuthCopy(waitlistClaimRequiresPortalLogin, wizard.waitlistClaim.loginMessage, props.demoEmailSuppressed);
162821
163682
  const showPortalAuthPrompt = waitlistClaimRequiresPortalLogin || wizard.step === "select-tickets" && wizard.portalAuthState !== "authenticated" && wizard.portalAuthState !== "checking" && summaryEventPricingType !== "free";
162822
163683
  const renderRegistrationSurface = (variant) => /* @__PURE__ */ jsx(EventRegistrationSurface, {
162823
163684
  variant,
@@ -162834,7 +163695,8 @@ function EventRegistrationWizard(props) {
162834
163695
  buttonText,
162835
163696
  buttonVariant,
162836
163697
  supportEmail,
162837
- successMessage
163698
+ successMessage,
163699
+ demoEmailSuppressed: props.demoEmailSuppressed
162838
163700
  });
162839
163701
  const isEmbedded = (className ?? "").includes("event-registration--embedded");
162840
163702
  const overlayEnabled = props.overlayEnabled === true;
@@ -162882,8 +163744,8 @@ var init_EventRegistrationWizard = __esmMin((() => {
162882
163744
  init_themePortalRoot();
162883
163745
  init_constants();
162884
163746
  init_useEventCheckoutHandoffRestore();
162885
- init_EventRegistrationSurface();
162886
163747
  init_EventRegistrationBookingLayer();
163748
+ init_EventRegistrationSurface();
162887
163749
  EVENT_PORTAL_AUTH_COPY = {
162888
163750
  membership: {
162889
163751
  title: "Already have an account?",
@@ -163191,7 +164053,7 @@ var init_event_registration_client = __esmMin((() => {
163191
164053
  * Loads Leaflet CSS/JS from CDN to avoid bundling in the blocks package.
163192
164054
  */
163193
164055
  function isLeafletApi(value) {
163194
- if (!isRecord$27(value)) return false;
164056
+ if (!isRecord$29(value)) return false;
163195
164057
  return typeof value.map === "function" && typeof value.tileLayer === "function" && typeof value.marker === "function";
163196
164058
  }
163197
164059
  function loadLeaflet() {
@@ -165733,6 +166595,9 @@ var init_events = __esmMin((() => {
165733
166595
  init_EventCalendar_client();
165734
166596
  init_EventCombined_client();
165735
166597
  init_EventListing_client();
166598
+ init_EventCard_client();
166599
+ init_eventCardPresentations();
166600
+ init_EventListing_interactive();
165736
166601
  }));
165737
166602
  //#endregion
165738
166603
  //#region src/rendering/islands/enhancers/eventRegistration.tsx
@@ -166494,14 +167359,26 @@ function CartController(props) {
166494
167359
  })] })
166495
167360
  });
166496
167361
  }
167362
+ function ShopCheckoutNoticeView(props) {
167363
+ if (!props.notice) return null;
167364
+ const succeeded = props.notice === "success";
167365
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(FeedbackMessage, {
167366
+ tone: succeeded ? "success" : "warning",
167367
+ className: "rb-mb-4 rb-rounded-xl rb-border rb-p-4",
167368
+ role: "status",
167369
+ children: succeeded ? "Payment successful." : "Checkout cancelled."
167370
+ }), succeeded && props.demoEmailSuppressed ? /* @__PURE__ */ jsx(DemoBookingPortalAccess, { email: props.email }) : null] });
167371
+ }
166497
167372
  function CheckoutController(props) {
166498
167373
  const api = useBlockApi();
166499
167374
  const cart = useCommerceCart(api.config.siteId);
166500
167375
  const [state, dispatch] = React$1.useReducer(shopCheckoutReducer, initialShopCheckoutState);
167376
+ const [checkoutReturnEmail, setCheckoutReturnEmail] = React$1.useState(null);
166501
167377
  const [discountApply, dispatchDiscountApply] = React$1.useReducer(discountApplyReducer, initialDiscountApplyState);
166502
167378
  React$1.useEffect(() => {
166503
167379
  const checkout = consumeSearchParam("checkout");
166504
167380
  if (checkout === "success") {
167381
+ setCheckoutReturnEmail(readDemoBookingCheckoutReturnEmail());
166505
167382
  cart.clear();
166506
167383
  dispatch({
166507
167384
  type: "setNotice",
@@ -166561,6 +167438,7 @@ function CheckoutController(props) {
166561
167438
  return;
166562
167439
  }
166563
167440
  const result = await api.createUnifiedCheckout(command.value);
167441
+ if (result.demoBookingPass) storeDemoBookingCheckoutReturn(state.form.email, result.demoBookingPass);
166564
167442
  if (result.type === "redirect") {
166565
167443
  window.location.href = result.checkoutUrl;
166566
167444
  return;
@@ -166579,12 +167457,11 @@ function CheckoutController(props) {
166579
167457
  };
166580
167458
  return /* @__PURE__ */ jsx(CheckoutShellView, {
166581
167459
  display,
166582
- notice: state.notice ? /* @__PURE__ */ jsx(FeedbackMessage, {
166583
- tone: state.notice === "success" ? "success" : "warning",
166584
- className: "rb-mb-4 rb-rounded-xl rb-border rb-p-4",
166585
- role: "status",
166586
- children: state.notice === "success" ? "Payment successful." : "Checkout cancelled."
166587
- }) : null,
167460
+ notice: /* @__PURE__ */ jsx(ShopCheckoutNoticeView, {
167461
+ notice: state.notice,
167462
+ demoEmailSuppressed: props.render.hydration.demoEmailSuppressed === true,
167463
+ email: checkoutReturnEmail
167464
+ }),
166588
167465
  body: /* @__PURE__ */ jsxs("form", {
166589
167466
  className: "rb-flex rb-flex-col rb-gap-4",
166590
167467
  onSubmit: handleSubmit,
@@ -166682,6 +167559,8 @@ var init_shop_commerce = __esmMin((() => {
166682
167559
  init_display();
166683
167560
  init_view$1();
166684
167561
  init_shop_commerce_store();
167562
+ init_DemoBookingPortalAccess();
167563
+ init_demoBookingPassStorage();
166685
167564
  init_shop_commerce_shared();
166686
167565
  init_shop_add_feedback();
166687
167566
  init_shop_checkout_state();
@@ -166832,6 +167711,109 @@ var init_shop_state = __esmMin((() => {
166832
167711
  }));
166833
167712
  //#endregion
166834
167713
  //#region ../blocks/src/system/runtime/nodes/shop.client.tsx
167714
+ function ShopCheckoutReturnNotice(props) {
167715
+ const succeeded = props.notice.kind === "success";
167716
+ const copy = getShopSuccessCopy(succeeded ? "success" : "cancelled");
167717
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(TerminalPanel, {
167718
+ tone: succeeded ? "success" : "warning",
167719
+ className: "shop__return",
167720
+ titleClassName: "shop__return-title",
167721
+ bodyClassName: "shop__return-text",
167722
+ icon: /* @__PURE__ */ jsx(StateIcon, {
167723
+ variant: succeeded ? "success" : "warning",
167724
+ children: succeeded ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CrossIcon, {})
167725
+ }),
167726
+ title: succeeded ? "Payment successful" : "Payment cancelled",
167727
+ body: /* @__PURE__ */ jsx(BookingConfirmation, {
167728
+ demoEmailSuppressed: succeeded && props.demoEmailSuppressed,
167729
+ email: props.email,
167730
+ copy,
167731
+ messagePresentation: { kind: "plain" },
167732
+ noteClassName: "shop__return-text"
167733
+ }),
167734
+ actions: /* @__PURE__ */ jsx(ThemedButton, {
167735
+ type: "button",
167736
+ variant: "secondary",
167737
+ size: "sm",
167738
+ extraClassName: "shop__return-dismiss",
167739
+ label: "Dismiss",
167740
+ onClick: props.onDismiss
167741
+ })
167742
+ }) });
167743
+ }
167744
+ function handleShopCheckoutResult(input) {
167745
+ switch (input.result.type) {
167746
+ case "duplicate_membership_warning":
167747
+ input.dispatch({
167748
+ type: "submitDuplicateWarning",
167749
+ warning: input.result
167750
+ });
167751
+ return;
167752
+ case "bypassed":
167753
+ if (input.result.demoBookingPass) storeDemoBookingCheckoutReturn(input.checkout.form.email, input.result.demoBookingPass);
167754
+ window.location.href = input.successUrl;
167755
+ return;
167756
+ case "redirect":
167757
+ if (input.result.demoBookingPass) storeDemoBookingCheckoutReturn(input.checkout.form.email, input.result.demoBookingPass);
167758
+ window.location.href = input.result.checkoutUrl;
167759
+ return;
167760
+ default: return assertNever$20(input.result);
167761
+ }
167762
+ }
167763
+ function buildDirectShopCheckoutPlan(input) {
167764
+ const successUrl = new URL(input.currentUrl);
167765
+ successUrl.searchParams.set("checkout", "success");
167766
+ successUrl.searchParams.set("product", input.checkout.item.product.id);
167767
+ const cancelUrl = new URL(input.currentUrl);
167768
+ cancelUrl.searchParams.set("checkout", "cancelled");
167769
+ const form = {
167770
+ ...input.checkout.form,
167771
+ discountCode: input.manualCodeEntryAllowed ? getAppliedDiscountCode(input.discountApply) ?? "" : ""
167772
+ };
167773
+ return {
167774
+ successUrl: successUrl.toString(),
167775
+ command: planDirectShopCheckoutRequest({
167776
+ productType: input.checkout.item.productType,
167777
+ productId: input.checkout.item.product.id,
167778
+ form,
167779
+ successUrl: successUrl.toString(),
167780
+ cancelUrl: cancelUrl.toString(),
167781
+ confirmDuplicate: input.confirmDuplicate
167782
+ })
167783
+ };
167784
+ }
167785
+ async function submitDirectShopCheckout(input) {
167786
+ const checkout = input.checkout;
167787
+ if (!checkout) return;
167788
+ input.dispatch({ type: "submitStarted" });
167789
+ try {
167790
+ const attempt = buildDirectShopCheckoutPlan({
167791
+ checkout,
167792
+ currentUrl: window.location.href,
167793
+ confirmDuplicate: input.confirmDuplicate,
167794
+ discountApply: input.discountApply,
167795
+ manualCodeEntryAllowed: input.manualCodeEntryAllowed
167796
+ });
167797
+ if (!attempt.command.ok) {
167798
+ input.dispatch({
167799
+ type: "submitFailed",
167800
+ error: attempt.command.error.message
167801
+ });
167802
+ return;
167803
+ }
167804
+ handleShopCheckoutResult({
167805
+ result: await input.api.createShopCheckout(attempt.command.value),
167806
+ checkout,
167807
+ successUrl: attempt.successUrl,
167808
+ dispatch: input.dispatch
167809
+ });
167810
+ } catch (error) {
167811
+ input.dispatch({
167812
+ type: "submitFailed",
167813
+ error: error instanceof Error ? error.message : "An error occurred"
167814
+ });
167815
+ }
167816
+ }
166835
167817
  function ShopClient(props) {
166836
167818
  return /* @__PURE__ */ jsx(PassesMembershipsController, { render: props.render });
166837
167819
  }
@@ -166881,6 +167863,7 @@ function PassesMembershipsController({ render }) {
166881
167863
  const [discountApply, dispatchDiscountApply] = React.useReducer(discountApplyReducer, initialDiscountApplyState);
166882
167864
  const passAddFeedback = useTransientShopAddFeedback();
166883
167865
  const [modalPortalRoot, setModalPortalRoot] = useState(null);
167866
+ const [checkoutReturnEmail, setCheckoutReturnEmail] = useState(null);
166884
167867
  const shopRootRef = useRef(null);
166885
167868
  const emailInputRef = useRef(null);
166886
167869
  const focusedCheckoutKeyRef = useRef(null);
@@ -166975,6 +167958,7 @@ function PassesMembershipsController({ render }) {
166975
167958
  if (!checkoutStatus) return;
166976
167959
  scrollToBlock(SHOP_ANCHOR_ID);
166977
167960
  if (checkoutStatus === "success") {
167961
+ setCheckoutReturnEmail(readDemoBookingCheckoutReturnEmail());
166978
167962
  dispatch({
166979
167963
  type: "setReturnNotice",
166980
167964
  notice: { kind: "success" }
@@ -166986,58 +167970,14 @@ function PassesMembershipsController({ render }) {
166986
167970
  notice: { kind: "cancelled" }
166987
167971
  });
166988
167972
  }, []);
166989
- const submitCheckout = useCallback(async (confirmDuplicate = false) => {
166990
- if (!checkout) return;
166991
- dispatch({ type: "submitStarted" });
166992
- try {
166993
- const currentUrl = window.location.href;
166994
- const successUrl = new URL(currentUrl);
166995
- successUrl.searchParams.set("checkout", "success");
166996
- successUrl.searchParams.set("product", checkout.item.product.id);
166997
- const cancelUrl = new URL(currentUrl);
166998
- cancelUrl.searchParams.set("checkout", "cancelled");
166999
- const form = {
167000
- ...checkout.form,
167001
- discountCode: discountUi.manualCodeEntryAllowed ? getAppliedDiscountCode(discountApply) ?? "" : ""
167002
- };
167003
- const command = planDirectShopCheckoutRequest({
167004
- productType: checkout.item.productType,
167005
- productId: checkout.item.product.id,
167006
- form,
167007
- successUrl: successUrl.toString(),
167008
- cancelUrl: cancelUrl.toString(),
167009
- confirmDuplicate
167010
- });
167011
- if (!command.ok) {
167012
- dispatch({
167013
- type: "submitFailed",
167014
- error: command.error.message
167015
- });
167016
- return;
167017
- }
167018
- const result = await api.createShopCheckout(command.value);
167019
- switch (result.type) {
167020
- case "duplicate_membership_warning":
167021
- dispatch({
167022
- type: "submitDuplicateWarning",
167023
- warning: result
167024
- });
167025
- return;
167026
- case "bypassed":
167027
- window.location.href = successUrl.toString();
167028
- return;
167029
- case "redirect":
167030
- window.location.href = result.checkoutUrl;
167031
- return;
167032
- default: return assertNever$20(result);
167033
- }
167034
- } catch (submitError) {
167035
- dispatch({
167036
- type: "submitFailed",
167037
- error: submitError instanceof Error ? submitError.message : "An error occurred"
167038
- });
167039
- }
167040
- }, [
167973
+ const submitCheckout = useCallback((confirmDuplicate = false) => submitDirectShopCheckout({
167974
+ checkout,
167975
+ confirmDuplicate,
167976
+ api,
167977
+ discountApply,
167978
+ manualCodeEntryAllowed: discountUi.manualCodeEntryAllowed,
167979
+ dispatch
167980
+ }), [
167041
167981
  api,
167042
167982
  checkout,
167043
167983
  discountApply,
@@ -167064,26 +168004,12 @@ function PassesMembershipsController({ render }) {
167064
168004
  ref: shopRootRef,
167065
168005
  children: /* @__PURE__ */ jsx(PassesMembershipsSectionView, {
167066
168006
  display,
167067
- beforeContent: /* @__PURE__ */ jsx(Fragment, { children: state.returnNotice ? /* @__PURE__ */ jsx(TerminalPanel, {
167068
- tone: state.returnNotice.kind === "success" ? "success" : "warning",
167069
- className: "shop__return",
167070
- titleClassName: "shop__return-title",
167071
- bodyClassName: "shop__return-text",
167072
- icon: /* @__PURE__ */ jsx(StateIcon, {
167073
- variant: state.returnNotice.kind === "success" ? "success" : "warning",
167074
- children: state.returnNotice.kind === "success" ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CrossIcon, {})
167075
- }),
167076
- title: state.returnNotice.kind === "success" ? "Payment successful" : "Payment cancelled",
167077
- body: state.returnNotice.kind === "success" ? "Check your email for confirmation." : "You can try again whenever you’re ready.",
167078
- actions: /* @__PURE__ */ jsx(ThemedButton, {
167079
- type: "button",
167080
- variant: "secondary",
167081
- size: "sm",
167082
- extraClassName: "shop__return-dismiss",
167083
- label: "Dismiss",
167084
- onClick: () => dispatch({ type: "clearReturnNotice" })
167085
- })
167086
- }) : null }),
168007
+ beforeContent: state.returnNotice ? /* @__PURE__ */ jsx(ShopCheckoutReturnNotice, {
168008
+ notice: state.returnNotice,
168009
+ demoEmailSuppressed: hydration.demoEmailSuppressed === true,
168010
+ email: checkoutReturnEmail,
168011
+ onDismiss: () => dispatch({ type: "clearReturnNotice" })
168012
+ }) : null,
167087
168013
  passCards: display.passes.map((passDisplay) => {
167088
168014
  return /* @__PURE__ */ jsx(PassProductCard, {
167089
168015
  display: passDisplay,
@@ -167303,6 +168229,9 @@ var init_shop_client = __esmMin((() => {
167303
168229
  init_shop_checkout_form();
167304
168230
  init_DiscountCodeDisclosure();
167305
168231
  init_useDiscountApply();
168232
+ init_DemoBookingPortalAccess();
168233
+ init_booking_form_state();
168234
+ init_demoBookingPassStorage();
167306
168235
  SHOP_ANCHOR_ID = "shop";
167307
168236
  }));
167308
168237
  //#endregion
@@ -168268,6 +169197,7 @@ function buildPageRouteRenderContext(dataContext) {
168268
169197
  }
168269
169198
  function buildPageIdentityRenderContext(dataContext) {
168270
169199
  return {
169200
+ demoEmailSuppressed: dataContext.demoEmailSuppressed,
168271
169201
  siteName: dataContext.siteName,
168272
169202
  pathname: dataContext.pathname
168273
169203
  };
@@ -168487,7 +169417,7 @@ var SimpleCache = class {
168487
169417
  * 1. This constant
168488
169418
  * 2. The "version" field in package.json
168489
169419
  */
168490
- const SDK_VERSION = "0.147.0";
169420
+ const SDK_VERSION = "0.148.0";
168491
169421
  //#endregion
168492
169422
  //#region src/client/error.ts
168493
169423
  let _Symbol$for;