@riverbankcms/sdk 0.138.0 → 0.140.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 (293) hide show
  1. package/README.md +12 -16
  2. package/dist/{PreviewEditorSidebar-BVPur_CU.mjs → PreviewEditorSidebar-CUyTzd5z.mjs} +4 -4
  3. package/dist/{PreviewEditorUI-DLhWX8oh.mjs → PreviewEditorUI-Agkw4v5i.mjs} +3 -3
  4. package/dist/{PreviewQueryProvider-BguJY1SW.mjs → PreviewQueryProvider-CN0ewic5.mjs} +1 -1
  5. package/dist/{SdkPreviewModeRuntime-Tda6qw4z.mjs → SdkPreviewModeRuntime-DdbeAdS8.mjs} +62 -28
  6. package/dist/{SiteChromeCustomizeContext-BHFgMjde.mjs → SiteChromeCustomizeContext-CqGOz-Kv.mjs} +8467 -5616
  7. package/dist/_dts/ai/src/contracts/proposals.d.ts +264 -495
  8. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +221 -242
  9. package/dist/_dts/api/src/accessAdmin.d.ts +74 -104
  10. package/dist/_dts/api/src/aiEndpoints.d.ts +5 -1
  11. package/dist/_dts/api/src/authSubmission.d.ts +46 -0
  12. package/dist/_dts/api/src/billing.d.ts +18 -7
  13. package/dist/_dts/api/src/billingEndpointDefinitions.d.ts +23 -0
  14. package/dist/_dts/api/src/billingEndpointTypes.d.ts +26 -0
  15. package/dist/_dts/api/src/blocks.d.ts +2 -0
  16. package/dist/_dts/api/src/bookingRecords.d.ts +1 -2
  17. package/dist/_dts/api/src/commercePortalEndpoints.d.ts +8 -1
  18. package/dist/_dts/api/src/communications.d.ts +0 -1
  19. package/dist/_dts/api/src/contentRuntime.d.ts +16 -4
  20. package/dist/_dts/api/src/endpoints.d.ts +275 -167
  21. package/dist/_dts/api/src/event-destination-policy.d.ts +2 -1
  22. package/dist/_dts/api/src/footerSettings.d.ts +10 -10
  23. package/dist/_dts/api/src/index.d.ts +11 -10
  24. package/dist/_dts/api/src/indexCoreTypes.d.ts +1 -1
  25. package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -1
  26. package/dist/_dts/api/src/mailchimpIntegration.d.ts +2 -59
  27. package/dist/_dts/api/src/mailingListIntegration.d.ts +123 -0
  28. package/dist/_dts/api/src/navigation/dashboardSettingsNav.d.ts +1 -1
  29. package/dist/_dts/api/src/navigation/locations.d.ts +1 -0
  30. package/dist/_dts/api/src/navigation/types.d.ts +1 -1
  31. package/dist/_dts/api/src/navigation.d.ts +1 -26
  32. package/dist/_dts/api/src/newsletterEndpointDefinitions.d.ts +109 -2
  33. package/dist/_dts/api/src/onboarding/confirmationResend.d.ts +25 -0
  34. package/dist/_dts/api/src/onboarding/surfaceData.d.ts +185 -0
  35. package/dist/_dts/api/src/privacyPolicy.d.ts +74 -2
  36. package/dist/_dts/api/src/publicBookingAvailabilityEndpointDefinitions.d.ts +14 -6
  37. package/dist/_dts/api/src/publicEventEndpointDefinitions.d.ts +1 -1
  38. package/dist/_dts/api/src/publicExperience/commerceEndpoints.d.ts +1 -0
  39. package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +11 -3
  40. package/dist/_dts/api/src/publicExperience/newsletterEndpoints.d.ts +2 -4
  41. package/dist/_dts/api/src/publicExperience/sharedTypes.d.ts +9 -49
  42. package/dist/_dts/api/src/publicOnboardingAttemptEndpointDefinitions.d.ts +65 -0
  43. package/dist/_dts/api/src/publicReadEndpointDefinitions.d.ts +73 -0
  44. package/dist/_dts/api/src/saveOutcome.d.ts +20 -0
  45. package/dist/_dts/api/src/schemas/site-api-keys.d.ts +1 -1
  46. package/dist/_dts/api/src/sdkContracts.d.ts +5 -32
  47. package/dist/_dts/api/src/sdkPushContracts.d.ts +18 -0
  48. package/dist/_dts/api/src/sdkThemeWire.d.ts +46 -46
  49. package/dist/_dts/api/src/settings/permissions.d.ts +12 -0
  50. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +9 -34
  51. package/dist/_dts/api/src/siteOnboarding.d.ts +84 -228
  52. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +3 -13
  53. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +3 -1
  54. package/dist/_dts/api/src/siteSettings.d.ts +38 -6
  55. package/dist/_dts/api/src/types.d.ts +78 -77
  56. package/dist/_dts/api/src/wholeSeriesRuns.d.ts +2 -37
  57. package/dist/_dts/billing/src/membership/index.d.ts +17 -7
  58. package/dist/_dts/billing/src/plans/display.d.ts +15 -0
  59. package/dist/_dts/billing/src/plans/registry.d.ts +2 -0
  60. package/dist/_dts/billing/src/plans/standing.d.ts +19 -0
  61. package/dist/_dts/billing/src/plans/types.d.ts +4 -7
  62. package/dist/_dts/billing/src/site-arrangements.d.ts +14 -3
  63. package/dist/_dts/billing/src/subscriptions/evidence.d.ts +12 -0
  64. package/dist/_dts/billing/src/subscriptions/standingEvidence.d.ts +31 -0
  65. package/dist/_dts/billing/src/subscriptions/store.d.ts +23 -5
  66. package/dist/_dts/blocks/src/PageRenderer.d.ts +6 -15
  67. package/dist/_dts/blocks/src/client.d.ts +1 -1
  68. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +48 -20
  69. package/dist/_dts/blocks/src/pageRenderAdmission.d.ts +2 -0
  70. package/dist/_dts/blocks/src/pageRendererContracts.d.ts +9 -0
  71. package/dist/_dts/blocks/src/pageRenderingMode.d.ts +12 -6
  72. package/dist/_dts/blocks/src/portal/types.d.ts +2 -4
  73. package/dist/_dts/blocks/src/portal/waitlist-types.d.ts +35 -0
  74. package/dist/_dts/blocks/src/system/blocks/appointment-services.d.ts +11 -0
  75. package/dist/_dts/blocks/src/system/blocks/contact-newsletter.d.ts +39 -66
  76. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +2 -0
  77. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +42 -0
  78. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +4 -0
  79. package/dist/_dts/blocks/src/system/blocks/newsletter-signup.d.ts +39 -114
  80. package/dist/_dts/blocks/src/system/blocks/offerings-preview/catalogue.d.ts +18 -0
  81. package/dist/_dts/blocks/src/system/blocks/offerings-preview/fields.d.ts +2 -0
  82. package/dist/_dts/blocks/src/system/blocks/offerings-preview/index.d.ts +4 -0
  83. package/dist/_dts/blocks/src/system/blocks/site-footer-runtime.d.ts +7 -13
  84. package/dist/_dts/blocks/src/system/constants/blockKinds.d.ts +1 -1
  85. package/dist/_dts/blocks/src/system/data/index.d.ts +4 -4
  86. package/dist/_dts/blocks/src/system/data/loaderEndpoints.d.ts +1 -1
  87. package/dist/_dts/blocks/src/system/data/prefetchBlockData.d.ts +2 -1
  88. package/dist/_dts/blocks/src/system/data/publicLoaderCachePolicy.d.ts +2 -74
  89. package/dist/_dts/blocks/src/system/data/types.d.ts +9 -0
  90. package/dist/_dts/blocks/src/system/fragments/library/newsletterForm.d.ts +33 -100
  91. package/dist/_dts/blocks/src/system/registry.d.ts +1 -0
  92. package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +0 -28
  93. package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
  94. package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +7 -3
  95. package/dist/_dts/blocks/src/system/runtime/api/types/newsletter.d.ts +5 -15
  96. package/dist/_dts/blocks/src/system/runtime/api/types/portal.d.ts +1 -1
  97. package/dist/_dts/blocks/src/system/runtime/api/types/waitlist-claims.d.ts +7 -2
  98. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +78 -30
  99. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +39 -15
  100. package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.d.ts +3 -0
  101. package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.state.d.ts +1 -1
  102. package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarToday.d.ts +22 -0
  103. package/dist/_dts/blocks/src/system/runtime/nodes/appointment-services.d.ts +94 -0
  104. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationSurface.d.ts +1 -2
  105. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/TicketSelectionStep.d.ts +2 -0
  106. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/checkoutRecovery.d.ts +14 -0
  107. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventSourceRecovery.d.ts +56 -0
  108. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +6 -8
  109. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useCheckoutRecovery.d.ts +8 -0
  110. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +8 -7
  111. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +12 -2
  112. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventSourceRecovery.d.ts +18 -0
  113. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.client.d.ts +1 -1
  114. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +24 -7
  115. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.server.d.ts +4 -2
  116. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +28 -0
  117. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/bookability.d.ts +9 -0
  118. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/dates.d.ts +14 -0
  119. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/duration.d.ts +2 -0
  120. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/index.d.ts +4 -0
  121. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/location.d.ts +2 -0
  122. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/quickDates.d.ts +16 -0
  123. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/AgendaEventCard.d.ts +9 -1
  124. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/CalendarDayCell.d.ts +2 -0
  125. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/CalendarDayHeaders.d.ts +4 -0
  126. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/DayEventsModal.d.ts +2 -1
  127. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventCard.d.ts +5 -0
  128. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventModals.d.ts +2 -1
  129. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventQuickDates.d.ts +15 -0
  130. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekAgendaView.d.ts +7 -3
  131. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekTimetableView.d.ts +1 -0
  132. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/index.d.ts +2 -0
  133. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/timetableModel.d.ts +1 -0
  134. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/useHydrationReady.d.ts +6 -0
  135. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.client.state.d.ts +3 -0
  136. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.interactive.d.ts +62 -33
  137. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.submission.d.ts +3 -3
  138. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.types.d.ts +14 -31
  139. package/dist/_dts/blocks/src/system/runtime/nodes/offerings-preview-catalogue.d.ts +14 -0
  140. package/dist/_dts/blocks/src/system/runtime/nodes/offerings-preview-content.d.ts +23 -0
  141. package/dist/_dts/blocks/src/system/runtime/nodes/offerings-preview.d.ts +4 -2
  142. package/dist/_dts/blocks/src/system/runtime/resolver.d.ts +1 -0
  143. package/dist/_dts/blocks/src/system/runtime/shared/components/index.d.ts +2 -6
  144. package/dist/_dts/blocks/src/system/runtime/shared/index.d.ts +2 -2
  145. package/dist/_dts/blocks/src/system/runtime/shared/useWaitlistClaim.d.ts +2 -0
  146. package/dist/_dts/blocks/src/system/transforms/registry/formatting.d.ts +5 -0
  147. package/dist/_dts/commerce/src/purchase/event-registration-errors.d.ts +4 -0
  148. package/dist/_dts/commerce/src/purchase/index.d.ts +1 -0
  149. package/dist/_dts/commerce/src/purchase/orderItemMetadata.d.ts +32 -16
  150. package/dist/_dts/commerce/src/purchase/stripeCommissionMetadata.d.ts +34 -0
  151. package/dist/_dts/content-editor/src/controller/EntryControllerProvider.d.ts +2 -1
  152. package/dist/_dts/content-editor/src/footerEngagementDraft.d.ts +6 -24
  153. package/dist/_dts/content-editor/src/hooks/useBlockAutosave.d.ts +3 -1
  154. package/dist/_dts/content-editor/src/useFooterComposerState.d.ts +4 -2
  155. package/dist/_dts/core/src/branded.d.ts +0 -8
  156. package/dist/_dts/core/src/footer-engagement.d.ts +2 -6
  157. package/dist/_dts/core/src/index.d.ts +10 -1
  158. package/dist/_dts/core/src/mailing-list-identifiers.d.ts +21 -0
  159. package/dist/_dts/core/src/mailing-list-runtime.d.ts +42 -0
  160. package/dist/_dts/core/src/mailing-list-setup-parser.d.ts +14 -0
  161. package/dist/_dts/core/src/mailing-list-setup.d.ts +142 -0
  162. package/dist/_dts/core/src/mailing-list-submission.d.ts +224 -0
  163. package/dist/_dts/core/src/mailing-list-targeting-parser.d.ts +12 -0
  164. package/dist/_dts/core/src/mailing-list-targeting.d.ts +93 -0
  165. package/dist/_dts/core/src/navigation-locations.d.ts +28 -0
  166. package/dist/_dts/core/src/participants.d.ts +2 -29
  167. package/dist/_dts/core/src/public-experience.d.ts +4 -0
  168. package/dist/_dts/core/src/public-profile.d.ts +35 -1
  169. package/dist/_dts/core/src/public-read-cache-contract.d.ts +45 -0
  170. package/dist/_dts/core/src/site-route-target.d.ts +9 -2
  171. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +797 -954
  172. package/dist/_dts/editor-blocks/src/widgets/index.d.ts +1 -0
  173. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/MailingListGlobalSettingsSummary.d.ts +10 -0
  174. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/MailingListTargetingField.d.ts +12 -0
  175. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/context.d.ts +14 -0
  176. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/index.d.ts +3 -0
  177. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/loaders.d.ts +7 -0
  178. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/targetingState.d.ts +19 -0
  179. package/dist/_dts/preview-next/src/client/widgets/widgetOverrides.d.ts +1 -0
  180. package/dist/_dts/sdk/src/client/publicAppointmentReadOperations.d.ts +12 -0
  181. package/dist/_dts/sdk/src/client/publicEventReadOperations.d.ts +2 -1
  182. package/dist/_dts/sdk/src/client/publicLoaderCacheAccess.d.ts +11 -4
  183. package/dist/_dts/sdk/src/config/content-types.d.ts +3 -13
  184. package/dist/_dts/sdk/src/config/content-validation.d.ts +5 -8
  185. package/dist/_dts/sdk/src/constants.d.ts +3 -3
  186. package/dist/_dts/sdk/src/contracts/index.d.ts +1 -1
  187. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +12 -31
  188. package/dist/_dts/sdk/src/navigation/index.d.ts +11 -29
  189. package/dist/_dts/sdk/src/next/index.d.ts +4 -4
  190. package/dist/_dts/sdk/src/prebuild/types.d.ts +1 -5
  191. package/dist/_dts/sdk/src/public-api/contracts.d.ts +44 -33
  192. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +5 -0
  193. package/dist/_dts/sdk/src/rendering/client.d.ts +3 -20
  194. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +5 -0
  195. package/dist/_dts/sdk/src/rendering/helpers/loadContent.d.ts +4 -0
  196. package/dist/_dts/sdk/src/rendering/helpers/pageRuntimeSupport.d.ts +8 -1
  197. package/dist/_dts/sdk/src/rendering/helpers/templateContent.d.ts +1 -0
  198. package/dist/_dts/sdk/src/rendering/index.d.ts +1 -1
  199. package/dist/_dts/sdk/src/types/block-kinds.d.ts +1 -1
  200. package/dist/_dts/sdk/src/version.d.ts +1 -1
  201. package/dist/_dts/theme-core/src/accordions/types.d.ts +3 -3
  202. package/dist/_dts/theme-core/src/cards/types.d.ts +21 -21
  203. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  204. package/dist/_dts/theme-core/src/header/interactionPalette.d.ts +8 -2
  205. package/dist/_dts/theme-core/src/header/legacyHeaderVariant.d.ts +2 -2
  206. package/dist/_dts/theme-core/src/hosted-booking-appearance.d.ts +41 -0
  207. package/dist/_dts/theme-core/src/index.d.ts +1 -0
  208. package/dist/_dts/theme-core/src/inputs/types.d.ts +2 -2
  209. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +54 -54
  210. package/dist/_dts/theme-core/src/runtime/buildThemeRuntime.d.ts +0 -1
  211. package/dist/_dts/theme-core/src/runtime/buildThemeRuntimeFromBridge.d.ts +1 -4
  212. package/dist/_dts/theme-core/src/schema.d.ts +84 -84
  213. package/dist/_dts/theme-core/src/shared/componentStyles.d.ts +1 -1
  214. package/dist/_dts/theme-core/src/site-styles/backgroundAppearance.d.ts +2 -2
  215. package/dist/_dts/theme-core/src/surfaces/foregroundInteraction.d.ts +77 -0
  216. package/dist/_dts/theme-core/src/surfaces/index.d.ts +1 -0
  217. package/dist/_dts/theme-core/src/tokens/tokens.d.ts +7 -0
  218. package/dist/_dts/theme-core/src/typography/generateTypographyCss.d.ts +2 -2
  219. package/dist/_dts/ui/src/badge.d.ts +1 -1
  220. package/dist/_dts/ui/src/callout.d.ts +1 -1
  221. package/dist/_dts/ui/src/lib/use-delayed-flag.d.ts +9 -0
  222. package/dist/_dts/ui/src/pending-button.d.ts +10 -0
  223. package/dist/client/{BookingConsentAgreement-DQUik1Mx.mjs → BookingConsentAgreement-CuKa82V4.mjs} +4 -4
  224. package/dist/client/{DiscountCodeDisclosure-CU67Q4vH.mjs → DiscountCodeDisclosure-BbYieKWB.mjs} +1 -1
  225. package/dist/client/{EventCombined.client-a02TXUgg.mjs → EventCombined.client-LTfR1Aby.mjs} +444 -200
  226. package/dist/client/{EventListing.client-99qx7jFl.mjs → EventListing.client-DUHpYSuo.mjs} +2 -2
  227. package/dist/client/{LeafletStaticMap-CWzcq73L.mjs → LeafletStaticMap-CHRupL6m.mjs} +1 -1
  228. package/dist/client/{accordion-D1nb3-Oj.mjs → accordion-6HiIFxNL.mjs} +1 -1
  229. package/dist/client/{bookingForm-BGrmLhaO.mjs → bookingForm-Dlmid43H.mjs} +7 -7
  230. package/dist/client/bookings.mjs +368 -142
  231. package/dist/client/{carousel-DSmOx3ad.mjs → carousel-DmkZRRq_.mjs} +2 -2
  232. package/dist/client/{carousel.client-59G_WMr4.mjs → carousel.client-DQTjCVQT.mjs} +1 -1
  233. package/dist/client/{cart-COWeOIUk.mjs → cart-CIC24330.mjs} +3 -3
  234. package/dist/client/{checkout-CeysaIJK.mjs → checkout-D1Zw9imo.mjs} +3 -3
  235. package/dist/client/{checkoutUrls-BuseL0dw.mjs → checkoutUrls-FL6lRkrt.mjs} +1 -1
  236. package/dist/client/client.mjs +5017 -2258
  237. package/dist/client/{colorStyles-CrxJrPjJ.mjs → colorStyles-3013aRAY.mjs} +3 -1
  238. package/dist/client/{context-DBzX85Xc.mjs → context-Cy1OayHx.mjs} +9 -21
  239. package/dist/client/{dates-DCYhZBlW.mjs → dates-aDcfoLHr.mjs} +21 -3
  240. package/dist/client/{eventCalendar-BgsN73Ul.mjs → eventCalendar-FQxMPAjf.mjs} +81 -79
  241. package/dist/client/{eventCombined-DcZQAMQP.mjs → eventCombined-Dr3ac6Hb.mjs} +3 -3
  242. package/dist/client/{eventDetails-BWwGJ54l.mjs → eventDetails-D-AzUHFQ.mjs} +4 -4
  243. package/dist/client/{eventListing-DqYqV8vp.mjs → eventListing-B3XxBf3i.mjs} +3 -3
  244. package/dist/client/{eventRegistration-DQGDgu_e.mjs → eventRegistration-I6EaokFD.mjs} +543 -155
  245. package/dist/client/{form-ClfpasVT.mjs → form-BbWckVWY.mjs} +3 -3
  246. package/dist/client/{headerSection-BuOMe98N.mjs → headerSection-C9qU4Y7x.mjs} +2 -2
  247. package/dist/client/hooks.mjs +1685 -716
  248. package/dist/client/{locationMap-CEqu_sfa.mjs → locationMap-CLCShvlG.mjs} +3 -3
  249. package/dist/client/{media-BOHuueS5.mjs → media-DHpfFwd3.mjs} +1 -1
  250. package/dist/client/newsletterForm-Briukxzi.mjs +444 -0
  251. package/dist/client/{pricing-xj7MPZlK.mjs → pricing-Copadu-2.mjs} +1 -1
  252. package/dist/client/{productDetail-vxqTt5Xj.mjs → productDetail-oujlRd-r.mjs} +3 -3
  253. package/dist/client/{productList-OTdZu8sb.mjs → productList-BRiIRUcd.mjs} +3 -3
  254. package/dist/client/{propsDecoder-CY9gGEF7.mjs → propsDecoder-CB2KS_ko.mjs} +706 -160
  255. package/dist/client/rendering/client.mjs +3161 -1226
  256. package/dist/client/rendering/islands.mjs +19 -19
  257. package/dist/client/rendering.mjs +4864 -1914
  258. package/dist/client/{scrollToBlock--BFV6kl-.mjs → scrollToBlock-B1IS1_ua.mjs} +1 -1
  259. package/dist/client/{shop-CP4YbDL9.mjs → shop-Vn6yNFED.mjs} +6 -6
  260. package/dist/client/{shop-commerce-APs4XBXE.mjs → shop-commerce-BVTqipYp.mjs} +7 -7
  261. package/dist/client/{shop-commerce-store-CAVLxLFr.mjs → shop-commerce-store-BVnJVy7v.mjs} +1 -1
  262. package/dist/client/{shopShared-BnSRrwXI.mjs → shopShared-COIeK77T.mjs} +4 -4
  263. package/dist/client/{useEventFilters-1a1by4c8.mjs → useEventFilters-DzIUcS9n.mjs} +58 -11
  264. package/dist/preview-next/before-render.mjs +357 -175
  265. package/dist/preview-next/client/runtime.mjs +4 -4
  266. package/dist/preview-next/keepAlive.mjs +357 -175
  267. package/dist/preview-next/middleware.mjs +357 -175
  268. package/dist/{previewAuthStore-BkEgnYPP.mjs → previewAuthStore-Gjb6r6vz.mjs} +357 -175
  269. package/dist/{sdk-runtime-DwGfsT0S.mjs → sdk-runtime-CnCLvZRv.mjs} +2 -2
  270. package/dist/{separator-BeqDLneQ.mjs → separator-DKDRJ1oH.mjs} +1 -1
  271. package/dist/server/components.mjs +3389 -1251
  272. package/dist/server/config-validation.mjs +2737 -1784
  273. package/dist/server/config.mjs +2742 -1788
  274. package/dist/server/data.mjs +1586 -615
  275. package/dist/server/index.mjs +496 -352
  276. package/dist/server/navigation.mjs +16 -47
  277. package/dist/server/next.mjs +3978 -2007
  278. package/dist/server/page-converter.mjs +1109 -553
  279. package/dist/server/prebuild.mjs +2 -3
  280. package/dist/server/rendering/server.mjs +4101 -1951
  281. package/dist/server/rendering.mjs +3416 -1259
  282. package/dist/server/routing.mjs +1869 -786
  283. package/dist/server/server.mjs +3260 -2482
  284. package/dist/server/theme-bridge.mjs +725 -124
  285. package/dist/server/theme.mjs +8 -2
  286. package/dist/styles/index.css +526 -68
  287. package/package.json +1 -1
  288. package/dist/_dts/api/src/navigation/identity.d.ts +0 -59
  289. package/dist/_dts/blocks/src/system/blocks/newsletter-signup-destination.d.ts +0 -291
  290. package/dist/_dts/blocks/src/system/runtime/shared/components/BookingOptionCompactRow.d.ts +0 -29
  291. package/dist/_dts/blocks/src/system/runtime/shared/components/BookingOptionList.d.ts +0 -13
  292. package/dist/_dts/core/src/newsletter-signup-destination.d.ts +0 -38
  293. package/dist/client/newsletterForm-IbrHjMxy.mjs +0 -322
