@riverbankcms/sdk 0.138.0 → 0.139.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 (208) hide show
  1. package/README.md +11 -15
  2. package/dist/{PreviewEditorSidebar-BVPur_CU.mjs → PreviewEditorSidebar-BDeenhi3.mjs} +4 -4
  3. package/dist/{PreviewEditorUI-DLhWX8oh.mjs → PreviewEditorUI-DSRhgjF5.mjs} +3 -3
  4. package/dist/{PreviewQueryProvider-BguJY1SW.mjs → PreviewQueryProvider-D2K8GLUG.mjs} +1 -1
  5. package/dist/{SdkPreviewModeRuntime-Tda6qw4z.mjs → SdkPreviewModeRuntime-CL7wSnYu.mjs} +47 -27
  6. package/dist/{SiteChromeCustomizeContext-BHFgMjde.mjs → SiteChromeCustomizeContext-BhDn-5ir.mjs} +7771 -5863
  7. package/dist/_dts/ai/src/contracts/proposals.d.ts +99 -330
  8. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +9 -30
  9. package/dist/_dts/api/src/billing.d.ts +10 -3
  10. package/dist/_dts/api/src/contentRuntime.d.ts +8 -1
  11. package/dist/_dts/api/src/endpoints.d.ts +182 -103
  12. package/dist/_dts/api/src/footerSettings.d.ts +2 -5
  13. package/dist/_dts/api/src/index.d.ts +11 -9
  14. package/dist/_dts/api/src/mailchimpIntegration.d.ts +2 -59
  15. package/dist/_dts/api/src/mailingListIntegration.d.ts +117 -0
  16. package/dist/_dts/api/src/navigation/locations.d.ts +1 -0
  17. package/dist/_dts/api/src/navigation.d.ts +1 -26
  18. package/dist/_dts/api/src/newsletterEndpointDefinitions.d.ts +109 -2
  19. package/dist/_dts/api/src/onboarding/surfaceData.d.ts +185 -0
  20. package/dist/_dts/api/src/privacyPolicy.d.ts +74 -2
  21. package/dist/_dts/api/src/publicBookingAvailabilityEndpointDefinitions.d.ts +6 -6
  22. package/dist/_dts/api/src/publicEventEndpointDefinitions.d.ts +1 -1
  23. package/dist/_dts/api/src/publicExperience/newsletterEndpoints.d.ts +2 -4
  24. package/dist/_dts/api/src/publicExperience/sharedTypes.d.ts +10 -24
  25. package/dist/_dts/api/src/publicReadEndpointDefinitions.d.ts +73 -0
  26. package/dist/_dts/api/src/schemas/site-api-keys.d.ts +1 -1
  27. package/dist/_dts/api/src/sdkContracts.d.ts +2 -10
  28. package/dist/_dts/api/src/sdkThemeWire.d.ts +2 -2
  29. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +0 -29
  30. package/dist/_dts/api/src/siteOnboarding.d.ts +91 -228
  31. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +1 -9
  32. package/dist/_dts/api/src/siteSettings.d.ts +20 -1
  33. package/dist/_dts/api/src/types.d.ts +5 -4
  34. package/dist/_dts/billing/src/membership/index.d.ts +14 -7
  35. package/dist/_dts/billing/src/plans/display.d.ts +15 -0
  36. package/dist/_dts/billing/src/plans/registry.d.ts +2 -0
  37. package/dist/_dts/billing/src/plans/standing.d.ts +19 -0
  38. package/dist/_dts/billing/src/plans/types.d.ts +1 -7
  39. package/dist/_dts/billing/src/subscriptions/evidence.d.ts +12 -0
  40. package/dist/_dts/billing/src/subscriptions/standingEvidence.d.ts +31 -0
  41. package/dist/_dts/billing/src/subscriptions/store.d.ts +23 -5
  42. package/dist/_dts/blocks/src/PageRenderer.d.ts +6 -15
  43. package/dist/_dts/blocks/src/client.d.ts +1 -1
  44. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +32 -16
  45. package/dist/_dts/blocks/src/pageRendererContracts.d.ts +4 -0
  46. package/dist/_dts/blocks/src/pageRenderingMode.d.ts +12 -6
  47. package/dist/_dts/blocks/src/system/blocks/appointment-services.d.ts +11 -0
  48. package/dist/_dts/blocks/src/system/blocks/contact-newsletter.d.ts +39 -66
  49. package/dist/_dts/blocks/src/system/blocks/newsletter-signup.d.ts +39 -114
  50. package/dist/_dts/blocks/src/system/blocks/offerings-preview/catalogue.d.ts +18 -0
  51. package/dist/_dts/blocks/src/system/blocks/offerings-preview/fields.d.ts +2 -0
  52. package/dist/_dts/blocks/src/system/blocks/offerings-preview/index.d.ts +4 -0
  53. package/dist/_dts/blocks/src/system/blocks/site-footer-runtime.d.ts +7 -13
  54. package/dist/_dts/blocks/src/system/constants/blockKinds.d.ts +1 -1
  55. package/dist/_dts/blocks/src/system/data/index.d.ts +2 -2
  56. package/dist/_dts/blocks/src/system/data/loaderEndpoints.d.ts +1 -1
  57. package/dist/_dts/blocks/src/system/data/publicLoaderCachePolicy.d.ts +2 -74
  58. package/dist/_dts/blocks/src/system/fragments/library/newsletterForm.d.ts +33 -100
  59. package/dist/_dts/blocks/src/system/runtime/api/types/newsletter.d.ts +5 -15
  60. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +48 -24
  61. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +24 -12
  62. package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.d.ts +3 -0
  63. package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.state.d.ts +1 -1
  64. package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarToday.d.ts +22 -0
  65. package/dist/_dts/blocks/src/system/runtime/nodes/appointment-services.d.ts +51 -0
  66. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +2 -0
  67. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +0 -1
  68. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +28 -0
  69. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/bookability.d.ts +9 -0
  70. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/dates.d.ts +14 -0
  71. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/duration.d.ts +2 -0
  72. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/index.d.ts +4 -0
  73. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/location.d.ts +2 -0
  74. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/quickDates.d.ts +16 -0
  75. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/AgendaEventCard.d.ts +9 -1
  76. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/CalendarDayCell.d.ts +2 -0
  77. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/CalendarDayHeaders.d.ts +4 -0
  78. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/DayEventsModal.d.ts +2 -1
  79. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventCard.d.ts +5 -0
  80. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventModals.d.ts +2 -1
  81. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventQuickDates.d.ts +15 -0
  82. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekAgendaView.d.ts +7 -3
  83. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekTimetableView.d.ts +1 -0
  84. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/index.d.ts +2 -0
  85. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/timetableModel.d.ts +1 -0
  86. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/useHydrationReady.d.ts +6 -0
  87. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.client.state.d.ts +3 -0
  88. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.interactive.d.ts +56 -33
  89. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.submission.d.ts +3 -3
  90. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.types.d.ts +13 -31
  91. package/dist/_dts/blocks/src/system/runtime/nodes/offerings-preview-catalogue.d.ts +14 -0
  92. package/dist/_dts/blocks/src/system/runtime/nodes/offerings-preview-content.d.ts +23 -0
  93. package/dist/_dts/blocks/src/system/runtime/nodes/offerings-preview.d.ts +4 -2
  94. package/dist/_dts/blocks/src/system/transforms/registry/formatting.d.ts +5 -0
  95. package/dist/_dts/commerce/src/purchase/index.d.ts +1 -0
  96. package/dist/_dts/commerce/src/purchase/orderItemMetadata.d.ts +5 -12
  97. package/dist/_dts/commerce/src/purchase/stripeCommissionMetadata.d.ts +34 -0
  98. package/dist/_dts/content-editor/src/footerEngagementDraft.d.ts +6 -24
  99. package/dist/_dts/content-editor/src/useFooterComposerState.d.ts +1 -2
  100. package/dist/_dts/core/src/footer-engagement.d.ts +2 -6
  101. package/dist/_dts/core/src/index.d.ts +9 -1
  102. package/dist/_dts/core/src/mailing-list-identifiers.d.ts +21 -0
  103. package/dist/_dts/core/src/mailing-list-runtime.d.ts +42 -0
  104. package/dist/_dts/core/src/mailing-list-setup-parser.d.ts +14 -0
  105. package/dist/_dts/core/src/mailing-list-setup.d.ts +129 -0
  106. package/dist/_dts/core/src/mailing-list-submission.d.ts +244 -0
  107. package/dist/_dts/core/src/mailing-list-targeting-parser.d.ts +12 -0
  108. package/dist/_dts/core/src/mailing-list-targeting.d.ts +93 -0
  109. package/dist/_dts/core/src/navigation-locations.d.ts +28 -0
  110. package/dist/_dts/core/src/public-profile.d.ts +9 -1
  111. package/dist/_dts/core/src/public-read-cache-contract.d.ts +45 -0
  112. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +529 -373
  113. package/dist/_dts/editor-blocks/src/widgets/index.d.ts +1 -0
  114. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/MailingListTargetingField.d.ts +11 -0
  115. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/context.d.ts +13 -0
  116. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/index.d.ts +3 -0
  117. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/loaders.d.ts +6 -0
  118. package/dist/_dts/preview-next/src/client/widgets/widgetOverrides.d.ts +1 -0
  119. package/dist/_dts/sdk/src/client/publicAppointmentReadOperations.d.ts +12 -0
  120. package/dist/_dts/sdk/src/client/publicEventReadOperations.d.ts +2 -1
  121. package/dist/_dts/sdk/src/client/publicLoaderCacheAccess.d.ts +11 -4
  122. package/dist/_dts/sdk/src/config/content-types.d.ts +3 -13
  123. package/dist/_dts/sdk/src/config/content-validation.d.ts +5 -8
  124. package/dist/_dts/sdk/src/constants.d.ts +3 -3
  125. package/dist/_dts/sdk/src/contracts/index.d.ts +1 -1
  126. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +12 -31
  127. package/dist/_dts/sdk/src/navigation/index.d.ts +11 -29
  128. package/dist/_dts/sdk/src/next/index.d.ts +4 -4
  129. package/dist/_dts/sdk/src/prebuild/types.d.ts +1 -5
  130. package/dist/_dts/sdk/src/public-api/contracts.d.ts +33 -16
  131. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +3 -0
  132. package/dist/_dts/sdk/src/rendering/client.d.ts +3 -20
  133. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +3 -0
  134. package/dist/_dts/sdk/src/rendering/helpers/loadContent.d.ts +4 -0
  135. package/dist/_dts/sdk/src/rendering/helpers/pageRuntimeSupport.d.ts +1 -0
  136. package/dist/_dts/sdk/src/rendering/index.d.ts +1 -1
  137. package/dist/_dts/sdk/src/types/block-kinds.d.ts +1 -1
  138. package/dist/_dts/sdk/src/version.d.ts +1 -1
  139. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  140. package/dist/_dts/theme-core/src/hosted-booking-appearance.d.ts +41 -0
  141. package/dist/_dts/theme-core/src/index.d.ts +1 -0
  142. package/dist/_dts/theme-core/src/runtime/buildThemeRuntime.d.ts +0 -1
  143. package/dist/_dts/theme-core/src/tokens/tokens.d.ts +7 -0
  144. package/dist/_dts/ui/src/badge.d.ts +1 -1
  145. package/dist/_dts/ui/src/callout.d.ts +1 -1
  146. package/dist/client/{BookingConsentAgreement-DQUik1Mx.mjs → BookingConsentAgreement-CZvTDtsK.mjs} +2 -2
  147. package/dist/client/{DiscountCodeDisclosure-CU67Q4vH.mjs → DiscountCodeDisclosure-D-DsLCMU.mjs} +1 -1
  148. package/dist/client/{EventCombined.client-a02TXUgg.mjs → EventCombined.client-dWqgd5ZO.mjs} +443 -199
  149. package/dist/client/{EventListing.client-99qx7jFl.mjs → EventListing.client-BMRa9IYp.mjs} +2 -2
  150. package/dist/client/{LeafletStaticMap-CWzcq73L.mjs → LeafletStaticMap-D21W9kBZ.mjs} +1 -1
  151. package/dist/client/{accordion-D1nb3-Oj.mjs → accordion-FxF_ta47.mjs} +1 -1
  152. package/dist/client/{bookingForm-BGrmLhaO.mjs → bookingForm-YnwW4TGw.mjs} +5 -5
  153. package/dist/client/bookings.mjs +43 -2
  154. package/dist/client/{carousel-DSmOx3ad.mjs → carousel-vng7fFT5.mjs} +1 -1
  155. package/dist/client/{cart-COWeOIUk.mjs → cart-DEPDsjNk.mjs} +3 -3
  156. package/dist/client/{checkout-CeysaIJK.mjs → checkout-CZRWu9rW.mjs} +3 -3
  157. package/dist/client/client.mjs +3331 -1407
  158. package/dist/client/{context-DBzX85Xc.mjs → context-DvU_WUmd.mjs} +4 -3
  159. package/dist/client/{dates-DCYhZBlW.mjs → dates-wnPMiRl5.mjs} +21 -3
  160. package/dist/client/{eventCalendar-BgsN73Ul.mjs → eventCalendar-BA3Q5L15.mjs} +80 -78
  161. package/dist/client/{eventCombined-DcZQAMQP.mjs → eventCombined-51wgR-1R.mjs} +3 -3
  162. package/dist/client/{eventDetails-BWwGJ54l.mjs → eventDetails-modaetpm.mjs} +4 -4
  163. package/dist/client/{eventListing-DqYqV8vp.mjs → eventListing-D8t2J3Kv.mjs} +3 -3
  164. package/dist/client/{eventRegistration-DQGDgu_e.mjs → eventRegistration-CYqtkCE_.mjs} +49 -9
  165. package/dist/client/{form-ClfpasVT.mjs → form-CBKXN5In.mjs} +2 -2
  166. package/dist/client/{headerSection-BuOMe98N.mjs → headerSection-DylDqNrs.mjs} +2 -2
  167. package/dist/client/hooks.mjs +1259 -555
  168. package/dist/client/{locationMap-CEqu_sfa.mjs → locationMap-CvWrG0vZ.mjs} +2 -2
  169. package/dist/client/{newsletterForm-IbrHjMxy.mjs → newsletterForm-Btwk70zw.mjs} +117 -38
  170. package/dist/client/{pricing-xj7MPZlK.mjs → pricing-Uzw-GQ6Y.mjs} +1 -1
  171. package/dist/client/{productDetail-vxqTt5Xj.mjs → productDetail-JLcUYKnd.mjs} +3 -3
  172. package/dist/client/{productList-OTdZu8sb.mjs → productList-FM0cbUzj.mjs} +3 -3
  173. package/dist/client/{propsDecoder-CY9gGEF7.mjs → propsDecoder-DYzafZb2.mjs} +592 -152
  174. package/dist/client/rendering/client.mjs +2259 -835
  175. package/dist/client/rendering/islands.mjs +17 -17
  176. package/dist/client/rendering.mjs +3308 -1236
  177. package/dist/client/{scrollToBlock--BFV6kl-.mjs → scrollToBlock-CvXszexS.mjs} +1 -1
  178. package/dist/client/{shop-CP4YbDL9.mjs → shop-BIcjvy5a.mjs} +6 -6
  179. package/dist/client/{shop-commerce-APs4XBXE.mjs → shop-commerce-BZQsy7xw.mjs} +5 -5
  180. package/dist/client/{shop-commerce-store-CAVLxLFr.mjs → shop-commerce-store-D5V7XAb5.mjs} +1 -1
  181. package/dist/client/{shopShared-BnSRrwXI.mjs → shopShared-DowkXevB.mjs} +3 -3
  182. package/dist/client/{useEventFilters-1a1by4c8.mjs → useEventFilters-oMoTw_JE.mjs} +56 -9
  183. package/dist/preview-next/before-render.mjs +238 -111
  184. package/dist/preview-next/client/runtime.mjs +4 -4
  185. package/dist/preview-next/keepAlive.mjs +238 -111
  186. package/dist/preview-next/middleware.mjs +238 -111
  187. package/dist/{previewAuthStore-BkEgnYPP.mjs → previewAuthStore-COUyAKaX.mjs} +238 -111
  188. package/dist/{sdk-runtime-DwGfsT0S.mjs → sdk-runtime-D4k2LSGF.mjs} +2 -2
  189. package/dist/{separator-BeqDLneQ.mjs → separator-UGtpag4Z.mjs} +1 -1
  190. package/dist/server/components.mjs +2697 -1023
  191. package/dist/server/config-validation.mjs +2424 -1720
  192. package/dist/server/config.mjs +2429 -1724
  193. package/dist/server/data.mjs +1164 -454
  194. package/dist/server/index.mjs +364 -280
  195. package/dist/server/navigation.mjs +16 -47
  196. package/dist/server/next.mjs +2915 -1380
  197. package/dist/server/page-converter.mjs +969 -522
  198. package/dist/server/prebuild.mjs +2 -3
  199. package/dist/server/rendering/server.mjs +2704 -1030
  200. package/dist/server/rendering.mjs +2742 -1063
  201. package/dist/server/routing.mjs +1386 -595
  202. package/dist/server/server.mjs +2878 -2324
  203. package/dist/server/theme-bridge.mjs +292 -24
  204. package/dist/styles/index.css +289 -25
  205. package/package.json +1 -1
  206. package/dist/_dts/api/src/navigation/identity.d.ts +0 -59
  207. package/dist/_dts/blocks/src/system/blocks/newsletter-signup-destination.d.ts +0 -291
  208. package/dist/_dts/core/src/newsletter-signup-destination.d.ts +0 -38
@@ -682,7 +682,7 @@ function subtractDaysFromIso(isoString, dayCount) {
682
682
  return addDaysToIso(isoString, -dayCount);
683
683
  }
684
684
  var init_date_math = __esmMin((() => {}));
685
- var init_duration = __esmMin((() => {}));
685
+ var init_duration$1 = __esmMin((() => {}));
686
686
  var init_demo_capability_policy = __esmMin((() => {
687
687
  init_src$2();
688
688
  })), init_demo_claim_access = __esmMin((() => {})), init_demo_lifecycle_status = __esmMin((() => {}));
@@ -698,6 +698,10 @@ var init_event_booking_offer = __esmMin((() => {
698
698
  init_assert_never();
699
699
  init_result$1();
700
700
  }));
701
+ /** Parse + normalize a currency code, or return null if it isn't a 3-letter code. */
702
+ function parseCurrencyCode(value) {
703
+ return CURRENCY_CODE_INPUT_PATTERN.test(value) ? value.toUpperCase() : null;
704
+ }
701
705
  function resolveCurrencyLocale(currencyCode, override) {
702
706
  return override ?? CURRENCY_LOCALE_BY_CODE[currencyCode] ?? "en";
703
707
  }
@@ -731,8 +735,9 @@ function formatCurrencyAmount(amountCents, currency, options) {
731
735
  return `${(amountCents / 100).toFixed(2)} ${currencyCode}`;
732
736
  }
733
737
  }
