@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
@@ -84,7 +84,6 @@ const TAG_TEMPLATES = {
84
84
  formSubmissionsBySlug: "riverbank:form-submissions:{slug}",
85
85
  publicEvents: "riverbank:site:{siteId}:public-events",
86
86
  publicEventFilters: "riverbank:site:{siteId}:public-event-filters",
87
- publicWholeSeriesOfferings: "riverbank:site:{siteId}:public-whole-series-offerings",
88
87
  publicTeamMembers: "riverbank:site:{siteId}:public-team-members",
89
88
  publicProducts: "riverbank:site:{siteId}:public-products",
90
89
  publicPasses: "riverbank:site:{siteId}:public-passes",
@@ -93,6 +92,7 @@ const TAG_TEMPLATES = {
93
92
  publicShop: "riverbank:site:{siteId}:public-shop",
94
93
  publicCheckout: "riverbank:site:{siteId}:public-checkout",
95
94
  publicBookingServices: "riverbank:site:{siteId}:public-booking-services",
95
+ publicBookingAvailability: "riverbank:site:{siteId}:public-booking-availability",
96
96
  siteNavigation: "riverbank:site:{siteId}:navigation",
97
97
  navigationMenuById: "riverbank:navigation-menu:{menuId}",
98
98
  navigationItemById: "riverbank:navigation-item:{itemId}",
@@ -1219,30 +1219,15 @@ const NEWSLETTER_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1219
1219
  }
1220
1220
  });
1221
1221
  //#endregion
1222
- //#region ../api/src/publicWholeSeriesEndpointDefinitions.ts
1223
- const PUBLIC_WHOLE_SERIES_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1224
- listPublicWholeSeriesOfferings: {
1225
- path: "/public/sites/{siteId}/dated-offerings/whole-series",
1222
+ //#region ../api/src/publicEventEndpointDefinitions.ts
1223
+ const PUBLIC_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1224
+ listPublicEventCalendarWindow: {
1225
+ path: "/public/sites/{siteId}/events/calendar-window",
1226
1226
  method: "GET",
1227
- revalidate: 60,
1228
- tags: [TAG_TEMPLATES.publicWholeSeriesOfferings],
1229
- errors: ["server:internal_error"],
1227
+ revalidate: 0,
1230
1228
  auth: "public",
1231
1229
  responseKind: "json"
1232
1230
  },
1233
- getPublicWholeSeriesOffering: {
1234
- path: "/public/sites/{siteId}/dated-offerings/whole-series/{eventSeriesId}",
1235
- method: "GET",
1236
- revalidate: 60,
1237
- tags: [TAG_TEMPLATES.publicWholeSeriesOfferings],
1238
- errors: ["resource:not_found", "server:internal_error"],
1239
- auth: "public",
1240
- responseKind: "json"
1241
- }
1242
- });
1243
- //#endregion
1244
- //#region ../api/src/publicEventEndpointDefinitions.ts
1245
- const PUBLIC_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1246
1231
  resolvePublicEventCheckoutReturn: {
1247
1232
  path: "/public/sites/{siteId}/events/checkout-return",
1248
1233
  method: "POST",
@@ -1274,6 +1259,99 @@ const PUBLIC_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1274
1259
  }
1275
1260
  });
1276
1261
  //#endregion
1262
+ //#region ../api/src/publicEventCheckoutEndpointDefinitions.ts
1263
+ /**
1264
+ * The public event registration/checkout endpoints, extracted from
1265
+ * `endpoints.ts`.
1266
+ *
1267
+ * They were moved out for the same reason the `sdkMedia*` block was: adding the
1268
+ * `errors` metadata `require-api-endpoint-errors` asks of a newly-added endpoint
1269
+ * pushed `endpoints.ts` past its `max-lines` baseline. The block is spread back
1270
+ * at the exact position it occupied, so `API_ENDPOINTS` key order is unchanged.
1271
+ * (The endpoint that originally motivated the move, `checkPublicEventEligibility`,
1272
+ * was since deleted on dev by #1326.)
1273
+ */
1274
+ const PUBLIC_EVENT_CHECKOUT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1275
+ registerForEvent: {
1276
+ path: "/public/sites/{siteId}/events/register",
1277
+ method: "POST",
1278
+ tags: [TAG_TEMPLATES.publicEvents, "event-registration"],
1279
+ auth: "public",
1280
+ responseKind: "json"
1281
+ },
1282
+ createPublicEventCheckout: {
1283
+ path: "/public/sites/{siteId}/events/checkout",
1284
+ method: "POST",
1285
+ tags: [TAG_TEMPLATES.publicEvents, "event-checkout"],
1286
+ auth: "public",
1287
+ responseKind: "json"
1288
+ }
1289
+ });
1290
+ //#endregion
1291
+ //#region ../api/src/publicBookingAvailabilityEndpointDefinitions.ts
1292
+ /**
1293
+ * Public appointment reads: the service catalogue and the bookable slot grid.
1294
+ *
1295
+ * These are the reads that appointment writes invalidate. They carry canonical
1296
+ * `riverbank:*` tags because the frontend revalidate endpoint discards anything
1297
+ * else, which is why the legacy `site-{siteId}` tag they used to declare could
1298
+ * never actually be cleared (issue 1364).
1299
+ *
1300
+ * Slot availability depends on both tags: the grid moves when a booking lands,
1301
+ * and again when the service definition behind it changes.
1302
+ */
1303
+ const PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1304
+ getPublicBookingServices: {
1305
+ path: "/public/bookings/services",
1306
+ method: "GET",
1307
+ revalidate: 60,
1308
+ tags: [TAG_TEMPLATES.publicBookingServices],
1309
+ auth: "public",
1310
+ responseKind: "json"
1311
+ },
1312
+ getPublicBookingService: {
1313
+ path: "/public/bookings/services/{serviceId}",
1314
+ method: "GET",
1315
+ revalidate: 60,
1316
+ tags: [TAG_TEMPLATES.publicBookingServices],
1317
+ auth: "public",
1318
+ responseKind: "json"
1319
+ },
1320
+ getPublicBookingResourcesReference: {
1321
+ path: "/public/bookings/resources/reference",
1322
+ method: "GET",
1323
+ revalidate: 60,
1324
+ tags: [TAG_TEMPLATES.publicBookingServices],
1325
+ auth: "public",
1326
+ responseKind: "json"
1327
+ },
1328
+ getPublicBookingAvailableDates: {
1329
+ path: "/public/bookings/availability/dates",
1330
+ method: "GET",
1331
+ revalidate: 60,
1332
+ tags: [TAG_TEMPLATES.publicBookingAvailability, TAG_TEMPLATES.publicBookingServices],
1333
+ auth: "public",
1334
+ responseKind: "json"
1335
+ },
1336
+ getPublicBookingAvailableSlots: {
1337
+ path: "/public/bookings/availability/slots",
1338
+ method: "GET",
1339
+ revalidate: 60,
1340
+ tags: [TAG_TEMPLATES.publicBookingAvailability, TAG_TEMPLATES.publicBookingServices],
1341
+ auth: "public",
1342
+ responseKind: "json"
1343
+ },
1344
+ getPublicWeeklySlotAvailability: {
1345
+ path: "/public/bookings/weekly-slot-availability",
1346
+ method: "GET",
1347
+ revalidate: 60,
1348
+ tags: [TAG_TEMPLATES.publicBookingAvailability, TAG_TEMPLATES.publicBookingServices],
1349
+ auth: "public",
1350
+ responseKind: "json",
1351
+ errors: []
1352
+ }
1353
+ });
1354
+ //#endregion
1277
1355
  //#region ../api/src/siteApiKeyEndpointDefinitions.ts
1278
1356
  const SITE_API_KEY_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1279
1357
  listSiteApiKeys: {
@@ -1634,6 +1712,88 @@ const SDK_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1634
1712
  errors: ["validation:invalid_input", "server:internal_error"]
1635
1713
  }
1636
1714
  });