@@ -1,14 +1,14 @@
1
1
  "use client";
2
- import { a as buildBookingPaymentSelectionViewModel, i as usePolling, n as StepIndicator$1, o as resolveBookingPaymentDueNowCents, r as SpinnerNode, s as formatPrice, t as BookingConsentAgreement } from "./BookingConsentAgreement-DQUik1Mx.mjs";
3
- import { $t as toBookingTimeZone, C as WIZARD_STEPS, Gt as formatBookingDateTime, Nt as assertNever, O as resolveEventRegistrationScopedEvents, S as resolveRegistrationTarget, T as getWizardStepsForContext, Ut as formatBookingDate, _ as toWholeSeriesRegistrationEvents, an as publicEventPricingCurrency, at as groupPublicEventsByRun, b as resolveDiscountContext, cn as publicEventPricingStrategy, g as toRegistrationEvents, h as getRegistrationStartAt, ln as publicEventPricingType, qt as formatBookingTime, sn as publicEventPricingOptions, t as defineIslandPropsDecoder, tn as toScheduledBookingDateTime, un as formatCurrencyAmount, ut as themeButtonClassName, v as findEventByOccurrenceId, w as getStepNumber, x as resolveEventRequiresPayment, y as findPreSelectedEvent } from "./propsDecoder-CY9gGEF7.mjs";
4
- import { a as canJoinEventWaitlistOnAnyMode, c as formatTicketTypeRemaining, f as getRemainingPlaces, h as selectMostOpenCapacitySource, i as canJoinEventWaitlist, m as selectEventCapacitySource, o as formatEventRemainingPlaces, p as isEventFull, r as formatEventPriceDisplay, s as formatRemainingPlaces, u as getEventAvailability } from "./pricing-xj7MPZlK.mjs";
5
- import { n as useBlockApi, r as BlockApiError, t as BlockApiProvider } from "./context-DBzX85Xc.mjs";
2
+ import { a as buildBookingPaymentSelectionViewModel, i as usePolling, n as StepIndicator$1, o as resolveBookingPaymentDueNowCents, r as SpinnerNode, s as formatPrice, t as BookingConsentAgreement } from "./BookingConsentAgreement-CuKa82V4.mjs";
3
+ import { C as resolveRegistrationTarget, E as getWizardStepsForContext, Gt as formatBookingDate, Pt as assertNever, S as resolveEventRequiresPayment, T as getStepNumber, Yt as formatBookingTime, _ as toRegistrationEvents, b as findPreSelectedEvent, dn as publicEventPricingType, dt as themeButtonClassName, fn as formatCurrencyAmount, g as getRegistrationStartAt, h as buildEventRegistrationDisplayFromScopedEvents, k as resolveEventRegistrationScopedEvents, ln as publicEventPricingOptions, ot as groupPublicEventsByRun, pn as parseCurrencyCode, qt as formatBookingDateTime, rn as toScheduledBookingDateTime, sn as publicEventPricingCurrency, t as defineIslandPropsDecoder, tn as toBookingTimeZone, un as publicEventPricingStrategy, v as toWholeSeriesRegistrationEvents, w as WIZARD_STEPS, x as resolveDiscountContext, y as findEventByOccurrenceId } from "./propsDecoder-CB2KS_ko.mjs";
4
+ import { a as canJoinEventWaitlistOnAnyMode, c as formatTicketTypeRemaining, f as getRemainingPlaces, h as selectMostOpenCapacitySource, i as canJoinEventWaitlist, m as selectEventCapacitySource, o as formatEventRemainingPlaces, p as isEventFull, r as formatEventPriceDisplay, s as formatRemainingPlaces, u as getEventAvailability } from "./pricing-Copadu-2.mjs";
5
+ import { n as useBlockApi, r as BlockApiError, t as BlockApiProvider } from "./context-Cy1OayHx.mjs";
6
6
  import { n as isSpamProtectionEnabled, r as AltchaWidget, t as getChallengeUrl } from "./src-B833rYRr.mjs";