734
- var CURRENCY_LOCALE_BY_CODE;
738
+ var CURRENCY_CODE_INPUT_PATTERN, CURRENCY_LOCALE_BY_CODE;
735
739
  var init_currency_format = __esmMin((() => {
740
+ CURRENCY_CODE_INPUT_PATTERN = /^[A-Za-z]{3}$/;
736
741
  CURRENCY_LOCALE_BY_CODE = {
737
742
  USD: "en-US",
738
743
  GBP: "en-GB",
@@ -858,6 +863,17 @@ function resolvePricingOptionSaleWindowState(option, now) {
858
863
  if (option.saleEndsAt !== null && option.saleEndsAt !== void 0 && new Date(option.saleEndsAt) < now) return "ended";
859
864
  return "open";
860
865
  }
866
+ function resolveExactOrFreePriceDisplay(amount, currency) {
867
+ const resolvedAmount = amount ?? 0;
868
+ return resolvedAmount > 0 ? {
869
+ kind: "exact",
870
+ amount: resolvedAmount,
871
+ currency
872
+ } : {
873
+ kind: "free",
874
+ currency
875
+ };
876
+ }
861
877
  function resolvePricingOptionsPriceDisplay(input) {
862
878
  const now = input.purpose === "available_now" ? resolvePlanningNowDate({
863
879
  now: input.now,
@@ -1000,7 +1016,7 @@ function parseEventPageSurfaceDestinationMode(value) {
1000
1016
  return value === "cms-managed" || value === "system-managed" ? value : void 0;
1001
1017
  }
1002
1018
  function parseEventPageSurfaceSubject(value) {
1003
- if (!isRecord$27(value)) return err$2({ kind: "notObject" });
1019
+ if (!isRecord$28(value)) return err$2({ kind: "notObject" });
1004
1020
  switch (value.kind) {
1005
1021
  case "eventSeries": {
1006
1022
  const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
@@ -1055,7 +1071,7 @@ function parseEventSeriesIdList(values) {
1055
1071
  }
1056
1072
  return ok$2(parsed);
1057
1073
  }
1058
- function isRecord$27(value) {
1074
+ function isRecord$28(value) {
1059
1075
  return typeof value === "object" && value !== null && !Array.isArray(value);
1060
1076
  }
1061
1077
  var init_event_page_surface_subject = __esmMin((() => {
@@ -1531,7 +1547,7 @@ function toLocationCoordinates(value) {
1531
1547
  lng: value.lng
1532
1548
  };
1533
1549
  }
1534
- var init_location = __esmMin((() => {}));
1550
+ var init_location$1 = __esmMin((() => {}));
1535
1551
  var init_string = __esmMin((() => {}));
1536
1552
  var init_business_address = __esmMin((() => {
1537
1553
  init_string();
@@ -1561,7 +1577,7 @@ var init_public_profile = __esmMin((() => {
1561
1577
  }));
1562
1578
  //#endregion
1563
1579
  //#region ../core/src/rich-text.ts
1564
- function isRecord$25(value) {
1580
+ function isRecord$26(value) {
1565
1581
  return typeof value === "object" && value !== null && !Array.isArray(value);
1566
1582
  }
1567
1583
  function hasOnlyKeys(value, allowed) {
@@ -1572,10 +1588,10 @@ function isDenseArrayOf(value, predicate) {
1572
1588
  return true;
1573
1589
  }
1574
1590
  function isTipTapMark(value) {
1575
- return isRecord$25(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$25(value.attrs));
1591
+ return isRecord$26(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$26(value.attrs));
1576
1592
  }
1577
1593
  function isTipTapNode(value) {
1578
- if (!isRecord$25(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$25(value.attrs) || value.marks !== void 0 && (!Array.isArray(value.marks) || !isDenseArrayOf(value.marks, isTipTapMark)) || value.content !== void 0 && (!Array.isArray(value.content) || !isDenseArrayOf(value.content, isTipTapNode))) return false;
1594
+ if (!isRecord$26(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$26(value.attrs) || value.marks !== void 0 && (!Array.isArray(value.marks) || !isDenseArrayOf(value.marks, isTipTapMark)) || value.content !== void 0 && (!Array.isArray(value.content) || !isDenseArrayOf(value.content, isTipTapNode))) return false;
1579
1595
  if (value.type === "text") return typeof value.text === "string" && value.text.length > 0 && value.content === void 0;
1580
1596
  return value.text === void 0;
1581
1597
  }
@@ -1590,15 +1606,203 @@ var init_rich_text = __esmMin((() => {
1590
1606
  ]);
1591
1607
  markKeys = /* @__PURE__ */ new Set(["type", "attrs"]);
1592
1608
  }));
1593
- function parseNewsletterSignupDestinationProvider(value) {
1594
- return value === "riverbank" || value === "mailchimp" ? value : null;
1609
+ //#endregion
1610
+ //#region ../core/src/mailing-list-identifiers.ts
1611
+ function parseTrimmedMatchingString(value, pattern) {
1612
+ if (typeof value !== "string") return null;
1613
+ const trimmed = value.trim();
1614
+ return pattern.test(trimmed) ? trimmed : null;
1615
+ }
1616
+ function parsePositiveInteger(value) {
1617
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : null;
1618
+ }
1619
+ function parseNewsletterListId(value) {
1620
+ return parseTrimmedMatchingString(value, UUID_PATTERN);
1621
+ }
1622
+ function parseMailchimpAudienceId(value) {
1623
+ return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
1624
+ }
1625
+ function parseMailchimpInterestId(value) {
1626
+ return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
1627
+ }
1628
+ function parseBrevoListId(value) {
1629
+ return parsePositiveInteger(value);
1630
+ }
1631
+ var UUID_PATTERN, OPAQUE_ID_PATTERN;
1632
+ var init_mailing_list_identifiers = __esmMin((() => {
1633
+ 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;
1634
+ OPAQUE_ID_PATTERN = /^[A-Za-z0-9_-]{1,100}$/u;
1635
+ }));
1636
+ //#endregion
1637
+ //#region ../core/src/mailing-list-targeting-parser.ts
1638
+ function parseMailingListPlacementTargeting(value) {
1639
+ if (!isRecord$25(value)) return targetingError("shape");
1640
+ if (value.mode === "default") return ok$2({ mode: "default" });
1641
+ if (value.mode !== "custom") return targetingError("mode");
1642
+ if (!isRecord$25(value.selection)) return targetingError("selection");
1643
+ switch (value.provider) {
1644
+ case "native": return parseNativeTargeting(value.selection);
1645
+ case "brevo": return parseBrevoTargeting(value.selection);
1646
+ case "mailchimp": return parseMailchimpTargeting(value, value.selection);
1647
+ default: return targetingError("provider");
1648
+ }
1649
+ }
1650
+ function parseMailingListVisitorSelection(value) {
1651
+ if (!isRecord$25(value)) return visitorSelectionError("shape");
1652
+ switch (value.provider) {
1653
+ case "native": {
1654
+ const topicIds = parseVisitorIds(value.topicIds, parseNewsletterListId);
1655
+ return topicIds === null ? visitorSelectionError("targets") : ok$2({
1656
+ provider: "native",
1657
+ topicIds
1658
+ });
1659
+ }
1660
+ case "brevo": {
1661
+ const listIds = parseVisitorIds(value.listIds, parseBrevoListId);
1662
+ return listIds === null ? visitorSelectionError("targets") : ok$2({
1663
+ provider: "brevo",
1664
+ listIds
1665
+ });
1666
+ }
1667
+ case "mailchimp": {
1668
+ const interestIds = parseVisitorIds(value.interestIds, parseMailchimpInterestId);
1669
+ return interestIds === null ? visitorSelectionError("targets") : ok$2({
1670
+ provider: "mailchimp",
1671
+ interestIds
1672
+ });
1673
+ }
1674
+ default: return visitorSelectionError("provider");
1675
+ }
1676
+ }
1677
+ function parseNativeTargeting(selection) {
1678
+ if (selection.tag === "fixed") {
1679
+ const topicIds = parseNonEmptyUniqueIds(selection.topicIds, parseNewsletterListId);
1680
+ return topicIds.ok ? ok$2({
1681
+ mode: "custom",
1682
+ provider: "native",
1683
+ selection: {
1684
+ tag: "fixed",
1685
+ topicIds: topicIds.value
1686
+ }
1687
+ }) : topicIds;
1688
+ }
1689
+ if (selection.tag === "visitor_choice") {
1690
+ const offeredTopicIds = parseNonEmptyUniqueIds(selection.offeredTopicIds, parseNewsletterListId);
1691
+ return offeredTopicIds.ok ? ok$2({
1692
+ mode: "custom",
1693
+ provider: "native",
1694
+ selection: {
1695
+ tag: "visitor_choice",
1696
+ offeredTopicIds: offeredTopicIds.value
1697
+ }
1698
+ }) : offeredTopicIds;
1699
+ }
1700
+ return targetingError("selection");
1701
+ }
1702
+ function parseBrevoTargeting(selection) {
1703
+ if (selection.tag === "fixed") {
1704
+ const listIds = parseNonEmptyUniqueIds(selection.listIds, parseBrevoListId);
1705
+ return listIds.ok ? ok$2({
1706
+ mode: "custom",
1707
+ provider: "brevo",
1708
+ selection: {
1709
+ tag: "fixed",
1710
+ listIds: listIds.value
1711
+ }
1712
+ }) : listIds;
1713
+ }
1714
+ if (selection.tag === "visitor_choice") {
1715
+ const offeredListIds = parseNonEmptyUniqueIds(selection.offeredListIds, parseBrevoListId);
1716
+ return offeredListIds.ok ? ok$2({
1717
+ mode: "custom",
1718
+ provider: "brevo",
1719
+ selection: {
1720
+ tag: "visitor_choice",
1721
+ offeredListIds: offeredListIds.value
1722
+ }
1723
+ }) : offeredListIds;
1724
+ }
1725
+ return targetingError("selection");
1726
+ }
1727
+ function parseMailchimpTargeting(value, selection) {
1728
+ const audienceId = parseMailchimpAudienceId(value.audienceId);
1729
+ if (audienceId === null) return targetingError("audienceId");
1730
+ if (selection.tag === "fixed") {
1731
+ const interestIds = parseUniqueIds(selection.interestIds, parseMailchimpInterestId);
1732
+ return interestIds.ok ? ok$2({
1733
+ mode: "custom",
1734
+ provider: "mailchimp",
1735
+ audienceId,
1736
+ selection: {
1737
+ tag: "fixed",
1738
+ interestIds: interestIds.value
1739
+ }
1740
+ }) : interestIds;
1741
+ }
1742
+ if (selection.tag === "visitor_choice") {
1743
+ const offeredInterestIds = parseNonEmptyUniqueIds(selection.offeredInterestIds, parseMailchimpInterestId);
1744
+ return offeredInterestIds.ok ? ok$2({
1745
+ mode: "custom",
1746
+ provider: "mailchimp",
1747
+ audienceId,
1748
+ selection: {
1749
+ tag: "visitor_choice",
1750
+ offeredInterestIds: offeredInterestIds.value
1751
+ }
1752
+ }) : offeredInterestIds;
1753
+ }
1754
+ return targetingError("selection");
1755
+ }
1756
+ function parseNonEmptyUniqueIds(value, parseId) {
1757
+ const parsed = parseUniqueIds(value, parseId);
1758
+ if (!parsed.ok) return parsed;
1759
+ const [first, ...rest] = parsed.value;
1760
+ return first === void 0 ? targetingError("targets") : ok$2([first, ...rest]);
1761
+ }
1762
+ function parseUniqueIds(value, parseId) {
1763
+ if (!Array.isArray(value)) return targetingError("targets");
1764
+ const parsed = [];
1765
+ for (const item of value) {
1766
+ const id = parseId(item);
1767
+ if (id === null) return targetingError("targets");
1768
+ if (parsed.includes(id)) return targetingError("duplicate_target");
1769
+ parsed.push(id);
1770
+ }
1771
+ return ok$2(parsed);
1772
+ }
1773
+ function parseVisitorIds(value, parseId) {
1774
+ if (!Array.isArray(value) || value.length === 0) return null;
1775
+ const parsed = [];
1776
+ for (const item of value) {
1777
+ const id = parseId(item);
1778
+ if (id === null) return null;
1779
+ if (parsed.includes(id)) return null;
1780
+ parsed.push(id);
1781
+ }
1782
+ return parsed;
1595
1783
  }
1596
- var init_newsletter_signup_destination$1 = __esmMin((() => {
1784
+ function isRecord$25(value) {
1785
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1786
+ }
1787
+ function targetingError(field) {
1788
+ return err$2({
1789
+ tag: "invalid_mailing_list_targeting",
1790
+ field
1791
+ });
1792
+ }
1793
+ function visitorSelectionError(field) {
1794
+ return err$2({
1795
+ tag: "invalid_mailing_list_visitor_selection",
1796
+ field
1797
+ });
1798
+ }
1799
+ var init_mailing_list_targeting_parser = __esmMin((() => {
1800
+ init_mailing_list_identifiers();
1597
1801
  init_result$1();
1598
1802
  }));
1599
1803
  var init_footer_engagement = __esmMin((() => {
1600
1804
  init_branded();
1601
- init_newsletter_signup_destination$1();
1805
+ init_mailing_list_targeting_parser();
1602
1806
  init_result$1();
1603
1807
  })), sectionKinds;
1604
1808
  var init_footer_arrangement = __esmMin((() => {
@@ -1626,6 +1830,253 @@ var init_footer_navigation_layout = __esmMin((() => {}));
1626
1830
  //#endregion
1627
1831
  //#region ../core/src/footer-composition-types.ts
1628
1832
  var init_footer_composition_types = __esmMin((() => {}));
1833
+ var init_mailing_list_setup = __esmMin((() => {}));
1834
+ //#endregion
1835
+ //#region ../core/src/mailing-list-setup-parser.ts
1836
+ function parseMailingListGlobalForm(value) {
1837
+ if (!isRecord$22(value)) return formError("shape");
1838
+ const fields = parseGlobalFields(value.fields);
1839
+ if (fields === null) return formError("fields");
1840
+ if (typeof value.includeOptionalPhone !== "boolean") return formError("includeOptionalPhone");
1841
+ const buttonLabel = parseRequiredString(value.buttonLabel);
1842
+ if (buttonLabel === null) return formError("buttonLabel");
1843
+ const privacyNote = parseOptionalString(value.privacyNote);
1844
+ if (privacyNote === void 0) return formError("privacyNote");
1845
+ return ok$2({
1846
+ fields,
1847
+ includeOptionalPhone: value.includeOptionalPhone,
1848
+ buttonLabel,
1849
+ privacyNote
1850
+ });
1851
+ }
1852
+ function parseGlobalFields(value) {
1853
+ if (!isRecord$22(value) || typeof value.preset !== "string") return null;
1854
+ switch (value.preset) {
1855
+ case "emailOnly": return { preset: "emailOnly" };
1856
+ case "emailName": return isRequirement(value.name) ? {
1857
+ preset: "emailName",
1858
+ name: value.name
1859
+ } : null;
1860
+ case "emailFirstLast": return isRequirement(value.firstName) && isRequirement(value.lastName) ? {
1861
+ preset: "emailFirstLast",
1862
+ firstName: value.firstName,
1863
+ lastName: value.lastName
1864
+ } : null;
1865
+ case "emailNameCompany": return isRequirement(value.name) && isRequirement(value.company) ? {
1866
+ preset: "emailNameCompany",
1867
+ name: value.name,
1868
+ company: value.company
1869
+ } : null;
1870
+ default: return null;
1871
+ }
1872
+ }
1873
+ function parseMailingListSetupRevision(value) {
1874
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : null;
1875
+ }
1876
+ function parseRequiredString(value) {
1877
+ if (typeof value !== "string") return null;
1878
+ const trimmed = value.trim();
1879
+ return trimmed.length > 0 ? trimmed : null;
1880
+ }
1881
+ function parseOptionalString(value) {
1882
+ if (value === null || value === void 0) return null;
1883
+ if (typeof value !== "string") return void 0;
1884
+ const trimmed = value.trim();
1885
+ return trimmed.length > 0 ? trimmed : null;
1886
+ }
1887
+ function isRequirement(value) {
1888
+ return value === "required" || value === "optional";
1889
+ }
1890
+ function isRecord$22(value) {
1891
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1892
+ }
1893
+ function formError(field) {
1894
+ return err$2({
1895
+ tag: "invalid_mailing_list_global_form",
1896
+ field
1897
+ });
1898
+ }
1899
+ var init_mailing_list_setup_parser = __esmMin((() => {
1900
+ init_branded();
1901
+ init_mailing_list_identifiers();
1902
+ init_result$1();
1903
+ }));
1904
+ function planMailingListChoicePresentation(targeting) {
1905
+ if (targeting.mode === "default" || targeting.selection.tag === "fixed") return { tag: "hidden" };
1906
+ switch (targeting.provider) {
1907
+ case "native": return targeting.selection.offeredTopicIds.length === 1 ? {
1908
+ tag: "automatic",
1909
+ selection: {
1910
+ provider: "native",
1911
+ topicIds: targeting.selection.offeredTopicIds
1912
+ }
1913
+ } : {
1914
+ tag: "visitor_choice",
1915
+ provider: "native",
1916
+ optionCount: targeting.selection.offeredTopicIds.length
1917
+ };
1918
+ case "brevo": return targeting.selection.offeredListIds.length === 1 ? {
1919
+ tag: "automatic",
1920
+ selection: {
1921
+ provider: "brevo",
1922
+ listIds: targeting.selection.offeredListIds
1923
+ }
1924
+ } : {
1925
+ tag: "visitor_choice",
1926
+ provider: "brevo",
1927
+ optionCount: targeting.selection.offeredListIds.length
1928
+ };
1929
+ case "mailchimp": return targeting.selection.offeredInterestIds.length === 1 ? {
1930
+ tag: "automatic",
1931
+ selection: {
1932
+ provider: "mailchimp",
1933
+ interestIds: targeting.selection.offeredInterestIds
1934
+ }
1935
+ } : {
1936
+ tag: "visitor_choice",
1937
+ provider: "mailchimp",
1938
+ optionCount: targeting.selection.offeredInterestIds.length
1939
+ };
1940
+ }
1941
+ }
1942
+ var init_mailing_list_targeting = __esmMin((() => {
1943
+ init_result$1();
1944
+ }));
1945
+ //#endregion
1946
+ //#region ../core/src/mailing-list-runtime.ts
1947
+ function parseMailingListRuntimeContext(value) {
1948
+ if (!isRecord$21(value)) return invalidRuntimeContext();
1949
+ if (value.tag === "not_configured") return ok$2({ tag: "not_configured" });
1950
+ if (value.tag !== "configured") return invalidRuntimeContext();
1951
+ const revision = parseMailingListSetupRevision(value.revision);
1952
+ const form = parseMailingListGlobalForm(value.form);
1953
+ const provider = parseRuntimeProvider(value.provider);
1954
+ if (revision === null || !form.ok || provider === null) return invalidRuntimeContext();
1955
+ return ok$2({
1956
+ tag: "configured",
1957
+ revision,
1958
+ form: form.value,
1959
+ provider
1960
+ });
1961
+ }
1962
+ function parseRuntimeProvider(value) {
1963
+ if (!isRecord$21(value)) return null;
1964
+ switch (value.provider) {
1965
+ case "native": return parseNativeRuntimeProvider(value);
1966
+ case "brevo": return parseBrevoRuntimeProvider(value);
1967
+ case "mailchimp": return parseMailchimpRuntimeProvider(value);
1968
+ default: return null;
1969
+ }
1970
+ }
1971
+ function parseNativeRuntimeProvider(value) {
1972
+ const defaultTopicId = parseNewsletterListId(value.defaultTopicId);
1973
+ const topics = parseNamedItems(value.topics, parseNewsletterListId);
1974
+ return defaultTopicId !== null && topics !== null ? {
1975
+ provider: "native",
1976
+ defaultTopicId,
1977
+ topics
1978
+ } : null;
1979
+ }
1980
+ function parseBrevoRuntimeProvider(value) {
1981
+ const defaultListId = parseBrevoListId(value.defaultListId);
1982
+ const lists = parseNamedItems(value.lists, parseBrevoListId);
1983
+ return defaultListId !== null && lists !== null ? {
1984
+ provider: "brevo",
1985
+ defaultListId,
1986
+ lists
1987
+ } : null;
1988
+ }
1989
+ function parseMailchimpRuntimeProvider(value) {
1990
+ if (!Array.isArray(value.audiences)) return null;
1991
+ const defaultAudienceId = parseMailchimpAudienceId(value.defaultAudienceId);
1992
+ if (defaultAudienceId === null) return null;
1993
+ const audiences = [];
1994
+ for (const audience of value.audiences) {
1995
+ if (!isRecord$21(audience)) return null;
1996
+ const id = parseMailchimpAudienceId(audience.id);
1997
+ const name = parseName(audience.name);
1998
+ if (id === null || name === null || !Array.isArray(audience.interests)) return null;
1999
+ const interests = parseMailchimpInterests(audience.interests);
2000
+ if (interests === null) return null;
2001
+ audiences.push({
2002
+ id,
2003
+ name,
2004
+ interests
2005
+ });
2006
+ }
2007
+ return {
2008
+ provider: "mailchimp",
2009
+ defaultAudienceId,
2010
+ audiences
2011
+ };
2012
+ }
2013
+ function parseMailchimpInterests(value) {
2014
+ const interests = [];
2015
+ for (const interest of value) {
2016
+ if (!isRecord$21(interest)) return null;
2017
+ const id = parseMailchimpInterestId(interest.id);
2018
+ const name = parseName(interest.name);
2019
+ const categoryName = parseName(interest.categoryName);
2020
+ if (id === null || name === null || categoryName === null) return null;
2021
+ interests.push({
2022
+ id,
2023
+ name,
2024
+ categoryName
2025
+ });
2026
+ }
2027
+ return interests;
2028
+ }
2029
+ function parseNamedItems(value, parseId) {
2030
+ if (!Array.isArray(value)) return null;
2031
+ const items = [];
2032
+ for (const item of value) {
2033
+ if (!isRecord$21(item)) return null;
2034
+ const id = parseId(item.id);
2035
+ const name = parseName(item.name);
2036
+ if (id === null || name === null) return null;
2037
+ items.push({
2038
+ id,
2039
+ name
2040
+ });
2041
+ }
2042
+ return items;
2043
+ }
2044
+ function parseName(value) {
2045
+ if (typeof value !== "string") return null;
2046
+ const name = value.trim();
2047
+ return name.length > 0 ? name : null;
2048
+ }
2049
+ function isRecord$21(value) {
2050
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2051
+ }
2052
+ function invalidRuntimeContext() {
2053
+ return err$2({ tag: "invalid_mailing_list_runtime_context" });
2054
+ }
2055
+ var init_mailing_list_runtime = __esmMin((() => {
2056
+ init_mailing_list_identifiers();
2057
+ init_mailing_list_setup_parser();
2058
+ init_result$1();
2059
+ }));
2060
+ //#endregion
2061
+ //#region ../core/src/mailing-list-submission.ts
2062
+ function parseMailingListBlockId(value) {
2063
+ const parsed = typeof value === "string" ? value.trim() : "";
2064
+ 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;
2065
+ }
2066
+ function parseMailingListSignedSourceToken(value) {
2067
+ const parsed = typeof value === "string" ? value.trim() : "";
2068
+ return /^[A-Za-z0-9._~-]{16,1000}$/u.test(parsed) ? parsed : null;
2069
+ }
2070
+ function buildMailingListSignupBlockSourceRef(blockId) {
2071
+ const parsed = parseMailingListBlockId(blockId);
2072
+ return parsed !== null ? {
2073
+ tag: "block_ref",
2074
+ blockId: parsed
2075
+ } : null;
2076
+ }
2077
+ var init_mailing_list_submission = __esmMin((() => {
2078
+ init_branded();
2079
+ }));
1629
2080
  var init_number_input = __esmMin((() => {}));
1630
2081
  var init_field_errors = __esmMin((() => {})), init_form_submission_preview = __esmMin((() => {
1631
2082
  init_string();
@@ -1739,8 +2190,55 @@ function resolveWholeSeriesBookingPhase(run, now) {
1739
2190
  };
1740
2191
  }
1741
2192
  }
1742
- var CANCELLED_SESSION_STATUS, init_whole_series_run_schedule = __esmMin((() => {
2193
+ var CANCELLED_SESSION_STATUS;
2194
+ var init_whole_series_run_schedule = __esmMin((() => {
1743
2195
  CANCELLED_SESSION_STATUS = "cancelled";
2196
+ }));
2197
+ //#endregion
2198
+ //#region ../core/src/public-read-cache-contract.ts
2199
+ function availability(transport) {
2200
+ return {
2201
+ kind: "live",
2202
+ reason: "booking_correctness",
2203
+ freshness: "availability",
2204
+ transport
2205
+ };
2206
+ }
2207
+ function content(tags, transport = "direct") {
2208
+ return {
2209
+ kind: "tagged",
2210
+ tags,
2211
+ freshness: "content",
2212
+ transport
2213
+ };
2214
+ }
2215
+ var PUBLIC_READ_CACHE_POLICIES, init_public_read_cache_contract = __esmMin((() => {
2216
+ PUBLIC_READ_CACHE_POLICIES = {
2217
+ listPublishedEntries: content(["published_content"]),
2218
+ getPublishedEntryPreview: content(["published_content"]),
2219
+ listPublicEvents: availability("direct"),
2220
+ listPublicEventCalendarWindow: availability("direct"),
2221
+ listPublicRecurringSchedule: availability("batch_only"),
2222
+ getPublicEventDetails: availability("batch_only"),
2223
+ resolveEventSubroute: availability("direct"),
2224
+ listPublicRouteCandidates: content(["published_content"], "batch_only"),
2225
+ listPublicTeamMembers: content(["public_team_members"]),
2226
+ listPublicProducts: availability("direct"),
2227
+ listPublicPasses: availability("direct"),
2228
+ listPublicMemberships: availability("direct"),
2229
+ getPublicFormById: content(["site_forms"]),
2230
+ getPublicBookingServices: availability("direct"),
2231
+ getPublicBookingService: availability("direct"),
2232
+ getPublicBookingResourcesReference: availability("direct"),
2233
+ getPublicBookingAvailableDates: availability("direct"),
2234
+ getPublicBookingAvailableSlots: availability("direct"),
2235
+ getPublicWeeklySlotAvailability: availability("direct"),
2236
+ listPublicForms: content(["site_forms"]),
2237
+ checkRedirect: content([]),
2238
+ getPublicRoutableContent: content(["published_content"]),
2239
+ getPublicSitemapRoutes: content(["published_content"])
2240
+ };
2241
+ new Set(Object.keys(PUBLIC_READ_CACHE_POLICIES));
1744
2242
  })), SURFACE_EVENT_PRESET_VALUES;
1745
2243
  var init_event_series_behaviour = __esmMin((() => {
1746
2244
  SURFACE_EVENT_PRESET_VALUES = [
@@ -1951,12 +2449,15 @@ var init_booking_verticals = __esmMin((() => {
1951
2449
  init_booking_vertical_definitions();
1952
2450
  init_booking_vertical_config();
1953
2451
  }));
2452
+ var init_navigation_locations = __esmMin((() => {
2453
+ init_result$1();
2454
+ }));
1954
2455
  //#endregion
1955
2456
  //#region ../core/src/index.ts
1956
2457
  var init_src$2 = __esmMin((() => {
1957
2458
  init_branded();
1958
2459
  init_date_math();
1959
- init_duration();
2460
+ init_duration$1();
1960
2461
  init_demo_capability_policy();
1961
2462
  init_demo_claim_access();
1962
2463
  init_demo_lifecycle_status();
@@ -1977,7 +2478,7 @@ var init_src$2 = __esmMin((() => {
1977
2478
  init_dated_offering_settlement();
1978
2479
  init_person_records();
1979
2480
  init_rectification();
1980
- init_location();
2481
+ init_location$1();
1981
2482
  init_business_address();
1982
2483
  init_result$1();
1983
2484
  init_assert_never();
@@ -1997,7 +2498,13 @@ var init_src$2 = __esmMin((() => {
1997
2498
  init_footer_arrangement();
1998
2499
  init_footer_composition_types();
1999
2500
  init_footer_engagement();
2000
- init_newsletter_signup_destination$1();
2501
+ init_mailing_list_identifiers();
2502
+ init_mailing_list_setup();
2503
+ init_mailing_list_setup_parser();
2504
+ init_mailing_list_targeting();
2505
+ init_mailing_list_runtime();
2506
+ init_mailing_list_targeting_parser();
2507
+ init_mailing_list_submission();
2001
2508
  init_number_input();
2002
2509
  init_field_errors();
2003
2510
  init_form_submission_preview();
@@ -2018,8 +2525,10 @@ var init_src$2 = __esmMin((() => {
2018
2525
  init_planner();
2019
2526
  init_booking_time_zone();
2020
2527
  init_whole_series_run_schedule();
2528
+ init_public_read_cache_contract();
2021
2529
  init_booking_verticals();
2022
2530
  init_event_series_behaviour();
2531
+ init_navigation_locations();
2023
2532
  }));
2024
2533
  var init_types$15 = __esmMin((() => {}));
2025
2534
  //#endregion
@@ -2147,11 +2656,11 @@ var init_storagePathDomain = __esmMin((() => {}));
2147
2656
  var init_fileAssetLegacyProjection = __esmMin((() => {}));
2148
2657
  //#endregion
2149
2658
  //#region ../media-core/src/typeGuards.ts
2150
- function isRecord$20(value) {
2659
+ function isRecord$19(value) {
2151
2660
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2152
2661
  }
2153
2662
  function asRecord$1(value) {
2154
- return isRecord$20(value) ? value : void 0;
2663
+ return isRecord$19(value) ? value : void 0;
2155
2664
  }
2156
2665
  var init_typeGuards$1 = __esmMin((() => {}));
2157
2666
  function isFileJsonObject(value) {
@@ -2161,7 +2670,7 @@ function isFileJsonValue(value) {
2161
2670
  if (value === null || typeof value === "string" || typeof value === "boolean") return true;
2162
2671
  if (typeof value === "number") return Number.isFinite(value);
2163
2672
  if (Array.isArray(value)) return value.every(isFileJsonValue);
2164
- return isRecord$20(value) && isFileJsonObject(value);
2673
+ return isRecord$19(value) && isFileJsonObject(value);
2165
2674
  }
2166
2675
  var init_filePersistence = __esmMin((() => {
2167
2676
  init_src$2();
@@ -2469,7 +2978,7 @@ function isCmsMediaObjectType(value) {
2469
2978
  return typeof value === "string" && CMS_MEDIA_OBJECT_TYPES.includes(value);
2470
2979
  }
2471
2980
  function isCmsMediaObject(value) {
2472
- if (!isRecord$20(value)) return false;
2981
+ if (!isRecord$19(value)) return false;
2473
2982
  const type = value.type;
2474
2983
  if (!isCmsMediaObjectType(type)) return false;
2475
2984
  if ("attrs" in value) return false;
@@ -2480,7 +2989,7 @@ function collectMediaObjects(value, out, location = "") {
2480
2989
  value.forEach((item, index) => collectMediaObjects(item, out, `${location}[${index}]`));
2481
2990
  return;
2482
2991
  }
2483
- if (!isRecord$20(value)) return;
2992
+ if (!isRecord$19(value)) return;
2484
2993
  if (isCmsMediaObject(value)) out.push({
2485
2994
  obj: value,
2486
2995
  location
@@ -2514,8 +3023,8 @@ function walkAndCollectImageAttrs(value, out, location = "") {
2514
3023
  value.forEach((item, index) => walkAndCollectImageAttrs(item, out, `${location}[${index}]`));
2515
3024
  return;
2516
3025
  }
2517
- if (!isRecord$20(value)) return;
2518
- if (value.type === "image" && isRecord$20(value.attrs)) out.push({
3026
+ if (!isRecord$19(value)) return;
3027
+ if (value.type === "image" && isRecord$19(value.attrs)) out.push({
2519
3028
  attrs: value.attrs,
2520
3029
  location: location ? `${location}.attrs` : "attrs"
2521
3030
  });
@@ -2575,7 +3084,7 @@ function mediaIdentifierOrFallback(current, fallback) {
2575
3084
  var init_renderableMediaAsset = __esmMin((() => {}));
2576
3085
  //#endregion
2577
3086
  //#region ../media-core/src/contentMediaAudit.ts
2578
- function isRecord$19(value) {
3087
+ function isRecord$18(value) {
2579
3088
  return typeof value === "object" && value !== null && !Array.isArray(value);
2580
3089
  }
2581
3090
  function summarizeContentMediaValue(value) {
@@ -2586,7 +3095,7 @@ function summarizeContentMediaValue(value) {
2586
3095
  }
2587
3096
  if (value === null) return "null";
2588
3097
  if (Array.isArray(value)) return `array(${value.length})`;
2589
- if (isRecord$19(value)) return `object(${Object.keys(value).sort().join(",")})`;
3098
+ if (isRecord$18(value)) return `object(${Object.keys(value).sort().join(",")})`;
2590
3099
  return typeof value;
2591
3100
  }
2592
3101
  function auditMediaValue(context, path, allowedMediaTypes, value) {
@@ -2610,9 +3119,9 @@ function auditMediaValue(context, path, allowedMediaTypes, value) {
2610
3119
  allowedMediaTypes
2611
3120
  }];
2612
3121
  }
2613
- const hasValidIdentifier = isRecord$19(value) && typeof value.identifier === "string" && value.identifier.trim().length > 0;
2614
- const hasValidExplicitType = isRecord$19(value) && (!("type" in value) || typeof value.type === "string" && allowedMediaTypes.includes(value.type));
2615
- const hasRetiredEnvironmentField = isRecord$19(value) && ("assetId" in value || "storagePath" in value || "storageBucket" in value || "src" in value || "mimeType" in value || looksLikeUuid(value.id));
3122
+ const hasValidIdentifier = isRecord$18(value) && typeof value.identifier === "string" && value.identifier.trim().length > 0;
3123
+ const hasValidExplicitType = isRecord$18(value) && (!("type" in value) || typeof value.type === "string" && allowedMediaTypes.includes(value.type));
3124
+ const hasRetiredEnvironmentField = isRecord$18(value) && ("assetId" in value || "storagePath" in value || "storageBucket" in value || "src" in value || "mimeType" in value || looksLikeUuid(value.id));
2616
3125
  if (hasValidIdentifier && hasValidExplicitType && !hasRetiredEnvironmentField) return [];
2617
3126
  return [{
2618
3127
  tag: "malformed-object",
@@ -2623,7 +3132,7 @@ function auditMediaValue(context, path, allowedMediaTypes, value) {
2623
3132
  }];
2624
3133
  }
2625
3134
  function auditFields(context, fields, value, parentPath) {
2626
- if (!isRecord$19(value)) return [];
3135
+ if (!isRecord$18(value)) return [];
2627
3136
  const findings = [];
2628
3137
  for (const field of fields) {
2629
3138
  if (!(field.id in value)) continue;
@@ -2640,7 +3149,7 @@ function auditFields(context, fields, value, parentPath) {
2640
3149
  if (!Array.isArray(fieldValue)) break;
2641
3150
  for (const [index, item] of fieldValue.entries()) {
2642
3151
  const itemPath = [...fieldPath, index];
2643
- if (!isRecord$19(item)) {
3152
+ if (!isRecord$18(item)) {
2644
3153
  findings.push({
2645
3154
  tag: "missing-schema",
2646
3155
  context,
@@ -2674,7 +3183,7 @@ var init_contentMediaAudit = __esmMin((() => {
2674
3183
  }));
2675
3184
  //#endregion
2676
3185
  //#region ../media-core/src/contentMediaAuditFieldAdapter.ts
2677
- function isRecord$18(value) {
3186
+ function isRecord$17(value) {
2678
3187
  return typeof value === "object" && value !== null && !Array.isArray(value);
2679
3188
  }
2680
3189
  function unknownArray(value) {
@@ -2683,7 +3192,7 @@ function unknownArray(value) {
2683
3192
  function fieldsArray(value) {
2684
3193
  const directFields = unknownArray(value);
2685
3194
  if (directFields) return directFields;
2686
- if (!isRecord$18(value)) return null;
3195
+ if (!isRecord$17(value)) return null;
2687
3196
  return unknownArray(value.fields);
2688
3197
  }
2689
3198
  function nestedFields(field) {
@@ -2748,7 +3257,7 @@ function mergeFields(fields) {
2748
3257
  }
2749
3258
  function adaptFields(rawFields, flattenRepeaterGroups = false, defaultFileKinds = ["document"]) {
2750
3259
  return mergeFields(rawFields.flatMap((rawField) => {
2751
- if (!isRecord$18(rawField)) return [];
3260
+ if (!isRecord$17(rawField)) return [];
2752
3261
  const { id, type } = rawField;
2753
3262
  if (typeof id !== "string" || !id || typeof type !== "string") return [];
2754
3263
  if (type === "media" || type === "file") return [{
@@ -2756,7 +3265,7 @@ function adaptFields(rawFields, flattenRepeaterGroups = false, defaultFileKinds
2756
3265
  id,
2757
3266
  allowedMediaTypes: allowedMediaTypes(rawField, type, defaultFileKinds)
2758
3267
  }];
2759
- if (flattenRepeaterGroups && type === "group" && isRecord$18(rawField.ui) && rawField.ui.flattenInRepeater === true) return adaptFields(nestedFields(rawField), false, defaultFileKinds);
3268
+ if (flattenRepeaterGroups && type === "group" && isRecord$17(rawField.ui) && rawField.ui.flattenInRepeater === true) return adaptFields(nestedFields(rawField), false, defaultFileKinds);
2760
3269
  if (type === "group" || type === "modal") return [{
2761
3270
  kind: "object",
2762
3271
  id,
@@ -2765,14 +3274,14 @@ function adaptFields(rawFields, flattenRepeaterGroups = false, defaultFileKinds
2765
3274
  if (type === "tabGroup") return [{
2766
3275
  kind: "object",
2767
3276
  id,
2768
- fields: adaptFields((unknownArray(rawField.tabs) ?? []).flatMap((tab) => isRecord$18(tab) ? unknownArray(tab.fields) ?? [] : []), false, defaultFileKinds)
3277
+ fields: adaptFields((unknownArray(rawField.tabs) ?? []).flatMap((tab) => isRecord$17(tab) ? unknownArray(tab.fields) ?? [] : []), false, defaultFileKinds)
2769
3278
  }];
2770
3279
  if (type !== "repeater") return [];
2771
- if (isRecord$18(rawField.itemTypes)) return [{
3280
+ if (isRecord$17(rawField.itemTypes)) return [{
2772
3281
  kind: "repeater",
2773
3282
  id,
2774
3283
  mode: "variants",
2775
- variants: Object.entries(rawField.itemTypes).flatMap(([typeId, itemType]) => isRecord$18(itemType) && Array.isArray(itemType.fields) ? [{
3284
+ variants: Object.entries(rawField.itemTypes).flatMap(([typeId, itemType]) => isRecord$17(itemType) && Array.isArray(itemType.fields) ? [{
2776
3285
  typeId,
2777
3286
  fields: adaptFields(itemType.fields, true, defaultFileKinds)
2778
3287
  }] : []),
@@ -7392,7 +7901,7 @@ var init_interactionPalette = __esmMin((() => {
7392
7901
  //#endregion
7393
7902
  //#region ../theme-core/src/boxBackgroundSchema.ts
7394
7903
  function normalizeAuthoringOpacity(value) {
7395
- if (!isRecord$17(value)) return value;
7904
+ if (!isRecord$16(value)) return value;
7396
7905
  return {
7397
7906
  ...value,
7398
7907
  opacity: normalizeOpacity(value.opacity)
@@ -7401,7 +7910,7 @@ function normalizeAuthoringOpacity(value) {
7401
7910
  function normalizeOpacity(value) {
7402
7911
  return typeof value === "number" && value > 1 && value <= 100 ? value / 100 : value;
7403
7912
  }
7404
- function isRecord$17(value) {
7913
+ function isRecord$16(value) {
7405
7914
  return typeof value === "object" && value !== null && !Array.isArray(value);
7406
7915
  }
7407
7916
  var boxBackgroundOverlaySchema, commonSchema, mediaPresentationSchema, boxBackgroundSchema;
@@ -8225,7 +8734,7 @@ var init_media$1 = __esmMin((() => {
8225
8734
  /**
8226
8735
  * Strict record guard: excludes null, primitives, and arrays.
8227
8736
  */
8228
- function isRecord$16(value) {
8737
+ function isRecord$15(value) {
8229
8738
  return typeof value === "object" && value !== null && !Array.isArray(value);
8230
8739
  }
8231
8740
  var init_typeGuards = __esmMin((() => {}));
@@ -9266,7 +9775,7 @@ function encodePublicProductCategorySelector(selector) {
9266
9775
  };
9267
9776
  }
9268
9777
  }
9269
- function isRecord$15(value) {
9778
+ function isRecord$14(value) {
9270
9779
  return typeof value === "object" && value !== null;
9271
9780
  }
9272
9781
  function isJsonResponseContentType(contentType) {
@@ -9290,15 +9799,15 @@ async function parseJsonBody(response) {
9290
9799
  }
9291
9800
  }
9292
9801
  function isFieldError(value) {
9293
- return isRecord$15(value) && !Array.isArray(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
9802
+ return isRecord$14(value) && !Array.isArray(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
9294
9803
  }
9295
9804
  function fieldErrorsFromUnknown(value) {
9296
9805
  if (!Array.isArray(value)) return void 0;
9297
9806
  return value.every(isFieldError) ? value : void 0;
9298
9807
  }
9299
9808
  function getBlockApiErrorDetails(data) {
9300
- if (!isRecord$15(data)) return {};
9301
- const nestedError = isRecord$15(data.error) ? data.error : void 0;
9809
+ if (!isRecord$14(data)) return {};
9810
+ const nestedError = isRecord$14(data.error) ? data.error : void 0;
9302
9811
  const message = typeof nestedError?.message === "string" ? nestedError.message : typeof data.message === "string" ? data.message : void 0;
9303
9812
  const code = typeof nestedError?.code === "string" ? nestedError.code : typeof data.code === "string" ? data.code : void 0;
9304
9813
  const fieldErrors = fieldErrorsFromUnknown(nestedError?.fieldErrors) ?? fieldErrorsFromUnknown(data.fieldErrors);
@@ -9710,8 +10219,9 @@ function createBlockApi(config) {
9710
10219
  name: data.name,
9711
10220
  company: data.company,
9712
10221
  phone: data.phone,
9713
- target: data.target,
9714
- tags: data.tags,
10222
+ sourceRef: data.sourceRef,
10223
+ setupRevision: data.setupRevision,
10224
+ visitorSelection: data.visitorSelection,
9715
10225
  meta: data.meta
9716
10226
  }
9717
10227
  });
@@ -10274,11 +10784,11 @@ var UnsafePathSegmentError = class extends Error {
10274
10784
  function assertSafePathSegments(segments) {
10275
10785
  for (const segment of segments) if (typeof segment === "string" && UNSAFE_PATH_SEGMENTS.has(segment)) throw new UnsafePathSegmentError(segment);
10276
10786
  }
10277
- function isRecord$14(value) {
10787
+ function isRecord$13(value) {
10278
10788
  return typeof value === "object" && value !== null && !Array.isArray(value);
10279
10789
  }
10280
10790
  function isPathContainer(value) {
10281
- return Array.isArray(value) || isRecord$14(value);
10791
+ return Array.isArray(value) || isRecord$13(value);
10282
10792
  }
10283
10793
  function getContainerValue(container, segment) {
10284
10794
  if (typeof segment === "number") return Array.isArray(container) ? container[segment] : void 0;
@@ -13114,7 +13624,7 @@ function parseSiteIconStyleGuideVersionId(value) {
13114
13624
  //#endregion
13115
13625
  //#region ../blocks/src/system/icons/value.ts
13116
13626
  const NO_BLOCK_ICON_VALUE = { kind: "none" };
13117
- function isRecord$13(value) {
13627
+ function isRecord$12(value) {
13118
13628
  return typeof value === "object" && value !== null && !Array.isArray(value);
13119
13629
  }
13120
13630
  function parseBlockIconValue(value) {
@@ -13122,7 +13632,7 @@ function parseBlockIconValue(value) {
13122
13632
  kind: "semantic",
13123
13633
  iconId: value
13124
13634
  };
13125
- if (!isRecord$13(value)) return NO_BLOCK_ICON_VALUE;
13635
+ if (!isRecord$12(value)) return NO_BLOCK_ICON_VALUE;
13126
13636
  switch (value.kind) {
13127
13637
  case "none": return NO_BLOCK_ICON_VALUE;
13128
13638
  case "semantic": return isSemanticIconId(value.iconId) ? {
@@ -13195,7 +13705,7 @@ function buildGeneratedBlockIconRenderAssetLookupFromUnknown(value) {
13195
13705
  if (!Array.isArray(value)) return { kind: "invalid_asset_list" };
13196
13706
  const inputs = [];
13197
13707
  for (const [index, item] of value.entries()) {
13198
- if (!isRecord$13(item)) return {
13708
+ if (!isRecord$12(item)) return {
13199
13709
  kind: "invalid_asset_entry",
13200
13710
  index,
13201
13711
  reason: "not_object"
@@ -13313,11 +13823,11 @@ function resolveFeatureCardGeneratedIconSizePx(value) {
13313
13823
  const parsed = parseFeatureCardGeneratedIconSizePx(value);
13314
13824
  return parsed.ok ? parsed.value : unsafeAsFeatureCardGeneratedIconSizePx(FEATURE_CARD_GENERATED_ICON_SIZE_PX.default);
13315
13825
  }
13316
- function isRecord$12(value) {
13826
+ function isRecord$11(value) {
13317
13827
  return typeof value === "object" && value !== null && !Array.isArray(value);
13318
13828
  }
13319
13829
  function toPlainTextFromTipTap(value) {
13320
- if (!isRecord$12(value)) return "";
13830
+ if (!isRecord$11(value)) return "";
13321
13831
  if (typeof value.text === "string") return value.text;
13322
13832
  const content = value.content;
13323
13833
  if (!Array.isArray(content)) return "";
@@ -14552,6 +15062,268 @@ const SvgNode = ({ blockId: _blockId, blockKind: _blockKind, blockContent: _bloc
14552
15062
  });
14553
15063
  };
14554
15064
  //#endregion
15065
+ //#region ../blocks/src/system/runtime/shared/utils/bookingRoute.ts
15066
+ function resolveDedicatedBookingTarget(pathname) {
15067
+ const internalPublishedMatch = pathname.match(/^\/internal-sites\/([^/]+)\/([^/]+)\/published(?:\/.*)?$/);
15068
+ if (internalPublishedMatch) {
15069
+ const hostKey = internalPublishedMatch[1];
15070
+ const siteIdentifier = internalPublishedMatch[2];
15071
+ if (hostKey && siteIdentifier) return {
15072
+ kind: "internal_published_preview",
15073
+ hostKey,
15074
+ siteIdentifier
15075
+ };
15076
+ }
15077
+ return { kind: "public" };
15078
+ }
15079
+ function resolveDedicatedBookingPath(pathname) {
15080
+ const target = resolveDedicatedBookingTarget(pathname);
15081
+ if (target.kind === "internal_published_preview") return `/internal-sites/${target.hostKey}/${target.siteIdentifier}/published/book`;
15082
+ return "/book";
15083
+ }
15084
+ function resolveDedicatedBookingHref(pathname, bookingTarget = { kind: "chooser" }) {
15085
+ const bookingPath = resolveDedicatedBookingPath(pathname);
15086
+ const params = new URLSearchParams();
15087
+ switch (bookingTarget.kind) {
15088
+ case "chooser": break;
15089
+ case "appointment_service":
15090
+ params.set(BOOK_TARGET_PARAMS.service, bookingTarget.serviceId);
15091
+ if (bookingTarget.resourceId) params.set(BOOK_TARGET_PARAMS.resource, bookingTarget.resourceId);
15092
+ break;
15093
+ case "event_occurrence":
15094
+ params.set(BOOK_TARGET_PARAMS.occurrence, bookingTarget.occurrenceId);
15095
+ break;
15096
+ case "event_series":
15097
+ params.set(BOOK_TARGET_PARAMS.event, bookingTarget.eventId);
15098
+ break;
15099
+ default:
15100
+ }
15101
+ const queryString = params.toString();
15102
+ return queryString ? `${bookingPath}?${queryString}` : bookingPath;
15103
+ }
15104
+ var BOOK_TARGET_PARAMS;
15105
+ var init_bookingRoute = __esmMin((() => {
15106
+ BOOK_TARGET_PARAMS = {
15107
+ service: "service",
15108
+ resource: "resource",
15109
+ occurrence: "occurrence",
15110
+ event: "event"
15111
+ };
15112
+ }));
15113
+ //#endregion
15114
+ //#region ../blocks/src/system/runtime/nodes/appointment-services.tsx
15115
+ init_src$2();
15116
+ init_buttons();
15117
+ init_bookingRoute();
15118
+ const publicVenueSchema = z.object({
15119
+ name: z.string(),
15120
+ area: z.string().nullable()
15121
+ });
15122
+ const publicLocationSchema = z.discriminatedUnion("mode", [
15123
+ z.object({ mode: z.literal("online") }),
15124
+ z.object({
15125
+ mode: z.literal("in_person"),
15126
+ venue: publicVenueSchema.nullable()
15127
+ }),
15128
+ z.object({
15129
+ mode: z.literal("either"),
15130
+ venue: publicVenueSchema.nullable()
15131
+ })
15132
+ ]);
15133
+ const publicPricingOptionSchema = z.object({
15134
+ priceAmount: z.number().finite(),
15135
+ isActive: z.boolean(),
15136
+ saleStartsAt: z.string().nullable(),
15137
+ saleEndsAt: z.string().nullable()
15138
+ });
15139
+ const publicPricingSchema = z.object({
15140
+ pricingStrategy: z.enum([
15141
+ "free",
15142
+ "single",
15143
+ "tiered",
15144
+ "sliding_scale"
15145
+ ]),
15146
+ currency: z.string().min(1),
15147
+ singlePriceAmount: z.number().nullable(),
15148
+ slidingMinAmount: z.number().nullable(),
15149
+ slidingMaxAmount: z.number().nullable(),
15150
+ options: z.array(publicPricingOptionSchema)
15151
+ });
15152
+ const publicAppointmentServiceSchema = z.object({
15153
+ id: z.string().min(1),
15154
+ title: z.string(),
15155
+ description: z.string().nullable().optional(),
15156
+ durationMinutes: z.number().int().positive(),
15157
+ pricing: publicPricingSchema.optional(),
15158
+ priceAmount: z.number().nullable(),
15159
+ priceCurrency: z.string().nullable(),
15160
+ location: publicLocationSchema
15161
+ });
15162
+ const publicAppointmentServicesSchema = z.array(publicAppointmentServiceSchema);
15163
+ const EMPTY_MESSAGE = "No appointments are available right now.";
15164
+ const ERROR_MESSAGE = "Appointments are temporarily unavailable. Please try again shortly.";
15165
+ function parseServices(value) {
15166
+ const result = publicAppointmentServicesSchema.safeParse(value);
15167
+ return result.success ? {
15168
+ kind: "valid",
15169
+ services: result.data
15170
+ } : { kind: "invalid" };
15171
+ }
15172
+ function formatAppointmentDuration(durationMinutes) {
15173
+ return `${durationMinutes} min`;
15174
+ }
15175
+ function formatAppointmentLocation(location) {
15176
+ switch (location.mode) {
15177
+ case "online": return "Online";
15178
+ case "in_person": return formatVenue(location.venue);
15179
+ case "either": {
15180
+ const venue = formatVenue(location.venue);
15181
+ return venue ? `${venue} or online` : "In person or online";
15182
+ }
15183
+ default: return assertNever$22(location);
15184
+ }
15185
+ }
15186
+ function formatVenue(venue) {
15187
+ if (!venue) return null;
15188
+ return venue.area ? `${venue.name}, ${venue.area}` : venue.name;
15189
+ }
15190
+ function formatAppointmentPrice(service) {
15191
+ const pricing = service.pricing;
15192
+ if (pricing) {
15193
+ const display = (() => {
15194
+ switch (pricing.pricingStrategy) {
15195
+ case "free": return {
15196
+ kind: "free",
15197
+ currency: pricing.currency
15198
+ };
15199
+ case "single": return resolveExactOrFreePriceDisplay(pricing.singlePriceAmount, pricing.currency);
15200
+ case "tiered": return resolvePricingOptionsPriceDisplay({
15201
+ options: pricing.options,
15202
+ currency: pricing.currency,
15203
+ purpose: "available_now"
15204
+ });
15205
+ case "sliding_scale": return pricing.slidingMinAmount === null || pricing.slidingMaxAmount === null ? {
15206
+ kind: "unavailable",
15207
+ currency: pricing.currency
15208
+ } : {
15209
+ kind: "range",
15210
+ minAmount: pricing.slidingMinAmount,
15211
+ maxAmount: pricing.slidingMaxAmount,
15212
+ currency: pricing.currency
15213
+ };
15214
+ default: return assertNever$22(pricing.pricingStrategy);
15215
+ }
15216
+ })();
15217
+ return display.kind === "unavailable" ? null : formatBookingPriceDisplay(display, { decimals: "auto" });
15218
+ }
15219
+ return formatAmountOrFree(service.priceAmount, service.priceCurrency);
15220
+ }
15221
+ function formatAmountOrFree(amount, currency) {
15222
+ if (amount === null || currency === null) return null;
15223
+ if (amount === 0) return "Free";
15224
+ return formatBookingPriceDisplay({
15225
+ kind: "exact",
15226
+ amount,
15227
+ currency
15228
+ }, { decimals: "auto" });
15229
+ }
15230
+ function buildRows(services, pathname) {
15231
+ return services.map((service) => ({
15232
+ id: service.id,
15233
+ title: service.title,
15234
+ description: service.description ?? null,
15235
+ durationLabel: formatAppointmentDuration(service.durationMinutes),
15236
+ locationLabel: formatAppointmentLocation(service.location),
15237
+ priceLabel: formatAppointmentPrice(service),
15238
+ href: resolveDedicatedBookingHref(pathname, {
15239
+ kind: "appointment_service",
15240
+ serviceId: service.id
15241
+ })
15242
+ }));
15243
+ }
15244
+ function buildAppointmentServicesView(input) {
15245
+ if (!input.pathname) return {
15246
+ kind: "error",
15247
+ message: ERROR_MESSAGE
15248
+ };
15249
+ const parsed = parseServices(input.services);
15250
+ if (parsed.kind === "invalid") return {
15251
+ kind: "error",
15252
+ message: ERROR_MESSAGE
15253
+ };
15254
+ if (parsed.services.length === 0) return {
15255
+ kind: "empty",
15256
+ message: EMPTY_MESSAGE
15257
+ };
15258
+ return {
15259
+ kind: "items",
15260
+ rows: buildRows(parsed.services, input.pathname)
15261
+ };
15262
+ }
15263
+ function AppointmentServicesNode({ sectionHeading, services, pathname, className }) {
15264
+ const view = buildAppointmentServicesView({
15265
+ services,
15266
+ pathname: typeof pathname === "string" ? pathname : void 0
15267
+ });
15268
+ const rootClassName = `appointment-services ${className ?? ""}`.trim();
15269
+ const RowTitle = sectionHeading ? "h3" : "h2";
15270
+ if (view.kind === "error" || view.kind === "empty") return /* @__PURE__ */ jsx("div", {
15271
+ className: rootClassName,
15272
+ "data-appointment-services-state": view.kind,
15273
+ children: /* @__PURE__ */ jsx("p", {
15274
+ className: "rb-caption status-muted",
15275
+ role: "status",
15276
+ children: view.message
15277
+ })
15278
+ });
15279
+ const actionClassName = themeButtonClassName({
15280
+ variant: "secondary",
15281
+ size: "sm",
15282
+ extraClassName: "appointment-services-row-action"
15283
+ });
15284
+ return /* @__PURE__ */ jsx("div", {
15285
+ className: `${rootClassName} rb-flex rb-flex-col`,
15286
+ "data-appointment-services-state": "populated",
15287
+ children: /* @__PURE__ */ jsx("div", {
15288
+ className: "appointment-services-rows rb-flex rb-flex-col",
15289
+ children: view.rows.map((row) => /* @__PURE__ */ jsxs("article", {
15290
+ className: "appointment-services-row rb-border-b rb-border-border rb-py-4",
15291
+ children: [
15292
+ /* @__PURE__ */ jsxs("div", {
15293
+ className: "appointment-services-row-main rb-min-w-0",
15294
+ children: [
15295
+ /* @__PURE__ */ jsx(RowTitle, {
15296
+ className: "appointment-services-row-title rb-text-lg rb-font-medium rb-leading-tight",
15297
+ children: row.title
15298
+ }),
15299
+ row.description ? /* @__PURE__ */ jsx("p", {
15300
+ className: "appointment-services-row-description rb-text-sm rb-leading-6 status-muted",
15301
+ children: row.description
15302
+ }) : null,
15303
+ /* @__PURE__ */ jsxs("p", {
15304
+ className: "appointment-services-row-meta rb-caption status-muted",
15305
+ children: [row.durationLabel, row.locationLabel ? ` · ${row.locationLabel}` : ""]
15306
+ })
15307
+ ]
15308
+ }),
15309
+ row.priceLabel ? /* @__PURE__ */ jsx("span", {
15310
+ className: "appointment-services-row-price rb-text-lg",
15311
+ children: row.priceLabel
15312
+ }) : null,
15313
+ /* @__PURE__ */ jsxs("a", {
15314
+ className: actionClassName,
15315
+ href: row.href,
15316
+ children: ["Check times", /* @__PURE__ */ jsxs("span", {
15317
+ className: "rb-sr-only",
15318
+ children: [" for ", row.title]
15319
+ })]
15320
+ })
15321
+ ]
15322
+ }, row.id))
15323
+ })
15324
+ });
15325
+ }
15326
+ //#endregion
14555
15327
  //#region ../blocks/src/contracts/runtime.ts
14556
15328
  function decodeSuccess(value) {
14557
15329
  return {
@@ -14718,7 +15490,7 @@ function successSubmissionFeedback(message) {
14718
15490
  message
14719
15491
  };
14720
15492
  }
14721
- function isRecord$10(value) {
15493
+ function isRecord$9(value) {
14722
15494
  return typeof value === "object" && value !== null && !Array.isArray(value);
14723
15495
  }
14724
15496
  function deepEqualJsonValue(left, right) {
@@ -14728,8 +15500,8 @@ function deepEqualJsonValue(left, right) {
14728
15500
  if (left.length !== right.length) return false;
14729
15501
  return left.every((item, index) => deepEqualJsonValue(item, right[index]));
14730
15502
  }
14731
- if (isRecord$10(left) || isRecord$10(right)) {
14732
- if (!isRecord$10(left) || !isRecord$10(right)) return false;
15503
+ if (isRecord$9(left) || isRecord$9(right)) {
15504
+ if (!isRecord$9(left) || !isRecord$9(right)) return false;
14733
15505
  const leftKeys = Object.keys(left).sort();
14734
15506
  if (!deepEqualJsonValue(leftKeys, Object.keys(right).sort())) return false;
14735
15507
  return leftKeys.every((key) => deepEqualJsonValue(left[key], right[key]));
@@ -14911,12 +15683,12 @@ function resolveBookingSiteId(siteId, form) {
14911
15683
  return siteId || form?.siteId || "";
14912
15684
  }
14913
15685
  function normalizeBookingFormConfig(form) {
14914
- if (!isRecord$9(form)) return null;
15686
+ if (!isRecord$8(form)) return null;
14915
15687
  const id = readNonEmptyString(form.id);
14916
15688
  const name = readNonEmptyString(form.name);
14917
15689
  if (!id || !name) return null;
14918
- const schemaSource = isRecord$9(form.schema) ? form.schema : isRecord$9(form.schemaJson) ? form.schemaJson : null;
14919
- const settingsSource = isRecord$9(form.settings) ? form.settings : isRecord$9(form.settingsJson) ? form.settingsJson : null;
15690
+ const schemaSource = isRecord$8(form.schema) ? form.schema : isRecord$8(form.schemaJson) ? form.schemaJson : null;
15691
+ const settingsSource = isRecord$8(form.settings) ? form.settings : isRecord$8(form.settingsJson) ? form.settingsJson : null;
14920
15692
  return {
14921
15693
  id,
14922
15694
  name,
@@ -14936,8 +15708,8 @@ function normalizeBookingServices(services) {
14936
15708
  };
14937
15709
  if (!services) return [];
14938
15710
  if (Array.isArray(services)) return services.filter(isBookingFormService).map(normalizeService);
14939
- if (isRecord$9(services) && "services" in services) return Array.isArray(services.services) ? services.services.filter(isBookingFormService).map(normalizeService) : [];
14940
- return isRecord$9(services) ? Object.values(services).filter(isBookingFormService).map(normalizeService) : [];
15711
+ if (isRecord$8(services) && "services" in services) return Array.isArray(services.services) ? services.services.filter(isBookingFormService).map(normalizeService) : [];
15712
+ return isRecord$8(services) ? Object.values(services).filter(isBookingFormService).map(normalizeService) : [];
14941
15713
  }
14942
15714
  function normalizeBookingSchema(value) {
14943
15715
  if (!value) return void 0;
@@ -14948,7 +15720,7 @@ function normalizeBookingSchema(value) {
14948
15720
  };
14949
15721
  }
14950
15722
  function readBookingFormField(value) {
14951
- if (!isRecord$9(value)) return null;
15723
+ if (!isRecord$8(value)) return null;
14952
15724
  const id = readNonEmptyString(value.id);
14953
15725
  const label = readNonEmptyString(value.label);
14954
15726
  const type = readBookingFieldType(value.type);
@@ -14991,7 +15763,7 @@ function readBookingFieldOptions(value) {
14991
15763
  return options.length > 0 ? options : void 0;
14992
15764
  }
14993
15765
  function readBookingFieldOption(value) {
14994
- if (!isRecord$9(value)) return null;
15766
+ if (!isRecord$8(value)) return null;
14995
15767
  const optionValue = readNonEmptyString(value.value);
14996
15768
  const label = readNonEmptyString(value.label);
14997
15769
  return optionValue && label ? {
@@ -15011,7 +15783,7 @@ function normalizeBookingSettings(value) {
15011
15783
  };
15012
15784
  }
15013
15785
  function isBookingFormService(value) {
15014
- return isRecord$9(value) && typeof value.id === "string" && typeof value.siteId === "string" && typeof value.title === "string" && (value.consent === void 0 || blockBookingConsentSchema.safeParse(value.consent).success);
15786
+ return isRecord$8(value) && typeof value.id === "string" && typeof value.siteId === "string" && typeof value.title === "string" && (value.consent === void 0 || blockBookingConsentSchema.safeParse(value.consent).success);
15015
15787
  }
15016
15788
  function collectBookingCustomFields(data) {
15017
15789
  const customFields = {};
@@ -15061,7 +15833,7 @@ function readStringArray(value) {
15061
15833
  const strings = value.filter((item) => typeof item === "string");
15062
15834
  return strings.length > 0 ? strings : void 0;
15063
15835
  }
15064
- function isRecord$9(value) {
15836
+ function isRecord$8(value) {
15065
15837
  return typeof value === "object" && value !== null;
15066
15838
  }
15067
15839
  function getBookingServicePaymentSelectionMode(service) {
@@ -16218,12 +16990,29 @@ var init_capacity = __esmMin((() => {
16218
16990
  PLACES_AVAILABLE = "Places available";
16219
16991
  }));
16220
16992
  //#endregion
16993
+ //#region ../blocks/src/system/runtime/nodes/events/domain/bookability.ts
16994
+ /**
16995
+ * Whether a public event has a registration path a visitor can take.
16996
+ *
16997
+ * Lifecycle admission comes from the public booking-availability contract;
16998
+ * capacity comes from the shared event-domain helpers so uncapped, fallback,
16999
+ * and hybrid attendance-mode cases agree with the registration runtime.
17000
+ */
17001
+ function isBookableEvent(event) {
17002
+ if (!event.requiresRegistration) return false;
17003
+ if (event.bookingAvailability.kind !== "open") return false;
17004
+ return !isEventFull(event) || canJoinEventWaitlistOnAnyMode(event);
17005
+ }
17006
+ var init_bookability = __esmMin((() => {
17007
+ init_capacity();
17008
+ }));
17009
+ //#endregion
16221
17010
  //#region ../blocks/src/system/runtime/nodes/events/domain/destination.ts
16222
- function isRecord$8(value) {
17011
+ function isRecord$7(value) {
16223
17012
  return typeof value === "object" && value !== null && !Array.isArray(value);
16224
17013
  }
16225
17014
  function isRuntimeEventDestination(value) {
16226
- if (!isRecord$8(value) || typeof value.kind !== "string") return false;
17015
+ if (!isRecord$7(value) || typeof value.kind !== "string") return false;
16227
17016
  if (value.kind === "native") return (value.mode === "cms-managed" || value.mode === "system-managed") && typeof value.path === "string";
16228
17017
  return value.kind === "external" && typeof value.url === "string" && typeof value.label === "string";
16229
17018
  }
@@ -16315,6 +17104,10 @@ var init_cta = __esmMin((() => {
16315
17104
  }));
16316
17105
  //#endregion
16317
17106
  //#region ../blocks/src/system/runtime/nodes/events/domain/dates.ts
17107
+ /** Use the event timezone when present, otherwise the calendar/site timezone. */
17108
+ function resolveEventTimeZone(event, calendarTimeZone) {
17109
+ return event.timeZone || calendarTimeZone;
17110
+ }
16318
17111
  /**
16319
17112
  * Format date for display.
16320
17113
  * Returns: "Monday, January 15, 2025"
@@ -16389,6 +17182,20 @@ function formatEventCompactDateRail(isoTimestamp, options) {
16389
17182
  };
16390
17183
  }
16391
17184
  /**
17185
+ * Format the next occurrence for the image-free catalogue card treatment.
17186
+ *
17187
+ * The compact rail already owns this short, booking-local date vocabulary;
17188
+ * keep the fact panel on the same date and timezone rules as event rows.
17189
+ */
17190
+ function formatEventNextDateFact(event) {
17191
+ const rail = formatEventCompactDateRail(event.startsAt, { timeZone: event.timeZone });
17192
+ return {
17193
+ dateTime: event.startsAt,
17194
+ value: `${rail.weekday} ${rail.day} ${rail.month}`,
17195
+ label: rail.label
17196
+ };
17197
+ }
17198
+ /**
16392
17199
  * Group events by their local date (YYYY-MM-DD key in each event's own
16393
17200
  * timezone). Thin domain wrapper over `groupItemsByDate` from the calendar
16394
17201
  * package; preserves the historical `Map<string, PublicEvent[]>` shape.
@@ -16407,6 +17214,24 @@ var init_dates = __esmMin((() => {
16407
17214
  init_src$3();
16408
17215
  }));
16409
17216
  //#endregion
17217
+ //#region ../blocks/src/system/runtime/nodes/events/domain/duration.ts
17218
+ function formatEventDuration(event) {
17219
+ const durationMinutes = Math.max(0, Math.round((Date.parse(event.endsAt) - Date.parse(event.startsAt)) / 6e4));
17220
+ if (durationMinutes < 120 || durationMinutes % 60 !== 0) return `${durationMinutes} min`;
17221
+ return `${durationMinutes / 60} hrs`;
17222
+ }
17223
+ var init_duration = __esmMin((() => {}));
17224
+ //#endregion
17225
+ //#region ../blocks/src/system/runtime/nodes/events/domain/location.ts
17226
+ function formatEventLocation(event) {
17227
+ switch (event.deliveryMode) {
17228
+ case "online": return "Online";
17229
+ case "hybrid": return event.venue ? `${event.venue.name} + online` : "Hybrid";
17230
+ case "in_person": return event.venue?.name ?? "In person";
17231
+ }
17232
+ }
17233
+ var init_location = __esmMin((() => {}));
17234
+ //#endregion
16410
17235
  //#region ../blocks/src/system/runtime/nodes/events/domain/people.ts
16411
17236
  function formatTeamMemberNames(names) {
16412
17237
  const normalized = names.map((name) => name.trim()).filter(Boolean);
@@ -16424,14 +17249,57 @@ function formatEventTeacherLine(event) {
16424
17249
  }
16425
17250
  var init_people = __esmMin((() => {}));
16426
17251
  //#endregion
17252
+ //#region ../blocks/src/system/runtime/nodes/events/domain/quickDates.ts
17253
+ /**
17254
+ * Select the next occurrence-targeted events for a quick-book rail.
17255
+ *
17256
+ * The API normally returns valid timestamps, but malformed values sort after
17257
+ * valid events so one bad record cannot displace an otherwise useful rail.
17258
+ * Sorting before deduplication means a duplicate occurrence keeps its earliest
17259
+ * deterministic representation.
17260
+ */
17261
+ function selectQuickDateEvents(events) {
17262
+ const sorted = [...events].filter((event) => event.bookingScope !== "whole_series" && isBookableEvent(event)).sort(compareQuickDateEvents);
17263
+ const seenOccurrenceIds = /* @__PURE__ */ new Set();
17264
+ return sorted.filter((event) => {
17265
+ if (seenOccurrenceIds.has(event.occurrenceId)) return false;
17266
+ seenOccurrenceIds.add(event.occurrenceId);
17267
+ return true;
17268
+ }).slice(0, 4);
17269
+ }
17270
+ function formatEventQuickDate(event) {
17271
+ const dateRail = formatEventCompactDateRail(event.startsAt, { timeZone: event.timeZone });
17272
+ return {
17273
+ dateTime: event.startsAt,
17274
+ label: `${dateRail.weekday} ${dateRail.day} ${dateRail.month} · ${formatTime$2(event.startsAt, { timeZone: event.timeZone })}`
17275
+ };
17276
+ }
17277
+ function compareQuickDateEvents(left, right) {
17278
+ const startsAtOrder = compareTimestamp(left.startsAt, right.startsAt);
17279
+ return startsAtOrder === 0 ? left.occurrenceId.localeCompare(right.occurrenceId) : startsAtOrder;
17280
+ }
17281
+ function compareTimestamp(left, right) {
17282
+ const leftTime = Date.parse(left);
17283
+ const rightTime = Date.parse(right);
17284
+ return (Number.isNaN(leftTime) ? Number.POSITIVE_INFINITY : leftTime) - (Number.isNaN(rightTime) ? Number.POSITIVE_INFINITY : rightTime);
17285
+ }
17286
+ var init_quickDates = __esmMin((() => {
17287
+ init_dates();
17288
+ init_bookability();
17289
+ }));
17290
+ //#endregion
16427
17291
  //#region ../blocks/src/system/runtime/nodes/events/domain/index.ts
16428
17292
  var init_domain = __esmMin((() => {
16429
17293
  init_capacity();
17294
+ init_bookability();
16430
17295
  init_cta();
16431
17296
  init_dates();
16432
17297
  init_destination();
17298
+ init_duration();
17299
+ init_location();
16433
17300
  init_people();
16434
17301
  init_pricing();
17302
+ init_quickDates();
16435
17303
  }));
16436
17304
  //#endregion
16437
17305
  //#region ../blocks/src/system/runtime/nodes/events/shared/DateTimeTile.tsx
@@ -17222,6 +18090,18 @@ var init_EventCardIcons = __esmMin((() => {}));
17222
18090
  //#endregion
17223
18091
  //#region ../blocks/src/system/runtime/nodes/events/shared/EventCard.tsx
17224
18092
  function EventCardMedia(props) {
18093
+ if (props.dateFact) return /* @__PURE__ */ jsxs("div", {
18094
+ className: "card-media event-card-media event-card-date-fallback",
18095
+ children: [/* @__PURE__ */ jsx("span", {
18096
+ className: "event-card-date-fallback-label",
18097
+ children: "Next"
18098
+ }), /* @__PURE__ */ jsx("time", {
18099
+ className: "event-card-date-fallback-value",
18100
+ dateTime: props.dateFact.dateTime,
18101
+ "aria-label": props.dateFact.label,
18102
+ children: props.dateFact.value
18103
+ })]
18104
+ });
17225
18105
  if (!props.hasImage || !props.image) return null;
17226
18106
  return /* @__PURE__ */ jsxs("div", {
17227
18107
  className: "card-media event-card-media",
@@ -17246,6 +18126,7 @@ function EventCardMedia(props) {
17246
18126
  }
17247
18127
  function EventCardContent(props) {
17248
18128
  const { event } = props;
18129
+ const Heading = props.headingLevel === 4 ? "h4" : "h3";
17249
18130
  return /* @__PURE__ */ jsxs("div", {
17250
18131
  className: "card-content rb-flex rb-flex-1 rb-flex-col",
17251
18132
  children: [
@@ -17255,7 +18136,7 @@ function EventCardContent(props) {
17255
18136
  style: props.categoryBadge.style,
17256
18137
  children: props.categoryBadge.label
17257
18138
  }),
17258
- /* @__PURE__ */ jsx("h3", {
18139
+ /* @__PURE__ */ jsx(Heading, {
17259
18140
  className: "card-title rb-mb-3",
17260
18141
  children: /* @__PURE__ */ jsx("a", {
17261
18142
  className: "event-title-link",
@@ -17291,7 +18172,8 @@ function EventCardContent(props) {
17291
18172
  /* @__PURE__ */ jsx(EventCardFooter, {
17292
18173
  buttonClass: props.buttonClass,
17293
18174
  capacityText: props.capacityText,
17294
- cta: props.cta
18175
+ cta: props.cta,
18176
+ priceText: props.priceText
17295
18177
  })
17296
18178
  ]
17297
18179
  });
@@ -17314,6 +18196,10 @@ function EventCardFooter(props) {
17314
18196
  return /* @__PURE__ */ jsxs("div", {
17315
18197
  className: "event-card-footer rb-mt-auto rb-pt-4 rb-flex rb-flex-col rb-gap-3",
17316
18198
  children: [
18199
+ props.priceText && /* @__PURE__ */ jsx("p", {
18200
+ className: "event-card-price rb-caption",
18201
+ children: props.priceText
18202
+ }),
17317
18203
  props.capacityText && /* @__PURE__ */ jsx("p", {
17318
18204
  className: "event-card-capacity rb-caption status-muted rb-text-center",
17319
18205
  children: props.capacityText
@@ -17332,6 +18218,21 @@ function EventCardFooter(props) {
17332
18218
  ]
17333
18219
  });
17334
18220
  }
18221
+ function resolveEventCardOptions(props) {
18222
+ const presentation = props.presentation ?? "default";
18223
+ return {
18224
+ presentation,
18225
+ presentationClass: presentation === "catalogue" ? " event-card--catalogue" : "",
18226
+ headingLevel: props.headingLevel ?? 3
18227
+ };
18228
+ }
18229
+ function resolveEventCardDateFact(props) {
18230
+ if (!props.showImage || props.image || props.presentation !== "catalogue") return null;
18231
+ return formatEventNextDateFact(props.event);
18232
+ }
18233
+ function resolveEventCardPrice(event, presentation) {
18234
+ return presentation === "catalogue" ? formatEventPrice(event) : null;
18235
+ }
17335
18236
  function eventCardOrientationClass(orientation) {
17336
18237
  switch (orientation) {
17337
18238
  case "horizontal": return "event-card--horizontal";
@@ -17369,7 +18270,11 @@ var init_EventCard = __esmMin((() => {
17369
18270
  init_EventCardIcons();
17370
18271
  init_domain();
17371
18272
  init_buttons();
17372
- EventCard = ({ event, cardRole = "default", buttonVariant = "primary", buttonText, showVenue = true, showMap = true, mapSlot, allowMap = true, showCapacity = true, showImage = true, showCategory = true, showSummary = true, orientation = "vertical" }) => {
18273
+ EventCard = ({ event, cardRole = "default", buttonVariant = "primary", buttonText, showVenue = true, showMap = true, mapSlot, allowMap = true, showCapacity = true, showImage = true, showCategory = true, showSummary = true, orientation = "vertical", presentation, headingLevel }) => {
18274
+ const { presentation: cardPresentation, presentationClass, headingLevel: cardHeadingLevel } = resolveEventCardOptions({
18275
+ presentation,
18276
+ headingLevel
18277
+ });
17373
18278
  const timeZone = event.timeZone ?? null;
17374
18279
  const formattedDate = formatDate$2(event.startsAt, { timeZone });
17375
18280
  const formattedTime = `${formatTime$2(event.startsAt, { timeZone })} - ${formatTime$2(event.endsAt, { timeZone })}`;
@@ -17388,14 +18293,22 @@ var init_EventCard = __esmMin((() => {
17388
18293
  style: getCategoryBadgeStyle(category.color ?? null)
17389
18294
  } : null;
17390
18295
  const hasImage = Boolean(showImage && image);
18296
+ const dateFact = resolveEventCardDateFact({
18297
+ event,
18298
+ image,
18299
+ presentation: cardPresentation,
18300
+ showImage
18301
+ });
18302
+ const priceText = resolveEventCardPrice(event, cardPresentation);
17391
18303
  const teacherLine = formatEventTeacherLine(event);
17392
18304
  const capacityText = showCapacity ? formatEventRemainingPlaces(event, { full: "Sold out" }) : null;
17393
18305
  return /* @__PURE__ */ jsxs("article", {
17394
- className: `${cardClass} group rb-flex rb-flex-col rb-h-full ${eventCardOrientationClass(orientation)}`,
18306
+ className: `${cardClass} group rb-flex rb-flex-col rb-h-full ${eventCardOrientationClass(orientation)}${presentationClass}`,
17395
18307
  "data-orientation": orientation,
17396
18308
  children: [/* @__PURE__ */ jsx(EventCardMedia, {
17397
18309
  categoryBadge,
17398
18310
  categoryId: category?.id,
18311
+ dateFact,
17399
18312
  hasImage,
17400
18313
  image
17401
18314
  }), /* @__PURE__ */ jsx(EventCardContent, {
@@ -17409,7 +18322,9 @@ var init_EventCard = __esmMin((() => {
17409
18322
  formattedDate,
17410
18323
  formattedTime,
17411
18324
  hasImage,
18325
+ headingLevel: cardHeadingLevel,
17412
18326
  mapSlot,
18327
+ priceText,
17413
18328
  showMap,
17414
18329
  showSummary,
17415
18330
  showVenue,
@@ -17515,6 +18430,94 @@ var init_EventCompactRow = __esmMin((() => {
17515
18430
  };
17516
18431
  }));
17517
18432
  //#endregion
18433
+ //#region ../blocks/src/system/runtime/nodes/events/shared/EventQuickDates.tsx
18434
+ /**
18435
+ * Render a bounded rail of direct occurrence booking choices.
18436
+ *
18437
+ * The heading belongs to this runtime component so it stays with the
18438
+ * bounded rail. Native events target the occurrence booking route while
18439
+ * external events retain their canonical destination and target behaviour.
18440
+ */
18441
+ function EventQuickDates({ events, pathname, buttonVariant = "primary" }) {
18442
+ const quickDateEvents = selectQuickDateEvents(events);
18443
+ if (quickDateEvents.length === 0) return null;
18444
+ return /* @__PURE__ */ jsxs("div", {
18445
+ className: "event-quick-dates rb-flex rb-flex-col rb-gap-4",
18446
+ "data-event-quick-dates": "true",
18447
+ children: [/* @__PURE__ */ jsx("h2", {
18448
+ className: "event-quick-dates-heading",
18449
+ children: "Next few dates"
18450
+ }), /* @__PURE__ */ jsx("div", {
18451
+ className: "event-quick-dates-rail rb-overflow-x-auto rb-flex rb-gap-4",
18452
+ children: quickDateEvents.map((event) => /* @__PURE__ */ jsx(EventQuickDateCard, {
18453
+ event,
18454
+ pathname,
18455
+ buttonVariant
18456
+ }, event.occurrenceId))
18457
+ })]
18458
+ });
18459
+ }
18460
+ function EventQuickDateCard(props) {
18461
+ const { event } = props;
18462
+ const date = formatEventQuickDate(event);
18463
+ const cta = resolveEventCta(event);
18464
+ const ctaHref = resolveRuntimeEventDestination(event).kind === "external" ? cta.href : resolveDedicatedBookingHref(props.pathname, {
18465
+ kind: "event_occurrence",
18466
+ occurrenceId: event.occurrenceId
18467
+ });
18468
+ const buttonClass = themeButtonClassName({
18469
+ variant: props.buttonVariant,
18470
+ size: "sm"
18471
+ });
18472
+ const quickDateLabel = `${event.title}, ${date.label}`;
18473
+ return /* @__PURE__ */ jsxs("article", {
18474
+ className: "event-quick-date rb-flex rb-min-w-12rem rb-shrink-0 rb-flex-col rb-gap-3 rb-rounded-lg rb-border rb-bg-surface rb-p-4",
18475
+ children: [
18476
+ /* @__PURE__ */ jsx("time", {
18477
+ className: "event-quick-date-when",
18478
+ dateTime: date.dateTime,
18479
+ "aria-label": date.label,
18480
+ children: date.label
18481
+ }),
18482
+ /* @__PURE__ */ jsx("h3", {
18483
+ className: "event-quick-date-title",
18484
+ children: /* @__PURE__ */ jsx("a", {
18485
+ className: "event-title-link",
18486
+ ...resolveEventLinkProps(event),
18487
+ children: event.title
18488
+ })
18489
+ }),
18490
+ /* @__PURE__ */ jsxs("p", {
18491
+ className: "event-quick-date-meta status-muted",
18492
+ children: [
18493
+ formatEventLocation(event),
18494
+ " · ",
18495
+ formatEventDuration(event)
18496
+ ]
18497
+ }),
18498
+ /* @__PURE__ */ jsxs("div", {
18499
+ className: "event-quick-date-footer rb-mt-auto rb-flex rb-items-center rb-justify-between rb-gap-3",
18500
+ children: [/* @__PURE__ */ jsx("span", {
18501
+ className: "event-quick-date-price",
18502
+ children: formatEventPrice(event)
18503
+ }), /* @__PURE__ */ jsx("a", {
18504
+ className: `${buttonClass} event-quick-date-cta`,
18505
+ href: ctaHref,
18506
+ target: cta.external ? "_blank" : void 0,
18507
+ rel: cta.external ? "noopener noreferrer" : void 0,
18508
+ "aria-label": `${cta.label} ${quickDateLabel}`,
18509
+ children: cta.label
18510
+ })]
18511
+ })
18512
+ ]
18513
+ });
18514
+ }
18515
+ var init_EventQuickDates = __esmMin((() => {
18516
+ init_buttons();
18517
+ init_bookingRoute();
18518
+ init_domain();
18519
+ }));
18520
+ //#endregion
17518
18521
  //#region ../blocks/src/system/runtime/nodes/events/shared/EmptyState.tsx
17519
18522
  var EmptyState;
17520
18523
  var init_EmptyState = __esmMin((() => {
@@ -17534,6 +18537,18 @@ var init_EmptyState = __esmMin((() => {
17534
18537
  };
17535
18538
  }));
17536
18539
  //#endregion
18540
+ //#region ../blocks/src/system/runtime/nodes/events/shared/CalendarDayHeaders.tsx
18541
+ function CalendarDayHeaders({ dayNames }) {
18542
+ return /* @__PURE__ */ jsx("div", {
18543
+ className: "event-calendar-day-headers",
18544
+ children: dayNames.map((day) => /* @__PURE__ */ jsx("div", {
18545
+ className: "event-calendar-day-header",
18546
+ children: day
18547
+ }, day))
18548
+ });
18549
+ }
18550
+ var init_CalendarDayHeaders = __esmMin((() => {}));
18551
+ //#endregion
17537
18552
  //#region ../blocks/src/system/runtime/nodes/events/shared/OfferingTitle.tsx
17538
18553
  /**
17539
18554
  * Heading for an offering card or row. Links to the offering's page when one
@@ -17558,8 +18573,10 @@ var init_shared$3 = __esmMin((() => {
17558
18573
  init_listingLayout();
17559
18574
  init_EventCard();
17560
18575
  init_EventCompactRow();
18576
+ init_EventQuickDates();
17561
18577
  init_EmptyState();
17562
18578
  init_DateTimeTile();
18579
+ init_CalendarDayHeaders();
17563
18580
  init_OfferingTitle();
17564
18581
  }));
17565
18582
  //#endregion
@@ -19331,16 +20348,7 @@ const EventCombinedSSR = ({ blockId, ...source }) => {
19331
20348
  });
19332
20349
  };
19333
20350
  //#endregion
19334
- //#region ../blocks/src/system/transforms/registry/_utils/themeColorResolution.ts
19335
- function resolveBackgroundColorValue(value, context) {
19336
- return resolveThemeColorReferenceValue(value, { palette: context.theme?.palette });
19337
- }
19338
- var init_themeColorResolution = __esmMin((() => {
19339
- init_tokenOrColor();
19340
- }));
19341
- //#endregion
19342
20351
  //#region ../blocks/src/system/blocks/offerings-preview/model.ts
19343
- init_themeColorResolution();
19344
20352
  init_src$2();
19345
20353
  const OFFERINGS_PREVIEW_EVENT_PRESET_DEFINITIONS = [
19346
20354
  {
@@ -19609,7 +20617,169 @@ function normalizeTextOverride(value) {
19609
20617
  return trimmed.length > 0 ? trimmed : null;
19610
20618
  }
19611
20619
  //#endregion
20620
+ //#region ../blocks/src/system/blocks/offerings-preview/catalogue.ts
20621
+ init_src$2();
20622
+ /** Rows arrive representative-grained from the existing public event reader. */
20623
+ function buildOfferingsCatalogueState(input) {
20624
+ if (!input.events) return { kind: "failed" };
20625
+ const events = input.events;
20626
+ const groups = resolveOfferingsPreviewGroups({ presets: input.presets }).map((group) => ({
20627
+ group,
20628
+ events: events.filter((event) => matchesGroup(group, event))
20629
+ })).filter((group) => group.events.length > 0);
20630
+ return groups.length ? {
20631
+ kind: "groups",
20632
+ groups
20633
+ } : { kind: "empty" };
20634
+ }
20635
+ function matchesGroup(group, event) {
20636
+ const source = group.source;
20637
+ switch (source.kind) {
20638
+ case "eventPreset": return event.bookingScope === "single_occurrence" && event.eventPreset === source.preset;
20639
+ case "wholeSeries": return event.bookingScope === "whole_series";
20640
+ default: return assertNever$22(source);
20641
+ }
20642
+ }
20643
+ //#endregion
20644
+ //#region ../blocks/src/system/runtime/nodes/offerings-preview-catalogue.tsx
20645
+ init_shared$3();
20646
+ init_domain();
20647
+ function OfferingsCatalogue(props) {
20648
+ const state = buildOfferingsCatalogueState({
20649
+ presets: props.bookingOfferingPresets,
20650
+ events: props.catalogueEvents
20651
+ });
20652
+ if (state.kind !== "groups") return /* @__PURE__ */ jsxs("div", {
20653
+ className: "offerings-preview rb-flex rb-flex-col rb-gap-6",
20654
+ "data-block": "offerings-preview",
20655
+ "data-offerings-mode": "catalogue",
20656
+ children: [props.children, /* @__PURE__ */ jsx(EmptyState, {
20657
+ className: "offerings-catalogue-empty",
20658
+ message: state.kind === "failed" ? props.failedMessage ?? "This list is unavailable right now." : props.emptyMessage ?? "Nothing scheduled just yet."
20659
+ })]
20660
+ });
20661
+ const enabledSeriesIds = new Set(state.groups.flatMap(({ events }) => events.map((event) => event.seriesId)));
20662
+ const quickDateEvents = selectQuickDateEvents((props.quickDateEvents ?? []).filter((event) => enabledSeriesIds.has(event.seriesId)));
20663
+ return /* @__PURE__ */ jsxs("div", {
20664
+ className: "offerings-preview rb-flex rb-flex-col rb-gap-6",
20665
+ "data-block": "offerings-preview",
20666
+ "data-offerings-mode": "catalogue",
20667
+ children: [
20668
+ quickDateEvents.length > 0 ? /* @__PURE__ */ jsx("div", {
20669
+ className: "offerings-preview-quick-dates rb-flex rb-flex-col rb-gap-4",
20670
+ children: /* @__PURE__ */ jsx(EventQuickDates, {
20671
+ events: quickDateEvents,
20672
+ pathname: props.pathname ?? "/",
20673
+ buttonVariant: props.buttonVariant ?? "primary"
20674
+ })
20675
+ }) : null,
20676
+ props.children,
20677
+ /* @__PURE__ */ jsx("div", {
20678
+ className: "offerings-catalogue rb-flex rb-flex-col rb-gap-8",
20679
+ children: state.groups.map(({ group, events }) => /* @__PURE__ */ jsxs("section", {
20680
+ className: "rb-flex rb-flex-col rb-gap-5",
20681
+ "data-offering-source": group.sourceKey,
20682
+ children: [/* @__PURE__ */ jsx("h3", { children: group.title }), /* @__PURE__ */ jsx("div", {
20683
+ className: "rb-grid rb-gap-6",
20684
+ style: { gridTemplateColumns: "repeat(auto-fill, minmax(min(100%, 18rem), 1fr))" },
20685
+ children: events.map((event) => /* @__PURE__ */ jsx(EventCard, {
20686
+ event,
20687
+ presentation: "catalogue",
20688
+ headingLevel: 4,
20689
+ buttonVariant: props.buttonVariant ?? "primary",
20690
+ buttonText: event.bookingScope === "single_occurrence" ? "See dates" : void 0,
20691
+ showMap: false,
20692
+ allowMap: false,
20693
+ showCategory: false,
20694
+ orientation: "vertical"
20695
+ }, event.seriesId))
20696
+ })]
20697
+ }, group.sourceKey))
20698
+ })
20699
+ ]
20700
+ });
20701
+ }
20702
+ //#endregion
20703
+ //#region ../blocks/src/system/runtime/nodes/offerings-preview-content.tsx
20704
+ init_buttons();
20705
+ init_svg();
20706
+ init_shared$3();
20707
+ function OfferingsPreviewContent(props) {
20708
+ const groupLinkClass = themeButtonClassName({
20709
+ variant: props.buttonVariant,
20710
+ size: "md",
20711
+ extraClassName: "offerings-preview-card-link rb-inline-flex rb-items-center rb-gap-2"
20712
+ });
20713
+ return /* @__PURE__ */ jsx("div", {
20714
+ className: "offerings-preview rb-flex rb-flex-col rb-gap-6",
20715
+ "data-block": "offerings-preview",
20716
+ children: /* @__PURE__ */ jsx("div", {
20717
+ className: "offerings-preview-grid rb-grid rb-items-stretch rb-gap-6",
20718
+ style: OFFERINGS_PREVIEW_GRID_STYLE,
20719
+ children: props.states.map((state) => {
20720
+ const groupCta = resolveOfferingsPreviewGroupCta({
20721
+ group: state.group,
20722
+ routes: props.routeCandidates
20723
+ });
20724
+ return /* @__PURE__ */ jsx("section", {
20725
+ className: props.groupFrame.containerClassName,
20726
+ style: props.groupFrame.containerStyle,
20727
+ "data-offering-presentation": state.group.presentation,
20728
+ "data-offering-source": state.group.sourceKey,
20729
+ children: /* @__PURE__ */ jsxs("div", {
20730
+ className: props.groupFrame.contentClassName,
20731
+ children: [
20732
+ /* @__PURE__ */ jsxs("header", {
20733
+ className: "offerings-preview-card-header rb-flex rb-flex-col rb-gap-2 rb-text-center",
20734
+ children: [/* @__PURE__ */ jsx("h3", {
20735
+ className: "offerings-preview-card-title rb-text-xl rb-font-semibold rb-leading-tight",
20736
+ children: state.group.title
20737
+ }), state.group.intro ? /* @__PURE__ */ jsx("p", {
20738
+ className: "offerings-preview-card-intro rb-text-sm rb-leading-6 status-muted",
20739
+ children: state.group.intro
20740
+ }) : null]
20741
+ }),
20742
+ state.kind === "items" ? props.renderGroupItems(state.group.presentation, state.items, {
20743
+ buttonVariant: props.buttonVariant,
20744
+ buttonText: props.buttonText,
20745
+ now: props.now
20746
+ }) : /* @__PURE__ */ jsx(EmptyState, {
20747
+ className: "offerings-preview-card-empty",
20748
+ message: state.message
20749
+ }),
20750
+ groupCta ? /* @__PURE__ */ jsx("footer", {
20751
+ className: "offerings-preview-card-footer rb-mt-auto rb-flex",
20752
+ children: /* @__PURE__ */ jsxs("a", {
20753
+ className: groupLinkClass,
20754
+ href: groupCta.href,
20755
+ children: [/* @__PURE__ */ jsx("span", { children: groupCta.label }), /* @__PURE__ */ jsx(ArrowRightIcon, {
20756
+ "aria-hidden": "true",
20757
+ className: "offerings-preview-link-icon rb-h-4 rb-w-4"
20758
+ })]
20759
+ })
20760
+ }) : null
20761
+ ]
20762
+ })
20763
+ }, state.group.sourceKey);
20764
+ })
20765
+ })
20766
+ });
20767
+ }
20768
+ const OFFERINGS_PREVIEW_GRID_STYLE = {
20769
+ gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 20rem), min(24rem, 100%)))",
20770
+ justifyContent: "center"
20771
+ };
20772
+ //#endregion
20773
+ //#region ../blocks/src/system/transforms/registry/_utils/themeColorResolution.ts
20774
+ function resolveBackgroundColorValue(value, context) {
20775
+ return resolveThemeColorReferenceValue(value, { palette: context.theme?.palette });
20776
+ }
20777
+ var init_themeColorResolution = __esmMin((() => {
20778
+ init_tokenOrColor();
20779
+ }));
20780
+ //#endregion
19612
20781
  //#region ../blocks/src/system/blocks/offerings-preview/scheduleSummary.ts
20782
+ init_themeColorResolution();
19613
20783
  init_src$2();
19614
20784
  function deriveEventScheduleSummary(event) {
19615
20785
  const occurrence = occurrenceFromEvent(event);
@@ -19714,9 +20884,12 @@ init_shared$3();
19714
20884
  init_domain();
19715
20885
  init_runGrouping();
19716
20886
  init_boxStyleClassNames();
19717
- init_svg();
19718
20887
  const OFFERINGS_WHOLE_SERIES_CARD_CLASS = boxStyleClassNames({ role: "default" }, { baseClass: "group rb-flex rb-h-full rb-flex-col event-card offerings-preview-whole-series-card" });
19719
20888
  function OfferingsPreviewNode(props) {
20889
+ if (props.displayMode === "catalogue") return /* @__PURE__ */ jsx(OfferingsCatalogue, { ...props });
20890
+ return /* @__PURE__ */ jsxs(Fragment, { children: [props.children, /* @__PURE__ */ jsx(OfferingsPreview, { ...props })] });
20891
+ }
20892
+ function OfferingsPreview(props) {
19720
20893
  const groups = resolveOfferingsPreviewGroups({
19721
20894
  presets: props.bookingOfferingPresets,
19722
20895
  groupOrder: props.groupOrder,
@@ -19734,75 +20907,16 @@ function OfferingsPreviewNode(props) {
19734
20907
  failedMessage: props.failedMessage ?? "This list is unavailable right now."
19735
20908
  });
19736
20909
  if (states.length === 0) return null;
19737
- const now = props.now ?? /* @__PURE__ */ new Date();
19738
- const buttonVariant = props.buttonVariant ?? "primary";
19739
- const buttonText = props.buttonText ?? "Book";
19740
- const routeCandidates = props.routeCandidates?.routes ?? [];
19741
- const groupLinkClass = themeButtonClassName({
19742
- variant: buttonVariant,
19743
- size: "md",
19744
- extraClassName: "offerings-preview-card-link rb-inline-flex rb-items-center rb-gap-2"
19745
- });
19746
- const groupFrame = resolveGroupFrame(props.cardStyles);
19747
- return /* @__PURE__ */ jsx("div", {
19748
- className: "offerings-preview rb-flex rb-flex-col rb-gap-6",
19749
- "data-block": "offerings-preview",
19750
- children: /* @__PURE__ */ jsx("div", {
19751
- className: "offerings-preview-grid rb-grid rb-items-stretch rb-gap-6",
19752
- style: OFFERINGS_PREVIEW_GRID_STYLE,
19753
- children: states.map((state) => {
19754
- const groupCta = resolveOfferingsPreviewGroupCta({
19755
- group: state.group,
19756
- routes: routeCandidates
19757
- });
19758
- return /* @__PURE__ */ jsx("section", {
19759
- className: groupFrame.containerClassName,
19760
- style: groupFrame.containerStyle,
19761
- "data-offering-presentation": state.group.presentation,
19762
- "data-offering-source": state.group.sourceKey,
19763
- children: /* @__PURE__ */ jsxs("div", {
19764
- className: groupFrame.contentClassName,
19765
- children: [
19766
- /* @__PURE__ */ jsxs("header", {
19767
- className: "offerings-preview-card-header rb-flex rb-flex-col rb-gap-2 rb-text-center",
19768
- children: [/* @__PURE__ */ jsx("h3", {
19769
- className: "offerings-preview-card-title rb-text-xl rb-font-semibold rb-leading-tight",
19770
- children: state.group.title
19771
- }), state.group.intro ? /* @__PURE__ */ jsx("p", {
19772
- className: "offerings-preview-card-intro rb-text-sm rb-leading-6 status-muted",
19773
- children: state.group.intro
19774
- }) : null]
19775
- }),
19776
- state.kind === "items" ? renderOfferingGroupItems(state.group.presentation, state.items, {
19777
- buttonVariant,
19778
- buttonText,
19779
- now
19780
- }) : /* @__PURE__ */ jsx(EmptyState, {
19781
- className: "offerings-preview-card-empty",
19782
- message: state.message
19783
- }),
19784
- groupCta ? /* @__PURE__ */ jsx("footer", {
19785
- className: "offerings-preview-card-footer rb-mt-auto rb-flex",
19786
- children: /* @__PURE__ */ jsxs("a", {
19787
- className: groupLinkClass,
19788
- href: groupCta.href,
19789
- children: [/* @__PURE__ */ jsx("span", { children: groupCta.label }), /* @__PURE__ */ jsx(ArrowRightIcon, {
19790
- "aria-hidden": "true",
19791
- className: "offerings-preview-link-icon rb-h-4 rb-w-4"
19792
- })]
19793
- })
19794
- }) : null
19795
- ]
19796
- })
19797
- }, state.group.sourceKey);
19798
- })
19799
- })
20910
+ return /* @__PURE__ */ jsx(OfferingsPreviewContent, {
20911
+ states,
20912
+ now: props.now ?? /* @__PURE__ */ new Date(),
20913
+ buttonVariant: props.buttonVariant ?? "primary",
20914
+ buttonText: props.buttonText ?? "Book",
20915
+ routeCandidates: props.routeCandidates?.routes ?? [],
20916
+ groupFrame: resolveGroupFrame(props.cardStyles),
20917
+ renderGroupItems: renderOfferingGroupItems
19800
20918
  });
19801
20919
  }
19802
- const OFFERINGS_PREVIEW_GRID_STYLE = {
19803
- gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 20rem), min(24rem, 100%)))",
19804
- justifyContent: "center"
19805
- };
19806
20920
  function buildItemDataMap(props) {
19807
20921
  const routeCandidates = props.routeCandidates?.routes ?? [];
19808
20922
  const entries = OFFERINGS_PREVIEW_EVENT_PRESET_DEFINITIONS.map((definition) => [definition.sourceKey, eventDataFromMaybeArray(props[definition.dataKey])]);
@@ -21579,7 +22693,8 @@ var init_appearancePresets = __esmMin((() => {
21579
22693
  init_appearancePresetTypes();
21580
22694
  init_blockAppearancePresets();
21581
22695
  init_headerCtaVariants();
21582
- })), init_blockFlow = __esmMin((() => {
22696
+ }));
22697
+ var init_blockFlow = __esmMin((() => {
21583
22698
  init_types$8();
21584
22699
  }));
21585
22700
  var init_tokens$1 = __esmMin((() => {}));
@@ -30583,102 +31698,31 @@ var init_newsletterForm$1 = __esmMin((() => {
30583
31698
  description: "Newsletter subscription form with preset field configurations.",
30584
31699
  fields: [
30585
31700
  {
30586
- id: "destinationProvider",
30587
- type: "select",
30588
- label: "Send signups to",
30589
- description: "Choose where new subscribers from this form should go.",
30590
- defaultValue: "riverbank",
30591
- required: false,
30592
- ui: { intent: "behavior" },
30593
- options: [{
30594
- value: "riverbank",
30595
- label: "Riverbank newsletter"
30596
- }]
30597
- },
30598
- {
30599
- id: "listId",
30600
- type: "reference",
30601
- label: "Newsletter list",
30602
- description: "Select the list new subscribers should be added to.",
30603
- required: false,
30604
- referenceKind: "newsletterList",
30605
- allowManualEntry: false,
30606
- ui: {
30607
- intent: "behavior",
30608
- visibleWhen: {
30609
- field: "destinationProvider",
30610
- equals: "riverbank"
30611
- }
30612
- }
30613
- },
30614
- {
30615
- id: "mailchimpAudienceId",
30616
- type: "reference",
30617
- label: "Mailchimp audience",
30618
- description: "Choose the Mailchimp audience for new subscribers.",
30619
- required: false,
30620
- referenceKind: "mailchimpAudience",
30621
- allowManualEntry: false,
30622
- ui: {
30623
- intent: "behavior",
30624
- visibleWhen: {
30625
- field: "destinationProvider",
30626
- equals: "mailchimp"
30627
- }
30628
- }
30629
- },
30630
- {
30631
- id: "mailchimpTags",
30632
- type: "text",
30633
- label: "Mailchimp tags",
30634
- description: "Optional tags to apply in Mailchimp, separated by commas or semicolons.",
31701
+ id: "targeting",
31702
+ type: "group",
31703
+ label: "Mailing-list targeting",
31704
+ description: "Choose what kind of emails people signing up here will receive.",
31705
+ defaultValue: { mode: "default" },
31706
+ required: true,
30635
31707
  ui: {
30636
31708
  intent: "behavior",
30637
- visibleWhen: {
30638
- field: "destinationProvider",
30639
- equals: "mailchimp"
30640
- }
30641
- }
30642
- },
30643
- {
30644
- id: "preset",
30645
- type: "select",
30646
- label: "Form fields",
30647
- description: "Choose which fields to collect.",
30648
- defaultValue: "emailOnly",
30649
- ui: { intent: "display" },
30650
- options: [
30651
- {
30652
- value: "emailOnly",
30653
- label: "Email only"
30654
- },
30655
- {
30656
- value: "emailName",
30657
- label: "Email + Name"
30658
- },
30659
- {
30660
- value: "emailFirstLast",
30661
- label: "Email + First/Last Name"
30662
- },
30663
- {
30664
- value: "emailNameCompany",
30665
- label: "Email + Name + Company (B2B)"
30666
- }
30667
- ]
30668
- },
30669
- {
30670
- id: "includePhone",
30671
- type: "boolean",
30672
- label: "Include phone field (optional)",
30673
- description: "Adds an optional phone field to the selected preset (never required).",
30674
- defaultValue: false,
30675
- ui: { intent: "display" }
30676
- },
30677
- {
30678
- id: "buttonLabel",
30679
- type: "text",
30680
- label: "Button label",
30681
- defaultValue: "Subscribe"
31709
+ widget: "mailingListTargeting"
31710
+ },
31711
+ schema: { fields: [{
31712
+ id: "mode",
31713
+ type: "select",
31714
+ label: "Mode",
31715
+ required: true,
31716
+ defaultValue: "default",
31717
+ options: [{
31718
+ value: "default",
31719
+ label: "Default"
31720
+ }, {
31721
+ value: "custom",
31722
+ label: "Custom"
31723
+ }],
31724
+ ui: { hidden: true }
31725
+ }] }
30682
31726
  },
30683
31727
  createButtonVariantField({
30684
31728
  id: "buttonVariant",
@@ -30686,46 +31730,42 @@ var init_newsletterForm$1 = __esmMin((() => {
30686
31730
  defaultValue: "primary"
30687
31731
  }),
30688
31732
  {
30689
- id: "successMessage",
30690
- type: "text",
30691
- label: "Success message",
30692
- description: "Shown after successful subscription.",
30693
- defaultValue: "Thanks for subscribing!"
30694
- },
30695
- {
30696
- id: "privacyNote",
31733
+ id: "mailingListSource",
30697
31734
  type: "text",
30698
- label: "Privacy note",
30699
- description: "Optional small text below the form (e.g., privacy policy link)."
31735
+ label: "Mailing-list source",
31736
+ ui: {
31737
+ hidden: true,
31738
+ intent: "behavior"
31739
+ }
30700
31740
  },
30701
31741
  {
30702
- id: "tags",
31742
+ id: "mailingListSourceToken",
30703
31743
  type: "text",
30704
- label: "Tags (optional)",
30705
- description: "Optional tags to apply on subscribe (comma or semicolon separated).",
31744
+ label: "Mailing-list source token",
30706
31745
  ui: {
30707
- intent: "behavior",
30708
- visibleWhen: {
30709
- field: "destinationProvider",
30710
- equals: "riverbank"
30711
- }
31746
+ hidden: true,
31747
+ intent: "behavior"
30712
31748
  }
30713
31749
  }
30714
31750
  ],
30715
31751
  layout: [el("newsletter-form", withApiBindings({
30716
- source: "block",
30717
- destinationProvider: { $bind: { from: "destinationProvider" } },
30718
- listId: { $bind: { from: "listId" } },
30719
- preset: { $bind: { from: "preset" } },
30720
- includePhone: { $bind: { from: "includePhone" } },
30721
- buttonLabel: { $bind: { from: "buttonLabel" } },
31752
+ source: { $bind: {
31753
+ from: "mailingListSource",
31754
+ fallback: "block"
31755
+ } },
31756
+ sourceRef: {
31757
+ tag: "signed_source_ref",
31758
+ token: { $bind: { from: "mailingListSourceToken" } }
31759
+ },
31760
+ targeting: { $bind: {
31761
+ from: "targeting",
31762
+ fallback: { mode: "default" }
31763
+ } },
31764
+ mailingList: { $bind: { from: "$root.mailingList" } },
30722
31765
  buttonVariant: { $bind: {
30723
31766
  from: "buttonVariant",
30724
31767
  fallback: "primary"
30725
31768
  } },
30726
- successMessage: { $bind: { from: "successMessage" } },
30727
- privacyNote: { $bind: { from: "privacyNote" } },
30728
- tags: { $bind: { from: "tags" } },
30729
31769
  spamProtectionEnabled: { $bind: { from: "$root.spamProtectionEnabled" } }
30730
31770
  }), [])]
30731
31771
  });
@@ -32585,8 +33625,8 @@ var init_registrationEventAdapter = __esmMin((() => {
32585
33625
  }));
32586
33626
  //#endregion
32587
33627
  //#region ../blocks/src/system/runtime/nodes/event-registration.interactive.ts
32588
- function buildEventRegistrationDisplay(source) {
32589
- const selectedRun = resolveSelectedWholeSeriesRun(source);
33628
+ function buildEventRegistrationDisplayFromScopedEvents(source, scopedSourceEvents) {
33629
+ const selectedRun = resolveSelectedWholeSeriesRun(scopedSourceEvents);
32590
33630
  if (selectedRun && (!selectedRun.run.enrollmentOpen || toWholeSeriesRegistrationEvent(selectedRun) === null)) return {
32591
33631
  kind: "event-registration",
32592
33632
  state: "registration-closed",
@@ -32594,7 +33634,7 @@ function buildEventRegistrationDisplay(source) {
32594
33634
  titleText: "Registration closed",
32595
33635
  bodyText: "This run is no longer open for bookings."
32596
33636
  };
32597
- const stepLabels = buildEventRegistrationShellStepLabels(source);
33637
+ const stepLabels = buildEventRegistrationShellStepLabels(source, scopedSourceEvents);
32598
33638
  return {
32599
33639
  kind: "event-registration",
32600
33640
  state: "generic-shell",
@@ -32605,8 +33645,8 @@ function buildEventRegistrationDisplay(source) {
32605
33645
  summaryButtonText: source.buttonText?.trim() || "Register"
32606
33646
  };
32607
33647
  }
32608
- function buildEventRegistrationShellStepLabels(source) {
32609
- const selectedRun = resolveSelectedWholeSeriesRun(source);
33648
+ function buildEventRegistrationShellStepLabels(source, scopedSourceEvents) {
33649
+ const selectedRun = resolveSelectedWholeSeriesRun(scopedSourceEvents);
32610
33650
  if (selectedRun) {
32611
33651
  const selectedEvent = toWholeSeriesRegistrationEvent(selectedRun);
32612
33652
  if (!selectedEvent) return EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS;
@@ -32616,7 +33656,7 @@ function buildEventRegistrationShellStepLabels(source) {
32616
33656
  event: selectedEvent
32617
33657
  })).map((step) => shellLabelForRegistrationStep(step, [selectedEvent]));
32618
33658
  }
32619
- const scopedEvents = scopeEventRegistrationEvents(source);
33659
+ const scopedEvents = toScopedEventRegistrationEvents(scopedSourceEvents);
32620
33660
  if (scopedEvents.length === 0) return EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS;
32621
33661
  const preSelectedEvent = findPreSelectedEvent({
32622
33662
  scopedEvents,
@@ -32629,31 +33669,25 @@ function buildEventRegistrationShellStepLabels(source) {
32629
33669
  event: preSelectedEvent
32630
33670
  }) : false).map((step) => shellLabelForRegistrationStep(step, scopedEvents));
32631
33671
  }
32632
- function scopeEventRegistrationEvents(source) {
32633
- const scoped = scopeEventRegistrationSourceEvents(source);
32634
- return [...toRegistrationEvents(scoped), ...toWholeSeriesRegistrationEvents(scoped)];
33672
+ function toScopedEventRegistrationEvents(scopedSourceEvents) {
33673
+ return [...toRegistrationEvents(scopedSourceEvents), ...toWholeSeriesRegistrationEvents(scopedSourceEvents)];
32635
33674
  }
32636
- /**
32637
- * Every event this surface may register for, from both of its loads.
32638
- *
32639
- * The date page and the run read answer different questions and can name the
32640
- * same occurrence, so the two lists are joined and any occurrence that arrives
32641
- * twice is kept once, in the order the date page gave it.
32642
- */
32643
33675
  function scopeEventRegistrationSourceEvents(source) {
32644
- const byOccurrenceId = /* @__PURE__ */ new Map();
32645
- for (const event of [...source.events ?? [], ...source.wholeSeriesRunEvents ?? []]) if (!byOccurrenceId.has(event.occurrenceId)) byOccurrenceId.set(event.occurrenceId, event);
32646
- return resolveEventRegistrationScopedEvents([...byOccurrenceId.values()], {
33676
+ return resolveEventRegistrationScopedEvents(source.wholeSeriesRunEvents ?? source.events ?? [], {
32647
33677
  occurrenceContext: source.occurrenceContext,
32648
33678
  subject: source.subject
32649
33679
  });
32650
33680
  }
33681
+ function resolveLoadedEventRegistrationSourceEvents(source, scopedSourceEvents) {
33682
+ if (source.events == null && source.wholeSeriesRunEvents == null) return null;
33683
+ return [...scopedSourceEvents];
33684
+ }
32651
33685
  /**
32652
33686
  * The one run this surface is registering for, when the scoped events describe
32653
33687
  * exactly one. More than one run means the visitor still has to choose.
32654
33688
  */
32655
- function resolveSelectedWholeSeriesRun(source) {
32656
- const runs = groupPublicEventsByRun(scopeEventRegistrationSourceEvents(source));
33689
+ function resolveSelectedWholeSeriesRun(scopedSourceEvents) {
33690
+ const runs = groupPublicEventsByRun(scopedSourceEvents);
32657
33691
  return runs.length === 1 ? runs[0] : null;
32658
33692
  }
32659
33693
  function shellLabelForRegistrationStep(step, events) {
@@ -32681,13 +33715,13 @@ function buildEventRegistrationShellBodyText(stepLabels) {
32681
33715
  return "Preparing dates, tickets, and booking details.";
32682
33716
  }
32683
33717
  function normalizeEventRegistrationEventInput(value) {
32684
- if (!isRecord$5(value)) return value;
33718
+ if (!isRecord$4(value)) return value;
32685
33719
  return {
32686
33720
  ...value,
32687
33721
  destination: resolveRuntimeEventDestination(value)
32688
33722
  };
32689
33723
  }
32690
- function isRecord$5(value) {
33724
+ function isRecord$4(value) {
32691
33725
  return typeof value === "object" && value !== null && !Array.isArray(value);
32692
33726
  }
32693
33727
  function buildEventRegistrationInteractiveIslandProps(props) {
@@ -32793,9 +33827,10 @@ var init_event_registration_interactive = __esmMin((() => {
32793
33827
  render: createZodCodec(eventRegistrationRenderSchema)
32794
33828
  },
32795
33829
  buildRender: (source) => {
32796
- const events = source.events == null ? null : scopeEventRegistrationSourceEvents(source);
33830
+ const scopedSourceEvents = scopeEventRegistrationSourceEvents(source);
33831
+ const events = resolveLoadedEventRegistrationSourceEvents(source, scopedSourceEvents);
32797
33832
  return {
32798
- display: buildEventRegistrationDisplay(source),
33833
+ display: buildEventRegistrationDisplayFromScopedEvents(source, scopedSourceEvents),
32799
33834
  hydration: {
32800
33835
  occurrenceContext: source.occurrenceContext ?? null,
32801
33836
  subject: source.subject ?? null,
@@ -33012,6 +34047,11 @@ const eventRegistrationBlockDefinition = {
33012
34047
  dataLoaders: {
33013
34048
  events: {
33014
34049
  endpoint: "listPublicEvents",
34050
+ when: { $bind: {
34051
+ from: "$root.subject.isWholeSeriesBooking",
34052
+ fallback: true,
34053
+ transforms: [{ id: "boolean.not" }]
34054
+ } },
33015
34055
  params: {
33016
34056
  siteId: { $bind: { from: "$root.siteId" } },
33017
34057
  limit: "50",
@@ -33033,13 +34073,9 @@ const eventRegistrationBlockDefinition = {
33033
34073
  /**
33034
34074
  * The runs this page can register for, finished ones included.
33035
34075
  *
33036
- * The `events` page above is date-bounded, so a run whose first session has
33037
- * passed contributes no rows to it and the surface would have nothing to
33038
- * render as closed. This asks for runs instead, and only on a page whose
33039
- * subject books whole runs. It is scoped exactly like the date page — same
33040
- * series, same run subroute — because scope and grain are separate
33041
- * questions. The two lists are joined by occurrence, so a run that appears
33042
- * in both is still one run.
34076
+ * A run read is the sole Event source on a whole-series surface. It is
34077
+ * status-bounded rather than date-bounded, so completed runs can still
34078
+ * render their closed state and every run carries its complete schedule.
33043
34079
  */
33044
34080
  wholeSeriesRunEvents: {
33045
34081
  endpoint: "listPublicEvents",
@@ -34964,66 +36000,14 @@ const eventListingBlockDefinition = {
34964
36000
  mode: "server"
34965
36001
  } }
34966
36002
  };
34967
- function parseNewsletterSignupBlockId(value) {
34968
- const trimmed = parseTrimmedString(value);
34969
- return trimmed && BLOCK_ID_PATTERN.test(trimmed) ? trimmed : null;
34970
- }
34971
- function parseSignedNewsletterDestinationRef(value) {
34972
- const trimmed = parseTrimmedString(value);
34973
- return trimmed && SIGNED_DESTINATION_REF_PATTERN.test(trimmed) ? trimmed : null;
34974
- }
34975
- function buildNewsletterSignupBlockRef(blockId) {
34976
- const parsed = parseNewsletterSignupBlockId(blockId);
34977
- return parsed ? {
34978
- tag: "block_ref",
34979
- blockId: parsed
34980
- } : null;
34981
- }
34982
- function normalizeNewsletterSignupEditorValuesForDestination(values) {
34983
- const destinationProvider = parseNewsletterSignupDestinationProvider(values.destinationProvider) ?? "riverbank";
34984
- if (destinationProvider === "mailchimp") return {
34985
- destinationProvider,
34986
- mailchimpAudienceId: values.mailchimpAudienceId,
34987
- mailchimpTags: values.mailchimpTags
34988
- };
34989
- return {
34990
- destinationProvider,
34991
- listId: values.listId,
34992
- tags: values.tags
34993
- };
34994
- }
34995
- function deriveNewsletterSignupRuntimeSource(values) {
34996
- const normalized = normalizeNewsletterSignupEditorValuesForDestination(values);
34997
- if (normalized.destinationProvider === "mailchimp") return {
34998
- destinationProvider: "mailchimp",
34999
- listId: null,
35000
- tags: null
35001
- };
35002
- return {
35003
- destinationProvider: "riverbank",
35004
- listId: parseTrimmedString(normalized.listId),
35005
- tags: parseTrimmedString(normalized.tags)
35006
- };
35007
- }
35008
- function parseTrimmedString(value) {
35009
- if (typeof value !== "string") return null;
35010
- const trimmed = value.trim();
35011
- return trimmed.length > 0 ? trimmed : null;
35012
- }
35013
- var BLOCK_ID_PATTERN, SIGNED_DESTINATION_REF_PATTERN;
35014
- var init_newsletter_signup_destination = __esmMin((() => {
35015
- init_src$2();
35016
- BLOCK_ID_PATTERN = /^[A-Za-z0-9._:-]{1,200}$/;
35017
- SIGNED_DESTINATION_REF_PATTERN = /^[A-Za-z0-9._~-]{16,1000}$/;
35018
- }));
35019
36003
  //#endregion
35020
36004
  //#region ../blocks/src/system/runtime/nodes/newsletter-form.types.ts
35021
36005
  /**
35022
36006
  * Get form fields based on preset configuration.
35023
36007
  */
35024
- function getPresetFields(preset, options) {
35025
- const includePhone = Boolean(options?.includePhone);
35026
- switch (preset) {
36008
+ function getGlobalFormFields(form) {
36009
+ const includePhone = form.includeOptionalPhone;
36010
+ switch (form.fields.preset) {
35027
36011
  case "emailOnly": return withOptionalPhone([{
35028
36012
  id: "email",
35029
36013
  type: "email",
@@ -35041,7 +36025,7 @@ function getPresetFields(preset, options) {
35041
36025
  id: "name",
35042
36026
  type: "text",
35043
36027
  label: "Name",
35044
- required: false,
36028
+ required: form.fields.name === "required",
35045
36029
  placeholder: "Your name"
35046
36030
  }], includePhone);
35047
36031
  case "emailFirstLast": return withOptionalPhone([
@@ -35056,14 +36040,14 @@ function getPresetFields(preset, options) {
35056
36040
  id: "firstName",
35057
36041
  type: "text",
35058
36042
  label: "First Name",
35059
- required: false,
36043
+ required: form.fields.firstName === "required",
35060
36044
  placeholder: "First name"
35061
36045
  },
35062
36046
  {
35063
36047
  id: "lastName",
35064
36048
  type: "text",
35065
36049
  label: "Last Name",
35066
- required: false,
36050
+ required: form.fields.lastName === "required",
35067
36051
  placeholder: "Last name"
35068
36052
  }
35069
36053
  ], includePhone);
@@ -35079,14 +36063,14 @@ function getPresetFields(preset, options) {
35079
36063
  id: "name",
35080
36064
  type: "text",
35081
36065
  label: "Name",
35082
- required: false,
36066
+ required: form.fields.name === "required",
35083
36067
  placeholder: "Your name"
35084
36068
  },
35085
36069
  {
35086
36070
  id: "company",
35087
36071
  type: "text",
35088
36072
  label: "Company",
35089
- required: false,
36073
+ required: form.fields.company === "required",
35090
36074
  placeholder: "Company name"
35091
36075
  }
35092
36076
  ], includePhone);
@@ -35107,43 +36091,109 @@ var init_newsletter_form_types = __esmMin((() => {}));
35107
36091
  //#endregion
35108
36092
  //#region ../blocks/src/system/runtime/nodes/newsletter-form.interactive.ts
35109
36093
  function buildNewsletterDisplay(source) {
35110
- const preset = source.preset ?? "emailOnly";
35111
- const includePhone = source.includePhone ?? false;
36094
+ const context = source.mailingList;
36095
+ const form = context?.tag === "configured" ? context.form : {
36096
+ fields: { preset: "emailOnly" },
36097
+ includeOptionalPhone: false,
36098
+ buttonLabel: "Subscribe",
36099
+ privacyNote: null
36100
+ };
36101
+ const targeting = source.targeting ?? { mode: "default" };
36102
+ const choices = resolveRuntimeChoices(context, targeting);
35112
36103
  return {
35113
36104
  kind: "newsletter-form",
36105
+ availability: runtimeTargetingIsAvailable(context, targeting, choices) ? "ready" : "unavailable",
35114
36106
  className: source.className ?? null,
35115
- buttonLabel: source.buttonLabel?.trim() || "Subscribe",
36107
+ buttonLabel: form.buttonLabel,
35116
36108
  buttonVariant: source.buttonVariant ?? "primary",
35117
- successMessage: source.successMessage ?? "Thanks for subscribing!",
35118
- privacyNote: source.privacyNote ?? null,
35119
- fields: getPresetFields(preset, { includePhone })
36109
+ privacyNote: form.privacyNote,
36110
+ fields: getGlobalFormFields(form),
36111
+ choices
35120
36112
  };
35121
36113
  }
35122
36114
  function projectNewsletterFormHydrationTarget(source) {
35123
36115
  switch (source.source) {
35124
36116
  case "block": {
35125
- const destinationRef = buildNewsletterSignupBlockRef(source.blockId);
35126
- if (destinationRef?.tag === "block_ref") return {
36117
+ const sourceRef = buildMailingListSignupBlockSourceRef(source.blockId);
36118
+ if (sourceRef?.tag === "block_ref") return {
35127
36119
  tag: "block-source",
35128
- destinationRef
36120
+ sourceRef
35129
36121
  };
35130
36122
  return {
35131
- tag: "legacy-direct-list",
35132
- listId: source.listId ?? null
36123
+ tag: "block-source",
36124
+ sourceRef: null
35133
36125
  };
35134
36126
  }
35135
36127
  case "signed-footer": return {
35136
36128
  tag: "signed-footer-source",
35137
- destinationRef: source.destinationRef
35138
- };
35139
- case "legacy-direct-list": return {
35140
- tag: "legacy-direct-list",
35141
- listId: source.listId
36129
+ sourceRef: source.sourceRef
35142
36130
  };
36131
+ case "preview": return { tag: "preview" };
35143
36132
  default: return assertNever$22(source);
35144
36133
  }
35145
36134
  }
36135
+ function resolveRuntimeChoices(context, targeting) {
36136
+ if (context?.tag !== "configured" || targeting.mode !== "custom" || targeting.selection.tag !== "visitor_choice" || context.provider.provider !== targeting.provider) return [];
36137
+ switch (targeting.provider) {
36138
+ case "native": {
36139
+ const offered = new Set(targeting.selection.offeredTopicIds);
36140
+ return context.provider.provider === "native" ? context.provider.topics.filter((item) => offered.has(item.id)).map((item) => ({
36141
+ id: item.id,
36142
+ label: item.name
36143
+ })) : [];
36144
+ }
36145
+ case "brevo": {
36146
+ const offered = new Set(targeting.selection.offeredListIds);
36147
+ return context.provider.provider === "brevo" ? context.provider.lists.filter((item) => offered.has(item.id)).map((item) => ({
36148
+ id: String(item.id),
36149
+ label: item.name
36150
+ })) : [];
36151
+ }
36152
+ case "mailchimp": {
36153
+ const offered = new Set(targeting.selection.offeredInterestIds);
36154
+ 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) => ({
36155
+ id: item.id,
36156
+ label: item.name
36157
+ })) ?? [];
36158
+ }
36159
+ }
36160
+ }
36161
+ function runtimeTargetingIsAvailable(context, targeting, choices) {
36162
+ if (context?.tag !== "configured") return false;
36163
+ const provider = context.provider;
36164
+ if (targeting.mode === "default") switch (provider.provider) {
36165
+ case "native": return provider.topics.some((item) => item.id === provider.defaultTopicId);
36166
+ case "brevo": return provider.lists.some((item) => item.id === provider.defaultListId);
36167
+ case "mailchimp": return provider.audiences.some((item) => item.id === provider.defaultAudienceId);
36168
+ }
36169
+ if (targeting.provider !== provider.provider) return false;
36170
+ switch (targeting.provider) {
36171
+ case "native": return provider.provider === "native" && nativeTargetIsAvailable(provider, targeting, choices);
36172
+ case "brevo": return provider.provider === "brevo" && brevoTargetIsAvailable(provider, targeting, choices);
36173
+ case "mailchimp": return provider.provider === "mailchimp" && mailchimpTargetIsAvailable(provider, targeting, choices);
36174
+ }
36175
+ }
36176
+ function nativeTargetIsAvailable(provider, targeting, choices) {
36177
+ const ids = targeting.selection.tag === "fixed" ? targeting.selection.topicIds : targeting.selection.offeredTopicIds;
36178
+ return ids.every((id) => provider.topics.some((item) => item.id === id)) && (targeting.selection.tag !== "visitor_choice" || choices.length === ids.length);
36179
+ }
36180
+ function brevoTargetIsAvailable(provider, targeting, choices) {
36181
+ const ids = targeting.selection.tag === "fixed" ? targeting.selection.listIds : targeting.selection.offeredListIds;
36182
+ return ids.every((id) => provider.lists.some((item) => item.id === id)) && (targeting.selection.tag !== "visitor_choice" || choices.length === ids.length);
36183
+ }
36184
+ function mailchimpTargetIsAvailable(provider, targeting, choices) {
36185
+ const audience = provider.audiences.find((item) => item.id === targeting.audienceId);
36186
+ if (!audience) return false;
36187
+ const ids = targeting.selection.tag === "fixed" ? targeting.selection.interestIds : targeting.selection.offeredInterestIds;
36188
+ return ids.every((id) => audience.interests.some((item) => item.id === id)) && (targeting.selection.tag !== "visitor_choice" || choices.length === ids.length);
36189
+ }
35146
36190
  function buildNewsletterFormInteractiveIslandProps(props) {
36191
+ const decoded = newsletterFormBlockRuntime.contracts.source.decode(props);
36192
+ const source = isDecodeSuccess(decoded) ? decoded.value : {
36193
+ ...props,
36194
+ mailingList: void 0,
36195
+ targeting: { mode: "default" }
36196
+ };
35147
36197
  return buildInteractiveIslandProps({
35148
36198
  runtime: newsletterFormBlockRuntime,
35149
36199
  mode: "newsletter-form",
@@ -35151,35 +36201,49 @@ function buildNewsletterFormInteractiveIslandProps(props) {
35151
36201
  siteId: props.siteId,
35152
36202
  apiBaseUrl: props.apiBaseUrl
35153
36203
  },
35154
- source: props
36204
+ source
35155
36205
  });
35156
36206
  }
35157
- function parseRequiredNewsletterSignupBlockId(value) {
35158
- const parsed = parseNewsletterSignupBlockId(value);
35159
- if (!parsed) throw new Error("Newsletter signup block destination ref requires blockId");
36207
+ function parseRequiredMailingListSignupBlockId(value) {
36208
+ const parsed = parseMailingListBlockId(value);
36209
+ if (!parsed) throw new Error("Mailing-list signup block source ref requires blockId");
35160
36210
  return parsed;
35161
36211
  }
35162
- function parseRequiredSignedNewsletterDestinationRef(value) {
35163
- const parsed = parseSignedNewsletterDestinationRef(value);
35164
- if (!parsed) throw new Error("Newsletter signup signed destination ref requires token");
36212
+ function parseRequiredMailingListSignedSourceToken(value) {
36213
+ const parsed = parseMailingListSignedSourceToken(value);
36214
+ if (!parsed) throw new Error("Mailing-list signup signed source ref requires token");
35165
36215
  return parsed;
35166
36216
  }
35167
- var newsletterPresetSchema, newsletterDestinationProviderSchema, newsletterButtonVariantSchema, newsletterFieldSchema, newsletterSignupBlockIdSchema, signedNewsletterDestinationRefSchema, newsletterSourceCommonSchema, newsletterSourceSchema, newsletterDisplaySchema, newsletterHydrationSchema, newsletterRenderSchema, newsletterIslandMetaCodec, newsletterIslandMetaKeys, newsletterFormBlockRuntime, newsletterFormInteractiveIslandPropsCodec;
36217
+ var newsletterButtonVariantSchema, mailingListContextSchema, mailingListTargetingSchema, newsletterFieldSchema, mailingListSignupBlockIdSchema, signedMailingListSourceTokenSchema, newsletterSourceCommonSchema, newsletterSourceSchema, newsletterDisplaySchema, newsletterHydrationSchema, newsletterRenderSchema, newsletterIslandMetaCodec, newsletterIslandMetaKeys, newsletterFormBlockRuntime, newsletterFormInteractiveIslandPropsCodec;
35168
36218
  var init_newsletter_form_interactive = __esmMin((() => {
35169
36219
  init_src$2();
35170
36220
  init_islands();
35171
36221
  init_runtime();
35172
- init_newsletter_signup_destination();
35173
36222
  init_newsletter_form_types();
35174
36223
  init_buttonRoles();
35175
- newsletterPresetSchema = z.enum([
35176
- "emailOnly",
35177
- "emailName",
35178
- "emailFirstLast",
35179
- "emailNameCompany"
35180
- ]);
35181
- newsletterDestinationProviderSchema = z.enum(["riverbank", "mailchimp"]);
35182
36224
  newsletterButtonVariantSchema = blockButtonRoleSchema;
36225
+ mailingListContextSchema = z.unknown().transform((value, ctx) => {
36226
+ const parsed = parseMailingListRuntimeContext(value);
36227
+ if (!parsed.ok) {
36228
+ ctx.addIssue({
36229
+ code: z.ZodIssueCode.custom,
36230
+ message: "Invalid mailing-list runtime context"
36231
+ });
36232
+ return z.NEVER;
36233
+ }
36234
+ return parsed.value;
36235
+ });
36236
+ mailingListTargetingSchema = z.unknown().transform((value, ctx) => {
36237
+ const parsed = parseMailingListPlacementTargeting(value);
36238
+ if (!parsed.ok) {
36239
+ ctx.addIssue({
36240
+ code: z.ZodIssueCode.custom,
36241
+ message: "Invalid mailing-list targeting"
36242
+ });
36243
+ return z.NEVER;
36244
+ }
36245
+ return parsed.value;
36246
+ });
35183
36247
  newsletterFieldSchema = z.object({
35184
36248
  id: z.string(),
35185
36249
  type: z.enum(["email", "text"]),
@@ -35187,73 +36251,73 @@ var init_newsletter_form_interactive = __esmMin((() => {
35187
36251
  required: z.boolean(),
35188
36252
  placeholder: z.string().optional()
35189
36253
  });
35190
- newsletterSignupBlockIdSchema = z.string().trim().min(1).transform(parseRequiredNewsletterSignupBlockId);
35191
- signedNewsletterDestinationRefSchema = z.string().trim().min(1).transform(parseRequiredSignedNewsletterDestinationRef);
36254
+ mailingListSignupBlockIdSchema = z.string().trim().min(1).transform(parseRequiredMailingListSignupBlockId);
36255
+ signedMailingListSourceTokenSchema = z.string().trim().min(1).transform(parseRequiredMailingListSignedSourceToken);
35192
36256
  newsletterSourceCommonSchema = z.object({
35193
36257
  siteId: z.string().optional(),
35194
36258
  apiBaseUrl: z.string().optional(),
35195
- preset: newsletterPresetSchema.optional(),
35196
- includePhone: z.boolean().optional(),
35197
- buttonLabel: z.string().nullable().optional(),
36259
+ mailingList: mailingListContextSchema.optional(),
36260
+ targeting: mailingListTargetingSchema.optional(),
35198
36261
  buttonVariant: newsletterButtonVariantSchema.nullable().optional(),
35199
- successMessage: z.string().nullable().optional(),
35200
- privacyNote: z.string().nullable().optional(),
35201
- tags: z.string().nullable().optional(),
35202
36262
  spamProtectionEnabled: z.boolean().optional(),
35203
36263
  className: z.string().nullable().optional()
35204
36264
  });
35205
36265
  newsletterSourceSchema = z.discriminatedUnion("source", [
35206
36266
  newsletterSourceCommonSchema.extend({
35207
36267
  source: z.literal("block"),
35208
- blockId: z.string().nullable().optional(),
35209
- listId: z.string().nullable().optional(),
35210
- destinationProvider: newsletterDestinationProviderSchema.nullable().optional()
36268
+ blockId: z.string().nullable().optional()
35211
36269
  }),
35212
36270
  newsletterSourceCommonSchema.extend({
35213
36271
  source: z.literal("signed-footer"),
35214
- destinationRef: z.object({
35215
- tag: z.literal("signed_destination_ref"),
35216
- token: signedNewsletterDestinationRefSchema
36272
+ sourceRef: z.object({
36273
+ tag: z.literal("signed_source_ref"),
36274
+ token: signedMailingListSourceTokenSchema
35217
36275
  })
35218
36276
  }),
35219
- newsletterSourceCommonSchema.extend({
35220
- source: z.literal("legacy-direct-list"),
35221
- listId: z.string().nullable()
35222
- })
36277
+ newsletterSourceCommonSchema.extend({ source: z.literal("preview") })
35223
36278
  ]);
35224
36279
  newsletterDisplaySchema = z.object({
35225
36280
  kind: z.literal("newsletter-form"),
36281
+ availability: z.enum(["ready", "unavailable"]),
35226
36282
  className: z.string().nullable(),
35227
36283
  buttonLabel: z.string(),
35228
36284
  buttonVariant: newsletterButtonVariantSchema,
35229
- successMessage: z.string().nullable(),
35230
36285
  privacyNote: z.string().nullable(),
35231
- fields: z.array(newsletterFieldSchema)
36286
+ fields: z.array(newsletterFieldSchema),
36287
+ choices: z.array(z.object({
36288
+ id: z.string(),
36289
+ label: z.string()
36290
+ }))
35232
36291
  });
35233
36292
  newsletterHydrationSchema = z.object({
35234
36293
  target: z.discriminatedUnion("tag", [
35235
36294
  z.object({
35236
36295
  tag: z.literal("block-source"),
35237
- destinationRef: z.object({
36296
+ sourceRef: z.object({
35238
36297
  tag: z.literal("block_ref"),
35239
- blockId: newsletterSignupBlockIdSchema
36298
+ blockId: mailingListSignupBlockIdSchema
35240
36299
  }).nullable()
35241
36300
  }),
35242
36301
  z.object({
35243
36302
  tag: z.literal("signed-footer-source"),
35244
- destinationRef: z.object({
35245
- tag: z.literal("signed_destination_ref"),
35246
- token: signedNewsletterDestinationRefSchema
36303
+ sourceRef: z.object({
36304
+ tag: z.literal("signed_source_ref"),
36305
+ token: signedMailingListSourceTokenSchema
35247
36306
  })
35248
36307
  }),
35249
- z.object({
35250
- tag: z.literal("legacy-direct-list"),
35251
- listId: z.string().nullable()
35252
- })
36308
+ z.object({ tag: z.literal("preview") })
36309
+ ]),
36310
+ setupRevision: z.number().int().positive().nullable(),
36311
+ choiceProvider: z.enum([
36312
+ "native",
36313
+ "brevo",
36314
+ "mailchimp"
36315
+ ]).nullable(),
36316
+ choicePresentation: z.enum([
36317
+ "hidden",
36318
+ "automatic",
36319
+ "visitor_choice"
35253
36320
  ]),
35254
- preset: newsletterPresetSchema,
35255
- includePhone: z.boolean(),
35256
- tags: z.string().nullable().optional(),
35257
36321
  spamProtectionEnabled: z.boolean().optional()
35258
36322
  });
35259
36323
  newsletterRenderSchema = z.object({
@@ -35272,14 +36336,15 @@ var init_newsletter_form_interactive = __esmMin((() => {
35272
36336
  render: createZodCodec(newsletterRenderSchema)
35273
36337
  },
35274
36338
  buildRender: (source) => {
35275
- const runtimeSource = source.source === "block" ? deriveNewsletterSignupRuntimeSource(source) : null;
36339
+ const targeting = source.targeting ?? { mode: "default" };
36340
+ const presentation = planMailingListChoicePresentation(targeting);
35276
36341
  return {
35277
36342
  display: buildNewsletterDisplay(source),
35278
36343
  hydration: {
35279
36344
  target: projectNewsletterFormHydrationTarget(source),
35280
- preset: source.preset ?? "emailOnly",
35281
- includePhone: source.includePhone ?? false,
35282
- tags: runtimeSource ? runtimeSource.tags : source.tags,
36345
+ setupRevision: source.mailingList?.tag === "configured" ? source.mailingList.revision : null,
36346
+ choiceProvider: targeting.mode === "custom" ? targeting.provider : null,
36347
+ choicePresentation: presentation.tag,
35283
36348
  spamProtectionEnabled: source.spamProtectionEnabled
35284
36349
  }
35285
36350
  };
@@ -35304,7 +36369,6 @@ init_styledSection();
35304
36369
  init_defineBlock();
35305
36370
  init_fragments();
35306
36371
  init_newsletter_form_interactive();
35307
- init_newsletter_signup_destination();
35308
36372
  const stackedComposition = composeFragments([{ fragment: newsletterCopyFragment }, { fragment: newsletterFormFragment }]);
35309
36373
  const stackedLayout = styledSection({
35310
36374
  children: sectionContainer(stackedComposition.layout, {
@@ -36603,19 +37667,18 @@ var init_EventListing_view = __esmMin((() => {
36603
37667
  }));
36604
37668
  //#endregion
36605
37669
  //#region ../blocks/src/system/runtime/nodes/events/shared/AgendaEventCard.tsx
36606
- var AgendaEventCard;
36607
- var init_AgendaEventCard = __esmMin((() => {
36608
- init_domain();
36609
- AgendaEventCard = ({ event, showCapacity, onClick }) => {
36610
- const eventLinkProps = resolveEventLinkProps(event);
36611
- const categoryColor = event.eventCategory?.color || "rgb(var(--tb-accent))";
36612
- const price = formatEventPrice(event);
36613
- const capacity = showCapacity ? formatEventRemainingPlaces(event) : null;
36614
- const isFull = isEventFull(event);
36615
- const title = event.title;
36616
- const timeZone = event.timeZone ?? null;
36617
- const teacherLine = formatEventTeacherLine(event);
36618
- const cardContent = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
37670
+ function AgendaModalCard({ event, showCapacity, calendarTimeZone, onClick }) {
37671
+ const categoryColor = event.eventCategory?.color || "rgb(var(--tb-accent))";
37672
+ const price = formatEventPrice(event);
37673
+ const capacity = showCapacity ? formatEventRemainingPlaces(event) : null;
37674
+ const isFull = isEventFull(event);
37675
+ const teacherLine = formatEventTeacherLine(event);
37676
+ const timeZone = resolveEventTimeZone(event, calendarTimeZone);
37677
+ return /* @__PURE__ */ jsxs("button", {
37678
+ type: "button",
37679
+ className: "event-agenda-card",
37680
+ onClick: () => onClick(event),
37681
+ children: [/* @__PURE__ */ jsx("div", {
36619
37682
  className: "event-agenda-card-indicator",
36620
37683
  style: { backgroundColor: categoryColor },
36621
37684
  "aria-hidden": "true"
@@ -36628,29 +37691,14 @@ var init_AgendaEventCard = __esmMin((() => {
36628
37691
  children: formatTime$2(event.startsAt, { timeZone })
36629
37692
  }), /* @__PURE__ */ jsx("span", {
36630
37693
  className: "event-agenda-card-title",
36631
- children: title
37694
+ children: event.title
36632
37695
  })]
36633
37696
  }), /* @__PURE__ */ jsxs("div", {
36634
- className: "event-agenda-card-details",
37697
+ className: "event-agenda-card-details status-muted",
36635
37698
  children: [
36636
37699
  event.venue && /* @__PURE__ */ jsxs("span", {
36637
37700
  className: "event-agenda-card-venue",
36638
- children: [/* @__PURE__ */ jsxs("svg", {
36639
- className: "event-agenda-card-icon",
36640
- width: "14",
36641
- height: "14",
36642
- viewBox: "0 0 24 24",
36643
- fill: "none",
36644
- stroke: "currentColor",
36645
- strokeWidth: "2",
36646
- strokeLinecap: "round",
36647
- strokeLinejoin: "round",
36648
- children: [/* @__PURE__ */ jsx("path", { d: "M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" }), /* @__PURE__ */ jsx("circle", {
36649
- cx: "12",
36650
- cy: "10",
36651
- r: "3"
36652
- })]
36653
- }), event.venue.name]
37701
+ children: [/* @__PURE__ */ jsx(LocationIcon, {}), event.venue.name]
36654
37702
  }),
36655
37703
  teacherLine && /* @__PURE__ */ jsx("span", {
36656
37704
  className: "event-agenda-card-teacher",
@@ -36661,22 +37709,127 @@ var init_AgendaEventCard = __esmMin((() => {
36661
37709
  children: price
36662
37710
  }),
36663
37711
  capacity && /* @__PURE__ */ jsx("span", {
36664
- className: `event-agenda-card-capacity ${isFull ? "event-agenda-card-capacity--full" : ""}`,
37712
+ className: `event-agenda-card-capacity ${isFull ? "event-agenda-card-capacity--full status-error" : ""}`,
36665
37713
  children: capacity
36666
37714
  })
36667
37715
  ]
36668
37716
  })]
36669
- })] });
36670
- if (onClick) return /* @__PURE__ */ jsx("button", {
36671
- type: "button",
36672
- className: "event-agenda-card",
36673
- onClick: () => onClick(event),
36674
- children: cardContent
37717
+ })]
37718
+ });
37719
+ }
37720
+ function AgendaLinkCard({ event, showCapacity, showVenue, buttonVariant, buttonText, calendarTimeZone }) {
37721
+ const eventLinkProps = resolveEventLinkProps(event);
37722
+ const categoryColor = event.eventCategory?.color || "rgb(var(--tb-accent))";
37723
+ const timeZone = resolveEventTimeZone(event, calendarTimeZone);
37724
+ const teacherLine = formatEventTeacherLine(event);
37725
+ const location = formatEventLocation(event);
37726
+ const duration = formatEventDuration(event);
37727
+ const price = formatEventPrice(event);
37728
+ const capacity = showCapacity ? formatEventRemainingPlaces(event) : null;
37729
+ const cta = resolveEventCta(event, buttonText);
37730
+ const buttonClass = themeButtonClassName({
37731
+ variant: buttonVariant,
37732
+ size: "sm"
37733
+ });
37734
+ return /* @__PURE__ */ jsxs("article", {
37735
+ className: "event-agenda-card event-agenda-card--agenda",
37736
+ children: [
37737
+ /* @__PURE__ */ jsx("div", {
37738
+ className: "event-agenda-card-indicator",
37739
+ style: { backgroundColor: categoryColor },
37740
+ "aria-hidden": "true"
37741
+ }),
37742
+ /* @__PURE__ */ jsx("time", {
37743
+ className: "event-agenda-card-time",
37744
+ dateTime: event.startsAt,
37745
+ children: formatTime$2(event.startsAt, { timeZone })
37746
+ }),
37747
+ /* @__PURE__ */ jsxs("div", {
37748
+ className: "event-agenda-card-content",
37749
+ children: [/* @__PURE__ */ jsx("h5", {
37750
+ className: "event-agenda-card-title",
37751
+ children: /* @__PURE__ */ jsx("a", {
37752
+ ...eventLinkProps,
37753
+ children: event.title
37754
+ })
37755
+ }), /* @__PURE__ */ jsxs("div", {
37756
+ className: "event-agenda-card-details status-muted",
37757
+ children: [
37758
+ showVenue ? /* @__PURE__ */ jsxs("span", {
37759
+ className: "event-agenda-card-location",
37760
+ children: [/* @__PURE__ */ jsx(LocationIcon, {}), location]
37761
+ }) : null,
37762
+ /* @__PURE__ */ jsx("span", {
37763
+ className: "event-agenda-card-duration",
37764
+ children: duration
37765
+ }),
37766
+ teacherLine && /* @__PURE__ */ jsx("span", {
37767
+ className: "event-agenda-card-teacher",
37768
+ children: teacherLine
37769
+ }),
37770
+ capacity && /* @__PURE__ */ jsx("span", {
37771
+ className: `event-agenda-card-capacity ${isEventFull(event) ? "event-agenda-card-capacity--full status-error" : ""}`,
37772
+ children: capacity
37773
+ })
37774
+ ]
37775
+ })]
37776
+ }),
37777
+ /* @__PURE__ */ jsxs("div", {
37778
+ className: "event-agenda-card-action",
37779
+ children: [/* @__PURE__ */ jsx("span", {
37780
+ className: "event-agenda-card-price",
37781
+ children: price
37782
+ }), cta.hidden ? /* @__PURE__ */ jsx("span", {
37783
+ className: "event-agenda-card-status status-muted",
37784
+ children: cta.label
37785
+ }) : /* @__PURE__ */ jsx("a", {
37786
+ href: cta.href,
37787
+ target: cta.external ? "_blank" : void 0,
37788
+ rel: cta.external ? "noopener noreferrer" : void 0,
37789
+ className: `${buttonClass} event-agenda-card-cta`,
37790
+ children: cta.label
37791
+ })]
37792
+ })
37793
+ ]
37794
+ });
37795
+ }
37796
+ function LocationIcon() {
37797
+ return /* @__PURE__ */ jsxs("svg", {
37798
+ className: "event-agenda-card-icon",
37799
+ width: "14",
37800
+ height: "14",
37801
+ viewBox: "0 0 24 24",
37802
+ fill: "none",
37803
+ stroke: "currentColor",
37804
+ strokeWidth: "2",
37805
+ strokeLinecap: "round",
37806
+ strokeLinejoin: "round",
37807
+ "aria-hidden": "true",
37808
+ children: [/* @__PURE__ */ jsx("path", { d: "M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" }), /* @__PURE__ */ jsx("circle", {
37809
+ cx: "12",
37810
+ cy: "10",
37811
+ r: "3"
37812
+ })]
37813
+ });
37814
+ }
37815
+ var AgendaEventCard;
37816
+ var init_AgendaEventCard = __esmMin((() => {
37817
+ init_buttons();
37818
+ init_domain();
37819
+ AgendaEventCard = ({ event, showCapacity, showVenue = true, buttonVariant = "primary", buttonText, calendarTimeZone, onClick }) => {
37820
+ if (onClick) return /* @__PURE__ */ jsx(AgendaModalCard, {
37821
+ event,
37822
+ showCapacity,
37823
+ calendarTimeZone,
37824
+ onClick
36675
37825
  });
36676
- return /* @__PURE__ */ jsx("a", {
36677
- ...eventLinkProps,
36678
- className: "event-agenda-card",
36679
- children: cardContent
37826
+ return /* @__PURE__ */ jsx(AgendaLinkCard, {
37827
+ event,
37828
+ showCapacity,
37829
+ showVenue,
37830
+ buttonVariant,
37831
+ buttonText,
37832
+ calendarTimeZone
36680
37833
  });
36681
37834
  };
36682
37835
  }));
@@ -36705,11 +37858,13 @@ var init_WeekAgendaView = __esmMin((() => {
36705
37858
  "Friday",
36706
37859
  "Saturday"
36707
37860
  ];
36708
- WeekAgendaView = ({ days, events, showCapacity, emptyMessage = "No events scheduled", calendarTimeZone, today: currentDate }) => {
37861
+ WeekAgendaView = ({ days, events, showCapacity, showVenue = true, emptyMessage = "No events scheduled", showEmptyState, calendarTimeZone, today: currentDate, buttonVariant = "primary", buttonText }) => {
36709
37862
  const eventsByDate = groupEventsByDate(events, calendarTimeZone);
36710
- return /* @__PURE__ */ jsx("div", {
37863
+ const populatedDays = days.filter((date) => (eventsByDate.get(formatDateKey$1(date))?.length ?? 0) > 0);
37864
+ return /* @__PURE__ */ jsxs("div", {
36711
37865
  className: "event-agenda-week",
36712
- children: days.map((date) => {
37866
+ "data-agenda-state": populatedDays.length > 0 ? "populated" : showEmptyState ? "empty" : "loading",
37867
+ children: [populatedDays.map((date) => {
36713
37868
  const dateKey = formatDateKey$1(date);
36714
37869
  const dayEvents = eventsByDate.get(dateKey) || [];
36715
37870
  const today = isToday(date, currentDate);
@@ -36726,19 +37881,23 @@ var init_WeekAgendaView = __esmMin((() => {
36726
37881
  })
36727
37882
  }), /* @__PURE__ */ jsx("div", {
36728
37883
  className: "event-agenda-day-content",
36729
- children: dayEvents.length === 0 ? /* @__PURE__ */ jsx("p", {
36730
- className: "event-agenda-day-empty",
36731
- children: emptyMessage
36732
- }) : /* @__PURE__ */ jsx("div", {
37884
+ children: /* @__PURE__ */ jsx("div", {
36733
37885
  className: "event-agenda-day-events",
36734
37886
  children: dayEvents.map((event) => /* @__PURE__ */ jsx(AgendaEventCard, {
36735
37887
  event,
36736
- showCapacity
37888
+ showCapacity,
37889
+ showVenue,
37890
+ buttonVariant,
37891
+ buttonText,
37892
+ calendarTimeZone
36737
37893
  }, event.occurrenceId || event.id))
36738
37894
  })
36739
37895
  })]
36740
37896
  }, dateKey);
36741
- })
37897
+ }), populatedDays.length === 0 && showEmptyState ? /* @__PURE__ */ jsx("p", {
37898
+ className: "event-agenda-empty",
37899
+ children: emptyMessage
37900
+ }) : null]
36742
37901
  });
36743
37902
  };
36744
37903
  }));
@@ -36791,8 +37950,8 @@ function buildWeekBoardViewProps(display, days, navigation, events = display.eve
36791
37950
  * Format an event's start–end as a compact range, merging the shared meridiem.
36792
37951
  * "6:00 PM" + "7:00 PM" -> "6:00 – 7:00 PM"; "9:30 AM" + "10:15 AM" -> "9:30 – 10:15 AM".
36793
37952
  */
36794
- function formatCompactTimeRange(event) {
36795
- const timeZone = event.timeZone ?? null;
37953
+ function formatCompactTimeRange(event, calendarTimeZone) {
37954
+ const timeZone = resolveEventTimeZone(event, calendarTimeZone);
36796
37955
  const start = formatTime$2(event.startsAt, { timeZone });
36797
37956
  const end = formatTime$2(event.endsAt, { timeZone });
36798
37957
  const startMeridiem = start.slice(-2);
@@ -36830,7 +37989,7 @@ var init_WeekBoardView = __esmMin((() => {
36830
37989
  label: "Waitlist"
36831
37990
  }
36832
37991
  ];
36833
- WeekBoardCard = ({ event, showCapacity }) => {
37992
+ WeekBoardCard = ({ event, showCapacity, calendarTimeZone }) => {
36834
37993
  const linkProps = resolveEventLinkProps(event);
36835
37994
  const { status, label } = getEventAvailabilityStatus(event);
36836
37995
  const pill = showCapacity ? label : null;
@@ -36845,7 +38004,7 @@ var init_WeekBoardView = __esmMin((() => {
36845
38004
  }),
36846
38005
  /* @__PURE__ */ jsx("span", {
36847
38006
  className: "event-week-board-card-time",
36848
- children: formatCompactTimeRange(event)
38007
+ children: formatCompactTimeRange(event, calendarTimeZone)
36849
38008
  }),
36850
38009
  pill ? /* @__PURE__ */ jsx("span", {
36851
38010
  className: "event-week-board-card-pill",
@@ -36922,7 +38081,7 @@ var init_WeekBoardView = __esmMin((() => {
36922
38081
  })]
36923
38082
  });
36924
38083
  };
36925
- WeekBoardGrid = ({ days, eventsByDate, showCapacity, today: currentDate }) => /* @__PURE__ */ jsx("div", {
38084
+ WeekBoardGrid = ({ days, eventsByDate, showCapacity, calendarTimeZone, today: currentDate }) => /* @__PURE__ */ jsx("div", {
36926
38085
  className: "event-week-board-grid",
36927
38086
  children: days.map((date) => {
36928
38087
  const dateKey = formatDateKey$1(date);
@@ -36943,7 +38102,8 @@ var init_WeekBoardView = __esmMin((() => {
36943
38102
  className: "event-week-board-day-body",
36944
38103
  children: dayEvents.map((event) => /* @__PURE__ */ jsx(WeekBoardCard, {
36945
38104
  event,
36946
- showCapacity
38105
+ showCapacity,
38106
+ calendarTimeZone
36947
38107
  }, event.occurrenceId || event.id))
36948
38108
  })]
36949
38109
  }, dateKey);
@@ -37009,6 +38169,7 @@ var init_WeekBoardView = __esmMin((() => {
37009
38169
  days,
37010
38170
  eventsByDate,
37011
38171
  showCapacity,
38172
+ calendarTimeZone,
37012
38173
  today
37013
38174
  }),
37014
38175
  /* @__PURE__ */ jsx(WeekBoardFooter, {
@@ -37025,6 +38186,7 @@ var init_WeekBoardView = __esmMin((() => {
37025
38186
  //#endregion
37026
38187
  //#region ../blocks/src/system/runtime/nodes/events/shared/timetableModel.ts
37027
38188
  function buildTimetableModel(input) {
38189
+ const calendarTimeZone = input.calendarTimeZone;
37028
38190
  const generic = buildTimetableModel$1({
37029
38191
  items: input.events,
37030
38192
  viewDate: input.viewDate,
@@ -37033,7 +38195,7 @@ function buildTimetableModel(input) {
37033
38195
  getId: (event) => event.id,
37034
38196
  getStartsAt: (event) => event.startsAt,
37035
38197
  getEndsAt: (event) => event.endsAt,
37036
- getTimeZone: (event) => event.timeZone ?? "UTC",
38198
+ getTimeZone: (event) => resolveEventTimeZone(event, calendarTimeZone),
37037
38199
  getColor: (event) => event.eventCategory?.color ?? null,
37038
38200
  getOrderKey: (event) => `${event.title}\u0000${event.id}`
37039
38201
  });
@@ -37049,11 +38211,11 @@ function buildTimetableModel(input) {
37049
38211
  label: formatDayLabel(day.date),
37050
38212
  shortLabel: formatShortDayLabel(day.date),
37051
38213
  isToday: day.isToday,
37052
- events: day.cells.map(toEventCell)
38214
+ events: day.cells.map((cell) => toEventCell(cell, calendarTimeZone))
37053
38215
  }))
37054
38216
  };
37055
38217
  }
37056
- function toEventCell(cell) {
38218
+ function toEventCell(cell, calendarTimeZone) {
37057
38219
  const event = cell.item;
37058
38220
  const capacity = formatTimetableCapacity(event);
37059
38221
  return {
@@ -37065,7 +38227,7 @@ function toEventCell(cell) {
37065
38227
  laneIndex: cell.laneIndex,
37066
38228
  laneCount: cell.laneCount,
37067
38229
  categoryColor: cell.color ?? DEFAULT_EVENT_CELL_COLOR,
37068
- timeLabel: formatEventTimeRange(event),
38230
+ timeLabel: formatEventTimeRange(event, calendarTimeZone),
37069
38231
  teacherLine: formatEventTeacherLine(event),
37070
38232
  capacityLabel: capacity.label,
37071
38233
  isFull: capacity.isFull
@@ -37077,8 +38239,8 @@ function formatTimetableCapacity(event) {
37077
38239
  isFull: isEventFull(event)
37078
38240
  };
37079
38241
  }
37080
- function formatEventTimeRange(event) {
37081
- const timeZone = event.timeZone ?? null;
38242
+ function formatEventTimeRange(event, calendarTimeZone) {
38243
+ const timeZone = resolveEventTimeZone(event, calendarTimeZone);
37082
38244
  return `${formatTime$2(event.startsAt, { timeZone })} - ${formatTime$2(event.endsAt, { timeZone })}`;
37083
38245
  }
37084
38246
  function formatDayLabel(date) {
@@ -37112,12 +38274,11 @@ init_WeekBoardView();
37112
38274
  init_shared$3();
37113
38275
  init_timetableModel();
37114
38276
  init_buttons();
38277
+ init_CalendarDayHeaders();
38278
+ init_domain();
37115
38279
  function assertNeverDisplayMode(value) {
37116
38280
  throw new Error(`Unsupported event-calendar displayMode: ${String(value)}`);
37117
38281
  }
37118
- function getEventTimeZone(event) {
37119
- return event.timeZone ?? null;
37120
- }
37121
38282
  function renderEventCard(event, display) {
37122
38283
  return renderEventListItem(event, display);
37123
38284
  }
@@ -37168,126 +38329,117 @@ function renderCalendarSsr(display, hydration) {
37168
38329
  return /* @__PURE__ */ jsxs("div", {
37169
38330
  className: clsx("event-calendar", display.className ?? void 0),
37170
38331
  "data-block": "event-calendar",
37171
- children: [
37172
- /* @__PURE__ */ jsxs("div", {
37173
- className: "event-calendar-header",
37174
- children: [/* @__PURE__ */ jsxs("div", {
37175
- className: "event-calendar-nav",
37176
- children: [
37177
- /* @__PURE__ */ jsx("button", {
37178
- type: "button",
37179
- className: "event-calendar-nav-btn",
37180
- "aria-label": calendarView === "week" ? "Previous week" : "Previous month",
37181
- children: /* @__PURE__ */ jsx("svg", {
37182
- width: "20",
37183
- height: "20",
37184
- fill: "none",
37185
- stroke: "currentColor",
38332
+ children: [/* @__PURE__ */ jsxs("div", {
38333
+ className: "event-calendar-header",
38334
+ children: [/* @__PURE__ */ jsxs("div", {
38335
+ className: "event-calendar-nav",
38336
+ children: [
38337
+ /* @__PURE__ */ jsx("button", {
38338
+ type: "button",
38339
+ className: "event-calendar-nav-btn",
38340
+ "aria-label": calendarView === "week" ? "Previous week" : "Previous month",
38341
+ children: /* @__PURE__ */ jsx("svg", {
38342
+ width: "20",
38343
+ height: "20",
38344
+ fill: "none",
38345
+ stroke: "currentColor",
38346
+ strokeWidth: 2,
38347
+ viewBox: "0 0 24 24",
38348
+ children: /* @__PURE__ */ jsx("path", {
38349
+ strokeLinecap: "round",
38350
+ strokeLinejoin: "round",
37186
38351
  strokeWidth: 2,
37187
- viewBox: "0 0 24 24",
37188
- children: /* @__PURE__ */ jsx("path", {
37189
- strokeLinecap: "round",
37190
- strokeLinejoin: "round",
37191
- strokeWidth: 2,
37192
- d: "M15 19l-7-7 7-7"
37193
- })
38352
+ d: "M15 19l-7-7 7-7"
37194
38353
  })
37195
- }),
37196
- /* @__PURE__ */ jsx("h3", {
37197
- className: "event-calendar-title",
37198
- children: viewport.title
37199
- }),
37200
- /* @__PURE__ */ jsx("button", {
37201
- type: "button",
37202
- className: "event-calendar-nav-btn",
37203
- "aria-label": calendarView === "week" ? "Next week" : "Next month",
37204
- children: /* @__PURE__ */ jsx("svg", {
37205
- width: "20",
37206
- height: "20",
37207
- fill: "none",
37208
- stroke: "currentColor",
38354
+ })
38355
+ }),
38356
+ /* @__PURE__ */ jsx("h3", {
38357
+ className: "event-calendar-title",
38358
+ children: viewport.title
38359
+ }),
38360
+ /* @__PURE__ */ jsx("button", {
38361
+ type: "button",
38362
+ className: "event-calendar-nav-btn",
38363
+ "aria-label": calendarView === "week" ? "Next week" : "Next month",
38364
+ children: /* @__PURE__ */ jsx("svg", {
38365
+ width: "20",
38366
+ height: "20",
38367
+ fill: "none",
38368
+ stroke: "currentColor",
38369
+ strokeWidth: 2,
38370
+ viewBox: "0 0 24 24",
38371
+ children: /* @__PURE__ */ jsx("path", {
38372
+ strokeLinecap: "round",
38373
+ strokeLinejoin: "round",
37209
38374
  strokeWidth: 2,
37210
- viewBox: "0 0 24 24",
37211
- children: /* @__PURE__ */ jsx("path", {
37212
- strokeLinecap: "round",
37213
- strokeLinejoin: "round",
37214
- strokeWidth: 2,
37215
- d: "M9 5l7 7-7 7"
37216
- })
38375
+ d: "M9 5l7 7-7 7"
37217
38376
  })
37218
38377
  })
37219
- ]
37220
- }), /* @__PURE__ */ jsx("button", {
37221
- type: "button",
37222
- className: themeButtonClassName({
37223
- variant: display.buttonVariant,
37224
- size: "sm"
37225
- }),
37226
- children: "Today"
37227
- })]
37228
- }),
37229
- viewport.kind === "week" ? /* @__PURE__ */ jsx(WeekAgendaView, {
37230
- days: viewport.days,
37231
- events: [...display.events],
37232
- emptyMessage: display.emptyMessage,
37233
- showCapacity: display.showCapacity,
37234
- calendarTimeZone: hydration.calendarContext.timeZone,
37235
- today: hydration.calendarContext.initialToday
37236
- }) : /* @__PURE__ */ jsxs("div", {
37237
- className: "event-calendar-container",
37238
- children: [/* @__PURE__ */ jsx("div", {
37239
- className: "event-calendar-day-headers",
37240
- children: dayNames.map((day) => /* @__PURE__ */ jsx("div", {
37241
- className: "event-calendar-day-header",
37242
- children: day
37243
- }, day))
37244
- }), /* @__PURE__ */ jsx("div", {
37245
- className: "event-calendar-grid",
37246
- children: viewport.days.map((date) => {
37247
- const dateKey = formatDateKey$1(date);
37248
- const dayEvents = eventsByDate.get(dateKey) || [];
37249
- const isCurrentMonth = date.month === viewDate.month;
37250
- const today = isToday(date, hydration.calendarContext.initialToday);
37251
- return /* @__PURE__ */ jsxs("div", {
37252
- className: clsx("event-calendar-day", !isCurrentMonth && "event-calendar-day--other-month", today && "event-calendar-day--today"),
37253
- children: [/* @__PURE__ */ jsx("div", {
37254
- className: "event-calendar-day-number",
37255
- children: date.day
37256
- }), /* @__PURE__ */ jsxs("div", {
37257
- className: "event-calendar-events",
37258
- children: [dayEvents.slice(0, 3).map((event) => /* @__PURE__ */ jsxs("a", {
37259
- ...resolveEventLinkProps(event),
37260
- className: "event-calendar-event",
37261
- title: `${event.title} at ${formatTime$2(event.startsAt, { timeZone: getEventTimeZone(event) })}`,
37262
- children: [
37263
- /* @__PURE__ */ jsx("span", {
37264
- className: "event-calendar-event-time",
37265
- children: formatTime$2(event.startsAt, { timeZone: getEventTimeZone(event) })
37266
- }),
37267
- " ",
37268
- /* @__PURE__ */ jsx("span", {
37269
- className: "event-calendar-event-title",
37270
- children: event.title
37271
- })
37272
- ]
37273
- }, event.occurrenceId || event.id)), dayEvents.length > 3 ? /* @__PURE__ */ jsxs("div", {
37274
- className: "event-calendar-more",
37275
- children: [
37276
- "+",
37277
- dayEvents.length - 3,
37278
- " more"
37279
- ]
37280
- }) : null]
37281
- })]
37282
- }, dateKey);
37283
38378
  })
37284
- })]
37285
- }),
37286
- viewport.kind === "month" && display.events.length === 0 ? /* @__PURE__ */ jsx("p", {
37287
- className: "event-calendar-empty",
37288
- children: display.emptyMessage
37289
- }) : null
37290
- ]
38379
+ ]
38380
+ }), /* @__PURE__ */ jsx("button", {
38381
+ type: "button",
38382
+ className: themeButtonClassName({
38383
+ variant: display.buttonVariant,
38384
+ size: "sm"
38385
+ }),
38386
+ children: "Today"
38387
+ })]
38388
+ }), viewport.kind === "week" ? /* @__PURE__ */ jsx(WeekAgendaView, {
38389
+ days: viewport.days,
38390
+ events: [...display.events],
38391
+ emptyMessage: display.emptyMessage,
38392
+ showCapacity: display.showCapacity,
38393
+ showVenue: display.showVenue,
38394
+ showEmptyState: false,
38395
+ buttonVariant: display.buttonVariant,
38396
+ buttonText: display.buttonText,
38397
+ calendarTimeZone: hydration.calendarContext.timeZone,
38398
+ today: hydration.calendarContext.initialToday
38399
+ }) : /* @__PURE__ */ jsxs("div", {
38400
+ className: "event-calendar-container",
38401
+ children: [/* @__PURE__ */ jsx(CalendarDayHeaders, { dayNames }), /* @__PURE__ */ jsx("div", {
38402
+ className: "event-calendar-grid",
38403
+ children: viewport.days.map((date) => {
38404
+ const dateKey = formatDateKey$1(date);
38405
+ const dayEvents = eventsByDate.get(dateKey) || [];
38406
+ const isCurrentMonth = date.month === viewDate.month;
38407
+ const today = isToday(date, hydration.calendarContext.initialToday);
38408
+ return /* @__PURE__ */ jsxs("div", {
38409
+ className: clsx("event-calendar-day", !isCurrentMonth && "event-calendar-day--other-month", today && "event-calendar-day--today"),
38410
+ children: [/* @__PURE__ */ jsx("div", {
38411
+ className: "event-calendar-day-number",
38412
+ children: date.day
38413
+ }), /* @__PURE__ */ jsxs("div", {
38414
+ className: "event-calendar-events",
38415
+ children: [dayEvents.slice(0, 3).map((event) => /* @__PURE__ */ jsxs("a", {
38416
+ ...resolveEventLinkProps(event),
38417
+ className: "event-calendar-event",
38418
+ title: `${event.title} at ${formatTime$2(event.startsAt, { timeZone: resolveEventTimeZone(event, hydration.calendarContext.timeZone) })}`,
38419
+ children: [
38420
+ /* @__PURE__ */ jsx("span", {
38421
+ className: "event-calendar-event-time",
38422
+ children: formatTime$2(event.startsAt, { timeZone: resolveEventTimeZone(event, hydration.calendarContext.timeZone) })
38423
+ }),
38424
+ " ",
38425
+ /* @__PURE__ */ jsx("span", {
38426
+ className: "event-calendar-event-title",
38427
+ children: event.title
38428
+ })
38429
+ ]
38430
+ }, event.occurrenceId || event.id)), dayEvents.length > 3 ? /* @__PURE__ */ jsxs("div", {
38431
+ className: "event-calendar-more",
38432
+ children: [
38433
+ "+",
38434
+ dayEvents.length - 3,
38435
+ " more"
38436
+ ]
38437
+ }) : null]
38438
+ })]
38439
+ }, dateKey);
38440
+ })
38441
+ })]
38442
+ })]
37291
38443
  });
37292
38444
  }
37293
38445
  function renderTimetableSsr(display, hydration) {
@@ -37301,7 +38453,8 @@ function renderTimetableSsr(display, hydration) {
37301
38453
  events: [...display.events],
37302
38454
  viewDate,
37303
38455
  startOfWeek: display.startOfWeek,
37304
- today: hydration.calendarContext.initialToday
38456
+ today: hydration.calendarContext.initialToday,
38457
+ calendarTimeZone: hydration.calendarContext.timeZone
37305
38458
  });
37306
38459
  const selectedDayKey = model.days.find((day) => day.isToday)?.dateKey ?? model.days[0]?.dateKey ?? "";
37307
38460
  return /* @__PURE__ */ jsxs("div", {
@@ -37902,24 +39055,25 @@ init_newsletter_form_interactive();
37902
39055
  * Uses the islands architecture pattern to hydrate on the client.
37903
39056
  */
37904
39057
  function NewsletterFormSSR(props) {
37905
- const { siteId, apiBaseUrl, preset = "emailOnly", includePhone, buttonLabel = "Subscribe", buttonVariant = "primary", successMessage, privacyNote, tags, spamProtectionEnabled, className } = props;
39058
+ const { siteId, apiBaseUrl, buttonVariant = "primary", spamProtectionEnabled, className } = props;
37906
39059
  const blockId = props.source === "block" ? props.blockId : null;
37907
39060
  const islandProps = buildNewsletterFormInteractiveIslandProps({
37908
39061
  ...props,
37909
39062
  siteId,
37910
39063
  apiBaseUrl,
37911
- preset,
37912
- includePhone,
37913
- buttonLabel,
37914
39064
  buttonVariant,
37915
- successMessage,
37916
- privacyNote,
37917
- tags,
37918
39065
  spamProtectionEnabled,
37919
39066
  className
37920
39067
  });
37921
39068
  const display = islandProps.render.display;
37922
39069
  const fields = display.fields;
39070
+ if (display.availability === "unavailable") return /* @__PURE__ */ jsx("div", {
39071
+ className: clsx("newsletter-form-ssr", className),
39072
+ children: /* @__PURE__ */ jsx("p", {
39073
+ role: "status",
39074
+ children: "Mailing-list signup is not available right now."
39075
+ })
39076
+ });
37923
39077
  const renderField = (field) => {
37924
39078
  const inputId = `newsletter_${field.id}`;
37925
39079
  return /* @__PURE__ */ jsxs("div", {
@@ -37960,17 +39114,31 @@ function NewsletterFormSSR(props) {
37960
39114
  }),
37961
39115
  /* @__PURE__ */ jsxs("div", {
37962
39116
  className: "newsletter-form-fields",
37963
- children: [fields.map(renderField), /* @__PURE__ */ jsx("div", {
37964
- className: "newsletter-submit",
37965
- children: /* @__PURE__ */ jsx("button", {
37966
- type: "submit",
37967
- className: themeButtonClassName({
37968
- variant: display.buttonVariant,
37969
- size: "md"
37970
- }),
37971
- children: display.buttonLabel
39117
+ children: [
39118
+ fields.map(renderField),
39119
+ islandProps.render.hydration.choicePresentation === "visitor_choice" ? /* @__PURE__ */ jsxs("fieldset", {
39120
+ className: "newsletter-topics",
39121
+ children: [/* @__PURE__ */ jsx("legend", { children: "What would you like to hear about?" }), display.choices.map((choice) => /* @__PURE__ */ jsxs("label", {
39122
+ className: "newsletter-topic-choice",
39123
+ children: [/* @__PURE__ */ jsx("input", {
39124
+ type: "checkbox",
39125
+ name: "mailingListChoice",
39126
+ value: choice.id
39127
+ }), choice.label]
39128
+ }, choice.id))]
39129
+ }) : null,
39130
+ /* @__PURE__ */ jsx("div", {
39131
+ className: "newsletter-submit",
39132
+ children: /* @__PURE__ */ jsx("button", {
39133
+ type: "submit",
39134
+ className: themeButtonClassName({
39135
+ variant: display.buttonVariant,
39136
+ size: "md"
39137
+ }),
39138
+ children: display.buttonLabel
39139
+ })
37972
39140
  })
37973
- })]
39141
+ ]
37974
39142
  }),
37975
39143
  display.privacyNote && /* @__PURE__ */ jsx("p", {
37976
39144
  className: "newsletter-privacy-note",
@@ -38155,6 +39323,7 @@ const serverComponentRegistry = {
38155
39323
  carousel: CarouselNodeSSR,
38156
39324
  accordion: AccordionNodeSSR,
38157
39325
  accordionItem: AccordionItemNodeSSR,
39326
+ "appointment-services": AppointmentServicesNode,
38158
39327
  "booking-form": BookingFormSSR,
38159
39328
  "event-details": EventDetailsSSR,
38160
39329
  "location-map": LocationMapSSR,
@@ -44547,7 +45716,6 @@ function buildCheckoutReturnUrls(paramName, anchorId, returnParams = {}) {
44547
45716
  };
44548
45717
  }
44549
45718
  var init_checkoutUrls = __esmMin((() => {}));
44550
- var init_bookingRoute = __esmMin((() => {}));
44551
45719
  //#endregion
44552
45720
  //#region ../blocks/src/system/runtime/shared/utils/checkoutRoute.ts
44553
45721
  function resolveDedicatedCheckoutTarget(pathname) {
@@ -46517,11 +47685,46 @@ var init_orderInstalmentPlan = __esmMin((() => {
46517
47685
  init_src$2();
46518
47686
  init_assertNever();
46519
47687
  init_bookingInstalmentSchedule();
47688
+ })), STRIPE_COMMISSION_FREE_REASONS, historicalContext, percentSchema;
47689
+ var init_stripeCommissionMetadata = __esmMin((() => {
47690
+ init_src$2();
47691
+ STRIPE_COMMISSION_FREE_REASONS = [
47692
+ "managed_billing",
47693
+ "no_commission_plan",
47694
+ "billing_evidence_invalid",
47695
+ "fee_rounds_to_zero",
47696
+ "non_commissionable_scope",
47697
+ "payment_not_stripe"
47698
+ ];
47699
+ historicalContext = {
47700
+ currency: z.string().refine((value) => parseCurrencyCode(value) !== null).optional(),
47701
+ sourcePlanId: z.string().trim().min(1).optional()
47702
+ };
47703
+ percentSchema = z.number().finite().min(0).max(100);
47704
+ z.discriminatedUnion("kind", [
47705
+ z.object({
47706
+ kind: z.literal("commission_free"),
47707
+ reason: z.enum(STRIPE_COMMISSION_FREE_REASONS),
47708
+ ...historicalContext
47709
+ }),
47710
+ z.object({
47711
+ kind: z.literal("application_fee_amount"),
47712
+ amountCents: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER),
47713
+ percent: percentSchema,
47714
+ ...historicalContext
47715
+ }),
47716
+ z.object({
47717
+ kind: z.literal("application_fee_percent"),
47718
+ percent: percentSchema,
47719
+ ...historicalContext
47720
+ })
47721
+ ]);
46520
47722
  }));
46521
47723
  var init_eventOrderOptionSnapshot = __esmMin((() => {
46522
47724
  init_src$2();
46523
47725
  }));
46524
47726
  var init_orderItemMetadata = __esmMin((() => {
47727
+ init_stripeCommissionMetadata();
46525
47728
  init_src$2();
46526
47729
  init_eventOrderOptionSnapshot();
46527
47730
  }));
@@ -46739,6 +47942,7 @@ var init_purchase = __esmMin((() => {
46739
47942
  init_stripeCheckoutReturnUrl();
46740
47943
  init_stateTransitions();
46741
47944
  init_event_registration_errors();
47945
+ init_stripeCommissionMetadata();
46742
47946
  }));
46743
47947
  //#endregion
46744
47948
  //#region ../blocks/src/system/runtime/shared/useWaitlistClaim.state.ts
@@ -48361,6 +49565,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
48361
49565
  isMembershipFastTrack,
48362
49566
  waitlistClaim,
48363
49567
  eligibility,
49568
+ registrationOptionsState: eligibilityResult.state,
48364
49569
  eligibilityLoading,
48365
49570
  eligibilityError,
48366
49571
  existingRegistration: existingRegistrationResult.registration,
@@ -48830,6 +50035,8 @@ function isFullWithNoWaitlist(event, attendanceMode) {
48830
50035
  }
48831
50036
  function resolveTicketSelectionContinueLabel(input) {
48832
50037
  if (input.isCheckingExistingRegistration) return "Checking registration...";
50038
+ if (input.registrationOptionsPending) return "Checking availability...";
50039
+ if (input.registrationOptionsFailed) return "Availability unavailable";
48833
50040
  if (input.hasExistingRegistration) return resolveExistingRegistrationLabel(input.wizard);
48834
50041
  if (input.isSoldOutWithoutWaitlist) return "Sold out";
48835
50042
  if (input.ticketTypeSelectionBlocked) return "Choose a ticket";
@@ -48839,14 +50046,17 @@ function SelectTicketsActions(props) {
48839
50046
  const { wizard } = props;
48840
50047
  const hasWaitlistClaim = wizard.waitlistClaim.claim !== null;
48841
50048
  const currentEvent = wizard.selectedEvent ?? wizard.preSelectedEvent;
50049
+ const registrationOptionsPending = wizard.registrationOptionsState.tag === "idle" || wizard.registrationOptionsState.tag === "loading";
50050
+ const registrationOptionsFailed = wizard.registrationOptionsState.tag === "failed";
48842
50051
  const isSoldOutWithoutWaitlist = !hasWaitlistClaim && isFullWithNoWaitlist(currentEvent, wizard.selectedAttendanceMode);
48843
- const isWaitingForEligibility = wizard.portalAuthState === "authenticated" && wizard.eligibilityLoading;
48844
50052
  const isCheckingExistingRegistration = wizard.portalAuthState === "authenticated" && wizard.existingRegistrationLoading;
48845
50053
  const hasExistingRegistration = isExistingRegistrationBlocking$1(wizard);
48846
50054
  const ticketTypeSelectionBlocked = wizard.ticketTypeSelectionRequired && !wizard.hasValidTicketSelection;
48847
- const isContinueDisabled = isWaitingForEligibility || isCheckingExistingRegistration || hasExistingRegistration || isSoldOutWithoutWaitlist || ticketTypeSelectionBlocked;
50055
+ const isContinueDisabled = registrationOptionsPending || registrationOptionsFailed || isCheckingExistingRegistration || hasExistingRegistration || isSoldOutWithoutWaitlist || ticketTypeSelectionBlocked;
48848
50056
  const continueLabel = resolveTicketSelectionContinueLabel({
48849
50057
  wizard,
50058
+ registrationOptionsPending,
50059
+ registrationOptionsFailed,
48850
50060
  isCheckingExistingRegistration,
48851
50061
  hasExistingRegistration,
48852
50062
  isSoldOutWithoutWaitlist,
@@ -48864,7 +50074,7 @@ function SelectTicketsActions(props) {
48864
50074
  onClick: () => wizard.setStep("enter-details"),
48865
50075
  disabled: isContinueDisabled,
48866
50076
  className: props.buttonClass,
48867
- children: isWaitingForEligibility ? /* @__PURE__ */ jsxs("span", {
50077
+ children: registrationOptionsPending ? /* @__PURE__ */ jsxs("span", {
48868
50078
  className: "er-button-with-spinner",
48869
50079
  children: [/* @__PURE__ */ jsx(SpinnerNode, {
48870
50080
  size: "xs",
@@ -105699,7 +106909,7 @@ var init_event_registration_client = __esmMin((() => {
105699
106909
  * Loads Leaflet CSS/JS from CDN to avoid bundling in the blocks package.
105700
106910
  */
105701
106911
  function isLeafletApi(value) {
105702
- if (!isRecord$16(value)) return false;
106912
+ if (!isRecord$15(value)) return false;
105703
106913
  return typeof value.map === "function" && typeof value.tileLayer === "function" && typeof value.marker === "function";
105704
106914
  }
105705
106915
  function loadLeaflet() {
@@ -112483,10 +113693,91 @@ function projectCalendarLoadState(state, months) {
112483
113693
  }
112484
113694
  var init_useCalendarEvents_state = __esmMin((() => {
112485
113695
  init_src$2();
112486
- init_domain();
113696
+ init_src$3();
112487
113697
  init_calendarWindow();
112488
113698
  }));
112489
113699
  //#endregion
113700
+ //#region ../blocks/src/system/runtime/hooks/useCalendarToday.ts
113701
+ /** Find the first instant after `now` whose site-local civil date differs. */
113702
+ function findNextCalendarDateBoundary(now, timeZone, resolveDate = getLocalScheduleDate) {
113703
+ const currentDate = resolveDate(now, timeZone);
113704
+ const lowerBound = now.getTime();
113705
+ let upperBound = lowerBound + SEARCH_STEP_MS;
113706
+ const searchLimit = lowerBound + MAX_BOUNDARY_SEARCH_MS;
113707
+ while (upperBound <= searchLimit && isSameCalendarDay(resolveDate(new Date(upperBound), timeZone), currentDate)) upperBound += SEARCH_STEP_MS;
113708
+ if (upperBound > searchLimit) return {
113709
+ kind: "retry",
113710
+ delayMs: SEARCH_STEP_MS
113711
+ };
113712
+ let lower = lowerBound;
113713
+ let upper = upperBound;
113714
+ while (upper - lower > 1) {
113715
+ const midpoint = lower + Math.floor((upper - lower) / 2);
113716
+ if (isSameCalendarDay(resolveDate(new Date(midpoint), timeZone), currentDate)) lower = midpoint;
113717
+ else upper = midpoint;
113718
+ }
113719
+ return {
113720
+ kind: "found",
113721
+ instant: new Date(upper)
113722
+ };
113723
+ }
113724
+ function useCalendarToday(context, clock = systemCalendarTodayClock) {
113725
+ const [today, setToday] = useState(context.initialToday);
113726
+ const now = clock.now;
113727
+ const resolveDate = clock.resolveDate ?? getLocalScheduleDate;
113728
+ const refreshToday = useCallback(() => {
113729
+ const next = resolveDate(now(), context.timeZone);
113730
+ setToday((current) => isSameCalendarDay(current, next) ? current : next);
113731
+ }, [
113732
+ context.timeZone,
113733
+ now,
113734
+ resolveDate
113735
+ ]);
113736
+ useEffect(() => {
113737
+ let timeoutId;
113738
+ const scheduleBoundary = () => {
113739
+ if (timeoutId !== void 0) clearTimeout(timeoutId);
113740
+ const currentInstant = now();
113741
+ const boundary = findNextCalendarDateBoundary(currentInstant, context.timeZone, resolveDate);
113742
+ const boundaryDelay = boundary.kind === "found" ? boundary.instant.getTime() - currentInstant.getTime() : boundary.delayMs;
113743
+ timeoutId = setTimeout(() => {
113744
+ refreshToday();
113745
+ scheduleBoundary();
113746
+ }, Math.min(Math.max(1, boundaryDelay), MAX_TIMER_DELAY_MS));
113747
+ };
113748
+ const reconcileAndReschedule = () => {
113749
+ refreshToday();
113750
+ scheduleBoundary();
113751
+ };
113752
+ const handleVisibilityChange = () => {
113753
+ if (document.visibilityState === "visible") reconcileAndReschedule();
113754
+ };
113755
+ reconcileAndReschedule();
113756
+ document.addEventListener("visibilitychange", handleVisibilityChange);
113757
+ window.addEventListener("focus", reconcileAndReschedule);
113758
+ return () => {
113759
+ if (timeoutId !== void 0) clearTimeout(timeoutId);
113760
+ document.removeEventListener("visibilitychange", handleVisibilityChange);
113761
+ window.removeEventListener("focus", reconcileAndReschedule);
113762
+ };
113763
+ }, [
113764
+ context.timeZone,
113765
+ now,
113766
+ refreshToday,
113767
+ resolveDate
113768
+ ]);
113769
+ return today;
113770
+ }
113771
+ var SEARCH_STEP_MS, MAX_BOUNDARY_SEARCH_MS, MAX_TIMER_DELAY_MS, systemCalendarTodayClock;
113772
+ var init_useCalendarToday = __esmMin((() => {
113773
+ init_src$2();
113774
+ init_src$3();
113775
+ SEARCH_STEP_MS = 3600 * 1e3;
113776
+ MAX_BOUNDARY_SEARCH_MS = 72 * SEARCH_STEP_MS;
113777
+ MAX_TIMER_DELAY_MS = 2147483647;
113778
+ systemCalendarTodayClock = { now: () => /* @__PURE__ */ new Date() };
113779
+ }));
113780
+ //#endregion
112490
113781
  //#region ../blocks/src/system/runtime/hooks/useCalendarEvents.ts
112491
113782
  /**
112492
113783
  * Hook for calendar event management with month-based caching
@@ -112494,7 +113785,7 @@ var init_useCalendarEvents_state = __esmMin((() => {
112494
113785
  * Uses the Block API Client for type-safe API calls.
112495
113786
  * Must be used within a BlockApiProvider.
112496
113787
  */
112497
- function useCalendarViewport({ view = "month", startOfWeek = "monday", initialDate }) {
113788
+ function useCalendarViewport({ view = "month", startOfWeek = "monday", initialDate, today }) {
112498
113789
  const [viewDate, setViewDate] = useState(initialDate);
112499
113790
  const viewport = useMemo(() => buildCalendarViewport({
112500
113791
  view,
@@ -112520,8 +113811,8 @@ function useCalendarViewport({ view = "month", startOfWeek = "monday", initialDa
112520
113811
  goToPrevious,
112521
113812
  goToNext,
112522
113813
  goToToday: useCallback(() => {
112523
- setViewDate(initialDate);
112524
- }, [initialDate])
113814
+ setViewDate(today);
113815
+ }, [today])
112525
113816
  };
112526
113817
  }
112527
113818
  /**
@@ -112643,10 +113934,12 @@ function useCalendarEventCache({ readProfile = "listing-card", viewDate, calenda
112643
113934
  };
112644
113935
  }
112645
113936
  function useCalendarEvents({ readProfile, siteId: _siteId, calendarWindow, view = "month", startOfWeek = "monday", preloadMonths = 1, filters, stage, calendarContext }) {
113937
+ const today = useCalendarToday(calendarContext);
112646
113938
  const { viewDate, viewport, goToDate, goToPrevious, goToNext, goToToday } = useCalendarViewport({
112647
113939
  view,
112648
113940
  startOfWeek,
112649
- initialDate: calendarContext.initialToday
113941
+ initialDate: calendarContext.initialToday,
113942
+ today
112650
113943
  });
112651
113944
  const { events, loadState, retryCurrentView } = useCalendarEventCache({
112652
113945
  readProfile,
@@ -112660,6 +113953,7 @@ function useCalendarEvents({ readProfile, siteId: _siteId, calendarWindow, view
112660
113953
  return {
112661
113954
  events,
112662
113955
  viewDate,
113956
+ today,
112663
113957
  viewport,
112664
113958
  loadState,
112665
113959
  setViewDate: useCallback((date) => {
@@ -112678,6 +113972,7 @@ var init_useCalendarEvents = __esmMin((() => {
112678
113972
  init_listOptions();
112679
113973
  init_useCalendarEvents_state();
112680
113974
  init_loadStateError();
113975
+ init_useCalendarToday();
112681
113976
  }));
112682
113977
  //#endregion
112683
113978
  //#region ../blocks/src/system/runtime/nodes/events/shared/EventModalContext.tsx
@@ -112734,7 +114029,7 @@ var CalendarDayCell;
112734
114029
  var init_CalendarDayCell = __esmMin((() => {
112735
114030
  init_domain();
112736
114031
  init_EventModalContext();
112737
- CalendarDayCell = ({ date, events, isCurrentMonth, today: currentDate }) => {
114032
+ CalendarDayCell = ({ date, events, isCurrentMonth, calendarTimeZone, today: currentDate }) => {
112738
114033
  const { openEventModal, openDayModal } = useEventModal();
112739
114034
  const today = isToday(date, currentDate);
112740
114035
  const dayClasses = [
@@ -112756,7 +114051,7 @@ var init_CalendarDayCell = __esmMin((() => {
112756
114051
  }), /* @__PURE__ */ jsxs("div", {
112757
114052
  className: "event-calendar-events",
112758
114053
  children: [events.slice(0, 3).map((event) => {
112759
- const timeZone = event.timeZone ?? null;
114054
+ const timeZone = resolveEventTimeZone(event, calendarTimeZone);
112760
114055
  return /* @__PURE__ */ jsxs("button", {
112761
114056
  type: "button",
112762
114057
  className: "event-calendar-event",
@@ -112789,6 +114084,21 @@ var init_CalendarDayCell = __esmMin((() => {
112789
114084
  };
112790
114085
  }));
112791
114086
  //#endregion
114087
+ //#region ../blocks/src/system/runtime/nodes/events/shared/useHydrationReady.ts
114088
+ /**
114089
+ * The first client render must retain the server's data-dependent shell.
114090
+ * State becomes ready after hydration so subsequent loading transitions can
114091
+ * use the live calendar state without changing the server markup mid-hydrate.
114092
+ */
114093
+ function useHydrationReady() {
114094
+ const [ready, setReady] = useState(false);
114095
+ useEffect(() => {
114096
+ setReady(true);
114097
+ }, []);
114098
+ return ready;
114099
+ }
114100
+ var init_useHydrationReady = __esmMin((() => {}));
114101
+ //#endregion
112792
114102
  //#region ../blocks/src/system/runtime/nodes/events/shared/EventModalCloseButton.tsx
112793
114103
  function EventModalCloseButton({ closeButtonRef, onClose }) {
112794
114104
  return /* @__PURE__ */ jsx("button", {
@@ -112863,7 +114173,7 @@ var init_EventDetailModal = __esmMin((() => {
112863
114173
  * Uses AgendaEventCard with onClick prop to display events.
112864
114174
  * Clicking an event triggers onSelectEvent (typically opens EventDetailModal).
112865
114175
  */
112866
- function DayEventsModal({ date, events, showCapacity, onClose, onSelectEvent, portalRoot }) {
114176
+ function DayEventsModal({ date, events, showCapacity, calendarTimeZone, onClose, onSelectEvent, portalRoot }) {
112867
114177
  const formattedDate = formatDate$2(`${formatLocalScheduleDate(date)}T12:00:00Z`);
112868
114178
  return /* @__PURE__ */ jsxs(ModalShell, {
112869
114179
  title: formattedDate,
@@ -112893,7 +114203,8 @@ function DayEventsModal({ date, events, showCapacity, onClose, onSelectEvent, po
112893
114203
  children: events.map((event) => /* @__PURE__ */ jsx(AgendaEventCard, {
112894
114204
  event,
112895
114205
  onClick: onSelectEvent,
112896
- showCapacity
114206
+ showCapacity,
114207
+ calendarTimeZone
112897
114208
  }, event.occurrenceId || event.id))
112898
114209
  })]
112899
114210
  });
@@ -112915,7 +114226,7 @@ var init_DayEventsModal = __esmMin((() => {
112915
114226
  * - EventDetailModal for single event view
112916
114227
  * - DayEventsModal for day events list (clicking an event switches to event modal)
112917
114228
  */
112918
- function EventModals({ showCapacity, cardRole, buttonVariant, buttonText }) {
114229
+ function EventModals({ showCapacity, cardRole, buttonVariant, buttonText, calendarTimeZone }) {
112919
114230
  const markerRef = React.useRef(null);
112920
114231
  const [portalRoot, setPortalRoot] = React.useState(null);
112921
114232
  const { modalState, openEventModal, closeModal } = useEventModal();
@@ -112956,7 +114267,8 @@ function EventModals({ showCapacity, cardRole, buttonVariant, buttonText }) {
112956
114267
  openEventModal(event);
112957
114268
  },
112958
114269
  portalRoot,
112959
- showCapacity
114270
+ showCapacity,
114271
+ calendarTimeZone
112960
114272
  })] });
112961
114273
  return marker;
112962
114274
  }
@@ -113025,7 +114337,7 @@ function toEventCombinedControllerProps(props) {
113025
114337
  calendarWindow: props.render.hydration.calendarWindow
113026
114338
  };
113027
114339
  }
113028
- var EventCombinedClient, EventCombinedIslandClient;
114340
+ var EventCombinedCalendarHeader, EventCombinedCalendarTab, EventCombinedClient, EventCombinedIslandClient;
113029
114341
  var init_EventCombined_client = __esmMin((() => {
113030
114342
  init_shared$3();
113031
114343
  init_TabBar();
@@ -113035,16 +114347,118 @@ var init_EventCombined_client = __esmMin((() => {
113035
114347
  init_useEventPagination();
113036
114348
  init_useCalendarEvents();
113037
114349
  init_CalendarDayCell();
114350
+ init_CalendarDayHeaders();
114351
+ init_CalendarNavigationChevron();
113038
114352
  init_WeekAgendaView();
114353
+ init_useHydrationReady();
113039
114354
  init_EventModalContext();
113040
114355
  init_EventModals();
113041
114356
  init_buttons();
113042
114357
  init_listOptions();
113043
114358
  init_calendarViewOptions();
114359
+ EventCombinedCalendarHeader = ({ calendarView, title, loadState, onPrevious, onNext, onToday, buttonVariant }) => /* @__PURE__ */ jsxs("div", {
114360
+ className: "event-calendar-header",
114361
+ children: [/* @__PURE__ */ jsxs("div", {
114362
+ className: "event-calendar-nav",
114363
+ children: [
114364
+ /* @__PURE__ */ jsx("button", {
114365
+ type: "button",
114366
+ onClick: onPrevious,
114367
+ className: "event-calendar-nav-btn",
114368
+ "aria-label": calendarView === "week" ? "Previous week" : "Previous month",
114369
+ children: /* @__PURE__ */ jsx(CalendarNavigationChevron, { direction: "previous" })
114370
+ }),
114371
+ /* @__PURE__ */ jsxs("h3", {
114372
+ className: "event-calendar-title",
114373
+ children: [title, loadState.kind === "loading" && /* @__PURE__ */ jsx("span", {
114374
+ className: "rb-ml-2 rb-caption status-muted",
114375
+ children: "(loading...)"
114376
+ })]
114377
+ }),
114378
+ /* @__PURE__ */ jsx("button", {
114379
+ type: "button",
114380
+ onClick: onNext,
114381
+ className: "event-calendar-nav-btn",
114382
+ "aria-label": calendarView === "week" ? "Next week" : "Next month",
114383
+ children: /* @__PURE__ */ jsx(CalendarNavigationChevron, { direction: "next" })
114384
+ })
114385
+ ]
114386
+ }), /* @__PURE__ */ jsx("button", {
114387
+ type: "button",
114388
+ onClick: onToday,
114389
+ className: themeButtonClassName({
114390
+ variant: buttonVariant,
114391
+ size: "sm"
114392
+ }),
114393
+ children: "Today"
114394
+ })]
114395
+ });
114396
+ EventCombinedCalendarTab = ({ calendarTabViews, calendarView, calendarViewOptions, onCalendarViewChange, calendarEvents, eventsByDate, viewDate, viewport, calendarLoadState, dayNames, calendarContext, today, goToPrevious, goToNext, goToToday, emptyMessage, showCapacity, showVenue, cardRole, buttonVariant, buttonText, showEmptyState }) => /* @__PURE__ */ jsxs(EventModalProvider, { children: [/* @__PURE__ */ jsxs("div", {
114397
+ className: "event-combined-content event-calendar",
114398
+ children: [
114399
+ calendarTabViews === "both" && /* @__PURE__ */ jsx("div", {
114400
+ className: "event-calendar-view-toggle",
114401
+ children: calendarViewOptions.map((option) => /* @__PURE__ */ jsx("button", {
114402
+ type: "button",
114403
+ className: `event-calendar-view-btn ${calendarView === option.id ? "event-calendar-view-btn--active" : ""}`,
114404
+ onClick: () => onCalendarViewChange(option.id),
114405
+ children: option.label
114406
+ }, option.id))
114407
+ }),
114408
+ /* @__PURE__ */ jsx(EventCombinedCalendarHeader, {
114409
+ calendarView,
114410
+ title: viewport.title,
114411
+ loadState: calendarLoadState,
114412
+ onPrevious: goToPrevious,
114413
+ onNext: goToNext,
114414
+ onToday: goToToday,
114415
+ buttonVariant
114416
+ }),
114417
+ viewport.kind === "week" ? /* @__PURE__ */ jsx(WeekAgendaView, {
114418
+ days: viewport.days,
114419
+ events: calendarEvents,
114420
+ emptyMessage,
114421
+ showCapacity,
114422
+ showVenue,
114423
+ showEmptyState,
114424
+ buttonVariant,
114425
+ buttonText,
114426
+ calendarTimeZone: calendarContext.timeZone,
114427
+ today
114428
+ }) : /* @__PURE__ */ jsxs("div", {
114429
+ className: "event-calendar-container",
114430
+ children: [/* @__PURE__ */ jsx(CalendarDayHeaders, { dayNames }), /* @__PURE__ */ jsx("div", {
114431
+ className: "event-calendar-grid",
114432
+ children: viewport.days.map((date) => {
114433
+ const dateKey = formatDateKey$1(date);
114434
+ const dayEvents = eventsByDate.get(dateKey) ?? [];
114435
+ return /* @__PURE__ */ jsx(CalendarDayCell, {
114436
+ date,
114437
+ events: dayEvents,
114438
+ isCurrentMonth: date.month === viewDate.month,
114439
+ calendarTimeZone: calendarContext.timeZone,
114440
+ today
114441
+ }, dateKey);
114442
+ })
114443
+ })]
114444
+ }),
114445
+ viewport.kind !== "week" && calendarEvents.length === 0 && showEmptyState && /* @__PURE__ */ jsx("p", {
114446
+ className: "event-calendar-empty",
114447
+ children: emptyMessage
114448
+ })
114449
+ ]
114450
+ }), /* @__PURE__ */ jsx(EventModals, {
114451
+ cardRole,
114452
+ buttonVariant,
114453
+ buttonText,
114454
+ showCapacity,
114455
+ calendarTimeZone: calendarContext.timeZone
114456
+ })] });
113044
114457
  EventCombinedClient = ({ events: initialEvents, siteId, stage, listLayout = "stack", listColumns = "3", eventsPerPage = 12, paginationAction = {
113045
114458
  kind: "loadMore",
113046
114459
  label: "Load more events"
113047
114460
  }, startOfWeek = "monday", calendarTabViews = "both", defaultCalendarView, showFilters, showCategoryFilter = "auto", showVenueFilter, showStaffFilter, eventSurface, filterEventPresets, scheduleScope, filterCategoryIds, filterStaffMemberId, filterVenueId, showVenue, showMap, showCapacity, cardRole, buttonVariant = "primary", buttonText = "Book", emptyMessage = "No upcoming events scheduled.", className, calendarContext, calendarWindow }) => {
114461
+ const hydrationReady = useHydrationReady();
113048
114462
  const fetchInitialEventsOnMount = initialEvents == null;
113049
114463
  const resolvedShowFilters = showFilters ?? true;
113050
114464
  const resolvedShowVenueFilter = showVenueFilter ?? false;
@@ -113102,7 +114516,7 @@ var init_EventCombined_client = __esmMin((() => {
113102
114516
  pageSize,
113103
114517
  stage
113104
114518
  });
113105
- const { events: calendarEventsRaw, viewDate, viewport, loadState: calendarLoadState, goToPrevious, goToNext, goToToday } = useCalendarEvents({
114519
+ const { events: calendarEventsRaw, viewDate, today, viewport, loadState: calendarLoadState, goToPrevious, goToNext, goToToday } = useCalendarEvents({
113106
114520
  siteId,
113107
114521
  view: calendarView,
113108
114522
  startOfWeek,
@@ -113176,119 +114590,30 @@ var init_EventCombined_client = __esmMin((() => {
113176
114590
  hasActiveFilters,
113177
114591
  onResetFilters: resetFilters
113178
114592
  }),
113179
- activeTab === "calendar" && /* @__PURE__ */ jsxs(EventModalProvider, { children: [/* @__PURE__ */ jsxs("div", {
113180
- className: "event-combined-content event-calendar",
113181
- children: [
113182
- calendarTabViews === "both" && /* @__PURE__ */ jsx("div", {
113183
- className: "event-calendar-view-toggle",
113184
- children: calendarViewOptions.map((option) => /* @__PURE__ */ jsx("button", {
113185
- type: "button",
113186
- className: `event-calendar-view-btn ${calendarView === option.id ? "event-calendar-view-btn--active" : ""}`,
113187
- onClick: () => setCalendarView(option.id),
113188
- children: option.label
113189
- }, option.id))
113190
- }),
113191
- /* @__PURE__ */ jsxs("div", {
113192
- className: "event-calendar-header",
113193
- children: [/* @__PURE__ */ jsxs("div", {
113194
- className: "event-calendar-nav",
113195
- children: [
113196
- /* @__PURE__ */ jsx("button", {
113197
- type: "button",
113198
- onClick: goToPrevious,
113199
- className: "event-calendar-nav-btn",
113200
- "aria-label": calendarView === "week" ? "Previous week" : "Previous month",
113201
- children: /* @__PURE__ */ jsx("svg", {
113202
- width: "20",
113203
- height: "20",
113204
- fill: "none",
113205
- stroke: "currentColor",
113206
- strokeWidth: 2,
113207
- viewBox: "0 0 24 24",
113208
- children: /* @__PURE__ */ jsx("path", {
113209
- strokeLinecap: "round",
113210
- strokeLinejoin: "round",
113211
- d: "M15 19l-7-7 7-7"
113212
- })
113213
- })
113214
- }),
113215
- /* @__PURE__ */ jsxs("h3", {
113216
- className: "event-calendar-title",
113217
- children: [viewport.title, calendarLoadState.kind === "loading" && /* @__PURE__ */ jsx("span", {
113218
- className: "rb-ml-2 rb-caption status-muted",
113219
- children: "(loading...)"
113220
- })]
113221
- }),
113222
- /* @__PURE__ */ jsx("button", {
113223
- type: "button",
113224
- onClick: goToNext,
113225
- className: "event-calendar-nav-btn",
113226
- "aria-label": calendarView === "week" ? "Next week" : "Next month",
113227
- children: /* @__PURE__ */ jsx("svg", {
113228
- width: "20",
113229
- height: "20",
113230
- fill: "none",
113231
- stroke: "currentColor",
113232
- strokeWidth: 2,
113233
- viewBox: "0 0 24 24",
113234
- children: /* @__PURE__ */ jsx("path", {
113235
- strokeLinecap: "round",
113236
- strokeLinejoin: "round",
113237
- d: "M9 5l7 7-7 7"
113238
- })
113239
- })
113240
- })
113241
- ]
113242
- }), /* @__PURE__ */ jsx("button", {
113243
- type: "button",
113244
- onClick: goToToday,
113245
- className: themeButtonClassName({
113246
- variant: buttonVariant,
113247
- size: "sm"
113248
- }),
113249
- children: "Today"
113250
- })]
113251
- }),
113252
- viewport.kind === "week" ? /* @__PURE__ */ jsx(WeekAgendaView, {
113253
- days: viewport.days,
113254
- events: calendarEventsRaw,
113255
- emptyMessage: "No events scheduled",
113256
- showCapacity: resolvedShowCapacity,
113257
- calendarTimeZone: calendarContext.timeZone,
113258
- today: calendarContext.initialToday
113259
- }) : /* @__PURE__ */ jsxs("div", {
113260
- className: "event-calendar-container",
113261
- children: [/* @__PURE__ */ jsx("div", {
113262
- className: "event-calendar-day-headers",
113263
- children: dayNames.map((day) => /* @__PURE__ */ jsx("div", {
113264
- className: "event-calendar-day-header",
113265
- children: day
113266
- }, day))
113267
- }), /* @__PURE__ */ jsx("div", {
113268
- className: "event-calendar-grid",
113269
- children: viewport.days.map((date) => {
113270
- const dateKey = formatDateKey$1(date);
113271
- const dayEvents = eventsByDate.get(dateKey) || [];
113272
- return /* @__PURE__ */ jsx(CalendarDayCell, {
113273
- date,
113274
- events: dayEvents,
113275
- isCurrentMonth: date.month === viewDate.month,
113276
- today: calendarContext.initialToday
113277
- }, dateKey);
113278
- })
113279
- })]
113280
- }),
113281
- calendarEventsRaw.length === 0 && calendarLoadState.kind === "idle" && /* @__PURE__ */ jsx("p", {
113282
- className: "event-calendar-empty",
113283
- children: emptyMessage
113284
- })
113285
- ]
113286
- }), /* @__PURE__ */ jsx(EventModals, {
114593
+ activeTab === "calendar" && /* @__PURE__ */ jsx(EventCombinedCalendarTab, {
114594
+ calendarTabViews,
114595
+ calendarView,
114596
+ calendarViewOptions,
114597
+ onCalendarViewChange: setCalendarView,
114598
+ calendarEvents: calendarEventsRaw,
114599
+ eventsByDate,
114600
+ viewDate,
114601
+ viewport,
114602
+ calendarLoadState,
114603
+ dayNames,
114604
+ calendarContext,
114605
+ today,
114606
+ goToPrevious,
114607
+ goToNext,
114608
+ goToToday,
114609
+ emptyMessage,
114610
+ showCapacity: resolvedShowCapacity,
114611
+ showVenue: resolvedShowVenue,
113287
114612
  cardRole,
113288
114613
  buttonVariant,
113289
114614
  buttonText,
113290
- showCapacity: resolvedShowCapacity
113291
- })] })
114615
+ showEmptyState: hydrationReady && calendarLoadState.kind === "idle"
114616
+ })
113292
114617
  ]
113293
114618
  });
113294
114619
  };
@@ -113311,14 +114636,16 @@ var WeekTimetableView, TimeRail, TimetableDayColumn, TimetableEventButton;
113311
114636
  var init_WeekTimetableView = __esmMin((() => {
113312
114637
  init_EventModalContext();
113313
114638
  init_timetableModel();
113314
- WeekTimetableView = ({ viewDate, events, startOfWeek, today, showCapacity, emptyMessage = "No classes scheduled" }) => {
114639
+ WeekTimetableView = ({ viewDate, events, startOfWeek, today, showCapacity, calendarTimeZone, emptyMessage = "No classes scheduled" }) => {
113315
114640
  const { openEventModal } = useEventModal();
113316
114641
  const model = useMemo(() => buildTimetableModel({
113317
114642
  events,
113318
114643
  viewDate,
113319
114644
  startOfWeek,
113320
- today
114645
+ today,
114646
+ calendarTimeZone
113321
114647
  }), [
114648
+ calendarTimeZone,
113322
114649
  events,
113323
114650
  startOfWeek,
113324
114651
  today,
@@ -113484,7 +114811,7 @@ function buildDisplayFilterParams(display) {
113484
114811
  filterVenueId: display.filterVenueId
113485
114812
  });
113486
114813
  }
113487
- var EventCalendarClient, EventCalendarWeekBoardClient, EventCalendarTimetableClient, EventCalendarGridClient, EventCalendarChrome;
114814
+ var EventCalendarClient, EventCalendarWeekBoardClient, EventCalendarTimetableClient, EventCalendarGridClient, EventCalendarGridContent, EventCalendarChrome;
113488
114815
  var init_EventCalendar_client = __esmMin((() => {
113489
114816
  init_calendarWindow();
113490
114817
  init_EventCalendar_interactive();
@@ -113493,12 +114820,14 @@ var init_EventCalendar_client = __esmMin((() => {
113493
114820
  init_useCalendarEvents();
113494
114821
  init_useEventFilters();
113495
114822
  init_CalendarDayCell();
114823
+ init_CalendarDayHeaders();
113496
114824
  init_CalendarNavigationChevron();
113497
114825
  init_EventFilters();
113498
114826
  init_shared$3();
113499
114827
  init_EventModalContext();
113500
114828
  init_EventModals();
113501
114829
  init_WeekAgendaView();
114830
+ init_useHydrationReady();
113502
114831
  init_WeekBoardView();
113503
114832
  init_WeekTimetableView();
113504
114833
  init_buttons();
@@ -113552,7 +114881,7 @@ var init_EventCalendar_client = __esmMin((() => {
113552
114881
  display.filterVenueId,
113553
114882
  display.scheduleScope
113554
114883
  ]);
113555
- const { events, viewport, loadState, goToPrevious, goToNext, goToToday, retryCurrentView } = useCalendarEvents({
114884
+ const { events, today, viewport, loadState, goToPrevious, goToNext, goToToday, retryCurrentView } = useCalendarEvents({
113556
114885
  readProfile: resolveCalendarReadProfile({ variant: display.displayMode }),
113557
114886
  siteId: hydration.siteId,
113558
114887
  view: "week",
@@ -113569,7 +114898,7 @@ var init_EventCalendar_client = __esmMin((() => {
113569
114898
  } : loadState;
113570
114899
  const navigation = {
113571
114900
  kind: "interactive",
113572
- ...buildWeekBoardNavigationState(viewport, hydration.calendarContext.initialToday),
114901
+ ...buildWeekBoardNavigationState(viewport, today),
113573
114902
  loadState: weekBoardLoadState,
113574
114903
  onPrevious: goToPrevious,
113575
114904
  onNext: goToNext,
@@ -113578,13 +114907,13 @@ var init_EventCalendar_client = __esmMin((() => {
113578
114907
  return /* @__PURE__ */ jsx(WeekBoardView, { ...buildWeekBoardViewProps({
113579
114908
  ...display,
113580
114909
  calendarTimeZone: hydration.calendarContext.timeZone,
113581
- today: hydration.calendarContext.initialToday
114910
+ today
113582
114911
  }, viewport.days, navigation, events) });
113583
114912
  };
113584
114913
  EventCalendarTimetableClient = ({ render }) => {
113585
114914
  const { display, hydration } = render;
113586
114915
  const { filtersNode, listFilters } = useEventCalendarFilterState(display);
113587
- const { events, viewDate, viewport, loadState, retryCurrentView, goToPrevious, goToNext, goToToday } = useCalendarEvents({
114916
+ const { events, today, viewDate, viewport, loadState, retryCurrentView, goToPrevious, goToNext, goToToday } = useCalendarEvents({
113588
114917
  readProfile: resolveCalendarReadProfile({ variant: display.displayMode }),
113589
114918
  siteId: hydration.siteId,
113590
114919
  view: "week",
@@ -113612,20 +114941,23 @@ var init_EventCalendar_client = __esmMin((() => {
113612
114941
  startOfWeek: display.startOfWeek,
113613
114942
  emptyMessage: display.emptyMessage,
113614
114943
  showCapacity: display.showCapacity,
113615
- today: hydration.calendarContext.initialToday
114944
+ calendarTimeZone: hydration.calendarContext.timeZone,
114945
+ today
113616
114946
  })
113617
114947
  }), /* @__PURE__ */ jsx(EventModals, {
113618
114948
  cardRole: display.cardRole,
113619
114949
  buttonVariant: display.buttonVariant,
113620
114950
  buttonText: display.buttonText,
113621
- showCapacity: display.showCapacity
114951
+ showCapacity: display.showCapacity,
114952
+ calendarTimeZone: hydration.calendarContext.timeZone
113622
114953
  })] });
113623
114954
  };
113624
114955
  EventCalendarGridClient = ({ render }) => {
113625
114956
  const { display, hydration } = render;
114957
+ const hydrationReady = useHydrationReady();
113626
114958
  const calendarView = display.defaultCalendarView;
113627
114959
  const { filtersNode, listFilters } = useEventCalendarFilterState(display);
113628
- const { events, viewDate, viewport, loadState, retryCurrentView, goToPrevious, goToNext, goToToday } = useCalendarEvents({
114960
+ const { events, today, viewDate, viewport, loadState, retryCurrentView, goToPrevious, goToNext, goToToday } = useCalendarEvents({
113629
114961
  readProfile: resolveCalendarReadProfile({ variant: display.displayMode }),
113630
114962
  siteId: hydration.siteId,
113631
114963
  view: calendarView,
@@ -113638,7 +114970,7 @@ var init_EventCalendar_client = __esmMin((() => {
113638
114970
  });
113639
114971
  const eventsByDate = useMemo(() => groupEventsByDate(events, hydration.calendarContext.timeZone), [events, hydration.calendarContext.timeZone]);
113640
114972
  const dayNames = useMemo(() => getOrderedDayNames(display.startOfWeek), [display.startOfWeek]);
113641
- return /* @__PURE__ */ jsxs(EventModalProvider, { children: [/* @__PURE__ */ jsxs(EventCalendarChrome, {
114973
+ return /* @__PURE__ */ jsxs(EventModalProvider, { children: [/* @__PURE__ */ jsx(EventCalendarChrome, {
113642
114974
  display,
113643
114975
  calendarView,
113644
114976
  loadState,
@@ -113648,45 +114980,57 @@ var init_EventCalendar_client = __esmMin((() => {
113648
114980
  onNext: goToNext,
113649
114981
  onPrevious: goToPrevious,
113650
114982
  onToday: goToToday,
113651
- children: [viewport.kind === "week" ? /* @__PURE__ */ jsx(WeekAgendaView, {
113652
- days: viewport.days,
114983
+ children: /* @__PURE__ */ jsx(EventCalendarGridContent, {
114984
+ display,
113653
114985
  events,
113654
- emptyMessage: display.emptyMessage,
113655
- showCapacity: display.showCapacity,
114986
+ eventsByDate,
114987
+ loadState,
114988
+ dayNames,
114989
+ viewDate,
114990
+ viewport,
113656
114991
  calendarTimeZone: hydration.calendarContext.timeZone,
113657
- today: hydration.calendarContext.initialToday
113658
- }) : /* @__PURE__ */ jsxs("div", {
113659
- className: "event-calendar-container",
113660
- children: [/* @__PURE__ */ jsx("div", {
113661
- className: "event-calendar-day-headers",
113662
- children: dayNames.map((day) => /* @__PURE__ */ jsx("div", {
113663
- className: "event-calendar-day-header",
113664
- children: day
113665
- }, day))
113666
- }), /* @__PURE__ */ jsx("div", {
113667
- className: "event-calendar-grid",
113668
- children: viewport.days.map((date) => {
113669
- const dateKey = formatDateKey$1(date);
113670
- const dayEvents = eventsByDate.get(dateKey) || [];
113671
- return /* @__PURE__ */ jsx(CalendarDayCell, {
113672
- date,
113673
- events: dayEvents,
113674
- isCurrentMonth: date.month === viewDate.month,
113675
- today: hydration.calendarContext.initialToday
113676
- }, dateKey);
113677
- })
113678
- })]
113679
- }), viewport.kind === "month" && events.length === 0 && loadState.kind === "idle" ? /* @__PURE__ */ jsx("p", {
113680
- className: "event-calendar-empty",
113681
- children: display.emptyMessage
113682
- }) : null]
114992
+ hydrationReady,
114993
+ today
114994
+ })
113683
114995
  }), /* @__PURE__ */ jsx(EventModals, {
113684
114996
  cardRole: display.cardRole,
113685
114997
  buttonVariant: display.buttonVariant,
113686
114998
  buttonText: display.buttonText,
113687
- showCapacity: display.showCapacity
114999
+ showCapacity: display.showCapacity,
115000
+ calendarTimeZone: hydration.calendarContext.timeZone
113688
115001
  })] });
113689
115002
  };
115003
+ EventCalendarGridContent = ({ display, events, eventsByDate, loadState, dayNames, viewDate, viewport, calendarTimeZone, hydrationReady, today }) => /* @__PURE__ */ jsxs(Fragment, { children: [viewport.kind === "week" ? /* @__PURE__ */ jsx(WeekAgendaView, {
115004
+ days: viewport.days,
115005
+ events,
115006
+ emptyMessage: display.emptyMessage,
115007
+ showCapacity: display.showCapacity,
115008
+ showVenue: display.showVenue,
115009
+ showEmptyState: hydrationReady && loadState.kind === "idle",
115010
+ buttonVariant: display.buttonVariant,
115011
+ buttonText: display.buttonText,
115012
+ calendarTimeZone,
115013
+ today
115014
+ }) : /* @__PURE__ */ jsxs("div", {
115015
+ className: "event-calendar-container",
115016
+ children: [/* @__PURE__ */ jsx(CalendarDayHeaders, { dayNames }), /* @__PURE__ */ jsx("div", {
115017
+ className: "event-calendar-grid",
115018
+ children: viewport.days.map((date) => {
115019
+ const dateKey = formatDateKey$1(date);
115020
+ const dayEvents = eventsByDate.get(dateKey) ?? [];
115021
+ return /* @__PURE__ */ jsx(CalendarDayCell, {
115022
+ date,
115023
+ events: dayEvents,
115024
+ isCurrentMonth: date.month === viewDate.month,
115025
+ calendarTimeZone,
115026
+ today
115027
+ }, dateKey);
115028
+ })
115029
+ })]
115030
+ }), viewport.kind === "month" && events.length === 0 && hydrationReady && loadState.kind === "idle" ? /* @__PURE__ */ jsx("p", {
115031
+ className: "event-calendar-empty",
115032
+ children: display.emptyMessage
115033
+ }) : null] });
113690
115034
  EventCalendarChrome = ({ children, display, calendarView, className, loadState, filters, headerTitle, onRetry, onNext, onPrevious, onToday }) => /* @__PURE__ */ jsxs("div", {
113691
115035
  className: [
113692
115036
  "event-calendar",
@@ -114184,7 +115528,10 @@ function newsletterFormSubmissionReducer(state, action) {
114184
115528
  tag: "error",
114185
115529
  error: action.error
114186
115530
  };
114187
- case "succeeded": return { tag: "success" };
115531
+ case "succeeded": return {
115532
+ tag: "success",
115533
+ outcome: action.outcome
115534
+ };
114188
115535
  default: return assertNever$11(action);
114189
115536
  }
114190
115537
  }
@@ -114213,6 +115560,9 @@ function isNewsletterFormSubmitting(state) {
114213
115560
  function isNewsletterFormSuccess(state) {
114214
115561
  return state.tag === "success";
114215
115562
  }
115563
+ function getNewsletterSuccessOutcome(state) {
115564
+ return state.tag === "success" ? state.outcome : null;
115565
+ }
114216
115566
  function getNewsletterSubmissionFieldError(state, fieldId) {
114217
115567
  return state.tag === "error" ? getNewsletterFieldError(state.error, fieldId) : null;
114218
115568
  }
@@ -114239,34 +115589,22 @@ function mapNewsletterFormFieldsToSubscriberInput(fields) {
114239
115589
  }
114240
115590
  function resolveNewsletterSubmitTarget(input) {
114241
115591
  switch (input.tag) {
114242
- case "block-source": return input.destinationRef ? publishedDestinationTarget(input.destinationRef) : {
115592
+ case "block-source": return input.sourceRef ? publishedSourceTarget(input.sourceRef) : {
115593
+ tag: "unavailable",
115594
+ reason: "missing_block_source"
115595
+ };
115596
+ case "signed-footer-source": return publishedSourceTarget(input.sourceRef);
115597
+ case "preview": return {
114243
115598
  tag: "unavailable",
114244
115599
  reason: "missing_block_source"
114245
115600
  };
114246
- case "signed-footer-source": return publishedDestinationTarget(input.destinationRef);
114247
- case "legacy-direct-list": {
114248
- const listId = input.listId?.trim();
114249
- return listId ? {
114250
- tag: "ready",
114251
- target: {
114252
- tag: "legacy_riverbank_list",
114253
- listId
114254
- }
114255
- } : {
114256
- tag: "unavailable",
114257
- reason: "missing_legacy_list"
114258
- };
114259
- }
114260
115601
  default: return assertNever$22(input);
114261
115602
  }
114262
115603
  }
114263
- function publishedDestinationTarget(destinationRef) {
115604
+ function publishedSourceTarget(sourceRef) {
114264
115605
  return {
114265
115606
  tag: "ready",
114266
- target: {
114267
- tag: "published_block_ref",
114268
- destinationRef
114269
- }
115607
+ sourceRef
114270
115608
  };
114271
115609
  }
114272
115610
  function readOptionalSubmittedText(value) {
@@ -114287,7 +115625,6 @@ function NewsletterFormClient({ render }) {
114287
115625
  const [altchaSolution, setAltchaSolution] = useState(null);
114288
115626
  const showSpamProtection = render.hydration.spamProtectionEnabled ?? isSpamProtectionEnabled();
114289
115627
  const fields = render.display.fields;
114290
- const parsedTags = typeof render.hydration.tags === "string" ? render.hydration.tags.split(/[;,]/g).map((t) => t.trim()).filter(Boolean) : [];
114291
115628
  const handleSubmit = async (e) => {
114292
115629
  e.preventDefault();
114293
115630
  const formData = new FormData(e.currentTarget);
@@ -114301,7 +115638,10 @@ function NewsletterFormClient({ render }) {
114301
115638
  website: formData.get("website")
114302
115639
  });
114303
115640
  if (submittedFields.honeypot) {
114304
- dispatchSubmission({ type: "succeeded" });
115641
+ dispatchSubmission({
115642
+ type: "succeeded",
115643
+ outcome: "subscribed"
115644
+ });
114305
115645
  return;
114306
115646
  }
114307
115647
  if (!submittedFields.email) {
@@ -114319,23 +115659,46 @@ function NewsletterFormClient({ render }) {
114319
115659
  });
114320
115660
  return;
114321
115661
  }
115662
+ if (render.hydration.setupRevision === null || render.display.availability === "unavailable") {
115663
+ dispatchSubmission({
115664
+ type: "failed",
115665
+ error: newsletterFormError("Mailing-list signup is not available right now.")
115666
+ });
115667
+ return;
115668
+ }
115669
+ const visitorSelection = readVisitorSelection(formData, render.hydration);
115670
+ if (visitorSelection === null) {
115671
+ dispatchSubmission({
115672
+ type: "failed",
115673
+ error: newsletterFormError("Choose at least one email topic.")
115674
+ });
115675
+ return;
115676
+ }
114322
115677
  dispatchSubmission({ type: "submitted" });
114323
115678
  try {
114324
- await api.subscribeNewsletter({
115679
+ const result = await api.subscribeNewsletter({
114325
115680
  email: submittedFields.email,
114326
115681
  firstName: submittedFields.firstName,
114327
115682
  lastName: submittedFields.lastName,
114328
115683
  name: submittedFields.name,
114329
115684
  company: submittedFields.company,
114330
115685
  phone: submittedFields.phone,
114331
- target: submitTarget.target,
114332
- tags: parsedTags.length > 0 ? parsedTags : void 0,
115686
+ sourceRef: submitTarget.sourceRef,
115687
+ setupRevision: render.hydration.setupRevision,
115688
+ ...visitorSelection ? { visitorSelection } : {},
114333
115689
  meta: {
114334
115690
  honeypot: submittedFields.honeypot,
114335
115691
  altchaSolution
114336
115692
  }
114337
115693
  });
114338
- dispatchSubmission({ type: "succeeded" });
115694
+ if (result.tag === "subscribed" || result.tag === "confirmation_required") dispatchSubmission({
115695
+ type: "succeeded",
115696
+ outcome: result.tag
115697
+ });
115698
+ else dispatchSubmission({
115699
+ type: "failed",
115700
+ error: newsletterFormError(publicSignupError(result))
115701
+ });
114339
115702
  } catch (err) {
114340
115703
  dispatchSubmission({
114341
115704
  type: "failed",
@@ -114383,15 +115746,19 @@ function NewsletterFormClient({ render }) {
114383
115746
  }, field.id);
114384
115747
  };
114385
115748
  const formError = getNewsletterSubmissionFormError(submissionState);
114386
- if (isNewsletterFormSuccess(submissionState)) return /* @__PURE__ */ jsx("div", {
114387
- className: clsx("newsletter-form", "newsletter-success", render.display.className ?? void 0),
114388
- children: /* @__PURE__ */ jsx(FeedbackMessage, {
114389
- tone: "success",
114390
- className: "fb-success",
114391
- role: "status",
114392
- children: render.display.successMessage?.trim() || "Thanks for subscribing!"
114393
- })
114394
- });
115749
+ if (isNewsletterFormSuccess(submissionState)) {
115750
+ const outcome = getNewsletterSuccessOutcome(submissionState);
115751
+ return /* @__PURE__ */ jsx("div", {
115752
+ className: clsx("newsletter-form", "newsletter-success", render.display.className ?? void 0),
115753
+ children: /* @__PURE__ */ jsx(FeedbackMessage, {
115754
+ tone: "success",
115755
+ className: "fb-success",
115756
+ role: "status",
115757
+ children: outcome === "confirmation_required" ? "Please check your inbox to confirm your signup." : "Thanks — you’re on the list."
115758
+ })
115759
+ });
115760
+ }
115761
+ if (render.display.availability === "unavailable") return /* @__PURE__ */ jsx(UnavailableNewsletterForm, { className: render.display.className });
114395
115762
  return /* @__PURE__ */ jsxs("div", {
114396
115763
  className: clsx("newsletter-form", render.display.className ?? void 0),
114397
115764
  children: [formError && /* @__PURE__ */ jsx(FeedbackMessage, {
@@ -114415,6 +115782,18 @@ function NewsletterFormClient({ render }) {
114415
115782
  className: "newsletter-form-fields",
114416
115783
  children: [
114417
115784
  fields.map(renderField),
115785
+ render.hydration.choicePresentation === "visitor_choice" ? /* @__PURE__ */ jsxs("fieldset", {
115786
+ className: "newsletter-topics",
115787
+ children: [/* @__PURE__ */ jsx("legend", { children: "What would you like to hear about?" }), render.display.choices.map((choice) => /* @__PURE__ */ jsxs("label", {
115788
+ className: "newsletter-topic-choice",
115789
+ children: [/* @__PURE__ */ jsx("input", {
115790
+ type: "checkbox",
115791
+ name: "mailingListChoice",
115792
+ value: choice.id,
115793
+ disabled: isNewsletterFormSubmitting(submissionState)
115794
+ }), choice.label]
115795
+ }, choice.id))]
115796
+ }) : null,
114418
115797
  showSpamProtection && /* @__PURE__ */ jsx("div", {
114419
115798
  className: "newsletter-altcha",
114420
115799
  children: /* @__PURE__ */ jsx(AltchaWidget, {
@@ -114444,11 +115823,56 @@ function NewsletterFormClient({ render }) {
114444
115823
  })]
114445
115824
  });
114446
115825
  }
115826
+ function UnavailableNewsletterForm({ className }) {
115827
+ return /* @__PURE__ */ jsx("div", {
115828
+ className: clsx("newsletter-form", className ?? void 0),
115829
+ children: /* @__PURE__ */ jsx(FeedbackMessage, {
115830
+ tone: "error",
115831
+ className: "fb-error",
115832
+ role: "status",
115833
+ children: "Mailing-list signup is not available right now."
115834
+ })
115835
+ });
115836
+ }
115837
+ function readVisitorSelection(formData, hydration) {
115838
+ if (hydration.choicePresentation !== "visitor_choice") return void 0;
115839
+ const ids = formData.getAll("mailingListChoice").flatMap((value) => typeof value === "string" ? [value] : []);
115840
+ if (ids.length === 0) return null;
115841
+ const raw = hydration.choiceProvider === "native" ? {
115842
+ provider: "native",
115843
+ topicIds: ids
115844
+ } : hydration.choiceProvider === "brevo" ? {
115845
+ provider: "brevo",
115846
+ listIds: ids.map((id) => /^\d+$/.test(id) ? Number(id) : id)
115847
+ } : hydration.choiceProvider === "mailchimp" ? {
115848
+ provider: "mailchimp",
115849
+ interestIds: ids
115850
+ } : null;
115851
+ if (raw === null) return null;
115852
+ const parsed = parseMailingListVisitorSelection(raw);
115853
+ return parsed.ok ? parsed.value : null;
115854
+ }
115855
+ function publicSignupError(outcome) {
115856
+ switch (outcome.tag) {
115857
+ case "invalid_input": return "Please check your details and try again.";
115858
+ case "unavailable": switch (outcome.reason) {
115859
+ case "configuration_unavailable":
115860
+ case "authentication_failed":
115861
+ case "target_unavailable": return "Mailing-list signup is not available right now.";
115862
+ case "stale_configuration": return "This signup form has changed. Refresh the page, then try again.";
115863
+ case "subscriber_suppressed": return "This address cannot be added. Please contact the site if you would like help.";
115864
+ case "rate_limited": return "There have been too many signup attempts. Please wait a moment and try again.";
115865
+ case "temporarily_unavailable": return "We could not sign you up just now. Please try again shortly.";
115866
+ }
115867
+ case "uncertain": return "We could not confirm whether your signup completed. Please wait a moment, then try again.";
115868
+ }
115869
+ }
114447
115870
  var init_newsletter_form_client = __esmMin((() => {
114448
115871
  init_clsx();
114449
115872
  init_client();
114450
115873
  init_src();
114451
115874
  init_api();
115875
+ init_src$2();
114452
115876
  init_buttons();
114453
115877
  init_FeedbackMessage();
114454
115878
  init_FieldValidationMessage();