@riverbankcms/sdk 0.130.0 → 0.132.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 (468) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/README.md +1 -1
  3. package/dist/{PreviewEditorSidebar-DiEpbOdw.mjs → PreviewEditorSidebar-DKQ5eFK9.mjs} +365 -106
  4. package/dist/{PreviewEditorUI-C6MvxnIa.mjs → PreviewEditorUI-CNTcOjCC.mjs} +3 -3
  5. package/dist/{PreviewQueryProvider-C2rnoPz6.mjs → PreviewQueryProvider-D51gQaG3.mjs} +1 -1
  6. package/dist/{SdkPreviewModeRuntime-DRXA_m5L.mjs → SdkPreviewModeRuntime-DJu3qu33.mjs} +91 -25
  7. package/dist/{SiteChromeCustomizeContext-BTHdv5_-.mjs → SiteChromeCustomizeContext-2TzT3vbj.mjs} +12577 -9240
  8. package/dist/_dts/ai/src/contracts/proposals.d.ts +991 -142
  9. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +1092 -148
  10. package/dist/_dts/api/src/accountApi.d.ts +213 -0
  11. package/dist/_dts/api/src/accountEndpointDefinitions.d.ts +30 -0
  12. package/dist/_dts/api/src/accountEndpoints.d.ts +254 -0
  13. package/dist/_dts/api/src/apiCallParams.d.ts +60 -0
  14. package/dist/_dts/api/src/bookingConfig.d.ts +18 -24
  15. package/dist/_dts/api/src/bookingManagementEndpoints.d.ts +12 -24
  16. package/dist/_dts/api/src/bookingManagementEventEndpointTypes.d.ts +44 -0
  17. package/dist/_dts/api/src/bookingSettingsSections.d.ts +9 -0
  18. package/dist/_dts/api/src/bookingVerticals.d.ts +1 -140
  19. package/dist/_dts/api/src/commercePortalEndpoints.d.ts +47 -12
  20. package/dist/_dts/api/src/contentRuntime.d.ts +2 -1
  21. package/dist/_dts/api/src/courses.d.ts +1 -19
  22. package/dist/_dts/api/src/endpoints.d.ts +885 -721
  23. package/dist/_dts/api/src/event-destination-policy.d.ts +2 -2
  24. package/dist/_dts/api/src/eventManagementContracts.d.ts +173 -7
  25. package/dist/_dts/api/src/eventManagementEndpointDefinitions.d.ts +58 -0
  26. package/dist/_dts/api/src/giftingDashboard.d.ts +117 -0
  27. package/dist/_dts/api/src/giftingEndpointDefinitions.d.ts +124 -0
  28. package/dist/_dts/api/src/index.d.ts +12 -4
  29. package/dist/_dts/api/src/indexCoreTypes.d.ts +1 -0
  30. package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -0
  31. package/dist/_dts/api/src/media.d.ts +1 -0
  32. package/dist/_dts/api/src/navigation/dashboardBookingsNav.d.ts +3 -4
  33. package/dist/_dts/api/src/oauth.d.ts +8 -0
  34. package/dist/_dts/api/src/preview-auth.d.ts +26 -0
  35. package/dist/_dts/api/src/publicEventEndpointDefinitions.d.ts +11 -0
  36. package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +29 -16
  37. package/dist/_dts/api/src/publicExperience/sharedTypes.d.ts +2 -0
  38. package/dist/_dts/api/src/publicExperience/wholeSeriesEndpoints.d.ts +1 -1
  39. package/dist/_dts/api/src/sdk-event-upsert.d.ts +3 -1
  40. package/dist/_dts/api/src/sdkBlockUpsertContracts.d.ts +48 -0
  41. package/dist/_dts/api/src/sdkBookingVerticalContracts.d.ts +29 -0
  42. package/dist/_dts/api/src/sdkContracts.d.ts +14 -45
  43. package/dist/_dts/api/src/sdkEndpointDefinitions.d.ts +23 -0
  44. package/dist/_dts/api/src/sdkEventCategoryContracts.d.ts +9 -0
  45. package/dist/_dts/api/src/sdkSettingsContracts.d.ts +25 -0
  46. package/dist/_dts/api/src/sdkThemeCatalogContracts.d.ts +20 -0
  47. package/dist/_dts/api/src/sdkThemeWire.d.ts +54 -12
  48. package/dist/_dts/api/src/settings/permissions.d.ts +2 -2
  49. package/dist/_dts/api/src/siteApiKeyEndpointDefinitions.d.ts +66 -0
  50. package/dist/_dts/api/src/siteInfrastructure.d.ts +3 -3
  51. package/dist/_dts/api/src/siteOnboarding.d.ts +3 -3
  52. package/dist/_dts/api/src/siteOperations.d.ts +1 -1
  53. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +16 -14
  54. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +0 -3
  55. package/dist/_dts/api/src/types.d.ts +8 -61
  56. package/dist/_dts/block-form/src/client/index.d.ts +15 -23
  57. package/dist/_dts/block-form/src/index.d.ts +23 -22
  58. package/dist/_dts/blocks/src/PageRenderer.d.ts +2 -13
  59. package/dist/_dts/blocks/src/contracts/non-block-islands.d.ts +9 -0
  60. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +26 -44
  61. package/dist/_dts/blocks/src/index.d.ts +1 -1
  62. package/dist/_dts/blocks/src/primitives/layout/Grid.d.ts +18 -1
  63. package/dist/_dts/blocks/src/subroutes/fold.d.ts +2 -1
  64. package/dist/_dts/blocks/src/system/blocks/appointment-booking.d.ts +1 -0
  65. package/dist/_dts/blocks/src/system/blocks/courses/shared/index.d.ts +0 -3
  66. package/dist/_dts/blocks/src/system/blocks/courses/shared/pricing.d.ts +2 -50
  67. package/dist/_dts/blocks/src/system/blocks/courses/shared/schemas.d.ts +1 -929
  68. package/dist/_dts/blocks/src/system/blocks/courses/shared/types.d.ts +1 -97
  69. package/dist/_dts/blocks/src/system/blocks/event-details.d.ts +39 -6
  70. package/dist/_dts/blocks/src/system/blocks/events/event-calendar.d.ts +2 -1
  71. package/dist/_dts/blocks/src/system/blocks/events/event-listing.d.ts +3 -3
  72. package/dist/_dts/blocks/src/system/blocks/events/event-spotlight.d.ts +2 -3
  73. package/dist/_dts/blocks/src/system/blocks/events/shared/filtering.d.ts +2 -2
  74. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +64 -3
  75. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +26 -31
  76. package/dist/_dts/blocks/src/system/blocks/events/whole-series/index.d.ts +3 -0
  77. package/dist/_dts/blocks/src/system/blocks/events/whole-series/pricing.d.ts +50 -0
  78. package/dist/_dts/blocks/src/system/blocks/events/whole-series/schemas.d.ts +135 -0
  79. package/dist/_dts/blocks/src/system/blocks/events/whole-series/types.d.ts +81 -0
  80. package/dist/_dts/blocks/src/system/blocks/feature-cards.d.ts +25 -1
  81. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +16 -39
  82. package/dist/_dts/blocks/src/system/blocks/offerings-preview/model.d.ts +1 -1
  83. package/dist/_dts/blocks/src/system/blocks/site-header.d.ts +0 -1
  84. package/dist/_dts/blocks/src/system/blocks/team-members.d.ts +4 -63
  85. package/dist/_dts/blocks/src/system/customize/backgrounds.d.ts +1 -3
  86. package/dist/_dts/blocks/src/system/fields/boxStyles.d.ts +13 -2
  87. package/dist/_dts/blocks/src/system/fields/gridLayout.d.ts +20 -0
  88. package/dist/_dts/blocks/src/system/node/fragments/classNameBinding.d.ts +6 -1
  89. package/dist/_dts/blocks/src/system/node/fragments/styledCard.d.ts +31 -0
  90. package/dist/_dts/blocks/src/system/node/validation-constants.d.ts +1 -1
  91. package/dist/_dts/blocks/src/system/runtime/api/endpoints.d.ts +4 -0
  92. package/dist/_dts/blocks/src/system/runtime/api/types/courses.d.ts +0 -1
  93. package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +0 -1
  94. package/dist/_dts/blocks/src/system/runtime/blockComposition.d.ts +1 -1
  95. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +45 -72
  96. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +21 -36
  97. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.state.d.ts +4 -2
  98. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessWholeSeriesRegistrationFlow.d.ts +6 -6
  99. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +24 -8
  100. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.server.d.ts +8 -0
  101. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.validationErrors.d.ts +17 -0
  102. package/dist/_dts/blocks/src/system/runtime/nodes/course-page-surface-scope.d.ts +2 -5
  103. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration.client.d.ts +4 -2
  104. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration.interactive.d.ts +19 -7
  105. package/dist/_dts/blocks/src/system/runtime/nodes/event-details/logic.d.ts +25 -4
  106. package/dist/_dts/blocks/src/system/runtime/nodes/event-details/presentation.d.ts +75 -0
  107. package/dist/_dts/blocks/src/system/runtime/nodes/event-details/view.d.ts +4 -1
  108. package/dist/_dts/blocks/src/system/runtime/nodes/event-details.client.d.ts +5 -2
  109. package/dist/_dts/blocks/src/system/runtime/nodes/event-details.server.d.ts +5 -2
  110. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/PaymentSelectionStep.d.ts +4 -0
  111. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/RegistrationClosedState.d.ts +5 -0
  112. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/SiteCreditPreviewPanel.d.ts +6 -0
  113. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.planning.d.ts +1 -1
  114. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventPaymentOptions.d.ts +2 -0
  115. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventScope.d.ts +1 -1
  116. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.d.ts +17 -0
  117. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationSurface.d.ts +3 -3
  118. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/siteCreditPreview.d.ts +51 -0
  119. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +3 -3
  120. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +2 -0
  121. package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/BookingModeStep.d.ts +1 -1
  122. package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/CheckIcon.d.ts +1 -1
  123. package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/ErrorStep.d.ts +1 -1
  124. package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/MembershipHero.d.ts +3 -3
  125. package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/PaymentFailedStep.d.ts +1 -1
  126. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/StepIndicator.d.ts +6 -0
  127. package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/VerifyingTimeoutStep.d.ts +1 -1
  128. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationActiveSteps.d.ts +9 -0
  129. package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration/CourseRegistrationErrorBoundary.d.ts → event-registration/whole-series/WholeSeriesRegistrationErrorBoundary.d.ts} +5 -2
  130. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationTerminalContent.d.ts +8 -0
  131. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationWizard.d.ts +8 -0
  132. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/components.d.ts +45 -0
  133. package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/index.d.ts +4 -4
  134. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/presentation.d.ts +7 -0
  135. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/pricing.d.ts +14 -0
  136. package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/types.d.ts +18 -16
  137. package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration/useCourseEligibility.d.ts → event-registration/whole-series/useWholeSeriesEligibility.d.ts} +6 -6
  138. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesPaymentVerification.d.ts +10 -0
  139. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationActions.d.ts +35 -0
  140. package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration/useCourseRegistrationPortal.d.ts → event-registration/whole-series/useWholeSeriesRegistrationPortal.d.ts} +2 -2
  141. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationSelection.d.ts +35 -0
  142. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationWizard.d.ts +185 -0
  143. package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration/useCourseWaitlistSelection.d.ts → event-registration/whole-series/useWholeSeriesWaitlistSelection.d.ts} +5 -5
  144. package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/utils.d.ts +4 -4
  145. package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/whole-series-registration.headless.contract.d.ts +5 -7
  146. package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/whole-series-registration.headless.planning.d.ts +2 -2
  147. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/wholeSeriesPageSurfaceScope.d.ts +17 -0
  148. package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration/courseRegistrationViewState.d.ts → event-registration/whole-series/wholeSeriesRegistrationViewState.d.ts} +7 -7
  149. package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/wizardSteps.d.ts +4 -4
  150. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +24 -54
  151. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.server.d.ts +1 -1
  152. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +2 -0
  153. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.interactive.d.ts +3 -0
  154. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventListing.interactive.d.ts +12 -11
  155. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventListing.server.d.ts +3 -2
  156. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventSpotlight.d.ts +3 -2
  157. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventCard.d.ts +3 -2
  158. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventDetailModal.d.ts +4 -3
  159. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventModalCloseButton.d.ts +7 -0
  160. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventModals.d.ts +4 -3
  161. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekBoardView.d.ts +14 -0
  162. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +59 -2
  163. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/utils.d.ts +4 -1
  164. package/dist/_dts/blocks/src/system/runtime/nodes/shared/MagicLinkForm.d.ts +1 -1
  165. package/dist/_dts/blocks/src/system/runtime/shared/components/DiscountCodeDisclosure.d.ts +12 -12
  166. package/dist/_dts/blocks/src/system/runtime/shared/components/FeedbackMessage.d.ts +17 -1
  167. package/dist/_dts/blocks/src/system/runtime/shared/components/index.d.ts +1 -1
  168. package/dist/_dts/blocks/src/system/runtime/shared/useWaitlistClaim.d.ts +1 -0
  169. package/dist/_dts/blocks/src/system/spacing.d.ts +1 -1
  170. package/dist/_dts/blocks/src/system/transforms/registry/_utils/boxStyleClassNames.d.ts +109 -0
  171. package/dist/_dts/blocks/src/system/transforms/registry/_utils/surfaceForegroundStyles.d.ts +4 -0
  172. package/dist/_dts/blocks/src/system/transforms/registry/boxStyles.d.ts +40 -3
  173. package/dist/_dts/blocks/src/system/transforms/registry/index.d.ts +1 -0
  174. package/dist/_dts/blocks/src/system/transforms/registry/layout.d.ts +4 -37
  175. package/dist/_dts/blocks/src/system/transforms/typed.d.ts +1 -4
  176. package/dist/_dts/commerce/src/purchase/bookingInstalmentSchedule.d.ts +13 -0
  177. package/dist/_dts/commerce/src/purchase/cancellationPolicy.d.ts +7 -0
  178. package/dist/_dts/commerce/src/purchase/canonicalRefundPlanner.d.ts +48 -0
  179. package/dist/_dts/commerce/src/purchase/checkoutCollectionPlan.d.ts +39 -0
  180. package/dist/_dts/commerce/src/purchase/checkoutCommitPlan.d.ts +40 -0
  181. package/dist/_dts/commerce/src/purchase/checkoutDiscountContextPlanning.d.ts +80 -0
  182. package/dist/_dts/commerce/src/purchase/checkoutErrorCodes.d.ts +1 -0
  183. package/dist/_dts/commerce/src/purchase/checkoutOrderItemProjection.d.ts +22 -0
  184. package/dist/_dts/commerce/src/purchase/checkoutPaymentFlow.d.ts +50 -0
  185. package/dist/_dts/commerce/src/purchase/checkoutPaymentPlanPlanning.d.ts +30 -0
  186. package/dist/_dts/commerce/src/purchase/checkoutPaymentTermPlanning.d.ts +10 -0
  187. package/dist/_dts/commerce/src/purchase/checkoutPaymentTerms.d.ts +53 -0
  188. package/dist/_dts/commerce/src/purchase/checkoutQuantity.d.ts +8 -0
  189. package/dist/_dts/commerce/src/purchase/checkoutSessionMetadata.d.ts +76 -0
  190. package/dist/_dts/commerce/src/purchase/checkoutSettlement.d.ts +46 -0
  191. package/dist/_dts/commerce/src/purchase/checkoutStripeFinalizationPlanning.d.ts +12 -0
  192. package/dist/_dts/commerce/src/purchase/checkoutStripeSessionPlanning.d.ts +125 -0
  193. package/dist/_dts/commerce/src/purchase/checkoutValidatedItemPlanning.d.ts +55 -0
  194. package/dist/_dts/commerce/src/purchase/confirmationEmailPayment.d.ts +91 -0
  195. package/dist/_dts/commerce/src/purchase/discountApplication.d.ts +74 -0
  196. package/dist/_dts/commerce/src/purchase/index.d.ts +55 -0
  197. package/dist/_dts/commerce/src/purchase/oneTimeCheckoutPlanning.d.ts +86 -0
  198. package/dist/_dts/commerce/src/purchase/order-number.d.ts +33 -0
  199. package/dist/_dts/commerce/src/purchase/orderCancellationPlan.d.ts +19 -0
  200. package/dist/_dts/commerce/src/purchase/orderCompletionEmailPlan.d.ts +71 -0
  201. package/dist/_dts/commerce/src/purchase/orderConfirmationPlanning.d.ts +120 -0
  202. package/dist/_dts/commerce/src/purchase/orderFulfillmentPlan.d.ts +81 -0
  203. package/dist/_dts/commerce/src/purchase/orderFulfillmentResult.d.ts +8 -0
  204. package/dist/_dts/commerce/src/purchase/orderHistoryLedgerFilters.d.ts +1 -0
  205. package/dist/_dts/commerce/src/purchase/orderHistorySource.d.ts +11 -0
  206. package/dist/_dts/commerce/src/purchase/orderInstalmentAdminSettlement.d.ts +43 -0
  207. package/dist/_dts/commerce/src/purchase/orderInstalmentClosure.d.ts +29 -0
  208. package/dist/_dts/commerce/src/purchase/orderInstalmentLifecycle.d.ts +44 -0
  209. package/dist/_dts/commerce/src/purchase/orderInstalmentPayoff.d.ts +24 -0
  210. package/dist/_dts/commerce/src/purchase/orderInstalmentPlan.d.ts +40 -0
  211. package/dist/_dts/commerce/src/purchase/orderItemMetadata.d.ts +151 -0
  212. package/dist/_dts/commerce/src/purchase/orderItemSupport.d.ts +14 -0
  213. package/dist/_dts/commerce/src/purchase/orderListFilters.d.ts +3 -0
  214. package/dist/_dts/commerce/src/purchase/orderPaymentLinkPlanning.d.ts +60 -0
  215. package/dist/_dts/commerce/src/purchase/orderPaymentReceipt.d.ts +184 -0
  216. package/dist/_dts/commerce/src/purchase/orderPaymentState.d.ts +135 -0
  217. package/dist/_dts/commerce/src/purchase/orderPlanningTypes.d.ts +102 -0
  218. package/dist/_dts/commerce/src/purchase/orderRefundPlanning.d.ts +50 -0
  219. package/dist/_dts/commerce/src/purchase/orderRefundPolicy.d.ts +36 -0
  220. package/dist/_dts/commerce/src/purchase/orderTotals.d.ts +23 -0
  221. package/dist/_dts/commerce/src/purchase/orderTypes.d.ts +39 -0
  222. package/dist/_dts/commerce/src/purchase/pendingCheckoutSessionClaim.d.ts +1 -0
  223. package/dist/_dts/commerce/src/purchase/persistedCheckoutLines.d.ts +27 -0
  224. package/dist/_dts/commerce/src/purchase/protectedDepositRefundPolicy.d.ts +86 -0
  225. package/dist/_dts/commerce/src/purchase/refundPolicy.d.ts +8 -0
  226. package/dist/_dts/commerce/src/purchase/refundRailSplit.d.ts +40 -0
  227. package/dist/_dts/commerce/src/purchase/result.d.ts +2 -0
  228. package/dist/_dts/commerce/src/purchase/settlement.d.ts +97 -0
  229. package/dist/_dts/commerce/src/purchase/shopRefundPlanning.d.ts +43 -0
  230. package/dist/_dts/commerce/src/purchase/stateTransitions.d.ts +31 -0
  231. package/dist/_dts/commerce/src/purchase/stripeMinimumCharge.d.ts +10 -0
  232. package/dist/_dts/commerce/src/purchase/types.d.ts +168 -0
  233. package/dist/_dts/commerce/src/shop/shipmentEligibility.d.ts +14 -0
  234. package/dist/_dts/commerce/src/utils/assertNever.d.ts +1 -0
  235. package/dist/_dts/content-editor/src/components/ContentFieldsForm.d.ts +2 -2
  236. package/dist/_dts/content-model/src/content-types/builtin-schemas.d.ts +10 -6
  237. package/dist/_dts/content-model/src/content-types/builtins.d.ts +10 -6
  238. package/dist/_dts/core/src/booking-vertical-catalog.d.ts +741 -0
  239. package/dist/_dts/core/src/booking-vertical-config.d.ts +66 -0
  240. package/dist/_dts/core/src/booking-vertical-definitions.d.ts +68 -0
  241. package/dist/_dts/{api/src/bookingVerticalPreset.d.ts → core/src/booking-vertical-preset.d.ts} +1 -1
  242. package/dist/_dts/core/src/booking-verticals.d.ts +98 -0
  243. package/dist/_dts/core/src/branded.d.ts +4 -0
  244. package/dist/_dts/core/src/event-page-selection.d.ts +22 -0
  245. package/dist/_dts/core/src/event-page-surface-subject.d.ts +25 -4
  246. package/dist/_dts/core/src/event-pricing.d.ts +5 -0
  247. package/dist/_dts/core/src/event-series-behaviour.d.ts +16 -0
  248. package/dist/_dts/core/src/index.d.ts +6 -0
  249. package/dist/_dts/core/src/public-event-booking-availability.d.ts +8 -0
  250. package/dist/_dts/core/src/secret.d.ts +44 -0
  251. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +413 -0
  252. package/dist/_dts/db/src/schemas/forms.d.ts +4 -4
  253. package/dist/_dts/editor-blocks/src/BlockEditor.d.ts +2 -1
  254. package/dist/_dts/editor-blocks/src/BlockForm.d.ts +2 -2
  255. package/dist/_dts/editor-blocks/src/block-editor/BlockCard.d.ts +2 -2
  256. package/dist/_dts/editor-blocks/src/block-editor/BlockCardBody.d.ts +1 -1
  257. package/dist/_dts/editor-blocks/src/block-editor/BlockCardHeader.d.ts +1 -1
  258. package/dist/_dts/editor-blocks/src/block-editor/SortableBlockItem.d.ts +1 -1
  259. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockValidationManifests.d.ts +1 -1
  260. package/dist/_dts/editor-blocks/src/block-editor/preparedManifest.d.ts +1 -1
  261. package/dist/_dts/editor-blocks/src/blockPayload.d.ts +1 -1
  262. package/dist/_dts/editor-blocks/src/index.d.ts +2 -2
  263. package/dist/_dts/editor-blocks/src/media/MediaField.d.ts +2 -2
  264. package/dist/_dts/editor-blocks/src/widgets/button/ButtonField.d.ts +1 -1
  265. package/dist/_dts/editor-blocks/src/widgets/button/ButtonVariantField.d.ts +1 -1
  266. package/dist/_dts/editor-blocks/src/widgets/button/index.d.ts +1 -1
  267. package/dist/_dts/editor-blocks/src/widgets/content-type-select/ContentTypeSelectField.d.ts +1 -1
  268. package/dist/_dts/editor-blocks/src/widgets/entry-picker/EntryPickerField.d.ts +1 -1
  269. package/dist/_dts/editor-blocks/src/widgets/entry-picker/index.d.ts +1 -1
  270. package/dist/_dts/editor-blocks/src/widgets/icon-picker/IconPickerField.d.ts +1 -1
  271. package/dist/_dts/editor-blocks/src/widgets/inline-text/InlineTextField.d.ts +1 -1
  272. package/dist/_dts/editor-blocks/src/widgets/link/LinkField.d.ts +2 -2
  273. package/dist/_dts/editor-blocks/src/widgets/offerings-preview/OfferingsPreviewGroupOrderField.d.ts +1 -1
  274. package/dist/_dts/editor-blocks/src/widgets/reference/ReferenceField.d.ts +2 -2
  275. package/dist/_dts/editor-blocks/src/widgets/rich-text/RichTextField.d.ts +2 -2
  276. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/SiteOptionPickerField.d.ts +1 -1
  277. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/utils.d.ts +1 -1
  278. package/dist/_dts/media-core/src/fileUploadCompletion.d.ts +3 -0
  279. package/dist/_dts/media-core/src/fileUploadDurableFinalization.d.ts +2 -0
  280. package/dist/_dts/media-core/src/identifiers.d.ts +10 -0
  281. package/dist/_dts/media-core/src/mediaWriteNormalizer.d.ts +2 -6
  282. package/dist/_dts/media-core/src/types.d.ts +2 -1
  283. package/dist/_dts/media-editor/src/index.d.ts +2 -2
  284. package/dist/_dts/media-editor/src/mediaSelection.d.ts +1 -22
  285. package/dist/_dts/media-editor/src/useMediaSelection.d.ts +0 -9
  286. package/dist/_dts/preview-next/src/client/blocks/useBlockCustomizeControls.d.ts +1 -1
  287. package/dist/_dts/preview-next/src/client/preview/ButtonHoverRoleControls.d.ts +10 -0
  288. package/dist/_dts/preview-next/src/client/preview/ButtonStylePicker.d.ts +3 -2
  289. package/dist/_dts/preview-next/src/client/preview/EntryEditorPanel.d.ts +1 -1
  290. package/dist/_dts/preview-next/src/client/preview/EntrySlotBlockEditorPanel.d.ts +1 -1
  291. package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +3 -1
  292. package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +4 -1
  293. package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +2 -1
  294. package/dist/_dts/preview-next/src/client/preview/PreviewSiteFontStorageContext.d.ts +6 -0
  295. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.d.ts +3 -1
  296. package/dist/_dts/preview-next/src/client/preview/StyleConfiguratorWarningNotice.d.ts +7 -0
  297. package/dist/_dts/preview-next/src/client/preview/siteFontPreview.d.ts +5 -0
  298. package/dist/_dts/preview-next/src/client/preview/siteStylePreviewPlanner.d.ts +1 -1
  299. package/dist/_dts/preview-next/src/client/sdk/contentStorage.d.ts +10 -0
  300. package/dist/_dts/preview-next/src/client/widgets/widgetOverrides.d.ts +1 -1
  301. package/dist/_dts/preview-next/src/index.d.ts +1 -0
  302. package/dist/_dts/preview-next/src/keepAlive.d.ts +3 -5
  303. package/dist/_dts/preview-next/src/refresh-contract.d.ts +1 -0
  304. package/dist/_dts/preview-next/src/route-contract.d.ts +7 -0
  305. package/dist/_dts/sdk/src/client/eventSubrouteReadOperations.d.ts +11 -0
  306. package/dist/_dts/sdk/src/client/types.d.ts +12 -5
  307. package/dist/_dts/sdk/src/components.d.ts +1 -1
  308. package/dist/_dts/sdk/src/contracts/index.d.ts +1 -1
  309. package/dist/_dts/sdk/src/contracts/page.d.ts +2 -13
  310. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +64 -54
  311. package/dist/_dts/sdk/src/next/pageMetadataProjection.d.ts +7 -0
  312. package/dist/_dts/sdk/src/next/resolveEventPageSubroute.d.ts +12 -0
  313. package/dist/_dts/sdk/src/preview-next/keep-alive.d.ts +1 -1
  314. package/dist/_dts/sdk/src/public-api/contracts.d.ts +5 -19
  315. package/dist/_dts/sdk/src/public-api/eventSubrouteContracts.d.ts +12 -0
  316. package/dist/_dts/sdk/src/public-api/runtime.d.ts +1 -1
  317. package/dist/_dts/sdk/src/rendering/client.d.ts +44 -0
  318. package/dist/_dts/sdk/src/rendering/components/Layout.d.ts +1 -1
  319. package/dist/_dts/sdk/src/rendering/index.d.ts +1 -1
  320. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +9 -1
  321. package/dist/_dts/sdk/src/routing/entrySubroutes.d.ts +1 -1
  322. package/dist/_dts/sdk/src/routing/resolveOccurrence.d.ts +4 -3
  323. package/dist/_dts/sdk/src/routing/resolvePageContent.d.ts +7 -3
  324. package/dist/_dts/sdk/src/theme-bridge/types.d.ts +4 -2
  325. package/dist/_dts/sdk/src/version.d.ts +1 -1
  326. package/dist/_dts/theme-core/src/buttons/buttonSurfaceContext.d.ts +1 -1
  327. package/dist/_dts/theme-core/src/buttons/contextualHover.d.ts +41 -0
  328. package/dist/_dts/theme-core/src/buttons/index.d.ts +1 -0
  329. package/dist/_dts/theme-core/src/buttons/resolveButtonColourStates.d.ts +3 -0
  330. package/dist/_dts/theme-core/src/buttons/resolveButtonHoverTreatment.d.ts +14 -0
  331. package/dist/_dts/theme-core/src/buttons/styles/domain.d.ts +21 -4
  332. package/dist/_dts/theme-core/src/buttons/styles/recipes/flatInk.d.ts +92 -0
  333. package/dist/_dts/theme-core/src/buttons/styles/recipes/staticRecipes.d.ts +10 -150
  334. package/dist/_dts/theme-core/src/buttons/styles/registry.d.ts +57 -102
  335. package/dist/_dts/theme-core/src/buttons/styles/selection.d.ts +50 -2
  336. package/dist/_dts/theme-core/src/buttons/types.d.ts +29 -0
  337. package/dist/_dts/theme-core/src/cards/core.d.ts +54 -10
  338. package/dist/_dts/theme-core/src/cards/decorations.d.ts +33 -0
  339. package/dist/_dts/theme-core/src/cards/generateDefaultCardSystem.d.ts +7 -2
  340. package/dist/_dts/theme-core/src/cards/index.d.ts +3 -0
  341. package/dist/_dts/theme-core/src/cards/openCardVariant.d.ts +24 -0
  342. package/dist/_dts/theme-core/src/cards/roles.d.ts +38 -0
  343. package/dist/_dts/theme-core/src/cards/siteStyleDefaults.d.ts +53 -8
  344. package/dist/_dts/theme-core/src/cards/types.d.ts +474 -28
  345. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  346. package/dist/_dts/theme-core/src/header/legacyHeaderVariant.d.ts +59 -0
  347. package/dist/_dts/theme-core/src/header/paintTargets.d.ts +2 -2
  348. package/dist/_dts/theme-core/src/header/scrollTreatment.d.ts +3 -2
  349. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +30 -138
  350. package/dist/_dts/theme-core/src/palette/utils/contrast.d.ts +1 -0
  351. package/dist/_dts/theme-core/src/palette/utils/opaqueSurfaceColor.d.ts +6 -0
  352. package/dist/_dts/theme-core/src/runtime/buildThemeRuntimeFromBridge.d.ts +1 -1
  353. package/dist/_dts/theme-core/src/schema.d.ts +302 -107
  354. package/dist/_dts/theme-core/src/site-styles/appearancePresetCatalog.d.ts +111 -102
  355. package/dist/_dts/theme-core/src/site-styles/appearancePresetResolution.d.ts +12 -1
  356. package/dist/_dts/theme-core/src/site-styles/appearancePresetTypes.d.ts +9 -4
  357. package/dist/_dts/theme-core/src/site-styles/backgroundAppearance.d.ts +0 -20
  358. package/dist/_dts/theme-core/src/site-styles/blockAppearancePresets.d.ts +111 -102
  359. package/dist/_dts/theme-core/src/site-styles/buttonSelectionCompiler.d.ts +18 -0
  360. package/dist/_dts/theme-core/src/site-styles/cardRoleVocabulary.d.ts +48 -0
  361. package/dist/_dts/theme-core/src/site-styles/compilationPlan.d.ts +21 -0
  362. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +21 -385
  363. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +10 -18
  364. package/dist/_dts/theme-core/src/site-styles/headerLayoutTypes.d.ts +2 -4
  365. package/dist/_dts/theme-core/src/site-styles/headerOpeningForeground.d.ts +2 -9
  366. package/dist/_dts/theme-core/src/site-styles/headerOpeningSection.d.ts +0 -2
  367. package/dist/_dts/theme-core/src/site-styles/index.d.ts +5 -0
  368. package/dist/_dts/theme-core/src/site-styles/pageDesignAppearanceAvailability.d.ts +3 -0
  369. package/dist/_dts/theme-core/src/site-styles/pageDesignEditorCapabilities.d.ts +22 -0
  370. package/dist/_dts/theme-core/src/site-styles/pageDesignEditorModel.d.ts +9 -8
  371. package/dist/_dts/theme-core/src/site-styles/pageDesignIntentEquality.d.ts +3 -0
  372. package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +2 -11
  373. package/dist/_dts/theme-core/src/site-styles/previewRuntimeCapabilities.d.ts +19 -0
  374. package/dist/_dts/theme-core/src/site-styles/runtimeBackgroundResolution.d.ts +9 -0
  375. package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +1 -62
  376. package/dist/_dts/theme-core/src/site-styles/selectionFallbackWarning.d.ts +15 -0
  377. package/dist/_dts/theme-core/src/site-styles/sourceCatalogs.d.ts +13 -12
  378. package/dist/_dts/theme-core/src/site-styles/types.d.ts +62 -39
  379. package/dist/_dts/theme-core/src/siteChromePlanning.d.ts +9 -9
  380. package/dist/_dts/theme-core/src/status/generateStatusCss.d.ts +1 -0
  381. package/dist/_dts/theme-core/src/surfaces/index.d.ts +1 -0
  382. package/dist/_dts/theme-core/src/surfaces/resolveSurfaceForeground.d.ts +39 -0
  383. package/dist/_dts/ui/src/navigation-tabs.d.ts +5 -2
  384. package/dist/client/{DiscountCodeDisclosure-Ur-Xx1U_.mjs → DiscountCodeDisclosure-DO7llLxm.mjs} +12 -12
  385. package/dist/client/{EventCombined.client-EhscD4U6.mjs → EventCombined.client-xID7zN__.mjs} +38 -50
  386. package/dist/client/{EventListing.client-Bn26cFTY.mjs → EventListing.client-CriBslp0.mjs} +2 -2
  387. package/dist/client/{FeedbackMessage-ByMrs3cr.mjs → FeedbackMessage-CtLvvS_d.mjs} +15 -3
  388. package/dist/client/{LeafletStaticMap-BUw9Ntzr.mjs → LeafletStaticMap-DYmHnM8g.mjs} +1 -1
  389. package/dist/client/{StepIndicator-BfbdiVQI.mjs → StepIndicator-CGixP_LW.mjs} +3 -3
  390. package/dist/client/{CourseRegistrationWizard-Bvtz9G9g.mjs → WholeSeriesRegistrationWizard-BEjzSiOA.mjs} +1410 -1247
  391. package/dist/client/{accordion-CjIeof73.mjs → accordion-CgFbnnnQ.mjs} +1 -1
  392. package/dist/client/{bookingForm-DwEeovf_.mjs → bookingForm-dUyGpbxc.mjs} +56 -39
  393. package/dist/client/bookings.mjs +1096 -731
  394. package/dist/client/{carousel-BMrfgOba.mjs → carousel-BvBwkUzx.mjs} +2 -2
  395. package/dist/client/{carousel.client-CpwTUhIo.mjs → carousel.client-59G_WMr4.mjs} +1 -1
  396. package/dist/client/{cart-rXEdxTdb.mjs → cart-DiZENT2E.mjs} +3 -3
  397. package/dist/client/{checkout-D3JlSzh3.mjs → checkout-Dq13KIgR.mjs} +3 -3
  398. package/dist/client/client.mjs +10645 -6794
  399. package/dist/client/{colorStyles-BWpj_h4C.mjs → colorStyles-CrxJrPjJ.mjs} +277 -1
  400. package/dist/client/{context-CJz1Vlsz.mjs → context-B83PiNzm.mjs} +6 -21
  401. package/dist/client/{courseRegistration-DO5XvMAA.mjs → courseRegistration-CKC5NmyH.mjs} +11 -5
  402. package/dist/client/{eventCalendar-DO6rTqCn.mjs → eventCalendar-BF0Jatfw.mjs} +42 -45
  403. package/dist/client/{eventCombined-bJ3i_ovU.mjs → eventCombined-BuoCF8je.mjs} +3 -3
  404. package/dist/client/{eventDetails-CCbrXE7o.mjs → eventDetails-CKwh0S9s.mjs} +276 -94
  405. package/dist/client/{eventListing-Bdlt9YTm.mjs → eventListing-eUxaWFaB.mjs} +3 -3
  406. package/dist/client/{eventRegistration-B02lt6iY.mjs → eventRegistration-CfkNOkPb.mjs} +630 -138
  407. package/dist/client/{form-DrUBAAox.mjs → form-C17H1c_H.mjs} +4 -4
  408. package/dist/client/{headerSection-MzqvHL6T.mjs → headerSection-DEwUmrtt.mjs} +2 -2
  409. package/dist/client/hooks.mjs +3224 -2485
  410. package/dist/client/{locationMap-DG8BxTBm.mjs → locationMap-Pf2QwuvW.mjs} +3 -3
  411. package/dist/client/{media-CNE1Z-wb.mjs → media-BOHuueS5.mjs} +16 -4
  412. package/dist/client/{newsletterForm-BzO-Td3p.mjs → newsletterForm-BWQAH5Sv.mjs} +4 -4
  413. package/dist/client/pricing-CVdvbopJ.mjs +195 -0
  414. package/dist/client/{productDetail-CfQ7rhVK.mjs → productDetail-BZi1Fa_G.mjs} +3 -3
  415. package/dist/client/{productList-C23rOLUi.mjs → productList-qq-55DNk.mjs} +3 -3
  416. package/dist/client/{propsDecoder-CAZdhwjs.mjs → propsDecoder-BxmqPKdP.mjs} +859 -650
  417. package/dist/client/rendering/client.mjs +8658 -7862
  418. package/dist/client/rendering/islands.mjs +20 -20
  419. package/dist/client/rendering.mjs +11437 -7446
  420. package/dist/client/{scrollToBlock-DSSqVQr1.mjs → scrollToBlock-B3CcKdtG.mjs} +1 -1
  421. package/dist/client/{shop-BMToKLK7.mjs → shop-DNWJPut5.mjs} +7 -7
  422. package/dist/client/{shop-commerce-DB4JRKmp.mjs → shop-commerce-BhvQCosS.mjs} +8 -8
  423. package/dist/client/{shop-commerce-store-BOqSIOuc.mjs → shop-commerce-store-B04sCNnW.mjs} +1 -1
  424. package/dist/client/{shopShared-B6SK9DZv.mjs → shopShared-DNNgZlmW.mjs} +5 -5
  425. package/dist/client/{useEventFilters-CULOa4nB.mjs → useEventFilters-CUmhE24_.mjs} +329 -84
  426. package/dist/client/{usePolling-BGG_8-jl.mjs → usePolling-M5jG675x.mjs} +3 -3
  427. package/dist/preview-next/before-render.mjs +439 -168
  428. package/dist/preview-next/client/runtime.mjs +4 -4
  429. package/dist/preview-next/keepAlive.mjs +7593 -29
  430. package/dist/preview-next/middleware.mjs +433 -167
  431. package/dist/{previewAuthStore-_GXFRg2W.mjs → previewAuthStore-BFKd4LrN.mjs} +432 -167
  432. package/dist/{sdk-runtime-hhSOMShR.mjs → sdk-runtime-BEXb1wqo.mjs} +2 -2
  433. package/dist/{separator-flRaFc14.mjs → separator-DGMuip1D.mjs} +1 -1
  434. package/dist/server/components.mjs +9596 -6347
  435. package/dist/server/config-validation.mjs +3224 -2486
  436. package/dist/server/config.mjs +3224 -2486
  437. package/dist/server/data.mjs +3224 -2485
  438. package/dist/server/index.mjs +486 -200
  439. package/dist/server/manifest.mjs +0 -1
  440. package/dist/server/next.mjs +10343 -7188
  441. package/dist/server/page-converter.mjs +1828 -2094
  442. package/dist/server/prebuild.mjs +1 -1
  443. package/dist/server/rendering/server.mjs +6750 -4519
  444. package/dist/server/rendering.mjs +9591 -6342
  445. package/dist/server/routing.mjs +3403 -1594
  446. package/dist/server/server.mjs +3274 -2671
  447. package/dist/server/theme-bridge.mjs +2979 -1639
  448. package/dist/server/theme.mjs +590 -176
  449. package/dist/styles/index.css +1896 -1129
  450. package/package.json +3 -2
  451. package/dist/_dts/api/src/bookingVerticalCatalog.d.ts +0 -746
  452. package/dist/_dts/block-form/src/client/blockDraftSaveability.d.ts +0 -1
  453. package/dist/_dts/block-form/src/widgets/index.d.ts +0 -20
  454. package/dist/_dts/blocks/src/system/runtime/api/requestBody.d.ts +0 -7
  455. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/CourseRegistrationWizard.d.ts +0 -3
  456. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/StepIndicator.d.ts +0 -6
  457. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/components.d.ts +0 -45
  458. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/pricing.d.ts +0 -14
  459. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCoursePaymentVerification.d.ts +0 -9
  460. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationActions.d.ts +0 -35
  461. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationSelection.d.ts +0 -31
  462. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.d.ts +0 -102
  463. package/dist/client/clsx-DgIEfj3H.mjs +0 -16
  464. package/dist/client/eventProductEligibility-AVxyCB1u.mjs +0 -50
  465. package/dist/client/pricing-NgK7ozkg.mjs +0 -174
  466. /package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/PortalAuthSidebar.d.ts +0 -0
  467. /package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/SuccessStep.d.ts +0 -0
  468. /package/dist/_dts/blocks/src/system/runtime/nodes/{course-registration → event-registration/whole-series}/WaitlistStep.d.ts +0 -0