7
- import { a as CheckIcon, i as StateIcon, n as useDiscountCodeUi, r as TerminalPanel, t as scrollToBlock } from "./scrollToBlock--BFV6kl-.mjs";
8
- import { t as DiscountCodeDisclosure } from "./DiscountCodeDisclosure-CU67Q4vH.mjs";
7
+ import { a as CheckIcon, i as StateIcon, n as useDiscountCodeUi, r as TerminalPanel, t as scrollToBlock } from "./scrollToBlock-B1IS1_ua.mjs";
8
+ import { t as DiscountCodeDisclosure } from "./DiscountCodeDisclosure-BbYieKWB.mjs";
9
9
  import { t as FeedbackMessage } from "./FeedbackMessage-CtLvvS_d.mjs";
10
10
  import { n as getFieldValidationControlProps, t as FieldValidationMessage } from "./FieldValidationMessage-AYanWFb-.mjs";
11
- import { t as buildCheckoutReturnUrls } from "./checkoutUrls-BuseL0dw.mjs";
11
+ import { t as buildCheckoutReturnUrls } from "./checkoutUrls-FL6lRkrt.mjs";
12
12
  import { t as createBodyThemePortalRoot } from "./themePortalRoot-AGs4cE7t.mjs";
13
13
  import { n as consumeSearchParams } from "./urlParams-D71VXFGx.mjs";
14
14
  import { t as CrossIcon } from "./CrossIcon-Dn1KRKW5.mjs";
@@ -503,6 +503,90 @@ function missingPaymentSelection() {
503
503
  };
504
504
  }
505
505
  //#endregion
506
+ //#region ../blocks/src/system/runtime/nodes/event-registration/checkoutRecovery.ts
507
+ /** Recovery may select held places; checkout still owns admission and payment validation. */
508
+ function checkoutRecoveryOptionAvailability(availability) {
509
+ if (availability.kind === "available" || availability.reason === "sold_out" || availability.reason === "overallCapacityUnavailable") return {
510
+ kind: "available",
511
+ remainingPlaces: null
512
+ };
513
+ return availability;
514
+ }
515
+ /**
516
+ * A form-only projection for the explicit existing-checkout path. It permits
517
+ * collecting the original selection without claiming a new place is available.
518
+ * The public checkout service identifies the customer and remains the admission
519
+ * authority; no reservation/customer data is exposed through this projection.
520
+ */
521
+ function getCheckoutRecoveryFormEligibility(eligibility) {
522
+ if (!eligibility || eligibility.registration.kind !== "none" && eligibility.registration.kind !== "pending_payment" || eligibility.availability.kind === "unavailable" && eligibility.availability.reason !== "full" && eligibility.availability.reason !== "selectionRequired") return eligibility;
523
+ const amountCents = eligibility.price ?? 0;
524
+ if (amountCents <= 0 || !eligibility.currency || eligibility.availability.kind === "unavailable" && eligibility.availability.reason === "selectionRequired") return eligibility.registration.kind === "pending_payment" ? {
525
+ ...eligibility,
526
+ registration: { kind: "none" },
527
+ ticketTypes: eligibility.ticketTypes.map((option) => ({
528
+ ...option,
529
+ availability: checkoutRecoveryOptionAvailability(option.availability)
530
+ }))
531
+ } : eligibility;
532
+ const currency = eligibility.currency;
533
+ const paymentOptions = eligibility.paymentTerms.allowedOptions.map((option) => {
534
+ switch (option.kind) {
535
+ case "upfront": return {
536
+ kind: "payInFull",
537
+ amountCents,
538
+ currency
539
+ };
540
+ case "deferred_manual": return {
541
+ kind: "deferredManual",
542
+ amountCents,
543
+ currency
544
+ };
545
+ case "instalment_plan": return {
546
+ kind: "instalmentPlan",
547
+ amountCents,
548
+ currency
549
+ };
550
+ case "flexible_balance": return {
551
+ kind: "flexibleBalance",
552
+ amountCents,
553
+ currency
554
+ };
555
+ }
556
+ });
557
+ return {
558
+ ...eligibility,
559
+ registration: { kind: "none" },
560
+ availability: {
561
+ kind: "available",
562
+ remainingPlaces: null,
563
+ waitlistEnabled: eligibility.waitlistEnabled
564
+ },
565
+ eligible: paymentOptions.length > 0,
566
+ isFull: false,
567
+ canJoinWaitlist: false,
568
+ isFree: false,
569
+ requiresPayment: true,
570
+ canPayDirectly: paymentOptions.length > 0,
571
+ paymentOptions,
572
+ eligiblePasses: [],
573
+ eligibleMemberships: [],
574
+ ticketTypes: eligibility.ticketTypes.map((option) => ({
575
+ ...option,
576
+ availability: checkoutRecoveryOptionAvailability(option.availability)
577
+ }))
578
+ };
579
+ }
580
+ function isSoldOutEventSelectable(event, waitlistAvailable) {
581
+ return waitlistAvailable || canRecoverEventCheckout(event);
582
+ }
583
+ function canJoinWaitlistOutsideRecovery(event, attendanceMode, checkoutRecovery) {
584
+ return !checkoutRecovery && event !== null && canJoinEventWaitlist(event, { attendanceMode });
585
+ }
586
+ function canRecoverEventCheckout(event) {
587
+ return event !== null && (event.registrationSubject.kind === "wholeSeries" || event.pricing.kind !== "free" && event.pricing.kind !== "external");
588
+ }
589
+ //#endregion
506
590
  //#region ../blocks/src/system/runtime/nodes/event-registration/utils.ts
