@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
@@ -2178,59 +2178,6 @@ function surfaceForegroundStyle(input) {
2178
2178
  [SURFACE_FOREGROUND_CSS_VARS.supporting]: foregrounds.supporting
2179
2179
  };
2180
2180
  }
2181
- shadeBackgroundEffect({
2182
- id: "darken-background",
2183
- name: "Darken on Hover",
2184
- description: "Darkens the background color on hover",
2185
- label: "Darken Amount (shade step)",
2186
- shadeDirection: 1
2187
- });
2188
- shadeBackgroundEffect({
2189
- id: "lighten-background",
2190
- name: "Lighten on Hover",
2191
- description: "Lightens the background color on hover",
2192
- label: "Lighten Amount (shade step)",
2193
- shadeDirection: -1
2194
- });
2195
- function shadeBackgroundEffect(config) {
2196
- return {
2197
- id: config.id,
2198
- name: config.name,
2199
- description: config.description,
2200
- category: "background",
2201
- pseudoElement: "none",
2202
- applicableTo: ["button"],
2203
- customizableOption: {
2204
- name: "amount",
2205
- type: "select",
2206
- label: config.label,
2207
- default: 100,
2208
- options: [
2209
- 0,
2210
- 100,
2211
- 200,
2212
- 300,
2213
- 400,
2214
- 500,
2215
- 600,
2216
- 700,
2217
- 800,
2218
- 900
2219
- ]
2220
- },
2221
- isApplicable: (buttonConfig) => buttonConfig.background.type === "solid",
2222
- generateCSS: ({ themeId, variantId, options, tokens, buttonConfig }) => {
2223
- if (buttonConfig.background.type !== "solid") return "";
2224
- const amount = (options.amount || 100) * config.shadeDirection;
2225
- const baseToken = buttonConfig.background.colorToken ?? "primary-500";
2226
- return `
2227
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
2228
- background-color: ${tokens.getColor(tokens.adjustShade(baseToken, amount))};
2229
- }
2230
- `;
2231
- }
2232
- };
2233
- }
2234
2181
  //#endregion
2235
2182
  //#region ../theme-core/src/utils/colorStyles.ts
2236
2183
  const COLOR_VAR_PREFIX = "--tb-";
@@ -2327,6 +2274,59 @@ function mergeStyles(...styles) {
2327
2274
  }
2328
2275
  return Object.keys(merged).length ? merged : void 0;
2329
2276
  }
2277
+ shadeBackgroundEffect({
2278
+ id: "darken-background",
2279
+ name: "Darken on Hover",
2280
+ description: "Darkens the background color on hover",
2281
+ label: "Darken Amount (shade step)",
2282
+ shadeDirection: 1
2283
+ });
2284
+ shadeBackgroundEffect({
2285
+ id: "lighten-background",
2286
+ name: "Lighten on Hover",
2287
+ description: "Lightens the background color on hover",
2288
+ label: "Lighten Amount (shade step)",
2289
+ shadeDirection: -1
2290
+ });
2291
+ function shadeBackgroundEffect(config) {
2292
+ return {
2293
+ id: config.id,
2294
+ name: config.name,
2295
+ description: config.description,
2296
+ category: "background",
2297
+ pseudoElement: "none",
2298
+ applicableTo: ["button"],
2299
+ customizableOption: {
2300
+ name: "amount",
2301
+ type: "select",
2302
+ label: config.label,
2303
+ default: 100,
2304
+ options: [
2305
+ 0,
2306
+ 100,
2307
+ 200,
2308
+ 300,
2309
+ 400,
2310
+ 500,
2311
+ 600,
2312
+ 700,
2313
+ 800,
2314
+ 900
2315
+ ]
2316
+ },
2317
+ isApplicable: (buttonConfig) => buttonConfig.background.type === "solid",
2318
+ generateCSS: ({ themeId, variantId, options, tokens, buttonConfig }) => {
2319
+ if (buttonConfig.background.type !== "solid") return "";
2320
+ const amount = (options.amount || 100) * config.shadeDirection;
2321
+ const baseToken = buttonConfig.background.colorToken ?? "primary-500";
2322
+ return `
2323
+ :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
2324
+ background-color: ${tokens.getColor(tokens.adjustShade(baseToken, amount))};
2325
+ }
2326
+ `;
2327
+ }
2328
+ };
2329
+ }
2330
2330
  //#endregion
2331
2331
  //#region ../theme-core/src/utils/tokenOrColor.ts
