@riverbankcms/sdk 0.138.0 → 0.140.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 (293) hide show
  1. package/README.md +12 -16
  2. package/dist/{PreviewEditorSidebar-BVPur_CU.mjs → PreviewEditorSidebar-CUyTzd5z.mjs} +4 -4
  3. package/dist/{PreviewEditorUI-DLhWX8oh.mjs → PreviewEditorUI-Agkw4v5i.mjs} +3 -3
  4. package/dist/{PreviewQueryProvider-BguJY1SW.mjs → PreviewQueryProvider-CN0ewic5.mjs} +1 -1
  5. package/dist/{SdkPreviewModeRuntime-Tda6qw4z.mjs → SdkPreviewModeRuntime-DdbeAdS8.mjs} +62 -28
  6. package/dist/{SiteChromeCustomizeContext-BHFgMjde.mjs → SiteChromeCustomizeContext-CqGOz-Kv.mjs} +8467 -5616
  7. package/dist/_dts/ai/src/contracts/proposals.d.ts +264 -495
  8. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +221 -242
  9. package/dist/_dts/api/src/accessAdmin.d.ts +74 -104
  10. package/dist/_dts/api/src/aiEndpoints.d.ts +5 -1
  11. package/dist/_dts/api/src/authSubmission.d.ts +46 -0
  12. package/dist/_dts/api/src/billing.d.ts +18 -7
  13. package/dist/_dts/api/src/billingEndpointDefinitions.d.ts +23 -0
  14. package/dist/_dts/api/src/billingEndpointTypes.d.ts +26 -0
  15. package/dist/_dts/api/src/blocks.d.ts +2 -0
  16. package/dist/_dts/api/src/bookingRecords.d.ts +1 -2
  17. package/dist/_dts/api/src/commercePortalEndpoints.d.ts +8 -1
  18. package/dist/_dts/api/src/communications.d.ts +0 -1
  19. package/dist/_dts/api/src/contentRuntime.d.ts +16 -4
  20. package/dist/_dts/api/src/endpoints.d.ts +275 -167
  21. package/dist/_dts/api/src/event-destination-policy.d.ts +2 -1
  22. package/dist/_dts/api/src/footerSettings.d.ts +10 -10
  23. package/dist/_dts/api/src/index.d.ts +11 -10
  24. package/dist/_dts/api/src/indexCoreTypes.d.ts +1 -1
  25. package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -1
  26. package/dist/_dts/api/src/mailchimpIntegration.d.ts +2 -59
  27. package/dist/_dts/api/src/mailingListIntegration.d.ts +123 -0
  28. package/dist/_dts/api/src/navigation/dashboardSettingsNav.d.ts +1 -1
  29. package/dist/_dts/api/src/navigation/locations.d.ts +1 -0
  30. package/dist/_dts/api/src/navigation/types.d.ts +1 -1
  31. package/dist/_dts/api/src/navigation.d.ts +1 -26
  32. package/dist/_dts/api/src/newsletterEndpointDefinitions.d.ts +109 -2
  33. package/dist/_dts/api/src/onboarding/confirmationResend.d.ts +25 -0
  34. package/dist/_dts/api/src/onboarding/surfaceData.d.ts +185 -0
  35. package/dist/_dts/api/src/privacyPolicy.d.ts +74 -2
  36. package/dist/_dts/api/src/publicBookingAvailabilityEndpointDefinitions.d.ts +14 -6
  37. package/dist/_dts/api/src/publicEventEndpointDefinitions.d.ts +1 -1
  38. package/dist/_dts/api/src/publicExperience/commerceEndpoints.d.ts +1 -0
  39. package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +11 -3
  40. package/dist/_dts/api/src/publicExperience/newsletterEndpoints.d.ts +2 -4
  41. package/dist/_dts/api/src/publicExperience/sharedTypes.d.ts +9 -49
  42. package/dist/_dts/api/src/publicOnboardingAttemptEndpointDefinitions.d.ts +65 -0
  43. package/dist/_dts/api/src/publicReadEndpointDefinitions.d.ts +73 -0
  44. package/dist/_dts/api/src/saveOutcome.d.ts +20 -0
  45. package/dist/_dts/api/src/schemas/site-api-keys.d.ts +1 -1
  46. package/dist/_dts/api/src/sdkContracts.d.ts +5 -32
  47. package/dist/_dts/api/src/sdkPushContracts.d.ts +18 -0
  48. package/dist/_dts/api/src/sdkThemeWire.d.ts +46 -46
  49. package/dist/_dts/api/src/settings/permissions.d.ts +12 -0
  50. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +9 -34
  51. package/dist/_dts/api/src/siteOnboarding.d.ts +84 -228
  52. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +3 -13
  53. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +3 -1
  54. package/dist/_dts/api/src/siteSettings.d.ts +38 -6
  55. package/dist/_dts/api/src/types.d.ts +78 -77
  56. package/dist/_dts/api/src/wholeSeriesRuns.d.ts +2 -37
  57. package/dist/_dts/billing/src/membership/index.d.ts +17 -7
  58. package/dist/_dts/billing/src/plans/display.d.ts +15 -0
  59. package/dist/_dts/billing/src/plans/registry.d.ts +2 -0
  60. package/dist/_dts/billing/src/plans/standing.d.ts +19 -0
  61. package/dist/_dts/billing/src/plans/types.d.ts +4 -7
  62. package/dist/_dts/billing/src/site-arrangements.d.ts +14 -3
  63. package/dist/_dts/billing/src/subscriptions/evidence.d.ts +12 -0
  64. package/dist/_dts/billing/src/subscriptions/standingEvidence.d.ts +31 -0
  65. package/dist/_dts/billing/src/subscriptions/store.d.ts +23 -5
  66. package/dist/_dts/blocks/src/PageRenderer.d.ts +6 -15
  67. package/dist/_dts/blocks/src/client.d.ts +1 -1
  68. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +48 -20
  69. package/dist/_dts/blocks/src/pageRenderAdmission.d.ts +2 -0
  70. package/dist/_dts/blocks/src/pageRendererContracts.d.ts +9 -0
  71. package/dist/_dts/blocks/src/pageRenderingMode.d.ts +12 -6
  72. package/dist/_dts/blocks/src/portal/types.d.ts +2 -4
  73. package/dist/_dts/blocks/src/portal/waitlist-types.d.ts +35 -0
  74. package/dist/_dts/blocks/src/system/blocks/appointment-services.d.ts +11 -0
  75. package/dist/_dts/blocks/src/system/blocks/contact-newsletter.d.ts +39 -66
  76. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +2 -0
  77. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +42 -0
  78. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +4 -0
  79. package/dist/_dts/blocks/src/system/blocks/newsletter-signup.d.ts +39 -114
  80. package/dist/_dts/blocks/src/system/blocks/offerings-preview/catalogue.d.ts +18 -0
  81. package/dist/_dts/blocks/src/system/blocks/offerings-preview/fields.d.ts +2 -0
  82. package/dist/_dts/blocks/src/system/blocks/offerings-preview/index.d.ts +4 -0
  83. package/dist/_dts/blocks/src/system/blocks/site-footer-runtime.d.ts +7 -13
  84. package/dist/_dts/blocks/src/system/constants/blockKinds.d.ts +1 -1
  85. package/dist/_dts/blocks/src/system/data/index.d.ts +4 -4
  86. package/dist/_dts/blocks/src/system/data/loaderEndpoints.d.ts +1 -1
  87. package/dist/_dts/blocks/src/system/data/prefetchBlockData.d.ts +2 -1
  88. package/dist/_dts/blocks/src/system/data/publicLoaderCachePolicy.d.ts +2 -74
  89. package/dist/_dts/blocks/src/system/data/types.d.ts +9 -0
  90. package/dist/_dts/blocks/src/system/fragments/library/newsletterForm.d.ts +33 -100
  91. package/dist/_dts/blocks/src/system/registry.d.ts +1 -0
  92. package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +0 -28
  93. package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
  94. package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +7 -3
  95. package/dist/_dts/blocks/src/system/runtime/api/types/newsletter.d.ts +5 -15
  96. package/dist/_dts/blocks/src/system/runtime/api/types/portal.d.ts +1 -1
  97. package/dist/_dts/blocks/src/system/runtime/api/types/waitlist-claims.d.ts +7 -2
  98. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +78 -30
  99. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +39 -15
  100. package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.d.ts +3 -0
  101. package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.state.d.ts +1 -1
  102. package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarToday.d.ts +22 -0
  103. package/dist/_dts/blocks/src/system/runtime/nodes/appointment-services.d.ts +94 -0
  104. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationSurface.d.ts +1 -2
  105. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/TicketSelectionStep.d.ts +2 -0
  106. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/checkoutRecovery.d.ts +14 -0
  107. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventSourceRecovery.d.ts +56 -0
  108. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +6 -8
  109. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useCheckoutRecovery.d.ts +8 -0
  110. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +8 -7
  111. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +12 -2
  112. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventSourceRecovery.d.ts +18 -0
  113. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.client.d.ts +1 -1
  114. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +24 -7
  115. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.server.d.ts +4 -2
  116. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +28 -0
  117. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/bookability.d.ts +9 -0
  118. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/dates.d.ts +14 -0
  119. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/duration.d.ts +2 -0
  120. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/index.d.ts +4 -0
  121. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/location.d.ts +2 -0
  122. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/quickDates.d.ts +16 -0
  123. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/AgendaEventCard.d.ts +9 -1
  124. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/CalendarDayCell.d.ts +2 -0
  125. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/CalendarDayHeaders.d.ts +4 -0
  126. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/DayEventsModal.d.ts +2 -1
  127. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventCard.d.ts +5 -0
  128. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventModals.d.ts +2 -1
  129. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventQuickDates.d.ts +15 -0
  130. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekAgendaView.d.ts +7 -3
  131. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekTimetableView.d.ts +1 -0
  132. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/index.d.ts +2 -0
  133. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/timetableModel.d.ts +1 -0
  134. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/useHydrationReady.d.ts +6 -0
  135. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.client.state.d.ts +3 -0
  136. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.interactive.d.ts +62 -33
  137. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.submission.d.ts +3 -3
  138. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.types.d.ts +14 -31
  139. package/dist/_dts/blocks/src/system/runtime/nodes/offerings-preview-catalogue.d.ts +14 -0
  140. package/dist/_dts/blocks/src/system/runtime/nodes/offerings-preview-content.d.ts +23 -0
  141. package/dist/_dts/blocks/src/system/runtime/nodes/offerings-preview.d.ts +4 -2
  142. package/dist/_dts/blocks/src/system/runtime/resolver.d.ts +1 -0
  143. package/dist/_dts/blocks/src/system/runtime/shared/components/index.d.ts +2 -6
  144. package/dist/_dts/blocks/src/system/runtime/shared/index.d.ts +2 -2
  145. package/dist/_dts/blocks/src/system/runtime/shared/useWaitlistClaim.d.ts +2 -0
  146. package/dist/_dts/blocks/src/system/transforms/registry/formatting.d.ts +5 -0
  147. package/dist/_dts/commerce/src/purchase/event-registration-errors.d.ts +4 -0
  148. package/dist/_dts/commerce/src/purchase/index.d.ts +1 -0
  149. package/dist/_dts/commerce/src/purchase/orderItemMetadata.d.ts +32 -16
  150. package/dist/_dts/commerce/src/purchase/stripeCommissionMetadata.d.ts +34 -0
  151. package/dist/_dts/content-editor/src/controller/EntryControllerProvider.d.ts +2 -1
  152. package/dist/_dts/content-editor/src/footerEngagementDraft.d.ts +6 -24
  153. package/dist/_dts/content-editor/src/hooks/useBlockAutosave.d.ts +3 -1
  154. package/dist/_dts/content-editor/src/useFooterComposerState.d.ts +4 -2
  155. package/dist/_dts/core/src/branded.d.ts +0 -8
  156. package/dist/_dts/core/src/footer-engagement.d.ts +2 -6
  157. package/dist/_dts/core/src/index.d.ts +10 -1
  158. package/dist/_dts/core/src/mailing-list-identifiers.d.ts +21 -0
  159. package/dist/_dts/core/src/mailing-list-runtime.d.ts +42 -0
  160. package/dist/_dts/core/src/mailing-list-setup-parser.d.ts +14 -0
  161. package/dist/_dts/core/src/mailing-list-setup.d.ts +142 -0
  162. package/dist/_dts/core/src/mailing-list-submission.d.ts +224 -0
  163. package/dist/_dts/core/src/mailing-list-targeting-parser.d.ts +12 -0
  164. package/dist/_dts/core/src/mailing-list-targeting.d.ts +93 -0
  165. package/dist/_dts/core/src/navigation-locations.d.ts +28 -0
  166. package/dist/_dts/core/src/participants.d.ts +2 -29
  167. package/dist/_dts/core/src/public-experience.d.ts +4 -0
  168. package/dist/_dts/core/src/public-profile.d.ts +35 -1
  169. package/dist/_dts/core/src/public-read-cache-contract.d.ts +45 -0
  170. package/dist/_dts/core/src/site-route-target.d.ts +9 -2
  171. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +797 -954
  172. package/dist/_dts/editor-blocks/src/widgets/index.d.ts +1 -0
  173. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/MailingListGlobalSettingsSummary.d.ts +10 -0
  174. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/MailingListTargetingField.d.ts +12 -0
  175. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/context.d.ts +14 -0
  176. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/index.d.ts +3 -0
  177. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/loaders.d.ts +7 -0
  178. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/targetingState.d.ts +19 -0
  179. package/dist/_dts/preview-next/src/client/widgets/widgetOverrides.d.ts +1 -0
  180. package/dist/_dts/sdk/src/client/publicAppointmentReadOperations.d.ts +12 -0
  181. package/dist/_dts/sdk/src/client/publicEventReadOperations.d.ts +2 -1
  182. package/dist/_dts/sdk/src/client/publicLoaderCacheAccess.d.ts +11 -4
  183. package/dist/_dts/sdk/src/config/content-types.d.ts +3 -13
  184. package/dist/_dts/sdk/src/config/content-validation.d.ts +5 -8
  185. package/dist/_dts/sdk/src/constants.d.ts +3 -3
  186. package/dist/_dts/sdk/src/contracts/index.d.ts +1 -1
  187. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +12 -31
  188. package/dist/_dts/sdk/src/navigation/index.d.ts +11 -29
  189. package/dist/_dts/sdk/src/next/index.d.ts +4 -4
  190. package/dist/_dts/sdk/src/prebuild/types.d.ts +1 -5
  191. package/dist/_dts/sdk/src/public-api/contracts.d.ts +44 -33
  192. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +5 -0
  193. package/dist/_dts/sdk/src/rendering/client.d.ts +3 -20
  194. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +5 -0
  195. package/dist/_dts/sdk/src/rendering/helpers/loadContent.d.ts +4 -0
  196. package/dist/_dts/sdk/src/rendering/helpers/pageRuntimeSupport.d.ts +8 -1
  197. package/dist/_dts/sdk/src/rendering/helpers/templateContent.d.ts +1 -0
  198. package/dist/_dts/sdk/src/rendering/index.d.ts +1 -1
  199. package/dist/_dts/sdk/src/types/block-kinds.d.ts +1 -1
  200. package/dist/_dts/sdk/src/version.d.ts +1 -1
  201. package/dist/_dts/theme-core/src/accordions/types.d.ts +3 -3
  202. package/dist/_dts/theme-core/src/cards/types.d.ts +21 -21
  203. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  204. package/dist/_dts/theme-core/src/header/interactionPalette.d.ts +8 -2
  205. package/dist/_dts/theme-core/src/header/legacyHeaderVariant.d.ts +2 -2
  206. package/dist/_dts/theme-core/src/hosted-booking-appearance.d.ts +41 -0
  207. package/dist/_dts/theme-core/src/index.d.ts +1 -0
  208. package/dist/_dts/theme-core/src/inputs/types.d.ts +2 -2
  209. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +54 -54
  210. package/dist/_dts/theme-core/src/runtime/buildThemeRuntime.d.ts +0 -1
  211. package/dist/_dts/theme-core/src/runtime/buildThemeRuntimeFromBridge.d.ts +1 -4
  212. package/dist/_dts/theme-core/src/schema.d.ts +84 -84
  213. package/dist/_dts/theme-core/src/shared/componentStyles.d.ts +1 -1
  214. package/dist/_dts/theme-core/src/site-styles/backgroundAppearance.d.ts +2 -2
  215. package/dist/_dts/theme-core/src/surfaces/foregroundInteraction.d.ts +77 -0
  216. package/dist/_dts/theme-core/src/surfaces/index.d.ts +1 -0
  217. package/dist/_dts/theme-core/src/tokens/tokens.d.ts +7 -0
  218. package/dist/_dts/theme-core/src/typography/generateTypographyCss.d.ts +2 -2
  219. package/dist/_dts/ui/src/badge.d.ts +1 -1
  220. package/dist/_dts/ui/src/callout.d.ts +1 -1
  221. package/dist/_dts/ui/src/lib/use-delayed-flag.d.ts +9 -0
  222. package/dist/_dts/ui/src/pending-button.d.ts +10 -0
  223. package/dist/client/{BookingConsentAgreement-DQUik1Mx.mjs → BookingConsentAgreement-CuKa82V4.mjs} +4 -4
  224. package/dist/client/{DiscountCodeDisclosure-CU67Q4vH.mjs → DiscountCodeDisclosure-BbYieKWB.mjs} +1 -1
  225. package/dist/client/{EventCombined.client-a02TXUgg.mjs → EventCombined.client-LTfR1Aby.mjs} +444 -200
  226. package/dist/client/{EventListing.client-99qx7jFl.mjs → EventListing.client-DUHpYSuo.mjs} +2 -2
  227. package/dist/client/{LeafletStaticMap-CWzcq73L.mjs → LeafletStaticMap-CHRupL6m.mjs} +1 -1
  228. package/dist/client/{accordion-D1nb3-Oj.mjs → accordion-6HiIFxNL.mjs} +1 -1
  229. package/dist/client/{bookingForm-BGrmLhaO.mjs → bookingForm-Dlmid43H.mjs} +7 -7
  230. package/dist/client/bookings.mjs +368 -142
  231. package/dist/client/{carousel-DSmOx3ad.mjs → carousel-DmkZRRq_.mjs} +2 -2
  232. package/dist/client/{carousel.client-59G_WMr4.mjs → carousel.client-DQTjCVQT.mjs} +1 -1
  233. package/dist/client/{cart-COWeOIUk.mjs → cart-CIC24330.mjs} +3 -3
  234. package/dist/client/{checkout-CeysaIJK.mjs → checkout-D1Zw9imo.mjs} +3 -3
  235. package/dist/client/{checkoutUrls-BuseL0dw.mjs → checkoutUrls-FL6lRkrt.mjs} +1 -1
  236. package/dist/client/client.mjs +5017 -2258
  237. package/dist/client/{colorStyles-CrxJrPjJ.mjs → colorStyles-3013aRAY.mjs} +3 -1
  238. package/dist/client/{context-DBzX85Xc.mjs → context-Cy1OayHx.mjs} +9 -21
  239. package/dist/client/{dates-DCYhZBlW.mjs → dates-aDcfoLHr.mjs} +21 -3
  240. package/dist/client/{eventCalendar-BgsN73Ul.mjs → eventCalendar-FQxMPAjf.mjs} +81 -79
  241. package/dist/client/{eventCombined-DcZQAMQP.mjs → eventCombined-Dr3ac6Hb.mjs} +3 -3
  242. package/dist/client/{eventDetails-BWwGJ54l.mjs → eventDetails-D-AzUHFQ.mjs} +4 -4
  243. package/dist/client/{eventListing-DqYqV8vp.mjs → eventListing-B3XxBf3i.mjs} +3 -3
  244. package/dist/client/{eventRegistration-DQGDgu_e.mjs → eventRegistration-I6EaokFD.mjs} +543 -155
  245. package/dist/client/{form-ClfpasVT.mjs → form-BbWckVWY.mjs} +3 -3
  246. package/dist/client/{headerSection-BuOMe98N.mjs → headerSection-C9qU4Y7x.mjs} +2 -2
  247. package/dist/client/hooks.mjs +1685 -716
  248. package/dist/client/{locationMap-CEqu_sfa.mjs → locationMap-CLCShvlG.mjs} +3 -3
  249. package/dist/client/{media-BOHuueS5.mjs → media-DHpfFwd3.mjs} +1 -1
  250. package/dist/client/newsletterForm-Briukxzi.mjs +444 -0
  251. package/dist/client/{pricing-xj7MPZlK.mjs → pricing-Copadu-2.mjs} +1 -1
  252. package/dist/client/{productDetail-vxqTt5Xj.mjs → productDetail-oujlRd-r.mjs} +3 -3
  253. package/dist/client/{productList-OTdZu8sb.mjs → productList-BRiIRUcd.mjs} +3 -3
  254. package/dist/client/{propsDecoder-CY9gGEF7.mjs → propsDecoder-CB2KS_ko.mjs} +706 -160
  255. package/dist/client/rendering/client.mjs +3161 -1226
  256. package/dist/client/rendering/islands.mjs +19 -19
  257. package/dist/client/rendering.mjs +4864 -1914
  258. package/dist/client/{scrollToBlock--BFV6kl-.mjs → scrollToBlock-B1IS1_ua.mjs} +1 -1
  259. package/dist/client/{shop-CP4YbDL9.mjs → shop-Vn6yNFED.mjs} +6 -6
  260. package/dist/client/{shop-commerce-APs4XBXE.mjs → shop-commerce-BVTqipYp.mjs} +7 -7
  261. package/dist/client/{shop-commerce-store-CAVLxLFr.mjs → shop-commerce-store-BVnJVy7v.mjs} +1 -1
  262. package/dist/client/{shopShared-BnSRrwXI.mjs → shopShared-COIeK77T.mjs} +4 -4
  263. package/dist/client/{useEventFilters-1a1by4c8.mjs → useEventFilters-DzIUcS9n.mjs} +58 -11
  264. package/dist/preview-next/before-render.mjs +357 -175
  265. package/dist/preview-next/client/runtime.mjs +4 -4
  266. package/dist/preview-next/keepAlive.mjs +357 -175
  267. package/dist/preview-next/middleware.mjs +357 -175
  268. package/dist/{previewAuthStore-BkEgnYPP.mjs → previewAuthStore-Gjb6r6vz.mjs} +357 -175
  269. package/dist/{sdk-runtime-DwGfsT0S.mjs → sdk-runtime-CnCLvZRv.mjs} +2 -2
  270. package/dist/{separator-BeqDLneQ.mjs → separator-DKDRJ1oH.mjs} +1 -1
  271. package/dist/server/components.mjs +3389 -1251
  272. package/dist/server/config-validation.mjs +2737 -1784
  273. package/dist/server/config.mjs +2742 -1788
  274. package/dist/server/data.mjs +1586 -615
  275. package/dist/server/index.mjs +496 -352
  276. package/dist/server/navigation.mjs +16 -47
  277. package/dist/server/next.mjs +3978 -2007
  278. package/dist/server/page-converter.mjs +1109 -553
  279. package/dist/server/prebuild.mjs +2 -3
  280. package/dist/server/rendering/server.mjs +4101 -1951
  281. package/dist/server/rendering.mjs +3416 -1259
  282. package/dist/server/routing.mjs +1869 -786
  283. package/dist/server/server.mjs +3260 -2482
  284. package/dist/server/theme-bridge.mjs +725 -124
  285. package/dist/server/theme.mjs +8 -2
  286. package/dist/styles/index.css +526 -68
  287. package/package.json +1 -1
  288. package/dist/_dts/api/src/navigation/identity.d.ts +0 -59
  289. package/dist/_dts/blocks/src/system/blocks/newsletter-signup-destination.d.ts +0 -291
  290. package/dist/_dts/blocks/src/system/runtime/shared/components/BookingOptionCompactRow.d.ts +0 -29
  291. package/dist/_dts/blocks/src/system/runtime/shared/components/BookingOptionList.d.ts +0 -13
  292. package/dist/_dts/core/src/newsletter-signup-destination.d.ts +0 -38
  293. package/dist/client/newsletterForm-IbrHjMxy.mjs +0 -322