507
591
  function getPortalSubjectEmail(profile) {
508
592
  return profile?.email ?? null;
@@ -688,7 +772,7 @@ const EventSelectionStep = ({ events, selectedEvent, onSelect, showVenue, showCa
688
772
  const remaining = getRemainingPlaces(selectMostOpenCapacitySource(event));
689
773
  const isSoldOut = isEventFull(event);
690
774
  const canJoinWaitlist = canJoinEventWaitlistOnAnyMode(event);
691
- const isUnavailable = isSoldOut && !canJoinWaitlist;
775
+ const isUnavailable = isSoldOut && !isSoldOutEventSelectable(event, canJoinWaitlist);
692
776
  const isLowCapacity = remaining.kind === "low";
693
777
  const capacityLabel = formatEventRemainingPlaces(event, { full: "Sold out" });
694
778
  const timeZone = event.timeZone ?? null;
@@ -733,6 +817,33 @@ const EventSelectionStep = ({ events, selectedEvent, onSelect, showVenue, showCa
733
817
  });
734
818
  };
735
819
  //#endregion
820
+ //#region ../blocks/src/system/runtime/nodes/event-registration/useCheckoutRecovery.ts
821
+ /** Recovery belongs to the selected booking subject; changing events resets its scope. */
822
+ function useCheckoutRecovery(event, setStep) {
823
+ const [recoveryEventId, setRecoveryEventId] = useState(null);
824
+ return {
825
+ checkoutRecovery: event !== null && recoveryEventId === event.selectionId,
826
+ startCheckoutRecovery: useCallback(() => {
827
+ if (!event) return;
828
+ setRecoveryEventId(event.selectionId);
829
+ setStep("select-tickets");
830
+ }, [event, setStep])
831
+ };
832
+ }
833
+ /** Authenticated pending bookings enter the same form-only recovery path as guests. */
834
+ function useCheckoutRecoveryEligibility(eligibility, step, checkoutRecovery, startCheckoutRecovery) {
835
+ const registrationKind = eligibility?.registration.kind;
836
+ useEffect(() => {
837
+ if ((step === "select-event" || step === "select-tickets" || step === "enter-details" || step === "select-payment") && registrationKind === "pending_payment" && !checkoutRecovery) startCheckoutRecovery();
838
+ }, [
839
+ registrationKind,
840
+ step,
841
+ checkoutRecovery,
842
+ startCheckoutRecovery
843
+ ]);
844
+ return useMemo(() => checkoutRecovery ? getCheckoutRecoveryFormEligibility(eligibility) : eligibility, [checkoutRecovery, eligibility]);
845
+ }
846
+ //#endregion
736
847
  //#region ../blocks/src/system/runtime/nodes/event-registration/registrationErrorRecovery.ts
737
848
  function resolveRegistrationRecoveryAction(step, action) {
738
849
  if (step === "payment-failed") return "payment-options";
@@ -1283,6 +1394,40 @@ const SharedDatedOfferingOrderCheckoutSessionMetadataSchema = z.object({
1283
1394
  ...datedOfferingSharedEngineMetadataShape
1284
1395
  });
1285
1396
  z.union([SharedDatedOfferingOrderCheckoutSessionMetadataSchema, LegacyOrderCheckoutSessionMetadataSchema]);
1397
+ //#endregion
1398
+ //#region ../commerce/src/purchase/stripeCommissionMetadata.ts
1399
+ /** Reasons are payment evidence, not an independent pricing policy. */
1400
+ const STRIPE_COMMISSION_FREE_REASONS = [
1401
+ "managed_billing",
1402
+ "no_commission_plan",
1403
+ "billing_evidence_invalid",
1404
+ "fee_rounds_to_zero",
1405
+ "non_commissionable_scope",
1406
+ "payment_not_stripe"
1407
+ ];
1408
+ const historicalContext = {
1409
+ currency: z.string().refine((value) => parseCurrencyCode(value) !== null).optional(),
1410
+ sourcePlanId: z.string().trim().min(1).optional()
1411
+ };
1412
+ const percentSchema = z.number().finite().min(0).max(100);
1413
+ z.discriminatedUnion("kind", [
1414
+ z.object({
1415
+ kind: z.literal("commission_free"),
1416
+ reason: z.enum(STRIPE_COMMISSION_FREE_REASONS),
1417
+ ...historicalContext
1418
+ }),
1419
+ z.object({
1420
+ kind: z.literal("application_fee_amount"),
1421
+ amountCents: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER),
1422
+ percent: percentSchema,
1423
+ ...historicalContext
1424
+ }),
1425
+ z.object({
1426
+ kind: z.literal("application_fee_percent"),
1427
+ percent: percentSchema,
1428
+ ...historicalContext
1429
+ })
1430
+ ]);
1286
1431
  toNonNegativeCents(0);
1287
1432
  //#endregion
1288
1433
  //#region ../commerce/src/purchase/stripeMinimumCharge.ts
@@ -1339,6 +1484,10 @@ const eventRegistrationErrors = {
1339
1484
  message: "We’re checking your booking and payment. Please don’t try to book again yet. If you’ve already paid, you don’t need to pay again.",
1340
1485
  action: "payment-status"
1341
1486
  },
1487
+ paymentProviderUnavailable: {
1488
+ message: "We couldn’t reach the payment provider. Please try again in a minute.",
1489
+ action: "retry"
1490
+ },
1342
1491
  paymentPageUnavailable: {
1343
1492
  message: "We couldn’t open the payment page. Please refresh this page and try again. If this keeps happening, contact the organiser for help.",
1344
1493
  action: "retry"
@@ -1461,11 +1610,6 @@ function ensureWaitlistClaimLocationTracking() {
1461
1610
  } catch {}
1462
1611
  window.addEventListener("popstate", emitWaitlistClaimLocationChange);
1463
1612
  }
1464
- function getWaitlistClaimTokenFromUrl() {
1465
- if (typeof window === "undefined") return null;
1466
- const token = new URLSearchParams(window.location.search).get("waitlist_claim")?.trim() ?? "";
1467
- return token.length > 0 ? token : null;
1468
- }
1469
1613
  const useWaitlistClaimDeps = { useBlockApi };
1470
1614
  function subscribeToWaitlistClaimToken(callback) {
1471
1615
  if (typeof window === "undefined") return () => {};
@@ -1475,28 +1619,42 @@ function subscribeToWaitlistClaimToken(callback) {
1475
1619
  window.removeEventListener(WAITLIST_CLAIM_LOCATION_EVENT, callback);
1476
1620
  };
1477
1621
  }
1478
- function getWaitlistClaimTokenSnapshot() {
1479
- return getWaitlistClaimTokenFromUrl();
1622
+ function getWaitlistClaimLocationSnapshot() {
1623
+ return typeof window === "undefined" ? "" : window.location.search;
1624
+ }
1625
+ function parseWaitlistClaimCredential(search) {
1626
+ const params = new URLSearchParams(search);
1627
+ const token = params.get("waitlist_claim")?.trim();
1628
+ if (token) return {
1629
+ kind: "emailedToken",
1630
+ token
1631
+ };
1632
+ const entryId = params.get("waitlistEntry")?.trim();
1633
+ return entryId ? {
1634
+ kind: "portalOwnedEntry",
1635
+ entryId
1636
+ } : null;
1480
1637
  }
1481
1638
  function useWaitlistClaim() {
1482
1639
  return useWaitlistClaimWithDeps(useWaitlistClaimDeps);
1483
1640
  }
1484
1641
  function useWaitlistClaimWithDeps(deps) {
1485
- return useResolvedWaitlistClaim(deps, useSyncExternalStore(subscribeToWaitlistClaimToken, getWaitlistClaimTokenSnapshot, () => null));
1642
+ const locationSearch = useSyncExternalStore(subscribeToWaitlistClaimToken, getWaitlistClaimLocationSnapshot, () => "");
1643
+ return useResolvedWaitlistClaim(deps, useMemo(() => parseWaitlistClaimCredential(locationSearch), [locationSearch]));
1486
1644
  }
1487
- function useResolvedWaitlistClaim(deps, token) {
1645
+ function useResolvedWaitlistClaim(deps, credential) {
1488
1646
  const api = deps.useBlockApi();
1489
- const [state, dispatch] = useReducer(waitlistClaimReducer, Boolean(token), createInitialWaitlistClaimState);
1647
+ const [state, dispatch] = useReducer(waitlistClaimReducer, Boolean(credential), createInitialWaitlistClaimState);
1490
1648
  useEffect(() => {
1491
1649
  let cancelled = false;
1492
1650
  async function resolveClaim() {
1493
- if (!token) {
1651
+ if (!credential) {
1494
1652
  dispatch({ type: "cleared" });
1495
1653
  return;
1496
1654
  }
1497
1655
  dispatch({ type: "started" });
1498
1656
  try {
1499
- const result = await api.resolveWaitlistClaim({ claimToken: token });
1657
+ const result = credential.kind === "portalOwnedEntry" ? await api.resolveWaitlistClaim({ waitlistEntryId: credential.entryId }) : await api.resolveWaitlistClaim({ claimToken: credential.token });
1500
1658
  if (cancelled) return;
1501
1659
  dispatch({
1502
1660
  type: "resolved",
@@ -1514,9 +1672,10 @@ function useResolvedWaitlistClaim(deps, token) {
1514
1672
  return () => {
1515
1673
  cancelled = true;
1516
1674
  };
1517
- }, [api, token]);
1675
+ }, [api, credential]);
1518
1676
  return {
1519
- token,
1677
+ token: credential?.kind === "emailedToken" ? credential.token : null,
1678
+ entryId: credential?.kind === "portalOwnedEntry" ? credential.entryId : null,
1520
1679
  claim: getWaitlistClaim(state),
1521
1680
  error: getWaitlistClaimError(state),
1522
1681
  loginMessage: getWaitlistClaimLoginMessage(state),
@@ -1998,15 +2157,12 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
1998
2157
  * landed — a success, or a hand-off to checkout — because until then nobody
1999
2158
  * knows whether the first one committed.
2000
2159
  *
2001
- * Reusing it after a failure is safe even if the customer edits their
2002
- * details. The server consults the command record before it re-checks
2003
- * anything, so a submission that already booked is answered with the booking
2004
- * that exists — not refused for spending a credit or a claim that this very
2005
- * command already spent, and not treated as a second booking because a name
2006
- * or a note changed in between.
2160
+ * Identical retries retain the command after a lost response. Changed form
2161
+ * details get a new command so the server applies the new booking intent.
2007
2162
  */
2008
- const commandIdRef = useRef(null);
2009
- return async (method, passId, membershipId, selection, submitOptions) => {
2163
+ const commandRef = useRef(null);
2164
+ const inFlightRef = useRef(null);
2165
+ const submit = async (method, passId, membershipId, selection, submitOptions) => {
2010
2166
  const target = options.registrationTarget;
2011
2167
  if (!target) return {
2012
2168
  ok: false,
@@ -2014,44 +2170,34 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
2014
2170
  message: "Select an event to continue."
2015
2171
  };
2016
2172
  options.setStep("submitting");
2017
- const registrationCommandId = commandIdRef.current ?? deps.createClientCommandId();
2018
- commandIdRef.current = registrationCommandId;
2173
+ const registrationCommandId = commandRef.current?.id ?? deps.createClientCommandId();
2019
2174
  try {
2020
- const prepared = prepareSubmitContext(options, registrationCommandId, target, method, passId, membershipId, selection);
2175
+ let prepared = prepareSubmitContext(options, registrationCommandId, target, method, passId, membershipId, selection);
2021
2176
  if (prepared.subject.kind === "wholeSeries" && method === "stripe") {
2022
- commandIdRef.current = null;
2177
+ commandRef.current = null;
2023
2178
  return await submitWholeSeriesCheckout(options, deps, {
2024
2179
  ...prepared,
2025
2180
  subject: prepared.subject
2026
2181
  }, submitOptions);
2027
2182
  }
2183
+ const request = buildOccurrenceRegistrationRequest(options, prepared, method, passId, membershipId);
2184
+ const intentKey = registrationRequestIntentKey(request);
2185
+ if (commandRef.current !== null && commandRef.current.intentKey !== intentKey) prepared = {
2186
+ ...prepared,
2187
+ registrationCommandId: deps.createClientCommandId()
2188
+ };
2189
+ commandRef.current = {
2190
+ id: prepared.registrationCommandId,
2191
+ intentKey
2192
+ };
2028
2193
  const result = await options.api.registerForEvent({
2029
- registrationCommandId: prepared.registrationCommandId,
2030
- subject: prepared.subject,
2031
- ticketSelections: toTicketSelectionRequests(prepared.ticketSelections),
2032
- selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
2033
- email: options.formData.email.trim().toLowerCase(),
2034
- name: options.formData.name.trim(),
2035
- phone: options.formData.phone.trim() || void 0,
2036
- notes: options.formData.notes.trim() || void 0,
2037
- consentAccepted: options.formData.consentAccepted,
2038
- altchaSolution: options.altchaSolution,
2039
- paymentMethod: method,
2040
- customerPassId: method === "pass" ? passId : void 0,
2041
- customerMembershipId: method === "membership" ? membershipId : void 0,
2042
- bundleProductId: prepared.bundleProductId,
2043
- claimToken: options.claimToken ?? void 0,
2044
- guests: prepared.guestsPayload
2194
+ ...request,
2195
+ registrationCommandId: prepared.registrationCommandId
2045
2196
  });
2046
- commandIdRef.current = null;
2047
- if (needsOccurrenceCheckout(result, method)) return await submitOccurrenceCheckout(options, deps, prepared, result, method, submitOptions);
2048
- options.setRegistrationResult(toRegistrationResult(result));
2049
- options.setStep("success");
2050
- return {
2051
- ok: true,
2052
- outcome: { kind: "completed" }
2053
- };
2197
+ commandRef.current = null;
2198
+ return await completeRegistrationSubmission(options, deps, prepared, result, method, submitOptions);
2054
2199
  } catch (error) {
2200
+ if (error instanceof BlockApiError && error.tag === "registrationPreparationChanged") commandRef.current = null;
2055
2201
  const { message, action } = registrationErrorPresentation(error);
2056
2202
  options.setErrorAction?.(action);
2057
2203
  options.setErrorMessage(message);
@@ -2063,6 +2209,24 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
2063
2209
  };
2064
2210
  }
2065
2211
  };
2212
+ return (...args) => {
2213
+ if (inFlightRef.current) return inFlightRef.current;
2214
+ const pending = Promise.resolve().then(() => submit(...args));
2215
+ inFlightRef.current = pending;
2216
+ pending.finally(() => {
2217
+ if (inFlightRef.current === pending) inFlightRef.current = null;
2218
+ });
2219
+ return pending;
2220
+ };
2221
+ }
2222
+ async function completeRegistrationSubmission(options, deps, prepared, result, method, submitOptions) {
2223
+ if (needsOccurrenceCheckout(result, method)) return await submitOccurrenceCheckout(options, deps, prepared, result, method, submitOptions);
2224
+ options.setRegistrationResult(toRegistrationResult(result));
2225
+ options.setStep("success");
2226
+ return {
2227
+ ok: true,
2228
+ outcome: { kind: "completed" }
2229
+ };
2066
2230
  }
2067
2231
  function toTicketSelectionRequests(lines) {
2068
2232
  return lines.map((line) => ({
@@ -2137,6 +2301,7 @@ async function submitWholeSeriesCheckout(options, deps, prepared, submitOptions)
2137
2301
  altchaSolution: options.altchaSolution,
2138
2302
  guests: prepared.guestsPayload,
2139
2303
  claimToken: options.claimToken ?? void 0,
2304
+ waitlistEntryId: options.waitlistEntryId ?? void 0,
2140
2305
  discountCode: options.discountCode.trim() || void 0,
2141
2306
  collectionOptionKind: prepared.selectionSnapshot.collectionOptionKind,
2142
2307
  checkoutAttemptId,
@@ -2158,14 +2323,14 @@ async function submitWholeSeriesCheckout(options, deps, prepared, submitOptions)
2158
2323
  }
2159
2324
  if (result.bypassed) return completeBypassedCheckout(options);
2160
2325
  if (!result.checkoutUrl) throw new Error("Checkout URL missing");
2161
- savePendingCheckout(options, deps, prepared, checkoutAttemptId, {
2326
+ savePendingCheckout(options, deps, prepared, result.checkoutAttemptId, {
2162
2327
  scope: "wholeSeries",
2163
2328
  registrationId: result.registrationId
2164
2329
  });
2165
2330
  return redirectToCheckout(result.checkoutUrl, submitOptions);
2166
2331
  }
2167
2332
  function needsOccurrenceCheckout(result, method) {
2168
- return result.scope === "occurrence" && !result.alreadyRegistered && result.status === "confirmed" && result.pendingPayment && [
2333
+ return result.scope === "occurrence" && result.status === "confirmed" && result.pendingPayment && [
2169
2334
  "stripe",
2170
2335
  "pass_bundle",
2171
2336
  "membership_bundle"
@@ -2185,6 +2350,7 @@ async function submitOccurrenceCheckout(options, deps, prepared, registration, m
2185
2350
  kind: "occurrence",
2186
2351
  attendeeId: registration.attendeeId
2187
2352
  },
2353
+ registrationCommandId: prepared.registrationCommandId,
2188
2354
  checkoutType: method === "pass_bundle" ? "pass_bundle" : method === "membership_bundle" ? "membership_bundle" : "event",
2189
2355
  productId: prepared.bundleProductId,
2190
2356
  discountCode: options.discountCode.trim() || void 0,
@@ -2227,6 +2393,31 @@ function redirectToCheckout(checkoutUrl, submitOptions) {
2227
2393
  }
2228
2394
  };
2229
2395
  }
2396
+ function registrationRequestIntentKey(request) {
2397
+ const { registrationCommandId: _command, altchaSolution: _proof, ...intent } = request;
2398
+ return JSON.stringify(intent);
2399
+ }
2400
+ function buildOccurrenceRegistrationRequest(options, prepared, method, passId, membershipId) {
2401
+ return {
2402
+ registrationCommandId: prepared.registrationCommandId,
2403
+ subject: prepared.subject,
2404
+ ticketSelections: toTicketSelectionRequests(prepared.ticketSelections),
2405
+ selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
2406
+ email: options.formData.email.trim().toLowerCase(),
2407
+ name: options.formData.name.trim(),
2408
+ phone: options.formData.phone.trim() || void 0,
2409
+ notes: options.formData.notes.trim() || void 0,
2410
+ consentAccepted: options.formData.consentAccepted,
2411
+ altchaSolution: options.altchaSolution,
2412
+ paymentMethod: method,
2413
+ customerPassId: method === "pass" ? passId : void 0,
2414
+ customerMembershipId: method === "membership" ? membershipId : void 0,
2415
+ bundleProductId: prepared.bundleProductId,
2416
+ claimToken: options.claimToken ?? void 0,
2417
+ waitlistEntryId: options.waitlistEntryId ?? void 0,
2418
+ guests: prepared.guestsPayload
2419
+ };
2420
+ }
2230
2421
  //#endregion
2231
2422
  //#region ../blocks/src/system/runtime/nodes/event-registration/registrationWizardContext.ts
2232
2423
  function getEventSelectionDefaults(event) {
@@ -2465,14 +2656,28 @@ function useEventRegistrationWizardWithDeps(options, deps) {
2465
2656
  }), [options.occurrenceContext, selectedEvent]);
2466
2657
  const registrationOccurrenceId = getRegistrationOccurrenceId(registrationTarget);
2467
2658
  const currentEvent = selectedEvent ?? preSelectedEvent;
2659
+ const setStep = useCallback((nextStep) => {
2660
+ dispatchFlow({
2661
+ type: "set-step",
2662
+ step: nextStep
2663
+ });
2664
+ }, []);
2665
+ const { checkoutRecovery, startCheckoutRecovery } = useCheckoutRecovery(currentEvent, setStep);
2468
2666
  const currentEventUsesTicketTypes = usesTieredPricing(currentEvent);
2469
- const currentCanJoinWaitlist = currentEvent ? canJoinEventWaitlist(currentEvent, { attendanceMode: selectedAttendanceMode }) : false;
2667
+ const currentCanJoinWaitlist = canJoinWaitlistOutsideRecovery(currentEvent, selectedAttendanceMode, checkoutRecovery);
2470
2668
  const usesTicketTypeSelections = currentEventUsesTicketTypes && !currentCanJoinWaitlist;
2471
2669
  const eventTicketTypesForSelection = useMemo(() => getVisibleTicketTypes({
2472
2670
  event: currentEvent,
2473
2671
  eligibility: null,
2474
2672
  selectedAttendanceMode
2475
- }), [currentEvent, selectedAttendanceMode]);
2673
+ }).map((option) => checkoutRecovery ? {
2674
+ ...option,
2675
+ availability: checkoutRecoveryOptionAvailability(option.availability)
2676
+ } : option), [
2677
+ currentEvent,
2678
+ selectedAttendanceMode,
2679
+ checkoutRecovery
2680
+ ]);
2476
2681
  const normalizedSelectedTicketLines = useMemo(() => normalizeTicketSelectionLines(selectedTicketLines), [selectedTicketLines]);
2477
2682
  const ticketTypeSelectionTotal = useMemo(() => getTicketSelectionTotal(normalizedSelectedTicketLines), [normalizedSelectedTicketLines]);
2478
2683
  const ticketsCount = usesTicketTypeSelections ? ticketTypeSelectionTotal : flowState.ticketsCount;
@@ -2510,17 +2715,11 @@ function useEventRegistrationWizardWithDeps(options, deps) {
2510
2715
  isAuthenticated: portalAuthState === "authenticated",
2511
2716
  occurrenceId: registrationOccurrenceId
2512
2717
  });
2513
- const eligibility = eligibilityResult.eligibility;
2718
+ const eligibility = useCheckoutRecoveryEligibility(eligibilityResult.eligibility, step, checkoutRecovery, startCheckoutRecovery);
2514
2719
  const eligibilityLoading = eligibilityResult.isLoading;
2515
2720
  const eligibilityError = eligibilityResult.error;
2516
2721
  const portalCreditState = eligibilityResult.creditState;
2517
2722
  const registrationState = eligibility?.registration ?? { kind: "none" };
2518
- const setStep = useCallback((nextStep) => {
2519
- dispatchFlow({
2520
- type: "set-step",
2521
- step: nextStep
2522
- });
2523
- }, []);
2524
2723
  const setTicketsCount = useCallback((nextTicketsCount) => {
2525
2724
  dispatchFlow({
2526
2725
  type: "set-tickets-count",
@@ -2628,10 +2827,14 @@ function useEventRegistrationWizardWithDeps(options, deps) {
2628
2827
  event: currentEvent,
2629
2828
  eligibility,
2630
2829
  selectedAttendanceMode
2631
- }), [
2830
+ }).map((option) => checkoutRecovery ? {
2831
+ ...option,
2832
+ availability: checkoutRecoveryOptionAvailability(option.availability)
2833
+ } : option), [
2632
2834
  currentEvent,
2633
2835
  selectedAttendanceMode,
2634
- eligibility
2836
+ eligibility,
2837
+ checkoutRecovery
2635
2838
  ]);
2636
2839
  const singleSelectedPricingOptionId = getSingleSelectedPricingOptionId(normalizedSelectedTicketLines);
2637
2840
  const selectedTicketType = useMemo(() => findSelectedTicketType({
@@ -2655,8 +2858,12 @@ function useEventRegistrationWizardWithDeps(options, deps) {
2655
2858
  const event = currentEvent;
2656
2859
  if (!usesTieredPricing(event)) return false;
2657
2860
  if ((event.deliveryMode ?? "in_person") === "hybrid" && !selectedAttendanceMode) return false;
2658
- return !canJoinEventWaitlist(event, { attendanceMode: selectedAttendanceMode });
2659
- }, [currentEvent, selectedAttendanceMode]);
2861
+ return checkoutRecovery || !canJoinEventWaitlist(event, { attendanceMode: selectedAttendanceMode });
2862
+ }, [
2863
+ currentEvent,
2864
+ selectedAttendanceMode,
2865
+ checkoutRecovery
2866
+ ]);
2660
2867
  const hasValidTicketSelection = hasValidPricingOptionSelection({
2661
2868
  selectionRequired: ticketTypeSelectionRequired,
2662
2869
  lines: normalizedSelectedTicketLines,
@@ -2860,6 +3067,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
2860
3067
  guests,
2861
3068
  discountCode: discountUi.discountCode,
2862
3069
  claimToken: waitlistClaim.token,
3070
+ waitlistEntryId: waitlistClaim.entryId,
2863
3071
  setPendingRegistrationReference,
2864
3072
  setStep,
2865
3073
  setRegistrationResult: (result) => setRegistrationResult(result),
@@ -2922,6 +3130,8 @@ function useEventRegistrationWizardWithDeps(options, deps) {
2922
3130
  scopedEvents,
2923
3131
  preSelectedEvent,
2924
3132
  hasPreSelectedContext,
3133
+ checkoutRecovery,
3134
+ startCheckoutRecovery,
2925
3135
  step,
2926
3136
  setStep,
2927
3137
  selectedEvent,
@@ -2974,6 +3184,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
2974
3184
  isMembershipFastTrack,
2975
3185
  waitlistClaim,
2976
3186
  eligibility,
3187
+ registrationOptionsState: eligibilityResult.state,
2977
3188
  eligibilityLoading,
2978
3189
  eligibilityError,
2979
3190
  existingRegistration: existingRegistrationResult.registration,
@@ -3124,6 +3335,51 @@ function getMagicLinkErrorMessage(error) {
3124
3335
  return error instanceof Error ? error.message : "Failed to send. Please try again.";
3125
3336
  }
3126
3337
  //#endregion
3338
+ //#region ../blocks/src/system/runtime/nodes/event-registration/ErrorStep.tsx
3339
+ /**
3340
+ * Error Step
3341
+ *
3342
+ * Displays an error message with a retry button when registration fails.
3343
+ */
3344
+ const labels = {
3345
+ none: "",
3346
+ retry: "Try again",
3347
+ places: "Choose places",
3348
+ start: "Start again",
3349
+ details: "Check my details",
3350
+ "payment-options": "View payment options",
3351
+ "payment-status": "Check payment status",
3352
+ portal: "View my bookings",
3353
+ event: "View event"
3354
+ };
3355
+ const ErrorStep = ({ message, onRetry, action = "retry", canJoinWaitlist = false }) => {
3356
+ const offerWaitlist = action === "places" && canJoinWaitlist;
3357
+ return /* @__PURE__ */ jsx(TerminalPanel, {
3358
+ tone: "error",
3359
+ className: "er-center",
3360
+ titleClassName: "er-title--lg er-message",
3361
+ icon: /* @__PURE__ */ jsx(StateIcon, {
3362
+ variant: "error",
3363
+ children: /* @__PURE__ */ jsx(CrossIcon, {})
3364
+ }),
3365
+ title: "We couldn’t complete your booking",
3366
+ body: /* @__PURE__ */ jsx("p", {
3367
+ className: "er-text--muted er-message",
3368
+ children: offerWaitlist ? "Sorry, this event is now full. You can join the waiting list, and we’ll email you if a place becomes available." : message
3369
+ }),
3370
+ actions: action === "none" ? void 0 : action === "portal" || action === "payment-status" ? /* @__PURE__ */ jsx("a", {
3371
+ href: "/portal",
3372
+ className: "er-retry-btn",
3373
+ children: labels[action]
3374
+ }) : /* @__PURE__ */ jsx("button", {
3375
+ type: "button",
3376
+ onClick: onRetry,
3377
+ className: "er-retry-btn",
3378
+ children: offerWaitlist ? "Join the waiting list" : labels[action]
3379
+ })
3380
+ });
3381
+ };
3382
+ //#endregion
3127
3383
  //#region ../blocks/src/system/runtime/nodes/event-registration/EventRegistrationSummaryBar.tsx
3128
3384
  function getScheduleSummary(wizard, summaryEvent) {
3129
3385
  if (summaryEvent.registrationSubject.kind !== "wholeSeries") {
@@ -3394,6 +3650,8 @@ function isFullWithNoWaitlist(event, attendanceMode) {
3394
3650
  }
3395
3651
  function resolveTicketSelectionContinueLabel(input) {
3396
3652
  if (input.isCheckingExistingRegistration) return "Checking registration...";
3653
+ if (input.registrationOptionsPending) return "Checking availability...";
3654
+ if (input.registrationOptionsFailed) return "Availability unavailable";
3397
3655
  if (input.hasExistingRegistration) return resolveExistingRegistrationLabel(input.wizard);
3398
3656
  if (input.isSoldOutWithoutWaitlist) return "Sold out";
3399
3657
  if (input.ticketTypeSelectionBlocked) return "Choose a ticket";
@@ -3403,14 +3661,17 @@ function SelectTicketsActions(props) {
3403
3661
  const { wizard } = props;
3404
3662
  const hasWaitlistClaim = wizard.waitlistClaim.claim !== null;
3405
3663
  const currentEvent = wizard.selectedEvent ?? wizard.preSelectedEvent;
3406
- const isSoldOutWithoutWaitlist = !hasWaitlistClaim && isFullWithNoWaitlist(currentEvent, wizard.selectedAttendanceMode);
3407
- const isWaitingForEligibility = wizard.portalAuthState === "authenticated" && wizard.eligibilityLoading;
3664
+ const registrationOptionsPending = wizard.registrationOptionsState.tag === "idle" || wizard.registrationOptionsState.tag === "loading";
3665
+ const registrationOptionsFailed = wizard.registrationOptionsState.tag === "failed";
3666
+ const isSoldOutWithoutWaitlist = !wizard.checkoutRecovery && !hasWaitlistClaim && isFullWithNoWaitlist(currentEvent, wizard.selectedAttendanceMode);
3408
3667
  const isCheckingExistingRegistration = wizard.portalAuthState === "authenticated" && wizard.existingRegistrationLoading;
3409
3668
  const hasExistingRegistration = isExistingRegistrationBlocking$1(wizard);
3410
3669
  const ticketTypeSelectionBlocked = wizard.ticketTypeSelectionRequired && !wizard.hasValidTicketSelection;
3411
- const isContinueDisabled = isWaitingForEligibility || isCheckingExistingRegistration || hasExistingRegistration || isSoldOutWithoutWaitlist || ticketTypeSelectionBlocked;
3670
+ const isContinueDisabled = registrationOptionsPending || registrationOptionsFailed || isCheckingExistingRegistration || hasExistingRegistration || isSoldOutWithoutWaitlist || ticketTypeSelectionBlocked;
3412
3671
  const continueLabel = resolveTicketSelectionContinueLabel({
3413
3672
  wizard,
3673
+ registrationOptionsPending,
3674
+ registrationOptionsFailed,
3414
3675
  isCheckingExistingRegistration,
3415
3676
  hasExistingRegistration,
3416
3677
  isSoldOutWithoutWaitlist,
@@ -3428,7 +3689,7 @@ function SelectTicketsActions(props) {
3428
3689
  onClick: () => wizard.setStep("enter-details"),
3429
3690
  disabled: isContinueDisabled,
3430
3691
  className: props.buttonClass,
3431
- children: isWaitingForEligibility ? /* @__PURE__ */ jsxs("span", {
3692
+ children: registrationOptionsPending ? /* @__PURE__ */ jsxs("span", {
3432
3693
  className: "er-button-with-spinner",
3433
3694
  children: [/* @__PURE__ */ jsx(SpinnerNode, {
3434
3695
  size: "xs",
@@ -3992,6 +4253,31 @@ function resolveTicketSelectionPricing(event) {
3992
4253
  currency: event ? publicEventPricingCurrency(event.pricing) : null
3993
4254
  };
3994
4255
  }
4256
+ function CheckoutRecoveryEntry(props) {
4257
+ return props.onContinue ? /* @__PURE__ */ jsx("button", {
4258
+ type: "button",
4259
+ className: "er-back-btn",
4260
+ onClick: props.onContinue,
4261
+ children: "Continue an existing booking"
4262
+ }) : null;
4263
+ }
4264
+ function getTicketSelectionCapacity(event, attendanceMode, checkoutRecovery) {
4265
+ if (checkoutRecovery) return {
4266
+ availableSpots: null,
4267
+ isSoldOut: false,
4268
+ canJoinWaitlist: false,
4269
+ eventAvailabilityLabel: null
4270
+ };
4271
+ const source = event ? selectEventCapacitySource(event, attendanceMode) : null;
4272
+ const availability = source ? getEventAvailability(source) : null;
4273
+ const canJoinWaitlist = source ? canJoinEventWaitlist(source) : false;
4274
+ return {
4275
+ availableSpots: availability?.available,
4276
+ isSoldOut: availability?.isFull ?? false,
4277
+ canJoinWaitlist,
4278
+ eventAvailabilityLabel: !canJoinWaitlist && source ? formatRemainingPlaces(source) : null
4279
+ };
4280
+ }
3995
4281
  /**
3996
4282
  * Ticket Selection Step
3997
4283
  *
@@ -4000,15 +4286,11 @@ function resolveTicketSelectionPricing(event) {
4000
4286
  *
4001
4287
  * Can use either a full PublicEvent or just occurrence context (when on event page).
4002
4288
  */
4003
- const TicketSelectionStep = ({ event, occurrenceContext: _occurrenceContext, selectedAttendanceMode = null, onAttendanceModeChange, ticketsCount, maxTickets, visibleTicketTypes: visibleTicketTypesOverride, ticketSelections = [], onTicketSelectionsChange, slidingScale = null, selectedSlidingAmountInput = "", slidingScaleSelectionMessage = null, onSlidingAmountChange, onTicketsChange, bookingUnit = { kind: "ticket" } }) => {
4289
+ const TicketSelectionStep = ({ event, occurrenceContext: _occurrenceContext, selectedAttendanceMode = null, onAttendanceModeChange, ticketsCount, maxTickets, visibleTicketTypes: visibleTicketTypesOverride, ticketSelections = [], onTicketSelectionsChange, slidingScale = null, selectedSlidingAmountInput = "", slidingScaleSelectionMessage = null, onSlidingAmountChange, onTicketsChange, bookingUnit = { kind: "ticket" }, checkoutRecovery = false, onCheckoutRecovery }) => {
4004
4290
  const unit = bookingUnit.kind;
4005
4291
  const deliveryMode = event?.deliveryMode ?? "in_person";
4006
4292
  const attendanceModes = event?.attendanceModes ?? [];
4007
- const capacitySource = event ? selectEventCapacitySource(event, selectedAttendanceMode) : null;
4008
- const availability = capacitySource ? getEventAvailability(capacitySource) : null;
4009
- const availableSpots = availability?.available;
4010
- const isSoldOut = availability?.isFull ?? false;
4011
- const canJoinWaitlist = capacitySource ? canJoinEventWaitlist(capacitySource) : false;
4293
+ const { availableSpots, isSoldOut, canJoinWaitlist, eventAvailabilityLabel } = getTicketSelectionCapacity(event, selectedAttendanceMode, checkoutRecovery);
4012
4294
  const { mode: eventPricingMode, currency: eventPricingCurrency } = resolveTicketSelectionPricing(event);
4013
4295
  const usesTicketTypes = eventPricingMode === "tiered" && !canJoinWaitlist;
4014
4296
  const visibleTicketTypes = usesTicketTypes ? visibleTicketTypesOverride ?? getVisibleTicketTypes({
@@ -4027,7 +4309,6 @@ const TicketSelectionStep = ({ event, occurrenceContext: _occurrenceContext, sel
4027
4309
  selectedTicketTypeRemainingCapacity: implicitTicketType?.availability.remainingPlaces ?? null,
4028
4310
  hasSelectedTicketType: implicitTicketType !== null
4029
4311
  });
4030
- const eventAvailabilityLabel = !canJoinWaitlist && capacitySource ? formatRemainingPlaces(capacitySource) : null;
4031
4312
  if (deliveryMode === "hybrid" && !selectedAttendanceMode) return /* @__PURE__ */ jsxs("div", {
4032
4313
  className: "rb-reg-stack er-stack",
4033
4314
  children: [
@@ -4048,13 +4329,17 @@ const TicketSelectionStep = ({ event, occurrenceContext: _occurrenceContext, sel
4048
4329
  });
4049
4330
  if (isSoldOut && !canJoinWaitlist) return /* @__PURE__ */ jsxs("div", {
4050
4331
  className: "rb-reg-stack er-stack",
4051
- children: [/* @__PURE__ */ jsx("h3", {
4052
- className: "er-title",
4053
- children: "Sold out"
4054
- }), /* @__PURE__ */ jsx("p", {
4055
- className: "er-text er-text--muted",
4056
- children: "Sorry you missed out! This event is fully booked."
4057
- })]
4332
+ children: [
4333
+ /* @__PURE__ */ jsx("h3", {
4334
+ className: "er-title",
4335
+ children: "Sold out"
4336
+ }),
4337
+ /* @__PURE__ */ jsx("p", {
4338
+ className: "er-text er-text--muted",
4339
+ children: "Sorry you missed out! This event is fully booked."
4340
+ }),
4341
+ /* @__PURE__ */ jsx(CheckoutRecoveryEntry, { onContinue: onCheckoutRecovery })
4342
+ ]
4058
4343
  });
4059
4344
  if (!eventPricingCurrency) return /* @__PURE__ */ jsx("div", {
4060
4345
  className: "rb-reg-stack er-stack",
@@ -4122,9 +4407,13 @@ const TicketSelectionStep = ({ event, occurrenceContext: _occurrenceContext, sel
4122
4407
  })]
4123
4408
  })
4124
4409
  ] }),
4125
- canJoinWaitlist && /* @__PURE__ */ jsx("p", {
4410
+ canJoinWaitlist && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
4126
4411
  className: "er-text er-text--muted",
4127
4412
  children: "This event is currently full. Continue to join the waitlist if a place opens up."
4413
+ }), /* @__PURE__ */ jsx(CheckoutRecoveryEntry, { onContinue: onCheckoutRecovery })] }),
4414
+ checkoutRecovery && /* @__PURE__ */ jsx("p", {
4415
+ className: "er-text er-text--muted",
4416
+ children: "Enter the details from your earlier booking. We’ll check your checkout before continuing to payment."
4128
4417
  })
4129
4418
  ]
4130
4419
  });
@@ -5032,12 +5321,14 @@ function EventRegistrationWizardContent(props) {
5032
5321
  onBookForSomeoneElse: wizard.handleBookForSomeoneElse
5033
5322
  }), /* @__PURE__ */ jsx(TicketSelectionStep, {
5034
5323
  event: wizard.selectedEvent,
5324
+ checkoutRecovery: wizard.checkoutRecovery,
5325
+ onCheckoutRecovery: canRecoverEventCheckout(wizard.selectedEvent) ? wizard.startCheckoutRecovery : void 0,
5035
5326
  occurrenceContext: wizard.occurrenceContext,
5036
5327
  selectedAttendanceMode: wizard.selectedAttendanceMode,
5037
5328
  onAttendanceModeChange: wizard.setSelectedAttendanceMode,
5038
5329
  ticketsCount: wizard.ticketsCount,
5039
5330
  maxTickets: wizard.maxTicketsNum,
5040
- visibleTicketTypes: wizard.eligibility ? wizard.visibleTicketTypes : void 0,
5331
+ visibleTicketTypes: wizard.visibleTicketTypes,
5041
5332
  ticketSelections: wizard.selectedTicketLines,
5042
5333
  onTicketSelectionsChange: wizard.setSelectedTicketLines,
5043
5334
  slidingScale: wizard.selectedEventSlidingScale,
@@ -5056,66 +5347,6 @@ function EventRegistrationWizardContent(props) {
5056
5347
  }
5057
5348
  }
5058
5349
  //#endregion
5059
- //#region ../blocks/src/system/runtime/nodes/event-registration/StepIndicator.tsx
5060
- /**
5061
- * Step indicator component for the event registration wizard.
5062
- * Thin wrapper around the shared StepIndicator: styled by the shared
5063
- * registration-surface classes, with 'er'-prefixed classes kept in the
5064
- * markup as the stable hook surface for per-site theme CSS.
5065
- */
5066
- function StepIndicator(props) {
5067
- return /* @__PURE__ */ jsx(StepIndicator$1, {
5068
- ...props,
5069
- classPrefix: "er",
5070
- emitSharedClasses: true
5071
- });
5072
- }
5073
- //#endregion
5074
- //#region ../blocks/src/system/runtime/nodes/event-registration/ErrorStep.tsx
5075
- /**
5076
- * Error Step
5077
- *
5078
- * Displays an error message with a retry button when registration fails.
5079
- */
5080
- const labels = {
5081
- none: "",
5082
- retry: "Try again",
5083
- places: "Choose places",
5084
- start: "Start again",
5085
- details: "Check my details",
5086
- "payment-options": "View payment options",
5087
- "payment-status": "Check payment status",
5088
- portal: "View my bookings",
5089
- event: "View event"
5090
- };
5091
- const ErrorStep = ({ message, onRetry, action = "retry", canJoinWaitlist = false }) => {
5092
- const offerWaitlist = action === "places" && canJoinWaitlist;
5093
- return /* @__PURE__ */ jsx(TerminalPanel, {
5094
- tone: "error",
5095
- className: "er-center",
5096
- titleClassName: "er-title--lg er-message",
5097
- icon: /* @__PURE__ */ jsx(StateIcon, {
5098
- variant: "error",
5099
- children: /* @__PURE__ */ jsx(CrossIcon, {})
5100
- }),
5101
- title: "We couldn’t complete your booking",
5102
- body: /* @__PURE__ */ jsx("p", {
5103
- className: "er-text--muted er-message",
5104
- children: offerWaitlist ? "Sorry, this event is now full. You can join the waiting list, and we’ll email you if a place becomes available." : message
5105
- }),
5106
- actions: action === "none" ? void 0 : action === "portal" || action === "payment-status" ? /* @__PURE__ */ jsx("a", {
5107
- href: "/portal",
5108
- className: "er-retry-btn",
5109
- children: labels[action]
5110
- }) : /* @__PURE__ */ jsx("button", {
5111
- type: "button",
5112
- onClick: onRetry,
5113
- className: "er-retry-btn",
5114
- children: offerWaitlist ? "Join the waiting list" : labels[action]
5115
- })
5116
- });
5117
- };
5118
- //#endregion
5119
5350
  //#region ../blocks/src/system/runtime/nodes/event-registration/PaymentFailedStep.tsx
5120
5351
  /**
5121
5352
  * Payment Failed Step
@@ -5146,6 +5377,21 @@ const PaymentFailedStep = ({ onRetry }) => {
5146
5377
  });
5147
5378
  };
5148
5379
  //#endregion
5380
+ //#region ../blocks/src/system/runtime/nodes/event-registration/StepIndicator.tsx
5381
+ /**
5382
+ * Step indicator component for the event registration wizard.
5383
+ * Thin wrapper around the shared StepIndicator: styled by the shared
5384
+ * registration-surface classes, with 'er'-prefixed classes kept in the
5385
+ * markup as the stable hook surface for per-site theme CSS.
5386
+ */
5387
+ function StepIndicator(props) {
5388
+ return /* @__PURE__ */ jsx(StepIndicator$1, {
5389
+ ...props,
5390
+ classPrefix: "er",
5391
+ emitSharedClasses: true
5392
+ });
5393
+ }
5394
+ //#endregion
5149
5395
  //#region ../blocks/src/system/runtime/nodes/event-registration/SuccessStep.tsx
5150
5396
  /**
5151
5397
  * Success Step
@@ -5418,7 +5664,8 @@ function EventRegistrationSurface(props) {
5418
5664
  }), /* @__PURE__ */ jsx(EventRegistrationTerminalState, {
5419
5665
  wizard,
5420
5666
  supportEmail: props.supportEmail,
5421
- successMessage: props.successMessage
5667
+ successMessage: props.successMessage,
5668
+ buttonClass: props.buttonClass
5422
5669
  })]
5423
5670
  });
5424
5671
  }
@@ -5816,6 +6063,84 @@ function RegistrationClosedState({ title, body }) {
5816
6063
  });
5817
6064
  }
5818
6065
  //#endregion
6066
+ //#region ../blocks/src/system/runtime/nodes/event-registration/useEventSourceRecovery.ts
6067
+ const RECOVERY_DELAYS_MS = [
6068
+ 0,
6069
+ 250,
6070
+ 750
6071
+ ];
6072
+ const defaultRecoveryDeps = {
6073
+ useApi: useBlockApi,
6074
+ wait: waitForRetry
6075
+ };
6076
+ function useEventSourceRecovery(source, deps = defaultRecoveryDeps) {
6077
+ const api = deps.useApi();
6078
+ const wait = deps.wait;
6079
+ const [cycle, setCycle] = useState(0);
6080
+ const [state, setState] = useState(() => source.kind === "loaded" ? {
6081
+ kind: "ready",
6082
+ events: source.events
6083
+ } : { kind: "loading" });
6084
+ const retry = useCallback(() => {
6085
+ setState({ kind: "loading" });
6086
+ setCycle((value) => value + 1);
6087
+ }, []);
6088
+ useEffect(() => {
6089
+ if (source.kind === "loaded") {
6090
+ setState({
6091
+ kind: "ready",
6092
+ events: source.events
6093
+ });
6094
+ return;
6095
+ }
6096
+ if (!source.request) {
6097
+ setState({
6098
+ kind: "exhausted",
6099
+ retry
6100
+ });
6101
+ return;
6102
+ }
6103
+ const controller = new AbortController();
6104
+ const isCurrent = () => !controller.signal.aborted;
6105
+ (async () => {
6106
+ for (const delayMs of RECOVERY_DELAYS_MS) try {
6107
+ await wait(delayMs, controller.signal);
6108
+ const events = await api.getPublicEvents(source.request ?? void 0);
6109
+ if (isCurrent()) setState({
6110
+ kind: "ready",
6111
+ events
6112
+ });
6113
+ return;
6114
+ } catch {
6115
+ if (!isCurrent()) return;
6116
+ }
6117
+ if (isCurrent()) setState({
6118
+ kind: "exhausted",
6119
+ retry
6120
+ });
6121
+ })();
6122
+ return () => controller.abort();
6123
+ }, [
6124
+ api,
6125
+ cycle,
6126
+ retry,
6127
+ source,
6128
+ wait
6129
+ ]);
6130
+ return state;
6131
+ }
6132
+ function waitForRetry(milliseconds, signal) {
6133
+ if (signal.aborted) return Promise.reject(/* @__PURE__ */ new Error("Recovery aborted"));
6134
+ if (milliseconds === 0) return Promise.resolve();
6135
+ return new Promise((resolve, reject) => {
6136
+ const timeout = setTimeout(resolve, milliseconds);
6137
+ signal.addEventListener("abort", () => {
6138
+ clearTimeout(timeout);
6139
+ reject(/* @__PURE__ */ new Error("Recovery aborted"));
6140
+ }, { once: true });
6141
+ });
6142
+ }
6143
+ //#endregion
5819
6144
  //#region ../blocks/src/system/runtime/nodes/event-registration.client.tsx
5820
6145
  function toEventRegistrationClientProps(props, display) {
5821
6146
  return {
@@ -5849,8 +6174,71 @@ const EventRegistrationIslandClient = (props) => {
5849
6174
  title: props.render.display.titleText,
5850
6175
  body: props.render.display.bodyText
5851
6176
  });
5852
- return /* @__PURE__ */ jsx(EventRegistrationClient, { ...toEventRegistrationClientProps(props, props.render.display) });
6177
+ return /* @__PURE__ */ jsx(RecoverableEventRegistrationClient, {
6178
+ props,
6179
+ display: props.render.display
6180
+ });
5853
6181
  };
6182
+ function RecoverableEventRegistrationClient({ props, display }) {
6183
+ const recovery = useEventSourceRecovery(props.render.hydration.eventSource);
6184
+ if (recovery.kind === "loading") return /* @__PURE__ */ jsxs("div", {
6185
+ id: EVENT_REGISTRATION_ANCHOR_ID,
6186
+ className: "rb-reg-surface er-container er-registration-shell",
6187
+ "aria-busy": "true",
6188
+ role: "status",
6189
+ children: [
6190
+ /* @__PURE__ */ jsx("p", {
6191
+ className: "er-registration-shell__eyebrow",
6192
+ children: "Registration"
6193
+ }),
6194
+ /* @__PURE__ */ jsx("h3", {
6195
+ className: "er-title er-registration-shell__title",
6196
+ children: display.titleText
6197
+ }),
6198
+ /* @__PURE__ */ jsx("p", {
6199
+ className: "er-text er-text--muted",
6200
+ children: "Loading event dates…"
6201
+ }),
6202
+ /* @__PURE__ */ jsxs("div", {
6203
+ className: "er-event-grid er-registration-shell__cards",
6204
+ "aria-hidden": "true",
6205
+ children: [/* @__PURE__ */ jsx("div", { className: "er-event-card er-registration-shell__card" }), /* @__PURE__ */ jsx("div", { className: "er-event-card er-registration-shell__card" })]
6206
+ })
6207
+ ]
6208
+ });
6209
+ if (recovery.kind === "exhausted") return /* @__PURE__ */ jsxs("div", {
6210
+ id: EVENT_REGISTRATION_ANCHOR_ID,
6211
+ className: "rb-reg-surface er-container er-registration-shell",
6212
+ role: "alert",
6213
+ children: [/* @__PURE__ */ jsx("p", { children: "We couldn’t load the event dates. Please try again." }), /* @__PURE__ */ jsx("button", {
6214
+ type: "button",
6215
+ className: themeButtonClassName({
6216
+ variant: props.render.hydration.buttonVariant ?? "primary",
6217
+ size: "md"
6218
+ }),
6219
+ onClick: recovery.retry,
6220
+ children: "Try again"
6221
+ })]
6222
+ });
6223
+ const events = resolveEventRegistrationScopedEvents(recovery.events, {
6224
+ occurrenceContext: props.render.hydration.occurrenceContext,
6225
+ subject: props.render.hydration.subject
6226
+ });
6227
+ const recoveredDisplay = buildEventRegistrationDisplayFromScopedEvents({
6228
+ ...props.render.hydration,
6229
+ events,
6230
+ className: display.className,
6231
+ buttonText: display.summaryButtonText
6232
+ }, events);
6233
+ if (recoveredDisplay.state === "registration-closed") return /* @__PURE__ */ jsx(RegistrationClosedState, {
6234
+ title: recoveredDisplay.titleText,
6235
+ body: recoveredDisplay.bodyText
6236
+ });
6237
+ return /* @__PURE__ */ jsx(EventRegistrationClient, {
6238
+ ...toEventRegistrationClientProps(props, display),
6239
+ events
6240
+ });
6241
+ }
5854
6242
  //#endregion
5855
6243
  //#region src/rendering/islands/enhancers/eventRegistration.tsx
5856
6244
  const decode = defineIslandPropsDecoder("event-registration");