@riverbankcms/sdk 0.136.0 → 0.138.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 (343) hide show
  1. package/CHANGELOG.md +109 -0
  2. package/README.md +7 -4
  3. package/dist/{PreviewEditorSidebar-BU5ZlhQR.mjs → PreviewEditorSidebar-BVPur_CU.mjs} +12 -18
  4. package/dist/{PreviewEditorUI-9XkHL-bC.mjs → PreviewEditorUI-DLhWX8oh.mjs} +3 -3
  5. package/dist/{PreviewQueryProvider-wbEpXryy.mjs → PreviewQueryProvider-BguJY1SW.mjs} +1 -1
  6. package/dist/{SdkPreviewModeRuntime-CnWmj-2B.mjs → SdkPreviewModeRuntime-Tda6qw4z.mjs} +1375 -495
  7. package/dist/{SiteChromeCustomizeContext-B6d5zkog.mjs → SiteChromeCustomizeContext-BHFgMjde.mjs} +35665 -33602
  8. package/dist/_dts/ai/src/contracts/proposals.d.ts +7226 -3057
  9. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +1223 -811
  10. package/dist/_dts/ai/src/designer/themePatch.d.ts +5 -10
  11. package/dist/_dts/api/src/accessAdmin.d.ts +16 -18
  12. package/dist/_dts/api/src/accountApi.d.ts +49 -2
  13. package/dist/_dts/api/src/appointmentServiceContracts.d.ts +83 -0
  14. package/dist/_dts/api/src/appointmentServiceLocation.d.ts +12 -0
  15. package/dist/_dts/api/src/appointmentServiceVisibility.d.ts +14 -0
  16. package/dist/_dts/api/src/appointmentSetup.d.ts +8 -0
  17. package/dist/_dts/api/src/bookingConfig.d.ts +35 -87
  18. package/dist/_dts/api/src/bookingManagementEndpoints.d.ts +1 -1
  19. package/dist/_dts/api/src/bookingOperations.d.ts +2 -69
  20. package/dist/_dts/api/src/bookingRecords.d.ts +2 -2
  21. package/dist/_dts/api/src/bookingRefundOutcomes.d.ts +2 -2
  22. package/dist/_dts/api/src/bookingServicePricing.d.ts +47 -0
  23. package/dist/_dts/api/src/bookings.d.ts +2 -2
  24. package/dist/_dts/api/src/cache-tags.d.ts +7 -2
  25. package/dist/_dts/api/src/common/index.d.ts +1 -0
  26. package/dist/_dts/api/src/common/zodFieldErrors.d.ts +34 -0
  27. package/dist/_dts/api/src/communications.d.ts +14 -8
  28. package/dist/_dts/api/src/contentRuntime.d.ts +3 -6
  29. package/dist/_dts/api/src/domainConnection.d.ts +41 -0
  30. package/dist/_dts/api/src/endpoints.d.ts +1636 -1637
  31. package/dist/_dts/api/src/eventAttendanceLabels.d.ts +2 -2
  32. package/dist/_dts/api/src/eventManagementContracts.d.ts +10 -14
  33. package/dist/_dts/api/src/index.d.ts +11 -9
  34. package/dist/_dts/api/src/indexCoreTypes.d.ts +1 -1
  35. package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -1
  36. package/dist/_dts/api/src/media.d.ts +19 -2
  37. package/dist/_dts/api/src/occurrenceScheduling.d.ts +1 -1
  38. package/dist/_dts/api/src/participantMessaging.d.ts +3 -3
  39. package/dist/_dts/api/src/public/endpoints.d.ts +1 -1
  40. package/dist/_dts/api/src/publicBookingAvailabilityEndpointDefinitions.d.ts +62 -0
  41. package/dist/_dts/api/src/publicBookingService.d.ts +109 -2
  42. package/dist/_dts/api/src/publicEventCheckoutEndpointDefinitions.d.ts +27 -0
  43. package/dist/_dts/api/src/publicEventEndpointDefinitions.d.ts +7 -0
  44. package/dist/_dts/api/src/publicExperience/commerceEndpoints.d.ts +2 -1
  45. package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +30 -148
  46. package/dist/_dts/api/src/publicExperience/sharedTypes.d.ts +8 -26
  47. package/dist/_dts/api/src/publicExperience/siteEndpoints.d.ts +5 -13
  48. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +2 -3
  49. package/dist/_dts/api/src/schemas/admin-allowed-domains.d.ts +76 -0
  50. package/dist/_dts/api/src/schemas/admin-observability-logs.d.ts +61 -0
  51. package/dist/_dts/api/src/schemas/admin-users.d.ts +80 -0
  52. package/dist/_dts/api/src/schemas/newsletter-memberships.d.ts +98 -0
  53. package/dist/_dts/api/src/schemas/sdk-entries.d.ts +128 -0
  54. package/dist/_dts/api/src/schemas/site-api-keys.d.ts +112 -0
  55. package/dist/_dts/api/src/schemas/support.d.ts +35 -0
  56. package/dist/_dts/api/src/sdk-event-booking-offer.d.ts +14 -0
  57. package/dist/_dts/api/src/sdk-event-payment-terms.d.ts +4 -16
  58. package/dist/_dts/api/src/sdk-event-upsert.d.ts +11 -21
  59. package/dist/_dts/api/src/sdkContracts.d.ts +8 -23
  60. package/dist/_dts/api/src/sdkManagedEventContracts.d.ts +37 -0
  61. package/dist/_dts/api/src/sdkMediaContracts.d.ts +40 -0
  62. package/dist/_dts/api/src/sdkMediaEndpointDefinitions.d.ts +66 -0
  63. package/dist/_dts/api/src/sdkThemeWire.d.ts +157 -146
  64. package/dist/_dts/api/src/siteInfrastructure.d.ts +37 -37
  65. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +35 -54
  66. package/dist/_dts/api/src/siteOnboarding.d.ts +3 -3
  67. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +38 -16
  68. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +37 -17
  69. package/dist/_dts/api/src/types.d.ts +2 -2
  70. package/dist/_dts/api/src/{wholeSeriesOfferings.d.ts → wholeSeriesRuns.d.ts} +11 -67
  71. package/dist/_dts/block-form/src/FormRenderer.d.ts +3 -1
  72. package/dist/_dts/block-form/src/backend/store-backend.d.ts +2 -1
  73. package/dist/_dts/block-form/src/backend/types.d.ts +2 -0
  74. package/dist/_dts/block-form/src/context/FormFocusContext.d.ts +7 -0
  75. package/dist/_dts/block-form/src/index.d.ts +2 -0
  76. package/dist/_dts/block-form/src/manifest/ManifestForm.d.ts +2 -1
  77. package/dist/_dts/block-form/src/utils/promotedFieldBackend.d.ts +8 -0
  78. package/dist/_dts/block-form/src/utils/promotedFieldPlan.d.ts +18 -0
  79. package/dist/_dts/block-form/src/utils/resolvePromotedFields.d.ts +8 -1
  80. package/dist/_dts/blocks/src/BlockErrorBoundary.d.ts +46 -0
  81. package/dist/_dts/blocks/src/PageRenderer.d.ts +2 -141
  82. package/dist/_dts/blocks/src/contracts/index.d.ts +2 -0
  83. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +12 -6
  84. package/dist/_dts/blocks/src/index.d.ts +1 -0
  85. package/dist/_dts/blocks/src/pageRenderAudience.d.ts +54 -0
  86. package/dist/_dts/blocks/src/pageRenderDiagnostics.d.ts +26 -0
  87. package/dist/_dts/blocks/src/pageRenderPlan.d.ts +116 -0
  88. package/dist/_dts/blocks/src/pageRenderPreparation.d.ts +109 -0
  89. package/dist/_dts/blocks/src/pageRendererBoundaries.d.ts +1 -0
  90. package/dist/_dts/blocks/src/pageRendererContracts.d.ts +154 -0
  91. package/dist/_dts/blocks/src/portal/types.d.ts +1 -1
  92. package/dist/_dts/blocks/src/server.d.ts +1 -0
  93. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +12 -20
  94. package/dist/_dts/blocks/src/system/blocks/events/event-calendar.d.ts +1 -1
  95. package/dist/_dts/blocks/src/system/blocks/events/eventCalendarDataLoaders.d.ts +3 -0
  96. package/dist/_dts/blocks/src/system/blocks/events/shared/calendarWindow.d.ts +95 -0
  97. package/dist/_dts/blocks/src/system/blocks/events/shared/index.d.ts +1 -0
  98. package/dist/_dts/blocks/src/system/blocks/events/shared/runGrouping.d.ts +37 -0
  99. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +1046 -773
  100. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +59 -46
  101. package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +3 -3
  102. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +161 -161
  103. package/dist/_dts/blocks/src/system/blocks/offerings-preview/model.d.ts +13 -6
  104. package/dist/_dts/blocks/src/system/blocks/offerings-preview/scheduleSummary.d.ts +10 -4
  105. package/dist/_dts/blocks/src/system/constants/buttonRoles.d.ts +2 -2
  106. package/dist/_dts/blocks/src/system/constants/events.d.ts +4 -0
  107. package/dist/_dts/blocks/src/system/customize/facets.d.ts +4 -4
  108. package/dist/_dts/blocks/src/system/data/loaderEndpoints.d.ts +1 -1
  109. package/dist/_dts/blocks/src/system/data/publicLoaderCachePolicy.d.ts +5 -9
  110. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +83 -83
  111. package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +12 -3
  112. package/dist/_dts/blocks/src/system/runtime/api/endpoints.d.ts +8 -8
  113. package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
  114. package/dist/_dts/blocks/src/system/runtime/api/types/core.d.ts +13 -0
  115. package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +12 -20
  116. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +32 -37
  117. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +15 -18
  118. package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.d.ts +11 -8
  119. package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.state.d.ts +38 -22
  120. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessEventRegistrationFlow.d.ts +7 -0
  121. package/dist/_dts/blocks/src/system/runtime/nodes/event-details/WholeSeriesPricingDisplay.d.ts +2 -2
  122. package/dist/_dts/blocks/src/system/runtime/nodes/event-details/logic.d.ts +16 -4
  123. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/ErrorStep.d.ts +3 -5
  124. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationWizardActions.d.ts +4 -2
  125. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/PaymentSelectionStep.d.ts +1 -1
  126. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +5 -3
  127. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.planning.d.ts +1 -1
  128. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventScope.d.ts +1 -1
  129. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.d.ts +2 -0
  130. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationCompletion.d.ts +15 -0
  131. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationDerivations.d.ts +2 -2
  132. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationErrorPresentation.d.ts +5 -0
  133. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationErrorRecovery.d.ts +25 -0
  134. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationEventAdapter.d.ts +14 -3
  135. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationSurface.d.ts +3 -21
  136. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationWizardContext.d.ts +4 -0
  137. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/siteCreditPreview.d.ts +0 -3
  138. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/ticketSelectionLines.d.ts +14 -16
  139. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +13 -15
  140. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationStripeReturn.d.ts +7 -3
  141. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +9 -3
  142. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +25 -23
  143. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useWaitlistClaimRestoration.d.ts +2 -0
  144. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/utils.d.ts +11 -4
  145. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +8 -13
  146. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCalendar.interactive.d.ts +5 -0
  147. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +1 -0
  148. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.interactive.d.ts +11 -3
  149. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/capacity.d.ts +164 -0
  150. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/cta.d.ts +29 -0
  151. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/dates.d.ts +47 -0
  152. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/index.d.ts +14 -0
  153. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/people.d.ts +6 -0
  154. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/pricing.d.ts +24 -0
  155. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/OfferingTitle.d.ts +11 -0
  156. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekAgendaView.d.ts +1 -1
  157. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekBoardView.d.ts +1 -1
  158. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +1080 -560
  159. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventProductEligibility.d.ts +2 -2
  160. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/index.d.ts +3 -1
  161. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/listingLayout.d.ts +23 -0
  162. package/dist/_dts/blocks/src/system/runtime/nodes/offerings-preview.d.ts +2 -2
  163. package/dist/_dts/blocks/src/system/runtime/nodes/shared/contract-schemas.d.ts +7 -7
  164. package/dist/_dts/blocks/src/system/transforms/registry/eventCalendar.d.ts +11 -0
  165. package/dist/_dts/commerce/src/moneyReport.d.ts +1 -1
  166. package/dist/_dts/commerce/src/purchase/checkoutErrorCodes.d.ts +1 -1
  167. package/dist/_dts/commerce/src/purchase/event-registration-errors.d.ts +57 -0
  168. package/dist/_dts/commerce/src/purchase/eventOrderOptionSnapshot.d.ts +3 -0
  169. package/dist/_dts/commerce/src/purchase/index.d.ts +1 -0
  170. package/dist/_dts/commerce/src/purchase/orderItemMetadata.d.ts +6 -3
  171. package/dist/_dts/commerce/src/purchase/types.d.ts +3 -2
  172. package/dist/_dts/commerce/src/waitlists.d.ts +1 -1
  173. package/dist/_dts/content-editor/src/controller/EntryControllerProvider.d.ts +4 -0
  174. package/dist/_dts/content-editor/src/controller/useBlockedPublishPlan.d.ts +11 -0
  175. package/dist/_dts/content-editor/src/hooks/applyBlockedPublishPlan.d.ts +1 -1
  176. package/dist/_dts/content-editor/src/hooks/blockedPublishPlan.d.ts +13 -5
  177. package/dist/_dts/content-editor/src/hooks/useEntryActions.d.ts +5 -1
  178. package/dist/_dts/content-editor/src/hooks/validateBlocksForPublish.d.ts +34 -2
  179. package/dist/_dts/content-editor/src/index.d.ts +2 -1
  180. package/dist/_dts/content-editor/src/ui/blockValidationManifestRegistry.d.ts +2 -0
  181. package/dist/_dts/content-editor/src/ui/editorUiStore.d.ts +4 -2
  182. package/dist/_dts/content-editor/src/ui/stores/types.d.ts +27 -5
  183. package/dist/_dts/content-model/src/content-types/schema.d.ts +3 -3
  184. package/dist/_dts/content-model/src/templates/defaults.d.ts +11 -0
  185. package/dist/_dts/core/src/branded.d.ts +28 -9
  186. package/dist/_dts/core/src/event-booking-offer-parser.d.ts +82 -0
  187. package/dist/_dts/core/src/event-booking-offer.d.ts +89 -0
  188. package/dist/_dts/core/src/event-page-surface-subject.d.ts +81 -4
  189. package/dist/_dts/core/src/event-pricing.d.ts +81 -89
  190. package/dist/_dts/core/src/index.d.ts +3 -0
  191. package/dist/_dts/core/src/non-empty-array.d.ts +3 -0
  192. package/dist/_dts/core/src/whole-series-run-schedule.d.ts +92 -0
  193. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +495 -279
  194. package/dist/_dts/db/src/index.d.ts +1 -0
  195. package/dist/_dts/db/src/utils/postgrestFilter.d.ts +2 -0
  196. package/dist/_dts/editor-blocks/src/BlockForm.d.ts +2 -6
  197. package/dist/_dts/editor-blocks/src/block-editor/BlockCard.d.ts +1 -1
  198. package/dist/_dts/editor-blocks/src/block-editor/BlockCardHeader.d.ts +2 -2
  199. package/dist/_dts/editor-blocks/src/block-editor/BlockSettingsModal.d.ts +4 -2
  200. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockValidationManifests.d.ts +1 -0
  201. package/dist/_dts/editor-blocks/src/block-editor/types.d.ts +22 -7
  202. package/dist/_dts/editor-blocks/src/block-editor/useSettingsFieldFocus.d.ts +18 -0
  203. package/dist/_dts/media-core/src/bulkDeletePlanning.d.ts +4 -0
  204. package/dist/_dts/media-core/src/fileDomain.d.ts +3 -0
  205. package/dist/_dts/preview-next/src/client/blocks/previewBatchLoaderParams.d.ts +2 -0
  206. package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +1 -0
  207. package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +1 -0
  208. package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeContext.d.ts +3 -2
  209. package/dist/_dts/preview-next/src/client/preview/siteChromeBrandPreferences.d.ts +1 -1
  210. package/dist/_dts/preview-next/src/client/preview/siteChromeQuickControlHistoryState.d.ts +2 -0
  211. package/dist/_dts/preview-next/src/client/preview/siteChromeQuickControlSaveRequest.d.ts +51 -0
  212. package/dist/_dts/preview-next/src/client/preview/siteChromeSavePlan.d.ts +24 -2
  213. package/dist/_dts/preview-next/src/client/preview/siteStylePreviewPlanner.d.ts +23 -1
  214. package/dist/_dts/preview-next/src/client/preview/usePersistedHeaderPreferences.d.ts +8 -0
  215. package/dist/_dts/sdk/src/client/{eventSubrouteReadOperations.d.ts → publicEventReadOperations.d.ts} +4 -3
  216. package/dist/_dts/sdk/src/client/types.d.ts +6 -10
  217. package/dist/_dts/sdk/src/config/types.d.ts +1 -1
  218. package/dist/_dts/sdk/src/config/validation.d.ts +3 -3
  219. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +5 -0
  220. package/dist/_dts/sdk/src/data/prefetchBlockData.d.ts +2 -3
  221. package/dist/_dts/sdk/src/manifest/passes/pass1-fields.d.ts +8 -8
  222. package/dist/_dts/sdk/src/next/tags.d.ts +5 -8
  223. package/dist/_dts/sdk/src/public-api/contracts.d.ts +2 -26
  224. package/dist/_dts/sdk/src/rendering/helpers/footerPageOutline.d.ts +9 -1
  225. package/dist/_dts/sdk/src/rendering/index.d.ts +1 -0
  226. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +6 -53
  227. package/dist/_dts/sdk/src/rendering/server.d.ts +1 -0
  228. package/dist/_dts/sdk/src/version.d.ts +1 -1
  229. package/dist/_dts/theme-core/src/accordions/types.d.ts +5 -5
  230. package/dist/_dts/theme-core/src/buttons/styles/recipes/flatInk.d.ts +25 -25
  231. package/dist/_dts/theme-core/src/buttons/styles/registry.d.ts +25 -25
  232. package/dist/_dts/theme-core/src/buttons/styles/selection.d.ts +7 -7
  233. package/dist/_dts/theme-core/src/buttons/types.d.ts +22 -22
  234. package/dist/_dts/theme-core/src/cards/types.d.ts +49 -49
  235. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  236. package/dist/_dts/theme-core/src/gradients/types.d.ts +5 -0
  237. package/dist/_dts/theme-core/src/header/interactionPalette.d.ts +26 -3
  238. package/dist/_dts/theme-core/src/inputs/types.d.ts +2 -2
  239. package/dist/_dts/theme-core/src/interactive/baseSchema.d.ts +1 -1
  240. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +195 -195
  241. package/dist/_dts/theme-core/src/navigation/types.d.ts +3 -3
  242. package/dist/_dts/theme-core/src/palette/colors.d.ts +1 -1
  243. package/dist/_dts/theme-core/src/palette/curated/types.d.ts +2 -2
  244. package/dist/_dts/theme-core/src/schema.d.ts +258 -257
  245. package/dist/_dts/theme-core/src/shared/componentStyles.d.ts +1 -1
  246. package/dist/_dts/theme-core/src/site-styles/backgroundAppearance.d.ts +2 -2
  247. package/dist/_dts/theme-core/src/site-styles/cardRoleVocabulary.d.ts +1 -1
  248. package/dist/_dts/theme-core/src/site-styles/compilationPlan.d.ts +43 -3
  249. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +10 -0
  250. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +4 -4
  251. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +2 -2
  252. package/dist/_dts/theme-core/src/site-styles/headerBrandPresentation.d.ts +63 -0
  253. package/dist/_dts/theme-core/src/site-styles/headerBytesComparison.d.ts +30 -0
  254. package/dist/_dts/theme-core/src/site-styles/headerInteractionPalette.d.ts +50 -1
  255. package/dist/_dts/theme-core/src/site-styles/headerLayoutCatalog.d.ts +48 -9
  256. package/dist/_dts/theme-core/src/site-styles/headerPreferences.d.ts +162 -0
  257. package/dist/_dts/theme-core/src/site-styles/headerPreferencesPersistence.d.ts +73 -0
  258. package/dist/_dts/theme-core/src/site-styles/headerRecompile.d.ts +118 -0
  259. package/dist/_dts/theme-core/src/site-styles/headerStyleCompiler.d.ts +10 -1
  260. package/dist/_dts/theme-core/src/site-styles/headerStyleDefaults.d.ts +1 -1
  261. package/dist/_dts/theme-core/src/site-styles/headerStyleRecipe.d.ts +7 -0
  262. package/dist/_dts/theme-core/src/site-styles/index.d.ts +5 -0
  263. package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +1 -1
  264. package/dist/_dts/theme-core/src/site-styles/siteChromeBackgrounds.d.ts +20 -1
  265. package/dist/_dts/theme-core/src/site-styles/siteChromeNavPreferences.d.ts +43 -2
  266. package/dist/_dts/theme-core/src/site-styles/tokenRecipes.d.ts +1 -1
  267. package/dist/_dts/theme-core/src/tokens/themeColorTokens.d.ts +3 -3
  268. package/dist/_dts/ui/src/badge.d.ts +1 -1
  269. package/dist/_dts/ui/src/button.d.ts +2 -2
  270. package/dist/client/{BookingConsentAgreement-DCch21a6.mjs → BookingConsentAgreement-DQUik1Mx.mjs} +2 -2
  271. package/dist/client/{DiscountCodeDisclosure-DIj1T59K.mjs → DiscountCodeDisclosure-CU67Q4vH.mjs} +1 -1
  272. package/dist/client/{EventCombined.client-BWVNlXTx.mjs → EventCombined.client-a02TXUgg.mjs} +233 -348
  273. package/dist/client/{EventListing.client-DVFCDe3i.mjs → EventListing.client-99qx7jFl.mjs} +2 -2
  274. package/dist/client/{LeafletStaticMap-BY5mIHw9.mjs → LeafletStaticMap-CWzcq73L.mjs} +1 -1
  275. package/dist/client/{accordion-CK29E8rG.mjs → accordion-D1nb3-Oj.mjs} +1 -1
  276. package/dist/client/{bookingForm-DFvnet-N.mjs → bookingForm-BGrmLhaO.mjs} +5 -5
  277. package/dist/client/bookings.mjs +10555 -10475
  278. package/dist/client/{carousel-BVU5NQlb.mjs → carousel-DSmOx3ad.mjs} +1 -1
  279. package/dist/client/{cart-BNItcZVa.mjs → cart-COWeOIUk.mjs} +3 -3
  280. package/dist/client/{checkout-Bu6iCdkP.mjs → checkout-CeysaIJK.mjs} +3 -3
  281. package/dist/client/client.mjs +58968 -57441
  282. package/dist/client/{context-BImarOAq.mjs → context-DBzX85Xc.mjs} +46 -18
  283. package/dist/client/dates-DCYhZBlW.mjs +264 -0
  284. package/dist/client/{eventCalendar-DS2h-UXD.mjs → eventCalendar-BgsN73Ul.mjs} +21 -44
  285. package/dist/client/{eventCombined-Drt4Oq9p.mjs → eventCombined-DcZQAMQP.mjs} +3 -3
  286. package/dist/client/{eventDetails-Bl2vWgTX.mjs → eventDetails-BWwGJ54l.mjs} +131 -51
  287. package/dist/client/{eventListing-CS7PHY7v.mjs → eventListing-DqYqV8vp.mjs} +3 -3
  288. package/dist/client/{eventRegistration-D-j8eNy2.mjs → eventRegistration-DQGDgu_e.mjs} +1122 -803
  289. package/dist/client/{form-RMpoLTyr.mjs → form-ClfpasVT.mjs} +2 -2
  290. package/dist/client/{headerSection-BYE3Lb3k.mjs → headerSection-BuOMe98N.mjs} +2 -2
  291. package/dist/client/hooks.mjs +9630 -9526
  292. package/dist/client/{locationMap-BxSr7Kkh.mjs → locationMap-CEqu_sfa.mjs} +2 -2
  293. package/dist/client/{newsletterForm-DerbXwFC.mjs → newsletterForm-IbrHjMxy.mjs} +2 -2
  294. package/dist/client/pricing-xj7MPZlK.mjs +314 -0
  295. package/dist/client/{productDetail-4SZCLhAf.mjs → productDetail-vxqTt5Xj.mjs} +3 -3
  296. package/dist/client/{productList-D7AP4GNq.mjs → productList-OTdZu8sb.mjs} +3 -3
  297. package/dist/client/{propsDecoder-pzBeCh14.mjs → propsDecoder-CY9gGEF7.mjs} +786 -1194
  298. package/dist/client/rendering/client.mjs +11481 -10469
  299. package/dist/client/rendering/islands.mjs +17 -17
  300. package/dist/client/rendering.mjs +26871 -25232
  301. package/dist/client/{scrollToBlock-CduAKf8T.mjs → scrollToBlock--BFV6kl-.mjs} +1 -1
  302. package/dist/client/{shop-Cp5p_kGe.mjs → shop-CP4YbDL9.mjs} +6 -6
  303. package/dist/client/{shop-commerce-DicXYaYX.mjs → shop-commerce-APs4XBXE.mjs} +5 -5
  304. package/dist/client/{shop-commerce-store-CGWnpY4K.mjs → shop-commerce-store-CAVLxLFr.mjs} +1 -1
  305. package/dist/client/{shopShared-BDf9ljkm.mjs → shopShared-BnSRrwXI.mjs} +3 -3
  306. package/dist/client/{useEventFilters-DeeyGYuk.mjs → useEventFilters-1a1by4c8.mjs} +33 -18
  307. package/dist/preview-next/before-render.mjs +186 -148
  308. package/dist/preview-next/client/runtime.mjs +4 -4
  309. package/dist/preview-next/keepAlive.mjs +186 -148
  310. package/dist/preview-next/middleware.mjs +186 -148
  311. package/dist/{previewAuthStore-DbqBol0V.mjs → previewAuthStore-BkEgnYPP.mjs} +186 -148
  312. package/dist/{sdk-runtime-19MO27F0.mjs → sdk-runtime-DwGfsT0S.mjs} +2 -2
  313. package/dist/{separator-DaPLtJ1f.mjs → separator-BeqDLneQ.mjs} +1 -1
  314. package/dist/server/components.mjs +53243 -51879
  315. package/dist/server/config-validation.mjs +1015 -906
  316. package/dist/server/config.mjs +1019 -910
  317. package/dist/server/data.mjs +10304 -10200
  318. package/dist/server/index.mjs +217 -198
  319. package/dist/server/next/tags.mjs +18 -4
  320. package/dist/server/next.mjs +62787 -61617
  321. package/dist/server/page-converter.mjs +797 -917
  322. package/dist/server/prebuild.mjs +1 -1
  323. package/dist/server/rendering/server.mjs +52557 -51365
  324. package/dist/server/rendering.mjs +54373 -53054
  325. package/dist/server/routing.mjs +13274 -13142
  326. package/dist/server/server.mjs +1076 -1154
  327. package/dist/server/theme-bridge.mjs +69 -9
  328. package/dist/server/theme.mjs +27 -8
  329. package/dist/styles/index.css +32 -1
  330. package/package.json +1 -1
  331. package/dist/_dts/api/src/publicExperience/wholeSeriesEndpoints.d.ts +0 -65
  332. package/dist/_dts/api/src/publicWholeSeriesEndpointDefinitions.d.ts +0 -20
  333. package/dist/_dts/api/src/sdk-event-pricing.d.ts +0 -61
  334. package/dist/_dts/blocks/src/system/blocks/events/whole-series/index.d.ts +0 -3
  335. package/dist/_dts/blocks/src/system/blocks/events/whole-series/pricing.d.ts +0 -50
  336. package/dist/_dts/blocks/src/system/blocks/events/whole-series/schemas.d.ts +0 -135
  337. package/dist/_dts/blocks/src/system/blocks/events/whole-series/types.d.ts +0 -87
  338. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCapacity.d.ts +0 -48
  339. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/pricing.d.ts +0 -17
  340. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/utils.d.ts +0 -100
  341. package/dist/_dts/sdk/src/client/wholeSeriesReadOperations.d.ts +0 -11
  342. package/dist/_dts/sdk/src/public-api/wholeSeriesContracts.d.ts +0 -2
  343. /package/dist/_dts/blocks/src/system/runtime/nodes/events/{shared → domain}/destination.d.ts +0 -0