2332
2332
  /**
@@ -5335,8 +5335,14 @@ const headerInteractionPillPaletteValues = [
5335
5335
  "accent"
5336
5336
  ];
5337
5337
  /**
5338
- * "No pill": the nav link keeps whatever hover treatment its recipe compiled,
5339
- * and the palette step writes nothing at all (#1318 Phase 4c decision 2).
5338
+ * "No pill": a colour change on hover rather than a filled background.
5339
+ *
5340
+ * The palette step writes nothing (#1318 Phase 4c decision 2), but on a
5341
+ * foreground-adaptive style that is not the end of the story: the hover colour
5342
+ * is derived from the resolved opening foreground at render time, paired with
5343
+ * the resting colour, so `quiet` resolves to a definite colour rather than to
5344
+ * whatever brand token the recipe happened to name. See
5345
+ * `applyOpeningForeground`.
5340
5346
  *
5341
5347
  * It exists because "a colour change on hover, no filled background" was not
5342
5348
  * expressible in the vocabulary, and it is what
@@ -5404,7 +5410,7 @@ const boxBackgroundSchema = z.discriminatedUnion("type", [
5404
5410
  })
5405
5411
  ]);
5406
5412
  function normalizeAuthoringOpacity(value) {
5407
- if (!isRecord$6(value)) return value;
5413
+ if (!isRecord$9(value)) return value;
5408
5414
  return {
5409
5415
  ...value,
5410
5416
  opacity: normalizeOpacity(value.opacity)
@@ -5413,7 +5419,7 @@ function normalizeAuthoringOpacity(value) {
5413
5419
  function normalizeOpacity(value) {
5414
5420
  return typeof value === "number" && value > 1 && value <= 100 ? value / 100 : value;
5415
5421
  }
5416
- function isRecord$6(value) {
5422
+ function isRecord$9(value) {
5417
5423
  return typeof value === "object" && value !== null && !Array.isArray(value);
5418
5424
  }
5419
5425
  //#endregion
@@ -10973,17 +10979,19 @@ function err(error) {
10973
10979
  }
10974
10980
  //#endregion
10975
10981
  //#region ../core/src/branded.ts
10976
- const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
10982
+ 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;
10977
10983
  function parseUuidBrand(value, unsafeConstructor) {
10978
10984
  if (typeof value !== "string") return err({ kind: "not_string" });
10979
10985
  const normalized = value.trim().toLowerCase();
10980
10986
  if (normalized.length === 0) return err({ kind: "empty_string" });
10981
- if (!UUID_PATTERN.test(normalized)) return err({ kind: "invalid_uuid" });
10987
+ if (!UUID_PATTERN$1.test(normalized)) return err({ kind: "invalid_uuid" });
10982
10988
  return ok(unsafeConstructor(normalized));
10983
10989
  }
10984
10990
  const unsafeAsEventOfferingId = (id) => id;
10985
10991
  const unsafeAsEventSeriesId = (id) => id;
10992
+ const unsafeAsContentVersionId = (id) => id;
10986
10993
  const parseEventOfferingId = (value) => parseUuidBrand(value, unsafeAsEventOfferingId);
10994
+ const parseContentVersionId = (value) => parseUuidBrand(value, unsafeAsContentVersionId);
10987
10995
  const parseEventSeriesId = (value) => parseUuidBrand(value, unsafeAsEventSeriesId);
10988
10996
  //#endregion
10989
10997
  //#region ../core/src/assert-never.ts
@@ -11217,7 +11225,7 @@ function parseEventPageSurfaceDestinationMode(value) {
11217
11225
  return value === "cms-managed" || value === "system-managed" ? value : void 0;
11218
11226
  }
11219
11227
  function parseEventPageSurfaceSubject(value) {
11220
- if (!isRecord$5(value)) return err({ kind: "notObject" });
11228
+ if (!isRecord$8(value)) return err({ kind: "notObject" });
11221
11229
  switch (value.kind) {
11222
11230
  case "eventSeries": {
11223
11231
  const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
@@ -11272,7 +11280,7 @@ function parseEventSeriesIdList(values) {
11272
11280
  }
11273
11281
  return ok(parsed);
11274
11282
  }
11275
- function isRecord$5(value) {
11283
+ function isRecord$8(value) {
11276
11284
  return typeof value === "object" && value !== null && !Array.isArray(value);
11277
11285
  }
11278
11286
  //#endregion
@@ -11442,9 +11450,391 @@ function toLocationCoordinates(value) {
11442
11450
  };
11443
11451
  }
11444
11452
  //#endregion
11445
- //#region ../core/src/newsletter-signup-destination.ts
11446
- function parseNewsletterSignupDestinationProvider(value) {
11447
- return value === "riverbank" || value === "mailchimp" ? value : null;
11453
+ //#region ../core/src/mailing-list-identifiers.ts
11454
+ 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;
11455
+ const OPAQUE_ID_PATTERN = /^[A-Za-z0-9_-]{1,100}$/u;
11456
+ function parseTrimmedMatchingString(value, pattern) {
11457
+ if (typeof value !== "string") return null;
11458
+ const trimmed = value.trim();
11459
+ return pattern.test(trimmed) ? trimmed : null;
11460
+ }
11461
+ function parsePositiveInteger(value) {
11462
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : null;
11463
+ }
11464
+ function parseNewsletterListId(value) {
11465
+ return parseTrimmedMatchingString(value, UUID_PATTERN);
11466
+ }
11467
+ function parseMailchimpAudienceId(value) {
11468
+ return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
11469
+ }
11470
+ function parseMailchimpInterestId(value) {
11471
+ return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
11472
+ }
11473
+ function parseBrevoListId(value) {
11474
+ return parsePositiveInteger(value);
11475
+ }
11476
+ //#endregion
11477
+ //#region ../core/src/mailing-list-setup.ts
11478
+ const DEFAULT_MAILING_LIST_SUCCESS_MESSAGE = "Thanks — you're on the list.";
11479
+ //#endregion
11480
+ //#region ../core/src/mailing-list-setup-parser.ts
11481
+ function parseMailingListGlobalForm(value) {
11482
+ if (!isRecord$7(value)) return formError("shape");
11483
+ const fields = parseGlobalFields(value.fields);
11484
+ if (fields === null) return formError("fields");
11485
+ if (typeof value.includeOptionalPhone !== "boolean") return formError("includeOptionalPhone");
11486
+ const buttonLabel = parseRequiredString(value.buttonLabel);
11487
+ if (buttonLabel === null) return formError("buttonLabel");
11488
+ const successMessage = parseRequiredString(value.successMessage);
11489
+ if (successMessage === null) return formError("successMessage");
11490
+ const privacyNote = parseOptionalString(value.privacyNote);
11491
+ if (privacyNote === void 0) return formError("privacyNote");
11492
+ return ok({
11493
+ fields,
11494
+ includeOptionalPhone: value.includeOptionalPhone,
11495
+ buttonLabel,
11496
+ successMessage,
11497
+ privacyNote
11498
+ });
11499
+ }
11500
+ function parseGlobalFields(value) {
11501
+ if (!isRecord$7(value) || typeof value.preset !== "string") return null;
11502
+ switch (value.preset) {
11503
+ case "emailOnly": return { preset: "emailOnly" };
11504
+ case "emailName": return isRequirement(value.name) ? {
11505
+ preset: "emailName",
11506
+ name: value.name
11507
+ } : null;
11508
+ case "emailFirstLast": return isRequirement(value.firstName) && isRequirement(value.lastName) ? {
11509
+ preset: "emailFirstLast",
11510
+ firstName: value.firstName,
11511
+ lastName: value.lastName
11512
+ } : null;
11513
+ case "emailNameCompany": return isRequirement(value.name) && isRequirement(value.company) ? {
11514
+ preset: "emailNameCompany",
11515
+ name: value.name,
11516
+ company: value.company
11517
+ } : null;
11518
+ default: return null;
11519
+ }
11520
+ }
11521
+ function parseMailingListSetupRevision(value) {
11522
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : null;
11523
+ }
11524
+ function parseRequiredString(value) {
11525
+ if (typeof value !== "string") return null;
11526
+ const trimmed = value.trim();
11527
+ return trimmed.length > 0 ? trimmed : null;
11528
+ }
11529
+ function parseOptionalString(value) {
11530
+ if (value === null || value === void 0) return null;
11531
+ if (typeof value !== "string") return void 0;
11532
+ const trimmed = value.trim();
11533
+ return trimmed.length > 0 ? trimmed : null;
11534
+ }
11535
+ function isRequirement(value) {
11536
+ return value === "required" || value === "optional";
11537
+ }
11538
+ function isRecord$7(value) {
11539
+ return typeof value === "object" && value !== null && !Array.isArray(value);
11540
+ }
11541
+ function formError(field) {
11542
+ return err({
11543
+ tag: "invalid_mailing_list_global_form",
11544
+ field
11545
+ });
11546
+ }
11547
+ //#endregion
11548
+ //#region ../core/src/mailing-list-targeting.ts
11549
+ function planMailingListChoicePresentation(targeting) {
11550
+ if (targeting.mode === "default" || targeting.selection.tag === "fixed") return { tag: "hidden" };
11551
+ switch (targeting.provider) {
11552
+ case "native": return targeting.selection.offeredTopicIds.length === 1 ? {
11553
+ tag: "automatic",
11554
+ selection: {
11555
+ provider: "native",
11556
+ topicIds: targeting.selection.offeredTopicIds
11557
+ }
11558
+ } : {
11559
+ tag: "visitor_choice",
11560
+ provider: "native",
11561
+ optionCount: targeting.selection.offeredTopicIds.length
11562
+ };
11563
+ case "brevo": return targeting.selection.offeredListIds.length === 1 ? {
11564
+ tag: "automatic",
11565
+ selection: {
11566
+ provider: "brevo",
11567
+ listIds: targeting.selection.offeredListIds
11568
+ }
11569
+ } : {
11570
+ tag: "visitor_choice",
11571
+ provider: "brevo",
11572
+ optionCount: targeting.selection.offeredListIds.length
11573
+ };
11574
+ case "mailchimp": return targeting.selection.offeredInterestIds.length === 1 ? {
11575
+ tag: "automatic",
11576
+ selection: {
11577
+ provider: "mailchimp",
11578
+ interestIds: targeting.selection.offeredInterestIds
11579
+ }
11580
+ } : {
11581
+ tag: "visitor_choice",
11582
+ provider: "mailchimp",
11583
+ optionCount: targeting.selection.offeredInterestIds.length
11584
+ };
11585
+ }
11586
+ }
11587
+ //#endregion
11588
+ //#region ../core/src/mailing-list-runtime.ts
11589
+ function parseMailingListRuntimeContext(value) {
11590
+ if (!isRecord$6(value)) return invalidRuntimeContext();
11591
+ if (value.tag === "not_configured") return ok({ tag: "not_configured" });
11592
+ if (value.tag !== "configured") return invalidRuntimeContext();
11593
+ const revision = parseMailingListSetupRevision(value.revision);
11594
+ const form = parseMailingListGlobalForm(value.form);
11595
+ const provider = parseRuntimeProvider(value.provider);
11596
+ if (revision === null || !form.ok || provider === null) return invalidRuntimeContext();
11597
+ return ok({
11598
+ tag: "configured",
11599
+ revision,
11600
+ form: form.value,
11601
+ provider
11602
+ });
11603
+ }
11604
+ function parseRuntimeProvider(value) {
11605
+ if (!isRecord$6(value)) return null;
11606
+ switch (value.provider) {
11607
+ case "native": return parseNativeRuntimeProvider(value);
11608
+ case "brevo": return parseBrevoRuntimeProvider(value);
11609
+ case "mailchimp": return parseMailchimpRuntimeProvider(value);
11610
+ default: return null;
11611
+ }
11612
+ }
11613
+ function parseNativeRuntimeProvider(value) {
11614
+ const defaultTopicId = parseNewsletterListId(value.defaultTopicId);
11615
+ const topics = parseNamedItems(value.topics, parseNewsletterListId);
11616
+ return defaultTopicId !== null && topics !== null ? {
11617
+ provider: "native",
11618
+ defaultTopicId,
11619
+ topics
11620
+ } : null;
11621
+ }
11622
+ function parseBrevoRuntimeProvider(value) {
11623
+ const defaultListId = parseBrevoListId(value.defaultListId);
11624
+ const lists = parseNamedItems(value.lists, parseBrevoListId);
11625
+ return defaultListId !== null && lists !== null ? {
11626
+ provider: "brevo",
11627
+ defaultListId,
11628
+ lists
11629
+ } : null;
11630
+ }
11631
+ function parseMailchimpRuntimeProvider(value) {
11632
+ if (!Array.isArray(value.audiences)) return null;
11633
+ const defaultAudienceId = parseMailchimpAudienceId(value.defaultAudienceId);
11634
+ if (defaultAudienceId === null) return null;
11635
+ const audiences = [];
11636
+ for (const audience of value.audiences) {
11637
+ if (!isRecord$6(audience)) return null;
11638
+ const id = parseMailchimpAudienceId(audience.id);
11639
+ const name = parseName(audience.name);
11640
+ if (id === null || name === null || !Array.isArray(audience.interests)) return null;
11641
+ const interests = parseMailchimpInterests(audience.interests);
11642
+ if (interests === null) return null;
11643
+ audiences.push({
11644
+ id,
11645
+ name,
11646
+ interests
11647
+ });
11648
+ }
11649
+ return {
11650
+ provider: "mailchimp",
11651
+ defaultAudienceId,
11652
+ audiences
11653
+ };
11654
+ }
11655
+ function parseMailchimpInterests(value) {
11656
+ const interests = [];
11657
+ for (const interest of value) {
11658
+ if (!isRecord$6(interest)) return null;
11659
+ const id = parseMailchimpInterestId(interest.id);
11660
+ const name = parseName(interest.name);
11661
+ const categoryName = parseName(interest.categoryName);
11662
+ if (id === null || name === null || categoryName === null) return null;
11663
+ interests.push({
11664
+ id,
11665
+ name,
11666
+ categoryName
11667
+ });
11668
+ }
11669
+ return interests;
11670
+ }
11671
+ function parseNamedItems(value, parseId) {
11672
+ if (!Array.isArray(value)) return null;
11673
+ const items = [];
11674
+ for (const item of value) {
11675
+ if (!isRecord$6(item)) return null;
11676
+ const id = parseId(item.id);
11677
+ const name = parseName(item.name);
11678
+ if (id === null || name === null) return null;
11679
+ items.push({
11680
+ id,
11681
+ name
11682
+ });
11683
+ }
11684
+ return items;
11685
+ }
11686
+ function parseName(value) {
11687
+ if (typeof value !== "string") return null;
11688
+ const name = value.trim();
11689
+ return name.length > 0 ? name : null;
11690
+ }
11691
+ function isRecord$6(value) {
11692
+ return typeof value === "object" && value !== null && !Array.isArray(value);
11693
+ }
11694
+ function invalidRuntimeContext() {
11695
+ return err({ tag: "invalid_mailing_list_runtime_context" });
11696
+ }
11697
+ //#endregion
11698
+ //#region ../core/src/mailing-list-targeting-parser.ts
11699
+ function parseMailingListPlacementTargeting(value) {
11700
+ if (!isRecord$5(value)) return targetingError("shape");
11701
+ if (value.mode === "default") return ok({ mode: "default" });
11702
+ if (value.mode !== "custom") return targetingError("mode");
11703
+ if (!isRecord$5(value.selection)) return targetingError("selection");
11704
+ switch (value.provider) {
11705
+ case "native": return parseNativeTargeting(value.selection);
11706
+ case "brevo": return parseBrevoTargeting(value.selection);
11707
+ case "mailchimp": return parseMailchimpTargeting(value, value.selection);
11708
+ default: return targetingError("provider");
11709
+ }
11710
+ }
11711
+ function parseNativeTargeting(selection) {
11712
+ if (selection.tag === "fixed") {
11713
+ const topicIds = parseNonEmptyUniqueIds(selection.topicIds, parseNewsletterListId);
11714
+ return topicIds.ok ? ok({
11715
+ mode: "custom",
11716
+ provider: "native",
11717
+ selection: {
11718
+ tag: "fixed",
11719
+ topicIds: topicIds.value
11720
+ }
11721
+ }) : topicIds;
11722
+ }
11723
+ if (selection.tag === "visitor_choice") {
11724
+ const offeredTopicIds = parseNonEmptyUniqueIds(selection.offeredTopicIds, parseNewsletterListId);
11725
+ return offeredTopicIds.ok ? ok({
11726
+ mode: "custom",
11727
+ provider: "native",
11728
+ selection: {
11729
+ tag: "visitor_choice",
11730
+ offeredTopicIds: offeredTopicIds.value
11731
+ }
11732
+ }) : offeredTopicIds;
11733
+ }
11734
+ return targetingError("selection");
11735
+ }
11736
+ function parseBrevoTargeting(selection) {
11737
+ if (selection.tag === "fixed") {
11738
+ const listIds = parseNonEmptyUniqueIds(selection.listIds, parseBrevoListId);
11739
+ return listIds.ok ? ok({
11740
+ mode: "custom",
11741
+ provider: "brevo",
11742
+ selection: {
11743
+ tag: "fixed",
11744
+ listIds: listIds.value
11745
+ }
11746
+ }) : listIds;
11747
+ }
11748
+ if (selection.tag === "visitor_choice") {
11749
+ const offeredListIds = parseNonEmptyUniqueIds(selection.offeredListIds, parseBrevoListId);
11750
+ return offeredListIds.ok ? ok({
11751
+ mode: "custom",
11752
+ provider: "brevo",
11753
+ selection: {
11754
+ tag: "visitor_choice",
11755
+ offeredListIds: offeredListIds.value
11756
+ }
11757
+ }) : offeredListIds;
11758
+ }
11759
+ return targetingError("selection");
11760
+ }
11761
+ function parseMailchimpTargeting(value, selection) {
11762
+ const audienceId = parseMailchimpAudienceId(value.audienceId);
11763
+ if (audienceId === null) return targetingError("audienceId");
11764
+ if (selection.tag === "fixed") {
11765
+ const interestIds = parseUniqueIds(selection.interestIds, parseMailchimpInterestId);
11766
+ return interestIds.ok ? ok({
11767
+ mode: "custom",
11768
+ provider: "mailchimp",
11769
+ audienceId,
11770
+ selection: {
11771
+ tag: "fixed",
11772
+ interestIds: interestIds.value
11773
+ }
11774
+ }) : interestIds;
11775
+ }
11776
+ if (selection.tag === "visitor_choice") {
11777
+ const offeredInterestIds = parseNonEmptyUniqueIds(selection.offeredInterestIds, parseMailchimpInterestId);
11778
+ return offeredInterestIds.ok ? ok({
11779
+ mode: "custom",
11780
+ provider: "mailchimp",
11781
+ audienceId,
11782
+ selection: {
11783
+ tag: "visitor_choice",
11784
+ offeredInterestIds: offeredInterestIds.value
11785
+ }
11786
+ }) : offeredInterestIds;
11787
+ }
11788
+ return targetingError("selection");
11789
+ }
11790
+ function parseNonEmptyUniqueIds(value, parseId) {
11791
+ const parsed = parseUniqueIds(value, parseId);
11792
+ if (!parsed.ok) return parsed;
11793
+ const [first, ...rest] = parsed.value;
11794
+ return first === void 0 ? targetingError("targets") : ok([first, ...rest]);
11795
+ }
11796
+ function parseUniqueIds(value, parseId) {
11797
+ if (!Array.isArray(value)) return targetingError("targets");
11798
+ const parsed = [];
11799
+ for (const item of value) {
11800
+ const id = parseId(item);
11801
+ if (id === null) return targetingError("targets");
11802
+ if (parsed.includes(id)) return targetingError("duplicate_target");
11803
+ parsed.push(id);
11804
+ }
11805
+ return ok(parsed);
11806
+ }
11807
+ function isRecord$5(value) {
11808
+ return typeof value === "object" && value !== null && !Array.isArray(value);
11809
+ }
11810
+ function targetingError(field) {
11811
+ return err({
11812
+ tag: "invalid_mailing_list_targeting",
11813
+ field
11814
+ });
11815
+ }
11816
+ //#endregion
11817
+ //#region ../core/src/mailing-list-submission.ts
11818
+ function parseMailingListBlockId(value) {
11819
+ const parsed = typeof value === "string" ? value.trim() : "";
11820
+ 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;
11821
+ }
11822
+ function parseMailingListSignedSourceToken(value) {
11823
+ const parsed = typeof value === "string" ? value.trim() : "";
11824
+ return /^[A-Za-z0-9._~-]{16,1000}$/u.test(parsed) ? parsed : null;
11825
+ }
11826
+ function parseMailingListContentVersionId(value) {
11827
+ const parsed = parseContentVersionId(value);
11828
+ return parsed.ok ? parsed.value : null;
11829
+ }
11830
+ function buildMailingListSignupBlockSourceRef(blockId, contentVersionId) {
11831
+ const parsedBlockId = parseMailingListBlockId(blockId);
11832
+ const parsedContentVersionId = parseMailingListContentVersionId(contentVersionId);
11833
+ return parsedBlockId !== null && parsedContentVersionId !== null ? {
11834
+ tag: "block_ref",
11835
+ blockId: parsedBlockId,
11836
+ contentVersionId: parsedContentVersionId
11837
+ } : null;
11448
11838
  }
11449
11839
  function sessionStartMs(session) {
11450
11840
  return Date.parse(session.startsAt);
@@ -16264,149 +16654,74 @@ const newsletterFormFragment = defineFragment({
16264
16654
  description: "Newsletter subscription form with preset field configurations.",
16265
16655
  fields: [
16266
16656
  {
16267
- id: "destinationProvider",
16268
- type: "select",
16269
- label: "Send signups to",
16270
- description: "Choose where new subscribers from this form should go.",
16271
- defaultValue: "riverbank",
16272
- required: false,
16273
- ui: { intent: "behavior" },
16274
- options: [{
16275
- value: "riverbank",
16276
- label: "Riverbank newsletter"
16277
- }]
16278
- },
16279
- {
16280
- id: "listId",
16281
- type: "reference",
16282
- label: "Newsletter list",
16283
- description: "Select the list new subscribers should be added to.",
16284
- required: false,
16285
- referenceKind: "newsletterList",
16286
- allowManualEntry: false,
16657
+ id: "targeting",
16658
+ type: "group",
16659
+ label: "Mailing-list targeting",
16660
+ description: "Choose what kind of emails people signing up here will receive.",
16661
+ defaultValue: { mode: "default" },
16662
+ required: true,
16287
16663
  ui: {
16288
16664
  intent: "behavior",
16289
- visibleWhen: {
16290
- field: "destinationProvider",
16291
- equals: "riverbank"
16292
- }
16293
- }
16665
+ widget: "mailingListTargeting"
16666
+ },
16667
+ schema: { fields: [{
16668
+ id: "mode",
16669
+ type: "select",
16670
+ label: "Mode",
16671
+ required: true,
16672
+ defaultValue: "default",
16673
+ options: [{
16674
+ value: "default",
16675
+ label: "Default"
16676
+ }, {
16677
+ value: "custom",
16678
+ label: "Custom"
16679
+ }],
16680
+ ui: { hidden: true }
16681
+ }] }
16294
16682
  },
16683
+ createButtonVariantField({
16684
+ id: "buttonVariant",
16685
+ label: "Button style",
16686
+ defaultValue: "primary"
16687
+ }),
16295
16688
  {
16296
- id: "mailchimpAudienceId",
16297
- type: "reference",
16298
- label: "Mailchimp audience",
16299
- description: "Choose the Mailchimp audience for new subscribers.",
16300
- required: false,
16301
- referenceKind: "mailchimpAudience",
16302
- allowManualEntry: false,
16689
+ id: "mailingListSource",
16690
+ type: "text",
16691
+ label: "Mailing-list source",
16303
16692
  ui: {
16304
- intent: "behavior",
16305
- visibleWhen: {
16306
- field: "destinationProvider",
16307
- equals: "mailchimp"
16308
- }
16693
+ hidden: true,
16694
+ intent: "behavior"
16309
16695
  }
16310
16696
  },
16311
16697
  {
16312
- id: "mailchimpTags",
16698
+ id: "mailingListSourceToken",
16313
16699
  type: "text",
16314
- label: "Mailchimp tags",
16315
- description: "Optional tags to apply in Mailchimp, separated by commas or semicolons.",
16700
+ label: "Mailing-list source token",
16316
16701
  ui: {
16317
- intent: "behavior",
16318
- visibleWhen: {
16319
- field: "destinationProvider",
16320
- equals: "mailchimp"
16321
- }
16702
+ hidden: true,
16703
+ intent: "behavior"
16322
16704
  }
16705
+ }
16706
+ ],
16707
+ layout: [el("newsletter-form", withApiBindings({
16708
+ source: { $bind: {
16709
+ from: "mailingListSource",
16710
+ fallback: "block"
16711
+ } },
16712
+ sourceRef: {
16713
+ tag: "signed_source_ref",
16714
+ token: { $bind: { from: "mailingListSourceToken" } }
16323
16715
  },
16324
- {
16325
- id: "preset",
16326
- type: "select",
16327
- label: "Form fields",
16328
- description: "Choose which fields to collect.",
16329
- defaultValue: "emailOnly",
16330
- ui: { intent: "display" },
16331
- options: [
16332
- {
16333
- value: "emailOnly",
16334
- label: "Email only"
16335
- },
16336
- {
16337
- value: "emailName",
16338
- label: "Email + Name"
16339
- },
16340
- {
16341
- value: "emailFirstLast",
16342
- label: "Email + First/Last Name"
16343
- },
16344
- {
16345
- value: "emailNameCompany",
16346
- label: "Email + Name + Company (B2B)"
16347
- }
16348
- ]
16349
- },
16350
- {
16351
- id: "includePhone",
16352
- type: "boolean",
16353
- label: "Include phone field (optional)",
16354
- description: "Adds an optional phone field to the selected preset (never required).",
16355
- defaultValue: false,
16356
- ui: { intent: "display" }
16357
- },
16358
- {
16359
- id: "buttonLabel",
16360
- type: "text",
16361
- label: "Button label",
16362
- defaultValue: "Subscribe"
16363
- },
16364
- createButtonVariantField({
16365
- id: "buttonVariant",
16366
- label: "Button style",
16367
- defaultValue: "primary"
16368
- }),
16369
- {
16370
- id: "successMessage",
16371
- type: "text",
16372
- label: "Success message",
16373
- description: "Shown after successful subscription.",
16374
- defaultValue: "Thanks for subscribing!"
16375
- },
16376
- {
16377
- id: "privacyNote",
16378
- type: "text",
16379
- label: "Privacy note",
16380
- description: "Optional small text below the form (e.g., privacy policy link)."
16381
- },
16382
- {
16383
- id: "tags",
16384
- type: "text",
16385
- label: "Tags (optional)",
16386
- description: "Optional tags to apply on subscribe (comma or semicolon separated).",
16387
- ui: {
16388
- intent: "behavior",
16389
- visibleWhen: {
16390
- field: "destinationProvider",
16391
- equals: "riverbank"
16392
- }
16393
- }
16394
- }
16395
- ],
16396
- layout: [el("newsletter-form", withApiBindings({
16397
- source: "block",
16398
- destinationProvider: { $bind: { from: "destinationProvider" } },
16399
- listId: { $bind: { from: "listId" } },
16400
- preset: { $bind: { from: "preset" } },
16401
- includePhone: { $bind: { from: "includePhone" } },
16402
- buttonLabel: { $bind: { from: "buttonLabel" } },
16716
+ targeting: { $bind: {
16717
+ from: "targeting",
16718
+ fallback: { mode: "default" }
16719
+ } },
16720
+ mailingList: { $bind: { from: "$root.mailingList" } },
16403
16721
  buttonVariant: { $bind: {
16404
16722
  from: "buttonVariant",
16405
16723
  fallback: "primary"
16406
16724
  } },
16407
- successMessage: { $bind: { from: "successMessage" } },
16408
- privacyNote: { $bind: { from: "privacyNote" } },
16409
- tags: { $bind: { from: "tags" } },
16410
16725
  spamProtectionEnabled: { $bind: { from: "$root.spamProtectionEnabled" } }
16411
16726
  }), [])]
16412
16727
  });
@@ -18581,14 +18896,19 @@ const contactNewsletterLayout = styledSection({
18581
18896
  as: "h2",
18582
18897
  className: "newsletter-copy-title"
18583
18898
  }, when("newsletterTitle"), bind("newsletterTitle")), richText({ className: "newsletter-copy-subtitle rb-prose rb-max-w-none" }, when("newsletterSubtitle"), bind("newsletterSubtitle"))]), el("newsletter-form", withApiBindings({
18584
- source: "block",
18585
- listId: { $bind: { from: "listId" } },
18586
- preset: { $bind: { from: "preset" } },
18587
- includePhone: { $bind: { from: "includePhone" } },
18588
- buttonLabel: { $bind: { from: "newsletterButtonLabel" } },
18589
- successMessage: { $bind: { from: "newsletterSuccessMessage" } },
18590
- privacyNote: { $bind: { from: "newsletterPrivacyNote" } },
18591
- tags: { $bind: { from: "newsletterTags" } },
18899
+ source: { $bind: {
18900
+ from: "mailingListSource",
18901
+ fallback: "block"
18902
+ } },
18903
+ sourceRef: {
18904
+ tag: "signed_source_ref",
18905
+ token: { $bind: { from: "mailingListSourceToken" } }
18906
+ },
18907
+ targeting: { $bind: {
18908
+ from: "targeting",
18909
+ fallback: { mode: "default" }
18910
+ } },
18911
+ mailingList: { $bind: { from: "$root.mailingList" } },
18592
18912
  spamProtectionEnabled: { $bind: { from: "$root.spamProtectionEnabled" } }
18593
18913
  }), [])])])], { className: "contact-newsletter-container" }),
18594
18914
  baseClass: "",
@@ -18624,79 +18944,55 @@ const contactNewsletterBlockDefinition = {
18624
18944
  label: "Newsletter intro"
18625
18945
  },
18626
18946
  {
18627
- id: "listId",
18628
- type: "reference",
18629
- label: "Newsletter list",
18630
- description: "Select the list new subscribers should be added to.",
18947
+ id: "targeting",
18948
+ type: "group",
18949
+ label: "Mailing-list targeting",
18950
+ description: "Choose what kind of emails people signing up here will receive.",
18631
18951
  required: true,
18632
- referenceKind: "newsletterList",
18633
- allowManualEntry: false,
18634
- ui: { intent: "behavior" }
18635
- },
18636
- {
18637
- id: "preset",
18638
- type: "select",
18639
- label: "Newsletter fields",
18640
- defaultValue: "emailOnly",
18641
- ui: { intent: "display" },
18642
- options: [
18643
- {
18644
- value: "emailOnly",
18645
- label: "Email only"
18646
- },
18647
- {
18648
- value: "emailName",
18649
- label: "Email + Name"
18650
- },
18651
- {
18652
- value: "emailFirstLast",
18653
- label: "Email + First/Last Name"
18654
- },
18655
- {
18656
- value: "emailNameCompany",
18657
- label: "Email + Name + Company (B2B)"
18658
- }
18659
- ]
18660
- },
18661
- {
18662
- id: "includePhone",
18663
- type: "boolean",
18664
- label: "Include phone field",
18665
- defaultValue: false,
18666
- ui: { intent: "display" }
18667
- },
18668
- {
18669
- id: "newsletterButtonLabel",
18670
- type: "text",
18671
- label: "Newsletter button label",
18672
- defaultValue: "Subscribe",
18673
- ui: { intent: "display" }
18674
- },
18675
- {
18676
- id: "newsletterSuccessMessage",
18677
- type: "text",
18678
- label: "Newsletter success message",
18679
- defaultValue: "Thanks for subscribing!",
18680
- ui: { intent: "behavior" }
18952
+ defaultValue: { mode: "default" },
18953
+ ui: {
18954
+ intent: "behavior",
18955
+ widget: "mailingListTargeting"
18956
+ },
18957
+ schema: { fields: [{
18958
+ id: "mode",
18959
+ type: "select",
18960
+ label: "Mode",
18961
+ required: true,
18962
+ defaultValue: "default",
18963
+ options: [{
18964
+ value: "default",
18965
+ label: "Default"
18966
+ }, {
18967
+ value: "custom",
18968
+ label: "Custom"
18969
+ }],
18970
+ ui: { hidden: true }
18971
+ }] }
18681
18972
  },
18682
18973
  {
18683
- id: "newsletterPrivacyNote",
18974
+ id: "contactTitle",
18684
18975
  type: "text",
18685
- label: "Privacy note",
18686
- ui: { intent: "display" }
18976
+ label: "Contact title",
18977
+ defaultValue: "Get in touch"
18687
18978
  },
18688
18979
  {
18689
- id: "newsletterTags",
18980
+ id: "mailingListSource",
18690
18981
  type: "text",
18691
- label: "Newsletter tags",
18692
- description: "Optional tags to apply on subscribe, separated by comma or semicolon.",
18693
- ui: { intent: "behavior" }
18982
+ label: "Mailing-list source",
18983
+ ui: {
18984
+ hidden: true,
18985
+ intent: "behavior"
18986
+ }
18694
18987
  },
18695
18988
  {
18696
- id: "contactTitle",
18989
+ id: "mailingListSourceToken",
18697
18990
  type: "text",
18698
- label: "Contact title",
18699
- defaultValue: "Get in touch"
18991
+ label: "Mailing-list source token",
18992
+ ui: {
18993
+ hidden: true,
18994
+ intent: "behavior"
18995
+ }
18700
18996
  },
18701
18997
  {
18702
18998
  id: "contactIntro",
@@ -19206,13 +19502,9 @@ const footerStandardContactBindings = {
19206
19502
  };
19207
19503
  const footerMailingListBindings = {
19208
19504
  source: { $bind: { from: "module.engagement.runtime.source" } },
19209
- destinationRef: { $bind: { from: "module.engagement.runtime.destinationRef" } },
19210
- listId: { $bind: { from: "module.engagement.runtime.listId" } },
19211
- preset: { $bind: { from: "module.engagement.runtime.preset" } },
19212
- includePhone: { $bind: { from: "module.engagement.runtime.includePhone" } },
19213
- buttonLabel: { $bind: { from: "module.engagement.runtime.buttonLabel" } },
19214
- successMessage: { $bind: { from: "module.engagement.runtime.successMessage" } },
19215
- privacyNote: { $bind: { from: "module.engagement.runtime.privacyNote" } }
19505
+ sourceRef: { $bind: { from: "module.engagement.runtime.sourceRef" } },
19506
+ mailingList: { $bind: { from: "module.engagement.runtime.mailingList" } },
19507
+ targeting: { $bind: { from: "module.engagement.runtime.targeting" } }
19216
19508
  };
19217
19509
  const footerSpamProtectionBinding = { spamProtectionEnabled: { $bind: { from: "$root.spamProtectionEnabled" } } };
19218
19510
  const brandLogo = link({
@@ -20900,6 +21192,78 @@ const appointmentBookingBlockDefinition = {
20900
21192
  }
20901
21193
  }
20902
21194
  };
21195
+ const appointmentServicesBlockDefinition = {
21196
+ manifest: createBlockManifest({
21197
+ id: "block.appointment-services",
21198
+ version: "1.0.0",
21199
+ title: "Appointment Services",
21200
+ titleSource: "heading",
21201
+ description: "List public appointment services with booking links",
21202
+ skipSectionStyles: true,
21203
+ additionalFields: [
21204
+ {
21205
+ id: "heading",
21206
+ type: "text",
21207
+ label: "Heading",
21208
+ required: false,
21209
+ multiline: false,
21210
+ defaultValue: "Appointments",
21211
+ ui: { intent: "content" }
21212
+ },
21213
+ {
21214
+ id: "description",
21215
+ type: "richText",
21216
+ label: "Description",
21217
+ required: false,
21218
+ ui: { intent: "content" }
21219
+ },
21220
+ sectionStylesField({
21221
+ id: "_sectionStyles",
21222
+ label: "Section styles",
21223
+ renderInHeader: false
21224
+ })
21225
+ ],
21226
+ styleTokens: {
21227
+ background: "surface",
21228
+ typography: "body",
21229
+ spacing: "md"
21230
+ },
21231
+ behaviours: {
21232
+ supportsThemeSwitching: true,
21233
+ inlineEditing: true,
21234
+ animation: false,
21235
+ paletteHidden: false
21236
+ },
21237
+ category: "interactive",
21238
+ contentSource: { kind: "inline" },
21239
+ tags: [
21240
+ "booking",
21241
+ "appointment",
21242
+ "services",
21243
+ "scheduling"
21244
+ ],
21245
+ icon: "CalendarDays",
21246
+ layout: [styledSection({
21247
+ baseClass: "",
21248
+ spacing: "spacious",
21249
+ children: sectionContainer([
21250
+ text({ as: "h2" }, bind("content.heading"), when("content.heading")),
21251
+ richText({ className: "rb-prose rb-max-w-none" }, bind("content.description"), when("content.description")),
21252
+ el("appointment-services", {
21253
+ sectionHeading: { $bind: { from: "content.heading" } },
21254
+ services: { $bind: { from: "data.services" } },
21255
+ pathname: { $bind: { from: "$root.pathname" } }
21256
+ })
21257
+ ], { gap: "lg" })
21258
+ })]
21259
+ }),
21260
+ dataSchemas: { services: z.unknown().optional() },
21261
+ dataLoaders: { services: {
21262
+ endpoint: "getPublicBookingServices",
21263
+ params: { siteId: { $bind: { from: "$root.siteId" } } },
21264
+ mode: "server"
21265
+ } }
21266
+ };
20903
21267
  //#endregion
20904
21268
  //#region ../blocks/src/system/blocks/weekly-slot-availability.ts
20905
21269
  const weeklySlotAvailabilityManifest = createBlockManifest({
@@ -21338,6 +21702,28 @@ const bookingRequirementConsentFieldSchema = z.object({
21338
21702
  z.union([blockBookingConsentSchema, bookingRequirementConsentFieldSchema]);
21339
21703
  //#endregion
21340
21704
  //#region ../blocks/src/system/blocks/events/shared/schemas.ts
21705
+ const publicEventLoaderQuerySchemaShape = {
21706
+ limit: z.string().optional(),
21707
+ from: z.string().optional(),
21708
+ to: z.string().optional(),
21709
+ afterStartsAt: z.string().optional(),
21710
+ afterId: z.string().optional(),
21711
+ categoryIds: z.string().optional(),
21712
+ venueId: z.string().optional(),
21713
+ staffMemberId: z.string().optional(),
21714
+ eventSurface: z.string().optional(),
21715
+ eventPresets: z.string().optional(),
21716
+ scheduleScope: z.string().optional(),
21717
+ seriesId: z.string().optional(),
21718
+ seriesIds: z.string().optional(),
21719
+ runSeriesId: z.string().optional(),
21720
+ seriesSlug: z.string().optional(),
21721
+ includeOccurrenceId: z.string().optional(),
21722
+ readIntent: z.string().optional(),
21723
+ detailLevel: z.string().optional(),
21724
+ readProfile: z.string().optional()
21725
+ };
21726
+ z.object(publicEventLoaderQuerySchemaShape);
21341
21727
  const eventPresetSchema = z.enum([
21342
21728
  "event",
21343
21729
  "class",
@@ -22140,6 +22526,44 @@ function toWholeSeriesRegistrationEvents(events) {
22140
22526
  return groupPublicEventsByRun(events).map(toWholeSeriesRegistrationEvent).filter((event) => event !== null);
22141
22527
  }
22142
22528
  //#endregion
22529
+ //#region ../blocks/src/system/runtime/nodes/event-registration/eventSourceRecovery.ts
22530
+ const { limit: _rawLimit, eventSurface: _rawEventSurface, scheduleScope: _rawScheduleScope, detailLevel: _rawDetailLevel, ...stringEventQueryShape } = publicEventLoaderQuerySchemaShape;
22531
+ const eventRecoveryRequestSchema = z.object({
22532
+ ...stringEventQueryShape,
22533
+ limit: z.coerce.number().int().positive().optional(),
22534
+ eventSurface: z.enum(eventSurfaceScopeValues).optional(),
22535
+ scheduleScope: z.enum(eventScheduleScopeValues).optional(),
22536
+ detailLevel: z.enum(["full", "listing"]).optional(),
22537
+ stage: z.enum(["preview", "published"]).optional()
22538
+ });
22539
+ function resolveEventRegistrationEventSource(input) {
22540
+ if (input.wholeSeriesRunEvents != null) return {
22541
+ kind: "loaded",
22542
+ events: input.wholeSeriesRunEvents
22543
+ };
22544
+ if (input.events != null) return {
22545
+ kind: "loaded",
22546
+ events: input.events
22547
+ };
22548
+ return {
22549
+ kind: "unresolved",
22550
+ request: parseEventLoaderRecoveryRequest(input.failures?.wholeSeriesRunEvents ?? input.failures?.events)
22551
+ };
22552
+ }
22553
+ const eventLoaderFailureSchema = z.object({
22554
+ endpoint: z.literal("listPublicEvents"),
22555
+ params: eventRecoveryRequestSchema.extend({ siteId: z.string().optional() })
22556
+ });
22557
+ function parseEventLoaderRecoveryRequest(value) {
22558
+ const parsed = eventLoaderFailureSchema.safeParse(value);
22559
+ if (!parsed.success) return null;
22560
+ const { siteId: _siteId, stage, ...params } = parsed.data.params;
22561
+ return {
22562
+ ...params,
22563
+ stage: stage ?? "published"
22564
+ };
22565
+ }
22566
+ //#endregion
22143
22567
  //#region ../blocks/src/system/runtime/nodes/event-registration.interactive.ts
22144
22568
  const EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS = [
22145
22569
  "Date",
@@ -22157,8 +22581,6 @@ const eventRegistrationPublicEventSchema = z.preprocess(normalizeEventRegistrati
22157
22581
  const eventRegistrationHydrationSchemaShape = {
22158
22582
  occurrenceContext: occurrenceContextSchema.optional(),
22159
22583
  subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
22160
- events: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
22161
- wholeSeriesRunEvents: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
22162
22584
  maxTickets: z.string().optional(),
22163
22585
  showVenue: z.boolean().optional(),
22164
22586
  showCapacity: z.boolean().optional(),
@@ -22170,12 +22592,22 @@ const eventRegistrationHydrationSchemaShape = {
22170
22592
  sitePasses: publicPassProductCollectionSchema.nullable().optional(),
22171
22593
  siteMemberships: publicMembershipProductCollectionSchema.nullable().optional()
22172
22594
  };
22595
+ const eventRegistrationEventSourceSchema = z.discriminatedUnion("kind", [z.object({
22596
+ kind: z.literal("loaded"),
22597
+ events: z.array(eventRegistrationPublicEventSchema)
22598
+ }), z.object({
22599
+ kind: z.literal("unresolved"),
22600
+ request: eventRecoveryRequestSchema.nullable()
22601
+ })]);
22173
22602
  const eventRegistrationSourceSchema = z.object({
22174
22603
  siteId: z.string().optional(),
22175
22604
  apiBaseUrl: z.string().optional(),
22176
22605
  portalToken: z.string().nullable().optional(),
22177
22606
  previewToken: z.string().nullable().optional(),
22178
22607
  ...eventRegistrationHydrationSchemaShape,
22608
+ events: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
22609
+ wholeSeriesRunEvents: z.array(eventRegistrationPublicEventSchema).nullable().optional(),
22610
+ eventLoaderFailures: z.record(z.string(), z.unknown()).nullable().optional(),
22179
22611
  className: z.string().nullable().optional(),
22180
22612
  buttonText: z.string().nullable().optional(),
22181
22613
  maxTickets: z.string().nullable().optional(),
@@ -22196,7 +22628,10 @@ const eventRegistrationDisplaySchema = z.discriminatedUnion("state", [z.object({
22196
22628
  titleText: z.string(),
22197
22629
  bodyText: z.string()
22198
22630
  })]);
22199
- const eventRegistrationHydrationSchema = z.object(eventRegistrationHydrationSchemaShape);
22631
+ const eventRegistrationHydrationSchema = z.object({
22632
+ ...eventRegistrationHydrationSchemaShape,
22633
+ eventSource: eventRegistrationEventSourceSchema
22634
+ });
22200
22635
  const eventRegistrationRenderSchema = z.object({
22201
22636
  display: eventRegistrationDisplaySchema,
22202
22637
  hydration: eventRegistrationHydrationSchema
@@ -22208,8 +22643,8 @@ z.object({
22208
22643
  previewToken: z.string().nullable().optional(),
22209
22644
  stage: previewStageSchema.optional()
22210
22645
  });
22211
- function buildEventRegistrationDisplay(source) {
22212
- const selectedRun = resolveSelectedWholeSeriesRun(source);
22646
+ function buildEventRegistrationDisplayFromScopedEvents(source, scopedSourceEvents) {
22647
+ const selectedRun = resolveSelectedWholeSeriesRun(scopedSourceEvents);
22213
22648
  if (selectedRun && (!selectedRun.run.enrollmentOpen || toWholeSeriesRegistrationEvent(selectedRun) === null)) return {
22214
22649
  kind: "event-registration",
22215
22650
  state: "registration-closed",
@@ -22217,7 +22652,7 @@ function buildEventRegistrationDisplay(source) {
22217
22652
  titleText: "Registration closed",
22218
22653
  bodyText: "This run is no longer open for bookings."
22219
22654
  };
22220
- const stepLabels = buildEventRegistrationShellStepLabels(source);
22655
+ const stepLabels = buildEventRegistrationShellStepLabels(source, scopedSourceEvents);
22221
22656
  return {
22222
22657
  kind: "event-registration",
22223
22658
  state: "generic-shell",
@@ -22228,8 +22663,8 @@ function buildEventRegistrationDisplay(source) {
22228
22663
  summaryButtonText: source.buttonText?.trim() || "Register"
22229
22664
  };
22230
22665
  }
22231
- function buildEventRegistrationShellStepLabels(source) {
22232
- const selectedRun = resolveSelectedWholeSeriesRun(source);
22666
+ function buildEventRegistrationShellStepLabels(source, scopedSourceEvents) {
22667
+ const selectedRun = resolveSelectedWholeSeriesRun(scopedSourceEvents);
22233
22668
  if (selectedRun) {
22234
22669
  const selectedEvent = toWholeSeriesRegistrationEvent(selectedRun);
22235
22670
  if (!selectedEvent) return EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS;
@@ -22239,7 +22674,7 @@ function buildEventRegistrationShellStepLabels(source) {
22239
22674
  event: selectedEvent
22240
22675
  })).map((step) => shellLabelForRegistrationStep(step, [selectedEvent]));
22241
22676
  }
22242
- const scopedEvents = scopeEventRegistrationEvents(source);
22677
+ const scopedEvents = toScopedEventRegistrationEvents(scopedSourceEvents);
22243
22678
  if (scopedEvents.length === 0) return EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS;
22244
22679
  const preSelectedEvent = findPreSelectedEvent({
22245
22680
  scopedEvents,
@@ -22252,21 +22687,11 @@ function buildEventRegistrationShellStepLabels(source) {
22252
22687
  event: preSelectedEvent
22253
22688
  }) : false).map((step) => shellLabelForRegistrationStep(step, scopedEvents));
22254
22689
  }
22255
- function scopeEventRegistrationEvents(source) {
22256
- const scoped = scopeEventRegistrationSourceEvents(source);
22257
- return [...toRegistrationEvents(scoped), ...toWholeSeriesRegistrationEvents(scoped)];
22690
+ function toScopedEventRegistrationEvents(scopedSourceEvents) {
22691
+ return [...toRegistrationEvents(scopedSourceEvents), ...toWholeSeriesRegistrationEvents(scopedSourceEvents)];
22258
22692
  }
22259
- /**
22260
- * Every event this surface may register for, from both of its loads.
22261
- *
22262
- * The date page and the run read answer different questions and can name the
22263
- * same occurrence, so the two lists are joined and any occurrence that arrives
22264
- * twice is kept once, in the order the date page gave it.
22265
- */
22266
- function scopeEventRegistrationSourceEvents(source) {
22267
- const byOccurrenceId = /* @__PURE__ */ new Map();
22268
- for (const event of [...source.events ?? [], ...source.wholeSeriesRunEvents ?? []]) if (!byOccurrenceId.has(event.occurrenceId)) byOccurrenceId.set(event.occurrenceId, event);
22269
- return resolveEventRegistrationScopedEvents([...byOccurrenceId.values()], {
22693
+ function scopeEventRegistrationSourceEvents(source, eventSource) {
22694
+ return resolveEventRegistrationScopedEvents(eventSource.kind === "loaded" ? eventSource.events : [], {
22270
22695
  occurrenceContext: source.occurrenceContext,
22271
22696
  subject: source.subject
22272
22697
  });
@@ -22275,8 +22700,8 @@ function scopeEventRegistrationSourceEvents(source) {
22275
22700
  * The one run this surface is registering for, when the scoped events describe
22276
22701
  * exactly one. More than one run means the visitor still has to choose.
22277
22702
  */
22278
- function resolveSelectedWholeSeriesRun(source) {
22279
- const runs = groupPublicEventsByRun(scopeEventRegistrationSourceEvents(source));
22703
+ function resolveSelectedWholeSeriesRun(scopedSourceEvents) {
22704
+ const runs = groupPublicEventsByRun(scopedSourceEvents);
22280
22705
  return runs.length === 1 ? runs[0] : null;
22281
22706
  }
22282
22707
  function shellLabelForRegistrationStep(step, events) {
@@ -22310,13 +22735,21 @@ const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
22310
22735
  render: createZodCodec(eventRegistrationRenderSchema)
22311
22736
  },
22312
22737
  buildRender: (source) => {
22313
- const events = source.events == null ? null : scopeEventRegistrationSourceEvents(source);
22738
+ const eventSource = resolveEventRegistrationEventSource({
22739
+ events: source.events,
22740
+ wholeSeriesRunEvents: source.wholeSeriesRunEvents,
22741
+ failures: source.eventLoaderFailures
22742
+ });
22743
+ const scopedSourceEvents = scopeEventRegistrationSourceEvents(source, eventSource);
22314
22744
  return {
22315
- display: buildEventRegistrationDisplay(source),
22745
+ display: buildEventRegistrationDisplayFromScopedEvents(source, scopedSourceEvents),
22316
22746
  hydration: {
22317
22747
  occurrenceContext: source.occurrenceContext ?? null,
22318
22748
  subject: source.subject ?? null,
22319
- events,
22749
+ eventSource: eventSource.kind === "loaded" ? {
22750
+ ...eventSource,
22751
+ events: [...scopedSourceEvents]
22752
+ } : eventSource,
22320
22753
  maxTickets: source.maxTickets ?? void 0,
22321
22754
  showVenue: source.showVenue,
22322
22755
  showCapacity: source.showCapacity,
@@ -22492,6 +22925,7 @@ const eventRegistrationBlockDefinition = {
22492
22925
  } },
22493
22926
  events: { $bind: { from: "data.events" } },
22494
22927
  wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
22928
+ loaderFailures: { $bind: { from: "$root.loaderFailures" } },
22495
22929
  sitePasses: { $bind: { from: "data.sitePasses" } },
22496
22930
  siteMemberships: { $bind: { from: "data.siteMemberships" } },
22497
22931
  stage: { $bind: {
@@ -22513,6 +22947,11 @@ const eventRegistrationBlockDefinition = {
22513
22947
  dataLoaders: {
22514
22948
  events: {
22515
22949
  endpoint: "listPublicEvents",
22950
+ when: { $bind: {
22951
+ from: "$root.subject.isWholeSeriesBooking",
22952
+ fallback: true,
22953
+ transforms: [{ id: "boolean.not" }]
22954
+ } },
22516
22955
  params: {
22517
22956
  siteId: { $bind: { from: "$root.siteId" } },
22518
22957
  limit: "50",
@@ -22534,13 +22973,9 @@ const eventRegistrationBlockDefinition = {
22534
22973
  /**
22535
22974
  * The runs this page can register for, finished ones included.
22536
22975
  *
22537
- * The `events` page above is date-bounded, so a run whose first session has
22538
- * passed contributes no rows to it and the surface would have nothing to
22539
- * render as closed. This asks for runs instead, and only on a page whose
22540
- * subject books whole runs. It is scoped exactly like the date page — same
22541
- * series, same run subroute — because scope and grain are separate
22542
- * questions. The two lists are joined by occurrence, so a run that appears
22543
- * in both is still one run.
22976
+ * A run read is the sole Event source on a whole-series surface. It is
22977
+ * status-bounded rather than date-bounded, so completed runs can still
22978
+ * render their closed state and every run carries its complete schedule.
22544
22979
  */
22545
22980
  wholeSeriesRunEvents: {
22546
22981
  endpoint: "listPublicEvents",
@@ -25045,68 +25480,6 @@ const recurringScheduleBlockDefinition = {
25045
25480
  } }
25046
25481
  };
25047
25482
  //#endregion
25048
- //#region ../blocks/src/system/types/link.ts
25049
- const nullableString = z.union([z.string().min(1), z.null()]);
25050
- const RESOLVED_INTERNAL_LINK_ENTITY_TYPES = [
25051
- "page",
25052
- "content",
25053
- "pageSurface"
25054
- ];
25055
- const resolvedInternalLinkKeys = [
25056
- "entityId",
25057
- "entityType",
25058
- "href",
25059
- "title",
25060
- "typeLabel"
25061
- ];
25062
- const internalRouteOnlyLinkSchema = z.object({
25063
- kind: z.literal("internal"),
25064
- routeId: z.string().min(1)
25065
- }).passthrough().superRefine((value, ctx) => {
25066
- if (!resolvedInternalLinkKeys.some((key) => value[key] != null)) return;
25067
- ctx.addIssue({
25068
- code: "custom",
25069
- message: "Internal links with resolved metadata must include entityId, entityType, href, title, and typeLabel"
25070
- });
25071
- });
25072
- const internalResolvedLinkSchema = z.object({
25073
- kind: z.literal("internal"),
25074
- routeId: z.string().min(1),
25075
- entityId: z.string().min(1),
25076
- entityType: z.enum(RESOLVED_INTERNAL_LINK_ENTITY_TYPES),
25077
- href: z.string().min(1),
25078
- title: z.string().min(1),
25079
- typeLabel: z.string().min(1),
25080
- contentTypeKey: nullableString.optional(),
25081
- contentTypeName: nullableString.optional(),
25082
- updatedAt: nullableString.optional()
25083
- }).passthrough();
25084
- const internalLinkSchema = z.union([internalResolvedLinkSchema, internalRouteOnlyLinkSchema]);
25085
- const externalLinkSchema = z.object({
25086
- kind: z.literal("external"),
25087
- href: z.string().min(1)
25088
- }).passthrough();
25089
- const customLinkSchema = z.object({
25090
- kind: z.literal("url"),
25091
- href: z.string().min(1)
25092
- }).passthrough();
25093
- const pageLinkSchema = z.object({
25094
- kind: z.literal("page"),
25095
- identifier: z.string().min(1)
25096
- }).passthrough();
25097
- const entryLinkSchema = z.object({
25098
- kind: z.literal("entry"),
25099
- contentType: z.string().min(1),
25100
- identifier: z.string().min(1)
25101
- }).passthrough();
25102
- z.union([
25103
- internalLinkSchema,
25104
- externalLinkSchema,
25105
- customLinkSchema,
25106
- pageLinkSchema,
25107
- entryLinkSchema
25108
- ]);
25109
- //#endregion
25110
25483
  //#region ../blocks/src/system/blocks/offerings-preview/model.ts
25111
25484
  const OFFERINGS_PREVIEW_DEFAULT_BUTTON_TEXT = "Book";
25112
25485
  const OFFERINGS_PREVIEW_DEFAULT_EMPTY_MESSAGE = "Nothing scheduled just yet.";
@@ -25191,20 +25564,7 @@ function isRecord$2(value) {
25191
25564
  return typeof value === "object" && value !== null && !Array.isArray(value);
25192
25565
  }
25193
25566
  //#endregion
25194
- //#region ../blocks/src/system/blocks/offerings-preview/index.ts
25195
- /**
25196
- * The whole-series presets, as the CSV `listPublicEvents` expects. Both
25197
- * whole-series presets share one loader: the block renders them as a single
25198
- * run group.
25199
- */
25200
- const WHOLE_SERIES_EVENT_PRESETS_PARAM = WHOLE_SERIES_EVENT_PRESET_VALUES.join(",");
25201
- const publicRouteCandidatesSchema = z.object({ routes: z.array(z.object({
25202
- entityId: z.string(),
25203
- path: z.string(),
25204
- title: z.string(),
25205
- kind: z.enum(RESOLVED_INTERNAL_LINK_ENTITY_TYPES),
25206
- contentTypeKey: z.string().nullable().optional()
25207
- })) });
25567
+ //#region ../blocks/src/system/blocks/offerings-preview/fields.ts
25208
25568
  const groupOverrideFields = [
25209
25569
  {
25210
25570
  id: "sourceKey",
@@ -25410,7 +25770,127 @@ const offeringsPreviewFields = [
25410
25770
  renderInHeader: false
25411
25771
  })
25412
25772
  ];
25773
+ function labelForOfferingPreviewSourceKey(sourceKey) {
25774
+ const eventDefinition = OFFERINGS_PREVIEW_EVENT_PRESET_DEFINITIONS.find((definition) => definition.sourceKey === sourceKey);
25775
+ if (eventDefinition) return eventDefinition.label;
25776
+ return "Courses";
25777
+ }
25778
+ //#endregion
25779
+ //#region ../blocks/src/system/types/link.ts
25780
+ const nullableString = z.union([z.string().min(1), z.null()]);
25781
+ const RESOLVED_INTERNAL_LINK_ENTITY_TYPES = [
25782
+ "page",
25783
+ "content",
25784
+ "pageSurface"
25785
+ ];
25786
+ const resolvedInternalLinkKeys = [
25787
+ "entityId",
25788
+ "entityType",
25789
+ "href",
25790
+ "title",
25791
+ "typeLabel"
25792
+ ];
25793
+ const internalRouteOnlyLinkSchema = z.object({
25794
+ kind: z.literal("internal"),
25795
+ routeId: z.string().min(1)
25796
+ }).passthrough().superRefine((value, ctx) => {
25797
+ if (!resolvedInternalLinkKeys.some((key) => value[key] != null)) return;
25798
+ ctx.addIssue({
25799
+ code: "custom",
25800
+ message: "Internal links with resolved metadata must include entityId, entityType, href, title, and typeLabel"
25801
+ });
25802
+ });
25803
+ const internalResolvedLinkSchema = z.object({
25804
+ kind: z.literal("internal"),
25805
+ routeId: z.string().min(1),
25806
+ entityId: z.string().min(1),
25807
+ entityType: z.enum(RESOLVED_INTERNAL_LINK_ENTITY_TYPES),
25808
+ href: z.string().min(1),
25809
+ title: z.string().min(1),
25810
+ typeLabel: z.string().min(1),
25811
+ contentTypeKey: nullableString.optional(),
25812
+ contentTypeName: nullableString.optional(),
25813
+ updatedAt: nullableString.optional()
25814
+ }).passthrough();
25815
+ const internalLinkSchema = z.union([internalResolvedLinkSchema, internalRouteOnlyLinkSchema]);
25816
+ const externalLinkSchema = z.object({
25817
+ kind: z.literal("external"),
25818
+ href: z.string().min(1)
25819
+ }).passthrough();
25820
+ const customLinkSchema = z.object({
25821
+ kind: z.literal("url"),
25822
+ href: z.string().min(1)
25823
+ }).passthrough();
25824
+ const pageLinkSchema = z.object({
25825
+ kind: z.literal("page"),
25826
+ identifier: z.string().min(1)
25827
+ }).passthrough();
25828
+ const entryLinkSchema = z.object({
25829
+ kind: z.literal("entry"),
25830
+ contentType: z.string().min(1),
25831
+ identifier: z.string().min(1)
25832
+ }).passthrough();
25833
+ z.union([
25834
+ internalLinkSchema,
25835
+ externalLinkSchema,
25836
+ customLinkSchema,
25837
+ pageLinkSchema,
25838
+ entryLinkSchema
25839
+ ]);
25840
+ //#endregion
25841
+ //#region ../blocks/src/system/blocks/offerings-preview/index.ts
25842
+ /**
25843
+ * The whole-series presets, as the CSV `listPublicEvents` expects. Both
25844
+ * whole-series presets share one loader: the block renders them as a single
25845
+ * run group.
25846
+ */
25847
+ const WHOLE_SERIES_EVENT_PRESETS_PARAM = WHOLE_SERIES_EVENT_PRESET_VALUES.join(",");
25848
+ const publicRouteCandidatesSchema = z.object({ routes: z.array(z.object({
25849
+ entityId: z.string(),
25850
+ path: z.string(),
25851
+ title: z.string(),
25852
+ kind: z.enum(RESOLVED_INTERNAL_LINK_ENTITY_TYPES),
25853
+ contentTypeKey: z.string().nullable().optional()
25854
+ })) });
25413
25855
  const offeringsPreviewEventDataBindings = Object.fromEntries(OFFERINGS_PREVIEW_EVENT_PRESET_DEFINITIONS.map((definition) => [definition.dataKey, { $bind: { from: `data.${definition.dataKey}` } }]));
25856
+ const DEFAULT_OFFERINGS_PREVIEW_DISPLAY_MODE = "preview";
25857
+ const displayModeBinding = {
25858
+ from: "content.displayMode",
25859
+ fallback: DEFAULT_OFFERINGS_PREVIEW_DISPLAY_MODE
25860
+ };
25861
+ const catalogueMode = { $bind: {
25862
+ ...displayModeBinding,
25863
+ transforms: [{
25864
+ id: "value.equals",
25865
+ options: { value: "catalogue" }
25866
+ }]
25867
+ } };
25868
+ const previewMode = { $bind: {
25869
+ ...displayModeBinding,
25870
+ transforms: [{
25871
+ id: "value.equals",
25872
+ options: { value: "preview" }
25873
+ }]
25874
+ } };
25875
+ function offeringsPreviewHeaderNodes() {
25876
+ return [text({
25877
+ as: "h2",
25878
+ className: { $bind: {
25879
+ from: "content.displayMode",
25880
+ fallback: "rb-text-center",
25881
+ transforms: [{
25882
+ id: "value.equals",
25883
+ options: { value: "catalogue" }
25884
+ }, {
25885
+ id: "ui.conditionalClass",
25886
+ options: {
25887
+ whenTrue: "rb-text-left",
25888
+ whenFalse: "rb-text-center"
25889
+ }
25890
+ }]
25891
+ } }
25892
+ }, bind("content.heading"), when("content.heading")), richText({ className: "rb-prose rb-max-w-none" }, bind("content.description"), when("content.description"))];
25893
+ }
25414
25894
  const offeringsPreviewManifest = createBlockManifest({
25415
25895
  id: "block.offerings-preview",
25416
25896
  version: "1.0.0",
@@ -25441,48 +25921,45 @@ const offeringsPreviewManifest = createBlockManifest({
25441
25921
  ],
25442
25922
  icon: "PanelsTopLeft",
25443
25923
  layout: [styledSection({
25444
- children: sectionContainer([
25445
- text({
25446
- as: "h2",
25447
- className: "rb-text-center"
25448
- }, bind("content.heading"), when("content.heading")),
25449
- richText({ className: "rb-prose rb-max-w-none" }, bind("content.description"), when("content.description")),
25450
- el("offerings-preview", {
25451
- bookingOfferingPresets: { $bind: {
25452
- from: "$root.bookingOfferingPresets",
25453
- fallback: []
25454
- } },
25455
- groupOverrides: { $bind: {
25456
- from: "content.groupOverrides",
25457
- fallback: []
25458
- } },
25459
- groupOrder: { $bind: { from: "content.groupOrder" } },
25460
- cardStyles: { $bind: { from: "content._cardStyles" } },
25461
- itemLimit: { $bind: {
25462
- from: "content.itemLimit",
25463
- fallback: "3"
25464
- } },
25465
- buttonVariant: { $bind: {
25466
- from: "content.buttonVariant",
25467
- fallback: "primary"
25468
- } },
25469
- buttonText: { $bind: {
25470
- from: "content.buttonText",
25471
- fallback: OFFERINGS_PREVIEW_DEFAULT_BUTTON_TEXT
25472
- } },
25473
- emptyMessage: { $bind: {
25474
- from: "content.emptyMessage",
25475
- fallback: OFFERINGS_PREVIEW_DEFAULT_EMPTY_MESSAGE
25476
- } },
25477
- previewStage: { $bind: {
25478
- from: "$root.previewStage",
25479
- fallback: "published"
25480
- } },
25481
- routeCandidates: { $bind: { from: "data.routeCandidates" } },
25482
- wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
25483
- ...offeringsPreviewEventDataBindings
25484
- })
25485
- ], { gap: "lg" }),
25924
+ children: sectionContainer([el("offerings-preview", {
25925
+ displayMode: { $bind: displayModeBinding },
25926
+ pathname: { $bind: { from: "$root.pathname" } },
25927
+ catalogueEvents: { $bind: { from: "data.catalogueEvents" } },
25928
+ quickDateEvents: { $bind: { from: "data.quickDateEvents" } },
25929
+ bookingOfferingPresets: { $bind: {
25930
+ from: "$root.bookingOfferingPresets",
25931
+ fallback: []
25932
+ } },
25933
+ groupOverrides: { $bind: {
25934
+ from: "content.groupOverrides",
25935
+ fallback: []
25936
+ } },
25937
+ groupOrder: { $bind: { from: "content.groupOrder" } },
25938
+ cardStyles: { $bind: { from: "content._cardStyles" } },
25939
+ itemLimit: { $bind: {
25940
+ from: "content.itemLimit",
25941
+ fallback: "3"
25942
+ } },
25943
+ buttonVariant: { $bind: {
25944
+ from: "content.buttonVariant",
25945
+ fallback: "primary"
25946
+ } },
25947
+ buttonText: { $bind: {
25948
+ from: "content.buttonText",
25949
+ fallback: OFFERINGS_PREVIEW_DEFAULT_BUTTON_TEXT
25950
+ } },
25951
+ emptyMessage: { $bind: {
25952
+ from: "content.emptyMessage",
25953
+ fallback: OFFERINGS_PREVIEW_DEFAULT_EMPTY_MESSAGE
25954
+ } },
25955
+ previewStage: { $bind: {
25956
+ from: "$root.previewStage",
25957
+ fallback: "published"
25958
+ } },
25959
+ routeCandidates: { $bind: { from: "data.routeCandidates" } },
25960
+ wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
25961
+ ...offeringsPreviewEventDataBindings
25962
+ }, offeringsPreviewHeaderNodes())], { gap: "lg" }),
25486
25963
  baseClass: "",
25487
25964
  spacing: "comfortable"
25488
25965
  })]
@@ -25496,16 +25973,48 @@ const offeringsPreviewBlockDefinition = {
25496
25973
  dataSchemas: {
25497
25974
  ...offeringsPreviewEventDataSchemas,
25498
25975
  routeCandidates: publicRouteCandidatesSchema.optional(),
25499
- wholeSeriesRunEvents: optionalPublicEventsArraySchema
25976
+ wholeSeriesRunEvents: optionalPublicEventsArraySchema,
25977
+ catalogueEvents: optionalPublicEventsArraySchema,
25978
+ quickDateEvents: optionalPublicEventsArraySchema
25500
25979
  },
25501
25980
  dataLoaders: {
25502
25981
  ...offeringsPreviewEventDataLoaders,
25503
25982
  routeCandidates: {
25504
25983
  endpoint: "listPublicRouteCandidates",
25984
+ when: previewMode,
25505
25985
  params: {},
25506
25986
  mode: "server"
25507
25987
  },
25508
- wholeSeriesRunEvents: wholeSeriesRunLoader()
25988
+ wholeSeriesRunEvents: wholeSeriesRunLoader(),
25989
+ catalogueEvents: {
25990
+ endpoint: "listPublicEvents",
25991
+ when: catalogueMode,
25992
+ params: {
25993
+ stage: { $bind: {
25994
+ from: "$root.previewStage",
25995
+ fallback: "published"
25996
+ } },
25997
+ detailLevel: "listing",
25998
+ readProfile: "listing-card",
25999
+ readIntent: "catalogue"
26000
+ },
26001
+ mode: "server"
26002
+ },
26003
+ quickDateEvents: {
26004
+ endpoint: "listPublicEvents",
26005
+ when: catalogueMode,
26006
+ params: {
26007
+ stage: { $bind: {
26008
+ from: "$root.previewStage",
26009
+ fallback: "published"
26010
+ } },
26011
+ detailLevel: "listing",
26012
+ readProfile: "listing-card",
26013
+ readIntent: "occurrences",
26014
+ limit: 40
26015
+ },
26016
+ mode: "server"
26017
+ }
25509
26018
  }
25510
26019
  };
25511
26020
  /**
@@ -25522,6 +26031,7 @@ function wholeSeriesRunLoader() {
25522
26031
  function eventPresetLoader(eventPresets, extraParams = {}) {
25523
26032
  return {
25524
26033
  endpoint: "listPublicEvents",
26034
+ when: previewMode,
25525
26035
  params: {
25526
26036
  siteId: { $bind: { from: "$root.siteId" } },
25527
26037
  limit: { $bind: {
@@ -25540,15 +26050,10 @@ function eventPresetLoader(eventPresets, extraParams = {}) {
25540
26050
  mode: "server"
25541
26051
  };
25542
26052
  }
25543
- function labelForOfferingPreviewSourceKey(sourceKey) {
25544
- const eventDefinition = OFFERINGS_PREVIEW_EVENT_PRESET_DEFINITIONS.find((definition) => definition.sourceKey === sourceKey);
25545
- if (eventDefinition) return eventDefinition.label;
25546
- return "Courses";
25547
- }
25548
26053
  function normalizeOfferingsPreviewBlockContent(value) {
25549
26054
  const record = normalizeOfferingsPreviewContentForWrite(value);
25550
- if (!record) return {};
25551
- const normalized = {};
26055
+ if (!record) return { displayMode: DEFAULT_OFFERINGS_PREVIEW_DISPLAY_MODE };
26056
+ const normalized = { displayMode: normalizeOfferingsPreviewDisplayMode(record.displayMode) };
25552
26057
  if (typeof record.heading === "string" || record.heading === null) normalized.heading = record.heading;
25553
26058
  if ("description" in record) normalized.description = record.description;
25554
26059
  if (isOfferingsPreviewItemLimit(record.itemLimit)) normalized.itemLimit = record.itemLimit;
@@ -25565,6 +26070,9 @@ function normalizeOfferingsPreviewBlockContent(value) {
25565
26070
  if (sectionStyles !== void 0) normalized._sectionStyles = sectionStyles;
25566
26071
  return normalized;
25567
26072
  }
26073
+ function normalizeOfferingsPreviewDisplayMode(value) {
26074
+ return value === "catalogue" ? "catalogue" : DEFAULT_OFFERINGS_PREVIEW_DISPLAY_MODE;
26075
+ }
25568
26076
  function isOfferingsPreviewItemLimit(value) {
25569
26077
  return value === "1" || value === "2" || value === "3" || value === "4" || value === "5" || value === "6" || value === null;
25570
26078
  }
@@ -28779,63 +29287,13 @@ const giftingBlockDefinition = {
28779
29287
  } }
28780
29288
  };
28781
29289
  //#endregion
28782
- //#region ../blocks/src/system/blocks/newsletter-signup-destination.ts
28783
- function parseNewsletterSignupBlockId(value) {
28784
- const trimmed = parseTrimmedString(value);
28785
- return trimmed && BLOCK_ID_PATTERN.test(trimmed) ? trimmed : null;
28786
- }
28787
- function parseSignedNewsletterDestinationRef(value) {
28788
- const trimmed = parseTrimmedString(value);
28789
- return trimmed && SIGNED_DESTINATION_REF_PATTERN.test(trimmed) ? trimmed : null;
28790
- }
28791
- function buildNewsletterSignupBlockRef(blockId) {
28792
- const parsed = parseNewsletterSignupBlockId(blockId);
28793
- return parsed ? {
28794
- tag: "block_ref",
28795
- blockId: parsed
28796
- } : null;
28797
- }
28798
- function normalizeNewsletterSignupEditorValuesForDestination(values) {
28799
- const destinationProvider = parseNewsletterSignupDestinationProvider(values.destinationProvider) ?? "riverbank";
28800
- if (destinationProvider === "mailchimp") return {
28801
- destinationProvider,
28802
- mailchimpAudienceId: values.mailchimpAudienceId,
28803
- mailchimpTags: values.mailchimpTags
28804
- };
28805
- return {
28806
- destinationProvider,
28807
- listId: values.listId,
28808
- tags: values.tags
28809
- };
28810
- }
28811
- function deriveNewsletterSignupRuntimeSource(values) {
28812
- const normalized = normalizeNewsletterSignupEditorValuesForDestination(values);
28813
- if (normalized.destinationProvider === "mailchimp") return {
28814
- destinationProvider: "mailchimp",
28815
- listId: null,
28816
- tags: null
28817
- };
28818
- return {
28819
- destinationProvider: "riverbank",
28820
- listId: parseTrimmedString(normalized.listId),
28821
- tags: parseTrimmedString(normalized.tags)
28822
- };
28823
- }
28824
- const BLOCK_ID_PATTERN = /^[A-Za-z0-9._:-]{1,200}$/;
28825
- const SIGNED_DESTINATION_REF_PATTERN = /^[A-Za-z0-9._~-]{16,1000}$/;
28826
- function parseTrimmedString(value) {
28827
- if (typeof value !== "string") return null;
28828
- const trimmed = value.trim();
28829
- return trimmed.length > 0 ? trimmed : null;
28830
- }
28831
- //#endregion
28832
29290
  //#region ../blocks/src/system/runtime/nodes/newsletter-form.types.ts
28833
29291
  /**
28834
29292
  * Get form fields based on preset configuration.
28835
29293
  */
28836
- function getPresetFields(preset, options) {
28837
- const includePhone = Boolean(options?.includePhone);
28838
- switch (preset) {
29294
+ function getGlobalFormFields(form) {
29295
+ const includePhone = form.includeOptionalPhone;
29296
+ switch (form.fields.preset) {
28839
29297
  case "emailOnly": return withOptionalPhone([{
28840
29298
  id: "email",
28841
29299
  type: "email",
@@ -28853,7 +29311,7 @@ function getPresetFields(preset, options) {
28853
29311
  id: "name",
28854
29312
  type: "text",
28855
29313
  label: "Name",
28856
- required: false,
29314
+ required: form.fields.name === "required",
28857
29315
  placeholder: "Your name"
28858
29316
  }], includePhone);
28859
29317
  case "emailFirstLast": return withOptionalPhone([
@@ -28868,14 +29326,14 @@ function getPresetFields(preset, options) {
28868
29326
  id: "firstName",
28869
29327
  type: "text",
28870
29328
  label: "First Name",
28871
- required: false,
29329
+ required: form.fields.firstName === "required",
28872
29330
  placeholder: "First name"
28873
29331
  },
28874
29332
  {
28875
29333
  id: "lastName",
28876
29334
  type: "text",
28877
29335
  label: "Last Name",
28878
- required: false,
29336
+ required: form.fields.lastName === "required",
28879
29337
  placeholder: "Last name"
28880
29338
  }
28881
29339
  ], includePhone);
@@ -28891,14 +29349,14 @@ function getPresetFields(preset, options) {
28891
29349
  id: "name",
28892
29350
  type: "text",
28893
29351
  label: "Name",
28894
- required: false,
29352
+ required: form.fields.name === "required",
28895
29353
  placeholder: "Your name"
28896
29354
  },
28897
29355
  {
28898
29356
  id: "company",
28899
29357
  type: "text",
28900
29358
  label: "Company",
28901
- required: false,
29359
+ required: form.fields.company === "required",
28902
29360
  placeholder: "Company name"
28903
29361
  }
28904
29362
  ], includePhone);
@@ -28917,14 +29375,29 @@ function withOptionalPhone(fields, includePhone) {
28917
29375
  }
28918
29376
  //#endregion
28919
29377
  //#region ../blocks/src/system/runtime/nodes/newsletter-form.interactive.ts
28920
- const newsletterPresetSchema = z.enum([
28921
- "emailOnly",
28922
- "emailName",
28923
- "emailFirstLast",
28924
- "emailNameCompany"
28925
- ]);
28926
- const newsletterDestinationProviderSchema = z.enum(["riverbank", "mailchimp"]);
28927
29378
  const newsletterButtonVariantSchema = blockButtonRoleSchema;
29379
+ const mailingListContextSchema = z.unknown().transform((value, ctx) => {
29380
+ const parsed = parseMailingListRuntimeContext(value);
29381
+ if (!parsed.ok) {
29382
+ ctx.addIssue({
29383
+ code: z.ZodIssueCode.custom,
29384
+ message: "Invalid mailing-list runtime context"
29385
+ });
29386
+ return z.NEVER;
29387
+ }
29388
+ return parsed.value;
29389
+ });
29390
+ const mailingListTargetingSchema = z.unknown().transform((value, ctx) => {
29391
+ const parsed = parseMailingListPlacementTargeting(value);
29392
+ if (!parsed.ok) {
29393
+ ctx.addIssue({
29394
+ code: z.ZodIssueCode.custom,
29395
+ message: "Invalid mailing-list targeting"
29396
+ });
29397
+ return z.NEVER;
29398
+ }
29399
+ return parsed.value;
29400
+ });
28928
29401
  const newsletterFieldSchema = z.object({
28929
29402
  id: z.string(),
28930
29403
  type: z.enum(["email", "text"]),
@@ -28932,18 +29405,23 @@ const newsletterFieldSchema = z.object({
28932
29405
  required: z.boolean(),
28933
29406
  placeholder: z.string().optional()
28934
29407
  });
28935
- const newsletterSignupBlockIdSchema = z.string().trim().min(1).transform(parseRequiredNewsletterSignupBlockId);
28936
- const signedNewsletterDestinationRefSchema = z.string().trim().min(1).transform(parseRequiredSignedNewsletterDestinationRef);
29408
+ const mailingListSignupBlockIdSchema = z.string().trim().min(1).transform(parseRequiredMailingListSignupBlockId);
29409
+ const mailingListContentVersionIdSchema = z.string().transform((value, ctx) => {
29410
+ const parsed = parseMailingListContentVersionId(value);
29411
+ if (parsed) return parsed;
29412
+ ctx.addIssue({
29413
+ code: z.ZodIssueCode.custom,
29414
+ message: "Invalid mailing-list content version ID"
29415
+ });
29416
+ return z.NEVER;
29417
+ });
29418
+ const signedMailingListSourceTokenSchema = z.string().trim().min(1).transform(parseRequiredMailingListSignedSourceToken);
28937
29419
  const newsletterSourceCommonSchema = z.object({
28938
29420
  siteId: z.string().optional(),
28939
29421
  apiBaseUrl: z.string().optional(),
28940
- preset: newsletterPresetSchema.optional(),
28941
- includePhone: z.boolean().optional(),
28942
- buttonLabel: z.string().nullable().optional(),
29422
+ mailingList: mailingListContextSchema.optional(),
29423
+ targeting: mailingListTargetingSchema.optional(),
28943
29424
  buttonVariant: newsletterButtonVariantSchema.nullable().optional(),
28944
- successMessage: z.string().nullable().optional(),
28945
- privacyNote: z.string().nullable().optional(),
28946
- tags: z.string().nullable().optional(),
28947
29425
  spamProtectionEnabled: z.boolean().optional(),
28948
29426
  className: z.string().nullable().optional()
28949
29427
  });
@@ -28951,54 +29429,61 @@ const newsletterSourceSchema = z.discriminatedUnion("source", [
28951
29429
  newsletterSourceCommonSchema.extend({
28952
29430
  source: z.literal("block"),
28953
29431
  blockId: z.string().nullable().optional(),
28954
- listId: z.string().nullable().optional(),
28955
- destinationProvider: newsletterDestinationProviderSchema.nullable().optional()
29432
+ contentVersionId: z.string().nullable().optional()
28956
29433
  }),
28957
29434
  newsletterSourceCommonSchema.extend({
28958
29435
  source: z.literal("signed-footer"),
28959
- destinationRef: z.object({
28960
- tag: z.literal("signed_destination_ref"),
28961
- token: signedNewsletterDestinationRefSchema
29436
+ sourceRef: z.object({
29437
+ tag: z.literal("signed_source_ref"),
29438
+ token: signedMailingListSourceTokenSchema
28962
29439
  })
28963
29440
  }),
28964
- newsletterSourceCommonSchema.extend({
28965
- source: z.literal("legacy-direct-list"),
28966
- listId: z.string().nullable()
28967
- })
29441
+ newsletterSourceCommonSchema.extend({ source: z.literal("preview") })
28968
29442
  ]);
28969
29443
  const newsletterDisplaySchema = z.object({
28970
29444
  kind: z.literal("newsletter-form"),
29445
+ availability: z.enum(["ready", "unavailable"]),
28971
29446
  className: z.string().nullable(),
28972
29447
  buttonLabel: z.string(),
29448
+ successMessage: z.string(),
28973
29449
  buttonVariant: newsletterButtonVariantSchema,
28974
- successMessage: z.string().nullable(),
28975
29450
  privacyNote: z.string().nullable(),
28976
- fields: z.array(newsletterFieldSchema)
29451
+ fields: z.array(newsletterFieldSchema),
29452
+ choices: z.array(z.object({
29453
+ id: z.string(),
29454
+ label: z.string()
29455
+ }))
28977
29456
  });
28978
29457
  const newsletterHydrationSchema = z.object({
28979
29458
  target: z.discriminatedUnion("tag", [
28980
29459
  z.object({
28981
29460
  tag: z.literal("block-source"),
28982
- destinationRef: z.object({
29461
+ sourceRef: z.object({
28983
29462
  tag: z.literal("block_ref"),
28984
- blockId: newsletterSignupBlockIdSchema
29463
+ blockId: mailingListSignupBlockIdSchema,
29464
+ contentVersionId: mailingListContentVersionIdSchema
28985
29465
  }).nullable()
28986
29466
  }),
28987
29467
  z.object({
28988
29468
  tag: z.literal("signed-footer-source"),
28989
- destinationRef: z.object({
28990
- tag: z.literal("signed_destination_ref"),
28991
- token: signedNewsletterDestinationRefSchema
29469
+ sourceRef: z.object({
29470
+ tag: z.literal("signed_source_ref"),
29471
+ token: signedMailingListSourceTokenSchema
28992
29472
  })
28993
29473
  }),
28994
- z.object({
28995
- tag: z.literal("legacy-direct-list"),
28996
- listId: z.string().nullable()
28997
- })
29474
+ z.object({ tag: z.literal("preview") })
29475
+ ]),
29476
+ setupRevision: z.number().int().positive().nullable(),
29477
+ choiceProvider: z.enum([
29478
+ "native",
29479
+ "brevo",
29480
+ "mailchimp"
29481
+ ]).nullable(),
29482
+ choicePresentation: z.enum([
29483
+ "hidden",
29484
+ "automatic",
29485
+ "visitor_choice"
28998
29486
  ]),
28999
- preset: newsletterPresetSchema,
29000
- includePhone: z.boolean(),
29001
- tags: z.string().nullable().optional(),
29002
29487
  spamProtectionEnabled: z.boolean().optional()
29003
29488
  });
29004
29489
  const newsletterRenderSchema = z.object({
@@ -29010,16 +29495,26 @@ z.object({
29010
29495
  apiBaseUrl: z.string().optional()
29011
29496
  });
29012
29497
  function buildNewsletterDisplay(source) {
29013
- const preset = source.preset ?? "emailOnly";
29014
- const includePhone = source.includePhone ?? false;
29498
+ const context = source.mailingList;
29499
+ const form = context?.tag === "configured" ? context.form : {
29500
+ fields: { preset: "emailOnly" },
29501
+ includeOptionalPhone: false,
29502
+ buttonLabel: "Subscribe",
29503
+ successMessage: DEFAULT_MAILING_LIST_SUCCESS_MESSAGE,
29504
+ privacyNote: null
29505
+ };
29506
+ const targeting = source.targeting ?? { mode: "default" };
29507
+ const choices = resolveRuntimeChoices(context, targeting);
29015
29508
  return {
29016
29509
  kind: "newsletter-form",
29510
+ availability: runtimeTargetingIsAvailable(context, targeting, choices) ? "ready" : "unavailable",
29017
29511
  className: source.className ?? null,
29018
- buttonLabel: source.buttonLabel?.trim() || "Subscribe",
29512
+ buttonLabel: form.buttonLabel,
29513
+ successMessage: form.successMessage,
29019
29514
  buttonVariant: source.buttonVariant ?? "primary",
29020
- successMessage: source.successMessage ?? "Thanks for subscribing!",
29021
- privacyNote: source.privacyNote ?? null,
29022
- fields: getPresetFields(preset, { includePhone })
29515
+ privacyNote: form.privacyNote,
29516
+ fields: getGlobalFormFields(form),
29517
+ choices
29023
29518
  };
29024
29519
  }
29025
29520
  const newsletterFormBlockRuntime = defineProgressiveBlockRuntime({
@@ -29029,14 +29524,15 @@ const newsletterFormBlockRuntime = defineProgressiveBlockRuntime({
29029
29524
  render: createZodCodec(newsletterRenderSchema)
29030
29525
  },
29031
29526
  buildRender: (source) => {
29032
- const runtimeSource = source.source === "block" ? deriveNewsletterSignupRuntimeSource(source) : null;
29527
+ const targeting = source.targeting ?? { mode: "default" };
29528
+ const presentation = planMailingListChoicePresentation(targeting);
29033
29529
  return {
29034
29530
  display: buildNewsletterDisplay(source),
29035
29531
  hydration: {
29036
29532
  target: projectNewsletterFormHydrationTarget(source),
29037
- preset: source.preset ?? "emailOnly",
29038
- includePhone: source.includePhone ?? false,
29039
- tags: runtimeSource ? runtimeSource.tags : source.tags,
29533
+ setupRevision: source.mailingList?.tag === "configured" ? source.mailingList.revision : null,
29534
+ choiceProvider: targeting.mode === "custom" ? targeting.provider : null,
29535
+ choicePresentation: presentation.tag,
29040
29536
  spamProtectionEnabled: source.spamProtectionEnabled
29041
29537
  }
29042
29538
  };
@@ -29045,35 +29541,87 @@ const newsletterFormBlockRuntime = defineProgressiveBlockRuntime({
29045
29541
  function projectNewsletterFormHydrationTarget(source) {
29046
29542
  switch (source.source) {
29047
29543
  case "block": {
29048
- const destinationRef = buildNewsletterSignupBlockRef(source.blockId);
29049
- if (destinationRef?.tag === "block_ref") return {
29544
+ const sourceRef = buildMailingListSignupBlockSourceRef(source.blockId, source.contentVersionId);
29545
+ if (sourceRef?.tag === "block_ref") return {
29050
29546
  tag: "block-source",
29051
- destinationRef
29547
+ sourceRef
29052
29548
  };
29053
29549
  return {
29054
- tag: "legacy-direct-list",
29055
- listId: source.listId ?? null
29550
+ tag: "block-source",
29551
+ sourceRef: null
29056
29552
  };
29057
29553
  }
29058
29554
  case "signed-footer": return {
29059
29555
  tag: "signed-footer-source",
29060
- destinationRef: source.destinationRef
29061
- };
29062
- case "legacy-direct-list": return {
29063
- tag: "legacy-direct-list",
29064
- listId: source.listId
29556
+ sourceRef: source.sourceRef
29065
29557
  };
29558
+ case "preview": return { tag: "preview" };
29066
29559
  default: return assertNever$1(source);
29067
29560
  }
29068
29561
  }
29069
- function parseRequiredNewsletterSignupBlockId(value) {
29070
- const parsed = parseNewsletterSignupBlockId(value);
29071
- if (!parsed) throw new Error("Newsletter signup block destination ref requires blockId");
29562
+ function resolveRuntimeChoices(context, targeting) {
29563
+ if (context?.tag !== "configured" || targeting.mode !== "custom" || targeting.selection.tag !== "visitor_choice" || context.provider.provider !== targeting.provider) return [];
29564
+ switch (targeting.provider) {
29565
+ case "native": {
29566
+ const offered = new Set(targeting.selection.offeredTopicIds);
29567
+ return context.provider.provider === "native" ? context.provider.topics.filter((item) => offered.has(item.id)).map((item) => ({
29568
+ id: item.id,
29569
+ label: item.name
29570
+ })) : [];
29571
+ }
29572
+ case "brevo": {
29573
+ const offered = new Set(targeting.selection.offeredListIds);
29574
+ return context.provider.provider === "brevo" ? context.provider.lists.filter((item) => offered.has(item.id)).map((item) => ({
29575
+ id: String(item.id),
29576
+ label: item.name
29577
+ })) : [];
29578
+ }
29579
+ case "mailchimp": {
29580
+ const offered = new Set(targeting.selection.offeredInterestIds);
29581
+ 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) => ({
29582
+ id: item.id,
29583
+ label: item.name
29584
+ })) ?? [];
29585
+ }
29586
+ }
29587
+ }
29588
+ function runtimeTargetingIsAvailable(context, targeting, choices) {
29589
+ if (context?.tag !== "configured") return false;
29590
+ const provider = context.provider;
29591
+ if (targeting.mode === "default") switch (provider.provider) {
29592
+ case "native": return provider.topics.some((item) => item.id === provider.defaultTopicId);
29593
+ case "brevo": return provider.lists.some((item) => item.id === provider.defaultListId);
29594
+ case "mailchimp": return provider.audiences.some((item) => item.id === provider.defaultAudienceId);
29595
+ }
29596
+ if (targeting.provider !== provider.provider) return false;
29597
+ switch (targeting.provider) {
29598
+ case "native": return provider.provider === "native" && nativeTargetIsAvailable(provider, targeting, choices);
29599
+ case "brevo": return provider.provider === "brevo" && brevoTargetIsAvailable(provider, targeting, choices);
29600
+ case "mailchimp": return provider.provider === "mailchimp" && mailchimpTargetIsAvailable(provider, targeting, choices);
29601
+ }
29602
+ }
29603
+ function nativeTargetIsAvailable(provider, targeting, choices) {
29604
+ const ids = targeting.selection.tag === "fixed" ? targeting.selection.topicIds : targeting.selection.offeredTopicIds;
29605
+ return ids.every((id) => provider.topics.some((item) => item.id === id)) && (targeting.selection.tag !== "visitor_choice" || choices.length === ids.length);
29606
+ }
29607
+ function brevoTargetIsAvailable(provider, targeting, choices) {
29608
+ const ids = targeting.selection.tag === "fixed" ? targeting.selection.listIds : targeting.selection.offeredListIds;
29609
+ return ids.every((id) => provider.lists.some((item) => item.id === id)) && (targeting.selection.tag !== "visitor_choice" || choices.length === ids.length);
29610
+ }
29611
+ function mailchimpTargetIsAvailable(provider, targeting, choices) {
29612
+ const audience = provider.audiences.find((item) => item.id === targeting.audienceId);
29613
+ if (!audience) return false;
29614
+ const ids = targeting.selection.tag === "fixed" ? targeting.selection.interestIds : targeting.selection.offeredInterestIds;
29615
+ return ids.every((id) => audience.interests.some((item) => item.id === id)) && (targeting.selection.tag !== "visitor_choice" || choices.length === ids.length);
29616
+ }
29617
+ function parseRequiredMailingListSignupBlockId(value) {
29618
+ const parsed = parseMailingListBlockId(value);
29619
+ if (!parsed) throw new Error("Mailing-list signup block source ref requires blockId");
29072
29620
  return parsed;
29073
29621
  }
29074
- function parseRequiredSignedNewsletterDestinationRef(value) {
29075
- const parsed = parseSignedNewsletterDestinationRef(value);
29076
- if (!parsed) throw new Error("Newsletter signup signed destination ref requires token");
29622
+ function parseRequiredMailingListSignedSourceToken(value) {
29623
+ const parsed = parseMailingListSignedSourceToken(value);
29624
+ if (!parsed) throw new Error("Mailing-list signup signed source ref requires token");
29077
29625
  return parsed;
29078
29626
  }
29079
29627
  //#endregion
@@ -30446,6 +30994,14 @@ const systemBlockDefinitions = [
30446
30994
  weight: "standard"
30447
30995
  })]
30448
30996
  })),
30997
+ withDesignCapability("block.appointment-services", appointmentServicesBlockDefinition, sectionOnly(), defineBlockDesignMetadata({
30998
+ flow: conversionFlow,
30999
+ layoutProfiles: [layoutProfile({
31000
+ variantKey: "default",
31001
+ family: "stack",
31002
+ weight: "standard"
31003
+ })]
31004
+ })),
30449
31005
  withDesignCapability("block.weekly-slot-availability", weeklySlotAvailabilityBlockDefinition, sectionOnly(), defineBlockDesignMetadata({
30450
31006
  flow: offeringsFlow,
30451
31007
  layoutProfiles: [layoutProfile({