@riverbankcms/sdk 0.139.0 → 0.141.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 (232) hide show
  1. package/README.md +1 -1
  2. package/dist/{PreviewEditorSidebar-BDeenhi3.mjs → PreviewEditorSidebar-Q-fy9GYw.mjs} +4 -4
  3. package/dist/{PreviewEditorUI-DSRhgjF5.mjs → PreviewEditorUI-LYGzgk85.mjs} +3 -3
  4. package/dist/{PreviewQueryProvider-D2K8GLUG.mjs → PreviewQueryProvider-CN0ewic5.mjs} +1 -1
  5. package/dist/{SdkPreviewModeRuntime-CL7wSnYu.mjs → SdkPreviewModeRuntime-CoPYI5Jq.mjs} +90 -50
  6. package/dist/{SiteChromeCustomizeContext-BhDn-5ir.mjs → SiteChromeCustomizeContext-D8LePX8x.mjs} +2731 -1303
  7. package/dist/_dts/ai/src/contracts/proposals.d.ts +165 -165
  8. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +212 -212
  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 +8 -4
  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 +17 -31
  20. package/dist/_dts/api/src/domainConnection.d.ts +4 -0
  21. package/dist/_dts/api/src/endpoints.d.ts +93 -64
  22. package/dist/_dts/api/src/event-destination-policy.d.ts +2 -1
  23. package/dist/_dts/api/src/footerCompositionContracts.d.ts +25 -0
  24. package/dist/_dts/api/src/footerSettings.d.ts +9 -6
  25. package/dist/_dts/api/src/index.d.ts +6 -7
  26. package/dist/_dts/api/src/indexCoreTypes.d.ts +1 -1
  27. package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -1
  28. package/dist/_dts/api/src/launchReadiness.d.ts +1 -0
  29. package/dist/_dts/api/src/mailingListIntegration.d.ts +8 -2
  30. package/dist/_dts/api/src/navigation/dashboardSettingsNav.d.ts +1 -1
  31. package/dist/_dts/api/src/navigation/dashboardSiteNav.d.ts +2 -1
  32. package/dist/_dts/api/src/navigation/types.d.ts +1 -1
  33. package/dist/_dts/api/src/onboarding/confirmationResend.d.ts +25 -0
  34. package/dist/_dts/api/src/onboarding/surfaceData.d.ts +32 -32
  35. package/dist/_dts/api/src/publicBookingAvailabilityEndpointDefinitions.d.ts +8 -0
  36. package/dist/_dts/api/src/publicExperience/commerceEndpoints.d.ts +1 -0
  37. package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +11 -3
  38. package/dist/_dts/api/src/publicExperience/sharedTypes.d.ts +3 -29
  39. package/dist/_dts/api/src/publicOnboardingAttemptEndpointDefinitions.d.ts +65 -0
  40. package/dist/_dts/api/src/saveOutcome.d.ts +20 -0
  41. package/dist/_dts/api/src/sdkContracts.d.ts +3 -22
  42. package/dist/_dts/api/src/sdkPushContracts.d.ts +18 -0
  43. package/dist/_dts/api/src/sdkThemeWire.d.ts +44 -44
  44. package/dist/_dts/api/src/settings/permissions.d.ts +12 -0
  45. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +10 -29
  46. package/dist/_dts/api/src/siteOnboarding.d.ts +9 -9
  47. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +2 -4
  48. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +3 -1
  49. package/dist/_dts/api/src/siteSettings.d.ts +20 -7
  50. package/dist/_dts/api/src/types.d.ts +77 -77
  51. package/dist/_dts/api/src/wholeSeriesRuns.d.ts +2 -37
  52. package/dist/_dts/billing/src/membership/index.d.ts +3 -0
  53. package/dist/_dts/billing/src/plans/types.d.ts +3 -0
  54. package/dist/_dts/billing/src/site-arrangements.d.ts +23 -3
  55. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +20 -4
  56. package/dist/_dts/blocks/src/pageRenderAdmission.d.ts +2 -0
  57. package/dist/_dts/blocks/src/pageRendererContracts.d.ts +7 -0
  58. package/dist/_dts/blocks/src/portal/types.d.ts +2 -4
  59. package/dist/_dts/blocks/src/portal/waitlist-types.d.ts +35 -0
  60. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +2 -0
  61. package/dist/_dts/blocks/src/system/blocks/events/event-calendar.d.ts +2 -0
  62. package/dist/_dts/blocks/src/system/blocks/events/eventSelectionFields.d.ts +122 -0
  63. package/dist/_dts/blocks/src/system/blocks/events/shared/calendarWindow.d.ts +2 -1
  64. package/dist/_dts/blocks/src/system/blocks/events/shared/eventSelection.d.ts +11 -0
  65. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +42 -0
  66. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +4 -0
  67. package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +2 -2
  68. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +47 -47
  69. package/dist/_dts/blocks/src/system/data/index.d.ts +2 -2
  70. package/dist/_dts/blocks/src/system/data/prefetchBlockData.d.ts +7 -1
  71. package/dist/_dts/blocks/src/system/data/types.d.ts +9 -0
  72. package/dist/_dts/blocks/src/system/data/utils.d.ts +1 -1
  73. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +27 -1
  74. package/dist/_dts/blocks/src/system/registry.d.ts +1 -0
  75. package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +0 -28
  76. package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
  77. package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +7 -3
  78. package/dist/_dts/blocks/src/system/runtime/api/types/portal.d.ts +1 -1
  79. package/dist/_dts/blocks/src/system/runtime/api/types/waitlist-claims.d.ts +7 -2
  80. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +42 -186
  81. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +21 -93
  82. package/dist/_dts/blocks/src/system/runtime/hooks/useEventFilters.d.ts +2 -1
  83. package/dist/_dts/blocks/src/system/runtime/nodes/appointment-services.d.ts +48 -1
  84. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationSurface.d.ts +1 -2
  85. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/TicketSelectionStep.d.ts +2 -0
  86. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/checkoutRecovery.d.ts +14 -0
  87. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventSourceRecovery.d.ts +56 -0
  88. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.d.ts +4 -0
  89. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.state.d.ts +5 -0
  90. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +6 -8
  91. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useCheckoutRecovery.d.ts +8 -0
  92. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useDiscountCodeUi.d.ts +3 -0
  93. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useDiscountCodeUi.state.d.ts +10 -3
  94. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventCheckoutHandoffRestore.d.ts +9 -0
  95. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +8 -7
  96. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +14 -7
  97. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventSourceRecovery.d.ts +18 -0
  98. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useSettledCommerceView.d.ts +37 -0
  99. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.client.d.ts +1 -1
  100. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +24 -6
  101. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.server.d.ts +4 -2
  102. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +4 -3
  103. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.interactive.d.ts +3 -0
  104. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventListing.interactive.d.ts +11 -101
  105. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +7 -2
  106. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/listOptions.d.ts +2 -0
  107. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.interactive.d.ts +6 -0
  108. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.types.d.ts +1 -0
  109. package/dist/_dts/blocks/src/system/runtime/resolver.d.ts +1 -0
  110. package/dist/_dts/blocks/src/system/runtime/shared/components/index.d.ts +2 -6
  111. package/dist/_dts/blocks/src/system/runtime/shared/index.d.ts +2 -2
  112. package/dist/_dts/blocks/src/system/runtime/shared/useWaitlistClaim.d.ts +2 -0
  113. package/dist/_dts/blocks/src/system/transforms/registry/eventCalendar.d.ts +12 -0
  114. package/dist/_dts/commerce/src/purchase/bookingInstalmentSchedule.d.ts +4 -0
  115. package/dist/_dts/commerce/src/purchase/event-registration-errors.d.ts +4 -0
  116. package/dist/_dts/commerce/src/purchase/orderItemMetadata.d.ts +27 -4
  117. package/dist/_dts/content-editor/src/controller/EntryControllerProvider.d.ts +2 -1
  118. package/dist/_dts/content-editor/src/hooks/useBlockAutosave.d.ts +3 -1
  119. package/dist/_dts/content-editor/src/useFooterComposerState.d.ts +3 -0
  120. package/dist/_dts/core/src/branded.d.ts +0 -8
  121. package/dist/_dts/core/src/index.d.ts +1 -0
  122. package/dist/_dts/core/src/mailing-list-setup-parser.d.ts +1 -1
  123. package/dist/_dts/core/src/mailing-list-setup.d.ts +14 -1
  124. package/dist/_dts/core/src/mailing-list-submission.d.ts +7 -27
  125. package/dist/_dts/core/src/participants.d.ts +2 -29
  126. package/dist/_dts/core/src/public-experience.d.ts +4 -0
  127. package/dist/_dts/core/src/public-profile.d.ts +27 -1
  128. package/dist/_dts/core/src/site-route-target.d.ts +9 -2
  129. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +296 -606
  130. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/MailingListGlobalSettingsSummary.d.ts +10 -0
  131. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/MailingListTargetingField.d.ts +3 -2
  132. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/context.d.ts +3 -2
  133. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/loaders.d.ts +3 -2
  134. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/targetingState.d.ts +19 -0
  135. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/loaders.d.ts +27 -1
  136. package/dist/_dts/sdk/src/public-api/contracts.d.ts +14 -20
  137. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +2 -0
  138. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +2 -0
  139. package/dist/_dts/sdk/src/rendering/helpers/pageRuntimeSupport.d.ts +7 -1
  140. package/dist/_dts/sdk/src/rendering/helpers/templateContent.d.ts +1 -0
  141. package/dist/_dts/sdk/src/version.d.ts +1 -1
  142. package/dist/_dts/theme-core/src/ThemeFontLoader.d.ts +17 -1
  143. package/dist/_dts/theme-core/src/accordions/types.d.ts +3 -3
  144. package/dist/_dts/theme-core/src/buttons/affordanceSuppression.d.ts +17 -0
  145. package/dist/_dts/theme-core/src/buttons/buttonColourContract.d.ts +1 -1
  146. package/dist/_dts/theme-core/src/buttons/classNames.d.ts +16 -0
  147. package/dist/_dts/theme-core/src/buttons/generateButtonCss.d.ts +0 -6
  148. package/dist/_dts/theme-core/src/buttons/resolvedButtonCss.d.ts +4 -4
  149. package/dist/_dts/theme-core/src/cards/types.d.ts +21 -21
  150. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  151. package/dist/_dts/theme-core/src/header/interactionPalette.d.ts +8 -2
  152. package/dist/_dts/theme-core/src/header/legacyHeaderVariant.d.ts +2 -2
  153. package/dist/_dts/theme-core/src/hosted-booking-appearance.d.ts +54 -12
  154. package/dist/_dts/theme-core/src/index.d.ts +1 -1
  155. package/dist/_dts/theme-core/src/inputs/types.d.ts +2 -2
  156. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +54 -54
  157. package/dist/_dts/theme-core/src/runtime/buildThemeRuntimeFromBridge.d.ts +1 -4
  158. package/dist/_dts/theme-core/src/schema.d.ts +84 -84
  159. package/dist/_dts/theme-core/src/shared/componentStyles.d.ts +1 -1
  160. package/dist/_dts/theme-core/src/site-styles/backgroundAppearance.d.ts +2 -2
  161. package/dist/_dts/theme-core/src/surfaces/foregroundInteraction.d.ts +77 -0
  162. package/dist/_dts/theme-core/src/surfaces/index.d.ts +1 -0
  163. package/dist/_dts/theme-core/src/typography/generateTypographyCss.d.ts +2 -2
  164. package/dist/_dts/ui/src/lib/use-delayed-flag.d.ts +9 -0
  165. package/dist/_dts/ui/src/pending-button.d.ts +10 -0
  166. package/dist/client/{BookingConsentAgreement-CZvTDtsK.mjs → BookingConsentAgreement-xJeYNdnb.mjs} +4 -4
  167. package/dist/client/{DiscountCodeDisclosure-D-DsLCMU.mjs → DiscountCodeDisclosure-DdT6uzl9.mjs} +1 -1
  168. package/dist/client/{EventCombined.client-dWqgd5ZO.mjs → EventCombined.client-Cp28uYuM.mjs} +12 -16
  169. package/dist/client/{EventListing.client-BMRa9IYp.mjs → EventListing.client-CD6AJsMr.mjs} +4 -17
  170. package/dist/client/{LeafletStaticMap-D21W9kBZ.mjs → LeafletStaticMap-DBsAi9-e.mjs} +1 -1
  171. package/dist/client/{accordion-FxF_ta47.mjs → accordion-6dwbOKYR.mjs} +1 -1
  172. package/dist/client/{bookingForm-YnwW4TGw.mjs → bookingForm-CZE9_qPQ.mjs} +7 -7
  173. package/dist/client/bookings.mjs +500 -233
  174. package/dist/client/{carousel-vng7fFT5.mjs → carousel-7VHGQARz.mjs} +2 -2
  175. package/dist/client/{carousel.client-59G_WMr4.mjs → carousel.client-DQTjCVQT.mjs} +1 -1
  176. package/dist/client/{cart-DEPDsjNk.mjs → cart-Qg_mvQhh.mjs} +3 -3
  177. package/dist/client/{checkout-CZRWu9rW.mjs → checkout-D84rpgdr.mjs} +3 -3
  178. package/dist/client/{checkoutUrls-BuseL0dw.mjs → checkoutUrls-FL6lRkrt.mjs} +1 -1
  179. package/dist/client/client.mjs +2315 -1017
  180. package/dist/client/{colorStyles-CrxJrPjJ.mjs → colorStyles-3013aRAY.mjs} +3 -1
  181. package/dist/client/{context-DvU_WUmd.mjs → context-Ctp3T0Wr.mjs} +6 -19
  182. package/dist/client/{dates-wnPMiRl5.mjs → dates-DJKFcI_N.mjs} +2 -2
  183. package/dist/client/{eventCalendar-BA3Q5L15.mjs → eventCalendar-CK31z3vs.mjs} +12 -8
  184. package/dist/client/{eventCombined-51wgR-1R.mjs → eventCombined-DiXd-ewn.mjs} +3 -3
  185. package/dist/client/{eventDetails-modaetpm.mjs → eventDetails-CTRgt2DK.mjs} +4 -4
  186. package/dist/client/{eventListing-D8t2J3Kv.mjs → eventListing-Dy9vi_j_.mjs} +3 -3
  187. package/dist/client/{eventRegistration-CYqtkCE_.mjs → eventRegistration-CnalYMr2.mjs} +618 -177
  188. package/dist/client/{form-CBKXN5In.mjs → form-eUiMveTT.mjs} +3 -3
  189. package/dist/client/{headerSection-DylDqNrs.mjs → headerSection-Dy9kQpB1.mjs} +2 -2
  190. package/dist/client/hooks.mjs +692 -212
  191. package/dist/client/{locationMap-CvWrG0vZ.mjs → locationMap-DalCmWU0.mjs} +3 -3
  192. package/dist/client/{media-BOHuueS5.mjs → media-DHpfFwd3.mjs} +1 -1
  193. package/dist/client/{newsletterForm-Btwk70zw.mjs → newsletterForm-SDDPvhS0.mjs} +150 -94
  194. package/dist/client/{pricing-Uzw-GQ6Y.mjs → pricing-OcMz4SnX.mjs} +1 -1
  195. package/dist/client/{productDetail-JLcUYKnd.mjs → productDetail-BQrgHElM.mjs} +3 -3
  196. package/dist/client/{productList-FM0cbUzj.mjs → productList-OnPn_UJj.mjs} +3 -3
  197. package/dist/client/{propsDecoder-DYzafZb2.mjs → propsDecoder-zBdsnS-N.mjs} +168 -32
  198. package/dist/client/rendering/client.mjs +1355 -519
  199. package/dist/client/rendering/islands.mjs +19 -19
  200. package/dist/client/rendering.mjs +2294 -953
  201. package/dist/client/{scrollToBlock-CvXszexS.mjs → scrollToBlock-BNM4Ob2Y.mjs} +28 -11
  202. package/dist/client/{shop-BIcjvy5a.mjs → shop-Bv1fPTwQ.mjs} +6 -6
  203. package/dist/client/{shop-commerce-BZQsy7xw.mjs → shop-commerce-D4KNGaW8.mjs} +7 -7
  204. package/dist/client/{shop-commerce-store-D5V7XAb5.mjs → shop-commerce-store-2N5EV0Rc.mjs} +1 -1
  205. package/dist/client/{shopShared-DowkXevB.mjs → shopShared-DvJGdHTV.mjs} +4 -4
  206. package/dist/client/{useEventFilters-oMoTw_JE.mjs → useEventFilters-BBBvGDHQ.mjs} +19 -13
  207. package/dist/preview-next/before-render.mjs +119 -64
  208. package/dist/preview-next/client/runtime.mjs +4 -4
  209. package/dist/preview-next/editor-chrome.css +4 -8
  210. package/dist/preview-next/keepAlive.mjs +119 -64
  211. package/dist/preview-next/middleware.mjs +119 -64
  212. package/dist/{previewAuthStore-COUyAKaX.mjs → previewAuthStore-Gjb6r6vz.mjs} +119 -64
  213. package/dist/{sdk-runtime-D4k2LSGF.mjs → sdk-runtime-Defnbfzw.mjs} +2 -2
  214. package/dist/{separator-UGtpag4Z.mjs → separator-CZXO3Sb0.mjs} +1 -1
  215. package/dist/server/components.mjs +1170 -384
  216. package/dist/server/config-validation.mjs +560 -105
  217. package/dist/server/config.mjs +564 -109
  218. package/dist/server/data.mjs +688 -212
  219. package/dist/server/index.mjs +126 -66
  220. package/dist/server/next.mjs +1429 -662
  221. package/dist/server/page-converter.mjs +372 -99
  222. package/dist/server/prebuild.mjs +1 -1
  223. package/dist/server/rendering/server.mjs +1624 -817
  224. package/dist/server/rendering.mjs +1200 -391
  225. package/dist/server/routing.mjs +767 -247
  226. package/dist/server/server.mjs +715 -276
  227. package/dist/server/theme-bridge.mjs +475 -110
  228. package/dist/server/theme.mjs +9 -3
  229. package/dist/styles/index.css +265 -45
  230. package/package.json +1 -1
  231. package/dist/_dts/blocks/src/system/runtime/shared/components/BookingOptionCompactRow.d.ts +0 -29
  232. package/dist/_dts/blocks/src/system/runtime/shared/components/BookingOptionList.d.ts +0 -13
