@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
@@ -90,7 +90,6 @@ const TAG_TEMPLATES = {
90
90
  formSubmissionsBySlug: "riverbank:form-submissions:{slug}",
91
91
  publicEvents: "riverbank:site:{siteId}:public-events",
92
92
  publicEventFilters: "riverbank:site:{siteId}:public-event-filters",
93
- publicWholeSeriesOfferings: "riverbank:site:{siteId}:public-whole-series-offerings",
94
93
  publicTeamMembers: "riverbank:site:{siteId}:public-team-members",
95
94
  publicProducts: "riverbank:site:{siteId}:public-products",
96
95
  publicPasses: "riverbank:site:{siteId}:public-passes",
@@ -99,6 +98,7 @@ const TAG_TEMPLATES = {
99
98
  publicShop: "riverbank:site:{siteId}:public-shop",
100
99
  publicCheckout: "riverbank:site:{siteId}:public-checkout",
101
100
  publicBookingServices: "riverbank:site:{siteId}:public-booking-services",
101
+ publicBookingAvailability: "riverbank:site:{siteId}:public-booking-availability",
102
102
  siteNavigation: "riverbank:site:{siteId}:navigation",
103
103
  navigationMenuById: "riverbank:navigation-menu:{menuId}",
104
104
  navigationItemById: "riverbank:navigation-item:{itemId}",
@@ -1225,30 +1225,15 @@ const NEWSLETTER_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1225
1225
  }
1226
1226
  });
1227
1227
  //#endregion
1228
- //#region ../api/src/publicWholeSeriesEndpointDefinitions.ts
1229
- const PUBLIC_WHOLE_SERIES_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1230
- listPublicWholeSeriesOfferings: {
1231
- path: "/public/sites/{siteId}/dated-offerings/whole-series",
1228
+ //#region ../api/src/publicEventEndpointDefinitions.ts
1229
+ const PUBLIC_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1230
+ listPublicEventCalendarWindow: {
1231
+ path: "/public/sites/{siteId}/events/calendar-window",
1232
1232
  method: "GET",
1233
- revalidate: 60,
1234
- tags: [TAG_TEMPLATES.publicWholeSeriesOfferings],
1235
- errors: ["server:internal_error"],
1233
+ revalidate: 0,
1236
1234
  auth: "public",
1237
1235
  responseKind: "json"
1238
1236
  },
1239
- getPublicWholeSeriesOffering: {
1240
- path: "/public/sites/{siteId}/dated-offerings/whole-series/{eventSeriesId}",
1241
- method: "GET",
1242
- revalidate: 60,
1243
- tags: [TAG_TEMPLATES.publicWholeSeriesOfferings],
1244
- errors: ["resource:not_found", "server:internal_error"],
1245
- auth: "public",
1246
- responseKind: "json"
1247
- }
1248
- });
1249
- //#endregion
1250
- //#region ../api/src/publicEventEndpointDefinitions.ts
1251
- const PUBLIC_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1252
1237
  resolvePublicEventCheckoutReturn: {
1253
1238
  path: "/public/sites/{siteId}/events/checkout-return",
1254
1239
  method: "POST",
@@ -1280,6 +1265,99 @@ const PUBLIC_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1280
1265
  }
1281
1266
  });
1282
1267
  //#endregion
1268
+ //#region ../api/src/publicEventCheckoutEndpointDefinitions.ts
1269
+ /**
1270
+ * The public event registration/checkout endpoints, extracted from
1271
+ * `endpoints.ts`.
1272
+ *
1273
+ * They were moved out for the same reason the `sdkMedia*` block was: adding the
1274
+ * `errors` metadata `require-api-endpoint-errors` asks of a newly-added endpoint
1275
+ * pushed `endpoints.ts` past its `max-lines` baseline. The block is spread back
1276
+ * at the exact position it occupied, so `API_ENDPOINTS` key order is unchanged.
1277
+ * (The endpoint that originally motivated the move, `checkPublicEventEligibility`,
1278
+ * was since deleted on dev by #1326.)
1279
+ */
1280
+ const PUBLIC_EVENT_CHECKOUT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1281
+ registerForEvent: {
1282
+ path: "/public/sites/{siteId}/events/register",
1283
+ method: "POST",
1284
+ tags: [TAG_TEMPLATES.publicEvents, "event-registration"],
1285
+ auth: "public",
1286
+ responseKind: "json"
1287
+ },
1288
+ createPublicEventCheckout: {
1289
+ path: "/public/sites/{siteId}/events/checkout",
1290
+ method: "POST",
1291
+ tags: [TAG_TEMPLATES.publicEvents, "event-checkout"],
1292
+ auth: "public",
1293
+ responseKind: "json"
1294
+ }
1295
+ });
1296
+ //#endregion
1297
+ //#region ../api/src/publicBookingAvailabilityEndpointDefinitions.ts
1298
+ /**
1299
+ * Public appointment reads: the service catalogue and the bookable slot grid.
1300
+ *
1301
+ * These are the reads that appointment writes invalidate. They carry canonical
1302
+ * `riverbank:*` tags because the frontend revalidate endpoint discards anything
1303
+ * else, which is why the legacy `site-{siteId}` tag they used to declare could
1304
+ * never actually be cleared (issue 1364).
1305
+ *
1306
+ * Slot availability depends on both tags: the grid moves when a booking lands,
1307
+ * and again when the service definition behind it changes.
1308
+ */
1309
+ const PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1310
+ getPublicBookingServices: {
1311
+ path: "/public/bookings/services",
1312
+ method: "GET",
1313
+ revalidate: 60,
1314
+ tags: [TAG_TEMPLATES.publicBookingServices],
1315
+ auth: "public",
1316
+ responseKind: "json"
1317
+ },
1318
+ getPublicBookingService: {
1319
+ path: "/public/bookings/services/{serviceId}",
1320
+ method: "GET",
1321
+ revalidate: 60,
1322
+ tags: [TAG_TEMPLATES.publicBookingServices],
1323
+ auth: "public",
1324
+ responseKind: "json"
1325
+ },
1326
+ getPublicBookingResourcesReference: {
1327
+ path: "/public/bookings/resources/reference",
1328
+ method: "GET",
1329
+ revalidate: 60,
1330
+ tags: [TAG_TEMPLATES.publicBookingServices],
1331
+ auth: "public",
1332
+ responseKind: "json"
1333
+ },
1334
+ getPublicBookingAvailableDates: {
1335
+ path: "/public/bookings/availability/dates",
1336
+ method: "GET",
1337
+ revalidate: 60,
1338
+ tags: [TAG_TEMPLATES.publicBookingAvailability, TAG_TEMPLATES.publicBookingServices],
1339
+ auth: "public",
1340
+ responseKind: "json"
1341
+ },
1342
+ getPublicBookingAvailableSlots: {
1343
+ path: "/public/bookings/availability/slots",
1344
+ method: "GET",
1345
+ revalidate: 60,
1346
+ tags: [TAG_TEMPLATES.publicBookingAvailability, TAG_TEMPLATES.publicBookingServices],
1347
+ auth: "public",
1348
+ responseKind: "json"
1349
+ },
1350
+ getPublicWeeklySlotAvailability: {
1351
+ path: "/public/bookings/weekly-slot-availability",
1352
+ method: "GET",
1353
+ revalidate: 60,
1354
+ tags: [TAG_TEMPLATES.publicBookingAvailability, TAG_TEMPLATES.publicBookingServices],
1355
+ auth: "public",
1356
+ responseKind: "json",
1357
+ errors: []
1358
+ }
1359
+ });
1360
+ //#endregion
1283
1361
  //#region ../api/src/siteApiKeyEndpointDefinitions.ts
1284
1362
  const SITE_API_KEY_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1285
1363
  listSiteApiKeys: {
@@ -1640,6 +1718,88 @@ const SDK_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1640
1718
  errors: ["validation:invalid_input", "server:internal_error"]
1641
1719
  }
1642
1720
  });