@@ -16,12 +16,12 @@ function err(error) {
16
16
  }
17
17
  //#endregion
18
18
  //#region ../core/src/branded.ts
19
- const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
19
+ const UUID_PATTERN$1 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
20
20
  function parseUuidBrand(value, unsafeConstructor) {
21
21
  if (typeof value !== "string") return err({ kind: "not_string" });
22
22
  const normalized = value.trim().toLowerCase();
23
23
  if (normalized.length === 0) return err({ kind: "empty_string" });
24
- if (!UUID_PATTERN.test(normalized)) return err({ kind: "invalid_uuid" });
24
+ if (!UUID_PATTERN$1.test(normalized)) return err({ kind: "invalid_uuid" });
25
25
  return ok(unsafeConstructor(normalized));
26
26
  }
27
27
  const unsafeAsSiteId = (id) => id;
@@ -29,10 +29,12 @@ const unsafeAsApiKeyId = (id) => id;
29
29
  const unsafeAsEventOfferingId = (id) => id;
30
30
  const unsafeAsEventSeriesId = (id) => id;
31
31
  const unsafeAsUserId = (id) => id;
32
+ const unsafeAsContentVersionId = (id) => id;
32
33
  const parseSiteId = (value) => parseUuidBrand(value, unsafeAsSiteId);
33
34
  const parseApiKeyId = (value) => parseUuidBrand(value, unsafeAsApiKeyId);
34
35
  const parseEventOfferingId = (value) => parseUuidBrand(value, unsafeAsEventOfferingId);
35
36
  const parseUserId = (value) => parseUuidBrand(value, unsafeAsUserId);
37
+ const parseContentVersionId = (value) => parseUuidBrand(value, unsafeAsContentVersionId);
36
38
  const parseEventSeriesId = (value) => parseUuidBrand(value, unsafeAsEventSeriesId);
37
39
  //#endregion
38
40
  //#region ../core/src/assert-never.ts
@@ -266,7 +268,7 @@ function parseEventPageSurfaceDestinationMode(value) {
266
268
  return value === "cms-managed" || value === "system-managed" ? value : void 0;
267
269
  }
