@riverbankcms/sdk 0.145.0 → 0.146.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 (159) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/{PreviewEditorSidebar-O-V6Pl5a.mjs → PreviewEditorSidebar-kg2r2Fyi.mjs} +4 -4
  3. package/dist/{PreviewEditorUI-1UlX_9cw.mjs → PreviewEditorUI-sWMLp5dT.mjs} +3 -3
  4. package/dist/{PreviewQueryProvider-BxGwdOCV.mjs → PreviewQueryProvider-Cg51xq1w.mjs} +1 -1
  5. package/dist/{SdkPreviewModeRuntime-DYbA_4iv.mjs → SdkPreviewModeRuntime-h2ti3Hch.mjs} +280 -182
  6. package/dist/{SiteChromeCustomizeContext-CNTKQ9nx.mjs → SiteChromeCustomizeContext-DEACFH9m.mjs} +1330 -734
  7. package/dist/_dts/ai/src/contracts/proposals.d.ts +924 -0
  8. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +84 -0
  9. package/dist/_dts/api/src/bookingConfig.d.ts +8 -1
  10. package/dist/_dts/api/src/bookingManagementEndpoints.d.ts +8 -14
  11. package/dist/_dts/api/src/bookingManagementEventEndpointTypes.d.ts +45 -1
  12. package/dist/_dts/api/src/clientErrorReporting.d.ts +50 -0
  13. package/dist/_dts/api/src/communications.d.ts +20 -4
  14. package/dist/_dts/api/src/contentRuntime.d.ts +3 -7
  15. package/dist/_dts/api/src/endpoints.d.ts +223 -88
  16. package/dist/_dts/api/src/event-visibility.d.ts +20 -0
  17. package/dist/_dts/api/src/eventManagementContracts.d.ts +56 -3
  18. package/dist/_dts/api/src/eventManagementEndpointDefinitions.d.ts +24 -0
  19. package/dist/_dts/api/src/eventPageWords.d.ts +19 -0
  20. package/dist/_dts/api/src/eventSeriesRegistrationEndpointDefinitions.d.ts +14 -0
  21. package/dist/_dts/api/src/index.d.ts +7 -1
  22. package/dist/_dts/api/src/indexCoreTypes.d.ts +1 -1
  23. package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -1
  24. package/dist/_dts/api/src/launchReadiness.d.ts +20 -2
  25. package/dist/_dts/api/src/launchRequirementPriority.d.ts +3 -0
  26. package/dist/_dts/api/src/newsletterCampaignCommandEndpoints.d.ts +13 -0
  27. package/dist/_dts/api/src/newsletterEndpointDefinitions.d.ts +42 -0
  28. package/dist/_dts/api/src/occurrenceScheduling.d.ts +10 -0
  29. package/dist/_dts/api/src/pageSurfaceEndpoints.d.ts +44 -0
  30. package/dist/_dts/api/src/participantMessaging.d.ts +11 -1
  31. package/dist/_dts/api/src/sdk-event-upsert.d.ts +40 -1
  32. package/dist/_dts/api/src/sdkContracts.d.ts +3 -42
  33. package/dist/_dts/api/src/sdkCourseBooking.d.ts +30 -0
  34. package/dist/_dts/api/src/sdkEventEndpointDefinitions.d.ts +76 -0
  35. package/dist/_dts/api/src/sdkEventLifecycle.d.ts +37 -0
  36. package/dist/_dts/api/src/sdkManagedEventContracts.d.ts +18 -0
  37. package/dist/_dts/api/src/sdkPageDesign.d.ts +388 -0
  38. package/dist/_dts/api/src/sdkPageDesignEndpointDefinitions.d.ts +22 -0
  39. package/dist/_dts/api/src/sdkPullEventContracts.d.ts +46 -0
  40. package/dist/_dts/api/src/siteAddressEndpoints.d.ts +29 -0
  41. package/dist/_dts/api/src/siteManagementEndpointDefinitions.d.ts +49 -0
  42. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +2 -32
  43. package/dist/_dts/api/src/siteOnboarding.d.ts +75 -9
  44. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +1 -1
  45. package/dist/_dts/api/src/types.d.ts +7 -1
  46. package/dist/_dts/api/src/wholeSeriesRuns.d.ts +14 -0
  47. package/dist/_dts/blocks/src/index.d.ts +2 -0
  48. package/dist/_dts/blocks/src/pageRenderAdmission.d.ts +10 -0
  49. package/dist/_dts/blocks/src/pageRendererContracts.d.ts +3 -1
  50. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +27 -5
  51. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +14 -1
  52. package/dist/_dts/blocks/src/system/icons/social.d.ts +1 -1
  53. package/dist/_dts/blocks/src/system/registry.d.ts +1 -1
  54. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventSourceRecovery.d.ts +1 -0
  55. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +20 -4
  56. package/dist/_dts/blocks/src/system/runtime/nodes/form.fields.d.ts +5 -0
  57. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.block-submission.d.ts +36 -0
  58. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.client.d.ts +1 -1
  59. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.interactive.d.ts +6 -1
  60. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.parts.d.ts +46 -0
  61. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.types.d.ts +2 -1
  62. package/dist/_dts/blocks/src/system/runtime/resolver.d.ts +2 -1
  63. package/dist/_dts/blocks/src/system/runtime/shared/components/CheckboxChoice.d.ts +18 -0
  64. package/dist/_dts/blocks/src/system/runtime/shared/components/index.d.ts +1 -0
  65. package/dist/_dts/content-editor/src/index.d.ts +1 -0
  66. package/dist/_dts/content-editor/src/primitives/previewEditableOutline.d.ts +2 -0
  67. package/dist/_dts/content-editor/src/ui/editorBlockEquality.d.ts +3 -0
  68. package/dist/_dts/content-editor/src/ui/editorSnapshot.d.ts +3 -5
  69. package/dist/_dts/core/src/block-content-identity.d.ts +5 -0
  70. package/dist/_dts/core/src/editor-state.d.ts +2 -7
  71. package/dist/_dts/core/src/index.d.ts +1 -0
  72. package/dist/_dts/core/src/mailing-list-submission.d.ts +3 -1
  73. package/dist/_dts/core/src/public-event-booking-availability.d.ts +20 -1
  74. package/dist/_dts/core/src/public-profile.d.ts +3 -1
  75. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +49 -2
  76. package/dist/_dts/editor-blocks/src/BlockEditor.d.ts +3 -0
  77. package/dist/_dts/editor-blocks/src/block-editor/EmptyState.d.ts +13 -1
  78. package/dist/_dts/editor-blocks/src/block-editor/types.d.ts +2 -8
  79. package/dist/_dts/editor-blocks/src/index.d.ts +1 -0
  80. package/dist/_dts/preview-next/src/client/blocks/composer/types.d.ts +3 -4
  81. package/dist/_dts/preview-next/src/client/preview/PreviewEntryControllerProvider.d.ts +1 -2
  82. package/dist/_dts/sdk/src/next/renderSdkContent.d.ts +0 -1
  83. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +2 -2
  84. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +2 -2
  85. package/dist/_dts/sdk/src/rendering/helpers/loadContent.d.ts +6 -1
  86. package/dist/_dts/sdk/src/rendering/helpers/loadPage.d.ts +5 -2
  87. package/dist/_dts/sdk/src/rendering/helpers/pageRuntimeSupport.d.ts +6 -1
  88. package/dist/_dts/sdk/src/rendering/helpers/templateContent.d.ts +2 -0
  89. package/dist/_dts/sdk/src/rendering/hooks/useContent.d.ts +5 -1
  90. package/dist/_dts/sdk/src/rendering/hooks/usePage.d.ts +5 -1
  91. package/dist/_dts/sdk/src/version.d.ts +1 -1
  92. package/dist/_dts/surfaces/src/index.d.ts +9 -0
  93. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  94. package/dist/_dts/theme-core/src/inputs/checkable.d.ts +42 -0
  95. package/dist/_dts/theme-core/src/inputs/inputGroup.d.ts +19 -0
  96. package/dist/_dts/ui/src/navigation-tabs.d.ts +2 -1
  97. package/dist/client/{BookingConsentAgreement-DlVOmpW4.mjs → BookingConsentAgreement-BQKL045f.mjs} +2 -2
  98. package/dist/client/CheckboxChoice--W2n6yKs.mjs +24 -0
  99. package/dist/client/{DiscountCodeDisclosure-T9q623PQ.mjs → DiscountCodeDisclosure-CsOtjFY7.mjs} +1 -1
  100. package/dist/client/{EventCombined.client-DnsUeONl.mjs → EventCombined.client-BdRjVbhH.mjs} +6 -6
  101. package/dist/client/{EventListing.client-CNBFqJS4.mjs → EventListing.client-DBxC6xOU.mjs} +2 -2
  102. package/dist/client/{LeafletStaticMap-C7higg52.mjs → LeafletStaticMap-mHEJKrTs.mjs} +1 -1
  103. package/dist/client/{ThemedButton-LAJTNrS8.mjs → ThemedButton-CE5KYT6z.mjs} +1 -1
  104. package/dist/client/{accordion-BcNF9TjX.mjs → accordion-BEQNSptH.mjs} +1 -1
  105. package/dist/client/{bookingForm-BUaQ3S03.mjs → bookingForm-AMr-s5vw.mjs} +33 -52
  106. package/dist/client/bookings.mjs +48 -46
  107. package/dist/client/{carousel-CTdF6e0V.mjs → carousel-Bbt_QgJy.mjs} +1 -1
  108. package/dist/client/{cart-pGtyf_XU.mjs → cart-CnWi30zJ.mjs} +3 -3
  109. package/dist/client/{checkout-Da9WSn7Y.mjs → checkout-f3nkWgd4.mjs} +3 -3
  110. package/dist/client/client.mjs +1611 -815
  111. package/dist/client/{context-BFeY_Wbm.mjs → context-Bc8T6pCe.mjs} +1 -1
  112. package/dist/client/{dates-BhwVSxDg.mjs → dates-DUsCEzLb.mjs} +2 -3
  113. package/dist/client/{eventCalendar-BAtdnR4s.mjs → eventCalendar-CKwgXui5.mjs} +9 -9
  114. package/dist/client/{eventCombined-RksA3tRC.mjs → eventCombined-CBAOSTGR.mjs} +4 -4
  115. package/dist/client/{eventDetails-BB9hB4wR.mjs → eventDetails-Dh-_WiBD.mjs} +4 -4
  116. package/dist/client/{eventListing-BpJBkviM.mjs → eventListing-CA3frIH5.mjs} +4 -4
  117. package/dist/client/{eventRegistration-B18jFq_o.mjs → eventRegistration-BHtsgdcg.mjs} +21 -22
  118. package/dist/client/{form-Dodt8Y8t.mjs → form-C2h3YAcg.mjs} +135 -104
  119. package/dist/client/{headerSection-B0qj9ttg.mjs → headerSection-lwMuMTH9.mjs} +3 -3
  120. package/dist/client/hooks.mjs +489 -65
  121. package/dist/client/{locationMap-gn-iMk7a.mjs → locationMap-DJ2bLODV.mjs} +3 -3
  122. package/dist/client/{newsletterForm-oByLdFkr.mjs → newsletterForm-8Pu5K32g.mjs} +203 -101
  123. package/dist/client/{pricing-BOU0_Hai.mjs → pricing-HHx3IgBz.mjs} +1 -1
  124. package/dist/client/{productDetail-D9v1zH2j.mjs → productDetail-C_1odnAf.mjs} +3 -3
  125. package/dist/client/{productList-D-mItx1n.mjs → productList-CtCv-Nmx.mjs} +3 -3
  126. package/dist/client/{propsDecoder-C3TP_z4x.mjs → propsDecoder-Dcgsncxb.mjs} +40 -23
  127. package/dist/client/rendering/client.mjs +490 -457
  128. package/dist/client/rendering/islands.mjs +17 -17
  129. package/dist/client/rendering.mjs +1515 -628
  130. package/dist/client/{routeIslandApiConfig-DzN1W0sq.mjs → routeIslandApiConfig-CWLP7wu3.mjs} +1 -1
  131. package/dist/client/{scrollToBlock-CWs8EIdo.mjs → scrollToBlock-BNgaEUpo.mjs} +1 -1
  132. package/dist/client/{shop-Dufw7N7o.mjs → shop-DQXrQ8kJ.mjs} +7 -7
  133. package/dist/client/{shop-commerce-gklw_hLF.mjs → shop-commerce-B88zmWWo.mjs} +6 -6
  134. package/dist/client/{shop-commerce-store-Sf1eyTaZ.mjs → shop-commerce-store-DtSfkKuX.mjs} +1 -1
  135. package/dist/client/{shopShared-B5nyA41S.mjs → shopShared-cuaONpkJ.mjs} +4 -4
  136. package/dist/client/{useEventFilters-CLL829vy.mjs → useEventFilters-Bukew6Gb.mjs} +6 -6
  137. package/dist/preview-next/before-render.mjs +368 -103
  138. package/dist/preview-next/client/runtime.mjs +4 -4
  139. package/dist/preview-next/editor-base.css +11 -0
  140. package/dist/preview-next/keepAlive.mjs +328 -103
  141. package/dist/preview-next/middleware.mjs +329 -103
  142. package/dist/{previewAuthStore-BxAFlu-j.mjs → previewAuthStore-h5IgbSp4.mjs} +353 -103
  143. package/dist/{sdk-runtime-D0uZFev7.mjs → sdk-runtime-DTc1uIXn.mjs} +2 -2
  144. package/dist/{separator-EvdCAn4V.mjs → separator-BpHS1KZK.mjs} +1 -1
  145. package/dist/server/components.mjs +1376 -331
  146. package/dist/server/config-validation.mjs +405 -27
  147. package/dist/server/config.mjs +405 -27
  148. package/dist/server/data.mjs +405 -27
  149. package/dist/server/index.mjs +370 -104
  150. package/dist/server/next.mjs +1430 -463
  151. package/dist/server/page-converter.mjs +36 -25
  152. package/dist/server/prebuild.mjs +1 -1
  153. package/dist/server/rendering/server.mjs +1374 -331
  154. package/dist/server/rendering.mjs +1436 -364
  155. package/dist/server/routing.mjs +476 -43
  156. package/dist/server/server.mjs +504 -169
  157. package/dist/server/theme-bridge.mjs +467 -111
  158. package/dist/styles/index.css +186 -65
  159. package/package.json +1 -1