1715
+ //#endregion
1716
+ //#region ../api/src/sdkMediaEndpointDefinitions.ts
1717
+ /** SDK media lookup, listing, deletion and upload endpoints (management-key authenticated). */
1718
+ const SDK_MEDIA_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1719
+ sdkMediaExists: {
1720
+ path: "/sdk/{siteId}/media/exists",
1721
+ method: "POST",
1722
+ errors: ["validation:invalid_input"],
1723
+ auth: "service",
1724
+ responseKind: "json"
1725
+ },
1726
+ sdkMediaFindByChecksum: {
1727
+ path: "/sdk/{siteId}/media/find-by-checksum",
1728
+ method: "POST",
1729
+ errors: ["server:internal_error"],
1730
+ auth: "service",
1731
+ responseKind: "json"
1732
+ },
1733
+ sdkMediaResolve: {
1734
+ path: "/sdk/{siteId}/media/resolve",
1735
+ method: "POST",
1736
+ errors: ["server:internal_error"],
1737
+ auth: "service",
1738
+ responseKind: "json"
1739
+ },
1740
+ sdkMediaList: {
1741
+ path: "/sdk/{siteId}/media",
1742
+ method: "GET",
1743
+ auth: "service",
1744
+ errors: [],
1745
+ responseKind: "json"
1746
+ },
1747
+ sdkMediaDownload: {
1748
+ path: "/sdk/{siteId}/media/{identifier}/download",
1749
+ method: "GET",
1750
+ auth: "service",
1751
+ errors: [],
1752
+ responseKind: "json"
1753
+ },
1754
+ sdkMediaDeletePreview: {
1755
+ path: "/sdk/{siteId}/media/{identifier}/delete-preview",
1756
+ method: "POST",
1757
+ auth: "service",
1758
+ errors: [],
1759
+ responseKind: "json"
1760
+ },
1761
+ sdkMediaDeleteApply: {
1762
+ path: "/sdk/{siteId}/media/{identifier}",
1763
+ method: "DELETE",
1764
+ auth: "service",
1765
+ errors: [],
1766
+ responseKind: "json"
1767
+ },
1768
+ sdkMediaUploadUrl: {
1769
+ path: "/sdk/{siteId}/media/upload-url",
1770
+ method: "POST",
1771
+ errors: [
1772
+ "resource:not_found",
1773
+ "validation:invalid_input",
1774
+ "resource:conflict",
1775
+ "validation:payload_too_large",
1776
+ "billing:plan_limit_exceeded",
1777
+ "server:internal_error"
1778
+ ],
1779
+ auth: "service",
1780
+ responseKind: "json"
1781
+ },
1782
+ sdkMediaUploadFinalize: {
1783
+ path: "/sdk/{siteId}/media/upload",
1784
+ method: "POST",
1785
+ errors: [
1786
+ "resource:not_found",
1787
+ "validation:invalid_input",
1788
+ "resource:conflict",
1789
+ "validation:payload_too_large",
1790
+ "billing:plan_limit_exceeded",
1791
+ "server:internal_error"
1792
+ ],
1793
+ auth: "service",
1794
+ responseKind: "json"
1795
+ }
1796
+ });
1637
1797
  ({
1638
1798
  ...ACCOUNT_ENDPOINT_DEFINITIONS,
1639
1799
  ...PUBLIC_EVENT_ENDPOINT_DEFINITIONS,
@@ -1642,7 +1802,7 @@ const SDK_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1642
1802
  ...NEWSLETTER_ENDPOINT_DEFINITIONS,
1643
1803
  ...APPOINTMENT_ENDPOINT_DEFINITIONS,
1644
1804
  ...EVENT_SERIES_REGISTRATION_ENDPOINT_DEFINITIONS
1645
- }, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.workflowRunById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.routeById, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.formById, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEventFilters, { ...PUBLIC_WHOLE_SERIES_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.publicTeamMembers, TAG_TEMPLATES.publicWholeSeriesOfferings, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicPasses, TAG_TEMPLATES.publicMemberships, TAG_TEMPLATES.publicProducts, TAG_TEMPLATES.publicShop, TAG_TEMPLATES.publicCheckout, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, { ...EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS }, { ...SDK_ENDPOINT_DEFINITIONS }, { ...SDK_ENTRY_READ_ENDPOINTS };
1805
+ }, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.workflowRunById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.routeById, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.formById, TAG_TEMPLATES.siteForms, { ...PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEventFilters, TAG_TEMPLATES.publicTeamMembers, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicPasses, TAG_TEMPLATES.publicMemberships, TAG_TEMPLATES.publicProducts, TAG_TEMPLATES.publicShop, TAG_TEMPLATES.publicCheckout, TAG_TEMPLATES.siteRoutableContent, { ...PUBLIC_EVENT_CHECKOUT_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, { ...EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS }, { ...SDK_MEDIA_ENDPOINT_DEFINITIONS }, { ...SDK_ENDPOINT_DEFINITIONS }, { ...SDK_ENTRY_READ_ENDPOINTS };
1646
1806
  z.object({ refreshToken: z.string().min(1).max(4096) }).strict();
1647
1807
  z.object({
1648
1808
  accessToken: z.string().min(1).max(4096),
@@ -1809,22 +1969,59 @@ function formatCurrencyAmount(amountCents, currency, options) {
1809
1969
  }
1810
1970
  }
1811
1971
  //#endregion
1972
+ //#region ../core/src/planner.ts
1973
+ /** Default clock for production callers that do not inject time explicitly. */
1974
+ const systemPlanningClock = { now: () => Date.now() };
1975
+ /** Resolve current time as a Date from an explicit Date, injected clock, or system clock. */
1976
+ function resolvePlanningNowDate(input = {}) {
1977
+ if (input.now !== void 0) return input.now;
1978
+ return new Date((input.clock ?? systemPlanningClock).now());
1979
+ }
1980
+ //#endregion
1812
1981
  //#region ../core/src/event-pricing.ts
1982
+ /** Capacity closes booking, but does not make an otherwise eligible price unknown. */
1983
+ function isPublicEventPricingOptionDisplayable(option) {
1984
+ if (!option.isActive) return false;
1985
+ if (option.availability.kind === "available") return true;
1986
+ const reason = option.availability.reason;
1987
+ switch (reason) {
1988
+ case "sold_out":
1989
+ case "overallCapacityUnavailable": return true;
1990
+ case "inactive":
1991
+ case "not_on_sale_yet":
1992
+ case "sale_ended":
1993
+ case "attendance_mode_unavailable": return false;
1994
+ default: return assertNever$2(reason);
1995
+ }
1996
+ }
1997
+ function publicEventPricingDisplay(pricing) {
1998
+ switch (pricing.kind) {
1999
+ case "free":
2000
+ case "single":
2001
+ case "sliding_scale": return canonicalEventPricingDisplay(pricing);
2002
+ case "tiered": return resolvePricingOptionsPriceDisplay({
2003
+ options: pricing.options.filter(isPublicEventPricingOptionDisplayable),
2004
+ currency: pricing.currency,
2005
+ purpose: "configured"
2006
+ });
2007
+ case "external": return {
2008
+ kind: "external",
2009
+ label: pricing.label
2010
+ };
2011
+ }
2012
+ }
1813
2013
  function publicEventPricingType(pricing) {
1814
2014
  switch (pricing.kind) {
1815
- case "drop_in":
1816
- case "free_registration": return "free";
1817
- case "single_paid":
1818
- case "ticket_types":
1819
- case "sliding_scale":
1820
- case "whole_series": return isFreePublicEventPriceDisplay(pricing.display) ? "free" : "paid";
2015
+ case "free": return "free";
2016
+ case "single":
2017
+ case "tiered":
2018
+ case "sliding_scale": return isFreePublicEventPriceDisplay(publicEventPricingDisplay(pricing)) ? "free" : "paid";
1821
2019
  case "external": return "external";
1822
2020
  }
1823
2021
  }
1824
2022
  function isFreePublicEventPriceDisplay(display) {
1825
2023
  switch (display.kind) {
1826
2024
  case "free": return true;
1827
- case "whole_series": return display.display.kind === "free";
1828
2025
  case "exact":
1829
2026
  case "from":
1830
2027
  case "range":
@@ -1833,22 +2030,126 @@ function isFreePublicEventPriceDisplay(display) {
1833
2030
  case "external": return false;
1834
2031
  }
1835
2032
  }
2033
+ function resolvePricingOptionSaleWindowState(option, now) {
2034
+ if (option.saleStartsAt !== null && option.saleStartsAt !== void 0 && new Date(option.saleStartsAt) > now) return "not_started";
2035
+ if (option.saleEndsAt !== null && option.saleEndsAt !== void 0 && new Date(option.saleEndsAt) < now) return "ended";
2036
+ return "open";
2037
+ }
2038
+ function resolvePricingOptionsPriceDisplay(input) {
2039
+ const now = input.purpose === "available_now" ? resolvePlanningNowDate({
2040
+ now: input.now,
2041
+ clock: input.clock
2042
+ }) : null;
2043
+ const amounts = input.options.filter((option) => option.isActive && (now === null || resolvePricingOptionSaleWindowState(option, now) === "open")).map((option) => option.priceAmount);
2044
+ return amounts.length === 0 ? {
2045
+ kind: "unavailable",
2046
+ currency: input.currency
2047
+ } : amountRangeDisplay(amounts, input.currency);
2048
+ }
2049
+ function amountRangeDisplay(amounts, currency) {
2050
+ const minAmount = Math.min(...amounts);
2051
+ const maxAmount = Math.max(...amounts);
2052
+ if (minAmount === maxAmount) return minAmount === 0 ? {
2053
+ kind: "free",
2054
+ currency
2055
+ } : {
2056
+ kind: "exact",
2057
+ amount: minAmount,
2058
+ currency
2059
+ };
2060
+ if (minAmount === 0) {
2061
+ const paidAmounts = amounts.filter((amount) => amount > 0);
2062
+ return {
2063
+ kind: "mixed",
2064
+ paidFromAmount: Math.min(...paidAmounts),
2065
+ paidToAmount: maxAmount,
2066
+ currency
2067
+ };
2068
+ }
2069
+ return {
2070
+ kind: "range",
2071
+ minAmount,
2072
+ maxAmount,
2073
+ currency
2074
+ };
2075
+ }
2076
+ /** Derives configured price presentation directly from canonical pricing. */
2077
+ function canonicalEventPricingDisplay(pricing) {
2078
+ switch (pricing.kind) {
2079
+ case "free": return {
2080
+ kind: "free",
2081
+ currency: pricing.currency
2082
+ };
2083
+ case "single": return {
2084
+ kind: "exact",
2085
+ amount: pricing.amount,
2086
+ currency: pricing.currency
2087
+ };
2088
+ case "sliding_scale": return pricing.minimum === pricing.maximum ? {
2089
+ kind: "exact",
2090
+ amount: pricing.maximum,
2091
+ currency: pricing.currency
2092
+ } : {
2093
+ kind: "range",
2094
+ minAmount: pricing.minimum,
2095
+ maxAmount: pricing.maximum,
2096
+ currency: pricing.currency
2097
+ };
2098
+ case "tiered": return resolvePricingOptionsPriceDisplay({
2099
+ options: pricing.options,
2100
+ currency: pricing.currency,
2101
+ purpose: "configured"
2102
+ });
2103
+ default: return assertNever$2(pricing);
2104
+ }
2105
+ }
1836
2106
  //#endregion
1837
2107
  //#region ../core/src/event-page-surface-subject.ts
1838
- function createEventSeriesPageSurfaceSubject(eventSeriesId, bookingScope) {
2108
+ function createEventSeriesPageSurfaceSubject(eventSeriesId, bookingScope, eventDestinationMode) {
2109
+ const mode = eventDestinationMode ? { eventDestinationMode } : {};
1839
2110
  return bookingScope === "whole_series" ? {
1840
2111
  kind: "eventSeries",
1841
2112
  eventSeriesId,
1842
2113
  bookingScope,
1843
- isWholeSeriesBooking: true
2114
+ isWholeSeriesBooking: true,
2115
+ ...mode
1844
2116
  } : {
1845
2117
  kind: "eventSeries",
1846
2118
  eventSeriesId,
1847
- bookingScope
2119
+ bookingScope,
2120
+ ...mode
2121
+ };
2122
+ }
2123
+ function createEventOfferingPageSurfaceSubject(eventOfferingId, input) {
2124
+ const mode = input.eventDestinationMode ? { eventDestinationMode: input.eventDestinationMode } : {};
2125
+ const identity = {
2126
+ kind: "eventOffering",
2127
+ eventOfferingId,
2128
+ catalogueEventSeriesIds: input.catalogueEventSeriesIds
2129
+ };
2130
+ return input.bookingScope === "whole_series" ? {
2131
+ ...identity,
2132
+ bookingScope: input.bookingScope,
2133
+ isWholeSeriesBooking: true,
2134
+ ...mode
2135
+ } : {
2136
+ ...identity,
2137
+ bookingScope: input.bookingScope,
2138
+ ...mode
1848
2139
  };
1849
2140
  }
2141
+ /**
2142
+ * Read the destination mode off a wire value.
2143
+ *
2144
+ * Absent or unrecognised reads as absent, which leaves the routed Event record
2145
+ * as the only authority — the behaviour every caller had before the field
2146
+ * existed.
2147
+ */
2148
+ function parseEventPageSurfaceDestinationMode(value) {
2149
+ return value === "cms-managed" || value === "system-managed" ? value : void 0;
2150
+ }
1850
2151
  function parseEventPageSurfaceSubject(value) {
1851
- if (!isRecord$9(value)) return err({ kind: "notObject" });
2152
+ if (!isRecord$8(value)) return err({ kind: "notObject" });
1852
2153
  switch (value.kind) {
1853
2154
  case "eventSeries": {
1854
2155
  const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
@@ -1860,7 +2161,7 @@ function parseEventPageSurfaceSubject(value) {
1860
2161
  kind: "invalidEventSeriesBookingScope",
1861
2162
  bookingScope: value.bookingScope
1862
2163
  });
1863
- return ok(createEventSeriesPageSurfaceSubject(eventSeriesId.value, value.bookingScope));
2164
+ return ok(createEventSeriesPageSurfaceSubject(eventSeriesId.value, value.bookingScope, parseEventPageSurfaceDestinationMode(value.eventDestinationMode)));
1864
2165
  }
1865
2166
  case "eventOffering": {
1866
2167
  const eventOfferingId = parseEventOfferingId(value.eventOfferingId);
@@ -1868,24 +2169,22 @@ function parseEventPageSurfaceSubject(value) {
1868
2169
  kind: "invalidEventOfferingId",
1869
2170
  error: eventOfferingId.error
1870
2171
  });
1871
- if (!Array.isArray(value.availableEventSeriesIds)) return err({
1872
- kind: "unsupportedSubject",
1873
- subjectKind: value.kind
2172
+ if (!Array.isArray(value.catalogueEventSeriesIds)) return err({
2173
+ kind: "invalidEventOfferingCatalogue",
2174
+ catalogue: value.catalogueEventSeriesIds
1874
2175
  });
1875
- const parsedSeriesIds = [];
1876
- for (const valueId of value.availableEventSeriesIds) {
1877
- const eventSeriesId = parseEventSeriesId(valueId);
1878
- if (!eventSeriesId.ok) return err({
1879
- kind: "invalidEventSeriesId",
1880
- error: eventSeriesId.error
1881
- });
1882
- parsedSeriesIds.push(eventSeriesId.value);
1883
- }
1884
- return ok({
1885
- kind: "eventOffering",
1886
- eventOfferingId: eventOfferingId.value,
1887
- availableEventSeriesIds: parsedSeriesIds
2176
+ if (value.bookingScope !== "single_occurrence" && value.bookingScope !== "whole_series") return err({
2177
+ kind: "invalidEventOfferingBookingScope",
2178
+ bookingScope: value.bookingScope
1888
2179
  });
2180
+ const parsedCatalogueIds = parseEventSeriesIdList(value.catalogueEventSeriesIds);
2181
+ if (!parsedCatalogueIds.ok) return parsedCatalogueIds;
2182
+ const eventDestinationMode = parseEventPageSurfaceDestinationMode(value.eventDestinationMode);
2183
+ return ok(createEventOfferingPageSurfaceSubject(eventOfferingId.value, {
2184
+ catalogueEventSeriesIds: parsedCatalogueIds.value,
2185
+ bookingScope: value.bookingScope,
2186
+ ...eventDestinationMode ? { eventDestinationMode } : {}
2187
+ }));
1889
2188
  }
1890
2189
  default: return err({
1891
2190
  kind: "unsupportedSubject",
@@ -1893,7 +2192,19 @@ function parseEventPageSurfaceSubject(value) {
1893
2192
  });
1894
2193
  }
1895
2194
  }
1896
- function isRecord$9(value) {
2195
+ function parseEventSeriesIdList(values) {
2196
+ const parsed = [];
2197
+ for (const value of values) {
2198
+ const eventSeriesId = parseEventSeriesId(value);
2199
+ if (!eventSeriesId.ok) return err({
2200
+ kind: "invalidEventSeriesId",
2201
+ error: eventSeriesId.error
2202
+ });
2203
+ parsed.push(eventSeriesId.value);
2204
+ }
2205
+ return ok(parsed);
2206
+ }
2207
+ function isRecord$8(value) {
1897
2208
  return typeof value === "object" && value !== null && !Array.isArray(value);
1898
2209
  }
1899
2210
  //#endregion
@@ -2064,7 +2375,7 @@ function toLocationCoordinates(value) {
2064
2375
  }
2065
2376
  //#endregion
2066
2377
  //#region ../core/src/rich-text.ts
2067
- function isRecord$8(value) {
2378
+ function isRecord$7(value) {
2068
2379
  return typeof value === "object" && value !== null && !Array.isArray(value);
2069
2380
  }
2070
2381
  function hasOnlyKeys(value, allowed) {
@@ -2084,15 +2395,15 @@ function isDenseArrayOf(value, predicate) {
2084
2395
  return true;
2085
2396
  }
2086
2397
  function isTipTapMark(value) {
2087
- return isRecord$8(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$8(value.attrs));
2398
+ return isRecord$7(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$7(value.attrs));
2088
2399
  }
2089
2400
  function isTipTapNode(value) {
2090
- if (!isRecord$8(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$8(value.attrs) || value.marks !== void 0 && (!Array.isArray(value.marks) || !isDenseArrayOf(value.marks, isTipTapMark)) || value.content !== void 0 && (!Array.isArray(value.content) || !isDenseArrayOf(value.content, isTipTapNode))) return false;
2401
+ if (!isRecord$7(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$7(value.attrs) || value.marks !== void 0 && (!Array.isArray(value.marks) || !isDenseArrayOf(value.marks, isTipTapMark)) || value.content !== void 0 && (!Array.isArray(value.content) || !isDenseArrayOf(value.content, isTipTapNode))) return false;
2091
2402
  if (value.type === "text") return typeof value.text === "string" && value.text.length > 0 && value.content === void 0;
2092
2403
  return value.text === void 0;
2093
2404
  }
2094
2405
  function isCanonicalRichTextDoc(value) {
2095
- return isRecord$8(value) && hasOnlyKeys(value, rootKeys) && value.type === "doc" && Array.isArray(value.content) && isDenseArrayOf(value.content, isTipTapNode);
2406
+ return isRecord$7(value) && hasOnlyKeys(value, rootKeys) && value.type === "doc" && Array.isArray(value.content) && isDenseArrayOf(value.content, isTipTapNode);
2096
2407
  }
2097
2408
  //#endregion
2098
2409
  //#region ../core/src/newsletter-signup-destination.ts
@@ -2147,27 +2458,21 @@ function parseManagementKey(raw) {
2147
2458
  if (typeof raw !== "string" || !raw.startsWith("bld_mgmt_sk_") || raw.length === 12) return err({ kind: "invalid-management-key" });
2148
2459
  return ok(createSecretInternal("management-key", raw));
2149
2460
  }
2150
- //#endregion
2151
- //#region ../core/src/planner.ts
2152
- /** Default clock for production callers that do not inject time explicitly. */
2153
- const systemPlanningClock = { now: () => Date.now() };
2154
- /** Resolve current time as a Date from an explicit Date, injected clock, or system clock. */
2155
- function resolvePlanningNowDate(input = {}) {
2156
- if (input.now !== void 0) return input.now;
2157
- return new Date((input.clock ?? systemPlanningClock).now());
2461
+ function sessionStartMs(session) {
2462
+ return Date.parse(session.startsAt);
2158
2463
  }
2159
2464
  /**
2160
- * Resolve a Date-compatible planner input.
2465
+ * The run's sessions that still count, in schedule order.
2161
2466
  *
2162
- * Precedence: bare Date, `{ now }`, `{ clock }`, then `systemPlanningClock`.
2163
- * Explicit Date inputs are returned by reference, not cloned.
2467
+ * Sessions whose start cannot be read are dropped rather than sorted to an
2468
+ * arbitrary end: an unparseable date is not a date a visitor can attend.
2164
2469
  */
2165
- function resolvePlanningDateInput(input = {}) {
2166
- if (input instanceof Date) return input;
2167
- return resolvePlanningNowDate(input);
2470
+ function orderedLiveRunSessions(sessions) {
2471
+ return sessions.filter((session) => session.status !== "cancelled" && Number.isFinite(sessionStartMs(session))).sort((left, right) => sessionStartMs(left) - sessionStartMs(right));
2168
2472
  }
2169
2473
  //#endregion
2170
2474
  //#region ../core/src/event-series-behaviour.ts
2475
+ const WHOLE_SERIES_EVENT_PRESET_VALUES = ["course", "term"];
2171
2476
  const SURFACE_EVENT_PRESET_VALUES = [
2172
2477
  "class",
2173
2478
  "course",
@@ -8532,6 +8837,11 @@ const gradientConfigSchema = z.object({
8532
8837
  position: z.string().optional(),
8533
8838
  stops: z.array(gradientStopSchema).min(2)
8534
8839
  });
8840
+ const gradientsSchema = z.object({
8841
+ button: z.string().min(1).nullable().optional(),
8842
+ hero: z.string().min(1).nullable().optional(),
8843
+ background: z.string().min(1).nullable().optional()
8844
+ });
8535
8845
  //#endregion
8536
8846
  //#region ../theme-core/src/interactive/baseSchema.ts
8537
8847
  /**
@@ -9285,11 +9595,30 @@ const headerContainerSchema = z.object({
9285
9595
  tint: z.string().nullable().optional(),
9286
9596
  opacity: z.number().min(0).max(1).default(.12)
9287
9597
  }).optional();
9288
- const headerInteractionPaletteSchema = z.enum([
9598
+ //#endregion
9599
+ //#region ../theme-core/src/header/interactionPalette.ts
9600
+ /**
9601
+ * The palettes that fill the nav link with a colour on hover and focus. Each
9602
+ * one names a background/foreground token pair.
9603
+ */
9604
+ const headerInteractionPillPaletteValues = [
9289
9605
  "primary",
9290
9606
  "secondary",
9291
9607
  "accent"
9292
- ]);
9608
+ ];
9609
+ /**
9610
+ * "No pill": the nav link keeps whatever hover treatment its recipe compiled,
9611
+ * and the palette step writes nothing at all (#1318 Phase 4c decision 2).
9612
+ *
9613
+ * It exists because "a colour change on hover, no filled background" was not
9614
+ * expressible in the vocabulary, and it is what
9615
+ * `anna-raven-therapy-and-yoga` and `kirtan-lucy` have rendered since before
9616
+ * the palette existed. Without it those two rows can only be classified as a
9617
+ * conscious visual change.
9618
+ */
9619
+ const headerInteractionQuietPalette = "quiet";
9620
+ const headerInteractionPaletteValues = [...headerInteractionPillPaletteValues, headerInteractionQuietPalette];
9621
+ const headerInteractionPaletteSchema = z.enum(headerInteractionPaletteValues);
9293
9622
  //#endregion
9294
9623
  //#region ../theme-core/src/boxBackgroundSchema.ts
9295
9624
  const boxBackgroundOverlaySchema = z.preprocess(normalizeAuthoringOpacity, z.discriminatedUnion("type", [
@@ -9347,7 +9676,7 @@ const boxBackgroundSchema = z.discriminatedUnion("type", [
9347
9676
  })
9348
9677
  ]);
9349
9678
  function normalizeAuthoringOpacity(value) {
9350
- if (!isRecord$7(value)) return value;
9679
+ if (!isRecord$6(value)) return value;
9351
9680
  return {
9352
9681
  ...value,
9353
9682
  opacity: normalizeOpacity(value.opacity)
@@ -9356,7 +9685,7 @@ function normalizeAuthoringOpacity(value) {
9356
9685
  function normalizeOpacity(value) {
9357
9686
  return typeof value === "number" && value > 1 && value <= 100 ? value / 100 : value;
9358
9687
  }
9359
- function isRecord$7(value) {
9688
+ function isRecord$6(value) {
9360
9689
  return typeof value === "object" && value !== null && !Array.isArray(value);
9361
9690
  }
9362
9691
  //#endregion
@@ -9671,11 +10000,12 @@ const inputStyle = z.object({
9671
10000
  ]),
9672
10001
  label: z.enum(["inside", "above"])
9673
10002
  });
9674
- const headerPositioning = z.enum([
10003
+ const headerPositioningValues = [
9675
10004
  "static",
9676
10005
  "sticky",
9677
10006
  "fixed"
9678
- ]);
10007
+ ];
10008
+ const headerPositioning = z.enum(headerPositioningValues);
9679
10009
  const headerNavStyle = z.enum([
9680
10010
  "minimal",
9681
10011
  "underline",
@@ -9810,7 +10140,7 @@ const headerSchema = z.object({
9810
10140
  variant: headerVariantWithLegacyAliasSchema,
9811
10141
  positioning: headerPositioning,
9812
10142
  shrinkOnScroll: z.boolean(),
9813
- maxWidth: headerMaxWidth,
10143
+ maxWidth: headerMaxWidth.default("container"),
9814
10144
  scrollTreatment: headerScrollTreatmentSchema,
9815
10145
  background: headerBackgroundSchema.default({
9816
10146
  type: "color",
@@ -10009,11 +10339,6 @@ const bodyTextSchema = z.object({ intro: z.object({
10009
10339
  paragraphSize: bodyTextIntroTypographySizeSchema.optional(),
10010
10340
  headingSize: bodyTextIntroTypographySizeSchema.optional()
10011
10341
  }).optional() }).optional();
10012
- const gradientsSchema = z.object({
10013
- button: z.string().min(1).nullable().optional(),
10014
- hero: z.string().min(1).nullable().optional(),
10015
- background: z.string().min(1).nullable().optional()
10016
- });
10017
10342
  /**
10018
10343
  * Testimonial quote-mark treatment, owned by the site style (analogous to the
10019
10344
  * accordion icon). `style` is the coarse selector; the optional fields fine-tune
@@ -10894,6 +11219,12 @@ function cardRoleFromLegacyVocabulary(value) {
10894
11219
  */
10895
11220
  const cardRoleWithLegacyAliasSchema = z.preprocess((value) => cardRoleFromLegacyVocabulary(value) ?? value, cardRoleSchema);
10896
11221
  //#endregion
11222
+ //#region ../theme-core/src/site-styles/compilationPlan.ts
11223
+ const defaultHeaderBrandPreferences = {
11224
+ brandDisplay: "auto",
11225
+ logoSize: "auto"
11226
+ };
11227
+ //#endregion
10897
11228
  //#region ../theme-core/src/site-styles/sectionTransitions.ts
10898
11229
  function boundaryRuntimeMetrics(family, size, heightExpression) {
10899
11230
  return {
@@ -11939,6 +12270,12 @@ const overlayLogoAccommodations = [
11939
12270
  inlineMarkWithTitleLogoAccommodation,
11940
12271
  unbackedOverlayLogoAccommodation
11941
12272
  ];
12273
+ const allCuratedLogoAccommodations = [
12274
+ ...inlineClassicLogoAccommodations,
12275
+ ...centeredLogoAccommodations,
12276
+ ...overlayLogoAccommodations
12277
+ ];
12278
+ new Set(allCuratedLogoAccommodations.filter((option) => option.providesBacking === true).map((option) => option.pattern));
11942
12279
  const headerLayoutCatalog = defineExactCatalog()([
11943
12280
  {
11944
12281
  id: asHeaderLayoutId("classic"),
@@ -12088,6 +12425,10 @@ defineLookOptionGroup({
12088
12425
  {
12089
12426
  id: "secondary",
12090
12427
  label: "Secondary"
12428
+ },
12429
+ {
12430
+ id: headerInteractionQuietPalette,
12431
+ label: "Text only"
12091
12432
  }
12092
12433
  ]
12093
12434
  });
@@ -14509,6 +14850,67 @@ const blockDesignFallback = {
14509
14850
  };
14510
14851
  blockDesignFallback.sectionSurface, blockDesignFallback.contentFrame, blockDesignFallback.transitionAfter, blockDesignFallback.sectionHeight, blockDesignFallback.heroLegibility, blockDesignFallback.imageSurfaceTreatment, blockDesignFallback.imageSurfaceMotion, blockDesignFallback.tileTreatment, blockDesignFallback.eventListTreatment, blockDesignFallback.eyebrowTreatment, blockDesignFallback.accordionIconTreatment, blockDesignFallback.composition;
14511
14852
  //#endregion
14853
+ //#region ../theme-core/src/site-styles/siteChromeBackgrounds.ts
14854
+ const siteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceColorTokenNames);
14855
+ const quickSiteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceQuickColorTokenNames);
14856
+ siteChromeBackgroundColorTokens.filter((token) => !quickSiteChromeBackgroundColorTokens.includes(token));
14857
+ function parseSiteChromeBackgroundColorToken(value) {
14858
+ const token = parseBackgroundAppearanceColorToken(value);
14859
+ return token ? token : null;
14860
+ }
14861
+ function toSiteChromeBackgroundColorTokens(tokenNames) {
14862
+ return tokenNames.flatMap((name) => {
14863
+ const token = parseSiteChromeBackgroundColorToken(name);
14864
+ return token ? [token] : [];
14865
+ });
14866
+ }
14867
+ //#endregion
14868
+ //#region ../theme-core/src/site-styles/siteChromeNavPreferences.ts
14869
+ const headerNavTypographyPreferenceValues = [
14870
+ "inherit",
14871
+ "body",
14872
+ "heading"
14873
+ ];
14874
+ const headerNavFontSizePreferenceValues = [
14875
+ "inherit",
14876
+ "sm",
14877
+ "base",
14878
+ "lg",
14879
+ "xl"
14880
+ ];
14881
+ const defaultHeaderNavPreferences = {
14882
+ typography: "inherit",
14883
+ fontSize: "inherit",
14884
+ interactionPalette: "recommended"
14885
+ };
14886
+ //#endregion
14887
+ //#region ../theme-core/src/site-styles/headerBrandPresentation.ts
14888
+ /**
14889
+ * Whether the header wears a brand presentation at all (#1318 Phase 4c).
14890
+ *
14891
+ * `applyHeaderBrandPresentation` is unconditional today: given a logo context
14892
+ * it always writes a `logo` object carrying a resolved display, size and
14893
+ * accommodation. That makes "this header has no brand presentation block" —
14894
+ * which is what several live sites persist, including one whose site *does*
14895
+ * have a logo asset — a state the preference record could not express, so a
14896
+ * recompile would silently give the site a logo treatment it has never
14897
+ * rendered.
14898
+ *
14899
+ * This is the third field in this phase with that shape, after the interaction
14900
+ * palette and the nav text size: the persisted bytes carry intent the reader
14901
+ * cannot say, so the recompile "corrects" it. The fix is the same one — widen
14902
+ * the closed vocabulary with a named member and derive it by baseline
14903
+ * comparison — and it is a *widening*, not a restyle: `'recommended'` is the
14904
+ * default and reproduces today's behaviour exactly, so no row whose bytes carry
14905
+ * a presentation compiles differently for `'plain'` existing.
14906
+ *
14907
+ * `'plain'` is deliberately not "preserve whatever bytes are there". It is a
14908
+ * constructive instruction — *write no presentation block* — so Phase 4e's
14909
+ * compiler, which builds the header from nothing, can produce it.
14910
+ */
14911
+ const headerBrandPresentationValues = ["recommended", "plain"];
14912
+ defaultHeaderBrandPreferences.brandDisplay, defaultHeaderBrandPreferences.logoSize, defaultHeaderNavPreferences.typography, defaultHeaderNavPreferences.fontSize, defaultHeaderNavPreferences.interactionPalette;
14913
+ //#endregion
14512
14914
  //#region ../theme-core/src/site-styles/generatedSchemas.ts
14513
14915
  function uniqueNonEmpty(values) {
14514
14916
  const uniqueValues = [...new Set(values)];
@@ -14577,6 +14979,56 @@ z.object({
14577
14979
  blocks: z.array(generatedPageDesignBlockIntentSchema)
14578
14980
  }).strict();
14579
14981
  //#endregion
14982
+ //#region ../theme-core/src/site-styles/headerPreferencesPersistence.ts
14983
+ const backgroundColorTokenSchema = z.unknown().transform((value, ctx) => {
14984
+ const token = parseSiteChromeBackgroundColorToken(value);
14985
+ if (token === null) {
14986
+ ctx.addIssue({
14987
+ code: "custom",
14988
+ message: "Unknown site chrome background colour token"
14989
+ });
14990
+ return z.NEVER;
14991
+ }
14992
+ return token;
14993
+ });
14994
+ const backgroundOverrideSchema = z.discriminatedUnion("kind", [z.object({ kind: z.literal("default") }).strict(), z.object({
14995
+ kind: z.literal("color"),
14996
+ token: backgroundColorTokenSchema
14997
+ }).strict()]);
14998
+ const logoTextIntentSchema = z.object({
14999
+ mobileMaxWidth: z.enum([
15000
+ "xs",
15001
+ "sm",
15002
+ "md"
15003
+ ]).optional(),
15004
+ mobileWrapLines: z.union([z.literal(1), z.literal(2)]).optional(),
15005
+ hideOnShrink: z.boolean().optional()
15006
+ }).strict();
15007
+ const structureSchema = z.object({
15008
+ positioning: z.union([z.literal("inherit"), z.enum(headerPositioningValues)]),
15009
+ shrinkOnScroll: z.union([z.literal("inherit"), z.boolean()]),
15010
+ logoText: z.union([
15011
+ z.literal("inherit"),
15012
+ z.literal("none"),
15013
+ logoTextIntentSchema
15014
+ ])
15015
+ }).strict();
15016
+ const headerPreferencesShape = {
15017
+ brandPresentation: z.enum(headerBrandPresentationValues),
15018
+ brandDisplay: z.enum(brandDisplayModeValues),
15019
+ logoSize: z.enum(logoSizePolicyValues),
15020
+ navFontRole: z.enum(headerNavTypographyPreferenceValues),
15021
+ navTextSize: z.enum(headerNavFontSizePreferenceValues),
15022
+ interactionPalette: z.union([z.literal("recommended"), z.enum(headerInteractionPaletteValues)]),
15023
+ background: backgroundOverrideSchema,
15024
+ structure: structureSchema
15025
+ };
15026
+ z.object(headerPreferencesShape).strict();
15027
+ z.object(headerPreferencesShape).omit({
15028
+ brandPresentation: true,
15029
+ structure: true
15030
+ }).strict();
15031
+ //#endregion
14580
15032
  //#region ../theme-core/src/site-styles/pageDesignAuthority.ts
14581
15033
  const nonEmptyStringSchema = z.string().min(1);
14582
15034
  const blockContentVersionIdSchema = nonEmptyStringSchema.transform(asBlockContentVersionId);
@@ -14678,21 +15130,6 @@ function collectBlockSequenceIssues(snapshots) {
14678
15130
  return issues;
14679
15131
  }
14680
15132
  //#endregion
14681
- //#region ../theme-core/src/site-styles/siteChromeBackgrounds.ts
14682
- const siteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceColorTokenNames);
14683
- const quickSiteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceQuickColorTokenNames);
14684
- siteChromeBackgroundColorTokens.filter((token) => !quickSiteChromeBackgroundColorTokens.includes(token));
14685
- function parseSiteChromeBackgroundColorToken(value) {
14686
- const token = parseBackgroundAppearanceColorToken(value);
14687
- return token ? token : null;
14688
- }
14689
- function toSiteChromeBackgroundColorTokens(tokenNames) {
14690
- return tokenNames.flatMap((name) => {
14691
- const token = parseSiteChromeBackgroundColorToken(name);
14692
- return token ? [token] : [];
14693
- });
14694
- }
14695
- //#endregion
14696
15133
  //#region ../theme-core/src/site-styles/tokenRecipes.ts
14697
15134
  const themeTokenRecipeOptions = {
14698
15135
  palette: [
@@ -23987,7 +24424,7 @@ const mediaTransforms = [{
23987
24424
  /**
23988
24425
  * Strict record guard: excludes null, primitives, and arrays.
23989
24426
  */
23990
- function isRecord$6(value) {
24427
+ function isRecord$5(value) {
23991
24428
  return typeof value === "object" && value !== null && !Array.isArray(value);
23992
24429
  }
23993
24430
  //#endregion
@@ -23997,16 +24434,16 @@ const interpolateRichTextTokensOptionsSchema = z.object({ tokens: z.array(suppor
23997
24434
  const richTextTokenPattern = /\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/g;
23998
24435
  function getSiteName(context) {
23999
24436
  const viewModel = context.viewModel;
24000
- if (!isRecord$6(viewModel)) return null;
24437
+ if (!isRecord$5(viewModel)) return null;
24001
24438
  const site = viewModel.site;
24002
- if (isRecord$6(site) && typeof site.title === "string") {
24439
+ if (isRecord$5(site) && typeof site.title === "string") {
24003
24440
  const title = site.title.trim();
24004
24441
  return title.length > 0 ? title : null;
24005
24442
  }
24006
24443
  const root = viewModel.$root;
24007
- if (isRecord$6(root)) {
24444
+ if (isRecord$5(root)) {
24008
24445
  const rootSite = root.site;
24009
- if (isRecord$6(rootSite) && typeof rootSite.title === "string") {
24446
+ if (isRecord$5(rootSite) && typeof rootSite.title === "string") {
24010
24447
  const title = rootSite.title.trim();
24011
24448
  if (title.length > 0) return title;
24012
24449
  }
@@ -24028,7 +24465,7 @@ function replaceTokenText(input, allowedTokens, tokenValues) {
24028
24465
  });
24029
24466
  }
24030
24467
  function visitRichTextNode(node, allowedTokens, tokenValues) {
24031
- if (!isRecord$6(node)) return node;
24468
+ if (!isRecord$5(node)) return node;
24032
24469
  let changed = false;
24033
24470
  const nextNode = { ...node };
24034
24471
  if (nextNode.type === "text" && typeof nextNode.text === "string") {
@@ -24049,7 +24486,7 @@ function visitRichTextNode(node, allowedTokens, tokenValues) {
24049
24486
  return changed ? nextNode : node;
24050
24487
  }
24051
24488
  function interpolateRichTextTokens(value, options, context) {
24052
- if (!isRecord$6(value)) return value;
24489
+ if (!isRecord$5(value)) return value;
24053
24490
  return visitRichTextNode(value, new Set(options.tokens), {
24054
24491
  year: String((/* @__PURE__ */ new Date()).getFullYear()),
24055
24492
  site_name: getSiteName(context)
@@ -26472,251 +26909,6 @@ const bookingRequirementConsentFieldSchema = z.object({
26472
26909
  });
26473
26910
  z.union([blockBookingConsentSchema, bookingRequirementConsentFieldSchema]);
26474
26911
  //#endregion
26475
- //#region ../blocks/src/system/blocks/events/whole-series/pricing.ts
26476
- function isSaleWindowOpen(option, now) {
26477
- if (!option.isActive) return false;
26478
- if (option.saleStartsAt && new Date(option.saleStartsAt) > now) return false;
26479
- if (option.saleEndsAt && new Date(option.saleEndsAt) < now) return false;
26480
- return true;
26481
- }
26482
- function toExactOrFreeDisplay(amount, currency) {
26483
- if (amount <= 0) return {
26484
- kind: "free",
26485
- currency
26486
- };
26487
- return {
26488
- kind: "exact",
26489
- amount,
26490
- currency
26491
- };
26492
- }
26493
- function getSelectableWholeSeriesPricingOptionsForNow(offering, now) {
26494
- if (offering.pricing.pricingStrategy !== "tiered") return [];
26495
- return [...offering.pricing.options].filter((option) => isSaleWindowOpen(option, now)).sort((left, right) => {
26496
- if (left.sortOrder !== right.sortOrder) return left.sortOrder - right.sortOrder;
26497
- if (left.priceAmount !== right.priceAmount) return left.priceAmount - right.priceAmount;
26498
- return left.name.localeCompare(right.name);
26499
- });
26500
- }
26501
- function resolveWholeSeriesPricingState(offering, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
26502
- const selection = normalizePricingSelectionInput(selectedSlidingAmountOrNowInput, nowInput);
26503
- const currency = offering.pricing.currency;
26504
- switch (offering.pricing.pricingStrategy) {
26505
- case "free": return resolveFreePricing(currency);
26506
- case "single": return resolveSinglePricing(offering.pricing.singlePriceAmount ?? 0, currency);
26507
- case "tiered": return resolveTieredPricing(offering, selectedPricingOptionId, selection.nowInput);
26508
- case "sliding_scale": return resolveSlidingScalePricing(offering, selection.selectedSlidingAmount);
26509
- }
26510
- }
26511
- function normalizePricingSelectionInput(selectedSlidingAmountOrNowInput, nowInput) {
26512
- return typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? {
26513
- selectedSlidingAmount: null,
26514
- nowInput: selectedSlidingAmountOrNowInput
26515
- } : {
26516
- selectedSlidingAmount: typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null,
26517
- nowInput
26518
- };
26519
- }
26520
- function resolveFreePricing(currency) {
26521
- return {
26522
- currency,
26523
- display: {
26524
- kind: "free",
26525
- currency
26526
- },
26527
- selectableOptions: [],
26528
- requiresSelection: false,
26529
- selectedOption: null,
26530
- slidingScale: null,
26531
- selectedSlidingAmount: null,
26532
- selectedPriceAmount: 0,
26533
- selectedRequiresPayment: false,
26534
- hasPaidSelection: false,
26535
- hasFreeSelection: true
26536
- };
26537
- }
26538
- function resolveSinglePricing(amount, currency) {
26539
- return {
26540
- currency,
26541
- display: toExactOrFreeDisplay(amount, currency),
26542
- selectableOptions: [],
26543
- requiresSelection: false,
26544
- selectedOption: null,
26545
- slidingScale: null,
26546
- selectedSlidingAmount: null,
26547
- selectedPriceAmount: amount,
26548
- selectedRequiresPayment: amount > 0,
26549
- hasPaidSelection: amount > 0,
26550
- hasFreeSelection: amount <= 0
26551
- };
26552
- }
26553
- function resolveTieredPricing(offering, selectedPricingOptionId, nowInput) {
26554
- const currency = offering.pricing.currency;
26555
- const selectableOptions = getSelectableWholeSeriesPricingOptionsForNow(offering, resolvePlanningDateInput(nowInput));
26556
- const selectedOption = resolveSelectedTier(selectableOptions, selectedPricingOptionId);
26557
- return {
26558
- currency,
26559
- display: resolveTieredDisplay(selectableOptions.reduce((lowest, option) => lowest === null || option.priceAmount < lowest ? option.priceAmount : lowest, null), selectableOptions.length, currency),
26560
- selectableOptions,
26561
- requiresSelection: selectableOptions.length > 1,
26562
- selectedOption,
26563
- slidingScale: null,
26564
- selectedSlidingAmount: null,
26565
- selectedPriceAmount: selectedOption?.priceAmount ?? null,
26566
- selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
26567
- hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
26568
- hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
26569
- };
26570
- }
26571
- function resolveSelectedTier(options, selectedId) {
26572
- return (selectedId ? options.find((option) => option.id === selectedId) : null) ?? (options.length === 1 ? options[0] ?? null : null);
26573
- }
26574
- function resolveTieredDisplay(lowestAmount, optionCount, currency) {
26575
- if (lowestAmount === null) return {
26576
- kind: "unavailable",
26577
- currency
26578
- };
26579
- return optionCount > 1 && lowestAmount > 0 ? {
26580
- kind: "from",
26581
- amount: lowestAmount,
26582
- currency
26583
- } : toExactOrFreeDisplay(lowestAmount, currency);
26584
- }
26585
- function resolveSlidingScalePricing(offering, selectedSlidingAmount) {
26586
- const currency = offering.pricing.currency;
26587
- const minAmount = offering.pricing.slidingMinAmount ?? null;
26588
- const maxAmount = offering.pricing.slidingMaxAmount ?? null;
26589
- if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) return unavailableSlidingScale(currency);
26590
- const selectedAmount = Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
26591
- return {
26592
- currency,
26593
- display: {
26594
- kind: "range",
26595
- minAmount,
26596
- maxAmount,
26597
- currency
26598
- },
26599
- selectableOptions: [],
26600
- requiresSelection: selectedAmount === null,
26601
- selectedOption: null,
26602
- slidingScale: {
26603
- minAmount,
26604
- maxAmount,
26605
- suggestedAmount: offering.pricing.slidingSuggestedAmount ?? null
26606
- },
26607
- selectedSlidingAmount: selectedAmount,
26608
- selectedPriceAmount: selectedAmount,
26609
- selectedRequiresPayment: (selectedAmount ?? 0) > 0,
26610
- hasPaidSelection: maxAmount > 0,
26611
- hasFreeSelection: minAmount === 0
26612
- };
26613
- }
26614
- function unavailableSlidingScale(currency) {
26615
- return {
26616
- currency,
26617
- display: {
26618
- kind: "unavailable",
26619
- currency
26620
- },
26621
- selectableOptions: [],
26622
- requiresSelection: true,
26623
- selectedOption: null,
26624
- slidingScale: null,
26625
- selectedSlidingAmount: null,
26626
- selectedPriceAmount: null,
26627
- selectedRequiresPayment: false,
26628
- hasPaidSelection: false,
26629
- hasFreeSelection: false
26630
- };
26631
- }
26632
- //#endregion
26633
- //#region ../blocks/src/system/blocks/events/whole-series/schemas.ts
26634
- const wholeSeriesVenueSchema = z.object({
26635
- id: z.string(),
26636
- name: z.string(),
26637
- address: z.string().nullable()
26638
- });
26639
- const wholeSeriesSessionSchema = z.object({
26640
- id: z.string(),
26641
- startsAt: z.string(),
26642
- endsAt: z.string(),
26643
- timeZone: z.string(),
26644
- capacityOverride: z.number().nullable().optional(),
26645
- overrides: z.record(z.string(), z.unknown()).nullable().optional()
26646
- });
26647
- const wholeSeriesTeamMemberSummarySchema = z.object({
26648
- id: z.string(),
26649
- name: z.string(),
26650
- roleLabel: z.string().nullable(),
26651
- summary: z.string().nullable(),
26652
- profilePath: z.string().nullable()
26653
- });
26654
- const wholeSeriesPricingOptionSchema = z.object({
26655
- id: z.string(),
26656
- name: z.string(),
26657
- description: z.string().nullable(),
26658
- priceAmount: z.number(),
26659
- isActive: z.boolean(),
26660
- sortOrder: z.number(),
26661
- capacityLimit: z.number().nullable(),
26662
- saleStartsAt: z.string().nullable(),
26663
- saleEndsAt: z.string().nullable(),
26664
- attendanceScope: z.enum([
26665
- "in_person",
26666
- "online",
26667
- "both"
26668
- ]).nullable().optional()
26669
- });
26670
- const wholeSeriesPricingSchema = z.object({
26671
- bookingRequirement: z.enum(["none", "required"]),
26672
- pricingStrategy: z.enum([
26673
- "free",
26674
- "single",
26675
- "tiered",
26676
- "sliding_scale"
26677
- ]),
26678
- currency: z.string(),
26679
- singlePriceAmount: z.number().nullable(),
26680
- slidingMinAmount: z.number().nullable().optional(),
26681
- slidingMaxAmount: z.number().nullable().optional(),
26682
- slidingSuggestedAmount: z.number().nullable().optional(),
26683
- paymentTerms: blockBookingPaymentTermsSchema,
26684
- options: z.array(wholeSeriesPricingOptionSchema)
26685
- });
26686
- const publicWholeSeriesOfferingSchema = z.object({
26687
- eventSeriesId: z.string(),
26688
- eventOfferingId: z.string(),
26689
- title: z.string(),
26690
- slug: z.string(),
26691
- description: z.unknown().nullable(),
26692
- deliveryMode: z.enum([
26693
- "in_person",
26694
- "online",
26695
- "hybrid"
26696
- ]),
26697
- waitlistEnabled: z.boolean(),
26698
- requireGuestDetails: z.boolean(),
26699
- teamMembers: z.array(wholeSeriesTeamMemberSummarySchema).optional(),
26700
- enrollmentOpen: z.boolean(),
26701
- pricing: wholeSeriesPricingSchema,
26702
- currency: z.string(),
26703
- paymentTerms: blockBookingPaymentTermsSchema,
26704
- consent: blockBookingConsentSchema.nullable(),
26705
- enrollmentCapacity: z.number().nullable(),
26706
- acceptsMemberships: z.boolean(),
26707
- status: z.enum([
26708
- "active",
26709
- "draft",
26710
- "cancelled"
26711
- ]),
26712
- sessionsCount: z.number(),
26713
- enrolledCount: z.number(),
26714
- availableSpots: z.number().nullable(),
26715
- sessions: z.array(wholeSeriesSessionSchema),
26716
- venue: wholeSeriesVenueSchema.nullable()
26717
- });
26718
- const publicWholeSeriesOfferingsArraySchema = z.array(publicWholeSeriesOfferingSchema);
26719
- //#endregion
26720
26912
  //#region ../blocks/src/system/blocks/events/shared/schemas.ts
26721
26913
  const eventPresetSchema = z.enum([
26722
26914
  "event",
@@ -26771,77 +26963,14 @@ const eventCategorySchema = z.object({
26771
26963
  name: z.string(),
26772
26964
  color: z.string().nullable()
26773
26965
  });
26774
- z.enum([
26775
- "free",
26776
- "paid",
26777
- "external"
26778
- ]);
26779
26966
  /**
26780
26967
  * Access restriction type for public events
26781
26968
  */
26782
26969
  const accessRestrictionSchema = z.enum(["none", "category"]);
26783
- z.enum(["single", "ticket_types"]);
26784
- const freePriceDisplaySchema = z.object({
26785
- kind: z.literal("free"),
26786
- currency: z.string()
26787
- });
26788
- const exactPriceDisplaySchema = z.object({
26789
- kind: z.literal("exact"),
26790
- amount: z.number(),
26791
- currency: z.string()
26792
- });
26793
- const fromPriceDisplaySchema = z.object({
26794
- kind: z.literal("from"),
26795
- amount: z.number(),
26796
- currency: z.string()
26797
- });
26798
- const unavailablePriceDisplaySchema = z.object({
26799
- kind: z.literal("unavailable"),
26800
- currency: z.string()
26801
- });
26802
- const rangePriceDisplaySchema = z.object({
26803
- kind: z.literal("range"),
26804
- minAmount: z.number(),
26805
- maxAmount: z.number(),
26806
- currency: z.string()
26807
- });
26808
- const mixedPriceDisplaySchema = z.object({
26809
- kind: z.literal("mixed"),
26810
- paidFromAmount: z.number(),
26811
- paidToAmount: z.number(),
26812
- currency: z.string()
26813
- });
26814
- const publicWholeSeriesPriceDisplaySchema = z.discriminatedUnion("kind", [
26815
- freePriceDisplaySchema,
26816
- exactPriceDisplaySchema,
26817
- fromPriceDisplaySchema,
26818
- rangePriceDisplaySchema,
26819
- unavailablePriceDisplaySchema
26820
- ]);
26821
- z.discriminatedUnion("kind", [
26822
- freePriceDisplaySchema,
26823
- exactPriceDisplaySchema,
26824
- fromPriceDisplaySchema,
26825
- rangePriceDisplaySchema,
26826
- mixedPriceDisplaySchema,
26827
- unavailablePriceDisplaySchema,
26828
- z.object({
26829
- kind: z.literal("external"),
26830
- label: z.string()
26831
- }),
26832
- z.object({
26833
- kind: z.literal("whole_series"),
26834
- display: publicWholeSeriesPriceDisplaySchema
26835
- })
26836
- ]);
26837
- const publicEventTicketTypePriceDisplaySchema = z.union([
26838
- freePriceDisplaySchema,
26839
- exactPriceDisplaySchema,
26840
- fromPriceDisplaySchema,
26841
- rangePriceDisplaySchema,
26842
- mixedPriceDisplaySchema,
26843
- unavailablePriceDisplaySchema
26844
- ]);
26970
+ const publicCurrencySchema = z.string().regex(/^[A-Z]{3}$/u);
26971
+ const publicCentsSchema = z.number().int().nonnegative();
26972
+ const publicPositiveCentsSchema = z.number().int().positive();
26973
+ const publicIsoDateTimeSchema = z.string().datetime({ offset: true });
26845
26974
  const publicEventAttendanceModeSchema = z.enum(["in_person", "online"]);
26846
26975
  const publicEventAttendanceModeAvailabilitySchema = z.object({
26847
26976
  mode: publicEventAttendanceModeSchema,
@@ -26850,9 +26979,9 @@ const publicEventAttendanceModeAvailabilitySchema = z.object({
26850
26979
  availableSpots: z.number().nullable(),
26851
26980
  waitlistEnabled: z.boolean()
26852
26981
  });
26853
- const publicEventTicketTypeAvailabilitySchema = z.union([z.object({
26982
+ const publicEventPricingOptionAvailabilitySchema = z.union([z.object({
26854
26983
  kind: z.literal("available"),
26855
- remainingCapacity: z.number().nullable()
26984
+ remainingPlaces: z.number().int().nonnegative().nullable()
26856
26985
  }), z.object({
26857
26986
  kind: z.literal("unavailable"),
26858
26987
  reason: z.enum([
@@ -26860,91 +26989,69 @@ const publicEventTicketTypeAvailabilitySchema = z.union([z.object({
26860
26989
  "not_on_sale_yet",
26861
26990
  "sale_ended",
26862
26991
  "sold_out",
26863
- "event_sold_out"
26992
+ "attendance_mode_unavailable",
26993
+ "overallCapacityUnavailable"
26864
26994
  ]),
26865
- remainingCapacity: z.number().nullable()
26995
+ remainingPlaces: z.number().int().nonnegative().nullable()
26866
26996
  })]);
26867
- const publicEventTicketTypeSchema = z.object({
26868
- id: z.string(),
26869
- siteId: z.string(),
26870
- eventSeriesId: z.string(),
26871
- name: z.string(),
26997
+ const publicEventPricingOptionSchema = z.object({
26998
+ id: z.string().min(1),
26999
+ name: z.string().min(1),
26872
27000
  description: z.string().nullable(),
26873
- priceAmount: z.number(),
27001
+ priceAmount: publicCentsSchema,
26874
27002
  isActive: z.boolean(),
26875
- sortOrder: z.number(),
26876
- capacityMode: z.enum(["limited", "unlimited"]),
26877
- capacityLimit: z.number().nullable(),
27003
+ sortOrder: z.number().int().nonnegative(),
26878
27004
  attendanceScope: z.enum([
26879
27005
  "in_person",
26880
27006
  "online",
26881
27007
  "both"
26882
- ]).optional(),
26883
- saleStartsAt: z.string().nullable(),
26884
- saleEndsAt: z.string().nullable(),
26885
- availability: publicEventTicketTypeAvailabilitySchema,
26886
- createdAt: z.string(),
26887
- updatedAt: z.string()
27008
+ ]),
27009
+ saleStartsAt: publicIsoDateTimeSchema.nullable(),
27010
+ saleEndsAt: publicIsoDateTimeSchema.nullable(),
27011
+ availability: publicEventPricingOptionAvailabilitySchema
27012
+ }).superRefine((option, context) => {
27013
+ if (option.saleStartsAt && option.saleEndsAt && Date.parse(option.saleEndsAt) <= Date.parse(option.saleStartsAt)) context.addIssue({
27014
+ code: "custom",
27015
+ path: ["saleEndsAt"],
27016
+ message: "Sale end must be after sale start"
27017
+ });
26888
27018
  });
26889
27019
  const publicEventPricingSchema = z.discriminatedUnion("kind", [
26890
27020
  z.object({
26891
- kind: z.literal("drop_in"),
26892
- currency: z.string(),
26893
- display: z.object({
26894
- kind: z.literal("free"),
26895
- currency: z.string()
26896
- })
27021
+ kind: z.literal("free"),
27022
+ currency: publicCurrencySchema
26897
27023
  }),
26898
27024
  z.object({
26899
- kind: z.literal("free_registration"),
26900
- currency: z.string(),
26901
- display: z.object({
26902
- kind: z.literal("free"),
26903
- currency: z.string()
26904
- })
27025
+ kind: z.literal("single"),
27026
+ amount: publicPositiveCentsSchema,
27027
+ currency: publicCurrencySchema
26905
27028
  }),
26906
27029
  z.object({
26907
- kind: z.literal("single_paid"),
26908
- amount: z.number(),
26909
- currency: z.string(),
26910
- display: z.object({
26911
- kind: z.literal("exact"),
26912
- amount: z.number(),
26913
- currency: z.string()
26914
- })
26915
- }),
26916
- z.object({
26917
- kind: z.literal("ticket_types"),
26918
- currency: z.string(),
26919
- ticketTypes: z.array(publicEventTicketTypeSchema),
26920
- display: publicEventTicketTypePriceDisplaySchema
27030
+ kind: z.literal("tiered"),
27031
+ currency: publicCurrencySchema,
27032
+ options: z.tuple([publicEventPricingOptionSchema], publicEventPricingOptionSchema)
26921
27033
  }),
26922
27034
  z.object({
26923
27035
  kind: z.literal("sliding_scale"),
26924
- minAmount: z.number(),
26925
- maxAmount: z.number(),
26926
- suggestedAmount: z.number().nullable(),
26927
- currency: z.string(),
26928
- display: z.object({
26929
- kind: z.literal("range"),
26930
- minAmount: z.number(),
26931
- maxAmount: z.number(),
26932
- currency: z.string()
26933
- })
26934
- }),
26935
- z.object({
26936
- kind: z.literal("whole_series"),
26937
- display: z.object({
26938
- kind: z.literal("whole_series"),
26939
- display: publicWholeSeriesPriceDisplaySchema
26940
- })
27036
+ minimum: publicCentsSchema,
27037
+ maximum: publicPositiveCentsSchema,
27038
+ suggested: publicCentsSchema.nullable(),
27039
+ currency: publicCurrencySchema
27040
+ }).superRefine((pricing, context) => {
27041
+ if (pricing.minimum > pricing.maximum) context.addIssue({
27042
+ code: "custom",
27043
+ path: ["minimum"],
27044
+ message: "Minimum must not exceed maximum"
27045
+ });
27046
+ if (pricing.suggested !== null && (pricing.suggested < pricing.minimum || pricing.suggested > pricing.maximum)) context.addIssue({
27047
+ code: "custom",
27048
+ path: ["suggested"],
27049
+ message: "Suggested amount must be within the sliding-scale range"
27050
+ });
26941
27051
  }),
26942
27052
  z.object({
26943
27053
  kind: z.literal("external"),
26944
- display: z.object({
26945
- kind: z.literal("external"),
26946
- label: z.string()
26947
- })
27054
+ label: z.string().min(1)
26948
27055
  })
26949
27056
  ]);
26950
27057
  const publicTeamMemberSummarySchema = z.object({
@@ -26970,11 +27077,30 @@ const publicEventBookingAvailabilitySchema = z.discriminatedUnion("kind", [z.obj
26970
27077
  "enrollment_closed"
26971
27078
  ])
26972
27079
  })]);
27080
+ const publicRunSessionSchema = z.object({
27081
+ occurrenceId: z.string(),
27082
+ startsAt: z.string(),
27083
+ endsAt: z.string(),
27084
+ timeZone: z.string(),
27085
+ status: z.string()
27086
+ });
27087
+ const publicWholeSeriesRunSchema = z.object({
27088
+ eventSeriesId: z.string(),
27089
+ eventOfferingId: z.string(),
27090
+ enrollmentOpen: z.boolean(),
27091
+ visibility: z.enum(["public", "unlisted"]),
27092
+ lifecycle: z.enum([
27093
+ "upcoming",
27094
+ "in_progress",
27095
+ "completed",
27096
+ "cancelled"
27097
+ ]),
27098
+ sessions: z.array(publicRunSessionSchema)
27099
+ });
26973
27100
  /**
26974
- * Zod schema for public event data
27101
+ * Zod schema for the fields shared by both booking scopes.
26975
27102
  */
26976
- const publicEventSchema = z.object({
26977
- bookingScope: z.enum(["single_occurrence", "whole_series"]),
27103
+ const publicEventBaseSchema = z.object({
26978
27104
  eventPreset: eventPresetSchema.optional(),
26979
27105
  eventDestinationMode: eventDestinationModeSchema.optional(),
26980
27106
  scheduleScope: eventScheduleScopeSchema$2.optional(),
@@ -27024,20 +27150,68 @@ const publicEventSchema = z.object({
27024
27150
  accessRestriction: accessRestrictionSchema,
27025
27151
  allowedCategoryIds: z.array(z.string()),
27026
27152
  requireGuestDetails: z.boolean().optional(),
27027
- acceptsPasses: z.boolean().optional(),
27028
- acceptsMemberships: z.boolean().optional(),
27029
- wholeSeries: z.object({
27030
- eventSeriesId: z.string(),
27031
- pricing: wholeSeriesPricingSchema,
27032
- currency: z.string(),
27033
- enrollmentOpen: z.boolean()
27034
- }).nullable().optional()
27153
+ acceptsPasses: z.boolean(),
27154
+ acceptsMemberships: z.boolean()
27035
27155
  });
27036
27156
  /**
27157
+ * Zod schema for public event data.
27158
+ *
27159
+ * The booking scope discriminates: a `whole_series` record without complete
27160
+ * `run` facts is rejected, and a `single_occurrence` record never carries them.
27161
+ */
27162
+ const publicEventSchema = z.union([publicEventBaseSchema.extend({
27163
+ bookingScope: z.literal("single_occurrence"),
27164
+ run: z.undefined().optional()
27165
+ }), publicEventBaseSchema.extend({
27166
+ bookingScope: z.literal("whole_series"),
27167
+ run: publicWholeSeriesRunSchema
27168
+ })]);
27169
+ /**
27037
27170
  * Schema for an array of public events
27038
27171
  */
27039
27172
  const publicEventsArraySchema = z.array(publicEventSchema);
27040
27173
  //#endregion
27174
+ //#region ../blocks/src/system/blocks/events/shared/runGrouping.ts
27175
+ function isWholeSeriesPublicEvent(event) {
27176
+ return event.bookingScope === "whole_series";
27177
+ }
27178
+ /**
27179
+ * Group events into one entry per whole-series run.
27180
+ *
27181
+ * Single-occurrence events are ignored. Run order follows first appearance, so
27182
+ * a caller's sort survives the grouping, and an occurrence that arrives twice
27183
+ * is kept once.
27184
+ */
27185
+ function groupPublicEventsByRun(events) {
27186
+ const occurrencesBySeriesId = /* @__PURE__ */ new Map();
27187
+ const order = [];
27188
+ const seenOccurrenceIds = /* @__PURE__ */ new Set();
27189
+ for (const event of events) {
27190
+ if (!isWholeSeriesPublicEvent(event)) continue;
27191
+ if (seenOccurrenceIds.has(event.occurrenceId)) continue;
27192
+ seenOccurrenceIds.add(event.occurrenceId);
27193
+ const seriesId = event.run.eventSeriesId;
27194
+ const existing = occurrencesBySeriesId.get(seriesId);
27195
+ if (existing) {
27196
+ existing.push(event);
27197
+ continue;
27198
+ }
27199
+ occurrencesBySeriesId.set(seriesId, [event]);
27200
+ order.push(seriesId);
27201
+ }
27202
+ return order.map((eventSeriesId) => {
27203
+ const occurrences = occurrencesBySeriesId.get(eventSeriesId) ?? [];
27204
+ const representative = occurrences[0];
27205
+ if (!representative) throw new Error(`Run ${eventSeriesId} grouped without any occurrence`);
27206
+ return {
27207
+ eventSeriesId,
27208
+ run: representative.run,
27209
+ occurrences,
27210
+ representative
27211
+ };
27212
+ });
27213
+ }
27214
+ //#endregion
27041
27215
  //#region ../blocks/src/system/blocks/events/shared/fields.ts
27042
27216
  /**
27043
27217
  * Shared card styling fields for event blocks
@@ -27087,7 +27261,7 @@ const eventDisplayFields = [
27087
27261
  {
27088
27262
  id: "showCapacity",
27089
27263
  type: "boolean",
27090
- label: "Show available spots",
27264
+ label: "Show available places",
27091
27265
  description: "Display remaining capacity",
27092
27266
  required: false,
27093
27267
  defaultValue: true,
@@ -27318,7 +27492,9 @@ const unsupportedEventRegistrationPageSurfaceSubjectSchema = z.object({
27318
27492
  "unsupportedSubject",
27319
27493
  "invalidEventSeriesId",
27320
27494
  "invalidEventSeriesBookingScope",
27321
- "invalidEventOfferingId"
27495
+ "invalidEventOfferingId",
27496
+ "invalidEventOfferingBookingScope",
27497
+ "invalidEventOfferingCatalogue"
27322
27498
  ])
27323
27499
  });
27324
27500
  const eventRegistrationPageSurfaceSubjectSchema = z.unknown().transform((value, ctx) => {
@@ -27345,7 +27521,7 @@ function resolveEventRegistrationScope(context) {
27345
27521
  if (context.subject?.kind === "eventOffering") return {
27346
27522
  kind: "pageSurfaceOffering",
27347
27523
  offeringId: context.subject.eventOfferingId,
27348
- seriesIds: context.subject.availableEventSeriesIds
27524
+ seriesIds: context.subject.catalogueEventSeriesIds
27349
27525
  };
27350
27526
  if (context.subject?.kind === "unsupported") return {
27351
27527
  kind: "unsupportedPageSurfaceSubject",
@@ -27367,31 +27543,12 @@ function resolveEventRegistrationScopedEvents(events, context) {
27367
27543
  }
27368
27544
  }
27369
27545
  //#endregion
27370
- //#region ../blocks/src/system/runtime/nodes/event-registration/registrationSurface.ts
27371
- function planEventRegistrationScope(input) {
27372
- const subject = input.subject;
27373
- const selectedRunOffering = input.wholeSeriesOffering;
27374
- if (subject?.kind !== "eventOffering" || !selectedRunOffering) return {
27375
- kind: "context",
27376
- events: resolveEventRegistrationScopedEvents(input.events, {
27377
- occurrenceContext: input.occurrenceContext,
27378
- subject
27379
- })
27380
- };
27381
- if (!(selectedRunOffering.eventOfferingId === subject.eventOfferingId && subject.availableEventSeriesIds.some((seriesId) => seriesId === selectedRunOffering.eventSeriesId))) return { kind: "invalidSelectedRun" };
27382
- return {
27383
- kind: "selectedRun",
27384
- events: input.events.filter((event) => event.seriesId === selectedRunOffering.eventSeriesId),
27385
- offering: selectedRunOffering
27386
- };
27387
- }
27388
- //#endregion
27389
- //#region ../blocks/src/system/runtime/nodes/events/shared/destination.ts
27390
- function isRecord$5(value) {
27546
+ //#region ../blocks/src/system/runtime/nodes/events/domain/destination.ts
27547
+ function isRecord$4(value) {
27391
27548
  return typeof value === "object" && value !== null && !Array.isArray(value);
27392
27549
  }
27393
27550
  function isRuntimeEventDestination(value) {
27394
- if (!isRecord$5(value) || typeof value.kind !== "string") return false;
27551
+ if (!isRecord$4(value) || typeof value.kind !== "string") return false;
27395
27552
  if (value.kind === "native") return (value.mode === "cms-managed" || value.mode === "system-managed") && typeof value.path === "string";
27396
27553
  return value.kind === "external" && typeof value.url === "string" && typeof value.label === "string";
27397
27554
  }
@@ -27404,174 +27561,6 @@ function resolveRuntimeEventDestination(event) {
27404
27561
  };
27405
27562
  }
27406
27563
  //#endregion
27407
- //#region ../blocks/src/system/runtime/nodes/events/shared/pricing.ts
27408
- const DEFAULT_EVENT_CURRENCY = "USD";
27409
- function resolveRuntimeEventPricing(event) {
27410
- if (isPublicEventPricing(event.pricing)) return event.pricing;
27411
- if (resolveRuntimeEventDestination(event).kind === "external") return {
27412
- kind: "external",
27413
- display: {
27414
- kind: "external",
27415
- label: "External registration"
27416
- }
27417
- };
27418
- const legacy = event;
27419
- const currency = readCurrency(legacy.currency);
27420
- if (event.requiresRegistration === false) return {
27421
- kind: "drop_in",
27422
- currency,
27423
- display: {
27424
- kind: "free",
27425
- currency
27426
- }
27427
- };
27428
- if (legacy.pricingMode === "ticket_types") return {
27429
- kind: "ticket_types",
27430
- currency,
27431
- ticketTypes: Array.isArray(legacy.ticketTypes) ? legacy.ticketTypes.filter(isPublicEventTicketType) : [],
27432
- display: readTicketTypePriceDisplay(legacy.priceDisplay, currency)
27433
- };
27434
- const amount = typeof legacy.price === "number" ? legacy.price : 0;
27435
- if (legacy.pricingType === "paid" && amount > 0) return {
27436
- kind: "single_paid",
27437
- amount,
27438
- currency,
27439
- display: {
27440
- kind: "exact",
27441
- amount,
27442
- currency
27443
- }
27444
- };
27445
- return {
27446
- kind: "free_registration",
27447
- currency,
27448
- display: {
27449
- kind: "free",
27450
- currency
27451
- }
27452
- };
27453
- }
27454
- function readCurrency(value) {
27455
- return typeof value === "string" && value.trim().length > 0 ? value : DEFAULT_EVENT_CURRENCY;
27456
- }
27457
- function isRecord$4(value) {
27458
- return typeof value === "object" && value !== null && !Array.isArray(value);
27459
- }
27460
- function isPublicEventPricing(value) {
27461
- if (!isRecord$4(value) || typeof value.kind !== "string") return false;
27462
- 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";
27463
- }
27464
- function isPublicEventTicketType(value) {
27465
- return isRecord$4(value) && typeof value.id === "string";
27466
- }
27467
- function readTicketTypePriceDisplay(value, currency) {
27468
- const display = readLegacyPriceDisplay(value, currency);
27469
- return display.kind === "whole_series" || display.kind === "external" ? {
27470
- kind: "unavailable",
27471
- currency
27472
- } : display;
27473
- }
27474
- function readLegacyPriceDisplay(value, currency) {
27475
- if (!isRecord$4(value) || typeof value.kind !== "string") return {
27476
- kind: "unavailable",
27477
- currency
27478
- };
27479
- const displayCurrency = readCurrency(value.currency);
27480
- switch (value.kind) {
27481
- case "free": return {
27482
- kind: "free",
27483
- currency: displayCurrency
27484
- };
27485
- case "exact": return readAmount(value.amount) !== null ? {
27486
- kind: "exact",
27487
- amount: readAmount(value.amount) ?? 0,
27488
- currency: displayCurrency
27489
- } : {
27490
- kind: "unavailable",
27491
- currency
27492
- };
27493
- case "from": return readAmount(value.amount) !== null ? {
27494
- kind: "from",
27495
- amount: readAmount(value.amount) ?? 0,
27496
- currency: displayCurrency
27497
- } : {
27498
- kind: "unavailable",
27499
- currency
27500
- };
27501
- case "range": {
27502
- const minAmount = readAmount(value.minAmount);
27503
- const maxAmount = readAmount(value.maxAmount);
27504
- return minAmount !== null && maxAmount !== null ? {
27505
- kind: "range",
27506
- minAmount,
27507
- maxAmount,
27508
- currency: displayCurrency
27509
- } : {
27510
- kind: "unavailable",
27511
- currency
27512
- };
27513
- }
27514
- case "mixed": return readAmount(value.paidFromAmount) !== null ? {
27515
- kind: "mixed",
27516
- paidFromAmount: readAmount(value.paidFromAmount) ?? 0,
27517
- paidToAmount: readAmount(value.paidToAmount) ?? readAmount(value.paidFromAmount) ?? 0,
27518
- currency: displayCurrency
27519
- } : {
27520
- kind: "unavailable",
27521
- currency
27522
- };
27523
- case "unavailable": return {
27524
- kind: "unavailable",
27525
- currency: displayCurrency
27526
- };
27527
- case "whole_series": return isRecord$4(value.display) ? {
27528
- kind: "whole_series",
27529
- display: readCoursePriceDisplay(value.display, displayCurrency)
27530
- } : {
27531
- kind: "whole_series",
27532
- display: {
27533
- kind: "unavailable",
27534
- currency: displayCurrency
27535
- }
27536
- };
27537
- default: return {
27538
- kind: "unavailable",
27539
- currency
27540
- };
27541
- }
27542
- }
27543
- function readCoursePriceDisplay(value, currency) {
27544
- switch (value.kind) {
27545
- case "free": return {
27546
- kind: "free",
27547
- currency: readCurrency(value.currency)
27548
- };
27549
- case "exact": return readAmount(value.amount) !== null ? {
27550
- kind: "exact",
27551
- amount: readAmount(value.amount) ?? 0,
27552
- currency: readCurrency(value.currency)
27553
- } : {
27554
- kind: "unavailable",
27555
- currency
27556
- };
27557
- case "from": return readAmount(value.amount) !== null ? {
27558
- kind: "from",
27559
- amount: readAmount(value.amount) ?? 0,
27560
- currency: readCurrency(value.currency)
27561
- } : {
27562
- kind: "unavailable",
27563
- currency
27564
- };
27565
- default: return {
27566
- kind: "unavailable",
27567
- currency
27568
- };
27569
- }
27570
- }
27571
- function readAmount(value) {
27572
- return typeof value === "number" && Number.isFinite(value) ? value : null;
27573
- }
27574
- //#endregion
27575
27564
  //#region ../blocks/src/system/constants/events.ts
27576
27565
  const eventCalendarDisplayModeValues = [
27577
27566
  "combined",
@@ -27603,6 +27592,10 @@ const eventCalendarListLayoutOptions = [
27603
27592
  function isEventCalendarDisplayMode(value) {
27604
27593
  return typeof value === "string" && eventCalendarDisplayModeValues.includes(value);
27605
27594
  }
27595
+ function normalizeEventCalendarDisplayMode$1(input) {
27596
+ if (isEventCalendarDisplayMode(input.variant)) return input.variant;
27597
+ return isEventCalendarDisplayMode(input.displayMode) ? input.displayMode : void 0;
27598
+ }
27606
27599
  function isEventCalendarDefaultView(value) {
27607
27600
  return typeof value === "string" && eventCalendarDefaultViewValues.includes(value);
27608
27601
  }
@@ -27672,14 +27665,13 @@ function resolveEventRequiresPayment(input) {
27672
27665
  if (input.eligibility) return input.eligibility.requiresPayment;
27673
27666
  if (input.selectedTicketType) return input.selectedTicketType.priceAmount > 0;
27674
27667
  if (!input.event) return false;
27675
- return publicEventPricingType(resolveRuntimeEventPricing(input.event)) === "paid";
27668
+ return publicEventPricingType(input.event.pricing) === "paid";
27676
27669
  }
27677
27670
  //#endregion
27678
27671
  //#region ../blocks/src/system/runtime/nodes/event-registration/registrationEventAdapter.ts
27679
27672
  function toRegistrationEvent(event) {
27680
27673
  return {
27681
27674
  ...event,
27682
- pricing: resolveRuntimeEventPricing(event),
27683
27675
  selectionId: event.id,
27684
27676
  registrationSubject: {
27685
27677
  kind: "occurrence",
@@ -27690,118 +27682,35 @@ function toRegistrationEvent(event) {
27690
27682
  function toRegistrationEvents(events) {
27691
27683
  return events.filter((event) => event.bookingScope === "single_occurrence").map(toRegistrationEvent);
27692
27684
  }
27693
- function toWholeSeriesTicketType(option) {
27694
- return {
27695
- ...option,
27696
- capacityMode: option.capacityLimit === null ? "unlimited" : "limited",
27697
- attendanceScope: option.attendanceScope ?? void 0,
27698
- availability: {
27699
- kind: "available",
27700
- remainingCapacity: option.capacityLimit
27701
- }
27702
- };
27703
- }
27704
- function toWholeSeriesPricing(offering) {
27705
- const resolved = resolveWholeSeriesPricingState(offering);
27706
- switch (offering.pricing.pricingStrategy) {
27707
- case "free": return {
27708
- kind: "free_registration",
27709
- currency: offering.currency,
27710
- display: {
27711
- kind: "free",
27712
- currency: offering.currency
27713
- }
27714
- };
27715
- case "single": {
27716
- const amount = offering.pricing.singlePriceAmount ?? 0;
27717
- return amount === 0 ? {
27718
- kind: "free_registration",
27719
- currency: offering.currency,
27720
- display: {
27721
- kind: "free",
27722
- currency: offering.currency
27723
- }
27724
- } : {
27725
- kind: "single_paid",
27726
- amount,
27727
- currency: offering.currency,
27728
- display: {
27729
- kind: "exact",
27730
- amount,
27731
- currency: offering.currency
27732
- }
27733
- };
27734
- }
27735
- case "tiered": return {
27736
- kind: "ticket_types",
27737
- currency: offering.currency,
27738
- ticketTypes: resolved.selectableOptions.map((option) => toWholeSeriesTicketType(option)),
27739
- display: resolved.display
27740
- };
27741
- case "sliding_scale": return {
27742
- kind: "sliding_scale",
27743
- minAmount: offering.pricing.slidingMinAmount ?? 0,
27744
- maxAmount: offering.pricing.slidingMaxAmount ?? 0,
27745
- suggestedAmount: offering.pricing.slidingSuggestedAmount ?? null,
27746
- currency: offering.currency,
27747
- display: {
27748
- kind: "range",
27749
- minAmount: offering.pricing.slidingMinAmount ?? 0,
27750
- maxAmount: offering.pricing.slidingMaxAmount ?? 0,
27751
- currency: offering.currency
27752
- }
27753
- };
27754
- }
27755
- }
27756
- function toAttendanceModes(offering) {
27757
- return (offering.deliveryMode === "hybrid" ? ["in_person", "online"] : [offering.deliveryMode]).map((mode) => ({
27758
- mode,
27759
- capacity: offering.enrollmentCapacity,
27760
- registeredCount: offering.enrolledCount,
27761
- availableSpots: offering.availableSpots,
27762
- waitlistEnabled: offering.waitlistEnabled
27763
- }));
27764
- }
27765
- function toWholeSeriesRegistrationEvent(offering) {
27766
- const firstSession = offering.sessions[0];
27767
- const lastSession = offering.sessions[offering.sessions.length - 1];
27685
+ /**
27686
+ * Project one whole-series run onto the registration surface.
27687
+ *
27688
+ * Capacity, pricing, payment terms and consent come straight off the canonical
27689
+ * Event record; only the schedule is widened from the single occurrence to the
27690
+ * live run. A run without live sessions has no registration event.
27691
+ */
27692
+ function toWholeSeriesRegistrationEvent(group) {
27693
+ const { representative, run } = group;
27694
+ const sessions = orderedLiveRunSessions(run.sessions);
27695
+ const firstSession = sessions[0];
27696
+ if (!firstSession) return null;
27697
+ const lastSession = sessions[sessions.length - 1] ?? firstSession;
27768
27698
  return {
27769
- selectionId: offering.eventSeriesId,
27699
+ ...representative,
27700
+ selectionId: run.eventSeriesId,
27770
27701
  registrationSubject: {
27771
27702
  kind: "wholeSeries",
27772
- eventSeriesId: offering.eventSeriesId,
27773
- sessions: offering.sessions
27774
- },
27775
- seriesId: offering.eventSeriesId,
27776
- title: offering.title,
27777
- startsAt: firstSession?.startsAt ?? "",
27778
- endsAt: lastSession?.endsAt ?? firstSession?.endsAt ?? "",
27779
- bookingAvailability: offering.enrollmentOpen ? { kind: "open" } : {
27780
- kind: "closed",
27781
- reason: "enrollment_closed"
27782
- },
27783
- deliveryMode: offering.deliveryMode,
27784
- attendanceModes: toAttendanceModes(offering),
27785
- capacity: offering.enrollmentCapacity,
27786
- registeredCount: offering.enrolledCount,
27787
- availableSpots: offering.availableSpots,
27788
- waitlistEnabled: offering.waitlistEnabled,
27789
- venue: offering.venue ? {
27790
- ...offering.venue,
27791
- location: null
27792
- } : null,
27793
- eventCategory: null,
27794
- teamMembers: offering.teamMembers,
27795
- status: offering.status,
27796
- timeZone: firstSession?.timeZone ?? "UTC",
27797
- pricing: toWholeSeriesPricing(offering),
27798
- paymentTerms: offering.paymentTerms,
27799
- consent: offering.consent,
27800
- requireGuestDetails: offering.requireGuestDetails,
27801
- acceptsPasses: false,
27802
- acceptsMemberships: offering.acceptsMemberships
27703
+ eventSeriesId: run.eventSeriesId,
27704
+ sessions
27705
+ },
27706
+ startsAt: firstSession.startsAt,
27707
+ endsAt: lastSession.endsAt,
27708
+ timeZone: firstSession.timeZone
27803
27709
  };
27804
27710
  }
27711
+ function toWholeSeriesRegistrationEvents(events) {
27712
+ return groupPublicEventsByRun(events).map(toWholeSeriesRegistrationEvent).filter((event) => event !== null);
27713
+ }
27805
27714
  //#endregion
27806
27715
  //#region ../blocks/src/system/runtime/nodes/event-registration.interactive.ts
27807
27716
  const EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS = [
@@ -27821,8 +27730,7 @@ const eventRegistrationHydrationSchemaShape = {
27821
27730
  occurrenceContext: occurrenceContextSchema.optional(),
27822
27731
  subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
27823
27732
  events: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
27824
- wholeSeriesOfferings: publicWholeSeriesOfferingsArraySchema.nullable().optional(),
27825
- wholeSeriesOffering: publicWholeSeriesOfferingSchema.nullable().optional(),
27733
+ wholeSeriesRunEvents: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
27826
27734
  maxTickets: z.string().optional(),
27827
27735
  showVenue: z.boolean().optional(),
27828
27736
  showCapacity: z.boolean().optional(),
@@ -27840,7 +27748,6 @@ const eventRegistrationSourceSchema = z.object({
27840
27748
  portalToken: z.string().nullable().optional(),
27841
27749
  previewToken: z.string().nullable().optional(),
27842
27750
  ...eventRegistrationHydrationSchemaShape,
27843
- subjectWholeSeriesOffering: publicWholeSeriesOfferingSchema.nullable().optional(),
27844
27751
  className: z.string().nullable().optional(),
27845
27752
  buttonText: z.string().nullable().optional(),
27846
27753
  maxTickets: z.string().nullable().optional(),
@@ -27874,7 +27781,8 @@ z.object({
27874
27781
  stage: previewStageSchema.optional()
27875
27782
  });
27876
27783
  function buildEventRegistrationDisplay(source) {
27877
- if (resolveWholeSeriesOffering(source)?.enrollmentOpen === false) return {
27784
+ const selectedRun = resolveSelectedWholeSeriesRun(source);
27785
+ if (selectedRun && (!selectedRun.run.enrollmentOpen || toWholeSeriesRegistrationEvent(selectedRun) === null)) return {
27878
27786
  kind: "event-registration",
27879
27787
  state: "registration-closed",
27880
27788
  className: source.className ?? null,
@@ -27892,13 +27800,11 @@ function buildEventRegistrationDisplay(source) {
27892
27800
  summaryButtonText: source.buttonText?.trim() || "Register"
27893
27801
  };
27894
27802
  }
27895
- function resolveWholeSeriesOffering(source) {
27896
- return source.wholeSeriesOffering ?? source.subjectWholeSeriesOffering ?? null;
27897
- }
27898
27803
  function buildEventRegistrationShellStepLabels(source) {
27899
- const selectedOffering = resolveWholeSeriesOffering(source);
27900
- if (selectedOffering) {
27901
- const selectedEvent = toWholeSeriesRegistrationEvent(selectedOffering);
27804
+ const selectedRun = resolveSelectedWholeSeriesRun(source);
27805
+ if (selectedRun) {
27806
+ const selectedEvent = toWholeSeriesRegistrationEvent(selectedRun);
27807
+ if (!selectedEvent) return EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS;
27902
27808
  return getWizardStepsForContext(true, resolveEventRequiresPayment({
27903
27809
  eligibility: null,
27904
27810
  selectedTicketType: null,
@@ -27919,16 +27825,31 @@ function buildEventRegistrationShellStepLabels(source) {
27919
27825
  }) : false).map((step) => shellLabelForRegistrationStep(step, scopedEvents));
27920
27826
  }
27921
27827
  function scopeEventRegistrationEvents(source) {
27922
- return toRegistrationEvents(scopeEventRegistrationSourceEvents(source));
27828
+ const scoped = scopeEventRegistrationSourceEvents(source);
27829
+ return [...toRegistrationEvents(scoped), ...toWholeSeriesRegistrationEvents(scoped)];
27923
27830
  }
27831
+ /**
27832
+ * Every event this surface may register for, from both of its loads.
27833
+ *
27834
+ * The date page and the run read answer different questions and can name the
27835
+ * same occurrence, so the two lists are joined and any occurrence that arrives
27836
+ * twice is kept once, in the order the date page gave it.
27837
+ */
27924
27838
  function scopeEventRegistrationSourceEvents(source) {
27925
- const scope = planEventRegistrationScope({
27926
- events: source.events ?? [],
27927
- wholeSeriesOffering: source.wholeSeriesOffering,
27839
+ const byOccurrenceId = /* @__PURE__ */ new Map();
27840
+ for (const event of [...source.events ?? [], ...source.wholeSeriesRunEvents ?? []]) if (!byOccurrenceId.has(event.occurrenceId)) byOccurrenceId.set(event.occurrenceId, event);
27841
+ return resolveEventRegistrationScopedEvents([...byOccurrenceId.values()], {
27928
27842
  occurrenceContext: source.occurrenceContext,
27929
27843
  subject: source.subject
27930
27844
  });
27931
- return scope.kind === "invalidSelectedRun" ? [] : [...scope.events];
27845
+ }
27846
+ /**
27847
+ * The one run this surface is registering for, when the scoped events describe
27848
+ * exactly one. More than one run means the visitor still has to choose.
27849
+ */
27850
+ function resolveSelectedWholeSeriesRun(source) {
27851
+ const runs = groupPublicEventsByRun(scopeEventRegistrationSourceEvents(source));
27852
+ return runs.length === 1 ? runs[0] : null;
27932
27853
  }
27933
27854
  function shellLabelForRegistrationStep(step, events) {
27934
27855
  switch (step) {
@@ -27968,8 +27889,6 @@ const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
27968
27889
  occurrenceContext: source.occurrenceContext ?? null,
27969
27890
  subject: source.subject ?? null,
27970
27891
  events,
27971
- wholeSeriesOfferings: source.wholeSeriesOfferings ?? null,
27972
- wholeSeriesOffering: resolveWholeSeriesOffering(source),
27973
27892
  maxTickets: source.maxTickets ?? void 0,
27974
27893
  showVenue: source.showVenue,
27975
27894
  showCapacity: source.showCapacity,
@@ -27988,8 +27907,7 @@ function normalizeEventRegistrationEventInput(value) {
27988
27907
  if (!isRecord$3(value)) return value;
27989
27908
  return {
27990
27909
  ...value,
27991
- destination: resolveRuntimeEventDestination(value),
27992
- pricing: resolveRuntimeEventPricing(value)
27910
+ destination: resolveRuntimeEventDestination(value)
27993
27911
  };
27994
27912
  }
27995
27913
  function isRecord$3(value) {
@@ -28084,7 +28002,7 @@ const eventRegistrationBlockDefinition = {
28084
28002
  {
28085
28003
  id: "showCapacity",
28086
28004
  type: "boolean",
28087
- label: "Show available spots",
28005
+ label: "Show available places",
28088
28006
  description: "Display remaining capacity",
28089
28007
  required: false,
28090
28008
  defaultValue: true,
@@ -28145,9 +28063,7 @@ const eventRegistrationBlockDefinition = {
28145
28063
  fallback: false
28146
28064
  } },
28147
28065
  events: { $bind: { from: "data.events" } },
28148
- wholeSeriesOffering: { $bind: { from: "data.selectedRunOffering.offering" } },
28149
- subjectWholeSeriesOffering: { $bind: { from: "data.subjectWholeSeriesOffering.offering" } },
28150
- wholeSeriesOfferings: { $bind: { from: "data.wholeSeriesOfferings" } },
28066
+ wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
28151
28067
  sitePasses: { $bind: { from: "data.sitePasses" } },
28152
28068
  siteMemberships: { $bind: { from: "data.siteMemberships" } },
28153
28069
  stage: { $bind: {
@@ -28161,9 +28077,7 @@ const eventRegistrationBlockDefinition = {
28161
28077
  runtime: eventRegistrationBlockRuntime,
28162
28078
  dataSchemas: {
28163
28079
  events: publicEventsArraySchema.optional(),
28164
- selectedRunOffering: z.object({ offering: publicWholeSeriesOfferingSchema }).optional(),
28165
- subjectWholeSeriesOffering: z.object({ offering: publicWholeSeriesOfferingSchema }).optional(),
28166
- wholeSeriesOfferings: z.array(publicWholeSeriesOfferingSchema).optional(),
28080
+ wholeSeriesRunEvents: publicEventsArraySchema.optional(),
28167
28081
  sitePasses: publicPassProductCollectionSchema.optional(),
28168
28082
  siteMemberships: publicMembershipProductCollectionSchema.optional(),
28169
28083
  occurrenceContext: occurrenceContextSchema.optional()
@@ -28181,7 +28095,7 @@ const eventRegistrationBlockDefinition = {
28181
28095
  readProfile: "registration",
28182
28096
  seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
28183
28097
  seriesIds: { $bind: {
28184
- from: "$root.subject.availableEventSeriesIds",
28098
+ from: "$root.subject.catalogueEventSeriesIds",
28185
28099
  transforms: [{ id: "value.csv" }]
28186
28100
  } },
28187
28101
  runSeriesId: { $bind: { from: "$root.entrySubrouteContext.run.seriesId" } },
@@ -28189,50 +28103,39 @@ const eventRegistrationBlockDefinition = {
28189
28103
  },
28190
28104
  mode: "server"
28191
28105
  },
28192
- selectedRunOffering: {
28193
- endpoint: "getPublicWholeSeriesOffering",
28194
- params: {
28195
- siteId: { $bind: { from: "$root.siteId" } },
28196
- eventSeriesId: { $bind: { from: "$root.entrySubrouteContext.run.seriesId" } },
28197
- stage: { $bind: {
28198
- from: "$root.previewStage",
28199
- fallback: "published"
28200
- } }
28201
- },
28202
- requiredParams: ["eventSeriesId"],
28203
- mode: "server"
28204
- },
28205
- subjectWholeSeriesOffering: {
28206
- endpoint: "getPublicWholeSeriesOffering",
28106
+ /**
28107
+ * The runs this page can register for, finished ones included.
28108
+ *
28109
+ * The `events` page above is date-bounded, so a run whose first session has
28110
+ * passed contributes no rows to it and the surface would have nothing to
28111
+ * render as closed. This asks for runs instead, and only on a page whose
28112
+ * subject books whole runs. It is scoped exactly like the date page — same
28113
+ * series, same run subroute — because scope and grain are separate
28114
+ * questions. The two lists are joined by occurrence, so a run that appears
28115
+ * in both is still one run.
28116
+ */
28117
+ wholeSeriesRunEvents: {
28118
+ endpoint: "listPublicEvents",
28207
28119
  when: { $bind: {
28208
28120
  from: "$root.subject.isWholeSeriesBooking",
28209
28121
  fallback: false
28210
28122
  } },
28211
28123
  params: {
28212
28124
  siteId: { $bind: { from: "$root.siteId" } },
28213
- eventSeriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
28125
+ readIntent: "runs",
28126
+ limit: "50",
28214
28127
  stage: { $bind: {
28215
28128
  from: "$root.previewStage",
28216
28129
  fallback: "published"
28217
- } }
28218
- },
28219
- requiredParams: ["eventSeriesId"],
28220
- mode: "server"
28221
- },
28222
- wholeSeriesOfferings: {
28223
- endpoint: "listPublicWholeSeriesOfferings",
28224
- params: {
28225
- siteId: { $bind: { from: "$root.siteId" } },
28226
- eventSeriesIds: { $bind: {
28227
- from: "$root.subject.availableEventSeriesIds",
28130
+ } },
28131
+ readProfile: "registration",
28132
+ seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
28133
+ seriesIds: { $bind: {
28134
+ from: "$root.subject.catalogueEventSeriesIds",
28228
28135
  transforms: [{ id: "value.csv" }]
28229
28136
  } },
28230
- stage: { $bind: {
28231
- from: "$root.previewStage",
28232
- fallback: "published"
28233
- } }
28137
+ runSeriesId: { $bind: { from: "$root.entrySubrouteContext.run.seriesId" } }
28234
28138
  },
28235
- requiredParams: ["eventSeriesIds"],
28236
28139
  mode: "server"
28237
28140
  },
28238
28141
  sitePasses: {
@@ -28485,7 +28388,7 @@ const eventDetailsBlockDefinition = {
28485
28388
  readProfile: "details",
28486
28389
  seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
28487
28390
  seriesIds: { $bind: {
28488
- from: "$root.subject.availableEventSeriesIds",
28391
+ from: "$root.subject.catalogueEventSeriesIds",
28489
28392
  transforms: [{ id: "value.csv" }]
28490
28393
  } },
28491
28394
  runSeriesId: { $bind: { from: "$root.entrySubrouteContext.run.seriesId" } },
@@ -28645,7 +28548,11 @@ const eventSpotlightBlockDefinition = {
28645
28548
  } }
28646
28549
  };
28647
28550
  //#endregion
28648
- //#region ../blocks/src/system/runtime/nodes/events/shared/utils.ts
28551
+ //#region ../blocks/src/system/runtime/nodes/events/shared/listingLayout.ts
28552
+ /**
28553
+ * Layout classes for event listing containers and cards. Presentation
28554
+ * plumbing rather than event domain logic, so it lives beside the components.
28555
+ */
28649
28556
  /**
28650
28557
  * Column class mappings for grid layouts, derived from the canonical
28651
28558
  * responsive column ladder (see gridUserColumnLadder).
@@ -28729,6 +28636,97 @@ function resolveEventListPaginationAction(input) {
28729
28636
  };
28730
28637
  }
28731
28638
  //#endregion
28639
+ //#region ../blocks/src/system/blocks/events/shared/calendarWindow.ts
28640
+ function resolveCalendarReadProfile(content) {
28641
+ const mode = normalizeEventCalendarDisplayMode$1(content);
28642
+ return mode === "timetable" || mode === "week-board" ? "timetable" : "listing-card";
28643
+ }
28644
+ /** Runtime picker sentinels and bound loader IDs must describe the same query. */
28645
+ function normalizeCalendarFilterId(value) {
28646
+ const id = value?.trim();
28647
+ return !id || id === "all" ? void 0 : id;
28648
+ }
28649
+ const calendarMonthSchema = z.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).refine((month) => Number(month.slice(0, 4)) > 0, "Invalid calendar year");
28650
+ function calendarMonthDate(month) {
28651
+ return {
28652
+ year: Number(month.slice(0, 4)),
28653
+ month: Number(month.slice(5, 7)),
28654
+ day: 1
28655
+ };
28656
+ }
28657
+ const monthNumber = (month) => {
28658
+ const date = calendarMonthDate(month);
28659
+ return date.year * 12 + date.month - 1;
28660
+ };
28661
+ const calendarMonthWindowSchema = z.object({
28662
+ startMonth: calendarMonthSchema,
28663
+ endMonthExclusive: calendarMonthSchema
28664
+ }).refine((window) => {
28665
+ const width = monthNumber(window.endMonthExclusive) - monthNumber(window.startMonth);
28666
+ return width > 0 && width <= 3;
28667
+ }, "Calendar windows must cover one to three months");
28668
+ z.object({
28669
+ startMonth: calendarMonthSchema.optional(),
28670
+ endMonthExclusive: calendarMonthSchema.optional(),
28671
+ afterStartsAt: z.string().datetime({ offset: true }).optional(),
28672
+ afterId: z.string().uuid().optional(),
28673
+ limit: z.coerce.number().int().min(1).max(200).default(100),
28674
+ stage: z.enum(["published", "preview"]).default("published"),
28675
+ readProfile: z.enum(["listing-card", "timetable"]).optional(),
28676
+ eventSurface: z.enum(eventSurfaceScopeValues).optional(),
28677
+ eventPresets: z.string().optional(),
28678
+ scheduleScope: z.enum(eventScheduleScopeValues).optional(),
28679
+ categoryIds: z.string().optional(),
28680
+ venueId: z.string().transform(normalizeCalendarFilterId).optional(),
28681
+ staffMemberId: z.string().transform(normalizeCalendarFilterId).optional()
28682
+ }).superRefine((query, ctx) => {
28683
+ if (Boolean(query.startMonth) !== Boolean(query.endMonthExclusive)) ctx.addIssue({
28684
+ code: "custom",
28685
+ message: "Both month bounds are required"
28686
+ });
28687
+ if (query.startMonth && query.endMonthExclusive && !calendarMonthWindowSchema.safeParse(query).success) ctx.addIssue({
28688
+ code: "custom",
28689
+ message: "Invalid calendar window"
28690
+ });
28691
+ if (Boolean(query.afterStartsAt) !== Boolean(query.afterId)) ctx.addIssue({
28692
+ code: "custom",
28693
+ message: "Both cursor fields are required"
28694
+ });
28695
+ if (query.afterStartsAt && !query.startMonth) ctx.addIssue({
28696
+ code: "custom",
28697
+ message: "A continuation requires explicit month bounds"
28698
+ });
28699
+ });
28700
+ const calendarSourceCursorSchema = z.object({
28701
+ startsAt: z.string().datetime({ offset: true }),
28702
+ occurrenceId: z.string().uuid()
28703
+ });
28704
+ z.discriminatedUnion("kind", [z.object({ kind: z.literal("complete") }), z.object({
28705
+ kind: z.literal("partial"),
28706
+ nextCursor: calendarSourceCursorSchema
28707
+ })]);
28708
+ const pageFields = {
28709
+ scope: z.object({
28710
+ key: z.string(),
28711
+ timeZone: z.string().transform(toBookingTimeZone)
28712
+ }),
28713
+ window: calendarMonthWindowSchema,
28714
+ initialToday: z.object({
28715
+ year: z.number().int(),
28716
+ month: z.number().int().min(1).max(12),
28717
+ day: z.number().int().min(1).max(31)
28718
+ }),
28719
+ events: z.array(publicEventSchema)
28720
+ };
28721
+ const calendarWindowPageSchema = z.discriminatedUnion("kind", [z.object({
28722
+ ...pageFields,
28723
+ kind: z.literal("complete")
28724
+ }), z.object({
28725
+ ...pageFields,
28726
+ kind: z.literal("partial"),
28727
+ nextCursor: calendarSourceCursorSchema
28728
+ })]);
28729
+ //#endregion
28732
28730
  //#region ../blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.ts
28733
28731
  const eventSurfaceScopeSchema$1 = z.enum(eventSurfaceScopeValues);
28734
28732
  const eventScheduleScopeSchema$1 = z.enum(eventScheduleScopeValues);
@@ -28745,6 +28743,7 @@ const eventCollectionFilterSourceSchemaShape = {
28745
28743
  filterVenueId: z.string().nullable().optional()
28746
28744
  };
28747
28745
  const eventCollectionSourceSchemaShape = {
28746
+ calendarWindow: calendarWindowPageSchema.nullable().optional(),
28748
28747
  events: z.array(publicEventSchema).nullable().optional(),
28749
28748
  siteId: z.string(),
28750
28749
  apiBaseUrl: z.string().optional(),
@@ -28798,6 +28797,7 @@ const eventCollectionDisplaySchemaShape = {
28798
28797
  };
28799
28798
  const eventCollectionHydrationSchema = z.object({
28800
28799
  siteId: z.string(),
28800
+ calendarWindow: calendarWindowPageSchema.optional(),
28801
28801
  stage: previewStageSchema.optional(),
28802
28802
  prefetchedEvents: z.boolean(),
28803
28803
  eventSurface: eventSurfaceScopeSchema$1,
@@ -28856,8 +28856,9 @@ function buildEventCollectionPresentationDisplay(source) {
28856
28856
  };
28857
28857
  }
28858
28858
  function buildEventCollectionHydration(source, now = /* @__PURE__ */ new Date()) {
28859
- const timeZone = toBookingTimeZone(source.bookingTimeZone);
28859
+ const timeZone = source.calendarWindow?.scope.timeZone ?? toBookingTimeZone(source.bookingTimeZone);
28860
28860
  return {
28861
+ calendarWindow: source.calendarWindow ?? void 0,
28861
28862
  siteId: source.siteId,
28862
28863
  stage: source.stage,
28863
28864
  prefetchedEvents: source.events != null,
@@ -28866,7 +28867,7 @@ function buildEventCollectionHydration(source, now = /* @__PURE__ */ new Date())
28866
28867
  scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
28867
28868
  calendarContext: {
28868
28869
  timeZone,
28869
- initialToday: getLocalScheduleDate(now, timeZone)
28870
+ initialToday: source.calendarWindow?.initialToday ?? getLocalScheduleDate(now, timeZone)
28870
28871
  }
28871
28872
  };
28872
28873
  }
@@ -29415,7 +29416,7 @@ function buildEventCalendarDisplay(source) {
29415
29416
  listColumns: source.listColumns ?? source.columns
29416
29417
  }),
29417
29418
  kind: "event-calendar",
29418
- displayMode: source.variant ?? source.displayMode ?? "combined",
29419
+ displayMode: normalizeEventCalendarDisplayMode$1(source) ?? "combined",
29419
29420
  className: source.className ?? null,
29420
29421
  events: (source.events ?? []).slice().sort((left, right) => new Date(left.startsAt).getTime() - new Date(right.startsAt).getTime()),
29421
29422
  boardTitle: normalizeOptionalText(source.boardTitle),
@@ -29433,15 +29434,75 @@ const eventCalendarBlockRuntime = defineProgressiveBlockRuntime({
29433
29434
  render: createZodCodec(eventCalendarRenderSchema)
29434
29435
  },
29435
29436
  buildRender: (source) => ({
29436
- display: buildEventCalendarDisplay(source),
29437
+ display: buildEventCalendarDisplay(source.calendarWindow && (source.variant ?? source.displayMode ?? "combined") !== "combined" && (source.variant ?? source.displayMode) !== "list" ? {
29438
+ ...source,
29439
+ events: source.calendarWindow.events
29440
+ } : source),
29437
29441
  hydration: buildEventCollectionHydration(source)
29438
29442
  })
29439
29443
  });
29440
29444
  //#endregion
29445
+ //#region ../blocks/src/system/blocks/events/eventCalendarDataLoaders.ts
29446
+ const scopeParams = {
29447
+ siteId: { $bind: { from: "$root.siteId" } },
29448
+ stage: { $bind: {
29449
+ from: "$root.previewStage",
29450
+ fallback: "published"
29451
+ } },
29452
+ eventSurface: { $bind: { from: "content.eventSurface" } },
29453
+ eventPresets: { $bind: {
29454
+ from: "content.filterEventPresets",
29455
+ transforms: [{ id: "value.csv" }]
29456
+ } },
29457
+ scheduleScope: { $bind: { from: "content.scheduleScope" } },
29458
+ categoryIds: { $bind: { from: "content.filterCategoryIds" } },
29459
+ staffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
29460
+ venueId: { $bind: { from: "content.filterVenueId" } }
29461
+ };
29462
+ /** Combined renders two jobs; calendar-only variants never pay for the list seed. */
29463
+ const eventCalendarDataLoaders = {
29464
+ events: {
29465
+ endpoint: "listPublicEvents",
29466
+ when: { $bind: {
29467
+ from: "content",
29468
+ transforms: [{
29469
+ id: "events.calendarReadEnabled",
29470
+ options: { job: "list" }
29471
+ }]
29472
+ } },
29473
+ params: {
29474
+ ...scopeParams,
29475
+ limit: 100,
29476
+ detailLevel: "listing",
29477
+ readProfile: "listing-card"
29478
+ },
29479
+ mode: "server"
29480
+ },
29481
+ calendarWindow: {
29482
+ endpoint: "listPublicEventCalendarWindow",
29483
+ when: { $bind: {
29484
+ from: "content",
29485
+ transforms: [{
29486
+ id: "events.calendarReadEnabled",
29487
+ options: { job: "calendar" }
29488
+ }]
29489
+ } },
29490
+ params: {
29491
+ ...scopeParams,
29492
+ limit: 100,
29493
+ readProfile: { $bind: {
29494
+ from: "content",
29495
+ transforms: [{ id: "events.calendarReadProfile" }]
29496
+ } }
29497
+ },
29498
+ mode: "server"
29499
+ }
29500
+ };
29501
+ //#endregion
29441
29502
  //#region ../blocks/src/system/blocks/events/event-calendar.ts
29442
29503
  function normalizeEventCalendarContent(content) {
29443
29504
  const record = typeof content === "object" && content !== null ? content : {};
29444
- const variant = normalizeEventCalendarDisplayMode(record.variant) ?? normalizeEventCalendarDisplayMode(record.displayMode);
29505
+ const variant = normalizeEventCalendarDisplayMode$1(record);
29445
29506
  return {
29446
29507
  ...record,
29447
29508
  ...variant ? { variant } : {},
@@ -29489,6 +29550,7 @@ const eventCalendarLayout = [styledSection({
29489
29550
  rootProps: { gap: "lg" },
29490
29551
  children: [...eventSectionHeaderLayoutNodes({ splitClassName: "event-section-head event-section-head--split" }), el("event-calendar", withApiBindings({
29491
29552
  events: { $bind: { from: "data.events" } },
29553
+ calendarWindow: { $bind: { from: "data.calendarWindow" } },
29492
29554
  stage: { $bind: {
29493
29555
  from: "$root.previewStage",
29494
29556
  fallback: "published"
@@ -29977,7 +30039,7 @@ const eventCalendarAdditionalFields = [
29977
30039
  {
29978
30040
  id: "showCapacity",
29979
30041
  type: "boolean",
29980
- label: "Show available spots",
30042
+ label: "Show available places",
29981
30043
  description: "Display remaining capacity on event cards and timetable cells",
29982
30044
  required: false,
29983
30045
  defaultValue: true,
@@ -30312,33 +30374,11 @@ const eventCalendarBlockDefinition = {
30312
30374
  }
30313
30375
  }, eventCalendarContentShape),
30314
30376
  normalizeContent: normalizeEventCalendarContent,
30315
- dataSchemas: { events: publicEventsArraySchema.optional() },
30316
- dataLoaders: { events: {
30317
- endpoint: "listPublicEvents",
30318
- params: {
30319
- siteId: { $bind: { from: "$root.siteId" } },
30320
- limit: 100,
30321
- stage: { $bind: {
30322
- from: "$root.previewStage",
30323
- fallback: "published"
30324
- } },
30325
- detailLevel: "listing",
30326
- readProfile: { $bind: {
30327
- from: "content.variant",
30328
- fallback: "listing-card"
30329
- } },
30330
- eventSurface: { $bind: { from: "content.eventSurface" } },
30331
- eventPresets: { $bind: {
30332
- from: "content.filterEventPresets",
30333
- transforms: [{ id: "value.csv" }]
30334
- } },
30335
- scheduleScope: { $bind: { from: "content.scheduleScope" } },
30336
- categoryIds: { $bind: { from: "content.filterCategoryIds" } },
30337
- staffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
30338
- venueId: { $bind: { from: "content.filterVenueId" } }
30339
- },
30340
- mode: "server"
30341
- } },
30377
+ dataSchemas: {
30378
+ events: publicEventsArraySchema.optional(),
30379
+ calendarWindow: calendarWindowPageSchema.optional()
30380
+ },
30381
+ dataLoaders: eventCalendarDataLoaders,
30342
30382
  runtime: eventCalendarBlockRuntime
30343
30383
  };
30344
30384
  const recurringScheduleWeekdaySchema = z.enum([
@@ -30666,6 +30706,12 @@ function isRecord$2(value) {
30666
30706
  }
30667
30707
  //#endregion
30668
30708
  //#region ../blocks/src/system/blocks/offerings-preview/index.ts
30709
+ /**
30710
+ * The whole-series presets, as the CSV `listPublicEvents` expects. Both
30711
+ * whole-series presets share one loader: the block renders them as a single
30712
+ * run group.
30713
+ */
30714
+ const WHOLE_SERIES_EVENT_PRESETS_PARAM = WHOLE_SERIES_EVENT_PRESET_VALUES.join(",");
30669
30715
  const publicRouteCandidatesSchema = z.object({ routes: z.array(z.object({
30670
30716
  entityId: z.string(),
30671
30717
  path: z.string(),
@@ -30947,7 +30993,7 @@ const offeringsPreviewManifest = createBlockManifest({
30947
30993
  fallback: "published"
30948
30994
  } },
30949
30995
  routeCandidates: { $bind: { from: "data.routeCandidates" } },
30950
- wholeSeriesOfferings: { $bind: { from: "data.wholeSeriesOfferings" } },
30996
+ wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
30951
30997
  ...offeringsPreviewEventDataBindings
30952
30998
  })
30953
30999
  ], { gap: "lg" }),
@@ -30964,7 +31010,7 @@ const offeringsPreviewBlockDefinition = {
30964
31010
  dataSchemas: {
30965
31011
  ...offeringsPreviewEventDataSchemas,
30966
31012
  routeCandidates: publicRouteCandidatesSchema.optional(),
30967
- wholeSeriesOfferings: publicWholeSeriesOfferingsArraySchema.optional()
31013
+ wholeSeriesRunEvents: optionalPublicEventsArraySchema
30968
31014
  },
30969
31015
  dataLoaders: {
30970
31016
  ...offeringsPreviewEventDataLoaders,
@@ -30973,24 +31019,21 @@ const offeringsPreviewBlockDefinition = {
30973
31019
  params: {},
30974
31020
  mode: "server"
30975
31021
  },
30976
- wholeSeriesOfferings: {
30977
- endpoint: "listPublicWholeSeriesOfferings",
30978
- params: {
30979
- siteId: { $bind: { from: "$root.siteId" } },
30980
- limit: { $bind: {
30981
- from: "content.itemLimit",
30982
- fallback: "3"
30983
- } },
30984
- stage: { $bind: {
30985
- from: "$root.previewStage",
30986
- fallback: "published"
30987
- } }
30988
- },
30989
- mode: "server"
30990
- }
31022
+ wholeSeriesRunEvents: wholeSeriesRunLoader()
30991
31023
  }
30992
31024
  };
30993
- function eventPresetLoader(preset) {
31025
+ /**
31026
+ * One row per whole-series run, finished runs included.
31027
+ *
31028
+ * A page of dates cannot answer this: a finished run has no upcoming date, and
31029
+ * a long run would spend the whole page on its own sessions. `readIntent:
31030
+ * 'runs'` asks for runs instead, so `itemLimit` counts run cards rather than
31031
+ * dates, and each card arrives with the run's complete schedule.
31032
+ */
31033
+ function wholeSeriesRunLoader() {
31034
+ return eventPresetLoader(WHOLE_SERIES_EVENT_PRESETS_PARAM, { readIntent: "runs" });
31035
+ }
31036
+ function eventPresetLoader(eventPresets, extraParams = {}) {
30994
31037
  return {
30995
31038
  endpoint: "listPublicEvents",
30996
31039
  params: {
@@ -31005,7 +31048,8 @@ function eventPresetLoader(preset) {
31005
31048
  } },
31006
31049
  detailLevel: "listing",
31007
31050
  readProfile: "listing-card",
31008
- eventPresets: preset
31051
+ eventPresets,
31052
+ ...extraParams
31009
31053
  },
31010
31054
  mode: "server"
31011
31055
  };
@@ -36589,6 +36633,24 @@ const linksTransforms = [{
36589
36633
  //#endregion
36590
36634
  //#region ../blocks/src/system/transforms/registry/index.ts
36591
36635
  const builtinTransformDefinitions = [
36636
+ {
36637
+ id: "events.calendarReadEnabled",
36638
+ kind: "formatter",
36639
+ summary: "Choose the read projection required by the calendar display mode",
36640
+ schema: z.object({ job: z.enum(["list", "calendar"]) }),
36641
+ run(value, options) {
36642
+ const mode = normalizeEventCalendarDisplayMode$1(asPartialObject(value) ?? {}) ?? "combined";
36643
+ return options.job === "calendar" ? mode !== "list" : mode === "list" || mode === "combined";
36644
+ }
36645
+ },
36646
+ {
36647
+ id: "events.calendarReadProfile",
36648
+ kind: "formatter",
36649
+ summary: "Select media enrichment for the calendar display mode",
36650
+ run(value) {
36651
+ return resolveCalendarReadProfile(asPartialObject(value) ?? {});
36652
+ }
36653
+ },
36592
36654
  ...formattingTransforms,
36593
36655
  ...layoutTransforms,
36594
36656
  ...uiTransforms,
@@ -36606,10 +36668,9 @@ const SUPPORTED_LOADER_ENDPOINTS$1 = [
36606
36668
  "listPublishedEntries",
36607
36669
  "getPublishedEntryPreview",
36608
36670
  "listPublicEvents",
36671
+ "listPublicEventCalendarWindow",
36609
36672
  "listPublicRecurringSchedule",
36610
36673
  "getPublicEventDetails",
36611
- "listPublicWholeSeriesOfferings",
36612
- "getPublicWholeSeriesOffering",
36613
36674
  "listPublicRouteCandidates",
36614
36675
  "listPublicTeamMembers",
36615
36676
  "listPublicProducts",
@@ -37025,6 +37086,50 @@ z.object({
37025
37086
  title: z.string(),
37026
37087
  slug: z.string().min(1)
37027
37088
  });
37089
+ z.object({
37090
+ signedUrl: z.string().url(),
37091
+ token: z.string().min(1),
37092
+ storagePath: z.string().min(1)
37093
+ }).strict();
37094
+ const backupManifestSchema = z.object({
37095
+ siteId: z.string().min(1),
37096
+ siteSlug: z.string().min(1),
37097
+ siteTitle: z.string(),
37098
+ exportedAt: z.string().min(1),
37099
+ tableCount: z.number().int().nonnegative(),
37100
+ totalRecords: z.number().int().nonnegative(),
37101
+ pageCount: z.number().int().nonnegative(),
37102
+ blockCount: z.number().int().nonnegative(),
37103
+ contentEntryCount: z.number().int().nonnegative(),
37104
+ formCount: z.number().int().nonnegative(),
37105
+ navigationMenuCount: z.number().int().nonnegative(),
37106
+ mediaCount: z.number().int().nonnegative(),
37107
+ mediaBytes: z.number().int().nonnegative()
37108
+ }).strict();
37109
+ z.object({
37110
+ ok: z.literal(true),
37111
+ manifest: backupManifestSchema,
37112
+ storagePath: z.string().min(1)
37113
+ }).strict();
37114
+ z.object({
37115
+ ok: z.literal(true),
37116
+ siteId: brandedIdSchema(parseSiteId, "site id"),
37117
+ slug: z.string().min(1),
37118
+ title: z.string(),
37119
+ counts: z.record(z.string(), z.object({
37120
+ created: z.number().int().nonnegative(),
37121
+ updated: z.number().int().nonnegative(),
37122
+ skipped: z.number().int().nonnegative(),
37123
+ failed: z.number().int().nonnegative()
37124
+ }).strict()),
37125
+ warnings: z.array(z.string()),
37126
+ errors: z.array(z.object({
37127
+ table: z.string(),
37128
+ id: z.string(),
37129
+ error: z.string()
37130
+ }).strict())
37131
+ }).strict();
37132
+ z.object({ deleted: z.boolean() }).strict();
37028
37133
  const apiKeyIdSchema = brandedIdSchema(parseApiKeyId, "API key id");
37029
37134
  const standardKeyIdsSchema = z.object({
37030
37135
  live: apiKeyIdSchema.optional(),
@@ -37240,6 +37345,9 @@ z.object({
37240
37345
  return resolved.config;
37241
37346
  });
37242
37347
  //#endregion
37348
+ //#region ../api/src/appointmentServiceVisibility.ts
37349
+ const APPOINTMENT_SERVICE_VISIBILITY_VALUES = ["public", "unlisted"];
37350
+ //#endregion
37243
37351
  //#region ../api/src/utils/isRecord.ts
37244
37352
  function isRecord(value) {
37245
37353
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -37291,6 +37399,7 @@ const appointmentSetupServiceDraftSchema = z.object({
37291
37399
  cleanupMinutes: z.number().int().nonnegative().max(APPOINTMENT_SETUP_MAX_MINUTES).default(0),
37292
37400
  priceAmount: z.number().int().nonnegative().nullable(),
37293
37401
  isActive: z.boolean(),
37402
+ visibility: z.enum(APPOINTMENT_SERVICE_VISIBILITY_VALUES).default("public"),
37294
37403
  locationType: z.union([
37295
37404
  z.literal("virtual"),
37296
37405
  z.literal("in_person"),
@@ -38293,7 +38402,7 @@ const dashboardConfigSchema = z.object({
38293
38402
  const titleSourceValueSchema = z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]);
38294
38403
  //#endregion
38295
38404
  //#region src/data/prefetchBlockData.ts
38296
- const SUPPORTED_LOADER_ENDPOINTS = SUPPORTED_LOADER_ENDPOINTS$1.filter((endpoint) => endpoint !== "listPublicWholeSeriesOfferings");
38405
+ const SUPPORTED_LOADER_ENDPOINTS = SUPPORTED_LOADER_ENDPOINTS$1;
38297
38406
  //#endregion
38298
38407
  //#region src/config/validation.ts
38299
38408
  /**