268
270
  function parseEventPageSurfaceSubject(value) {
269
- if (!isRecord$9(value)) return err({ kind: "notObject" });
271
+ if (!isRecord$13(value)) return err({ kind: "notObject" });
270
272
  switch (value.kind) {
271
273
  case "eventSeries": {
272
274
  const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
@@ -321,7 +323,7 @@ function parseEventSeriesIdList(values) {
321
323
  }
322
324
  return ok(parsed);
323
325
  }
324
- function isRecord$9(value) {
326
+ function isRecord$13(value) {
325
327
  return typeof value === "object" && value !== null && !Array.isArray(value);
326
328
  }
327
329
  //#endregion
@@ -491,9 +493,419 @@ function toLocationCoordinates(value) {
491
493
  };
492
494
  }
493
495
  //#endregion
494
- //#region ../core/src/newsletter-signup-destination.ts
495
- function parseNewsletterSignupDestinationProvider(value) {
496
- return value === "riverbank" || value === "mailchimp" ? value : null;
496
+ //#region ../core/src/mailing-list-identifiers.ts
497
+ const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
498
+ const OPAQUE_ID_PATTERN = /^[A-Za-z0-9_-]{1,100}$/u;
499
+ function parseTrimmedMatchingString(value, pattern) {
500
+ if (typeof value !== "string") return null;
501
+ const trimmed = value.trim();
502
+ return pattern.test(trimmed) ? trimmed : null;
503
+ }
504
+ function parsePositiveInteger(value) {
505
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : null;
506
+ }
507
+ function parseNewsletterListId(value) {
508
+ return parseTrimmedMatchingString(value, UUID_PATTERN);
509
+ }
510
+ function parseMailchimpAccountId(value) {
511
+ return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
512
+ }
513
+ function parseMailchimpAudienceId(value) {
514
+ return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
515
+ }
516
+ function parseMailchimpInterestId(value) {
517
+ return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
518
+ }
519
+ function parseBrevoAccountId(value) {
520
+ return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
521
+ }
522
+ function parseBrevoListId(value) {
523
+ return parsePositiveInteger(value);
524
+ }
525
+ //#endregion
526
+ //#region ../core/src/mailing-list-setup.ts
527
+ function isRecord$12(value) {
528
+ return typeof value === "object" && value !== null && !Array.isArray(value);
529
+ }
530
+ const DEFAULT_MAILING_LIST_SUCCESS_MESSAGE = "Thanks — you're on the list.";
531
+ function parseMailingListProviderScope(value) {
532
+ if (!isRecord$12(value)) return err("invalid_mailing_list_provider_scope");
533
+ if (value.provider === "native") return ok({ provider: "native" });
534
+ if (value.provider === "brevo") {
535
+ const accountId = parseBrevoAccountId(value.accountId);
536
+ return accountId !== null ? ok({
537
+ provider: "brevo",
538
+ accountId
539
+ }) : err("invalid_mailing_list_provider_scope");
540
+ }
541
+ if (value.provider === "mailchimp") {
542
+ const accountId = parseMailchimpAccountId(value.accountId);
543
+ return accountId !== null ? ok({
544
+ provider: "mailchimp",
545
+ accountId
546
+ }) : err("invalid_mailing_list_provider_scope");
547
+ }
548
+ return err("invalid_mailing_list_provider_scope");
549
+ }
550
+ //#endregion
551
+ //#region ../core/src/mailing-list-setup-parser.ts
552
+ function parseMailingListGlobalForm(value) {
553
+ if (!isRecord$11(value)) return formError("shape");
554
+ const fields = parseGlobalFields(value.fields);
555
+ if (fields === null) return formError("fields");
556
+ if (typeof value.includeOptionalPhone !== "boolean") return formError("includeOptionalPhone");
557
+ const buttonLabel = parseRequiredString(value.buttonLabel);
558
+ if (buttonLabel === null) return formError("buttonLabel");
559
+ const successMessage = parseRequiredString(value.successMessage);
560
+ if (successMessage === null) return formError("successMessage");
561
+ const privacyNote = parseOptionalString(value.privacyNote);
562
+ if (privacyNote === void 0) return formError("privacyNote");
563
+ return ok({
564
+ fields,
565
+ includeOptionalPhone: value.includeOptionalPhone,
566
+ buttonLabel,
567
+ successMessage,
568
+ privacyNote
569
+ });
570
+ }
571
+ function parseGlobalFields(value) {
572
+ if (!isRecord$11(value) || typeof value.preset !== "string") return null;
573
+ switch (value.preset) {
574
+ case "emailOnly": return { preset: "emailOnly" };
575
+ case "emailName": return isRequirement(value.name) ? {
576
+ preset: "emailName",
577
+ name: value.name
578
+ } : null;
579
+ case "emailFirstLast": return isRequirement(value.firstName) && isRequirement(value.lastName) ? {
580
+ preset: "emailFirstLast",
581
+ firstName: value.firstName,
582
+ lastName: value.lastName
583
+ } : null;
584
+ case "emailNameCompany": return isRequirement(value.name) && isRequirement(value.company) ? {
585
+ preset: "emailNameCompany",
586
+ name: value.name,
587
+ company: value.company
588
+ } : null;
589
+ default: return null;
590
+ }
591
+ }
592
+ function parseMailingListSetupRevision(value) {
593
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : null;
594
+ }
595
+ function parseRequiredString(value) {
596
+ if (typeof value !== "string") return null;
597
+ const trimmed = value.trim();
598
+ return trimmed.length > 0 ? trimmed : null;
599
+ }
600
+ function parseOptionalString(value) {
601
+ if (value === null || value === void 0) return null;
602
+ if (typeof value !== "string") return void 0;
603
+ const trimmed = value.trim();
604
+ return trimmed.length > 0 ? trimmed : null;
605
+ }
606
+ function isRequirement(value) {
607
+ return value === "required" || value === "optional";
608
+ }
609
+ function isRecord$11(value) {
610
+ return typeof value === "object" && value !== null && !Array.isArray(value);
611
+ }
612
+ function formError(field) {
613
+ return err({
614
+ tag: "invalid_mailing_list_global_form",
615
+ field
616
+ });
617
+ }
618
+ //#endregion
619
+ //#region ../core/src/mailing-list-targeting.ts
620
+ function planMailingListChoicePresentation(targeting) {
621
+ if (targeting.mode === "default" || targeting.selection.tag === "fixed") return { tag: "hidden" };
622
+ switch (targeting.provider) {
623
+ case "native": return targeting.selection.offeredTopicIds.length === 1 ? {
624
+ tag: "automatic",
625
+ selection: {
626
+ provider: "native",
627
+ topicIds: targeting.selection.offeredTopicIds
628
+ }
629
+ } : {
630
+ tag: "visitor_choice",
631
+ provider: "native",
632
+ optionCount: targeting.selection.offeredTopicIds.length
633
+ };
634
+ case "brevo": return targeting.selection.offeredListIds.length === 1 ? {
635
+ tag: "automatic",
636
+ selection: {
637
+ provider: "brevo",
638
+ listIds: targeting.selection.offeredListIds
639
+ }
640
+ } : {
641
+ tag: "visitor_choice",
642
+ provider: "brevo",
643
+ optionCount: targeting.selection.offeredListIds.length
644
+ };
645
+ case "mailchimp": return targeting.selection.offeredInterestIds.length === 1 ? {
646
+ tag: "automatic",
647
+ selection: {
648
+ provider: "mailchimp",
649
+ interestIds: targeting.selection.offeredInterestIds
650
+ }
651
+ } : {
652
+ tag: "visitor_choice",
653
+ provider: "mailchimp",
654
+ optionCount: targeting.selection.offeredInterestIds.length
655
+ };
656
+ }
657
+ }
658
+ //#endregion
659
+ //#region ../core/src/mailing-list-runtime.ts
660
+ function parseMailingListRuntimeContext(value) {
661
+ if (!isRecord$10(value)) return invalidRuntimeContext();
662
+ if (value.tag === "not_configured") return ok({ tag: "not_configured" });
663
+ if (value.tag !== "configured") return invalidRuntimeContext();
664
+ const revision = parseMailingListSetupRevision(value.revision);
665
+ const form = parseMailingListGlobalForm(value.form);
666
+ const provider = parseRuntimeProvider(value.provider);
667
+ if (revision === null || !form.ok || provider === null) return invalidRuntimeContext();
668
+ return ok({
669
+ tag: "configured",
670
+ revision,
671
+ form: form.value,
672
+ provider
673
+ });
674
+ }
675
+ function parseRuntimeProvider(value) {
676
+ if (!isRecord$10(value)) return null;
677
+ switch (value.provider) {
678
+ case "native": return parseNativeRuntimeProvider(value);
679
+ case "brevo": return parseBrevoRuntimeProvider(value);
680
+ case "mailchimp": return parseMailchimpRuntimeProvider(value);
681
+ default: return null;
682
+ }
683
+ }
684
+ function parseNativeRuntimeProvider(value) {
685
+ const defaultTopicId = parseNewsletterListId(value.defaultTopicId);
686
+ const topics = parseNamedItems(value.topics, parseNewsletterListId);
687
+ return defaultTopicId !== null && topics !== null ? {
688
+ provider: "native",
689
+ defaultTopicId,
690
+ topics
691
+ } : null;
692
+ }
693
+ function parseBrevoRuntimeProvider(value) {
694
+ const defaultListId = parseBrevoListId(value.defaultListId);
695
+ const lists = parseNamedItems(value.lists, parseBrevoListId);
696
+ return defaultListId !== null && lists !== null ? {
697
+ provider: "brevo",
698
+ defaultListId,
699
+ lists
700
+ } : null;
701
+ }
702
+ function parseMailchimpRuntimeProvider(value) {
703
+ if (!Array.isArray(value.audiences)) return null;
704
+ const defaultAudienceId = parseMailchimpAudienceId(value.defaultAudienceId);
705
+ if (defaultAudienceId === null) return null;
706
+ const audiences = [];
707
+ for (const audience of value.audiences) {
708
+ if (!isRecord$10(audience)) return null;
709
+ const id = parseMailchimpAudienceId(audience.id);
710
+ const name = parseName(audience.name);
711
+ if (id === null || name === null || !Array.isArray(audience.interests)) return null;
712
+ const interests = parseMailchimpInterests(audience.interests);
713
+ if (interests === null) return null;
714
+ audiences.push({
715
+ id,
716
+ name,
717
+ interests
718
+ });
719
+ }
720
+ return {
721
+ provider: "mailchimp",
722
+ defaultAudienceId,
723
+ audiences
724
+ };
725
+ }
726
+ function parseMailchimpInterests(value) {
727
+ const interests = [];
728
+ for (const interest of value) {
729
+ if (!isRecord$10(interest)) return null;
730
+ const id = parseMailchimpInterestId(interest.id);
731
+ const name = parseName(interest.name);
732
+ const categoryName = parseName(interest.categoryName);
733
+ if (id === null || name === null || categoryName === null) return null;
734
+ interests.push({
735
+ id,
736
+ name,
737
+ categoryName
738
+ });
739
+ }
740
+ return interests;
741
+ }
742
+ function parseNamedItems(value, parseId) {
743
+ if (!Array.isArray(value)) return null;
744
+ const items = [];
745
+ for (const item of value) {
746
+ if (!isRecord$10(item)) return null;
747
+ const id = parseId(item.id);
748
+ const name = parseName(item.name);
749
+ if (id === null || name === null) return null;
750
+ items.push({
751
+ id,
752
+ name
753
+ });
754
+ }
755
+ return items;
756
+ }
757
+ function parseName(value) {
758
+ if (typeof value !== "string") return null;
759
+ const name = value.trim();
760
+ return name.length > 0 ? name : null;
761
+ }
762
+ function isRecord$10(value) {
763
+ return typeof value === "object" && value !== null && !Array.isArray(value);
764
+ }
765
+ function invalidRuntimeContext() {
766
+ return err({ tag: "invalid_mailing_list_runtime_context" });
767
+ }
768
+ //#endregion
769
+ //#region ../core/src/mailing-list-targeting-parser.ts
770
+ function parseMailingListPlacementTargeting(value) {
771
+ if (!isRecord$9(value)) return targetingError("shape");
772
+ if (value.mode === "default") return ok({ mode: "default" });
773
+ if (value.mode !== "custom") return targetingError("mode");
774
+ if (!isRecord$9(value.selection)) return targetingError("selection");
775
+ switch (value.provider) {
776
+ case "native": return parseNativeTargeting(value.selection);
777
+ case "brevo": return parseBrevoTargeting(value.selection);
778
+ case "mailchimp": return parseMailchimpTargeting(value, value.selection);
779
+ default: return targetingError("provider");
780
+ }
781
+ }
782
+ function parseNativeTargeting(selection) {
783
+ if (selection.tag === "fixed") {
784
+ const topicIds = parseNonEmptyUniqueIds(selection.topicIds, parseNewsletterListId);
785
+ return topicIds.ok ? ok({
786
+ mode: "custom",
787
+ provider: "native",
788
+ selection: {
789
+ tag: "fixed",
790
+ topicIds: topicIds.value
791
+ }
792
+ }) : topicIds;
793
+ }
794
+ if (selection.tag === "visitor_choice") {
795
+ const offeredTopicIds = parseNonEmptyUniqueIds(selection.offeredTopicIds, parseNewsletterListId);
796
+ return offeredTopicIds.ok ? ok({
797
+ mode: "custom",
798
+ provider: "native",
799
+ selection: {
800
+ tag: "visitor_choice",
801
+ offeredTopicIds: offeredTopicIds.value
802
+ }
803
+ }) : offeredTopicIds;
804
+ }
805
+ return targetingError("selection");
806
+ }
807
+ function parseBrevoTargeting(selection) {
808
+ if (selection.tag === "fixed") {
809
+ const listIds = parseNonEmptyUniqueIds(selection.listIds, parseBrevoListId);
810
+ return listIds.ok ? ok({
811
+ mode: "custom",
812
+ provider: "brevo",
813
+ selection: {
814
+ tag: "fixed",
815
+ listIds: listIds.value
816
+ }
817
+ }) : listIds;
818
+ }
819
+ if (selection.tag === "visitor_choice") {
820
+ const offeredListIds = parseNonEmptyUniqueIds(selection.offeredListIds, parseBrevoListId);
821
+ return offeredListIds.ok ? ok({
822
+ mode: "custom",
823
+ provider: "brevo",
824
+ selection: {
825
+ tag: "visitor_choice",
826
+ offeredListIds: offeredListIds.value
827
+ }
828
+ }) : offeredListIds;
829
+ }
830
+ return targetingError("selection");
831
+ }
832
+ function parseMailchimpTargeting(value, selection) {
833
+ const audienceId = parseMailchimpAudienceId(value.audienceId);
834
+ if (audienceId === null) return targetingError("audienceId");
835
+ if (selection.tag === "fixed") {
836
+ const interestIds = parseUniqueIds(selection.interestIds, parseMailchimpInterestId);
837
+ return interestIds.ok ? ok({
838
+ mode: "custom",
839
+ provider: "mailchimp",
840
+ audienceId,
841
+ selection: {
842
+ tag: "fixed",
843
+ interestIds: interestIds.value
844
+ }
845
+ }) : interestIds;
846
+ }
847
+ if (selection.tag === "visitor_choice") {
848
+ const offeredInterestIds = parseNonEmptyUniqueIds(selection.offeredInterestIds, parseMailchimpInterestId);
849
+ return offeredInterestIds.ok ? ok({
850
+ mode: "custom",
851
+ provider: "mailchimp",
852
+ audienceId,
853
+ selection: {
854
+ tag: "visitor_choice",
855
+ offeredInterestIds: offeredInterestIds.value
856
+ }
857
+ }) : offeredInterestIds;
858
+ }
859
+ return targetingError("selection");
860
+ }
861
+ function parseNonEmptyUniqueIds(value, parseId) {
862
+ const parsed = parseUniqueIds(value, parseId);
863
+ if (!parsed.ok) return parsed;
864
+ const [first, ...rest] = parsed.value;
865
+ return first === void 0 ? targetingError("targets") : ok([first, ...rest]);
866
+ }
867
+ function parseUniqueIds(value, parseId) {
868
+ if (!Array.isArray(value)) return targetingError("targets");
869
+ const parsed = [];
870
+ for (const item of value) {
871
+ const id = parseId(item);
872
+ if (id === null) return targetingError("targets");
873
+ if (parsed.includes(id)) return targetingError("duplicate_target");
874
+ parsed.push(id);
875
+ }
876
+ return ok(parsed);
877
+ }
878
+ function isRecord$9(value) {
879
+ return typeof value === "object" && value !== null && !Array.isArray(value);
880
+ }
881
+ function targetingError(field) {
882
+ return err({
883
+ tag: "invalid_mailing_list_targeting",
884
+ field
885
+ });
886
+ }
887
+ //#endregion
888
+ //#region ../core/src/mailing-list-submission.ts
889
+ function parseMailingListBlockId(value) {
890
+ const parsed = typeof value === "string" ? value.trim() : "";
891
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(parsed) ? parsed : null;
892
+ }
893
+ function parseMailingListSignedSourceToken(value) {
894
+ const parsed = typeof value === "string" ? value.trim() : "";
895
+ return /^[A-Za-z0-9._~-]{16,1000}$/u.test(parsed) ? parsed : null;
896
+ }
897
+ function parseMailingListContentVersionId(value) {
898
+ const parsed = parseContentVersionId(value);
899
+ return parsed.ok ? parsed.value : null;
900
+ }
901
+ function buildMailingListSignupBlockSourceRef(blockId, contentVersionId) {
902
+ const parsedBlockId = parseMailingListBlockId(blockId);
903
+ const parsedContentVersionId = parseMailingListContentVersionId(contentVersionId);
904
+ return parsedBlockId !== null && parsedContentVersionId !== null ? {
905
+ tag: "block_ref",
906
+ blockId: parsedBlockId,
907
+ contentVersionId: parsedContentVersionId
908
+ } : null;
497
909
  }
498
910
  //#endregion
499
911
  //#region ../core/src/secret.ts
@@ -555,6 +967,56 @@ function sessionStartMs(session) {
555
967
  function orderedLiveRunSessions(sessions) {
556
968
  return sessions.filter((session) => session.status !== "cancelled" && Number.isFinite(sessionStartMs(session))).sort((left, right) => sessionStartMs(left) - sessionStartMs(right));
557
969
  }
970
+ const PUBLIC_CONTENT_FRESHNESS_SECONDS = 3600;
971
+ function availability(transport) {
972
+ return {
973
+ kind: "live",
974
+ reason: "booking_correctness",
975
+ freshness: "availability",
976
+ transport
977
+ };
978
+ }
979
+ function content(tags, transport = "direct") {
980
+ return {
981
+ kind: "tagged",
982
+ tags,
983
+ freshness: "content",
984
+ transport
985
+ };
986
+ }
987
+ /** The single classification authority for cacheable public reads. */
988
+ const PUBLIC_READ_CACHE_POLICIES = {
989
+ listPublishedEntries: content(["published_content"]),
990
+ getPublishedEntryPreview: content(["published_content"]),
991
+ listPublicEvents: availability("direct"),
992
+ listPublicEventCalendarWindow: availability("direct"),
993
+ listPublicRecurringSchedule: availability("batch_only"),
994
+ getPublicEventDetails: availability("batch_only"),
995
+ resolveEventSubroute: availability("direct"),
996
+ listPublicRouteCandidates: content(["published_content"], "batch_only"),
997
+ listPublicTeamMembers: content(["public_team_members"]),
998
+ listPublicProducts: availability("direct"),
999
+ listPublicPasses: availability("direct"),
1000
+ listPublicMemberships: availability("direct"),
1001
+ getPublicFormById: content(["site_forms"]),
1002
+ getPublicBookingServices: availability("direct"),
1003
+ getPublicBookingService: availability("direct"),
1004
+ getPublicBookingResourcesReference: availability("direct"),
1005
+ getPublicBookingAvailableDates: availability("direct"),
1006
+ getPublicBookingAvailableSlots: availability("direct"),
1007
+ getPublicWeeklySlotAvailability: availability("direct"),
1008
+ listPublicForms: content(["site_forms"]),
1009
+ checkRedirect: content([]),
1010
+ getPublicRoutableContent: content(["published_content"]),
1011
+ getPublicSitemapRoutes: content(["published_content"])
1012
+ };
1013
+ new Set(Object.keys(PUBLIC_READ_CACHE_POLICIES));
1014
+ function getPublicReadCachePolicy(endpoint) {
1015
+ return PUBLIC_READ_CACHE_POLICIES[endpoint];
1016
+ }
1017
+ function publicReadFreshnessSeconds(endpoint) {
1018
+ return getPublicReadCachePolicy(endpoint).freshness === "availability" ? 60 : PUBLIC_CONTENT_FRESHNESS_SECONDS;
1019
+ }
558
1020
  //#endregion
559
1021
  //#region ../core/src/event-series-behaviour.ts
560
1022
  const WHOLE_SERIES_EVENT_PRESET_VALUES = ["course", "term"];
@@ -2551,59 +3013,108 @@ function interpolateHex(startHex, endHex, position) {
2551
3013
  const channel = (from, to) => Math.round(from + (to - from) * position).toString(16).padStart(2, "0");
2552
3014
  return `#${channel(start.r, end.r)}${channel(start.g, end.g)}${channel(start.b, end.b)}`;
2553
3015
  }
2554
- shadeBackgroundEffect({
2555
- id: "darken-background",
2556
- name: "Darken on Hover",
2557
- description: "Darkens the background color on hover",
2558
- label: "Darken Amount (shade step)",
2559
- shadeDirection: 1
2560
- });
2561
- shadeBackgroundEffect({
2562
- id: "lighten-background",
2563
- name: "Lighten on Hover",
2564
- description: "Lightens the background color on hover",
2565
- label: "Lighten Amount (shade step)",
2566
- shadeDirection: -1
2567
- });
2568
- function shadeBackgroundEffect(config) {
2569
- return {
2570
- id: config.id,
2571
- name: config.name,
2572
- description: config.description,
2573
- category: "background",
2574
- pseudoElement: "none",
2575
- applicableTo: ["button"],
2576
- customizableOption: {
2577
- name: "amount",
2578
- type: "select",
2579
- label: config.label,
2580
- default: 100,
2581
- options: [
2582
- 0,
2583
- 100,
2584
- 200,
2585
- 300,
2586
- 400,
2587
- 500,
2588
- 600,
2589
- 700,
2590
- 800,
2591
- 900
2592
- ]
3016
+ //#endregion
3017
+ //#region ../theme-core/src/tokens/tokens.ts
3018
+ const defaultThemeTokens = {
3019
+ color: {
3020
+ "background/base": "#ffffff",
3021
+ "background/elevated": "#f5f5f5",
3022
+ "surface/base": "#ffffff",
3023
+ "surface/subtle": "#f9f9fb",
3024
+ "surface/inverted": "#111111",
3025
+ "content/primary": "#111111",
3026
+ "content/secondary": "#3f3f46",
3027
+ "accent/primary": "#2563eb",
3028
+ "accent/secondary": "#1d4ed8",
3029
+ "border/base": "#e5e7eb"
3030
+ },
3031
+ typography: {
3032
+ "display/hero": {
3033
+ fontSize: "clamp(48px, 8vw, 96px)",
3034
+ lineHeight: "1.05",
3035
+ fontWeight: "700"
2593
3036
  },
2594
- isApplicable: (buttonConfig) => buttonConfig.background.type === "solid",
2595
- generateCSS: ({ themeId, variantId, options, tokens, buttonConfig }) => {
2596
- if (buttonConfig.background.type !== "solid") return "";
2597
- const amount = (options.amount || 100) * config.shadeDirection;
2598
- const baseToken = buttonConfig.background.colorToken ?? "primary-500";
2599
- return `
2600
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
2601
- background-color: ${tokens.getColor(tokens.adjustShade(baseToken, amount))};
2602
- }
2603
- `;
3037
+ "display/section": {
3038
+ fontSize: "clamp(40px, 6vw, 72px)",
3039
+ lineHeight: "1.1",
3040
+ fontWeight: "700"
3041
+ },
3042
+ "heading/large": {
3043
+ fontSize: "clamp(32px, 4vw, 48px)",
3044
+ lineHeight: "1.2",
3045
+ fontWeight: "600"
3046
+ },
3047
+ "heading/medium": {
3048
+ fontSize: "clamp(24px, 3vw, 32px)",
3049
+ lineHeight: "1.25",
3050
+ fontWeight: "600"
3051
+ },
3052
+ "heading/small": {
3053
+ fontSize: "20px",
3054
+ lineHeight: "1.3",
3055
+ fontWeight: "600"
3056
+ },
3057
+ "body/normal": {
3058
+ fontSize: "16px",
3059
+ lineHeight: "1.6",
3060
+ fontWeight: "400"
3061
+ },
3062
+ "body/small": {
3063
+ fontSize: "14px",
3064
+ lineHeight: "1.5",
3065
+ fontWeight: "400"
3066
+ },
3067
+ caption: {
3068
+ fontSize: "12px",
3069
+ lineHeight: "1.4",
3070
+ fontWeight: "500"
2604
3071
  }
2605
- };
2606
- }
3072
+ },
3073
+ spacing: {
3074
+ none: "0px",
3075
+ "3xs": "4px",
3076
+ "2xs": "8px",
3077
+ xs: "12px",
3078
+ sm: "16px",
3079
+ md: "24px",
3080
+ lg: "32px",
3081
+ xl: "40px",
3082
+ "2xl": "56px",
3083
+ "3xl": "72px"
3084
+ },
3085
+ radius: {
3086
+ none: "0px",
3087
+ xs: "2px",
3088
+ sm: "4px",
3089
+ md: "8px",
3090
+ lg: "12px",
3091
+ pill: "999px",
3092
+ full: "9999px"
3093
+ },
3094
+ shadow: {
3095
+ none: "none",
3096
+ soft: "0px 2px 8px rgba(15, 23, 42, 0.08)",
3097
+ medium: "0px 6px 18px rgba(15, 23, 42, 0.12)",
3098
+ strong: "0px 12px 36px rgba(15, 23, 42, 0.16)"
3099
+ },
3100
+ palette: {
3101
+ surface: "#ffffff",
3102
+ "neutral-50": "#f9fafb",
3103
+ "neutral-900": "#111827",
3104
+ primary: "#2563eb",
3105
+ "primary-50": "#eff6ff",
3106
+ "primary-500": "#2563eb",
3107
+ "primary-900": "#1d4ed8",
3108
+ secondary: "#9333ea",
3109
+ "secondary-50": "#f3e8ff",
3110
+ "secondary-500": "#9333ea",
3111
+ "secondary-900": "#4c1d95",
3112
+ accent: "#f97316",
3113
+ "accent-50": "#fff7ed",
3114
+ "accent-500": "#f97316",
3115
+ "accent-900": "#7c2d12"
3116
+ }
3117
+ };
2607
3118
  //#endregion
2608
3119
  //#region ../theme-core/src/palette/utils/opaqueSurfaceColor.ts
2609
3120
  /** Resolve an opaque colour, compositing alpha against an explicit underlay. */
@@ -2888,6 +3399,59 @@ function mergeStyles(...styles) {
2888
3399
  }
2889
3400
  return Object.keys(merged).length ? merged : void 0;
2890
3401
  }
3402
+ shadeBackgroundEffect({
3403
+ id: "darken-background",
3404
+ name: "Darken on Hover",
3405
+ description: "Darkens the background color on hover",
3406
+ label: "Darken Amount (shade step)",
3407
+ shadeDirection: 1
3408
+ });
3409
+ shadeBackgroundEffect({
3410
+ id: "lighten-background",
3411
+ name: "Lighten on Hover",
3412
+ description: "Lightens the background color on hover",
3413
+ label: "Lighten Amount (shade step)",
3414
+ shadeDirection: -1
3415
+ });
3416
+ function shadeBackgroundEffect(config) {
3417
+ return {
3418
+ id: config.id,
3419
+ name: config.name,
3420
+ description: config.description,
3421
+ category: "background",
3422
+ pseudoElement: "none",
3423
+ applicableTo: ["button"],
3424
+ customizableOption: {
3425
+ name: "amount",
3426
+ type: "select",
3427
+ label: config.label,
3428
+ default: 100,
3429
+ options: [
3430
+ 0,
3431
+ 100,
3432
+ 200,
3433
+ 300,
3434
+ 400,
3435
+ 500,
3436
+ 600,
3437
+ 700,
3438
+ 800,
3439
+ 900
3440
+ ]
3441
+ },
3442
+ isApplicable: (buttonConfig) => buttonConfig.background.type === "solid",
3443
+ generateCSS: ({ themeId, variantId, options, tokens, buttonConfig }) => {
3444
+ if (buttonConfig.background.type !== "solid") return "";
3445
+ const amount = (options.amount || 100) * config.shadeDirection;
3446
+ const baseToken = buttonConfig.background.colorToken ?? "primary-500";
3447
+ return `
3448
+ :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
3449
+ background-color: ${tokens.getColor(tokens.adjustShade(baseToken, amount))};
3450
+ }
3451
+ `;
3452
+ }
3453
+ };
3454
+ }
2891
3455
  //#endregion
2892
3456
  //#region ../theme-core/src/utils/tokenOrColor.ts
2893
3457
  /**
@@ -6310,8 +6874,14 @@ const headerInteractionPillPaletteValues = [
6310
6874
  "accent"
6311
6875
  ];
6312
6876
  /**
6313
- * "No pill": the nav link keeps whatever hover treatment its recipe compiled,
6314
- * and the palette step writes nothing at all (#1318 Phase 4c decision 2).
6877
+ * "No pill": a colour change on hover rather than a filled background.
6878
+ *
6879
+ * The palette step writes nothing (#1318 Phase 4c decision 2), but on a
6880
+ * foreground-adaptive style that is not the end of the story: the hover colour
6881
+ * is derived from the resolved opening foreground at render time, paired with
6882
+ * the resting colour, so `quiet` resolves to a definite colour rather than to
6883
+ * whatever brand token the recipe happened to name. See
6884
+ * `applyOpeningForeground`.
6315
6885
  *
6316
6886
  * It exists because "a colour change on hover, no filled background" was not
6317
6887
  * expressible in the vocabulary, and it is what
@@ -7303,6 +7873,28 @@ const bookingRequirementConsentFieldSchema = z.object({
7303
7873
  z.union([blockBookingConsentSchema, bookingRequirementConsentFieldSchema]);
7304
7874
  //#endregion
7305
7875
  //#region ../blocks/src/system/blocks/events/shared/schemas.ts
7876
+ const publicEventLoaderQuerySchemaShape = {
7877
+ limit: z.string().optional(),
7878
+ from: z.string().optional(),
7879
+ to: z.string().optional(),
7880
+ afterStartsAt: z.string().optional(),
7881
+ afterId: z.string().optional(),
7882
+ categoryIds: z.string().optional(),
7883
+ venueId: z.string().optional(),
7884
+ staffMemberId: z.string().optional(),
7885
+ eventSurface: z.string().optional(),
7886
+ eventPresets: z.string().optional(),
7887
+ scheduleScope: z.string().optional(),
7888
+ seriesId: z.string().optional(),
7889
+ seriesIds: z.string().optional(),
7890
+ runSeriesId: z.string().optional(),
7891
+ seriesSlug: z.string().optional(),
7892
+ includeOccurrenceId: z.string().optional(),
7893
+ readIntent: z.string().optional(),
7894
+ detailLevel: z.string().optional(),
7895
+ readProfile: z.string().optional()
7896
+ };
7897
+ z.object(publicEventLoaderQuerySchemaShape);
7306
7898
  const eventPresetSchema = z.enum([
7307
7899
  "event",
7308
7900
  "class",
@@ -7761,6 +8353,14 @@ const calendarWindowPageSchema = z.discriminatedUnion("kind", [z.object({
7761
8353
  kind: z.literal("partial"),
7762
8354
  nextCursor: calendarSourceCursorSchema
7763
8355
  })]);
8356
+ //#endregion
8357
+ //#region ../api/src/apiEndpointTypes.ts
8358
+ function allowedDemoMutationPolicy() {
8359
+ return {
8360
+ classification: "allowed",
8361
+ publicMessage: ""
8362
+ };
8363
+ }
7764
8364
  function blockedDemoMutationPolicy(classification, publicMessage) {
7765
8365
  if (publicMessage.trim() === "") throw new Error(`Demo mutation policy ${classification} requires publicMessage.`);
7766
8366
  return {
@@ -7773,6 +8373,7 @@ function blockedDemoMutationPolicy(classification, publicMessage) {
7773
8373
  const DEMO_MUTATION_BLOCKED_HIDDEN = blockedDemoMutationPolicy("blocked-hidden", "This action is not available in demo sites.");
7774
8374
  const DEMO_MUTATION_BLOCKED_DISABLED = blockedDemoMutationPolicy("blocked-disabled", "This setting is disabled in demo sites.");
7775
8375
  blockedDemoMutationPolicy("internal-only", "This internal operation is not available in demo sites.");
8376
+ const DEMO_MUTATION_ALLOWED = allowedDemoMutationPolicy();
7776
8377
  //#endregion
7777
8378
  //#region ../api/src/cache-tags.ts
7778
8379
  /**
@@ -8704,14 +9305,117 @@ const NEWSLETTER_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
8704
9305
  responseKind: "json",
8705
9306
  errors: ["auth:forbidden", "server:internal_error"]
8706
9307
  },
8707
- getMailchimpSignupSyncHealth: {
8708
- path: "/sites/{siteId}/integrations/mailchimp/signup-sync-health",
9308
+ getMailingListSetup: {
9309
+ path: "/sites/{siteId}/mailing-list/setup",
9310
+ method: "GET",
9311
+ tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
9312
+ auth: "user",
9313
+ responseKind: "json",
9314
+ errors: ["auth:forbidden", "server:internal_error"]
9315
+ },
9316
+ getMailingListAuthoringContext: {
9317
+ path: "/sites/{siteId}/mailing-list/authoring-context",
9318
+ method: "GET",
9319
+ tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
9320
+ auth: "user",
9321
+ responseKind: "json",
9322
+ errors: ["auth:forbidden", "server:internal_error"]
9323
+ },
9324
+ previewMailingListSetupChange: {
9325
+ path: "/sites/{siteId}/mailing-list/setup/preview",
9326
+ method: "POST",
9327
+ tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
9328
+ auth: "user",
9329
+ responseKind: "json",
9330
+ demoMutation: DEMO_MUTATION_ALLOWED,
9331
+ errors: [
9332
+ "auth:forbidden",
9333
+ "validation:invalid_input",
9334
+ "server:internal_error"
9335
+ ]
9336
+ },
9337
+ applyMailingListSetupChange: {
9338
+ path: "/sites/{siteId}/mailing-list/setup",
9339
+ method: "PUT",
9340
+ tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
9341
+ auth: "user",
9342
+ responseKind: "json",
9343
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
9344
+ errors: [
9345
+ "auth:forbidden",
9346
+ "validation:invalid_input",
9347
+ "resource:conflict",
9348
+ "server:internal_error"
9349
+ ]
9350
+ },
9351
+ getMailingListProviderCatalog: {
9352
+ path: "/sites/{siteId}/mailing-list/providers/{provider}/catalog",
9353
+ method: "GET",
9354
+ tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
9355
+ auth: "user",
9356
+ responseKind: "json",
9357
+ errors: [
9358
+ "auth:forbidden",
9359
+ "validation:invalid_input",
9360
+ "server:internal_error"
9361
+ ]
9362
+ },
9363
+ refreshMailingListProviderCatalog: {
9364
+ path: "/sites/{siteId}/mailing-list/providers/{provider}/catalog/refresh",
9365
+ method: "POST",
9366
+ tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
9367
+ auth: "user",
9368
+ responseKind: "json",
9369
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
9370
+ errors: [
9371
+ "auth:forbidden",
9372
+ "validation:invalid_input",
9373
+ "server:internal_error"
9374
+ ]
9375
+ },
9376
+ getMailingListProviderHealth: {
9377
+ path: "/sites/{siteId}/mailing-list/health",
9378
+ method: "GET",
9379
+ tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
9380
+ auth: "user",
9381
+ responseKind: "json",
9382
+ errors: ["auth:forbidden", "server:internal_error"]
9383
+ },
9384
+ getBrevoConnection: {
9385
+ path: "/sites/{siteId}/integrations/brevo/connection",
8709
9386
  method: "GET",
8710
9387
  tags: [TAG_TEMPLATES.site],
8711
9388
  auth: "user",
8712
9389
  responseKind: "json",
8713
9390
  errors: ["auth:forbidden", "server:internal_error"]
8714
9391
  },
9392
+ connectBrevo: {
9393
+ path: "/sites/{siteId}/integrations/brevo/connection",
9394
+ method: "PUT",
9395
+ tags: [TAG_TEMPLATES.site],
9396
+ auth: "user",
9397
+ responseKind: "json",
9398
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
9399
+ errors: [
9400
+ "auth:forbidden",
9401
+ "validation:invalid_input",
9402
+ "resource:conflict",
9403
+ "server:internal_error"
9404
+ ]
9405
+ },
9406
+ disconnectBrevo: {
9407
+ path: "/sites/{siteId}/integrations/brevo/disconnect",
9408
+ method: "POST",
9409
+ tags: [TAG_TEMPLATES.site],
9410
+ auth: "user",
9411
+ responseKind: "json",
9412
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
9413
+ errors: [
9414
+ "auth:forbidden",
9415
+ "resource:conflict",
9416
+ "server:internal_error"
9417
+ ]
9418
+ },
8715
9419
  getMailchimpConnection: {
8716
9420
  path: "/sites/{siteId}/integrations/mailchimp/connection",
8717
9421
  method: "GET",
@@ -8967,7 +9671,7 @@ const PUBLIC_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
8967
9671
  resolveEventSubroute: {
8968
9672
  path: "/public/sites/{siteId}/events/subroutes/resolve",
8969
9673
  method: "GET",
8970
- revalidate: 60,
9674
+ revalidate: publicReadFreshnessSeconds("resolveEventSubroute"),
8971
9675
  tags: [TAG_TEMPLATES.publicEvents, "event-subroute"],
8972
9676
  auth: "public",
8973
9677
  responseKind: "json",
@@ -9020,7 +9724,7 @@ const PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS = defineEndpointDefinitio
9020
9724
  getPublicBookingServices: {
9021
9725
  path: "/public/bookings/services",
9022
9726
  method: "GET",
9023
- revalidate: 60,
9727
+ revalidate: publicReadFreshnessSeconds("getPublicBookingServices"),
9024
9728
  tags: [TAG_TEMPLATES.publicBookingServices],
9025
9729
  auth: "public",
9026
9730
  responseKind: "json"
@@ -9028,7 +9732,15 @@ const PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS = defineEndpointDefinitio
9028
9732
  getPublicBookingService: {
9029
9733
  path: "/public/bookings/services/{serviceId}",
9030
9734
  method: "GET",
9031
- revalidate: 60,
9735
+ revalidate: publicReadFreshnessSeconds("getPublicBookingService"),
9736
+ tags: [TAG_TEMPLATES.publicBookingServices],
9737
+ auth: "public",
9738
+ responseKind: "json"
9739
+ },
9740
+ getPublicBookingServiceBySlug: {
9741
+ path: "/public/bookings/services/by-slug/{slug}",
9742
+ method: "GET",
9743
+ revalidate: publicReadFreshnessSeconds("getPublicBookingService"),
9032
9744
  tags: [TAG_TEMPLATES.publicBookingServices],
9033
9745
  auth: "public",
9034
9746
  responseKind: "json"
@@ -9036,7 +9748,7 @@ const PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS = defineEndpointDefinitio
9036
9748
  getPublicBookingResourcesReference: {
9037
9749
  path: "/public/bookings/resources/reference",
9038
9750
  method: "GET",
9039
- revalidate: 60,
9751
+ revalidate: publicReadFreshnessSeconds("getPublicBookingResourcesReference"),
9040
9752
  tags: [TAG_TEMPLATES.publicBookingServices],
9041
9753
  auth: "public",
9042
9754
  responseKind: "json"
@@ -9044,7 +9756,7 @@ const PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS = defineEndpointDefinitio
9044
9756
  getPublicBookingAvailableDates: {
9045
9757
  path: "/public/bookings/availability/dates",
9046
9758
  method: "GET",
9047
- revalidate: 60,
9759
+ revalidate: publicReadFreshnessSeconds("getPublicBookingAvailableDates"),
9048
9760
  tags: [TAG_TEMPLATES.publicBookingAvailability, TAG_TEMPLATES.publicBookingServices],
9049
9761
  auth: "public",
9050
9762
  responseKind: "json"
@@ -9052,7 +9764,7 @@ const PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS = defineEndpointDefinitio
9052
9764
  getPublicBookingAvailableSlots: {
9053
9765
  path: "/public/bookings/availability/slots",
9054
9766
  method: "GET",
9055
- revalidate: 60,
9767
+ revalidate: publicReadFreshnessSeconds("getPublicBookingAvailableSlots"),
9056
9768
  tags: [TAG_TEMPLATES.publicBookingAvailability, TAG_TEMPLATES.publicBookingServices],
9057
9769
  auth: "public",
9058
9770
  responseKind: "json"
@@ -9060,7 +9772,7 @@ const PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS = defineEndpointDefinitio
9060
9772
  getPublicWeeklySlotAvailability: {
9061
9773
  path: "/public/bookings/weekly-slot-availability",
9062
9774
  method: "GET",
9063
- revalidate: 60,
9775
+ revalidate: publicReadFreshnessSeconds("getPublicWeeklySlotAvailability"),
9064
9776
  tags: [TAG_TEMPLATES.publicBookingAvailability, TAG_TEMPLATES.publicBookingServices],
9065
9777
  auth: "public",
9066
9778
  responseKind: "json",
@@ -9510,15 +10222,185 @@ const SDK_MEDIA_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
9510
10222
  responseKind: "json"
9511
10223
  }
9512
10224
  });
10225
+ //#endregion
10226
+ //#region ../api/src/publicReadEndpointDefinitions.ts
10227
+ /**
10228
+ * Direct public reads governed by the canonical public-read freshness policy.
10229
+ * Keeping these definitions together makes the endpoint identity used to
10230
+ * derive freshness reviewable beside its route and tags.
10231
+ */
10232
+ const PUBLIC_READ_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
10233
+ getPublishedEntryPreview: {
10234
+ path: "/public/content/{siteId}/{type}/{slug}/preview",
10235
+ method: "GET",
10236
+ revalidate: publicReadFreshnessSeconds("getPublishedEntryPreview"),
10237
+ tags: ["content-{siteId}-{type}-{slug}"],
10238
+ auth: "public",
10239
+ responseKind: "json"
10240
+ },
10241
+ listPublishedEntries: {
10242
+ path: "/public/content/{siteId}/{type}/entries",
10243
+ method: "GET",
10244
+ revalidate: publicReadFreshnessSeconds("listPublishedEntries"),
10245
+ tags: ["content-{siteId}-{type}"],
10246
+ auth: "public",
10247
+ responseKind: "json"
10248
+ },
10249
+ getPublicFormById: {
10250
+ path: "/public/forms/{formId}",
10251
+ method: "GET",
10252
+ revalidate: publicReadFreshnessSeconds("getPublicFormById"),
10253
+ tags: [TAG_TEMPLATES.formById],
10254
+ auth: "public",
10255
+ responseKind: "json"
10256
+ },
10257
+ listPublicEvents: {
10258
+ path: "/public/sites/{siteId}/events",
10259
+ method: "GET",
10260
+ revalidate: publicReadFreshnessSeconds("listPublicEvents"),
10261
+ tags: [TAG_TEMPLATES.publicEvents],
10262
+ auth: "public",
10263
+ responseKind: "json"
10264
+ },
10265
+ listPublicTeamMembers: {
10266
+ path: "/public/sites/{siteId}/team-members",
10267
+ method: "GET",
10268
+ revalidate: publicReadFreshnessSeconds("listPublicTeamMembers"),
10269
+ tags: [TAG_TEMPLATES.publicTeamMembers],
10270
+ errors: [],
10271
+ auth: "public",
10272
+ responseKind: "json"
10273
+ },
10274
+ listPublicPasses: {
10275
+ path: "/public/sites/{siteId}/bookings/products/passes",
10276
+ method: "GET",
10277
+ revalidate: publicReadFreshnessSeconds("listPublicPasses"),
10278
+ tags: [TAG_TEMPLATES.publicPasses],
10279
+ auth: "public",
10280
+ responseKind: "json"
10281
+ },
10282
+ listPublicMemberships: {
10283
+ path: "/public/sites/{siteId}/bookings/products/memberships",
10284
+ method: "GET",
10285
+ revalidate: publicReadFreshnessSeconds("listPublicMemberships"),
10286
+ tags: [TAG_TEMPLATES.publicMemberships],
10287
+ auth: "public",
10288
+ responseKind: "json"
10289
+ },
10290
+ listPublicProducts: {
10291
+ path: "/public/sites/{siteId}/products",
10292
+ method: "GET",
10293
+ revalidate: publicReadFreshnessSeconds("listPublicProducts"),
10294
+ tags: [TAG_TEMPLATES.publicProducts],
10295
+ errors: [],
10296
+ auth: "public",
10297
+ responseKind: "json"
10298
+ }
10299
+ });
10300
+ //#endregion
10301
+ //#region ../api/src/publicOnboardingAttemptEndpointDefinitions.ts
10302
+ /**
10303
+ * The anonymous onboarding attempt, addressed by its opaque resume token.
10304
+ *
10305
+ * Every route here is reached before there is an account, so none of them can
10306
+ * be scoped to a site or a user: the token is the whole credential. They are
10307
+ * kept together so that stays obvious.
10308
+ */
10309
+ const PUBLIC_ONBOARDING_ATTEMPT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
10310
+ createPublicOnboardingAttempt: {
10311
+ path: "/public/onboarding/attempts",
10312
+ method: "POST",
10313
+ auth: "public",
10314
+ errors: [],
10315
+ responseKind: "json"
10316
+ },
10317
+ createPublicOnboardingLogoUploadUrl: {
10318
+ path: "/public/onboarding/attempts/{attemptToken}/logo-upload-url",
10319
+ method: "POST",
10320
+ auth: "public",
10321
+ errors: [],
10322
+ responseKind: "json"
10323
+ },
10324
+ uploadPublicOnboardingLogo: {
10325
+ path: "/public/onboarding/attempts/{attemptToken}/logo",
10326
+ method: "POST",
10327
+ auth: "public",
10328
+ errors: [],
10329
+ responseKind: "json"
10330
+ },
10331
+ getPublicOnboardingAttempt: {
10332
+ path: "/public/onboarding/attempts/{attemptToken}",
10333
+ method: "GET",
10334
+ auth: "public",
10335
+ errors: [],
10336
+ responseKind: "json"
10337
+ },
10338
+ getPublicOnboardingAttemptProgress: {
10339
+ path: "/public/onboarding/attempts/{attemptToken}/status",
10340
+ method: "GET",
10341
+ auth: "public",
10342
+ errors: [],
10343
+ responseKind: "json"
10344
+ },
10345
+ updatePublicOnboardingAttempt: {
10346
+ path: "/public/onboarding/attempts/{attemptToken}",
10347
+ method: "PATCH",
10348
+ auth: "public",
10349
+ errors: [],
10350
+ responseKind: "json"
10351
+ },
10352
+ runPublicOnboardingAttempt: {
10353
+ path: "/public/onboarding/attempts/{attemptToken}/run",
10354
+ method: "POST",
10355
+ auth: "public",
10356
+ errors: [],
10357
+ responseKind: "json"
10358
+ },
10359
+ resendPublicOnboardingAttemptConfirmation: {
10360
+ path: "/public/onboarding/attempts/{attemptToken}/resend-confirmation",
10361
+ method: "POST",
10362
+ auth: "public",
10363
+ errors: [],
10364
+ responseKind: "json"
10365
+ }
10366
+ });
10367
+ //#endregion
10368
+ //#region ../api/src/billingEndpointDefinitions.ts
10369
+ const BILLING_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
10370
+ adminChangePlan: {
10371
+ path: "/admin/billing/plan",
10372
+ method: "POST",
10373
+ tags: ["admin", "billing"],
10374
+ auth: "admin",
10375
+ responseKind: "json"
10376
+ },
10377
+ changePlan: {
10378
+ path: "/billing/plan/change",
10379
+ method: "POST",
10380
+ tags: ["billing"],
10381
+ auth: "user",
10382
+ responseKind: "json"
10383
+ },
10384
+ createBillingPortalSession: {
10385
+ path: "/billing/portal/session",
10386
+ method: "POST",
10387
+ tags: ["billing"],
10388
+ auth: "user",
10389
+ responseKind: "json"
10390
+ }
10391
+ });
9513
10392
  ({
9514
10393
  ...ACCOUNT_ENDPOINT_DEFINITIONS,
10394
+ ...PUBLIC_ONBOARDING_ATTEMPT_ENDPOINT_DEFINITIONS,
9515
10395
  ...PUBLIC_EVENT_ENDPOINT_DEFINITIONS,
9516
- ...GIFTING_ENDPOINT_DEFINITIONS
10396
+ ...GIFTING_ENDPOINT_DEFINITIONS,
10397
+ ...PUBLIC_READ_ENDPOINT_DEFINITIONS,
10398
+ ...BILLING_ENDPOINT_DEFINITIONS
9517
10399
  }), TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, { ...SITE_API_KEY_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.site, TAG_TEMPLATES.siteBookingSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteBookingSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, {
9518
10400
  ...NEWSLETTER_ENDPOINT_DEFINITIONS,
9519
10401
  ...APPOINTMENT_ENDPOINT_DEFINITIONS,
9520
10402
  ...EVENT_SERIES_REGISTRATION_ENDPOINT_DEFINITIONS
9521
- }, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.workflowRunById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.routeById, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.formById, TAG_TEMPLATES.siteForms, { ...PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEventFilters, TAG_TEMPLATES.publicTeamMembers, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicPasses, TAG_TEMPLATES.publicMemberships, TAG_TEMPLATES.publicProducts, TAG_TEMPLATES.publicShop, TAG_TEMPLATES.publicCheckout, TAG_TEMPLATES.siteRoutableContent, { ...PUBLIC_EVENT_CHECKOUT_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, { ...EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS }, { ...SDK_MEDIA_ENDPOINT_DEFINITIONS }, { ...SDK_ENDPOINT_DEFINITIONS }, { ...SDK_ENTRY_READ_ENDPOINTS };
10403
+ }, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.workflowRunById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.routeById, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicBookingServices, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, { ...PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.publicEventFilters, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicShop, TAG_TEMPLATES.publicCheckout, TAG_TEMPLATES.siteRoutableContent, { ...PUBLIC_EVENT_CHECKOUT_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, { ...EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS }, { ...SDK_MEDIA_ENDPOINT_DEFINITIONS }, { ...SDK_ENDPOINT_DEFINITIONS }, { ...SDK_ENTRY_READ_ENDPOINTS };
9522
10404
  z.object({ refreshToken: z.string().min(1).max(4096) }).strict();
9523
10405
  z.object({
9524
10406
  accessToken: z.string().min(1).max(4096),
@@ -11787,108 +12669,6 @@ function assertUniqueLayoutProfileKeys(profiles) {
11787
12669
  if (duplicates.length > 0) throw new Error(`Duplicate block layout design profiles: ${duplicates.join(", ")}`);
11788
12670
  }
11789
12671
  //#endregion
11790
- //#region ../theme-core/src/tokens/tokens.ts
11791
- const defaultThemeTokens = {
11792
- color: {
11793
- "background/base": "#ffffff",
11794
- "background/elevated": "#f5f5f5",
11795
- "surface/base": "#ffffff",
11796
- "surface/subtle": "#f9f9fb",
11797
- "surface/inverted": "#111111",
11798
- "content/primary": "#111111",
11799
- "content/secondary": "#3f3f46",
11800
- "accent/primary": "#2563eb",
11801
- "accent/secondary": "#1d4ed8",
11802
- "border/base": "#e5e7eb"
11803
- },
11804
- typography: {
11805
- "display/hero": {
11806
- fontSize: "clamp(48px, 8vw, 96px)",
11807
- lineHeight: "1.05",
11808
- fontWeight: "700"
11809
- },
11810
- "display/section": {
11811
- fontSize: "clamp(40px, 6vw, 72px)",
11812
- lineHeight: "1.1",
11813
- fontWeight: "700"
11814
- },
11815
- "heading/large": {
11816
- fontSize: "clamp(32px, 4vw, 48px)",
11817
- lineHeight: "1.2",
11818
- fontWeight: "600"
11819
- },
11820
- "heading/medium": {
11821
- fontSize: "clamp(24px, 3vw, 32px)",
11822
- lineHeight: "1.25",
11823
- fontWeight: "600"
11824
- },
11825
- "heading/small": {
11826
- fontSize: "20px",
11827
- lineHeight: "1.3",
11828
- fontWeight: "600"
11829
- },
11830
- "body/normal": {
11831
- fontSize: "16px",
11832
- lineHeight: "1.6",
11833
- fontWeight: "400"
11834
- },
11835
- "body/small": {
11836
- fontSize: "14px",
11837
- lineHeight: "1.5",
11838
- fontWeight: "400"
11839
- },
11840
- caption: {
11841
- fontSize: "12px",
11842
- lineHeight: "1.4",
11843
- fontWeight: "500"
11844
- }
11845
- },
11846
- spacing: {
11847
- none: "0px",
11848
- "3xs": "4px",
11849
- "2xs": "8px",
11850
- xs: "12px",
11851
- sm: "16px",
11852
- md: "24px",
11853
- lg: "32px",
11854
- xl: "40px",
11855
- "2xl": "56px",
11856
- "3xl": "72px"
11857
- },
11858
- radius: {
11859
- none: "0px",
11860
- xs: "2px",
11861
- sm: "4px",
11862
- md: "8px",
11863
- lg: "12px",
11864
- pill: "999px",
11865
- full: "9999px"
11866
- },
11867
- shadow: {
11868
- none: "none",
11869
- soft: "0px 2px 8px rgba(15, 23, 42, 0.08)",
11870
- medium: "0px 6px 18px rgba(15, 23, 42, 0.12)",
11871
- strong: "0px 12px 36px rgba(15, 23, 42, 0.16)"
11872
- },
11873
- palette: {
11874
- surface: "#ffffff",
11875
- "neutral-50": "#f9fafb",
11876
- "neutral-900": "#111827",
11877
- primary: "#2563eb",
11878
- "primary-50": "#eff6ff",
11879
- "primary-500": "#2563eb",
11880
- "primary-900": "#1d4ed8",
11881
- secondary: "#9333ea",
11882
- "secondary-50": "#f3e8ff",
11883
- "secondary-500": "#9333ea",
11884
- "secondary-900": "#4c1d95",
11885
- accent: "#f97316",
11886
- "accent-50": "#fff7ed",
11887
- "accent-500": "#f97316",
11888
- "accent-900": "#7c2d12"
11889
- }
11890
- };
11891
- //#endregion
11892
12672
  //#region ../theme-core/src/site-styles/backgroundAppearance.ts
11893
12673
  const backgroundAppearanceQuickColorTokenNames = [
11894
12674
  "background",
@@ -21273,102 +22053,31 @@ const newsletterFormFragment = defineFragment({
21273
22053
  description: "Newsletter subscription form with preset field configurations.",
21274
22054
  fields: [
21275
22055
  {
21276
- id: "destinationProvider",
21277
- type: "select",
21278
- label: "Send signups to",
21279
- description: "Choose where new subscribers from this form should go.",
21280
- defaultValue: "riverbank",
21281
- required: false,
21282
- ui: { intent: "behavior" },
21283
- options: [{
21284
- value: "riverbank",
21285
- label: "Riverbank newsletter"
21286
- }]
21287
- },
21288
- {
21289
- id: "listId",
21290
- type: "reference",
21291
- label: "Newsletter list",
21292
- description: "Select the list new subscribers should be added to.",
21293
- required: false,
21294
- referenceKind: "newsletterList",
21295
- allowManualEntry: false,
21296
- ui: {
21297
- intent: "behavior",
21298
- visibleWhen: {
21299
- field: "destinationProvider",
21300
- equals: "riverbank"
21301
- }
21302
- }
21303
- },
21304
- {
21305
- id: "mailchimpAudienceId",
21306
- type: "reference",
21307
- label: "Mailchimp audience",
21308
- description: "Choose the Mailchimp audience for new subscribers.",
21309
- required: false,
21310
- referenceKind: "mailchimpAudience",
21311
- allowManualEntry: false,
21312
- ui: {
21313
- intent: "behavior",
21314
- visibleWhen: {
21315
- field: "destinationProvider",
21316
- equals: "mailchimp"
21317
- }
21318
- }
21319
- },
21320
- {
21321
- id: "mailchimpTags",
21322
- type: "text",
21323
- label: "Mailchimp tags",
21324
- description: "Optional tags to apply in Mailchimp, separated by commas or semicolons.",
22056
+ id: "targeting",
22057
+ type: "group",
22058
+ label: "Mailing-list targeting",
22059
+ description: "Choose what kind of emails people signing up here will receive.",
22060
+ defaultValue: { mode: "default" },
22061
+ required: true,
21325
22062
  ui: {
21326
22063
  intent: "behavior",
21327
- visibleWhen: {
21328
- field: "destinationProvider",
21329
- equals: "mailchimp"
21330
- }
21331
- }
21332
- },
21333
- {
21334
- id: "preset",
21335
- type: "select",
21336
- label: "Form fields",
21337
- description: "Choose which fields to collect.",
21338
- defaultValue: "emailOnly",
21339
- ui: { intent: "display" },
21340
- options: [
21341
- {
21342
- value: "emailOnly",
21343
- label: "Email only"
21344
- },
21345
- {
21346
- value: "emailName",
21347
- label: "Email + Name"
21348
- },
21349
- {
21350
- value: "emailFirstLast",
21351
- label: "Email + First/Last Name"
21352
- },
21353
- {
21354
- value: "emailNameCompany",
21355
- label: "Email + Name + Company (B2B)"
21356
- }
21357
- ]
21358
- },
21359
- {
21360
- id: "includePhone",
21361
- type: "boolean",
21362
- label: "Include phone field (optional)",
21363
- description: "Adds an optional phone field to the selected preset (never required).",
21364
- defaultValue: false,
21365
- ui: { intent: "display" }
21366
- },
21367
- {
21368
- id: "buttonLabel",
21369
- type: "text",
21370
- label: "Button label",
21371
- defaultValue: "Subscribe"
22064
+ widget: "mailingListTargeting"
22065
+ },
22066
+ schema: { fields: [{
22067
+ id: "mode",
22068
+ type: "select",
22069
+ label: "Mode",
22070
+ required: true,
22071
+ defaultValue: "default",
22072
+ options: [{
22073
+ value: "default",
22074
+ label: "Default"
22075
+ }, {
22076
+ value: "custom",
22077
+ label: "Custom"
22078
+ }],
22079
+ ui: { hidden: true }
22080
+ }] }
21372
22081
  },
21373
22082
  createButtonVariantField({
21374
22083
  id: "buttonVariant",
@@ -21376,46 +22085,42 @@ const newsletterFormFragment = defineFragment({
21376
22085
  defaultValue: "primary"
21377
22086
  }),
21378
22087
  {
21379
- id: "successMessage",
21380
- type: "text",
21381
- label: "Success message",
21382
- description: "Shown after successful subscription.",
21383
- defaultValue: "Thanks for subscribing!"
21384
- },
21385
- {
21386
- id: "privacyNote",
22088
+ id: "mailingListSource",
21387
22089
  type: "text",
21388
- label: "Privacy note",
21389
- description: "Optional small text below the form (e.g., privacy policy link)."
22090
+ label: "Mailing-list source",
22091
+ ui: {
22092
+ hidden: true,
22093
+ intent: "behavior"
22094
+ }
21390
22095
  },
21391
22096
  {
21392
- id: "tags",
22097
+ id: "mailingListSourceToken",
21393
22098
  type: "text",
21394
- label: "Tags (optional)",
21395
- description: "Optional tags to apply on subscribe (comma or semicolon separated).",
22099
+ label: "Mailing-list source token",
21396
22100
  ui: {
21397
- intent: "behavior",
21398
- visibleWhen: {
21399
- field: "destinationProvider",
21400
- equals: "riverbank"
21401
- }
22101
+ hidden: true,
22102
+ intent: "behavior"
21402
22103
  }
21403
22104
  }
21404
22105
  ],
21405
22106
  layout: [el("newsletter-form", withApiBindings({
21406
- source: "block",
21407
- destinationProvider: { $bind: { from: "destinationProvider" } },
21408
- listId: { $bind: { from: "listId" } },
21409
- preset: { $bind: { from: "preset" } },
21410
- includePhone: { $bind: { from: "includePhone" } },
21411
- buttonLabel: { $bind: { from: "buttonLabel" } },
22107
+ source: { $bind: {
22108
+ from: "mailingListSource",
22109
+ fallback: "block"
22110
+ } },
22111
+ sourceRef: {
22112
+ tag: "signed_source_ref",
22113
+ token: { $bind: { from: "mailingListSourceToken" } }
22114
+ },
22115
+ targeting: { $bind: {
22116
+ from: "targeting",
22117
+ fallback: { mode: "default" }
22118
+ } },
22119
+ mailingList: { $bind: { from: "$root.mailingList" } },
21412
22120
  buttonVariant: { $bind: {
21413
22121
  from: "buttonVariant",
21414
22122
  fallback: "primary"
21415
22123
  } },
21416
- successMessage: { $bind: { from: "successMessage" } },
21417
- privacyNote: { $bind: { from: "privacyNote" } },
21418
- tags: { $bind: { from: "tags" } },
21419
22124
  spamProtectionEnabled: { $bind: { from: "$root.spamProtectionEnabled" } }
21420
22125
  }), [])]
21421
22126
  });
@@ -23590,14 +24295,19 @@ const contactNewsletterLayout = styledSection({
23590
24295
  as: "h2",
23591
24296
  className: "newsletter-copy-title"
23592
24297
  }, when("newsletterTitle"), bind("newsletterTitle")), richText({ className: "newsletter-copy-subtitle rb-prose rb-max-w-none" }, when("newsletterSubtitle"), bind("newsletterSubtitle"))]), el("newsletter-form", withApiBindings({
23593
- source: "block",
23594
- listId: { $bind: { from: "listId" } },
23595
- preset: { $bind: { from: "preset" } },
23596
- includePhone: { $bind: { from: "includePhone" } },
23597
- buttonLabel: { $bind: { from: "newsletterButtonLabel" } },
23598
- successMessage: { $bind: { from: "newsletterSuccessMessage" } },
23599
- privacyNote: { $bind: { from: "newsletterPrivacyNote" } },
23600
- tags: { $bind: { from: "newsletterTags" } },
24298
+ source: { $bind: {
24299
+ from: "mailingListSource",
24300
+ fallback: "block"
24301
+ } },
24302
+ sourceRef: {
24303
+ tag: "signed_source_ref",
24304
+ token: { $bind: { from: "mailingListSourceToken" } }
24305
+ },
24306
+ targeting: { $bind: {
24307
+ from: "targeting",
24308
+ fallback: { mode: "default" }
24309
+ } },
24310
+ mailingList: { $bind: { from: "$root.mailingList" } },
23601
24311
  spamProtectionEnabled: { $bind: { from: "$root.spamProtectionEnabled" } }
23602
24312
  }), [])])])], { className: "contact-newsletter-container" }),