@@ -1619,7 +1619,8 @@ var init_business_address = __esmMin((() => {
1619
1619
  var init_try_async = __esmMin((() => {
1620
1620
  init_result$1();
1621
1621
  }));
1622
- var init_narrow_result = __esmMin((() => {})), init_editor_state = __esmMin((() => {}));
1622
+ var init_narrow_result = __esmMin((() => {}));
1623
+ var init_editor_state = __esmMin((() => {})), init_block_content_identity = __esmMin((() => {}));
1623
1624
  var init_sensitive_collection = __esmMin((() => {}));
1624
1625
  //#endregion
1625
1626
  //#region ../core/src/assertNever.ts
@@ -2003,6 +2004,27 @@ var init_mailing_list_setup_parser = __esmMin((() => {
2003
2004
  init_mailing_list_identifiers();
2004
2005
  init_result$1();
2005
2006
  }));
2007
+ //#endregion
2008
+ //#region ../core/src/mailing-list-targeting.ts
2009
+ function sameMailingListPlacementTargeting(left, right) {
2010
+ if (left.mode !== right.mode) return false;
2011
+ if (left.mode === "default" || right.mode === "default") return true;
2012
+ if (left.provider !== right.provider || left.selection.tag !== right.selection.tag) return false;
2013
+ if (left.provider === "mailchimp" && (right.provider !== "mailchimp" || left.audienceId !== right.audienceId)) return false;
2014
+ return sameIds(targetingSelectionIds(left), targetingSelectionIds(right));
2015
+ }
2016
+ function targetingSelectionIds(targeting) {
2017
+ switch (targeting.provider) {
2018
+ case "native": return targeting.selection.tag === "fixed" ? targeting.selection.topicIds : targeting.selection.offeredTopicIds;
2019
+ case "brevo": return targeting.selection.tag === "fixed" ? targeting.selection.listIds : targeting.selection.offeredListIds;
2020
+ case "mailchimp": return targeting.selection.tag === "fixed" ? targeting.selection.interestIds : targeting.selection.offeredInterestIds;
2021
+ }
2022
+ }
2023
+ function sameIds(left, right) {
2024
+ const leftIds = new Set(left);
2025
+ const rightIds = new Set(right);
2026
+ return leftIds.size === left.length && rightIds.size === right.length && leftIds.size === rightIds.size && [...leftIds].every((id) => rightIds.has(id));
2027
+ }
2006
2028
  function planMailingListChoicePresentation(targeting) {
2007
2029
  if (targeting.mode === "default" || targeting.selection.tag === "fixed") return { tag: "hidden" };
2008
2030
  switch (targeting.provider) {
@@ -2751,6 +2773,7 @@ var init_src$2 = __esmMin((() => {
2751
2773
  init_narrow_result();
2752
2774
  init_non_empty_array();
2753
2775
  init_editor_state();
2776
+ init_block_content_identity();
2754
2777
  init_sensitive_collection();
2755
2778
  init_assertNever$1();
2756
2779
  init_participants();
@@ -13636,7 +13659,7 @@ var init_bookingConsent = __esmMin((() => {
13636
13659
  checkboxLabel: z$1.string().min(1)
13637
13660
  });
13638
13661
  bookingConsentCarrierSchema = z$1.union([blockBookingConsentSchema, bookingRequirementConsentFieldSchema]);
13639
- })), publicEventLoaderQuerySchemaShape, eventPresetSchema, eventScheduleScopeSchema$2, publicEventRecurrenceSchema, eventDestinationModeSchema, publicEventDestinationSchema, eventVenueSchema, eventCategorySchema, accessRestrictionSchema, publicCurrencySchema, publicCentsSchema, publicPositiveCentsSchema, publicIsoDateTimeSchema, publicEventAttendanceModeSchema, publicEventAttendanceModeAvailabilitySchema, publicEventPricingOptionAvailabilitySchema, publicEventPricingOptionSchema, publicEventPricingSchema, publicTeamMemberSummarySchema, publicEventBookingAvailabilitySchema, publicRunSessionSchema, publicWholeSeriesRunSchema, publicEventBaseSchema, publicEventSchema, publicEventsArraySchema;
13662
+ })), publicEventLoaderQuerySchemaShape, eventPresetSchema, eventScheduleScopeSchema$2, publicEventRecurrenceSchema, eventDestinationModeSchema, publicEventDestinationSchema, eventVenueSchema, eventCategorySchema, accessRestrictionSchema, publicCurrencySchema, publicCentsSchema, publicPositiveCentsSchema, publicIsoDateTimeSchema, publicEventAttendanceModeSchema, publicEventAttendanceModeAvailabilitySchema, publicEventPricingOptionAvailabilitySchema, publicEventPricingOptionSchema, publicEventPricingSchema, publicTeamMemberSummarySchema, publicEventBookingAvailabilitySchema, publicEventBookingClosedDetailSchema, publicRunSessionSchema, publicWholeSeriesRunSchema, publicEventBaseSchema, publicEventSchema, publicEventsArraySchema;
13640
13663
  var init_schemas = __esmMin((() => {
13641
13664
  init_media$1();
13642
13665
  init_richTextSchema();
@@ -13660,6 +13683,7 @@ var init_schemas = __esmMin((() => {
13660
13683
  seriesSlug: z$1.string().optional(),
13661
13684
  includeOccurrenceId: z$1.string().optional(),
13662
13685
  readIntent: z$1.string().optional(),
13686
+ detailAdmission: z$1.string().optional(),
13663
13687
  detailLevel: z$1.string().optional(),
13664
13688
  readProfile: z$1.string().optional()
13665
13689
  };
@@ -13817,11 +13841,11 @@ var init_schemas = __esmMin((() => {
13817
13841
  "series_archived",
13818
13842
  "parent_archived",
13819
13843
  "parent_inconsistent",
13820
- "not_public",
13821
13844
  "already_started",
13822
13845
  "enrollment_closed"
13823
13846
  ])
13824
13847
  })]);
13848
+ publicEventBookingClosedDetailSchema = z$1.discriminatedUnion("kind", [z$1.object({ kind: z$1.literal("opensSoon") }), z$1.object({ kind: z$1.literal("paused") })]);
13825
13849
  publicRunSessionSchema = z$1.object({
13826
13850
  occurrenceId: z$1.string(),
13827
13851
  startsAt: z$1.string(),
@@ -13863,6 +13887,7 @@ var init_schemas = __esmMin((() => {
13863
13887
  destination: publicEventDestinationSchema,
13864
13888
  requiresRegistration: z$1.boolean(),
13865
13889
  bookingAvailability: publicEventBookingAvailabilitySchema,
13890
+ bookingClosedDetail: publicEventBookingClosedDetailSchema.optional(),
13866
13891
  deliveryMode: z$1.enum([
13867
13892
  "in_person",
13868
13893
  "online",
@@ -30043,7 +30068,6 @@ function closedEventBookingLabel(reason) {
30043
30068
  case "series_archived":
30044
30069
  case "parent_archived":
30045
30070
  case "parent_inconsistent":
30046
- case "not_public":
30047
30071
  case "already_started":
30048
30072
  case "enrollment_closed": return "Registration closed";
30049
30073
  default: return assertNever$20(reason);
@@ -32879,6 +32903,7 @@ var init_social = __esmMin((() => {
32879
32903
  "SocialInstagram",
32880
32904
  "SocialLinkedIn",
32881
32905
  "SocialTikTok",
32906
+ "SocialWhatsApp",
32882
32907
  "SocialX",
32883
32908
  "SocialYouTube"
32884
32909
  ];
@@ -32915,6 +32940,7 @@ var init_social = __esmMin((() => {
32915
32940
  /* @__PURE__ */ jsx("path", { d: "M10.5 9v10" })
32916
32941
  ] })),
32917
32942
  SocialTikTok: createIcon("SocialTikTokIcon", /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("path", { d: "M14 4v11.5a4.5 4.5 0 1 1-4-4.47" }), /* @__PURE__ */ jsx("path", { d: "M14 4c.7 3 2.4 4.5 5 4.5" })] })),
32943
+ SocialWhatsApp: createIcon("SocialWhatsAppIcon", /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("path", { d: "M3.5 20.5 4.8 16.4A8.5 8.5 0 1 1 8 19.3Z" }), /* @__PURE__ */ jsx("path", { d: "M9.2 8.2c.2-.5.9-.6 1.2-.1l.8 1.4c.2.3.1.7-.2 1l-.5.5c.5 1.1 1.4 2 2.5 2.5l.5-.5c.3-.3.7-.4 1-.2l1.4.8c.5.3.4 1-.1 1.2-2.9 1.1-7.7-3.7-6.6-6.6Z" })] })),
32918
32944
  SocialX: createIcon("SocialXIcon", /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("path", { d: "m5 4 14 16" }), /* @__PURE__ */ jsx("path", { d: "M19 4 5 20" })] })),
32919
32945
  SocialYouTube: createIcon("SocialYouTubeIcon", /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("path", { d: "M21 12c0 3.5-.5 5.5-1.3 6.3S16.5 19.5 12 19.5s-6.9-.4-7.7-1.2S3 15.5 3 12s.5-5.5 1.3-6.3S7.5 4.5 12 4.5s6.9.4 7.7 1.2S21 8.5 21 12Z" }), /* @__PURE__ */ jsx("path", { d: "m10 9 5 3-5 3Z" })] }))
32920
32946
  };
@@ -35186,6 +35212,11 @@ function withOptionalPhone(fields, includePhone) {
35186
35212
  var init_newsletter_form_types = __esmMin((() => {}));
35187
35213
  //#endregion
35188
35214
  //#region ../blocks/src/system/runtime/nodes/newsletter-form.interactive.ts
35215
+ function newsletterBlockSubmissionMessage(target) {
35216
+ if (target.tag === "block-source") return target.sourceRef ? null : NEWSLETTER_SIGNUPS_PAUSED_MESSAGE;
35217
+ if (target.tag !== "unpublished-preview") return null;
35218
+ return target.reason === "unpublished-form" ? "Publish this form to test a signup here." : "This form's signup settings are unpublished. Publish it to test a signup here.";
35219
+ }
35189
35220
  function buildNewsletterDisplay(source) {
35190
35221
  const context = source.mailingList;
35191
35222
  const form = context?.tag === "configured" ? context.form : {
@@ -35211,16 +35242,21 @@ function buildNewsletterDisplay(source) {
35211
35242
  }
35212
35243
  function projectNewsletterFormHydrationTarget(source) {
35213
35244
  switch (source.source) {
35214
- case "block": {
35215
- const sourceRef = buildMailingListSignupBlockSourceRef(source.blockId, source.contentVersionId);
35216
- if (sourceRef?.tag === "block_ref") return {
35245
+ case "block": switch (source.newsletterBlockSubmission.tag) {
35246
+ case "unpublished-form":
35247
+ case "unpublished-settings": return {
35248
+ tag: "unpublished-preview",
35249
+ reason: source.newsletterBlockSubmission.tag
35250
+ };
35251
+ case "ready": return {
35217
35252
  tag: "block-source",
35218
- sourceRef
35253
+ sourceRef: source.newsletterBlockSubmission.sourceRef
35219
35254
  };
35220
- return {
35255
+ case "unavailable": return {
35221
35256
  tag: "block-source",
35222
35257
  sourceRef: null
35223
35258
  };
35259
+ default: return assertNever$20(source.newsletterBlockSubmission);
35224
35260
  }
35225
35261
  case "signed-footer": return {
35226
35262
  tag: "signed-footer-source",
@@ -35289,6 +35325,7 @@ function buildNewsletterFormInteractiveIslandProps(props) {
35289
35325
  const decoded = newsletterFormBlockRuntime.contracts.source.decode(props);
35290
35326
  const source = isDecodeSuccess(decoded) ? decoded.value : {
35291
35327
  ...props,
35328
+ ...props.source === "block" ? { newsletterBlockSubmission: { tag: "unavailable" } } : {},
35292
35329
  mailingList: void 0,
35293
35330
  targeting: { mode: "default" }
35294
35331
  };
@@ -35312,13 +35349,14 @@ function parseRequiredMailingListSignedSourceToken(value) {
35312
35349
  if (!parsed) throw new Error("Mailing-list signup signed source ref requires token");
35313
35350
  return parsed;
35314
35351
  }
35315
- var newsletterButtonVariantSchema, mailingListContextSchema, mailingListTargetingSchema, newsletterFieldSchema, mailingListSignupBlockIdSchema, mailingListContentVersionIdSchema, signedMailingListSourceTokenSchema, newsletterSourceCommonSchema, newsletterSourceSchema, newsletterDisplaySchema, newsletterHydrationSchema, newsletterRenderSchema, newsletterIslandMetaCodec, newsletterIslandMetaKeys, newsletterFormBlockRuntime, newsletterFormInteractiveIslandPropsCodec;
35352
+ var NEWSLETTER_SIGNUPS_PAUSED_MESSAGE, newsletterButtonVariantSchema, mailingListContextSchema, mailingListTargetingSchema, newsletterFieldSchema, mailingListSignupBlockIdSchema, mailingListContentVersionIdSchema, mailingListSignupBlockSourceRefSchema, signedMailingListSourceTokenSchema, newsletterSourceCommonSchema, newsletterSourceSchema, newsletterDisplaySchema, newsletterHydrationSchema, newsletterRenderSchema, newsletterIslandMetaCodec, newsletterIslandMetaKeys, newsletterFormBlockRuntime, newsletterFormInteractiveIslandPropsCodec;
35316
35353
  var init_newsletter_form_interactive = __esmMin((() => {
35317
35354
  init_src$2();
35318
35355
  init_islands();
35319
35356
  init_runtime();
35320
35357
  init_newsletter_form_types();
35321
35358
  init_buttonRoles();
35359
+ NEWSLETTER_SIGNUPS_PAUSED_MESSAGE = "We can’t accept signups right now. Please try again later.";
35322
35360
  newsletterButtonVariantSchema = blockButtonRoleSchema;
35323
35361
  mailingListContextSchema = z$1.unknown().transform((value, ctx) => {
35324
35362
  const parsed = parseMailingListRuntimeContext(value);
@@ -35359,6 +35397,11 @@ var init_newsletter_form_interactive = __esmMin((() => {
35359
35397
  });
35360
35398
  return z$1.NEVER;
35361
35399
  });
35400
+ mailingListSignupBlockSourceRefSchema = z$1.object({
35401
+ tag: z$1.literal("block_ref"),
35402
+ blockId: mailingListSignupBlockIdSchema,
35403
+ contentVersionId: mailingListContentVersionIdSchema
35404
+ });
35362
35405
  signedMailingListSourceTokenSchema = z$1.string().trim().min(1).transform(parseRequiredMailingListSignedSourceToken);
35363
35406
  newsletterSourceCommonSchema = z$1.object({
35364
35407
  siteId: z$1.string().optional(),
@@ -35373,7 +35416,15 @@ var init_newsletter_form_interactive = __esmMin((() => {
35373
35416
  newsletterSourceCommonSchema.extend({
35374
35417
  source: z$1.literal("block"),
35375
35418
  blockId: z$1.string().nullable().optional(),
35376
- contentVersionId: z$1.string().nullable().optional()
35419
+ newsletterBlockSubmission: z$1.discriminatedUnion("tag", [
35420
+ z$1.object({
35421
+ tag: z$1.literal("ready"),
35422
+ sourceRef: mailingListSignupBlockSourceRefSchema
35423
+ }),
35424
+ z$1.object({ tag: z$1.literal("unpublished-form") }),
35425
+ z$1.object({ tag: z$1.literal("unpublished-settings") }),
35426
+ z$1.object({ tag: z$1.literal("unavailable") })
35427
+ ])
35377
35428
  }),
35378
35429
  newsletterSourceCommonSchema.extend({
35379
35430
  source: z$1.literal("signed-footer"),
@@ -35402,11 +35453,7 @@ var init_newsletter_form_interactive = __esmMin((() => {
35402
35453
  target: z$1.discriminatedUnion("tag", [
35403
35454
  z$1.object({
35404
35455
  tag: z$1.literal("block-source"),
35405
- sourceRef: z$1.object({
35406
- tag: z$1.literal("block_ref"),
35407
- blockId: mailingListSignupBlockIdSchema,
35408
- contentVersionId: mailingListContentVersionIdSchema
35409
- }).nullable()
35456
+ sourceRef: mailingListSignupBlockSourceRefSchema.nullable()
35410
35457
  }),
35411
35458
  z$1.object({
35412
35459
  tag: z$1.literal("signed-footer-source"),
@@ -35415,7 +35462,11 @@ var init_newsletter_form_interactive = __esmMin((() => {
35415
35462
  token: signedMailingListSourceTokenSchema
35416
35463
  })
35417
35464
  }),
35418
- z$1.object({ tag: z$1.literal("preview") })
35465
+ z$1.object({ tag: z$1.literal("preview") }),
35466
+ z$1.object({
35467
+ tag: z$1.literal("unpublished-preview"),
35468
+ reason: z$1.enum(["unpublished-form", "unpublished-settings"])
35469
+ })
35419
35470
  ]),
35420
35471
  setupRevision: z$1.number().int().positive().nullable(),
35421
35472
  choiceProvider: z$1.enum([
@@ -97684,6 +97735,162 @@ function FeedbackMessage({ tone, treatment = "panel", children, className, id, t
97684
97735
  }
97685
97736
  var init_FeedbackMessage = __esmMin((() => {}));
97686
97737
  //#endregion
97738
+ //#region ../blocks/src/system/runtime/shared/components/CheckboxChoice.tsx
97739
+ /**
97740
+ * The customer-facing checkbox every block renders. Styling comes from the
97741
+ * theme's input CSS (`.form-check`, `.form-checkbox`), so it follows each
97742
+ * site's input colours, borders and corners.
97743
+ */
97744
+ function CheckboxChoice({ label, presentation = "row", className, ...inputProps }) {
97745
+ return /* @__PURE__ */ jsxs("label", {
97746
+ className: clsx("form-check", presentation === "tile" && "form-check--tile", className),
97747
+ children: [/* @__PURE__ */ jsx("input", {
97748
+ ...inputProps,
97749
+ type: "checkbox",
97750
+ className: "form-checkbox"
97751
+ }), /* @__PURE__ */ jsx("span", {
97752
+ className: "form-check-label",
97753
+ children: label
97754
+ })]
97755
+ });
97756
+ }
97757
+ var init_CheckboxChoice = __esmMin((() => {
97758
+ init_clsx();
97759
+ }));
97760
+ //#endregion
97761
+ //#region ../blocks/src/system/runtime/nodes/form.fields.tsx
97762
+ function fieldBasics(field) {
97763
+ return {
97764
+ inputId: `f_${field.id}`,
97765
+ label: String(field.label ?? field.id),
97766
+ required: Boolean(field.required)
97767
+ };
97768
+ }
97769
+ function textInputType(type) {
97770
+ return type === "email" || type === "url" || type === "tel" || type === "number" ? type : "text";
97771
+ }
97772
+ function textInputConstraints(field, inputType) {
97773
+ if (inputType === "number") return {
97774
+ ...typeof field.min === "number" ? { min: field.min } : {},
97775
+ ...typeof field.max === "number" ? { max: field.max } : {}
97776
+ };
97777
+ return {
97778
+ ...typeof field.minLength === "number" ? { minLength: field.minLength } : {},
97779
+ ...typeof field.maxLength === "number" ? { maxLength: field.maxLength } : {},
97780
+ ...typeof field.pattern === "string" && field.pattern ? { pattern: field.pattern } : {}
97781
+ };
97782
+ }
97783
+ function LabelledField({ basics, children }) {
97784
+ return /* @__PURE__ */ jsxs("div", {
97785
+ className: "fb-field",
97786
+ children: [/* @__PURE__ */ jsx("label", {
97787
+ htmlFor: basics.inputId,
97788
+ className: "form-label",
97789
+ children: basics.label
97790
+ }), children]
97791
+ });
97792
+ }
97793
+ function TextareaField({ field }) {
97794
+ const basics = fieldBasics(field);
97795
+ return /* @__PURE__ */ jsx(LabelledField, {
97796
+ basics,
97797
+ children: /* @__PURE__ */ jsx("textarea", {
97798
+ id: basics.inputId,
97799
+ name: field.id,
97800
+ required: basics.required,
97801
+ placeholder: field.placeholder,
97802
+ rows: field.rows,
97803
+ className: "form-textarea"
97804
+ })
97805
+ });
97806
+ }
97807
+ function SelectField({ field }) {
97808
+ const basics = fieldBasics(field);
97809
+ const options = field.options ?? [];
97810
+ const multiple = Boolean(field.multiple);
97811
+ return /* @__PURE__ */ jsx(LabelledField, {
97812
+ basics,
97813
+ children: /* @__PURE__ */ jsxs("select", {
97814
+ id: basics.inputId,
97815
+ name: field.id,
97816
+ multiple,
97817
+ required: basics.required,
97818
+ className: "form-select",
97819
+ children: [!multiple && /* @__PURE__ */ jsx("option", {
97820
+ value: "",
97821
+ children: "Select…"
97822
+ }), options.map((opt) => /* @__PURE__ */ jsx("option", {
97823
+ value: opt.value,
97824
+ children: opt.label
97825
+ }, opt.value))]
97826
+ })
97827
+ });
97828
+ }
97829
+ function RadioField({ field }) {
97830
+ const basics = fieldBasics(field);
97831
+ const options = field.options ?? [];
97832
+ return /* @__PURE__ */ jsxs("fieldset", {
97833
+ className: "fb-fieldset",
97834
+ children: [/* @__PURE__ */ jsx("legend", {
97835
+ className: "form-label",
97836
+ children: basics.label
97837
+ }), options.map((opt) => /* @__PURE__ */ jsxs("label", {
97838
+ className: "form-check",
97839
+ children: [/* @__PURE__ */ jsx("input", {
97840
+ type: "radio",
97841
+ name: field.id,
97842
+ value: opt.value,
97843
+ required: basics.required,
97844
+ className: "form-radio"
97845
+ }), /* @__PURE__ */ jsx("span", {
97846
+ className: "form-check-label",
97847
+ children: opt.label
97848
+ })]
97849
+ }, opt.value))]
97850
+ });
97851
+ }
97852
+ function TextInputField({ field, type }) {
97853
+ const basics = fieldBasics(field);
97854
+ const inputType = textInputType(type);
97855
+ return /* @__PURE__ */ jsx(LabelledField, {
97856
+ basics,
97857
+ children: /* @__PURE__ */ jsx("input", {
97858
+ id: basics.inputId,
97859
+ name: field.id,
97860
+ type: inputType,
97861
+ required: basics.required,
97862
+ placeholder: field.placeholder,
97863
+ ...textInputConstraints(field, inputType),
97864
+ className: "form-input"
97865
+ })
97866
+ });
97867
+ }
97868
+ function FormFieldControl({ field }) {
97869
+ const type = String(field.type ?? "text");
97870
+ switch (type) {
97871
+ case "textarea": return /* @__PURE__ */ jsx(TextareaField, { field });
97872
+ case "select": return /* @__PURE__ */ jsx(SelectField, { field });
97873
+ case "radio": return /* @__PURE__ */ jsx(RadioField, { field });
97874
+ case "checkbox":
97875
+ case "consent": {
97876
+ const basics = fieldBasics(field);
97877
+ return /* @__PURE__ */ jsx(CheckboxChoice, {
97878
+ name: field.id,
97879
+ required: basics.required,
97880
+ label: basics.label,
97881
+ presentation: type === "consent" ? "tile" : "row"
97882
+ });
97883
+ }
97884
+ default: return /* @__PURE__ */ jsx(TextInputField, {
97885
+ field,
97886
+ type
97887
+ });
97888
+ }
97889
+ }
97890
+ var init_form_fields = __esmMin((() => {
97891
+ init_CheckboxChoice();
97892
+ }));
97893
+ //#endregion
97687
97894
  //#region ../blocks/src/system/runtime/nodes/form.client.tsx
97688
97895
  function isUnknownArray$4(value) {
97689
97896
  return Array.isArray(value);
@@ -97696,6 +97903,7 @@ var init_form_client = __esmMin((() => {
97696
97903
  init_useFormSubmission();
97697
97904
  init_ThemedButton();
97698
97905
  init_FeedbackMessage();
97906
+ init_form_fields();
97699
97907
  FormNodeClient = ({ render }) => {
97700
97908
  const form = render.display.form;
97701
97909
  const { submit, state } = useFormSubmission();
@@ -97708,107 +97916,7 @@ var init_form_client = __esmMin((() => {
97708
97916
  children: "Missing or unknown form."
97709
97917
  });
97710
97918
  const groups = render.display.groups;
97711
- const renderField = (field) => {
97712
- const inputId = `f_${field.id}`;
97713
- const label = String(field.label ?? field.id);
97714
- const required = Boolean(field.required);
97715
- const type = String(field.type ?? "text");
97716
- if (type === "textarea") return /* @__PURE__ */ jsxs("div", {
97717
- className: "fb-field",
97718
- children: [/* @__PURE__ */ jsx("label", {
97719
- htmlFor: inputId,
97720
- className: "form-label",
97721
- children: label
97722
- }), /* @__PURE__ */ jsx("textarea", {
97723
- id: inputId,
97724
- name: field.id,
97725
- required,
97726
- placeholder: field.placeholder,
97727
- rows: field.rows,
97728
- className: "form-textarea"
97729
- })]
97730
- }, field.id);
97731
- if (type === "select") {
97732
- const options = field.options ?? [];
97733
- const multiple = Boolean(field.multiple);
97734
- return /* @__PURE__ */ jsxs("div", {
97735
- className: "fb-field",
97736
- children: [/* @__PURE__ */ jsx("label", {
97737
- htmlFor: inputId,
97738
- className: "form-label",
97739
- children: label
97740
- }), /* @__PURE__ */ jsxs("select", {
97741
- id: inputId,
97742
- name: field.id,
97743
- multiple,
97744
- required,
97745
- className: "form-select",
97746
- children: [!multiple && /* @__PURE__ */ jsx("option", {
97747
- value: "",
97748
- children: "Select…"
97749
- }), options.map((opt) => /* @__PURE__ */ jsx("option", {
97750
- value: opt.value,
97751
- children: opt.label
97752
- }, opt.value))]
97753
- })]
97754
- }, field.id);
97755
- }
97756
- if (type === "radio") {
97757
- const options = field.options ?? [];
97758
- return /* @__PURE__ */ jsxs("fieldset", {
97759
- className: "fb-fieldset",
97760
- children: [/* @__PURE__ */ jsx("legend", {
97761
- className: "form-label",
97762
- children: label
97763
- }), options.map((opt) => /* @__PURE__ */ jsxs("label", {
97764
- className: "fb-inline form-label",
97765
- children: [/* @__PURE__ */ jsx("input", {
97766
- type: "radio",
97767
- name: field.id,
97768
- value: opt.value,
97769
- required,
97770
- className: "form-radio"
97771
- }), /* @__PURE__ */ jsx("span", { children: opt.label })]
97772
- }, opt.value))]
97773
- }, field.id);
97774
- }
97775
- if (type === "checkbox" || type === "consent") return /* @__PURE__ */ jsxs("label", {
97776
- className: "fb-inline form-label",
97777
- children: [/* @__PURE__ */ jsx("input", {
97778
- type: "checkbox",
97779
- name: field.id,
97780
- required,
97781
- className: "form-checkbox"
97782
- }), /* @__PURE__ */ jsx("span", { children: label })]
97783
- }, field.id);
97784
- const inputType = type === "email" || type === "url" || type === "tel" || type === "number" ? type : "text";
97785
- const extra = {};
97786
- if (inputType === "text" || inputType === "email" || inputType === "url" || inputType === "tel") {
97787
- if (typeof field.minLength === "number") extra.minLength = field.minLength;
97788
- if (typeof field.maxLength === "number") extra.maxLength = field.maxLength;
97789
- if (typeof field.pattern === "string" && field.pattern) extra.pattern = field.pattern;
97790
- }
97791
- if (inputType === "number") {
97792
- if (typeof field.min === "number") extra.min = field.min;
97793
- if (typeof field.max === "number") extra.max = field.max;
97794
- }
97795
- return /* @__PURE__ */ jsxs("div", {
97796
- className: "fb-field",
97797
- children: [/* @__PURE__ */ jsx("label", {
97798
- htmlFor: inputId,
97799
- className: "form-label",
97800
- children: label
97801
- }), /* @__PURE__ */ jsx("input", {
97802
- id: inputId,
97803
- name: field.id,
97804
- type: inputType,
97805
- required,
97806
- placeholder: field.placeholder,
97807
- ...extra,
97808
- className: "form-input"
97809
- })]
97810
- }, field.id);
97811
- };
97919
+ const renderField = (field) => /* @__PURE__ */ jsx(FormFieldControl, { field }, field.id);
97812
97920
  const handleSubmit = async (e) => {
97813
97921
  e.preventDefault();
97814
97922
  const formData = new FormData(e.currentTarget);
@@ -101998,7 +102106,7 @@ function DefaultFieldInput({ describedBy, error, errorId, field, onBlur, onChang
101998
102106
  case "radio": return /* @__PURE__ */ jsx("div", {
101999
102107
  className: "rb-space-y-2",
102000
102108
  children: field.field.options?.map((option) => /* @__PURE__ */ jsxs("label", {
102001
- className: "rb-flex rb-items-center rb-gap-2 rb-cursor-pointer",
102109
+ className: "form-check",
102002
102110
  children: [/* @__PURE__ */ jsx("input", {
102003
102111
  type: "radio",
102004
102112
  name: field.id,
@@ -102010,7 +102118,7 @@ function DefaultFieldInput({ describedBy, error, errorId, field, onBlur, onChang
102010
102118
  ...validationProps,
102011
102119
  className: "form-radio"
102012
102120
  }), /* @__PURE__ */ jsx("span", {
102013
- className: "rb-caption",
102121
+ className: "form-check-label",
102014
102122
  children: option.label
102015
102123
  })]
102016
102124
  }, option.value))
@@ -102020,47 +102128,20 @@ function DefaultFieldInput({ describedBy, error, errorId, field, onBlur, onChang
102020
102128
  const checkedValues = toStringArray(value);
102021
102129
  return /* @__PURE__ */ jsx("div", {
102022
102130
  className: "rb-space-y-2",
102023
- children: field.field.options.map((option) => /* @__PURE__ */ jsxs("label", {
102024
- className: "rb-flex rb-items-center rb-gap-2 rb-cursor-pointer",
102025
- children: [/* @__PURE__ */ jsx("input", {
102026
- type: "checkbox",
102027
- name: field.id,
102028
- value: option.value,
102029
- checked: checkedValues.includes(option.value),
102030
- onChange: (event) => {
102031
- onChange(event.target.checked ? [...checkedValues, option.value] : checkedValues.filter((item) => item !== option.value));
102032
- },
102033
- onBlur,
102034
- ...validationProps,
102035
- className: "form-checkbox"
102036
- }), /* @__PURE__ */ jsx("span", {
102037
- className: "rb-caption",
102038
- children: option.label
102039
- })]
102131
+ children: field.field.options.map((option) => /* @__PURE__ */ jsx(CheckboxChoice, {
102132
+ name: field.id,
102133
+ value: option.value,
102134
+ checked: checkedValues.includes(option.value),
102135
+ onChange: (event) => {
102136
+ onChange(event.target.checked ? [...checkedValues, option.value] : checkedValues.filter((item) => item !== option.value));
102137
+ },
102138
+ onBlur,
102139
+ ...validationProps,
102140
+ label: option.label
102040
102141
  }, option.value))
102041
102142
  });
102042
102143
  }
102043
- return /* @__PURE__ */ jsxs("label", {
102044
- className: "rb-flex rb-items-center rb-gap-2 rb-cursor-pointer",
102045
- children: [/* @__PURE__ */ jsx("input", {
102046
- type: "checkbox",
102047
- id: field.inputId,
102048
- name: field.id,
102049
- checked: Boolean(value),
102050
- onChange: (event) => onChange(event.target.checked),
102051
- onBlur,
102052
- required: field.required,
102053
- ...validationProps,
102054
- className: "form-checkbox"
102055
- }), /* @__PURE__ */ jsx("span", {
102056
- className: "rb-caption",
102057
- children: field.field.placeholder || field.label
102058
- })]
102059
- });
102060
- case "booking_requirement_consent": return /* @__PURE__ */ jsxs("label", {
102061
- className: "rb-flex rb-items-start rb-gap-2 rb-cursor-pointer",
102062
- children: [/* @__PURE__ */ jsx("input", {
102063
- type: "checkbox",
102144
+ return /* @__PURE__ */ jsx(CheckboxChoice, {
102064
102145
  id: field.inputId,
102065
102146
  name: field.id,
102066
102147
  checked: Boolean(value),
@@ -102068,11 +102149,18 @@ function DefaultFieldInput({ describedBy, error, errorId, field, onBlur, onChang
102068
102149
  onBlur,
102069
102150
  required: field.required,
102070
102151
  ...validationProps,
102071
- className: "form-checkbox rb-mt-0.5"
102072
- }), /* @__PURE__ */ jsx("span", {
102073
- className: "rb-caption",
102074
- children: field.field.checkboxLabel
102075
- })]
102152
+ label: field.field.placeholder || field.label
102153
+ });
102154
+ case "booking_requirement_consent": return /* @__PURE__ */ jsx(CheckboxChoice, {
102155
+ id: field.inputId,
102156
+ name: field.id,
102157
+ checked: Boolean(value),
102158
+ onChange: (event) => onChange(event.target.checked),
102159
+ onBlur,
102160
+ required: field.required,
102161
+ ...validationProps,
102162
+ label: field.field.checkboxLabel,
102163
+ presentation: "tile"
102076
102164
  });
102077
102165
  case "number": return /* @__PURE__ */ jsx("input", {
102078
102166
  ...commonProps,
@@ -102201,6 +102289,7 @@ var init_booking_form_default_ui = __esmMin((() => {
102201
102289
  init_DiscountCodeDisclosure();
102202
102290
  init_FieldValidationMessage();
102203
102291
  init_BookingConsentAgreement();
102292
+ init_CheckboxChoice();
102204
102293
  init_booking_form_service_choices();
102205
102294
  }));
102206
102295
  //#endregion
@@ -102542,6 +102631,7 @@ var init_SelectableOptionCard = __esmMin((() => {}));
102542
102631
  //#endregion
102543
102632
  //#region ../blocks/src/system/runtime/shared/components/index.ts
102544
102633
  var init_components = __esmMin((() => {
102634
+ init_CheckboxChoice();
102545
102635
  init_CheckIcon$1();
102546
102636
  init_ClockIcon();
102547
102637
  init_CrossIcon();
@@ -107616,26 +107706,24 @@ function EventConsentField({ consent, error, formData, idBase, onChange }) {
107616
107706
  title: consent.title,
107617
107707
  titleId: `${idBase}-consent-title`
107618
107708
  }),
107619
- /* @__PURE__ */ jsxs("label", {
107620
- className: "er-label rb-flex rb-items-start rb-gap-2 rb-cursor-pointer",
107621
- children: [
107622
- /* @__PURE__ */ jsx("input", {
107623
- "aria-describedby": error ? errorId : void 0,
107624
- className: "form-checkbox rb-mt-0.5",
107625
- checked: formData.consentAccepted === true,
107626
- onChange: (event) => onChange({
107627
- ...formData,
107628
- consentAccepted: event.target.checked
107629
- }),
107630
- type: "checkbox"
107631
- }),
107709
+ /* @__PURE__ */ jsx(CheckboxChoice, {
107710
+ "aria-describedby": error ? errorId : void 0,
107711
+ "aria-invalid": error ? true : void 0,
107712
+ checked: formData.consentAccepted === true,
107713
+ onChange: (event) => onChange({
107714
+ ...formData,
107715
+ consentAccepted: event.target.checked
107716
+ }),
107717
+ label: /* @__PURE__ */ jsxs(Fragment, { children: [
107632
107718
  consent.checkboxLabel,
107633
107719
  " ",
107634
107720
  /* @__PURE__ */ jsx("span", {
107635
107721
  className: "er-required",
107636
107722
  children: "*"
107637
107723
  })
107638
- ]
107724
+ ] }),
107725
+ presentation: "tile",
107726
+ className: "er-consent-check"
107639
107727
  }),
107640
107728
  error ? /* @__PURE__ */ jsx(FieldValidationMessage, {
107641
107729
  id: errorId,
@@ -107671,6 +107759,7 @@ var init_AttendeeDetailsStep = __esmMin((() => {
107671
107759
  init_LoggedInAsUser();
107672
107760
  init_FieldValidationMessage();
107673
107761
  init_BookingConsentAgreement();
107762
+ init_CheckboxChoice();
107674
107763
  AttendeeDetailsStep = ({ formData, onChange, errors, emailLocked = false, onLogout, ticketsCount = 1, requireGuestDetails = false, guests = [], onGuestsChange, guestErrors = {}, guestSectionShake = false, onGuestShakeEnd, consent }) => {
107675
107764
  const idBase = useId();
107676
107765
  const nameId = `${idBase}-name`;
@@ -115445,6 +115534,148 @@ var init_shop = __esmMin((() => {
115445
115534
  };
115446
115535
  }));
115447
115536
  //#endregion
115537
+ //#region ../blocks/src/system/runtime/nodes/newsletter-form.parts.tsx
115538
+ /** Splits the preset's fields into the email (joined with the button) and the rest. */
115539
+ function partitionNewsletterFields(fields) {
115540
+ const email = fields.find((field) => field.type === "email") ?? null;
115541
+ return {
115542
+ email,
115543
+ extra: fields.filter((field) => field !== email)
115544
+ };
115545
+ }
115546
+ function NewsletterExtraField({ field, disabled, error }) {
115547
+ const inputId = inputIdFor(field);
115548
+ const errorId = `${inputId}-error`;
115549
+ return /* @__PURE__ */ jsxs("div", {
115550
+ className: "fb-field newsletter-field",
115551
+ children: [
115552
+ /* @__PURE__ */ jsx("label", {
115553
+ htmlFor: inputId,
115554
+ className: "rb-sr-only",
115555
+ children: field.label
115556
+ }),
115557
+ /* @__PURE__ */ jsx("input", {
115558
+ id: inputId,
115559
+ name: field.id,
115560
+ type: field.type,
115561
+ required: field.required,
115562
+ placeholder: field.placeholder ?? field.label,
115563
+ className: "form-input",
115564
+ disabled,
115565
+ ...getFieldValidationControlProps({
115566
+ message: error,
115567
+ messageId: errorId
115568
+ })
115569
+ }),
115570
+ error ? /* @__PURE__ */ jsx(FieldValidationMessage, {
115571
+ id: errorId,
115572
+ className: "fb-error",
115573
+ children: error
115574
+ }) : null
115575
+ ]
115576
+ });
115577
+ }
115578
+ /** The email field and submit button sharing one input-styled shell. */
115579
+ function NewsletterEmailEntry({ field, buttonVariant, buttonLabel, disabled, error }) {
115580
+ const inputId = inputIdFor(field);
115581
+ const errorId = `${inputId}-error`;
115582
+ return /* @__PURE__ */ jsxs("div", {
115583
+ className: "newsletter-entry",
115584
+ children: [/* @__PURE__ */ jsxs("div", {
115585
+ className: "form-input-group newsletter-entry-group",
115586
+ children: [
115587
+ /* @__PURE__ */ jsx("label", {
115588
+ htmlFor: inputId,
115589
+ className: "rb-sr-only",
115590
+ children: field.label
115591
+ }),
115592
+ /* @__PURE__ */ jsx("input", {
115593
+ id: inputId,
115594
+ name: field.id,
115595
+ type: "email",
115596
+ required: field.required,
115597
+ placeholder: field.placeholder ?? field.label,
115598
+ className: "form-input-group-field",
115599
+ autoComplete: "email",
115600
+ disabled,
115601
+ ...getFieldValidationControlProps({
115602
+ message: error,
115603
+ messageId: errorId
115604
+ })
115605
+ }),
115606
+ /* @__PURE__ */ jsx(ThemedButton, {
115607
+ type: "submit",
115608
+ variant: buttonVariant,
115609
+ size: "md",
115610
+ disabled,
115611
+ label: buttonLabel
115612
+ })
115613
+ ]
115614
+ }), error ? /* @__PURE__ */ jsx(FieldValidationMessage, {
115615
+ id: errorId,
115616
+ className: "fb-error",
115617
+ children: error
115618
+ }) : null]
115619
+ });
115620
+ }
115621
+ /**
115622
+ * The submit action: joined to the email field when the preset has one
115623
+ * (every current preset does), otherwise a plain themed button.
115624
+ */
115625
+ function NewsletterSubmitRow({ emailField, buttonVariant, buttonLabel, disabled, error }) {
115626
+ if (emailField) return /* @__PURE__ */ jsx(NewsletterEmailEntry, {
115627
+ field: emailField,
115628
+ buttonVariant,
115629
+ buttonLabel,
115630
+ disabled,
115631
+ error
115632
+ });
115633
+ return /* @__PURE__ */ jsx("div", {
115634
+ className: "newsletter-submit",
115635
+ children: /* @__PURE__ */ jsx(ThemedButton, {
115636
+ type: "submit",
115637
+ variant: buttonVariant,
115638
+ size: "md",
115639
+ disabled,
115640
+ label: buttonLabel
115641
+ })
115642
+ });
115643
+ }
115644
+ /** Visitor-chosen topics as toggle chips. Real checkboxes underneath. */
115645
+ function NewsletterTopicChips({ choices, disabled, error }) {
115646
+ const errorId = `newsletter_${TOPIC_CHOICE_FIELD_ID}-error`;
115647
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("fieldset", {
115648
+ className: "newsletter-topics",
115649
+ "aria-describedby": error ? errorId : void 0,
115650
+ children: [/* @__PURE__ */ jsx("legend", {
115651
+ className: "newsletter-topics-legend",
115652
+ children: "What would you like to hear about?"
115653
+ }), /* @__PURE__ */ jsx("div", {
115654
+ className: "newsletter-topic-chips",
115655
+ children: choices.map((choice) => /* @__PURE__ */ jsxs("label", {
115656
+ className: "newsletter-topic-chip",
115657
+ children: [/* @__PURE__ */ jsx("input", {
115658
+ type: "checkbox",
115659
+ name: TOPIC_CHOICE_FIELD_ID,
115660
+ value: choice.id,
115661
+ disabled
115662
+ }), /* @__PURE__ */ jsx("span", { children: choice.label })]
115663
+ }, choice.id))
115664
+ })]
115665
+ }), error ? /* @__PURE__ */ jsx(FieldValidationMessage, {
115666
+ id: errorId,
115667
+ className: "fb-error",
115668
+ children: error
115669
+ }) : null] });
115670
+ }
115671
+ var TOPIC_CHOICE_FIELD_ID, inputIdFor;
115672
+ var init_newsletter_form_parts = __esmMin((() => {
115673
+ init_ThemedButton();
115674
+ init_FieldValidationMessage();
115675
+ TOPIC_CHOICE_FIELD_ID = "mailingListChoice";
115676
+ inputIdFor = (field) => `newsletter_${field.id}`;
115677
+ }));
115678
+ //#endregion
115448
115679
  //#region ../blocks/src/system/runtime/nodes/newsletter-form.client.state.ts
115449
115680
  function newsletterFormSubmissionReducer(state, action) {
115450
115681
  switch (action.type) {
@@ -115537,6 +115768,10 @@ function resolveNewsletterSubmitTarget(input) {
115537
115768
  tag: "unavailable",
115538
115769
  reason: "preview_only_source"
115539
115770
  };
115771
+ case "unpublished-preview": return {
115772
+ tag: "unavailable",
115773
+ reason: "preview_only_source"
115774
+ };
115540
115775
  default: return assertNever$20(input);
115541
115776
  }
115542
115777
  }
@@ -115559,6 +115794,7 @@ var init_newsletter_form_submission = __esmMin((() => {
115559
115794
  //#endregion
115560
115795
  //#region ../blocks/src/system/runtime/nodes/newsletter-form.client.tsx
115561
115796
  function NewsletterFormClient({ render }) {
115797
+ const submissionMessage = newsletterBlockSubmissionMessage(render.hydration.target);
115562
115798
  const api = useBlockApi();
115563
115799
  const [submissionState, dispatchSubmission] = useReducer(newsletterFormSubmissionReducer, initialNewsletterFormSubmissionState);
115564
115800
  const [altchaSolution, setAltchaSolution] = useState(null);
@@ -115568,7 +115804,6 @@ function NewsletterFormClient({ render }) {
115568
115804
  if (succeeded) successRef.current?.focus();
115569
115805
  }, [succeeded]);
115570
115806
  const showSpamProtection = render.hydration.spamProtectionEnabled ?? isSpamProtectionEnabled();
115571
- const fields = render.display.fields;
115572
115807
  const handleSubmit = async (e) => {
115573
115808
  e.preventDefault();
115574
115809
  const formData = new FormData(e.currentTarget);
@@ -115600,7 +115835,7 @@ function NewsletterFormClient({ render }) {
115600
115835
  reportNewsletterSignupRefusal(submitTarget.reason, { target: render.hydration.target });
115601
115836
  dispatchSubmission({
115602
115837
  type: "failed",
115603
- error: newsletterFormError(SIGNUPS_PAUSED_MESSAGE)
115838
+ error: newsletterFormError(NEWSLETTER_SIGNUPS_PAUSED_MESSAGE)
115604
115839
  });
115605
115840
  return;
115606
115841
  }
@@ -115608,7 +115843,7 @@ function NewsletterFormClient({ render }) {
115608
115843
  reportNewsletterSignupRefusal("setup_not_configured");
115609
115844
  dispatchSubmission({
115610
115845
  type: "failed",
115611
- error: newsletterFormError(SIGNUPS_PAUSED_MESSAGE)
115846
+ error: newsletterFormError(NEWSLETTER_SIGNUPS_PAUSED_MESSAGE)
115612
115847
  });
115613
115848
  return;
115614
115849
  }
@@ -115616,7 +115851,7 @@ function NewsletterFormClient({ render }) {
115616
115851
  reportNewsletterSignupRefusal("destination_unavailable", { setupRevision: render.hydration.setupRevision });
115617
115852
  dispatchSubmission({
115618
115853
  type: "failed",
115619
- error: newsletterFormError(SIGNUPS_PAUSED_MESSAGE)
115854
+ error: newsletterFormError(NEWSLETTER_SIGNUPS_PAUSED_MESSAGE)
115620
115855
  });
115621
115856
  return;
115622
115857
  }
@@ -115691,43 +115926,14 @@ function NewsletterFormClient({ render }) {
115691
115926
  autoComplete: "off",
115692
115927
  "aria-hidden": "true"
115693
115928
  }),
115694
- /* @__PURE__ */ jsxs("div", {
115695
- className: "newsletter-form-fields",
115696
- children: [
115697
- fields.map((field) => /* @__PURE__ */ jsx(NewsletterField, {
115698
- field,
115699
- submitting,
115700
- error: getNewsletterSubmissionFieldError(submissionState, field.id)
115701
- }, field.id)),
115702
- render.hydration.choicePresentation === "visitor_choice" ? /* @__PURE__ */ jsx(NewsletterTopicChoices, {
115703
- choices: render.display.choices,
115704
- submitting,
115705
- error: getNewsletterSubmissionFieldError(submissionState, TOPIC_CHOICE_FIELD_ID)
115706
- }) : null,
115707
- showSpamProtection && /* @__PURE__ */ jsx("div", {
115708
- className: "newsletter-altcha",
115709
- children: /* @__PURE__ */ jsx(AltchaWidget, {
115710
- challengeUrl: getChallengeUrl(),
115711
- onSolutionChange: setAltchaSolution
115712
- })
115713
- }),
115714
- formError && /* @__PURE__ */ jsx(FeedbackMessage, {
115715
- tone: "error",
115716
- className: "fb-error",
115717
- role: "alert",
115718
- children: formError
115719
- }),
115720
- /* @__PURE__ */ jsx("div", {
115721
- className: "newsletter-submit",
115722
- children: /* @__PURE__ */ jsx(ThemedButton, {
115723
- type: "submit",
115724
- variant: render.display.buttonVariant,
115725
- size: "md",
115726
- disabled: submitting,
115727
- label: submitting ? "Subscribing..." : render.display.buttonLabel
115728
- })
115729
- })
115730
- ]
115929
+ /* @__PURE__ */ jsx(NewsletterFormFields, {
115930
+ render,
115931
+ submissionState,
115932
+ submitting,
115933
+ submissionMessage,
115934
+ formError,
115935
+ showSpamProtection,
115936
+ onAltchaSolution: setAltchaSolution
115731
115937
  }),
115732
115938
  render.display.privacyNote && /* @__PURE__ */ jsx("p", {
115733
115939
  className: "newsletter-privacy-note",
@@ -115737,67 +115943,52 @@ function NewsletterFormClient({ render }) {
115737
115943
  })
115738
115944
  });
115739
115945
  }
115740
- function NewsletterField({ field, submitting, error }) {
115741
- const inputId = `newsletter_${field.id}`;
115742
- const errorId = `${inputId}-error`;
115946
+ function NewsletterFormFields({ render, submissionState, submitting, submissionMessage, formError, showSpamProtection, onAltchaSolution }) {
115947
+ const { email: emailField, extra: extraFields } = partitionNewsletterFields(render.display.fields);
115948
+ const fieldError = (id) => getNewsletterSubmissionFieldError(submissionState, id);
115743
115949
  return /* @__PURE__ */ jsxs("div", {
115744
- className: "fb-field newsletter-field",
115950
+ className: "newsletter-form-fields",
115745
115951
  children: [
115746
- /* @__PURE__ */ jsxs("label", {
115747
- htmlFor: inputId,
115748
- className: "form-label",
115749
- children: [field.label, field.required && /* @__PURE__ */ jsx("span", {
115750
- className: "newsletter-required",
115751
- "aria-hidden": "true",
115752
- children: "*"
115753
- })]
115754
- }),
115755
- /* @__PURE__ */ jsx("input", {
115756
- id: inputId,
115757
- name: field.id,
115758
- type: field.type,
115759
- required: field.required,
115760
- placeholder: field.placeholder,
115761
- className: "form-input",
115762
- autoComplete: field.type === "email" ? "email" : void 0,
115952
+ render.hydration.choicePresentation === "visitor_choice" ? /* @__PURE__ */ jsx(NewsletterTopicChips, {
115953
+ choices: render.display.choices,
115763
115954
  disabled: submitting,
115764
- ...getFieldValidationControlProps({
115765
- message: error,
115766
- messageId: errorId
115955
+ error: fieldError(TOPIC_CHOICE_FIELD_ID)
115956
+ }) : null,
115957
+ extraFields.length > 0 ? /* @__PURE__ */ jsx("div", {
115958
+ className: "newsletter-extra-fields",
115959
+ children: extraFields.map((field) => /* @__PURE__ */ jsx(NewsletterExtraField, {
115960
+ field,
115961
+ disabled: submitting,
115962
+ error: fieldError(field.id)
115963
+ }, field.id))
115964
+ }) : null,
115965
+ showSpamProtection && /* @__PURE__ */ jsx("div", {
115966
+ className: "newsletter-altcha",
115967
+ children: /* @__PURE__ */ jsx(AltchaWidget, {
115968
+ challengeUrl: getChallengeUrl(),
115969
+ onSolutionChange: onAltchaSolution
115767
115970
  })
115768
115971
  }),
115769
- error && /* @__PURE__ */ jsx(FieldValidationMessage, {
115770
- id: errorId,
115972
+ formError && /* @__PURE__ */ jsx(FeedbackMessage, {
115973
+ tone: "error",
115771
115974
  className: "fb-error",
115772
- children: error
115975
+ role: "alert",
115976
+ children: formError
115977
+ }),
115978
+ /* @__PURE__ */ jsx(NewsletterSubmitRow, {
115979
+ emailField,
115980
+ buttonVariant: render.display.buttonVariant,
115981
+ buttonLabel: submitting ? "Subscribing..." : render.display.buttonLabel,
115982
+ disabled: submitting || submissionMessage !== null,
115983
+ error: emailField ? fieldError(emailField.id) : null
115984
+ }),
115985
+ submissionMessage && /* @__PURE__ */ jsx("p", {
115986
+ role: "status",
115987
+ children: submissionMessage
115773
115988
  })
115774
115989
  ]
115775
115990
  });
115776
115991
  }
115777
- function NewsletterTopicChoices({ choices, submitting, error }) {
115778
- const errorId = `newsletter_${TOPIC_CHOICE_FIELD_ID}-error`;
115779
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("fieldset", {
115780
- className: "fb-fieldset newsletter-topics",
115781
- "aria-describedby": error ? errorId : void 0,
115782
- children: [/* @__PURE__ */ jsx("legend", {
115783
- className: "form-label",
115784
- children: "What would you like to hear about?"
115785
- }), choices.map((choice) => /* @__PURE__ */ jsxs("label", {
115786
- className: "fb-inline form-label newsletter-topic-choice",
115787
- children: [/* @__PURE__ */ jsx("input", {
115788
- type: "checkbox",
115789
- name: TOPIC_CHOICE_FIELD_ID,
115790
- value: choice.id,
115791
- className: "form-checkbox",
115792
- disabled: submitting
115793
- }), /* @__PURE__ */ jsx("span", { children: choice.label })]
115794
- }, choice.id))]
115795
- }), error && /* @__PURE__ */ jsx(FieldValidationMessage, {
115796
- id: errorId,
115797
- className: "fb-error",
115798
- children: error
115799
- })] });
115800
- }
115801
115992
  function UnavailableNewsletterForm({ className }) {
115802
115993
  return /* @__PURE__ */ jsx("div", {
115803
115994
  className: clsx("newsletter-form", className ?? void 0),
@@ -115805,7 +115996,7 @@ function UnavailableNewsletterForm({ className }) {
115805
115996
  tone: "error",
115806
115997
  className: "fb-error",
115807
115998
  role: "status",
115808
- children: SIGNUPS_PAUSED_MESSAGE
115999
+ children: NEWSLETTER_SIGNUPS_PAUSED_MESSAGE
115809
116000
  })
115810
116001
  });
115811
116002
  }
@@ -115825,7 +116016,7 @@ function transportFailureMessage(err) {
115825
116016
  function visitorSelectionError(selection) {
115826
116017
  switch (selection.tag) {
115827
116018
  case "nothing_chosen": return newsletterFieldError(TOPIC_CHOICE_FIELD_ID, "Choose at least one email topic.");
115828
- case "unusable": return newsletterFormError(SIGNUPS_PAUSED_MESSAGE);
116019
+ case "unusable": return newsletterFormError(NEWSLETTER_SIGNUPS_PAUSED_MESSAGE);
115829
116020
  case "not_offered":
115830
116021
  case "chosen": return null;
115831
116022
  }
@@ -115857,7 +116048,7 @@ function publicSignupError(outcome) {
115857
116048
  case "unavailable": switch (outcome.reason) {
115858
116049
  case "configuration_unavailable":
115859
116050
  case "authentication_failed":
115860
- case "target_unavailable": return SIGNUPS_PAUSED_MESSAGE;
116051
+ case "target_unavailable": return NEWSLETTER_SIGNUPS_PAUSED_MESSAGE;
115861
116052
  case "stale_configuration": return "This signup form has changed. Refresh the page, then try again.";
115862
116053
  case "rate_limited": return TOO_MANY_ATTEMPTS_MESSAGE;
115863
116054
  case "temporarily_unavailable": return RETRY_SHORTLY_MESSAGE;
@@ -115865,20 +116056,18 @@ function publicSignupError(outcome) {
115865
116056
  case "uncertain": return "We could not confirm whether your signup completed. Please wait a moment, then try again.";
115866
116057
  }
115867
116058
  }
115868
- var TOPIC_CHOICE_FIELD_ID, SIGNUPS_PAUSED_MESSAGE, RETRY_SHORTLY_MESSAGE, TOO_MANY_ATTEMPTS_MESSAGE;
116059
+ var RETRY_SHORTLY_MESSAGE, TOO_MANY_ATTEMPTS_MESSAGE;
115869
116060
  var init_newsletter_form_client = __esmMin((() => {
115870
116061
  init_clsx();
115871
116062
  init_client();
115872
116063
  init_src();
115873
116064
  init_api$1();
115874
116065
  init_src$2();
115875
- init_ThemedButton();
115876
116066
  init_FeedbackMessage();
115877
- init_FieldValidationMessage();
116067
+ init_newsletter_form_parts();
115878
116068
  init_newsletter_form_client_state();
115879
116069
  init_newsletter_form_submission();
115880
- TOPIC_CHOICE_FIELD_ID = "mailingListChoice";
115881
- SIGNUPS_PAUSED_MESSAGE = "We can’t accept signups right now. Please try again later.";
116070
+ init_newsletter_form_interactive();
115882
116071
  RETRY_SHORTLY_MESSAGE = "We couldn’t confirm your signup. Please try again in a little while.";
115883
116072
  TOO_MANY_ATTEMPTS_MESSAGE = "There have been too many signup attempts. Please wait a moment and try again.";
115884
116073
  }));
@@ -124986,6 +125175,7 @@ function EventRegistrationShell({ display }) {
124986
125175
  init_clsx();
124987
125176
  init_ThemedButton();
124988
125177
  init_FeedbackMessage();
125178
+ init_form_fields();
124989
125179
  init_form_interactive();
124990
125180
  const FormNodeSSR = ({ blockId, value, submitLabel, successMessage, className, onSubmit, action = "/api/forms/submit", siteId, apiBaseUrl, spamProtectionEnabled }) => {
124991
125181
  const islandProps = buildFormInteractiveIslandProps({
@@ -125009,107 +125199,7 @@ const FormNodeSSR = ({ blockId, value, submitLabel, successMessage, className, o
125009
125199
  })]
125010
125200
  });
125011
125201
  const groups = display.groups;
125012
- const renderField = (field) => {
125013
- const inputId = `f_${field.id}`;
125014
- const label = String(field.label ?? field.id);
125015
- const required = Boolean(field.required);
125016
- const type = String(field.type ?? "text");
125017
- if (type === "textarea") return /* @__PURE__ */ jsxs("div", {
125018
- className: "fb-field",
125019
- children: [/* @__PURE__ */ jsx("label", {
125020
- htmlFor: inputId,
125021
- className: "form-label",
125022
- children: label
125023
- }), /* @__PURE__ */ jsx("textarea", {
125024
- id: inputId,
125025
- name: field.id,
125026
- required,
125027
- placeholder: field.placeholder,
125028
- rows: field.rows,
125029
- className: "form-textarea"
125030
- })]
125031
- }, field.id);
125032
- if (type === "select") {
125033
- const options = field.options ?? [];
125034
- const multiple = Boolean(field.multiple);
125035
- return /* @__PURE__ */ jsxs("div", {
125036
- className: "fb-field",
125037
- children: [/* @__PURE__ */ jsx("label", {
125038
- htmlFor: inputId,
125039
- className: "form-label",
125040
- children: label
125041
- }), /* @__PURE__ */ jsxs("select", {
125042
- id: inputId,
125043
- name: field.id,
125044
- multiple,
125045
- required,
125046
- className: "form-select",
125047
- children: [!multiple && /* @__PURE__ */ jsx("option", {
125048
- value: "",
125049
- children: "Select…"
125050
- }), options.map((opt) => /* @__PURE__ */ jsx("option", {
125051
- value: opt.value,
125052
- children: opt.label
125053
- }, opt.value))]
125054
- })]
125055
- }, field.id);
125056
- }
125057
- if (type === "radio") {
125058
- const options = field.options ?? [];
125059
- return /* @__PURE__ */ jsxs("fieldset", {
125060
- className: "fb-fieldset",
125061
- children: [/* @__PURE__ */ jsx("legend", {
125062
- className: "form-label",
125063
- children: label
125064
- }), options.map((opt) => /* @__PURE__ */ jsxs("label", {
125065
- className: "fb-inline form-label",
125066
- children: [/* @__PURE__ */ jsx("input", {
125067
- type: "radio",
125068
- name: field.id,
125069
- value: opt.value,
125070
- required,
125071
- className: "form-radio"
125072
- }), /* @__PURE__ */ jsx("span", { children: opt.label })]
125073
- }, opt.value))]
125074
- }, field.id);
125075
- }
125076
- if (type === "checkbox" || type === "consent") return /* @__PURE__ */ jsxs("label", {
125077
- className: "fb-inline form-label",
125078
- children: [/* @__PURE__ */ jsx("input", {
125079
- type: "checkbox",
125080
- name: field.id,
125081
- required,
125082
- className: "form-checkbox"
125083
- }), /* @__PURE__ */ jsx("span", { children: label })]
125084
- }, field.id);
125085
- const inputType = type === "email" || type === "url" || type === "tel" || type === "number" ? type : "text";
125086
- const extra = {};
125087
- if (inputType === "text" || inputType === "email" || inputType === "url" || inputType === "tel") {
125088
- if (typeof field.minLength === "number") extra.minLength = field.minLength;
125089
- if (typeof field.maxLength === "number") extra.maxLength = field.maxLength;
125090
- if (typeof field.pattern === "string" && field.pattern) extra.pattern = field.pattern;
125091
- }
125092
- if (inputType === "number") {
125093
- if (typeof field.min === "number") extra.min = field.min;
125094
- if (typeof field.max === "number") extra.max = field.max;
125095
- }
125096
- return /* @__PURE__ */ jsxs("div", {
125097
- className: "fb-field",
125098
- children: [/* @__PURE__ */ jsx("label", {
125099
- htmlFor: inputId,
125100
- className: "form-label",
125101
- children: label
125102
- }), /* @__PURE__ */ jsx("input", {
125103
- id: inputId,
125104
- name: field.id,
125105
- type: inputType,
125106
- required,
125107
- placeholder: field.placeholder,
125108
- ...extra,
125109
- className: "form-input"
125110
- })]
125111
- }, field.id);
125112
- };
125202
+ const renderField = (field) => /* @__PURE__ */ jsx(FormFieldControl, { field }, field.id);
125113
125203
  return /* @__PURE__ */ jsxs("div", {
125114
125204
  ...getIslandRootProps("form", blockId),
125115
125205
  children: [/* @__PURE__ */ jsx(IslandPropsScript, { value: islandProps }), /* @__PURE__ */ jsxs("form", {
@@ -125157,7 +125247,7 @@ const FormNodeSSR = ({ blockId, value, submitLabel, successMessage, className, o
125157
125247
  //#endregion
125158
125248
  //#region ../blocks/src/system/runtime/nodes/newsletter-form.server.tsx
125159
125249
  init_clsx();
125160
- init_ThemedButton();
125250
+ init_newsletter_form_parts();
125161
125251
  init_newsletter_form_interactive();
125162
125252
  /**
125163
125253
  * Newsletter Form Server Component
@@ -125178,36 +125268,15 @@ function NewsletterFormSSR(props) {
125178
125268
  });
125179
125269
  const display = islandProps.render.display;
125180
125270
  const fields = display.fields;
125271
+ const submissionMessage = newsletterBlockSubmissionMessage(islandProps.render.hydration.target);
125181
125272
  if (display.availability === "unavailable") return /* @__PURE__ */ jsx("div", {
125182
125273
  className: clsx("newsletter-form-ssr", className),
125183
125274
  children: /* @__PURE__ */ jsx("p", {
125184
125275
  role: "status",
125185
- children: "We can’t accept signups right now. Please try again later."
125276
+ children: NEWSLETTER_SIGNUPS_PAUSED_MESSAGE
125186
125277
  })
125187
125278
  });
125188
- const renderField = (field) => {
125189
- const inputId = `newsletter_${field.id}`;
125190
- return /* @__PURE__ */ jsxs("div", {
125191
- className: "fb-field newsletter-field",
125192
- children: [/* @__PURE__ */ jsxs("label", {
125193
- htmlFor: inputId,
125194
- className: "form-label",
125195
- children: [field.label, field.required && /* @__PURE__ */ jsx("span", {
125196
- className: "newsletter-required",
125197
- "aria-hidden": "true",
125198
- children: "*"
125199
- })]
125200
- }), /* @__PURE__ */ jsx("input", {
125201
- id: inputId,
125202
- name: field.id,
125203
- type: field.type,
125204
- required: field.required,
125205
- placeholder: field.placeholder,
125206
- className: "form-input",
125207
- autoComplete: field.type === "email" ? "email" : void 0
125208
- })]
125209
- }, field.id);
125210
- };
125279
+ const { email: emailField, extra: extraFields } = partitionNewsletterFields(fields);
125211
125280
  return /* @__PURE__ */ jsxs("div", {
125212
125281
  ...getIslandRootProps("newsletter-form", blockId),
125213
125282
  className: clsx("newsletter-form-ssr", className),
@@ -125226,30 +125295,20 @@ function NewsletterFormSSR(props) {
125226
125295
  /* @__PURE__ */ jsxs("div", {
125227
125296
  className: "newsletter-form-fields",
125228
125297
  children: [
125229
- fields.map(renderField),
125230
- islandProps.render.hydration.choicePresentation === "visitor_choice" ? /* @__PURE__ */ jsxs("fieldset", {
125231
- className: "fb-fieldset newsletter-topics",
125232
- children: [/* @__PURE__ */ jsx("legend", {
125233
- className: "form-label",
125234
- children: "What would you like to hear about?"
125235
- }), display.choices.map((choice) => /* @__PURE__ */ jsxs("label", {
125236
- className: "fb-inline form-label newsletter-topic-choice",
125237
- children: [/* @__PURE__ */ jsx("input", {
125238
- type: "checkbox",
125239
- name: "mailingListChoice",
125240
- value: choice.id,
125241
- className: "form-checkbox"
125242
- }), /* @__PURE__ */ jsx("span", { children: choice.label })]
125243
- }, choice.id))]
125298
+ islandProps.render.hydration.choicePresentation === "visitor_choice" ? /* @__PURE__ */ jsx(NewsletterTopicChips, { choices: display.choices }) : null,
125299
+ extraFields.length > 0 ? /* @__PURE__ */ jsx("div", {
125300
+ className: "newsletter-extra-fields",
125301
+ children: extraFields.map((field) => /* @__PURE__ */ jsx(NewsletterExtraField, { field }, field.id))
125244
125302
  }) : null,
125245
- /* @__PURE__ */ jsx("div", {
125246
- className: "newsletter-submit",
125247
- children: /* @__PURE__ */ jsx(ThemedButton, {
125248
- type: "submit",
125249
- variant: display.buttonVariant,
125250
- size: "md",
125251
- label: display.buttonLabel
125252
- })
125303
+ /* @__PURE__ */ jsx(NewsletterSubmitRow, {
125304
+ emailField,
125305
+ buttonVariant: display.buttonVariant,
125306
+ buttonLabel: display.buttonLabel,
125307
+ disabled: submissionMessage !== null
125308
+ }),
125309
+ submissionMessage && /* @__PURE__ */ jsx("p", {
125310
+ role: "status",
125311
+ children: submissionMessage
125253
125312
  })
125254
125313
  ]
125255
125314
  }),
@@ -126242,7 +126301,7 @@ const RENDERER_METADATA_PROP_KEYS = /* @__PURE__ */ new Set([
126242
126301
  "blockContent",
126243
126302
  "fragmentRegistry",
126244
126303
  "previewAuthoring",
126245
- "contentVersionId",
126304
+ "newsletterBlockSubmission",
126246
126305
  "imageResolveContext"
126247
126306
  ]);
126248
126307
  function omitRendererMetadataProps(props) {
@@ -126298,7 +126357,7 @@ function resolveNodeMetadata(nodeType, context) {
126298
126357
  pathBase: context.pathBase,
126299
126358
  fragmentRegistry: context.fragmentRegistry
126300
126359
  } : {},
126301
- ...normalizedType === "newsletter-form" ? { contentVersionId: context.contentVersionId } : {},
126360
+ ...normalizedType === "newsletter-form" ? { newsletterBlockSubmission: context.newsletterBlockSubmission } : {},
126302
126361
  ...normalizedType === "media" && context.imageResolveContext ? { imageResolveContext: context.imageResolveContext } : {}
126303
126362
  };
126304
126363
  }
@@ -126917,6 +126976,259 @@ function generateHoverEffects(axes, _space) {
126917
126976
  };
126918
126977
  }
126919
126978
  //#endregion
126979
+ //#region ../theme-core/src/inputs/checkable.ts
126980
+ init_colorTokenParts();
126981
+ init_colorStyles();
126982
+ const CHECKABLE_SIZE = "1.375rem";
126983
+ /** Never fully round: a round checkbox reads as a radio. */
126984
+ const CHECKBOX_RADIUS = {
126985
+ square: "0",
126986
+ soft: "0.25rem",
126987
+ rounded: "0.375rem",
126988
+ pill: "0.375rem"
126989
+ };
126990
+ /** Tiles hold wrapping text, so pill themes get a generous radius, not a capsule. */
126991
+ const TILE_RADIUS = {
126992
+ square: "0",
126993
+ soft: "0.5rem",
126994
+ rounded: "0.75rem",
126995
+ pill: "1rem"
126996
+ };
126997
+ const ON_ACCENT_TOKENS = {
126998
+ primary: "onPrimary",
126999
+ secondary: "onSecondary",
127000
+ accent: "onAccent"
127001
+ };
127002
+ /**
127003
+ * Colour for the tick/dot drawn on top of the accent fill. Uses the palette's
127004
+ * matching "on" token where there is one, falling back to white.
127005
+ */
127006
+ /** The accent at full strength: `primary/70` becomes `primary`. */
127007
+ function solidAccentToken(accentToken) {
127008
+ const parsed = parseColorTokenParts(accentToken);
127009
+ return parsed.kind === "token" ? parsed.token : accentToken;
127010
+ }
127011
+ function checkableMarkColor(accentToken) {
127012
+ const parsed = parseColorTokenParts(accentToken);
127013
+ const onToken = parsed.kind === "token" ? ON_ACCENT_TOKENS[parsed.token] : void 0;
127014
+ return onToken ? `rgb(var(--tb-${onToken}, 255 255 255))` : "rgb(255 255 255)";
127015
+ }
127016
+ function checkableSelectors(root) {
127017
+ return {
127018
+ checkbox: `${root} .form-checkbox`,
127019
+ radio: `${root} .form-radio`,
127020
+ check: `${root} .form-check`,
127021
+ tile: `${root} .form-check--tile`
127022
+ };
127023
+ }
127024
+ /** The box and circle themselves, unchecked. */
127025
+ function controlBaseCss(sel, input) {
127026
+ const border = input.borderWidth === "0" ? "1px" : input.borderWidth;
127027
+ return [
127028
+ `${sel.checkbox},
127029
+ ${sel.radio} {
127030
+ appearance: none;
127031
+ display: inline-grid;
127032
+ place-content: center;
127033
+ width: ${CHECKABLE_SIZE};
127034
+ height: ${CHECKABLE_SIZE};
127035
+ margin: 0;
127036
+ flex-shrink: 0;
127037
+ border: ${border} solid ${input.borderColor};
127038
+ background-color: ${input.background};
127039
+ color: inherit;
127040
+ cursor: pointer;
127041
+ transition: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
127042
+ }`,
127043
+ `${sel.checkbox} {
127044
+ border-radius: ${CHECKBOX_RADIUS[input.corners]};
127045
+ }`,
127046
+ `${sel.radio} {
127047
+ border-radius: 9999px;
127048
+ }`
127049
+ ];
127050
+ }
127051
+ /** The tick and dot, drawn with ::before so their colour is a theme token. */
127052
+ function controlMarkCss(sel, accentToken) {
127053
+ return [
127054
+ `${sel.checkbox}::before,
127055
+ ${sel.radio}::before {
127056
+ content: "";
127057
+ background-color: ${checkableMarkColor(accentToken)};
127058
+ transform: scale(0);
127059
+ transition: transform 0.12s ease;
127060
+ }`,
127061
+ `${sel.checkbox}::before {
127062
+ width: 0.75rem;
127063
+ height: 0.75rem;
127064
+ clip-path: polygon(14% 52%, 0 67%, 38% 100%, 100% 22%, 85% 8%, 37% 70%);
127065
+ }`,
127066
+ `${sel.radio}::before {
127067
+ width: 0.5rem;
127068
+ height: 0.5rem;
127069
+ border-radius: 9999px;
127070
+ }`
127071
+ ];
127072
+ }
127073
+ function controlStateCss(sel, input) {
127074
+ const accent = rgbColorValue(solidAccentToken(input.accentToken));
127075
+ return [
127076
+ `${sel.checkbox}:hover,
127077
+ ${sel.radio}:hover,
127078
+ ${sel.check}:hover > .form-checkbox,
127079
+ ${sel.check}:hover > .form-radio {
127080
+ border-color: ${accent};
127081
+ }`,
127082
+ `${sel.checkbox}:checked,
127083
+ ${sel.radio}:checked {
127084
+ background-color: ${accent};
127085
+ border-color: ${accent};
127086
+ }`,
127087
+ `${sel.checkbox}:checked::before,
127088
+ ${sel.radio}:checked::before {
127089
+ transform: scale(1);
127090
+ }`,
127091
+ `${sel.checkbox}:focus-visible,
127092
+ ${sel.radio}:focus-visible {
127093
+ outline: 2px solid ${accent};
127094
+ outline-offset: 2px;
127095
+ }`,
127096
+ `${sel.checkbox}:disabled,
127097
+ ${sel.radio}:disabled {
127098
+ opacity: 0.5;
127099
+ cursor: not-allowed;
127100
+ }`
127101
+ ];
127102
+ }
127103
+ /** Label row: control lined up with the first line of wrapping text. */
127104
+ function checkRowCss(sel) {
127105
+ return [
127106
+ `${sel.check} {
127107
+ display: flex;
127108
+ align-items: flex-start;
127109
+ gap: 0.75rem;
127110
+ line-height: 1.5;
127111
+ cursor: pointer;
127112
+ }`,
127113
+ `${sel.check} > .form-checkbox,
127114
+ ${sel.check} > .form-radio {
127115
+ margin-top: 0.0625rem;
127116
+ margin-top: max(0px, calc((1lh - ${CHECKABLE_SIZE}) / 2));
127117
+ }`,
127118
+ `${sel.check}:has(> :disabled) {
127119
+ cursor: not-allowed;
127120
+ }`
127121
+ ];
127122
+ }
127123
+ function agreementTileCss(sel, input) {
127124
+ const accent = rgbColorValue(solidAccentToken(input.accentToken));
127125
+ return [
127126
+ `${sel.tile} {
127127
+ padding: 0.875rem 1rem;
127128
+ border: 1px solid color-mix(in srgb, currentColor 22%, transparent);
127129
+ border-radius: ${TILE_RADIUS[input.corners]};
127130
+ transition: border-color 0.15s ease, background-color 0.15s ease;
127131
+ }`,
127132
+ `${sel.tile}:hover {
127133
+ border-color: color-mix(in srgb, ${accent} 55%, transparent);
127134
+ }`,
127135
+ `${sel.tile}:has(> .form-checkbox:checked) {
127136
+ border-color: ${accent};
127137
+ background-color: color-mix(in srgb, ${accent} 7%, transparent);
127138
+ }`,
127139
+ `${sel.tile}:has(> .form-checkbox[aria-invalid="true"]) {
127140
+ border-color: ${input.errorColor};
127141
+ }`
127142
+ ];
127143
+ }
127144
+ function checkableMediaCss(sel) {
127145
+ return [`@media (prefers-reduced-motion: reduce) {
127146
+ ${sel.checkbox}, ${sel.radio}, ${sel.checkbox}::before, ${sel.radio}::before, ${sel.tile} {
127147
+ transition: none;
127148
+ }
127149
+ }`, `@media (forced-colors: active) {
127150
+ ${sel.checkbox}::before,
127151
+ ${sel.radio}::before {
127152
+ background-color: CanvasText;
127153
+ }
127154
+ }`];
127155
+ }
127156
+ /**
127157
+ * Exposes the accent and mark colours so other choice controls (newsletter
127158
+ * topic chips) match the checkboxes without re-deriving the theme tokens.
127159
+ */
127160
+ function checkableVarsCss(input) {
127161
+ return [`${input.root} {
127162
+ --rb-check-accent: ${rgbColorValue(solidAccentToken(input.accentToken))};
127163
+ --rb-check-mark: ${checkableMarkColor(input.accentToken)};
127164
+ }`];
127165
+ }
127166
+ function generateCheckableCss(input) {
127167
+ const sel = checkableSelectors(input.root);
127168
+ return [
127169
+ ...checkableVarsCss(input),
127170
+ ...controlBaseCss(sel, input),
127171
+ ...controlMarkCss(sel, input.accentToken),
127172
+ ...controlStateCss(sel, input),
127173
+ ...checkRowCss(sel),
127174
+ ...agreementTileCss(sel, input),
127175
+ ...checkableMediaCss(sel)
127176
+ ].join("\n\n");
127177
+ }
127178
+ //#endregion
127179
+ //#region ../theme-core/src/inputs/inputGroup.ts
127180
+ /**
127181
+ * Input group: a field and an action (usually a themed button) sharing one
127182
+ * input-styled shell, e.g. the newsletter email + Sign up row.
127183
+ *
127184
+ * The shell `.form-input-group` takes the theme's `.form-input` rules (the
127185
+ * generators add it to that selector list, plus focus and error), so it
127186
+ * follows the site's input background, border, corners and shadow. This file
127187
+ * only adds the layout overrides and the borderless inner field.
127188
+ */
127189
+ const INPUT_GROUP_SELECTOR = ".form-input-group";
127190
+ /** Shell focus ring follows the field only, not the button beside it. */
127191
+ const INPUT_GROUP_FOCUS_SELECTOR = ".form-input-group:has(> .form-input-group-field:focus-visible)";
127192
+ const INPUT_GROUP_ERROR_SELECTOR = ".form-input-group:has(> .form-input-group-field[aria-invalid=\"true\"])";
127193
+ const GROUP_INSET = "0.25rem";
127194
+ /**
127195
+ * @param root - scoped root selector
127196
+ * @param padding - the theme's input padding shorthand (`block inline`), so the
127197
+ * inner field's text sits where a plain input's text would.
127198
+ */
127199
+ function generateInputGroupCss(root, padding) {
127200
+ const [block = padding, inline = block] = padding.trim().split(/\s+/);
127201
+ return `${root} .form-input-group {
127202
+ display: flex;
127203
+ align-items: stretch;
127204
+ gap: ${GROUP_INSET};
127205
+ padding: ${GROUP_INSET};
127206
+ }
127207
+
127208
+ ${root} .form-input-group-field {
127209
+ flex: 1 1 auto;
127210
+ min-width: 0;
127211
+ margin: 0;
127212
+ border: 0;
127213
+ border-radius: 0;
127214
+ background: transparent;
127215
+ box-shadow: none;
127216
+ outline: none;
127217
+ color: inherit;
127218
+ font: inherit;
127219
+ padding: calc(${block} - ${GROUP_INSET}) calc(${inline} - ${GROUP_INSET});
127220
+ }
127221
+
127222
+ ${root} .form-input-group-field::placeholder {
127223
+ color: inherit;
127224
+ opacity: 0.6;
127225
+ }
127226
+
127227
+ ${root} .form-input-group > :not(.form-input-group-field) {
127228
+ flex-shrink: 0;
127229
+ }`;
127230
+ }
127231
+ //#endregion
126920
127232
  //#region ../theme-core/src/inputs/generateInputCss.ts
126921
127233
  init_types$11();
126922
127234
  init_constants$2();
@@ -126930,6 +127242,9 @@ const CORNER_MAP$1 = {
126930
127242
  rounded: "1rem",
126931
127243
  pill: "9999px"
126932
127244
  };
127245
+ function inputBackgroundValue(background) {
127246
+ return background.type === "transparent" ? "transparent" : rgbColorValue(background.colorToken);
127247
+ }
126933
127248
  /**
126934
127249
  * Generate CSS for form input styling based on theme configuration
126935
127250
  *
@@ -126947,8 +127262,7 @@ const CORNER_MAP$1 = {
126947
127262
  function generateInputCss({ themeId, theme, inputSystem }) {
126948
127263
  const rootSelector = `:where([data-theme-scope="${themeId}"])`;
126949
127264
  const baseInputRules = [];
126950
- if (inputSystem.base.background.type === "transparent") baseInputRules.push("background-color: transparent");
126951
- else baseInputRules.push(`background-color: ${rgbColorValue(inputSystem.base.background.colorToken)}`);
127265
+ baseInputRules.push(`background-color: ${inputBackgroundValue(inputSystem.base.background)}`);
126952
127266
  baseInputRules.push(`color: ${rgbColorValue(inputSystem.base.textColorToken)}`);
126953
127267
  const borderPx = parseBorderWidth(inputSystem.base.border.widthClass);
126954
127268
  const borderStyle = inputSystem.base.border.style ?? "all";
@@ -127004,7 +127318,8 @@ function generateInputCss({ themeId, theme, inputSystem }) {
127004
127318
  const focusSelectors = [
127005
127319
  `${inputSelector}:focus-visible`,
127006
127320
  `${textareaSelector}:focus-visible`,
127007
- `${selectSelector}:focus-visible`
127321
+ `${selectSelector}:focus-visible`,
127322
+ `${rootSelector} ${INPUT_GROUP_FOCUS_SELECTOR}`
127008
127323
  ];
127009
127324
  const focusRules = [];
127010
127325
  focusRules.push("outline: none");
@@ -127013,7 +127328,8 @@ function generateInputCss({ themeId, theme, inputSystem }) {
127013
127328
  const errorSelectors = [
127014
127329
  `${inputSelector}[aria-invalid="true"]`,
127015
127330
  `${textareaSelector}[aria-invalid="true"]`,
127016
- `${selectSelector}[aria-invalid="true"]`
127331
+ `${selectSelector}[aria-invalid="true"]`,
127332
+ `${rootSelector} ${INPUT_GROUP_ERROR_SELECTOR}`
127017
127333
  ];
127018
127334
  const errorRules = [];
127019
127335
  errorRules.push(`border-color: ${rgbColorValue(inputSystem.error.borderColorToken)}`);
@@ -127028,53 +127344,25 @@ function generateInputCss({ themeId, theme, inputSystem }) {
127028
127344
  disabledRules.push(`color: ${rgbColorValue(inputSystem.disabled.textColorToken)}`);
127029
127345
  disabledRules.push(`opacity: ${inputSystem.disabled.opacity}`);
127030
127346
  disabledRules.push("cursor: not-allowed");
127031
- const checkboxSelector = `${rootSelector} .form-checkbox`;
127032
- const radioSelector = `${rootSelector} .form-radio`;
127033
- const checkableRules = [];
127034
- checkableRules.push("appearance: none");
127035
- checkableRules.push("width: 1.125rem");
127036
- checkableRules.push("height: 1.125rem");
127037
- checkableRules.push("flex-shrink: 0");
127038
- checkableRules.push(`border: ${borderPx} solid ${rgbColorValue(inputSystem.base.border.colorToken)}`);
127039
- if (inputSystem.base.background.type === "transparent") checkableRules.push("background-color: transparent");
127040
- else checkableRules.push(`background-color: ${rgbColorValue(inputSystem.base.background.colorToken)}`);
127041
- checkableRules.push("cursor: pointer");
127042
- checkableRules.push("transition: background-color 0.2s ease, border-color 0.2s ease");
127043
- const checkboxSpecificRules = [...checkableRules];
127044
- checkboxSpecificRules.push(`border-radius: ${CORNER_MAP$1.soft}`);
127045
- const radioSpecificRules = [...checkableRules];
127046
- radioSpecificRules.push("border-radius: 9999px");
127047
- const checkboxCheckedSelector = `${checkboxSelector}:checked`;
127048
- const checkboxCheckedRules = [];
127049
- checkboxCheckedRules.push(`background-color: ${rgbColorValue(inputSystem.focus.ringColorToken)}`);
127050
- checkboxCheckedRules.push(`border-color: ${rgbColorValue(inputSystem.focus.ringColorToken)}`);
127051
- checkboxCheckedRules.push("background-image: url(\"data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e\")");
127052
- checkboxCheckedRules.push("background-size: 100% 100%");
127053
- checkboxCheckedRules.push("background-position: center");
127054
- checkboxCheckedRules.push("background-repeat: no-repeat");
127055
- const radioCheckedSelector = `${radioSelector}:checked`;
127056
- const radioCheckedRules = [];
127057
- radioCheckedRules.push(`background-color: ${rgbColorValue(inputSystem.focus.ringColorToken)}`);
127058
- radioCheckedRules.push(`border-color: ${rgbColorValue(inputSystem.focus.ringColorToken)}`);
127059
- radioCheckedRules.push("background-image: radial-gradient(circle, white 40%, transparent 40%)");
127060
- const checkboxFocusSelector = `${checkboxSelector}:focus-visible`;
127061
- const radioFocusSelector = `${radioSelector}:focus-visible`;
127062
- const checkableFocusRules = [];
127063
- checkableFocusRules.push("outline: none");
127064
- checkableFocusRules.push(`box-shadow: 0 0 0 ${inputSystem.focus.ringWidth}px ${rgbColorValue(inputSystem.focus.ringColorToken)}`);
127347
+ const checkableCss = generateCheckableCss({
127348
+ root: rootSelector,
127349
+ borderWidth: borderPx,
127350
+ borderColor: rgbColorValue(inputSystem.base.border.colorToken),
127351
+ background: inputBackgroundValue(inputSystem.base.background),
127352
+ corners: inputSystem.base.corners ?? theme.corners,
127353
+ accentToken: inputSystem.focus.borderColorToken ?? inputSystem.focus.ringColorToken,
127354
+ errorColor: rgbColorValue(inputSystem.error.borderColorToken)
127355
+ });
127065
127356
  const cssBlocks = [];
127066
127357
  cssBlocks.push(`${labelSelector} {\n ${labelRules.join(";\n ")};\n}`);
127067
- cssBlocks.push(`${inputSelector} {\n ${inputRules.join(";\n ")};\n}`);
127358
+ cssBlocks.push(`${inputSelector},\n${rootSelector} ${INPUT_GROUP_SELECTOR} {\n ${inputRules.join(";\n ")};\n}`);
127068
127359
  cssBlocks.push(`${textareaSelector} {\n ${textareaRules.join(";\n ")};\n}`);
127069
127360
  cssBlocks.push(`${selectSelector} {\n ${selectRules.join(";\n ")};\n}`);
127070
127361
  cssBlocks.push(`${focusSelectors.join(",\n")} {\n ${focusRules.join(";\n ")};\n}`);
127071
127362
  cssBlocks.push(`${errorSelectors.join(",\n")} {\n ${errorRules.join(";\n ")};\n}`);
127072
127363
  cssBlocks.push(`${disabledSelectors.join(",\n")} {\n ${disabledRules.join(";\n ")};\n}`);
127073
- cssBlocks.push(`${checkboxSelector} {\n ${checkboxSpecificRules.join(";\n ")};\n}`);
127074
- cssBlocks.push(`${radioSelector} {\n ${radioSpecificRules.join(";\n ")};\n}`);
127075
- cssBlocks.push(`${checkboxCheckedSelector} {\n ${checkboxCheckedRules.join(";\n ")};\n}`);
127076
- cssBlocks.push(`${radioCheckedSelector} {\n ${radioCheckedRules.join(";\n ")};\n}`);
127077
- cssBlocks.push(`${checkboxFocusSelector},\n${radioFocusSelector} {\n ${checkableFocusRules.join(";\n ")};\n}`);
127364
+ cssBlocks.push(generateInputGroupCss(rootSelector, padding));
127365
+ cssBlocks.push(checkableCss);
127078
127366
  return cssBlocks.join("\n\n");
127079
127367
  }
127080
127368
  //#endregion
@@ -133622,13 +133910,13 @@ const hours = stack({
133622
133910
  as: "p",
133623
133911
  className: "rb-caption rb-opacity-70"
133624
133912
  }, bind("module.timeZone"), when("module.timeZone"))], when("module.kind", { equals: "opening-hours" }));
133625
- const socials = inline({ className: "rb-flex rb-flex-wrap rb-gap-x-5 rb-gap-y-3" }, [link({
133913
+ const socials = inline({ className: "rb-footer-socials" }, [link({
133626
133914
  href: { $bind: { from: "social.href" } },
133627
133915
  target: "_blank",
133628
133916
  rel: "noreferrer noopener",
133629
133917
  "aria-label": { $bind: { from: "social.label" } },
133630
- className: "rb-nav-text transition-theme-standard"
133631
- }, [icon({ className: "rb-h-5 rb-w-5" }, bind("social.icon"), when("social.icon")), text({ as: "span" }, bind("social.label"), when("social.icon", { equals: null }))], repeat("module.socialLinks", "social"))], when("module.kind", { equals: "social-links" }));
133918
+ className: "rb-footer-social-link rb-nav-text transition-theme-standard"
133919
+ }, [icon({ className: "rb-footer-social-icon" }, bind("social.icon"), when("social.icon")), text({ as: "span" }, bind("social.label"), when("social.icon", { equals: null }))], repeat("module.socialLinks", "social"))], when("module.kind", { equals: "social-links" }));
133632
133920
  const authoredCopy = richText({
133633
133921
  className: "rb-prose rb-prose-sm rb-max-w-none",
133634
133922
  style: textColorStyle("text/80")
@@ -139732,43 +140020,53 @@ function collectNestedPreviewFieldConstraintEntries(field, path) {
139732
140020
  default: return assertNever$20(field);
139733
140021
  }
139734
140022
  }
140023
+ function prepareDefaultBlockRender(manifest, props) {
140024
+ if (!props.theme) throw new Error("Block rendering requires theme tokens; none were provided to makeDefaultBlockComponent");
140025
+ if (!props.registry) throw new Error("Block rendering requires a component registry; none was provided");
140026
+ const content = props.content;
140027
+ const layout = resolveBlockLayout(manifest, content);
140028
+ if (!layout) throw new Error(`Block manifest "${manifest.name}" requires a layout definition`);
140029
+ const mergedContent = mergeContentWithBlockStyleOverrides(content, props.themeConfig, props.blockKind ?? manifest.name);
140030
+ return {
140031
+ registry: props.registry,
140032
+ layout,
140033
+ mergedContent,
140034
+ fieldConstraints: buildPreviewFieldConstraints(manifest),
140035
+ viewModel: buildBlockViewModel({
140036
+ mergedContent,
140037
+ data: props.data,
140038
+ resolvedThemeConfig: resolveThemeConfigForBindings(props.themeConfig),
140039
+ viewModelOverrides: props.viewModelOverrides
140040
+ }),
140041
+ themeForTransforms: withButtonSystem(props.theme, props.themeConfig)
140042
+ };
140043
+ }
139735
140044
  function makeDefaultBlockComponent(args) {
139736
- const { manifest } = args;
139737
- return function DefaultBlockComponent({ content, data, registry, theme, themeConfig, transforms, viewModelOverrides, pathBase, blockId, contentVersionId, blockKind, blockBindings, editableRouteMetadataFieldIds, fragmentRegistry, imageResolveContext, previewAuthoring }) {
140045
+ return function DefaultBlockComponent(props) {
139738
140046
  const perf = beginBlockRenderMeasurement();
139739
- if (!theme) throw new Error("Block rendering requires theme tokens; none were provided to makeDefaultBlockComponent");
139740
- if (!registry) throw new Error("Block rendering requires a component registry; none was provided");
139741
- const layout = resolveBlockLayout(manifest, content);
139742
- if (!layout) throw new Error(`Block manifest "${manifest.name}" requires a layout definition`);
139743
- const fieldConstraints = buildPreviewFieldConstraints(manifest);
139744
- const mergedContent = mergeContentWithBlockStyleOverrides(content, themeConfig, blockKind ?? manifest.name);
139745
- const result = resolveTree(layout, {
139746
- registry,
139747
- viewModel: buildBlockViewModel({
139748
- mergedContent,
139749
- data,
139750
- resolvedThemeConfig: resolveThemeConfigForBindings(themeConfig),
139751
- viewModelOverrides
139752
- }),
139753
- transforms,
139754
- theme: withButtonSystem(theme, themeConfig),
139755
- pathBase,
139756
- blockId,
139757
- contentVersionId,
139758
- blockKind,
139759
- blockContent: mergedContent,
139760
- blockBindings,
139761
- editableRouteMetadataFieldIds,
139762
- fragmentRegistry,
139763
- fieldConstraints,
139764
- imageResolveContext,
139765
- previewAuthoring
140047
+ const prepared = prepareDefaultBlockRender(args.manifest, props);
140048
+ const result = resolveTree(prepared.layout, {
140049
+ registry: prepared.registry,
140050
+ viewModel: prepared.viewModel,
140051
+ transforms: props.transforms,
140052
+ theme: prepared.themeForTransforms,
140053
+ pathBase: props.pathBase,
140054
+ blockId: props.blockId,
140055
+ newsletterBlockSubmission: props.newsletterBlockSubmission,
140056
+ blockKind: props.blockKind,
140057
+ blockContent: prepared.mergedContent,
140058
+ blockBindings: props.blockBindings,
140059
+ editableRouteMetadataFieldIds: props.editableRouteMetadataFieldIds,
140060
+ fragmentRegistry: props.fragmentRegistry,
140061
+ fieldConstraints: prepared.fieldConstraints,
140062
+ imageResolveContext: props.imageResolveContext,
140063
+ previewAuthoring: props.previewAuthoring
139766
140064
  });
139767
140065
  reportSlowBlockRender(perf, {
139768
- content,
139769
- blockId,
139770
- blockKind: blockKind ?? manifest.name,
139771
- manifestName: manifest.name
140066
+ content: props.content,
140067
+ blockId: props.blockId,
140068
+ blockKind: props.blockKind ?? args.manifest.name,
140069
+ manifestName: args.manifest.name
139772
140070
  });
139773
140071
  return result;
139774
140072
  };
@@ -140386,6 +140684,40 @@ function resolveBlockData$1(blockId, dataLoaders, dataContext, routes) {
140386
140684
  return dataLoaders && typeof dataLoaders === "object" && Object.keys(dataLoaders).length > 0 ? {} : void 0;
140387
140685
  }
140388
140686
  //#endregion
140687
+ //#region ../blocks/src/system/runtime/nodes/newsletter-form.block-submission.ts
140688
+ init_src$2();
140689
+ /** Authorise one block source for both public and preview rendering. */
140690
+ function planNewsletterBlockSubmission(placement) {
140691
+ if (placement.stage === "published") {
140692
+ const sourceRef = buildMailingListSignupBlockSourceRef(placement.blockId, placement.selectedContentVersionId);
140693
+ return sourceRef ? {
140694
+ tag: "ready",
140695
+ sourceRef
140696
+ } : { tag: "unavailable" };
140697
+ }
140698
+ if (placement.publishedPlacement) return planNewsletterPreviewSubmission({
140699
+ blockId: placement.blockId,
140700
+ publishedContentId: placement.publishedPlacement.id,
140701
+ renderedContent: placement.renderedContent,
140702
+ publishedContent: placement.publishedPlacement.content
140703
+ });
140704
+ if (placement.stage === "preview") return { tag: "unpublished-form" };
140705
+ return { tag: "unavailable" };
140706
+ }
140707
+ /** Decide whether the visible draft can safely cite the published placement. */
140708
+ function planNewsletterPreviewSubmission(placement) {
140709
+ if (!placement.publishedContentId) return { tag: "unpublished-form" };
140710
+ if (!placement.publishedContent) return { tag: "unpublished-settings" };
140711
+ const draft = parseMailingListPlacementTargeting(placement.renderedContent.targeting ?? { mode: "default" });
140712
+ const published = parseMailingListPlacementTargeting(placement.publishedContent.targeting);
140713
+ if (!draft.ok || !published.ok || !sameMailingListPlacementTargeting(draft.value, published.value)) return { tag: "unpublished-settings" };
140714
+ const sourceRef = buildMailingListSignupBlockSourceRef(placement.blockId, placement.publishedContentId);
140715
+ return sourceRef ? {
140716
+ tag: "ready",
140717
+ sourceRef
140718
+ } : { tag: "unpublished-settings" };
140719
+ }
140720
+ //#endregion
140389
140721
  //#region ../blocks/src/pageRenderPreparation.ts
140390
140722
  /**
140391
140723
  * Stage two of the render plan.
@@ -140514,9 +140846,20 @@ function buildBlockOverrideProps(input) {
140514
140846
  imageResolveContext: input.imageResolveContext,
140515
140847
  blockId: block.id ?? null,
140516
140848
  contentVersionId: block.contentVersionId ?? null,
140849
+ ...newsletterBlockProps(block, input.content, dataContext?.previewStage),
140517
140850
  blockKind: block.kind
140518
140851
  };
140519
140852
  }
140853
+ function newsletterBlockProps(block, renderedContent, stage) {
140854
+ if (block.kind !== "block.newsletter-signup") return {};
140855
+ return { newsletterBlockSubmission: planNewsletterBlockSubmission({
140856
+ blockId: block.id,
140857
+ selectedContentVersionId: block.contentVersionId ?? null,
140858
+ publishedPlacement: block.publishedPlacement ?? null,
140859
+ renderedContent,
140860
+ stage
140861
+ }) };
140862
+ }
140520
140863
  /** Site, transport and session context a block needs to call back to the API. */
140521
140864
  function blockSessionProps(dataContext) {
140522
140865
  return {
@@ -140606,6 +140949,15 @@ function createBlockErrorBoundary() {
140606
140949
  const BlockErrorBoundary = createBlockErrorBoundary();
140607
140950
  //#endregion
140608
140951
  //#region ../blocks/src/pageRenderAdmission.ts
140952
+ /** Pair a published version with the content it authorises at the render boundary. */
140953
+ function readPublishedBlockPlacement(id, content) {
140954
+ if (id == null && content == null) return null;
140955
+ if (id == null || content == null) throw new Error("Published block placement requires both an ID and content");
140956
+ return {
140957
+ id,
140958
+ content
140959
+ };
140960
+ }
140609
140961
  function toPresentationPage(page) {
140610
140962
  if (!page) return null;
140611
140963
  return {
@@ -140616,6 +140968,8 @@ function toPresentationPage(page) {
140616
140968
  kind: block.kind,
140617
140969
  purpose: block.purpose,
140618
140970
  ...block.contentVersionId ? { contentVersionId: block.contentVersionId } : {},
140971
+ ...block.draftContentId !== void 0 ? { draftContentId: block.draftContentId } : {},
140972
+ ...block.publishedPlacement !== void 0 ? { publishedPlacement: block.publishedPlacement } : {},
140619
140973
  ...block.bindings ? { bindings: block.bindings } : {}
140620
140974
  };
140621
140975
  return block.admission.kind === "renderable" ? {
@@ -141363,6 +141717,9 @@ const containerResponsiveThemeCss = `/*
141363
141717
  .rb-h-4 {
141364
141718
  height: 1rem;
141365
141719
  }
141720
+ .rb-h-5 {
141721
+ height: 1.25rem;
141722
+ }
141366
141723
  .rb-h-8 {
141367
141724
  height: 2rem;
141368
141725
  }
@@ -145328,6 +145685,10 @@ const containerResponsiveThemeCss = `/*
145328
145685
  margin-bottom: 0.25rem;
145329
145686
  }
145330
145687
 
145688
+ :where(.theme-scope) :where([data-block='event-registration']) .er-consent-check {
145689
+ margin-top: 0.75rem;
145690
+ }
145691
+
145331
145692
  :where(.theme-scope) :where([data-block='event-registration']) .er-required {
145332
145693
  color: var(--er-required);
145333
145694
  }
@@ -150047,13 +150408,6 @@ const containerResponsiveThemeCss = `/*
150047
150408
  margin: 0;
150048
150409
  }
150049
150410
 
150050
- /* Inline field (checkbox, radio with label) */
150051
- :where(.theme-scope) :where([data-block="form"]) .fb-inline {
150052
- display: flex;
150053
- align-items: center;
150054
- gap: 0.5rem;
150055
- }
150056
-
150057
150411
  /* Success state */
150058
150412
  :where(.theme-scope) :where([data-block="form"]) .fb-success {
150059
150413
  background-color: var(--fb-success-bg);
@@ -152170,9 +152524,11 @@ const containerResponsiveThemeCss = `/*
152170
152524
  */
152171
152525
 
152172
152526
  /* Newsletter copy styling */
152527
+ /* Size only: weight, family and colour come from the theme's heading styles */
152173
152528
  :where(.theme-scope) :where([data-block="newsletter-signup"]) .newsletter-copy-title {
152174
- font-size: 1.5rem;
152175
- font-weight: 600;
152529
+ font-size: clamp(1.75rem, 1.35rem + 1.6vw, 2.5rem);
152530
+ line-height: 1.15;
152531
+ text-wrap: balance;
152176
152532
  }
152177
152533
 
152178
152534
  :where(.theme-scope) :where([data-block="newsletter-signup"]) .newsletter-copy-subtitle {
@@ -152196,37 +152552,150 @@ const containerResponsiveThemeCss = `/*
152196
152552
  gap: var(--rb-gap-sm, 0.75rem);
152197
152553
  }
152198
152554
 
152199
- /* Individual field styling */
152555
+ /* Extra preset fields (name, company...). Labels are visually hidden, so
152556
+ these sit in a row above the email entry. */
152557
+ :where(.theme-scope) .newsletter-extra-fields {
152558
+ display: grid;
152559
+ grid-template-columns: repeat(auto-fit, minmax(min(12rem, 100%), 1fr));
152560
+ gap: 0.5rem;
152561
+ }
152562
+
152200
152563
  :where(.theme-scope) .newsletter-field {
152201
152564
  display: flex;
152202
152565
  flex-direction: column;
152203
152566
  gap: 0.25rem;
152567
+ text-align: left;
152204
152568
  }
152205
152569
 
152206
- /* Topic choices (visitor picks what to hear about). Same treatment as the
152207
- form block's .fb-fieldset / .fb-inline, defined here because the newsletter
152208
- form also renders inside contact-newsletter and the site footer. */
152209
- :where(.theme-scope) .newsletter-topics {
152570
+ /* Email entry: the email field and the themed submit button share one shell.
152571
+ The shell's look (background, border, corners, focus ring) comes from the
152572
+ theme's input system via .form-input-group; this only handles layout. */
152573
+ :where(.theme-scope) .newsletter-entry {
152574
+ container-type: inline-size;
152210
152575
  display: flex;
152211
152576
  flex-direction: column;
152212
- gap: 0.5rem;
152577
+ gap: 0.375rem;
152578
+ text-align: left;
152579
+ }
152580
+
152581
+ :where(.theme-scope) .newsletter-entry-group > button {
152582
+ white-space: nowrap;
152583
+ }
152584
+
152585
+ /* Too narrow for field and button side by side (phones, footer columns):
152586
+ stack them inside the shell and keep pill themes from turning the taller
152587
+ shell into a capsule. */
152588
+ @container (max-width: 22rem) {
152589
+ :where(.theme-scope) .newsletter-entry .newsletter-entry-group {
152590
+ flex-direction: column;
152591
+ border-radius: min(var(--rb-input-radius, 0.5rem), 1rem);
152592
+ }
152593
+
152594
+ :where(.theme-scope) .newsletter-entry .newsletter-entry-group > button {
152595
+ width: 100%;
152596
+ justify-content: center;
152597
+ }
152598
+ }
152599
+
152600
+ /* Topic choices (visitor picks what to hear about) as toggle chips. Each chip
152601
+ is a real checkbox underneath; the chip is its visible face. */
152602
+ :where(.theme-scope) .newsletter-topics {
152213
152603
  border: none;
152214
152604
  padding: 0;
152215
152605
  margin: 0;
152216
152606
  min-width: 0;
152217
152607
  }
152218
152608
 
152219
- :where(.theme-scope) .newsletter-topics > legend {
152609
+ :where(.theme-scope) .newsletter-topics-legend {
152220
152610
  padding: 0;
152221
- margin-bottom: 0.25rem;
152611
+ margin-bottom: 0.625rem;
152612
+ font-size: 0.9375rem;
152613
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
152222
152614
  }
152223
152615
 
152224
- :where(.theme-scope) .newsletter-topic-choice {
152616
+ :where(.theme-scope) .newsletter-topic-chips {
152225
152617
  display: flex;
152226
- align-items: center;
152618
+ flex-wrap: wrap;
152227
152619
  gap: 0.5rem;
152228
152620
  }
152229
152621
 
152622
+ :where(.theme-scope) .newsletter-stacked .newsletter-topics-legend {
152623
+ width: 100%;
152624
+ }
152625
+
152626
+ :where(.theme-scope) .newsletter-stacked .newsletter-topic-chips {
152627
+ justify-content: center;
152628
+ }
152629
+
152630
+ :where(.theme-scope) .newsletter-topic-chip {
152631
+ position: relative;
152632
+ display: inline-flex;
152633
+ }
152634
+
152635
+ :where(.theme-scope) .newsletter-topic-chip > input {
152636
+ position: absolute;
152637
+ inset: 0;
152638
+ width: 100%;
152639
+ height: 100%;
152640
+ margin: 0;
152641
+ opacity: 0;
152642
+ cursor: pointer;
152643
+ }
152644
+
152645
+ :where(.theme-scope) .newsletter-topic-chip > span {
152646
+ display: inline-flex;
152647
+ align-items: center;
152648
+ gap: 0.375rem;
152649
+ padding: 0.4375rem 0.9375rem;
152650
+ border: 1px solid color-mix(in srgb, currentColor 35%, transparent);
152651
+ border-radius: var(--rb-button-radius, var(--rb-input-radius, 9999px));
152652
+ font-size: 0.9375rem;
152653
+ line-height: 1.3;
152654
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
152655
+ transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
152656
+ }
152657
+
152658
+ /* Tick that grows in when the chip is on */
152659
+ :where(.theme-scope) .newsletter-topic-chip > span::before {
152660
+ content: "";
152661
+ width: 0;
152662
+ height: 0.7em;
152663
+ background-color: currentColor;
152664
+ clip-path: polygon(14% 52%, 0 67%, 38% 100%, 100% 22%, 85% 8%, 37% 70%);
152665
+ transition: width 0.15s ease;
152666
+ }
152667
+
152668
+ :where(.theme-scope) .newsletter-topic-chip:hover > span {
152669
+ border-color: currentColor;
152670
+ }
152671
+
152672
+ /* Same accent and mark colours as the theme's checkboxes */
152673
+ :where(.theme-scope) .newsletter-topic-chip > input:checked + span {
152674
+ background-color: var(--rb-check-accent, rgb(var(--tb-primary)));
152675
+ border-color: var(--rb-check-accent, rgb(var(--tb-primary)));
152676
+ color: var(--rb-check-mark, rgb(var(--tb-onPrimary, 255 255 255)));
152677
+ }
152678
+
152679
+ :where(.theme-scope) .newsletter-topic-chip > input:checked + span::before {
152680
+ width: 0.7em;
152681
+ }
152682
+
152683
+ :where(.theme-scope) .newsletter-topic-chip > input:focus-visible + span {
152684
+ outline: 2px solid var(--rb-check-accent, rgb(var(--tb-primary)));
152685
+ outline-offset: 2px;
152686
+ }
152687
+
152688
+ :where(.theme-scope) .newsletter-topic-chip > input:disabled + span {
152689
+ opacity: 0.6;
152690
+ }
152691
+
152692
+ @media (prefers-reduced-motion: reduce) {
152693
+ :where(.theme-scope) .newsletter-topic-chip > span,
152694
+ :where(.theme-scope) .newsletter-topic-chip > span::before {
152695
+ transition: none;
152696
+ }
152697
+ }
152698
+
152230
152699
  /* Error panel and field notes. The form block scopes these to its own
152231
152700
  data-block, so the newsletter form (which also renders in the footer)
152232
152701
  needs its own copy of the treatment. */
@@ -152244,13 +152713,7 @@ const containerResponsiveThemeCss = `/*
152244
152713
  color: var(--fb-error-text);
152245
152714
  }
152246
152715
 
152247
- /* Required indicator */
152248
- :where(.theme-scope) .newsletter-required {
152249
- color: rgb(var(--tb-primary));
152250
- margin-left: 0.125rem;
152251
- }
152252
-
152253
- /* Submit button container */
152716
+ /* Submit button container (only when a preset has no email field) */
152254
152717
  :where(.theme-scope) .newsletter-submit {
152255
152718
  margin-top: 0.5rem;
152256
152719
  }
@@ -152262,52 +152725,29 @@ const containerResponsiveThemeCss = `/*
152262
152725
  justify-content: center;
152263
152726
  }
152264
152727
 
152265
- /* Privacy note */
152728
+ /* Privacy note: quieter than the intro so the entry row leads */
152266
152729
  :where(.theme-scope) .newsletter-privacy-note {
152267
152730
  margin-top: 0.75rem;
152268
- font-size: 1rem;
152269
- line-height: 1.6;
152270
- color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
152731
+ font-size: 0.8125rem;
152732
+ line-height: 1.5;
152733
+ color: var(--rb-surface-supporting-color, var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39))));
152734
+ opacity: 0.85;
152271
152735
  text-align: center;
152272
152736
  }
152273
152737
 
152274
152738
  /* =============================================================================
152275
- * Inline Variant - Horizontal layout
152739
+ * Inline Variant - left-aligned, wider entry row
152276
152740
  * =============================================================================
152277
152741
  */
152278
152742
 
152279
- :where(.theme-scope) .newsletter-inline .newsletter-form-fields {
152280
- flex-direction: row;
152281
- align-items: flex-end;
152282
- flex-wrap: wrap;
152283
- gap: var(--rb-gap-sm, 0.75rem);
152284
- }
152285
-
152286
- :where(.theme-scope) .newsletter-inline .newsletter-field {
152287
- flex: 1 1 auto;
152288
- min-width: 10rem;
152289
- }
152290
-
152291
- :where(.theme-scope) .newsletter-inline .newsletter-submit {
152292
- margin-top: 0;
152293
- flex-shrink: 0;
152294
- }
152295
-
152296
- :where(.theme-scope) .newsletter-inline .newsletter-topics {
152297
- flex-basis: 100%;
152743
+ :where(.theme-scope) .newsletter-inline .newsletter-form {
152744
+ max-width: 40rem;
152745
+ margin-left: 0;
152746
+ margin-right: 0;
152298
152747
  }
152299
152748
 
152300
- /* Mobile fallback for inline variant */
152301
- @container rb-site (max-width: 640px) {
152302
- @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
152303
- :where(.theme-scope) .newsletter-inline .newsletter-form-fields {
152304
- flex-direction: column;
152305
- }
152306
-
152307
- :where(.theme-scope) .newsletter-inline .newsletter-field {
152308
- min-width: 100%;
152309
- }
152310
- }
152749
+ :where(.theme-scope) .newsletter-inline .newsletter-privacy-note {
152750
+ text-align: left;
152311
152751
  }
152312
152752
 
152313
152753
  /* =============================================================================
@@ -152445,12 +152885,6 @@ const containerResponsiveThemeCss = `/*
152445
152885
  margin: 0;
152446
152886
  }
152447
152887
 
152448
- :where(.theme-scope) :where([data-block="contact-newsletter"]) .fb-inline {
152449
- display: flex;
152450
- align-items: center;
152451
- gap: 0.5rem;
152452
- }
152453
-
152454
152888
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .fb-success,
152455
152889
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .fb-error,
152456
152890
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .fb-empty {
@@ -154347,6 +154781,44 @@ const containerResponsiveThemeCss = `/*
154347
154781
  flex: 0 0 auto;
154348
154782
  }
154349
154783
  }
154784
+ }
154785
+
154786
+ /* =============================================================================
154787
+ * Site footer: social links
154788
+ *
154789
+ * Icon links get a 40px tap target with a hairline ring drawn from the link's
154790
+ * own colour, so it follows the footer's text colour on any surface. Links
154791
+ * without an icon (unknown platforms) stay plain text.
154792
+ * =============================================================================
154793
+ */
154794
+
154795
+ :where(.theme-scope) .rb-footer-socials {
154796
+ display: flex;
154797
+ flex-wrap: wrap;
154798
+ align-items: center;
154799
+ gap: 0.75rem 1.25rem;
154800
+ }
154801
+
154802
+ :where(.theme-scope) .rb-footer-social-link:has(> .rb-footer-social-icon) {
154803
+ display: inline-grid;
154804
+ place-items: center;
154805
+ width: 2.5rem;
154806
+ height: 2.5rem;
154807
+ border: 1px solid color-mix(in srgb, currentColor 22%, transparent);
154808
+ border-radius: 9999px;
154809
+ }
154810
+
154811
+ :where(.theme-scope) .rb-footer-socials:has(.rb-footer-social-icon) {
154812
+ gap: 0.5rem;
154813
+ }
154814
+
154815
+ :where(.theme-scope) .rb-footer-social-link:has(> .rb-footer-social-icon):hover {
154816
+ border-color: currentColor;
154817
+ }
154818
+
154819
+ :where(.theme-scope) .rb-footer-social-icon {
154820
+ width: 1.5rem;
154821
+ height: 1.5rem;
154350
154822
  }`;
154351
154823
  //#endregion
154352
154824
  //#region ../theme-core/src/ThemeScopeCore.tsx
@@ -154744,7 +155216,7 @@ function toBlocksCommonProps(props) {
154744
155216
  return {
154745
155217
  page: props.page,
154746
155218
  runtimeJoins: props.runtimeJoins,
154747
- dataContext: props.dataContext ? toBlocksPageRendererDataContext(props.dataContext) : void 0,
155219
+ dataContext: toBlocksPageRendererDataContext(props.dataContext),
154748
155220
  routeMap: props.routeMap,
154749
155221
  wrapBlock: props.wrapBlock,
154750
155222
  registry: props.registry,
@@ -154856,14 +155328,14 @@ function resolveSdkBookingTimeZone(timeZone) {
154856
155328
  }
154857
155329
  function buildPageRouteRenderContext(dataContext) {
154858
155330
  return {
154859
- pathname: dataContext?.pathname,
154860
- occurrenceContext: dataContext?.occurrenceContext ?? null,
154861
- entrySubrouteContext: dataContext?.entrySubrouteContext ?? null,
154862
- contentEntry: dataContext?.contentEntry ?? null,
154863
- pageSurface: dataContext?.pageSurface ?? null,
154864
- subject: dataContext?.subject ?? null,
154865
- editableRouteMetadataFieldIds: dataContext?.editableRouteMetadataFieldIds ?? null,
154866
- previewStage: dataContext?.previewStage
155331
+ pathname: dataContext.pathname,
155332
+ occurrenceContext: dataContext.occurrenceContext ?? null,
155333
+ entrySubrouteContext: dataContext.entrySubrouteContext ?? null,
155334
+ contentEntry: dataContext.contentEntry ?? null,
155335
+ pageSurface: dataContext.pageSurface ?? null,
155336
+ subject: dataContext.subject ?? null,
155337
+ editableRouteMetadataFieldIds: dataContext.editableRouteMetadataFieldIds ?? null,
155338
+ previewStage: dataContext.previewStage
154867
155339
  };
154868
155340
  }
154869
155341
  function PageContent(props) {
@@ -154877,10 +155349,10 @@ function PageContent(props) {
154877
155349
  apiBaseUrl,
154878
155350
  portalToken,
154879
155351
  previewToken,
154880
- readAuthority: readAuthority ?? dataContext?.readAuthority,
155352
+ readAuthority: readAuthority ?? dataContext.readAuthority,
154881
155353
  resolvedData,
154882
155354
  bookingOfferingPresets: bookingOfferingPresets ?? [],
154883
- mailingList: mailingList ?? dataContext?.mailingList,
155355
+ mailingList: mailingList ?? dataContext.mailingList,
154884
155356
  bookingTimeZone: resolveSdkBookingTimeZone(bookingTimeZone),
154885
155357
  routes: routeMap,
154886
155358
  pagesByIdentifier,
@@ -157101,21 +157573,39 @@ function buildSiteRenderSupport(site, mediaAssets) {
157101
157573
  function collectMediaAssetSidecar(mediaAssets) {
157102
157574
  return Array.isArray(mediaAssets) && mediaAssets.length > 0 ? mediaAssets : void 0;
157103
157575
  }
157104
- function convertPageResponseBlock(block) {
157576
+ function readBlockContentId(value, name) {
157577
+ if (value === null || value === void 0) return null;
157578
+ if (typeof value === "string") return value;
157579
+ throw new Error(`Invalid ${name} in page: expected string or null`);
157580
+ }
157581
+ function readTransportedBlockIdentity(block, kind, stage) {
157582
+ return {
157583
+ draftContentId: readBlockContentId(block.draftContentId, "draft content id"),
157584
+ publishedPlacement: stage === "preview" ? readPublishedBlockPlacement(readBlockContentId(block.publishedContentId, "published content id"), sanitizeNullableSdkRuntimeBlockContent(kind, readNestedContentRecord(block.publishedContent))) : null
157585
+ };
157586
+ }
157587
+ function convertPageResponseBlock(block, stage) {
157105
157588
  if (!isRecord$8(block)) throw new Error("Invalid block format in page API response");
157589
+ const header = readTransportedBlockHeader(block);
157590
+ const admission = readInvalidBlockAdmission(block.admission);
157591
+ return {
157592
+ ...header,
157593
+ ...readTransportedBlockIdentity(block, header.kind, stage),
157594
+ content: sanitizeSdkRuntimeBlockContent(header.kind, readContentRecord(block.content) ?? {}),
157595
+ draftContent: sanitizeNullableSdkRuntimeBlockContent(header.kind, readNestedContentRecord(block.draftContent)),
157596
+ ...admission ? { admission } : {}
157597
+ };
157598
+ }
157599
+ function readTransportedBlockHeader(block) {
157106
157600
  if (typeof block.id !== "string" && block.id !== null) throw new Error(`Invalid block id in page: expected string or null, got ${typeof block.id}`);
157107
157601
  if (typeof block.kind !== "string") throw new Error(`Invalid block kind in page: expected string, got ${typeof block.kind}`);
157108
157602
  if (typeof block.purpose !== "string") throw new Error(`Invalid block purpose in page: expected string, got ${typeof block.purpose}`);
157109
157603
  if (block.contentVersionId !== void 0 && block.contentVersionId !== null && typeof block.contentVersionId !== "string") throw new Error(`Invalid content version id in page: expected string or null, got ${typeof block.contentVersionId}`);
157110
- const admission = readInvalidBlockAdmission(block.admission);
157111
157604
  return {
157112
157605
  id: block.id,
157113
157606
  ...block.contentVersionId !== void 0 ? { contentVersionId: block.contentVersionId } : {},
157114
157607
  kind: block.kind,
157115
- purpose: block.purpose,
157116
- content: sanitizeSdkRuntimeBlockContent(block.kind, readContentRecord(block.content) ?? {}),
157117
- draftContent: sanitizeNullableSdkRuntimeBlockContent(block.kind, readNestedContentRecord(block.draftContent)),
157118
- ...admission ? { admission } : {}
157608
+ purpose: block.purpose
157119
157609
  };
157120
157610
  }
157121
157611
  function readInvalidBlockAdmission(value) {
@@ -157128,7 +157618,7 @@ function buildPageOutline(input) {
157128
157618
  name: input.name,
157129
157619
  path: input.path ?? input.fallbackPath,
157130
157620
  purpose: input.purpose,
157131
- blocks: input.blocks.map(convertPageResponseBlock)
157621
+ blocks: input.blocks.map((block) => convertPageResponseBlock(block, input.previewStage))
157132
157622
  };
157133
157623
  }
157134
157624
  function buildRenderablePageOutline(input) {
@@ -157154,6 +157644,8 @@ function projectRenderablePageOutline(page) {
157154
157644
  function admitSdkRuntimePageBlock(block, customBlocks) {
157155
157645
  const base = {
157156
157646
  id: block.id,
157647
+ draftContentId: block.draftContentId,
157648
+ publishedPlacement: block.publishedPlacement,
157157
157649
  ...block.contentVersionId !== void 0 ? { contentVersionId: block.contentVersionId } : {},
157158
157650
  kind: block.kind,
157159
157651
  purpose: block.purpose,
@@ -157224,6 +157716,7 @@ function buildFooterRenderablePageOutline(siteData, blocks) {
157224
157716
  fallbackPath: "/__footer",
157225
157717
  purpose: "footer",
157226
157718
  blocks,
157719
+ previewStage: "published",
157227
157720
  customBlocks: resolveSiteCustomBlocks(siteData)
157228
157721
  });
157229
157722
  }
@@ -158393,6 +158886,13 @@ const EVENT_SERIES_REGISTRATION_ENDPOINT_DEFINITIONS = defineEndpointDefinitions
158393
158886
  errors: [],
158394
158887
  responseKind: "blob"
158395
158888
  },
158889
+ exportEventOfferingRegistrationsCsv: {
158890
+ path: "/sites/{siteId}/bookings/event-offerings/{eventOfferingId}/registrations/export.csv",
158891
+ method: "GET",
158892
+ auth: "user",
158893
+ errors: [],
158894
+ responseKind: "blob"
158895
+ },
158396
158896
  updateEventSeriesRegistration: {
158397
158897
  path: "/sites/{siteId}/bookings/event-series/{seriesId}/registrations/{registrationId}",
158398
158898
  method: "PATCH",
@@ -158403,6 +158903,19 @@ const EVENT_SERIES_REGISTRATION_ENDPOINT_DEFINITIONS = defineEndpointDefinitions
158403
158903
  "resource:not_found",
158404
158904
  "server:internal_error"
158405
158905
  ]
158906
+ },
158907
+ saveEventSeriesRegistrationAnswers: {
158908
+ path: "/sites/{siteId}/bookings/event-series/{seriesId}/registrations/{registrationId}/answers",
158909
+ method: "PUT",
158910
+ auth: "user",
158911
+ responseKind: "json",
158912
+ errors: [
158913
+ "validation:invalid_input",
158914
+ "auth:forbidden",
158915
+ "resource:not_found",
158916
+ "resource:conflict",
158917
+ "server:internal_error"
158918
+ ]
158406
158919
  }
158407
158920
  });
158408
158921
  //#endregion
@@ -158823,6 +159336,30 @@ const NEWSLETTER_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
158823
159336
  responseKind: "json",
158824
159337
  demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
158825
159338
  },
159339
+ scheduleNewsletterCampaign: {
159340
+ path: "/sites/{siteId}/newsletter/campaigns/{campaignId}/schedule",
159341
+ method: "POST",
159342
+ tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
159343
+ auth: "user",
159344
+ responseKind: "json",
159345
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
159346
+ },
159347
+ unscheduleNewsletterCampaign: {
159348
+ path: "/sites/{siteId}/newsletter/campaigns/{campaignId}/unschedule",
159349
+ method: "POST",
159350
+ tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
159351
+ auth: "user",
159352
+ responseKind: "json",
159353
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
159354
+ },
159355
+ stopNewsletterCampaign: {
159356
+ path: "/sites/{siteId}/newsletter/campaigns/{campaignId}/stop",
159357
+ method: "POST",
159358
+ tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
159359
+ auth: "user",
159360
+ responseKind: "json",
159361
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
159362
+ },
158826
159363
  testSendNewsletterCampaign: {
158827
159364
  path: "/sites/{siteId}/newsletter/campaigns/{campaignId}/test-send",
158828
159365
  method: "POST",
@@ -158833,6 +159370,154 @@ const NEWSLETTER_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
158833
159370
  }
158834
159371
  });
158835
159372
  //#endregion
159373
+ //#region ../api/src/sdkEventEndpointDefinitions.ts
159374
+ /**
159375
+ * The SDK's Event graph: the Events themselves and the occurrences of one run.
159376
+ * Extracted from `endpoints.ts` so this family can be read, and added to, on
159377
+ * its own. New entries here must declare `errors`; the
159378
+ * require-api-endpoint-errors lint enforces that here as in endpoints.ts.
159379
+ */
159380
+ const SDK_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
159381
+ sdkListEvents: {
159382
+ path: "/sdk/{siteId}/events",
159383
+ method: "GET",
159384
+ auth: "service",
159385
+ responseKind: "json"
159386
+ },
159387
+ sdkUpsertEvent: {
159388
+ path: "/sdk/{siteId}/events",
159389
+ method: "POST",
159390
+ auth: "service",
159391
+ responseKind: "json",
159392
+ errors: [
159393
+ "validation:invalid_input",
159394
+ "resource:not_found",
159395
+ "resource:conflict",
159396
+ "billing:plan_limit_exceeded",
159397
+ "server:internal_error"
159398
+ ]
159399
+ },
159400
+ sdkGetEvent: {
159401
+ path: "/sdk/{siteId}/events/{identifier}",
159402
+ method: "GET",
159403
+ auth: "service",
159404
+ responseKind: "json"
159405
+ },
159406
+ sdkDeleteEvent: {
159407
+ path: "/sdk/{siteId}/events/{identifier}",
159408
+ method: "DELETE",
159409
+ auth: "service",
159410
+ responseKind: "json",
159411
+ errors: [
159412
+ "resource:not_found",
159413
+ "resource:conflict",
159414
+ "server:internal_error"
159415
+ ]
159416
+ },
159417
+ sdkTakeEventOffline: {
159418
+ path: "/sdk/{siteId}/events/{identifier}/lifecycle",
159419
+ method: "POST",
159420
+ auth: "service",
159421
+ responseKind: "json",
159422
+ errors: [
159423
+ "resource:not_found",
159424
+ "validation:invalid_input",
159425
+ "resource:conflict",
159426
+ "server:internal_error"
159427
+ ]
159428
+ },
159429
+ sdkListEventOccurrences: {
159430
+ path: "/sdk/{siteId}/events/{identifier}/runs/{runIdentifier}/occurrences",
159431
+ method: "GET",
159432
+ auth: "service",
159433
+ responseKind: "json",
159434
+ errors: [
159435
+ "resource:not_found",
159436
+ "validation:invalid_input",
159437
+ "server:internal_error"
159438
+ ]
159439
+ },
159440
+ sdkAddEventOccurrence: {
159441
+ path: "/sdk/{siteId}/events/{identifier}/runs/{runIdentifier}/occurrences",
159442
+ method: "POST",
159443
+ auth: "service",
159444
+ responseKind: "json",
159445
+ errors: [
159446
+ "resource:not_found",
159447
+ "validation:invalid_input",
159448
+ "resource:conflict",
159449
+ "server:internal_error"
159450
+ ]
159451
+ },
159452
+ sdkUpdateEventOccurrence: {
159453
+ path: "/sdk/{siteId}/events/{identifier}/runs/{runIdentifier}/occurrences/{occurrenceId}",
159454
+ method: "PATCH",
159455
+ auth: "service",
159456
+ responseKind: "json",
159457
+ errors: [
159458
+ "resource:not_found",
159459
+ "validation:invalid_input",
159460
+ "resource:conflict",
159461
+ "server:internal_error"
159462
+ ]
159463
+ },
159464
+ sdkCancelEventOccurrence: {
159465
+ path: "/sdk/{siteId}/events/{identifier}/runs/{runIdentifier}/occurrences/{occurrenceId}/cancel",
159466
+ method: "POST",
159467
+ auth: "service",
159468
+ responseKind: "json",
159469
+ errors: [
159470
+ "resource:not_found",
159471
+ "resource:conflict",
159472
+ "server:internal_error"
159473
+ ]
159474
+ },
159475
+ sdkDeleteEventOccurrence: {
159476
+ path: "/sdk/{siteId}/events/{identifier}/runs/{runIdentifier}/occurrences/{occurrenceId}",
159477
+ method: "DELETE",
159478
+ auth: "service",
159479
+ responseKind: "json",
159480
+ errors: [
159481
+ "resource:not_found",
159482
+ "resource:conflict",
159483
+ "server:internal_error"
159484
+ ]
159485
+ }
159486
+ });
159487
+ //#endregion
159488
+ //#region ../api/src/sdkPageDesignEndpointDefinitions.ts
159489
+ /**
159490
+ * SDK management endpoints for a page's draft design (issue 1497), spread into
159491
+ * `ENDPOINT_DEFINITIONS` like the other endpoint-definition modules. New
159492
+ * entries here must declare `errors`, which the require-api-endpoint-errors
159493
+ * lint enforces.
159494
+ */
159495
+ const SDK_PAGE_DESIGN_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
159496
+ sdkGetPageDesign: {
159497
+ path: "/sdk/{siteId}/pages/{identifier}/design",
159498
+ method: "GET",
159499
+ auth: "service",
159500
+ responseKind: "json",
159501
+ errors: [
159502
+ "resource:not_found",
159503
+ "validation:invalid_input",
159504
+ "server:internal_error"
159505
+ ]
159506
+ },
159507
+ sdkSavePageDesign: {
159508
+ path: "/sdk/{siteId}/pages/{identifier}/design",
159509
+ method: "POST",
159510
+ auth: "service",
159511
+ responseKind: "json",
159512
+ errors: [
159513
+ "resource:not_found",
159514
+ "validation:invalid_input",
159515
+ "resource:conflict",
159516
+ "server:internal_error"
159517
+ ]
159518
+ }
159519
+ });
159520
+ //#endregion
158836
159521
  //#region ../api/src/publicEventEndpointDefinitions.ts
158837
159522
  init_src$2();
158838
159523
  const PUBLIC_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
@@ -159079,6 +159764,45 @@ const SITE_API_KEY_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
159079
159764
  }
159080
159765
  });
159081
159766
  //#endregion
159767
+ //#region ../api/src/siteManagementEndpointDefinitions.ts
159768
+ const SITE_MANAGEMENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
159769
+ createSite: {
159770
+ path: "/sites/manage",
159771
+ method: "POST",
159772
+ tags: ["site"],
159773
+ auth: "user",
159774
+ responseKind: "json"
159775
+ },
159776
+ updateSite: {
159777
+ path: "/sites/manage",
159778
+ method: "PUT",
159779
+ tags: ["site"],
159780
+ auth: "user",
159781
+ responseKind: "json"
159782
+ },
159783
+ changeSiteAddress: {
159784
+ path: "/sites/{siteId}/address",
159785
+ method: "PUT",
159786
+ auth: "user",
159787
+ responseKind: "json",
159788
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED
159789
+ },
159790
+ getSiteAddressAvailability: {
159791
+ path: "/sites/{siteId}/address/availability",
159792
+ method: "GET",
159793
+ auth: "user",
159794
+ responseKind: "json"
159795
+ },
159796
+ deleteSite: {
159797
+ path: "/sites/{siteId}",
159798
+ method: "DELETE",
159799
+ tags: ["site", "site-{siteId}"],
159800
+ auth: "user",
159801
+ responseKind: "json",
159802
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
159803
+ }
159804
+ });
159805
+ //#endregion
159082
159806
  //#region ../api/src/eventManagementEndpointDefinitions.ts
159083
159807
  const EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
159084
159808
  listEvents: {
@@ -159126,6 +159850,28 @@ const EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
159126
159850
  "server:internal_error"
159127
159851
  ]
159128
159852
  },
159853
+ /**
159854
+ * The web address of an event's own page. A course page belongs to the
159855
+ * event itself, so its address is written here rather than through a run.
159856
+ */
159857
+ updateEventAddress: {
159858
+ path: "/sites/{siteId}/bookings/events/{eventId}/address",
159859
+ method: "PATCH",
159860
+ tags: [
159861
+ "site-{siteId}",
159862
+ "event-series-{siteId}",
159863
+ TAG_TEMPLATES.siteRoutableContent,
159864
+ TAG_TEMPLATES.siteRedirects
159865
+ ],
159866
+ auth: "user",
159867
+ responseKind: "json",
159868
+ errors: [
159869
+ "validation:invalid_input",
159870
+ "resource:not_found",
159871
+ "resource:conflict",
159872
+ "server:internal_error"
159873
+ ]
159874
+ },
159129
159875
  createWholeSeriesRun: {
159130
159876
  path: "/sites/{siteId}/bookings/events/{eventId}/runs",
159131
159877
  method: "POST",
@@ -159152,6 +159898,20 @@ const EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
159152
159898
  "server:internal_error"
159153
159899
  ]
159154
159900
  },
159901
+ updateCourseBookingSettings: {
159902
+ path: "/sites/{siteId}/bookings/events/{eventId}/booking-settings",
159903
+ method: "PATCH",
159904
+ tags: ["site-{siteId}", "event-series-{siteId}"],
159905
+ auth: "user",
159906
+ responseKind: "json",
159907
+ errors: [
159908
+ "validation:invalid_input",
159909
+ "auth:forbidden",
159910
+ "resource:not_found",
159911
+ "resource:conflict",
159912
+ "server:internal_error"
159913
+ ]
159914
+ },
159155
159915
  cancelWholeSeriesRun: {
159156
159916
  path: "/sites/{siteId}/bookings/events/{eventId}/runs/{runId}/cancellation",
159157
159917
  method: "POST",
@@ -159164,6 +159924,28 @@ const EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
159164
159924
  "resource:conflict",
159165
159925
  "server:internal_error"
159166
159926
  ]
159927
+ },
159928
+ /**
159929
+ * The Content tab's one write: the short introduction, image and
159930
+ * description of an event's page, published without its layout.
159931
+ */
159932
+ saveEventPageWords: {
159933
+ path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/words",
159934
+ method: "PUT",
159935
+ tags: [
159936
+ TAG_TEMPLATES.siteCollection,
159937
+ TAG_TEMPLATES.siteRoutableContent,
159938
+ TAG_TEMPLATES.pageSurfaceById
159939
+ ],
159940
+ auth: "user",
159941
+ responseKind: "json",
159942
+ errors: [
159943
+ "auth:forbidden",
159944
+ "validation:invalid_input",
159945
+ "resource:not_found",
159946
+ "resource:conflict",
159947
+ "server:internal_error"
159948
+ ]
159167
159949
  }
159168
159950
  });
159169
159951
  //#endregion
@@ -159597,19 +160379,56 @@ const BILLING_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
159597
160379
  responseKind: "json"
159598
160380
  }
159599
160381
  });
160382
+ //#endregion
160383
+ //#region ../api/src/clientErrorReporting.ts
160384
+ const CLIENT_ERROR_REPORT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({ reportClientError: {
160385
+ path: "/client/error-report",
160386
+ method: "POST",
160387
+ auth: "user",
160388
+ errors: [],
160389
+ responseKind: "json"
160390
+ } });
160391
+ const CLIENT_ERROR_REPORT_LIMITS = {
160392
+ pathname: 1024,
160393
+ name: 120,
160394
+ message: 2e3,
160395
+ stack: 8e3,
160396
+ digest: 128,
160397
+ componentStack: 8e3,
160398
+ sourceLocation: 1024
160399
+ };
160400
+ const clientErrorEventSchema = z$1.enum([
160401
+ "dashboard:route-error",
160402
+ "dashboard:app-error",
160403
+ "client:error-boundary",
160404
+ "client:window-error",
160405
+ "client:unhandled-rejection"
160406
+ ]);
160407
+ z$1.object({
160408
+ event: clientErrorEventSchema,
160409
+ pathname: z$1.string().startsWith("/").max(CLIENT_ERROR_REPORT_LIMITS.pathname),
160410
+ name: z$1.string().max(CLIENT_ERROR_REPORT_LIMITS.name),
160411
+ message: z$1.string().max(CLIENT_ERROR_REPORT_LIMITS.message),
160412
+ stack: z$1.string().max(CLIENT_ERROR_REPORT_LIMITS.stack).nullable(),
160413
+ digest: z$1.string().max(CLIENT_ERROR_REPORT_LIMITS.digest).nullable(),
160414
+ componentStack: z$1.string().max(CLIENT_ERROR_REPORT_LIMITS.componentStack).nullable(),
160415
+ sourceLocation: z$1.string().max(CLIENT_ERROR_REPORT_LIMITS.sourceLocation).nullable()
160416
+ }).strict();
159600
160417
  ({
160418
+ ...CLIENT_ERROR_REPORT_ENDPOINT_DEFINITIONS,
159601
160419
  ...PUBLIC_NEWSLETTER_ENDPOINT_DEFINITIONS,
159602
160420
  ...ACCOUNT_ENDPOINT_DEFINITIONS,
159603
160421
  ...PUBLIC_ONBOARDING_ATTEMPT_ENDPOINT_DEFINITIONS,
159604
160422
  ...PUBLIC_EVENT_ENDPOINT_DEFINITIONS,
159605
160423
  ...GIFTING_ENDPOINT_DEFINITIONS,
159606
160424
  ...PUBLIC_READ_ENDPOINT_DEFINITIONS,
159607
- ...BILLING_ENDPOINT_DEFINITIONS
160425
+ ...BILLING_ENDPOINT_DEFINITIONS,
160426
+ ...SITE_MANAGEMENT_ENDPOINT_DEFINITIONS
159608
160427
  }), TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, { ...SITE_API_KEY_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.site, TAG_TEMPLATES.siteBookingSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteBookingSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, {
159609
160428
  ...NEWSLETTER_ENDPOINT_DEFINITIONS,
159610
160429
  ...APPOINTMENT_ENDPOINT_DEFINITIONS,
159611
160430
  ...EVENT_SERIES_REGISTRATION_ENDPOINT_DEFINITIONS
159612
- }, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.workflowRunById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.routeById, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicBookingServices, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, { ...PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.publicEventFilters, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicShop, TAG_TEMPLATES.publicCheckout, TAG_TEMPLATES.siteRoutableContent, { ...PUBLIC_EVENT_CHECKOUT_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, { ...EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS }, { ...SDK_MEDIA_ENDPOINT_DEFINITIONS }, { ...SDK_ENDPOINT_DEFINITIONS }, { ...SDK_ENTRY_READ_ENDPOINTS };
160431
+ }, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.workflowRunById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.routeById, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicBookingServices, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, { ...PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.publicEventFilters, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicShop, TAG_TEMPLATES.publicCheckout, TAG_TEMPLATES.siteRoutableContent, { ...PUBLIC_EVENT_CHECKOUT_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, { ...EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS }, { ...SDK_MEDIA_ENDPOINT_DEFINITIONS }, { ...SDK_ENDPOINT_DEFINITIONS }, { ...SDK_PAGE_DESIGN_ENDPOINT_DEFINITIONS }, { ...SDK_EVENT_ENDPOINT_DEFINITIONS }, { ...SDK_ENTRY_READ_ENDPOINTS };
159613
160432
  z$1.object({ refreshToken: z$1.string().min(1).max(4096) }).strict();
159614
160433
  z$1.object({
159615
160434
  accessToken: z$1.string().min(1).max(4096),
@@ -160222,6 +161041,46 @@ z$1.object({ acceptExtraSiteCharge: z$1.boolean().optional() });
160222
161041
  //#region ../surfaces/src/index.ts
160223
161042
  const SURFACE_IDS = ["core", "macadamia"];
160224
161043
  const DEFAULT_SURFACE_ID = "core";
161044
+ /**
161045
+ * Root hosts for each surface, keyed by deployment tier. The tier-keyed shape
161046
+ * makes it impossible to mis-order entries: callers like
161047
+ * `buildSurfaceAwareDashboardOriginForSurfaceId` look up by tier directly
161048
+ * rather than relying on positional alignment between arrays.
161049
+ */
161050
+ const SURFACE_ROOT_HOSTS = {
161051
+ core: {
161052
+ local: "localhost",
161053
+ prod: "riverbankcms.com"
161054
+ },
161055
+ macadamia: {
161056
+ local: "macadamia.localhost",
161057
+ prod: "macadamia.studio"
161058
+ }
161059
+ };
161060
+ const SURFACE_SITE_ROOT_HOSTS = {
161061
+ core: {
161062
+ local: "localhost",
161063
+ prod: "riverbanksites.com"
161064
+ },
161065
+ macadamia: {
161066
+ local: "macadamia.localhost",
161067
+ prod: "macadamia.studio"
161068
+ }
161069
+ };
161070
+ const SURFACE_SITE_ROOT_HOST_ALIASES = { core: { prod: ["preview.riverbanksites.com"] } };
161071
+ function surfaceHostTableValues(table) {
161072
+ return Object.values(table).flatMap((byTier) => Object.values(byTier).flat());
161073
+ }
161074
+ function siteSlugLabelUnderRoot(host, siteRootHost) {
161075
+ if (!host.endsWith(`.${siteRootHost}`)) return [];
161076
+ return host.slice(0, host.length - siteRootHost.length - 1).split(".").slice(-1);
161077
+ }
161078
+ function deriveSurfaceOwnedSiteSlugs() {
161079
+ const siteRootHosts = [...surfaceHostTableValues(SURFACE_SITE_ROOT_HOSTS), ...surfaceHostTableValues(SURFACE_SITE_ROOT_HOST_ALIASES)];
161080
+ const labels = [...surfaceHostTableValues(SURFACE_ROOT_HOSTS), ...siteRootHosts].flatMap((host) => siteRootHosts.flatMap((root) => siteSlugLabelUnderRoot(host, root)));
161081
+ return [...new Set(labels)].sort();
161082
+ }
161083
+ deriveSurfaceOwnedSiteSlugs();
160225
161084
  [...SURFACE_IDS.filter((surfaceId) => surfaceId !== DEFAULT_SURFACE_ID)];
160226
161085
  //#endregion
160227
161086
  //#region ../api/src/accountApi.ts
@@ -160865,6 +161724,7 @@ function parsePublicProductCategorySelector(value) {
160865
161724
  productCategoryEntryId: record.productCategoryEntryId
160866
161725
  };
160867
161726
  }
161727
+ z$1.enum(["public", "unlisted"], { error: "visibility must be 'public' or 'unlisted'" });
160868
161728
  //#endregion
160869
161729
  //#region ../api/src/bookingConfig.ts
160870
161730
  init_src$2();
@@ -162193,23 +163053,23 @@ async function loadPageWithDeps(deps, params) {
162193
163053
  if ("pageSurface" in pageResponse) throw new Error("This path resolves to a page surface, not a page. Use loadContent() instead, which handles pages, entries, and page surfaces.");
162194
163054
  const { page: pageData } = pageResponse;
162195
163055
  const support = buildSiteRenderSupport(site, collectMediaAssetSidecar(pageResponse.mediaAssets));
163056
+ const previewStage = preview ? "preview" : "published";
162196
163057
  const pageOutline = buildRenderablePageOutline({
162197
163058
  name: pageData.name,
162198
163059
  path: pageData.path,
162199
163060
  fallbackPath: path,
162200
163061
  purpose: pageData.purpose,
162201
163062
  blocks: pageData.blocks,
163063
+ previewStage,
162202
163064
  customBlocks: support.customBlocks
162203
163065
  });
162204
- const previewStage = preview ? "preview" : "published";
162205
- const renderTarget = {
162206
- kind: "page",
162207
- pageId: pageId ?? pageData.id
162208
- };
162209
163066
  const resolvedData = await resolveBlockDataWithDeps(deps, {
162210
163067
  page: projectRenderablePageOutline(pageOutline),
162211
163068
  siteId,
162212
- renderTarget,
163069
+ renderTarget: {
163070
+ kind: "page",
163071
+ pageId: pageId ?? pageData.id
163072
+ },
162213
163073
  previewStage,
162214
163074
  policy: createBlockDataLoadPolicy(dataLoaderOverrides, normalizeDataLoaderSearchParams(searchParams)),
162215
163075
  client,
@@ -162222,6 +163082,7 @@ async function loadPageWithDeps(deps, params) {
162222
163082
  sdkConfig: support.sdkConfig,
162223
163083
  siteId,
162224
163084
  resolvedData,
163085
+ dataContext: { previewStage },
162225
163086
  bookingOfferingPresets: support.bookingOfferingPresets,
162226
163087
  mailingList: support.mailingList,
162227
163088
  bookingTimeZone: support.bookingTimeZone,
@@ -164791,7 +165652,8 @@ async function processTemplatePage(input) {
164791
165652
  block,
164792
165653
  bindingContext: input.bindingContext,
164793
165654
  slotContent: input.slotContent,
164794
- customBlocks: input.customBlocks
165655
+ customBlocks: input.customBlocks,
165656
+ previewStage: input.previewStage
164795
165657
  }));
164796
165658
  if (blocks.length === 0) return {
164797
165659
  templatePage: null,
@@ -164822,7 +165684,7 @@ function resolveTemplateBlockSequence(input) {
164822
165684
  if (slotKey) return selectBlocksForDeclaredEntrySlot({
164823
165685
  declaredSlotKey: slotKey,
164824
165686
  entrySlots: input.slotContent ?? []
164825
- }).map((slotBlock) => admitEntrySlotBlock(slotBlock, input.customBlocks));
165687
+ }).map((slotBlock) => admitEntrySlotBlock(slotBlock, input.customBlocks, input.previewStage));
164826
165688
  if (block.blockKind === "system.entry-slot") return [];
164827
165689
  return [resolveTemplateBlock(block, input.bindingContext, input.customBlocks)];
164828
165690
  }
@@ -164856,10 +165718,11 @@ function readEntrySlotKey(block) {
164856
165718
  const parsed = parseSlotKey(block.content?.slotKey);
164857
165719
  return parsed.ok ? parsed.value : null;
164858
165720
  }
164859
- function admitEntrySlotBlock(block, customBlocks) {
165721
+ function admitEntrySlotBlock(block, customBlocks, previewStage) {
164860
165722
  const base = {
164861
165723
  id: block.id ?? block.blockId ?? null,
164862
165724
  contentVersionId: block.contentVersionId,
165725
+ ...entrySlotBlockIdentity(block, previewStage),
164863
165726
  kind: block.kind,
164864
165727
  purpose: block.purpose,
164865
165728
  ...isRecord(block.bindings) ? { bindings: block.bindings } : {}
@@ -164880,6 +165743,12 @@ function admitEntrySlotBlock(block, customBlocks) {
164880
165743
  error: renderable.error
164881
165744
  });
164882
165745
  }
165746
+ function entrySlotBlockIdentity(block, previewStage) {
165747
+ return {
165748
+ draftContentId: block.draftContentId ?? null,
165749
+ publishedPlacement: previewStage === "preview" ? readPublishedBlockPlacement(block.publishedContentId, isRecord(block.publishedContent) && isRecord(block.publishedContent.data) ? block.publishedContent.data : null) : null
165750
+ };
165751
+ }
164883
165752
  //#endregion
164884
165753
  //#region src/rendering/helpers/loadContent.ts
164885
165754
  /**
@@ -165051,15 +165920,18 @@ async function loadContentFromContentResponseWithDeps(deps, params) {
165051
165920
  entry,
165052
165921
  templatePage,
165053
165922
  resolvedData,
165054
- dataContext: { contentEntry: {
165055
- ...entry.content ?? {},
165056
- id: entry.id,
165057
- slug: entry.slug,
165058
- contentTypeSlug: entry.type,
165059
- _entryId: entry.id,
165060
- _entrySlug: entry.slug,
165061
- _contentTypeSlug: entry.type
165062
- } },
165923
+ dataContext: {
165924
+ previewStage,
165925
+ contentEntry: {
165926
+ ...entry.content ?? {},
165927
+ id: entry.id,
165928
+ slug: entry.slug,
165929
+ contentTypeSlug: entry.type,
165930
+ _entryId: entry.id,
165931
+ _entrySlug: entry.slug,
165932
+ _contentTypeSlug: entry.type
165933
+ }
165934
+ },
165063
165935
  ...templateContentSupport
165064
165936
  };
165065
165937
  }
@@ -165120,6 +165992,7 @@ async function loadContentFromContentResponseWithDeps(deps, params) {
165120
165992
  templatePage,
165121
165993
  resolvedData,
165122
165994
  dataContext: {
165995
+ previewStage,
165123
165996
  pageSurface: {
165124
165997
  ...pageSurface.content ?? {},
165125
165998
  id: pageSurface.id,
@@ -165136,13 +166009,13 @@ async function loadContentFromContentResponseWithDeps(deps, params) {
165136
166009
  const { page: pageData } = contentResponse;
165137
166010
  const pageRecord = pageData;
165138
166011
  const canonicalPagePath = pageData.path ?? pageRecord.path ?? "/";
165139
- const draftPagePath = pageRecord.draftPath ?? pageRecord.path ?? canonicalPagePath;
165140
166012
  const pageOutline = buildRenderablePageOutline({
165141
166013
  name: pageData.name,
165142
166014
  path: canonicalPagePath,
165143
166015
  fallbackPath: "/",
165144
166016
  purpose: pageData.purpose,
165145
166017
  blocks: pageData.blocks,
166018
+ previewStage,
165146
166019
  customBlocks: support.customBlocks
165147
166020
  });
165148
166021
  const resolvedData = await resolveBlockDataWithDeps(deps, {
@@ -165161,26 +166034,14 @@ async function loadContentFromContentResponseWithDeps(deps, params) {
165161
166034
  type: "page",
165162
166035
  pageId: pageRecord.id,
165163
166036
  routeId: pageRecord.routeId ?? null,
165164
- pageMetadata: {
165165
- draftTitle: pageRecord.draftTitle ?? pageRecord.name ?? pageData.name,
165166
- draftPath: draftPagePath,
165167
- draftStatus: pageRecord.draftStatus ?? pageRecord.status ?? "draft",
165168
- title: pageRecord.name ?? pageData.name,
165169
- path: canonicalPagePath,
165170
- status: pageRecord.status ?? pageRecord.draftStatus ?? "draft",
165171
- publishedAt: pageRecord.publishedAt ?? null,
165172
- draftMetaTitle: pageRecord.draftMetaTitle ?? null,
165173
- draftMetaDescription: pageRecord.draftMetaDescription ?? null,
165174
- publishedMetaTitle: pageRecord.publishedMetaTitle ?? null,
165175
- publishedMetaDescription: pageRecord.publishedMetaDescription ?? null,
165176
- ogImageId: pageRecord.ogImageId ?? null
165177
- },
166037
+ pageMetadata: projectPagePreviewMetadata(pageRecord, pageData.name, canonicalPagePath),
165178
166038
  page: pageOutline,
165179
166039
  runtimeJoins: pageData.runtimeJoins,
165180
166040
  theme: support.theme,
165181
166041
  siteId,
165182
166042
  ...support.customBlocks ? { customBlocks: support.customBlocks } : {},
165183
166043
  resolvedData,
166044
+ dataContext: { previewStage },
165184
166045
  bookingOfferingPresets: support.bookingOfferingPresets,
165185
166046
  mailingList: support.mailingList,
165186
166047
  bookingTimeZone: support.bookingTimeZone,
@@ -165193,6 +166054,32 @@ async function loadContentFromContentResponseWithDeps(deps, params) {
165193
166054
  ...support.mediaAssets ? { mediaAssets: support.mediaAssets } : {}
165194
166055
  };
165195
166056
  }
166057
+ function projectPagePreviewMetadata(page, pageName, canonicalPath) {
166058
+ return {
166059
+ ...projectDraftPageMetadata(page, pageName, canonicalPath),
166060
+ ...projectPublishedPageMetadata(page, pageName, canonicalPath)
166061
+ };
166062
+ }
166063
+ function projectDraftPageMetadata(page, pageName, canonicalPath) {
166064
+ return {
166065
+ draftTitle: page.draftTitle ?? page.name ?? pageName,
166066
+ draftPath: page.draftPath ?? page.path ?? canonicalPath,
166067
+ draftStatus: page.draftStatus ?? page.status ?? "draft",
166068
+ draftMetaTitle: page.draftMetaTitle ?? null,
166069
+ draftMetaDescription: page.draftMetaDescription ?? null
166070
+ };
166071
+ }
166072
+ function projectPublishedPageMetadata(page, pageName, canonicalPath) {
166073
+ return {
166074
+ title: page.name ?? pageName,
166075
+ path: canonicalPath,
166076
+ status: page.status ?? page.draftStatus ?? "draft",
166077
+ publishedAt: page.publishedAt ?? null,
166078
+ publishedMetaTitle: page.publishedMetaTitle ?? null,
166079
+ publishedMetaDescription: page.publishedMetaDescription ?? null,
166080
+ ogImageId: page.ogImageId ?? null
166081
+ };
166082
+ }
165196
166083
  /**
165197
166084
  * Type guard to check if API response is an entry
165198
166085
  */