@@ -4568,6 +4568,11 @@ const gradientConfigSchema = z.object({
4568
4568
  position: z.string().optional(),
4569
4569
  stops: z.array(gradientStopSchema).min(2)
4570
4570
  });
4571
+ const gradientsSchema = z.object({
4572
+ button: z.string().min(1).nullable().optional(),
4573
+ hero: z.string().min(1).nullable().optional(),
4574
+ background: z.string().min(1).nullable().optional()
4575
+ });
4571
4576
  //#endregion
4572
4577
  //#region ../theme-core/src/interactive/baseSchema.ts
4573
4578
  /**
@@ -5318,11 +5323,30 @@ const headerContainerSchema = z.object({
5318
5323
  tint: z.string().nullable().optional(),
5319
5324
  opacity: z.number().min(0).max(1).default(.12)
5320
5325
  }).optional();
5321
- const headerInteractionPaletteSchema = z.enum([
5326
+ //#endregion
5327
+ //#region ../theme-core/src/header/interactionPalette.ts
5328
+ /**
5329
+ * The palettes that fill the nav link with a colour on hover and focus. Each
5330
+ * one names a background/foreground token pair.
5331
+ */
5332
+ const headerInteractionPillPaletteValues = [
5322
5333
  "primary",
5323
5334
  "secondary",
5324
5335
  "accent"
5325
- ]);
5336
+ ];
5337
+ /**
5338
+ * "No pill": the nav link keeps whatever hover treatment its recipe compiled,
5339
+ * and the palette step writes nothing at all (#1318 Phase 4c decision 2).
5340
+ *
5341
+ * It exists because "a colour change on hover, no filled background" was not
5342
+ * expressible in the vocabulary, and it is what
5343
+ * `anna-raven-therapy-and-yoga` and `kirtan-lucy` have rendered since before
5344
+ * the palette existed. Without it those two rows can only be classified as a
5345
+ * conscious visual change.
5346
+ */
5347
+ const headerInteractionQuietPalette = "quiet";
5348
+ const headerInteractionPaletteValues = [...headerInteractionPillPaletteValues, headerInteractionQuietPalette];
5349
+ const headerInteractionPaletteSchema = z.enum(headerInteractionPaletteValues);
5326
5350
  //#endregion
5327
5351
  //#region ../theme-core/src/boxBackgroundSchema.ts