@@ -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-CZvTDtsK.mjs";
3
- import { C as WIZARD_STEPS, Jt as formatBookingTime, Kt as formatBookingDateTime, Nt as assertNever, O as resolveEventRegistrationScopedEvents, S as resolveRegistrationTarget, T as getWizardStepsForContext, Wt as formatBookingDate, _ as toWholeSeriesRegistrationEvents, at as groupPublicEventsByRun, b as resolveDiscountContext, cn as publicEventPricingOptions, dn as formatCurrencyAmount, en as toBookingTimeZone, fn as parseCurrencyCode, g as toRegistrationEvents, h as getRegistrationStartAt, ln as publicEventPricingStrategy, nn as toScheduledBookingDateTime, on as publicEventPricingCurrency, t as defineIslandPropsDecoder, un as publicEventPricingType, ut as themeButtonClassName, v as findEventByOccurrenceId, w as getStepNumber, x as resolveEventRequiresPayment, y as findPreSelectedEvent } from "./propsDecoder-DYzafZb2.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-Uzw-GQ6Y.mjs";
5
- import { n as useBlockApi, r as BlockApiError, t as BlockApiProvider } from "./context-DvU_WUmd.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-xJeYNdnb.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-zBdsnS-N.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-OcMz4SnX.mjs";
5
+ import { n as useBlockApi, r as BlockApiError, t as BlockApiProvider } from "./context-Ctp3T0Wr.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-CvXszexS.mjs";
8
- import { t as DiscountCodeDisclosure } from "./DiscountCodeDisclosure-D-DsLCMU.mjs";
7
+ import { a as CheckIcon, i as StateIcon, n as useDiscountCodeUi, r as TerminalPanel, t as scrollToBlock } from "./scrollToBlock-BNM4Ob2Y.mjs";
8
+ import { t as DiscountCodeDisclosure } from "./DiscountCodeDisclosure-DdT6uzl9.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";
@@ -858,6 +969,7 @@ function getTicketTypeLineMax(input) {
858
969
  const initialEligibilityLookupState = {
859
970
  tag: "idle",
860
971
  eligibility: null,
972
+ settledRequestKey: null,
861
973
  error: null
862
974
  };
863
975
  function eligibilityLookupReducer(state, action) {
@@ -866,16 +978,19 @@ function eligibilityLookupReducer(state, action) {
866
978
  case "loading-started": return {
867
979
  tag: "loading",
868
980
  eligibility: state.eligibility,
981
+ settledRequestKey: state.settledRequestKey,
869
982
  error: null
870
983
  };
871
984
  case "resolved": return {
872
985
  tag: "resolved",
873
986
  eligibility: action.eligibility,
987
+ settledRequestKey: action.requestKey,
874
988
  error: null
875
989
  };
876
990
  case "failed": return {
877
991
  tag: "failed",
878
992
  eligibility: null,
993
+ settledRequestKey: null,
879
994
  error: action.message
880
995
  };
881
996
  default: return assertNever(action);
@@ -981,9 +1096,23 @@ function toRegistrationOptionsSubject(subject, attendanceMode) {
981
1096
  function useEligibility(params) {
982
1097
  return useEligibilityWithDeps(params, eventRegistrationHooksDeps);
983
1098
  }
1099
+ function eligibilityRequestKey(params) {
1100
+ return JSON.stringify({
1101
+ enabled: params.enabled,
1102
+ refreshKey: params.refreshKey ?? 0,
1103
+ subject: params.subject,
1104
+ attendanceMode: params.attendanceMode ?? null,
1105
+ ticketSelections: params.ticketSelectionsKey,
1106
+ selectedSlidingAmount: params.selectedSlidingAmount ?? null
1107
+ });
1108
+ }
984
1109
  function useEligibilityWithDeps(params, deps) {
985
1110
  const api = deps.useBlockApi();
986
1111
  const ticketSelectionsKey = JSON.stringify(normalizeTicketSelectionLines(params.ticketSelections));
1112
+ const requestKey = eligibilityRequestKey({
1113
+ ...params,
1114
+ ticketSelectionsKey
1115
+ });
987
1116
  const [state, dispatch] = useReducer(eligibilityLookupReducer, initialEligibilityLookupState);
988
1117
  const requestIdRef = useRef(0);
989
1118
  useEffect(() => {
@@ -1016,7 +1145,8 @@ function useEligibilityWithDeps(params, deps) {
1016
1145
  if (cancelled || requestIdRef.current !== requestId) return;
1017
1146
  dispatch({
1018
1147
  type: "resolved",
1019
- eligibility: transformRegistrationOptionsResponse(result)
1148
+ eligibility: transformRegistrationOptionsResponse(result),
1149
+ requestKey
1020
1150
  });
1021
1151
  } catch {
1022
1152
  if (cancelled || requestIdRef.current !== requestId) return;
@@ -1045,6 +1175,8 @@ function useEligibilityWithDeps(params, deps) {
1045
1175
  return {
1046
1176
  state,
1047
1177
  eligibility: state.eligibility,
1178
+ settledRequestKey: state.settledRequestKey,
1179
+ requestKey,
1048
1180
  isLoading: state.tag === "loading",
1049
1181
  error: state.error,
1050
1182
  creditState
@@ -1373,6 +1505,10 @@ const eventRegistrationErrors = {
1373
1505
  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.",
1374
1506
  action: "payment-status"
1375
1507
  },
1508
+ paymentProviderUnavailable: {
1509
+ message: "We couldn’t reach the payment provider. Please try again in a minute.",
1510
+ action: "retry"
1511
+ },
1376
1512
  paymentPageUnavailable: {
1377
1513
  message: "We couldn’t open the payment page. Please refresh this page and try again. If this keeps happening, contact the organiser for help.",
1378
1514
  action: "retry"
@@ -1495,11 +1631,6 @@ function ensureWaitlistClaimLocationTracking() {
1495
1631
  } catch {}
1496
1632
  window.addEventListener("popstate", emitWaitlistClaimLocationChange);
1497
1633
  }
1498
- function getWaitlistClaimTokenFromUrl() {
1499
- if (typeof window === "undefined") return null;
1500
- const token = new URLSearchParams(window.location.search).get("waitlist_claim")?.trim() ?? "";
1501
- return token.length > 0 ? token : null;
1502
- }
1503
1634
  const useWaitlistClaimDeps = { useBlockApi };
1504
1635
  function subscribeToWaitlistClaimToken(callback) {
1505
1636
  if (typeof window === "undefined") return () => {};
@@ -1509,28 +1640,42 @@ function subscribeToWaitlistClaimToken(callback) {
1509
1640
  window.removeEventListener(WAITLIST_CLAIM_LOCATION_EVENT, callback);
1510
1641
  };
1511
1642
  }
1512
- function getWaitlistClaimTokenSnapshot() {
1513
- return getWaitlistClaimTokenFromUrl();
1643
+ function getWaitlistClaimLocationSnapshot() {
1644
+ return typeof window === "undefined" ? "" : window.location.search;
1645
+ }
1646
+ function parseWaitlistClaimCredential(search) {
1647
+ const params = new URLSearchParams(search);
1648
+ const token = params.get("waitlist_claim")?.trim();
1649
+ if (token) return {
1650
+ kind: "emailedToken",
1651
+ token
1652
+ };
1653
+ const entryId = params.get("waitlistEntry")?.trim();
1654
+ return entryId ? {
1655
+ kind: "portalOwnedEntry",
1656
+ entryId
1657
+ } : null;
1514
1658
  }
1515
1659
  function useWaitlistClaim() {
1516
1660
  return useWaitlistClaimWithDeps(useWaitlistClaimDeps);
1517
1661
  }
1518
1662
  function useWaitlistClaimWithDeps(deps) {
1519
- return useResolvedWaitlistClaim(deps, useSyncExternalStore(subscribeToWaitlistClaimToken, getWaitlistClaimTokenSnapshot, () => null));
1663
+ const locationSearch = useSyncExternalStore(subscribeToWaitlistClaimToken, getWaitlistClaimLocationSnapshot, () => "");
1664
+ return useResolvedWaitlistClaim(deps, useMemo(() => parseWaitlistClaimCredential(locationSearch), [locationSearch]));
1520
1665
  }
1521
- function useResolvedWaitlistClaim(deps, token) {
1666
+ function useResolvedWaitlistClaim(deps, credential) {
1522
1667
  const api = deps.useBlockApi();
1523
- const [state, dispatch] = useReducer(waitlistClaimReducer, Boolean(token), createInitialWaitlistClaimState);
1668
+ const [state, dispatch] = useReducer(waitlistClaimReducer, Boolean(credential), createInitialWaitlistClaimState);
1524
1669
  useEffect(() => {
1525
1670
  let cancelled = false;
1526
1671
  async function resolveClaim() {
1527
- if (!token) {
1672
+ if (!credential) {
1528
1673
  dispatch({ type: "cleared" });
1529
1674
  return;
1530
1675
  }
1531
1676
  dispatch({ type: "started" });
1532
1677
  try {
1533
- const result = await api.resolveWaitlistClaim({ claimToken: token });
1678
+ const result = credential.kind === "portalOwnedEntry" ? await api.resolveWaitlistClaim({ waitlistEntryId: credential.entryId }) : await api.resolveWaitlistClaim({ claimToken: credential.token });
1534
1679
  if (cancelled) return;
1535
1680
  dispatch({
1536
1681
  type: "resolved",
@@ -1548,9 +1693,10 @@ function useResolvedWaitlistClaim(deps, token) {
1548
1693
  return () => {
1549
1694
  cancelled = true;
1550
1695
  };
1551
- }, [api, token]);
1696
+ }, [api, credential]);
1552
1697
  return {
1553
- token,
1698
+ token: credential?.kind === "emailedToken" ? credential.token : null,
1699
+ entryId: credential?.kind === "portalOwnedEntry" ? credential.entryId : null,
1554
1700
  claim: getWaitlistClaim(state),
1555
1701
  error: getWaitlistClaimError(state),
1556
1702
  loginMessage: getWaitlistClaimLoginMessage(state),
@@ -2032,15 +2178,12 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
2032
2178
  * landed — a success, or a hand-off to checkout — because until then nobody
2033
2179
  * knows whether the first one committed.
2034
2180
  *
2035
- * Reusing it after a failure is safe even if the customer edits their
2036
- * details. The server consults the command record before it re-checks
2037
- * anything, so a submission that already booked is answered with the booking
2038
- * that exists — not refused for spending a credit or a claim that this very
2039
- * command already spent, and not treated as a second booking because a name
2040
- * or a note changed in between.
2181
+ * Identical retries retain the command after a lost response. Changed form
2182
+ * details get a new command so the server applies the new booking intent.
2041
2183
  */
2042
- const commandIdRef = useRef(null);
2043
- return async (method, passId, membershipId, selection, submitOptions) => {
2184
+ const commandRef = useRef(null);
2185
+ const inFlightRef = useRef(null);
2186
+ const submit = async (method, passId, membershipId, selection, submitOptions) => {
2044
2187
  const target = options.registrationTarget;
2045
2188
  if (!target) return {
2046
2189
  ok: false,
@@ -2048,44 +2191,34 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
2048
2191
  message: "Select an event to continue."
2049
2192
  };
2050
2193
  options.setStep("submitting");
2051
- const registrationCommandId = commandIdRef.current ?? deps.createClientCommandId();
2052
- commandIdRef.current = registrationCommandId;
2194
+ const registrationCommandId = commandRef.current?.id ?? deps.createClientCommandId();
2053
2195
  try {
2054
- const prepared = prepareSubmitContext(options, registrationCommandId, target, method, passId, membershipId, selection);
2196
+ let prepared = prepareSubmitContext(options, registrationCommandId, target, method, passId, membershipId, selection);
2055
2197
  if (prepared.subject.kind === "wholeSeries" && method === "stripe") {
2056
- commandIdRef.current = null;
2198
+ commandRef.current = null;
2057
2199
  return await submitWholeSeriesCheckout(options, deps, {
2058
2200
  ...prepared,
2059
2201
  subject: prepared.subject
2060
2202
  }, submitOptions);
2061
2203
  }
2204
+ const request = buildOccurrenceRegistrationRequest(options, prepared, method, passId, membershipId);
2205
+ const intentKey = registrationRequestIntentKey(request);
2206
+ if (commandRef.current !== null && commandRef.current.intentKey !== intentKey) prepared = {
2207
+ ...prepared,
2208
+ registrationCommandId: deps.createClientCommandId()
2209
+ };
2210
+ commandRef.current = {
2211
+ id: prepared.registrationCommandId,
2212
+ intentKey
2213
+ };
2062
2214
  const result = await options.api.registerForEvent({
2063
- registrationCommandId: prepared.registrationCommandId,
2064
- subject: prepared.subject,
2065
- ticketSelections: toTicketSelectionRequests(prepared.ticketSelections),
2066
- selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
2067
- email: options.formData.email.trim().toLowerCase(),
2068
- name: options.formData.name.trim(),
2069
- phone: options.formData.phone.trim() || void 0,
2070
- notes: options.formData.notes.trim() || void 0,
2071
- consentAccepted: options.formData.consentAccepted,
2072
- altchaSolution: options.altchaSolution,
2073
- paymentMethod: method,
2074
- customerPassId: method === "pass" ? passId : void 0,
2075
- customerMembershipId: method === "membership" ? membershipId : void 0,
2076
- bundleProductId: prepared.bundleProductId,
2077
- claimToken: options.claimToken ?? void 0,
2078
- guests: prepared.guestsPayload
2215
+ ...request,
2216
+ registrationCommandId: prepared.registrationCommandId
2079
2217
  });
2080
- commandIdRef.current = null;
2081
- if (needsOccurrenceCheckout(result, method)) return await submitOccurrenceCheckout(options, deps, prepared, result, method, submitOptions);
2082
- options.setRegistrationResult(toRegistrationResult(result));
2083
- options.setStep("success");
2084
- return {
2085
- ok: true,
2086
- outcome: { kind: "completed" }
2087
- };
2218
+ commandRef.current = null;
2219
+ return await completeRegistrationSubmission(options, deps, prepared, result, method, submitOptions);
2088
2220
  } catch (error) {
2221
+ if (error instanceof BlockApiError && error.tag === "registrationPreparationChanged") commandRef.current = null;
2089
2222
  const { message, action } = registrationErrorPresentation(error);
2090
2223
  options.setErrorAction?.(action);
2091
2224
  options.setErrorMessage(message);
@@ -2097,6 +2230,24 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
2097
2230
  };
2098
2231
  }
2099
2232
  };
2233
+ return (...args) => {
2234
+ if (inFlightRef.current) return inFlightRef.current;
2235
+ const pending = Promise.resolve().then(() => submit(...args));
2236
+ inFlightRef.current = pending;
2237
+ pending.finally(() => {
2238
+ if (inFlightRef.current === pending) inFlightRef.current = null;
2239
+ });
2240
+ return pending;
2241
+ };
2242
+ }
2243
+ async function completeRegistrationSubmission(options, deps, prepared, result, method, submitOptions) {
2244
+ if (needsOccurrenceCheckout(result, method)) return await submitOccurrenceCheckout(options, deps, prepared, result, method, submitOptions);
2245
+ options.setRegistrationResult(toRegistrationResult(result));
2246
+ options.setStep("success");
2247
+ return {
2248
+ ok: true,
2249
+ outcome: { kind: "completed" }
2250
+ };
2100
2251
  }
2101
2252
  function toTicketSelectionRequests(lines) {
2102
2253
  return lines.map((line) => ({
@@ -2171,6 +2322,7 @@ async function submitWholeSeriesCheckout(options, deps, prepared, submitOptions)
2171
2322
  altchaSolution: options.altchaSolution,
2172
2323
  guests: prepared.guestsPayload,
2173
2324
  claimToken: options.claimToken ?? void 0,
2325
+ waitlistEntryId: options.waitlistEntryId ?? void 0,
2174
2326
  discountCode: options.discountCode.trim() || void 0,
2175
2327
  collectionOptionKind: prepared.selectionSnapshot.collectionOptionKind,
2176
2328
  checkoutAttemptId,
@@ -2192,14 +2344,14 @@ async function submitWholeSeriesCheckout(options, deps, prepared, submitOptions)
2192
2344
  }
2193
2345
  if (result.bypassed) return completeBypassedCheckout(options);
2194
2346
  if (!result.checkoutUrl) throw new Error("Checkout URL missing");
2195
- savePendingCheckout(options, deps, prepared, checkoutAttemptId, {
2347
+ savePendingCheckout(options, deps, prepared, result.checkoutAttemptId, {
2196
2348
  scope: "wholeSeries",
2197
2349
  registrationId: result.registrationId
2198
2350
  });
2199
2351
  return redirectToCheckout(result.checkoutUrl, submitOptions);
2200
2352
  }
2201
2353
  function needsOccurrenceCheckout(result, method) {
2202
- return result.scope === "occurrence" && !result.alreadyRegistered && result.status === "confirmed" && result.pendingPayment && [
2354
+ return result.scope === "occurrence" && result.status === "confirmed" && result.pendingPayment && [
2203
2355
  "stripe",
2204
2356
  "pass_bundle",
2205
2357
  "membership_bundle"
@@ -2219,6 +2371,7 @@ async function submitOccurrenceCheckout(options, deps, prepared, registration, m
2219
2371
  kind: "occurrence",
2220
2372
  attendeeId: registration.attendeeId
2221
2373
  },
2374
+ registrationCommandId: prepared.registrationCommandId,
2222
2375
  checkoutType: method === "pass_bundle" ? "pass_bundle" : method === "membership_bundle" ? "membership_bundle" : "event",
2223
2376
  productId: prepared.bundleProductId,
2224
2377
  discountCode: options.discountCode.trim() || void 0,
@@ -2261,6 +2414,93 @@ function redirectToCheckout(checkoutUrl, submitOptions) {
2261
2414
  }
2262
2415
  };
2263
2416
  }
2417
+ function registrationRequestIntentKey(request) {
2418
+ const { registrationCommandId: _command, altchaSolution: _proof, ...intent } = request;
2419
+ return JSON.stringify(intent);
2420
+ }
2421
+ function buildOccurrenceRegistrationRequest(options, prepared, method, passId, membershipId) {
2422
+ return {
2423
+ registrationCommandId: prepared.registrationCommandId,
2424
+ subject: prepared.subject,
2425
+ ticketSelections: toTicketSelectionRequests(prepared.ticketSelections),
2426
+ selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
2427
+ email: options.formData.email.trim().toLowerCase(),
2428
+ name: options.formData.name.trim(),
2429
+ phone: options.formData.phone.trim() || void 0,
2430
+ notes: options.formData.notes.trim() || void 0,
2431
+ consentAccepted: options.formData.consentAccepted,
2432
+ altchaSolution: options.altchaSolution,
2433
+ paymentMethod: method,
2434
+ customerPassId: method === "pass" ? passId : void 0,
2435
+ customerMembershipId: method === "membership" ? membershipId : void 0,
2436
+ bundleProductId: prepared.bundleProductId,
2437
+ claimToken: options.claimToken ?? void 0,
2438
+ waitlistEntryId: options.waitlistEntryId ?? void 0,
2439
+ guests: prepared.guestsPayload
2440
+ };
2441
+ }
2442
+ //#endregion
2443
+ //#region ../blocks/src/system/runtime/nodes/event-registration/useSettledCommerceView.ts
2444
+ function buildCandidate(input) {
2445
+ if (!input.eligibilityIsSettled || !input.eligibility || !input.currentEvent) return null;
2446
+ return {
2447
+ eventSelectionId: input.currentEvent.selectionId,
2448
+ discountContext: resolveDiscountContext({
2449
+ paymentSelection: input.paymentSelection,
2450
+ event: input.currentEvent,
2451
+ eventRequiresPayment: input.eventRequiresPayment,
2452
+ ticketsCount: input.ticketsCount
2453
+ }),
2454
+ subtotalCents: input.eligibility.price,
2455
+ summaryLines: input.eligibility.ticketLines.map((line) => ({
2456
+ pricingOptionId: line.pricingOptionId,
2457
+ label: line.label,
2458
+ quantity: line.quantity,
2459
+ unitPriceCents: line.unitPriceCents,
2460
+ subtotalCents: line.subtotalCents
2461
+ }))
2462
+ };
2463
+ }
2464
+ function eligibilityIsSettled(result) {
2465
+ return result.settledRequestKey === result.requestKey;
2466
+ }
2467
+ function viewIsStale(view, currentEvent, eligibilityState) {
2468
+ return view.eventSelectionId !== currentEvent?.selectionId || eligibilityState?.tag === "failed" || eligibilityState?.tag === "idle";
2469
+ }
2470
+ function requestIsSettled(discountUi) {
2471
+ return discountUi.discountAvailabilityRequestKey === "disabled" || discountUi.settledDiscountAvailabilityRequestKey === discountUi.discountAvailabilityRequestKey;
2472
+ }
2473
+ function discountRequest(view) {
2474
+ const discountContext = view?.discountContext ?? null;
2475
+ return {
2476
+ discountContext,
2477
+ subtotalCents: discountContext?.type === "event" && view?.subtotalCents !== null ? view?.subtotalCents : void 0
2478
+ };
2479
+ }
2480
+ function useSettledCommerceView(input) {
2481
+ const candidate = buildCandidate({
2482
+ eligibilityIsSettled: eligibilityIsSettled(input.eligibilityResult),
2483
+ eligibility: input.eligibility,
2484
+ currentEvent: input.currentEvent,
2485
+ paymentSelection: input.paymentSelection,
2486
+ eventRequiresPayment: input.eventRequiresPayment,
2487
+ ticketsCount: input.ticketsCount
2488
+ });
2489
+ const settledRef = useRef(candidate);
2490
+ if (settledRef.current && viewIsStale(settledRef.current, input.currentEvent, input.eligibilityResult.state)) settledRef.current = null;
2491
+ const requestView = candidate ?? settledRef.current;
2492
+ const discountUi = input.useDiscountCodeUi({
2493
+ api: input.api,
2494
+ ...discountRequest(requestView)
2495
+ });
2496
+ if (candidate && requestIsSettled(discountUi)) settledRef.current = candidate;
2497
+ return {
2498
+ discountUi,
2499
+ discountContext: settledRef.current?.discountContext ?? null,
2500
+ ticketSelectionSubtotalCents: settledRef.current?.subtotalCents ?? null,
2501
+ ticketSelectionSummaryLines: settledRef.current?.summaryLines ?? []
2502
+ };
2503
+ }
2264
2504
  //#endregion
2265
2505
  //#region ../blocks/src/system/runtime/nodes/event-registration/registrationWizardContext.ts
2266
2506
  function getEventSelectionDefaults(event) {
@@ -2415,10 +2655,6 @@ function isSoldOutWithoutWaitlist(input) {
2415
2655
  }
2416
2656
  //#endregion
2417
2657
  //#region ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
2418
- function resolveDiscountSubtotalCents(context, subtotalCents) {
2419
- if (context?.type !== "event" || subtotalCents === null) return void 0;
2420
- return subtotalCents;
2421
- }
2422
2658
  function usesTieredPricing(event) {
2423
2659
  return event !== null && event !== void 0 ? publicEventPricingStrategy(event.pricing) === "tiered" : false;
2424
2660
  }
@@ -2499,14 +2735,28 @@ function useEventRegistrationWizardWithDeps(options, deps) {
2499
2735
  }), [options.occurrenceContext, selectedEvent]);
2500
2736
  const registrationOccurrenceId = getRegistrationOccurrenceId(registrationTarget);
2501
2737
  const currentEvent = selectedEvent ?? preSelectedEvent;
2738
+ const setStep = useCallback((nextStep) => {
2739
+ dispatchFlow({
2740
+ type: "set-step",
2741
+ step: nextStep
2742
+ });
2743
+ }, []);
2744
+ const { checkoutRecovery, startCheckoutRecovery } = useCheckoutRecovery(currentEvent, setStep);
2502
2745
  const currentEventUsesTicketTypes = usesTieredPricing(currentEvent);
2503
- const currentCanJoinWaitlist = currentEvent ? canJoinEventWaitlist(currentEvent, { attendanceMode: selectedAttendanceMode }) : false;
2746
+ const currentCanJoinWaitlist = canJoinWaitlistOutsideRecovery(currentEvent, selectedAttendanceMode, checkoutRecovery);
2504
2747
  const usesTicketTypeSelections = currentEventUsesTicketTypes && !currentCanJoinWaitlist;
2505
2748
  const eventTicketTypesForSelection = useMemo(() => getVisibleTicketTypes({
2506
2749
  event: currentEvent,
2507
2750
  eligibility: null,
2508
2751
  selectedAttendanceMode
2509
- }), [currentEvent, selectedAttendanceMode]);
2752
+ }).map((option) => checkoutRecovery ? {
2753
+ ...option,
2754
+ availability: checkoutRecoveryOptionAvailability(option.availability)
2755
+ } : option), [
2756
+ currentEvent,
2757
+ selectedAttendanceMode,
2758
+ checkoutRecovery
2759
+ ]);
2510
2760
  const normalizedSelectedTicketLines = useMemo(() => normalizeTicketSelectionLines(selectedTicketLines), [selectedTicketLines]);
2511
2761
  const ticketTypeSelectionTotal = useMemo(() => getTicketSelectionTotal(normalizedSelectedTicketLines), [normalizedSelectedTicketLines]);
2512
2762
  const ticketsCount = usesTicketTypeSelections ? ticketTypeSelectionTotal : flowState.ticketsCount;
@@ -2544,17 +2794,11 @@ function useEventRegistrationWizardWithDeps(options, deps) {
2544
2794
  isAuthenticated: portalAuthState === "authenticated",
2545
2795
  occurrenceId: registrationOccurrenceId
2546
2796
  });
2547
- const eligibility = eligibilityResult.eligibility;
2797
+ const eligibility = useCheckoutRecoveryEligibility(eligibilityResult.eligibility, step, checkoutRecovery, startCheckoutRecovery);
2548
2798
  const eligibilityLoading = eligibilityResult.isLoading;
2549
2799
  const eligibilityError = eligibilityResult.error;
2550
2800
  const portalCreditState = eligibilityResult.creditState;
2551
2801
  const registrationState = eligibility?.registration ?? { kind: "none" };
2552
- const setStep = useCallback((nextStep) => {
2553
- dispatchFlow({
2554
- type: "set-step",
2555
- step: nextStep
2556
- });
2557
- }, []);
2558
2802
  const setTicketsCount = useCallback((nextTicketsCount) => {
2559
2803
  dispatchFlow({
2560
2804
  type: "set-tickets-count",
@@ -2662,10 +2906,14 @@ function useEventRegistrationWizardWithDeps(options, deps) {
2662
2906
  event: currentEvent,
2663
2907
  eligibility,
2664
2908
  selectedAttendanceMode
2665
- }), [
2909
+ }).map((option) => checkoutRecovery ? {
2910
+ ...option,
2911
+ availability: checkoutRecoveryOptionAvailability(option.availability)
2912
+ } : option), [
2666
2913
  currentEvent,
2667
2914
  selectedAttendanceMode,
2668
- eligibility
2915
+ eligibility,
2916
+ checkoutRecovery
2669
2917
  ]);
2670
2918
  const singleSelectedPricingOptionId = getSingleSelectedPricingOptionId(normalizedSelectedTicketLines);
2671
2919
  const selectedTicketType = useMemo(() => findSelectedTicketType({
@@ -2689,8 +2937,12 @@ function useEventRegistrationWizardWithDeps(options, deps) {
2689
2937
  const event = currentEvent;
2690
2938
  if (!usesTieredPricing(event)) return false;
2691
2939
  if ((event.deliveryMode ?? "in_person") === "hybrid" && !selectedAttendanceMode) return false;
2692
- return !canJoinEventWaitlist(event, { attendanceMode: selectedAttendanceMode });
2693
- }, [currentEvent, selectedAttendanceMode]);
2940
+ return checkoutRecovery || !canJoinEventWaitlist(event, { attendanceMode: selectedAttendanceMode });
2941
+ }, [
2942
+ currentEvent,
2943
+ selectedAttendanceMode,
2944
+ checkoutRecovery
2945
+ ]);
2694
2946
  const hasValidTicketSelection = hasValidPricingOptionSelection({
2695
2947
  selectionRequired: ticketTypeSelectionRequired,
2696
2948
  lines: normalizedSelectedTicketLines,
@@ -2854,30 +3106,15 @@ function useEventRegistrationWizardWithDeps(options, deps) {
2854
3106
  }
2855
3107
  setStep("select-tickets");
2856
3108
  };
2857
- const discountContext = useMemo(() => resolveDiscountContext({
2858
- paymentSelection,
2859
- event: currentEvent,
2860
- eventRequiresPayment,
2861
- ticketsCount
2862
- }), [
3109
+ const { discountUi, discountContext, ticketSelectionSubtotalCents, ticketSelectionSummaryLines } = useSettledCommerceView({
3110
+ api,
3111
+ useDiscountCodeUi: deps.useDiscountCodeUi,
3112
+ eligibilityResult,
3113
+ eligibility,
2863
3114
  currentEvent,
2864
3115
  eventRequiresPayment,
2865
3116
  paymentSelection,
2866
3117
  ticketsCount
2867
- ]);
2868
- const ticketSelectionSubtotalCents = eligibility?.price ?? null;
2869
- const ticketSelectionSummaryLines = useMemo(() => eligibility?.ticketLines.map((line) => ({
2870
- pricingOptionId: line.pricingOptionId,
2871
- label: line.label,
2872
- quantity: line.quantity,
2873
- unitPriceCents: line.unitPriceCents,
2874
- subtotalCents: line.subtotalCents
2875
- })) ?? [], [eligibility]);
2876
- const discountSubtotalCents = resolveDiscountSubtotalCents(discountContext, ticketSelectionSubtotalCents);
2877
- const discountUi = deps.useDiscountCodeUi({
2878
- api,
2879
- discountContext,
2880
- subtotalCents: discountSubtotalCents
2881
3118
  });
2882
3119
  const selectionMethod = paymentSelection.method;
2883
3120
  const shouldShowDiscountToggle = discountContext !== null && discountUi.manualCodeEntryAllowed && (selectionMethod === "stripe" || selectionMethod === "pass_bundle" || selectionMethod === "membership_bundle");
@@ -2894,6 +3131,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
2894
3131
  guests,
2895
3132
  discountCode: discountUi.discountCode,
2896
3133
  claimToken: waitlistClaim.token,
3134
+ waitlistEntryId: waitlistClaim.entryId,
2897
3135
  setPendingRegistrationReference,
2898
3136
  setStep,
2899
3137
  setRegistrationResult: (result) => setRegistrationResult(result),
@@ -2956,6 +3194,8 @@ function useEventRegistrationWizardWithDeps(options, deps) {
2956
3194
  scopedEvents,
2957
3195
  preSelectedEvent,
2958
3196
  hasPreSelectedContext,
3197
+ checkoutRecovery,
3198
+ startCheckoutRecovery,
2959
3199
  step,
2960
3200
  setStep,
2961
3201
  selectedEvent,
@@ -3039,6 +3279,34 @@ function useEventRegistrationWizardWithDeps(options, deps) {
3039
3279
  };
3040
3280
  }
3041
3281
  //#endregion
3282
+ //#region ../blocks/src/system/runtime/nodes/event-registration/useEventCheckoutHandoffRestore.ts
3283
+ function eventRegistrationReloadTarget(location) {
3284
+ return `${location.pathname}${location.search}#${EVENT_REGISTRATION_ANCHOR_ID}`;
3285
+ }
3286
+ function reloadAtEventRegistration() {
3287
+ const target = eventRegistrationReloadTarget(window.location);
3288
+ window.history.replaceState(window.history.state, "", target);
3289
+ window.location.reload();
3290
+ }
3291
+ const browserCheckoutHandoffRestoreDeps = {
3292
+ addPageShowListener: (listener) => window.addEventListener("pageshow", listener),
3293
+ removePageShowListener: (listener) => window.removeEventListener("pageshow", listener),
3294
+ reloadAtRegistration: reloadAtEventRegistration
3295
+ };
3296
+ function useEventCheckoutHandoffRestore(active) {
3297
+ useEventCheckoutHandoffRestoreWithDeps(active, browserCheckoutHandoffRestoreDeps);
3298
+ }
3299
+ function useEventCheckoutHandoffRestoreWithDeps(active, deps) {
3300
+ useEffect(() => {
3301
+ if (!active) return;
3302
+ const handlePageShow = (event) => {
3303
+ if (event.persisted) deps.reloadAtRegistration();
3304
+ };
3305
+ deps.addPageShowListener(handlePageShow);
3306
+ return () => deps.removePageShowListener(handlePageShow);
3307
+ }, [active, deps]);
3308
+ }
3309
+ //#endregion
3042
3310
  //#region ../blocks/src/system/runtime/nodes/shared/MagicLinkForm.state.ts
3043
3311
  const initialMagicLinkSubmissionState = Object.freeze({ tag: "idle" });
3044
3312
  function magicLinkSubmissionReducer(state, action) {
@@ -3159,6 +3427,51 @@ function getMagicLinkErrorMessage(error) {
3159
3427
  return error instanceof Error ? error.message : "Failed to send. Please try again.";
3160
3428
  }
3161
3429
  //#endregion
3430
+ //#region ../blocks/src/system/runtime/nodes/event-registration/ErrorStep.tsx
3431
+ /**
3432
+ * Error Step
3433
+ *
3434
+ * Displays an error message with a retry button when registration fails.
3435
+ */
3436
+ const labels = {
3437
+ none: "",
3438
+ retry: "Try again",
3439
+ places: "Choose places",
3440
+ start: "Start again",
3441
+ details: "Check my details",
3442
+ "payment-options": "View payment options",
3443
+ "payment-status": "Check payment status",
3444
+ portal: "View my bookings",
3445
+ event: "View event"
3446
+ };
3447
+ const ErrorStep = ({ message, onRetry, action = "retry", canJoinWaitlist = false }) => {
3448
+ const offerWaitlist = action === "places" && canJoinWaitlist;
3449
+ return /* @__PURE__ */ jsx(TerminalPanel, {
3450
+ tone: "error",
3451
+ className: "er-center",
3452
+ titleClassName: "er-title--lg er-message",
3453
+ icon: /* @__PURE__ */ jsx(StateIcon, {
3454
+ variant: "error",
3455
+ children: /* @__PURE__ */ jsx(CrossIcon, {})
3456
+ }),
3457
+ title: "We couldn’t complete your booking",
3458
+ body: /* @__PURE__ */ jsx("p", {
3459
+ className: "er-text--muted er-message",
3460
+ 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
3461
+ }),
3462
+ actions: action === "none" ? void 0 : action === "portal" || action === "payment-status" ? /* @__PURE__ */ jsx("a", {
3463
+ href: "/portal",
3464
+ className: "er-retry-btn",
3465
+ children: labels[action]
3466
+ }) : /* @__PURE__ */ jsx("button", {
3467
+ type: "button",
3468
+ onClick: onRetry,
3469
+ className: "er-retry-btn",
3470
+ children: offerWaitlist ? "Join the waiting list" : labels[action]
3471
+ })
3472
+ });
3473
+ };
3474
+ //#endregion
3162
3475
  //#region ../blocks/src/system/runtime/nodes/event-registration/EventRegistrationSummaryBar.tsx
3163
3476
  function getScheduleSummary(wizard, summaryEvent) {
3164
3477
  if (summaryEvent.registrationSubject.kind !== "wholeSeries") {
@@ -3442,7 +3755,7 @@ function SelectTicketsActions(props) {
3442
3755
  const currentEvent = wizard.selectedEvent ?? wizard.preSelectedEvent;
3443
3756
  const registrationOptionsPending = wizard.registrationOptionsState.tag === "idle" || wizard.registrationOptionsState.tag === "loading";
3444
3757
  const registrationOptionsFailed = wizard.registrationOptionsState.tag === "failed";
3445
- const isSoldOutWithoutWaitlist = !hasWaitlistClaim && isFullWithNoWaitlist(currentEvent, wizard.selectedAttendanceMode);
3758
+ const isSoldOutWithoutWaitlist = !wizard.checkoutRecovery && !hasWaitlistClaim && isFullWithNoWaitlist(currentEvent, wizard.selectedAttendanceMode);
3446
3759
  const isCheckingExistingRegistration = wizard.portalAuthState === "authenticated" && wizard.existingRegistrationLoading;
3447
3760
  const hasExistingRegistration = isExistingRegistrationBlocking$1(wizard);
3448
3761
  const ticketTypeSelectionBlocked = wizard.ticketTypeSelectionRequired && !wizard.hasValidTicketSelection;
@@ -4032,6 +4345,31 @@ function resolveTicketSelectionPricing(event) {
4032
4345
  currency: event ? publicEventPricingCurrency(event.pricing) : null
4033
4346
  };
4034
4347
  }
4348
+ function CheckoutRecoveryEntry(props) {
4349
+ return props.onContinue ? /* @__PURE__ */ jsx("button", {
4350
+ type: "button",
4351
+ className: "er-back-btn",
4352
+ onClick: props.onContinue,
4353
+ children: "Continue an existing booking"
4354
+ }) : null;
4355
+ }
4356
+ function getTicketSelectionCapacity(event, attendanceMode, checkoutRecovery) {
4357
+ if (checkoutRecovery) return {
4358
+ availableSpots: null,
4359
+ isSoldOut: false,
4360
+ canJoinWaitlist: false,
4361
+ eventAvailabilityLabel: null
4362
+ };
4363
+ const source = event ? selectEventCapacitySource(event, attendanceMode) : null;
4364
+ const availability = source ? getEventAvailability(source) : null;
4365
+ const canJoinWaitlist = source ? canJoinEventWaitlist(source) : false;
4366
+ return {
4367
+ availableSpots: availability?.available,
4368
+ isSoldOut: availability?.isFull ?? false,
4369
+ canJoinWaitlist,
4370
+ eventAvailabilityLabel: !canJoinWaitlist && source ? formatRemainingPlaces(source) : null
4371
+ };
4372
+ }
4035
4373
  /**
4036
4374
  * Ticket Selection Step
4037
4375
  *
@@ -4040,15 +4378,11 @@ function resolveTicketSelectionPricing(event) {
4040
4378
  *
4041
4379
  * Can use either a full PublicEvent or just occurrence context (when on event page).
4042
4380
  */
4043
- const TicketSelectionStep = ({ event, occurrenceContext: _occurrenceContext, selectedAttendanceMode = null, onAttendanceModeChange, ticketsCount, maxTickets, visibleTicketTypes: visibleTicketTypesOverride, ticketSelections = [], onTicketSelectionsChange, slidingScale = null, selectedSlidingAmountInput = "", slidingScaleSelectionMessage = null, onSlidingAmountChange, onTicketsChange, bookingUnit = { kind: "ticket" } }) => {
4381
+ 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 }) => {
4044
4382
  const unit = bookingUnit.kind;
4045
4383
  const deliveryMode = event?.deliveryMode ?? "in_person";
4046
4384
  const attendanceModes = event?.attendanceModes ?? [];
4047
- const capacitySource = event ? selectEventCapacitySource(event, selectedAttendanceMode) : null;
4048
- const availability = capacitySource ? getEventAvailability(capacitySource) : null;
4049
- const availableSpots = availability?.available;
4050
- const isSoldOut = availability?.isFull ?? false;
4051
- const canJoinWaitlist = capacitySource ? canJoinEventWaitlist(capacitySource) : false;
4385
+ const { availableSpots, isSoldOut, canJoinWaitlist, eventAvailabilityLabel } = getTicketSelectionCapacity(event, selectedAttendanceMode, checkoutRecovery);
4052
4386
  const { mode: eventPricingMode, currency: eventPricingCurrency } = resolveTicketSelectionPricing(event);
4053
4387
  const usesTicketTypes = eventPricingMode === "tiered" && !canJoinWaitlist;
4054
4388
  const visibleTicketTypes = usesTicketTypes ? visibleTicketTypesOverride ?? getVisibleTicketTypes({
@@ -4067,7 +4401,6 @@ const TicketSelectionStep = ({ event, occurrenceContext: _occurrenceContext, sel
4067
4401
  selectedTicketTypeRemainingCapacity: implicitTicketType?.availability.remainingPlaces ?? null,
4068
4402
  hasSelectedTicketType: implicitTicketType !== null
4069
4403
  });
4070
- const eventAvailabilityLabel = !canJoinWaitlist && capacitySource ? formatRemainingPlaces(capacitySource) : null;
4071
4404
  if (deliveryMode === "hybrid" && !selectedAttendanceMode) return /* @__PURE__ */ jsxs("div", {
4072
4405
  className: "rb-reg-stack er-stack",
4073
4406
  children: [
@@ -4088,13 +4421,17 @@ const TicketSelectionStep = ({ event, occurrenceContext: _occurrenceContext, sel
4088
4421
  });
4089
4422
  if (isSoldOut && !canJoinWaitlist) return /* @__PURE__ */ jsxs("div", {
4090
4423
  className: "rb-reg-stack er-stack",
4091
- children: [/* @__PURE__ */ jsx("h3", {
4092
- className: "er-title",
4093
- children: "Sold out"
4094
- }), /* @__PURE__ */ jsx("p", {
4095
- className: "er-text er-text--muted",
4096
- children: "Sorry you missed out! This event is fully booked."
4097
- })]
4424
+ children: [
4425
+ /* @__PURE__ */ jsx("h3", {
4426
+ className: "er-title",
4427
+ children: "Sold out"
4428
+ }),
4429
+ /* @__PURE__ */ jsx("p", {
4430
+ className: "er-text er-text--muted",
4431
+ children: "Sorry you missed out! This event is fully booked."
4432
+ }),
4433
+ /* @__PURE__ */ jsx(CheckoutRecoveryEntry, { onContinue: onCheckoutRecovery })
4434
+ ]
4098
4435
  });
4099
4436
  if (!eventPricingCurrency) return /* @__PURE__ */ jsx("div", {
4100
4437
  className: "rb-reg-stack er-stack",
@@ -4162,9 +4499,13 @@ const TicketSelectionStep = ({ event, occurrenceContext: _occurrenceContext, sel
4162
4499
  })]
4163
4500
  })
4164
4501
  ] }),
4165
- canJoinWaitlist && /* @__PURE__ */ jsx("p", {
4502
+ canJoinWaitlist && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
4166
4503
  className: "er-text er-text--muted",
4167
4504
  children: "This event is currently full. Continue to join the waitlist if a place opens up."
4505
+ }), /* @__PURE__ */ jsx(CheckoutRecoveryEntry, { onContinue: onCheckoutRecovery })] }),
4506
+ checkoutRecovery && /* @__PURE__ */ jsx("p", {
4507
+ className: "er-text er-text--muted",
4508
+ children: "Enter the details from your earlier booking. We’ll check your checkout before continuing to payment."
4168
4509
  })
4169
4510
  ]
4170
4511
  });
@@ -5072,12 +5413,14 @@ function EventRegistrationWizardContent(props) {
5072
5413
  onBookForSomeoneElse: wizard.handleBookForSomeoneElse
5073
5414
  }), /* @__PURE__ */ jsx(TicketSelectionStep, {
5074
5415
  event: wizard.selectedEvent,
5416
+ checkoutRecovery: wizard.checkoutRecovery,
5417
+ onCheckoutRecovery: canRecoverEventCheckout(wizard.selectedEvent) ? wizard.startCheckoutRecovery : void 0,
5075
5418
  occurrenceContext: wizard.occurrenceContext,
5076
5419
  selectedAttendanceMode: wizard.selectedAttendanceMode,
5077
5420
  onAttendanceModeChange: wizard.setSelectedAttendanceMode,
5078
5421
  ticketsCount: wizard.ticketsCount,
5079
5422
  maxTickets: wizard.maxTicketsNum,
5080
- visibleTicketTypes: wizard.eligibility ? wizard.visibleTicketTypes : void 0,
5423
+ visibleTicketTypes: wizard.visibleTicketTypes,
5081
5424
  ticketSelections: wizard.selectedTicketLines,
5082
5425
  onTicketSelectionsChange: wizard.setSelectedTicketLines,
5083
5426
  slidingScale: wizard.selectedEventSlidingScale,
@@ -5096,66 +5439,6 @@ function EventRegistrationWizardContent(props) {
5096
5439
  }
5097
5440
  }
5098
5441
  //#endregion
5099
- //#region ../blocks/src/system/runtime/nodes/event-registration/StepIndicator.tsx
5100
- /**
5101
- * Step indicator component for the event registration wizard.
5102
- * Thin wrapper around the shared StepIndicator: styled by the shared
5103
- * registration-surface classes, with 'er'-prefixed classes kept in the
5104
- * markup as the stable hook surface for per-site theme CSS.
5105
- */
5106
- function StepIndicator(props) {
5107
- return /* @__PURE__ */ jsx(StepIndicator$1, {
5108
- ...props,
5109
- classPrefix: "er",
5110
- emitSharedClasses: true
5111
- });
5112
- }
5113
- //#endregion
5114
- //#region ../blocks/src/system/runtime/nodes/event-registration/ErrorStep.tsx
5115
- /**
5116
- * Error Step
5117
- *
5118
- * Displays an error message with a retry button when registration fails.
5119
- */
5120
- const labels = {
5121
- none: "",
5122
- retry: "Try again",
5123
- places: "Choose places",
5124
- start: "Start again",
5125
- details: "Check my details",
5126
- "payment-options": "View payment options",
5127
- "payment-status": "Check payment status",
5128
- portal: "View my bookings",
5129
- event: "View event"
5130
- };
5131
- const ErrorStep = ({ message, onRetry, action = "retry", canJoinWaitlist = false }) => {
5132
- const offerWaitlist = action === "places" && canJoinWaitlist;
5133
- return /* @__PURE__ */ jsx(TerminalPanel, {
5134
- tone: "error",
5135
- className: "er-center",
5136
- titleClassName: "er-title--lg er-message",
5137
- icon: /* @__PURE__ */ jsx(StateIcon, {
5138
- variant: "error",
5139
- children: /* @__PURE__ */ jsx(CrossIcon, {})
5140
- }),
5141
- title: "We couldn’t complete your booking",
5142
- body: /* @__PURE__ */ jsx("p", {
5143
- className: "er-text--muted er-message",
5144
- 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
5145
- }),
5146
- actions: action === "none" ? void 0 : action === "portal" || action === "payment-status" ? /* @__PURE__ */ jsx("a", {
5147
- href: "/portal",
5148
- className: "er-retry-btn",
5149
- children: labels[action]
5150
- }) : /* @__PURE__ */ jsx("button", {
5151
- type: "button",
5152
- onClick: onRetry,
5153
- className: "er-retry-btn",
5154
- children: offerWaitlist ? "Join the waiting list" : labels[action]
5155
- })
5156
- });
5157
- };
5158
- //#endregion
5159
5442
  //#region ../blocks/src/system/runtime/nodes/event-registration/PaymentFailedStep.tsx
5160
5443
  /**
5161
5444
  * Payment Failed Step
@@ -5186,6 +5469,21 @@ const PaymentFailedStep = ({ onRetry }) => {
5186
5469
  });
5187
5470
  };
5188
5471
  //#endregion
5472
+ //#region ../blocks/src/system/runtime/nodes/event-registration/StepIndicator.tsx
5473
+ /**
5474
+ * Step indicator component for the event registration wizard.
5475
+ * Thin wrapper around the shared StepIndicator: styled by the shared
5476
+ * registration-surface classes, with 'er'-prefixed classes kept in the
5477
+ * markup as the stable hook surface for per-site theme CSS.
5478
+ */
5479
+ function StepIndicator(props) {
5480
+ return /* @__PURE__ */ jsx(StepIndicator$1, {
5481
+ ...props,
5482
+ classPrefix: "er",
5483
+ emitSharedClasses: true
5484
+ });
5485
+ }
5486
+ //#endregion
5189
5487
  //#region ../blocks/src/system/runtime/nodes/event-registration/SuccessStep.tsx
5190
5488
  /**
5191
5489
  * Success Step
@@ -5458,7 +5756,8 @@ function EventRegistrationSurface(props) {
5458
5756
  }), /* @__PURE__ */ jsx(EventRegistrationTerminalState, {
5459
5757
  wizard,
5460
5758
  supportEmail: props.supportEmail,
5461
- successMessage: props.successMessage
5759
+ successMessage: props.successMessage,
5760
+ buttonClass: props.buttonClass
5462
5761
  })]
5463
5762
  });
5464
5763
  }
@@ -5622,6 +5921,7 @@ function EventRegistrationWizard(props) {
5622
5921
  events: events ?? [],
5623
5922
  maxTicketsNum
5624
5923
  });
5924
+ useEventCheckoutHandoffRestore(wizard.step === "redirecting");
5625
5925
  const [bookingOverlayOpen, setBookingOverlayOpen] = useState(false);
5626
5926
  const [floatingPortalRoot, setFloatingPortalRoot] = useState(null);
5627
5927
  useEffect(() => {
@@ -5856,6 +6156,84 @@ function RegistrationClosedState({ title, body }) {
5856
6156
  });
5857
6157
  }
5858
6158
  //#endregion
6159
+ //#region ../blocks/src/system/runtime/nodes/event-registration/useEventSourceRecovery.ts
6160
+ const RECOVERY_DELAYS_MS = [
6161
+ 0,
6162
+ 250,
6163
+ 750
6164
+ ];
6165
+ const defaultRecoveryDeps = {
6166
+ useApi: useBlockApi,
6167
+ wait: waitForRetry
6168
+ };
6169
+ function useEventSourceRecovery(source, deps = defaultRecoveryDeps) {
6170
+ const api = deps.useApi();
6171
+ const wait = deps.wait;
6172
+ const [cycle, setCycle] = useState(0);
6173
+ const [state, setState] = useState(() => source.kind === "loaded" ? {
6174
+ kind: "ready",
6175
+ events: source.events
6176
+ } : { kind: "loading" });
6177
+ const retry = useCallback(() => {
6178
+ setState({ kind: "loading" });
6179
+ setCycle((value) => value + 1);
6180
+ }, []);
6181
+ useEffect(() => {
6182
+ if (source.kind === "loaded") {
6183
+ setState({
6184
+ kind: "ready",
6185
+ events: source.events
6186
+ });
6187
+ return;
6188
+ }
6189
+ if (!source.request) {
6190
+ setState({
6191
+ kind: "exhausted",
6192
+ retry
6193
+ });
6194
+ return;
6195
+ }
6196
+ const controller = new AbortController();
6197
+ const isCurrent = () => !controller.signal.aborted;
6198
+ (async () => {
6199
+ for (const delayMs of RECOVERY_DELAYS_MS) try {
6200
+ await wait(delayMs, controller.signal);
6201
+ const events = await api.getPublicEvents(source.request ?? void 0);
6202
+ if (isCurrent()) setState({
6203
+ kind: "ready",
6204
+ events
6205
+ });
6206
+ return;
6207
+ } catch {
6208
+ if (!isCurrent()) return;
6209
+ }
6210
+ if (isCurrent()) setState({
6211
+ kind: "exhausted",
6212
+ retry
6213
+ });
6214
+ })();
6215
+ return () => controller.abort();
6216
+ }, [
6217
+ api,
6218
+ cycle,
6219
+ retry,
6220
+ source,
6221
+ wait
6222
+ ]);
6223
+ return state;
6224
+ }
6225
+ function waitForRetry(milliseconds, signal) {
6226
+ if (signal.aborted) return Promise.reject(/* @__PURE__ */ new Error("Recovery aborted"));
6227
+ if (milliseconds === 0) return Promise.resolve();
6228
+ return new Promise((resolve, reject) => {
6229
+ const timeout = setTimeout(resolve, milliseconds);
6230
+ signal.addEventListener("abort", () => {
6231
+ clearTimeout(timeout);
6232
+ reject(/* @__PURE__ */ new Error("Recovery aborted"));
6233
+ }, { once: true });
6234
+ });
6235
+ }
6236
+ //#endregion
5859
6237
  //#region ../blocks/src/system/runtime/nodes/event-registration.client.tsx
5860
6238
  function toEventRegistrationClientProps(props, display) {
5861
6239
  return {
@@ -5889,8 +6267,71 @@ const EventRegistrationIslandClient = (props) => {
5889
6267
  title: props.render.display.titleText,
5890
6268
  body: props.render.display.bodyText
5891
6269
  });
5892
- return /* @__PURE__ */ jsx(EventRegistrationClient, { ...toEventRegistrationClientProps(props, props.render.display) });
6270
+ return /* @__PURE__ */ jsx(RecoverableEventRegistrationClient, {
6271
+ props,
6272
+ display: props.render.display
6273
+ });
5893
6274
  };
6275
+ function RecoverableEventRegistrationClient({ props, display }) {
6276
+ const recovery = useEventSourceRecovery(props.render.hydration.eventSource);
6277
+ if (recovery.kind === "loading") return /* @__PURE__ */ jsxs("div", {
6278
+ id: EVENT_REGISTRATION_ANCHOR_ID,
6279
+ className: "rb-reg-surface er-container er-registration-shell",
6280
+ "aria-busy": "true",
6281
+ role: "status",
6282
+ children: [
6283
+ /* @__PURE__ */ jsx("p", {
6284
+ className: "er-registration-shell__eyebrow",
6285
+ children: "Registration"
6286
+ }),
6287
+ /* @__PURE__ */ jsx("h3", {
6288
+ className: "er-title er-registration-shell__title",
6289
+ children: display.titleText
6290
+ }),
6291
+ /* @__PURE__ */ jsx("p", {
6292
+ className: "er-text er-text--muted",
6293
+ children: "Loading event dates…"
6294
+ }),
6295
+ /* @__PURE__ */ jsxs("div", {
6296
+ className: "er-event-grid er-registration-shell__cards",
6297
+ "aria-hidden": "true",
6298
+ children: [/* @__PURE__ */ jsx("div", { className: "er-event-card er-registration-shell__card" }), /* @__PURE__ */ jsx("div", { className: "er-event-card er-registration-shell__card" })]
6299
+ })
6300
+ ]
6301
+ });
6302
+ if (recovery.kind === "exhausted") return /* @__PURE__ */ jsxs("div", {
6303
+ id: EVENT_REGISTRATION_ANCHOR_ID,
6304
+ className: "rb-reg-surface er-container er-registration-shell",
6305
+ role: "alert",
6306
+ children: [/* @__PURE__ */ jsx("p", { children: "We couldn’t load the event dates. Please try again." }), /* @__PURE__ */ jsx("button", {
6307
+ type: "button",
6308
+ className: themeButtonClassName({
6309
+ variant: props.render.hydration.buttonVariant ?? "primary",
6310
+ size: "md"
6311
+ }),
6312
+ onClick: recovery.retry,
6313
+ children: "Try again"
6314
+ })]
6315
+ });
6316
+ const events = resolveEventRegistrationScopedEvents(recovery.events, {
6317
+ occurrenceContext: props.render.hydration.occurrenceContext,
6318
+ subject: props.render.hydration.subject
6319
+ });
6320
+ const recoveredDisplay = buildEventRegistrationDisplayFromScopedEvents({
6321
+ ...props.render.hydration,
6322
+ events,
6323
+ className: display.className,
6324
+ buttonText: display.summaryButtonText
6325
+ }, events);
6326
+ if (recoveredDisplay.state === "registration-closed") return /* @__PURE__ */ jsx(RegistrationClosedState, {
6327
+ title: recoveredDisplay.titleText,
6328
+ body: recoveredDisplay.bodyText
6329
+ });
6330
+ return /* @__PURE__ */ jsx(EventRegistrationClient, {
6331
+ ...toEventRegistrationClientProps(props, display),
6332
+ events
6333
+ });
6334
+ }
5894
6335
  //#endregion
5895
6336
  //#region src/rendering/islands/enhancers/eventRegistration.tsx
5896
6337
  const decode = defineIslandPropsDecoder("event-registration");