@@ -1,17 +1,17 @@
1
1
  "use client";
2
- import { It as toBookingTimeZone, Kt as assertNever, Lt as toScheduledBookingDateTime, Ot as formatBookingDate, Rt as parseEventPageSurfaceSubject, Z as themeButtonClassName, bt as assertNever$1, jt as formatBookingTime } from "./propsDecoder-CAZdhwjs.mjs";
3
- import { n as formatCoursePriceDisplay, r as resolveCoursePricingState, t as formatCoursePriceAmount } from "./pricing-NgK7ozkg.mjs";
4
- import { n as useBlockApi } from "./context-CJz1Vlsz.mjs";
2
+ import { At as formatBookingDate, Bt as parseEventPageSurfaceSubject, Jt as assertNever$1, Nt as formatBookingTime, Rt as toBookingTimeZone, St as assertNever, et as themeButtonClassName, zt as toScheduledBookingDateTime } from "./propsDecoder-BxmqPKdP.mjs";
3
+ import { n as formatWholeSeriesPriceDisplay, r as resolveWholeSeriesPricingState, t as formatWholeSeriesPriceAmount } from "./pricing-CVdvbopJ.mjs";
4
+ import { n as useBlockApi } from "./context-B83PiNzm.mjs";
5
5
  import { n as isSpamProtectionEnabled, r as AltchaWidget, t as getChallengeUrl } from "./src-B833rYRr.mjs";
6
- import { a as CheckIcon, i as StateIcon, n as useDiscountCodeUi, r as TerminalPanel, t as scrollToBlock } from "./scrollToBlock-DSSqVQr1.mjs";
7
- import { t as DiscountCodeDisclosure } from "./DiscountCodeDisclosure-Ur-Xx1U_.mjs";
8
- import { n as SpinnerNode, r as formatPrice, t as StepIndicator$1 } from "./StepIndicator-BfbdiVQI.mjs";
9
- import { t as FeedbackMessage } from "./FeedbackMessage-ByMrs3cr.mjs";
6
+ import { a as CheckIcon, i as StateIcon, n as useDiscountCodeUi, r as TerminalPanel, t as scrollToBlock } from "./scrollToBlock-B3CcKdtG.mjs";
7
+ import { t as DiscountCodeDisclosure } from "./DiscountCodeDisclosure-DO7llLxm.mjs";
8
+ import { n as SpinnerNode, r as formatPrice, t as StepIndicator$1 } from "./StepIndicator-CGixP_LW.mjs";
9
+ import { t as FeedbackMessage } from "./FeedbackMessage-CtLvvS_d.mjs";
10
10
  import { n as getFieldValidationControlProps, t as FieldValidationMessage } from "./FieldValidationMessage-AYanWFb-.mjs";
11
11
  import { t as buildCheckoutReturnUrls } from "./checkoutUrls-Ct8Mxna3.mjs";
12
12
  import { t as CrossIcon } from "./CrossIcon-Dn1KRKW5.mjs";
13
13
  import { t as ModalShell } from "./ModalShell-CqkBvBIC.mjs";
14
- import React, { Component, useCallback, useEffect, useMemo, useReducer, useState, useSyncExternalStore } from "react";
14
+ import React, { Component, useCallback, useEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore } from "react";
15
15
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
16
16
  //#region ../blocks/src/system/runtime/shared/utils/validation.ts
17
17
  const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
@@ -103,59 +103,28 @@ function MembershipHero$1({ membershipName, classPrefix, onBookForSomeoneElse })
103
103
  });
104
104
  }
105
105
  //#endregion
