@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
@@ -40,7 +40,6 @@ const TAG_TEMPLATES = {
40
40
  formSubmissionsBySlug: "riverbank:form-submissions:{slug}",
41
41
  publicEvents: "riverbank:site:{siteId}:public-events",
42
42
  publicEventFilters: "riverbank:site:{siteId}:public-event-filters",
43
- publicWholeSeriesOfferings: "riverbank:site:{siteId}:public-whole-series-offerings",
44
43
  publicTeamMembers: "riverbank:site:{siteId}:public-team-members",
45
44
  publicProducts: "riverbank:site:{siteId}:public-products",
46
45
  publicPasses: "riverbank:site:{siteId}:public-passes",
@@ -49,6 +48,7 @@ const TAG_TEMPLATES = {
49
48
  publicShop: "riverbank:site:{siteId}:public-shop",
50
49
  publicCheckout: "riverbank:site:{siteId}:public-checkout",
51
50
  publicBookingServices: "riverbank:site:{siteId}:public-booking-services",
51
+ publicBookingAvailability: "riverbank:site:{siteId}:public-booking-availability",
52
52
  siteNavigation: "riverbank:site:{siteId}:navigation",
53
53
  navigationMenuById: "riverbank:navigation-menu:{menuId}",
54
54
  navigationItemById: "riverbank:navigation-item:{itemId}",
@@ -1175,30 +1175,15 @@ const NEWSLETTER_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1175
1175
  }
1176
1176
  });
1177
1177
  //#endregion
1178
- //#region ../api/src/publicWholeSeriesEndpointDefinitions.ts
1179
- const PUBLIC_WHOLE_SERIES_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1180
- listPublicWholeSeriesOfferings: {
1181
- path: "/public/sites/{siteId}/dated-offerings/whole-series",
1178
+ //#region ../api/src/publicEventEndpointDefinitions.ts
1179
+ const PUBLIC_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1180
+ listPublicEventCalendarWindow: {
1181
+ path: "/public/sites/{siteId}/events/calendar-window",
1182
1182
  method: "GET",
1183
- revalidate: 60,
1184
- tags: [TAG_TEMPLATES.publicWholeSeriesOfferings],
1185
- errors: ["server:internal_error"],
1183
+ revalidate: 0,
1186
1184
  auth: "public",
1187
1185
  responseKind: "json"
1188
1186
  },
1189
- getPublicWholeSeriesOffering: {
1190
- path: "/public/sites/{siteId}/dated-offerings/whole-series/{eventSeriesId}",
1191
- method: "GET",
1192
- revalidate: 60,
1193
- tags: [TAG_TEMPLATES.publicWholeSeriesOfferings],
1194
- errors: ["resource:not_found", "server:internal_error"],
1195
- auth: "public",
1196
- responseKind: "json"
1197
- }
1198
- });
1199
- //#endregion
1200
- //#region ../api/src/publicEventEndpointDefinitions.ts
1201
- const PUBLIC_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1202
1187
  resolvePublicEventCheckoutReturn: {
1203
1188
  path: "/public/sites/{siteId}/events/checkout-return",
1204
1189
  method: "POST",
@@ -1230,6 +1215,99 @@ const PUBLIC_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1230
1215
  }
1231
1216
  });
1232
1217
  //#endregion
1218
+ //#region ../api/src/publicEventCheckoutEndpointDefinitions.ts
1219
+ /**
1220
+ * The public event registration/checkout endpoints, extracted from
1221
+ * `endpoints.ts`.
1222
+ *
1223
+ * They were moved out for the same reason the `sdkMedia*` block was: adding the
1224
+ * `errors` metadata `require-api-endpoint-errors` asks of a newly-added endpoint
1225
+ * pushed `endpoints.ts` past its `max-lines` baseline. The block is spread back
1226
+ * at the exact position it occupied, so `API_ENDPOINTS` key order is unchanged.
1227
+ * (The endpoint that originally motivated the move, `checkPublicEventEligibility`,
1228
+ * was since deleted on dev by #1326.)
1229
+ */
1230
+ const PUBLIC_EVENT_CHECKOUT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1231
+ registerForEvent: {
1232
+ path: "/public/sites/{siteId}/events/register",
1233
+ method: "POST",
1234
+ tags: [TAG_TEMPLATES.publicEvents, "event-registration"],
1235
+ auth: "public",
1236
+ responseKind: "json"
1237
+ },
1238
+ createPublicEventCheckout: {
1239
+ path: "/public/sites/{siteId}/events/checkout",
1240
+ method: "POST",
1241
+ tags: [TAG_TEMPLATES.publicEvents, "event-checkout"],
1242
+ auth: "public",
1243
+ responseKind: "json"
1244
+ }
1245
+ });
1246
+ //#endregion
1247
+ //#region ../api/src/publicBookingAvailabilityEndpointDefinitions.ts
1248
+ /**
1249
+ * Public appointment reads: the service catalogue and the bookable slot grid.
1250
+ *
1251
+ * These are the reads that appointment writes invalidate. They carry canonical
1252
+ * `riverbank:*` tags because the frontend revalidate endpoint discards anything
1253
+ * else, which is why the legacy `site-{siteId}` tag they used to declare could
1254
+ * never actually be cleared (issue 1364).
1255
+ *
1256
+ * Slot availability depends on both tags: the grid moves when a booking lands,
1257
+ * and again when the service definition behind it changes.
1258
+ */
1259
+ const PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1260
+ getPublicBookingServices: {
1261
+ path: "/public/bookings/services",
1262
+ method: "GET",
1263
+ revalidate: 60,
1264
+ tags: [TAG_TEMPLATES.publicBookingServices],
1265
+ auth: "public",
1266
+ responseKind: "json"
1267
+ },
1268
+ getPublicBookingService: {
1269
+ path: "/public/bookings/services/{serviceId}",
1270
+ method: "GET",
1271
+ revalidate: 60,
1272
+ tags: [TAG_TEMPLATES.publicBookingServices],
1273
+ auth: "public",
1274
+ responseKind: "json"
1275
+ },
1276
+ getPublicBookingResourcesReference: {
1277
+ path: "/public/bookings/resources/reference",
1278
+ method: "GET",
1279
+ revalidate: 60,
1280
+ tags: [TAG_TEMPLATES.publicBookingServices],
1281
+ auth: "public",
1282
+ responseKind: "json"
1283
+ },
1284
+ getPublicBookingAvailableDates: {
1285
+ path: "/public/bookings/availability/dates",
1286
+ method: "GET",
1287
+ revalidate: 60,
1288
+ tags: [TAG_TEMPLATES.publicBookingAvailability, TAG_TEMPLATES.publicBookingServices],
1289
+ auth: "public",
1290
+ responseKind: "json"
1291
+ },
1292
+ getPublicBookingAvailableSlots: {
1293
+ path: "/public/bookings/availability/slots",
1294
+ method: "GET",
1295
+ revalidate: 60,
1296
+ tags: [TAG_TEMPLATES.publicBookingAvailability, TAG_TEMPLATES.publicBookingServices],
1297
+ auth: "public",
1298
+ responseKind: "json"
1299
+ },
1300
+ getPublicWeeklySlotAvailability: {
1301
+ path: "/public/bookings/weekly-slot-availability",
1302
+ method: "GET",
1303
+ revalidate: 60,
1304
+ tags: [TAG_TEMPLATES.publicBookingAvailability, TAG_TEMPLATES.publicBookingServices],
1305
+ auth: "public",
1306
+ responseKind: "json",
1307
+ errors: []
1308
+ }
1309
+ });
1310
+ //#endregion
1233
1311
  //#region ../api/src/siteApiKeyEndpointDefinitions.ts
1234
1312
  const SITE_API_KEY_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1235
1313
  listSiteApiKeys: {
@@ -1590,6 +1668,88 @@ const SDK_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1590
1668
  errors: ["validation:invalid_input", "server:internal_error"]
1591
1669
  }
1592
1670
  });
1671
+ //#endregion
1672
+ //#region ../api/src/sdkMediaEndpointDefinitions.ts
1673
+ /** SDK media lookup, listing, deletion and upload endpoints (management-key authenticated). */
1674
+ const SDK_MEDIA_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1675
+ sdkMediaExists: {
1676
+ path: "/sdk/{siteId}/media/exists",
1677
+ method: "POST",
1678
+ errors: ["validation:invalid_input"],
1679
+ auth: "service",
1680
+ responseKind: "json"
1681
+ },
1682
+ sdkMediaFindByChecksum: {
1683
+ path: "/sdk/{siteId}/media/find-by-checksum",
1684
+ method: "POST",
1685
+ errors: ["server:internal_error"],
1686
+ auth: "service",
1687
+ responseKind: "json"
1688
+ },
1689
+ sdkMediaResolve: {
1690
+ path: "/sdk/{siteId}/media/resolve",
1691
+ method: "POST",
1692
+ errors: ["server:internal_error"],
1693
+ auth: "service",
1694
+ responseKind: "json"
1695
+ },
1696
+ sdkMediaList: {
1697
+ path: "/sdk/{siteId}/media",
1698
+ method: "GET",
1699
+ auth: "service",
1700
+ errors: [],
1701
+ responseKind: "json"
1702
+ },
1703
+ sdkMediaDownload: {
1704
+ path: "/sdk/{siteId}/media/{identifier}/download",
1705
+ method: "GET",
1706
+ auth: "service",
1707
+ errors: [],
1708
+ responseKind: "json"
1709
+ },
1710
+ sdkMediaDeletePreview: {
1711
+ path: "/sdk/{siteId}/media/{identifier}/delete-preview",
1712
+ method: "POST",
1713
+ auth: "service",
1714
+ errors: [],
1715
+ responseKind: "json"
1716
+ },
1717
+ sdkMediaDeleteApply: {
1718
+ path: "/sdk/{siteId}/media/{identifier}",
1719
+ method: "DELETE",
1720
+ auth: "service",
1721
+ errors: [],
1722
+ responseKind: "json"
1723
+ },
1724
+ sdkMediaUploadUrl: {
1725
+ path: "/sdk/{siteId}/media/upload-url",
1726
+ method: "POST",
1727
+ errors: [
1728
+ "resource:not_found",
1729
+ "validation:invalid_input",
1730
+ "resource:conflict",
1731
+ "validation:payload_too_large",
1732
+ "billing:plan_limit_exceeded",
1733
+ "server:internal_error"
1734
+ ],
1735
+ auth: "service",
1736
+ responseKind: "json"
1737
+ },
1738
+ sdkMediaUploadFinalize: {
1739
+ path: "/sdk/{siteId}/media/upload",
1740
+ method: "POST",
1741
+ errors: [
1742
+ "resource:not_found",
1743
+ "validation:invalid_input",
1744
+ "resource:conflict",
1745
+ "validation:payload_too_large",
1746
+ "billing:plan_limit_exceeded",
1747
+ "server:internal_error"
1748
+ ],
1749
+ auth: "service",
1750
+ responseKind: "json"
1751
+ }
1752
+ });
1593
1753
  ({
1594
1754
  ...ACCOUNT_ENDPOINT_DEFINITIONS,
1595
1755
  ...PUBLIC_EVENT_ENDPOINT_DEFINITIONS,
@@ -1598,7 +1758,7 @@ const SDK_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1598
1758
  ...NEWSLETTER_ENDPOINT_DEFINITIONS,
1599
1759
  ...APPOINTMENT_ENDPOINT_DEFINITIONS,
1600
1760
  ...EVENT_SERIES_REGISTRATION_ENDPOINT_DEFINITIONS
1601
- }, 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 };
1761
+ }, 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 };
1602
1762
  z.object({ refreshToken: z.string().min(1).max(4096) }).strict();