1721
+ //#endregion
1722
+ //#region ../api/src/sdkMediaEndpointDefinitions.ts
1723
+ /** SDK media lookup, listing, deletion and upload endpoints (management-key authenticated). */
1724
+ const SDK_MEDIA_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
1725
+ sdkMediaExists: {
1726
+ path: "/sdk/{siteId}/media/exists",
1727
+ method: "POST",
1728
+ errors: ["validation:invalid_input"],
1729
+ auth: "service",
1730
+ responseKind: "json"
1731
+ },
1732
+ sdkMediaFindByChecksum: {
1733
+ path: "/sdk/{siteId}/media/find-by-checksum",
1734
+ method: "POST",
1735
+ errors: ["server:internal_error"],
1736
+ auth: "service",
1737
+ responseKind: "json"
1738
+ },
1739
+ sdkMediaResolve: {
1740
+ path: "/sdk/{siteId}/media/resolve",
1741
+ method: "POST",
1742
+ errors: ["server:internal_error"],
1743
+ auth: "service",
1744
+ responseKind: "json"
1745
+ },
1746
+ sdkMediaList: {
1747
+ path: "/sdk/{siteId}/media",
1748
+ method: "GET",
1749
+ auth: "service",
1750
+ errors: [],
1751
+ responseKind: "json"
1752
+ },
1753
+ sdkMediaDownload: {
1754
+ path: "/sdk/{siteId}/media/{identifier}/download",
1755
+ method: "GET",
1756
+ auth: "service",
1757
+ errors: [],
1758
+ responseKind: "json"
1759
+ },
1760
+ sdkMediaDeletePreview: {
1761
+ path: "/sdk/{siteId}/media/{identifier}/delete-preview",
1762
+ method: "POST",
1763
+ auth: "service",
1764
+ errors: [],
1765
+ responseKind: "json"
1766
+ },
1767
+ sdkMediaDeleteApply: {
1768
+ path: "/sdk/{siteId}/media/{identifier}",
1769
+ method: "DELETE",
1770
+ auth: "service",
1771
+ errors: [],
1772
+ responseKind: "json"
1773
+ },
1774
+ sdkMediaUploadUrl: {
1775
+ path: "/sdk/{siteId}/media/upload-url",
1776
+ method: "POST",
1777
+ errors: [
1778
+ "resource:not_found",
1779
+ "validation:invalid_input",
1780
+ "resource:conflict",
1781
+ "validation:payload_too_large",
1782
+ "billing:plan_limit_exceeded",
1783
+ "server:internal_error"
1784
+ ],
1785
+ auth: "service",
1786
+ responseKind: "json"
1787
+ },
1788
+ sdkMediaUploadFinalize: {
1789
+ path: "/sdk/{siteId}/media/upload",
1790
+ method: "POST",
1791
+ errors: [
1792
+ "resource:not_found",
1793
+ "validation:invalid_input",
1794
+ "resource:conflict",
1795
+ "validation:payload_too_large",
1796
+ "billing:plan_limit_exceeded",
1797
+ "server:internal_error"
1798
+ ],
1799
+ auth: "service",
1800
+ responseKind: "json"
1801
+ }
1802
+ });
1643
1803
  const API_ENDPOINTS$1 = {
1644
1804
  ...ACCOUNT_ENDPOINT_DEFINITIONS,
1645
1805
  ...PUBLIC_EVENT_ENDPOINT_DEFINITIONS,
@@ -3780,26 +3940,6 @@ const API_ENDPOINTS$1 = {
3780
3940
  auth: "public",
3781
3941
  responseKind: "json"
3782
3942
  },
3783
- createTheme: {
3784
- path: "/ai/chat/create-theme",
3785
- method: "POST",
3786
- revalidate: 60,
3787
- tags: ["theme", "ai-theme"],
3788
- auth: "user",
3789
- responseKind: "json"
3790
- },
3791
- generateThemes: {
3792
- path: "/theme/generate",
3793
- method: "POST",
3794
- errors: [
3795
- "validation:invalid_input",
3796
- "resource:not_found",
3797
- "server:internal_error"
3798
- ],
3799
- tags: ["theme"],
3800
- auth: "user",
3801
- responseKind: "json"
3802
- },
3803
3943
  extractThemeFromInspiration: {
3804
3944
  path: "/theme/extract-from-inspiration",
3805
3945
  method: "POST",
@@ -3973,7 +4113,7 @@ const API_ENDPOINTS$1 = {
3973
4113
  method: "DELETE",
3974
4114
  tags: ["media", "media-{assetId}"],
3975
4115
  auth: "user",
3976
- responseKind: "void"
4116
+ responseKind: "json"
3977
4117
  },
3978
4118
  mediaBulkDelete: {
3979
4119
  path: "/media/bulk-delete",
@@ -4531,55 +4671,7 @@ const API_ENDPOINTS$1 = {
4531
4671
  auth: "public",
4532
4672
  responseKind: "json"
4533
4673
  },
4534
- getPublicBookingServices: {
4535
- path: "/public/bookings/services",
4536
- method: "GET",
4537
- revalidate: 60,
4538
- tags: ["site-{siteId}"],
4539
- auth: "public",
4540
- responseKind: "json"
4541
- },
4542
- getPublicBookingService: {
4543
- path: "/public/bookings/services/{serviceId}",
4544
- method: "GET",
4545
- revalidate: 60,
4546
- tags: ["site-{siteId}"],
4547
- auth: "public",
4548
- responseKind: "json"
4549
- },
4550
- getPublicBookingResourcesReference: {
4551
- path: "/public/bookings/resources/reference",
4552
- method: "GET",
4553
- revalidate: 60,
4554
- tags: ["site-{siteId}"],
4555
- auth: "public",
4556
- responseKind: "json"
4557
- },
4558
- getPublicBookingAvailableDates: {
4559
- path: "/public/bookings/availability/dates",
4560
- method: "GET",
4561
- revalidate: 300,
4562
- tags: ["site-{siteId}"],
4563
- auth: "public",
4564
- responseKind: "json"
4565
- },
4566
- getPublicBookingAvailableSlots: {
4567
- path: "/public/bookings/availability/slots",
4568
- method: "GET",
4569
- revalidate: 60,
4570
- tags: ["site-{siteId}"],
4571
- auth: "public",
4572
- responseKind: "json"
4573
- },
4574
- getPublicWeeklySlotAvailability: {
4575
- path: "/public/bookings/weekly-slot-availability",
4576
- method: "GET",
4577
- revalidate: 60,
4578
- tags: ["site-{siteId}"],
4579
- auth: "public",
4580
- responseKind: "json",
4581
- errors: []
4582
- },
4674
+ ...PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS,
4583
4675
  createPublicBookingAppointment: {
4584
4676
  path: "/public/bookings/appointments",
4585
4677
  method: "POST",
@@ -4869,7 +4961,6 @@ const API_ENDPOINTS$1 = {
4869
4961
  auth: "public",
4870
4962
  responseKind: "json"
4871
4963
  },
4872
- ...PUBLIC_WHOLE_SERIES_ENDPOINT_DEFINITIONS,
4873
4964
  listPublicTeamMembers: {
4874
4965
  path: "/public/sites/{siteId}/team-members",
4875
4966
  method: "GET",
@@ -4882,11 +4973,7 @@ const API_ENDPOINTS$1 = {
4882
4973
  resolveWaitlistClaim: {
4883
4974
  path: "/public/sites/{siteId}/waitlists/claim/resolve",
4884
4975
  method: "POST",
4885
- tags: [
4886
- TAG_TEMPLATES.publicWholeSeriesOfferings,
4887
- TAG_TEMPLATES.publicEvents,
4888
- "waitlist-claims"
4889
- ],
4976
+ tags: [TAG_TEMPLATES.publicEvents, "waitlist-claims"],
4890
4977
  auth: "public",
4891
4978
  responseKind: "json",
4892
4979
  errors: [
@@ -4971,27 +5058,7 @@ const API_ENDPOINTS$1 = {
4971
5058
  responseKind: "json",
4972
5059
  errors: []
4973
5060
  },
4974
- registerForEvent: {
4975
- path: "/public/sites/{siteId}/events/register",
4976
- method: "POST",
4977
- tags: [TAG_TEMPLATES.publicEvents, "event-registration"],
4978
- auth: "public",
4979
- responseKind: "json"
4980
- },
4981
- createPublicEventCheckout: {
4982
- path: "/public/sites/{siteId}/events/checkout",
4983
- method: "POST",
4984
- tags: [TAG_TEMPLATES.publicEvents, "event-checkout"],
4985
- auth: "public",
4986
- responseKind: "json"
4987
- },
4988
- checkPublicEventEligibility: {
4989
- path: "/public/sites/{siteId}/events/check-eligibility",
4990
- method: "POST",
4991
- tags: [TAG_TEMPLATES.publicEvents, "event-eligibility"],
4992
- auth: "public",
4993
- responseKind: "json"
4994
- },
5061
+ ...PUBLIC_EVENT_CHECKOUT_ENDPOINT_DEFINITIONS,
4995
5062
  getPublicEventRegistrationStatus: {
4996
5063
  path: "/public/sites/{siteId}/events/registration-status",
4997
5064
  method: "GET",
@@ -6559,42 +6626,13 @@ const API_ENDPOINTS$1 = {
6559
6626
  auth: "user",
6560
6627
  responseKind: "json"
6561
6628
  },
6629
+ ...SDK_MEDIA_ENDPOINT_DEFINITIONS,
6562
6630
  sdkIdentifiersBackfill: {
6563
6631
  path: "/sdk/{siteId}/identifiers/backfill",
6564
6632
  method: "POST",
6565
6633
  auth: "service",
6566
6634
  responseKind: "json"
6567
6635
  },
6568
- sdkMediaExists: {
6569
- path: "/sdk/{siteId}/media/exists",
6570
- method: "POST",
6571
- auth: "service",
6572
- responseKind: "json"
6573
- },
6574
- sdkMediaFindByChecksum: {
6575
- path: "/sdk/{siteId}/media/find-by-checksum",
6576
- method: "POST",
6577
- auth: "service",
6578
- responseKind: "json"
6579
- },
6580
- sdkMediaResolve: {
6581
- path: "/sdk/{siteId}/media/resolve",
6582
- method: "POST",
6583
- auth: "service",
6584
- responseKind: "json"
6585
- },
6586
- sdkMediaUploadUrl: {
6587
- path: "/sdk/{siteId}/media/upload-url",
6588
- method: "POST",
6589
- auth: "service",
6590
- responseKind: "json"
6591
- },
6592
- sdkMediaUploadFinalize: {
6593
- path: "/sdk/{siteId}/media/upload",
6594
- method: "POST",
6595
- auth: "service",
6596
- responseKind: "json"
6597
- },
6598
6636
  sdkUpdateWorkflowRunStatus: {
6599
6637
  path: "/sdk/{siteId}/workflows/runs/{runId}/status",
6600
6638
  method: "POST",
@@ -7560,20 +7598,20 @@ function isApiError(result) {
7560
7598
  function isApiSuccess(result) {
7561
7599
  return result.success === true;
7562
7600
  }
7563
- function isRecord$16(value) {
7601
+ function isRecord$15(value) {
7564
7602
  return typeof value === "object" && value !== null && !Array.isArray(value);
7565
7603
  }
7566
7604
  function isFieldError(value) {
7567
- return isRecord$16(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
7605
+ return isRecord$15(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
7568
7606
  }
7569
7607
  function fieldErrorsFromUnknown(value) {
7570
7608
  if (!Array.isArray(value)) return null;
7571
7609
  return value.every(isFieldError) ? value : null;
7572
7610
  }
7573
7611
  function extractEnvelopeErrorObject(body) {
7574
- if (!isRecord$16(body)) return null;
7612
+ if (!isRecord$15(body)) return null;
7575
7613
  const error = body.error;
7576
- if (!isRecord$16(error)) return null;
7614
+ if (!isRecord$15(error)) return null;
7577
7615
  if ("success" in body && body.success !== false) return null;
7578
7616
  return error;
7579
7617
  }
@@ -8082,7 +8120,7 @@ var SimpleCache = class {
8082
8120
  * 1. This constant
8083
8121
  * 2. The "version" field in package.json
8084
8122
  */
8085
- const SDK_VERSION = "0.136.0";
8123
+ const SDK_VERSION = "0.138.0";
8086
8124
  //#endregion
8087
8125
  //#region src/client/error.ts
8088
8126
  let _Symbol$for;
@@ -8372,7 +8410,7 @@ const API_ENDPOINTS = Object.freeze({
8372
8410
  path: "/public/bookings/services",
8373
8411
  method: "GET",
8374
8412
  revalidate: 60,
8375
- tags: ["site-{siteId}"],
8413
+ tags: ["riverbank:site:{siteId}:public-booking-services"],
8376
8414
  auth: "public",
8377
8415
  responseKind: "json"
8378
8416
  },
@@ -8380,7 +8418,7 @@ const API_ENDPOINTS = Object.freeze({
8380
8418
  path: "/public/bookings/weekly-slot-availability",
8381
8419
  method: "GET",
8382
8420
  revalidate: 60,
8383
- tags: ["site-{siteId}"],
8421
+ tags: ["riverbank:site:{siteId}:public-booking-availability", "riverbank:site:{siteId}:public-booking-services"],
8384
8422
  auth: "public",
8385
8423
  responseKind: "json"
8386
8424
  },
@@ -13141,6 +13179,11 @@ const gradientConfigSchema = z.object({
13141
13179
  position: z.string().optional(),
13142
13180
  stops: z.array(gradientStopSchema).min(2)
13143
13181
  });
13182
+ const gradientsSchema = z.object({
13183
+ button: z.string().min(1).nullable().optional(),
13184
+ hero: z.string().min(1).nullable().optional(),
13185
+ background: z.string().min(1).nullable().optional()
13186
+ });
13144
13187
  //#endregion
13145
13188
  //#region ../theme-core/src/interactive/baseSchema.ts
13146
13189
  /**
@@ -13894,11 +13937,30 @@ const headerContainerSchema = z.object({
13894
13937
  tint: z.string().nullable().optional(),
13895
13938
  opacity: z.number().min(0).max(1).default(.12)
13896
13939
  }).optional();
13897
- const headerInteractionPaletteSchema = z.enum([
13940
+ //#endregion
13941
+ //#region ../theme-core/src/header/interactionPalette.ts
13942
+ /**
13943
+ * The palettes that fill the nav link with a colour on hover and focus. Each
13944
+ * one names a background/foreground token pair.
13945
+ */
13946
+ const headerInteractionPillPaletteValues = [
13898
13947
  "primary",
13899
13948
  "secondary",
13900
13949
  "accent"
13901
- ]);
13950
+ ];
13951
+ /**
13952
+ * "No pill": the nav link keeps whatever hover treatment its recipe compiled,
13953
+ * and the palette step writes nothing at all (#1318 Phase 4c decision 2).
13954
+ *
13955
+ * It exists because "a colour change on hover, no filled background" was not
13956
+ * expressible in the vocabulary, and it is what
13957
+ * `anna-raven-therapy-and-yoga` and `kirtan-lucy` have rendered since before
13958
+ * the palette existed. Without it those two rows can only be classified as a
13959
+ * conscious visual change.
13960
+ */
13961
+ const headerInteractionQuietPalette = "quiet";
13962
+ const headerInteractionPaletteValues = [...headerInteractionPillPaletteValues, headerInteractionQuietPalette];
13963
+ const headerInteractionPaletteSchema = z.enum(headerInteractionPaletteValues);
13902
13964
  //#endregion
13903
13965
  //#region ../theme-core/src/boxBackgroundSchema.ts
13904
13966
  const boxBackgroundOverlaySchema = z.preprocess(normalizeAuthoringOpacity, z.discriminatedUnion("type", [
@@ -13956,7 +14018,7 @@ const boxBackgroundSchema = z.discriminatedUnion("type", [
13956
14018
  })
13957
14019
  ]);
13958
14020
  function normalizeAuthoringOpacity(value) {
13959
- if (!isRecord$15(value)) return value;
14021
+ if (!isRecord$14(value)) return value;
13960
14022
  return {
13961
14023
  ...value,
13962
14024
  opacity: normalizeOpacity(value.opacity)
@@ -13965,7 +14027,7 @@ function normalizeAuthoringOpacity(value) {
13965
14027
  function normalizeOpacity(value) {
13966
14028
  return typeof value === "number" && value > 1 && value <= 100 ? value / 100 : value;
13967
14029
  }
13968
- function isRecord$15(value) {
14030
+ function isRecord$14(value) {
13969
14031
  return typeof value === "object" && value !== null && !Array.isArray(value);
13970
14032
  }
13971
14033
  //#endregion
@@ -14280,11 +14342,12 @@ const inputStyle = z.object({
14280
14342
  ]),
14281
14343
  label: z.enum(["inside", "above"])
14282
14344
  });
14283
- const headerPositioning = z.enum([
14345
+ const headerPositioningValues = [
14284
14346
  "static",
14285
14347
  "sticky",
14286
14348
  "fixed"
14287
- ]);
14349
+ ];
14350
+ const headerPositioning = z.enum(headerPositioningValues);
14288
14351
  const headerNavStyle = z.enum([
14289
14352
  "minimal",
14290
14353
  "underline",
@@ -14419,7 +14482,7 @@ const headerSchema = z.object({
14419
14482
  variant: headerVariantWithLegacyAliasSchema,
14420
14483
  positioning: headerPositioning,
14421
14484
  shrinkOnScroll: z.boolean(),
14422
- maxWidth: headerMaxWidth,
14485
+ maxWidth: headerMaxWidth.default("container"),
14423
14486
  scrollTreatment: headerScrollTreatmentSchema,
14424
14487
  background: headerBackgroundSchema.default({
14425
14488
  type: "color",
@@ -14618,11 +14681,6 @@ const bodyTextSchema = z.object({ intro: z.object({
14618
14681
  paragraphSize: bodyTextIntroTypographySizeSchema.optional(),
14619
14682
  headingSize: bodyTextIntroTypographySizeSchema.optional()
14620
14683
  }).optional() }).optional();
14621
- const gradientsSchema = z.object({
14622
- button: z.string().min(1).nullable().optional(),
14623
- hero: z.string().min(1).nullable().optional(),
14624
- background: z.string().min(1).nullable().optional()
14625
- });
14626
14684
  /**
14627
14685
  * Testimonial quote-mark treatment, owned by the site style (analogous to the
14628
14686
  * accordion icon). `style` is the coarse selector; the optional fields fine-tune
@@ -14855,22 +14913,59 @@ function formatCurrencyAmount(amountCents, currency, options) {
14855
14913
  }
14856
14914
  }
14857
14915
  //#endregion
14916
+ //#region ../core/src/planner.ts
14917
+ /** Default clock for production callers that do not inject time explicitly. */
14918
+ const systemPlanningClock = { now: () => Date.now() };
14919
+ /** Resolve current time as a Date from an explicit Date, injected clock, or system clock. */
14920
+ function resolvePlanningNowDate(input = {}) {
14921
+ if (input.now !== void 0) return input.now;
14922
+ return new Date((input.clock ?? systemPlanningClock).now());
14923
+ }
14924
+ //#endregion
14858
14925
  //#region ../core/src/event-pricing.ts
14926
+ /** Capacity closes booking, but does not make an otherwise eligible price unknown. */
14927
+ function isPublicEventPricingOptionDisplayable(option) {
14928
+ if (!option.isActive) return false;
14929
+ if (option.availability.kind === "available") return true;
14930
+ const reason = option.availability.reason;
14931
+ switch (reason) {
14932
+ case "sold_out":
14933
+ case "overallCapacityUnavailable": return true;
14934
+ case "inactive":
14935
+ case "not_on_sale_yet":
14936
+ case "sale_ended":
14937
+ case "attendance_mode_unavailable": return false;
14938
+ default: return assertNever$5(reason);
14939
+ }
14940
+ }
14941
+ function publicEventPricingDisplay(pricing) {
14942
+ switch (pricing.kind) {
14943
+ case "free":
14944
+ case "single":
14945
+ case "sliding_scale": return canonicalEventPricingDisplay(pricing);
14946
+ case "tiered": return resolvePricingOptionsPriceDisplay({
14947
+ options: pricing.options.filter(isPublicEventPricingOptionDisplayable),
14948
+ currency: pricing.currency,
14949
+ purpose: "configured"
14950
+ });
14951
+ case "external": return {
14952
+ kind: "external",
14953
+ label: pricing.label
14954
+ };
14955
+ }
14956
+ }
14859
14957
  function publicEventPricingType(pricing) {
14860
14958
  switch (pricing.kind) {
14861
- case "drop_in":
14862
- case "free_registration": return "free";
14863
- case "single_paid":
14864
- case "ticket_types":
14865
- case "sliding_scale":
14866
- case "whole_series": return isFreePublicEventPriceDisplay(pricing.display) ? "free" : "paid";
14959
+ case "free": return "free";
14960
+ case "single":
14961
+ case "tiered":
14962
+ case "sliding_scale": return isFreePublicEventPriceDisplay(publicEventPricingDisplay(pricing)) ? "free" : "paid";
14867
14963
  case "external": return "external";
14868
14964
  }
14869
14965
  }
14870
14966
  function isFreePublicEventPriceDisplay(display) {
14871
14967
  switch (display.kind) {
14872
14968
  case "free": return true;
14873
- case "whole_series": return display.display.kind === "free";
14874
14969
  case "exact":
14875
14970
  case "from":
14876
14971
  case "range":
@@ -14879,22 +14974,126 @@ function isFreePublicEventPriceDisplay(display) {
14879
14974
  case "external": return false;
14880
14975
  }
14881
14976
  }
14977
+ function resolvePricingOptionSaleWindowState(option, now) {
14978
+ if (option.saleStartsAt !== null && option.saleStartsAt !== void 0 && new Date(option.saleStartsAt) > now) return "not_started";
14979
+ if (option.saleEndsAt !== null && option.saleEndsAt !== void 0 && new Date(option.saleEndsAt) < now) return "ended";
14980
+ return "open";
14981
+ }
14982
+ function resolvePricingOptionsPriceDisplay(input) {
14983
+ const now = input.purpose === "available_now" ? resolvePlanningNowDate({
14984
+ now: input.now,
14985
+ clock: input.clock
14986
+ }) : null;
14987
+ const amounts = input.options.filter((option) => option.isActive && (now === null || resolvePricingOptionSaleWindowState(option, now) === "open")).map((option) => option.priceAmount);
14988
+ return amounts.length === 0 ? {
14989
+ kind: "unavailable",
14990
+ currency: input.currency
14991
+ } : amountRangeDisplay(amounts, input.currency);
14992
+ }
14993
+ function amountRangeDisplay(amounts, currency) {
14994
+ const minAmount = Math.min(...amounts);
14995
+ const maxAmount = Math.max(...amounts);
14996
+ if (minAmount === maxAmount) return minAmount === 0 ? {
14997
+ kind: "free",
14998
+ currency
14999
+ } : {
15000
+ kind: "exact",
15001
+ amount: minAmount,
15002
+ currency
15003
+ };
15004
+ if (minAmount === 0) {
15005
+ const paidAmounts = amounts.filter((amount) => amount > 0);
15006
+ return {
15007
+ kind: "mixed",
15008
+ paidFromAmount: Math.min(...paidAmounts),
15009
+ paidToAmount: maxAmount,
15010
+ currency
15011
+ };
15012
+ }
15013
+ return {
15014
+ kind: "range",
15015
+ minAmount,
15016
+ maxAmount,
15017
+ currency
15018
+ };
15019
+ }
15020
+ /** Derives configured price presentation directly from canonical pricing. */
15021
+ function canonicalEventPricingDisplay(pricing) {
15022
+ switch (pricing.kind) {
15023
+ case "free": return {
15024
+ kind: "free",
15025
+ currency: pricing.currency
15026
+ };
15027
+ case "single": return {
15028
+ kind: "exact",
15029
+ amount: pricing.amount,
15030
+ currency: pricing.currency
15031
+ };
15032
+ case "sliding_scale": return pricing.minimum === pricing.maximum ? {
15033
+ kind: "exact",
15034
+ amount: pricing.maximum,
15035
+ currency: pricing.currency
15036
+ } : {
15037
+ kind: "range",
15038
+ minAmount: pricing.minimum,
15039
+ maxAmount: pricing.maximum,
15040
+ currency: pricing.currency
15041
+ };
15042
+ case "tiered": return resolvePricingOptionsPriceDisplay({
15043
+ options: pricing.options,
15044
+ currency: pricing.currency,
15045
+ purpose: "configured"
15046
+ });
15047
+ default: return assertNever$5(pricing);
15048
+ }
15049
+ }
14882
15050
  //#endregion
14883
15051
  //#region ../core/src/event-page-surface-subject.ts
14884
- function createEventSeriesPageSurfaceSubject(eventSeriesId, bookingScope) {
15052
+ function createEventSeriesPageSurfaceSubject(eventSeriesId, bookingScope, eventDestinationMode) {
15053
+ const mode = eventDestinationMode ? { eventDestinationMode } : {};
14885
15054
  return bookingScope === "whole_series" ? {
14886
15055
  kind: "eventSeries",
14887
15056
  eventSeriesId,
14888
15057
  bookingScope,
14889
- isWholeSeriesBooking: true
15058
+ isWholeSeriesBooking: true,
15059
+ ...mode
14890
15060
  } : {
14891
15061
  kind: "eventSeries",
14892
15062
  eventSeriesId,
14893
- bookingScope
15063
+ bookingScope,
15064
+ ...mode
14894
15065
  };
14895
15066
  }
15067
+ function createEventOfferingPageSurfaceSubject(eventOfferingId, input) {
15068
+ const mode = input.eventDestinationMode ? { eventDestinationMode: input.eventDestinationMode } : {};
15069
+ const identity = {
15070
+ kind: "eventOffering",
15071
+ eventOfferingId,
15072
+ catalogueEventSeriesIds: input.catalogueEventSeriesIds
15073
+ };
15074
+ return input.bookingScope === "whole_series" ? {
15075
+ ...identity,
15076
+ bookingScope: input.bookingScope,
15077
+ isWholeSeriesBooking: true,
15078
+ ...mode
15079
+ } : {
15080
+ ...identity,
15081
+ bookingScope: input.bookingScope,
15082
+ ...mode
15083
+ };
15084
+ }
15085
+ /**
15086
+ * Read the destination mode off a wire value.
15087
+ *
15088
+ * Absent or unrecognised reads as absent, which leaves the routed Event record
15089
+ * as the only authority — the behaviour every caller had before the field
15090
+ * existed.
15091
+ */
15092
+ function parseEventPageSurfaceDestinationMode(value) {
15093
+ return value === "cms-managed" || value === "system-managed" ? value : void 0;
15094
+ }
14896
15095
  function parseEventPageSurfaceSubject(value) {
14897
- if (!isRecord$14(value)) return err$1({ kind: "notObject" });
15096
+ if (!isRecord$13(value)) return err$1({ kind: "notObject" });
14898
15097
  switch (value.kind) {
14899
15098
  case "eventSeries": {
14900
15099
  const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
@@ -14906,7 +15105,7 @@ function parseEventPageSurfaceSubject(value) {
14906
15105
  kind: "invalidEventSeriesBookingScope",
14907
15106
  bookingScope: value.bookingScope
14908
15107
  });
14909
- return ok$1(createEventSeriesPageSurfaceSubject(eventSeriesId.value, value.bookingScope));
15108
+ return ok$1(createEventSeriesPageSurfaceSubject(eventSeriesId.value, value.bookingScope, parseEventPageSurfaceDestinationMode(value.eventDestinationMode)));
14910
15109
  }
14911
15110
  case "eventOffering": {
14912
15111
  const eventOfferingId = parseEventOfferingId(value.eventOfferingId);
@@ -14914,24 +15113,22 @@ function parseEventPageSurfaceSubject(value) {
14914
15113
  kind: "invalidEventOfferingId",
14915
15114
  error: eventOfferingId.error
14916
15115
  });
14917
- if (!Array.isArray(value.availableEventSeriesIds)) return err$1({
14918
- kind: "unsupportedSubject",
14919
- subjectKind: value.kind
15116
+ if (!Array.isArray(value.catalogueEventSeriesIds)) return err$1({
15117
+ kind: "invalidEventOfferingCatalogue",
15118
+ catalogue: value.catalogueEventSeriesIds
14920
15119
  });
14921
- const parsedSeriesIds = [];
14922
- for (const valueId of value.availableEventSeriesIds) {
14923
- const eventSeriesId = parseEventSeriesId(valueId);
14924
- if (!eventSeriesId.ok) return err$1({
14925
- kind: "invalidEventSeriesId",
14926
- error: eventSeriesId.error
14927
- });
14928
- parsedSeriesIds.push(eventSeriesId.value);
14929
- }
14930
- return ok$1({
14931
- kind: "eventOffering",
14932
- eventOfferingId: eventOfferingId.value,
14933
- availableEventSeriesIds: parsedSeriesIds
15120
+ if (value.bookingScope !== "single_occurrence" && value.bookingScope !== "whole_series") return err$1({
15121
+ kind: "invalidEventOfferingBookingScope",
15122
+ bookingScope: value.bookingScope
14934
15123
  });
15124
+ const parsedCatalogueIds = parseEventSeriesIdList(value.catalogueEventSeriesIds);
15125
+ if (!parsedCatalogueIds.ok) return parsedCatalogueIds;
15126
+ const eventDestinationMode = parseEventPageSurfaceDestinationMode(value.eventDestinationMode);
15127
+ return ok$1(createEventOfferingPageSurfaceSubject(eventOfferingId.value, {
15128
+ catalogueEventSeriesIds: parsedCatalogueIds.value,
15129
+ bookingScope: value.bookingScope,
15130
+ ...eventDestinationMode ? { eventDestinationMode } : {}
15131
+ }));
14935
15132
  }
14936
15133
  default: return err$1({
14937
15134
  kind: "unsupportedSubject",
@@ -14939,7 +15136,19 @@ function parseEventPageSurfaceSubject(value) {
14939
15136
  });
14940
15137
  }
14941
15138
  }
14942
- function isRecord$14(value) {
15139
+ function parseEventSeriesIdList(values) {
15140
+ const parsed = [];
15141
+ for (const value of values) {
15142
+ const eventSeriesId = parseEventSeriesId(value);
15143
+ if (!eventSeriesId.ok) return err$1({
15144
+ kind: "invalidEventSeriesId",
15145
+ error: eventSeriesId.error
15146
+ });
15147
+ parsed.push(eventSeriesId.value);
15148
+ }
15149
+ return ok$1(parsed);
15150
+ }
15151
+ function isRecord$13(value) {
14943
15152
  return typeof value === "object" && value !== null && !Array.isArray(value);
14944
15153
  }
14945
15154
  //#endregion
@@ -15161,27 +15370,21 @@ function parseManagementKey(raw) {
15161
15370
  if (typeof raw !== "string" || !raw.startsWith("bld_mgmt_sk_") || raw.length === 12) return err$1({ kind: "invalid-management-key" });
15162
15371
  return ok$1(createSecretInternal("management-key", raw));
15163
15372
  }
15164
- //#endregion
15165
- //#region ../core/src/planner.ts
15166
- /** Default clock for production callers that do not inject time explicitly. */
15167
- const systemPlanningClock = { now: () => Date.now() };
15168
- /** Resolve current time as a Date from an explicit Date, injected clock, or system clock. */
15169
- function resolvePlanningNowDate(input = {}) {
15170
- if (input.now !== void 0) return input.now;
15171
- return new Date((input.clock ?? systemPlanningClock).now());
15373
+ function sessionStartMs(session) {
15374
+ return Date.parse(session.startsAt);
15172
15375
  }
15173
15376
  /**
15174
- * Resolve a Date-compatible planner input.
15377
+ * The run's sessions that still count, in schedule order.
15175
15378
  *
15176
- * Precedence: bare Date, `{ now }`, `{ clock }`, then `systemPlanningClock`.
15177
- * Explicit Date inputs are returned by reference, not cloned.
15379
+ * Sessions whose start cannot be read are dropped rather than sorted to an
15380
+ * arbitrary end: an unparseable date is not a date a visitor can attend.
15178
15381
  */
15179
- function resolvePlanningDateInput(input = {}) {
15180
- if (input instanceof Date) return input;
15181
- return resolvePlanningNowDate(input);
15382
+ function orderedLiveRunSessions(sessions) {
15383
+ return sessions.filter((session) => session.status !== "cancelled" && Number.isFinite(sessionStartMs(session))).sort((left, right) => sessionStartMs(left) - sessionStartMs(right));
15182
15384
  }
15183
15385
  //#endregion
15184
15386
  //#region ../core/src/event-series-behaviour.ts
15387
+ const WHOLE_SERIES_EVENT_PRESET_VALUES = ["course", "term"];
15185
15388
  const SURFACE_EVENT_PRESET_VALUES = [
15186
15389
  "class",
15187
15390
  "course",
@@ -15474,7 +15677,7 @@ function resolveSiteVerticalBookingConfig(rawConfig) {
15474
15677
  }
15475
15678
  //#endregion
15476
15679
  //#region ../media-core/src/typeGuards.ts
15477
- function isRecord$13(value) {
15680
+ function isRecord$12(value) {
15478
15681
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
15479
15682
  }
15480
15683
  //#endregion
@@ -15592,8 +15795,8 @@ function walkAndCollectImageAttrs(value, out, location = "") {
15592
15795
  value.forEach((item, index) => walkAndCollectImageAttrs(item, out, `${location}[${index}]`));
15593
15796
  return;
15594
15797
  }
15595
- if (!isRecord$13(value)) return;
15596
- if (value.type === "image" && isRecord$13(value.attrs)) out.push({
15798
+ if (!isRecord$12(value)) return;
15799
+ if (value.type === "image" && isRecord$12(value.attrs)) out.push({
15597
15800
  attrs: value.attrs,
15598
15801
  location: location ? `${location}.attrs` : "attrs"
15599
15802
  });
@@ -17187,7 +17390,7 @@ function isSemanticIconId(value) {
17187
17390
  //#endregion
17188
17391
  //#region ../blocks/src/system/icons/value.ts
17189
17392
  const NO_BLOCK_ICON_VALUE = { kind: "none" };
17190
- function isRecord$12(value) {
17393
+ function isRecord$11(value) {
17191
17394
  return typeof value === "object" && value !== null && !Array.isArray(value);
17192
17395
  }
17193
17396
  function parseBlockIconValue(value) {
@@ -17195,7 +17398,7 @@ function parseBlockIconValue(value) {
17195
17398
  kind: "semantic",
17196
17399
  iconId: value
17197
17400
  };
17198
- if (!isRecord$12(value)) return NO_BLOCK_ICON_VALUE;
17401
+ if (!isRecord$11(value)) return NO_BLOCK_ICON_VALUE;
17199
17402
  switch (value.kind) {
17200
17403
  case "none": return NO_BLOCK_ICON_VALUE;
17201
17404
  case "semantic": return isSemanticIconId(value.iconId) ? {
@@ -17222,7 +17425,7 @@ function parseBlockIconValue(value) {
17222
17425
  /**
17223
17426
  * Strict record guard: excludes null, primitives, and arrays.
17224
17427
  */
17225
- function isRecord$11(value) {
17428
+ function isRecord$10(value) {
17226
17429
  return typeof value === "object" && value !== null && !Array.isArray(value);
17227
17430
  }
17228
17431
  /**
@@ -18238,41 +18441,6 @@ function compileManifestContentContract(manifestOrFields) {
18238
18441
  findNonPortableMediaPaths: (content) => findNonPortableMediaPaths(plans, content)
18239
18442
  }) });
18240
18443
  }
18241
- /** Strictly admits already-persisted content without repairing it. */
18242
- function admitStoredManifestContent(contract, content) {
18243
- const state = contract[compiledManifestContentContract];
18244
- const nonPortablePaths = state.findNonPortableMediaPaths(content);
18245
- if (nonPortablePaths.length > 0) return {
18246
- ok: false,
18247
- error: {
18248
- kind: "non_portable_media",
18249
- paths: nonPortablePaths
18250
- }
18251
- };
18252
- const parsed = state.strictStoredSchema.safeParse(content);
18253
- return parsed.success ? {
18254
- ok: true,
18255
- value: content
18256
- } : {
18257
- ok: false,
18258
- error: zodAdmissionError(parsed.error)
18259
- };
18260
- }
18261
- /**
18262
- * Applies a pure runtime projection to admitted stored content and validates
18263
- * the resulting render shape before granting the renderable proof.
18264
- */
18265
- function deriveRenderableManifestContent(contract, stored, project) {
18266
- const projected = project(stored);
18267
- const parsed = contract[compiledManifestContentContract].renderSchema.safeParse(projected);
18268
- return parsed.success ? {
18269
- ok: true,
18270
- value: projected
18271
- } : {
18272
- ok: false,
18273
- error: zodAdmissionError(parsed.error)
18274
- };
18275
- }
18276
18444
  /**
18277
18445
  * Re-admits renderable content after a transport boundary has erased its
18278
18446
  * compile-time proof. Unlike write admission, this never canonicalizes or
@@ -19272,6 +19440,12 @@ function cardRoleFromLegacyVocabulary(value) {
19272
19440
  */
19273
19441
  const cardRoleWithLegacyAliasSchema = z.preprocess((value) => cardRoleFromLegacyVocabulary(value) ?? value, cardRoleSchema);
19274
19442
  //#endregion
19443
+ //#region ../theme-core/src/site-styles/compilationPlan.ts
19444
+ const defaultHeaderBrandPreferences = {
19445
+ brandDisplay: "auto",
19446
+ logoSize: "auto"
19447
+ };
19448
+ //#endregion
19275
19449
  //#region ../theme-core/src/site-styles/sectionTransitions.ts
19276
19450
  function boundaryRuntimeMetrics(family, size, heightExpression) {
19277
19451
  return {
@@ -21645,6 +21819,12 @@ const overlayLogoAccommodations = [
21645
21819
  inlineMarkWithTitleLogoAccommodation,
21646
21820
  unbackedOverlayLogoAccommodation
21647
21821
  ];
21822
+ const allCuratedLogoAccommodations = [
21823
+ ...inlineClassicLogoAccommodations,
21824
+ ...centeredLogoAccommodations,
21825
+ ...overlayLogoAccommodations
21826
+ ];
21827
+ new Set(allCuratedLogoAccommodations.filter((option) => option.providesBacking === true).map((option) => option.pattern));
21648
21828
  const headerLayoutCatalog = defineExactCatalog()([
21649
21829
  {
21650
21830
  id: asHeaderLayoutId("classic"),
@@ -21794,6 +21974,10 @@ defineLookOptionGroup({
21794
21974
  {
21795
21975
  id: "secondary",
21796
21976
  label: "Secondary"
21977
+ },
21978
+ {
21979
+ id: headerInteractionQuietPalette,
21980
+ label: "Text only"
21797
21981
  }
21798
21982
  ]
21799
21983
  });
@@ -24215,6 +24399,67 @@ const blockDesignFallback = {
24215
24399
  };
24216
24400
  blockDesignFallback.sectionSurface, blockDesignFallback.contentFrame, blockDesignFallback.transitionAfter, blockDesignFallback.sectionHeight, blockDesignFallback.heroLegibility, blockDesignFallback.imageSurfaceTreatment, blockDesignFallback.imageSurfaceMotion, blockDesignFallback.tileTreatment, blockDesignFallback.eventListTreatment, blockDesignFallback.eyebrowTreatment, blockDesignFallback.accordionIconTreatment, blockDesignFallback.composition;
24217
24401
  //#endregion
24402
+ //#region ../theme-core/src/site-styles/siteChromeBackgrounds.ts
24403
+ const siteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceColorTokenNames);
24404
+ const quickSiteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceQuickColorTokenNames);
24405
+ siteChromeBackgroundColorTokens.filter((token) => !quickSiteChromeBackgroundColorTokens.includes(token));
24406
+ function parseSiteChromeBackgroundColorToken(value) {
24407
+ const token = parseBackgroundAppearanceColorToken(value);
24408
+ return token ? token : null;
24409
+ }
24410
+ function toSiteChromeBackgroundColorTokens(tokenNames) {
24411
+ return tokenNames.flatMap((name) => {
24412
+ const token = parseSiteChromeBackgroundColorToken(name);
24413
+ return token ? [token] : [];
24414
+ });
24415
+ }
24416
+ //#endregion
24417
+ //#region ../theme-core/src/site-styles/siteChromeNavPreferences.ts
24418
+ const headerNavTypographyPreferenceValues = [
24419
+ "inherit",
24420
+ "body",
24421
+ "heading"
24422
+ ];
24423
+ const headerNavFontSizePreferenceValues = [
24424
+ "inherit",
24425
+ "sm",
24426
+ "base",
24427
+ "lg",
24428
+ "xl"
24429
+ ];
24430
+ const defaultHeaderNavPreferences = {
24431
+ typography: "inherit",
24432
+ fontSize: "inherit",
24433
+ interactionPalette: "recommended"
24434
+ };
24435
+ //#endregion
24436
+ //#region ../theme-core/src/site-styles/headerBrandPresentation.ts
24437
+ /**
24438
+ * Whether the header wears a brand presentation at all (#1318 Phase 4c).
24439
+ *
24440
+ * `applyHeaderBrandPresentation` is unconditional today: given a logo context
24441
+ * it always writes a `logo` object carrying a resolved display, size and
24442
+ * accommodation. That makes "this header has no brand presentation block" —
24443
+ * which is what several live sites persist, including one whose site *does*
24444
+ * have a logo asset — a state the preference record could not express, so a
24445
+ * recompile would silently give the site a logo treatment it has never
24446
+ * rendered.
24447
+ *
24448
+ * This is the third field in this phase with that shape, after the interaction
24449
+ * palette and the nav text size: the persisted bytes carry intent the reader
24450
+ * cannot say, so the recompile "corrects" it. The fix is the same one — widen
24451
+ * the closed vocabulary with a named member and derive it by baseline
24452
+ * comparison — and it is a *widening*, not a restyle: `'recommended'` is the
24453
+ * default and reproduces today's behaviour exactly, so no row whose bytes carry
24454
+ * a presentation compiles differently for `'plain'` existing.
24455
+ *
24456
+ * `'plain'` is deliberately not "preserve whatever bytes are there". It is a
24457
+ * constructive instruction — *write no presentation block* — so Phase 4e's
24458
+ * compiler, which builds the header from nothing, can produce it.
24459
+ */
24460
+ const headerBrandPresentationValues = ["recommended", "plain"];
24461
+ defaultHeaderBrandPreferences.brandDisplay, defaultHeaderBrandPreferences.logoSize, defaultHeaderNavPreferences.typography, defaultHeaderNavPreferences.fontSize, defaultHeaderNavPreferences.interactionPalette;
24462
+ //#endregion
24218
24463
  //#region ../theme-core/src/site-styles/generatedSchemas.ts
24219
24464
  function uniqueNonEmpty(values) {
24220
24465
  const uniqueValues = [...new Set(values)];
@@ -24283,6 +24528,56 @@ z.object({
24283
24528
  blocks: z.array(generatedPageDesignBlockIntentSchema)
24284
24529
  }).strict();
24285
24530
  //#endregion
24531
+ //#region ../theme-core/src/site-styles/headerPreferencesPersistence.ts
24532
+ const backgroundColorTokenSchema = z.unknown().transform((value, ctx) => {
24533
+ const token = parseSiteChromeBackgroundColorToken(value);
24534
+ if (token === null) {
24535
+ ctx.addIssue({
24536
+ code: "custom",
24537
+ message: "Unknown site chrome background colour token"
24538
+ });
24539
+ return z.NEVER;
24540
+ }
24541
+ return token;
24542
+ });
24543
+ const backgroundOverrideSchema = z.discriminatedUnion("kind", [z.object({ kind: z.literal("default") }).strict(), z.object({
24544
+ kind: z.literal("color"),
24545
+ token: backgroundColorTokenSchema
24546
+ }).strict()]);
24547
+ const logoTextIntentSchema = z.object({
24548
+ mobileMaxWidth: z.enum([
24549
+ "xs",
24550
+ "sm",
24551
+ "md"
24552
+ ]).optional(),
24553
+ mobileWrapLines: z.union([z.literal(1), z.literal(2)]).optional(),
24554
+ hideOnShrink: z.boolean().optional()
24555
+ }).strict();
24556
+ const structureSchema = z.object({
24557
+ positioning: z.union([z.literal("inherit"), z.enum(headerPositioningValues)]),
24558
+ shrinkOnScroll: z.union([z.literal("inherit"), z.boolean()]),
24559
+ logoText: z.union([
24560
+ z.literal("inherit"),
24561
+ z.literal("none"),
24562
+ logoTextIntentSchema
24563
+ ])
24564
+ }).strict();
24565
+ const headerPreferencesShape = {
24566
+ brandPresentation: z.enum(headerBrandPresentationValues),
24567
+ brandDisplay: z.enum(brandDisplayModeValues),
24568
+ logoSize: z.enum(logoSizePolicyValues),
24569
+ navFontRole: z.enum(headerNavTypographyPreferenceValues),
24570
+ navTextSize: z.enum(headerNavFontSizePreferenceValues),
24571
+ interactionPalette: z.union([z.literal("recommended"), z.enum(headerInteractionPaletteValues)]),
24572
+ background: backgroundOverrideSchema,
24573
+ structure: structureSchema
24574
+ };
24575
+ z.object(headerPreferencesShape).strict();
24576
+ z.object(headerPreferencesShape).omit({
24577
+ brandPresentation: true,
24578
+ structure: true
24579
+ }).strict();
24580
+ //#endregion
24286
24581
  //#region ../theme-core/src/site-styles/pageDesignAuthority.ts
24287
24582
  const nonEmptyStringSchema = z.string().min(1);
24288
24583
  const blockContentVersionIdSchema = nonEmptyStringSchema.transform(asBlockContentVersionId);
@@ -24384,21 +24679,6 @@ function collectBlockSequenceIssues(snapshots) {
24384
24679
  return issues;
24385
24680
  }
24386
24681
  //#endregion
24387
- //#region ../theme-core/src/site-styles/siteChromeBackgrounds.ts
24388
- const siteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceColorTokenNames);
24389
- const quickSiteChromeBackgroundColorTokens = toSiteChromeBackgroundColorTokens(backgroundAppearanceQuickColorTokenNames);
24390
- siteChromeBackgroundColorTokens.filter((token) => !quickSiteChromeBackgroundColorTokens.includes(token));
24391
- function parseSiteChromeBackgroundColorToken(value) {
24392
- const token = parseBackgroundAppearanceColorToken(value);
24393
- return token ? token : null;
24394
- }
24395
- function toSiteChromeBackgroundColorTokens(tokenNames) {
24396
- return tokenNames.flatMap((name) => {
24397
- const token = parseSiteChromeBackgroundColorToken(name);
24398
- return token ? [token] : [];
24399
- });
24400
- }
24401
- //#endregion
24402
24682
  //#region ../theme-core/src/site-styles/tokenRecipes.ts
24403
24683
  const themeTokenRecipeOptions = {
24404
24684
  palette: [
@@ -32613,16 +32893,16 @@ const interpolateRichTextTokensOptionsSchema = z.object({ tokens: z.array(suppor
32613
32893
  const richTextTokenPattern = /\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/g;
32614
32894
  function getSiteName(context) {
32615
32895
  const viewModel = context.viewModel;
32616
- if (!isRecord$11(viewModel)) return null;
32896
+ if (!isRecord$10(viewModel)) return null;
32617
32897
  const site = viewModel.site;
32618
- if (isRecord$11(site) && typeof site.title === "string") {
32898
+ if (isRecord$10(site) && typeof site.title === "string") {
32619
32899
  const title = site.title.trim();
32620
32900
  return title.length > 0 ? title : null;
32621
32901
  }
32622
32902
  const root = viewModel.$root;
32623
- if (isRecord$11(root)) {
32903
+ if (isRecord$10(root)) {
32624
32904
  const rootSite = root.site;
32625
- if (isRecord$11(rootSite) && typeof rootSite.title === "string") {
32905
+ if (isRecord$10(rootSite) && typeof rootSite.title === "string") {
32626
32906
  const title = rootSite.title.trim();
32627
32907
  if (title.length > 0) return title;
32628
32908
  }
@@ -32644,7 +32924,7 @@ function replaceTokenText(input, allowedTokens, tokenValues) {
32644
32924
  });
32645
32925
  }
32646
32926
  function visitRichTextNode(node, allowedTokens, tokenValues) {
32647
- if (!isRecord$11(node)) return node;
32927
+ if (!isRecord$10(node)) return node;
32648
32928
  let changed = false;
32649
32929
  const nextNode = { ...node };
32650
32930
  if (nextNode.type === "text" && typeof nextNode.text === "string") {
@@ -32665,7 +32945,7 @@ function visitRichTextNode(node, allowedTokens, tokenValues) {
32665
32945
  return changed ? nextNode : node;
32666
32946
  }
32667
32947
  function interpolateRichTextTokens(value, options, context) {
32668
- if (!isRecord$11(value)) return value;
32948
+ if (!isRecord$10(value)) return value;
32669
32949
  return visitRichTextNode(value, new Set(options.tokens), {
32670
32950
  year: String((/* @__PURE__ */ new Date()).getFullYear()),
32671
32951
  site_name: getSiteName(context)
@@ -35014,251 +35294,6 @@ const bookingRequirementConsentFieldSchema = z.object({
35014
35294
  });
35015
35295
  z.union([blockBookingConsentSchema, bookingRequirementConsentFieldSchema]);
35016
35296
  //#endregion
35017
- //#region ../blocks/src/system/blocks/events/whole-series/pricing.ts
35018
- function isSaleWindowOpen(option, now) {
35019
- if (!option.isActive) return false;
35020
- if (option.saleStartsAt && new Date(option.saleStartsAt) > now) return false;
35021
- if (option.saleEndsAt && new Date(option.saleEndsAt) < now) return false;
35022
- return true;
35023
- }
35024
- function toExactOrFreeDisplay(amount, currency) {
35025
- if (amount <= 0) return {
35026
- kind: "free",
35027
- currency
35028
- };
35029
- return {
35030
- kind: "exact",
35031
- amount,
35032
- currency
35033
- };
35034
- }
35035
- function getSelectableWholeSeriesPricingOptionsForNow(offering, now) {
35036
- if (offering.pricing.pricingStrategy !== "tiered") return [];
35037
- return [...offering.pricing.options].filter((option) => isSaleWindowOpen(option, now)).sort((left, right) => {
35038
- if (left.sortOrder !== right.sortOrder) return left.sortOrder - right.sortOrder;
35039
- if (left.priceAmount !== right.priceAmount) return left.priceAmount - right.priceAmount;
35040
- return left.name.localeCompare(right.name);
35041
- });
35042
- }
35043
- function resolveWholeSeriesPricingState(offering, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
35044
- const selection = normalizePricingSelectionInput(selectedSlidingAmountOrNowInput, nowInput);
35045
- const currency = offering.pricing.currency;
35046
- switch (offering.pricing.pricingStrategy) {
35047
- case "free": return resolveFreePricing(currency);
35048
- case "single": return resolveSinglePricing(offering.pricing.singlePriceAmount ?? 0, currency);
35049
- case "tiered": return resolveTieredPricing(offering, selectedPricingOptionId, selection.nowInput);
35050
- case "sliding_scale": return resolveSlidingScalePricing(offering, selection.selectedSlidingAmount);
35051
- }
35052
- }
35053
- function normalizePricingSelectionInput(selectedSlidingAmountOrNowInput, nowInput) {
35054
- return typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? {
35055
- selectedSlidingAmount: null,
35056
- nowInput: selectedSlidingAmountOrNowInput
35057
- } : {
35058
- selectedSlidingAmount: typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null,
35059
- nowInput
35060
- };
35061
- }
35062
- function resolveFreePricing(currency) {
35063
- return {
35064
- currency,
35065
- display: {
35066
- kind: "free",
35067
- currency
35068
- },
35069
- selectableOptions: [],
35070
- requiresSelection: false,
35071
- selectedOption: null,
35072
- slidingScale: null,
35073
- selectedSlidingAmount: null,
35074
- selectedPriceAmount: 0,
35075
- selectedRequiresPayment: false,
35076
- hasPaidSelection: false,
35077
- hasFreeSelection: true
35078
- };
35079
- }
35080
- function resolveSinglePricing(amount, currency) {
35081
- return {
35082
- currency,
35083
- display: toExactOrFreeDisplay(amount, currency),
35084
- selectableOptions: [],
35085
- requiresSelection: false,
35086
- selectedOption: null,
35087
- slidingScale: null,
35088
- selectedSlidingAmount: null,
35089
- selectedPriceAmount: amount,
35090
- selectedRequiresPayment: amount > 0,
35091
- hasPaidSelection: amount > 0,
35092
- hasFreeSelection: amount <= 0
35093
- };
35094
- }
35095
- function resolveTieredPricing(offering, selectedPricingOptionId, nowInput) {
35096
- const currency = offering.pricing.currency;
35097
- const selectableOptions = getSelectableWholeSeriesPricingOptionsForNow(offering, resolvePlanningDateInput(nowInput));
35098
- const selectedOption = resolveSelectedTier(selectableOptions, selectedPricingOptionId);
35099
- return {
35100
- currency,
35101
- display: resolveTieredDisplay(selectableOptions.reduce((lowest, option) => lowest === null || option.priceAmount < lowest ? option.priceAmount : lowest, null), selectableOptions.length, currency),
35102
- selectableOptions,
35103
- requiresSelection: selectableOptions.length > 1,
35104
- selectedOption,
35105
- slidingScale: null,
35106
- selectedSlidingAmount: null,
35107
- selectedPriceAmount: selectedOption?.priceAmount ?? null,
35108
- selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
35109
- hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
35110
- hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
35111
- };
35112
- }
35113
- function resolveSelectedTier(options, selectedId) {
35114
- return (selectedId ? options.find((option) => option.id === selectedId) : null) ?? (options.length === 1 ? options[0] ?? null : null);
35115
- }
35116
- function resolveTieredDisplay(lowestAmount, optionCount, currency) {
35117
- if (lowestAmount === null) return {
35118
- kind: "unavailable",
35119
- currency
35120
- };
35121
- return optionCount > 1 && lowestAmount > 0 ? {
35122
- kind: "from",
35123
- amount: lowestAmount,
35124
- currency
35125
- } : toExactOrFreeDisplay(lowestAmount, currency);
35126
- }
35127
- function resolveSlidingScalePricing(offering, selectedSlidingAmount) {
35128
- const currency = offering.pricing.currency;
35129
- const minAmount = offering.pricing.slidingMinAmount ?? null;
35130
- const maxAmount = offering.pricing.slidingMaxAmount ?? null;
35131
- if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) return unavailableSlidingScale(currency);
35132
- const selectedAmount = Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
35133
- return {
35134
- currency,
35135
- display: {
35136
- kind: "range",
35137
- minAmount,
35138
- maxAmount,
35139
- currency
35140
- },
35141
- selectableOptions: [],
35142
- requiresSelection: selectedAmount === null,
35143
- selectedOption: null,
35144
- slidingScale: {
35145
- minAmount,
35146
- maxAmount,
35147
- suggestedAmount: offering.pricing.slidingSuggestedAmount ?? null
35148
- },
35149
- selectedSlidingAmount: selectedAmount,
35150
- selectedPriceAmount: selectedAmount,
35151
- selectedRequiresPayment: (selectedAmount ?? 0) > 0,
35152
- hasPaidSelection: maxAmount > 0,
35153
- hasFreeSelection: minAmount === 0
35154
- };
35155
- }
35156
- function unavailableSlidingScale(currency) {
35157
- return {
35158
- currency,
35159
- display: {
35160
- kind: "unavailable",
35161
- currency
35162
- },
35163
- selectableOptions: [],
35164
- requiresSelection: true,
35165
- selectedOption: null,
35166
- slidingScale: null,
35167
- selectedSlidingAmount: null,
35168
- selectedPriceAmount: null,
35169
- selectedRequiresPayment: false,
35170
- hasPaidSelection: false,
35171
- hasFreeSelection: false
35172
- };
35173
- }
35174
- //#endregion
35175
- //#region ../blocks/src/system/blocks/events/whole-series/schemas.ts
35176
- const wholeSeriesVenueSchema = z.object({
35177
- id: z.string(),
35178
- name: z.string(),
35179
- address: z.string().nullable()
35180
- });
35181
- const wholeSeriesSessionSchema = z.object({
35182
- id: z.string(),
35183
- startsAt: z.string(),
35184
- endsAt: z.string(),
35185
- timeZone: z.string(),
35186
- capacityOverride: z.number().nullable().optional(),
35187
- overrides: z.record(z.string(), z.unknown()).nullable().optional()
35188
- });
35189
- const wholeSeriesTeamMemberSummarySchema = z.object({
35190
- id: z.string(),
35191
- name: z.string(),
35192
- roleLabel: z.string().nullable(),
35193
- summary: z.string().nullable(),
35194
- profilePath: z.string().nullable()
35195
- });
35196
- const wholeSeriesPricingOptionSchema = z.object({
35197
- id: z.string(),
35198
- name: z.string(),
35199
- description: z.string().nullable(),
35200
- priceAmount: z.number(),
35201
- isActive: z.boolean(),
35202
- sortOrder: z.number(),
35203
- capacityLimit: z.number().nullable(),
35204
- saleStartsAt: z.string().nullable(),
35205
- saleEndsAt: z.string().nullable(),
35206
- attendanceScope: z.enum([
35207
- "in_person",
35208
- "online",
35209
- "both"
35210
- ]).nullable().optional()
35211
- });
35212
- const wholeSeriesPricingSchema = z.object({
35213
- bookingRequirement: z.enum(["none", "required"]),
35214
- pricingStrategy: z.enum([
35215
- "free",
35216
- "single",
35217
- "tiered",
35218
- "sliding_scale"
35219
- ]),
35220
- currency: z.string(),
35221
- singlePriceAmount: z.number().nullable(),
35222
- slidingMinAmount: z.number().nullable().optional(),
35223
- slidingMaxAmount: z.number().nullable().optional(),
35224
- slidingSuggestedAmount: z.number().nullable().optional(),
35225
- paymentTerms: blockBookingPaymentTermsSchema,
35226
- options: z.array(wholeSeriesPricingOptionSchema)
35227
- });
35228
- const publicWholeSeriesOfferingSchema = z.object({
35229
- eventSeriesId: z.string(),
35230
- eventOfferingId: z.string(),
35231
- title: z.string(),
35232
- slug: z.string(),
35233
- description: z.unknown().nullable(),
35234
- deliveryMode: z.enum([
35235
- "in_person",
35236
- "online",
35237
- "hybrid"
35238
- ]),
35239
- waitlistEnabled: z.boolean(),
35240
- requireGuestDetails: z.boolean(),
35241
- teamMembers: z.array(wholeSeriesTeamMemberSummarySchema).optional(),
35242
- enrollmentOpen: z.boolean(),
35243
- pricing: wholeSeriesPricingSchema,
35244
- currency: z.string(),
35245
- paymentTerms: blockBookingPaymentTermsSchema,
35246
- consent: blockBookingConsentSchema.nullable(),
35247
- enrollmentCapacity: z.number().nullable(),
35248
- acceptsMemberships: z.boolean(),
35249
- status: z.enum([
35250
- "active",
35251
- "draft",
35252
- "cancelled"
35253
- ]),
35254
- sessionsCount: z.number(),
35255
- enrolledCount: z.number(),
35256
- availableSpots: z.number().nullable(),
35257
- sessions: z.array(wholeSeriesSessionSchema),
35258
- venue: wholeSeriesVenueSchema.nullable()
35259
- });
35260
- const publicWholeSeriesOfferingsArraySchema = z.array(publicWholeSeriesOfferingSchema);
35261
- //#endregion
35262
35297
  //#region ../blocks/src/system/blocks/events/shared/schemas.ts
35263
35298
  const eventPresetSchema = z.enum([
35264
35299
  "event",
@@ -35313,77 +35348,14 @@ const eventCategorySchema = z.object({
35313
35348
  name: z.string(),
35314
35349
  color: z.string().nullable()
35315
35350
  });
35316
- z.enum([
35317
- "free",
35318
- "paid",
35319
- "external"
35320
- ]);
35321
35351
  /**
35322
35352
  * Access restriction type for public events
35323
35353
  */
35324
35354
  const accessRestrictionSchema = z.enum(["none", "category"]);
35325
- z.enum(["single", "ticket_types"]);
35326
- const freePriceDisplaySchema = z.object({
35327
- kind: z.literal("free"),
35328
- currency: z.string()
35329
- });
35330
- const exactPriceDisplaySchema = z.object({
35331
- kind: z.literal("exact"),
35332
- amount: z.number(),
35333
- currency: z.string()
35334
- });
35335
- const fromPriceDisplaySchema = z.object({
35336
- kind: z.literal("from"),
35337
- amount: z.number(),
35338
- currency: z.string()
35339
- });
35340
- const unavailablePriceDisplaySchema = z.object({
35341
- kind: z.literal("unavailable"),
35342
- currency: z.string()
35343
- });
35344
- const rangePriceDisplaySchema = z.object({
35345
- kind: z.literal("range"),
35346
- minAmount: z.number(),
35347
- maxAmount: z.number(),
35348
- currency: z.string()
35349
- });
35350
- const mixedPriceDisplaySchema = z.object({
35351
- kind: z.literal("mixed"),
35352
- paidFromAmount: z.number(),
35353
- paidToAmount: z.number(),
35354
- currency: z.string()
35355
- });
35356
- const publicWholeSeriesPriceDisplaySchema = z.discriminatedUnion("kind", [
35357
- freePriceDisplaySchema,
35358
- exactPriceDisplaySchema,
35359
- fromPriceDisplaySchema,
35360
- rangePriceDisplaySchema,
35361
- unavailablePriceDisplaySchema
35362
- ]);
35363
- z.discriminatedUnion("kind", [
35364
- freePriceDisplaySchema,
35365
- exactPriceDisplaySchema,
35366
- fromPriceDisplaySchema,
35367
- rangePriceDisplaySchema,
35368
- mixedPriceDisplaySchema,
35369
- unavailablePriceDisplaySchema,
35370
- z.object({
35371
- kind: z.literal("external"),
35372
- label: z.string()
35373
- }),
35374
- z.object({
35375
- kind: z.literal("whole_series"),
35376
- display: publicWholeSeriesPriceDisplaySchema
35377
- })
35378
- ]);
35379
- const publicEventTicketTypePriceDisplaySchema = z.union([
35380
- freePriceDisplaySchema,
35381
- exactPriceDisplaySchema,
35382
- fromPriceDisplaySchema,
35383
- rangePriceDisplaySchema,
35384
- mixedPriceDisplaySchema,
35385
- unavailablePriceDisplaySchema
35386
- ]);
35355
+ const publicCurrencySchema = z.string().regex(/^[A-Z]{3}$/u);
35356
+ const publicCentsSchema = z.number().int().nonnegative();
35357
+ const publicPositiveCentsSchema = z.number().int().positive();
35358
+ const publicIsoDateTimeSchema = z.string().datetime({ offset: true });
35387
35359
  const publicEventAttendanceModeSchema = z.enum(["in_person", "online"]);
35388
35360
  const publicEventAttendanceModeAvailabilitySchema = z.object({
35389
35361
  mode: publicEventAttendanceModeSchema,
@@ -35392,9 +35364,9 @@ const publicEventAttendanceModeAvailabilitySchema = z.object({
35392
35364
  availableSpots: z.number().nullable(),
35393
35365
  waitlistEnabled: z.boolean()
35394
35366
  });
35395
- const publicEventTicketTypeAvailabilitySchema = z.union([z.object({
35367
+ const publicEventPricingOptionAvailabilitySchema = z.union([z.object({
35396
35368
  kind: z.literal("available"),
35397
- remainingCapacity: z.number().nullable()
35369
+ remainingPlaces: z.number().int().nonnegative().nullable()
35398
35370
  }), z.object({
35399
35371
  kind: z.literal("unavailable"),
35400
35372
  reason: z.enum([
@@ -35402,91 +35374,69 @@ const publicEventTicketTypeAvailabilitySchema = z.union([z.object({
35402
35374
  "not_on_sale_yet",
35403
35375
  "sale_ended",
35404
35376
  "sold_out",
35405
- "event_sold_out"
35377
+ "attendance_mode_unavailable",
35378
+ "overallCapacityUnavailable"
35406
35379
  ]),
35407
- remainingCapacity: z.number().nullable()
35380
+ remainingPlaces: z.number().int().nonnegative().nullable()
35408
35381
  })]);
35409
- const publicEventTicketTypeSchema = z.object({
35410
- id: z.string(),
35411
- siteId: z.string(),
35412
- eventSeriesId: z.string(),
35413
- name: z.string(),
35382
+ const publicEventPricingOptionSchema = z.object({
35383
+ id: z.string().min(1),
35384
+ name: z.string().min(1),
35414
35385
  description: z.string().nullable(),
35415
- priceAmount: z.number(),
35386
+ priceAmount: publicCentsSchema,
35416
35387
  isActive: z.boolean(),
35417
- sortOrder: z.number(),
35418
- capacityMode: z.enum(["limited", "unlimited"]),
35419
- capacityLimit: z.number().nullable(),
35388
+ sortOrder: z.number().int().nonnegative(),
35420
35389
  attendanceScope: z.enum([
35421
35390
  "in_person",
35422
35391
  "online",
35423
35392
  "both"
35424
- ]).optional(),
35425
- saleStartsAt: z.string().nullable(),
35426
- saleEndsAt: z.string().nullable(),
35427
- availability: publicEventTicketTypeAvailabilitySchema,
35428
- createdAt: z.string(),
35429
- updatedAt: z.string()
35393
+ ]),
35394
+ saleStartsAt: publicIsoDateTimeSchema.nullable(),
35395
+ saleEndsAt: publicIsoDateTimeSchema.nullable(),
35396
+ availability: publicEventPricingOptionAvailabilitySchema
35397
+ }).superRefine((option, context) => {
35398
+ if (option.saleStartsAt && option.saleEndsAt && Date.parse(option.saleEndsAt) <= Date.parse(option.saleStartsAt)) context.addIssue({
35399
+ code: "custom",
35400
+ path: ["saleEndsAt"],
35401
+ message: "Sale end must be after sale start"
35402
+ });
35430
35403
  });
35431
35404
  const publicEventPricingSchema = z.discriminatedUnion("kind", [
35432
35405
  z.object({
35433
- kind: z.literal("drop_in"),
35434
- currency: z.string(),
35435
- display: z.object({
35436
- kind: z.literal("free"),
35437
- currency: z.string()
35438
- })
35439
- }),
35440
- z.object({
35441
- kind: z.literal("free_registration"),
35442
- currency: z.string(),
35443
- display: z.object({
35444
- kind: z.literal("free"),
35445
- currency: z.string()
35446
- })
35406
+ kind: z.literal("free"),
35407
+ currency: publicCurrencySchema
35447
35408
  }),
35448
35409
  z.object({
35449
- kind: z.literal("single_paid"),
35450
- amount: z.number(),
35451
- currency: z.string(),
35452
- display: z.object({
35453
- kind: z.literal("exact"),
35454
- amount: z.number(),
35455
- currency: z.string()
35456
- })
35410
+ kind: z.literal("single"),
35411
+ amount: publicPositiveCentsSchema,
35412
+ currency: publicCurrencySchema
35457
35413
  }),
35458
35414
  z.object({
35459
- kind: z.literal("ticket_types"),
35460
- currency: z.string(),
35461
- ticketTypes: z.array(publicEventTicketTypeSchema),
35462
- display: publicEventTicketTypePriceDisplaySchema
35415
+ kind: z.literal("tiered"),
35416
+ currency: publicCurrencySchema,
35417
+ options: z.tuple([publicEventPricingOptionSchema], publicEventPricingOptionSchema)
35463
35418
  }),
35464
35419
  z.object({
35465
35420
  kind: z.literal("sliding_scale"),
35466
- minAmount: z.number(),
35467
- maxAmount: z.number(),
35468
- suggestedAmount: z.number().nullable(),
35469
- currency: z.string(),
35470
- display: z.object({
35471
- kind: z.literal("range"),
35472
- minAmount: z.number(),
35473
- maxAmount: z.number(),
35474
- currency: z.string()
35475
- })
35476
- }),
35477
- z.object({
35478
- kind: z.literal("whole_series"),
35479
- display: z.object({
35480
- kind: z.literal("whole_series"),
35481
- display: publicWholeSeriesPriceDisplaySchema
35482
- })
35421
+ minimum: publicCentsSchema,
35422
+ maximum: publicPositiveCentsSchema,
35423
+ suggested: publicCentsSchema.nullable(),
35424
+ currency: publicCurrencySchema
35425
+ }).superRefine((pricing, context) => {
35426
+ if (pricing.minimum > pricing.maximum) context.addIssue({
35427
+ code: "custom",
35428
+ path: ["minimum"],
35429
+ message: "Minimum must not exceed maximum"
35430
+ });
35431
+ if (pricing.suggested !== null && (pricing.suggested < pricing.minimum || pricing.suggested > pricing.maximum)) context.addIssue({
35432
+ code: "custom",
35433
+ path: ["suggested"],
35434
+ message: "Suggested amount must be within the sliding-scale range"
35435
+ });
35483
35436
  }),
35484
35437
  z.object({
35485
35438
  kind: z.literal("external"),
35486
- display: z.object({
35487
- kind: z.literal("external"),
35488
- label: z.string()
35489
- })
35439
+ label: z.string().min(1)
35490
35440
  })
35491
35441
  ]);
35492
35442
  const publicTeamMemberSummarySchema = z.object({
@@ -35512,11 +35462,30 @@ const publicEventBookingAvailabilitySchema = z.discriminatedUnion("kind", [z.obj
35512
35462
  "enrollment_closed"
35513
35463
  ])
35514
35464
  })]);
35465
+ const publicRunSessionSchema = z.object({
35466
+ occurrenceId: z.string(),
35467
+ startsAt: z.string(),
35468
+ endsAt: z.string(),
35469
+ timeZone: z.string(),
35470
+ status: z.string()
35471
+ });
35472
+ const publicWholeSeriesRunSchema = z.object({
35473
+ eventSeriesId: z.string(),
35474
+ eventOfferingId: z.string(),
35475
+ enrollmentOpen: z.boolean(),
35476
+ visibility: z.enum(["public", "unlisted"]),
35477
+ lifecycle: z.enum([
35478
+ "upcoming",
35479
+ "in_progress",
35480
+ "completed",
35481
+ "cancelled"
35482
+ ]),
35483
+ sessions: z.array(publicRunSessionSchema)
35484
+ });
35515
35485
  /**
35516
- * Zod schema for public event data
35486
+ * Zod schema for the fields shared by both booking scopes.
35517
35487
  */
35518
- const publicEventSchema = z.object({
35519
- bookingScope: z.enum(["single_occurrence", "whole_series"]),
35488
+ const publicEventBaseSchema = z.object({
35520
35489
  eventPreset: eventPresetSchema.optional(),
35521
35490
  eventDestinationMode: eventDestinationModeSchema.optional(),
35522
35491
  scheduleScope: eventScheduleScopeSchema$2.optional(),
@@ -35566,20 +35535,68 @@ const publicEventSchema = z.object({
35566
35535
  accessRestriction: accessRestrictionSchema,
35567
35536
  allowedCategoryIds: z.array(z.string()),
35568
35537
  requireGuestDetails: z.boolean().optional(),
35569
- acceptsPasses: z.boolean().optional(),
35570
- acceptsMemberships: z.boolean().optional(),
35571
- wholeSeries: z.object({
35572
- eventSeriesId: z.string(),
35573
- pricing: wholeSeriesPricingSchema,
35574
- currency: z.string(),
35575
- enrollmentOpen: z.boolean()
35576
- }).nullable().optional()
35538
+ acceptsPasses: z.boolean(),
35539
+ acceptsMemberships: z.boolean()
35577
35540
  });
35578
35541
  /**
35542
+ * Zod schema for public event data.
35543
+ *
35544
+ * The booking scope discriminates: a `whole_series` record without complete
35545
+ * `run` facts is rejected, and a `single_occurrence` record never carries them.
35546
+ */
35547
+ const publicEventSchema = z.union([publicEventBaseSchema.extend({
35548
+ bookingScope: z.literal("single_occurrence"),
35549
+ run: z.undefined().optional()
35550
+ }), publicEventBaseSchema.extend({
35551
+ bookingScope: z.literal("whole_series"),
35552
+ run: publicWholeSeriesRunSchema
35553
+ })]);
35554
+ /**
35579
35555
  * Schema for an array of public events
35580
35556
  */
35581
35557
  const publicEventsArraySchema = z.array(publicEventSchema);
35582
35558
  //#endregion
35559
+ //#region ../blocks/src/system/blocks/events/shared/runGrouping.ts
35560
+ function isWholeSeriesPublicEvent(event) {
35561
+ return event.bookingScope === "whole_series";
35562
+ }
35563
+ /**
35564
+ * Group events into one entry per whole-series run.
35565
+ *
35566
+ * Single-occurrence events are ignored. Run order follows first appearance, so
35567
+ * a caller's sort survives the grouping, and an occurrence that arrives twice
35568
+ * is kept once.
35569
+ */
35570
+ function groupPublicEventsByRun(events) {
35571
+ const occurrencesBySeriesId = /* @__PURE__ */ new Map();
35572
+ const order = [];
35573
+ const seenOccurrenceIds = /* @__PURE__ */ new Set();
35574
+ for (const event of events) {
35575
+ if (!isWholeSeriesPublicEvent(event)) continue;
35576
+ if (seenOccurrenceIds.has(event.occurrenceId)) continue;
35577
+ seenOccurrenceIds.add(event.occurrenceId);
35578
+ const seriesId = event.run.eventSeriesId;
35579
+ const existing = occurrencesBySeriesId.get(seriesId);
35580
+ if (existing) {
35581
+ existing.push(event);
35582
+ continue;
35583
+ }
35584
+ occurrencesBySeriesId.set(seriesId, [event]);
35585
+ order.push(seriesId);
35586
+ }
35587
+ return order.map((eventSeriesId) => {
35588
+ const occurrences = occurrencesBySeriesId.get(eventSeriesId) ?? [];
35589
+ const representative = occurrences[0];
35590
+ if (!representative) throw new Error(`Run ${eventSeriesId} grouped without any occurrence`);
35591
+ return {
35592
+ eventSeriesId,
35593
+ run: representative.run,
35594
+ occurrences,
35595
+ representative
35596
+ };
35597
+ });
35598
+ }
35599
+ //#endregion
35583
35600
  //#region ../blocks/src/system/blocks/events/shared/fields.ts
35584
35601
  /**
35585
35602
  * Shared card styling fields for event blocks
@@ -35629,7 +35646,7 @@ const eventDisplayFields = [
35629
35646
  {
35630
35647
  id: "showCapacity",
35631
35648
  type: "boolean",
35632
- label: "Show available spots",
35649
+ label: "Show available places",
35633
35650
  description: "Display remaining capacity",
35634
35651
  required: false,
35635
35652
  defaultValue: true,
@@ -35860,7 +35877,9 @@ const unsupportedEventRegistrationPageSurfaceSubjectSchema = z.object({
35860
35877
  "unsupportedSubject",
35861
35878
  "invalidEventSeriesId",
35862
35879
  "invalidEventSeriesBookingScope",
35863
- "invalidEventOfferingId"
35880
+ "invalidEventOfferingId",
35881
+ "invalidEventOfferingBookingScope",
35882
+ "invalidEventOfferingCatalogue"
35864
35883
  ])
35865
35884
  });
35866
35885
  const eventRegistrationPageSurfaceSubjectSchema = z.unknown().transform((value, ctx) => {
@@ -35887,7 +35906,7 @@ function resolveEventRegistrationScope(context) {
35887
35906
  if (context.subject?.kind === "eventOffering") return {
35888
35907
  kind: "pageSurfaceOffering",
35889
35908
  offeringId: context.subject.eventOfferingId,
35890
- seriesIds: context.subject.availableEventSeriesIds
35909
+ seriesIds: context.subject.catalogueEventSeriesIds
35891
35910
  };
35892
35911
  if (context.subject?.kind === "unsupported") return {
35893
35912
  kind: "unsupportedPageSurfaceSubject",
@@ -35909,31 +35928,12 @@ function resolveEventRegistrationScopedEvents(events, context) {
35909
35928
  }
35910
35929
  }
35911
35930
  //#endregion
35912
- //#region ../blocks/src/system/runtime/nodes/event-registration/registrationSurface.ts
35913
- function planEventRegistrationScope(input) {
35914
- const subject = input.subject;
35915
- const selectedRunOffering = input.wholeSeriesOffering;
35916
- if (subject?.kind !== "eventOffering" || !selectedRunOffering) return {
35917
- kind: "context",
35918
- events: resolveEventRegistrationScopedEvents(input.events, {
35919
- occurrenceContext: input.occurrenceContext,
35920
- subject
35921
- })
35922
- };
35923
- if (!(selectedRunOffering.eventOfferingId === subject.eventOfferingId && subject.availableEventSeriesIds.some((seriesId) => seriesId === selectedRunOffering.eventSeriesId))) return { kind: "invalidSelectedRun" };
35924
- return {
35925
- kind: "selectedRun",
35926
- events: input.events.filter((event) => event.seriesId === selectedRunOffering.eventSeriesId),
35927
- offering: selectedRunOffering
35928
- };
35929
- }
35930
- //#endregion
35931
- //#region ../blocks/src/system/runtime/nodes/events/shared/destination.ts
35932
- function isRecord$10(value) {
35931
+ //#region ../blocks/src/system/runtime/nodes/events/domain/destination.ts
35932
+ function isRecord$9(value) {
35933
35933
  return typeof value === "object" && value !== null && !Array.isArray(value);
35934
35934
  }
35935
35935
  function isRuntimeEventDestination(value) {
35936
- if (!isRecord$10(value) || typeof value.kind !== "string") return false;
35936
+ if (!isRecord$9(value) || typeof value.kind !== "string") return false;
35937
35937
  if (value.kind === "native") return (value.mode === "cms-managed" || value.mode === "system-managed") && typeof value.path === "string";
35938
35938
  return value.kind === "external" && typeof value.url === "string" && typeof value.label === "string";
35939
35939
  }
@@ -35946,174 +35946,6 @@ function resolveRuntimeEventDestination(event) {
35946
35946
  };
35947
35947
  }
35948
35948
  //#endregion
35949
- //#region ../blocks/src/system/runtime/nodes/events/shared/pricing.ts
35950
- const DEFAULT_EVENT_CURRENCY = "USD";
35951
- function resolveRuntimeEventPricing(event) {
35952
- if (isPublicEventPricing(event.pricing)) return event.pricing;
35953
- if (resolveRuntimeEventDestination(event).kind === "external") return {
35954
- kind: "external",
35955
- display: {
35956
- kind: "external",
35957
- label: "External registration"
35958
- }
35959
- };
35960
- const legacy = event;
35961
- const currency = readCurrency(legacy.currency);
35962
- if (event.requiresRegistration === false) return {
35963
- kind: "drop_in",
35964
- currency,
35965
- display: {
35966
- kind: "free",
35967
- currency
35968
- }
35969
- };
35970
- if (legacy.pricingMode === "ticket_types") return {
35971
- kind: "ticket_types",
35972
- currency,
35973
- ticketTypes: Array.isArray(legacy.ticketTypes) ? legacy.ticketTypes.filter(isPublicEventTicketType) : [],
35974
- display: readTicketTypePriceDisplay(legacy.priceDisplay, currency)
35975
- };
35976
- const amount = typeof legacy.price === "number" ? legacy.price : 0;
35977
- if (legacy.pricingType === "paid" && amount > 0) return {
35978
- kind: "single_paid",
35979
- amount,
35980
- currency,
35981
- display: {
35982
- kind: "exact",
35983
- amount,
35984
- currency
35985
- }
35986
- };
35987
- return {
35988
- kind: "free_registration",
35989
- currency,
35990
- display: {
35991
- kind: "free",
35992
- currency
35993
- }
35994
- };
35995
- }
35996
- function readCurrency(value) {
35997
- return typeof value === "string" && value.trim().length > 0 ? value : DEFAULT_EVENT_CURRENCY;
35998
- }
35999
- function isRecord$9(value) {
36000
- return typeof value === "object" && value !== null && !Array.isArray(value);
36001
- }
36002
- function isPublicEventPricing(value) {
36003
- if (!isRecord$9(value) || typeof value.kind !== "string") return false;
36004
- 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";
36005
- }
36006
- function isPublicEventTicketType(value) {
36007
- return isRecord$9(value) && typeof value.id === "string";
36008
- }
36009
- function readTicketTypePriceDisplay(value, currency) {
36010
- const display = readLegacyPriceDisplay(value, currency);
36011
- return display.kind === "whole_series" || display.kind === "external" ? {
36012
- kind: "unavailable",
36013
- currency
36014
- } : display;
36015
- }
36016
- function readLegacyPriceDisplay(value, currency) {
36017
- if (!isRecord$9(value) || typeof value.kind !== "string") return {
36018
- kind: "unavailable",
36019
- currency
36020
- };
36021
- const displayCurrency = readCurrency(value.currency);
36022
- switch (value.kind) {
36023
- case "free": return {
36024
- kind: "free",
36025
- currency: displayCurrency
36026
- };
36027
- case "exact": return readAmount(value.amount) !== null ? {
36028
- kind: "exact",
36029
- amount: readAmount(value.amount) ?? 0,
36030
- currency: displayCurrency
36031
- } : {
36032
- kind: "unavailable",
36033
- currency
36034
- };
36035
- case "from": return readAmount(value.amount) !== null ? {
36036
- kind: "from",
36037
- amount: readAmount(value.amount) ?? 0,
36038
- currency: displayCurrency
36039
- } : {
36040
- kind: "unavailable",
36041
- currency
36042
- };
36043
- case "range": {
36044
- const minAmount = readAmount(value.minAmount);
36045
- const maxAmount = readAmount(value.maxAmount);
36046
- return minAmount !== null && maxAmount !== null ? {
36047
- kind: "range",
36048
- minAmount,
36049
- maxAmount,
36050
- currency: displayCurrency
36051
- } : {
36052
- kind: "unavailable",
36053
- currency
36054
- };
36055
- }
36056
- case "mixed": return readAmount(value.paidFromAmount) !== null ? {
36057
- kind: "mixed",
36058
- paidFromAmount: readAmount(value.paidFromAmount) ?? 0,
36059
- paidToAmount: readAmount(value.paidToAmount) ?? readAmount(value.paidFromAmount) ?? 0,
36060
- currency: displayCurrency
36061
- } : {
36062
- kind: "unavailable",
36063
- currency
36064
- };
36065
- case "unavailable": return {
36066
- kind: "unavailable",
36067
- currency: displayCurrency
36068
- };
36069
- case "whole_series": return isRecord$9(value.display) ? {
36070
- kind: "whole_series",
36071
- display: readCoursePriceDisplay(value.display, displayCurrency)
36072
- } : {
36073
- kind: "whole_series",
36074
- display: {
36075
- kind: "unavailable",
36076
- currency: displayCurrency
36077
- }
36078
- };
36079
- default: return {
36080
- kind: "unavailable",
36081
- currency
36082
- };
36083
- }
36084
- }
36085
- function readCoursePriceDisplay(value, currency) {
36086
- switch (value.kind) {
36087
- case "free": return {
36088
- kind: "free",
36089
- currency: readCurrency(value.currency)
36090
- };
36091
- case "exact": return readAmount(value.amount) !== null ? {
36092
- kind: "exact",
36093
- amount: readAmount(value.amount) ?? 0,
36094
- currency: readCurrency(value.currency)
36095
- } : {
36096
- kind: "unavailable",
36097
- currency
36098
- };
36099
- case "from": return readAmount(value.amount) !== null ? {
36100
- kind: "from",
36101
- amount: readAmount(value.amount) ?? 0,
36102
- currency: readCurrency(value.currency)
36103
- } : {
36104
- kind: "unavailable",
36105
- currency
36106
- };
36107
- default: return {
36108
- kind: "unavailable",
36109
- currency
36110
- };
36111
- }
36112
- }
36113
- function readAmount(value) {
36114
- return typeof value === "number" && Number.isFinite(value) ? value : null;
36115
- }
36116
- //#endregion
36117
35949
  //#region ../blocks/src/system/constants/events.ts
36118
35950
  const eventCalendarDisplayModeValues = [
36119
35951
  "combined",
@@ -36145,6 +35977,10 @@ const eventCalendarListLayoutOptions = [
36145
35977
  function isEventCalendarDisplayMode(value) {
36146
35978
  return typeof value === "string" && eventCalendarDisplayModeValues.includes(value);
36147
35979
  }
35980
+ function normalizeEventCalendarDisplayMode$1(input) {
35981
+ if (isEventCalendarDisplayMode(input.variant)) return input.variant;
35982
+ return isEventCalendarDisplayMode(input.displayMode) ? input.displayMode : void 0;
35983
+ }
36148
35984
  function isEventCalendarDefaultView(value) {
36149
35985
  return typeof value === "string" && eventCalendarDefaultViewValues.includes(value);
36150
35986
  }
@@ -36214,14 +36050,13 @@ function resolveEventRequiresPayment(input) {
36214
36050
  if (input.eligibility) return input.eligibility.requiresPayment;
36215
36051
  if (input.selectedTicketType) return input.selectedTicketType.priceAmount > 0;
36216
36052
  if (!input.event) return false;
36217
- return publicEventPricingType(resolveRuntimeEventPricing(input.event)) === "paid";
36053
+ return publicEventPricingType(input.event.pricing) === "paid";
36218
36054
  }
36219
36055
  //#endregion
36220
36056
  //#region ../blocks/src/system/runtime/nodes/event-registration/registrationEventAdapter.ts
36221
36057
  function toRegistrationEvent(event) {
36222
36058
  return {
36223
36059
  ...event,
36224
- pricing: resolveRuntimeEventPricing(event),
36225
36060
  selectionId: event.id,
36226
36061
  registrationSubject: {
36227
36062
  kind: "occurrence",
@@ -36232,118 +36067,35 @@ function toRegistrationEvent(event) {
36232
36067
  function toRegistrationEvents(events) {
36233
36068
  return events.filter((event) => event.bookingScope === "single_occurrence").map(toRegistrationEvent);
36234
36069
  }
36235
- function toWholeSeriesTicketType(option) {
36236
- return {
36237
- ...option,
36238
- capacityMode: option.capacityLimit === null ? "unlimited" : "limited",
36239
- attendanceScope: option.attendanceScope ?? void 0,
36240
- availability: {
36241
- kind: "available",
36242
- remainingCapacity: option.capacityLimit
36243
- }
36244
- };
36245
- }
36246
- function toWholeSeriesPricing(offering) {
36247
- const resolved = resolveWholeSeriesPricingState(offering);
36248
- switch (offering.pricing.pricingStrategy) {
36249
- case "free": return {
36250
- kind: "free_registration",
36251
- currency: offering.currency,
36252
- display: {
36253
- kind: "free",
36254
- currency: offering.currency
36255
- }
36256
- };
36257
- case "single": {
36258
- const amount = offering.pricing.singlePriceAmount ?? 0;
36259
- return amount === 0 ? {
36260
- kind: "free_registration",
36261
- currency: offering.currency,
36262
- display: {
36263
- kind: "free",
36264
- currency: offering.currency
36265
- }
36266
- } : {
36267
- kind: "single_paid",
36268
- amount,
36269
- currency: offering.currency,
36270
- display: {
36271
- kind: "exact",
36272
- amount,
36273
- currency: offering.currency
36274
- }
36275
- };
36276
- }
36277
- case "tiered": return {
36278
- kind: "ticket_types",
36279
- currency: offering.currency,
36280
- ticketTypes: resolved.selectableOptions.map((option) => toWholeSeriesTicketType(option)),
36281
- display: resolved.display
36282
- };
36283
- case "sliding_scale": return {
36284
- kind: "sliding_scale",
36285
- minAmount: offering.pricing.slidingMinAmount ?? 0,
36286
- maxAmount: offering.pricing.slidingMaxAmount ?? 0,
36287
- suggestedAmount: offering.pricing.slidingSuggestedAmount ?? null,
36288
- currency: offering.currency,
36289
- display: {
36290
- kind: "range",
36291
- minAmount: offering.pricing.slidingMinAmount ?? 0,
36292
- maxAmount: offering.pricing.slidingMaxAmount ?? 0,
36293
- currency: offering.currency
36294
- }
36295
- };
36296
- }
36297
- }
36298
- function toAttendanceModes(offering) {
36299
- return (offering.deliveryMode === "hybrid" ? ["in_person", "online"] : [offering.deliveryMode]).map((mode) => ({
36300
- mode,
36301
- capacity: offering.enrollmentCapacity,
36302
- registeredCount: offering.enrolledCount,
36303
- availableSpots: offering.availableSpots,
36304
- waitlistEnabled: offering.waitlistEnabled
36305
- }));
36306
- }
36307
- function toWholeSeriesRegistrationEvent(offering) {
36308
- const firstSession = offering.sessions[0];
36309
- const lastSession = offering.sessions[offering.sessions.length - 1];
36070
+ /**
36071
+ * Project one whole-series run onto the registration surface.
36072
+ *
36073
+ * Capacity, pricing, payment terms and consent come straight off the canonical
36074
+ * Event record; only the schedule is widened from the single occurrence to the
36075
+ * live run. A run without live sessions has no registration event.
36076
+ */
36077
+ function toWholeSeriesRegistrationEvent(group) {
36078
+ const { representative, run } = group;
36079
+ const sessions = orderedLiveRunSessions(run.sessions);
36080
+ const firstSession = sessions[0];
36081
+ if (!firstSession) return null;
36082
+ const lastSession = sessions[sessions.length - 1] ?? firstSession;
36310
36083
  return {
36311
- selectionId: offering.eventSeriesId,
36084
+ ...representative,
36085
+ selectionId: run.eventSeriesId,
36312
36086
  registrationSubject: {
36313
36087
  kind: "wholeSeries",
36314
- eventSeriesId: offering.eventSeriesId,
36315
- sessions: offering.sessions
36316
- },
36317
- seriesId: offering.eventSeriesId,
36318
- title: offering.title,
36319
- startsAt: firstSession?.startsAt ?? "",
36320
- endsAt: lastSession?.endsAt ?? firstSession?.endsAt ?? "",
36321
- bookingAvailability: offering.enrollmentOpen ? { kind: "open" } : {
36322
- kind: "closed",
36323
- reason: "enrollment_closed"
36324
- },
36325
- deliveryMode: offering.deliveryMode,
36326
- attendanceModes: toAttendanceModes(offering),
36327
- capacity: offering.enrollmentCapacity,
36328
- registeredCount: offering.enrolledCount,
36329
- availableSpots: offering.availableSpots,
36330
- waitlistEnabled: offering.waitlistEnabled,
36331
- venue: offering.venue ? {
36332
- ...offering.venue,
36333
- location: null
36334
- } : null,
36335
- eventCategory: null,
36336
- teamMembers: offering.teamMembers,
36337
- status: offering.status,
36338
- timeZone: firstSession?.timeZone ?? "UTC",
36339
- pricing: toWholeSeriesPricing(offering),
36340
- paymentTerms: offering.paymentTerms,
36341
- consent: offering.consent,
36342
- requireGuestDetails: offering.requireGuestDetails,
36343
- acceptsPasses: false,
36344
- acceptsMemberships: offering.acceptsMemberships
36088
+ eventSeriesId: run.eventSeriesId,
36089
+ sessions
36090
+ },
36091
+ startsAt: firstSession.startsAt,
36092
+ endsAt: lastSession.endsAt,
36093
+ timeZone: firstSession.timeZone
36345
36094
  };
36346
36095
  }
36096
+ function toWholeSeriesRegistrationEvents(events) {
36097
+ return groupPublicEventsByRun(events).map(toWholeSeriesRegistrationEvent).filter((event) => event !== null);
36098
+ }
36347
36099
  //#endregion
36348
36100
  //#region ../blocks/src/system/runtime/nodes/event-registration.interactive.ts
36349
36101
  const EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS = [
@@ -36363,8 +36115,7 @@ const eventRegistrationHydrationSchemaShape = {
36363
36115
  occurrenceContext: occurrenceContextSchema.optional(),
36364
36116
  subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
36365
36117
  events: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
36366
- wholeSeriesOfferings: publicWholeSeriesOfferingsArraySchema.nullable().optional(),
36367
- wholeSeriesOffering: publicWholeSeriesOfferingSchema.nullable().optional(),
36118
+ wholeSeriesRunEvents: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
36368
36119
  maxTickets: z.string().optional(),
36369
36120
  showVenue: z.boolean().optional(),
36370
36121
  showCapacity: z.boolean().optional(),
@@ -36382,7 +36133,6 @@ const eventRegistrationSourceSchema = z.object({
36382
36133
  portalToken: z.string().nullable().optional(),
36383
36134
  previewToken: z.string().nullable().optional(),
36384
36135
  ...eventRegistrationHydrationSchemaShape,
36385
- subjectWholeSeriesOffering: publicWholeSeriesOfferingSchema.nullable().optional(),
36386
36136
  className: z.string().nullable().optional(),
36387
36137
  buttonText: z.string().nullable().optional(),
36388
36138
  maxTickets: z.string().nullable().optional(),
@@ -36416,7 +36166,8 @@ z.object({
36416
36166
  stage: previewStageSchema.optional()
36417
36167
  });
36418
36168
  function buildEventRegistrationDisplay(source) {
36419
- if (resolveWholeSeriesOffering(source)?.enrollmentOpen === false) return {
36169
+ const selectedRun = resolveSelectedWholeSeriesRun(source);
36170
+ if (selectedRun && (!selectedRun.run.enrollmentOpen || toWholeSeriesRegistrationEvent(selectedRun) === null)) return {
36420
36171
  kind: "event-registration",
36421
36172
  state: "registration-closed",
36422
36173
  className: source.className ?? null,
@@ -36434,13 +36185,11 @@ function buildEventRegistrationDisplay(source) {
36434
36185
  summaryButtonText: source.buttonText?.trim() || "Register"
36435
36186
  };
36436
36187
  }
36437
- function resolveWholeSeriesOffering(source) {
36438
- return source.wholeSeriesOffering ?? source.subjectWholeSeriesOffering ?? null;
36439
- }
36440
36188
  function buildEventRegistrationShellStepLabels(source) {
36441
- const selectedOffering = resolveWholeSeriesOffering(source);
36442
- if (selectedOffering) {
36443
- const selectedEvent = toWholeSeriesRegistrationEvent(selectedOffering);
36189
+ const selectedRun = resolveSelectedWholeSeriesRun(source);
36190
+ if (selectedRun) {
36191
+ const selectedEvent = toWholeSeriesRegistrationEvent(selectedRun);
36192
+ if (!selectedEvent) return EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS;
36444
36193
  return getWizardStepsForContext(true, resolveEventRequiresPayment({
36445
36194
  eligibility: null,
36446
36195
  selectedTicketType: null,
@@ -36461,16 +36210,31 @@ function buildEventRegistrationShellStepLabels(source) {
36461
36210
  }) : false).map((step) => shellLabelForRegistrationStep(step, scopedEvents));
36462
36211
  }
36463
36212
  function scopeEventRegistrationEvents(source) {
36464
- return toRegistrationEvents(scopeEventRegistrationSourceEvents(source));
36213
+ const scoped = scopeEventRegistrationSourceEvents(source);
36214
+ return [...toRegistrationEvents(scoped), ...toWholeSeriesRegistrationEvents(scoped)];
36465
36215
  }
36216
+ /**
36217
+ * Every event this surface may register for, from both of its loads.
36218
+ *
36219
+ * The date page and the run read answer different questions and can name the
36220
+ * same occurrence, so the two lists are joined and any occurrence that arrives
36221
+ * twice is kept once, in the order the date page gave it.
36222
+ */
36466
36223
  function scopeEventRegistrationSourceEvents(source) {
36467
- const scope = planEventRegistrationScope({
36468
- events: source.events ?? [],
36469
- wholeSeriesOffering: source.wholeSeriesOffering,
36224
+ const byOccurrenceId = /* @__PURE__ */ new Map();
36225
+ for (const event of [...source.events ?? [], ...source.wholeSeriesRunEvents ?? []]) if (!byOccurrenceId.has(event.occurrenceId)) byOccurrenceId.set(event.occurrenceId, event);
36226
+ return resolveEventRegistrationScopedEvents([...byOccurrenceId.values()], {
36470
36227
  occurrenceContext: source.occurrenceContext,
36471
36228
  subject: source.subject
36472
36229
  });
36473
- return scope.kind === "invalidSelectedRun" ? [] : [...scope.events];
36230
+ }
36231
+ /**
36232
+ * The one run this surface is registering for, when the scoped events describe
36233
+ * exactly one. More than one run means the visitor still has to choose.
36234
+ */
36235
+ function resolveSelectedWholeSeriesRun(source) {
36236
+ const runs = groupPublicEventsByRun(scopeEventRegistrationSourceEvents(source));
36237
+ return runs.length === 1 ? runs[0] : null;
36474
36238
  }
36475
36239
  function shellLabelForRegistrationStep(step, events) {
36476
36240
  switch (step) {
@@ -36510,8 +36274,6 @@ const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
36510
36274
  occurrenceContext: source.occurrenceContext ?? null,
36511
36275
  subject: source.subject ?? null,
36512
36276
  events,
36513
- wholeSeriesOfferings: source.wholeSeriesOfferings ?? null,
36514
- wholeSeriesOffering: resolveWholeSeriesOffering(source),
36515
36277
  maxTickets: source.maxTickets ?? void 0,
36516
36278
  showVenue: source.showVenue,
36517
36279
  showCapacity: source.showCapacity,
@@ -36530,8 +36292,7 @@ function normalizeEventRegistrationEventInput(value) {
36530
36292
  if (!isRecord$8(value)) return value;
36531
36293
  return {
36532
36294
  ...value,
36533
- destination: resolveRuntimeEventDestination(value),
36534
- pricing: resolveRuntimeEventPricing(value)
36295
+ destination: resolveRuntimeEventDestination(value)
36535
36296
  };
36536
36297
  }
36537
36298
  function isRecord$8(value) {
@@ -36626,7 +36387,7 @@ const eventRegistrationBlockDefinition = {
36626
36387
  {
36627
36388
  id: "showCapacity",
36628
36389
  type: "boolean",
36629
- label: "Show available spots",
36390
+ label: "Show available places",
36630
36391
  description: "Display remaining capacity",
36631
36392
  required: false,
36632
36393
  defaultValue: true,
@@ -36687,9 +36448,7 @@ const eventRegistrationBlockDefinition = {
36687
36448
  fallback: false
36688
36449
  } },
36689
36450
  events: { $bind: { from: "data.events" } },
36690
- wholeSeriesOffering: { $bind: { from: "data.selectedRunOffering.offering" } },
36691
- subjectWholeSeriesOffering: { $bind: { from: "data.subjectWholeSeriesOffering.offering" } },
36692
- wholeSeriesOfferings: { $bind: { from: "data.wholeSeriesOfferings" } },
36451
+ wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
36693
36452
  sitePasses: { $bind: { from: "data.sitePasses" } },
36694
36453
  siteMemberships: { $bind: { from: "data.siteMemberships" } },
36695
36454
  stage: { $bind: {
@@ -36703,9 +36462,7 @@ const eventRegistrationBlockDefinition = {
36703
36462
  runtime: eventRegistrationBlockRuntime,
36704
36463
  dataSchemas: {
36705
36464
  events: publicEventsArraySchema.optional(),
36706
- selectedRunOffering: z.object({ offering: publicWholeSeriesOfferingSchema }).optional(),
36707
- subjectWholeSeriesOffering: z.object({ offering: publicWholeSeriesOfferingSchema }).optional(),
36708
- wholeSeriesOfferings: z.array(publicWholeSeriesOfferingSchema).optional(),
36465
+ wholeSeriesRunEvents: publicEventsArraySchema.optional(),
36709
36466
  sitePasses: publicPassProductCollectionSchema.optional(),
36710
36467
  siteMemberships: publicMembershipProductCollectionSchema.optional(),
36711
36468
  occurrenceContext: occurrenceContextSchema.optional()
@@ -36723,7 +36480,7 @@ const eventRegistrationBlockDefinition = {
36723
36480
  readProfile: "registration",
36724
36481
  seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
36725
36482
  seriesIds: { $bind: {
36726
- from: "$root.subject.availableEventSeriesIds",
36483
+ from: "$root.subject.catalogueEventSeriesIds",
36727
36484
  transforms: [{ id: "value.csv" }]
36728
36485
  } },
36729
36486
  runSeriesId: { $bind: { from: "$root.entrySubrouteContext.run.seriesId" } },
@@ -36731,50 +36488,39 @@ const eventRegistrationBlockDefinition = {
36731
36488
  },
36732
36489
  mode: "server"
36733
36490
  },
36734
- selectedRunOffering: {
36735
- endpoint: "getPublicWholeSeriesOffering",
36736
- params: {
36737
- siteId: { $bind: { from: "$root.siteId" } },
36738
- eventSeriesId: { $bind: { from: "$root.entrySubrouteContext.run.seriesId" } },
36739
- stage: { $bind: {
36740
- from: "$root.previewStage",
36741
- fallback: "published"
36742
- } }
36743
- },
36744
- requiredParams: ["eventSeriesId"],
36745
- mode: "server"
36746
- },
36747
- subjectWholeSeriesOffering: {
36748
- endpoint: "getPublicWholeSeriesOffering",
36491
+ /**
36492
+ * The runs this page can register for, finished ones included.
36493
+ *
36494
+ * The `events` page above is date-bounded, so a run whose first session has
36495
+ * passed contributes no rows to it and the surface would have nothing to
36496
+ * render as closed. This asks for runs instead, and only on a page whose
36497
+ * subject books whole runs. It is scoped exactly like the date page — same
36498
+ * series, same run subroute — because scope and grain are separate
36499
+ * questions. The two lists are joined by occurrence, so a run that appears
36500
+ * in both is still one run.
36501
+ */
36502
+ wholeSeriesRunEvents: {
36503
+ endpoint: "listPublicEvents",
36749
36504
  when: { $bind: {
36750
36505
  from: "$root.subject.isWholeSeriesBooking",
36751
36506
  fallback: false
36752
36507
  } },
36753
36508
  params: {
36754
36509
  siteId: { $bind: { from: "$root.siteId" } },
36755
- eventSeriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
36510
+ readIntent: "runs",
36511
+ limit: "50",
36756
36512
  stage: { $bind: {
36757
36513
  from: "$root.previewStage",
36758
36514
  fallback: "published"
36759
- } }
36760
- },
36761
- requiredParams: ["eventSeriesId"],
36762
- mode: "server"
36763
- },
36764
- wholeSeriesOfferings: {
36765
- endpoint: "listPublicWholeSeriesOfferings",
36766
- params: {
36767
- siteId: { $bind: { from: "$root.siteId" } },
36768
- eventSeriesIds: { $bind: {
36769
- from: "$root.subject.availableEventSeriesIds",
36515
+ } },
36516
+ readProfile: "registration",
36517
+ seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
36518
+ seriesIds: { $bind: {
36519
+ from: "$root.subject.catalogueEventSeriesIds",
36770
36520
  transforms: [{ id: "value.csv" }]
36771
36521
  } },
36772
- stage: { $bind: {
36773
- from: "$root.previewStage",
36774
- fallback: "published"
36775
- } }
36522
+ runSeriesId: { $bind: { from: "$root.entrySubrouteContext.run.seriesId" } }
36776
36523
  },
36777
- requiredParams: ["eventSeriesIds"],
36778
36524
  mode: "server"
36779
36525
  },
36780
36526
  sitePasses: {
@@ -37027,7 +36773,7 @@ const eventDetailsBlockDefinition = {
37027
36773
  readProfile: "details",
37028
36774
  seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
37029
36775
  seriesIds: { $bind: {
37030
- from: "$root.subject.availableEventSeriesIds",
36776
+ from: "$root.subject.catalogueEventSeriesIds",
37031
36777
  transforms: [{ id: "value.csv" }]
37032
36778
  } },
37033
36779
  runSeriesId: { $bind: { from: "$root.entrySubrouteContext.run.seriesId" } },
@@ -37187,7 +36933,11 @@ const eventSpotlightBlockDefinition = {
37187
36933
  } }
37188
36934
  };
37189
36935
  //#endregion
37190
- //#region ../blocks/src/system/runtime/nodes/events/shared/utils.ts
36936
+ //#region ../blocks/src/system/runtime/nodes/events/shared/listingLayout.ts
36937
+ /**
36938
+ * Layout classes for event listing containers and cards. Presentation
36939
+ * plumbing rather than event domain logic, so it lives beside the components.
36940
+ */
37191
36941
  /**
37192
36942
  * Column class mappings for grid layouts, derived from the canonical
37193
36943
  * responsive column ladder (see gridUserColumnLadder).
@@ -37271,6 +37021,97 @@ function resolveEventListPaginationAction(input) {
37271
37021
  };
37272
37022
  }
37273
37023
  //#endregion
37024
+ //#region ../blocks/src/system/blocks/events/shared/calendarWindow.ts
37025
+ function resolveCalendarReadProfile(content) {
37026
+ const mode = normalizeEventCalendarDisplayMode$1(content);
37027
+ return mode === "timetable" || mode === "week-board" ? "timetable" : "listing-card";
37028
+ }
37029
+ /** Runtime picker sentinels and bound loader IDs must describe the same query. */
37030
+ function normalizeCalendarFilterId(value) {
37031
+ const id = value?.trim();
37032
+ return !id || id === "all" ? void 0 : id;
37033
+ }
37034
+ const calendarMonthSchema = z.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/).refine((month) => Number(month.slice(0, 4)) > 0, "Invalid calendar year");
37035
+ function calendarMonthDate(month) {
37036
+ return {
37037
+ year: Number(month.slice(0, 4)),
37038
+ month: Number(month.slice(5, 7)),
37039
+ day: 1
37040
+ };
37041
+ }
37042
+ const monthNumber = (month) => {
37043
+ const date = calendarMonthDate(month);
37044
+ return date.year * 12 + date.month - 1;
37045
+ };
37046
+ const calendarMonthWindowSchema = z.object({
37047
+ startMonth: calendarMonthSchema,
37048
+ endMonthExclusive: calendarMonthSchema
37049
+ }).refine((window) => {
37050
+ const width = monthNumber(window.endMonthExclusive) - monthNumber(window.startMonth);
37051
+ return width > 0 && width <= 3;
37052
+ }, "Calendar windows must cover one to three months");
37053
+ const calendarWindowQuerySchema = z.object({
37054
+ startMonth: calendarMonthSchema.optional(),
37055
+ endMonthExclusive: calendarMonthSchema.optional(),
37056
+ afterStartsAt: z.string().datetime({ offset: true }).optional(),
37057
+ afterId: z.string().uuid().optional(),
37058
+ limit: z.coerce.number().int().min(1).max(200).default(100),
37059
+ stage: z.enum(["published", "preview"]).default("published"),
37060
+ readProfile: z.enum(["listing-card", "timetable"]).optional(),
37061
+ eventSurface: z.enum(eventSurfaceScopeValues).optional(),
37062
+ eventPresets: z.string().optional(),
37063
+ scheduleScope: z.enum(eventScheduleScopeValues).optional(),
37064
+ categoryIds: z.string().optional(),
37065
+ venueId: z.string().transform(normalizeCalendarFilterId).optional(),
37066
+ staffMemberId: z.string().transform(normalizeCalendarFilterId).optional()
37067
+ }).superRefine((query, ctx) => {
37068
+ if (Boolean(query.startMonth) !== Boolean(query.endMonthExclusive)) ctx.addIssue({
37069
+ code: "custom",
37070
+ message: "Both month bounds are required"
37071
+ });
37072
+ if (query.startMonth && query.endMonthExclusive && !calendarMonthWindowSchema.safeParse(query).success) ctx.addIssue({
37073
+ code: "custom",
37074
+ message: "Invalid calendar window"
37075
+ });
37076
+ if (Boolean(query.afterStartsAt) !== Boolean(query.afterId)) ctx.addIssue({
37077
+ code: "custom",
37078
+ message: "Both cursor fields are required"
37079
+ });
37080
+ if (query.afterStartsAt && !query.startMonth) ctx.addIssue({
37081
+ code: "custom",
37082
+ message: "A continuation requires explicit month bounds"
37083
+ });
37084
+ });
37085
+ const calendarSourceCursorSchema = z.object({
37086
+ startsAt: z.string().datetime({ offset: true }),
37087
+ occurrenceId: z.string().uuid()
37088
+ });
37089
+ z.discriminatedUnion("kind", [z.object({ kind: z.literal("complete") }), z.object({
37090
+ kind: z.literal("partial"),
37091
+ nextCursor: calendarSourceCursorSchema
37092
+ })]);
37093
+ const pageFields = {
37094
+ scope: z.object({
37095
+ key: z.string(),
37096
+ timeZone: z.string().transform(toBookingTimeZone)
37097
+ }),
37098
+ window: calendarMonthWindowSchema,
37099
+ initialToday: z.object({
37100
+ year: z.number().int(),
37101
+ month: z.number().int().min(1).max(12),
37102
+ day: z.number().int().min(1).max(31)
37103
+ }),
37104
+ events: z.array(publicEventSchema)
37105
+ };
37106
+ const calendarWindowPageSchema = z.discriminatedUnion("kind", [z.object({
37107
+ ...pageFields,
37108
+ kind: z.literal("complete")
37109
+ }), z.object({
37110
+ ...pageFields,
37111
+ kind: z.literal("partial"),
37112
+ nextCursor: calendarSourceCursorSchema
37113
+ })]);
37114
+ //#endregion
37274
37115
  //#region ../blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.ts
37275
37116
  const eventSurfaceScopeSchema$1 = z.enum(eventSurfaceScopeValues);
37276
37117
  const eventScheduleScopeSchema$1 = z.enum(eventScheduleScopeValues);
@@ -37287,6 +37128,7 @@ const eventCollectionFilterSourceSchemaShape = {
37287
37128
  filterVenueId: z.string().nullable().optional()
37288
37129
  };
37289
37130
  const eventCollectionSourceSchemaShape = {
37131
+ calendarWindow: calendarWindowPageSchema.nullable().optional(),
37290
37132
  events: z.array(publicEventSchema).nullable().optional(),
37291
37133
  siteId: z.string(),
37292
37134
  apiBaseUrl: z.string().optional(),
@@ -37340,6 +37182,7 @@ const eventCollectionDisplaySchemaShape = {
37340
37182
  };
37341
37183
  const eventCollectionHydrationSchema = z.object({
37342
37184
  siteId: z.string(),
37185
+ calendarWindow: calendarWindowPageSchema.optional(),
37343
37186
  stage: previewStageSchema.optional(),
37344
37187
  prefetchedEvents: z.boolean(),
37345
37188
  eventSurface: eventSurfaceScopeSchema$1,
@@ -37398,8 +37241,9 @@ function buildEventCollectionPresentationDisplay(source) {
37398
37241
  };
37399
37242
  }
37400
37243
  function buildEventCollectionHydration(source, now = /* @__PURE__ */ new Date()) {
37401
- const timeZone = toBookingTimeZone(source.bookingTimeZone);
37244
+ const timeZone = source.calendarWindow?.scope.timeZone ?? toBookingTimeZone(source.bookingTimeZone);
37402
37245
  return {
37246
+ calendarWindow: source.calendarWindow ?? void 0,
37403
37247
  siteId: source.siteId,
37404
37248
  stage: source.stage,
37405
37249
  prefetchedEvents: source.events != null,
@@ -37408,7 +37252,7 @@ function buildEventCollectionHydration(source, now = /* @__PURE__ */ new Date())
37408
37252
  scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
37409
37253
  calendarContext: {
37410
37254
  timeZone,
37411
- initialToday: getLocalScheduleDate(now, timeZone)
37255
+ initialToday: source.calendarWindow?.initialToday ?? getLocalScheduleDate(now, timeZone)
37412
37256
  }
37413
37257
  };
37414
37258
  }
@@ -37957,7 +37801,7 @@ function buildEventCalendarDisplay(source) {
37957
37801
  listColumns: source.listColumns ?? source.columns
37958
37802
  }),
37959
37803
  kind: "event-calendar",
37960
- displayMode: source.variant ?? source.displayMode ?? "combined",
37804
+ displayMode: normalizeEventCalendarDisplayMode$1(source) ?? "combined",
37961
37805
  className: source.className ?? null,
37962
37806
  events: (source.events ?? []).slice().sort((left, right) => new Date(left.startsAt).getTime() - new Date(right.startsAt).getTime()),
37963
37807
  boardTitle: normalizeOptionalText(source.boardTitle),
@@ -37975,15 +37819,75 @@ const eventCalendarBlockRuntime = defineProgressiveBlockRuntime({
37975
37819
  render: createZodCodec(eventCalendarRenderSchema)
37976
37820
  },
37977
37821
  buildRender: (source) => ({
37978
- display: buildEventCalendarDisplay(source),
37822
+ display: buildEventCalendarDisplay(source.calendarWindow && (source.variant ?? source.displayMode ?? "combined") !== "combined" && (source.variant ?? source.displayMode) !== "list" ? {
37823
+ ...source,
37824
+ events: source.calendarWindow.events
37825
+ } : source),
37979
37826
  hydration: buildEventCollectionHydration(source)
37980
37827
  })
37981
37828
  });
37982
37829
  //#endregion
37830
+ //#region ../blocks/src/system/blocks/events/eventCalendarDataLoaders.ts
37831
+ const scopeParams = {
37832
+ siteId: { $bind: { from: "$root.siteId" } },
37833
+ stage: { $bind: {
37834
+ from: "$root.previewStage",
37835
+ fallback: "published"
37836
+ } },
37837
+ eventSurface: { $bind: { from: "content.eventSurface" } },
37838
+ eventPresets: { $bind: {
37839
+ from: "content.filterEventPresets",
37840
+ transforms: [{ id: "value.csv" }]
37841
+ } },
37842
+ scheduleScope: { $bind: { from: "content.scheduleScope" } },
37843
+ categoryIds: { $bind: { from: "content.filterCategoryIds" } },
37844
+ staffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
37845
+ venueId: { $bind: { from: "content.filterVenueId" } }
37846
+ };
37847
+ /** Combined renders two jobs; calendar-only variants never pay for the list seed. */
37848
+ const eventCalendarDataLoaders = {
37849
+ events: {
37850
+ endpoint: "listPublicEvents",
37851
+ when: { $bind: {
37852
+ from: "content",
37853
+ transforms: [{
37854
+ id: "events.calendarReadEnabled",
37855
+ options: { job: "list" }
37856
+ }]
37857
+ } },
37858
+ params: {
37859
+ ...scopeParams,
37860
+ limit: 100,
37861
+ detailLevel: "listing",
37862
+ readProfile: "listing-card"
37863
+ },
37864
+ mode: "server"
37865
+ },
37866
+ calendarWindow: {
37867
+ endpoint: "listPublicEventCalendarWindow",
37868
+ when: { $bind: {
37869
+ from: "content",
37870
+ transforms: [{
37871
+ id: "events.calendarReadEnabled",
37872
+ options: { job: "calendar" }
37873
+ }]
37874
+ } },
37875
+ params: {
37876
+ ...scopeParams,
37877
+ limit: 100,
37878
+ readProfile: { $bind: {
37879
+ from: "content",
37880
+ transforms: [{ id: "events.calendarReadProfile" }]
37881
+ } }
37882
+ },
37883
+ mode: "server"
37884
+ }
37885
+ };
37886
+ //#endregion
37983
37887
  //#region ../blocks/src/system/blocks/events/event-calendar.ts
37984
37888
  function normalizeEventCalendarContent(content) {
37985
37889
  const record = typeof content === "object" && content !== null ? content : {};
37986
- const variant = normalizeEventCalendarDisplayMode(record.variant) ?? normalizeEventCalendarDisplayMode(record.displayMode);
37890
+ const variant = normalizeEventCalendarDisplayMode$1(record);
37987
37891
  return {
37988
37892
  ...record,
37989
37893
  ...variant ? { variant } : {},
@@ -38031,6 +37935,7 @@ const eventCalendarLayout = [styledSection({
38031
37935
  rootProps: { gap: "lg" },
38032
37936
  children: [...eventSectionHeaderLayoutNodes({ splitClassName: "event-section-head event-section-head--split" }), el("event-calendar", withApiBindings({
38033
37937
  events: { $bind: { from: "data.events" } },
37938
+ calendarWindow: { $bind: { from: "data.calendarWindow" } },
38034
37939
  stage: { $bind: {
38035
37940
  from: "$root.previewStage",
38036
37941
  fallback: "published"
@@ -38519,7 +38424,7 @@ const eventCalendarAdditionalFields = [
38519
38424
  {
38520
38425
  id: "showCapacity",
38521
38426
  type: "boolean",
38522
- label: "Show available spots",
38427
+ label: "Show available places",
38523
38428
  description: "Display remaining capacity on event cards and timetable cells",
38524
38429
  required: false,
38525
38430
  defaultValue: true,
@@ -38854,33 +38759,11 @@ const eventCalendarBlockDefinition = {
38854
38759
  }
38855
38760
  }, eventCalendarContentShape),
38856
38761
  normalizeContent: normalizeEventCalendarContent,
38857
- dataSchemas: { events: publicEventsArraySchema.optional() },
38858
- dataLoaders: { events: {
38859
- endpoint: "listPublicEvents",
38860
- params: {
38861
- siteId: { $bind: { from: "$root.siteId" } },
38862
- limit: 100,
38863
- stage: { $bind: {
38864
- from: "$root.previewStage",
38865
- fallback: "published"
38866
- } },
38867
- detailLevel: "listing",
38868
- readProfile: { $bind: {
38869
- from: "content.variant",
38870
- fallback: "listing-card"
38871
- } },
38872
- eventSurface: { $bind: { from: "content.eventSurface" } },
38873
- eventPresets: { $bind: {
38874
- from: "content.filterEventPresets",
38875
- transforms: [{ id: "value.csv" }]
38876
- } },
38877
- scheduleScope: { $bind: { from: "content.scheduleScope" } },
38878
- categoryIds: { $bind: { from: "content.filterCategoryIds" } },
38879
- staffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
38880
- venueId: { $bind: { from: "content.filterVenueId" } }
38881
- },
38882
- mode: "server"
38883
- } },
38762
+ dataSchemas: {
38763
+ events: publicEventsArraySchema.optional(),
38764
+ calendarWindow: calendarWindowPageSchema.optional()
38765
+ },
38766
+ dataLoaders: eventCalendarDataLoaders,
38884
38767
  runtime: eventCalendarBlockRuntime
38885
38768
  };
38886
38769
  //#endregion
@@ -39432,6 +39315,12 @@ function isRecord$7(value) {
39432
39315
  }
39433
39316
  //#endregion
39434
39317
  //#region ../blocks/src/system/blocks/offerings-preview/index.ts
39318
+ /**
39319
+ * The whole-series presets, as the CSV `listPublicEvents` expects. Both
39320
+ * whole-series presets share one loader: the block renders them as a single
39321
+ * run group.
39322
+ */
39323
+ const WHOLE_SERIES_EVENT_PRESETS_PARAM = WHOLE_SERIES_EVENT_PRESET_VALUES.join(",");
39435
39324
  const publicRouteCandidatesSchema = z.object({ routes: z.array(z.object({
39436
39325
  entityId: z.string(),
39437
39326
  path: z.string(),
@@ -39713,7 +39602,7 @@ const offeringsPreviewManifest = createBlockManifest({
39713
39602
  fallback: "published"
39714
39603
  } },
39715
39604
  routeCandidates: { $bind: { from: "data.routeCandidates" } },
39716
- wholeSeriesOfferings: { $bind: { from: "data.wholeSeriesOfferings" } },
39605
+ wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
39717
39606
  ...offeringsPreviewEventDataBindings
39718
39607
  })
39719
39608
  ], { gap: "lg" }),
@@ -39730,7 +39619,7 @@ const offeringsPreviewBlockDefinition = {
39730
39619
  dataSchemas: {
39731
39620
  ...offeringsPreviewEventDataSchemas,
39732
39621
  routeCandidates: publicRouteCandidatesSchema.optional(),
39733
- wholeSeriesOfferings: publicWholeSeriesOfferingsArraySchema.optional()
39622
+ wholeSeriesRunEvents: optionalPublicEventsArraySchema
39734
39623
  },
39735
39624
  dataLoaders: {
39736
39625
  ...offeringsPreviewEventDataLoaders,
@@ -39739,24 +39628,21 @@ const offeringsPreviewBlockDefinition = {
39739
39628
  params: {},
39740
39629
  mode: "server"
39741
39630
  },
39742
- wholeSeriesOfferings: {
39743
- endpoint: "listPublicWholeSeriesOfferings",
39744
- params: {
39745
- siteId: { $bind: { from: "$root.siteId" } },
39746
- limit: { $bind: {
39747
- from: "content.itemLimit",
39748
- fallback: "3"
39749
- } },
39750
- stage: { $bind: {
39751
- from: "$root.previewStage",
39752
- fallback: "published"
39753
- } }
39754
- },
39755
- mode: "server"
39756
- }
39631
+ wholeSeriesRunEvents: wholeSeriesRunLoader()
39757
39632
  }
39758
39633
  };
39759
- function eventPresetLoader(preset) {
39634
+ /**
39635
+ * One row per whole-series run, finished runs included.
39636
+ *
39637
+ * A page of dates cannot answer this: a finished run has no upcoming date, and
39638
+ * a long run would spend the whole page on its own sessions. `readIntent:
39639
+ * 'runs'` asks for runs instead, so `itemLimit` counts run cards rather than
39640
+ * dates, and each card arrives with the run's complete schedule.
39641
+ */
39642
+ function wholeSeriesRunLoader() {
39643
+ return eventPresetLoader(WHOLE_SERIES_EVENT_PRESETS_PARAM, { readIntent: "runs" });
39644
+ }
39645
+ function eventPresetLoader(eventPresets, extraParams = {}) {
39760
39646
  return {
39761
39647
  endpoint: "listPublicEvents",
39762
39648
  params: {
@@ -39771,7 +39657,8 @@ function eventPresetLoader(preset) {
39771
39657
  } },
39772
39658
  detailLevel: "listing",
39773
39659
  readProfile: "listing-card",
39774
- eventPresets: preset
39660
+ eventPresets,
39661
+ ...extraParams
39775
39662
  },
39776
39663
  mode: "server"
39777
39664
  };
@@ -45373,6 +45260,24 @@ const linksTransforms = [{
45373
45260
  }
45374
45261
  }];
45375
45262
  const defaultTransforms = createTransformRegistry([
45263
+ {
45264
+ id: "events.calendarReadEnabled",
45265
+ kind: "formatter",
45266
+ summary: "Choose the read projection required by the calendar display mode",
45267
+ schema: z.object({ job: z.enum(["list", "calendar"]) }),
45268
+ run(value, options) {
45269
+ const mode = normalizeEventCalendarDisplayMode$1(asPartialObject(value) ?? {}) ?? "combined";
45270
+ return options.job === "calendar" ? mode !== "list" : mode === "list" || mode === "combined";
45271
+ }
45272
+ },
45273
+ {
45274
+ id: "events.calendarReadProfile",
45275
+ kind: "formatter",
45276
+ summary: "Select media enrichment for the calendar display mode",
45277
+ run(value) {
45278
+ return resolveCalendarReadProfile(asPartialObject(value) ?? {});
45279
+ }
45280
+ },
45376
45281
  ...formattingTransforms,
45377
45282
  ...layoutTransforms,
45378
45283
  ...uiTransforms,
@@ -45829,10 +45734,9 @@ const SUPPORTED_LOADER_ENDPOINTS$1 = [
45829
45734
  "listPublishedEntries",
45830
45735
  "getPublishedEntryPreview",
45831
45736
  "listPublicEvents",
45737
+ "listPublicEventCalendarWindow",
45832
45738
  "listPublicRecurringSchedule",
45833
45739
  "getPublicEventDetails",
45834
- "listPublicWholeSeriesOfferings",
45835
- "getPublicWholeSeriesOffering",
45836
45740
  "listPublicRouteCandidates",
45837
45741
  "listPublicTeamMembers",
45838
45742
  "listPublicProducts",
@@ -45854,6 +45758,10 @@ function isSupportedLoaderEndpoint$1(endpoint) {
45854
45758
  * live here must not be placed in a process-local or durable stale cache.
45855
45759
  */
45856
45760
  const PUBLIC_LOADER_CACHE_POLICIES = {
45761
+ listPublicEventCalendarWindow: {
45762
+ kind: "live",
45763
+ reason: "booking_correctness"
45764
+ },
45857
45765
  listPublishedEntries: {
45858
45766
  kind: "tagged",
45859
45767
  tags: ["published_content"]
@@ -45874,14 +45782,6 @@ const PUBLIC_LOADER_CACHE_POLICIES = {
45874
45782
  kind: "live",
45875
45783
  reason: "booking_correctness"
45876
45784
  },
45877
- listPublicWholeSeriesOfferings: {
45878
- kind: "tagged",
45879
- tags: ["public_whole_series_offerings"]
45880
- },
45881
- getPublicWholeSeriesOffering: {
45882
- kind: "tagged",
45883
- tags: ["public_whole_series_offerings"]
45884
- },
45885
45785
  listPublicRouteCandidates: {
45886
45786
  kind: "tagged",
45887
45787
  tags: ["published_content"]
@@ -45957,7 +45857,7 @@ function normalizeLoaderParams(endpoint, params, context) {
45957
45857
  ensureSiteId(out, context);
45958
45858
  return out;
45959
45859
  }
45960
- if (endpoint === "listPublicEvents" || endpoint === "listPublicRecurringSchedule") {
45860
+ if (endpoint === "listPublicEvents" || endpoint === "listPublicRecurringSchedule" || endpoint === "listPublicEventCalendarWindow") {
45961
45861
  ensureSiteId(out, context);
45962
45862
  return out;
45963
45863
  }
@@ -46350,27 +46250,19 @@ function createContentReadOperations(input) {
46350
46250
  };
46351
46251
  }
46352
46252
  //#endregion
46353
- //#region src/client/wholeSeriesReadOperations.ts
46354
- function createWholeSeriesReadOperations(deps) {
46355
- return { async getPublicWholeSeriesOffering(params) {
46356
- const { siteId, eventSeriesId, stage, signal } = params;
46357
- if (!siteId) throw new Error("getPublicWholeSeriesOffering() requires siteId");
46358
- if (!eventSeriesId) throw new Error("getPublicWholeSeriesOffering() requires eventSeriesId");
46359
- const cacheKey = `public-whole-series-offering:${siteId}:${eventSeriesId}:${stage ?? ""}`;
46360
- return deps.resilientFetchData(cacheKey, (requestSignal) => deps.apiClient({
46361
- endpoint: "getPublicWholeSeriesOffering",
46362
- params: {
46363
- siteId,
46364
- eventSeriesId,
46365
- ...stage && { stage }
46366
- },
46367
- options: { signal: requestSignal }
46368
- }), { signal });
46369
- } };
46253
+ //#region src/client/publicLoaderCacheAccess.ts
46254
+ function shouldWrite(cacheEnabled, force) {
46255
+ return cacheEnabled && !force;
46256
+ }
46257
+ function liveLoaderOptions(endpoint, signal) {
46258
+ return {
46259
+ force: getPublicLoaderCachePolicy(endpoint).kind === "live",
46260
+ signal
46261
+ };
46370
46262
  }
46371
46263
  //#endregion
46372
- //#region src/client/eventSubrouteReadOperations.ts
46373
- function createEventSubrouteReadOperations(deps) {
46264
+ //#region src/client/publicEventReadOperations.ts
46265
+ function createPublicEventReadOperations(deps) {
46374
46266
  async function resolveEventSubroute(params, kind) {
46375
46267
  const { siteId, subject, segment, signal } = params;
46376
46268
  if (!siteId || !segment) throw new Error(`${kind === "event-run" ? "resolveEventRun" : "resolveEventOccurrence"}() requires siteId, subject, and segment`);
@@ -46388,6 +46280,16 @@ function createEventSubrouteReadOperations(deps) {
46388
46280
  }), { signal });
46389
46281
  }
46390
46282
  return {
46283
+ async listPublicEventCalendarWindow({ signal, ...params }) {
46284
+ return deps.resilientFetchData(`public-calendar-window:${JSON.stringify(params)}`, (requestSignal) => deps.apiClient({
46285
+ endpoint: "listPublicEventCalendarWindow",
46286
+ params: {
46287
+ ...params,
46288
+ limit: params.limit === void 0 ? void 0 : String(params.limit)
46289
+ },
46290
+ options: { signal: requestSignal }
46291
+ }), liveLoaderOptions("listPublicEventCalendarWindow", signal));
46292
+ },
46391
46293
  async resolveEventOccurrence(params) {
46392
46294
  const response = await resolveEventSubroute(params, "event-occurrence");
46393
46295
  return { occurrence: response.subroute?.kind === "event-occurrence" ? response.subroute.occurrence : null };
@@ -46695,17 +46597,6 @@ var CircuitOpenError = class extends Error {
46695
46597
  }
46696
46598
  };
46697
46599
  //#endregion
46698
- //#region src/client/publicLoaderCacheAccess.ts
46699
- function shouldWrite(cacheEnabled, force) {
46700
- return cacheEnabled && !force;
46701
- }
46702
- function liveLoaderOptions(endpoint, signal) {
46703
- return {
46704
- force: getPublicLoaderCachePolicy(endpoint).kind === "live",
46705
- signal
46706
- };
46707
- }
46708
- //#endregion
46709
46600
  //#region src/client/index.ts
46710
46601
  let prebuildModule = null;
46711
46602
  function tryRequire(modulePath) {
@@ -47216,11 +47107,7 @@ function createRiverbankClientWithDeps(deps, config) {
47216
47107
  resilientFetch,
47217
47108
  prebuildLoader
47218
47109
  });
47219
- const wholeSeriesReads = createWholeSeriesReadOperations({
47220
- apiClient,
47221
- resilientFetchData
47222
- });
47223
- const eventSubrouteReads = createEventSubrouteReadOperations({
47110
+ const eventReads = createPublicEventReadOperations({
47224
47111
  apiClient,
47225
47112
  resilientFetchData
47226
47113
  });
@@ -47257,7 +47144,6 @@ function createRiverbankClientWithDeps(deps, config) {
47257
47144
  });
47258
47145
  }
47259
47146
  return {
47260
- ...wholeSeriesReads,
47261
47147
  async getSite(params) {
47262
47148
  return (await contentReads.getSiteWithResilience(params)).data;
47263
47149
  },
@@ -47506,7 +47392,7 @@ function createRiverbankClientWithDeps(deps, config) {
47506
47392
  });
47507
47393
  }, { signal });
47508
47394
  },
47509
- ...eventSubrouteReads,
47395
+ ...eventReads,
47510
47396
  async checkRedirect(params) {
47511
47397
  const { siteId, path, signal } = params;
47512
47398
  if (!siteId || !path) throw new Error("checkRedirect() requires siteId and path");
@@ -48548,6 +48434,50 @@ z.object({
48548
48434
  title: z.string(),
48549
48435
  slug: z.string().min(1)
48550
48436
  });
48437
+ z.object({
48438
+ signedUrl: z.string().url(),
48439
+ token: z.string().min(1),
48440
+ storagePath: z.string().min(1)
48441
+ }).strict();
48442
+ const backupManifestSchema = z.object({
48443
+ siteId: z.string().min(1),
48444
+ siteSlug: z.string().min(1),
48445
+ siteTitle: z.string(),
48446
+ exportedAt: z.string().min(1),
48447
+ tableCount: z.number().int().nonnegative(),
48448
+ totalRecords: z.number().int().nonnegative(),
48449
+ pageCount: z.number().int().nonnegative(),
48450
+ blockCount: z.number().int().nonnegative(),
48451
+ contentEntryCount: z.number().int().nonnegative(),
48452
+ formCount: z.number().int().nonnegative(),
48453
+ navigationMenuCount: z.number().int().nonnegative(),
48454
+ mediaCount: z.number().int().nonnegative(),
48455
+ mediaBytes: z.number().int().nonnegative()
48456
+ }).strict();
48457
+ z.object({
48458
+ ok: z.literal(true),
48459
+ manifest: backupManifestSchema,
48460
+ storagePath: z.string().min(1)
48461
+ }).strict();
48462
+ z.object({
48463
+ ok: z.literal(true),
48464
+ siteId: brandedIdSchema(parseSiteId, "site id"),
48465
+ slug: z.string().min(1),
48466
+ title: z.string(),
48467
+ counts: z.record(z.string(), z.object({
48468
+ created: z.number().int().nonnegative(),
48469
+ updated: z.number().int().nonnegative(),
48470
+ skipped: z.number().int().nonnegative(),
48471
+ failed: z.number().int().nonnegative()
48472
+ }).strict()),
48473
+ warnings: z.array(z.string()),
48474
+ errors: z.array(z.object({
48475
+ table: z.string(),
48476
+ id: z.string(),
48477
+ error: z.string()
48478
+ }).strict())
48479
+ }).strict();
48480
+ z.object({ deleted: z.boolean() }).strict();
48551
48481
  const apiKeyIdSchema = brandedIdSchema(parseApiKeyId, "API key id");
48552
48482
  const standardKeyIdsSchema = z.object({
48553
48483
  live: apiKeyIdSchema.optional(),
@@ -48763,6 +48693,9 @@ z.object({
48763
48693
  return resolved.config;
48764
48694
  });
48765
48695
  //#endregion
48696
+ //#region ../api/src/appointmentServiceVisibility.ts
48697
+ const APPOINTMENT_SERVICE_VISIBILITY_VALUES = ["public", "unlisted"];
48698
+ //#endregion
48766
48699
  //#region ../api/src/utils/isRecord.ts
48767
48700
  function isRecord$3(value) {
48768
48701
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -48814,6 +48747,7 @@ const appointmentSetupServiceDraftSchema = z.object({
48814
48747
  cleanupMinutes: z.number().int().nonnegative().max(APPOINTMENT_SETUP_MAX_MINUTES).default(0),
48815
48748
  priceAmount: z.number().int().nonnegative().nullable(),
48816
48749
  isActive: z.boolean(),
48750
+ visibility: z.enum(APPOINTMENT_SERVICE_VISIBILITY_VALUES).default("public"),
48817
48751
  locationType: z.union([
48818
48752
  z.literal("virtual"),
48819
48753
  z.literal("in_person"),
@@ -49166,7 +49100,7 @@ z.object({
49166
49100
  });
49167
49101
  //#endregion
49168
49102
  //#region src/data/prefetchBlockData.ts
49169
- const SUPPORTED_LOADER_ENDPOINTS = SUPPORTED_LOADER_ENDPOINTS$1.filter((endpoint) => endpoint !== "listPublicWholeSeriesOfferings");
49103
+ const SUPPORTED_LOADER_ENDPOINTS = SUPPORTED_LOADER_ENDPOINTS$1;
49170
49104
  function isSupportedLoaderEndpoint(endpoint) {
49171
49105
  return SUPPORTED_LOADER_ENDPOINTS.includes(endpoint);
49172
49106
  }
@@ -49229,9 +49163,12 @@ const loaderAdapters = {
49229
49163
  listPublishedEntries,
49230
49164
  getPublishedEntryPreview,
49231
49165
  listPublicEvents,
49166
+ listPublicEventCalendarWindow: ({ client, params }) => client.listPublicEventCalendarWindow({
49167
+ ...calendarWindowQuerySchema.parse(params),
49168
+ siteId: requireStringParam(params, "siteId", "listPublicEventCalendarWindow")
49169
+ }),
49232
49170
  listPublicRecurringSchedule,
49233
49171
  getPublicEventDetails,
49234
- getPublicWholeSeriesOffering,
49235
49172
  listPublicRouteCandidates,
49236
49173
  listPublicTeamMembers,
49237
49174
  listPublicProducts,
@@ -49326,13 +49263,6 @@ async function listPublicEvents({ client, params }) {
49326
49263
  async function listPublicRecurringSchedule(input) {
49327
49264
  return projectRecurringSchedule(await listPublicEvents(input));
49328
49265
  }
49329
- async function getPublicWholeSeriesOffering({ client, params }) {
49330
- return await client.getPublicWholeSeriesOffering({
49331
- siteId: requireStringParam(params, "siteId", "getPublicWholeSeriesOffering"),
49332
- eventSeriesId: requireStringParam(params, "eventSeriesId", "getPublicWholeSeriesOffering"),
49333
- stage: readStringParam(params, "stage")
49334
- });
49335
- }
49336
49266
  async function getPublicEventDetails({ client, params }) {
49337
49267
  return await client.getPublicEventDetails({
49338
49268
  siteId: requireStringParam(params, "siteId", "getPublicEventDetails"),
@@ -49925,7 +49855,7 @@ function applyBindings(bindings, context) {
49925
49855
  if (value !== void 0 && value !== null) setBindingValue(result, key, value);
49926
49856
  continue;
49927
49857
  }
49928
- if (isRecord$11(bindingSpec)) {
49858
+ if (isRecord$10(bindingSpec)) {
49929
49859
  const nested = applyBindings(bindingSpec, context);
49930
49860
  if (Object.keys(nested).length > 0) setBindingValue(result, key, nested);
49931
49861
  }
@@ -49966,7 +49896,7 @@ function mergeResolvedBindings(base, resolved) {
49966
49896
  const merged = { ...base };
49967
49897
  for (const [key, resolvedValue] of Object.entries(resolved)) {
49968
49898
  const baseValue = merged[key];
49969
- merged[key] = isRecord$11(baseValue) && isRecord$11(resolvedValue) ? mergeResolvedBindings(baseValue, resolvedValue) : resolvedValue;
49899
+ merged[key] = isRecord$10(baseValue) && isRecord$10(resolvedValue) ? mergeResolvedBindings(baseValue, resolvedValue) : resolvedValue;
49970
49900
  }
49971
49901
  return merged;
49972
49902
  }
@@ -49991,7 +49921,7 @@ function setBindingValue(target, path, value) {
49991
49921
  current[Number(segment)] = value;
49992
49922
  return;
49993
49923
  }
49994
- if (isRecord$11(current)) current[segment] = value;
49924
+ if (isRecord$10(current)) current[segment] = value;
49995
49925
  return;
49996
49926
  }
49997
49927
  const nextWantsArray = typeof nextSegment === "string" && isIndex(nextSegment);
@@ -50000,15 +49930,15 @@ function setBindingValue(target, path, value) {
50000
49930
  const existing = current[index];
50001
49931
  if (nextWantsArray) {
50002
49932
  if (!Array.isArray(existing)) current[index] = [];
50003
- } else if (!isRecord$11(existing)) current[index] = {};
49933
+ } else if (!isRecord$10(existing)) current[index] = {};
50004
49934
  current = current[index];
50005
49935
  continue;
50006
49936
  }
50007
- if (isRecord$11(current)) {
49937
+ if (isRecord$10(current)) {
50008
49938
  const existing = current[segment];
50009
49939
  if (nextWantsArray) {
50010
49940
  if (!Array.isArray(existing)) current[segment] = [];
50011
- } else if (!isRecord$11(existing)) current[segment] = {};
49941
+ } else if (!isRecord$10(existing)) current[segment] = {};
50012
49942
  current = current[segment];
50013
49943
  continue;
50014
49944
  }
@@ -50046,7 +49976,7 @@ function getPath(source, path) {
50046
49976
  const segments = path.split(".").map((segment) => segment.trim()).filter(Boolean);
50047
49977
  let current = source;
50048
49978
  for (const segment of segments) {
50049
- if (!isRecord$11(current)) return void 0;
49979
+ if (!isRecord$10(current)) return void 0;
50050
49980
  current = current[segment];
50051
49981
  }
50052
49982
  return current;
@@ -50079,7 +50009,7 @@ function textToInlineText(value) {
50079
50009
  function extractFirstParagraph(value) {
50080
50010
  if (!isRichTextDoc(value)) return null;
50081
50011
  for (const node of value.content) {
50082
- if (!isRecord$11(node)) continue;
50012
+ if (!isRecord$10(node)) continue;
50083
50013
  if (node.type !== "paragraph" || !Array.isArray(node.content)) continue;
50084
50014
  const text = node.content.filter((item) => item.type === "text").map((item) => typeof item.text === "string" ? item.text : "").join("").trim();
50085
50015
  if (text.length > 0) return text;
@@ -50099,7 +50029,7 @@ function formatDate(value, options) {
50099
50029
  * Type guard to check if a value is a valid binding descriptor.
50100
50030
  */
50101
50031
  function isBindingDescriptor(value) {
50102
- if (!isRecord$11(value) || typeof value.source !== "string") return false;
50032
+ if (!isRecord$10(value) || typeof value.source !== "string") return false;
50103
50033
  if (!BINDING_SOURCES.includes(value.source)) return false;
50104
50034
  switch (value.source) {
50105
50035
  case "field":
@@ -50114,7 +50044,7 @@ function isBindingDescriptor(value) {
50114
50044
  * Type guard to check if a value is binding-descriptor-like (can be normalized).
50115
50045
  */
50116
50046
  function isBindingDescriptorLike(value) {
50117
- return isBindingDescriptor(value) || typeof value === "string" || isRecord$11(value) && typeof value.source === "string" && typeof value.path === "string";
50047
+ return isBindingDescriptor(value) || typeof value === "string" || isRecord$10(value) && typeof value.source === "string" && typeof value.path === "string";
50118
50048
  }
50119
50049
  /**
50120
50050
  * Normalizes a binding input to a binding descriptor.
@@ -50140,7 +50070,7 @@ BINDING_TRANSFORM_VALUES$1.join(", ");
50140
50070
  * the SDK's public type surface must remain SDK-owned so consumers don't need
50141
50071
  * to install `@riverbankcms/blocks`.
50142
50072
  */
50143
- const isRecord = isRecord$11;
50073
+ const isRecord = isRecord$10;
50144
50074
  const applyBindingsToContent = applyBindingsToContent$1;
50145
50075
  //#endregion
50146
50076
  //#region src/rendering/helpers/templateContent.ts
@@ -50148,9 +50078,7 @@ function admitMaterializedSdkTemplateBlockContent(input) {
50148
50078
  const baseContent = sanitizeSdkRuntimeBlockContent(input.block.blockKind, input.block.content ?? {});
50149
50079
  const bindings = input.block.bindings ?? {};
50150
50080
  const materialized = input.block.scope === "entry" && Object.keys(bindings).length > 0 ? applyBindingsToContent(baseContent, bindings, input.bindingContext) : baseContent;
50151
- const contract = compileManifestContentContract(input.manifestOrFields);
50152
- const stored = admitStoredManifestContent(contract, materialized);
50153
- return stored.ok ? deriveRenderableManifestContent(contract, stored.value, (content) => content) : stored;
50081
+ return admitTransportedRenderableManifestContent(compileManifestContentContract(input.manifestOrFields), materialized);
50154
50082
  }
50155
50083
  function createTemplateRenderTarget(source, templateId) {
50156
50084
  switch (source.kind) {
@@ -50282,13 +50210,7 @@ function admitEntrySlotBlock(block, customBlocks) {
50282
50210
  if (transportedAdmission) return invalidRenderableBlock(base, transportedAdmission.error);
50283
50211
  const manifest = resolveSdkBlockManifest(block.kind, customBlocks);
50284
50212
  if (manifest === null) return invalidRenderableBlock(base, { kind: "manifest_unavailable" });
50285
- const contract = compileManifestContentContract(manifest);
50286
- const stored = admitStoredManifestContent(contract, block.content ?? {});
50287
- if (!stored.ok) return invalidRenderableBlock(base, {
50288
- kind: "invalid_manifest_content",
50289
- error: stored.error
50290
- });
50291
- const renderable = deriveRenderableManifestContent(contract, stored.value, (content) => content);
50213
+ const renderable = admitTransportedRenderableManifestContent(compileManifestContentContract(manifest), block.content ?? {});
50292
50214
  return renderable.ok ? {
50293
50215
  ...base,
50294
50216
  admission: {