5328
5352
  const boxBackgroundOverlaySchema = z.preprocess(normalizeAuthoringOpacity, z.discriminatedUnion("type", [
@@ -5380,7 +5404,7 @@ const boxBackgroundSchema = z.discriminatedUnion("type", [
5380
5404
  })
5381
5405
  ]);
5382
5406
  function normalizeAuthoringOpacity(value) {
5383
- if (!isRecord$7(value)) return value;
5407
+ if (!isRecord$6(value)) return value;
5384
5408
  return {
5385
5409
  ...value,
5386
5410
  opacity: normalizeOpacity(value.opacity)
@@ -5389,7 +5413,7 @@ function normalizeAuthoringOpacity(value) {
5389
5413
  function normalizeOpacity(value) {
5390
5414
  return typeof value === "number" && value > 1 && value <= 100 ? value / 100 : value;
5391
5415
  }
5392
- function isRecord$7(value) {
5416
+ function isRecord$6(value) {
5393
5417
  return typeof value === "object" && value !== null && !Array.isArray(value);
5394
5418
  }
5395
5419
  //#endregion
@@ -5704,11 +5728,12 @@ const inputStyle = z.object({
5704
5728
  ]),
5705
5729
  label: z.enum(["inside", "above"])
5706
5730
  });
5707
- const headerPositioning = z.enum([
5731
+ const headerPositioningValues = [
5708
5732
  "static",
5709
5733
  "sticky",
5710
5734
  "fixed"
5711
- ]);
5735
+ ];
5736
+ const headerPositioning = z.enum(headerPositioningValues);
5712
5737
  const headerNavStyle = z.enum([
5713
5738
  "minimal",
5714
5739
  "underline",
@@ -5843,7 +5868,7 @@ const headerSchema = z.object({
5843
5868
  variant: headerVariantWithLegacyAliasSchema,
5844
5869
  positioning: headerPositioning,
5845
5870
  shrinkOnScroll: z.boolean(),
5846
- maxWidth: headerMaxWidth,
5871
+ maxWidth: headerMaxWidth.default("container"),
5847
5872
  scrollTreatment: headerScrollTreatmentSchema,
5848
5873
  background: headerBackgroundSchema.default({
5849
5874
  type: "color",
@@ -6042,11 +6067,6 @@ const bodyTextSchema = z.object({ intro: z.object({
6042
6067
  paragraphSize: bodyTextIntroTypographySizeSchema.optional(),
6043
6068
  headingSize: bodyTextIntroTypographySizeSchema.optional()
6044
6069
  }).optional() }).optional();
6045
- const gradientsSchema = z.object({
6046
- button: z.string().min(1).nullable().optional(),
6047
- hero: z.string().min(1).nullable().optional(),
6048
- background: z.string().min(1).nullable().optional()
6049
- });
6050
6070
  /**
6051
6071
  * Testimonial quote-mark treatment, owned by the site style (analogous to the
6052
6072
  * accordion icon). `style` is the coarse selector; the optional fields fine-tune
@@ -6927,6 +6947,12 @@ function cardRoleFromLegacyVocabulary(value) {
6927
6947
  */
6928
6948
  const cardRoleWithLegacyAliasSchema = z.preprocess((value) => cardRoleFromLegacyVocabulary(value) ?? value, cardRoleSchema);
6929
6949
  //#endregion
6950
+ //#region ../theme-core/src/site-styles/compilationPlan.ts
6951
+ const defaultHeaderBrandPreferences = {
6952
+ brandDisplay: "auto",
6953
+ logoSize: "auto"
6954
+ };
6955
+ //#endregion
6930
6956
  //#region ../theme-core/src/site-styles/sectionTransitions.ts
6931
6957
  function boundaryRuntimeMetrics(family, size, heightExpression) {
6932
6958
  return {
@@ -7945,6 +7971,12 @@ const overlayLogoAccommodations = [
7945
7971
  inlineMarkWithTitleLogoAccommodation,
7946
7972
  unbackedOverlayLogoAccommodation
7947
7973
  ];
7974
+ const allCuratedLogoAccommodations = [
7975
+ ...inlineClassicLogoAccommodations,
7976
+ ...centeredLogoAccommodations,
7977
+ ...overlayLogoAccommodations
7978
+ ];
7979
+ new Set(allCuratedLogoAccommodations.filter((option) => option.providesBacking === true).map((option) => option.pattern));
7948
7980
  const headerLayoutCatalog = defineExactCatalog()([
7949
7981
  {
7950
7982
  id: asHeaderLayoutId("classic"),
@@ -8094,6 +8126,10 @@ defineLookOptionGroup({
8094
8126
  {
8095
8127
  id: "secondary",
8096
8128
  label: "Secondary"
8129
+ },
8130
+ {
8131
+ id: headerInteractionQuietPalette,
8132
+ label: "Text only"
8097
8133
  }
8098
8134
  ]
8099
8135
  });
@@ -10515,6 +10551,67 @@ const blockDesignFallback = {
10515
10551
  };
10516
10552
  blockDesignFallback.sectionSurface, blockDesignFallback.contentFrame, blockDesignFallback.transitionAfter, blockDesignFallback.sectionHeight, blockDesignFallback.heroLegibility, blockDesignFallback.imageSurfaceTreatment, blockDesignFallback.imageSurfaceMotion, blockDesignFallback.tileTreatment, blockDesignFallback.eventListTreatment, blockDesignFallback.eyebrowTreatment, blockDesignFallback.accordionIconTreatment, blockDesignFallback.composition;
10517
10553
  //#endregion
10554
+ //#region ../theme-core/src/site-styles/siteChromeBackgrounds.ts
10555
+ const siteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceColorTokenNames);
10556
+ const quickSiteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceQuickColorTokenNames);
10557
+ siteChromeBackgroundColorTokens.filter((token) => !quickSiteChromeBackgroundColorTokens.includes(token));
10558
+ function parseSiteChromeBackgroundColorToken(value) {
10559
+ const token = parseBackgroundAppearanceColorToken(value);
10560
+ return token ? token : null;
10561
+ }
10562
+ function toSiteChromeBackgroundColorTokens(tokenNames) {
10563
+ return tokenNames.flatMap((name) => {
10564
+ const token = parseSiteChromeBackgroundColorToken(name);
10565
+ return token ? [token] : [];
10566
+ });
10567
+ }
10568
+ //#endregion
10569
+ //#region ../theme-core/src/site-styles/siteChromeNavPreferences.ts
10570
+ const headerNavTypographyPreferenceValues = [
10571
+ "inherit",
10572
+ "body",
10573
+ "heading"
10574
+ ];
10575
+ const headerNavFontSizePreferenceValues = [
10576
+ "inherit",
10577
+ "sm",
10578
+ "base",
10579
+ "lg",
10580
+ "xl"
10581
+ ];
10582
+ const defaultHeaderNavPreferences = {
10583
+ typography: "inherit",
10584
+ fontSize: "inherit",
10585
+ interactionPalette: "recommended"
10586
+ };
10587
+ //#endregion
10588
+ //#region ../theme-core/src/site-styles/headerBrandPresentation.ts
10589
+ /**
10590
+ * Whether the header wears a brand presentation at all (#1318 Phase 4c).
10591
+ *
10592
+ * `applyHeaderBrandPresentation` is unconditional today: given a logo context
10593
+ * it always writes a `logo` object carrying a resolved display, size and
10594
+ * accommodation. That makes "this header has no brand presentation block" —
10595
+ * which is what several live sites persist, including one whose site *does*
10596
+ * have a logo asset — a state the preference record could not express, so a
10597
+ * recompile would silently give the site a logo treatment it has never
10598
+ * rendered.
10599
+ *
10600
+ * This is the third field in this phase with that shape, after the interaction
10601
+ * palette and the nav text size: the persisted bytes carry intent the reader
10602
+ * cannot say, so the recompile "corrects" it. The fix is the same one — widen
10603
+ * the closed vocabulary with a named member and derive it by baseline
10604
+ * comparison — and it is a *widening*, not a restyle: `'recommended'` is the
10605
+ * default and reproduces today's behaviour exactly, so no row whose bytes carry
10606
+ * a presentation compiles differently for `'plain'` existing.
10607
+ *
10608
+ * `'plain'` is deliberately not "preserve whatever bytes are there". It is a
10609
+ * constructive instruction — *write no presentation block* — so Phase 4e's
10610
+ * compiler, which builds the header from nothing, can produce it.
10611
+ */
10612
+ const headerBrandPresentationValues = ["recommended", "plain"];
10613
+ defaultHeaderBrandPreferences.brandDisplay, defaultHeaderBrandPreferences.logoSize, defaultHeaderNavPreferences.typography, defaultHeaderNavPreferences.fontSize, defaultHeaderNavPreferences.interactionPalette;
10614
+ //#endregion
10518
10615
  //#region ../theme-core/src/site-styles/generatedSchemas.ts
10519
10616
  function uniqueNonEmpty(values) {
10520
10617
  const uniqueValues = [...new Set(values)];
@@ -10583,6 +10680,56 @@ z.object({
10583
10680
  blocks: z.array(generatedPageDesignBlockIntentSchema)
10584
10681
  }).strict();
10585
10682
  //#endregion
10683
+ //#region ../theme-core/src/site-styles/headerPreferencesPersistence.ts
10684
+ const backgroundColorTokenSchema = z.unknown().transform((value, ctx) => {
10685
+ const token = parseSiteChromeBackgroundColorToken(value);
10686
+ if (token === null) {
10687
+ ctx.addIssue({
10688
+ code: "custom",
10689
+ message: "Unknown site chrome background colour token"
10690
+ });
10691
+ return z.NEVER;
10692
+ }
10693
+ return token;
10694
+ });
10695
+ const backgroundOverrideSchema = z.discriminatedUnion("kind", [z.object({ kind: z.literal("default") }).strict(), z.object({
10696
+ kind: z.literal("color"),
10697
+ token: backgroundColorTokenSchema
10698
+ }).strict()]);
10699
+ const logoTextIntentSchema = z.object({
10700
+ mobileMaxWidth: z.enum([
10701
+ "xs",
10702
+ "sm",
10703
+ "md"
10704
+ ]).optional(),
10705
+ mobileWrapLines: z.union([z.literal(1), z.literal(2)]).optional(),
10706
+ hideOnShrink: z.boolean().optional()
10707
+ }).strict();
10708
+ const structureSchema = z.object({
10709
+ positioning: z.union([z.literal("inherit"), z.enum(headerPositioningValues)]),
10710
+ shrinkOnScroll: z.union([z.literal("inherit"), z.boolean()]),
10711
+ logoText: z.union([
10712
+ z.literal("inherit"),
10713
+ z.literal("none"),
10714
+ logoTextIntentSchema
10715
+ ])
10716
+ }).strict();
10717
+ const headerPreferencesShape = {
10718
+ brandPresentation: z.enum(headerBrandPresentationValues),
10719
+ brandDisplay: z.enum(brandDisplayModeValues),
10720
+ logoSize: z.enum(logoSizePolicyValues),
10721
+ navFontRole: z.enum(headerNavTypographyPreferenceValues),
10722
+ navTextSize: z.enum(headerNavFontSizePreferenceValues),
10723
+ interactionPalette: z.union([z.literal("recommended"), z.enum(headerInteractionPaletteValues)]),
10724
+ background: backgroundOverrideSchema,
10725
+ structure: structureSchema
10726
+ };
10727
+ z.object(headerPreferencesShape).strict();
10728
+ z.object(headerPreferencesShape).omit({
10729
+ brandPresentation: true,
10730
+ structure: true
10731
+ }).strict();
10732
+ //#endregion
10586
10733
  //#region ../theme-core/src/site-styles/pageDesignAuthority.ts
10587
10734
  const nonEmptyStringSchema = z.string().min(1);
10588
10735
  const blockContentVersionIdSchema = nonEmptyStringSchema.transform(asBlockContentVersionId);
@@ -10684,21 +10831,6 @@ function collectBlockSequenceIssues(snapshots) {
10684
10831
  return issues;
10685
10832
  }
10686
10833
  //#endregion
10687
- //#region ../theme-core/src/site-styles/siteChromeBackgrounds.ts
10688
- const siteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceColorTokenNames);
10689
- const quickSiteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceQuickColorTokenNames);
10690
- siteChromeBackgroundColorTokens.filter((token) => !quickSiteChromeBackgroundColorTokens.includes(token));
10691
- function parseSiteChromeBackgroundColorToken(value) {
10692
- const token = parseBackgroundAppearanceColorToken(value);
10693
- return token ? token : null;
10694
- }
10695
- function toSiteChromeBackgroundColorTokens(tokenNames) {
10696
- return tokenNames.flatMap((name) => {
10697
- const token = parseSiteChromeBackgroundColorToken(name);
10698
- return token ? [token] : [];
10699
- });
10700
- }
10701
- //#endregion
10702
10834
  //#region ../theme-core/src/site-styles/tokenRecipes.ts
10703
10835
  const themeTokenRecipeOptions = {
10704
10836
  palette: [
@@ -10905,22 +11037,59 @@ function formatCurrencyAmount(amountCents, currency, options) {
10905
11037
  }
10906
11038
  }
10907
11039
  //#endregion
11040
+ //#region ../core/src/planner.ts
11041
+ /** Default clock for production callers that do not inject time explicitly. */
11042
+ const systemPlanningClock = { now: () => Date.now() };
11043
+ /** Resolve current time as a Date from an explicit Date, injected clock, or system clock. */
11044
+ function resolvePlanningNowDate(input = {}) {
11045
+ if (input.now !== void 0) return input.now;
11046
+ return new Date((input.clock ?? systemPlanningClock).now());
11047
+ }
11048
+ //#endregion
10908
11049
  //#region ../core/src/event-pricing.ts
11050
+ /** Capacity closes booking, but does not make an otherwise eligible price unknown. */
11051
+ function isPublicEventPricingOptionDisplayable(option) {
11052
+ if (!option.isActive) return false;
11053
+ if (option.availability.kind === "available") return true;
11054
+ const reason = option.availability.reason;
11055
+ switch (reason) {
11056
+ case "sold_out":
11057
+ case "overallCapacityUnavailable": return true;
11058
+ case "inactive":
11059
+ case "not_on_sale_yet":
11060
+ case "sale_ended":
11061
+ case "attendance_mode_unavailable": return false;
11062
+ default: return assertNever$1(reason);
11063
+ }
11064
+ }
11065
+ function publicEventPricingDisplay(pricing) {
11066
+ switch (pricing.kind) {
11067
+ case "free":
11068
+ case "single":
11069
+ case "sliding_scale": return canonicalEventPricingDisplay(pricing);
11070
+ case "tiered": return resolvePricingOptionsPriceDisplay({
11071
+ options: pricing.options.filter(isPublicEventPricingOptionDisplayable),
11072
+ currency: pricing.currency,
11073
+ purpose: "configured"
11074
+ });
11075
+ case "external": return {
11076
+ kind: "external",
11077
+ label: pricing.label
11078
+ };
11079
+ }
11080
+ }
10909
11081
  function publicEventPricingType(pricing) {
10910
11082
  switch (pricing.kind) {
10911
- case "drop_in":
10912
- case "free_registration": return "free";
10913
- case "single_paid":
10914
- case "ticket_types":
10915
- case "sliding_scale":
10916
- case "whole_series": return isFreePublicEventPriceDisplay(pricing.display) ? "free" : "paid";
11083
+ case "free": return "free";
11084
+ case "single":
11085
+ case "tiered":
11086
+ case "sliding_scale": return isFreePublicEventPriceDisplay(publicEventPricingDisplay(pricing)) ? "free" : "paid";
10917
11087
  case "external": return "external";
10918
11088
  }
10919
11089
  }
10920
11090
  function isFreePublicEventPriceDisplay(display) {
10921
11091
  switch (display.kind) {
10922
11092
  case "free": return true;
10923
- case "whole_series": return display.display.kind === "free";
10924
11093
  case "exact":
10925
11094
  case "from":
10926
11095
  case "range":
@@ -10929,22 +11098,126 @@ function isFreePublicEventPriceDisplay(display) {
10929
11098
  case "external": return false;
10930
11099
  }
10931
11100
  }
11101
+ function resolvePricingOptionSaleWindowState(option, now) {
11102
+ if (option.saleStartsAt !== null && option.saleStartsAt !== void 0 && new Date(option.saleStartsAt) > now) return "not_started";
11103
+ if (option.saleEndsAt !== null && option.saleEndsAt !== void 0 && new Date(option.saleEndsAt) < now) return "ended";
11104
+ return "open";
11105
+ }
11106
+ function resolvePricingOptionsPriceDisplay(input) {
11107
+ const now = input.purpose === "available_now" ? resolvePlanningNowDate({
11108
+ now: input.now,
11109
+ clock: input.clock
11110
+ }) : null;
11111
+ const amounts = input.options.filter((option) => option.isActive && (now === null || resolvePricingOptionSaleWindowState(option, now) === "open")).map((option) => option.priceAmount);
11112
+ return amounts.length === 0 ? {
11113
+ kind: "unavailable",
11114
+ currency: input.currency
11115
+ } : amountRangeDisplay(amounts, input.currency);
11116
+ }
11117
+ function amountRangeDisplay(amounts, currency) {
11118
+ const minAmount = Math.min(...amounts);
11119
+ const maxAmount = Math.max(...amounts);
11120
+ if (minAmount === maxAmount) return minAmount === 0 ? {
11121
+ kind: "free",
11122
+ currency
11123
+ } : {
11124
+ kind: "exact",
11125
+ amount: minAmount,
11126
+ currency
11127
+ };
11128
+ if (minAmount === 0) {
11129
+ const paidAmounts = amounts.filter((amount) => amount > 0);
11130
+ return {
11131
+ kind: "mixed",
11132
+ paidFromAmount: Math.min(...paidAmounts),
11133
+ paidToAmount: maxAmount,
11134
+ currency
11135
+ };
11136
+ }
11137
+ return {
11138
+ kind: "range",
11139
+ minAmount,
11140
+ maxAmount,
11141
+ currency
11142
+ };
11143
+ }
11144
+ /** Derives configured price presentation directly from canonical pricing. */
11145
+ function canonicalEventPricingDisplay(pricing) {
11146
+ switch (pricing.kind) {
11147
+ case "free": return {
11148
+ kind: "free",
11149
+ currency: pricing.currency
11150
+ };
11151
+ case "single": return {
11152
+ kind: "exact",
11153
+ amount: pricing.amount,
11154
+ currency: pricing.currency
11155
+ };
11156
+ case "sliding_scale": return pricing.minimum === pricing.maximum ? {
11157
+ kind: "exact",
11158
+ amount: pricing.maximum,
11159
+ currency: pricing.currency
11160
+ } : {
11161
+ kind: "range",
11162
+ minAmount: pricing.minimum,
11163
+ maxAmount: pricing.maximum,
11164
+ currency: pricing.currency
11165
+ };
11166
+ case "tiered": return resolvePricingOptionsPriceDisplay({
11167
+ options: pricing.options,
11168
+ currency: pricing.currency,
11169
+ purpose: "configured"
11170
+ });
11171
+ default: return assertNever$1(pricing);
11172
+ }
11173
+ }
10932
11174
  //#endregion
10933
11175
  //#region ../core/src/event-page-surface-subject.ts
10934
- function createEventSeriesPageSurfaceSubject(eventSeriesId, bookingScope) {
11176
+ function createEventSeriesPageSurfaceSubject(eventSeriesId, bookingScope, eventDestinationMode) {
11177
+ const mode = eventDestinationMode ? { eventDestinationMode } : {};
10935
11178
  return bookingScope === "whole_series" ? {
10936
11179
  kind: "eventSeries",
10937
11180
  eventSeriesId,
10938
11181
  bookingScope,
10939
- isWholeSeriesBooking: true
11182
+ isWholeSeriesBooking: true,
11183
+ ...mode
10940
11184
  } : {
10941
11185
  kind: "eventSeries",
10942
11186
  eventSeriesId,
10943
- bookingScope
11187
+ bookingScope,
11188
+ ...mode
11189
+ };
11190
+ }
11191
+ function createEventOfferingPageSurfaceSubject(eventOfferingId, input) {
11192
+ const mode = input.eventDestinationMode ? { eventDestinationMode: input.eventDestinationMode } : {};
11193
+ const identity = {
11194
+ kind: "eventOffering",
11195
+ eventOfferingId,
11196
+ catalogueEventSeriesIds: input.catalogueEventSeriesIds
11197
+ };
11198
+ return input.bookingScope === "whole_series" ? {
11199
+ ...identity,
11200
+ bookingScope: input.bookingScope,
11201
+ isWholeSeriesBooking: true,
11202
+ ...mode
11203
+ } : {
11204
+ ...identity,
11205
+ bookingScope: input.bookingScope,
11206
+ ...mode
10944
11207
  };
10945
11208
  }
11209
+ /**
11210
+ * Read the destination mode off a wire value.
11211
+ *
11212
+ * Absent or unrecognised reads as absent, which leaves the routed Event record
11213
+ * as the only authority — the behaviour every caller had before the field
11214
+ * existed.
11215
+ */
11216
+ function parseEventPageSurfaceDestinationMode(value) {
11217
+ return value === "cms-managed" || value === "system-managed" ? value : void 0;
11218
+ }
10946
11219
  function parseEventPageSurfaceSubject(value) {
10947
- if (!isRecord$6(value)) return err({ kind: "notObject" });
11220
+ if (!isRecord$5(value)) return err({ kind: "notObject" });
10948
11221
  switch (value.kind) {
10949
11222
  case "eventSeries": {
10950
11223
  const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
@@ -10956,7 +11229,7 @@ function parseEventPageSurfaceSubject(value) {
10956
11229
  kind: "invalidEventSeriesBookingScope",
10957
11230
  bookingScope: value.bookingScope
10958
11231
  });
10959
- return ok(createEventSeriesPageSurfaceSubject(eventSeriesId.value, value.bookingScope));
11232
+ return ok(createEventSeriesPageSurfaceSubject(eventSeriesId.value, value.bookingScope, parseEventPageSurfaceDestinationMode(value.eventDestinationMode)));
10960
11233
  }
10961
11234
  case "eventOffering": {
10962
11235
  const eventOfferingId = parseEventOfferingId(value.eventOfferingId);
@@ -10964,24 +11237,22 @@ function parseEventPageSurfaceSubject(value) {
10964
11237
  kind: "invalidEventOfferingId",
10965
11238
  error: eventOfferingId.error
10966
11239
  });
10967
- if (!Array.isArray(value.availableEventSeriesIds)) return err({
10968
- kind: "unsupportedSubject",
10969
- subjectKind: value.kind
11240
+ if (!Array.isArray(value.catalogueEventSeriesIds)) return err({
11241
+ kind: "invalidEventOfferingCatalogue",
11242
+ catalogue: value.catalogueEventSeriesIds
10970
11243
  });
10971
- const parsedSeriesIds = [];
10972
- for (const valueId of value.availableEventSeriesIds) {
10973
- const eventSeriesId = parseEventSeriesId(valueId);
10974
- if (!eventSeriesId.ok) return err({
10975
- kind: "invalidEventSeriesId",
10976
- error: eventSeriesId.error
10977
- });
10978
- parsedSeriesIds.push(eventSeriesId.value);
10979
- }
10980
- return ok({
10981
- kind: "eventOffering",
10982
- eventOfferingId: eventOfferingId.value,
10983
- availableEventSeriesIds: parsedSeriesIds
11244
+ if (value.bookingScope !== "single_occurrence" && value.bookingScope !== "whole_series") return err({
11245
+ kind: "invalidEventOfferingBookingScope",
11246
+ bookingScope: value.bookingScope
10984
11247
  });
11248
+ const parsedCatalogueIds = parseEventSeriesIdList(value.catalogueEventSeriesIds);
11249
+ if (!parsedCatalogueIds.ok) return parsedCatalogueIds;
11250
+ const eventDestinationMode = parseEventPageSurfaceDestinationMode(value.eventDestinationMode);
11251
+ return ok(createEventOfferingPageSurfaceSubject(eventOfferingId.value, {
11252
+ catalogueEventSeriesIds: parsedCatalogueIds.value,
11253
+ bookingScope: value.bookingScope,
11254
+ ...eventDestinationMode ? { eventDestinationMode } : {}
11255
+ }));
10985
11256
  }
10986
11257
  default: return err({
10987
11258
  kind: "unsupportedSubject",
@@ -10989,7 +11260,19 @@ function parseEventPageSurfaceSubject(value) {
10989
11260
  });
10990
11261
  }
10991
11262
  }
10992
- function isRecord$6(value) {
11263
+ function parseEventSeriesIdList(values) {
11264
+ const parsed = [];
11265
+ for (const value of values) {
11266
+ const eventSeriesId = parseEventSeriesId(value);
11267
+ if (!eventSeriesId.ok) return err({
11268
+ kind: "invalidEventSeriesId",
11269
+ error: eventSeriesId.error
11270
+ });
11271
+ parsed.push(eventSeriesId.value);
11272
+ }
11273
+ return ok(parsed);
11274
+ }
11275
+ function isRecord$5(value) {
10993
11276
  return typeof value === "object" && value !== null && !Array.isArray(value);
10994
11277
  }
10995
11278
  //#endregion
@@ -11163,27 +11446,21 @@ function toLocationCoordinates(value) {
11163
11446
  function parseNewsletterSignupDestinationProvider(value) {
11164
11447
  return value === "riverbank" || value === "mailchimp" ? value : null;
11165
11448
  }
11166
- //#endregion
11167
- //#region ../core/src/planner.ts
11168
- /** Default clock for production callers that do not inject time explicitly. */
11169
- const systemPlanningClock = { now: () => Date.now() };
11170
- /** Resolve current time as a Date from an explicit Date, injected clock, or system clock. */
11171
- function resolvePlanningNowDate(input = {}) {
11172
- if (input.now !== void 0) return input.now;
11173
- return new Date((input.clock ?? systemPlanningClock).now());
11449
+ function sessionStartMs(session) {
11450
+ return Date.parse(session.startsAt);
11174
11451
  }
11175
11452
  /**
11176
- * Resolve a Date-compatible planner input.
11453
+ * The run's sessions that still count, in schedule order.
11177
11454
  *
11178
- * Precedence: bare Date, `{ now }`, `{ clock }`, then `systemPlanningClock`.
11179
- * Explicit Date inputs are returned by reference, not cloned.
11455
+ * Sessions whose start cannot be read are dropped rather than sorted to an
11456
+ * arbitrary end: an unparseable date is not a date a visitor can attend.
11180
11457
  */
11181
- function resolvePlanningDateInput(input = {}) {
11182
- if (input instanceof Date) return input;
11183
- return resolvePlanningNowDate(input);
11458
+ function orderedLiveRunSessions(sessions) {
11459
+ return sessions.filter((session) => session.status !== "cancelled" && Number.isFinite(sessionStartMs(session))).sort((left, right) => sessionStartMs(left) - sessionStartMs(right));
11184
11460
  }
11185
11461
  //#endregion
11186
11462
  //#region ../core/src/event-series-behaviour.ts
11463
+ const WHOLE_SERIES_EVENT_PRESET_VALUES = ["course", "term"];
11187
11464
  const SURFACE_EVENT_PRESET_VALUES = [
11188
11465
  "class",
11189
11466
  "course",
@@ -21060,296 +21337,51 @@ const bookingRequirementConsentFieldSchema = z.object({
21060
21337
  });
21061
21338
  z.union([blockBookingConsentSchema, bookingRequirementConsentFieldSchema]);
21062
21339
  //#endregion
21063
- //#region ../blocks/src/system/blocks/events/whole-series/pricing.ts
21064
- function isSaleWindowOpen(option, now) {
21065
- if (!option.isActive) return false;
21066
- if (option.saleStartsAt && new Date(option.saleStartsAt) > now) return false;
21067
- if (option.saleEndsAt && new Date(option.saleEndsAt) < now) return false;
21068
- return true;
21069
- }
21070
- function toExactOrFreeDisplay(amount, currency) {
21071
- if (amount <= 0) return {
21072
- kind: "free",
21073
- currency
21074
- };
21075
- return {
21076
- kind: "exact",
21077
- amount,
21078
- currency
21079
- };
21080
- }
21081
- function getSelectableWholeSeriesPricingOptionsForNow(offering, now) {
21082
- if (offering.pricing.pricingStrategy !== "tiered") return [];
21083
- return [...offering.pricing.options].filter((option) => isSaleWindowOpen(option, now)).sort((left, right) => {
21084
- if (left.sortOrder !== right.sortOrder) return left.sortOrder - right.sortOrder;
21085
- if (left.priceAmount !== right.priceAmount) return left.priceAmount - right.priceAmount;
21086
- return left.name.localeCompare(right.name);
21087
- });
21088
- }
21089
- function resolveWholeSeriesPricingState(offering, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
21090
- const selection = normalizePricingSelectionInput(selectedSlidingAmountOrNowInput, nowInput);
21091
- const currency = offering.pricing.currency;
21092
- switch (offering.pricing.pricingStrategy) {
21093
- case "free": return resolveFreePricing(currency);
21094
- case "single": return resolveSinglePricing(offering.pricing.singlePriceAmount ?? 0, currency);
21095
- case "tiered": return resolveTieredPricing(offering, selectedPricingOptionId, selection.nowInput);
21096
- case "sliding_scale": return resolveSlidingScalePricing(offering, selection.selectedSlidingAmount);
21097
- }
21098
- }
21099
- function normalizePricingSelectionInput(selectedSlidingAmountOrNowInput, nowInput) {
21100
- return typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? {
21101
- selectedSlidingAmount: null,
21102
- nowInput: selectedSlidingAmountOrNowInput
21103
- } : {
21104
- selectedSlidingAmount: typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null,
21105
- nowInput
21106
- };
21107
- }
21108
- function resolveFreePricing(currency) {
21109
- return {
21110
- currency,
21111
- display: {
21112
- kind: "free",
21113
- currency
21114
- },
21115
- selectableOptions: [],
21116
- requiresSelection: false,
21117
- selectedOption: null,
21118
- slidingScale: null,
21119
- selectedSlidingAmount: null,
21120
- selectedPriceAmount: 0,
21121
- selectedRequiresPayment: false,
21122
- hasPaidSelection: false,
21123
- hasFreeSelection: true
21124
- };
21125
- }
21126
- function resolveSinglePricing(amount, currency) {
21127
- return {
21128
- currency,
21129
- display: toExactOrFreeDisplay(amount, currency),
21130
- selectableOptions: [],
21131
- requiresSelection: false,
21132
- selectedOption: null,
21133
- slidingScale: null,
21134
- selectedSlidingAmount: null,
21135
- selectedPriceAmount: amount,
21136
- selectedRequiresPayment: amount > 0,
21137
- hasPaidSelection: amount > 0,
21138
- hasFreeSelection: amount <= 0
21139
- };
21140
- }
21141
- function resolveTieredPricing(offering, selectedPricingOptionId, nowInput) {
21142
- const currency = offering.pricing.currency;
21143
- const selectableOptions = getSelectableWholeSeriesPricingOptionsForNow(offering, resolvePlanningDateInput(nowInput));
21144
- const selectedOption = resolveSelectedTier(selectableOptions, selectedPricingOptionId);
21145
- return {
21146
- currency,
21147
- display: resolveTieredDisplay(selectableOptions.reduce((lowest, option) => lowest === null || option.priceAmount < lowest ? option.priceAmount : lowest, null), selectableOptions.length, currency),
21148
- selectableOptions,
21149
- requiresSelection: selectableOptions.length > 1,
21150
- selectedOption,
21151
- slidingScale: null,
21152
- selectedSlidingAmount: null,
21153
- selectedPriceAmount: selectedOption?.priceAmount ?? null,
21154
- selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
21155
- hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
21156
- hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
21157
- };
21158
- }
21159
- function resolveSelectedTier(options, selectedId) {
21160
- return (selectedId ? options.find((option) => option.id === selectedId) : null) ?? (options.length === 1 ? options[0] ?? null : null);
21161
- }
21162
- function resolveTieredDisplay(lowestAmount, optionCount, currency) {
21163
- if (lowestAmount === null) return {
21164
- kind: "unavailable",
21165
- currency
21166
- };
21167
- return optionCount > 1 && lowestAmount > 0 ? {
21168
- kind: "from",
21169
- amount: lowestAmount,
21170
- currency
21171
- } : toExactOrFreeDisplay(lowestAmount, currency);
21172
- }
21173
- function resolveSlidingScalePricing(offering, selectedSlidingAmount) {
21174
- const currency = offering.pricing.currency;
21175
- const minAmount = offering.pricing.slidingMinAmount ?? null;
21176
- const maxAmount = offering.pricing.slidingMaxAmount ?? null;
21177
- if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) return unavailableSlidingScale(currency);
21178
- const selectedAmount = Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
21179
- return {
21180
- currency,
21181
- display: {
21182
- kind: "range",
21183
- minAmount,
21184
- maxAmount,
21185
- currency
21186
- },
21187
- selectableOptions: [],
21188
- requiresSelection: selectedAmount === null,
21189
- selectedOption: null,
21190
- slidingScale: {
21191
- minAmount,
21192
- maxAmount,
21193
- suggestedAmount: offering.pricing.slidingSuggestedAmount ?? null
21194
- },
21195
- selectedSlidingAmount: selectedAmount,
21196
- selectedPriceAmount: selectedAmount,
21197
- selectedRequiresPayment: (selectedAmount ?? 0) > 0,
21198
- hasPaidSelection: maxAmount > 0,
21199
- hasFreeSelection: minAmount === 0
21200
- };
21201
- }
21202
- function unavailableSlidingScale(currency) {
21203
- return {
21204
- currency,
21205
- display: {
21206
- kind: "unavailable",
21207
- currency
21208
- },
21209
- selectableOptions: [],
21210
- requiresSelection: true,
21211
- selectedOption: null,
21212
- slidingScale: null,
21213
- selectedSlidingAmount: null,
21214
- selectedPriceAmount: null,
21215
- selectedRequiresPayment: false,
21216
- hasPaidSelection: false,
21217
- hasFreeSelection: false
21218
- };
21219
- }
21220
- //#endregion
21221
- //#region ../blocks/src/system/blocks/events/whole-series/schemas.ts
21222
- const wholeSeriesVenueSchema = z.object({
21340
+ //#region ../blocks/src/system/blocks/events/shared/schemas.ts
21341
+ const eventPresetSchema = z.enum([
21342
+ "event",
21343
+ "class",
21344
+ "course",
21345
+ "term",
21346
+ "workshop",
21347
+ "retreat",
21348
+ "performance"
21349
+ ]);
21350
+ const eventScheduleScopeSchema$2 = z.enum(["recurring", "oneOff"]);
21351
+ const publicEventRecurrenceSchema = z.discriminatedUnion("kind", [z.object({
21352
+ kind: z.literal("weekly"),
21353
+ interval: z.number().int().positive(),
21354
+ weekdays: z.array(z.enum([
21355
+ "MO",
21356
+ "TU",
21357
+ "WE",
21358
+ "TH",
21359
+ "FR",
21360
+ "SA",
21361
+ "SU"
21362
+ ]))
21363
+ }).readonly(), z.object({ kind: z.literal("other") }).readonly()]);
21364
+ const eventDestinationModeSchema = z.enum(["cms-managed", "system-managed"]);
21365
+ const publicEventDestinationSchema = z.discriminatedUnion("kind", [z.object({
21366
+ kind: z.literal("native"),
21367
+ mode: eventDestinationModeSchema,
21368
+ path: z.string()
21369
+ }), z.object({
21370
+ kind: z.literal("external"),
21371
+ url: z.string(),
21372
+ label: z.string()
21373
+ })]);
21374
+ /**
21375
+ * Zod schema for venue data
21376
+ */
21377
+ const eventVenueSchema = z.object({
21223
21378
  id: z.string(),
21224
21379
  name: z.string(),
21225
- address: z.string().nullable()
21226
- });
21227
- const wholeSeriesSessionSchema = z.object({
21228
- id: z.string(),
21229
- startsAt: z.string(),
21230
- endsAt: z.string(),
21231
- timeZone: z.string(),
21232
- capacityOverride: z.number().nullable().optional(),
21233
- overrides: z.record(z.string(), z.unknown()).nullable().optional()
21234
- });
21235
- const wholeSeriesTeamMemberSummarySchema = z.object({
21236
- id: z.string(),
21237
- name: z.string(),
21238
- roleLabel: z.string().nullable(),
21239
- summary: z.string().nullable(),
21240
- profilePath: z.string().nullable()
21241
- });
21242
- const wholeSeriesPricingOptionSchema = z.object({
21243
- id: z.string(),
21244
- name: z.string(),
21245
- description: z.string().nullable(),
21246
- priceAmount: z.number(),
21247
- isActive: z.boolean(),
21248
- sortOrder: z.number(),
21249
- capacityLimit: z.number().nullable(),
21250
- saleStartsAt: z.string().nullable(),
21251
- saleEndsAt: z.string().nullable(),
21252
- attendanceScope: z.enum([
21253
- "in_person",
21254
- "online",
21255
- "both"
21256
- ]).nullable().optional()
21257
- });
21258
- const wholeSeriesPricingSchema = z.object({
21259
- bookingRequirement: z.enum(["none", "required"]),
21260
- pricingStrategy: z.enum([
21261
- "free",
21262
- "single",
21263
- "tiered",
21264
- "sliding_scale"
21265
- ]),
21266
- currency: z.string(),
21267
- singlePriceAmount: z.number().nullable(),
21268
- slidingMinAmount: z.number().nullable().optional(),
21269
- slidingMaxAmount: z.number().nullable().optional(),
21270
- slidingSuggestedAmount: z.number().nullable().optional(),
21271
- paymentTerms: blockBookingPaymentTermsSchema,
21272
- options: z.array(wholeSeriesPricingOptionSchema)
21273
- });
21274
- const publicWholeSeriesOfferingSchema = z.object({
21275
- eventSeriesId: z.string(),
21276
- eventOfferingId: z.string(),
21277
- title: z.string(),
21278
- slug: z.string(),
21279
- description: z.unknown().nullable(),
21280
- deliveryMode: z.enum([
21281
- "in_person",
21282
- "online",
21283
- "hybrid"
21284
- ]),
21285
- waitlistEnabled: z.boolean(),
21286
- requireGuestDetails: z.boolean(),
21287
- teamMembers: z.array(wholeSeriesTeamMemberSummarySchema).optional(),
21288
- enrollmentOpen: z.boolean(),
21289
- pricing: wholeSeriesPricingSchema,
21290
- currency: z.string(),
21291
- paymentTerms: blockBookingPaymentTermsSchema,
21292
- consent: blockBookingConsentSchema.nullable(),
21293
- enrollmentCapacity: z.number().nullable(),
21294
- acceptsMemberships: z.boolean(),
21295
- status: z.enum([
21296
- "active",
21297
- "draft",
21298
- "cancelled"
21299
- ]),
21300
- sessionsCount: z.number(),
21301
- enrolledCount: z.number(),
21302
- availableSpots: z.number().nullable(),
21303
- sessions: z.array(wholeSeriesSessionSchema),
21304
- venue: wholeSeriesVenueSchema.nullable()
21305
- });
21306
- const publicWholeSeriesOfferingsArraySchema = z.array(publicWholeSeriesOfferingSchema);
21307
- //#endregion
21308
- //#region ../blocks/src/system/blocks/events/shared/schemas.ts
21309
- const eventPresetSchema = z.enum([
21310
- "event",
21311
- "class",
21312
- "course",
21313
- "term",
21314
- "workshop",
21315
- "retreat",
21316
- "performance"
21317
- ]);
21318
- const eventScheduleScopeSchema$2 = z.enum(["recurring", "oneOff"]);
21319
- const publicEventRecurrenceSchema = z.discriminatedUnion("kind", [z.object({
21320
- kind: z.literal("weekly"),
21321
- interval: z.number().int().positive(),
21322
- weekdays: z.array(z.enum([
21323
- "MO",
21324
- "TU",
21325
- "WE",
21326
- "TH",
21327
- "FR",
21328
- "SA",
21329
- "SU"
21330
- ]))
21331
- }).readonly(), z.object({ kind: z.literal("other") }).readonly()]);
21332
- const eventDestinationModeSchema = z.enum(["cms-managed", "system-managed"]);
21333
- const publicEventDestinationSchema = z.discriminatedUnion("kind", [z.object({
21334
- kind: z.literal("native"),
21335
- mode: eventDestinationModeSchema,
21336
- path: z.string()
21337
- }), z.object({
21338
- kind: z.literal("external"),
21339
- url: z.string(),
21340
- label: z.string()
21341
- })]);
21342
- /**
21343
- * Zod schema for venue data
21344
- */
21345
- const eventVenueSchema = z.object({
21346
- id: z.string(),
21347
- name: z.string(),
21348
- address: z.string().nullable(),
21349
- location: z.object({
21350
- lat: z.number(),
21351
- lng: z.number()
21352
- }).nullable()
21380
+ address: z.string().nullable(),
21381
+ location: z.object({
21382
+ lat: z.number(),
21383
+ lng: z.number()
21384
+ }).nullable()
21353
21385
  });
21354
21386
  /**
21355
21387
  * Zod schema for event category data
@@ -21359,77 +21391,14 @@ const eventCategorySchema = z.object({
21359
21391
  name: z.string(),
21360
21392
  color: z.string().nullable()
21361
21393
  });
21362
- z.enum([
21363
- "free",
21364
- "paid",
21365
- "external"
21366
- ]);
21367
21394
  /**
21368
21395
  * Access restriction type for public events
21369
21396
  */
21370
21397
  const accessRestrictionSchema = z.enum(["none", "category"]);
21371
- z.enum(["single", "ticket_types"]);
21372
- const freePriceDisplaySchema = z.object({
21373
- kind: z.literal("free"),
21374
- currency: z.string()
21375
- });
21376
- const exactPriceDisplaySchema = z.object({
21377
- kind: z.literal("exact"),
21378
- amount: z.number(),
21379
- currency: z.string()
21380
- });
21381
- const fromPriceDisplaySchema = z.object({
21382
- kind: z.literal("from"),
21383
- amount: z.number(),
21384
- currency: z.string()
21385
- });
21386
- const unavailablePriceDisplaySchema = z.object({
21387
- kind: z.literal("unavailable"),
21388
- currency: z.string()
21389
- });
21390
- const rangePriceDisplaySchema = z.object({
21391
- kind: z.literal("range"),
21392
- minAmount: z.number(),
21393
- maxAmount: z.number(),
21394
- currency: z.string()
21395
- });
21396
- const mixedPriceDisplaySchema = z.object({
21397
- kind: z.literal("mixed"),
21398
- paidFromAmount: z.number(),
21399
- paidToAmount: z.number(),
21400
- currency: z.string()
21401
- });
21402
- const publicWholeSeriesPriceDisplaySchema = z.discriminatedUnion("kind", [
21403
- freePriceDisplaySchema,
21404
- exactPriceDisplaySchema,
21405
- fromPriceDisplaySchema,
21406
- rangePriceDisplaySchema,
21407
- unavailablePriceDisplaySchema
21408
- ]);
21409
- z.discriminatedUnion("kind", [
21410
- freePriceDisplaySchema,
21411
- exactPriceDisplaySchema,
21412
- fromPriceDisplaySchema,
21413
- rangePriceDisplaySchema,
21414
- mixedPriceDisplaySchema,
21415
- unavailablePriceDisplaySchema,
21416
- z.object({
21417
- kind: z.literal("external"),
21418
- label: z.string()
21419
- }),
21420
- z.object({
21421
- kind: z.literal("whole_series"),
21422
- display: publicWholeSeriesPriceDisplaySchema
21423
- })
21424
- ]);
21425
- const publicEventTicketTypePriceDisplaySchema = z.union([
21426
- freePriceDisplaySchema,
21427
- exactPriceDisplaySchema,
21428
- fromPriceDisplaySchema,
21429
- rangePriceDisplaySchema,
21430
- mixedPriceDisplaySchema,
21431
- unavailablePriceDisplaySchema
21432
- ]);
21398
+ const publicCurrencySchema = z.string().regex(/^[A-Z]{3}$/u);
21399
+ const publicCentsSchema = z.number().int().nonnegative();
21400
+ const publicPositiveCentsSchema = z.number().int().positive();
21401
+ const publicIsoDateTimeSchema = z.string().datetime({ offset: true });
21433
21402
  const publicEventAttendanceModeSchema = z.enum(["in_person", "online"]);
21434
21403
  const publicEventAttendanceModeAvailabilitySchema = z.object({
21435
21404
  mode: publicEventAttendanceModeSchema,
@@ -21438,9 +21407,9 @@ const publicEventAttendanceModeAvailabilitySchema = z.object({
21438
21407
  availableSpots: z.number().nullable(),
21439
21408
  waitlistEnabled: z.boolean()
21440
21409
  });
21441
- const publicEventTicketTypeAvailabilitySchema = z.union([z.object({
21410
+ const publicEventPricingOptionAvailabilitySchema = z.union([z.object({
21442
21411
  kind: z.literal("available"),
21443
- remainingCapacity: z.number().nullable()
21412
+ remainingPlaces: z.number().int().nonnegative().nullable()
21444
21413
  }), z.object({
21445
21414
  kind: z.literal("unavailable"),
21446
21415
  reason: z.enum([
@@ -21448,91 +21417,69 @@ const publicEventTicketTypeAvailabilitySchema = z.union([z.object({
21448
21417
  "not_on_sale_yet",
21449
21418
  "sale_ended",
21450
21419
  "sold_out",
21451
- "event_sold_out"
21420
+ "attendance_mode_unavailable",
21421
+ "overallCapacityUnavailable"
21452
21422
  ]),
21453
- remainingCapacity: z.number().nullable()
21423
+ remainingPlaces: z.number().int().nonnegative().nullable()
21454
21424
  })]);
21455
- const publicEventTicketTypeSchema = z.object({
21456
- id: z.string(),
21457
- siteId: z.string(),
21458
- eventSeriesId: z.string(),
21459
- name: z.string(),
21425
+ const publicEventPricingOptionSchema = z.object({
21426
+ id: z.string().min(1),
21427
+ name: z.string().min(1),
21460
21428
  description: z.string().nullable(),
21461
- priceAmount: z.number(),
21429
+ priceAmount: publicCentsSchema,
21462
21430
  isActive: z.boolean(),
21463
- sortOrder: z.number(),
21464
- capacityMode: z.enum(["limited", "unlimited"]),
21465
- capacityLimit: z.number().nullable(),
21431
+ sortOrder: z.number().int().nonnegative(),
21466
21432
  attendanceScope: z.enum([
21467
21433
  "in_person",
21468
21434
  "online",
21469
21435
  "both"
21470
- ]).optional(),
21471
- saleStartsAt: z.string().nullable(),
21472
- saleEndsAt: z.string().nullable(),
21473
- availability: publicEventTicketTypeAvailabilitySchema,
21474
- createdAt: z.string(),
21475
- updatedAt: z.string()
21436
+ ]),
21437
+ saleStartsAt: publicIsoDateTimeSchema.nullable(),
21438
+ saleEndsAt: publicIsoDateTimeSchema.nullable(),
21439
+ availability: publicEventPricingOptionAvailabilitySchema
21440
+ }).superRefine((option, context) => {
21441
+ if (option.saleStartsAt && option.saleEndsAt && Date.parse(option.saleEndsAt) <= Date.parse(option.saleStartsAt)) context.addIssue({
21442
+ code: "custom",
21443
+ path: ["saleEndsAt"],
21444
+ message: "Sale end must be after sale start"
21445
+ });
21476
21446
  });
21477
21447
  const publicEventPricingSchema = z.discriminatedUnion("kind", [
21478
21448
  z.object({
21479
- kind: z.literal("drop_in"),
21480
- currency: z.string(),
21481
- display: z.object({
21482
- kind: z.literal("free"),
21483
- currency: z.string()
21484
- })
21485
- }),
21486
- z.object({
21487
- kind: z.literal("free_registration"),
21488
- currency: z.string(),
21489
- display: z.object({
21490
- kind: z.literal("free"),
21491
- currency: z.string()
21492
- })
21449
+ kind: z.literal("free"),
21450
+ currency: publicCurrencySchema
21493
21451
  }),
21494
21452
  z.object({
21495
- kind: z.literal("single_paid"),
21496
- amount: z.number(),
21497
- currency: z.string(),
21498
- display: z.object({
21499
- kind: z.literal("exact"),
21500
- amount: z.number(),
21501
- currency: z.string()
21502
- })
21453
+ kind: z.literal("single"),
21454
+ amount: publicPositiveCentsSchema,
21455
+ currency: publicCurrencySchema
21503
21456
  }),
21504
21457
  z.object({
21505
- kind: z.literal("ticket_types"),
21506
- currency: z.string(),
21507
- ticketTypes: z.array(publicEventTicketTypeSchema),
21508
- display: publicEventTicketTypePriceDisplaySchema
21458
+ kind: z.literal("tiered"),
21459
+ currency: publicCurrencySchema,
21460
+ options: z.tuple([publicEventPricingOptionSchema], publicEventPricingOptionSchema)
21509
21461
  }),
21510
21462
  z.object({
21511
21463
  kind: z.literal("sliding_scale"),
21512
- minAmount: z.number(),
21513
- maxAmount: z.number(),
21514
- suggestedAmount: z.number().nullable(),
21515
- currency: z.string(),
21516
- display: z.object({
21517
- kind: z.literal("range"),
21518
- minAmount: z.number(),
21519
- maxAmount: z.number(),
21520
- currency: z.string()
21521
- })
21522
- }),
21523
- z.object({
21524
- kind: z.literal("whole_series"),
21525
- display: z.object({
21526
- kind: z.literal("whole_series"),
21527
- display: publicWholeSeriesPriceDisplaySchema
21528
- })
21464
+ minimum: publicCentsSchema,
21465
+ maximum: publicPositiveCentsSchema,
21466
+ suggested: publicCentsSchema.nullable(),
21467
+ currency: publicCurrencySchema
21468
+ }).superRefine((pricing, context) => {
21469
+ if (pricing.minimum > pricing.maximum) context.addIssue({
21470
+ code: "custom",
21471
+ path: ["minimum"],
21472
+ message: "Minimum must not exceed maximum"
21473
+ });
21474
+ if (pricing.suggested !== null && (pricing.suggested < pricing.minimum || pricing.suggested > pricing.maximum)) context.addIssue({
21475
+ code: "custom",
21476
+ path: ["suggested"],
21477
+ message: "Suggested amount must be within the sliding-scale range"
21478
+ });
21529
21479
  }),
21530
21480
  z.object({
21531
21481
  kind: z.literal("external"),
21532
- display: z.object({
21533
- kind: z.literal("external"),
21534
- label: z.string()
21535
- })
21482
+ label: z.string().min(1)
21536
21483
  })
21537
21484
  ]);
21538
21485
  const publicTeamMemberSummarySchema = z.object({
@@ -21558,11 +21505,30 @@ const publicEventBookingAvailabilitySchema = z.discriminatedUnion("kind", [z.obj
21558
21505
  "enrollment_closed"
21559
21506
  ])
21560
21507
  })]);
21508
+ const publicRunSessionSchema = z.object({
21509
+ occurrenceId: z.string(),
21510
+ startsAt: z.string(),
21511
+ endsAt: z.string(),
21512
+ timeZone: z.string(),
21513
+ status: z.string()
21514
+ });
21515
+ const publicWholeSeriesRunSchema = z.object({
21516
+ eventSeriesId: z.string(),
21517
+ eventOfferingId: z.string(),
21518
+ enrollmentOpen: z.boolean(),
21519
+ visibility: z.enum(["public", "unlisted"]),
21520
+ lifecycle: z.enum([
21521
+ "upcoming",
21522
+ "in_progress",
21523
+ "completed",
21524
+ "cancelled"
21525
+ ]),
21526
+ sessions: z.array(publicRunSessionSchema)
21527
+ });
21561
21528
  /**
21562
- * Zod schema for public event data
21529
+ * Zod schema for the fields shared by both booking scopes.
21563
21530
  */
21564
- const publicEventSchema = z.object({
21565
- bookingScope: z.enum(["single_occurrence", "whole_series"]),
21531
+ const publicEventBaseSchema = z.object({
21566
21532
  eventPreset: eventPresetSchema.optional(),
21567
21533
  eventDestinationMode: eventDestinationModeSchema.optional(),
21568
21534
  scheduleScope: eventScheduleScopeSchema$2.optional(),
@@ -21612,20 +21578,68 @@ const publicEventSchema = z.object({
21612
21578
  accessRestriction: accessRestrictionSchema,
21613
21579
  allowedCategoryIds: z.array(z.string()),
21614
21580
  requireGuestDetails: z.boolean().optional(),
21615
- acceptsPasses: z.boolean().optional(),
21616
- acceptsMemberships: z.boolean().optional(),
21617
- wholeSeries: z.object({
21618
- eventSeriesId: z.string(),
21619
- pricing: wholeSeriesPricingSchema,
21620
- currency: z.string(),
21621
- enrollmentOpen: z.boolean()
21622
- }).nullable().optional()
21581
+ acceptsPasses: z.boolean(),
21582
+ acceptsMemberships: z.boolean()
21623
21583
  });
21624
21584
  /**
21585
+ * Zod schema for public event data.
21586
+ *
21587
+ * The booking scope discriminates: a `whole_series` record without complete
21588
+ * `run` facts is rejected, and a `single_occurrence` record never carries them.
21589
+ */
21590
+ const publicEventSchema = z.union([publicEventBaseSchema.extend({
21591
+ bookingScope: z.literal("single_occurrence"),
21592
+ run: z.undefined().optional()
21593
+ }), publicEventBaseSchema.extend({
21594
+ bookingScope: z.literal("whole_series"),
21595
+ run: publicWholeSeriesRunSchema
21596
+ })]);
21597
+ /**
21625
21598
  * Schema for an array of public events
21626
21599
  */
21627
21600
  const publicEventsArraySchema = z.array(publicEventSchema);
21628
21601
  //#endregion
21602
+ //#region ../blocks/src/system/blocks/events/shared/runGrouping.ts
21603
+ function isWholeSeriesPublicEvent(event) {
21604
+ return event.bookingScope === "whole_series";
21605
+ }
21606
+ /**
21607
+ * Group events into one entry per whole-series run.
21608
+ *
21609
+ * Single-occurrence events are ignored. Run order follows first appearance, so
21610
+ * a caller's sort survives the grouping, and an occurrence that arrives twice
21611
+ * is kept once.
21612
+ */
21613
+ function groupPublicEventsByRun(events) {
21614
+ const occurrencesBySeriesId = /* @__PURE__ */ new Map();
21615
+ const order = [];
21616
+ const seenOccurrenceIds = /* @__PURE__ */ new Set();
21617
+ for (const event of events) {
21618
+ if (!isWholeSeriesPublicEvent(event)) continue;
21619
+ if (seenOccurrenceIds.has(event.occurrenceId)) continue;
21620
+ seenOccurrenceIds.add(event.occurrenceId);
21621
+ const seriesId = event.run.eventSeriesId;
21622
+ const existing = occurrencesBySeriesId.get(seriesId);
21623
+ if (existing) {
21624
+ existing.push(event);
21625
+ continue;
21626
+ }
21627
+ occurrencesBySeriesId.set(seriesId, [event]);
21628
+ order.push(seriesId);
21629
+ }
21630
+ return order.map((eventSeriesId) => {
21631
+ const occurrences = occurrencesBySeriesId.get(eventSeriesId) ?? [];
21632
+ const representative = occurrences[0];
21633
+ if (!representative) throw new Error(`Run ${eventSeriesId} grouped without any occurrence`);
21634
+ return {
21635
+ eventSeriesId,
21636
+ run: representative.run,
21637
+ occurrences,
21638
+ representative
21639
+ };
21640
+ });
21641
+ }
21642
+ //#endregion
21629
21643
  //#region ../blocks/src/system/blocks/events/shared/fields.ts
21630
21644
  /**
21631
21645
  * Shared card styling fields for event blocks
@@ -21675,7 +21689,7 @@ const eventDisplayFields = [
21675
21689
  {
21676
21690
  id: "showCapacity",
21677
21691
  type: "boolean",
21678
- label: "Show available spots",
21692
+ label: "Show available places",
21679
21693
  description: "Display remaining capacity",
21680
21694
  required: false,
21681
21695
  defaultValue: true,
@@ -21906,7 +21920,9 @@ const unsupportedEventRegistrationPageSurfaceSubjectSchema = z.object({
21906
21920
  "unsupportedSubject",
21907
21921
  "invalidEventSeriesId",
21908
21922
  "invalidEventSeriesBookingScope",
21909
- "invalidEventOfferingId"
21923
+ "invalidEventOfferingId",
21924
+ "invalidEventOfferingBookingScope",
21925
+ "invalidEventOfferingCatalogue"
21910
21926
  ])
21911
21927
  });
21912
21928
  const eventRegistrationPageSurfaceSubjectSchema = z.unknown().transform((value, ctx) => {
@@ -21933,7 +21949,7 @@ function resolveEventRegistrationScope(context) {
21933
21949
  if (context.subject?.kind === "eventOffering") return {
21934
21950
  kind: "pageSurfaceOffering",
21935
21951
  offeringId: context.subject.eventOfferingId,
21936
- seriesIds: context.subject.availableEventSeriesIds
21952
+ seriesIds: context.subject.catalogueEventSeriesIds
21937
21953
  };
21938
21954
  if (context.subject?.kind === "unsupported") return {
21939
21955
  kind: "unsupportedPageSurfaceSubject",
@@ -21955,31 +21971,12 @@ function resolveEventRegistrationScopedEvents(events, context) {
21955
21971
  }
21956
21972
  }
21957
21973
  //#endregion
21958
- //#region ../blocks/src/system/runtime/nodes/event-registration/registrationSurface.ts
21959
- function planEventRegistrationScope(input) {
21960
- const subject = input.subject;
21961
- const selectedRunOffering = input.wholeSeriesOffering;
21962
- if (subject?.kind !== "eventOffering" || !selectedRunOffering) return {
21963
- kind: "context",
21964
- events: resolveEventRegistrationScopedEvents(input.events, {
21965
- occurrenceContext: input.occurrenceContext,
21966
- subject
21967
- })
21968
- };
21969
- if (!(selectedRunOffering.eventOfferingId === subject.eventOfferingId && subject.availableEventSeriesIds.some((seriesId) => seriesId === selectedRunOffering.eventSeriesId))) return { kind: "invalidSelectedRun" };
21970
- return {
21971
- kind: "selectedRun",
21972
- events: input.events.filter((event) => event.seriesId === selectedRunOffering.eventSeriesId),
21973
- offering: selectedRunOffering
21974
- };
21975
- }
21976
- //#endregion
21977
- //#region ../blocks/src/system/runtime/nodes/events/shared/destination.ts
21978
- function isRecord$5(value) {
21974
+ //#region ../blocks/src/system/runtime/nodes/events/domain/destination.ts
21975
+ function isRecord$4(value) {
21979
21976
  return typeof value === "object" && value !== null && !Array.isArray(value);
21980
21977
  }
21981
21978
  function isRuntimeEventDestination(value) {
21982
- if (!isRecord$5(value) || typeof value.kind !== "string") return false;
21979
+ if (!isRecord$4(value) || typeof value.kind !== "string") return false;
21983
21980
  if (value.kind === "native") return (value.mode === "cms-managed" || value.mode === "system-managed") && typeof value.path === "string";
21984
21981
  return value.kind === "external" && typeof value.url === "string" && typeof value.label === "string";
21985
21982
  }
@@ -21992,174 +21989,6 @@ function resolveRuntimeEventDestination(event) {
21992
21989
  };
21993
21990
  }
21994
21991
  //#endregion
21995
- //#region ../blocks/src/system/runtime/nodes/events/shared/pricing.ts
21996
- const DEFAULT_EVENT_CURRENCY = "USD";
21997
- function resolveRuntimeEventPricing(event) {
21998
- if (isPublicEventPricing(event.pricing)) return event.pricing;
21999
- if (resolveRuntimeEventDestination(event).kind === "external") return {
22000
- kind: "external",
22001
- display: {
22002
- kind: "external",
22003
- label: "External registration"
22004
- }
22005
- };
22006
- const legacy = event;
22007
- const currency = readCurrency(legacy.currency);
22008
- if (event.requiresRegistration === false) return {
22009
- kind: "drop_in",
22010
- currency,
22011
- display: {
22012
- kind: "free",
22013
- currency
22014
- }
22015
- };
22016
- if (legacy.pricingMode === "ticket_types") return {
22017
- kind: "ticket_types",
22018
- currency,
22019
- ticketTypes: Array.isArray(legacy.ticketTypes) ? legacy.ticketTypes.filter(isPublicEventTicketType) : [],
22020
- display: readTicketTypePriceDisplay(legacy.priceDisplay, currency)
22021
- };
22022
- const amount = typeof legacy.price === "number" ? legacy.price : 0;
22023
- if (legacy.pricingType === "paid" && amount > 0) return {
22024
- kind: "single_paid",
22025
- amount,
22026
- currency,
22027
- display: {
22028
- kind: "exact",
22029
- amount,
22030
- currency
22031
- }
22032
- };
22033
- return {
22034
- kind: "free_registration",
22035
- currency,
22036
- display: {
22037
- kind: "free",
22038
- currency
22039
- }
22040
- };
22041
- }
22042
- function readCurrency(value) {
22043
- return typeof value === "string" && value.trim().length > 0 ? value : DEFAULT_EVENT_CURRENCY;
22044
- }
22045
- function isRecord$4(value) {
22046
- return typeof value === "object" && value !== null && !Array.isArray(value);
22047
- }
22048
- function isPublicEventPricing(value) {
22049
- if (!isRecord$4(value) || typeof value.kind !== "string") return false;
22050
- return value.kind === "drop_in" || value.kind === "free_registration" || value.kind === "single_paid" || value.kind === "sliding_scale" || value.kind === "ticket_types" || value.kind === "whole_series" || value.kind === "external";
22051
- }
22052
- function isPublicEventTicketType(value) {
22053
- return isRecord$4(value) && typeof value.id === "string";
22054
- }
22055
- function readTicketTypePriceDisplay(value, currency) {
22056
- const display = readLegacyPriceDisplay(value, currency);
22057
- return display.kind === "whole_series" || display.kind === "external" ? {
22058
- kind: "unavailable",
22059
- currency
22060
- } : display;
22061
- }
22062
- function readLegacyPriceDisplay(value, currency) {
22063
- if (!isRecord$4(value) || typeof value.kind !== "string") return {
22064
- kind: "unavailable",
22065
- currency
22066
- };
22067
- const displayCurrency = readCurrency(value.currency);
22068
- switch (value.kind) {
22069
- case "free": return {
22070
- kind: "free",
22071
- currency: displayCurrency
22072
- };
22073
- case "exact": return readAmount(value.amount) !== null ? {
22074
- kind: "exact",
22075
- amount: readAmount(value.amount) ?? 0,
22076
- currency: displayCurrency
22077
- } : {
22078
- kind: "unavailable",
22079
- currency
22080
- };
22081
- case "from": return readAmount(value.amount) !== null ? {
22082
- kind: "from",
22083
- amount: readAmount(value.amount) ?? 0,
22084
- currency: displayCurrency
22085
- } : {
22086
- kind: "unavailable",
22087
- currency
22088
- };
22089
- case "range": {
22090
- const minAmount = readAmount(value.minAmount);
22091
- const maxAmount = readAmount(value.maxAmount);
22092
- return minAmount !== null && maxAmount !== null ? {
22093
- kind: "range",
22094
- minAmount,
22095
- maxAmount,
22096
- currency: displayCurrency
22097
- } : {
22098
- kind: "unavailable",
22099
- currency
22100
- };
22101
- }
22102
- case "mixed": return readAmount(value.paidFromAmount) !== null ? {
22103
- kind: "mixed",
22104
- paidFromAmount: readAmount(value.paidFromAmount) ?? 0,
22105
- paidToAmount: readAmount(value.paidToAmount) ?? readAmount(value.paidFromAmount) ?? 0,
22106
- currency: displayCurrency
22107
- } : {
22108
- kind: "unavailable",
22109
- currency
22110
- };
22111
- case "unavailable": return {
22112
- kind: "unavailable",
22113
- currency: displayCurrency
22114
- };
22115
- case "whole_series": return isRecord$4(value.display) ? {
22116
- kind: "whole_series",
22117
- display: readCoursePriceDisplay(value.display, displayCurrency)
22118
- } : {
22119
- kind: "whole_series",
22120
- display: {
22121
- kind: "unavailable",
22122
- currency: displayCurrency
22123
- }
22124
- };
22125
- default: return {
22126
- kind: "unavailable",
22127
- currency
22128
- };
22129
- }
22130
- }
22131
- function readCoursePriceDisplay(value, currency) {
22132
- switch (value.kind) {
22133
- case "free": return {
22134
- kind: "free",
22135
- currency: readCurrency(value.currency)
22136
- };
22137
- case "exact": return readAmount(value.amount) !== null ? {
22138
- kind: "exact",
22139
- amount: readAmount(value.amount) ?? 0,
22140
- currency: readCurrency(value.currency)
22141
- } : {
22142
- kind: "unavailable",
22143
- currency
22144
- };
22145
- case "from": return readAmount(value.amount) !== null ? {
22146
- kind: "from",
22147
- amount: readAmount(value.amount) ?? 0,
22148
- currency: readCurrency(value.currency)
22149
- } : {
22150
- kind: "unavailable",
22151
- currency
22152
- };
22153
- default: return {
22154
- kind: "unavailable",
22155
- currency
22156
- };
22157
- }
22158
- }
22159
- function readAmount(value) {
22160
- return typeof value === "number" && Number.isFinite(value) ? value : null;
22161
- }
22162
- //#endregion
22163
21992
  //#region ../blocks/src/system/constants/events.ts
22164
21993
  const eventCalendarDisplayModeValues = [
22165
21994
  "combined",
@@ -22191,6 +22020,10 @@ const eventCalendarListLayoutOptions = [
22191
22020
  function isEventCalendarDisplayMode(value) {
22192
22021
  return typeof value === "string" && eventCalendarDisplayModeValues.includes(value);
22193
22022
  }
22023
+ function normalizeEventCalendarDisplayMode$1(input) {
22024
+ if (isEventCalendarDisplayMode(input.variant)) return input.variant;
22025
+ return isEventCalendarDisplayMode(input.displayMode) ? input.displayMode : void 0;
22026
+ }
22194
22027
  function isEventCalendarDefaultView(value) {
22195
22028
  return typeof value === "string" && eventCalendarDefaultViewValues.includes(value);
22196
22029
  }
@@ -22260,14 +22093,13 @@ function resolveEventRequiresPayment(input) {
22260
22093
  if (input.eligibility) return input.eligibility.requiresPayment;
22261
22094
  if (input.selectedTicketType) return input.selectedTicketType.priceAmount > 0;
22262
22095
  if (!input.event) return false;
22263
- return publicEventPricingType(resolveRuntimeEventPricing(input.event)) === "paid";
22096
+ return publicEventPricingType(input.event.pricing) === "paid";
22264
22097
  }
22265
22098
  //#endregion
22266
22099
  //#region ../blocks/src/system/runtime/nodes/event-registration/registrationEventAdapter.ts
22267
22100
  function toRegistrationEvent(event) {
22268
22101
  return {
22269
22102
  ...event,
22270
- pricing: resolveRuntimeEventPricing(event),
22271
22103
  selectionId: event.id,
22272
22104
  registrationSubject: {
22273
22105
  kind: "occurrence",
@@ -22278,118 +22110,35 @@ function toRegistrationEvent(event) {
22278
22110
  function toRegistrationEvents(events) {
22279
22111
  return events.filter((event) => event.bookingScope === "single_occurrence").map(toRegistrationEvent);
22280
22112
  }
22281
- function toWholeSeriesTicketType(option) {
22282
- return {
22283
- ...option,
22284
- capacityMode: option.capacityLimit === null ? "unlimited" : "limited",
22285
- attendanceScope: option.attendanceScope ?? void 0,
22286
- availability: {
22287
- kind: "available",
22288
- remainingCapacity: option.capacityLimit
22289
- }
22290
- };
22291
- }
22292
- function toWholeSeriesPricing(offering) {
22293
- const resolved = resolveWholeSeriesPricingState(offering);
22294
- switch (offering.pricing.pricingStrategy) {
22295
- case "free": return {
22296
- kind: "free_registration",
22297
- currency: offering.currency,
22298
- display: {
22299
- kind: "free",
22300
- currency: offering.currency
22301
- }
22302
- };
22303
- case "single": {
22304
- const amount = offering.pricing.singlePriceAmount ?? 0;
22305
- return amount === 0 ? {
22306
- kind: "free_registration",
22307
- currency: offering.currency,
22308
- display: {
22309
- kind: "free",
22310
- currency: offering.currency
22311
- }
22312
- } : {
22313
- kind: "single_paid",
22314
- amount,
22315
- currency: offering.currency,
22316
- display: {
22317
- kind: "exact",
22318
- amount,
22319
- currency: offering.currency
22320
- }
22321
- };
22322
- }
22323
- case "tiered": return {
22324
- kind: "ticket_types",
22325
- currency: offering.currency,
22326
- ticketTypes: resolved.selectableOptions.map((option) => toWholeSeriesTicketType(option)),
22327
- display: resolved.display
22328
- };
22329
- case "sliding_scale": return {
22330
- kind: "sliding_scale",
22331
- minAmount: offering.pricing.slidingMinAmount ?? 0,
22332
- maxAmount: offering.pricing.slidingMaxAmount ?? 0,
22333
- suggestedAmount: offering.pricing.slidingSuggestedAmount ?? null,
22334
- currency: offering.currency,
22335
- display: {
22336
- kind: "range",
22337
- minAmount: offering.pricing.slidingMinAmount ?? 0,
22338
- maxAmount: offering.pricing.slidingMaxAmount ?? 0,
22339
- currency: offering.currency
22340
- }
22341
- };
22342
- }
22343
- }
22344
- function toAttendanceModes(offering) {
22345
- return (offering.deliveryMode === "hybrid" ? ["in_person", "online"] : [offering.deliveryMode]).map((mode) => ({
22346
- mode,
22347
- capacity: offering.enrollmentCapacity,
22348
- registeredCount: offering.enrolledCount,
22349
- availableSpots: offering.availableSpots,
22350
- waitlistEnabled: offering.waitlistEnabled
22351
- }));
22352
- }
22353
- function toWholeSeriesRegistrationEvent(offering) {
22354
- const firstSession = offering.sessions[0];
22355
- const lastSession = offering.sessions[offering.sessions.length - 1];
22113
+ /**
22114
+ * Project one whole-series run onto the registration surface.
22115
+ *
22116
+ * Capacity, pricing, payment terms and consent come straight off the canonical
22117
+ * Event record; only the schedule is widened from the single occurrence to the
22118
+ * live run. A run without live sessions has no registration event.
22119
+ */
22120
+ function toWholeSeriesRegistrationEvent(group) {
22121
+ const { representative, run } = group;
22122
+ const sessions = orderedLiveRunSessions(run.sessions);
22123
+ const firstSession = sessions[0];
22124
+ if (!firstSession) return null;
22125
+ const lastSession = sessions[sessions.length - 1] ?? firstSession;
22356
22126
  return {
22357
- selectionId: offering.eventSeriesId,
22127
+ ...representative,
22128
+ selectionId: run.eventSeriesId,
22358
22129
  registrationSubject: {
22359
22130
  kind: "wholeSeries",
22360
- eventSeriesId: offering.eventSeriesId,
22361
- sessions: offering.sessions
22362
- },
22363
- seriesId: offering.eventSeriesId,
22364
- title: offering.title,
22365
- startsAt: firstSession?.startsAt ?? "",
22366
- endsAt: lastSession?.endsAt ?? firstSession?.endsAt ?? "",
22367
- bookingAvailability: offering.enrollmentOpen ? { kind: "open" } : {
22368
- kind: "closed",
22369
- reason: "enrollment_closed"
22370
- },
22371
- deliveryMode: offering.deliveryMode,
22372
- attendanceModes: toAttendanceModes(offering),
22373
- capacity: offering.enrollmentCapacity,
22374
- registeredCount: offering.enrolledCount,
22375
- availableSpots: offering.availableSpots,
22376
- waitlistEnabled: offering.waitlistEnabled,
22377
- venue: offering.venue ? {
22378
- ...offering.venue,
22379
- location: null
22380
- } : null,
22381
- eventCategory: null,
22382
- teamMembers: offering.teamMembers,
22383
- status: offering.status,
22384
- timeZone: firstSession?.timeZone ?? "UTC",
22385
- pricing: toWholeSeriesPricing(offering),
22386
- paymentTerms: offering.paymentTerms,
22387
- consent: offering.consent,
22388
- requireGuestDetails: offering.requireGuestDetails,
22389
- acceptsPasses: false,
22390
- acceptsMemberships: offering.acceptsMemberships
22131
+ eventSeriesId: run.eventSeriesId,
22132
+ sessions
22133
+ },
22134
+ startsAt: firstSession.startsAt,
22135
+ endsAt: lastSession.endsAt,
22136
+ timeZone: firstSession.timeZone
22391
22137
  };
22392
22138
  }
22139
+ function toWholeSeriesRegistrationEvents(events) {
22140
+ return groupPublicEventsByRun(events).map(toWholeSeriesRegistrationEvent).filter((event) => event !== null);
22141
+ }
22393
22142
  //#endregion
22394
22143
  //#region ../blocks/src/system/runtime/nodes/event-registration.interactive.ts
22395
22144
  const EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS = [
@@ -22409,8 +22158,7 @@ const eventRegistrationHydrationSchemaShape = {
22409
22158
  occurrenceContext: occurrenceContextSchema.optional(),
22410
22159
  subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
22411
22160
  events: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
22412
- wholeSeriesOfferings: publicWholeSeriesOfferingsArraySchema.nullable().optional(),
22413
- wholeSeriesOffering: publicWholeSeriesOfferingSchema.nullable().optional(),
22161
+ wholeSeriesRunEvents: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
22414
22162
  maxTickets: z.string().optional(),
22415
22163
  showVenue: z.boolean().optional(),
22416
22164
  showCapacity: z.boolean().optional(),
@@ -22428,7 +22176,6 @@ const eventRegistrationSourceSchema = z.object({
22428
22176
  portalToken: z.string().nullable().optional(),
22429
22177
  previewToken: z.string().nullable().optional(),
22430
22178
  ...eventRegistrationHydrationSchemaShape,
22431
- subjectWholeSeriesOffering: publicWholeSeriesOfferingSchema.nullable().optional(),
22432
22179
  className: z.string().nullable().optional(),
22433
22180
  buttonText: z.string().nullable().optional(),
22434
22181
  maxTickets: z.string().nullable().optional(),
@@ -22462,7 +22209,8 @@ z.object({
22462
22209
  stage: previewStageSchema.optional()
22463
22210
  });
22464
22211
  function buildEventRegistrationDisplay(source) {
22465
- if (resolveWholeSeriesOffering(source)?.enrollmentOpen === false) return {
22212
+ const selectedRun = resolveSelectedWholeSeriesRun(source);
22213
+ if (selectedRun && (!selectedRun.run.enrollmentOpen || toWholeSeriesRegistrationEvent(selectedRun) === null)) return {
22466
22214
  kind: "event-registration",
22467
22215
  state: "registration-closed",
22468
22216
  className: source.className ?? null,
@@ -22480,13 +22228,11 @@ function buildEventRegistrationDisplay(source) {
22480
22228
  summaryButtonText: source.buttonText?.trim() || "Register"
22481
22229
  };
22482
22230
  }
22483
- function resolveWholeSeriesOffering(source) {
22484
- return source.wholeSeriesOffering ?? source.subjectWholeSeriesOffering ?? null;
22485
- }
22486
22231
  function buildEventRegistrationShellStepLabels(source) {
22487
- const selectedOffering = resolveWholeSeriesOffering(source);
22488
- if (selectedOffering) {
22489
- const selectedEvent = toWholeSeriesRegistrationEvent(selectedOffering);
22232
+ const selectedRun = resolveSelectedWholeSeriesRun(source);
22233
+ if (selectedRun) {
22234
+ const selectedEvent = toWholeSeriesRegistrationEvent(selectedRun);
22235
+ if (!selectedEvent) return EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS;
22490
22236
  return getWizardStepsForContext(true, resolveEventRequiresPayment({
22491
22237
  eligibility: null,
22492
22238
  selectedTicketType: null,
@@ -22507,16 +22253,31 @@ function buildEventRegistrationShellStepLabels(source) {
22507
22253
  }) : false).map((step) => shellLabelForRegistrationStep(step, scopedEvents));
22508
22254
  }
22509
22255
  function scopeEventRegistrationEvents(source) {
22510
- return toRegistrationEvents(scopeEventRegistrationSourceEvents(source));
22256
+ const scoped = scopeEventRegistrationSourceEvents(source);
22257
+ return [...toRegistrationEvents(scoped), ...toWholeSeriesRegistrationEvents(scoped)];
22511
22258
  }
22259
+ /**
22260
+ * Every event this surface may register for, from both of its loads.
22261
+ *
22262
+ * The date page and the run read answer different questions and can name the
22263
+ * same occurrence, so the two lists are joined and any occurrence that arrives
22264
+ * twice is kept once, in the order the date page gave it.
22265
+ */
22512
22266
  function scopeEventRegistrationSourceEvents(source) {
22513
- const scope = planEventRegistrationScope({
22514
- events: source.events ?? [],
22515
- wholeSeriesOffering: source.wholeSeriesOffering,
22267
+ const byOccurrenceId = /* @__PURE__ */ new Map();
22268
+ for (const event of [...source.events ?? [], ...source.wholeSeriesRunEvents ?? []]) if (!byOccurrenceId.has(event.occurrenceId)) byOccurrenceId.set(event.occurrenceId, event);
22269
+ return resolveEventRegistrationScopedEvents([...byOccurrenceId.values()], {
22516
22270
  occurrenceContext: source.occurrenceContext,
22517
22271
  subject: source.subject
22518
22272
  });
22519
- return scope.kind === "invalidSelectedRun" ? [] : [...scope.events];
22273
+ }
22274
+ /**
22275
+ * The one run this surface is registering for, when the scoped events describe
22276
+ * exactly one. More than one run means the visitor still has to choose.
22277
+ */
22278
+ function resolveSelectedWholeSeriesRun(source) {
22279
+ const runs = groupPublicEventsByRun(scopeEventRegistrationSourceEvents(source));
22280
+ return runs.length === 1 ? runs[0] : null;
22520
22281
  }
22521
22282
  function shellLabelForRegistrationStep(step, events) {
22522
22283
  switch (step) {
@@ -22556,8 +22317,6 @@ const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
22556
22317
  occurrenceContext: source.occurrenceContext ?? null,
22557
22318
  subject: source.subject ?? null,
22558
22319
  events,
22559
- wholeSeriesOfferings: source.wholeSeriesOfferings ?? null,
22560
- wholeSeriesOffering: resolveWholeSeriesOffering(source),
22561
22320
  maxTickets: source.maxTickets ?? void 0,
22562
22321
  showVenue: source.showVenue,
22563
22322
  showCapacity: source.showCapacity,
@@ -22576,8 +22335,7 @@ function normalizeEventRegistrationEventInput(value) {
22576
22335
  if (!isRecord$3(value)) return value;
22577
22336
  return {
22578
22337
  ...value,
22579
- destination: resolveRuntimeEventDestination(value),
22580
- pricing: resolveRuntimeEventPricing(value)
22338
+ destination: resolveRuntimeEventDestination(value)
22581
22339
  };
22582
22340
  }
22583
22341
  function isRecord$3(value) {
@@ -22672,7 +22430,7 @@ const eventRegistrationBlockDefinition = {
22672
22430
  {
22673
22431
  id: "showCapacity",
22674
22432
  type: "boolean",
22675
- label: "Show available spots",
22433
+ label: "Show available places",
22676
22434
  description: "Display remaining capacity",
22677
22435
  required: false,
22678
22436
  defaultValue: true,
@@ -22733,9 +22491,7 @@ const eventRegistrationBlockDefinition = {
22733
22491
  fallback: false
22734
22492
  } },
22735
22493
  events: { $bind: { from: "data.events" } },
22736
- wholeSeriesOffering: { $bind: { from: "data.selectedRunOffering.offering" } },
22737
- subjectWholeSeriesOffering: { $bind: { from: "data.subjectWholeSeriesOffering.offering" } },
22738
- wholeSeriesOfferings: { $bind: { from: "data.wholeSeriesOfferings" } },
22494
+ wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
22739
22495
  sitePasses: { $bind: { from: "data.sitePasses" } },
22740
22496
  siteMemberships: { $bind: { from: "data.siteMemberships" } },
22741
22497
  stage: { $bind: {
@@ -22749,9 +22505,7 @@ const eventRegistrationBlockDefinition = {
22749
22505
  runtime: eventRegistrationBlockRuntime,
22750
22506
  dataSchemas: {
22751
22507
  events: publicEventsArraySchema.optional(),
22752
- selectedRunOffering: z.object({ offering: publicWholeSeriesOfferingSchema }).optional(),
22753
- subjectWholeSeriesOffering: z.object({ offering: publicWholeSeriesOfferingSchema }).optional(),
22754
- wholeSeriesOfferings: z.array(publicWholeSeriesOfferingSchema).optional(),
22508
+ wholeSeriesRunEvents: publicEventsArraySchema.optional(),
22755
22509
  sitePasses: publicPassProductCollectionSchema.optional(),
22756
22510
  siteMemberships: publicMembershipProductCollectionSchema.optional(),
22757
22511
  occurrenceContext: occurrenceContextSchema.optional()
@@ -22769,7 +22523,7 @@ const eventRegistrationBlockDefinition = {
22769
22523
  readProfile: "registration",
22770
22524
  seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
22771
22525
  seriesIds: { $bind: {
22772
- from: "$root.subject.availableEventSeriesIds",
22526
+ from: "$root.subject.catalogueEventSeriesIds",
22773
22527
  transforms: [{ id: "value.csv" }]
22774
22528
  } },
22775
22529
  runSeriesId: { $bind: { from: "$root.entrySubrouteContext.run.seriesId" } },
@@ -22777,50 +22531,39 @@ const eventRegistrationBlockDefinition = {
22777
22531
  },
22778
22532
  mode: "server"
22779
22533
  },
22780
- selectedRunOffering: {
22781
- endpoint: "getPublicWholeSeriesOffering",
22782
- params: {
22783
- siteId: { $bind: { from: "$root.siteId" } },
22784
- eventSeriesId: { $bind: { from: "$root.entrySubrouteContext.run.seriesId" } },
22785
- stage: { $bind: {
22786
- from: "$root.previewStage",
22787
- fallback: "published"
22788
- } }
22789
- },
22790
- requiredParams: ["eventSeriesId"],
22791
- mode: "server"
22792
- },
22793
- subjectWholeSeriesOffering: {
22794
- endpoint: "getPublicWholeSeriesOffering",
22534
+ /**
22535
+ * The runs this page can register for, finished ones included.
22536
+ *
22537
+ * The `events` page above is date-bounded, so a run whose first session has
22538
+ * passed contributes no rows to it and the surface would have nothing to
22539
+ * render as closed. This asks for runs instead, and only on a page whose
22540
+ * subject books whole runs. It is scoped exactly like the date page — same
22541
+ * series, same run subroute — because scope and grain are separate
22542
+ * questions. The two lists are joined by occurrence, so a run that appears
22543
+ * in both is still one run.
22544
+ */
22545
+ wholeSeriesRunEvents: {
22546
+ endpoint: "listPublicEvents",
22795
22547
  when: { $bind: {
22796
22548
  from: "$root.subject.isWholeSeriesBooking",
22797
22549
  fallback: false
22798
22550
  } },
22799
22551
  params: {
22800
22552
  siteId: { $bind: { from: "$root.siteId" } },
22801
- eventSeriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
22553
+ readIntent: "runs",
22554
+ limit: "50",
22802
22555
  stage: { $bind: {
22803
22556
  from: "$root.previewStage",
22804
22557
  fallback: "published"
22805
- } }
22806
- },
22807
- requiredParams: ["eventSeriesId"],
22808
- mode: "server"
22809
- },
22810
- wholeSeriesOfferings: {
22811
- endpoint: "listPublicWholeSeriesOfferings",
22812
- params: {
22813
- siteId: { $bind: { from: "$root.siteId" } },
22814
- eventSeriesIds: { $bind: {
22815
- from: "$root.subject.availableEventSeriesIds",
22558
+ } },
22559
+ readProfile: "registration",
22560
+ seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
22561
+ seriesIds: { $bind: {
22562
+ from: "$root.subject.catalogueEventSeriesIds",
22816
22563
  transforms: [{ id: "value.csv" }]
22817
22564
  } },
22818
- stage: { $bind: {
22819
- from: "$root.previewStage",
22820
- fallback: "published"
22821
- } }
22565
+ runSeriesId: { $bind: { from: "$root.entrySubrouteContext.run.seriesId" } }
22822
22566
  },
22823
- requiredParams: ["eventSeriesIds"],
22824
22567
  mode: "server"
22825
22568
  },
22826
22569
  sitePasses: {
@@ -23073,7 +22816,7 @@ const eventDetailsBlockDefinition = {
23073
22816
  readProfile: "details",
23074
22817
  seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
23075
22818
  seriesIds: { $bind: {
23076
- from: "$root.subject.availableEventSeriesIds",
22819
+ from: "$root.subject.catalogueEventSeriesIds",
23077
22820
  transforms: [{ id: "value.csv" }]
23078
22821
  } },
23079
22822
  runSeriesId: { $bind: { from: "$root.entrySubrouteContext.run.seriesId" } },
@@ -23233,7 +22976,11 @@ const eventSpotlightBlockDefinition = {
23233
22976
  } }
23234
22977
  };
23235
22978
  //#endregion
23236
- //#region ../blocks/src/system/runtime/nodes/events/shared/utils.ts
22979
+ //#region ../blocks/src/system/runtime/nodes/events/shared/listingLayout.ts
22980
+ /**
22981
+ * Layout classes for event listing containers and cards. Presentation
22982
+ * plumbing rather than event domain logic, so it lives beside the components.
22983
+ */
23237
22984
  /**
23238
22985
  * Column class mappings for grid layouts, derived from the canonical
23239
22986
  * responsive column ladder (see gridUserColumnLadder).
@@ -23317,6 +23064,93 @@ function resolveEventListPaginationAction(input) {
23317
23064
  };
23318
23065
  }
23319
23066
  //#endregion
23067
+ //#region ../blocks/src/system/blocks/events/shared/calendarWindow.ts
23068
+ /** Runtime picker sentinels and bound loader IDs must describe the same query. */
23069
+ function normalizeCalendarFilterId(value) {
23070
+ const id = value?.trim();
23071
+ return !id || id === "all" ? void 0 : id;
23072
+ }
23073
+ const calendarMonthSchema = z.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).refine((month) => Number(month.slice(0, 4)) > 0, "Invalid calendar year");
23074
+ function calendarMonthDate(month) {
23075
+ return {
23076
+ year: Number(month.slice(0, 4)),
23077
+ month: Number(month.slice(5, 7)),
23078
+ day: 1
23079
+ };
23080
+ }
23081
+ const monthNumber = (month) => {
23082
+ const date = calendarMonthDate(month);
23083
+ return date.year * 12 + date.month - 1;
23084
+ };
23085
+ const calendarMonthWindowSchema = z.object({
23086
+ startMonth: calendarMonthSchema,
23087
+ endMonthExclusive: calendarMonthSchema
23088
+ }).refine((window) => {
23089
+ const width = monthNumber(window.endMonthExclusive) - monthNumber(window.startMonth);
23090
+ return width > 0 && width <= 3;
23091
+ }, "Calendar windows must cover one to three months");
23092
+ z.object({
23093
+ startMonth: calendarMonthSchema.optional(),
23094
+ endMonthExclusive: calendarMonthSchema.optional(),
23095
+ afterStartsAt: z.string().datetime({ offset: true }).optional(),
23096
+ afterId: z.string().uuid().optional(),
23097
+ limit: z.coerce.number().int().min(1).max(200).default(100),
23098
+ stage: z.enum(["published", "preview"]).default("published"),
23099
+ readProfile: z.enum(["listing-card", "timetable"]).optional(),
23100
+ eventSurface: z.enum(eventSurfaceScopeValues).optional(),
23101
+ eventPresets: z.string().optional(),
23102
+ scheduleScope: z.enum(eventScheduleScopeValues).optional(),
23103
+ categoryIds: z.string().optional(),
23104
+ venueId: z.string().transform(normalizeCalendarFilterId).optional(),
23105
+ staffMemberId: z.string().transform(normalizeCalendarFilterId).optional()
23106
+ }).superRefine((query, ctx) => {
23107
+ if (Boolean(query.startMonth) !== Boolean(query.endMonthExclusive)) ctx.addIssue({
23108
+ code: "custom",
23109
+ message: "Both month bounds are required"
23110
+ });
23111
+ if (query.startMonth && query.endMonthExclusive && !calendarMonthWindowSchema.safeParse(query).success) ctx.addIssue({
23112
+ code: "custom",
23113
+ message: "Invalid calendar window"
23114
+ });
23115
+ if (Boolean(query.afterStartsAt) !== Boolean(query.afterId)) ctx.addIssue({
23116
+ code: "custom",
23117
+ message: "Both cursor fields are required"
23118
+ });
23119
+ if (query.afterStartsAt && !query.startMonth) ctx.addIssue({
23120
+ code: "custom",
23121
+ message: "A continuation requires explicit month bounds"
23122
+ });
23123
+ });
23124
+ const calendarSourceCursorSchema = z.object({
23125
+ startsAt: z.string().datetime({ offset: true }),
23126
+ occurrenceId: z.string().uuid()
23127
+ });
23128
+ z.discriminatedUnion("kind", [z.object({ kind: z.literal("complete") }), z.object({
23129
+ kind: z.literal("partial"),
23130
+ nextCursor: calendarSourceCursorSchema
23131
+ })]);
23132
+ const pageFields = {
23133
+ scope: z.object({
23134
+ key: z.string(),
23135
+ timeZone: z.string().transform(toBookingTimeZone)
23136
+ }),
23137
+ window: calendarMonthWindowSchema,
23138
+ initialToday: z.object({
23139
+ year: z.number().int(),
23140
+ month: z.number().int().min(1).max(12),
23141
+ day: z.number().int().min(1).max(31)
23142
+ }),
23143
+ events: z.array(publicEventSchema)
23144
+ };
23145
+ const calendarWindowPageSchema = z.discriminatedUnion("kind", [z.object({
23146
+ ...pageFields,
23147
+ kind: z.literal("complete")
23148
+ }), z.object({
23149
+ ...pageFields,
23150
+ kind: z.literal("partial"),
23151
+ nextCursor: calendarSourceCursorSchema
23152
+ })]);
23153
+ //#endregion
23320
23154
  //#region ../blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.ts
23321
23155
  const eventSurfaceScopeSchema$1 = z.enum(eventSurfaceScopeValues);
23322
23156
  const eventScheduleScopeSchema$1 = z.enum(eventScheduleScopeValues);
@@ -23333,6 +23167,7 @@ const eventCollectionFilterSourceSchemaShape = {
23333
23167
  filterVenueId: z.string().nullable().optional()
23334
23168
  };
23335
23169
  const eventCollectionSourceSchemaShape = {
23170
+ calendarWindow: calendarWindowPageSchema.nullable().optional(),
23336
23171
  events: z.array(publicEventSchema).nullable().optional(),
23337
23172
  siteId: z.string(),
23338
23173
  apiBaseUrl: z.string().optional(),
@@ -23386,6 +23221,7 @@ const eventCollectionDisplaySchemaShape = {
23386
23221
  };
23387
23222
  const eventCollectionHydrationSchema = z.object({
23388
23223
  siteId: z.string(),
23224
+ calendarWindow: calendarWindowPageSchema.optional(),
23389
23225
  stage: previewStageSchema.optional(),
23390
23226
  prefetchedEvents: z.boolean(),
23391
23227
  eventSurface: eventSurfaceScopeSchema$1,
@@ -23444,8 +23280,9 @@ function buildEventCollectionPresentationDisplay(source) {
23444
23280
  };
23445
23281
  }
23446
23282
  function buildEventCollectionHydration(source, now = /* @__PURE__ */ new Date()) {
23447
- const timeZone = toBookingTimeZone(source.bookingTimeZone);
23283
+ const timeZone = source.calendarWindow?.scope.timeZone ?? toBookingTimeZone(source.bookingTimeZone);
23448
23284
  return {
23285
+ calendarWindow: source.calendarWindow ?? void 0,
23449
23286
  siteId: source.siteId,
23450
23287
  stage: source.stage,
23451
23288
  prefetchedEvents: source.events != null,
@@ -23454,7 +23291,7 @@ function buildEventCollectionHydration(source, now = /* @__PURE__ */ new Date())
23454
23291
  scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
23455
23292
  calendarContext: {
23456
23293
  timeZone,
23457
- initialToday: getLocalScheduleDate(now, timeZone)
23294
+ initialToday: source.calendarWindow?.initialToday ?? getLocalScheduleDate(now, timeZone)
23458
23295
  }
23459
23296
  };
23460
23297
  }
@@ -24003,7 +23840,7 @@ function buildEventCalendarDisplay(source) {
24003
23840
  listColumns: source.listColumns ?? source.columns
24004
23841
  }),
24005
23842
  kind: "event-calendar",
24006
- displayMode: source.variant ?? source.displayMode ?? "combined",
23843
+ displayMode: normalizeEventCalendarDisplayMode$1(source) ?? "combined",
24007
23844
  className: source.className ?? null,
24008
23845
  events: (source.events ?? []).slice().sort((left, right) => new Date(left.startsAt).getTime() - new Date(right.startsAt).getTime()),
24009
23846
  boardTitle: normalizeOptionalText(source.boardTitle),
@@ -24021,15 +23858,75 @@ const eventCalendarBlockRuntime = defineProgressiveBlockRuntime({
24021
23858
  render: createZodCodec(eventCalendarRenderSchema)
24022
23859
  },
24023
23860
  buildRender: (source) => ({
24024
- display: buildEventCalendarDisplay(source),
23861
+ display: buildEventCalendarDisplay(source.calendarWindow && (source.variant ?? source.displayMode ?? "combined") !== "combined" && (source.variant ?? source.displayMode) !== "list" ? {
23862
+ ...source,
23863
+ events: source.calendarWindow.events
23864
+ } : source),
24025
23865
  hydration: buildEventCollectionHydration(source)
24026
23866
  })
24027
23867
  });
24028
23868
  //#endregion
23869
+ //#region ../blocks/src/system/blocks/events/eventCalendarDataLoaders.ts
23870
+ const scopeParams = {
23871
+ siteId: { $bind: { from: "$root.siteId" } },
23872
+ stage: { $bind: {
23873
+ from: "$root.previewStage",
23874
+ fallback: "published"
23875
+ } },
23876
+ eventSurface: { $bind: { from: "content.eventSurface" } },
23877
+ eventPresets: { $bind: {
23878
+ from: "content.filterEventPresets",
23879
+ transforms: [{ id: "value.csv" }]
23880
+ } },
23881
+ scheduleScope: { $bind: { from: "content.scheduleScope" } },
23882
+ categoryIds: { $bind: { from: "content.filterCategoryIds" } },
23883
+ staffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
23884
+ venueId: { $bind: { from: "content.filterVenueId" } }
23885
+ };
23886
+ /** Combined renders two jobs; calendar-only variants never pay for the list seed. */
23887
+ const eventCalendarDataLoaders = {
23888
+ events: {
23889
+ endpoint: "listPublicEvents",
23890
+ when: { $bind: {
23891
+ from: "content",
23892
+ transforms: [{
23893
+ id: "events.calendarReadEnabled",
23894
+ options: { job: "list" }
23895
+ }]
23896
+ } },
23897
+ params: {
23898
+ ...scopeParams,
23899
+ limit: 100,
23900
+ detailLevel: "listing",
23901
+ readProfile: "listing-card"
23902
+ },
23903
+ mode: "server"
23904
+ },
23905
+ calendarWindow: {
23906
+ endpoint: "listPublicEventCalendarWindow",
23907
+ when: { $bind: {
23908
+ from: "content",
23909
+ transforms: [{
23910
+ id: "events.calendarReadEnabled",
23911
+ options: { job: "calendar" }
23912
+ }]
23913
+ } },
23914
+ params: {
23915
+ ...scopeParams,
23916
+ limit: 100,
23917
+ readProfile: { $bind: {
23918
+ from: "content",
23919
+ transforms: [{ id: "events.calendarReadProfile" }]
23920
+ } }
23921
+ },
23922
+ mode: "server"
23923
+ }
23924
+ };
23925
+ //#endregion
24029
23926
  //#region ../blocks/src/system/blocks/events/event-calendar.ts
24030
23927
  function normalizeEventCalendarContent(content) {
24031
23928
  const record = typeof content === "object" && content !== null ? content : {};
24032
- const variant = normalizeEventCalendarDisplayMode(record.variant) ?? normalizeEventCalendarDisplayMode(record.displayMode);
23929
+ const variant = normalizeEventCalendarDisplayMode$1(record);
24033
23930
  return {
24034
23931
  ...record,
24035
23932
  ...variant ? { variant } : {},
@@ -24077,6 +23974,7 @@ const eventCalendarLayout = [styledSection({
24077
23974
  rootProps: { gap: "lg" },
24078
23975
  children: [...eventSectionHeaderLayoutNodes({ splitClassName: "event-section-head event-section-head--split" }), el("event-calendar", withApiBindings({
24079
23976
  events: { $bind: { from: "data.events" } },
23977
+ calendarWindow: { $bind: { from: "data.calendarWindow" } },
24080
23978
  stage: { $bind: {
24081
23979
  from: "$root.previewStage",
24082
23980
  fallback: "published"
@@ -24565,7 +24463,7 @@ const eventCalendarAdditionalFields = [
24565
24463
  {
24566
24464
  id: "showCapacity",
24567
24465
  type: "boolean",
24568
- label: "Show available spots",
24466
+ label: "Show available places",
24569
24467
  description: "Display remaining capacity on event cards and timetable cells",
24570
24468
  required: false,
24571
24469
  defaultValue: true,
@@ -24900,33 +24798,11 @@ const eventCalendarBlockDefinition = {
24900
24798
  }
24901
24799
  }, eventCalendarContentShape),
24902
24800
  normalizeContent: normalizeEventCalendarContent,
24903
- dataSchemas: { events: publicEventsArraySchema.optional() },
24904
- dataLoaders: { events: {
24905
- endpoint: "listPublicEvents",
24906
- params: {
24907
- siteId: { $bind: { from: "$root.siteId" } },
24908
- limit: 100,
24909
- stage: { $bind: {
24910
- from: "$root.previewStage",
24911
- fallback: "published"
24912
- } },
24913
- detailLevel: "listing",
24914
- readProfile: { $bind: {
24915
- from: "content.variant",
24916
- fallback: "listing-card"
24917
- } },
24918
- eventSurface: { $bind: { from: "content.eventSurface" } },
24919
- eventPresets: { $bind: {
24920
- from: "content.filterEventPresets",
24921
- transforms: [{ id: "value.csv" }]
24922
- } },
24923
- scheduleScope: { $bind: { from: "content.scheduleScope" } },
24924
- categoryIds: { $bind: { from: "content.filterCategoryIds" } },
24925
- staffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
24926
- venueId: { $bind: { from: "content.filterVenueId" } }
24927
- },
24928
- mode: "server"
24929
- } },
24801
+ dataSchemas: {
24802
+ events: publicEventsArraySchema.optional(),
24803
+ calendarWindow: calendarWindowPageSchema.optional()
24804
+ },
24805
+ dataLoaders: eventCalendarDataLoaders,
24930
24806
  runtime: eventCalendarBlockRuntime
24931
24807
  };
24932
24808
  const recurringScheduleWeekdaySchema = z.enum([
@@ -25316,6 +25192,12 @@ function isRecord$2(value) {
25316
25192
  }
25317
25193
  //#endregion
25318
25194
  //#region ../blocks/src/system/blocks/offerings-preview/index.ts
25195
+ /**
25196
+ * The whole-series presets, as the CSV `listPublicEvents` expects. Both
25197
+ * whole-series presets share one loader: the block renders them as a single
25198
+ * run group.
25199
+ */
25200
+ const WHOLE_SERIES_EVENT_PRESETS_PARAM = WHOLE_SERIES_EVENT_PRESET_VALUES.join(",");
25319
25201
  const publicRouteCandidatesSchema = z.object({ routes: z.array(z.object({
25320
25202
  entityId: z.string(),
25321
25203
  path: z.string(),
@@ -25597,7 +25479,7 @@ const offeringsPreviewManifest = createBlockManifest({
25597
25479
  fallback: "published"
25598
25480
  } },
25599
25481
  routeCandidates: { $bind: { from: "data.routeCandidates" } },
25600
- wholeSeriesOfferings: { $bind: { from: "data.wholeSeriesOfferings" } },
25482
+ wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
25601
25483
  ...offeringsPreviewEventDataBindings
25602
25484
  })
25603
25485
  ], { gap: "lg" }),
@@ -25614,7 +25496,7 @@ const offeringsPreviewBlockDefinition = {
25614
25496
  dataSchemas: {
25615
25497
  ...offeringsPreviewEventDataSchemas,
25616
25498
  routeCandidates: publicRouteCandidatesSchema.optional(),
25617
- wholeSeriesOfferings: publicWholeSeriesOfferingsArraySchema.optional()
25499
+ wholeSeriesRunEvents: optionalPublicEventsArraySchema
25618
25500
  },
25619
25501
  dataLoaders: {
25620
25502
  ...offeringsPreviewEventDataLoaders,
@@ -25623,24 +25505,21 @@ const offeringsPreviewBlockDefinition = {
25623
25505
  params: {},
25624
25506
  mode: "server"
25625
25507
  },
25626
- wholeSeriesOfferings: {
25627
- endpoint: "listPublicWholeSeriesOfferings",
25628
- params: {
25629
- siteId: { $bind: { from: "$root.siteId" } },
25630
- limit: { $bind: {
25631
- from: "content.itemLimit",
25632
- fallback: "3"
25633
- } },
25634
- stage: { $bind: {
25635
- from: "$root.previewStage",
25636
- fallback: "published"
25637
- } }
25638
- },
25639
- mode: "server"
25640
- }
25508
+ wholeSeriesRunEvents: wholeSeriesRunLoader()
25641
25509
  }
25642
25510
  };
25643
- function eventPresetLoader(preset) {
25511
+ /**
25512
+ * One row per whole-series run, finished runs included.
25513
+ *
25514
+ * A page of dates cannot answer this: a finished run has no upcoming date, and
25515
+ * a long run would spend the whole page on its own sessions. `readIntent:
25516
+ * 'runs'` asks for runs instead, so `itemLimit` counts run cards rather than
25517
+ * dates, and each card arrives with the run's complete schedule.
25518
+ */
25519
+ function wholeSeriesRunLoader() {
25520
+ return eventPresetLoader(WHOLE_SERIES_EVENT_PRESETS_PARAM, { readIntent: "runs" });
25521
+ }
25522
+ function eventPresetLoader(eventPresets, extraParams = {}) {
25644
25523
  return {
25645
25524
  endpoint: "listPublicEvents",
25646
25525
  params: {
@@ -25655,7 +25534,8 @@ function eventPresetLoader(preset) {
25655
25534
  } },
25656
25535
  detailLevel: "listing",
25657
25536
  readProfile: "listing-card",
25658
- eventPresets: preset
25537
+ eventPresets,
25538
+ ...extraParams
25659
25539
  },
25660
25540
  mode: "server"
25661
25541
  };