1603
1763
  z.object({
1604
1764
  accessToken: z.string().min(1).max(4096),
@@ -1765,22 +1925,59 @@ function formatCurrencyAmount(amountCents, currency, options) {
1765
1925
  }
1766
1926
  }
1767
1927
  //#endregion
1928
+ //#region ../core/src/planner.ts
1929
+ /** Default clock for production callers that do not inject time explicitly. */
1930
+ const systemPlanningClock = { now: () => Date.now() };
1931
+ /** Resolve current time as a Date from an explicit Date, injected clock, or system clock. */
1932
+ function resolvePlanningNowDate(input = {}) {
1933
+ if (input.now !== void 0) return input.now;
1934
+ return new Date((input.clock ?? systemPlanningClock).now());
1935
+ }
1936
+ //#endregion
1768
1937
  //#region ../core/src/event-pricing.ts
1938
+ /** Capacity closes booking, but does not make an otherwise eligible price unknown. */
1939
+ function isPublicEventPricingOptionDisplayable(option) {
1940
+ if (!option.isActive) return false;
1941
+ if (option.availability.kind === "available") return true;
1942
+ const reason = option.availability.reason;
1943
+ switch (reason) {
1944
+ case "sold_out":
1945
+ case "overallCapacityUnavailable": return true;
1946
+ case "inactive":
1947
+ case "not_on_sale_yet":
1948
+ case "sale_ended":
1949
+ case "attendance_mode_unavailable": return false;
1950
+ default: return assertNever$2(reason);
1951
+ }
1952
+ }
1953
+ function publicEventPricingDisplay(pricing) {
1954
+ switch (pricing.kind) {
1955
+ case "free":
1956
+ case "single":
1957
+ case "sliding_scale": return canonicalEventPricingDisplay(pricing);
1958
+ case "tiered": return resolvePricingOptionsPriceDisplay({
1959
+ options: pricing.options.filter(isPublicEventPricingOptionDisplayable),
1960
+ currency: pricing.currency,
1961
+ purpose: "configured"
1962
+ });
1963
+ case "external": return {
1964
+ kind: "external",
1965
+ label: pricing.label
1966
+ };
1967
+ }
1968
+ }
1769
1969
  function publicEventPricingType(pricing) {
1770
1970
  switch (pricing.kind) {
1771
- case "drop_in":
1772
- case "free_registration": return "free";
1773
- case "single_paid":
1774
- case "ticket_types":
1775
- case "sliding_scale":
1776
- case "whole_series": return isFreePublicEventPriceDisplay(pricing.display) ? "free" : "paid";
1971
+ case "free": return "free";
1972
+ case "single":
1973
+ case "tiered":
1974
+ case "sliding_scale": return isFreePublicEventPriceDisplay(publicEventPricingDisplay(pricing)) ? "free" : "paid";
1777
1975
  case "external": return "external";
1778
1976
  }
1779
1977
  }
1780
1978
  function isFreePublicEventPriceDisplay(display) {
1781
1979
  switch (display.kind) {
1782
1980
  case "free": return true;
1783
- case "whole_series": return display.display.kind === "free";
1784
1981
  case "exact":
1785
1982
  case "from":
1786
1983
  case "range":
@@ -1789,22 +1986,126 @@ function isFreePublicEventPriceDisplay(display) {
1789
1986
  case "external": return false;
1790
1987
  }
1791
1988
  }
1989
+ function resolvePricingOptionSaleWindowState(option, now) {
1990
+ if (option.saleStartsAt !== null && option.saleStartsAt !== void 0 && new Date(option.saleStartsAt) > now) return "not_started";
1991
+ if (option.saleEndsAt !== null && option.saleEndsAt !== void 0 && new Date(option.saleEndsAt) < now) return "ended";
1992
+ return "open";
1993
+ }
1994
+ function resolvePricingOptionsPriceDisplay(input) {
1995
+ const now = input.purpose === "available_now" ? resolvePlanningNowDate({
1996
+ now: input.now,
1997
+ clock: input.clock
1998
+ }) : null;
1999
+ const amounts = input.options.filter((option) => option.isActive && (now === null || resolvePricingOptionSaleWindowState(option, now) === "open")).map((option) => option.priceAmount);
2000
+ return amounts.length === 0 ? {
2001
+ kind: "unavailable",
2002
+ currency: input.currency
2003
+ } : amountRangeDisplay(amounts, input.currency);
2004
+ }
2005
+ function amountRangeDisplay(amounts, currency) {
2006
+ const minAmount = Math.min(...amounts);
2007
+ const maxAmount = Math.max(...amounts);
2008
+ if (minAmount === maxAmount) return minAmount === 0 ? {
2009
+ kind: "free",
2010
+ currency
2011
+ } : {
2012
+ kind: "exact",
2013
+ amount: minAmount,
2014
+ currency
2015
+ };
2016
+ if (minAmount === 0) {
2017
+ const paidAmounts = amounts.filter((amount) => amount > 0);
2018
+ return {
2019
+ kind: "mixed",
2020
+ paidFromAmount: Math.min(...paidAmounts),
2021
+ paidToAmount: maxAmount,
2022
+ currency
2023
+ };
2024
+ }
2025
+ return {
2026
+ kind: "range",
2027
+ minAmount,
2028
+ maxAmount,
2029
+ currency
2030
+ };
2031
+ }
2032
+ /** Derives configured price presentation directly from canonical pricing. */
2033
+ function canonicalEventPricingDisplay(pricing) {
2034
+ switch (pricing.kind) {
2035
+ case "free": return {
2036
+ kind: "free",
2037
+ currency: pricing.currency
2038
+ };
2039
+ case "single": return {
2040
+ kind: "exact",
2041
+ amount: pricing.amount,
2042
+ currency: pricing.currency
2043
+ };
2044
+ case "sliding_scale": return pricing.minimum === pricing.maximum ? {
2045
+ kind: "exact",
2046
+ amount: pricing.maximum,
2047
+ currency: pricing.currency
2048
+ } : {
2049
+ kind: "range",
2050
+ minAmount: pricing.minimum,
2051
+ maxAmount: pricing.maximum,
2052
+ currency: pricing.currency
2053
+ };
2054
+ case "tiered": return resolvePricingOptionsPriceDisplay({
2055
+ options: pricing.options,
2056
+ currency: pricing.currency,
2057
+ purpose: "configured"
2058
+ });
2059
+ default: return assertNever$2(pricing);
2060
+ }
2061
+ }
1792
2062
  //#endregion
1793
2063
  //#region ../core/src/event-page-surface-subject.ts
1794
- function createEventSeriesPageSurfaceSubject(eventSeriesId, bookingScope) {
2064
+ function createEventSeriesPageSurfaceSubject(eventSeriesId, bookingScope, eventDestinationMode) {
2065
+ const mode = eventDestinationMode ? { eventDestinationMode } : {};
1795
2066
  return bookingScope === "whole_series" ? {
1796
2067
  kind: "eventSeries",
1797
2068
  eventSeriesId,
1798
2069
  bookingScope,
1799
- isWholeSeriesBooking: true
2070
+ isWholeSeriesBooking: true,
2071
+ ...mode
1800
2072
  } : {
1801
2073
  kind: "eventSeries",
1802
2074
  eventSeriesId,
1803
- bookingScope
2075
+ bookingScope,
2076
+ ...mode
1804
2077
  };
1805
2078
  }
2079
+ function createEventOfferingPageSurfaceSubject(eventOfferingId, input) {
2080
+ const mode = input.eventDestinationMode ? { eventDestinationMode: input.eventDestinationMode } : {};
2081
+ const identity = {
2082
+ kind: "eventOffering",
2083
+ eventOfferingId,
2084
+ catalogueEventSeriesIds: input.catalogueEventSeriesIds
2085
+ };
2086
+ return input.bookingScope === "whole_series" ? {
2087
+ ...identity,
2088
+ bookingScope: input.bookingScope,
2089
+ isWholeSeriesBooking: true,
2090
+ ...mode
2091
+ } : {
2092
+ ...identity,
2093
+ bookingScope: input.bookingScope,
2094
+ ...mode
2095
+ };
2096
+ }
2097
+ /**
2098
+ * Read the destination mode off a wire value.
2099
+ *
2100
+ * Absent or unrecognised reads as absent, which leaves the routed Event record
2101
+ * as the only authority — the behaviour every caller had before the field
2102
+ * existed.
2103
+ */
2104
+ function parseEventPageSurfaceDestinationMode(value) {
2105
+ return value === "cms-managed" || value === "system-managed" ? value : void 0;
2106
+ }
1806
2107
  function parseEventPageSurfaceSubject(value) {
1807
- if (!isRecord$8(value)) return err({ kind: "notObject" });
2108
+ if (!isRecord$7(value)) return err({ kind: "notObject" });
1808
2109
  switch (value.kind) {
1809
2110
  case "eventSeries": {
1810
2111
  const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
@@ -1816,7 +2117,7 @@ function parseEventPageSurfaceSubject(value) {
1816
2117
  kind: "invalidEventSeriesBookingScope",
1817
2118
  bookingScope: value.bookingScope
1818
2119
  });
1819
- return ok(createEventSeriesPageSurfaceSubject(eventSeriesId.value, value.bookingScope));
2120
+ return ok(createEventSeriesPageSurfaceSubject(eventSeriesId.value, value.bookingScope, parseEventPageSurfaceDestinationMode(value.eventDestinationMode)));
1820
2121
  }
1821
2122
  case "eventOffering": {
1822
2123
  const eventOfferingId = parseEventOfferingId(value.eventOfferingId);
@@ -1824,24 +2125,22 @@ function parseEventPageSurfaceSubject(value) {
1824
2125
  kind: "invalidEventOfferingId",
1825
2126
  error: eventOfferingId.error
1826
2127
  });
1827
- if (!Array.isArray(value.availableEventSeriesIds)) return err({
1828
- kind: "unsupportedSubject",
1829
- subjectKind: value.kind
2128
+ if (!Array.isArray(value.catalogueEventSeriesIds)) return err({
2129
+ kind: "invalidEventOfferingCatalogue",
2130
+ catalogue: value.catalogueEventSeriesIds
1830
2131
  });
1831
- const parsedSeriesIds = [];
1832
- for (const valueId of value.availableEventSeriesIds) {
1833
- const eventSeriesId = parseEventSeriesId(valueId);
1834
- if (!eventSeriesId.ok) return err({
1835
- kind: "invalidEventSeriesId",
1836
- error: eventSeriesId.error
1837
- });
1838
- parsedSeriesIds.push(eventSeriesId.value);
1839
- }
1840
- return ok({
1841
- kind: "eventOffering",
1842
- eventOfferingId: eventOfferingId.value,
1843
- availableEventSeriesIds: parsedSeriesIds
2132
+ if (value.bookingScope !== "single_occurrence" && value.bookingScope !== "whole_series") return err({
2133
+ kind: "invalidEventOfferingBookingScope",
2134
+ bookingScope: value.bookingScope
1844
2135
  });
2136
+ const parsedCatalogueIds = parseEventSeriesIdList(value.catalogueEventSeriesIds);
2137
+ if (!parsedCatalogueIds.ok) return parsedCatalogueIds;
2138
+ const eventDestinationMode = parseEventPageSurfaceDestinationMode(value.eventDestinationMode);
2139
+ return ok(createEventOfferingPageSurfaceSubject(eventOfferingId.value, {
2140
+ catalogueEventSeriesIds: parsedCatalogueIds.value,
2141
+ bookingScope: value.bookingScope,
2142
+ ...eventDestinationMode ? { eventDestinationMode } : {}
2143
+ }));
1845
2144
  }
1846
2145
  default: return err({
1847
2146
  kind: "unsupportedSubject",
@@ -1849,7 +2148,19 @@ function parseEventPageSurfaceSubject(value) {
1849
2148
  });
1850
2149
  }
1851
2150
  }
1852
- function isRecord$8(value) {
2151
+ function parseEventSeriesIdList(values) {
2152
+ const parsed = [];
2153
+ for (const value of values) {
2154
+ const eventSeriesId = parseEventSeriesId(value);
2155
+ if (!eventSeriesId.ok) return err({
2156
+ kind: "invalidEventSeriesId",
2157
+ error: eventSeriesId.error
2158
+ });
2159
+ parsed.push(eventSeriesId.value);
2160
+ }
2161
+ return ok(parsed);
2162
+ }
2163
+ function isRecord$7(value) {
1853
2164
  return typeof value === "object" && value !== null && !Array.isArray(value);
1854
2165
  }
1855
2166
  //#endregion
@@ -2071,27 +2382,21 @@ function parseManagementKey(raw) {
2071
2382
  if (typeof raw !== "string" || !raw.startsWith("bld_mgmt_sk_") || raw.length === 12) return err({ kind: "invalid-management-key" });
2072
2383
  return ok(createSecretInternal("management-key", raw));
2073
2384
  }
2074
- //#endregion
2075
- //#region ../core/src/planner.ts
2076
- /** Default clock for production callers that do not inject time explicitly. */
2077
- const systemPlanningClock = { now: () => Date.now() };
2078
- /** Resolve current time as a Date from an explicit Date, injected clock, or system clock. */
2079
- function resolvePlanningNowDate(input = {}) {
2080
- if (input.now !== void 0) return input.now;
2081
- return new Date((input.clock ?? systemPlanningClock).now());
2385
+ function sessionStartMs(session) {
2386
+ return Date.parse(session.startsAt);
2082
2387
  }
2083
2388
  /**
2084
- * Resolve a Date-compatible planner input.
2389
+ * The run's sessions that still count, in schedule order.
2085
2390
  *
2086
- * Precedence: bare Date, `{ now }`, `{ clock }`, then `systemPlanningClock`.
2087
- * Explicit Date inputs are returned by reference, not cloned.
2391
+ * Sessions whose start cannot be read are dropped rather than sorted to an
2392
+ * arbitrary end: an unparseable date is not a date a visitor can attend.
2088
2393
  */
2089
- function resolvePlanningDateInput(input = {}) {
2090
- if (input instanceof Date) return input;
2091
- return resolvePlanningNowDate(input);
2394
+ function orderedLiveRunSessions(sessions) {
2395
+ return sessions.filter((session) => session.status !== "cancelled" && Number.isFinite(sessionStartMs(session))).sort((left, right) => sessionStartMs(left) - sessionStartMs(right));
2092
2396
  }
2093
2397
  //#endregion
2094
2398
  //#region ../core/src/event-series-behaviour.ts
2399
+ const WHOLE_SERIES_EVENT_PRESET_VALUES = ["course", "term"];
2095
2400
  const SURFACE_EVENT_PRESET_VALUES = [
2096
2401
  "class",
2097
2402
  "course",
@@ -8456,6 +8761,11 @@ const gradientConfigSchema = z.object({
8456
8761
  position: z.string().optional(),
8457
8762
  stops: z.array(gradientStopSchema).min(2)
8458
8763
  });
8764
+ const gradientsSchema = z.object({
8765
+ button: z.string().min(1).nullable().optional(),
8766
+ hero: z.string().min(1).nullable().optional(),
8767
+ background: z.string().min(1).nullable().optional()
8768
+ });
8459
8769
  //#endregion
8460
8770
  //#region ../theme-core/src/interactive/baseSchema.ts
8461
8771
  /**
@@ -9209,11 +9519,30 @@ const headerContainerSchema = z.object({
9209
9519
  tint: z.string().nullable().optional(),
9210
9520
  opacity: z.number().min(0).max(1).default(.12)
9211
9521
  }).optional();
9212
- const headerInteractionPaletteSchema = z.enum([
9522
+ //#endregion
9523
+ //#region ../theme-core/src/header/interactionPalette.ts
9524
+ /**
9525
+ * The palettes that fill the nav link with a colour on hover and focus. Each
9526
+ * one names a background/foreground token pair.
9527
+ */
9528
+ const headerInteractionPillPaletteValues = [
9213
9529
  "primary",
9214
9530
  "secondary",
9215
9531
  "accent"
9216
- ]);
9532
+ ];
9533
+ /**
9534
+ * "No pill": the nav link keeps whatever hover treatment its recipe compiled,
9535
+ * and the palette step writes nothing at all (#1318 Phase 4c decision 2).
9536
+ *
9537
+ * It exists because "a colour change on hover, no filled background" was not
9538
+ * expressible in the vocabulary, and it is what
9539
+ * `anna-raven-therapy-and-yoga` and `kirtan-lucy` have rendered since before
9540
+ * the palette existed. Without it those two rows can only be classified as a
9541
+ * conscious visual change.
9542
+ */
9543
+ const headerInteractionQuietPalette = "quiet";
9544
+ const headerInteractionPaletteValues = [...headerInteractionPillPaletteValues, headerInteractionQuietPalette];
9545
+ const headerInteractionPaletteSchema = z.enum(headerInteractionPaletteValues);
9217
9546
  //#endregion
9218
9547
  //#region ../theme-core/src/boxBackgroundSchema.ts
9219
9548
  const boxBackgroundOverlaySchema = z.preprocess(normalizeAuthoringOpacity, z.discriminatedUnion("type", [
@@ -9271,7 +9600,7 @@ const boxBackgroundSchema = z.discriminatedUnion("type", [
9271
9600
  })
9272
9601
  ]);
9273
9602
  function normalizeAuthoringOpacity(value) {
9274
- if (!isRecord$7(value)) return value;
9603
+ if (!isRecord$6(value)) return value;
9275
9604
  return {
9276
9605
  ...value,
9277
9606
  opacity: normalizeOpacity(value.opacity)
@@ -9280,7 +9609,7 @@ function normalizeAuthoringOpacity(value) {
9280
9609
  function normalizeOpacity(value) {
9281
9610
  return typeof value === "number" && value > 1 && value <= 100 ? value / 100 : value;
9282
9611
  }
9283
- function isRecord$7(value) {
9612
+ function isRecord$6(value) {
9284
9613
  return typeof value === "object" && value !== null && !Array.isArray(value);
9285
9614
  }
9286
9615
  //#endregion
@@ -9595,11 +9924,12 @@ const inputStyle = z.object({
9595
9924
  ]),
9596
9925
  label: z.enum(["inside", "above"])
9597
9926
  });
9598
- const headerPositioning = z.enum([
9927
+ const headerPositioningValues = [
9599
9928
  "static",
9600
9929
  "sticky",
9601
9930
  "fixed"
9602
- ]);
9931
+ ];
9932
+ const headerPositioning = z.enum(headerPositioningValues);
9603
9933
  const headerNavStyle = z.enum([
9604
9934
  "minimal",
9605
9935
  "underline",
@@ -9734,7 +10064,7 @@ const headerSchema = z.object({
9734
10064
  variant: headerVariantWithLegacyAliasSchema,
9735
10065
  positioning: headerPositioning,
9736
10066
  shrinkOnScroll: z.boolean(),
9737
- maxWidth: headerMaxWidth,
10067
+ maxWidth: headerMaxWidth.default("container"),
9738
10068
  scrollTreatment: headerScrollTreatmentSchema,
9739
10069
  background: headerBackgroundSchema.default({
9740
10070
  type: "color",
@@ -9933,11 +10263,6 @@ const bodyTextSchema = z.object({ intro: z.object({
9933
10263
  paragraphSize: bodyTextIntroTypographySizeSchema.optional(),
9934
10264
  headingSize: bodyTextIntroTypographySizeSchema.optional()
9935
10265
  }).optional() }).optional();
9936
- const gradientsSchema = z.object({
9937
- button: z.string().min(1).nullable().optional(),
9938
- hero: z.string().min(1).nullable().optional(),
9939
- background: z.string().min(1).nullable().optional()
9940
- });
9941
10266
  /**
9942
10267
  * Testimonial quote-mark treatment, owned by the site style (analogous to the
9943
10268
  * accordion icon). `style` is the coarse selector; the optional fields fine-tune
@@ -10818,6 +11143,12 @@ function cardRoleFromLegacyVocabulary(value) {
10818
11143
  */
10819
11144
  const cardRoleWithLegacyAliasSchema = z.preprocess((value) => cardRoleFromLegacyVocabulary(value) ?? value, cardRoleSchema);
10820
11145
  //#endregion
11146
+ //#region ../theme-core/src/site-styles/compilationPlan.ts
11147
+ const defaultHeaderBrandPreferences = {
11148
+ brandDisplay: "auto",
11149
+ logoSize: "auto"
11150
+ };
11151
+ //#endregion
10821
11152
  //#region ../theme-core/src/site-styles/sectionTransitions.ts
10822
11153
  function boundaryRuntimeMetrics(family, size, heightExpression) {
10823
11154
  return {
@@ -11863,6 +12194,12 @@ const overlayLogoAccommodations = [
11863
12194
  inlineMarkWithTitleLogoAccommodation,
11864
12195
  unbackedOverlayLogoAccommodation
11865
12196
  ];
12197
+ const allCuratedLogoAccommodations = [
12198
+ ...inlineClassicLogoAccommodations,
12199
+ ...centeredLogoAccommodations,
12200
+ ...overlayLogoAccommodations
12201
+ ];
12202
+ new Set(allCuratedLogoAccommodations.filter((option) => option.providesBacking === true).map((option) => option.pattern));
11866
12203
  const headerLayoutCatalog = defineExactCatalog()([
11867
12204
  {
11868
12205
  id: asHeaderLayoutId("classic"),
@@ -12012,6 +12349,10 @@ defineLookOptionGroup({
12012
12349
  {
12013
12350
  id: "secondary",
12014
12351
  label: "Secondary"
12352
+ },
12353
+ {
12354
+ id: headerInteractionQuietPalette,
12355
+ label: "Text only"
12015
12356
  }
12016
12357
  ]
12017
12358
  });
@@ -14433,6 +14774,67 @@ const blockDesignFallback = {
14433
14774
  };
14434
14775
  blockDesignFallback.sectionSurface, blockDesignFallback.contentFrame, blockDesignFallback.transitionAfter, blockDesignFallback.sectionHeight, blockDesignFallback.heroLegibility, blockDesignFallback.imageSurfaceTreatment, blockDesignFallback.imageSurfaceMotion, blockDesignFallback.tileTreatment, blockDesignFallback.eventListTreatment, blockDesignFallback.eyebrowTreatment, blockDesignFallback.accordionIconTreatment, blockDesignFallback.composition;
14435
14776
  //#endregion
14777
+ //#region ../theme-core/src/site-styles/siteChromeBackgrounds.ts
14778
+ const siteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceColorTokenNames);
14779
+ const quickSiteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceQuickColorTokenNames);
14780
+ siteChromeBackgroundColorTokens.filter((token) => !quickSiteChromeBackgroundColorTokens.includes(token));
14781
+ function parseSiteChromeBackgroundColorToken(value) {
14782
+ const token = parseBackgroundAppearanceColorToken(value);
14783
+ return token ? token : null;
14784
+ }
14785
+ function toSiteChromeBackgroundColorTokens(tokenNames) {
14786
+ return tokenNames.flatMap((name) => {
14787
+ const token = parseSiteChromeBackgroundColorToken(name);
14788
+ return token ? [token] : [];
14789
+ });
14790
+ }
14791
+ //#endregion
14792
+ //#region ../theme-core/src/site-styles/siteChromeNavPreferences.ts
14793
+ const headerNavTypographyPreferenceValues = [
14794
+ "inherit",
14795
+ "body",
14796
+ "heading"
14797
+ ];
14798
+ const headerNavFontSizePreferenceValues = [
14799
+ "inherit",
14800
+ "sm",
14801
+ "base",
14802
+ "lg",
14803
+ "xl"
14804
+ ];
14805
+ const defaultHeaderNavPreferences = {
14806
+ typography: "inherit",
14807
+ fontSize: "inherit",
14808
+ interactionPalette: "recommended"
14809
+ };
14810
+ //#endregion
14811
+ //#region ../theme-core/src/site-styles/headerBrandPresentation.ts
14812
+ /**
14813
+ * Whether the header wears a brand presentation at all (#1318 Phase 4c).
14814
+ *
14815
+ * `applyHeaderBrandPresentation` is unconditional today: given a logo context
14816
+ * it always writes a `logo` object carrying a resolved display, size and
14817
+ * accommodation. That makes "this header has no brand presentation block" —
14818
+ * which is what several live sites persist, including one whose site *does*
14819
+ * have a logo asset — a state the preference record could not express, so a
14820
+ * recompile would silently give the site a logo treatment it has never
14821
+ * rendered.
14822
+ *
14823
+ * This is the third field in this phase with that shape, after the interaction
14824
+ * palette and the nav text size: the persisted bytes carry intent the reader
14825
+ * cannot say, so the recompile "corrects" it. The fix is the same one — widen
14826
+ * the closed vocabulary with a named member and derive it by baseline
14827
+ * comparison — and it is a *widening*, not a restyle: `'recommended'` is the
14828
+ * default and reproduces today's behaviour exactly, so no row whose bytes carry
14829
+ * a presentation compiles differently for `'plain'` existing.
14830
+ *
14831
+ * `'plain'` is deliberately not "preserve whatever bytes are there". It is a
14832
+ * constructive instruction — *write no presentation block* — so Phase 4e's
14833
+ * compiler, which builds the header from nothing, can produce it.
14834
+ */
14835
+ const headerBrandPresentationValues = ["recommended", "plain"];
14836
+ defaultHeaderBrandPreferences.brandDisplay, defaultHeaderBrandPreferences.logoSize, defaultHeaderNavPreferences.typography, defaultHeaderNavPreferences.fontSize, defaultHeaderNavPreferences.interactionPalette;
14837
+ //#endregion
14436
14838
  //#region ../theme-core/src/site-styles/generatedSchemas.ts
14437
14839
  function uniqueNonEmpty(values) {
14438
14840
  const uniqueValues = [...new Set(values)];
@@ -14501,6 +14903,56 @@ z.object({
14501
14903
  blocks: z.array(generatedPageDesignBlockIntentSchema)
14502
14904
  }).strict();
14503
14905
  //#endregion
14906
+ //#region ../theme-core/src/site-styles/headerPreferencesPersistence.ts
14907
+ const backgroundColorTokenSchema = z.unknown().transform((value, ctx) => {
14908
+ const token = parseSiteChromeBackgroundColorToken(value);
14909
+ if (token === null) {
14910
+ ctx.addIssue({
14911
+ code: "custom",
14912
+ message: "Unknown site chrome background colour token"
14913
+ });
14914
+ return z.NEVER;
14915
+ }
14916
+ return token;
14917
+ });
14918
+ const backgroundOverrideSchema = z.discriminatedUnion("kind", [z.object({ kind: z.literal("default") }).strict(), z.object({
14919
+ kind: z.literal("color"),
14920
+ token: backgroundColorTokenSchema
14921
+ }).strict()]);
14922
+ const logoTextIntentSchema = z.object({
14923
+ mobileMaxWidth: z.enum([
14924
+ "xs",
14925
+ "sm",
14926
+ "md"
14927
+ ]).optional(),
14928
+ mobileWrapLines: z.union([z.literal(1), z.literal(2)]).optional(),
14929
+ hideOnShrink: z.boolean().optional()
14930
+ }).strict();
14931
+ const structureSchema = z.object({
14932
+ positioning: z.union([z.literal("inherit"), z.enum(headerPositioningValues)]),
14933
+ shrinkOnScroll: z.union([z.literal("inherit"), z.boolean()]),
14934
+ logoText: z.union([
14935
+ z.literal("inherit"),
14936
+ z.literal("none"),
14937
+ logoTextIntentSchema
14938
+ ])
14939
+ }).strict();
14940
+ const headerPreferencesShape = {
14941
+ brandPresentation: z.enum(headerBrandPresentationValues),
14942
+ brandDisplay: z.enum(brandDisplayModeValues),
14943
+ logoSize: z.enum(logoSizePolicyValues),
14944
+ navFontRole: z.enum(headerNavTypographyPreferenceValues),
14945
+ navTextSize: z.enum(headerNavFontSizePreferenceValues),
14946
+ interactionPalette: z.union([z.literal("recommended"), z.enum(headerInteractionPaletteValues)]),
14947
+ background: backgroundOverrideSchema,
14948
+ structure: structureSchema
14949
+ };
14950
+ z.object(headerPreferencesShape).strict();
14951
+ z.object(headerPreferencesShape).omit({
14952
+ brandPresentation: true,
14953
+ structure: true
14954
+ }).strict();
14955
+ //#endregion
14504
14956
  //#region ../theme-core/src/site-styles/pageDesignAuthority.ts
14505
14957
  const nonEmptyStringSchema = z.string().min(1);
14506
14958
  const blockContentVersionIdSchema = nonEmptyStringSchema.transform(asBlockContentVersionId);
@@ -14602,21 +15054,6 @@ function collectBlockSequenceIssues(snapshots) {
14602
15054
  return issues;
14603
15055
  }
14604
15056
  //#endregion
14605
- //#region ../theme-core/src/site-styles/siteChromeBackgrounds.ts
14606
- const siteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceColorTokenNames);
14607
- const quickSiteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceQuickColorTokenNames);
14608
- siteChromeBackgroundColorTokens.filter((token) => !quickSiteChromeBackgroundColorTokens.includes(token));
14609
- function parseSiteChromeBackgroundColorToken(value) {
14610
- const token = parseBackgroundAppearanceColorToken(value);
14611
- return token ? token : null;
14612
- }
14613
- function toSiteChromeBackgroundColorTokens(tokenNames) {
14614
- return tokenNames.flatMap((name) => {
14615
- const token = parseSiteChromeBackgroundColorToken(name);
14616
- return token ? [token] : [];
14617
- });
14618
- }
14619
- //#endregion
14620
15057
  //#region ../theme-core/src/site-styles/tokenRecipes.ts
14621
15058
  const themeTokenRecipeOptions = {
14622
15059
  palette: [
@@ -23911,7 +24348,7 @@ const mediaTransforms = [{
23911
24348
  /**
23912
24349
  * Strict record guard: excludes null, primitives, and arrays.
23913
24350
  */
23914
- function isRecord$6(value) {
24351
+ function isRecord$5(value) {
23915
24352
  return typeof value === "object" && value !== null && !Array.isArray(value);
23916
24353
  }
23917
24354
  //#endregion
@@ -23921,16 +24358,16 @@ const interpolateRichTextTokensOptionsSchema = z.object({ tokens: z.array(suppor
23921
24358
  const richTextTokenPattern = /\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/g;
23922
24359
  function getSiteName(context) {
23923
24360
  const viewModel = context.viewModel;
23924
- if (!isRecord$6(viewModel)) return null;
24361
+ if (!isRecord$5(viewModel)) return null;
23925
24362
  const site = viewModel.site;
23926
- if (isRecord$6(site) && typeof site.title === "string") {
24363
+ if (isRecord$5(site) && typeof site.title === "string") {
23927
24364
  const title = site.title.trim();
23928
24365
  return title.length > 0 ? title : null;
23929
24366
  }
23930
24367
  const root = viewModel.$root;
23931
- if (isRecord$6(root)) {
24368
+ if (isRecord$5(root)) {
23932
24369
  const rootSite = root.site;
23933
- if (isRecord$6(rootSite) && typeof rootSite.title === "string") {
24370
+ if (isRecord$5(rootSite) && typeof rootSite.title === "string") {
23934
24371
  const title = rootSite.title.trim();
23935
24372
  if (title.length > 0) return title;
23936
24373
  }
@@ -23952,7 +24389,7 @@ function replaceTokenText(input, allowedTokens, tokenValues) {
23952
24389
  });
23953
24390
  }
23954
24391
  function visitRichTextNode(node, allowedTokens, tokenValues) {
23955
- if (!isRecord$6(node)) return node;
24392
+ if (!isRecord$5(node)) return node;
23956
24393
  let changed = false;
23957
24394
  const nextNode = { ...node };
23958
24395
  if (nextNode.type === "text" && typeof nextNode.text === "string") {
@@ -23973,7 +24410,7 @@ function visitRichTextNode(node, allowedTokens, tokenValues) {
23973
24410
  return changed ? nextNode : node;
23974
24411
  }
23975
24412
  function interpolateRichTextTokens(value, options, context) {
23976
- if (!isRecord$6(value)) return value;
24413
+ if (!isRecord$5(value)) return value;
23977
24414
  return visitRichTextNode(value, new Set(options.tokens), {
23978
24415
  year: String((/* @__PURE__ */ new Date()).getFullYear()),
23979
24416
  site_name: getSiteName(context)
@@ -26396,251 +26833,6 @@ const bookingRequirementConsentFieldSchema = z.object({
26396
26833
  });
26397
26834
  z.union([blockBookingConsentSchema, bookingRequirementConsentFieldSchema]);
26398
26835
  //#endregion
26399
- //#region ../blocks/src/system/blocks/events/whole-series/pricing.ts
26400
- function isSaleWindowOpen(option, now) {
26401
- if (!option.isActive) return false;
26402
- if (option.saleStartsAt && new Date(option.saleStartsAt) > now) return false;
26403
- if (option.saleEndsAt && new Date(option.saleEndsAt) < now) return false;
26404
- return true;
26405
- }
26406
- function toExactOrFreeDisplay(amount, currency) {
26407
- if (amount <= 0) return {
26408
- kind: "free",
26409
- currency
26410
- };
26411
- return {
26412
- kind: "exact",
26413
- amount,
26414
- currency
26415
- };
26416
- }
26417
- function getSelectableWholeSeriesPricingOptionsForNow(offering, now) {
26418
- if (offering.pricing.pricingStrategy !== "tiered") return [];
26419
- return [...offering.pricing.options].filter((option) => isSaleWindowOpen(option, now)).sort((left, right) => {
26420
- if (left.sortOrder !== right.sortOrder) return left.sortOrder - right.sortOrder;
26421
- if (left.priceAmount !== right.priceAmount) return left.priceAmount - right.priceAmount;
26422
- return left.name.localeCompare(right.name);
26423
- });
26424
- }
26425
- function resolveWholeSeriesPricingState(offering, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
26426
- const selection = normalizePricingSelectionInput(selectedSlidingAmountOrNowInput, nowInput);
26427
- const currency = offering.pricing.currency;
26428
- switch (offering.pricing.pricingStrategy) {
26429
- case "free": return resolveFreePricing(currency);
26430
- case "single": return resolveSinglePricing(offering.pricing.singlePriceAmount ?? 0, currency);
26431
- case "tiered": return resolveTieredPricing(offering, selectedPricingOptionId, selection.nowInput);
26432
- case "sliding_scale": return resolveSlidingScalePricing(offering, selection.selectedSlidingAmount);
26433
- }
26434
- }
26435
- function normalizePricingSelectionInput(selectedSlidingAmountOrNowInput, nowInput) {
26436
- return typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? {
26437
- selectedSlidingAmount: null,
26438
- nowInput: selectedSlidingAmountOrNowInput
26439
- } : {
26440
- selectedSlidingAmount: typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null,
26441
- nowInput
26442
- };
26443
- }
26444
- function resolveFreePricing(currency) {
26445
- return {
26446
- currency,
26447
- display: {
26448
- kind: "free",
26449
- currency
26450
- },
26451
- selectableOptions: [],
26452
- requiresSelection: false,
26453
- selectedOption: null,
26454
- slidingScale: null,
26455
- selectedSlidingAmount: null,
26456
- selectedPriceAmount: 0,
26457
- selectedRequiresPayment: false,
26458
- hasPaidSelection: false,
26459
- hasFreeSelection: true
26460
- };
26461
- }
26462
- function resolveSinglePricing(amount, currency) {
26463
- return {
26464
- currency,
26465
- display: toExactOrFreeDisplay(amount, currency),
26466
- selectableOptions: [],
26467
- requiresSelection: false,
26468
- selectedOption: null,
26469
- slidingScale: null,
26470
- selectedSlidingAmount: null,
26471
- selectedPriceAmount: amount,
26472
- selectedRequiresPayment: amount > 0,
26473
- hasPaidSelection: amount > 0,
26474
- hasFreeSelection: amount <= 0
26475
- };
26476
- }
26477
- function resolveTieredPricing(offering, selectedPricingOptionId, nowInput) {
26478
- const currency = offering.pricing.currency;
26479
- const selectableOptions = getSelectableWholeSeriesPricingOptionsForNow(offering, resolvePlanningDateInput(nowInput));
26480
- const selectedOption = resolveSelectedTier(selectableOptions, selectedPricingOptionId);
26481
- return {
26482
- currency,
26483
- display: resolveTieredDisplay(selectableOptions.reduce((lowest, option) => lowest === null || option.priceAmount < lowest ? option.priceAmount : lowest, null), selectableOptions.length, currency),
26484
- selectableOptions,
26485
- requiresSelection: selectableOptions.length > 1,
26486
- selectedOption,
26487
- slidingScale: null,
26488
- selectedSlidingAmount: null,
26489
- selectedPriceAmount: selectedOption?.priceAmount ?? null,
26490
- selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
26491
- hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
26492
- hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
26493
- };
26494
- }
26495
- function resolveSelectedTier(options, selectedId) {
26496
- return (selectedId ? options.find((option) => option.id === selectedId) : null) ?? (options.length === 1 ? options[0] ?? null : null);
26497
- }
26498
- function resolveTieredDisplay(lowestAmount, optionCount, currency) {
26499
- if (lowestAmount === null) return {
26500
- kind: "unavailable",
26501
- currency
26502
- };
26503
- return optionCount > 1 && lowestAmount > 0 ? {
26504
- kind: "from",
26505
- amount: lowestAmount,
26506
- currency
26507
- } : toExactOrFreeDisplay(lowestAmount, currency);
26508
- }
26509
- function resolveSlidingScalePricing(offering, selectedSlidingAmount) {
26510
- const currency = offering.pricing.currency;
26511
- const minAmount = offering.pricing.slidingMinAmount ?? null;
26512
- const maxAmount = offering.pricing.slidingMaxAmount ?? null;
26513
- if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) return unavailableSlidingScale(currency);
26514
- const selectedAmount = Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
26515
- return {
26516
- currency,
26517
- display: {
26518
- kind: "range",
26519
- minAmount,
26520
- maxAmount,
26521
- currency
26522
- },
26523
- selectableOptions: [],
26524
- requiresSelection: selectedAmount === null,
26525
- selectedOption: null,
26526
- slidingScale: {
26527
- minAmount,
26528
- maxAmount,
26529
- suggestedAmount: offering.pricing.slidingSuggestedAmount ?? null
26530
- },
26531
- selectedSlidingAmount: selectedAmount,
26532
- selectedPriceAmount: selectedAmount,
26533
- selectedRequiresPayment: (selectedAmount ?? 0) > 0,
26534
- hasPaidSelection: maxAmount > 0,
26535
- hasFreeSelection: minAmount === 0
26536
- };
26537
- }
26538
- function unavailableSlidingScale(currency) {
26539
- return {
26540
- currency,
26541
- display: {
26542
- kind: "unavailable",
26543
- currency
26544
- },
26545
- selectableOptions: [],
26546
- requiresSelection: true,
26547
- selectedOption: null,
26548
- slidingScale: null,
26549
- selectedSlidingAmount: null,
26550
- selectedPriceAmount: null,
26551
- selectedRequiresPayment: false,
26552
- hasPaidSelection: false,
26553
- hasFreeSelection: false
26554
- };
26555
- }
26556
- //#endregion
26557
- //#region ../blocks/src/system/blocks/events/whole-series/schemas.ts
26558
- const wholeSeriesVenueSchema = z.object({
26559
- id: z.string(),
26560
- name: z.string(),
26561
- address: z.string().nullable()
26562
- });
26563
- const wholeSeriesSessionSchema = z.object({
26564
- id: z.string(),
26565
- startsAt: z.string(),
26566
- endsAt: z.string(),
26567
- timeZone: z.string(),
26568
- capacityOverride: z.number().nullable().optional(),
26569
- overrides: z.record(z.string(), z.unknown()).nullable().optional()
26570
- });
26571
- const wholeSeriesTeamMemberSummarySchema = z.object({
26572
- id: z.string(),
26573
- name: z.string(),
26574
- roleLabel: z.string().nullable(),
26575
- summary: z.string().nullable(),
26576
- profilePath: z.string().nullable()
26577
- });
26578
- const wholeSeriesPricingOptionSchema = z.object({
26579
- id: z.string(),
26580
- name: z.string(),
26581
- description: z.string().nullable(),
26582
- priceAmount: z.number(),
26583
- isActive: z.boolean(),
26584
- sortOrder: z.number(),
26585
- capacityLimit: z.number().nullable(),
26586
- saleStartsAt: z.string().nullable(),
26587
- saleEndsAt: z.string().nullable(),
26588
- attendanceScope: z.enum([
26589
- "in_person",
26590
- "online",
26591
- "both"
26592
- ]).nullable().optional()
26593
- });
26594
- const wholeSeriesPricingSchema = z.object({
26595
- bookingRequirement: z.enum(["none", "required"]),
26596
- pricingStrategy: z.enum([
26597
- "free",
26598
- "single",
26599
- "tiered",
26600
- "sliding_scale"
26601
- ]),
26602
- currency: z.string(),
26603
- singlePriceAmount: z.number().nullable(),
26604
- slidingMinAmount: z.number().nullable().optional(),
26605
- slidingMaxAmount: z.number().nullable().optional(),
26606
- slidingSuggestedAmount: z.number().nullable().optional(),
26607
- paymentTerms: blockBookingPaymentTermsSchema,
26608
- options: z.array(wholeSeriesPricingOptionSchema)
26609
- });
26610
- const publicWholeSeriesOfferingSchema = z.object({
26611
- eventSeriesId: z.string(),
26612
- eventOfferingId: z.string(),
26613
- title: z.string(),
26614
- slug: z.string(),
26615
- description: z.unknown().nullable(),
26616
- deliveryMode: z.enum([
26617
- "in_person",
26618
- "online",
26619
- "hybrid"
26620
- ]),
26621
- waitlistEnabled: z.boolean(),
26622
- requireGuestDetails: z.boolean(),
26623
- teamMembers: z.array(wholeSeriesTeamMemberSummarySchema).optional(),
26624
- enrollmentOpen: z.boolean(),
26625
- pricing: wholeSeriesPricingSchema,
26626
- currency: z.string(),
26627
- paymentTerms: blockBookingPaymentTermsSchema,
26628
- consent: blockBookingConsentSchema.nullable(),
26629
- enrollmentCapacity: z.number().nullable(),
26630
- acceptsMemberships: z.boolean(),
26631
- status: z.enum([
26632
- "active",
26633
- "draft",
26634
- "cancelled"
26635
- ]),
26636
- sessionsCount: z.number(),
26637
- enrolledCount: z.number(),
26638
- availableSpots: z.number().nullable(),
26639
- sessions: z.array(wholeSeriesSessionSchema),
26640
- venue: wholeSeriesVenueSchema.nullable()
26641
- });
26642
- const publicWholeSeriesOfferingsArraySchema = z.array(publicWholeSeriesOfferingSchema);
26643
- //#endregion
26644
26836
  //#region ../blocks/src/system/blocks/events/shared/schemas.ts
26645
26837
  const eventPresetSchema = z.enum([
26646
26838
  "event",
@@ -26695,77 +26887,14 @@ const eventCategorySchema = z.object({
26695
26887
  name: z.string(),
26696
26888
  color: z.string().nullable()
26697
26889
  });
26698
- z.enum([
26699
- "free",
26700
- "paid",
26701
- "external"
26702
- ]);
26703
26890
  /**
26704
26891
  * Access restriction type for public events
26705
26892
  */
26706
26893
  const accessRestrictionSchema = z.enum(["none", "category"]);
26707
- z.enum(["single", "ticket_types"]);
26708
- const freePriceDisplaySchema = z.object({
26709
- kind: z.literal("free"),
26710
- currency: z.string()
26711
- });
26712
- const exactPriceDisplaySchema = z.object({
26713
- kind: z.literal("exact"),
26714
- amount: z.number(),
26715
- currency: z.string()
26716
- });
26717
- const fromPriceDisplaySchema = z.object({
26718
- kind: z.literal("from"),
26719
- amount: z.number(),
26720
- currency: z.string()
26721
- });
26722
- const unavailablePriceDisplaySchema = z.object({
26723
- kind: z.literal("unavailable"),
26724
- currency: z.string()
26725
- });
26726
- const rangePriceDisplaySchema = z.object({
26727
- kind: z.literal("range"),
26728
- minAmount: z.number(),
26729
- maxAmount: z.number(),
26730
- currency: z.string()
26731
- });
26732
- const mixedPriceDisplaySchema = z.object({
26733
- kind: z.literal("mixed"),
26734
- paidFromAmount: z.number(),
26735
- paidToAmount: z.number(),
26736
- currency: z.string()
26737
- });
26738
- const publicWholeSeriesPriceDisplaySchema = z.discriminatedUnion("kind", [
26739
- freePriceDisplaySchema,
26740
- exactPriceDisplaySchema,
26741
- fromPriceDisplaySchema,
26742
- rangePriceDisplaySchema,
26743
- unavailablePriceDisplaySchema
26744
- ]);
26745
- z.discriminatedUnion("kind", [
26746
- freePriceDisplaySchema,
26747
- exactPriceDisplaySchema,
26748
- fromPriceDisplaySchema,
26749
- rangePriceDisplaySchema,
26750
- mixedPriceDisplaySchema,
26751
- unavailablePriceDisplaySchema,
26752
- z.object({
26753
- kind: z.literal("external"),
26754
- label: z.string()
26755
- }),
26756
- z.object({
26757
- kind: z.literal("whole_series"),
26758
- display: publicWholeSeriesPriceDisplaySchema
26759
- })
26760
- ]);
26761
- const publicEventTicketTypePriceDisplaySchema = z.union([
26762
- freePriceDisplaySchema,
26763
- exactPriceDisplaySchema,
26764
- fromPriceDisplaySchema,
26765
- rangePriceDisplaySchema,
26766
- mixedPriceDisplaySchema,
26767
- unavailablePriceDisplaySchema
26768
- ]);
26894
+ const publicCurrencySchema = z.string().regex(/^[A-Z]{3}$/u);
26895
+ const publicCentsSchema = z.number().int().nonnegative();
26896
+ const publicPositiveCentsSchema = z.number().int().positive();
26897
+ const publicIsoDateTimeSchema = z.string().datetime({ offset: true });
26769
26898
  const publicEventAttendanceModeSchema = z.enum(["in_person", "online"]);
26770
26899
  const publicEventAttendanceModeAvailabilitySchema = z.object({
26771
26900
  mode: publicEventAttendanceModeSchema,
@@ -26774,9 +26903,9 @@ const publicEventAttendanceModeAvailabilitySchema = z.object({
26774
26903
  availableSpots: z.number().nullable(),
26775
26904
  waitlistEnabled: z.boolean()
26776
26905
  });
26777
- const publicEventTicketTypeAvailabilitySchema = z.union([z.object({
26906
+ const publicEventPricingOptionAvailabilitySchema = z.union([z.object({
26778
26907
  kind: z.literal("available"),
26779
- remainingCapacity: z.number().nullable()
26908
+ remainingPlaces: z.number().int().nonnegative().nullable()
26780
26909
  }), z.object({
26781
26910
  kind: z.literal("unavailable"),
26782
26911
  reason: z.enum([
@@ -26784,91 +26913,69 @@ const publicEventTicketTypeAvailabilitySchema = z.union([z.object({
26784
26913
  "not_on_sale_yet",
26785
26914
  "sale_ended",
26786
26915
  "sold_out",
26787
- "event_sold_out"
26916
+ "attendance_mode_unavailable",
26917
+ "overallCapacityUnavailable"
26788
26918
  ]),
26789
- remainingCapacity: z.number().nullable()
26919
+ remainingPlaces: z.number().int().nonnegative().nullable()
26790
26920
  })]);
26791
- const publicEventTicketTypeSchema = z.object({
26792
- id: z.string(),
26793
- siteId: z.string(),
26794
- eventSeriesId: z.string(),
26795
- name: z.string(),
26921
+ const publicEventPricingOptionSchema = z.object({
26922
+ id: z.string().min(1),
26923
+ name: z.string().min(1),
26796
26924
  description: z.string().nullable(),
26797
- priceAmount: z.number(),
26925
+ priceAmount: publicCentsSchema,
26798
26926
  isActive: z.boolean(),
26799
- sortOrder: z.number(),
26800
- capacityMode: z.enum(["limited", "unlimited"]),
26801
- capacityLimit: z.number().nullable(),
26927
+ sortOrder: z.number().int().nonnegative(),
26802
26928
  attendanceScope: z.enum([
26803
26929
  "in_person",
26804
26930
  "online",
26805
26931
  "both"
26806
- ]).optional(),
26807
- saleStartsAt: z.string().nullable(),
26808
- saleEndsAt: z.string().nullable(),
26809
- availability: publicEventTicketTypeAvailabilitySchema,
26810
- createdAt: z.string(),
26811
- updatedAt: z.string()
26932
+ ]),
26933
+ saleStartsAt: publicIsoDateTimeSchema.nullable(),
26934
+ saleEndsAt: publicIsoDateTimeSchema.nullable(),
26935
+ availability: publicEventPricingOptionAvailabilitySchema
26936
+ }).superRefine((option, context) => {
26937
+ if (option.saleStartsAt && option.saleEndsAt && Date.parse(option.saleEndsAt) <= Date.parse(option.saleStartsAt)) context.addIssue({
26938
+ code: "custom",
26939
+ path: ["saleEndsAt"],
26940
+ message: "Sale end must be after sale start"
26941
+ });
26812
26942
  });
26813
26943
  const publicEventPricingSchema = z.discriminatedUnion("kind", [
26814
26944
  z.object({
26815
- kind: z.literal("drop_in"),
26816
- currency: z.string(),
26817
- display: z.object({
26818
- kind: z.literal("free"),
26819
- currency: z.string()
26820
- })
26945
+ kind: z.literal("free"),
26946
+ currency: publicCurrencySchema
26821
26947
  }),
26822
26948
  z.object({
26823
- kind: z.literal("free_registration"),
26824
- currency: z.string(),
26825
- display: z.object({
26826
- kind: z.literal("free"),
26827
- currency: z.string()
26828
- })
26949
+ kind: z.literal("single"),
26950
+ amount: publicPositiveCentsSchema,
26951
+ currency: publicCurrencySchema
26829
26952
  }),
26830
26953
  z.object({
26831
- kind: z.literal("single_paid"),
26832
- amount: z.number(),
26833
- currency: z.string(),
26834
- display: z.object({
26835
- kind: z.literal("exact"),
26836
- amount: z.number(),
26837
- currency: z.string()
26838
- })
26839
- }),
26840
- z.object({
26841
- kind: z.literal("ticket_types"),
26842
- currency: z.string(),
26843
- ticketTypes: z.array(publicEventTicketTypeSchema),
26844
- display: publicEventTicketTypePriceDisplaySchema
26954
+ kind: z.literal("tiered"),
26955
+ currency: publicCurrencySchema,
26956
+ options: z.tuple([publicEventPricingOptionSchema], publicEventPricingOptionSchema)
26845
26957
  }),
26846
26958
  z.object({
26847
26959
  kind: z.literal("sliding_scale"),
26848
- minAmount: z.number(),
26849
- maxAmount: z.number(),
26850
- suggestedAmount: z.number().nullable(),
26851
- currency: z.string(),
26852
- display: z.object({
26853
- kind: z.literal("range"),
26854
- minAmount: z.number(),
26855
- maxAmount: z.number(),
26856
- currency: z.string()
26857
- })
26858
- }),
26859
- z.object({
26860
- kind: z.literal("whole_series"),
26861
- display: z.object({
26862
- kind: z.literal("whole_series"),
26863
- display: publicWholeSeriesPriceDisplaySchema
26864
- })
26960
+ minimum: publicCentsSchema,
26961
+ maximum: publicPositiveCentsSchema,
26962
+ suggested: publicCentsSchema.nullable(),
26963
+ currency: publicCurrencySchema
26964
+ }).superRefine((pricing, context) => {
26965
+ if (pricing.minimum > pricing.maximum) context.addIssue({
26966
+ code: "custom",
26967
+ path: ["minimum"],
26968
+ message: "Minimum must not exceed maximum"
26969
+ });
26970
+ if (pricing.suggested !== null && (pricing.suggested < pricing.minimum || pricing.suggested > pricing.maximum)) context.addIssue({
26971
+ code: "custom",
26972
+ path: ["suggested"],
26973
+ message: "Suggested amount must be within the sliding-scale range"
26974
+ });
26865
26975
  }),
26866
26976
  z.object({
26867
26977
  kind: z.literal("external"),
26868
- display: z.object({
26869
- kind: z.literal("external"),
26870
- label: z.string()
26871
- })
26978
+ label: z.string().min(1)
26872
26979
  })
26873
26980
  ]);
26874
26981
  const publicTeamMemberSummarySchema = z.object({
@@ -26894,11 +27001,30 @@ const publicEventBookingAvailabilitySchema = z.discriminatedUnion("kind", [z.obj
26894
27001
  "enrollment_closed"
26895
27002
  ])
26896
27003
  })]);
27004
+ const publicRunSessionSchema = z.object({
27005
+ occurrenceId: z.string(),
27006
+ startsAt: z.string(),
27007
+ endsAt: z.string(),
27008
+ timeZone: z.string(),
27009
+ status: z.string()
27010
+ });
27011
+ const publicWholeSeriesRunSchema = z.object({
27012
+ eventSeriesId: z.string(),
27013
+ eventOfferingId: z.string(),
27014
+ enrollmentOpen: z.boolean(),
27015
+ visibility: z.enum(["public", "unlisted"]),
27016
+ lifecycle: z.enum([
27017
+ "upcoming",
27018
+ "in_progress",
27019
+ "completed",
27020
+ "cancelled"
27021
+ ]),
27022
+ sessions: z.array(publicRunSessionSchema)
27023
+ });
26897
27024
  /**
26898
- * Zod schema for public event data
27025
+ * Zod schema for the fields shared by both booking scopes.
26899
27026
  */
26900
- const publicEventSchema = z.object({
26901
- bookingScope: z.enum(["single_occurrence", "whole_series"]),
27027
+ const publicEventBaseSchema = z.object({
26902
27028
  eventPreset: eventPresetSchema.optional(),
26903
27029
  eventDestinationMode: eventDestinationModeSchema.optional(),
26904
27030
  scheduleScope: eventScheduleScopeSchema$2.optional(),
@@ -26948,20 +27074,68 @@ const publicEventSchema = z.object({
26948
27074
  accessRestriction: accessRestrictionSchema,
26949
27075
  allowedCategoryIds: z.array(z.string()),
26950
27076
  requireGuestDetails: z.boolean().optional(),
26951
- acceptsPasses: z.boolean().optional(),
26952
- acceptsMemberships: z.boolean().optional(),
26953
- wholeSeries: z.object({
26954
- eventSeriesId: z.string(),
26955
- pricing: wholeSeriesPricingSchema,
26956
- currency: z.string(),
26957
- enrollmentOpen: z.boolean()
26958
- }).nullable().optional()
27077
+ acceptsPasses: z.boolean(),
27078
+ acceptsMemberships: z.boolean()
26959
27079
  });
26960
27080
  /**
27081
+ * Zod schema for public event data.
27082
+ *
27083
+ * The booking scope discriminates: a `whole_series` record without complete
27084
+ * `run` facts is rejected, and a `single_occurrence` record never carries them.
27085
+ */
27086
+ const publicEventSchema = z.union([publicEventBaseSchema.extend({
27087
+ bookingScope: z.literal("single_occurrence"),
27088
+ run: z.undefined().optional()
27089
+ }), publicEventBaseSchema.extend({
27090
+ bookingScope: z.literal("whole_series"),
27091
+ run: publicWholeSeriesRunSchema
27092
+ })]);
27093
+ /**
26961
27094
  * Schema for an array of public events
26962
27095
  */
26963
27096
  const publicEventsArraySchema = z.array(publicEventSchema);
26964
27097
  //#endregion
27098
+ //#region ../blocks/src/system/blocks/events/shared/runGrouping.ts
27099
+ function isWholeSeriesPublicEvent(event) {
27100
+ return event.bookingScope === "whole_series";
27101
+ }
27102
+ /**
27103
+ * Group events into one entry per whole-series run.
27104
+ *
27105
+ * Single-occurrence events are ignored. Run order follows first appearance, so
27106
+ * a caller's sort survives the grouping, and an occurrence that arrives twice
27107
+ * is kept once.
27108
+ */
27109
+ function groupPublicEventsByRun(events) {
27110
+ const occurrencesBySeriesId = /* @__PURE__ */ new Map();
27111
+ const order = [];
27112
+ const seenOccurrenceIds = /* @__PURE__ */ new Set();
27113
+ for (const event of events) {
27114
+ if (!isWholeSeriesPublicEvent(event)) continue;
27115
+ if (seenOccurrenceIds.has(event.occurrenceId)) continue;
27116
+ seenOccurrenceIds.add(event.occurrenceId);
27117
+ const seriesId = event.run.eventSeriesId;
27118
+ const existing = occurrencesBySeriesId.get(seriesId);
27119
+ if (existing) {
27120
+ existing.push(event);
27121
+ continue;
27122
+ }
27123
+ occurrencesBySeriesId.set(seriesId, [event]);
27124
+ order.push(seriesId);
27125
+ }
27126
+ return order.map((eventSeriesId) => {
27127
+ const occurrences = occurrencesBySeriesId.get(eventSeriesId) ?? [];
27128
+ const representative = occurrences[0];
27129
+ if (!representative) throw new Error(`Run ${eventSeriesId} grouped without any occurrence`);
27130
+ return {
27131
+ eventSeriesId,
27132
+ run: representative.run,
27133
+ occurrences,
27134
+ representative
27135
+ };
27136
+ });
27137
+ }
27138
+ //#endregion
26965
27139
  //#region ../blocks/src/system/blocks/events/shared/fields.ts
26966
27140
  /**
26967
27141
  * Shared card styling fields for event blocks
@@ -27011,7 +27185,7 @@ const eventDisplayFields = [
27011
27185
  {
27012
27186
  id: "showCapacity",
27013
27187
  type: "boolean",
27014
- label: "Show available spots",
27188
+ label: "Show available places",
27015
27189
  description: "Display remaining capacity",
27016
27190
  required: false,
27017
27191
  defaultValue: true,
@@ -27242,7 +27416,9 @@ const unsupportedEventRegistrationPageSurfaceSubjectSchema = z.object({
27242
27416
  "unsupportedSubject",
27243
27417
  "invalidEventSeriesId",
27244
27418
  "invalidEventSeriesBookingScope",
27245
- "invalidEventOfferingId"
27419
+ "invalidEventOfferingId",
27420
+ "invalidEventOfferingBookingScope",
27421
+ "invalidEventOfferingCatalogue"
27246
27422
  ])
27247
27423
  });
27248
27424
  const eventRegistrationPageSurfaceSubjectSchema = z.unknown().transform((value, ctx) => {
@@ -27269,7 +27445,7 @@ function resolveEventRegistrationScope(context) {
27269
27445
  if (context.subject?.kind === "eventOffering") return {
27270
27446
  kind: "pageSurfaceOffering",
27271
27447
  offeringId: context.subject.eventOfferingId,
27272
- seriesIds: context.subject.availableEventSeriesIds
27448
+ seriesIds: context.subject.catalogueEventSeriesIds
27273
27449
  };
27274
27450
  if (context.subject?.kind === "unsupported") return {
27275
27451
  kind: "unsupportedPageSurfaceSubject",
@@ -27291,31 +27467,12 @@ function resolveEventRegistrationScopedEvents(events, context) {
27291
27467
  }
27292
27468
  }
27293
27469
  //#endregion
27294
- //#region ../blocks/src/system/runtime/nodes/event-registration/registrationSurface.ts
27295
- function planEventRegistrationScope(input) {
27296
- const subject = input.subject;
27297
- const selectedRunOffering = input.wholeSeriesOffering;
27298
- if (subject?.kind !== "eventOffering" || !selectedRunOffering) return {
27299
- kind: "context",
27300
- events: resolveEventRegistrationScopedEvents(input.events, {
27301
- occurrenceContext: input.occurrenceContext,
27302
- subject
27303
- })
27304
- };
27305
- if (!(selectedRunOffering.eventOfferingId === subject.eventOfferingId && subject.availableEventSeriesIds.some((seriesId) => seriesId === selectedRunOffering.eventSeriesId))) return { kind: "invalidSelectedRun" };
27306
- return {
27307
- kind: "selectedRun",
27308
- events: input.events.filter((event) => event.seriesId === selectedRunOffering.eventSeriesId),
27309
- offering: selectedRunOffering
27310
- };
27311
- }
27312
- //#endregion
27313
- //#region ../blocks/src/system/runtime/nodes/events/shared/destination.ts
27314
- function isRecord$5(value) {
27470
+ //#region ../blocks/src/system/runtime/nodes/events/domain/destination.ts
27471
+ function isRecord$4(value) {
27315
27472
  return typeof value === "object" && value !== null && !Array.isArray(value);
27316
27473
  }
27317
27474
  function isRuntimeEventDestination(value) {
27318
- if (!isRecord$5(value) || typeof value.kind !== "string") return false;
27475
+ if (!isRecord$4(value) || typeof value.kind !== "string") return false;
27319
27476
  if (value.kind === "native") return (value.mode === "cms-managed" || value.mode === "system-managed") && typeof value.path === "string";
27320
27477
  return value.kind === "external" && typeof value.url === "string" && typeof value.label === "string";
27321
27478
  }
@@ -27328,174 +27485,6 @@ function resolveRuntimeEventDestination(event) {
27328
27485
  };
27329
27486
  }
27330
27487
  //#endregion
27331
- //#region ../blocks/src/system/runtime/nodes/events/shared/pricing.ts
27332
- const DEFAULT_EVENT_CURRENCY = "USD";
27333
- function resolveRuntimeEventPricing(event) {
27334
- if (isPublicEventPricing(event.pricing)) return event.pricing;
27335
- if (resolveRuntimeEventDestination(event).kind === "external") return {
27336
- kind: "external",
27337
- display: {
27338
- kind: "external",
27339
- label: "External registration"
27340
- }
27341
- };
27342
- const legacy = event;
27343
- const currency = readCurrency(legacy.currency);
27344
- if (event.requiresRegistration === false) return {
27345
- kind: "drop_in",
27346
- currency,
27347
- display: {
27348
- kind: "free",
27349
- currency
27350
- }
27351
- };
27352
- if (legacy.pricingMode === "ticket_types") return {
27353
- kind: "ticket_types",
27354
- currency,
27355
- ticketTypes: Array.isArray(legacy.ticketTypes) ? legacy.ticketTypes.filter(isPublicEventTicketType) : [],
27356
- display: readTicketTypePriceDisplay(legacy.priceDisplay, currency)
27357
- };
27358
- const amount = typeof legacy.price === "number" ? legacy.price : 0;
27359
- if (legacy.pricingType === "paid" && amount > 0) return {
27360
- kind: "single_paid",
27361
- amount,
27362
- currency,
27363
- display: {
27364
- kind: "exact",
27365
- amount,
27366
- currency
27367
- }
27368
- };
27369
- return {
27370
- kind: "free_registration",
27371
- currency,
27372
- display: {
27373
- kind: "free",
27374
- currency
27375
- }
27376
- };
27377
- }
27378
- function readCurrency(value) {
27379
- return typeof value === "string" && value.trim().length > 0 ? value : DEFAULT_EVENT_CURRENCY;
27380
- }
27381
- function isRecord$4(value) {
27382
- return typeof value === "object" && value !== null && !Array.isArray(value);
27383
- }
27384
- function isPublicEventPricing(value) {
27385
- if (!isRecord$4(value) || typeof value.kind !== "string") return false;
27386
- 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";
27387
- }
27388
- function isPublicEventTicketType(value) {
27389
- return isRecord$4(value) && typeof value.id === "string";
27390
- }
27391
- function readTicketTypePriceDisplay(value, currency) {
27392
- const display = readLegacyPriceDisplay(value, currency);
27393
- return display.kind === "whole_series" || display.kind === "external" ? {
27394
- kind: "unavailable",
27395
- currency
27396
- } : display;
27397
- }
27398
- function readLegacyPriceDisplay(value, currency) {
27399
- if (!isRecord$4(value) || typeof value.kind !== "string") return {
27400
- kind: "unavailable",
27401
- currency
27402
- };
27403
- const displayCurrency = readCurrency(value.currency);
27404
- switch (value.kind) {
27405
- case "free": return {
27406
- kind: "free",
27407
- currency: displayCurrency
27408
- };
27409
- case "exact": return readAmount(value.amount) !== null ? {
27410
- kind: "exact",
27411
- amount: readAmount(value.amount) ?? 0,
27412
- currency: displayCurrency
27413
- } : {
27414
- kind: "unavailable",
27415
- currency
27416
- };
27417
- case "from": return readAmount(value.amount) !== null ? {
27418
- kind: "from",
27419
- amount: readAmount(value.amount) ?? 0,
27420
- currency: displayCurrency
27421
- } : {
27422
- kind: "unavailable",
27423
- currency
27424
- };
27425
- case "range": {
27426
- const minAmount = readAmount(value.minAmount);
27427
- const maxAmount = readAmount(value.maxAmount);
27428
- return minAmount !== null && maxAmount !== null ? {
27429
- kind: "range",
27430
- minAmount,
27431
- maxAmount,
27432
- currency: displayCurrency
27433
- } : {
27434
- kind: "unavailable",
27435
- currency
27436
- };
27437
- }
27438
- case "mixed": return readAmount(value.paidFromAmount) !== null ? {
27439
- kind: "mixed",
27440
- paidFromAmount: readAmount(value.paidFromAmount) ?? 0,
27441
- paidToAmount: readAmount(value.paidToAmount) ?? readAmount(value.paidFromAmount) ?? 0,
27442
- currency: displayCurrency
27443
- } : {
27444
- kind: "unavailable",
27445
- currency
27446
- };
27447
- case "unavailable": return {
27448
- kind: "unavailable",
27449
- currency: displayCurrency
27450
- };
27451
- case "whole_series": return isRecord$4(value.display) ? {
27452
- kind: "whole_series",
27453
- display: readCoursePriceDisplay(value.display, displayCurrency)
27454
- } : {
27455
- kind: "whole_series",
27456
- display: {
27457
- kind: "unavailable",
27458
- currency: displayCurrency
27459
- }
27460
- };
27461
- default: return {
27462
- kind: "unavailable",
27463
- currency
27464
- };
27465
- }
27466
- }
27467
- function readCoursePriceDisplay(value, currency) {
27468
- switch (value.kind) {
27469
- case "free": return {
27470
- kind: "free",
27471
- currency: readCurrency(value.currency)
27472
- };
27473
- case "exact": return readAmount(value.amount) !== null ? {
27474
- kind: "exact",
27475
- amount: readAmount(value.amount) ?? 0,
27476
- currency: readCurrency(value.currency)
27477
- } : {
27478
- kind: "unavailable",
27479
- currency
27480
- };
27481
- case "from": return readAmount(value.amount) !== null ? {
27482
- kind: "from",
27483
- amount: readAmount(value.amount) ?? 0,
27484
- currency: readCurrency(value.currency)
27485
- } : {
27486
- kind: "unavailable",
27487
- currency
27488
- };
27489
- default: return {
27490
- kind: "unavailable",
27491
- currency
27492
- };
27493
- }
27494
- }
27495
- function readAmount(value) {
27496
- return typeof value === "number" && Number.isFinite(value) ? value : null;
27497
- }
27498
- //#endregion
27499
27488
  //#region ../blocks/src/system/constants/events.ts
27500
27489
  const eventCalendarDisplayModeValues = [
27501
27490
  "combined",
@@ -27527,6 +27516,10 @@ const eventCalendarListLayoutOptions = [
27527
27516
  function isEventCalendarDisplayMode(value) {
27528
27517
  return typeof value === "string" && eventCalendarDisplayModeValues.includes(value);
27529
27518
  }
27519
+ function normalizeEventCalendarDisplayMode$1(input) {
27520
+ if (isEventCalendarDisplayMode(input.variant)) return input.variant;
27521
+ return isEventCalendarDisplayMode(input.displayMode) ? input.displayMode : void 0;
27522
+ }
27530
27523
  function isEventCalendarDefaultView(value) {
27531
27524
  return typeof value === "string" && eventCalendarDefaultViewValues.includes(value);
27532
27525
  }
@@ -27596,14 +27589,13 @@ function resolveEventRequiresPayment(input) {
27596
27589
  if (input.eligibility) return input.eligibility.requiresPayment;
27597
27590
  if (input.selectedTicketType) return input.selectedTicketType.priceAmount > 0;
27598
27591
  if (!input.event) return false;
27599
- return publicEventPricingType(resolveRuntimeEventPricing(input.event)) === "paid";
27592
+ return publicEventPricingType(input.event.pricing) === "paid";
27600
27593
  }
27601
27594
  //#endregion
27602
27595
  //#region ../blocks/src/system/runtime/nodes/event-registration/registrationEventAdapter.ts
27603
27596
  function toRegistrationEvent(event) {
27604
27597
  return {
27605
27598
  ...event,
27606
- pricing: resolveRuntimeEventPricing(event),
27607
27599
  selectionId: event.id,
27608
27600
  registrationSubject: {
27609
27601
  kind: "occurrence",
@@ -27614,118 +27606,35 @@ function toRegistrationEvent(event) {
27614
27606
  function toRegistrationEvents(events) {
27615
27607
  return events.filter((event) => event.bookingScope === "single_occurrence").map(toRegistrationEvent);
27616
27608
  }
27617
- function toWholeSeriesTicketType(option) {
27618
- return {
27619
- ...option,
27620
- capacityMode: option.capacityLimit === null ? "unlimited" : "limited",
27621
- attendanceScope: option.attendanceScope ?? void 0,
27622
- availability: {
27623
- kind: "available",
27624
- remainingCapacity: option.capacityLimit
27625
- }
27626
- };
27627
- }
27628
- function toWholeSeriesPricing(offering) {
27629
- const resolved = resolveWholeSeriesPricingState(offering);
27630
- switch (offering.pricing.pricingStrategy) {
27631
- case "free": return {
27632
- kind: "free_registration",
27633
- currency: offering.currency,
27634
- display: {
27635
- kind: "free",
27636
- currency: offering.currency
27637
- }
27638
- };
27639
- case "single": {
27640
- const amount = offering.pricing.singlePriceAmount ?? 0;
27641
- return amount === 0 ? {
27642
- kind: "free_registration",
27643
- currency: offering.currency,
27644
- display: {
27645
- kind: "free",
27646
- currency: offering.currency
27647
- }
27648
- } : {
27649
- kind: "single_paid",
27650
- amount,
27651
- currency: offering.currency,
27652
- display: {
27653
- kind: "exact",
27654
- amount,
27655
- currency: offering.currency
27656
- }
27657
- };
27658
- }
27659
- case "tiered": return {
27660
- kind: "ticket_types",
27661
- currency: offering.currency,
27662
- ticketTypes: resolved.selectableOptions.map((option) => toWholeSeriesTicketType(option)),
27663
- display: resolved.display
27664
- };
27665
- case "sliding_scale": return {
27666
- kind: "sliding_scale",
27667
- minAmount: offering.pricing.slidingMinAmount ?? 0,
27668
- maxAmount: offering.pricing.slidingMaxAmount ?? 0,
27669
- suggestedAmount: offering.pricing.slidingSuggestedAmount ?? null,
27670
- currency: offering.currency,
27671
- display: {
27672
- kind: "range",
27673
- minAmount: offering.pricing.slidingMinAmount ?? 0,
27674
- maxAmount: offering.pricing.slidingMaxAmount ?? 0,
27675
- currency: offering.currency
27676
- }
27677
- };
27678
- }
27679
- }
27680
- function toAttendanceModes(offering) {
27681
- return (offering.deliveryMode === "hybrid" ? ["in_person", "online"] : [offering.deliveryMode]).map((mode) => ({
27682
- mode,
27683
- capacity: offering.enrollmentCapacity,
27684
- registeredCount: offering.enrolledCount,
27685
- availableSpots: offering.availableSpots,
27686
- waitlistEnabled: offering.waitlistEnabled
27687
- }));
27688
- }
27689
- function toWholeSeriesRegistrationEvent(offering) {
27690
- const firstSession = offering.sessions[0];
27691
- const lastSession = offering.sessions[offering.sessions.length - 1];
27609
+ /**
27610
+ * Project one whole-series run onto the registration surface.
27611
+ *
27612
+ * Capacity, pricing, payment terms and consent come straight off the canonical
27613
+ * Event record; only the schedule is widened from the single occurrence to the
27614
+ * live run. A run without live sessions has no registration event.
27615
+ */
27616
+ function toWholeSeriesRegistrationEvent(group) {
27617
+ const { representative, run } = group;
27618
+ const sessions = orderedLiveRunSessions(run.sessions);
27619
+ const firstSession = sessions[0];
27620
+ if (!firstSession) return null;
27621
+ const lastSession = sessions[sessions.length - 1] ?? firstSession;
27692
27622
  return {
27693
- selectionId: offering.eventSeriesId,
27623
+ ...representative,
27624
+ selectionId: run.eventSeriesId,
27694
27625
  registrationSubject: {
27695
27626
  kind: "wholeSeries",
27696
- eventSeriesId: offering.eventSeriesId,
27697
- sessions: offering.sessions
27698
- },
27699
- seriesId: offering.eventSeriesId,
27700
- title: offering.title,
27701
- startsAt: firstSession?.startsAt ?? "",
27702
- endsAt: lastSession?.endsAt ?? firstSession?.endsAt ?? "",
27703
- bookingAvailability: offering.enrollmentOpen ? { kind: "open" } : {
27704
- kind: "closed",
27705
- reason: "enrollment_closed"
27706
- },
27707
- deliveryMode: offering.deliveryMode,
27708
- attendanceModes: toAttendanceModes(offering),
27709
- capacity: offering.enrollmentCapacity,
27710
- registeredCount: offering.enrolledCount,
27711
- availableSpots: offering.availableSpots,
27712
- waitlistEnabled: offering.waitlistEnabled,
27713
- venue: offering.venue ? {
27714
- ...offering.venue,
27715
- location: null
27716
- } : null,
27717
- eventCategory: null,
27718
- teamMembers: offering.teamMembers,
27719
- status: offering.status,
27720
- timeZone: firstSession?.timeZone ?? "UTC",
27721
- pricing: toWholeSeriesPricing(offering),
27722
- paymentTerms: offering.paymentTerms,
27723
- consent: offering.consent,
27724
- requireGuestDetails: offering.requireGuestDetails,
27725
- acceptsPasses: false,
27726
- acceptsMemberships: offering.acceptsMemberships
27627
+ eventSeriesId: run.eventSeriesId,
27628
+ sessions
27629
+ },
27630
+ startsAt: firstSession.startsAt,
27631
+ endsAt: lastSession.endsAt,
27632
+ timeZone: firstSession.timeZone
27727
27633
  };
27728
27634
  }
27635
+ function toWholeSeriesRegistrationEvents(events) {
27636
+ return groupPublicEventsByRun(events).map(toWholeSeriesRegistrationEvent).filter((event) => event !== null);
27637
+ }
27729
27638
  //#endregion
27730
27639
  //#region ../blocks/src/system/runtime/nodes/event-registration.interactive.ts
27731
27640
  const EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS = [
@@ -27745,8 +27654,7 @@ const eventRegistrationHydrationSchemaShape = {
27745
27654
  occurrenceContext: occurrenceContextSchema.optional(),
27746
27655
  subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
27747
27656
  events: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
27748
- wholeSeriesOfferings: publicWholeSeriesOfferingsArraySchema.nullable().optional(),
27749
- wholeSeriesOffering: publicWholeSeriesOfferingSchema.nullable().optional(),
27657
+ wholeSeriesRunEvents: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
27750
27658
  maxTickets: z.string().optional(),
27751
27659
  showVenue: z.boolean().optional(),
27752
27660
  showCapacity: z.boolean().optional(),
@@ -27764,7 +27672,6 @@ const eventRegistrationSourceSchema = z.object({
27764
27672
  portalToken: z.string().nullable().optional(),
27765
27673
  previewToken: z.string().nullable().optional(),
27766
27674
  ...eventRegistrationHydrationSchemaShape,
27767
- subjectWholeSeriesOffering: publicWholeSeriesOfferingSchema.nullable().optional(),
27768
27675
  className: z.string().nullable().optional(),
27769
27676
  buttonText: z.string().nullable().optional(),
27770
27677
  maxTickets: z.string().nullable().optional(),
@@ -27798,7 +27705,8 @@ z.object({
27798
27705
  stage: previewStageSchema.optional()
27799
27706
  });
27800
27707
  function buildEventRegistrationDisplay(source) {
27801
- if (resolveWholeSeriesOffering(source)?.enrollmentOpen === false) return {
27708
+ const selectedRun = resolveSelectedWholeSeriesRun(source);
27709
+ if (selectedRun && (!selectedRun.run.enrollmentOpen || toWholeSeriesRegistrationEvent(selectedRun) === null)) return {
27802
27710
  kind: "event-registration",
27803
27711
  state: "registration-closed",
27804
27712
  className: source.className ?? null,
@@ -27816,13 +27724,11 @@ function buildEventRegistrationDisplay(source) {
27816
27724
  summaryButtonText: source.buttonText?.trim() || "Register"
27817
27725
  };
27818
27726
  }
27819
- function resolveWholeSeriesOffering(source) {
27820
- return source.wholeSeriesOffering ?? source.subjectWholeSeriesOffering ?? null;
27821
- }
27822
27727
  function buildEventRegistrationShellStepLabels(source) {
27823
- const selectedOffering = resolveWholeSeriesOffering(source);
27824
- if (selectedOffering) {
27825
- const selectedEvent = toWholeSeriesRegistrationEvent(selectedOffering);
27728
+ const selectedRun = resolveSelectedWholeSeriesRun(source);
27729
+ if (selectedRun) {
27730
+ const selectedEvent = toWholeSeriesRegistrationEvent(selectedRun);
27731
+ if (!selectedEvent) return EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS;
27826
27732
  return getWizardStepsForContext(true, resolveEventRequiresPayment({
27827
27733
  eligibility: null,
27828
27734
  selectedTicketType: null,
@@ -27843,16 +27749,31 @@ function buildEventRegistrationShellStepLabels(source) {
27843
27749
  }) : false).map((step) => shellLabelForRegistrationStep(step, scopedEvents));
27844
27750
  }
27845
27751
  function scopeEventRegistrationEvents(source) {
27846
- return toRegistrationEvents(scopeEventRegistrationSourceEvents(source));
27752
+ const scoped = scopeEventRegistrationSourceEvents(source);
27753
+ return [...toRegistrationEvents(scoped), ...toWholeSeriesRegistrationEvents(scoped)];
27847
27754
  }
27755
+ /**
27756
+ * Every event this surface may register for, from both of its loads.
27757
+ *
27758
+ * The date page and the run read answer different questions and can name the
27759
+ * same occurrence, so the two lists are joined and any occurrence that arrives
27760
+ * twice is kept once, in the order the date page gave it.
27761
+ */
27848
27762
  function scopeEventRegistrationSourceEvents(source) {
27849
- const scope = planEventRegistrationScope({
27850
- events: source.events ?? [],
27851
- wholeSeriesOffering: source.wholeSeriesOffering,
27763
+ const byOccurrenceId = /* @__PURE__ */ new Map();
27764
+ for (const event of [...source.events ?? [], ...source.wholeSeriesRunEvents ?? []]) if (!byOccurrenceId.has(event.occurrenceId)) byOccurrenceId.set(event.occurrenceId, event);
27765
+ return resolveEventRegistrationScopedEvents([...byOccurrenceId.values()], {
27852
27766
  occurrenceContext: source.occurrenceContext,
27853
27767
  subject: source.subject
27854
27768
  });
27855
- return scope.kind === "invalidSelectedRun" ? [] : [...scope.events];
27769
+ }
27770
+ /**
27771
+ * The one run this surface is registering for, when the scoped events describe
27772
+ * exactly one. More than one run means the visitor still has to choose.
27773
+ */
27774
+ function resolveSelectedWholeSeriesRun(source) {
27775
+ const runs = groupPublicEventsByRun(scopeEventRegistrationSourceEvents(source));
27776
+ return runs.length === 1 ? runs[0] : null;
27856
27777
  }
27857
27778
  function shellLabelForRegistrationStep(step, events) {
27858
27779
  switch (step) {
@@ -27892,8 +27813,6 @@ const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
27892
27813
  occurrenceContext: source.occurrenceContext ?? null,
27893
27814
  subject: source.subject ?? null,
27894
27815
  events,
27895
- wholeSeriesOfferings: source.wholeSeriesOfferings ?? null,
27896
- wholeSeriesOffering: resolveWholeSeriesOffering(source),
27897
27816
  maxTickets: source.maxTickets ?? void 0,
27898
27817
  showVenue: source.showVenue,
27899
27818
  showCapacity: source.showCapacity,
@@ -27912,8 +27831,7 @@ function normalizeEventRegistrationEventInput(value) {
27912
27831
  if (!isRecord$3(value)) return value;
27913
27832
  return {
27914
27833
  ...value,
27915
- destination: resolveRuntimeEventDestination(value),
27916
- pricing: resolveRuntimeEventPricing(value)
27834
+ destination: resolveRuntimeEventDestination(value)
27917
27835
  };
27918
27836
  }
27919
27837
  function isRecord$3(value) {
@@ -28008,7 +27926,7 @@ const eventRegistrationBlockDefinition = {
28008
27926
  {
28009
27927
  id: "showCapacity",
28010
27928
  type: "boolean",
28011
- label: "Show available spots",
27929
+ label: "Show available places",
28012
27930
  description: "Display remaining capacity",
28013
27931
  required: false,
28014
27932
  defaultValue: true,
@@ -28069,9 +27987,7 @@ const eventRegistrationBlockDefinition = {
28069
27987
  fallback: false
28070
27988
  } },
28071
27989
  events: { $bind: { from: "data.events" } },
28072
- wholeSeriesOffering: { $bind: { from: "data.selectedRunOffering.offering" } },
28073
- subjectWholeSeriesOffering: { $bind: { from: "data.subjectWholeSeriesOffering.offering" } },
28074
- wholeSeriesOfferings: { $bind: { from: "data.wholeSeriesOfferings" } },
27990
+ wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
28075
27991
  sitePasses: { $bind: { from: "data.sitePasses" } },
28076
27992
  siteMemberships: { $bind: { from: "data.siteMemberships" } },
28077
27993
  stage: { $bind: {
@@ -28085,9 +28001,7 @@ const eventRegistrationBlockDefinition = {
28085
28001
  runtime: eventRegistrationBlockRuntime,
28086
28002
  dataSchemas: {
28087
28003
  events: publicEventsArraySchema.optional(),
28088
- selectedRunOffering: z.object({ offering: publicWholeSeriesOfferingSchema }).optional(),
28089
- subjectWholeSeriesOffering: z.object({ offering: publicWholeSeriesOfferingSchema }).optional(),
28090
- wholeSeriesOfferings: z.array(publicWholeSeriesOfferingSchema).optional(),
28004
+ wholeSeriesRunEvents: publicEventsArraySchema.optional(),
28091
28005
  sitePasses: publicPassProductCollectionSchema.optional(),
28092
28006
  siteMemberships: publicMembershipProductCollectionSchema.optional(),
28093
28007
  occurrenceContext: occurrenceContextSchema.optional()
@@ -28105,7 +28019,7 @@ const eventRegistrationBlockDefinition = {
28105
28019
  readProfile: "registration",
28106
28020
  seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
28107
28021
  seriesIds: { $bind: {
28108
- from: "$root.subject.availableEventSeriesIds",
28022
+ from: "$root.subject.catalogueEventSeriesIds",
28109
28023
  transforms: [{ id: "value.csv" }]
28110
28024
  } },
28111
28025
  runSeriesId: { $bind: { from: "$root.entrySubrouteContext.run.seriesId" } },
@@ -28113,50 +28027,39 @@ const eventRegistrationBlockDefinition = {
28113
28027
  },
28114
28028
  mode: "server"
28115
28029
  },
28116
- selectedRunOffering: {
28117
- endpoint: "getPublicWholeSeriesOffering",
28118
- params: {
28119
- siteId: { $bind: { from: "$root.siteId" } },
28120
- eventSeriesId: { $bind: { from: "$root.entrySubrouteContext.run.seriesId" } },
28121
- stage: { $bind: {
28122
- from: "$root.previewStage",
28123
- fallback: "published"
28124
- } }
28125
- },
28126
- requiredParams: ["eventSeriesId"],
28127
- mode: "server"
28128
- },
28129
- subjectWholeSeriesOffering: {
28130
- endpoint: "getPublicWholeSeriesOffering",
28030
+ /**
28031
+ * The runs this page can register for, finished ones included.
28032
+ *
28033
+ * The `events` page above is date-bounded, so a run whose first session has
28034
+ * passed contributes no rows to it and the surface would have nothing to
28035
+ * render as closed. This asks for runs instead, and only on a page whose
28036
+ * subject books whole runs. It is scoped exactly like the date page — same
28037
+ * series, same run subroute — because scope and grain are separate
28038
+ * questions. The two lists are joined by occurrence, so a run that appears
28039
+ * in both is still one run.
28040
+ */
28041
+ wholeSeriesRunEvents: {
28042
+ endpoint: "listPublicEvents",
28131
28043
  when: { $bind: {
28132
28044
  from: "$root.subject.isWholeSeriesBooking",
28133
28045
  fallback: false
28134
28046
  } },
28135
28047
  params: {
28136
28048
  siteId: { $bind: { from: "$root.siteId" } },
28137
- eventSeriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
28049
+ readIntent: "runs",
28050
+ limit: "50",
28138
28051
  stage: { $bind: {
28139
28052
  from: "$root.previewStage",
28140
28053
  fallback: "published"
28141
- } }
28142
- },
28143
- requiredParams: ["eventSeriesId"],
28144
- mode: "server"
28145
- },
28146
- wholeSeriesOfferings: {
28147
- endpoint: "listPublicWholeSeriesOfferings",
28148
- params: {
28149
- siteId: { $bind: { from: "$root.siteId" } },
28150
- eventSeriesIds: { $bind: {
28151
- from: "$root.subject.availableEventSeriesIds",
28054
+ } },
28055
+ readProfile: "registration",
28056
+ seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
28057
+ seriesIds: { $bind: {
28058
+ from: "$root.subject.catalogueEventSeriesIds",
28152
28059
  transforms: [{ id: "value.csv" }]
28153
28060
  } },
28154
- stage: { $bind: {
28155
- from: "$root.previewStage",
28156
- fallback: "published"
28157
- } }
28061
+ runSeriesId: { $bind: { from: "$root.entrySubrouteContext.run.seriesId" } }
28158
28062
  },
28159
- requiredParams: ["eventSeriesIds"],
28160
28063
  mode: "server"
28161
28064
  },
28162
28065
  sitePasses: {
@@ -28409,7 +28312,7 @@ const eventDetailsBlockDefinition = {
28409
28312
  readProfile: "details",
28410
28313
  seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
28411
28314
  seriesIds: { $bind: {
28412
- from: "$root.subject.availableEventSeriesIds",
28315
+ from: "$root.subject.catalogueEventSeriesIds",
28413
28316
  transforms: [{ id: "value.csv" }]
28414
28317
  } },
28415
28318
  runSeriesId: { $bind: { from: "$root.entrySubrouteContext.run.seriesId" } },
@@ -28569,7 +28472,11 @@ const eventSpotlightBlockDefinition = {
28569
28472
  } }
28570
28473
  };
28571
28474
  //#endregion
28572
- //#region ../blocks/src/system/runtime/nodes/events/shared/utils.ts
28475
+ //#region ../blocks/src/system/runtime/nodes/events/shared/listingLayout.ts
28476
+ /**
28477
+ * Layout classes for event listing containers and cards. Presentation
28478
+ * plumbing rather than event domain logic, so it lives beside the components.
28479
+ */
28573
28480
  /**
28574
28481
  * Column class mappings for grid layouts, derived from the canonical
28575
28482
  * responsive column ladder (see gridUserColumnLadder).
@@ -28653,6 +28560,97 @@ function resolveEventListPaginationAction(input) {
28653
28560
  };
28654
28561
  }
28655
28562
  //#endregion
28563
+ //#region ../blocks/src/system/blocks/events/shared/calendarWindow.ts
28564
+ function resolveCalendarReadProfile(content) {
28565
+ const mode = normalizeEventCalendarDisplayMode$1(content);
28566
+ return mode === "timetable" || mode === "week-board" ? "timetable" : "listing-card";
28567
+ }
28568
+ /** Runtime picker sentinels and bound loader IDs must describe the same query. */
28569
+ function normalizeCalendarFilterId(value) {
28570
+ const id = value?.trim();
28571
+ return !id || id === "all" ? void 0 : id;
28572
+ }
28573
+ const calendarMonthSchema = z.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).refine((month) => Number(month.slice(0, 4)) > 0, "Invalid calendar year");
28574
+ function calendarMonthDate(month) {
28575
+ return {
28576
+ year: Number(month.slice(0, 4)),
28577
+ month: Number(month.slice(5, 7)),
28578
+ day: 1
28579
+ };
28580
+ }
28581
+ const monthNumber = (month) => {
28582
+ const date = calendarMonthDate(month);
28583
+ return date.year * 12 + date.month - 1;
28584
+ };
28585
+ const calendarMonthWindowSchema = z.object({
28586
+ startMonth: calendarMonthSchema,
28587
+ endMonthExclusive: calendarMonthSchema
28588
+ }).refine((window) => {
28589
+ const width = monthNumber(window.endMonthExclusive) - monthNumber(window.startMonth);
28590
+ return width > 0 && width <= 3;
28591
+ }, "Calendar windows must cover one to three months");
28592
+ z.object({
28593
+ startMonth: calendarMonthSchema.optional(),
28594
+ endMonthExclusive: calendarMonthSchema.optional(),
28595
+ afterStartsAt: z.string().datetime({ offset: true }).optional(),
28596
+ afterId: z.string().uuid().optional(),
28597
+ limit: z.coerce.number().int().min(1).max(200).default(100),
28598
+ stage: z.enum(["published", "preview"]).default("published"),
28599
+ readProfile: z.enum(["listing-card", "timetable"]).optional(),
28600
+ eventSurface: z.enum(eventSurfaceScopeValues).optional(),
28601
+ eventPresets: z.string().optional(),
28602
+ scheduleScope: z.enum(eventScheduleScopeValues).optional(),
28603
+ categoryIds: z.string().optional(),
28604
+ venueId: z.string().transform(normalizeCalendarFilterId).optional(),
28605
+ staffMemberId: z.string().transform(normalizeCalendarFilterId).optional()
28606
+ }).superRefine((query, ctx) => {
28607
+ if (Boolean(query.startMonth) !== Boolean(query.endMonthExclusive)) ctx.addIssue({
28608
+ code: "custom",
28609
+ message: "Both month bounds are required"
28610
+ });
28611
+ if (query.startMonth && query.endMonthExclusive && !calendarMonthWindowSchema.safeParse(query).success) ctx.addIssue({
28612
+ code: "custom",
28613
+ message: "Invalid calendar window"
28614
+ });
28615
+ if (Boolean(query.afterStartsAt) !== Boolean(query.afterId)) ctx.addIssue({
28616
+ code: "custom",
28617
+ message: "Both cursor fields are required"
28618
+ });
28619
+ if (query.afterStartsAt && !query.startMonth) ctx.addIssue({
28620
+ code: "custom",
28621
+ message: "A continuation requires explicit month bounds"
28622
+ });
28623
+ });
28624
+ const calendarSourceCursorSchema = z.object({
28625
+ startsAt: z.string().datetime({ offset: true }),
28626
+ occurrenceId: z.string().uuid()
28627
+ });
28628
+ z.discriminatedUnion("kind", [z.object({ kind: z.literal("complete") }), z.object({
28629
+ kind: z.literal("partial"),
28630
+ nextCursor: calendarSourceCursorSchema
28631
+ })]);
28632
+ const pageFields = {
28633
+ scope: z.object({
28634
+ key: z.string(),
28635
+ timeZone: z.string().transform(toBookingTimeZone)
28636
+ }),
28637
+ window: calendarMonthWindowSchema,
28638
+ initialToday: z.object({
28639
+ year: z.number().int(),
28640
+ month: z.number().int().min(1).max(12),
28641
+ day: z.number().int().min(1).max(31)
28642
+ }),
28643
+ events: z.array(publicEventSchema)
28644
+ };
28645
+ const calendarWindowPageSchema = z.discriminatedUnion("kind", [z.object({
28646
+ ...pageFields,
28647
+ kind: z.literal("complete")
28648
+ }), z.object({
28649
+ ...pageFields,
28650
+ kind: z.literal("partial"),
28651
+ nextCursor: calendarSourceCursorSchema
28652
+ })]);
28653
+ //#endregion
28656
28654
  //#region ../blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.ts
28657
28655
  const eventSurfaceScopeSchema$1 = z.enum(eventSurfaceScopeValues);
28658
28656
  const eventScheduleScopeSchema$1 = z.enum(eventScheduleScopeValues);
@@ -28669,6 +28667,7 @@ const eventCollectionFilterSourceSchemaShape = {
28669
28667
  filterVenueId: z.string().nullable().optional()
28670
28668
  };
28671
28669
  const eventCollectionSourceSchemaShape = {
28670
+ calendarWindow: calendarWindowPageSchema.nullable().optional(),
28672
28671
  events: z.array(publicEventSchema).nullable().optional(),
28673
28672
  siteId: z.string(),
28674
28673
  apiBaseUrl: z.string().optional(),
@@ -28722,6 +28721,7 @@ const eventCollectionDisplaySchemaShape = {
28722
28721
  };
28723
28722
  const eventCollectionHydrationSchema = z.object({
28724
28723
  siteId: z.string(),
28724
+ calendarWindow: calendarWindowPageSchema.optional(),
28725
28725
  stage: previewStageSchema.optional(),
28726
28726
  prefetchedEvents: z.boolean(),
28727
28727
  eventSurface: eventSurfaceScopeSchema$1,
@@ -28780,8 +28780,9 @@ function buildEventCollectionPresentationDisplay(source) {
28780
28780
  };
28781
28781
  }
28782
28782
  function buildEventCollectionHydration(source, now = /* @__PURE__ */ new Date()) {
28783
- const timeZone = toBookingTimeZone(source.bookingTimeZone);
28783
+ const timeZone = source.calendarWindow?.scope.timeZone ?? toBookingTimeZone(source.bookingTimeZone);
28784
28784
  return {
28785
+ calendarWindow: source.calendarWindow ?? void 0,
28785
28786
  siteId: source.siteId,
28786
28787
  stage: source.stage,
28787
28788
  prefetchedEvents: source.events != null,
@@ -28790,7 +28791,7 @@ function buildEventCollectionHydration(source, now = /* @__PURE__ */ new Date())
28790
28791
  scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
28791
28792
  calendarContext: {
28792
28793
  timeZone,
28793
- initialToday: getLocalScheduleDate(now, timeZone)
28794
+ initialToday: source.calendarWindow?.initialToday ?? getLocalScheduleDate(now, timeZone)
28794
28795
  }
28795
28796
  };
28796
28797
  }
@@ -29339,7 +29340,7 @@ function buildEventCalendarDisplay(source) {
29339
29340
  listColumns: source.listColumns ?? source.columns
29340
29341
  }),
29341
29342
  kind: "event-calendar",
29342
- displayMode: source.variant ?? source.displayMode ?? "combined",
29343
+ displayMode: normalizeEventCalendarDisplayMode$1(source) ?? "combined",
29343
29344
  className: source.className ?? null,
29344
29345
  events: (source.events ?? []).slice().sort((left, right) => new Date(left.startsAt).getTime() - new Date(right.startsAt).getTime()),
29345
29346
  boardTitle: normalizeOptionalText(source.boardTitle),
@@ -29357,15 +29358,75 @@ const eventCalendarBlockRuntime = defineProgressiveBlockRuntime({
29357
29358
  render: createZodCodec(eventCalendarRenderSchema)
29358
29359
  },
29359
29360
  buildRender: (source) => ({
29360
- display: buildEventCalendarDisplay(source),
29361
+ display: buildEventCalendarDisplay(source.calendarWindow && (source.variant ?? source.displayMode ?? "combined") !== "combined" && (source.variant ?? source.displayMode) !== "list" ? {
29362
+ ...source,
29363
+ events: source.calendarWindow.events
29364
+ } : source),
29361
29365
  hydration: buildEventCollectionHydration(source)
29362
29366
  })
29363
29367
  });
29364
29368
  //#endregion
29369
+ //#region ../blocks/src/system/blocks/events/eventCalendarDataLoaders.ts
29370
+ const scopeParams = {
29371
+ siteId: { $bind: { from: "$root.siteId" } },
29372
+ stage: { $bind: {
29373
+ from: "$root.previewStage",
29374
+ fallback: "published"
29375
+ } },
29376
+ eventSurface: { $bind: { from: "content.eventSurface" } },
29377
+ eventPresets: { $bind: {
29378
+ from: "content.filterEventPresets",
29379
+ transforms: [{ id: "value.csv" }]
29380
+ } },
29381
+ scheduleScope: { $bind: { from: "content.scheduleScope" } },
29382
+ categoryIds: { $bind: { from: "content.filterCategoryIds" } },
29383
+ staffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
29384
+ venueId: { $bind: { from: "content.filterVenueId" } }
29385
+ };
29386
+ /** Combined renders two jobs; calendar-only variants never pay for the list seed. */
29387
+ const eventCalendarDataLoaders = {
29388
+ events: {
29389
+ endpoint: "listPublicEvents",
29390
+ when: { $bind: {
29391
+ from: "content",
29392
+ transforms: [{
29393
+ id: "events.calendarReadEnabled",
29394
+ options: { job: "list" }
29395
+ }]
29396
+ } },
29397
+ params: {
29398
+ ...scopeParams,
29399
+ limit: 100,
29400
+ detailLevel: "listing",
29401
+ readProfile: "listing-card"
29402
+ },
29403
+ mode: "server"
29404
+ },
29405
+ calendarWindow: {
29406
+ endpoint: "listPublicEventCalendarWindow",
29407
+ when: { $bind: {
29408
+ from: "content",
29409
+ transforms: [{
29410
+ id: "events.calendarReadEnabled",
29411
+ options: { job: "calendar" }
29412
+ }]
29413
+ } },
29414
+ params: {
29415
+ ...scopeParams,
29416
+ limit: 100,
29417
+ readProfile: { $bind: {
29418
+ from: "content",
29419
+ transforms: [{ id: "events.calendarReadProfile" }]
29420
+ } }
29421
+ },
29422
+ mode: "server"
29423
+ }
29424
+ };
29425
+ //#endregion
29365
29426
  //#region ../blocks/src/system/blocks/events/event-calendar.ts
29366
29427
  function normalizeEventCalendarContent(content) {
29367
29428
  const record = typeof content === "object" && content !== null ? content : {};
29368
- const variant = normalizeEventCalendarDisplayMode(record.variant) ?? normalizeEventCalendarDisplayMode(record.displayMode);
29429
+ const variant = normalizeEventCalendarDisplayMode$1(record);
29369
29430
  return {
29370
29431
  ...record,
29371
29432
  ...variant ? { variant } : {},
@@ -29413,6 +29474,7 @@ const eventCalendarLayout = [styledSection({
29413
29474
  rootProps: { gap: "lg" },
29414
29475
  children: [...eventSectionHeaderLayoutNodes({ splitClassName: "event-section-head event-section-head--split" }), el("event-calendar", withApiBindings({
29415
29476
  events: { $bind: { from: "data.events" } },
29477
+ calendarWindow: { $bind: { from: "data.calendarWindow" } },
29416
29478
  stage: { $bind: {
29417
29479
  from: "$root.previewStage",
29418
29480
  fallback: "published"
@@ -29901,7 +29963,7 @@ const eventCalendarAdditionalFields = [
29901
29963
  {
29902
29964
  id: "showCapacity",
29903
29965
  type: "boolean",
29904
- label: "Show available spots",
29966
+ label: "Show available places",
29905
29967
  description: "Display remaining capacity on event cards and timetable cells",
29906
29968
  required: false,
29907
29969
  defaultValue: true,
@@ -30236,33 +30298,11 @@ const eventCalendarBlockDefinition = {
30236
30298
  }
30237
30299
  }, eventCalendarContentShape),
30238
30300
  normalizeContent: normalizeEventCalendarContent,
30239
- dataSchemas: { events: publicEventsArraySchema.optional() },
30240
- dataLoaders: { events: {
30241
- endpoint: "listPublicEvents",
30242
- params: {
30243
- siteId: { $bind: { from: "$root.siteId" } },
30244
- limit: 100,
30245
- stage: { $bind: {
30246
- from: "$root.previewStage",
30247
- fallback: "published"
30248
- } },
30249
- detailLevel: "listing",
30250
- readProfile: { $bind: {
30251
- from: "content.variant",
30252
- fallback: "listing-card"
30253
- } },
30254
- eventSurface: { $bind: { from: "content.eventSurface" } },
30255
- eventPresets: { $bind: {
30256
- from: "content.filterEventPresets",
30257
- transforms: [{ id: "value.csv" }]
30258
- } },
30259
- scheduleScope: { $bind: { from: "content.scheduleScope" } },
30260
- categoryIds: { $bind: { from: "content.filterCategoryIds" } },
30261
- staffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
30262
- venueId: { $bind: { from: "content.filterVenueId" } }
30263
- },
30264
- mode: "server"
30265
- } },
30301
+ dataSchemas: {
30302
+ events: publicEventsArraySchema.optional(),
30303
+ calendarWindow: calendarWindowPageSchema.optional()
30304
+ },
30305
+ dataLoaders: eventCalendarDataLoaders,
30266
30306
  runtime: eventCalendarBlockRuntime
30267
30307
  };
30268
30308
  const recurringScheduleWeekdaySchema = z.enum([
@@ -30590,6 +30630,12 @@ function isRecord$2(value) {
30590
30630
  }
30591
30631
  //#endregion
30592
30632
  //#region ../blocks/src/system/blocks/offerings-preview/index.ts
30633
+ /**
30634
+ * The whole-series presets, as the CSV `listPublicEvents` expects. Both
30635
+ * whole-series presets share one loader: the block renders them as a single
30636
+ * run group.
30637
+ */
30638
+ const WHOLE_SERIES_EVENT_PRESETS_PARAM = WHOLE_SERIES_EVENT_PRESET_VALUES.join(",");
30593
30639
  const publicRouteCandidatesSchema = z.object({ routes: z.array(z.object({
30594
30640
  entityId: z.string(),
30595
30641
  path: z.string(),
@@ -30871,7 +30917,7 @@ const offeringsPreviewManifest = createBlockManifest({
30871
30917
  fallback: "published"
30872
30918
  } },
30873
30919
  routeCandidates: { $bind: { from: "data.routeCandidates" } },
30874
- wholeSeriesOfferings: { $bind: { from: "data.wholeSeriesOfferings" } },
30920
+ wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
30875
30921
  ...offeringsPreviewEventDataBindings
30876
30922
  })
30877
30923
  ], { gap: "lg" }),
@@ -30888,7 +30934,7 @@ const offeringsPreviewBlockDefinition = {
30888
30934
  dataSchemas: {
30889
30935
  ...offeringsPreviewEventDataSchemas,
30890
30936
  routeCandidates: publicRouteCandidatesSchema.optional(),
30891
- wholeSeriesOfferings: publicWholeSeriesOfferingsArraySchema.optional()
30937
+ wholeSeriesRunEvents: optionalPublicEventsArraySchema
30892
30938
  },
30893
30939
  dataLoaders: {
30894
30940
  ...offeringsPreviewEventDataLoaders,
@@ -30897,24 +30943,21 @@ const offeringsPreviewBlockDefinition = {
30897
30943
  params: {},
30898
30944
  mode: "server"
30899
30945
  },
30900
- wholeSeriesOfferings: {
30901
- endpoint: "listPublicWholeSeriesOfferings",
30902
- params: {
30903
- siteId: { $bind: { from: "$root.siteId" } },
30904
- limit: { $bind: {
30905
- from: "content.itemLimit",
30906
- fallback: "3"
30907
- } },
30908
- stage: { $bind: {
30909
- from: "$root.previewStage",
30910
- fallback: "published"
30911
- } }
30912
- },
30913
- mode: "server"
30914
- }
30946
+ wholeSeriesRunEvents: wholeSeriesRunLoader()
30915
30947
  }
30916
30948
  };
30917
- function eventPresetLoader(preset) {
30949
+ /**
30950
+ * One row per whole-series run, finished runs included.
30951
+ *
30952
+ * A page of dates cannot answer this: a finished run has no upcoming date, and
30953
+ * a long run would spend the whole page on its own sessions. `readIntent:
30954
+ * 'runs'` asks for runs instead, so `itemLimit` counts run cards rather than
30955
+ * dates, and each card arrives with the run's complete schedule.
30956
+ */
30957
+ function wholeSeriesRunLoader() {
30958
+ return eventPresetLoader(WHOLE_SERIES_EVENT_PRESETS_PARAM, { readIntent: "runs" });
30959
+ }
30960
+ function eventPresetLoader(eventPresets, extraParams = {}) {
30918
30961
  return {
30919
30962
  endpoint: "listPublicEvents",
30920
30963
  params: {
@@ -30929,7 +30972,8 @@ function eventPresetLoader(preset) {
30929
30972
  } },
30930
30973
  detailLevel: "listing",
30931
30974
  readProfile: "listing-card",
30932
- eventPresets: preset
30975
+ eventPresets,
30976
+ ...extraParams
30933
30977
  },
30934
30978
  mode: "server"
30935
30979
  };
@@ -36513,6 +36557,24 @@ const linksTransforms = [{
36513
36557
  //#endregion
36514
36558
  //#region ../blocks/src/system/transforms/registry/index.ts
36515
36559
  const builtinTransformDefinitions = [
36560
+ {
36561
+ id: "events.calendarReadEnabled",
36562
+ kind: "formatter",
36563
+ summary: "Choose the read projection required by the calendar display mode",
36564
+ schema: z.object({ job: z.enum(["list", "calendar"]) }),
36565
+ run(value, options) {
36566
+ const mode = normalizeEventCalendarDisplayMode$1(asPartialObject(value) ?? {}) ?? "combined";
36567
+ return options.job === "calendar" ? mode !== "list" : mode === "list" || mode === "combined";
36568
+ }
36569
+ },
36570
+ {
36571
+ id: "events.calendarReadProfile",
36572
+ kind: "formatter",
36573
+ summary: "Select media enrichment for the calendar display mode",
36574
+ run(value) {
36575
+ return resolveCalendarReadProfile(asPartialObject(value) ?? {});
36576
+ }
36577
+ },
36516
36578
  ...formattingTransforms,
36517
36579
  ...layoutTransforms,
36518
36580
  ...uiTransforms,
@@ -36530,10 +36592,9 @@ const SUPPORTED_LOADER_ENDPOINTS$1 = [
36530
36592
  "listPublishedEntries",
36531
36593
  "getPublishedEntryPreview",
36532
36594
  "listPublicEvents",
36595
+ "listPublicEventCalendarWindow",
36533
36596
  "listPublicRecurringSchedule",
36534
36597
  "getPublicEventDetails",
36535
- "listPublicWholeSeriesOfferings",
36536
- "getPublicWholeSeriesOffering",
36537
36598
  "listPublicRouteCandidates",
36538
36599
  "listPublicTeamMembers",
36539
36600
  "listPublicProducts",
@@ -36949,6 +37010,50 @@ z.object({
36949
37010
  title: z.string(),
36950
37011
  slug: z.string().min(1)
36951
37012
  });
37013
+ z.object({
37014
+ signedUrl: z.string().url(),
37015
+ token: z.string().min(1),
37016
+ storagePath: z.string().min(1)
37017
+ }).strict();
37018
+ const backupManifestSchema = z.object({
37019
+ siteId: z.string().min(1),
37020
+ siteSlug: z.string().min(1),
37021
+ siteTitle: z.string(),
37022
+ exportedAt: z.string().min(1),
37023
+ tableCount: z.number().int().nonnegative(),
37024
+ totalRecords: z.number().int().nonnegative(),
37025
+ pageCount: z.number().int().nonnegative(),
37026
+ blockCount: z.number().int().nonnegative(),
37027
+ contentEntryCount: z.number().int().nonnegative(),
37028
+ formCount: z.number().int().nonnegative(),
37029
+ navigationMenuCount: z.number().int().nonnegative(),
37030
+ mediaCount: z.number().int().nonnegative(),
37031
+ mediaBytes: z.number().int().nonnegative()
37032
+ }).strict();
37033
+ z.object({
37034
+ ok: z.literal(true),
37035
+ manifest: backupManifestSchema,
37036
+ storagePath: z.string().min(1)
37037
+ }).strict();
37038
+ z.object({
37039
+ ok: z.literal(true),
37040
+ siteId: brandedIdSchema(parseSiteId, "site id"),
37041
+ slug: z.string().min(1),
37042
+ title: z.string(),
37043
+ counts: z.record(z.string(), z.object({
37044
+ created: z.number().int().nonnegative(),
37045
+ updated: z.number().int().nonnegative(),
37046
+ skipped: z.number().int().nonnegative(),
37047
+ failed: z.number().int().nonnegative()
37048
+ }).strict()),
37049
+ warnings: z.array(z.string()),
37050
+ errors: z.array(z.object({
37051
+ table: z.string(),
37052
+ id: z.string(),
37053
+ error: z.string()
37054
+ }).strict())
37055
+ }).strict();
37056
+ z.object({ deleted: z.boolean() }).strict();
36952
37057
  const apiKeyIdSchema = brandedIdSchema(parseApiKeyId, "API key id");
36953
37058
  const standardKeyIdsSchema = z.object({
36954
37059
  live: apiKeyIdSchema.optional(),
@@ -37164,6 +37269,9 @@ z.object({
37164
37269
  return resolved.config;
37165
37270
  });
37166
37271
  //#endregion
37272
+ //#region ../api/src/appointmentServiceVisibility.ts
37273
+ const APPOINTMENT_SERVICE_VISIBILITY_VALUES = ["public", "unlisted"];
37274
+ //#endregion
37167
37275
  //#region ../api/src/utils/isRecord.ts
37168
37276
  function isRecord(value) {
37169
37277
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -37215,6 +37323,7 @@ const appointmentSetupServiceDraftSchema = z.object({
37215
37323
  cleanupMinutes: z.number().int().nonnegative().max(APPOINTMENT_SETUP_MAX_MINUTES).default(0),
37216
37324
  priceAmount: z.number().int().nonnegative().nullable(),
37217
37325
  isActive: z.boolean(),
37326
+ visibility: z.enum(APPOINTMENT_SERVICE_VISIBILITY_VALUES).default("public"),
37218
37327
  locationType: z.union([
37219
37328
  z.literal("virtual"),
37220
37329
  z.literal("in_person"),
@@ -38226,7 +38335,7 @@ const dashboardConfigSchema = z.object({
38226
38335
  const titleSourceValueSchema = z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]);
38227
38336
  //#endregion
38228
38337
  //#region src/data/prefetchBlockData.ts
38229
- const SUPPORTED_LOADER_ENDPOINTS = SUPPORTED_LOADER_ENDPOINTS$1.filter((endpoint) => endpoint !== "listPublicWholeSeriesOfferings");
38338
+ const SUPPORTED_LOADER_ENDPOINTS = SUPPORTED_LOADER_ENDPOINTS$1;
38230
38339
  //#endregion
38231
38340
  //#region src/config/validation.ts
38232
38341
  /**