23603
24313
  baseClass: "",
@@ -23633,79 +24343,55 @@ const contactNewsletterBlockDefinition = {
23633
24343
  label: "Newsletter intro"
23634
24344
  },
23635
24345
  {
23636
- id: "listId",
23637
- type: "reference",
23638
- label: "Newsletter list",
23639
- description: "Select the list new subscribers should be added to.",
24346
+ id: "targeting",
24347
+ type: "group",
24348
+ label: "Mailing-list targeting",
24349
+ description: "Choose what kind of emails people signing up here will receive.",
23640
24350
  required: true,
23641
- referenceKind: "newsletterList",
23642
- allowManualEntry: false,
23643
- ui: { intent: "behavior" }
23644
- },
23645
- {
23646
- id: "preset",
23647
- type: "select",
23648
- label: "Newsletter fields",
23649
- defaultValue: "emailOnly",
23650
- ui: { intent: "display" },
23651
- options: [
23652
- {
23653
- value: "emailOnly",
23654
- label: "Email only"
23655
- },
23656
- {
23657
- value: "emailName",
23658
- label: "Email + Name"
23659
- },
23660
- {
23661
- value: "emailFirstLast",
23662
- label: "Email + First/Last Name"
23663
- },
23664
- {
23665
- value: "emailNameCompany",
23666
- label: "Email + Name + Company (B2B)"
23667
- }
23668
- ]
23669
- },
23670
- {
23671
- id: "includePhone",
23672
- type: "boolean",
23673
- label: "Include phone field",
23674
- defaultValue: false,
23675
- ui: { intent: "display" }
23676
- },
23677
- {
23678
- id: "newsletterButtonLabel",
23679
- type: "text",
23680
- label: "Newsletter button label",
23681
- defaultValue: "Subscribe",
23682
- ui: { intent: "display" }
23683
- },
23684
- {
23685
- id: "newsletterSuccessMessage",
23686
- type: "text",
23687
- label: "Newsletter success message",
23688
- defaultValue: "Thanks for subscribing!",
23689
- ui: { intent: "behavior" }
24351
+ defaultValue: { mode: "default" },
24352
+ ui: {
24353
+ intent: "behavior",
24354
+ widget: "mailingListTargeting"
24355
+ },
24356
+ schema: { fields: [{
24357
+ id: "mode",
24358
+ type: "select",
24359
+ label: "Mode",
24360
+ required: true,
24361
+ defaultValue: "default",
24362
+ options: [{
24363
+ value: "default",
24364
+ label: "Default"
24365
+ }, {
24366
+ value: "custom",
24367
+ label: "Custom"
24368
+ }],
24369
+ ui: { hidden: true }
24370
+ }] }
23690
24371
  },