106
- //#region ../blocks/src/system/runtime/nodes/course-registration/utils.ts
107
- /**
108
- * Course Registration Utilities
109
- *
110
- * Formatting and validation helpers for course registration.
111
- */
112
- /**
113
- * Format a date string to a localized date.
114
- *
115
- * @param dateString - ISO 8601 date string
116
- * @param locale - Optional locale for formatting (defaults to browser locale)
117
- * @returns Formatted date string (e.g., "Sat, Feb 1, 2026")
118
- */
119
- function formatDate(dateString, options) {
120
- return formatBookingDate(toScheduledBookingDateTime({
121
- startsAt: dateString,
122
- locale: options?.locale,
123
- timeZone: toBookingTimeZone(options?.timeZone)
124
- }), {
125
- weekday: "short",
126
- month: "short",
127
- day: "numeric",
128
- year: "numeric"
129
- });
130
- }
131
- /**
132
- * Format a date string to a localized time.
133
- *
134
- * @param dateString - ISO 8601 date string
135
- * @param locale - Optional locale for formatting (defaults to browser locale)
136
- * @returns Formatted time string (e.g., "10:00 AM")
137
- */
138
- function formatTime(dateString, options) {
139
- return formatBookingTime(toScheduledBookingDateTime({
140
- startsAt: dateString,
141
- locale: options?.locale,
142
- timeZone: toBookingTimeZone(options?.timeZone)
143
- }), {
144
- hour: "numeric",
145
- minute: "2-digit"
146
- });
106
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/presentation.ts
107
+ function resolveWholeSeriesRegistrationPresentation(kind) {
108
+ switch (kind) {
109
+ case "event": return {
110
+ dataBlock: "event-registration",
111
+ anchorId: "event-registration",
112
+ rootClass: "event-registration"
113
+ };
114
+ case "temporary-course-adapter": return {
115
+ dataBlock: "course-registration",
116
+ anchorId: "course-registration",
117
+ rootClass: "course-registration"
118
+ };
119
+ }
147
120
  }
148
- /**
149
- * Anchor ID for the registration block, used for scroll targeting.
150
- */
151
- const COURSE_REGISTRATION_ANCHOR_ID = "course-registration";
152
121
  //#endregion
153
- //#region ../blocks/src/system/runtime/nodes/course-registration/CourseRegistrationErrorBoundary.tsx
122
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationErrorBoundary.tsx
154
123
  /**
155
- * Error boundary wrapper for course registration.
124
+ * Error boundary wrapper for run registration.
156
125
  * Catches render errors and displays a fallback UI.
157
126
  */
158
- var CourseRegistrationErrorBoundary = class extends Component {
127
+ var WholeSeriesRegistrationErrorBoundary = class extends Component {
159
128
  constructor(props) {
160
129
  super(props);
161
130
  this.state = { hasError: false };
@@ -167,364 +136,264 @@ var CourseRegistrationErrorBoundary = class extends Component {
167
136
  };
168
137
  }
169
138
  componentDidCatch(error, errorInfo) {
170
- console.error("Course registration error:", error, errorInfo);
139
+ console.error("Run registration error:", error, errorInfo);
171
140
  }
172
141
  render() {
173
- if (this.state.hasError) return /* @__PURE__ */ jsx("div", {
174
- id: COURSE_REGISTRATION_ANCHOR_ID,
175
- className: `course-registration ${this.props.className || ""}`,
176
- children: /* @__PURE__ */ jsxs("div", {
177
- className: "cr-error",
178
- children: [
179
- /* @__PURE__ */ jsx("div", {
180
- className: "cr-error__icon",
181
- children: "✕"
182
- }),
183
- /* @__PURE__ */ jsx("h3", {
184
- className: "cr-error__title",
185
- children: "Something went wrong"
186
- }),
187
- /* @__PURE__ */ jsx("p", {
188
- className: "cr-error__message",
189
- children: "Unable to load the booking form. Please refresh the page and try again."
190
- })
191
- ]
192
- })
193
- });
142
+ if (this.state.hasError) {
143
+ const presentation = resolveWholeSeriesRegistrationPresentation(this.props.presentationKind ?? "event");
144
+ return /* @__PURE__ */ jsx("div", {
145
+ id: presentation.anchorId,
146
+ "data-block": presentation.dataBlock,
147
+ className: `${presentation.rootClass} ${this.props.className || ""}`,
148
+ children: /* @__PURE__ */ jsxs("div", {
149
+ className: "er-whole-series-error",
150
+ children: [
151
+ /* @__PURE__ */ jsx("div", {
152
+ className: "er-whole-series-error__icon",
153
+ children: "✕"
154
+ }),
155
+ /* @__PURE__ */ jsx("h3", {
156
+ className: "er-whole-series-error__title",
157
+ children: "Something went wrong"
158
+ }),
159
+ /* @__PURE__ */ jsx("p", {
160
+ className: "er-whole-series-error__message",
161
+ children: "Unable to load the booking form. Please refresh the page and try again."
162
+ })
163
+ ]
164
+ })
165
+ });
166
+ }
194
167
  return this.props.children;
195
168
  }
196
169
  };
197
170
  //#endregion
198
- //#region ../blocks/src/system/runtime/shared/components/LoggedInAsUser.tsx
171
+ //#region ../blocks/src/system/runtime/nodes/shared/MagicLinkForm.state.ts
172
+ const initialMagicLinkSubmissionState = Object.freeze({ tag: "idle" });
173
+ function magicLinkSubmissionReducer(state, action) {
174
+ switch (action.type) {
175
+ case "submit-started":
176
+ if (state.tag === "submitting") return state;
177
+ return { tag: "submitting" };
178
+ case "submit-succeeded":
179
+ if (state.tag !== "submitting") return state;
180
+ return { tag: "success" };
181
+ case "submit-failed":
182
+ if (state.tag !== "submitting") return state;
183
+ return {
184
+ tag: "error",
185
+ message: action.message
186
+ };
187
+ case "reset": return initialMagicLinkSubmissionState;
188
+ default: return assertNever(action);
189
+ }
190
+ }
191
+ function isMagicLinkSubmitting(state) {
192
+ return state.tag === "submitting";
193
+ }
194
+ function getMagicLinkError(state) {
195
+ return state.tag === "error" ? state.message : null;
196
+ }
197
+ //#endregion
198
+ //#region ../blocks/src/system/runtime/nodes/shared/MagicLinkForm.tsx
199
199
  /**
200
- * Displays the logged-in user's email with an optional logout link.
201
- *
202
- * Used in registration forms when the email field is locked due to portal authentication.
203
- * Shows: "Logged in as {email} — Not you? Log out"
200
+ * Reusable magic link login form.
201
+ * Used by Customer Portal and Event Registration blocks.
204
202
  */
205
- function LoggedInAsUser({ email, onLogout, classPrefix }) {
206
- return /* @__PURE__ */ jsxs("p", {
207
- className: `${classPrefix}-logged-in-hint`,
208
- children: [
209
- "Logged in as ",
210
- email,
211
- onLogout && /* @__PURE__ */ jsxs(Fragment, { children: [" — ", /* @__PURE__ */ jsx("button", {
212
- type: "button",
213
- className: `${classPrefix}-link`,
214
- onClick: onLogout,
215
- children: "Not you? Log out"
216
- })] })
217
- ]
203
+ function MagicLinkForm({ initialEmail = "", title, subtitle, buttonText = "Send login link", successMessage = "Check your email for a login link to sign in.", onSuccess, classPrefix = "er", compact = false }) {
204
+ const api = useBlockApi();
205
+ const [email, setEmail] = useState(initialEmail);
206
+ const [submissionState, dispatchSubmission] = useReducer(magicLinkSubmissionReducer, initialMagicLinkSubmissionState);
207
+ const loading = isMagicLinkSubmitting(submissionState);
208
+ const error = getMagicLinkError(submissionState);
209
+ const handleSubmit = async (e) => {
210
+ e.preventDefault();
211
+ const normalizedEmail = email.trim().toLowerCase();
212
+ if (!normalizedEmail || loading) return;
213
+ dispatchSubmission({ type: "submit-started" });
214
+ try {
215
+ const redirectTo = `${window.location.pathname}${window.location.search}${window.location.hash}`;
216
+ await api.sendMagicLink({
217
+ email: normalizedEmail,
218
+ redirectUrl: `${window.location.origin}/api/portal/callback?redirect_to=${encodeURIComponent(redirectTo)}`
219
+ });
220
+ dispatchSubmission({ type: "submit-succeeded" });
221
+ onSuccess?.();
222
+ } catch (err) {
223
+ console.error("Magic link error:", err);
224
+ dispatchSubmission({
225
+ type: "submit-failed",
226
+ message: getMagicLinkErrorMessage(err)
227
+ });
228
+ }
229
+ };
230
+ const handleReset = () => {
231
+ setEmail("");
232
+ dispatchSubmission({ type: "reset" });
233
+ };
234
+ if (submissionState.tag === "success") return /* @__PURE__ */ jsxs("div", {
235
+ className: `${classPrefix}-magic-link-success`,
236
+ children: [/* @__PURE__ */ jsx("p", {
237
+ className: `${classPrefix}-portal-auth-text ${classPrefix}-portal-auth-text--success`,
238
+ children: successMessage
239
+ }), !compact && /* @__PURE__ */ jsx("button", {
240
+ type: "button",
241
+ className: classPrefix === "cp" ? themeButtonClassName({
242
+ variant: "secondary",
243
+ size: "md"
244
+ }) : `${classPrefix}-modal-btn ${classPrefix}-modal-btn--secondary`,
245
+ onClick: handleReset,
246
+ children: "Try a different email"
247
+ })]
218
248
  });
219
- }
220
- //#endregion
221
- //#region ../blocks/src/system/runtime/nodes/course-registration/components.tsx
222
- function TeamMemberInlineList({ teamMembers }) {
223
- return /* @__PURE__ */ jsx(Fragment, { children: teamMembers.map((teamMember, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [index > 0 ? ", " : "", teamMember.profilePath ? /* @__PURE__ */ jsx("a", {
224
- href: teamMember.profilePath,
225
- children: teamMember.name
226
- }) : teamMember.name] }, teamMember.id)) });
227
- }
228
- function CourseCard({ course, isSelected, onSelect, showSessions, showPrice, showCapacity, showVenue }) {
229
- const enrollmentClosed = course.enrollmentOpen === false;
230
- const teamMemberNames = (course.teamMembers ?? []).map((teamMember) => teamMember.name).filter(Boolean);
231
- const pricing = resolveCoursePricingState(course);
232
- const priceLabel = formatCoursePriceDisplay(pricing.display);
233
- return /* @__PURE__ */ jsxs("div", {
234
- className: `cr-course-card ${isSelected ? "cr-course-card--selected" : ""}`,
235
- onClick: onSelect,
236
- role: "button",
237
- tabIndex: 0,
238
- "aria-pressed": isSelected,
239
- onKeyDown: (e) => {
240
- if (e.key === "Enter" || e.key === " ") {
241
- e.preventDefault();
242
- onSelect();
243
- }
244
- },
249
+ return /* @__PURE__ */ jsxs("form", {
250
+ onSubmit: handleSubmit,
251
+ className: `${classPrefix}-magic-link-form`,
245
252
  children: [
246
- /* @__PURE__ */ jsx("h3", {
247
- className: "cr-course-card__title",
248
- children: course.title
249
- }),
250
- enrollmentClosed && /* @__PURE__ */ jsx("p", {
251
- className: "cr-course-card__status",
252
- children: "Registration closed"
253
- }),
254
- showSessions && course.sessionsCount > 0 && /* @__PURE__ */ jsxs("p", {
255
- className: "cr-course-card__sessions",
256
- children: [
257
- course.sessionsCount,
258
- " session",
259
- course.sessionsCount !== 1 ? "s" : ""
260
- ]
253
+ title && /* @__PURE__ */ jsx("h3", {
254
+ className: `${classPrefix}-magic-link-title`,
255
+ children: title
261
256
  }),
262
- showPrice && pricing.display.kind !== "unavailable" && /* @__PURE__ */ jsx("p", {
263
- className: "cr-course-card__price",
264
- children: priceLabel
257
+ subtitle && /* @__PURE__ */ jsx("p", {
258
+ className: `${classPrefix}-portal-auth-text`,
259
+ children: subtitle
265
260
  }),
266
- showCapacity && course.availableSpots !== null && /* @__PURE__ */ jsx("p", {
267
- className: "cr-course-card__capacity",
268
- children: course.availableSpots > 0 ? `${course.availableSpots} spot${course.availableSpots !== 1 ? "s" : ""} available` : "Waitlist only"
261
+ /* @__PURE__ */ jsx("input", {
262
+ type: "email",
263
+ className: classPrefix === "cp" ? "cp-input" : `${classPrefix}-form__input`,
264
+ placeholder: "your@email.com",
265
+ value: email,
266
+ onChange: (e) => setEmail(e.target.value),
267
+ autoFocus: !compact,
268
+ required: true,
269
+ disabled: loading
269
270
  }),
270
- showVenue && course.venue && /* @__PURE__ */ jsx("p", {
271
- className: "cr-course-card__venue",
272
- children: course.venue.name
271
+ error && /* @__PURE__ */ jsx("p", {
272
+ className: `${classPrefix}-portal-auth-text ${classPrefix}-portal-auth-text--error`,
273
+ children: error
273
274
  }),
274
- teamMemberNames.length > 0 && /* @__PURE__ */ jsxs("p", {
275
- className: "cr-course-card__venue",
276
- children: ["Team: ", teamMemberNames.join(", ")]
275
+ /* @__PURE__ */ jsx("button", {
276
+ type: "submit",
277
+ className: classPrefix === "cp" ? themeButtonClassName({
278
+ variant: "primary",
279
+ size: "md"
280
+ }) : `${classPrefix}-modal-btn`,
281
+ disabled: !email.trim() || loading,
282
+ children: loading ? "Sending..." : buttonText
277
283
  })
278
284
  ]
279
285
  });
280
286
  }
281
- function CourseSummary({ course, pricing, showSessions, showVenue, showPrice, showMembershipNote }) {
282
- const teamMembers = course.teamMembers ?? [];
283
- const priceLabel = pricing.selectedOption ? `${pricing.selectedOption.name} - ${formatCoursePriceAmount(pricing.selectedOption.priceAmount, pricing.currency)}` : formatCoursePriceDisplay(pricing.display);
284
- return /* @__PURE__ */ jsxs("div", {
285
- className: "cr-summary",
287
+ function getMagicLinkErrorMessage(error) {
288
+ return error instanceof Error ? error.message : "Failed to send. Please try again.";
289
+ }
290
+ //#endregion
291
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/PortalAuthSidebar.tsx
292
+ /**
293
+ * Portal authentication sidebar.
294
+ * Shows login prompt for unauthenticated users who might have memberships.
295
+ */
296
+ const PORTAL_AUTH_COPY = {
297
+ membership: {
298
+ title: "Have a membership?",
299
+ description: "Log in to use your membership to book for free",
300
+ buttonText: "Log in with email",
301
+ modalTitle: "Log in",
302
+ modalHeading: "Log in to your account",
303
+ modalSubtitle: "Enter your email to receive a magic link",
304
+ successMessage: "Check your email for a login link. After clicking, refresh this page."
305
+ },
306
+ "waitlist-claim": {
307
+ title: "Log in to claim your waitlist spot",
308
+ description: "",
309
+ buttonText: "Log in with email to continue",
310
+ modalTitle: "Log in to continue",
311
+ modalHeading: "Log in to your account to continue",
312
+ modalSubtitle: "Enter your email to receive a login link and continue your waitlist claim",
313
+ successMessage: "Check your email for a login link. After clicking it, return here to continue your claim."
314
+ }
315
+ };
316
+ function PortalAuthSidebar({ onMagicLinkSent, autoOpen = false, variant = "membership", loginMessage }) {
317
+ const [showModal, setShowModal] = useState(false);
318
+ const copy = PORTAL_AUTH_COPY[variant];
319
+ const description = variant === "waitlist-claim" ? loginMessage ?? "Log in to continue with your waitlist claim." : copy.description;
320
+ useEffect(() => {
321
+ if (!autoOpen) return;
322
+ setShowModal(true);
323
+ }, [autoOpen]);
324
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
325
+ className: "er-whole-series-portal-sidebar",
286
326
  children: [
327
+ /* @__PURE__ */ jsx("div", {
328
+ className: "er-whole-series-portal-sidebar__icon",
329
+ "aria-hidden": "true",
330
+ children: "👤"
331
+ }),
287
332
  /* @__PURE__ */ jsx("h3", {
288
- className: "cr-summary__title",
289
- children: course.title
333
+ className: "er-whole-series-portal-sidebar__title",
334
+ children: copy.title
290
335
  }),
291
- showSessions && course.sessions.length > 0 && /* @__PURE__ */ jsxs("div", {
292
- className: "cr-summary__sessions",
293
- children: [/* @__PURE__ */ jsx("h4", {
294
- className: "cr-summary__sessions-title",
295
- children: "Sessions"
296
- }), /* @__PURE__ */ jsx("ul", {
297
- className: "cr-summary__sessions-list",
298
- children: course.sessions.map((session) => /* @__PURE__ */ jsxs("li", {
299
- className: "cr-summary__session",
300
- children: [
301
- formatDate(session.startsAt, { timeZone: session.timeZone }),
302
- " ",
303
- "at",
304
- " ",
305
- formatTime(session.startsAt, { timeZone: session.timeZone })
306
- ]
307
- }, session.id))
308
- })]
309
- }),
310
- showVenue && course.venue && /* @__PURE__ */ jsxs("p", {
311
- className: "cr-summary__venue",
312
- children: [
313
- /* @__PURE__ */ jsx("strong", { children: "Venue:" }),
314
- " ",
315
- course.venue.name,
316
- course.venue.address && ` - ${course.venue.address}`
317
- ]
318
- }),
319
- teamMembers.length > 0 && /* @__PURE__ */ jsxs("div", {
320
- className: "cr-summary__venue",
321
- children: [
322
- /* @__PURE__ */ jsx("strong", { children: "Team:" }),
323
- " ",
324
- /* @__PURE__ */ jsx(TeamMemberInlineList, { teamMembers })
325
- ]
326
- }),
327
- showPrice && pricing.display.kind !== "unavailable" && /* @__PURE__ */ jsxs("p", {
328
- className: "cr-summary__price",
329
- children: [
330
- /* @__PURE__ */ jsx("strong", { children: pricing.selectableOptions.length > 0 ? "Pricing:" : "Price:" }),
331
- " ",
332
- priceLabel
333
- ]
336
+ /* @__PURE__ */ jsx("p", {
337
+ className: "er-whole-series-portal-sidebar__text",
338
+ children: description
334
339
  }),
335
- showMembershipNote && /* @__PURE__ */ jsx("p", {
336
- className: "cr-summary__membership",
337
- children: "✓ Your membership can be used to book for free"
338
- })
339
- ]
340
- });
341
- }
342
- function CoursePricingSelector({ pricing, selectedPricingOptionId, onSelect }) {
343
- if (pricing.selectableOptions.length <= 1) return null;
344
- return /* @__PURE__ */ jsxs("fieldset", {
345
- className: "cr-form__field",
346
- children: [/* @__PURE__ */ jsx("legend", {
347
- id: "cr-pricing-options-label",
348
- className: "cr-form__label",
349
- children: "Pricing option"
350
- }), /* @__PURE__ */ jsx("div", {
351
- className: "cr-payment-tiles",
352
- role: "radiogroup",
353
- "aria-labelledby": "cr-pricing-options-label",
354
- children: pricing.selectableOptions.map((option) => {
355
- const isSelected = selectedPricingOptionId === option.id;
356
- const priceLabel = formatCoursePriceAmount(option.priceAmount, pricing.currency);
357
- return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs("button", {
340
+ /* @__PURE__ */ jsx("div", {
341
+ className: "er-whole-series-portal-sidebar__action",
342
+ children: /* @__PURE__ */ jsx("button", {
358
343
  type: "button",
359
- role: "radio",
360
- "aria-checked": isSelected,
361
- className: `cr-payment-tile${isSelected ? " cr-payment-tile--selected" : ""}`,
362
- onClick: () => onSelect(option.id),
363
- children: [/* @__PURE__ */ jsxs("div", {
364
- className: "cr-payment-tile__header",
365
- children: [/* @__PURE__ */ jsx("h3", {
366
- className: "cr-payment-tile__name",
367
- children: option.name
368
- }), /* @__PURE__ */ jsx("span", {
369
- className: "cr-payment-tile__price",
370
- children: priceLabel
371
- })]
372
- }), option.description ? /* @__PURE__ */ jsx("p", {
373
- className: "cr-payment-tile__description",
374
- children: option.description
375
- }) : null]
376
- }) }, option.id);
377
- })
378
- })]
379
- });
380
- }
381
- function CourseSlidingScaleInput({ pricing, value, onChange }) {
382
- const slidingScale = pricing.slidingScale;
383
- if (!slidingScale) return null;
384
- const minLabel = formatCoursePriceAmount(slidingScale.minAmount, pricing.currency);
385
- const maxLabel = formatCoursePriceAmount(slidingScale.maxAmount, pricing.currency);
386
- const suggestedLabel = slidingScale.suggestedAmount !== null ? formatCoursePriceAmount(slidingScale.suggestedAmount, pricing.currency) : null;
387
- return /* @__PURE__ */ jsxs("div", {
388
- className: "cr-form__field",
389
- children: [
390
- /* @__PURE__ */ jsx("label", {
391
- htmlFor: "cr-sliding-amount",
392
- className: "cr-form__label",
393
- children: "Amount"
394
- }),
395
- /* @__PURE__ */ jsx("input", {
396
- id: "cr-sliding-amount",
397
- type: "number",
398
- min: slidingScale.minAmount / 100,
399
- max: slidingScale.maxAmount / 100,
400
- step: "0.01",
401
- inputMode: "decimal",
402
- className: "cr-form__input",
403
- value,
404
- onChange: (event) => onChange(event.target.value)
405
- }),
406
- /* @__PURE__ */ jsxs("p", {
407
- className: "cr-text cr-text--muted",
408
- children: [
409
- "Choose between ",
410
- minLabel,
411
- " and ",
412
- maxLabel,
413
- suggestedLabel ? `; suggested ${suggestedLabel}` : "",
414
- "."
415
- ]
344
+ className: "er-whole-series-portal-sidebar__link",
345
+ onClick: () => setShowModal(true),
346
+ children: copy.buttonText
347
+ })
416
348
  })
417
349
  ]
418
- });
419
- }
420
- function EnrollmentForm({ formData, errors, onChange, isEmailLocked, isLoading, onLogout }) {
421
- const nameErrorId = "cr-name-error";
422
- const emailErrorId = "cr-email-error";
423
- const nameValidationProps = getFieldValidationControlProps({
424
- message: errors.name,
425
- messageId: nameErrorId
426
- });
427
- const emailValidationProps = getFieldValidationControlProps({
428
- message: errors.email,
429
- messageId: emailErrorId
430
- });
431
- return /* @__PURE__ */ jsxs(Fragment, { children: [
432
- /* @__PURE__ */ jsxs("div", {
433
- className: "cr-form__field",
434
- children: [
435
- /* @__PURE__ */ jsx("label", {
436
- htmlFor: "cr-name",
437
- className: "cr-form__label",
438
- children: "Name *"
439
- }),
440
- /* @__PURE__ */ jsx("input", {
441
- id: "cr-name",
442
- type: "text",
443
- className: `cr-form__input ${errors.name ? "cr-form__input--error" : ""}`,
444
- value: formData.name,
445
- onChange: (e) => onChange({
446
- ...formData,
447
- name: e.target.value
448
- }),
449
- disabled: isLoading,
450
- ...nameValidationProps
451
- }),
452
- errors.name && /* @__PURE__ */ jsx(FieldValidationMessage, {
453
- id: nameErrorId,
454
- className: "cr-form__error",
455
- children: errors.name
456
- })
457
- ]
458
- }),
459
- /* @__PURE__ */ jsxs("div", {
460
- className: "cr-form__field",
461
- children: [
462
- /* @__PURE__ */ jsx("label", {
463
- htmlFor: "cr-email",
464
- className: "cr-form__label",
465
- children: "Email *"
466
- }),
467
- /* @__PURE__ */ jsx("input", {
468
- id: "cr-email",
469
- type: "email",
470
- className: `cr-form__input ${errors.email ? "cr-form__input--error" : ""}`,
471
- value: formData.email,
472
- onChange: (e) => onChange({
473
- ...formData,
474
- email: e.target.value
475
- }),
476
- disabled: isEmailLocked || isLoading,
477
- ...emailValidationProps
478
- }),
479
- errors.email && /* @__PURE__ */ jsx(FieldValidationMessage, {
480
- id: emailErrorId,
481
- className: "cr-form__error",
482
- children: errors.email
483
- }),
484
- isEmailLocked && /* @__PURE__ */ jsx(LoggedInAsUser, {
485
- email: formData.email,
486
- onLogout,
487
- classPrefix: "cr"
488
- })
489
- ]
490
- }),
491
- /* @__PURE__ */ jsxs("div", {
492
- className: "cr-form__field",
493
- children: [/* @__PURE__ */ jsx("label", {
494
- htmlFor: "cr-phone",
495
- className: "cr-form__label",
496
- children: "Phone"
497
- }), /* @__PURE__ */ jsx("input", {
498
- id: "cr-phone",
499
- type: "tel",
500
- className: "cr-form__input",
501
- value: formData.phone,
502
- onChange: (e) => onChange({
503
- ...formData,
504
- phone: e.target.value
505
- }),
506
- disabled: isLoading
507
- })]
350
+ }), showModal && /* @__PURE__ */ jsx(ModalShell, {
351
+ title: copy.modalTitle,
352
+ titleId: "er-whole-series-portal-auth-modal-title",
353
+ onClose: () => setShowModal(false),
354
+ overlayClassName: "er-whole-series-modal-overlay",
355
+ modalClassName: "er-whole-series-modal",
356
+ renderSrOnlyTitle: true,
357
+ renderHeader: ({ closeButtonRef, onClose }) => /* @__PURE__ */ jsx("button", {
358
+ ref: closeButtonRef,
359
+ type: "button",
360
+ className: "er-whole-series-modal-close",
361
+ onClick: onClose,
362
+ "aria-label": "Close",
363
+ children: /* @__PURE__ */ jsx("svg", {
364
+ width: "20",
365
+ height: "20",
366
+ viewBox: "0 0 24 24",
367
+ fill: "none",
368
+ stroke: "currentColor",
369
+ strokeWidth: "2",
370
+ "aria-hidden": "true",
371
+ children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" })
372
+ })
508
373
  }),
509
- /* @__PURE__ */ jsxs("div", {
510
- className: "cr-form__field",
511
- children: [/* @__PURE__ */ jsx("label", {
512
- htmlFor: "cr-notes",
513
- className: "cr-form__label",
514
- children: "Notes"
515
- }), /* @__PURE__ */ jsx("textarea", {
516
- id: "cr-notes",
517
- className: "cr-form__textarea",
518
- value: formData.notes,
519
- onChange: (e) => onChange({
520
- ...formData,
521
- notes: e.target.value
522
- }),
523
- rows: 3,
524
- disabled: isLoading
525
- })]
374
+ children: /* @__PURE__ */ jsx(MagicLinkForm, {
375
+ classPrefix: "er-whole-series",
376
+ title: copy.modalHeading,
377
+ subtitle: copy.modalSubtitle,
378
+ buttonText: "Send login link",
379
+ successMessage: copy.successMessage,
380
+ onSuccess: () => {
381
+ onMagicLinkSent?.();
382
+ }
526
383
  })
527
- ] });
384
+ })] });
385
+ }
386
+ //#endregion
387
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/StepIndicator.tsx
388
+ /**
389
+ * Step indicator component for the run registration wizard.
390
+ * Thin wrapper around the shared StepIndicator with the canonical Event class prefix.
391
+ */
392
+ function StepIndicator(props) {
393
+ return /* @__PURE__ */ jsx(StepIndicator$1, {
394
+ ...props,
395
+ classPrefix: "er-whole-series"
396
+ });
528
397
  }
529
398
  //#endregion
530
399
  //#region ../blocks/src/system/runtime/shared/useWaitlistClaim.state.ts
@@ -621,9 +490,14 @@ function getWaitlistClaimTokenSnapshot() {
621
490
  function useWaitlistClaim() {
622
491
  return useWaitlistClaimWithDeps(useWaitlistClaimDeps);
623
492
  }
493
+ function useWaitlistClaimForToken(token) {
494
+ return useResolvedWaitlistClaim(useWaitlistClaimDeps, token);
495
+ }
624
496
  function useWaitlistClaimWithDeps(deps) {
497
+ return useResolvedWaitlistClaim(deps, useSyncExternalStore(subscribeToWaitlistClaimToken, getWaitlistClaimTokenSnapshot, () => null));
498
+ }
499
+ function useResolvedWaitlistClaim(deps, token) {
625
500
  const api = deps.useBlockApi();
626
- const token = useSyncExternalStore(subscribeToWaitlistClaimToken, getWaitlistClaimTokenSnapshot, () => null);
627
501
  const [state, dispatch] = useReducer(waitlistClaimReducer, Boolean(token), createInitialWaitlistClaimState);
628
502
  useEffect(() => {
629
503
  let cancelled = false;
@@ -688,7 +562,54 @@ function logoutPortal(anchorId) {
688
562
  form.submit();
689
563
  }
690
564
  //#endregion
691
- //#region ../blocks/src/system/runtime/nodes/course-registration/pricing.ts
565
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/utils.ts
566
+ /**
567
+ * Run Registration Utilities
568
+ *
569
+ * Formatting and validation helpers for run registration.
570
+ */
571
+ /**
572
+ * Format a date string to a localized date.
573
+ *
574
+ * @param dateString - ISO 8601 date string
575
+ * @param locale - Optional locale for formatting (defaults to browser locale)
576
+ * @returns Formatted date string (e.g., "Sat, Feb 1, 2026")
577
+ */
578
+ function formatDate(dateString, options) {
579
+ return formatBookingDate(toScheduledBookingDateTime({
580
+ startsAt: dateString,
581
+ locale: options?.locale,
582
+ timeZone: toBookingTimeZone(options?.timeZone)
583
+ }), {
584
+ weekday: "short",
585
+ month: "short",
586
+ day: "numeric",
587
+ year: "numeric"
588
+ });
589
+ }
590
+ /**
591
+ * Format a date string to a localized time.
592
+ *
593
+ * @param dateString - ISO 8601 date string
594
+ * @param locale - Optional locale for formatting (defaults to browser locale)
595
+ * @returns Formatted time string (e.g., "10:00 AM")
596
+ */
597
+ function formatTime(dateString, options) {
598
+ return formatBookingTime(toScheduledBookingDateTime({
599
+ startsAt: dateString,
600
+ locale: options?.locale,
601
+ timeZone: toBookingTimeZone(options?.timeZone)
602
+ }), {
603
+ hour: "numeric",
604
+ minute: "2-digit"
605
+ });
606
+ }
607
+ /**
608
+ * Anchor ID for the registration block, used for scroll targeting.
609
+ */
610
+ const WHOLE_SERIES_REGISTRATION_ANCHOR_ID = "event-registration";
611
+ //#endregion
612
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/pricing.ts
692
613
  function parseCurrencyInputToCents(value) {
693
614
  const trimmed = value.trim();
694
615
  if (!trimmed) return null;
@@ -700,32 +621,32 @@ function formatCentsAsCurrencyInput(amount) {
700
621
  const major = amount / 100;
701
622
  return Number.isInteger(major) ? String(major) : major.toFixed(2);
702
623
  }
703
- function getMissingCoursePricingSelectionMessage(pricing) {
624
+ function getMissingWholeSeriesPricingSelectionMessage(pricing) {
704
625
  if (pricing?.requiresSelection && !pricing.selectedOption) return pricing.slidingScale ? "Choose an amount to continue." : "Choose a pricing option to continue.";
705
626
  const selectedAmount = pricing?.selectedSlidingAmount;
706
627
  const scale = pricing?.slidingScale;
707
628
  if (scale && selectedAmount !== null && selectedAmount !== void 0 && (selectedAmount < scale.minAmount || selectedAmount > scale.maxAmount)) return "Choose an amount within the sliding scale.";
708
629
  return null;
709
630
  }
710
- function buildCoursePricingOptionPayload(pricing) {
631
+ function buildWholeSeriesPricingOptionPayload(pricing) {
711
632
  if (pricing?.selectedOption) return { pricingOptionId: pricing.selectedOption.id };
712
633
  if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null) return { selectedSlidingAmount: pricing.selectedSlidingAmount };
713
634
  return {};
714
635
  }
715
- function defaultCoursePricingSelection(pricing, previousOptionId) {
636
+ function defaultWholeSeriesPricingSelection(pricing, previousOptionId) {
716
637
  return {
717
638
  pricingOptionId: previousOptionId && pricing.selectableOptions.some((option) => option.id === previousOptionId) ? previousOptionId : pricing.selectedOption?.id ?? null,
718
639
  slidingAmountInput: pricing.slidingScale?.suggestedAmount !== null && pricing.slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(pricing.slidingScale.suggestedAmount) : ""
719
640
  };
720
641
  }
721
642
  //#endregion
722
- //#region ../blocks/src/system/runtime/nodes/course-registration/wizardSteps.ts
643
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/wizardSteps.ts
723
644
  /**
724
645
  * Steps that are part of the main wizard and should show the step indicator.
725
646
  * Terminal states (success, error, etc.) are not included.
726
647
  */
727
648
  const WIZARD_STEPS = [
728
- "select-course",
649
+ "select-run",
729
650
  "enter-details",
730
651
  "booking-mode",
731
652
  "select-payment"
@@ -734,7 +655,7 @@ const WIZARD_STEPS = [
734
655
  * Step labels for the wizard indicator
735
656
  */
736
657
  const STEP_LABELS = {
737
- "select-course": "Course",
658
+ "select-run": "Run",
738
659
  "enter-details": "Details",
739
660
  "booking-mode": "Method",
740
661
  "select-payment": "Payment",
@@ -750,36 +671,36 @@ const STEP_LABELS = {
750
671
  /**
751
672
  * Determine which wizard steps to show based on context and eligibility.
752
673
  *
753
- * @param hasPreSelectedCourse - Whether course is pre-selected (skips course selection)
754
- * @param requiresPayment - Whether the course requires payment
674
+ * @param hasPreSelectedRun - Whether run is pre-selected (skips run selection)
675
+ * @param requiresPayment - Whether the run requires payment
755
676
  * @param hasEligibleMemberships - Whether user has eligible memberships
756
677
  * @param bookingMode - Current booking mode selection
757
678
  * @param isMembershipFastTrack - Whether user qualifies for single-step membership flow
758
679
  * @returns Array of wizard steps to display
759
680
  */
760
- function getWizardStepsForContext(hasPreSelectedCourse, requiresPayment, hasEligibleMemberships, bookingMode, isMembershipFastTrack) {
761
- if (isMembershipFastTrack) return hasPreSelectedCourse ? ["enter-details"] : ["select-course", "enter-details"];
762
- if (!requiresPayment) return hasPreSelectedCourse ? ["enter-details"] : ["select-course", "enter-details"];
681
+ function getWizardStepsForContext(hasPreSelectedRun, requiresPayment, hasEligibleMemberships, bookingMode, isMembershipFastTrack) {
682
+ if (isMembershipFastTrack) return hasPreSelectedRun ? ["enter-details"] : ["select-run", "enter-details"];
683
+ if (!requiresPayment) return hasPreSelectedRun ? ["enter-details"] : ["select-run", "enter-details"];
763
684
  if (hasEligibleMemberships) {
764
685
  const skipPayment = bookingMode === "membership";
765
- if (hasPreSelectedCourse) return skipPayment ? ["enter-details", "booking-mode"] : [
686
+ if (hasPreSelectedRun) return skipPayment ? ["enter-details", "booking-mode"] : [
766
687
  "enter-details",
767
688
  "booking-mode",
768
689
  "select-payment"
769
690
  ];
770
691
  return skipPayment ? [
771
- "select-course",
692
+ "select-run",
772
693
  "enter-details",
773
694
  "booking-mode"
774
695
  ] : [
775
- "select-course",
696
+ "select-run",
776
697
  "enter-details",
777
698
  "booking-mode",
778
699
  "select-payment"
779
700
  ];
780
701
  }
781
- return hasPreSelectedCourse ? ["enter-details", "select-payment"] : [
782
- "select-course",
702
+ return hasPreSelectedRun ? ["enter-details", "select-payment"] : [
703
+ "select-run",
783
704
  "enter-details",
784
705
  "select-payment"
785
706
  ];
@@ -791,21 +712,21 @@ function getStepLabels(steps) {
791
712
  return steps.map((step) => STEP_LABELS[step] ?? step);
792
713
  }
793
714
  //#endregion
794
- //#region ../blocks/src/system/runtime/nodes/course-registration/courseRegistrationViewState.ts
795
- function deriveCourseRegistrationViewState(input) {
796
- const hasCoursePayment = resolveCoursePaymentRequirement(input.pricing);
797
- const canUseMembership = hasCoursePayment && input.selectedCourse?.acceptsMemberships === true && input.portalAuthState === "authenticated" && input.eligibleMembershipCount > 0;
798
- const hasPreSelectedCourse = input.scopedCourses.length === 1;
715
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/wholeSeriesRegistrationViewState.ts
716
+ function deriveWholeSeriesRegistrationViewState(input) {
717
+ const hasRunPayment = resolveWholeSeriesPaymentRequirement(input.pricing);
718
+ const canUseMembership = hasRunPayment && input.selectedRun?.acceptsMemberships === true && input.portalAuthState === "authenticated" && input.eligibleMembershipCount > 0;
719
+ const hasPreSelectedRun = input.scopedRuns.length === 1;
799
720
  const fastTrack = canUseMembership && input.eligibleMembershipCount === 1 && input.bookingMode === "membership";
800
- const wizardSteps = getWizardStepsForContext(hasPreSelectedCourse, hasCoursePayment, canUseMembership, input.bookingMode, fastTrack);
721
+ const wizardSteps = getWizardStepsForContext(hasPreSelectedRun, hasRunPayment, canUseMembership, input.bookingMode, fastTrack);
801
722
  const showPortalAuthSidebar = shouldShowPortalAuthSidebar({
802
723
  ...input,
803
- hasCoursePayment
724
+ hasRunPayment
804
725
  });
805
726
  return {
806
- hasCoursePayment,
727
+ hasRunPayment,
807
728
  canUseMembership,
808
- hasPreSelectedCourse,
729
+ hasPreSelectedRun,
809
730
  wizardSteps,
810
731
  currentStepNumber: getStepNumber(input.step, wizardSteps),
811
732
  totalSteps: wizardSteps.length,
@@ -813,24 +734,24 @@ function deriveCourseRegistrationViewState(input) {
813
734
  showPortalAuthSidebar
814
735
  };
815
736
  }
816
- function resolveCoursePaymentRequirement(pricing) {
737
+ function resolveWholeSeriesPaymentRequirement(pricing) {
817
738
  if (!pricing) return false;
818
739
  return pricing.selectedOption ? pricing.selectedRequiresPayment : pricing.hasPaidSelection;
819
740
  }
820
741
  function shouldShowPortalAuthSidebar(input) {
821
742
  if (input.portalAuthState !== "unauthenticated") return false;
822
743
  if (input.step === "success" || input.step === "waitlist" || input.step === "error") return false;
823
- return input.waitlistRequiresPortalLogin || input.hasCoursePayment && input.selectedCourse?.acceptsMemberships === true && input.step !== "select-course";
744
+ return input.waitlistRequiresPortalLogin || input.hasRunPayment && input.selectedRun?.acceptsMemberships === true && input.step !== "select-run";
824
745
  }
825
746
  //#endregion
826
- //#region ../blocks/src/system/runtime/nodes/course-registration/useCourseEligibility.ts
747
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesEligibility.ts
827
748
  function shouldFetchEligibility(input) {
828
- if (!input.course || input.portalAuthState === "checking" || input.hasWaitlistClaimToken) return false;
829
- const membershipCheck = input.portalAuthState === "authenticated" && input.hasPaidSelection && input.course.acceptsMemberships;
830
- const capacityCheck = input.course.availableSpots !== null && input.course.availableSpots <= 0;
749
+ if (!input.run || input.portalAuthState === "checking" || input.hasWaitlistClaimToken) return false;
750
+ const membershipCheck = input.portalAuthState === "authenticated" && input.hasPaidSelection && input.run.acceptsMemberships;
751
+ const capacityCheck = input.run.availableSpots !== null && input.run.availableSpots <= 0;
831
752
  return membershipCheck || capacityCheck;
832
753
  }
833
- function useCourseEligibility(input) {
754
+ function useWholeSeriesEligibility(input) {
834
755
  const [loading, setLoading] = useState(false);
835
756
  const [error, setError] = useState(null);
836
757
  const [eligibility, setEligibility] = useState(null);
@@ -851,15 +772,15 @@ function useCourseEligibility(input) {
851
772
  setError(null);
852
773
  setPaymentChoice("checkout");
853
774
  const eligibilityInput = {
854
- course: input.selectedCourse,
775
+ run: input.selectedRun,
855
776
  hasPaidSelection: input.hasPaidSelection,
856
777
  portalAuthState: input.portalAuthState,
857
778
  hasWaitlistClaimToken: input.waitlistClaimToken !== null
858
779
  };
859
780
  if (!shouldFetchEligibility(eligibilityInput)) return;
860
- const course = eligibilityInput.course;
781
+ const run = eligibilityInput.run;
861
782
  setLoading(true);
862
- input.api.checkWholeSeriesEligibility({ eventSeriesId: course.eventSeriesId }).then((result) => {
783
+ input.api.checkWholeSeriesEligibility({ eventSeriesId: run.eventSeriesId }).then((result) => {
863
784
  if (cancelled) return;
864
785
  const eligibleMemberships = result.eligibleMemberships ?? [];
865
786
  setEligibility(result);
@@ -880,13 +801,13 @@ function useCourseEligibility(input) {
880
801
  input.api,
881
802
  input.hasPaidSelection,
882
803
  input.portalAuthState,
883
- input.selectedCourse,
804
+ input.selectedRun,
884
805
  input.waitlistClaimToken
885
806
  ]);
886
807
  return {
887
808
  eligibilityLoading: loading,
888
809
  eligibilityError: error,
889
- courseEligibility: eligibility,
810
+ runEligibility: eligibility,
890
811
  eligibleMemberships: memberships,
891
812
  paymentChoice,
892
813
  choosePaymentChoice,
@@ -895,12 +816,12 @@ function useCourseEligibility(input) {
895
816
  };
896
817
  }
897
818
  //#endregion
898
- //#region ../blocks/src/system/runtime/nodes/course-page-surface-scope.ts
819
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/wholeSeriesPageSurfaceScope.ts
899
820
  /**
900
- * Resolves native course-page ownership without falling back to entry or slug
821
+ * Resolves native run-page ownership without falling back to entry or slug
901
822
  * coincidence when a page-surface subject is present but invalid.
902
823
  */
903
- function resolveCoursePageSurfaceScope(courses, subjectValue) {
824
+ function resolveWholeSeriesPageSurfaceScope(runs, subjectValue) {
904
825
  if (subjectValue === null || subjectValue === void 0) return { kind: "absent" };
905
826
  const parsed = parseEventPageSurfaceSubject(subjectValue);
906
827
  if (!parsed.ok) return {
@@ -912,44 +833,54 @@ function resolveCoursePageSurfaceScope(courses, subjectValue) {
912
833
  return {
913
834
  kind: "scoped",
914
835
  subject: parsed.value,
915
- courses: courses.filter((course) => allowedSeriesIds.has(course.eventSeriesId))
836
+ runs: runs.filter((run) => allowedSeriesIds.has(run.eventSeriesId))
916
837
  };
917
838
  }
918
839
  function eventSeriesIdsForSubject(subject) {
919
840
  switch (subject.kind) {
920
841
  case "eventSeries": return [subject.eventSeriesId];
921
842
  case "eventOffering": return subject.availableEventSeriesIds;
922
- default: return assertNever(subject);
843
+ default: return assertNever$1(subject);
923
844
  }
924
845
  }
925
846
  //#endregion
926
- //#region ../blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationSelection.ts
927
- function selectScopedCourses(props) {
928
- const surfaceScope = resolveCoursePageSurfaceScope(props.courses ?? [], props.subject);
847
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationSelection.ts
848
+ function selectScopedRuns(props) {
849
+ const surfaceScope = resolveWholeSeriesPageSurfaceScope(props.runs ?? [], props.subject);
929
850
  if (surfaceScope.kind === "unsupported") return [];
930
- if (surfaceScope.kind === "scoped") return surfaceScope.courses;
851
+ if (surfaceScope.kind === "scoped") return surfaceScope.runs;
931
852
  return [];
932
853
  }
933
- function getCourseCheckoutSessionId() {
934
- const fromSearch = new URLSearchParams(window.location.search).get("session_id");
854
+ function getWholeSeriesCheckoutSessionId(location = window.location) {
855
+ const fromSearch = new URLSearchParams(location.search).get("session_id");
935
856
  if (fromSearch) return fromSearch;
936
- return window.location.hash.match(/[?&]session_id=([^&]+)/)?.[1] ?? null;
857
+ return location.hash.match(/[?&]session_id=([^&]+)/)?.[1] ?? null;
937
858
  }
938
- function initialStep(courses) {
939
- if (new URLSearchParams(window.location.search).get("enrollment") === "success" && getCourseCheckoutSessionId()) return "verifying-payment";
940
- return courses.length === 1 ? "enter-details" : "select-course";
859
+ function initialStep(runs, location) {
860
+ if (new URLSearchParams(location.search).get("enrollment") === "success" && getWholeSeriesCheckoutSessionId(location)) return "verifying-payment";
861
+ return runs.length === 1 ? "enter-details" : "select-run";
941
862
  }
942
- function useCourseRegistrationSelection(props) {
943
- const scopedCourses = useMemo(() => selectScopedCourses(props), [props.courses, props.subject]);
944
- const [step, setStep] = useState(() => initialStep(scopedCourses));
945
- const [selectedCourse, setSelectedCourse] = useState(scopedCourses.length === 1 ? scopedCourses[0] ?? null : null);
863
+ function useWholeSeriesRegistrationSelection(props, location = window.location) {
864
+ const scopeSnapshot = JSON.stringify({
865
+ runs: props.runs ?? [],
866
+ subject: props.subject ?? null
867
+ });
868
+ const stableScope = useRef(null);
869
+ if (stableScope.current?.snapshot !== scopeSnapshot) stableScope.current = {
870
+ snapshot: scopeSnapshot,
871
+ runs: selectScopedRuns(props)
872
+ };
873
+ const scopedRuns = stableScope.current.runs;
874
+ const [step, setStep] = useState(() => initialStep(scopedRuns, location));
875
+ const [selectedRunId, setSelectedRunId] = useState(scopedRuns.length === 1 ? scopedRuns[0]?.eventSeriesId ?? null : null);
876
+ const selectedRun = useMemo(() => scopedRuns.find((run) => run.eventSeriesId === selectedRunId) ?? (scopedRuns.length === 1 ? scopedRuns[0] ?? null : null), [scopedRuns, selectedRunId]);
946
877
  const [selectedPricingOptionId, setSelectedPricingOptionId] = useState(null);
947
878
  const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState("");
948
879
  const goToStep = useCallback((nextStep) => {
949
880
  setStep(nextStep);
950
881
  }, []);
951
- const chooseCourse = useCallback((course) => {
952
- setSelectedCourse(course);
882
+ const chooseRun = useCallback((run) => {
883
+ setSelectedRunId(run.eventSeriesId);
953
884
  }, []);
954
885
  const choosePricingOption = useCallback((pricingOptionId) => {
955
886
  setSelectedPricingOptionId(pricingOptionId);
@@ -957,36 +888,36 @@ function useCourseRegistrationSelection(props) {
957
888
  const changeSlidingAmount = useCallback((amount) => {
958
889
  setSelectedSlidingAmountInput(amount);
959
890
  }, []);
960
- const selectedCoursePricing = useMemo(() => selectedCourse ? resolveCoursePricingState(selectedCourse, selectedPricingOptionId, parseCurrencyInputToCents(selectedSlidingAmountInput)) : null, [
961
- selectedCourse,
891
+ const selectedRunPricing = useMemo(() => selectedRun ? resolveWholeSeriesPricingState(selectedRun, selectedPricingOptionId, parseCurrencyInputToCents(selectedSlidingAmountInput)) : null, [
892
+ selectedRun,
962
893
  selectedPricingOptionId,
963
894
  selectedSlidingAmountInput
964
895
  ]);
965
896
  useEffect(() => {
966
- if (!selectedCourse) {
897
+ if (!selectedRun) {
967
898
  setSelectedPricingOptionId(null);
968
899
  setSelectedSlidingAmountInput("");
969
900
  return;
970
901
  }
971
- const selection = defaultCoursePricingSelection(resolveCoursePricingState(selectedCourse, null), selectedPricingOptionId);
902
+ const selection = defaultWholeSeriesPricingSelection(resolveWholeSeriesPricingState(selectedRun, null), selectedPricingOptionId);
972
903
  setSelectedPricingOptionId(selection.pricingOptionId);
973
904
  setSelectedSlidingAmountInput(selection.slidingAmountInput);
974
- }, [selectedCourse]);
905
+ }, [selectedRun?.eventSeriesId]);
975
906
  return {
976
- scopedCourses,
907
+ scopedRuns,
977
908
  step,
978
909
  goToStep,
979
- selectedCourse,
980
- chooseCourse,
910
+ selectedRun,
911
+ chooseRun,
981
912
  selectedPricingOptionId,
982
913
  choosePricingOption,
983
914
  selectedSlidingAmountInput,
984
915
  changeSlidingAmount,
985
- selectedCoursePricing
916
+ selectedRunPricing
986
917
  };
987
918
  }
988
919
  //#endregion
989
- //#region ../blocks/src/system/runtime/nodes/course-registration/useCoursePaymentVerification.ts
920
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesPaymentVerification.ts
990
921
  function applyTerminalStatus(status, setters) {
991
922
  if (status === "enrolled" || status === "completed") {
992
923
  setters.setEnrollmentResult({
@@ -1008,7 +939,7 @@ function applyTerminalStatus(status, setters) {
1008
939
  setters.setStep("error");
1009
940
  return true;
1010
941
  }
1011
- async function pollCourseRegistrationStatus(api, sessionId, setters, isCancelled) {
942
+ async function pollWholeSeriesRegistrationStatus(api, sessionId, setters, isCancelled) {
1012
943
  const startedAt = Date.now();
1013
944
  while (!isCancelled()) {
1014
945
  try {
@@ -1029,21 +960,21 @@ async function pollCourseRegistrationStatus(api, sessionId, setters, isCancelled
1029
960
  await new Promise((resolve) => setTimeout(resolve, 1500));
1030
961
  }
1031
962
  }
1032
- function useCoursePaymentVerification(api, setters) {
963
+ function useWholeSeriesPaymentVerification(api, setters, anchorId = WHOLE_SERIES_REGISTRATION_ANCHOR_ID, location = window.location) {
1033
964
  useEffect(() => {
1034
965
  let cancelled = false;
1035
- const enrollment = new URLSearchParams(window.location.search).get("enrollment");
1036
- const sessionId = getCourseCheckoutSessionId();
966
+ const enrollment = new URLSearchParams(location.search).get("enrollment");
967
+ const sessionId = getWholeSeriesCheckoutSessionId(location);
1037
968
  if (enrollment === "cancelled") {
1038
- scrollToBlock(COURSE_REGISTRATION_ANCHOR_ID);
969
+ scrollToBlock(anchorId);
1039
970
  setters.setErrorMessage("Payment was cancelled. You can try again.");
1040
971
  setters.setStep("error");
1041
972
  return;
1042
973
  }
1043
974
  if (enrollment !== "success" || !sessionId) return;
1044
- scrollToBlock(COURSE_REGISTRATION_ANCHOR_ID);
975
+ scrollToBlock(anchorId);
1045
976
  setters.setStep("verifying-payment");
1046
- pollCourseRegistrationStatus(api, sessionId, setters, () => cancelled);
977
+ pollWholeSeriesRegistrationStatus(api, sessionId, setters, () => cancelled);
1047
978
  return () => {
1048
979
  cancelled = true;
1049
980
  };
@@ -1051,11 +982,13 @@ function useCoursePaymentVerification(api, setters) {
1051
982
  api,
1052
983
  setters.setEnrollmentResult,
1053
984
  setters.setErrorMessage,
1054
- setters.setStep
985
+ setters.setStep,
986
+ anchorId,
987
+ location
1055
988
  ]);
1056
989
  }
1057
990
  //#endregion
1058
- //#region ../blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationActions.ts
991
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationActions.ts
1059
992
  function blocked(message, setters) {
1060
993
  setters.setErrorMessage(message);
1061
994
  setters.setStep("error");
@@ -1065,16 +998,16 @@ function blocked(message, setters) {
1065
998
  };
1066
999
  }
1067
1000
  function validateSubmission(state, setters) {
1068
- if (!state.selectedCourse) return {
1001
+ if (!state.selectedRun) return {
1069
1002
  kind: "blocked",
1070
1003
  message: "Choose an available set of dates to continue."
1071
1004
  };
1072
1005
  const errors = validateFormData(state.formData);
1073
1006
  setters.setErrors(errors);
1074
1007
  if (Object.keys(errors).length > 0) return { kind: "validation-failed" };
1075
- const pricingMessage = getMissingCoursePricingSelectionMessage(state.pricing);
1008
+ const pricingMessage = getMissingWholeSeriesPricingSelectionMessage(state.pricing);
1076
1009
  if (pricingMessage) return blocked(pricingMessage, setters);
1077
- if (!state.hasClaim && state.eligibility?.isFull && !state.eligibility.canJoinWaitlist) return blocked(state.eligibility.reason ?? "This course is fully booked.", setters);
1010
+ if (!state.hasClaim && state.eligibility?.isFull && !state.eligibility.canJoinWaitlist) return blocked(state.eligibility.reason ?? "This run is fully booked.", setters);
1078
1011
  if (isSpamProtectionEnabled() && !state.altchaSolution) return blocked("Please complete the verification check.", setters);
1079
1012
  return null;
1080
1013
  }
@@ -1087,8 +1020,8 @@ function enrollmentPayload(state, payment) {
1087
1020
  }
1088
1021
  function registrantPayload(state) {
1089
1022
  return {
1090
- eventSeriesId: state.selectedCourse.eventSeriesId,
1091
- ...buildCoursePricingOptionPayload(state.pricing),
1023
+ eventSeriesId: state.selectedRun.eventSeriesId,
1024
+ ...buildWholeSeriesPricingOptionPayload(state.pricing),
1092
1025
  email: state.formData.email.trim().toLowerCase(),
1093
1026
  name: state.formData.name.trim(),
1094
1027
  phone: state.formData.phone.trim() || void 0,
@@ -1121,7 +1054,7 @@ async function enroll(state, setters, payment) {
1121
1054
  async function checkout(state, setters) {
1122
1055
  setters.setStep("submitting");
1123
1056
  try {
1124
- const urls = buildCheckoutReturnUrls("enrollment", COURSE_REGISTRATION_ANCHOR_ID);
1057
+ const urls = buildCheckoutReturnUrls("enrollment", state.options.anchorId ?? "event-registration");
1125
1058
  const result = await state.api.createWholeSeriesCheckout({
1126
1059
  ...registrantPayload(state),
1127
1060
  discountCode: state.discountCode.trim() || void 0,
@@ -1156,10 +1089,10 @@ async function checkout(state, setters) {
1156
1089
  }
1157
1090
  async function submitDetails(state, setters) {
1158
1091
  const invalid = validateSubmission(state, setters);
1159
- if (invalid || !state.selectedCourse) return invalid ?? { kind: "validation-failed" };
1092
+ if (invalid || !state.selectedRun) return invalid ?? { kind: "validation-failed" };
1160
1093
  if (state.eligibility?.canJoinWaitlist) return enroll(state, setters, { method: "free" });
1161
1094
  const requiresPayment = state.pricing?.selectedRequiresPayment ?? false;
1162
- const canUseMembership = requiresPayment && state.selectedCourse.acceptsMemberships && state.portalAuthState === "authenticated" && state.eligibleMemberships.length > 0;
1095
+ const canUseMembership = requiresPayment && state.selectedRun.acceptsMemberships && state.portalAuthState === "authenticated" && state.eligibleMemberships.length > 0;
1163
1096
  if (requiresPayment && canUseMembership) {
1164
1097
  setters.setStep("select-payment");
1165
1098
  return { kind: "state-updated" };
@@ -1169,7 +1102,7 @@ async function submitDetails(state, setters) {
1169
1102
  }
1170
1103
  async function continuePayment(state, setters) {
1171
1104
  const invalid = validateSubmission(state, setters);
1172
- if (invalid || !state.selectedCourse) return invalid ?? { kind: "validation-failed" };
1105
+ if (invalid || !state.selectedRun) return invalid ?? { kind: "validation-failed" };
1173
1106
  if (!state.pricing?.selectedRequiresPayment) {
1174
1107
  setters.setStep("enter-details");
1175
1108
  return { kind: "state-updated" };
@@ -1184,7 +1117,7 @@ async function continuePayment(state, setters) {
1184
1117
  }
1185
1118
  return checkout(selectedState, setters);
1186
1119
  }
1187
- function useCourseRegistrationActions(state, setStep) {
1120
+ function useWholeSeriesRegistrationActions(state, setStep) {
1188
1121
  const [errors, setErrors] = useState({});
1189
1122
  const [enrollmentResult, setEnrollmentResult] = useState(null);
1190
1123
  const [errorMessage, setErrorMessage] = useState("");
@@ -1211,14 +1144,14 @@ function useCourseRegistrationActions(state, setStep) {
1211
1144
  };
1212
1145
  }
1213
1146
  //#endregion
1214
- //#region ../blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationPortal.ts
1147
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationPortal.ts
1215
1148
  const EMPTY_FORM = {
1216
1149
  name: "",
1217
1150
  email: "",
1218
1151
  phone: "",
1219
1152
  notes: ""
1220
1153
  };
1221
- function useCourseRegistrationPortal(api) {
1154
+ function useWholeSeriesRegistrationPortal(api) {
1222
1155
  const [formData, setFormData] = useState(EMPTY_FORM);
1223
1156
  const [portalAuthState, setPortalAuthState] = useState("checking");
1224
1157
  const updateFormData = useCallback((updater) => {
@@ -1254,19 +1187,19 @@ function useCourseRegistrationPortal(api) {
1254
1187
  };
1255
1188
  }
1256
1189
  //#endregion
1257
- //#region ../blocks/src/system/runtime/nodes/course-registration/useCourseWaitlistSelection.ts
1258
- function useCourseWaitlistSelection(input) {
1190
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesWaitlistSelection.ts
1191
+ function useWholeSeriesWaitlistSelection(input) {
1259
1192
  useEffect(() => {
1260
1193
  const claim = input.waitlistClaim.claim;
1261
1194
  if (!claim || claim.subject.kind !== "whole_series") return;
1262
1195
  const eventSeriesId = claim.subject.eventSeriesId;
1263
- const course = input.scopedCourses.find((candidate) => candidate.eventSeriesId === eventSeriesId);
1264
- if (!course) {
1265
- input.reportError("This waitlist claim is for a different course.");
1196
+ const run = input.scopedRuns.find((candidate) => candidate.eventSeriesId === eventSeriesId);
1197
+ if (!run) {
1198
+ input.reportError("This waitlist claim is for a different run.");
1266
1199
  input.goToStep("error");
1267
1200
  return;
1268
1201
  }
1269
- input.chooseCourse(course);
1202
+ input.chooseRun(run);
1270
1203
  input.updateFormData((current) => ({
1271
1204
  ...current,
1272
1205
  email: claim.prefill.email,
@@ -1274,12 +1207,12 @@ function useCourseWaitlistSelection(input) {
1274
1207
  phone: claim.prefill.phone ?? "",
1275
1208
  notes: claim.prefill.notes ?? ""
1276
1209
  }));
1277
- if (input.step === "select-course") input.goToStep("enter-details");
1210
+ if (input.step === "select-run") input.goToStep("enter-details");
1278
1211
  }, [
1279
- input.chooseCourse,
1212
+ input.chooseRun,
1280
1213
  input.goToStep,
1281
1214
  input.reportError,
1282
- input.scopedCourses,
1215
+ input.scopedRuns,
1283
1216
  input.step,
1284
1217
  input.updateFormData,
1285
1218
  input.waitlistClaim.claim
@@ -1296,40 +1229,48 @@ function useCourseWaitlistSelection(input) {
1296
1229
  ]);
1297
1230
  }
1298
1231
  //#endregion
1299
- //#region ../blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.ts
1300
- function useCourseRegistrationWizard(props, options = {}) {
1232
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationWizard.ts
1233
+ function useWholeSeriesRegistrationWizard(props, options = {}) {
1234
+ return useWholeSeriesRegistrationWizardWithDeps(wholeSeriesRegistrationWizardDeps, props, options);
1235
+ }
1236
+ const wholeSeriesRegistrationWizardDeps = { readLocation: () => ({
1237
+ search: window.location.search,
1238
+ hash: window.location.hash
1239
+ }) };
1240
+ function useWholeSeriesRegistrationWizardWithDeps(deps, props, options = {}) {
1301
1241
  const api = useBlockApi();
1302
- const selection = useCourseRegistrationSelection(props);
1303
- const portal = useCourseRegistrationPortal(api);
1304
- const waitlistClaim = useWaitlistClaim();
1242
+ const [location] = useState(deps.readLocation);
1243
+ const selection = useWholeSeriesRegistrationSelection(props, location);
1244
+ const portal = useWholeSeriesRegistrationPortal(api);
1245
+ const waitlistClaim = useWaitlistClaimForToken(new URLSearchParams(location.search).get("waitlist_claim")?.trim() || null);
1305
1246
  const [bookingMode, setBookingMode] = useState(null);
1306
1247
  const [altchaSolution, setAltchaSolution] = useState(null);
1307
- const eligibility = useCourseEligibility({
1248
+ const eligibility = useWholeSeriesEligibility({
1308
1249
  api,
1309
- selectedCourse: selection.selectedCourse,
1310
- hasPaidSelection: selection.selectedCoursePricing?.hasPaidSelection ?? false,
1250
+ selectedRun: selection.selectedRun,
1251
+ hasPaidSelection: selection.selectedRunPricing?.hasPaidSelection ?? false,
1311
1252
  portalAuthState: portal.portalAuthState,
1312
1253
  waitlistClaimToken: waitlistClaim.token
1313
1254
  });
1314
1255
  const discountUi = useDiscountCodeUi({
1315
1256
  api,
1316
- discountContext: useMemo(() => selection.selectedCourse && selection.selectedCoursePricing?.selectedRequiresPayment && eligibility.paymentChoice === "checkout" ? {
1257
+ discountContext: useMemo(() => selection.selectedRun && selection.selectedRunPricing?.selectedRequiresPayment && eligibility.paymentChoice === "checkout" ? {
1317
1258
  type: "whole_series",
1318
- eventSeriesId: selection.selectedCourse.eventSeriesId
1259
+ eventSeriesId: selection.selectedRun.eventSeriesId
1319
1260
  } : null, [
1320
1261
  eligibility.paymentChoice,
1321
- selection.selectedCourse,
1322
- selection.selectedCoursePricing?.selectedRequiresPayment
1262
+ selection.selectedRun,
1263
+ selection.selectedRunPricing?.selectedRequiresPayment
1323
1264
  ]),
1324
- subtotalCents: selection.selectedCoursePricing?.selectedPriceAmount ?? void 0
1265
+ subtotalCents: selection.selectedRunPricing?.selectedPriceAmount ?? void 0
1325
1266
  });
1326
- const actions = useCourseRegistrationActions({
1267
+ const actions = useWholeSeriesRegistrationActions({
1327
1268
  api,
1328
- selectedCourse: selection.selectedCourse,
1329
- pricing: selection.selectedCoursePricing,
1269
+ selectedRun: selection.selectedRun,
1270
+ pricing: selection.selectedRunPricing,
1330
1271
  formData: portal.formData,
1331
1272
  portalAuthState: portal.portalAuthState,
1332
- eligibility: eligibility.courseEligibility,
1273
+ eligibility: eligibility.runEligibility,
1333
1274
  eligibleMemberships: eligibility.eligibleMemberships,
1334
1275
  paymentChoice: eligibility.paymentChoice,
1335
1276
  selectedMembershipId: eligibility.selectedMembershipId,
@@ -1339,14 +1280,16 @@ function useCourseRegistrationWizard(props, options = {}) {
1339
1280
  discountCode: discountUi.discountCode,
1340
1281
  options
1341
1282
  }, selection.goToStep);
1342
- useCourseRegistrationEffects({
1283
+ useWholeSeriesRegistrationEffects({
1343
1284
  api,
1344
1285
  actions,
1345
1286
  portal,
1346
1287
  selection,
1347
- waitlistClaim
1288
+ waitlistClaim,
1289
+ anchorId: options.anchorId ?? "event-registration",
1290
+ location
1348
1291
  });
1349
- return buildCourseRegistrationWizardResult({
1292
+ return buildWholeSeriesRegistrationWizardResult({
1350
1293
  api,
1351
1294
  selection,
1352
1295
  portal,
@@ -1354,10 +1297,10 @@ function useCourseRegistrationWizard(props, options = {}) {
1354
1297
  actions,
1355
1298
  discountUi,
1356
1299
  waitlistClaim,
1357
- view: deriveCourseRegistrationViewState({
1358
- scopedCourses: selection.scopedCourses,
1359
- selectedCourse: selection.selectedCourse,
1360
- pricing: selection.selectedCoursePricing,
1300
+ view: deriveWholeSeriesRegistrationViewState({
1301
+ scopedRuns: selection.scopedRuns,
1302
+ selectedRun: selection.selectedRun,
1303
+ pricing: selection.selectedRunPricing,
1361
1304
  portalAuthState: portal.portalAuthState,
1362
1305
  eligibleMembershipCount: eligibility.eligibleMemberships.length,
1363
1306
  bookingMode,
@@ -1367,26 +1310,27 @@ function useCourseRegistrationWizard(props, options = {}) {
1367
1310
  bookingMode,
1368
1311
  setBookingMode,
1369
1312
  altchaSolution,
1370
- setAltchaSolution
1313
+ setAltchaSolution,
1314
+ anchorId: options.anchorId ?? "event-registration"
1371
1315
  });
1372
1316
  }
1373
- function useCourseRegistrationEffects(input) {
1374
- useCoursePaymentVerification(input.api, {
1317
+ function useWholeSeriesRegistrationEffects(input) {
1318
+ useWholeSeriesPaymentVerification(input.api, {
1375
1319
  setStep: input.selection.goToStep,
1376
1320
  setErrorMessage: input.actions.reportError,
1377
1321
  setEnrollmentResult: input.actions.recordEnrollmentResult
1378
- });
1379
- useCourseWaitlistSelection({
1322
+ }, input.anchorId, input.location);
1323
+ useWholeSeriesWaitlistSelection({
1380
1324
  waitlistClaim: input.waitlistClaim,
1381
- scopedCourses: input.selection.scopedCourses,
1325
+ scopedRuns: input.selection.scopedRuns,
1382
1326
  step: input.selection.step,
1383
1327
  goToStep: input.selection.goToStep,
1384
- chooseCourse: input.selection.chooseCourse,
1328
+ chooseRun: input.selection.chooseRun,
1385
1329
  updateFormData: input.portal.updateFormData,
1386
1330
  reportError: input.actions.reportError
1387
1331
  });
1388
1332
  }
1389
- function buildCourseRegistrationWizardResult(parts) {
1333
+ function buildWholeSeriesRegistrationWizardResult(parts) {
1390
1334
  const handleBookingModeChange = (mode) => {
1391
1335
  parts.setBookingMode(mode);
1392
1336
  parts.eligibility.choosePaymentChoice(mode === "membership" ? "membership" : "checkout");
@@ -1410,156 +1354,85 @@ function buildCourseRegistrationWizardResult(parts) {
1410
1354
  manualCodeEntryAllowed: parts.discountUi.manualCodeEntryAllowed,
1411
1355
  discountsAvailableLoading: parts.discountUi.discountsAvailableLoading,
1412
1356
  ...parts.view,
1413
- handleCourseSelect: (course) => {
1414
- parts.selection.chooseCourse(course);
1357
+ handleRunSelect: (run) => {
1358
+ parts.selection.chooseRun(run);
1415
1359
  parts.selection.goToStep("enter-details");
1416
1360
  },
1417
1361
  handleRetry: () => {
1418
- parts.selection.goToStep(parts.selection.scopedCourses.length === 1 ? "enter-details" : "select-course");
1362
+ parts.selection.goToStep(parts.selection.scopedRuns.length === 1 ? "enter-details" : "select-run");
1419
1363
  parts.actions.reportError("");
1420
1364
  },
1421
1365
  handleBookingModeChange,
1422
- handleLogout: parts.portal.portalAuthState === "authenticated" ? () => logoutPortal(COURSE_REGISTRATION_ANCHOR_ID) : void 0,
1423
- selectedCoursePricingPayload: buildCoursePricingOptionPayload(parts.selection.selectedCoursePricing)
1366
+ handleLogout: parts.portal.portalAuthState === "authenticated" ? () => logoutPortal(parts.anchorId) : void 0,
1367
+ selectedRunPricingPayload: buildWholeSeriesPricingOptionPayload(parts.selection.selectedRunPricing)
1424
1368
  };
1425
1369
  }
1426
1370
  //#endregion
1427
- //#region ../blocks/src/system/runtime/nodes/course-registration/StepIndicator.tsx
1428
- /**
1429
- * Step indicator component for the course registration wizard.
1430
- * Thin wrapper around the shared StepIndicator with 'cr' class prefix.
1431
- */
1432
- function StepIndicator(props) {
1433
- return /* @__PURE__ */ jsx(StepIndicator$1, {
1434
- ...props,
1435
- classPrefix: "cr"
1436
- });
1437
- }
1438
- //#endregion
1439
- //#region ../blocks/src/system/runtime/nodes/course-registration/MembershipHero.tsx
1371
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/MembershipHero.tsx
1440
1372
  /**
1441
- * Membership Hero for course registration.
1442
- * Thin wrapper around the shared MembershipHero with 'cr' class prefix.
1373
+ * Membership Hero for run registration.
1374
+ * Thin wrapper around the shared MembershipHero with the canonical Event class prefix.
1443
1375
  */
1444
1376
  function MembershipHero(props) {
1445
1377
  return /* @__PURE__ */ jsx(MembershipHero$1, {
1446
1378
  ...props,
1447
- classPrefix: "cr"
1379
+ classPrefix: "er-whole-series"
1448
1380
  });
1449
1381
  }
1450
1382
  //#endregion
1451
- //#region ../blocks/src/system/runtime/nodes/course-registration/BookingModeStep.tsx
1383
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/BookingModeStep.tsx
1452
1384
  function BookingModeStep({ bookingMode, onBookingModeChange, eligibleMemberships, selectedMembershipId, onMembershipSelect, priceCents, currency, showEnrollForOtherLink = false, onEnrollForOther }) {
1453
1385
  const hasSingleMembership = eligibleMemberships.length === 1;
1454
1386
  const hasMultipleMemberships = eligibleMemberships.length > 1;
1455
1387
  const showMembershipHero = hasSingleMembership && bookingMode === "membership" && eligibleMemberships[0];
1456
1388
  const singleMembership = eligibleMemberships[0];
1457
1389
  return /* @__PURE__ */ jsxs("div", {
1458
- className: "cr-booking-mode",
1390
+ className: "er-whole-series-booking-mode",
1459
1391
  children: [
1460
1392
  /* @__PURE__ */ jsx("h2", {
1461
- className: "cr-booking-mode__title",
1393
+ className: "er-whole-series-booking-mode__title",
1462
1394
  children: "How would you like to enroll?"
1463
1395
  }),
1464
1396
  /* @__PURE__ */ jsx("p", {
1465
- className: "cr-booking-mode__subtitle",
1397
+ className: "er-whole-series-booking-mode__subtitle",
1466
1398
  children: "Choose how you want to book"
1467
1399
  }),
1468
1400
  showMembershipHero && singleMembership && /* @__PURE__ */ jsx(MembershipHero, { membershipName: singleMembership.membershipName }),
1469
1401
  /* @__PURE__ */ jsxs("div", {
1470
- className: "cr-payment-tiles",
1402
+ className: "er-whole-series-payment-tiles",
1471
1403
  children: [
1472
- hasSingleMembership && singleMembership && /* @__PURE__ */ jsxs("button", {
1473
- type: "button",
1474
- className: `cr-payment-tile${bookingMode === "membership" ? " cr-payment-tile--selected" : ""}`,
1475
- onClick: () => {
1404
+ hasSingleMembership && singleMembership && /* @__PURE__ */ jsx(MembershipOption, {
1405
+ membership: singleMembership,
1406
+ selected: bookingMode === "membership",
1407
+ description: "Use your membership to book for free",
1408
+ onSelect: () => {
1476
1409
  onBookingModeChange("membership");
1477
1410
  onMembershipSelect(singleMembership.customerMembershipId);
1478
- },
1479
- "aria-pressed": bookingMode === "membership",
1480
- children: [
1481
- /* @__PURE__ */ jsx("div", {
1482
- className: "cr-payment-tile__check",
1483
- children: /* @__PURE__ */ jsx(CheckIcon, { strokeWidth: 3 })
1484
- }),
1485
- /* @__PURE__ */ jsxs("div", {
1486
- className: "cr-payment-tile__header",
1487
- children: [/* @__PURE__ */ jsx("h3", {
1488
- className: "cr-payment-tile__name",
1489
- children: singleMembership.membershipName
1490
- }), /* @__PURE__ */ jsx("span", {
1491
- className: "cr-payment-tile__price",
1492
- children: "Free"
1493
- })]
1494
- }),
1495
- /* @__PURE__ */ jsx("p", {
1496
- className: "cr-payment-tile__description",
1497
- children: "Use your membership to book for free"
1498
- })
1499
- ]
1411
+ }
1500
1412
  }),
1501
- hasMultipleMemberships && eligibleMemberships.map((membership) => /* @__PURE__ */ jsxs("button", {
1502
- type: "button",
1503
- className: `cr-payment-tile${bookingMode === "membership" && selectedMembershipId === membership.customerMembershipId ? " cr-payment-tile--selected" : ""}`,
1504
- onClick: () => {
1413
+ hasMultipleMemberships && eligibleMemberships.map((membership) => /* @__PURE__ */ jsx(MembershipOption, {
1414
+ membership,
1415
+ selected: bookingMode === "membership" && selectedMembershipId === membership.customerMembershipId,
1416
+ description: "Use this membership to book for free",
1417
+ onSelect: () => {
1505
1418
  onBookingModeChange("membership");
1506
1419
  onMembershipSelect(membership.customerMembershipId);
1507
- },
1508
- "aria-pressed": bookingMode === "membership" && selectedMembershipId === membership.customerMembershipId,
1509
- children: [
1510
- /* @__PURE__ */ jsx("div", {
1511
- className: "cr-payment-tile__check",
1512
- children: /* @__PURE__ */ jsx(CheckIcon, { strokeWidth: 3 })
1513
- }),
1514
- /* @__PURE__ */ jsxs("div", {
1515
- className: "cr-payment-tile__header",
1516
- children: [/* @__PURE__ */ jsx("h3", {
1517
- className: "cr-payment-tile__name",
1518
- children: membership.membershipName
1519
- }), /* @__PURE__ */ jsx("span", {
1520
- className: "cr-payment-tile__price",
1521
- children: "Free"
1522
- })]
1523
- }),
1524
- /* @__PURE__ */ jsx("p", {
1525
- className: "cr-payment-tile__description",
1526
- children: "Use this membership to book for free"
1527
- })
1528
- ]
1420
+ }
1529
1421
  }, membership.customerMembershipId)),
1530
- /* @__PURE__ */ jsxs("button", {
1531
- type: "button",
1532
- className: `cr-payment-tile${bookingMode === "card" ? " cr-payment-tile--selected" : ""}`,
1533
- onClick: () => {
1422
+ /* @__PURE__ */ jsx(BookingOption, {
1423
+ selected: bookingMode === "card",
1424
+ name: "Pay by Card",
1425
+ price: priceCents === null ? null : formatPrice(priceCents, currency),
1426
+ description: "Pay with credit or debit card",
1427
+ onSelect: () => {
1534
1428
  onBookingModeChange("card");
1535
1429
  onMembershipSelect(null);
1536
- },
1537
- "aria-pressed": bookingMode === "card",
1538
- children: [
1539
- /* @__PURE__ */ jsx("div", {
1540
- className: "cr-payment-tile__check",
1541
- children: /* @__PURE__ */ jsx(CheckIcon, { strokeWidth: 3 })
1542
- }),
1543
- /* @__PURE__ */ jsxs("div", {
1544
- className: "cr-payment-tile__header",
1545
- children: [/* @__PURE__ */ jsx("h3", {
1546
- className: "cr-payment-tile__name",
1547
- children: "Pay by Card"
1548
- }), priceCents !== null && /* @__PURE__ */ jsx("span", {
1549
- className: "cr-payment-tile__price",
1550
- children: formatPrice(priceCents, currency)
1551
- })]
1552
- }),
1553
- /* @__PURE__ */ jsx("p", {
1554
- className: "cr-payment-tile__description",
1555
- children: "Pay with credit or debit card"
1556
- })
1557
- ]
1430
+ }
1558
1431
  })
1559
1432
  ]
1560
1433
  }),
1561
1434
  showEnrollForOtherLink && onEnrollForOther && /* @__PURE__ */ jsx("div", {
1562
- className: "cr-booking-mode__link",
1435
+ className: "er-whole-series-booking-mode__link",
1563
1436
  children: /* @__PURE__ */ jsx("a", {
1564
1437
  onClick: onEnrollForOther,
1565
1438
  role: "button",
@@ -1570,249 +1443,736 @@ function BookingModeStep({ bookingMode, onBookingModeChange, eligibleMemberships
1570
1443
  ]
1571
1444
  });
1572
1445
  }
1573
- //#endregion
1574
- //#region ../blocks/src/system/runtime/nodes/shared/MagicLinkForm.state.ts
1575
- const initialMagicLinkSubmissionState = Object.freeze({ tag: "idle" });
1576
- function magicLinkSubmissionReducer(state, action) {
1577
- switch (action.type) {
1578
- case "submit-started":
1579
- if (state.tag === "submitting") return state;
1580
- return { tag: "submitting" };
1581
- case "submit-succeeded":
1582
- if (state.tag !== "submitting") return state;
1583
- return { tag: "success" };
1584
- case "submit-failed":
1585
- if (state.tag !== "submitting") return state;
1586
- return {
1587
- tag: "error",
1588
- message: action.message
1589
- };
1590
- case "reset": return initialMagicLinkSubmissionState;
1591
- default: return assertNever$1(action);
1592
- }
1593
- }
1594
- function isMagicLinkSubmitting(state) {
1595
- return state.tag === "submitting";
1596
- }
1597
- function getMagicLinkError(state) {
1598
- return state.tag === "error" ? state.message : null;
1446
+ function MembershipOption({ membership, selected, description, onSelect }) {
1447
+ return /* @__PURE__ */ jsx(BookingOption, {
1448
+ selected,
1449
+ name: membership.membershipName,
1450
+ price: "Free",
1451
+ description,
1452
+ onSelect
1453
+ });
1599
1454
  }
1600
- //#endregion
1601
- //#region ../blocks/src/system/runtime/nodes/shared/MagicLinkForm.tsx
1602
- /**
1603
- * Reusable magic link login form.
1604
- * Used by Customer Portal and Event Registration blocks.
1605
- */
1606
- function MagicLinkForm({ initialEmail = "", title, subtitle, buttonText = "Send login link", successMessage = "Check your email for a login link to sign in.", onSuccess, classPrefix = "er", compact = false }) {
1607
- const api = useBlockApi();
1608
- const [email, setEmail] = useState(initialEmail);
1609
- const [submissionState, dispatchSubmission] = useReducer(magicLinkSubmissionReducer, initialMagicLinkSubmissionState);
1610
- const loading = isMagicLinkSubmitting(submissionState);
1611
- const error = getMagicLinkError(submissionState);
1612
- const handleSubmit = async (e) => {
1613
- e.preventDefault();
1614
- const normalizedEmail = email.trim().toLowerCase();
1615
- if (!normalizedEmail || loading) return;
1616
- dispatchSubmission({ type: "submit-started" });
1617
- try {
1618
- const redirectTo = `${window.location.pathname}${window.location.search}${window.location.hash}`;
1619
- await api.sendMagicLink({
1620
- email: normalizedEmail,
1621
- redirectUrl: `${window.location.origin}/api/portal/callback?redirect_to=${encodeURIComponent(redirectTo)}`
1622
- });
1623
- dispatchSubmission({ type: "submit-succeeded" });
1624
- onSuccess?.();
1625
- } catch (err) {
1626
- console.error("Magic link error:", err);
1627
- dispatchSubmission({
1628
- type: "submit-failed",
1629
- message: getMagicLinkErrorMessage(err)
1630
- });
1631
- }
1632
- };
1633
- const handleReset = () => {
1634
- setEmail("");
1635
- dispatchSubmission({ type: "reset" });
1455
+ function BookingOption({ selected, name, price, description, onSelect }) {
1456
+ return /* @__PURE__ */ jsxs("button", {
1457
+ type: "button",
1458
+ className: `er-whole-series-payment-tile${selected ? " er-whole-series-payment-tile--selected" : ""}`,
1459
+ onClick: onSelect,
1460
+ "aria-pressed": selected,
1461
+ children: [
1462
+ /* @__PURE__ */ jsx("div", {
1463
+ className: "er-whole-series-payment-tile__check",
1464
+ children: /* @__PURE__ */ jsx(CheckIcon, { strokeWidth: 3 })
1465
+ }),
1466
+ /* @__PURE__ */ jsxs("div", {
1467
+ className: "er-whole-series-payment-tile__header",
1468
+ children: [/* @__PURE__ */ jsx("h3", {
1469
+ className: "er-whole-series-payment-tile__name",
1470
+ children: name
1471
+ }), price ? /* @__PURE__ */ jsx("span", {
1472
+ className: "er-whole-series-payment-tile__price",
1473
+ children: price
1474
+ }) : null]
1475
+ }),
1476
+ /* @__PURE__ */ jsx("p", {
1477
+ className: "er-whole-series-payment-tile__description",
1478
+ children: description
1479
+ })
1480
+ ]
1481
+ });
1482
+ }
1483
+ //#endregion
1484
+ //#region ../blocks/src/system/runtime/shared/components/LoggedInAsUser.tsx
1485
+ /**
1486
+ * Displays the logged-in user's email with an optional logout link.
1487
+ *
1488
+ * Used in registration forms when the email field is locked due to portal authentication.
1489
+ * Shows: "Logged in as {email} — Not you? Log out"
1490
+ */
1491
+ function LoggedInAsUser({ email, onLogout, classPrefix }) {
1492
+ return /* @__PURE__ */ jsxs("p", {
1493
+ className: `${classPrefix}-logged-in-hint`,
1494
+ children: [
1495
+ "Logged in as ",
1496
+ email,
1497
+ onLogout && /* @__PURE__ */ jsxs(Fragment, { children: [" — ", /* @__PURE__ */ jsx("button", {
1498
+ type: "button",
1499
+ className: `${classPrefix}-link`,
1500
+ onClick: onLogout,
1501
+ children: "Not you? Log out"
1502
+ })] })
1503
+ ]
1504
+ });
1505
+ }
1506
+ //#endregion
1507
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/components.tsx
1508
+ function TeamMemberInlineList({ teamMembers }) {
1509
+ return /* @__PURE__ */ jsx(Fragment, { children: teamMembers.map((teamMember, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [index > 0 ? ", " : "", teamMember.profilePath ? /* @__PURE__ */ jsx("a", {
1510
+ href: teamMember.profilePath,
1511
+ children: teamMember.name
1512
+ }) : teamMember.name] }, teamMember.id)) });
1513
+ }
1514
+ function RunCard({ run, isSelected, onSelect, showSessions, showPrice, showCapacity, showVenue }) {
1515
+ const pricing = resolveWholeSeriesPricingState(run);
1516
+ const view = buildRunCardView(run, pricing);
1517
+ return /* @__PURE__ */ jsxs("div", {
1518
+ className: `er-whole-series-run-card ${isSelected ? "er-whole-series-run-card--selected" : ""}`,
1519
+ onClick: onSelect,
1520
+ role: "button",
1521
+ tabIndex: 0,
1522
+ "aria-pressed": isSelected,
1523
+ onKeyDown: (e) => {
1524
+ if (e.key === "Enter" || e.key === " ") {
1525
+ e.preventDefault();
1526
+ onSelect();
1527
+ }
1528
+ },
1529
+ children: [
1530
+ /* @__PURE__ */ jsx("h3", {
1531
+ className: "er-whole-series-run-card__title",
1532
+ children: run.title
1533
+ }),
1534
+ view.enrollmentClosed && /* @__PURE__ */ jsx("p", {
1535
+ className: "er-whole-series-run-card__status",
1536
+ children: "Registration closed"
1537
+ }),
1538
+ showSessions && run.sessionsCount > 0 && /* @__PURE__ */ jsxs("p", {
1539
+ className: "er-whole-series-run-card__sessions",
1540
+ children: [
1541
+ run.sessionsCount,
1542
+ " session",
1543
+ run.sessionsCount !== 1 ? "s" : ""
1544
+ ]
1545
+ }),
1546
+ showPrice && pricing.display.kind !== "unavailable" && /* @__PURE__ */ jsx("p", {
1547
+ className: "er-whole-series-run-card__price",
1548
+ children: view.priceLabel
1549
+ }),
1550
+ showCapacity && run.availableSpots !== null && /* @__PURE__ */ jsx("p", {
1551
+ className: "er-whole-series-run-card__capacity",
1552
+ children: view.capacityLabel
1553
+ }),
1554
+ showVenue && run.venue && /* @__PURE__ */ jsx("p", {
1555
+ className: "er-whole-series-run-card__venue",
1556
+ children: run.venue.name
1557
+ }),
1558
+ view.teamMemberNames.length > 0 && /* @__PURE__ */ jsxs("p", {
1559
+ className: "er-whole-series-run-card__venue",
1560
+ children: ["Team: ", view.teamMemberNames.join(", ")]
1561
+ })
1562
+ ]
1563
+ });
1564
+ }
1565
+ function buildRunCardView(run, pricing) {
1566
+ const availableSpots = run.availableSpots ?? 0;
1567
+ return {
1568
+ enrollmentClosed: run.enrollmentOpen === false,
1569
+ priceLabel: formatWholeSeriesPriceDisplay(pricing.display),
1570
+ capacityLabel: availableSpots > 0 ? `${availableSpots} spot${availableSpots === 1 ? "" : "s"} available` : "Waitlist only",
1571
+ teamMemberNames: (run.teamMembers ?? []).map((teamMember) => teamMember.name).filter(Boolean)
1636
1572
  };
1637
- if (submissionState.tag === "success") return /* @__PURE__ */ jsxs("div", {
1638
- className: `${classPrefix}-magic-link-success`,
1639
- children: [/* @__PURE__ */ jsx("p", {
1640
- className: `${classPrefix}-portal-auth-text ${classPrefix}-portal-auth-text--success`,
1641
- children: successMessage
1642
- }), !compact && /* @__PURE__ */ jsx("button", {
1643
- type: "button",
1644
- className: classPrefix === "cp" ? themeButtonClassName({
1645
- variant: "secondary",
1646
- size: "md"
1647
- }) : `${classPrefix}-modal-btn ${classPrefix}-modal-btn--secondary`,
1648
- onClick: handleReset,
1649
- children: "Try a different email"
1573
+ }
1574
+ function RunSummary({ run, pricing, showSessions, showVenue, showPrice, showMembershipNote }) {
1575
+ const teamMembers = run.teamMembers ?? [];
1576
+ const priceLabel = pricing.selectedOption ? `${pricing.selectedOption.name} - ${formatWholeSeriesPriceAmount(pricing.selectedOption.priceAmount, pricing.currency)}` : formatWholeSeriesPriceDisplay(pricing.display);
1577
+ return /* @__PURE__ */ jsxs("div", {
1578
+ className: "er-whole-series-summary",
1579
+ children: [
1580
+ /* @__PURE__ */ jsx("h3", {
1581
+ className: "er-whole-series-summary__title",
1582
+ children: run.title
1583
+ }),
1584
+ showSessions && run.sessions.length > 0 && /* @__PURE__ */ jsxs("div", {
1585
+ className: "er-whole-series-summary__sessions",
1586
+ children: [/* @__PURE__ */ jsx("h4", {
1587
+ className: "er-whole-series-summary__sessions-title",
1588
+ children: "Sessions"
1589
+ }), /* @__PURE__ */ jsx("ul", {
1590
+ className: "er-whole-series-summary__sessions-list",
1591
+ children: run.sessions.map((session) => /* @__PURE__ */ jsxs("li", {
1592
+ className: "er-whole-series-summary__session",
1593
+ children: [
1594
+ formatDate(session.startsAt, { timeZone: session.timeZone }),
1595
+ " ",
1596
+ "at",
1597
+ " ",
1598
+ formatTime(session.startsAt, { timeZone: session.timeZone })
1599
+ ]
1600
+ }, session.id))
1601
+ })]
1602
+ }),
1603
+ showVenue && run.venue && /* @__PURE__ */ jsxs("p", {
1604
+ className: "er-whole-series-summary__venue",
1605
+ children: [
1606
+ /* @__PURE__ */ jsx("strong", { children: "Venue:" }),
1607
+ " ",
1608
+ run.venue.name,
1609
+ run.venue.address && ` - ${run.venue.address}`
1610
+ ]
1611
+ }),
1612
+ teamMembers.length > 0 && /* @__PURE__ */ jsxs("div", {
1613
+ className: "er-whole-series-summary__venue",
1614
+ children: [
1615
+ /* @__PURE__ */ jsx("strong", { children: "Team:" }),
1616
+ " ",
1617
+ /* @__PURE__ */ jsx(TeamMemberInlineList, { teamMembers })
1618
+ ]
1619
+ }),
1620
+ showPrice && pricing.display.kind !== "unavailable" && /* @__PURE__ */ jsxs("p", {
1621
+ className: "er-whole-series-summary__price",
1622
+ children: [
1623
+ /* @__PURE__ */ jsx("strong", { children: pricing.selectableOptions.length > 0 ? "Pricing:" : "Price:" }),
1624
+ " ",
1625
+ priceLabel
1626
+ ]
1627
+ }),
1628
+ showMembershipNote && /* @__PURE__ */ jsx("p", {
1629
+ className: "er-whole-series-summary__membership",
1630
+ children: "✓ Your membership can be used to book for free"
1631
+ })
1632
+ ]
1633
+ });
1634
+ }
1635
+ function WholeSeriesPricingSelector({ pricing, selectedPricingOptionId, onSelect }) {
1636
+ if (pricing.selectableOptions.length <= 1) return null;
1637
+ return /* @__PURE__ */ jsxs("fieldset", {
1638
+ className: "er-whole-series-form__field",
1639
+ children: [/* @__PURE__ */ jsx("legend", {
1640
+ id: "er-whole-series-pricing-options-label",
1641
+ className: "er-whole-series-form__label",
1642
+ children: "Pricing option"
1643
+ }), /* @__PURE__ */ jsx("div", {
1644
+ className: "er-whole-series-payment-tiles",
1645
+ role: "radiogroup",
1646
+ "aria-labelledby": "er-whole-series-pricing-options-label",
1647
+ children: pricing.selectableOptions.map((option) => {
1648
+ const isSelected = selectedPricingOptionId === option.id;
1649
+ const priceLabel = formatWholeSeriesPriceAmount(option.priceAmount, pricing.currency);
1650
+ return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs("button", {
1651
+ type: "button",
1652
+ role: "radio",
1653
+ "aria-checked": isSelected,
1654
+ className: `er-whole-series-payment-tile${isSelected ? " er-whole-series-payment-tile--selected" : ""}`,
1655
+ onClick: () => onSelect(option.id),
1656
+ children: [/* @__PURE__ */ jsxs("div", {
1657
+ className: "er-whole-series-payment-tile__header",
1658
+ children: [/* @__PURE__ */ jsx("h3", {
1659
+ className: "er-whole-series-payment-tile__name",
1660
+ children: option.name
1661
+ }), /* @__PURE__ */ jsx("span", {
1662
+ className: "er-whole-series-payment-tile__price",
1663
+ children: priceLabel
1664
+ })]
1665
+ }), option.description ? /* @__PURE__ */ jsx("p", {
1666
+ className: "er-whole-series-payment-tile__description",
1667
+ children: option.description
1668
+ }) : null]
1669
+ }) }, option.id);
1670
+ })
1650
1671
  })]
1651
1672
  });
1652
- return /* @__PURE__ */ jsxs("form", {
1653
- onSubmit: handleSubmit,
1654
- className: `${classPrefix}-magic-link-form`,
1673
+ }
1674
+ function WholeSeriesSlidingScaleInput({ pricing, value, onChange }) {
1675
+ const slidingScale = pricing.slidingScale;
1676
+ if (!slidingScale) return null;
1677
+ const minLabel = formatWholeSeriesPriceAmount(slidingScale.minAmount, pricing.currency);
1678
+ const maxLabel = formatWholeSeriesPriceAmount(slidingScale.maxAmount, pricing.currency);
1679
+ const suggestedLabel = slidingScale.suggestedAmount !== null ? formatWholeSeriesPriceAmount(slidingScale.suggestedAmount, pricing.currency) : null;
1680
+ return /* @__PURE__ */ jsxs("div", {
1681
+ className: "er-whole-series-form__field",
1655
1682
  children: [
1656
- title && /* @__PURE__ */ jsx("h3", {
1657
- className: `${classPrefix}-magic-link-title`,
1658
- children: title
1659
- }),
1660
- subtitle && /* @__PURE__ */ jsx("p", {
1661
- className: `${classPrefix}-portal-auth-text`,
1662
- children: subtitle
1683
+ /* @__PURE__ */ jsx("label", {
1684
+ htmlFor: "er-whole-series-sliding-amount",
1685
+ className: "er-whole-series-form__label",
1686
+ children: "Amount"
1663
1687
  }),
1664
1688
  /* @__PURE__ */ jsx("input", {
1665
- type: "email",
1666
- className: classPrefix === "cp" ? "cp-input" : `${classPrefix}-form__input`,
1667
- placeholder: "your@email.com",
1668
- value: email,
1669
- onChange: (e) => setEmail(e.target.value),
1670
- autoFocus: !compact,
1671
- required: true,
1672
- disabled: loading
1673
- }),
1674
- error && /* @__PURE__ */ jsx("p", {
1675
- className: `${classPrefix}-portal-auth-text ${classPrefix}-portal-auth-text--error`,
1676
- children: error
1689
+ id: "er-whole-series-sliding-amount",
1690
+ type: "number",
1691
+ min: slidingScale.minAmount / 100,
1692
+ max: slidingScale.maxAmount / 100,
1693
+ step: "0.01",
1694
+ inputMode: "decimal",
1695
+ className: "er-whole-series-form__input",
1696
+ value,
1697
+ onChange: (event) => onChange(event.target.value)
1677
1698
  }),
1678
- /* @__PURE__ */ jsx("button", {
1679
- type: "submit",
1680
- className: classPrefix === "cp" ? themeButtonClassName({
1681
- variant: "primary",
1682
- size: "md"
1683
- }) : `${classPrefix}-modal-btn`,
1684
- disabled: !email.trim() || loading,
1685
- children: loading ? "Sending..." : buttonText
1699
+ /* @__PURE__ */ jsxs("p", {
1700
+ className: "er-whole-series-text er-whole-series-text--muted",
1701
+ children: [
1702
+ "Choose between ",
1703
+ minLabel,
1704
+ " and ",
1705
+ maxLabel,
1706
+ suggestedLabel ? `; suggested ${suggestedLabel}` : "",
1707
+ "."
1708
+ ]
1686
1709
  })
1687
1710
  ]
1688
1711
  });
1689
1712
  }
1690
- function getMagicLinkErrorMessage(error) {
1691
- return error instanceof Error ? error.message : "Failed to send. Please try again.";
1713
+ function EnrollmentForm({ formData, errors, onChange, isEmailLocked, isLoading, onLogout }) {
1714
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(EnrollmentIdentityFields, {
1715
+ formData,
1716
+ errors,
1717
+ onChange,
1718
+ isEmailLocked,
1719
+ isLoading,
1720
+ onLogout
1721
+ }), /* @__PURE__ */ jsx(EnrollmentOptionalFields, {
1722
+ formData,
1723
+ onChange,
1724
+ isLoading
1725
+ })] });
1692
1726
  }
1693
- //#endregion
1694
- //#region ../blocks/src/system/runtime/nodes/course-registration/PortalAuthSidebar.tsx
1695
- /**
1696
- * Portal authentication sidebar.
1697
- * Shows login prompt for unauthenticated users who might have memberships.
1698
- */
1699
- const PORTAL_AUTH_COPY = {
1700
- membership: {
1701
- title: "Have a membership?",
1702
- description: "Log in to use your membership to book for free",
1703
- buttonText: "Log in with email",
1704
- modalTitle: "Log in",
1705
- modalHeading: "Log in to your account",
1706
- modalSubtitle: "Enter your email to receive a magic link",
1707
- successMessage: "Check your email for a login link. After clicking, refresh this page."
1708
- },
1709
- "waitlist-claim": {
1710
- title: "Log in to claim your waitlist spot",
1711
- description: "",
1712
- buttonText: "Log in with email to continue",
1713
- modalTitle: "Log in to continue",
1714
- modalHeading: "Log in to your account to continue",
1715
- modalSubtitle: "Enter your email to receive a login link and continue your waitlist claim",
1716
- successMessage: "Check your email for a login link. After clicking it, return here to continue your claim."
1717
- }
1718
- };
1719
- function PortalAuthSidebar({ onMagicLinkSent, autoOpen = false, variant = "membership", loginMessage }) {
1720
- const [showModal, setShowModal] = useState(false);
1721
- const copy = PORTAL_AUTH_COPY[variant];
1722
- const description = variant === "waitlist-claim" ? loginMessage ?? "Log in to continue with your waitlist claim." : copy.description;
1723
- useEffect(() => {
1724
- if (!autoOpen) return;
1725
- setShowModal(true);
1726
- }, [autoOpen]);
1727
+ function EnrollmentIdentityFields({ formData, errors, onChange, isEmailLocked, isLoading, onLogout }) {
1728
+ const nameErrorId = "er-whole-series-name-error";
1729
+ const emailErrorId = "er-whole-series-email-error";
1730
+ const nameValidationProps = getFieldValidationControlProps({
1731
+ message: errors.name,
1732
+ messageId: nameErrorId
1733
+ });
1734
+ const emailValidationProps = getFieldValidationControlProps({
1735
+ message: errors.email,
1736
+ messageId: emailErrorId
1737
+ });
1738
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
1739
+ className: "er-whole-series-form__field",
1740
+ children: [
1741
+ /* @__PURE__ */ jsx("label", {
1742
+ htmlFor: "er-whole-series-name",
1743
+ className: "er-whole-series-form__label",
1744
+ children: "Name *"
1745
+ }),
1746
+ /* @__PURE__ */ jsx("input", {
1747
+ id: "er-whole-series-name",
1748
+ type: "text",
1749
+ className: `er-whole-series-form__input ${errors.name ? "er-whole-series-form__input--error" : ""}`,
1750
+ value: formData.name,
1751
+ onChange: (e) => onChange({
1752
+ ...formData,
1753
+ name: e.target.value
1754
+ }),
1755
+ disabled: isLoading,
1756
+ ...nameValidationProps
1757
+ }),
1758
+ errors.name && /* @__PURE__ */ jsx(FieldValidationMessage, {
1759
+ id: nameErrorId,
1760
+ className: "er-whole-series-form__error",
1761
+ children: errors.name
1762
+ })
1763
+ ]
1764
+ }), /* @__PURE__ */ jsxs("div", {
1765
+ className: "er-whole-series-form__field",
1766
+ children: [
1767
+ /* @__PURE__ */ jsx("label", {
1768
+ htmlFor: "er-whole-series-email",
1769
+ className: "er-whole-series-form__label",
1770
+ children: "Email *"
1771
+ }),
1772
+ /* @__PURE__ */ jsx("input", {
1773
+ id: "er-whole-series-email",
1774
+ type: "email",
1775
+ className: `er-whole-series-form__input ${errors.email ? "er-whole-series-form__input--error" : ""}`,
1776
+ value: formData.email,
1777
+ onChange: (e) => onChange({
1778
+ ...formData,
1779
+ email: e.target.value
1780
+ }),
1781
+ disabled: isEmailLocked || isLoading,
1782
+ ...emailValidationProps
1783
+ }),
1784
+ errors.email && /* @__PURE__ */ jsx(FieldValidationMessage, {
1785
+ id: emailErrorId,
1786
+ className: "er-whole-series-form__error",
1787
+ children: errors.email
1788
+ }),
1789
+ isEmailLocked && /* @__PURE__ */ jsx(LoggedInAsUser, {
1790
+ email: formData.email,
1791
+ onLogout,
1792
+ classPrefix: "er-whole-series"
1793
+ })
1794
+ ]
1795
+ })] });
1796
+ }
1797
+ function EnrollmentOptionalFields({ formData, onChange, isLoading }) {
1727
1798
  return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
1728
- className: "cr-portal-sidebar",
1729
- children: [
1730
- /* @__PURE__ */ jsx("div", {
1731
- className: "cr-portal-sidebar__icon",
1732
- "aria-hidden": "true",
1733
- children: "👤"
1799
+ className: "er-whole-series-form__field",
1800
+ children: [/* @__PURE__ */ jsx("label", {
1801
+ htmlFor: "er-whole-series-phone",
1802
+ className: "er-whole-series-form__label",
1803
+ children: "Phone"
1804
+ }), /* @__PURE__ */ jsx("input", {
1805
+ id: "er-whole-series-phone",
1806
+ type: "tel",
1807
+ className: "er-whole-series-form__input",
1808
+ value: formData.phone,
1809
+ onChange: (e) => onChange({
1810
+ ...formData,
1811
+ phone: e.target.value
1734
1812
  }),
1735
- /* @__PURE__ */ jsx("h3", {
1736
- className: "cr-portal-sidebar__title",
1737
- children: copy.title
1813
+ disabled: isLoading
1814
+ })]
1815
+ }), /* @__PURE__ */ jsxs("div", {
1816
+ className: "er-whole-series-form__field",
1817
+ children: [/* @__PURE__ */ jsx("label", {
1818
+ htmlFor: "er-whole-series-notes",
1819
+ className: "er-whole-series-form__label",
1820
+ children: "Notes"
1821
+ }), /* @__PURE__ */ jsx("textarea", {
1822
+ id: "er-whole-series-notes",
1823
+ className: "er-whole-series-form__textarea",
1824
+ value: formData.notes,
1825
+ onChange: (e) => onChange({
1826
+ ...formData,
1827
+ notes: e.target.value
1738
1828
  }),
1739
- /* @__PURE__ */ jsx("p", {
1740
- className: "cr-portal-sidebar__text",
1741
- children: description
1829
+ rows: 3,
1830
+ disabled: isLoading
1831
+ })]
1832
+ })] });
1833
+ }
1834
+ //#endregion
1835
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationActiveSteps.tsx
1836
+ function WholeSeriesRegistrationActiveStep({ wizard, display }) {
1837
+ switch (wizard.step) {
1838
+ case "select-run": return /* @__PURE__ */ jsx(RunSelectionStep, {
1839
+ wizard,
1840
+ display
1841
+ });
1842
+ case "enter-details": return /* @__PURE__ */ jsx(RegistrationDetailsStep, {
1843
+ wizard,
1844
+ display
1845
+ });
1846
+ case "booking-mode": return /* @__PURE__ */ jsx(RegistrationBookingModeStep, {
1847
+ wizard,
1848
+ display
1849
+ });
1850
+ case "select-payment": return /* @__PURE__ */ jsx(RegistrationPaymentStep, {
1851
+ wizard,
1852
+ display
1853
+ });
1854
+ case "error":
1855
+ case "payment-failed":
1856
+ case "redirecting":
1857
+ case "submitting":
1858
+ case "success":
1859
+ case "verifying-payment":
1860
+ case "verifying-timeout":
1861
+ case "waitlist": return null;
1862
+ }
1863
+ }
1864
+ function RunSelectionStep({ wizard, display }) {
1865
+ return /* @__PURE__ */ jsx("div", {
1866
+ className: "er-whole-series-run-list",
1867
+ children: wizard.scopedRuns.map((run) => /* @__PURE__ */ jsx(RunCard, {
1868
+ run,
1869
+ isSelected: wizard.selectedRun?.eventSeriesId === run.eventSeriesId,
1870
+ onSelect: () => wizard.handleRunSelect(run),
1871
+ showSessions: display.showSessions,
1872
+ showPrice: display.showPrice,
1873
+ showCapacity: display.showCapacity,
1874
+ showVenue: display.showVenue
1875
+ }, run.eventSeriesId))
1876
+ });
1877
+ }
1878
+ function RegistrationDetailsStep({ wizard, display }) {
1879
+ const selection = selectedRunWithPricing(wizard);
1880
+ if (!selection) return null;
1881
+ return /* @__PURE__ */ jsxs("div", {
1882
+ className: "er-whole-series-details",
1883
+ children: [/* @__PURE__ */ jsx(RunSummary, {
1884
+ run: selection.run,
1885
+ pricing: selection.pricing,
1886
+ showSessions: display.showSessions,
1887
+ showVenue: display.showVenue,
1888
+ showPrice: display.showPrice,
1889
+ showMembershipNote: selection.run.acceptsMemberships && wizard.portalAuthState === "authenticated"
1890
+ }), selection.run.enrollmentOpen === false ? /* @__PURE__ */ jsx(ClosedRunNotice, { wizard }) : /* @__PURE__ */ jsx(RegistrationDetailsForm, {
1891
+ wizard,
1892
+ display
1893
+ })]
1894
+ });
1895
+ }
1896
+ function ClosedRunNotice({ wizard }) {
1897
+ return /* @__PURE__ */ jsxs("div", {
1898
+ className: "er-whole-series-form",
1899
+ children: [/* @__PURE__ */ jsx(BackToRunsButton, { wizard }), /* @__PURE__ */ jsx("p", {
1900
+ className: "er-whole-series-text er-whole-series-text--muted",
1901
+ children: "Registration closed."
1902
+ })]
1903
+ });
1904
+ }
1905
+ function RegistrationDetailsForm({ wizard, display }) {
1906
+ const blockers = deriveDetailsBlockers(wizard);
1907
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("form", {
1908
+ className: "er-whole-series-form",
1909
+ onSubmit: (event) => {
1910
+ event.preventDefault();
1911
+ wizard.handleSubmit();
1912
+ },
1913
+ children: [
1914
+ /* @__PURE__ */ jsx(EnrollmentForm, {
1915
+ formData: wizard.formData,
1916
+ errors: wizard.errors,
1917
+ onChange: wizard.updateFormData,
1918
+ isEmailLocked: wizard.portalAuthState === "authenticated" || wizard.waitlistClaim.claim !== null,
1919
+ isLoading: wizard.portalAuthState === "checking" || wizard.waitlistClaim.isLoading,
1920
+ onLogout: wizard.handleLogout
1742
1921
  }),
1743
- /* @__PURE__ */ jsx("div", {
1744
- className: "cr-portal-sidebar__action",
1745
- children: /* @__PURE__ */ jsx("button", {
1746
- type: "button",
1747
- className: "cr-portal-sidebar__link",
1748
- onClick: () => setShowModal(true),
1749
- children: copy.buttonText
1922
+ /* @__PURE__ */ jsx(PricingFields, { wizard }),
1923
+ wizard.showSpamProtection ? /* @__PURE__ */ jsx("div", {
1924
+ className: "er-whole-series-altcha",
1925
+ children: /* @__PURE__ */ jsx(AltchaWidget, {
1926
+ challengeUrl: getChallengeUrl(),
1927
+ onSolutionChange: wizard.setAltchaSolution
1750
1928
  })
1929
+ }) : null,
1930
+ /* @__PURE__ */ jsx(DiscountFields, { wizard }),
1931
+ /* @__PURE__ */ jsxs("div", {
1932
+ className: "er-whole-series-actions",
1933
+ children: [/* @__PURE__ */ jsx(BackToRunsButton, {
1934
+ wizard,
1935
+ compact: true
1936
+ }), /* @__PURE__ */ jsx("button", {
1937
+ type: "submit",
1938
+ className: buttonClass(display.buttonVariant),
1939
+ disabled: blockers.disabled,
1940
+ children: detailsSubmitLabel(wizard, display.buttonText, blockers.soldOut)
1941
+ })]
1751
1942
  })
1752
1943
  ]
1753
- }), showModal && /* @__PURE__ */ jsx(ModalShell, {
1754
- title: copy.modalTitle,
1755
- titleId: "cr-portal-auth-modal-title",
1756
- onClose: () => setShowModal(false),
1757
- overlayClassName: "cr-modal-overlay",
1758
- modalClassName: "cr-modal",
1759
- renderSrOnlyTitle: true,
1760
- renderHeader: ({ closeButtonRef, onClose }) => /* @__PURE__ */ jsx("button", {
1761
- ref: closeButtonRef,
1762
- type: "button",
1763
- className: "cr-modal-close",
1764
- onClick: onClose,
1765
- "aria-label": "Close",
1766
- children: /* @__PURE__ */ jsx("svg", {
1767
- width: "20",
1768
- height: "20",
1769
- viewBox: "0 0 24 24",
1770
- fill: "none",
1771
- stroke: "currentColor",
1772
- strokeWidth: "2",
1773
- "aria-hidden": "true",
1774
- children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" })
1775
- })
1776
- }),
1777
- children: /* @__PURE__ */ jsx(MagicLinkForm, {
1778
- classPrefix: "cr",
1779
- title: copy.modalHeading,
1780
- subtitle: copy.modalSubtitle,
1781
- buttonText: "Send login link",
1782
- successMessage: copy.successMessage,
1783
- onSuccess: () => {
1784
- onMagicLinkSent?.();
1785
- }
1786
- })
1944
+ }), /* @__PURE__ */ jsx(DetailsBlockerMessages, {
1945
+ wizard,
1946
+ blockers
1787
1947
  })] });
1788
1948
  }
1789
- //#endregion
1790
- //#region ../blocks/src/system/runtime/nodes/course-registration/SuccessStep.tsx
1791
- /**
1792
- * Success terminal state component.
1793
- * Shows confirmation after successful enrollment.
1794
- */
1795
- function SuccessStep({ usedMembership, successMessage, membershipMessage }) {
1796
- return /* @__PURE__ */ jsx(TerminalPanel, {
1797
- tone: "success",
1798
- className: "cr-success",
1799
- titleClassName: "cr-success__title",
1800
- icon: /* @__PURE__ */ jsx(StateIcon, {
1801
- variant: "success",
1802
- children: /* @__PURE__ */ jsx(CheckIcon, { strokeWidth: 2 })
1803
- }),
1804
- title: "Enrollment Complete!",
1805
- body: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
1806
- className: "cr-success__message",
1807
- children: usedMembership ? membershipMessage : successMessage
1808
- }), usedMembership && /* @__PURE__ */ jsx("p", {
1809
- className: "cr-success__membership",
1810
- children: "Enrolled using your membership"
1811
- })] })
1949
+ function PricingFields({ wizard }) {
1950
+ if (!wizard.selectedRunPricing) return null;
1951
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(WholeSeriesPricingSelector, {
1952
+ pricing: wizard.selectedRunPricing,
1953
+ selectedPricingOptionId: wizard.selectedPricingOptionId,
1954
+ onSelect: wizard.choosePricingOption
1955
+ }), /* @__PURE__ */ jsx(WholeSeriesSlidingScaleInput, {
1956
+ pricing: wizard.selectedRunPricing,
1957
+ value: wizard.selectedSlidingAmountInput,
1958
+ onChange: wizard.changeSlidingAmount
1959
+ })] });
1960
+ }
1961
+ function RegistrationBookingModeStep({ wizard, display }) {
1962
+ const selection = selectedRunWithPricing(wizard);
1963
+ if (!selection) return null;
1964
+ const membershipMissing = wizard.bookingMode === "membership" && !wizard.selectedMembershipId;
1965
+ return /* @__PURE__ */ jsxs("div", {
1966
+ className: "er-whole-series-details",
1967
+ children: [
1968
+ /* @__PURE__ */ jsx(RunSummary, {
1969
+ run: selection.run,
1970
+ pricing: selection.pricing,
1971
+ showSessions: display.showSessions,
1972
+ showVenue: display.showVenue,
1973
+ showPrice: display.showPrice,
1974
+ showMembershipNote: false
1975
+ }),
1976
+ /* @__PURE__ */ jsx(BookingModeStep, {
1977
+ bookingMode: wizard.bookingMode,
1978
+ onBookingModeChange: wizard.handleBookingModeChange,
1979
+ eligibleMemberships: wizard.eligibleMemberships,
1980
+ selectedMembershipId: wizard.selectedMembershipId,
1981
+ onMembershipSelect: wizard.chooseMembership,
1982
+ priceCents: wizard.selectedRunPricing?.selectedPriceAmount ?? null,
1983
+ currency: selection.run.currency ?? "GBP"
1984
+ }),
1985
+ /* @__PURE__ */ jsxs("div", {
1986
+ className: "er-whole-series-actions",
1987
+ children: [/* @__PURE__ */ jsx(BackToDetailsButton, { wizard }), /* @__PURE__ */ jsx("button", {
1988
+ type: "button",
1989
+ className: buttonClass(display.buttonVariant),
1990
+ onClick: wizard.handlePaymentContinue,
1991
+ disabled: !wizard.bookingMode || membershipMissing,
1992
+ children: wizard.bookingMode === "membership" ? "Book run" : "Continue to payment"
1993
+ })]
1994
+ })
1995
+ ]
1996
+ });
1997
+ }
1998
+ function RegistrationPaymentStep({ wizard, display }) {
1999
+ const selection = selectedRunWithPricing(wizard);
2000
+ if (!selection) return null;
2001
+ return /* @__PURE__ */ jsxs("div", {
2002
+ className: "er-whole-series-details",
2003
+ children: [/* @__PURE__ */ jsx(RunSummary, {
2004
+ run: selection.run,
2005
+ pricing: selection.pricing,
2006
+ showSessions: display.showSessions,
2007
+ showVenue: display.showVenue,
2008
+ showPrice: display.showPrice,
2009
+ showMembershipNote: false
2010
+ }), /* @__PURE__ */ jsxs("div", {
2011
+ className: "er-whole-series-form",
2012
+ children: [
2013
+ /* @__PURE__ */ jsx(PaymentChoices, { wizard }),
2014
+ /* @__PURE__ */ jsx(DiscountFields, { wizard }),
2015
+ /* @__PURE__ */ jsxs("div", {
2016
+ className: "er-whole-series-actions",
2017
+ children: [/* @__PURE__ */ jsx(BackToDetailsButton, { wizard }), /* @__PURE__ */ jsx("button", {
2018
+ type: "button",
2019
+ className: buttonClass(display.buttonVariant),
2020
+ onClick: wizard.handlePaymentContinue,
2021
+ children: "Continue"
2022
+ })]
2023
+ })
2024
+ ]
2025
+ })]
2026
+ });
2027
+ }
2028
+ function PaymentChoices({ wizard }) {
2029
+ return /* @__PURE__ */ jsxs("fieldset", {
2030
+ className: "er-whole-series-form__field",
2031
+ children: [/* @__PURE__ */ jsx("legend", {
2032
+ className: "er-whole-series-form__label",
2033
+ children: "Choose how to book"
2034
+ }), /* @__PURE__ */ jsxs("div", {
2035
+ className: "er-whole-series-payment__options",
2036
+ children: [
2037
+ /* @__PURE__ */ jsx(PaymentChoice, {
2038
+ checked: wizard.paymentChoice === "membership",
2039
+ label: "Use a membership (free)",
2040
+ onChange: () => wizard.choosePaymentChoice("membership")
2041
+ }),
2042
+ wizard.paymentChoice === "membership" && wizard.eligibleMemberships.length > 1 ? /* @__PURE__ */ jsx(MembershipSelect, { wizard }) : null,
2043
+ /* @__PURE__ */ jsx(PaymentChoice, {
2044
+ checked: wizard.paymentChoice === "checkout",
2045
+ label: "Pay by card",
2046
+ onChange: () => wizard.choosePaymentChoice("checkout")
2047
+ })
2048
+ ]
2049
+ })]
2050
+ });
2051
+ }
2052
+ function PaymentChoice({ checked, label, onChange }) {
2053
+ return /* @__PURE__ */ jsxs("label", {
2054
+ className: "er-whole-series-payment__option",
2055
+ children: [/* @__PURE__ */ jsx("input", {
2056
+ type: "radio",
2057
+ name: "paymentChoice",
2058
+ checked,
2059
+ onChange
2060
+ }), /* @__PURE__ */ jsx("span", { children: label })]
2061
+ });
2062
+ }
2063
+ function MembershipSelect({ wizard }) {
2064
+ return /* @__PURE__ */ jsxs("div", {
2065
+ className: "er-whole-series-form__field",
2066
+ children: [/* @__PURE__ */ jsx("label", {
2067
+ htmlFor: "er-whole-series-membership",
2068
+ className: "er-whole-series-form__label",
2069
+ children: "Membership"
2070
+ }), /* @__PURE__ */ jsxs("select", {
2071
+ id: "er-whole-series-membership",
2072
+ className: "er-whole-series-form__input",
2073
+ value: wizard.selectedMembershipId ?? "",
2074
+ onChange: (event) => wizard.chooseMembership(event.target.value || null),
2075
+ children: [/* @__PURE__ */ jsx("option", {
2076
+ value: "",
2077
+ disabled: true,
2078
+ children: "Select a membership…"
2079
+ }), wizard.eligibleMemberships.map((membership) => /* @__PURE__ */ jsx("option", {
2080
+ value: membership.customerMembershipId,
2081
+ children: membership.membershipName
2082
+ }, membership.customerMembershipId))]
2083
+ })]
2084
+ });
2085
+ }
2086
+ function DiscountFields({ wizard }) {
2087
+ if (!canShowDiscount(wizard)) return null;
2088
+ return /* @__PURE__ */ jsx(DiscountCodeDisclosure, {
2089
+ surface: "whole-series-registration",
2090
+ isOpen: wizard.discountUiOpen,
2091
+ code: wizard.discountCode,
2092
+ onOpen: () => wizard.setDiscountUiOpen(true),
2093
+ onChange: wizard.setDiscountCode,
2094
+ onRemove: () => {
2095
+ wizard.setDiscountCode("");
2096
+ wizard.setDiscountUiOpen(false);
2097
+ },
2098
+ id: "er-whole-series-discount-code"
2099
+ });
2100
+ }
2101
+ function deriveDetailsBlockers(wizard) {
2102
+ const soldOut = wizard.waitlistClaim.claim === null && wizard.runEligibility?.isFull === true && wizard.runEligibility.canJoinWaitlist !== true;
2103
+ const missingPricing = wizard.selectedRunPricing?.requiresSelection === true && !wizard.selectedRunPricing.selectedOption && !wizard.selectedRunPricing.slidingScale;
2104
+ const slidingScaleMessage = slidingScaleBlocker(wizard.selectedRunPricing);
2105
+ const pricingUnavailable = wizard.selectedRunPricing?.display.kind === "unavailable";
2106
+ return {
2107
+ disabled: soldOut || wizard.eligibilityLoading || missingPricing || slidingScaleMessage !== null || pricingUnavailable,
2108
+ soldOut,
2109
+ missingPricing,
2110
+ slidingScaleMessage,
2111
+ pricingUnavailable
2112
+ };
2113
+ }
2114
+ function DetailsBlockerMessages({ wizard, blockers }) {
2115
+ return /* @__PURE__ */ jsxs(Fragment, { children: [[
2116
+ blockers.soldOut ? "This run is fully booked and there is no waitlist available right now." : null,
2117
+ blockers.missingPricing ? "Choose a pricing option to continue." : null,
2118
+ blockers.slidingScaleMessage,
2119
+ blockers.pricingUnavailable ? "Pricing is not available for this run right now." : null
2120
+ ].filter((message) => message !== null).map((message) => /* @__PURE__ */ jsx("p", {
2121
+ className: "er-whole-series-text er-whole-series-text--muted",
2122
+ children: message
2123
+ }, message)), wizard.eligibilityError ? /* @__PURE__ */ jsx("p", {
2124
+ className: "er-whole-series-text er-whole-series-text--error",
2125
+ children: wizard.eligibilityError
2126
+ }) : null] });
2127
+ }
2128
+ function BackToRunsButton({ wizard, compact = false }) {
2129
+ if (wizard.scopedRuns.length <= 1) return null;
2130
+ const button = /* @__PURE__ */ jsx("button", {
2131
+ type: "button",
2132
+ onClick: () => wizard.goToStep("select-run"),
2133
+ className: "er-whole-series-back-btn",
2134
+ children: "← Back"
2135
+ });
2136
+ return compact ? button : /* @__PURE__ */ jsx("div", {
2137
+ className: "er-whole-series-actions",
2138
+ children: button
2139
+ });
2140
+ }
2141
+ function BackToDetailsButton({ wizard }) {
2142
+ return /* @__PURE__ */ jsx("button", {
2143
+ type: "button",
2144
+ onClick: () => wizard.goToStep("enter-details"),
2145
+ className: "er-whole-series-back-btn",
2146
+ children: "← Back"
2147
+ });
2148
+ }
2149
+ function selectedRunWithPricing(wizard) {
2150
+ return wizard.selectedRun && wizard.selectedRunPricing ? {
2151
+ run: wizard.selectedRun,
2152
+ pricing: wizard.selectedRunPricing
2153
+ } : null;
2154
+ }
2155
+ function canShowDiscount(wizard) {
2156
+ return !wizard.discountsAvailableLoading && wizard.paymentChoice === "checkout" && wizard.discountsAvailable && wizard.manualCodeEntryAllowed;
2157
+ }
2158
+ function slidingScaleBlocker(pricing) {
2159
+ if (!pricing?.slidingScale) return null;
2160
+ if (pricing.selectedSlidingAmount === null) return "Choose an amount to continue.";
2161
+ return pricing.selectedSlidingAmount < pricing.slidingScale.minAmount || pricing.selectedSlidingAmount > pricing.slidingScale.maxAmount ? "Choose an amount within the sliding scale." : null;
2162
+ }
2163
+ function detailsSubmitLabel(wizard, buttonText, soldOut) {
2164
+ if (wizard.eligibilityLoading) return "Checking availability…";
2165
+ if (soldOut) return "Sold out";
2166
+ return wizard.runEligibility?.canJoinWaitlist ? "Join waitlist" : buttonText;
2167
+ }
2168
+ function buttonClass(variant) {
2169
+ return themeButtonClassName({
2170
+ variant: variant ?? "primary",
2171
+ size: "md"
1812
2172
  });
1813
2173
  }
1814
2174
  //#endregion
1815
- //#region ../blocks/src/system/runtime/nodes/course-registration/ErrorStep.tsx
2175
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/ErrorStep.tsx
1816
2176
  /**
1817
2177
  * Error terminal state component.
1818
2178
  * Shows error message with retry option.
@@ -1824,18 +2184,18 @@ function ErrorStep({ message, buttonText = "Try Again", buttonVariant = "primary
1824
2184
  });
1825
2185
  return /* @__PURE__ */ jsx(TerminalPanel, {
1826
2186
  tone: "error",
1827
- className: "cr-error",
1828
- titleClassName: "cr-error__title",
2187
+ className: "er-whole-series-error",
2188
+ titleClassName: "er-whole-series-error__title",
1829
2189
  icon: /* @__PURE__ */ jsx(StateIcon, {
1830
2190
  variant: "error",
1831
2191
  children: /* @__PURE__ */ jsx(CrossIcon, {})
1832
2192
  }),
1833
2193
  title: "Enrollment Failed",
1834
2194
  body: /* @__PURE__ */ jsx("p", {
1835
- className: "cr-error__message",
2195
+ className: "er-whole-series-error__message",
1836
2196
  children: message
1837
2197
  }),
1838
- actionsClassName: "cr-error__retry",
2198
+ actionsClassName: "er-whole-series-error__retry",
1839
2199
  actions: /* @__PURE__ */ jsx("button", {
1840
2200
  type: "button",
1841
2201
  onClick: onRetry,
@@ -1845,32 +2205,7 @@ function ErrorStep({ message, buttonText = "Try Again", buttonVariant = "primary
1845
2205
  });
1846
2206
  }
1847
2207
  //#endregion
1848
- //#region ../blocks/src/system/runtime/nodes/course-registration/WaitlistStep.tsx
1849
- /**
1850
- * Waitlist terminal state component.
1851
- * Shows confirmation when user is added to waitlist.
1852
- */
1853
- function WaitlistStep({ message, position }) {
1854
- return /* @__PURE__ */ jsx(TerminalPanel, {
1855
- tone: "info",
1856
- className: "cr-waitlist",
1857
- titleClassName: "cr-waitlist__title",
1858
- icon: /* @__PURE__ */ jsx(StateIcon, {
1859
- variant: "waitlist",
1860
- children: /* @__PURE__ */ jsx(ClockIcon, {})
1861
- }),
1862
- title: "Added to Waitlist",
1863
- body: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
1864
- className: "cr-waitlist__message",
1865
- children: message
1866
- }), typeof position === "number" && /* @__PURE__ */ jsxs("p", {
1867
- className: "cr-waitlist__position",
1868
- children: ["Your position: #", position]
1869
- })] })
1870
- });
1871
- }
1872
- //#endregion
1873
- //#region ../blocks/src/system/runtime/nodes/course-registration/PaymentFailedStep.tsx
2208
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/PaymentFailedStep.tsx
1874
2209
  /**
1875
2210
  * Payment failed terminal state component.
1876
2211
  * Shows when payment could not be processed.
@@ -1882,18 +2217,18 @@ function PaymentFailedStep({ message = "Your payment could not be processed.", b
1882
2217
  });
1883
2218
  return /* @__PURE__ */ jsx(TerminalPanel, {
1884
2219
  tone: "error",
1885
- className: "cr-payment-failed",
1886
- titleClassName: "cr-payment-failed__title",
2220
+ className: "er-whole-series-payment-failed",
2221
+ titleClassName: "er-whole-series-payment-failed__title",
1887
2222
  icon: /* @__PURE__ */ jsx(StateIcon, {
1888
2223
  variant: "error",
1889
2224
  children: /* @__PURE__ */ jsx(CrossIcon, {})
1890
2225
  }),
1891
2226
  title: "Payment Failed",
1892
2227
  body: /* @__PURE__ */ jsx("p", {
1893
- className: "cr-payment-failed__message",
2228
+ className: "er-whole-series-payment-failed__message",
1894
2229
  children: message
1895
2230
  }),
1896
- actionsClassName: "cr-payment-failed__retry",
2231
+ actionsClassName: "er-whole-series-payment-failed__retry",
1897
2232
  actions: /* @__PURE__ */ jsx("button", {
1898
2233
  type: "button",
1899
2234
  onClick: onRetry,
@@ -1903,7 +2238,32 @@ function PaymentFailedStep({ message = "Your payment could not be processed.", b
1903
2238
  });
1904
2239
  }
1905
2240
  //#endregion
1906
- //#region ../blocks/src/system/runtime/nodes/course-registration/VerifyingTimeoutStep.tsx
2241
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/SuccessStep.tsx
2242
+ /**
2243
+ * Success terminal state component.
2244
+ * Shows confirmation after successful enrollment.
2245
+ */
2246
+ function SuccessStep({ usedMembership, successMessage, membershipMessage }) {
2247
+ return /* @__PURE__ */ jsx(TerminalPanel, {
2248
+ tone: "success",
2249
+ className: "er-whole-series-success",
2250
+ titleClassName: "er-whole-series-success__title",
2251
+ icon: /* @__PURE__ */ jsx(StateIcon, {
2252
+ variant: "success",
2253
+ children: /* @__PURE__ */ jsx(CheckIcon, { strokeWidth: 2 })
2254
+ }),
2255
+ title: "Enrollment Complete!",
2256
+ body: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
2257
+ className: "er-whole-series-success__message",
2258
+ children: usedMembership ? membershipMessage : successMessage
2259
+ }), usedMembership && /* @__PURE__ */ jsx("p", {
2260
+ className: "er-whole-series-success__membership",
2261
+ children: "Enrolled using your membership"
2262
+ })] })
2263
+ });
2264
+ }
2265
+ //#endregion
2266
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/VerifyingTimeoutStep.tsx
1907
2267
  /**
1908
2268
  * Verifying timeout terminal state component.
1909
2269
  * Shows when payment verification takes too long.
@@ -1915,18 +2275,18 @@ function VerifyingTimeoutStep({ buttonText = "Check Again", buttonVariant = "pri
1915
2275
  });
1916
2276
  return /* @__PURE__ */ jsx(TerminalPanel, {
1917
2277
  tone: "warning",
1918
- className: "cr-error",
1919
- titleClassName: "cr-error__title",
2278
+ className: "er-whole-series-error",
2279
+ titleClassName: "er-whole-series-error__title",
1920
2280
  icon: /* @__PURE__ */ jsx(StateIcon, {
1921
2281
  variant: "warning",
1922
2282
  children: /* @__PURE__ */ jsx(ClockIcon, {})
1923
2283
  }),
1924
2284
  title: "Payment Verification Taking Longer",
1925
2285
  body: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
1926
- className: "cr-error__message",
2286
+ className: "er-whole-series-error__message",
1927
2287
  children: "Your payment may still be processing. Please check your email for confirmation."
1928
2288
  }), supportEmail && /* @__PURE__ */ jsxs("p", {
1929
- className: "cr-error__message",
2289
+ className: "er-whole-series-error__message",
1930
2290
  children: [
1931
2291
  "If you need help, contact us at",
1932
2292
  " ",
@@ -1936,7 +2296,7 @@ function VerifyingTimeoutStep({ buttonText = "Check Again", buttonVariant = "pri
1936
2296
  })
1937
2297
  ]
1938
2298
  })] }),
1939
- actionsClassName: "cr-error__retry",
2299
+ actionsClassName: "er-whole-series-error__retry",
1940
2300
  actions: /* @__PURE__ */ jsx("button", {
1941
2301
  type: "button",
1942
2302
  onClick: onCheckAgain,
@@ -1946,388 +2306,191 @@ function VerifyingTimeoutStep({ buttonText = "Check Again", buttonVariant = "pri
1946
2306
  });
1947
2307
  }
1948
2308
  //#endregion
1949
- //#region ../blocks/src/system/runtime/nodes/course-registration/CourseRegistrationWizard.tsx
1950
- function getCourseSlidingScaleMessage(pricing) {
1951
- if (!pricing.slidingScale) return null;
1952
- const selectedAmount = pricing.selectedSlidingAmount;
1953
- if (selectedAmount === null) return "Choose an amount to continue.";
1954
- if (selectedAmount < pricing.slidingScale.minAmount || selectedAmount > pricing.slidingScale.maxAmount) return "Choose an amount within the sliding scale.";
1955
- return null;
1956
- }
1957
- function CourseRegistrationWizard(props) {
1958
- const { showSessions = true, showPrice = true, showCapacity = true, showVenue = true, successMessage = "You're booked in! Check your email for confirmation and session details.", waitlistMessage = "You've been added to the waitlist. We'll email you a claim link if a spot opens up.", membershipMessage = "Booked using your membership! Check your email for session details.", buttonText = "Sign up", buttonVariant = "primary", className } = props;
1959
- const { api, scopedCourses, step, goToStep, selectedCourse, selectedPricingOptionId, choosePricingOption, selectedSlidingAmountInput, changeSlidingAmount, selectedCoursePricing, formData, updateFormData, errors, enrollmentResult, errorMessage, portalAuthState, handleLogout, altchaSolution: _altchaSolution, setAltchaSolution, showSpamProtection, eligibilityLoading, eligibilityError, courseEligibility, eligibleMemberships, paymentChoice, choosePaymentChoice, selectedMembershipId, chooseMembership, discountUiOpen, setDiscountUiOpen, discountCode, setDiscountCode, discountsAvailable, manualCodeEntryAllowed, discountsAvailableLoading, waitlistClaim, canUseMembership: _canUseMembership, bookingMode, currentStepNumber, totalSteps, stepLabels, showPortalAuthSidebar, hasPreSelectedCourse: _hasPreSelectedCourse, hasCoursePayment: _hasCoursePayment, handleCourseSelect, handleSubmit, handlePaymentContinue, handleRetry, handleBookingModeChange } = useCourseRegistrationWizard(props);
1960
- const buttonClass = themeButtonClassName({
1961
- variant: buttonVariant,
1962
- size: "md"
2309
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/WaitlistStep.tsx
2310
+ /**
2311
+ * Waitlist terminal state component.
2312
+ * Shows confirmation when user is added to waitlist.
2313
+ */
2314
+ function WaitlistStep({ message, position }) {
2315
+ return /* @__PURE__ */ jsx(TerminalPanel, {
2316
+ tone: "info",
2317
+ className: "er-whole-series-waitlist",
2318
+ titleClassName: "er-whole-series-waitlist__title",
2319
+ icon: /* @__PURE__ */ jsx(StateIcon, {
2320
+ variant: "waitlist",
2321
+ children: /* @__PURE__ */ jsx(ClockIcon, {})
2322
+ }),
2323
+ title: "Added to Waitlist",
2324
+ body: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
2325
+ className: "er-whole-series-waitlist__message",
2326
+ children: message
2327
+ }), typeof position === "number" && /* @__PURE__ */ jsxs("p", {
2328
+ className: "er-whole-series-waitlist__position",
2329
+ children: ["Your position: #", position]
2330
+ })] })
1963
2331
  });
1964
- if (scopedCourses.length === 0) {
1965
- const awaitingOfferingRuns = props.subject?.kind === "eventOffering" && props.subject.availableEventSeriesIds.length === 0;
1966
- return /* @__PURE__ */ jsx("div", {
1967
- id: COURSE_REGISTRATION_ANCHOR_ID,
1968
- className: `course-registration ${className || ""}`,
1969
- "data-block": "course-registration",
1970
- children: /* @__PURE__ */ jsx("div", {
1971
- className: "cr-empty",
1972
- children: /* @__PURE__ */ jsx("p", {
1973
- className: "cr-empty__text",
1974
- children: awaitingOfferingRuns ? "New dates are coming soon. Booking will open when the next run is ready." : "No courses available to book."
1975
- })
1976
- })
2332
+ }
2333
+ //#endregion
2334
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationTerminalContent.tsx
2335
+ function WholeSeriesRegistrationTerminalContent({ wizard, copy }) {
2336
+ switch (wizard.step) {
2337
+ case "submitting": return /* @__PURE__ */ jsx(PendingState, {
2338
+ label: "Booking run...",
2339
+ spinnerLabel: "Processing"
2340
+ });
2341
+ case "redirecting": return /* @__PURE__ */ jsx(PendingState, {
2342
+ label: "Redirecting to payment...",
2343
+ spinnerLabel: "Redirecting"
2344
+ });
2345
+ case "verifying-payment": return /* @__PURE__ */ jsx(PendingState, {
2346
+ label: "Verifying payment...",
2347
+ spinnerLabel: "Verifying payment"
1977
2348
  });
2349
+ case "verifying-timeout": return /* @__PURE__ */ jsx(VerifyingTimeoutStep, {
2350
+ buttonVariant: copy.buttonVariant,
2351
+ onCheckAgain: wizard.handleRetry
2352
+ });
2353
+ case "payment-failed": return /* @__PURE__ */ jsx(PaymentFailedStep, {
2354
+ message: wizard.errorMessage,
2355
+ buttonVariant: copy.buttonVariant,
2356
+ onRetry: wizard.handleRetry
2357
+ });
2358
+ case "success": return /* @__PURE__ */ jsx(SuccessStep, {
2359
+ usedMembership: wizard.enrollmentResult?.usedMembership,
2360
+ successMessage: copy.successMessage,
2361
+ membershipMessage: copy.membershipMessage
2362
+ });
2363
+ case "waitlist": return /* @__PURE__ */ jsx(WaitlistStep, {
2364
+ message: copy.waitlistMessage,
2365
+ position: wizard.enrollmentResult?.waitlistPosition
2366
+ });
2367
+ case "error": return /* @__PURE__ */ jsx(ErrorStep, {
2368
+ message: wizard.errorMessage,
2369
+ buttonVariant: copy.buttonVariant,
2370
+ onRetry: wizard.handleRetry
2371
+ });
2372
+ case "booking-mode":
2373
+ case "enter-details":
2374
+ case "select-payment":
2375
+ case "select-run": return null;
1978
2376
  }
1979
- const allowedStatuses = api.config.isPreview ? ["active", "draft"] : ["active"];
1980
- if (!scopedCourses.some((c) => !c.status || allowedStatuses.includes(c.status))) return /* @__PURE__ */ jsx("div", {
1981
- id: COURSE_REGISTRATION_ANCHOR_ID,
1982
- className: `course-registration ${className || ""}`,
1983
- "data-block": "course-registration",
2377
+ }
2378
+ function PendingState({ label, spinnerLabel }) {
2379
+ return /* @__PURE__ */ jsxs("div", {
2380
+ className: "er-whole-series-center",
2381
+ children: [/* @__PURE__ */ jsx(SpinnerNode, {
2382
+ size: "md",
2383
+ srLabel: spinnerLabel
2384
+ }), /* @__PURE__ */ jsx("p", {
2385
+ className: "er-whole-series-text--muted",
2386
+ children: label
2387
+ })]
2388
+ });
2389
+ }
2390
+ //#endregion
2391
+ //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationWizard.tsx
2392
+ const DEFAULT_COPY = {
2393
+ successMessage: "You're booked in! Check your email for confirmation and session details.",
2394
+ waitlistMessage: "You've been added to the waitlist. We'll email you a claim link if a spot opens up.",
2395
+ membershipMessage: "Booked using your membership! Check your email for session details.",
2396
+ buttonText: "Sign up"
2397
+ };
2398
+ function WholeSeriesRegistrationWizard(props) {
2399
+ const presentation = resolveWholeSeriesRegistrationPresentation(props.presentationKind ?? "event");
2400
+ const wizard = useWholeSeriesRegistrationWizard(props, { anchorId: presentation.anchorId });
2401
+ const className = `${presentation.rootClass} ${props.className ?? ""}`;
2402
+ const emptyMessage = resolveEmptyMessage(props, wizard);
2403
+ if (emptyMessage) return /* @__PURE__ */ jsx(RegistrationRoot, {
2404
+ className,
2405
+ presentation,
1984
2406
  children: /* @__PURE__ */ jsx("div", {
1985
- className: "cr-empty",
2407
+ className: "er-whole-series-empty",
1986
2408
  children: /* @__PURE__ */ jsx("p", {
1987
- className: "cr-empty__text",
1988
- children: "Booking is not currently available for this course."
2409
+ className: "er-whole-series-empty__text",
2410
+ children: emptyMessage
1989
2411
  })
1990
2412
  })
1991
2413
  });
1992
- const canShowDiscountUi = !discountsAvailableLoading && paymentChoice === "checkout" && discountsAvailable && manualCodeEntryAllowed;
1993
- const courseSoldOut = waitlistClaim.claim === null && courseEligibility?.isFull === true && courseEligibility.canJoinWaitlist !== true;
1994
- const detailsSubmitLabel = courseEligibility?.canJoinWaitlist ? "Join waitlist" : buttonText;
1995
- const pricingSelectionMissing = selectedCoursePricing?.requiresSelection === true && !selectedCoursePricing.selectedOption && !selectedCoursePricing.slidingScale;
1996
- const slidingScaleMessage = selectedCoursePricing ? getCourseSlidingScaleMessage(selectedCoursePricing) : null;
1997
- const pricingUnavailable = selectedCoursePricing?.display.kind === "unavailable";
1998
- const selectedCourseWithPricing = selectedCourse && selectedCoursePricing ? {
1999
- course: selectedCourse,
2000
- pricing: selectedCoursePricing
2001
- } : null;
2002
- const showStepIndicator = WIZARD_STEPS.includes(step) && totalSteps > 1;
2003
- const showSidebarLayout = showPortalAuthSidebar;
2004
- return /* @__PURE__ */ jsx("div", {
2005
- id: COURSE_REGISTRATION_ANCHOR_ID,
2006
- className: `course-registration ${className || ""}`,
2007
- "data-block": "course-registration",
2414
+ return /* @__PURE__ */ jsx(RegistrationWorkspace, {
2415
+ wizard,
2416
+ props,
2417
+ className,
2418
+ presentation
2419
+ });
2420
+ }
2421
+ function RegistrationWorkspace({ wizard, props, className, presentation }) {
2422
+ const display = resolveDisplayProps(props);
2423
+ const copy = resolveTerminalCopy(props);
2424
+ const showSidebar = wizard.showPortalAuthSidebar;
2425
+ return /* @__PURE__ */ jsx(RegistrationRoot, {
2426
+ className,
2427
+ presentation,
2008
2428
  children: /* @__PURE__ */ jsx("div", {
2009
- className: "rb-reg-surface cr-container",
2429
+ className: "rb-reg-surface er-whole-series-container",
2010
2430
  children: /* @__PURE__ */ jsxs("div", {
2011
- className: `cr-layout${showSidebarLayout ? " cr-layout--with-sidebar" : ""}`,
2431
+ className: `er-whole-series-layout${showSidebar ? " er-whole-series-layout--with-sidebar" : ""}`,
2012
2432
  children: [/* @__PURE__ */ jsxs("div", {
2013
- className: "cr-layout__main",
2433
+ className: "er-whole-series-layout__main",
2014
2434
  children: [
2015
- showStepIndicator && /* @__PURE__ */ jsx(StepIndicator, {
2016
- currentStep: currentStepNumber,
2017
- totalSteps,
2018
- stepLabels
2019
- }),
2020
- step === "select-course" && /* @__PURE__ */ jsx("div", {
2021
- className: "cr-course-list",
2022
- children: scopedCourses.map((course) => /* @__PURE__ */ jsx(CourseCard, {
2023
- course,
2024
- isSelected: selectedCourse?.eventSeriesId === course.eventSeriesId,
2025
- onSelect: () => handleCourseSelect(course),
2026
- showSessions,
2027
- showPrice,
2028
- showCapacity,
2029
- showVenue
2030
- }, course.eventSeriesId))
2031
- }),
2032
- step === "enter-details" && selectedCourseWithPricing && /* @__PURE__ */ jsxs("div", {
2033
- className: "cr-details",
2034
- children: [/* @__PURE__ */ jsx(CourseSummary, {
2035
- course: selectedCourseWithPricing.course,
2036
- pricing: selectedCourseWithPricing.pricing,
2037
- showSessions,
2038
- showVenue,
2039
- showPrice,
2040
- showMembershipNote: selectedCourseWithPricing.course.acceptsMemberships && portalAuthState === "authenticated"
2041
- }), selectedCourseWithPricing.course.enrollmentOpen === false ? /* @__PURE__ */ jsxs("div", {
2042
- className: "cr-form",
2043
- children: [scopedCourses.length > 1 && /* @__PURE__ */ jsx("div", {
2044
- className: "cr-actions",
2045
- children: /* @__PURE__ */ jsx("button", {
2046
- type: "button",
2047
- onClick: () => goToStep("select-course"),
2048
- className: "cr-back-btn",
2049
- children: "← Back"
2050
- })
2051
- }), /* @__PURE__ */ jsx("p", {
2052
- className: "cr-text cr-text--muted",
2053
- children: "Registration closed."
2054
- })]
2055
- }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2056
- /* @__PURE__ */ jsxs("form", {
2057
- className: "cr-form",
2058
- onSubmit: (e) => {
2059
- e.preventDefault();
2060
- handleSubmit();
2061
- },
2062
- children: [
2063
- /* @__PURE__ */ jsx(EnrollmentForm, {
2064
- formData,
2065
- errors,
2066
- onChange: updateFormData,
2067
- isEmailLocked: portalAuthState === "authenticated" || waitlistClaim.claim !== null,
2068
- isLoading: portalAuthState === "checking" || waitlistClaim.isLoading,
2069
- onLogout: handleLogout
2070
- }),
2071
- /* @__PURE__ */ jsx(CoursePricingSelector, {
2072
- pricing: selectedCourseWithPricing.pricing,
2073
- selectedPricingOptionId,
2074
- onSelect: choosePricingOption
2075
- }),
2076
- /* @__PURE__ */ jsx(CourseSlidingScaleInput, {
2077
- pricing: selectedCourseWithPricing.pricing,
2078
- value: selectedSlidingAmountInput,
2079
- onChange: changeSlidingAmount
2080
- }),
2081
- showSpamProtection && /* @__PURE__ */ jsx("div", {
2082
- className: "cr-altcha",
2083
- children: /* @__PURE__ */ jsx(AltchaWidget, {
2084
- challengeUrl: getChallengeUrl(),
2085
- onSolutionChange: setAltchaSolution
2086
- })
2087
- }),
2088
- canShowDiscountUi && /* @__PURE__ */ jsx(DiscountCodeDisclosure, {
2089
- surface: "course-registration",
2090
- isOpen: discountUiOpen,
2091
- code: discountCode,
2092
- onOpen: () => setDiscountUiOpen(true),
2093
- onChange: setDiscountCode,
2094
- onRemove: () => {
2095
- setDiscountCode("");
2096
- setDiscountUiOpen(false);
2097
- },
2098
- id: "cr-discount-code"
2099
- }),
2100
- /* @__PURE__ */ jsxs("div", {
2101
- className: "cr-actions",
2102
- children: [scopedCourses.length > 1 && /* @__PURE__ */ jsx("button", {
2103
- type: "button",
2104
- onClick: () => goToStep("select-course"),
2105
- className: "cr-back-btn",
2106
- children: "← Back"
2107
- }), /* @__PURE__ */ jsx("button", {
2108
- type: "submit",
2109
- className: buttonClass,
2110
- disabled: courseSoldOut || eligibilityLoading || pricingSelectionMissing || slidingScaleMessage !== null || pricingUnavailable,
2111
- children: eligibilityLoading ? "Checking availability…" : courseSoldOut ? "Sold out" : detailsSubmitLabel
2112
- })]
2113
- })
2114
- ]
2115
- }),
2116
- courseSoldOut && /* @__PURE__ */ jsx("p", {
2117
- className: "cr-text cr-text--muted",
2118
- children: "This course is fully booked and there is no waitlist available right now."
2119
- }),
2120
- pricingSelectionMissing && /* @__PURE__ */ jsx("p", {
2121
- className: "cr-text cr-text--muted",
2122
- children: "Choose a pricing option to continue."
2123
- }),
2124
- slidingScaleMessage && /* @__PURE__ */ jsx("p", {
2125
- className: "cr-text cr-text--muted",
2126
- children: slidingScaleMessage
2127
- }),
2128
- pricingUnavailable && /* @__PURE__ */ jsx("p", {
2129
- className: "cr-text cr-text--muted",
2130
- children: "Pricing is not available for this course right now."
2131
- }),
2132
- eligibilityError && /* @__PURE__ */ jsx("p", {
2133
- className: "cr-text cr-text--error",
2134
- children: eligibilityError
2135
- })
2136
- ] })]
2137
- }),
2138
- step === "booking-mode" && selectedCourseWithPricing && /* @__PURE__ */ jsxs("div", {
2139
- className: "cr-details",
2140
- children: [
2141
- /* @__PURE__ */ jsx(CourseSummary, {
2142
- course: selectedCourseWithPricing.course,
2143
- pricing: selectedCourseWithPricing.pricing,
2144
- showSessions,
2145
- showVenue,
2146
- showPrice,
2147
- showMembershipNote: false
2148
- }),
2149
- /* @__PURE__ */ jsx(BookingModeStep, {
2150
- bookingMode,
2151
- onBookingModeChange: handleBookingModeChange,
2152
- eligibleMemberships,
2153
- selectedMembershipId,
2154
- onMembershipSelect: chooseMembership,
2155
- priceCents: selectedCoursePricing?.selectedPriceAmount ?? null,
2156
- currency: selectedCourseWithPricing.course.currency ?? "GBP"
2157
- }),
2158
- /* @__PURE__ */ jsxs("div", {
2159
- className: "cr-actions",
2160
- children: [/* @__PURE__ */ jsx("button", {
2161
- type: "button",
2162
- onClick: () => goToStep("enter-details"),
2163
- className: "cr-back-btn",
2164
- children: "← Back"
2165
- }), /* @__PURE__ */ jsx("button", {
2166
- type: "button",
2167
- className: buttonClass,
2168
- onClick: handlePaymentContinue,
2169
- disabled: !bookingMode || bookingMode === "membership" && !selectedMembershipId,
2170
- children: bookingMode === "membership" ? "Book course" : "Continue to payment"
2171
- })]
2172
- })
2173
- ]
2174
- }),
2175
- step === "select-payment" && selectedCourseWithPricing && /* @__PURE__ */ jsxs("div", {
2176
- className: "cr-details",
2177
- children: [/* @__PURE__ */ jsx(CourseSummary, {
2178
- course: selectedCourseWithPricing.course,
2179
- pricing: selectedCourseWithPricing.pricing,
2180
- showSessions,
2181
- showVenue,
2182
- showPrice,
2183
- showMembershipNote: false
2184
- }), /* @__PURE__ */ jsxs("div", {
2185
- className: "cr-form",
2186
- children: [
2187
- /* @__PURE__ */ jsxs("div", {
2188
- className: "cr-form__field",
2189
- children: [/* @__PURE__ */ jsx("label", {
2190
- className: "cr-form__label",
2191
- children: "Choose how to book"
2192
- }), /* @__PURE__ */ jsxs("div", {
2193
- className: "cr-payment__options",
2194
- children: [
2195
- /* @__PURE__ */ jsxs("label", {
2196
- className: "cr-payment__option",
2197
- children: [/* @__PURE__ */ jsx("input", {
2198
- type: "radio",
2199
- name: "paymentChoice",
2200
- checked: paymentChoice === "membership",
2201
- onChange: () => choosePaymentChoice("membership")
2202
- }), /* @__PURE__ */ jsx("span", { children: "Use a membership (free)" })]
2203
- }),
2204
- paymentChoice === "membership" && eligibleMemberships.length > 1 && /* @__PURE__ */ jsxs("div", {
2205
- className: "cr-form__field",
2206
- children: [/* @__PURE__ */ jsx("label", {
2207
- htmlFor: "cr-membership",
2208
- className: "cr-form__label",
2209
- children: "Membership"
2210
- }), /* @__PURE__ */ jsxs("select", {
2211
- id: "cr-membership",
2212
- className: "cr-form__input",
2213
- value: selectedMembershipId ?? "",
2214
- onChange: (e) => chooseMembership(e.target.value || null),
2215
- children: [/* @__PURE__ */ jsx("option", {
2216
- value: "",
2217
- disabled: true,
2218
- children: "Select a membership…"
2219
- }), eligibleMemberships.map((m) => /* @__PURE__ */ jsx("option", {
2220
- value: m.customerMembershipId,
2221
- children: m.membershipName
2222
- }, m.customerMembershipId))]
2223
- })]
2224
- }),
2225
- /* @__PURE__ */ jsxs("label", {
2226
- className: "cr-payment__option",
2227
- children: [/* @__PURE__ */ jsx("input", {
2228
- type: "radio",
2229
- name: "paymentChoice",
2230
- checked: paymentChoice === "checkout",
2231
- onChange: () => choosePaymentChoice("checkout")
2232
- }), /* @__PURE__ */ jsx("span", { children: "Pay by card" })]
2233
- })
2234
- ]
2235
- })]
2236
- }),
2237
- canShowDiscountUi && /* @__PURE__ */ jsx(DiscountCodeDisclosure, {
2238
- surface: "course-registration",
2239
- isOpen: discountUiOpen,
2240
- code: discountCode,
2241
- onOpen: () => setDiscountUiOpen(true),
2242
- onChange: setDiscountCode,
2243
- onRemove: () => {
2244
- setDiscountCode("");
2245
- setDiscountUiOpen(false);
2246
- },
2247
- id: "cr-discount-code"
2248
- }),
2249
- /* @__PURE__ */ jsxs("div", {
2250
- className: "cr-actions",
2251
- children: [/* @__PURE__ */ jsx("button", {
2252
- type: "button",
2253
- onClick: () => goToStep("enter-details"),
2254
- className: "cr-back-btn",
2255
- children: "← Back"
2256
- }), /* @__PURE__ */ jsx("button", {
2257
- type: "button",
2258
- className: buttonClass,
2259
- onClick: handlePaymentContinue,
2260
- children: "Continue"
2261
- })]
2262
- })
2263
- ]
2264
- })]
2435
+ WIZARD_STEPS.includes(wizard.step) && wizard.totalSteps > 1 ? /* @__PURE__ */ jsx(StepIndicator, {
2436
+ currentStep: wizard.currentStepNumber,
2437
+ totalSteps: wizard.totalSteps,
2438
+ stepLabels: wizard.stepLabels
2439
+ }) : null,
2440
+ /* @__PURE__ */ jsx(WholeSeriesRegistrationActiveStep, {
2441
+ wizard,
2442
+ display
2265
2443
  }),
2266
- step === "submitting" && /* @__PURE__ */ jsxs("div", {
2267
- className: "cr-center",
2268
- children: [/* @__PURE__ */ jsx(SpinnerNode, {
2269
- size: "md",
2270
- srLabel: "Processing"
2271
- }), /* @__PURE__ */ jsx("p", {
2272
- className: "cr-text--muted",
2273
- children: "Booking course..."
2274
- })]
2275
- }),
2276
- step === "redirecting" && /* @__PURE__ */ jsxs("div", {
2277
- className: "cr-center",
2278
- children: [/* @__PURE__ */ jsx(SpinnerNode, {
2279
- size: "md",
2280
- srLabel: "Redirecting"
2281
- }), /* @__PURE__ */ jsx("p", {
2282
- className: "cr-text--muted",
2283
- children: "Redirecting to payment..."
2284
- })]
2285
- }),
2286
- step === "verifying-payment" && /* @__PURE__ */ jsxs("div", {
2287
- className: "cr-center",
2288
- children: [/* @__PURE__ */ jsx(SpinnerNode, {
2289
- size: "md",
2290
- srLabel: "Verifying payment"
2291
- }), /* @__PURE__ */ jsx("p", {
2292
- className: "cr-text--muted",
2293
- children: "Verifying payment..."
2294
- })]
2295
- }),
2296
- step === "verifying-timeout" && /* @__PURE__ */ jsx(VerifyingTimeoutStep, {
2297
- buttonVariant,
2298
- onCheckAgain: handleRetry
2299
- }),
2300
- step === "payment-failed" && /* @__PURE__ */ jsx(PaymentFailedStep, {
2301
- message: errorMessage,
2302
- buttonVariant,
2303
- onRetry: handleRetry
2304
- }),
2305
- step === "success" && /* @__PURE__ */ jsx(SuccessStep, {
2306
- usedMembership: enrollmentResult?.usedMembership,
2307
- successMessage,
2308
- membershipMessage
2309
- }),
2310
- step === "waitlist" && /* @__PURE__ */ jsx(WaitlistStep, {
2311
- message: waitlistMessage,
2312
- position: enrollmentResult?.waitlistPosition
2313
- }),
2314
- step === "error" && /* @__PURE__ */ jsx(ErrorStep, {
2315
- message: errorMessage,
2316
- buttonVariant,
2317
- onRetry: handleRetry
2444
+ /* @__PURE__ */ jsx(WholeSeriesRegistrationTerminalContent, {
2445
+ wizard,
2446
+ copy
2318
2447
  })
2319
2448
  ]
2320
- }), showSidebarLayout && /* @__PURE__ */ jsx("div", {
2321
- className: "cr-layout__sidebar",
2322
- children: /* @__PURE__ */ jsx(PortalAuthSidebar, {
2323
- autoOpen: waitlistClaim.requiresPortalLogin,
2324
- loginMessage: waitlistClaim.loginMessage,
2325
- variant: waitlistClaim.requiresPortalLogin ? "waitlist-claim" : "membership"
2326
- })
2327
- })]
2449
+ }), showSidebar ? /* @__PURE__ */ jsx(RegistrationSidebar, { wizard }) : null]
2328
2450
  })
2329
2451
  })
2330
2452
  });
2331
2453
  }
2454
+ function resolveDisplayProps(props) {
2455
+ return {
2456
+ showSessions: props.showSessions ?? true,
2457
+ showPrice: props.showPrice ?? true,
2458
+ showCapacity: props.showCapacity ?? true,
2459
+ showVenue: props.showVenue ?? true,
2460
+ buttonText: props.buttonText ?? DEFAULT_COPY.buttonText,
2461
+ buttonVariant: props.buttonVariant
2462
+ };
2463
+ }
2464
+ function resolveTerminalCopy(props) {
2465
+ return {
2466
+ successMessage: props.successMessage ?? DEFAULT_COPY.successMessage,
2467
+ waitlistMessage: props.waitlistMessage ?? DEFAULT_COPY.waitlistMessage,
2468
+ membershipMessage: props.membershipMessage ?? DEFAULT_COPY.membershipMessage,
2469
+ buttonVariant: props.buttonVariant
2470
+ };
2471
+ }
2472
+ function RegistrationRoot({ children, className, presentation }) {
2473
+ return /* @__PURE__ */ jsx("div", {
2474
+ id: presentation.anchorId,
2475
+ className,
2476
+ "data-block": presentation.dataBlock,
2477
+ children
2478
+ });
2479
+ }
2480
+ function RegistrationSidebar({ wizard }) {
2481
+ return /* @__PURE__ */ jsx("div", {
2482
+ className: "er-whole-series-layout__sidebar",
2483
+ children: /* @__PURE__ */ jsx(PortalAuthSidebar, {
2484
+ autoOpen: wizard.waitlistClaim.requiresPortalLogin,
2485
+ loginMessage: wizard.waitlistClaim.loginMessage,
2486
+ variant: wizard.waitlistClaim.requiresPortalLogin ? "waitlist-claim" : "membership"
2487
+ })
2488
+ });
2489
+ }
2490
+ function resolveEmptyMessage(props, wizard) {
2491
+ if (wizard.scopedRuns.length === 0) return props.subject?.kind === "eventOffering" && props.subject.availableEventSeriesIds.length === 0 ? "New dates are coming soon. Booking will open when the next run is ready." : "No runs available to book.";
2492
+ const allowedStatuses = wizard.api.config.isPreview ? ["active", "draft"] : ["active"];
2493
+ return wizard.scopedRuns.some((run) => !run.status || allowedStatuses.includes(run.status)) ? null : "Booking is not currently available for this run.";
2494
+ }
2332
2495
  //#endregion
2333
- export { LoggedInAsUser as a, useWaitlistClaim as i, MagicLinkForm as n, CourseRegistrationErrorBoundary as o, logoutPortal as r, ClockIcon as s, CourseRegistrationWizard as t };
2496
+ export { MagicLinkForm as a, useWaitlistClaim as i, LoggedInAsUser as n, WholeSeriesRegistrationErrorBoundary as o, logoutPortal as r, ClockIcon as s, WholeSeriesRegistrationWizard as t };