23691
24372
  {
23692
- id: "newsletterPrivacyNote",
24373
+ id: "contactTitle",
23693
24374
  type: "text",
23694
- label: "Privacy note",
23695
- ui: { intent: "display" }
24375
+ label: "Contact title",
24376
+ defaultValue: "Get in touch"
23696
24377
  },
23697
24378
  {
23698
- id: "newsletterTags",
24379
+ id: "mailingListSource",
23699
24380
  type: "text",
23700
- label: "Newsletter tags",
23701
- description: "Optional tags to apply on subscribe, separated by comma or semicolon.",
23702
- ui: { intent: "behavior" }
24381
+ label: "Mailing-list source",
24382
+ ui: {
24383
+ hidden: true,
24384
+ intent: "behavior"
24385
+ }
23703
24386
  },
23704
24387
  {
23705
- id: "contactTitle",
24388
+ id: "mailingListSourceToken",
23706
24389
  type: "text",
23707
- label: "Contact title",
23708
- defaultValue: "Get in touch"
24390
+ label: "Mailing-list source token",
24391
+ ui: {
24392
+ hidden: true,
24393
+ intent: "behavior"
24394
+ }
23709
24395
  },
23710
24396
  {
23711
24397
  id: "contactIntro",
@@ -23906,6 +24592,12 @@ const arrayLengthTransform = {
23906
24592
  summary: "Get the length of an array",
23907
24593
  run: (value) => Array.isArray(value) ? value.length : 0
23908
24594
  };
24595
+ const booleanNotTransform = {
24596
+ id: "boolean.not",
24597
+ kind: "formatter",
24598
+ summary: "Invert a boolean value; fail closed to false for other inputs",
24599
+ run: (value) => typeof value === "boolean" ? !value : false
24600
+ };
23909
24601
  const jsonArrayTransform = {
23910
24602
  id: "value.jsonArray",
23911
24603
  kind: "formatter",
@@ -23956,33 +24648,51 @@ const marqueeLoopTransform = {
23956
24648
  function toUnknownArray(value) {
23957
24649
  return Array.isArray(value) ? value : [];
23958
24650
  }
24651
+ /**
24652
+ * Map a content state/enum to a theme token colour — the first-class way to turn
24653
+ * a value like a class's availability (`available`/`filling`/`waitlist`), a
24654
+ * card's featured flag, or a pricing tier level into a themed colour. Authors
24655
+ * write role names and get `rgb(var(--tb-<role>))`, so the result live-recolours
24656
+ * with the theme and drops directly into a `style` binding (e.g.
24657
+ * `borderLeftColor`). Returns `undefined` when the value matches no case and no
24658
+ * fallback is given, so the style property is simply omitted.
24659
+ */
24660
+ const mapTokenTransform = {
24661
+ id: "value.mapToken",
24662
+ kind: "formatter",
24663
+ summary: "Map a state/enum value to a theme token colour (rgb(var(--tb-<role>)))",
24664
+ schema: z.object({
24665
+ /**
24666
+ * Maps an input state/enum value (stringified) to a theme token ROLE name
24667
+ * (e.g. `secondary`, `accent`, `muted`, `border`). The role is wrapped to
24668
+ * `rgb(var(--tb-<role>))` so the result drops straight into a `style` binding.
24669
+ */
24670
+ cases: z.record(z.string(), z.string()),
24671
+ /** Role used when the value matches no case. Omit to yield `undefined`. */
24672
+ fallback: z.string().optional()
24673
+ }),
24674
+ run: (value, options) => {
24675
+ const role = options.cases[String(value)] ?? options.fallback;
24676
+ return role ? `rgb(var(--tb-${role}))` : void 0;
24677
+ }
24678
+ };
23959
24679
  const formattingTransforms = [
24680
+ {
24681
+ id: "value.equals",
24682
+ kind: "formatter",
24683
+ summary: "Compare a value to a fixed string",
24684
+ schema: z.object({ value: z.string() }),
24685
+ run: (value, options) => value === options.value
24686
+ },
23960
24687
  uppercaseTransform,
23961
24688
  fallbackTransform,
23962
24689
  dateFormatShort,
23963
24690
  arrayLengthTransform,
24691
+ booleanNotTransform,
23964
24692
  jsonArrayTransform,
23965
24693
  csvTransform,
23966
24694
  marqueeLoopTransform,
23967
- {
23968
- id: "value.mapToken",
23969
- kind: "formatter",
23970
- summary: "Map a state/enum value to a theme token colour (rgb(var(--tb-<role>)))",
23971
- schema: z.object({
23972
- /**
23973
- * Maps an input state/enum value (stringified) to a theme token ROLE name
23974
- * (e.g. `secondary`, `accent`, `muted`, `border`). The role is wrapped to
23975
- * `rgb(var(--tb-<role>))` so the result drops straight into a `style` binding.
23976
- */
23977
- cases: z.record(z.string(), z.string()),
23978
- /** Role used when the value matches no case. Omit to yield `undefined`. */
23979
- fallback: z.string().optional()
23980
- }),
23981
- run: (value, options) => {
23982
- const role = options.cases[String(value)] ?? options.fallback;
23983
- return role ? `rgb(var(--tb-${role}))` : void 0;
23984
- }
23985
- }
24695
+ mapTokenTransform
23986
24696
  ];
23987
24697
  //#endregion
23988
24698
  //#region ../blocks/src/system/transforms/registry/ui.ts
@@ -25391,13 +26101,9 @@ const footerStandardContactBindings = {
25391
26101
  };
25392
26102
  const footerMailingListBindings = {
25393
26103
  source: { $bind: { from: "module.engagement.runtime.source" } },
25394
- destinationRef: { $bind: { from: "module.engagement.runtime.destinationRef" } },
25395
- listId: { $bind: { from: "module.engagement.runtime.listId" } },
25396
- preset: { $bind: { from: "module.engagement.runtime.preset" } },
25397
- includePhone: { $bind: { from: "module.engagement.runtime.includePhone" } },
25398
- buttonLabel: { $bind: { from: "module.engagement.runtime.buttonLabel" } },
25399
- successMessage: { $bind: { from: "module.engagement.runtime.successMessage" } },
25400
- privacyNote: { $bind: { from: "module.engagement.runtime.privacyNote" } }
26104
+ sourceRef: { $bind: { from: "module.engagement.runtime.sourceRef" } },
26105
+ mailingList: { $bind: { from: "module.engagement.runtime.mailingList" } },
26106
+ targeting: { $bind: { from: "module.engagement.runtime.targeting" } }
25401
26107
  };
25402
26108
  const footerSpamProtectionBinding = { spamProtectionEnabled: { $bind: { from: "$root.spamProtectionEnabled" } } };
25403
26109
  const brandLogo = link({
@@ -27085,6 +27791,78 @@ const appointmentBookingBlockDefinition = {
27085
27791
  }
27086
27792
  }
27087
27793
  };
27794
+ const appointmentServicesBlockDefinition = {
27795
+ manifest: createBlockManifest({
27796
+ id: "block.appointment-services",
27797
+ version: "1.0.0",
27798
+ title: "Appointment Services",
27799
+ titleSource: "heading",
27800
+ description: "List public appointment services with booking links",
27801
+ skipSectionStyles: true,
27802
+ additionalFields: [
27803
+ {
27804
+ id: "heading",
27805
+ type: "text",
27806
+ label: "Heading",
27807
+ required: false,
27808
+ multiline: false,
27809
+ defaultValue: "Appointments",
27810
+ ui: { intent: "content" }
27811
+ },
27812
+ {
27813
+ id: "description",
27814
+ type: "richText",
27815
+ label: "Description",
27816
+ required: false,
27817
+ ui: { intent: "content" }
27818
+ },
27819
+ sectionStylesField({
27820
+ id: "_sectionStyles",
27821
+ label: "Section styles",
27822
+ renderInHeader: false
27823
+ })
27824
+ ],
27825
+ styleTokens: {
27826
+ background: "surface",
27827
+ typography: "body",
27828
+ spacing: "md"
27829
+ },
27830
+ behaviours: {
27831
+ supportsThemeSwitching: true,
27832
+ inlineEditing: true,
27833
+ animation: false,
27834
+ paletteHidden: false
27835
+ },
27836
+ category: "interactive",
27837
+ contentSource: { kind: "inline" },
27838
+ tags: [
27839
+ "booking",
27840
+ "appointment",
27841
+ "services",
27842
+ "scheduling"
27843
+ ],
27844
+ icon: "CalendarDays",
27845
+ layout: [styledSection({
27846
+ baseClass: "",
27847
+ spacing: "spacious",
27848
+ children: sectionContainer([
27849
+ text({ as: "h2" }, bind("content.heading"), when("content.heading")),
27850
+ richText({ className: "rb-prose rb-max-w-none" }, bind("content.description"), when("content.description")),
27851
+ el("appointment-services", {
27852
+ sectionHeading: { $bind: { from: "content.heading" } },
27853
+ services: { $bind: { from: "data.services" } },
27854
+ pathname: { $bind: { from: "$root.pathname" } }
27855
+ })
27856
+ ], { gap: "lg" })
27857
+ })]
27858
+ }),
27859
+ dataSchemas: { services: z.unknown().optional() },
27860
+ dataLoaders: { services: {
27861
+ endpoint: "getPublicBookingServices",
27862
+ params: { siteId: { $bind: { from: "$root.siteId" } } },
27863
+ mode: "server"
27864
+ } }
27865
+ };
27088
27866
  //#endregion
27089
27867
  //#region ../blocks/src/system/blocks/weekly-slot-availability.ts
27090
27868
  const weeklySlotAvailabilityManifest = createBlockManifest({
@@ -27729,6 +28507,44 @@ function toWholeSeriesRegistrationEvents(events) {
27729
28507
  return groupPublicEventsByRun(events).map(toWholeSeriesRegistrationEvent).filter((event) => event !== null);
27730
28508
  }
27731
28509
  //#endregion
28510
+ //#region ../blocks/src/system/runtime/nodes/event-registration/eventSourceRecovery.ts
28511
+ const { limit: _rawLimit, eventSurface: _rawEventSurface, scheduleScope: _rawScheduleScope, detailLevel: _rawDetailLevel, ...stringEventQueryShape } = publicEventLoaderQuerySchemaShape;
28512
+ const eventRecoveryRequestSchema = z.object({
28513
+ ...stringEventQueryShape,
28514
+ limit: z.coerce.number().int().positive().optional(),
28515
+ eventSurface: z.enum(eventSurfaceScopeValues).optional(),
28516
+ scheduleScope: z.enum(eventScheduleScopeValues).optional(),
28517
+ detailLevel: z.enum(["full", "listing"]).optional(),
28518
+ stage: z.enum(["preview", "published"]).optional()
28519
+ });
28520
+ function resolveEventRegistrationEventSource(input) {
28521
+ if (input.wholeSeriesRunEvents != null) return {
28522
+ kind: "loaded",
28523
+ events: input.wholeSeriesRunEvents
28524
+ };
28525
+ if (input.events != null) return {
28526
+ kind: "loaded",
28527
+ events: input.events
28528
+ };
28529
+ return {
28530
+ kind: "unresolved",
28531
+ request: parseEventLoaderRecoveryRequest(input.failures?.wholeSeriesRunEvents ?? input.failures?.events)
28532
+ };
28533
+ }
28534
+ const eventLoaderFailureSchema = z.object({
28535
+ endpoint: z.literal("listPublicEvents"),
28536
+ params: eventRecoveryRequestSchema.extend({ siteId: z.string().optional() })
28537
+ });
28538
+ function parseEventLoaderRecoveryRequest(value) {
28539
+ const parsed = eventLoaderFailureSchema.safeParse(value);
28540
+ if (!parsed.success) return null;
28541
+ const { siteId: _siteId, stage, ...params } = parsed.data.params;
28542
+ return {
28543
+ ...params,
28544
+ stage: stage ?? "published"
28545
+ };
28546
+ }
28547
+ //#endregion
27732
28548
  //#region ../blocks/src/system/runtime/nodes/event-registration.interactive.ts
27733
28549
  const EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS = [
27734
28550
  "Date",
@@ -27746,8 +28562,6 @@ const eventRegistrationPublicEventSchema = z.preprocess(normalizeEventRegistrati
27746
28562
  const eventRegistrationHydrationSchemaShape = {
27747
28563
  occurrenceContext: occurrenceContextSchema.optional(),
27748
28564
  subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
27749
- events: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
27750
- wholeSeriesRunEvents: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
27751
28565
  maxTickets: z.string().optional(),
27752
28566
  showVenue: z.boolean().optional(),
27753
28567
  showCapacity: z.boolean().optional(),
@@ -27759,12 +28573,22 @@ const eventRegistrationHydrationSchemaShape = {
27759
28573
  sitePasses: publicPassProductCollectionSchema.nullable().optional(),
27760
28574
  siteMemberships: publicMembershipProductCollectionSchema.nullable().optional()
27761
28575
  };
28576
+ const eventRegistrationEventSourceSchema = z.discriminatedUnion("kind", [z.object({
28577
+ kind: z.literal("loaded"),
28578
+ events: z.array(eventRegistrationPublicEventSchema)
28579
+ }), z.object({
28580
+ kind: z.literal("unresolved"),
28581
+ request: eventRecoveryRequestSchema.nullable()
28582
+ })]);
27762
28583
  const eventRegistrationSourceSchema = z.object({
27763
28584
  siteId: z.string().optional(),
27764
28585
  apiBaseUrl: z.string().optional(),
27765
28586
  portalToken: z.string().nullable().optional(),
27766
28587
  previewToken: z.string().nullable().optional(),
27767
28588
  ...eventRegistrationHydrationSchemaShape,
28589
+ events: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
28590
+ wholeSeriesRunEvents: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
28591
+ eventLoaderFailures: z.record(z.string(), z.unknown()).nullable().optional(),
27768
28592
  className: z.string().nullable().optional(),
27769
28593
  buttonText: z.string().nullable().optional(),
27770
28594
  maxTickets: z.string().nullable().optional(),
@@ -27785,7 +28609,10 @@ const eventRegistrationDisplaySchema = z.discriminatedUnion("state", [z.object({
27785
28609
  titleText: z.string(),
27786
28610
  bodyText: z.string()
27787
28611
  })]);
27788
- const eventRegistrationHydrationSchema = z.object(eventRegistrationHydrationSchemaShape);
28612
+ const eventRegistrationHydrationSchema = z.object({
28613
+ ...eventRegistrationHydrationSchemaShape,
28614
+ eventSource: eventRegistrationEventSourceSchema
28615
+ });
27789
28616
  const eventRegistrationRenderSchema = z.object({
27790
28617
  display: eventRegistrationDisplaySchema,
27791
28618
  hydration: eventRegistrationHydrationSchema
@@ -27797,8 +28624,8 @@ z.object({
27797
28624
  previewToken: z.string().nullable().optional(),
27798
28625
  stage: previewStageSchema.optional()
27799
28626
  });
27800
- function buildEventRegistrationDisplay(source) {
27801
- const selectedRun = resolveSelectedWholeSeriesRun(source);
28627
+ function buildEventRegistrationDisplayFromScopedEvents(source, scopedSourceEvents) {
28628
+ const selectedRun = resolveSelectedWholeSeriesRun(scopedSourceEvents);
27802
28629
  if (selectedRun && (!selectedRun.run.enrollmentOpen || toWholeSeriesRegistrationEvent(selectedRun) === null)) return {
27803
28630
  kind: "event-registration",
27804
28631
  state: "registration-closed",
@@ -27806,7 +28633,7 @@ function buildEventRegistrationDisplay(source) {
27806
28633
  titleText: "Registration closed",
27807
28634
  bodyText: "This run is no longer open for bookings."
27808
28635
  };
27809
- const stepLabels = buildEventRegistrationShellStepLabels(source);
28636
+ const stepLabels = buildEventRegistrationShellStepLabels(source, scopedSourceEvents);
27810
28637
  return {
27811
28638
  kind: "event-registration",
27812
28639
  state: "generic-shell",
@@ -27817,8 +28644,8 @@ function buildEventRegistrationDisplay(source) {
27817
28644
  summaryButtonText: source.buttonText?.trim() || "Register"
27818
28645
  };
27819
28646
  }
27820
- function buildEventRegistrationShellStepLabels(source) {
27821
- const selectedRun = resolveSelectedWholeSeriesRun(source);
28647
+ function buildEventRegistrationShellStepLabels(source, scopedSourceEvents) {
28648
+ const selectedRun = resolveSelectedWholeSeriesRun(scopedSourceEvents);
27822
28649
  if (selectedRun) {
27823
28650
  const selectedEvent = toWholeSeriesRegistrationEvent(selectedRun);
27824
28651
  if (!selectedEvent) return EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS;
@@ -27828,7 +28655,7 @@ function buildEventRegistrationShellStepLabels(source) {
27828
28655
  event: selectedEvent
27829
28656
  })).map((step) => shellLabelForRegistrationStep(step, [selectedEvent]));
27830
28657
  }
27831
- const scopedEvents = scopeEventRegistrationEvents(source);
28658
+ const scopedEvents = toScopedEventRegistrationEvents(scopedSourceEvents);
27832
28659
  if (scopedEvents.length === 0) return EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS;
27833
28660
  const preSelectedEvent = findPreSelectedEvent({
27834
28661
  scopedEvents,
@@ -27841,21 +28668,11 @@ function buildEventRegistrationShellStepLabels(source) {
27841
28668
  event: preSelectedEvent
27842
28669
  }) : false).map((step) => shellLabelForRegistrationStep(step, scopedEvents));
27843
28670
  }
27844
- function scopeEventRegistrationEvents(source) {
27845
- const scoped = scopeEventRegistrationSourceEvents(source);
27846
- return [...toRegistrationEvents(scoped), ...toWholeSeriesRegistrationEvents(scoped)];
28671
+ function toScopedEventRegistrationEvents(scopedSourceEvents) {
28672
+ return [...toRegistrationEvents(scopedSourceEvents), ...toWholeSeriesRegistrationEvents(scopedSourceEvents)];
27847
28673
  }
27848
- /**
27849
- * Every event this surface may register for, from both of its loads.
27850
- *
27851
- * The date page and the run read answer different questions and can name the
27852
- * same occurrence, so the two lists are joined and any occurrence that arrives
27853
- * twice is kept once, in the order the date page gave it.
27854
- */
27855
- function scopeEventRegistrationSourceEvents(source) {
27856
- const byOccurrenceId = /* @__PURE__ */ new Map();
27857
- for (const event of [...source.events ?? [], ...source.wholeSeriesRunEvents ?? []]) if (!byOccurrenceId.has(event.occurrenceId)) byOccurrenceId.set(event.occurrenceId, event);
27858
- return resolveEventRegistrationScopedEvents([...byOccurrenceId.values()], {
28674
+ function scopeEventRegistrationSourceEvents(source, eventSource) {
28675
+ return resolveEventRegistrationScopedEvents(eventSource.kind === "loaded" ? eventSource.events : [], {
27859
28676
  occurrenceContext: source.occurrenceContext,
27860
28677
  subject: source.subject
27861
28678
  });
@@ -27864,8 +28681,8 @@ function scopeEventRegistrationSourceEvents(source) {
27864
28681
  * The one run this surface is registering for, when the scoped events describe
27865
28682
  * exactly one. More than one run means the visitor still has to choose.
27866
28683
  */
27867
- function resolveSelectedWholeSeriesRun(source) {
27868
- const runs = groupPublicEventsByRun(scopeEventRegistrationSourceEvents(source));
28684
+ function resolveSelectedWholeSeriesRun(scopedSourceEvents) {
28685
+ const runs = groupPublicEventsByRun(scopedSourceEvents);
27869
28686
  return runs.length === 1 ? runs[0] : null;
27870
28687
  }
27871
28688
  function shellLabelForRegistrationStep(step, events) {
@@ -27899,13 +28716,21 @@ const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
27899
28716
  render: createZodCodec(eventRegistrationRenderSchema)
27900
28717
  },
27901
28718
  buildRender: (source) => {
27902
- const events = source.events == null ? null : scopeEventRegistrationSourceEvents(source);
28719
+ const eventSource = resolveEventRegistrationEventSource({
28720
+ events: source.events,
28721
+ wholeSeriesRunEvents: source.wholeSeriesRunEvents,
28722
+ failures: source.eventLoaderFailures
28723
+ });
28724
+ const scopedSourceEvents = scopeEventRegistrationSourceEvents(source, eventSource);
27903
28725
  return {
27904
- display: buildEventRegistrationDisplay(source),
28726
+ display: buildEventRegistrationDisplayFromScopedEvents(source, scopedSourceEvents),
27905
28727
  hydration: {
27906
28728
  occurrenceContext: source.occurrenceContext ?? null,
27907
28729
  subject: source.subject ?? null,
27908
- events,
28730
+ eventSource: eventSource.kind === "loaded" ? {
28731
+ ...eventSource,
28732
+ events: [...scopedSourceEvents]
28733
+ } : eventSource,
27909
28734
  maxTickets: source.maxTickets ?? void 0,
27910
28735
  showVenue: source.showVenue,
27911
28736
  showCapacity: source.showCapacity,
@@ -28081,6 +28906,7 @@ const eventRegistrationBlockDefinition = {
28081
28906
  } },
28082
28907
  events: { $bind: { from: "data.events" } },
28083
28908
  wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
28909
+ loaderFailures: { $bind: { from: "$root.loaderFailures" } },
28084
28910
  sitePasses: { $bind: { from: "data.sitePasses" } },
28085
28911
  siteMemberships: { $bind: { from: "data.siteMemberships" } },
28086
28912
  stage: { $bind: {
@@ -28102,6 +28928,11 @@ const eventRegistrationBlockDefinition = {
28102
28928
  dataLoaders: {
28103
28929
  events: {
28104
28930
  endpoint: "listPublicEvents",
28931
+ when: { $bind: {
28932
+ from: "$root.subject.isWholeSeriesBooking",
28933
+ fallback: true,
28934
+ transforms: [{ id: "boolean.not" }]
28935
+ } },
28105
28936
  params: {
28106
28937
  siteId: { $bind: { from: "$root.siteId" } },
28107
28938
  limit: "50",
@@ -28123,13 +28954,9 @@ const eventRegistrationBlockDefinition = {
28123
28954
  /**
28124
28955
  * The runs this page can register for, finished ones included.
28125
28956
  *
28126
- * The `events` page above is date-bounded, so a run whose first session has
28127
- * passed contributes no rows to it and the surface would have nothing to
28128
- * render as closed. This asks for runs instead, and only on a page whose
28129
- * subject books whole runs. It is scoped exactly like the date page — same
28130
- * series, same run subroute — because scope and grain are separate
28131
- * questions. The two lists are joined by occurrence, so a run that appears
28132
- * in both is still one run.
28957
+ * A run read is the sole Event source on a whole-series surface. It is
28958
+ * status-bounded rather than date-bounded, so completed runs can still
28959
+ * render their closed state and every run carries its complete schedule.
28133
28960
  */
28134
28961
  wholeSeriesRunEvents: {
28135
28962
  endpoint: "listPublicEvents",
@@ -30855,20 +31682,7 @@ function isRecord$4(value) {
30855
31682
  return typeof value === "object" && value !== null && !Array.isArray(value);
30856
31683
  }
30857
31684
  //#endregion
30858
- //#region ../blocks/src/system/blocks/offerings-preview/index.ts
30859
- /**
30860
- * The whole-series presets, as the CSV `listPublicEvents` expects. Both
30861
- * whole-series presets share one loader: the block renders them as a single
30862
- * run group.
30863
- */
30864
- const WHOLE_SERIES_EVENT_PRESETS_PARAM = WHOLE_SERIES_EVENT_PRESET_VALUES.join(",");
30865
- const publicRouteCandidatesSchema = z.object({ routes: z.array(z.object({
30866
- entityId: z.string(),
30867
- path: z.string(),
30868
- title: z.string(),
30869
- kind: z.enum(RESOLVED_INTERNAL_LINK_ENTITY_TYPES),
30870
- contentTypeKey: z.string().nullable().optional()
30871
- })) });
31685
+ //#region ../blocks/src/system/blocks/offerings-preview/fields.ts
30872
31686
  const groupOverrideFields = [
30873
31687
  {
30874
31688
  id: "sourceKey",
@@ -31074,7 +31888,65 @@ const offeringsPreviewFields = [
31074
31888
  renderInHeader: false
31075
31889
  })
31076
31890
  ];
31891
+ function labelForOfferingPreviewSourceKey(sourceKey) {
31892
+ const eventDefinition = OFFERINGS_PREVIEW_EVENT_PRESET_DEFINITIONS.find((definition) => definition.sourceKey === sourceKey);
31893
+ if (eventDefinition) return eventDefinition.label;
31894
+ return "Courses";
31895
+ }
31896
+ //#endregion
31897
+ //#region ../blocks/src/system/blocks/offerings-preview/index.ts
31898
+ /**
31899
+ * The whole-series presets, as the CSV `listPublicEvents` expects. Both
31900
+ * whole-series presets share one loader: the block renders them as a single
31901
+ * run group.
31902
+ */
31903
+ const WHOLE_SERIES_EVENT_PRESETS_PARAM = WHOLE_SERIES_EVENT_PRESET_VALUES.join(",");
31904
+ const publicRouteCandidatesSchema = z.object({ routes: z.array(z.object({
31905
+ entityId: z.string(),
31906
+ path: z.string(),
31907
+ title: z.string(),
31908
+ kind: z.enum(RESOLVED_INTERNAL_LINK_ENTITY_TYPES),
31909
+ contentTypeKey: z.string().nullable().optional()
31910
+ })) });
31077
31911
  const offeringsPreviewEventDataBindings = Object.fromEntries(OFFERINGS_PREVIEW_EVENT_PRESET_DEFINITIONS.map((definition) => [definition.dataKey, { $bind: { from: `data.${definition.dataKey}` } }]));
31912
+ const DEFAULT_OFFERINGS_PREVIEW_DISPLAY_MODE = "preview";
31913
+ const displayModeBinding = {
31914
+ from: "content.displayMode",
31915
+ fallback: DEFAULT_OFFERINGS_PREVIEW_DISPLAY_MODE
31916
+ };
31917
+ const catalogueMode = { $bind: {
31918
+ ...displayModeBinding,
31919
+ transforms: [{
31920
+ id: "value.equals",
31921
+ options: { value: "catalogue" }
31922
+ }]
31923
+ } };
31924
+ const previewMode = { $bind: {
31925
+ ...displayModeBinding,
31926
+ transforms: [{
31927
+ id: "value.equals",
31928
+ options: { value: "preview" }
31929
+ }]
31930
+ } };
31931
+ function offeringsPreviewHeaderNodes() {
31932
+ return [text({
31933
+ as: "h2",
31934
+ className: { $bind: {
31935
+ from: "content.displayMode",
31936
+ fallback: "rb-text-center",
31937
+ transforms: [{
31938
+ id: "value.equals",
31939
+ options: { value: "catalogue" }
31940
+ }, {
31941
+ id: "ui.conditionalClass",
31942
+ options: {
31943
+ whenTrue: "rb-text-left",
31944
+ whenFalse: "rb-text-center"
31945
+ }
31946
+ }]
31947
+ } }
31948
+ }, bind("content.heading"), when("content.heading")), richText({ className: "rb-prose rb-max-w-none" }, bind("content.description"), when("content.description"))];
31949
+ }
31078
31950
  const offeringsPreviewManifest = createBlockManifest({
31079
31951
  id: "block.offerings-preview",
31080
31952
  version: "1.0.0",
@@ -31105,48 +31977,45 @@ const offeringsPreviewManifest = createBlockManifest({
31105
31977
  ],
31106
31978
  icon: "PanelsTopLeft",
31107
31979
  layout: [styledSection({
31108
- children: sectionContainer([
31109
- text({
31110
- as: "h2",
31111
- className: "rb-text-center"
31112
- }, bind("content.heading"), when("content.heading")),
31113
- richText({ className: "rb-prose rb-max-w-none" }, bind("content.description"), when("content.description")),
31114
- el("offerings-preview", {
31115
- bookingOfferingPresets: { $bind: {
31116
- from: "$root.bookingOfferingPresets",
31117
- fallback: []
31118
- } },
31119
- groupOverrides: { $bind: {
31120
- from: "content.groupOverrides",
31121
- fallback: []
31122
- } },
31123
- groupOrder: { $bind: { from: "content.groupOrder" } },
31124
- cardStyles: { $bind: { from: "content._cardStyles" } },
31125
- itemLimit: { $bind: {
31126
- from: "content.itemLimit",
31127
- fallback: "3"
31128
- } },
31129
- buttonVariant: { $bind: {
31130
- from: "content.buttonVariant",
31131
- fallback: "primary"
31132
- } },
31133
- buttonText: { $bind: {
31134
- from: "content.buttonText",
31135
- fallback: OFFERINGS_PREVIEW_DEFAULT_BUTTON_TEXT
31136
- } },
31137
- emptyMessage: { $bind: {
31138
- from: "content.emptyMessage",
31139
- fallback: OFFERINGS_PREVIEW_DEFAULT_EMPTY_MESSAGE
31140
- } },
31141
- previewStage: { $bind: {
31142
- from: "$root.previewStage",
31143
- fallback: "published"
31144
- } },
31145
- routeCandidates: { $bind: { from: "data.routeCandidates" } },
31146
- wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
31147
- ...offeringsPreviewEventDataBindings
31148
- })
31149
- ], { gap: "lg" }),
31980
+ children: sectionContainer([el("offerings-preview", {
31981
+ displayMode: { $bind: displayModeBinding },
31982
+ pathname: { $bind: { from: "$root.pathname" } },
31983
+ catalogueEvents: { $bind: { from: "data.catalogueEvents" } },
31984
+ quickDateEvents: { $bind: { from: "data.quickDateEvents" } },
31985
+ bookingOfferingPresets: { $bind: {
31986
+ from: "$root.bookingOfferingPresets",
31987
+ fallback: []
31988
+ } },
31989
+ groupOverrides: { $bind: {
31990
+ from: "content.groupOverrides",
31991
+ fallback: []
31992
+ } },
31993
+ groupOrder: { $bind: { from: "content.groupOrder" } },
31994
+ cardStyles: { $bind: { from: "content._cardStyles" } },
31995
+ itemLimit: { $bind: {
31996
+ from: "content.itemLimit",
31997
+ fallback: "3"
31998
+ } },
31999
+ buttonVariant: { $bind: {
32000
+ from: "content.buttonVariant",
32001
+ fallback: "primary"
32002
+ } },
32003
+ buttonText: { $bind: {
32004
+ from: "content.buttonText",
32005
+ fallback: OFFERINGS_PREVIEW_DEFAULT_BUTTON_TEXT
32006
+ } },
32007
+ emptyMessage: { $bind: {
32008
+ from: "content.emptyMessage",
32009
+ fallback: OFFERINGS_PREVIEW_DEFAULT_EMPTY_MESSAGE
32010
+ } },
32011
+ previewStage: { $bind: {
32012
+ from: "$root.previewStage",
32013
+ fallback: "published"
32014
+ } },
32015
+ routeCandidates: { $bind: { from: "data.routeCandidates" } },
32016
+ wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
32017
+ ...offeringsPreviewEventDataBindings
32018
+ }, offeringsPreviewHeaderNodes())], { gap: "lg" }),
31150
32019
  baseClass: "",
31151
32020
  spacing: "comfortable"
31152
32021
  })]
@@ -31160,16 +32029,48 @@ const offeringsPreviewBlockDefinition = {
31160
32029
  dataSchemas: {
31161
32030
  ...offeringsPreviewEventDataSchemas,
31162
32031
  routeCandidates: publicRouteCandidatesSchema.optional(),
31163
- wholeSeriesRunEvents: optionalPublicEventsArraySchema
32032
+ wholeSeriesRunEvents: optionalPublicEventsArraySchema,
32033
+ catalogueEvents: optionalPublicEventsArraySchema,
32034
+ quickDateEvents: optionalPublicEventsArraySchema
31164
32035
  },
31165
32036
  dataLoaders: {
31166
32037
  ...offeringsPreviewEventDataLoaders,
31167
32038
  routeCandidates: {
31168
32039
  endpoint: "listPublicRouteCandidates",
32040
+ when: previewMode,
31169
32041
  params: {},
31170
32042
  mode: "server"
31171
32043
  },
31172
- wholeSeriesRunEvents: wholeSeriesRunLoader()
32044
+ wholeSeriesRunEvents: wholeSeriesRunLoader(),
32045
+ catalogueEvents: {
32046
+ endpoint: "listPublicEvents",
32047
+ when: catalogueMode,
32048
+ params: {
32049
+ stage: { $bind: {
32050
+ from: "$root.previewStage",
32051
+ fallback: "published"
32052
+ } },
32053
+ detailLevel: "listing",
32054
+ readProfile: "listing-card",
32055
+ readIntent: "catalogue"
32056
+ },
32057
+ mode: "server"
32058
+ },
32059
+ quickDateEvents: {
32060
+ endpoint: "listPublicEvents",
32061
+ when: catalogueMode,
32062
+ params: {
32063
+ stage: { $bind: {
32064
+ from: "$root.previewStage",
32065
+ fallback: "published"
32066
+ } },
32067
+ detailLevel: "listing",
32068
+ readProfile: "listing-card",
32069
+ readIntent: "occurrences",
32070
+ limit: 40
32071
+ },
32072
+ mode: "server"
32073
+ }
31173
32074
  }
31174
32075
  };
31175
32076
  /**
@@ -31186,6 +32087,7 @@ function wholeSeriesRunLoader() {
31186
32087
  function eventPresetLoader(eventPresets, extraParams = {}) {
31187
32088
  return {
31188
32089
  endpoint: "listPublicEvents",
32090
+ when: previewMode,
31189
32091
  params: {
31190
32092
  siteId: { $bind: { from: "$root.siteId" } },
31191
32093
  limit: { $bind: {
@@ -31204,15 +32106,10 @@ function eventPresetLoader(eventPresets, extraParams = {}) {
31204
32106
  mode: "server"
31205
32107
  };
31206
32108
  }
31207
- function labelForOfferingPreviewSourceKey(sourceKey) {
31208
- const eventDefinition = OFFERINGS_PREVIEW_EVENT_PRESET_DEFINITIONS.find((definition) => definition.sourceKey === sourceKey);
31209
- if (eventDefinition) return eventDefinition.label;
31210
- return "Courses";
31211
- }
31212
32109
  function normalizeOfferingsPreviewBlockContent(value) {
31213
32110
  const record = normalizeOfferingsPreviewContentForWrite(value);
31214
- if (!record) return {};
31215
- const normalized = {};
32111
+ if (!record) return { displayMode: DEFAULT_OFFERINGS_PREVIEW_DISPLAY_MODE };
32112
+ const normalized = { displayMode: normalizeOfferingsPreviewDisplayMode(record.displayMode) };
31216
32113
  if (typeof record.heading === "string" || record.heading === null) normalized.heading = record.heading;
31217
32114
  if ("description" in record) normalized.description = record.description;
31218
32115
  if (isOfferingsPreviewItemLimit(record.itemLimit)) normalized.itemLimit = record.itemLimit;
@@ -31229,6 +32126,9 @@ function normalizeOfferingsPreviewBlockContent(value) {
31229
32126
  if (sectionStyles !== void 0) normalized._sectionStyles = sectionStyles;
31230
32127
  return normalized;
31231
32128
  }
32129
+ function normalizeOfferingsPreviewDisplayMode(value) {
32130
+ return value === "catalogue" ? "catalogue" : DEFAULT_OFFERINGS_PREVIEW_DISPLAY_MODE;
32131
+ }
31232
32132
  function isOfferingsPreviewItemLimit(value) {
31233
32133
  return value === "1" || value === "2" || value === "3" || value === "4" || value === "5" || value === "6" || value === null;
31234
32134
  }
@@ -34443,63 +35343,13 @@ const giftingBlockDefinition = {
34443
35343
  } }
34444
35344
  };
34445
35345
  //#endregion
34446
- //#region ../blocks/src/system/blocks/newsletter-signup-destination.ts
34447
- function parseNewsletterSignupBlockId(value) {
34448
- const trimmed = parseTrimmedString(value);
34449
- return trimmed && BLOCK_ID_PATTERN.test(trimmed) ? trimmed : null;
34450
- }
34451
- function parseSignedNewsletterDestinationRef(value) {
34452
- const trimmed = parseTrimmedString(value);
34453
- return trimmed && SIGNED_DESTINATION_REF_PATTERN.test(trimmed) ? trimmed : null;
34454
- }
34455
- function buildNewsletterSignupBlockRef(blockId) {
34456
- const parsed = parseNewsletterSignupBlockId(blockId);
34457
- return parsed ? {
34458
- tag: "block_ref",
34459
- blockId: parsed
34460
- } : null;
34461
- }
34462
- function normalizeNewsletterSignupEditorValuesForDestination(values) {
34463
- const destinationProvider = parseNewsletterSignupDestinationProvider(values.destinationProvider) ?? "riverbank";
34464
- if (destinationProvider === "mailchimp") return {
34465
- destinationProvider,
34466
- mailchimpAudienceId: values.mailchimpAudienceId,
34467
- mailchimpTags: values.mailchimpTags
34468
- };
34469
- return {
34470
- destinationProvider,
34471
- listId: values.listId,
34472
- tags: values.tags
34473
- };
34474
- }
34475
- function deriveNewsletterSignupRuntimeSource(values) {
34476
- const normalized = normalizeNewsletterSignupEditorValuesForDestination(values);
34477
- if (normalized.destinationProvider === "mailchimp") return {
34478
- destinationProvider: "mailchimp",
34479
- listId: null,
34480
- tags: null
34481
- };
34482
- return {
34483
- destinationProvider: "riverbank",
34484
- listId: parseTrimmedString(normalized.listId),
34485
- tags: parseTrimmedString(normalized.tags)
34486
- };
34487
- }
34488
- const BLOCK_ID_PATTERN = /^[A-Za-z0-9._:-]{1,200}$/;
34489
- const SIGNED_DESTINATION_REF_PATTERN = /^[A-Za-z0-9._~-]{16,1000}$/;
34490
- function parseTrimmedString(value) {
34491
- if (typeof value !== "string") return null;
34492
- const trimmed = value.trim();
34493
- return trimmed.length > 0 ? trimmed : null;
34494
- }
34495
- //#endregion
34496
35346
  //#region ../blocks/src/system/runtime/nodes/newsletter-form.types.ts
34497
35347
  /**
34498
35348
  * Get form fields based on preset configuration.
34499
35349
  */
34500
- function getPresetFields(preset, options) {
34501
- const includePhone = Boolean(options?.includePhone);
34502
- switch (preset) {
35350
+ function getGlobalFormFields(form) {
35351
+ const includePhone = form.includeOptionalPhone;
35352
+ switch (form.fields.preset) {
34503
35353
  case "emailOnly": return withOptionalPhone([{
34504
35354
  id: "email",
34505
35355
  type: "email",
@@ -34517,7 +35367,7 @@ function getPresetFields(preset, options) {
34517
35367
  id: "name",
34518
35368
  type: "text",
34519
35369
  label: "Name",
34520
- required: false,
35370
+ required: form.fields.name === "required",
34521
35371
  placeholder: "Your name"
34522
35372
  }], includePhone);
34523
35373
  case "emailFirstLast": return withOptionalPhone([
@@ -34532,14 +35382,14 @@ function getPresetFields(preset, options) {
34532
35382
  id: "firstName",
34533
35383
  type: "text",
34534
35384
  label: "First Name",
34535
- required: false,
35385
+ required: form.fields.firstName === "required",
34536
35386
  placeholder: "First name"
34537
35387
  },
34538
35388
  {
34539
35389
  id: "lastName",
34540
35390
  type: "text",
34541
35391
  label: "Last Name",
34542
- required: false,
35392
+ required: form.fields.lastName === "required",
34543
35393
  placeholder: "Last name"
34544
35394
  }
34545
35395
  ], includePhone);
@@ -34555,14 +35405,14 @@ function getPresetFields(preset, options) {
34555
35405
  id: "name",
34556
35406
  type: "text",
34557
35407
  label: "Name",
34558
- required: false,
35408
+ required: form.fields.name === "required",
34559
35409
  placeholder: "Your name"
34560
35410
  },
34561
35411
  {
34562
35412
  id: "company",
34563
35413
  type: "text",
34564
35414
  label: "Company",
34565
- required: false,
35415
+ required: form.fields.company === "required",
34566
35416
  placeholder: "Company name"
34567
35417
  }
34568
35418
  ], includePhone);
@@ -34581,14 +35431,29 @@ function withOptionalPhone(fields, includePhone) {
34581
35431
  }
34582
35432
  //#endregion
34583
35433
  //#region ../blocks/src/system/runtime/nodes/newsletter-form.interactive.ts
34584
- const newsletterPresetSchema = z.enum([
34585
- "emailOnly",
34586
- "emailName",
34587
- "emailFirstLast",
34588
- "emailNameCompany"
34589
- ]);
34590
- const newsletterDestinationProviderSchema = z.enum(["riverbank", "mailchimp"]);
34591
35434
  const newsletterButtonVariantSchema = blockButtonRoleSchema;
35435
+ const mailingListContextSchema = z.unknown().transform((value, ctx) => {
35436
+ const parsed = parseMailingListRuntimeContext(value);
35437
+ if (!parsed.ok) {
35438
+ ctx.addIssue({
35439
+ code: z.ZodIssueCode.custom,
35440
+ message: "Invalid mailing-list runtime context"
35441
+ });
35442
+ return z.NEVER;
35443
+ }
35444
+ return parsed.value;
35445
+ });
35446
+ const mailingListTargetingSchema = z.unknown().transform((value, ctx) => {
35447
+ const parsed = parseMailingListPlacementTargeting(value);
35448
+ if (!parsed.ok) {
35449
+ ctx.addIssue({
35450
+ code: z.ZodIssueCode.custom,
35451
+ message: "Invalid mailing-list targeting"
35452
+ });
35453
+ return z.NEVER;
35454
+ }
35455
+ return parsed.value;
35456
+ });
34592
35457
  const newsletterFieldSchema = z.object({
34593
35458
  id: z.string(),
34594
35459
  type: z.enum(["email", "text"]),
@@ -34596,18 +35461,23 @@ const newsletterFieldSchema = z.object({
34596
35461
  required: z.boolean(),
34597
35462
  placeholder: z.string().optional()
34598
35463
  });
34599
- const newsletterSignupBlockIdSchema = z.string().trim().min(1).transform(parseRequiredNewsletterSignupBlockId);
34600
- const signedNewsletterDestinationRefSchema = z.string().trim().min(1).transform(parseRequiredSignedNewsletterDestinationRef);
35464
+ const mailingListSignupBlockIdSchema = z.string().trim().min(1).transform(parseRequiredMailingListSignupBlockId);
35465
+ const mailingListContentVersionIdSchema = z.string().transform((value, ctx) => {
35466
+ const parsed = parseMailingListContentVersionId(value);
35467
+ if (parsed) return parsed;
35468
+ ctx.addIssue({
35469
+ code: z.ZodIssueCode.custom,
35470
+ message: "Invalid mailing-list content version ID"
35471
+ });
35472
+ return z.NEVER;
35473
+ });
35474
+ const signedMailingListSourceTokenSchema = z.string().trim().min(1).transform(parseRequiredMailingListSignedSourceToken);
34601
35475
  const newsletterSourceCommonSchema = z.object({
34602
35476
  siteId: z.string().optional(),
34603
35477
  apiBaseUrl: z.string().optional(),
34604
- preset: newsletterPresetSchema.optional(),
34605
- includePhone: z.boolean().optional(),
34606
- buttonLabel: z.string().nullable().optional(),
35478
+ mailingList: mailingListContextSchema.optional(),
35479
+ targeting: mailingListTargetingSchema.optional(),
34607
35480
  buttonVariant: newsletterButtonVariantSchema.nullable().optional(),
34608
- successMessage: z.string().nullable().optional(),
34609
- privacyNote: z.string().nullable().optional(),
34610
- tags: z.string().nullable().optional(),
34611
35481
  spamProtectionEnabled: z.boolean().optional(),
34612
35482
  className: z.string().nullable().optional()
34613
35483
  });
@@ -34615,54 +35485,61 @@ const newsletterSourceSchema = z.discriminatedUnion("source", [
34615
35485
  newsletterSourceCommonSchema.extend({
34616
35486
  source: z.literal("block"),
34617
35487
  blockId: z.string().nullable().optional(),
34618
- listId: z.string().nullable().optional(),
34619
- destinationProvider: newsletterDestinationProviderSchema.nullable().optional()
35488
+ contentVersionId: z.string().nullable().optional()
34620
35489
  }),
34621
35490
  newsletterSourceCommonSchema.extend({
34622
35491
  source: z.literal("signed-footer"),
34623
- destinationRef: z.object({
34624
- tag: z.literal("signed_destination_ref"),
34625
- token: signedNewsletterDestinationRefSchema
35492
+ sourceRef: z.object({
35493
+ tag: z.literal("signed_source_ref"),
35494
+ token: signedMailingListSourceTokenSchema
34626
35495
  })
34627
35496
  }),
34628
- newsletterSourceCommonSchema.extend({
34629
- source: z.literal("legacy-direct-list"),
34630
- listId: z.string().nullable()
34631
- })
35497
+ newsletterSourceCommonSchema.extend({ source: z.literal("preview") })
34632
35498
  ]);
34633
35499
  const newsletterDisplaySchema = z.object({
34634
35500
  kind: z.literal("newsletter-form"),
35501
+ availability: z.enum(["ready", "unavailable"]),
34635
35502
  className: z.string().nullable(),
34636
35503
  buttonLabel: z.string(),
35504
+ successMessage: z.string(),
34637
35505
  buttonVariant: newsletterButtonVariantSchema,
34638
- successMessage: z.string().nullable(),
34639
35506
  privacyNote: z.string().nullable(),
34640
- fields: z.array(newsletterFieldSchema)
35507
+ fields: z.array(newsletterFieldSchema),
35508
+ choices: z.array(z.object({
35509
+ id: z.string(),
35510
+ label: z.string()
35511
+ }))
34641
35512
  });
34642
35513
  const newsletterHydrationSchema = z.object({
34643
35514
  target: z.discriminatedUnion("tag", [
34644
35515
  z.object({
34645
35516
  tag: z.literal("block-source"),
34646
- destinationRef: z.object({
35517
+ sourceRef: z.object({
34647
35518
  tag: z.literal("block_ref"),
34648
- blockId: newsletterSignupBlockIdSchema
35519
+ blockId: mailingListSignupBlockIdSchema,
35520
+ contentVersionId: mailingListContentVersionIdSchema
34649
35521
  }).nullable()
34650
35522
  }),
34651
35523
  z.object({
34652
35524
  tag: z.literal("signed-footer-source"),
34653
- destinationRef: z.object({
34654
- tag: z.literal("signed_destination_ref"),
34655
- token: signedNewsletterDestinationRefSchema
35525
+ sourceRef: z.object({
35526
+ tag: z.literal("signed_source_ref"),
35527
+ token: signedMailingListSourceTokenSchema
34656
35528
  })
34657
35529
  }),
34658
- z.object({
34659
- tag: z.literal("legacy-direct-list"),
34660
- listId: z.string().nullable()
34661
- })
35530
+ z.object({ tag: z.literal("preview") })
35531
+ ]),
35532
+ setupRevision: z.number().int().positive().nullable(),
35533
+ choiceProvider: z.enum([
35534
+ "native",
35535
+ "brevo",
35536
+ "mailchimp"
35537
+ ]).nullable(),
35538
+ choicePresentation: z.enum([
35539
+ "hidden",
35540
+ "automatic",
35541
+ "visitor_choice"
34662
35542
  ]),
34663
- preset: newsletterPresetSchema,
34664
- includePhone: z.boolean(),
34665
- tags: z.string().nullable().optional(),
34666
35543
  spamProtectionEnabled: z.boolean().optional()
34667
35544
  });
34668
35545
  const newsletterRenderSchema = z.object({
@@ -34674,16 +35551,26 @@ z.object({
34674
35551
  apiBaseUrl: z.string().optional()
34675
35552
  });
34676
35553
  function buildNewsletterDisplay(source) {
34677
- const preset = source.preset ?? "emailOnly";
34678
- const includePhone = source.includePhone ?? false;
35554
+ const context = source.mailingList;
35555
+ const form = context?.tag === "configured" ? context.form : {
35556
+ fields: { preset: "emailOnly" },
35557
+ includeOptionalPhone: false,
35558
+ buttonLabel: "Subscribe",
35559
+ successMessage: DEFAULT_MAILING_LIST_SUCCESS_MESSAGE,
35560
+ privacyNote: null
35561
+ };
35562
+ const targeting = source.targeting ?? { mode: "default" };
35563
+ const choices = resolveRuntimeChoices(context, targeting);
34679
35564
  return {
34680
35565
  kind: "newsletter-form",
35566
+ availability: runtimeTargetingIsAvailable(context, targeting, choices) ? "ready" : "unavailable",
34681
35567
  className: source.className ?? null,
34682
- buttonLabel: source.buttonLabel?.trim() || "Subscribe",
35568
+ buttonLabel: form.buttonLabel,
35569
+ successMessage: form.successMessage,
34683
35570
  buttonVariant: source.buttonVariant ?? "primary",
34684
- successMessage: source.successMessage ?? "Thanks for subscribing!",
34685
- privacyNote: source.privacyNote ?? null,
34686
- fields: getPresetFields(preset, { includePhone })
35571
+ privacyNote: form.privacyNote,
35572
+ fields: getGlobalFormFields(form),
35573
+ choices
34687
35574
  };
34688
35575
  }
34689
35576
  const newsletterFormBlockRuntime = defineProgressiveBlockRuntime({
@@ -34693,14 +35580,15 @@ const newsletterFormBlockRuntime = defineProgressiveBlockRuntime({
34693
35580
  render: createZodCodec(newsletterRenderSchema)
34694
35581
  },
34695
35582
  buildRender: (source) => {
34696
- const runtimeSource = source.source === "block" ? deriveNewsletterSignupRuntimeSource(source) : null;
35583
+ const targeting = source.targeting ?? { mode: "default" };
35584
+ const presentation = planMailingListChoicePresentation(targeting);
34697
35585
  return {
34698
35586
  display: buildNewsletterDisplay(source),
34699
35587
  hydration: {
34700
35588
  target: projectNewsletterFormHydrationTarget(source),
34701
- preset: source.preset ?? "emailOnly",
34702
- includePhone: source.includePhone ?? false,
34703
- tags: runtimeSource ? runtimeSource.tags : source.tags,
35589
+ setupRevision: source.mailingList?.tag === "configured" ? source.mailingList.revision : null,
35590
+ choiceProvider: targeting.mode === "custom" ? targeting.provider : null,
35591
+ choicePresentation: presentation.tag,
34704
35592
  spamProtectionEnabled: source.spamProtectionEnabled
34705
35593
  }
34706
35594
  };
@@ -34709,35 +35597,87 @@ const newsletterFormBlockRuntime = defineProgressiveBlockRuntime({
34709
35597
  function projectNewsletterFormHydrationTarget(source) {
34710
35598
  switch (source.source) {
34711
35599
  case "block": {
34712
- const destinationRef = buildNewsletterSignupBlockRef(source.blockId);
34713
- if (destinationRef?.tag === "block_ref") return {
35600
+ const sourceRef = buildMailingListSignupBlockSourceRef(source.blockId, source.contentVersionId);
35601
+ if (sourceRef?.tag === "block_ref") return {
34714
35602
  tag: "block-source",
34715
- destinationRef
35603
+ sourceRef
34716
35604
  };
34717
35605
  return {
34718
- tag: "legacy-direct-list",
34719
- listId: source.listId ?? null
35606
+ tag: "block-source",
35607
+ sourceRef: null
34720
35608
  };
34721
35609
  }
34722
35610
  case "signed-footer": return {
34723
35611
  tag: "signed-footer-source",
34724
- destinationRef: source.destinationRef
34725
- };
34726
- case "legacy-direct-list": return {
34727
- tag: "legacy-direct-list",
34728
- listId: source.listId
35612
+ sourceRef: source.sourceRef
34729
35613
  };
35614
+ case "preview": return { tag: "preview" };
34730
35615
  default: return assertNever$3(source);
34731
35616
  }
34732
35617
  }
34733
- function parseRequiredNewsletterSignupBlockId(value) {
34734
- const parsed = parseNewsletterSignupBlockId(value);
34735
- if (!parsed) throw new Error("Newsletter signup block destination ref requires blockId");
35618
+ function resolveRuntimeChoices(context, targeting) {
35619
+ if (context?.tag !== "configured" || targeting.mode !== "custom" || targeting.selection.tag !== "visitor_choice" || context.provider.provider !== targeting.provider) return [];
35620
+ switch (targeting.provider) {
35621
+ case "native": {
35622
+ const offered = new Set(targeting.selection.offeredTopicIds);
35623
+ return context.provider.provider === "native" ? context.provider.topics.filter((item) => offered.has(item.id)).map((item) => ({
35624
+ id: item.id,
35625
+ label: item.name
35626
+ })) : [];
35627
+ }
35628
+ case "brevo": {
35629
+ const offered = new Set(targeting.selection.offeredListIds);
35630
+ return context.provider.provider === "brevo" ? context.provider.lists.filter((item) => offered.has(item.id)).map((item) => ({
35631
+ id: String(item.id),
35632
+ label: item.name
35633
+ })) : [];
35634
+ }
35635
+ case "mailchimp": {
35636
+ const offered = new Set(targeting.selection.offeredInterestIds);
35637
+ return (context.provider.provider === "mailchimp" ? context.provider.audiences.find((item) => item.id === targeting.audienceId) : void 0)?.interests.filter((item) => offered.has(item.id)).map((item) => ({
35638
+ id: item.id,
35639
+ label: item.name
35640
+ })) ?? [];
35641
+ }
35642
+ }
35643
+ }
35644
+ function runtimeTargetingIsAvailable(context, targeting, choices) {
35645
+ if (context?.tag !== "configured") return false;
35646
+ const provider = context.provider;
35647
+ if (targeting.mode === "default") switch (provider.provider) {
35648
+ case "native": return provider.topics.some((item) => item.id === provider.defaultTopicId);
35649
+ case "brevo": return provider.lists.some((item) => item.id === provider.defaultListId);
35650
+ case "mailchimp": return provider.audiences.some((item) => item.id === provider.defaultAudienceId);
35651
+ }
35652
+ if (targeting.provider !== provider.provider) return false;
35653
+ switch (targeting.provider) {
35654
+ case "native": return provider.provider === "native" && nativeTargetIsAvailable(provider, targeting, choices);
35655
+ case "brevo": return provider.provider === "brevo" && brevoTargetIsAvailable(provider, targeting, choices);
35656
+ case "mailchimp": return provider.provider === "mailchimp" && mailchimpTargetIsAvailable(provider, targeting, choices);
35657
+ }
35658
+ }
35659
+ function nativeTargetIsAvailable(provider, targeting, choices) {
35660
+ const ids = targeting.selection.tag === "fixed" ? targeting.selection.topicIds : targeting.selection.offeredTopicIds;
35661
+ return ids.every((id) => provider.topics.some((item) => item.id === id)) && (targeting.selection.tag !== "visitor_choice" || choices.length === ids.length);
35662
+ }
35663
+ function brevoTargetIsAvailable(provider, targeting, choices) {
35664
+ const ids = targeting.selection.tag === "fixed" ? targeting.selection.listIds : targeting.selection.offeredListIds;
35665
+ return ids.every((id) => provider.lists.some((item) => item.id === id)) && (targeting.selection.tag !== "visitor_choice" || choices.length === ids.length);
35666
+ }
35667
+ function mailchimpTargetIsAvailable(provider, targeting, choices) {
35668
+ const audience = provider.audiences.find((item) => item.id === targeting.audienceId);
35669
+ if (!audience) return false;
35670
+ const ids = targeting.selection.tag === "fixed" ? targeting.selection.interestIds : targeting.selection.offeredInterestIds;
35671
+ return ids.every((id) => audience.interests.some((item) => item.id === id)) && (targeting.selection.tag !== "visitor_choice" || choices.length === ids.length);
35672
+ }
35673
+ function parseRequiredMailingListSignupBlockId(value) {
35674
+ const parsed = parseMailingListBlockId(value);
35675
+ if (!parsed) throw new Error("Mailing-list signup block source ref requires blockId");
34736
35676
  return parsed;
34737
35677
  }
34738
- function parseRequiredSignedNewsletterDestinationRef(value) {
34739
- const parsed = parseSignedNewsletterDestinationRef(value);
34740
- if (!parsed) throw new Error("Newsletter signup signed destination ref requires token");
35678
+ function parseRequiredMailingListSignedSourceToken(value) {
35679
+ const parsed = parseMailingListSignedSourceToken(value);
35680
+ if (!parsed) throw new Error("Mailing-list signup signed source ref requires token");
34741
35681
  return parsed;
34742
35682
  }
34743
35683
  //#endregion
@@ -36110,6 +37050,14 @@ const systemBlockDefinitions = [
36110
37050
  weight: "standard"
36111
37051
  })]
36112
37052
  })),
37053
+ withDesignCapability("block.appointment-services", appointmentServicesBlockDefinition, sectionOnly(), defineBlockDesignMetadata({
37054
+ flow: conversionFlow,
37055
+ layoutProfiles: [layoutProfile({
37056
+ variantKey: "default",
37057
+ family: "stack",
37058
+ weight: "standard"
37059
+ })]
37060
+ })),
36113
37061
  withDesignCapability("block.weekly-slot-availability", weeklySlotAvailabilityBlockDefinition, sectionOnly(), defineBlockDesignMetadata({
36114
37062
  flow: offeringsFlow,
36115
37063
  layoutProfiles: [layoutProfile({
@@ -37189,8 +38137,12 @@ function shouldSkipResolvedLoader(input) {
37189
38137
  * ```
37190
38138
  */
37191
38139
  async function prefetchBlockData$1(page, context, options) {
38140
+ return (await prefetchBlockDataWithFailures(page, context, options)).resolvedData;
38141
+ }
38142
+ async function prefetchBlockDataWithFailures(page, context, options) {
37192
38143
  const { apiClient, isValidEndpoint, onError, getCustomBlockLoaders, getBlockDefinition: getBlockDefinition$1 = getBlockDefinition, resolveParamsBindings: resolveParamsBindings$1 = resolveParamsBindings } = options;
37193
38144
  const results = {};
38145
+ const loaderFailures = {};
37194
38146
  const tasks = [];
37195
38147
  for (const block of page.blocks) {
37196
38148
  const blockId = block.id;
@@ -37238,6 +38190,11 @@ async function prefetchBlockData$1(page, context, options) {
37238
38190
  const blockResults = results[blockId] ?? (results[blockId] = {});
37239
38191
  blockResults[key] = data;
37240
38192
  } catch (error) {
38193
+ const blockFailures = loaderFailures[blockId] ?? (loaderFailures[blockId] = {});
38194
+ blockFailures[key] = {
38195
+ endpoint,
38196
+ params
38197
+ };
37241
38198
  if (onError) onError(error, {
37242
38199
  block: block.kind,
37243
38200
  loader: key
@@ -37247,7 +38204,10 @@ async function prefetchBlockData$1(page, context, options) {
37247
38204
  }
37248
38205
  }
37249
38206
  if (tasks.length > 0) await Promise.all(tasks);
37250
- return results;
38207
+ return {
38208
+ resolvedData: results,
38209
+ loaderFailures
38210
+ };
37251
38211
  }
37252
38212
  //#endregion
37253
38213
  //#region ../blocks/src/system/data/loaderEndpoints.ts
@@ -37597,7 +38557,17 @@ const riverbankSiteConfigInputSchema = z.object({
37597
38557
  z.object({
37598
38558
  config: riverbankSiteConfigInputSchema,
37599
38559
  forceContentTypes: z.boolean().optional(),
37600
- mode: z.enum(["apply", "preview"]).optional()
38560
+ mode: z.enum(["apply", "preview"]).optional(),
38561
+ expectedMailingListProviderScope: z.unknown().transform((value, ctx) => {
38562
+ if (value === void 0) return void 0;
38563
+ const parsed = parseMailingListProviderScope(value);
38564
+ if (parsed.ok) return parsed.value;
38565
+ ctx.addIssue({
38566
+ code: "custom",
38567
+ message: "Invalid mailing-list provider scope"
38568
+ });
38569
+ return z.NEVER;
38570
+ }).optional()
37601
38571
  }).strict();
37602
38572
  //#endregion
37603
38573
  //#region ../api/src/sdkThemeWire.ts
@@ -38725,6 +39695,7 @@ const SYSTEM_BLOCK_KINDS = [
38725
39695
  "block.form",
38726
39696
  "block.contact-newsletter",
38727
39697
  "block.appointment-booking",
39698
+ "block.appointment-services",
38728
39699
  "block.weekly-slot-availability",
38729
39700
  "block.event-registration",
38730
39701
  "block.event-details",