@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
@@ -961,6 +961,27 @@ function formError(field) {
961
961
  field
962
962
  });
963
963
  }
964
+ //#endregion
965
+ //#region ../core/src/mailing-list-targeting.ts
966
+ function sameMailingListPlacementTargeting(left, right) {
967
+ if (left.mode !== right.mode) return false;
968
+ if (left.mode === "default" || right.mode === "default") return true;
969
+ if (left.provider !== right.provider || left.selection.tag !== right.selection.tag) return false;
970
+ if (left.provider === "mailchimp" && (right.provider !== "mailchimp" || left.audienceId !== right.audienceId)) return false;
971
+ return sameIds(targetingSelectionIds(left), targetingSelectionIds(right));
972
+ }
973
+ function targetingSelectionIds(targeting) {
974
+ switch (targeting.provider) {
975
+ case "native": return targeting.selection.tag === "fixed" ? targeting.selection.topicIds : targeting.selection.offeredTopicIds;
976
+ case "brevo": return targeting.selection.tag === "fixed" ? targeting.selection.listIds : targeting.selection.offeredListIds;
977
+ case "mailchimp": return targeting.selection.tag === "fixed" ? targeting.selection.interestIds : targeting.selection.offeredInterestIds;
978
+ }
979
+ }
980
+ function sameIds(left, right) {
981
+ const leftIds = new Set(left);
982
+ const rightIds = new Set(right);
983
+ return leftIds.size === left.length && rightIds.size === right.length && leftIds.size === rightIds.size && [...leftIds].every((id) => rightIds.has(id));
984
+ }
964
985
  function planMailingListChoicePresentation(targeting) {
965
986
  if (targeting.mode === "default" || targeting.selection.tag === "fixed") return { tag: "hidden" };
966
987
  switch (targeting.provider) {
@@ -28509,6 +28530,7 @@ const publicEventLoaderQuerySchemaShape = {
28509
28530
  seriesSlug: z$1.string().optional(),
28510
28531
  includeOccurrenceId: z$1.string().optional(),
28511
28532
  readIntent: z$1.string().optional(),
28533
+ detailAdmission: z$1.string().optional(),
28512
28534
  detailLevel: z$1.string().optional(),
28513
28535
  readProfile: z$1.string().optional()
28514
28536
  };
@@ -28675,11 +28697,11 @@ const publicEventBookingAvailabilitySchema = z$1.discriminatedUnion("kind", [z$1
28675
28697
  "series_archived",
28676
28698
  "parent_archived",
28677
28699
  "parent_inconsistent",
28678
- "not_public",
28679
28700
  "already_started",
28680
28701
  "enrollment_closed"
28681
28702
  ])
28682
28703
  })]);
28704
+ const publicEventBookingClosedDetailSchema = z$1.discriminatedUnion("kind", [z$1.object({ kind: z$1.literal("opensSoon") }), z$1.object({ kind: z$1.literal("paused") })]);
28683
28705
  const publicRunSessionSchema = z$1.object({
28684
28706
  occurrenceId: z$1.string(),
28685
28707
  startsAt: z$1.string(),
@@ -28724,6 +28746,7 @@ const publicEventBaseSchema = z$1.object({
28724
28746
  destination: publicEventDestinationSchema,
28725
28747
  requiresRegistration: z$1.boolean(),
28726
28748
  bookingAvailability: publicEventBookingAvailabilitySchema,
28749
+ bookingClosedDetail: publicEventBookingClosedDetailSchema.optional(),
28727
28750
  deliveryMode: z$1.enum([
28728
28751
  "in_person",
28729
28752
  "online",
@@ -30659,6 +30682,7 @@ const SOCIAL_ICON_NAMES = [
30659
30682
  "SocialInstagram",
30660
30683
  "SocialLinkedIn",
30661
30684
  "SocialTikTok",
30685
+ "SocialWhatsApp",
30662
30686
  "SocialX",
30663
30687
  "SocialYouTube"
30664
30688
  ];
@@ -30695,6 +30719,7 @@ const socialIcons = {
30695
30719
  /* @__PURE__ */ jsx("path", { d: "M10.5 9v10" })
30696
30720
  ] })),
30697
30721
  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" })] })),
30722
+ 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" })] })),
30698
30723
  SocialX: createIcon("SocialXIcon", /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("path", { d: "m5 4 14 16" }), /* @__PURE__ */ jsx("path", { d: "M19 4 5 20" })] })),
30699
30724
  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" })] }))
30700
30725
  };
@@ -33586,7 +33611,6 @@ function closedEventBookingLabel(reason) {
33586
33611
  case "series_archived":
33587
33612
  case "parent_archived":
33588
33613
  case "parent_inconsistent":
33589
- case "not_public":
33590
33614
  case "already_started":
33591
33615
  case "enrollment_closed": return "Registration closed";
33592
33616
  default: return assertNever$21(reason);
@@ -41443,6 +41467,12 @@ function withOptionalPhone(fields, includePhone) {
41443
41467
  }
41444
41468
  //#endregion
41445
41469
  //#region ../blocks/src/system/runtime/nodes/newsletter-form.interactive.ts
41470
+ const NEWSLETTER_SIGNUPS_PAUSED_MESSAGE = "We can’t accept signups right now. Please try again later.";
41471
+ function newsletterBlockSubmissionMessage(target) {
41472
+ if (target.tag === "block-source") return target.sourceRef ? null : NEWSLETTER_SIGNUPS_PAUSED_MESSAGE;
41473
+ if (target.tag !== "unpublished-preview") return null;
41474
+ 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.";
41475
+ }
41446
41476
  const newsletterButtonVariantSchema = blockButtonRoleSchema;
41447
41477
  const mailingListContextSchema = z$1.unknown().transform((value, ctx) => {
41448
41478
  const parsed = parseMailingListRuntimeContext(value);
@@ -41483,6 +41513,11 @@ const mailingListContentVersionIdSchema = z$1.string().transform((value, ctx) =>
41483
41513
  });
41484
41514
  return z$1.NEVER;
41485
41515
  });
41516
+ const mailingListSignupBlockSourceRefSchema = z$1.object({
41517
+ tag: z$1.literal("block_ref"),
41518
+ blockId: mailingListSignupBlockIdSchema,
41519
+ contentVersionId: mailingListContentVersionIdSchema
41520
+ });
41486
41521
  const signedMailingListSourceTokenSchema = z$1.string().trim().min(1).transform(parseRequiredMailingListSignedSourceToken);
41487
41522
  const newsletterSourceCommonSchema = z$1.object({
41488
41523
  siteId: z$1.string().optional(),
@@ -41497,7 +41532,15 @@ const newsletterSourceSchema = z$1.discriminatedUnion("source", [
41497
41532
  newsletterSourceCommonSchema.extend({
41498
41533
  source: z$1.literal("block"),
41499
41534
  blockId: z$1.string().nullable().optional(),
41500
- contentVersionId: z$1.string().nullable().optional()
41535
+ newsletterBlockSubmission: z$1.discriminatedUnion("tag", [
41536
+ z$1.object({
41537
+ tag: z$1.literal("ready"),
41538
+ sourceRef: mailingListSignupBlockSourceRefSchema
41539
+ }),
41540
+ z$1.object({ tag: z$1.literal("unpublished-form") }),
41541
+ z$1.object({ tag: z$1.literal("unpublished-settings") }),
41542
+ z$1.object({ tag: z$1.literal("unavailable") })
41543
+ ])
41501
41544
  }),
41502
41545
  newsletterSourceCommonSchema.extend({
41503
41546
  source: z$1.literal("signed-footer"),
@@ -41526,11 +41569,7 @@ const newsletterHydrationSchema = z$1.object({
41526
41569
  target: z$1.discriminatedUnion("tag", [
41527
41570
  z$1.object({
41528
41571
  tag: z$1.literal("block-source"),
41529
- sourceRef: z$1.object({
41530
- tag: z$1.literal("block_ref"),
41531
- blockId: mailingListSignupBlockIdSchema,
41532
- contentVersionId: mailingListContentVersionIdSchema
41533
- }).nullable()
41572
+ sourceRef: mailingListSignupBlockSourceRefSchema.nullable()
41534
41573
  }),
41535
41574
  z$1.object({
41536
41575
  tag: z$1.literal("signed-footer-source"),
@@ -41539,7 +41578,11 @@ const newsletterHydrationSchema = z$1.object({
41539
41578
  token: signedMailingListSourceTokenSchema
41540
41579
  })
41541
41580
  }),
41542
- z$1.object({ tag: z$1.literal("preview") })
41581
+ z$1.object({ tag: z$1.literal("preview") }),
41582
+ z$1.object({
41583
+ tag: z$1.literal("unpublished-preview"),
41584
+ reason: z$1.enum(["unpublished-form", "unpublished-settings"])
41585
+ })
41543
41586
  ]),
41544
41587
  setupRevision: z$1.number().int().positive().nullable(),
41545
41588
  choiceProvider: z$1.enum([
@@ -41608,16 +41651,21 @@ const newsletterFormBlockRuntime = defineProgressiveBlockRuntime({
41608
41651
  });
41609
41652
  function projectNewsletterFormHydrationTarget(source) {
41610
41653
  switch (source.source) {
41611
- case "block": {
41612
- const sourceRef = buildMailingListSignupBlockSourceRef(source.blockId, source.contentVersionId);
41613
- if (sourceRef?.tag === "block_ref") return {
41654
+ case "block": switch (source.newsletterBlockSubmission.tag) {
41655
+ case "unpublished-form":
41656
+ case "unpublished-settings": return {
41657
+ tag: "unpublished-preview",
41658
+ reason: source.newsletterBlockSubmission.tag
41659
+ };
41660
+ case "ready": return {
41614
41661
  tag: "block-source",
41615
- sourceRef
41662
+ sourceRef: source.newsletterBlockSubmission.sourceRef
41616
41663
  };
41617
- return {
41664
+ case "unavailable": return {
41618
41665
  tag: "block-source",
41619
41666
  sourceRef: null
41620
41667
  };
41668
+ default: return assertNever$21(source.newsletterBlockSubmission);
41621
41669
  }
41622
41670
  case "signed-footer": return {
41623
41671
  tag: "signed-footer-source",
@@ -41686,6 +41734,7 @@ function buildNewsletterFormInteractiveIslandProps(props) {
41686
41734
  const decoded = newsletterFormBlockRuntime.contracts.source.decode(props);
41687
41735
  const source = isDecodeSuccess(decoded) ? decoded.value : {
41688
41736
  ...props,
41737
+ ...props.source === "block" ? { newsletterBlockSubmission: { tag: "unavailable" } } : {},
41689
41738
  mailingList: void 0,
41690
41739
  targeting: { mode: "default" }
41691
41740
  };
@@ -44100,6 +44149,156 @@ function FeedbackMessage({ tone, treatment = "panel", children, className, id, t
44100
44149
  });
44101
44150
  }
44102
44151
  //#endregion
44152
+ //#region ../blocks/src/system/runtime/shared/components/CheckboxChoice.tsx
44153
+ /**
44154
+ * The customer-facing checkbox every block renders. Styling comes from the
44155
+ * theme's input CSS (`.form-check`, `.form-checkbox`), so it follows each
44156
+ * site's input colours, borders and corners.
44157
+ */
44158
+ function CheckboxChoice({ label, presentation = "row", className, ...inputProps }) {
44159
+ return /* @__PURE__ */ jsxs("label", {
44160
+ className: clsx("form-check", presentation === "tile" && "form-check--tile", className),
44161
+ children: [/* @__PURE__ */ jsx("input", {
44162
+ ...inputProps,
44163
+ type: "checkbox",
44164
+ className: "form-checkbox"
44165
+ }), /* @__PURE__ */ jsx("span", {
44166
+ className: "form-check-label",
44167
+ children: label
44168
+ })]
44169
+ });
44170
+ }
44171
+ //#endregion
44172
+ //#region ../blocks/src/system/runtime/nodes/form.fields.tsx
44173
+ function fieldBasics(field) {
44174
+ return {
44175
+ inputId: `f_${field.id}`,
44176
+ label: String(field.label ?? field.id),
44177
+ required: Boolean(field.required)
44178
+ };
44179
+ }
44180
+ function textInputType(type) {
44181
+ return type === "email" || type === "url" || type === "tel" || type === "number" ? type : "text";
44182
+ }
44183
+ function textInputConstraints(field, inputType) {
44184
+ if (inputType === "number") return {
44185
+ ...typeof field.min === "number" ? { min: field.min } : {},
44186
+ ...typeof field.max === "number" ? { max: field.max } : {}
44187
+ };
44188
+ return {
44189
+ ...typeof field.minLength === "number" ? { minLength: field.minLength } : {},
44190
+ ...typeof field.maxLength === "number" ? { maxLength: field.maxLength } : {},
44191
+ ...typeof field.pattern === "string" && field.pattern ? { pattern: field.pattern } : {}
44192
+ };
44193
+ }
44194
+ function LabelledField({ basics, children }) {
44195
+ return /* @__PURE__ */ jsxs("div", {
44196
+ className: "fb-field",
44197
+ children: [/* @__PURE__ */ jsx("label", {
44198
+ htmlFor: basics.inputId,
44199
+ className: "form-label",
44200
+ children: basics.label
44201
+ }), children]
44202
+ });
44203
+ }
44204
+ function TextareaField({ field }) {
44205
+ const basics = fieldBasics(field);
44206
+ return /* @__PURE__ */ jsx(LabelledField, {
44207
+ basics,
44208
+ children: /* @__PURE__ */ jsx("textarea", {
44209
+ id: basics.inputId,
44210
+ name: field.id,
44211
+ required: basics.required,
44212
+ placeholder: field.placeholder,
44213
+ rows: field.rows,
44214
+ className: "form-textarea"
44215
+ })
44216
+ });
44217
+ }
44218
+ function SelectField({ field }) {
44219
+ const basics = fieldBasics(field);
44220
+ const options = field.options ?? [];
44221
+ const multiple = Boolean(field.multiple);
44222
+ return /* @__PURE__ */ jsx(LabelledField, {
44223
+ basics,
44224
+ children: /* @__PURE__ */ jsxs("select", {
44225
+ id: basics.inputId,
44226
+ name: field.id,
44227
+ multiple,
44228
+ required: basics.required,
44229
+ className: "form-select",
44230
+ children: [!multiple && /* @__PURE__ */ jsx("option", {
44231
+ value: "",
44232
+ children: "Select…"
44233
+ }), options.map((opt) => /* @__PURE__ */ jsx("option", {
44234
+ value: opt.value,
44235
+ children: opt.label
44236
+ }, opt.value))]
44237
+ })
44238
+ });
44239
+ }
44240
+ function RadioField({ field }) {
44241
+ const basics = fieldBasics(field);
44242
+ const options = field.options ?? [];
44243
+ return /* @__PURE__ */ jsxs("fieldset", {
44244
+ className: "fb-fieldset",
44245
+ children: [/* @__PURE__ */ jsx("legend", {
44246
+ className: "form-label",
44247
+ children: basics.label
44248
+ }), options.map((opt) => /* @__PURE__ */ jsxs("label", {
44249
+ className: "form-check",
44250
+ children: [/* @__PURE__ */ jsx("input", {
44251
+ type: "radio",
44252
+ name: field.id,
44253
+ value: opt.value,
44254
+ required: basics.required,
44255
+ className: "form-radio"
44256
+ }), /* @__PURE__ */ jsx("span", {
44257
+ className: "form-check-label",
44258
+ children: opt.label
44259
+ })]
44260
+ }, opt.value))]
44261
+ });
44262
+ }
44263
+ function TextInputField({ field, type }) {
44264
+ const basics = fieldBasics(field);
44265
+ const inputType = textInputType(type);
44266
+ return /* @__PURE__ */ jsx(LabelledField, {
44267
+ basics,
44268
+ children: /* @__PURE__ */ jsx("input", {
44269
+ id: basics.inputId,
44270
+ name: field.id,
44271
+ type: inputType,
44272
+ required: basics.required,
44273
+ placeholder: field.placeholder,
44274
+ ...textInputConstraints(field, inputType),
44275
+ className: "form-input"
44276
+ })
44277
+ });
44278
+ }
44279
+ function FormFieldControl({ field }) {
44280
+ const type = String(field.type ?? "text");
44281
+ switch (type) {
44282
+ case "textarea": return /* @__PURE__ */ jsx(TextareaField, { field });
44283
+ case "select": return /* @__PURE__ */ jsx(SelectField, { field });
44284
+ case "radio": return /* @__PURE__ */ jsx(RadioField, { field });
44285
+ case "checkbox":
44286
+ case "consent": {
44287
+ const basics = fieldBasics(field);
44288
+ return /* @__PURE__ */ jsx(CheckboxChoice, {
44289
+ name: field.id,
44290
+ required: basics.required,
44291
+ label: basics.label,
44292
+ presentation: type === "consent" ? "tile" : "row"
44293
+ });
44294
+ }
44295
+ default: return /* @__PURE__ */ jsx(TextInputField, {
44296
+ field,
44297
+ type
44298
+ });
44299
+ }
44300
+ }
44301
+ //#endregion
44103
44302
  //#region ../blocks/src/system/runtime/nodes/form.server.tsx
44104
44303
  const FormNodeSSR = ({ blockId, value, submitLabel, successMessage, className, onSubmit, action = "/api/forms/submit", siteId, apiBaseUrl, spamProtectionEnabled }) => {
44105
44304
  const islandProps = buildFormInteractiveIslandProps({
@@ -44123,107 +44322,7 @@ const FormNodeSSR = ({ blockId, value, submitLabel, successMessage, className, o
44123
44322
  })]
44124
44323
  });
44125
44324
  const groups = display.groups;
44126
- const renderField = (field) => {
44127
- const inputId = `f_${field.id}`;
44128
- const label = String(field.label ?? field.id);
44129
- const required = Boolean(field.required);
44130
- const type = String(field.type ?? "text");
44131
- if (type === "textarea") return /* @__PURE__ */ jsxs("div", {
44132
- className: "fb-field",
44133
- children: [/* @__PURE__ */ jsx("label", {
44134
- htmlFor: inputId,
44135
- className: "form-label",
44136
- children: label
44137
- }), /* @__PURE__ */ jsx("textarea", {
44138
- id: inputId,
44139
- name: field.id,
44140
- required,
44141
- placeholder: field.placeholder,
44142
- rows: field.rows,
44143
- className: "form-textarea"
44144
- })]
44145
- }, field.id);
44146
- if (type === "select") {
44147
- const options = field.options ?? [];
44148
- const multiple = Boolean(field.multiple);
44149
- return /* @__PURE__ */ jsxs("div", {
44150
- className: "fb-field",
44151
- children: [/* @__PURE__ */ jsx("label", {
44152
- htmlFor: inputId,
44153
- className: "form-label",
44154
- children: label
44155
- }), /* @__PURE__ */ jsxs("select", {
44156
- id: inputId,
44157
- name: field.id,
44158
- multiple,
44159
- required,
44160
- className: "form-select",
44161
- children: [!multiple && /* @__PURE__ */ jsx("option", {
44162
- value: "",
44163
- children: "Select…"
44164
- }), options.map((opt) => /* @__PURE__ */ jsx("option", {
44165
- value: opt.value,
44166
- children: opt.label
44167
- }, opt.value))]
44168
- })]
44169
- }, field.id);
44170
- }
44171
- if (type === "radio") {
44172
- const options = field.options ?? [];
44173
- return /* @__PURE__ */ jsxs("fieldset", {
44174
- className: "fb-fieldset",
44175
- children: [/* @__PURE__ */ jsx("legend", {
44176
- className: "form-label",
44177
- children: label
44178
- }), options.map((opt) => /* @__PURE__ */ jsxs("label", {
44179
- className: "fb-inline form-label",
44180
- children: [/* @__PURE__ */ jsx("input", {
44181
- type: "radio",
44182
- name: field.id,
44183
- value: opt.value,
44184
- required,
44185
- className: "form-radio"
44186
- }), /* @__PURE__ */ jsx("span", { children: opt.label })]
44187
- }, opt.value))]
44188
- }, field.id);
44189
- }
44190
- if (type === "checkbox" || type === "consent") return /* @__PURE__ */ jsxs("label", {
44191
- className: "fb-inline form-label",
44192
- children: [/* @__PURE__ */ jsx("input", {
44193
- type: "checkbox",
44194
- name: field.id,
44195
- required,
44196
- className: "form-checkbox"
44197
- }), /* @__PURE__ */ jsx("span", { children: label })]
44198
- }, field.id);
44199
- const inputType = type === "email" || type === "url" || type === "tel" || type === "number" ? type : "text";
44200
- const extra = {};
44201
- if (inputType === "text" || inputType === "email" || inputType === "url" || inputType === "tel") {
44202
- if (typeof field.minLength === "number") extra.minLength = field.minLength;
44203
- if (typeof field.maxLength === "number") extra.maxLength = field.maxLength;
44204
- if (typeof field.pattern === "string" && field.pattern) extra.pattern = field.pattern;
44205
- }
44206
- if (inputType === "number") {
44207
- if (typeof field.min === "number") extra.min = field.min;
44208
- if (typeof field.max === "number") extra.max = field.max;
44209
- }
44210
- return /* @__PURE__ */ jsxs("div", {
44211
- className: "fb-field",
44212
- children: [/* @__PURE__ */ jsx("label", {
44213
- htmlFor: inputId,
44214
- className: "form-label",
44215
- children: label
44216
- }), /* @__PURE__ */ jsx("input", {
44217
- id: inputId,
44218
- name: field.id,
44219
- type: inputType,
44220
- required,
44221
- placeholder: field.placeholder,
44222
- ...extra,
44223
- className: "form-input"
44224
- })]
44225
- }, field.id);
44226
- };
44325
+ const renderField = (field) => /* @__PURE__ */ jsx(FormFieldControl, { field }, field.id);
44227
44326
  return /* @__PURE__ */ jsxs("div", {
44228
44327
  ...getIslandRootProps("form", blockId),
44229
44328
  children: [/* @__PURE__ */ jsx(IslandPropsScript, { value: islandProps }), /* @__PURE__ */ jsxs("form", {
@@ -44269,6 +44368,172 @@ const FormNodeSSR = ({ blockId, value, submitLabel, successMessage, className, o
44269
44368
  });
44270
44369
  };
44271
44370
  //#endregion
44371
+ //#region ../blocks/src/system/runtime/shared/components/FieldValidationMessage.tsx
44372
+ function getFieldValidationControlProps({ message, messageId, describedBy }) {
44373
+ const hasMessage = Boolean(message);
44374
+ const ariaDescribedBy = [describedBy, hasMessage ? messageId : void 0].filter((part) => typeof part === "string" && part.length > 0).join(" ");
44375
+ return {
44376
+ "aria-invalid": hasMessage ? "true" : void 0,
44377
+ "aria-describedby": ariaDescribedBy || void 0
44378
+ };
44379
+ }
44380
+ function FieldValidationMessage({ id, children, className, live = "assertive" }) {
44381
+ return /* @__PURE__ */ jsx("p", {
44382
+ id,
44383
+ className,
44384
+ "data-field-validation-message": true,
44385
+ "data-field-validation-tone": "error",
44386
+ role: "alert",
44387
+ "aria-live": live === "off" ? void 0 : live,
44388
+ children
44389
+ });
44390
+ }
44391
+ //#endregion
44392
+ //#region ../blocks/src/system/runtime/nodes/newsletter-form.parts.tsx
44393
+ /**
44394
+ * Newsletter form pieces shared by the SSR render and the hydrated island, so
44395
+ * both produce the same markup.
44396
+ *
44397
+ * Labels are visually hidden: every field has a placeholder, and a visible
44398
+ * "Email *" label over a single field reads like a generic form. Screen
44399
+ * readers still get the label.
44400
+ */
44401
+ const TOPIC_CHOICE_FIELD_ID = "mailingListChoice";
44402
+ const inputIdFor = (field) => `newsletter_${field.id}`;
44403
+ /** Splits the preset's fields into the email (joined with the button) and the rest. */
44404
+ function partitionNewsletterFields(fields) {
44405
+ const email = fields.find((field) => field.type === "email") ?? null;
44406
+ return {
44407
+ email,
44408
+ extra: fields.filter((field) => field !== email)
44409
+ };
44410
+ }
44411
+ function NewsletterExtraField({ field, disabled, error }) {
44412
+ const inputId = inputIdFor(field);
44413
+ const errorId = `${inputId}-error`;
44414
+ return /* @__PURE__ */ jsxs("div", {
44415
+ className: "fb-field newsletter-field",
44416
+ children: [
44417
+ /* @__PURE__ */ jsx("label", {
44418
+ htmlFor: inputId,
44419
+ className: "rb-sr-only",
44420
+ children: field.label
44421
+ }),
44422
+ /* @__PURE__ */ jsx("input", {
44423
+ id: inputId,
44424
+ name: field.id,
44425
+ type: field.type,
44426
+ required: field.required,
44427
+ placeholder: field.placeholder ?? field.label,
44428
+ className: "form-input",
44429
+ disabled,
44430
+ ...getFieldValidationControlProps({
44431
+ message: error,
44432
+ messageId: errorId
44433
+ })
44434
+ }),
44435
+ error ? /* @__PURE__ */ jsx(FieldValidationMessage, {
44436
+ id: errorId,
44437
+ className: "fb-error",
44438
+ children: error
44439
+ }) : null
44440
+ ]
44441
+ });
44442
+ }
44443
+ /** The email field and submit button sharing one input-styled shell. */
44444
+ function NewsletterEmailEntry({ field, buttonVariant, buttonLabel, disabled, error }) {
44445
+ const inputId = inputIdFor(field);
44446
+ const errorId = `${inputId}-error`;
44447
+ return /* @__PURE__ */ jsxs("div", {
44448
+ className: "newsletter-entry",
44449
+ children: [/* @__PURE__ */ jsxs("div", {
44450
+ className: "form-input-group newsletter-entry-group",
44451
+ children: [
44452
+ /* @__PURE__ */ jsx("label", {
44453
+ htmlFor: inputId,
44454
+ className: "rb-sr-only",
44455
+ children: field.label
44456
+ }),
44457
+ /* @__PURE__ */ jsx("input", {
44458
+ id: inputId,
44459
+ name: field.id,
44460
+ type: "email",
44461
+ required: field.required,
44462
+ placeholder: field.placeholder ?? field.label,
44463
+ className: "form-input-group-field",
44464
+ autoComplete: "email",
44465
+ disabled,
44466
+ ...getFieldValidationControlProps({
44467
+ message: error,
44468
+ messageId: errorId
44469
+ })
44470
+ }),
44471
+ /* @__PURE__ */ jsx(ThemedButton, {
44472
+ type: "submit",
44473
+ variant: buttonVariant,
44474
+ size: "md",
44475
+ disabled,
44476
+ label: buttonLabel
44477
+ })
44478
+ ]
44479
+ }), error ? /* @__PURE__ */ jsx(FieldValidationMessage, {
44480
+ id: errorId,
44481
+ className: "fb-error",
44482
+ children: error
44483
+ }) : null]
44484
+ });
44485
+ }
44486
+ /**
44487
+ * The submit action: joined to the email field when the preset has one
44488
+ * (every current preset does), otherwise a plain themed button.
44489
+ */
44490
+ function NewsletterSubmitRow({ emailField, buttonVariant, buttonLabel, disabled, error }) {
44491
+ if (emailField) return /* @__PURE__ */ jsx(NewsletterEmailEntry, {
44492
+ field: emailField,
44493
+ buttonVariant,
44494
+ buttonLabel,
44495
+ disabled,
44496
+ error
44497
+ });
44498
+ return /* @__PURE__ */ jsx("div", {
44499
+ className: "newsletter-submit",
44500
+ children: /* @__PURE__ */ jsx(ThemedButton, {
44501
+ type: "submit",
44502
+ variant: buttonVariant,
44503
+ size: "md",
44504
+ disabled,
44505
+ label: buttonLabel
44506
+ })
44507
+ });
44508
+ }
44509
+ /** Visitor-chosen topics as toggle chips. Real checkboxes underneath. */
44510
+ function NewsletterTopicChips({ choices, disabled, error }) {
44511
+ const errorId = `newsletter_${TOPIC_CHOICE_FIELD_ID}-error`;
44512
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("fieldset", {
44513
+ className: "newsletter-topics",
44514
+ "aria-describedby": error ? errorId : void 0,
44515
+ children: [/* @__PURE__ */ jsx("legend", {
44516
+ className: "newsletter-topics-legend",
44517
+ children: "What would you like to hear about?"
44518
+ }), /* @__PURE__ */ jsx("div", {
44519
+ className: "newsletter-topic-chips",
44520
+ children: choices.map((choice) => /* @__PURE__ */ jsxs("label", {
44521
+ className: "newsletter-topic-chip",
44522
+ children: [/* @__PURE__ */ jsx("input", {
44523
+ type: "checkbox",
44524
+ name: TOPIC_CHOICE_FIELD_ID,
44525
+ value: choice.id,
44526
+ disabled
44527
+ }), /* @__PURE__ */ jsx("span", { children: choice.label })]
44528
+ }, choice.id))
44529
+ })]
44530
+ }), error ? /* @__PURE__ */ jsx(FieldValidationMessage, {
44531
+ id: errorId,
44532
+ className: "fb-error",
44533
+ children: error
44534
+ }) : null] });
44535
+ }
44536
+ //#endregion
44272
44537
  //#region ../blocks/src/system/runtime/nodes/newsletter-form.server.tsx
44273
44538
  /**
44274
44539
  * Newsletter Form Server Component
@@ -44289,36 +44554,15 @@ function NewsletterFormSSR(props) {
44289
44554
  });
44290
44555
  const display = islandProps.render.display;
44291
44556
  const fields = display.fields;
44557
+ const submissionMessage = newsletterBlockSubmissionMessage(islandProps.render.hydration.target);
44292
44558
  if (display.availability === "unavailable") return /* @__PURE__ */ jsx("div", {
44293
44559
  className: clsx("newsletter-form-ssr", className),
44294
44560
  children: /* @__PURE__ */ jsx("p", {
44295
44561
  role: "status",
44296
- children: "We can’t accept signups right now. Please try again later."
44562
+ children: NEWSLETTER_SIGNUPS_PAUSED_MESSAGE
44297
44563
  })
44298
44564
  });
44299
- const renderField = (field) => {
44300
- const inputId = `newsletter_${field.id}`;
44301
- return /* @__PURE__ */ jsxs("div", {
44302
- className: "fb-field newsletter-field",
44303
- children: [/* @__PURE__ */ jsxs("label", {
44304
- htmlFor: inputId,
44305
- className: "form-label",
44306
- children: [field.label, field.required && /* @__PURE__ */ jsx("span", {
44307
- className: "newsletter-required",
44308
- "aria-hidden": "true",
44309
- children: "*"
44310
- })]
44311
- }), /* @__PURE__ */ jsx("input", {
44312
- id: inputId,
44313
- name: field.id,
44314
- type: field.type,
44315
- required: field.required,
44316
- placeholder: field.placeholder,
44317
- className: "form-input",
44318
- autoComplete: field.type === "email" ? "email" : void 0
44319
- })]
44320
- }, field.id);
44321
- };
44565
+ const { email: emailField, extra: extraFields } = partitionNewsletterFields(fields);
44322
44566
  return /* @__PURE__ */ jsxs("div", {
44323
44567
  ...getIslandRootProps("newsletter-form", blockId),
44324
44568
  className: clsx("newsletter-form-ssr", className),
@@ -44337,30 +44581,20 @@ function NewsletterFormSSR(props) {
44337
44581
  /* @__PURE__ */ jsxs("div", {
44338
44582
  className: "newsletter-form-fields",
44339
44583
  children: [
44340
- fields.map(renderField),
44341
- islandProps.render.hydration.choicePresentation === "visitor_choice" ? /* @__PURE__ */ jsxs("fieldset", {
44342
- className: "fb-fieldset newsletter-topics",
44343
- children: [/* @__PURE__ */ jsx("legend", {
44344
- className: "form-label",
44345
- children: "What would you like to hear about?"
44346
- }), display.choices.map((choice) => /* @__PURE__ */ jsxs("label", {
44347
- className: "fb-inline form-label newsletter-topic-choice",
44348
- children: [/* @__PURE__ */ jsx("input", {
44349
- type: "checkbox",
44350
- name: "mailingListChoice",
44351
- value: choice.id,
44352
- className: "form-checkbox"
44353
- }), /* @__PURE__ */ jsx("span", { children: choice.label })]
44354
- }, choice.id))]
44584
+ islandProps.render.hydration.choicePresentation === "visitor_choice" ? /* @__PURE__ */ jsx(NewsletterTopicChips, { choices: display.choices }) : null,
44585
+ extraFields.length > 0 ? /* @__PURE__ */ jsx("div", {
44586
+ className: "newsletter-extra-fields",
44587
+ children: extraFields.map((field) => /* @__PURE__ */ jsx(NewsletterExtraField, { field }, field.id))
44355
44588
  }) : null,
44356
- /* @__PURE__ */ jsx("div", {
44357
- className: "newsletter-submit",
44358
- children: /* @__PURE__ */ jsx(ThemedButton, {
44359
- type: "submit",
44360
- variant: display.buttonVariant,
44361
- size: "md",
44362
- label: display.buttonLabel
44363
- })
44589
+ /* @__PURE__ */ jsx(NewsletterSubmitRow, {
44590
+ emailField,
44591
+ buttonVariant: display.buttonVariant,
44592
+ buttonLabel: display.buttonLabel,
44593
+ disabled: submissionMessage !== null
44594
+ }),
44595
+ submissionMessage && /* @__PURE__ */ jsx("p", {
44596
+ role: "status",
44597
+ children: submissionMessage
44364
44598
  })
44365
44599
  ]
44366
44600
  }),
@@ -45341,7 +45575,7 @@ const RENDERER_METADATA_PROP_KEYS = /* @__PURE__ */ new Set([
45341
45575
  "blockContent",
45342
45576
  "fragmentRegistry",
45343
45577
  "previewAuthoring",
45344
- "contentVersionId",
45578
+ "newsletterBlockSubmission",
45345
45579
  "imageResolveContext"
45346
45580
  ]);
45347
45581
  function omitRendererMetadataProps(props) {
@@ -45397,7 +45631,7 @@ function resolveNodeMetadata(nodeType, context) {
45397
45631
  pathBase: context.pathBase,
45398
45632
  fragmentRegistry: context.fragmentRegistry
45399
45633
  } : {},
45400
- ...normalizedType === "newsletter-form" ? { contentVersionId: context.contentVersionId } : {},
45634
+ ...normalizedType === "newsletter-form" ? { newsletterBlockSubmission: context.newsletterBlockSubmission } : {},
45401
45635
  ...normalizedType === "media" && context.imageResolveContext ? { imageResolveContext: context.imageResolveContext } : {}
45402
45636
  };
45403
45637
  }
@@ -46008,6 +46242,270 @@ function generateHoverEffects(axes, _space) {
46008
46242
  };
46009
46243
  }
46010
46244
  //#endregion
46245
+ //#region ../theme-core/src/inputs/checkable.ts
46246
+ /**
46247
+ * Checkbox and radio CSS shared by the full theme generator and the SDK
46248
+ * theme bridge, so both render the same customer-facing controls.
46249
+ *
46250
+ * Emits:
46251
+ * - .form-checkbox / .form-radio: the controls themselves. The tick and dot
46252
+ * are drawn with ::before so their colour comes from theme tokens rather
46253
+ * than a baked-in SVG.
46254
+ * - .form-check: a label row holding a control and its text. The control
46255
+ * lines up with the first line of text, so long labels wrap cleanly.
46256
+ * - .form-check--tile: a bordered, fully clickable panel for agreements
46257
+ * (booking consent, consent fields) that tints when ticked.
46258
+ */
46259
+ const CHECKABLE_SIZE = "1.375rem";
46260
+ /** Never fully round: a round checkbox reads as a radio. */
46261
+ const CHECKBOX_RADIUS = {
46262
+ square: "0",
46263
+ soft: "0.25rem",
46264
+ rounded: "0.375rem",
46265
+ pill: "0.375rem"
46266
+ };
46267
+ /** Tiles hold wrapping text, so pill themes get a generous radius, not a capsule. */
46268
+ const TILE_RADIUS = {
46269
+ square: "0",
46270
+ soft: "0.5rem",
46271
+ rounded: "0.75rem",
46272
+ pill: "1rem"
46273
+ };
46274
+ const ON_ACCENT_TOKENS = {
46275
+ primary: "onPrimary",
46276
+ secondary: "onSecondary",
46277
+ accent: "onAccent"
46278
+ };
46279
+ /**
46280
+ * Colour for the tick/dot drawn on top of the accent fill. Uses the palette's
46281
+ * matching "on" token where there is one, falling back to white.
46282
+ */
46283
+ /** The accent at full strength: `primary/70` becomes `primary`. */
46284
+ function solidAccentToken(accentToken) {
46285
+ const parsed = parseColorTokenParts(accentToken);
46286
+ return parsed.kind === "token" ? parsed.token : accentToken;
46287
+ }
46288
+ function checkableMarkColor(accentToken) {
46289
+ const parsed = parseColorTokenParts(accentToken);
46290
+ const onToken = parsed.kind === "token" ? ON_ACCENT_TOKENS[parsed.token] : void 0;
46291
+ return onToken ? `rgb(var(--tb-${onToken}, 255 255 255))` : "rgb(255 255 255)";
46292
+ }
46293
+ function checkableSelectors(root) {
46294
+ return {
46295
+ checkbox: `${root} .form-checkbox`,
46296
+ radio: `${root} .form-radio`,
46297
+ check: `${root} .form-check`,
46298
+ tile: `${root} .form-check--tile`
46299
+ };
46300
+ }
46301
+ /** The box and circle themselves, unchecked. */
46302
+ function controlBaseCss(sel, input) {
46303
+ const border = input.borderWidth === "0" ? "1px" : input.borderWidth;
46304
+ return [
46305
+ `${sel.checkbox},
46306
+ ${sel.radio} {
46307
+ appearance: none;
46308
+ display: inline-grid;
46309
+ place-content: center;
46310
+ width: ${CHECKABLE_SIZE};
46311
+ height: ${CHECKABLE_SIZE};
46312
+ margin: 0;
46313
+ flex-shrink: 0;
46314
+ border: ${border} solid ${input.borderColor};
46315
+ background-color: ${input.background};
46316
+ color: inherit;
46317
+ cursor: pointer;
46318
+ transition: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
46319
+ }`,
46320
+ `${sel.checkbox} {
46321
+ border-radius: ${CHECKBOX_RADIUS[input.corners]};
46322
+ }`,
46323
+ `${sel.radio} {
46324
+ border-radius: 9999px;
46325
+ }`
46326
+ ];
46327
+ }
46328
+ /** The tick and dot, drawn with ::before so their colour is a theme token. */
46329
+ function controlMarkCss(sel, accentToken) {
46330
+ return [
46331
+ `${sel.checkbox}::before,
46332
+ ${sel.radio}::before {
46333
+ content: "";
46334
+ background-color: ${checkableMarkColor(accentToken)};
46335
+ transform: scale(0);
46336
+ transition: transform 0.12s ease;
46337
+ }`,
46338
+ `${sel.checkbox}::before {
46339
+ width: 0.75rem;
46340
+ height: 0.75rem;
46341
+ clip-path: polygon(14% 52%, 0 67%, 38% 100%, 100% 22%, 85% 8%, 37% 70%);
46342
+ }`,
46343
+ `${sel.radio}::before {
46344
+ width: 0.5rem;
46345
+ height: 0.5rem;
46346
+ border-radius: 9999px;
46347
+ }`
46348
+ ];
46349
+ }
46350
+ function controlStateCss(sel, input) {
46351
+ const accent = rgbColorValue(solidAccentToken(input.accentToken));
46352
+ return [
46353
+ `${sel.checkbox}:hover,
46354
+ ${sel.radio}:hover,
46355
+ ${sel.check}:hover > .form-checkbox,
46356
+ ${sel.check}:hover > .form-radio {
46357
+ border-color: ${accent};
46358
+ }`,
46359
+ `${sel.checkbox}:checked,
46360
+ ${sel.radio}:checked {
46361
+ background-color: ${accent};
46362
+ border-color: ${accent};
46363
+ }`,
46364
+ `${sel.checkbox}:checked::before,
46365
+ ${sel.radio}:checked::before {
46366
+ transform: scale(1);
46367
+ }`,
46368
+ `${sel.checkbox}:focus-visible,
46369
+ ${sel.radio}:focus-visible {
46370
+ outline: 2px solid ${accent};
46371
+ outline-offset: 2px;
46372
+ }`,
46373
+ `${sel.checkbox}:disabled,
46374
+ ${sel.radio}:disabled {
46375
+ opacity: 0.5;
46376
+ cursor: not-allowed;
46377
+ }`
46378
+ ];
46379
+ }
46380
+ /** Label row: control lined up with the first line of wrapping text. */
46381
+ function checkRowCss(sel) {
46382
+ return [
46383
+ `${sel.check} {
46384
+ display: flex;
46385
+ align-items: flex-start;
46386
+ gap: 0.75rem;
46387
+ line-height: 1.5;
46388
+ cursor: pointer;
46389
+ }`,
46390
+ `${sel.check} > .form-checkbox,
46391
+ ${sel.check} > .form-radio {
46392
+ margin-top: 0.0625rem;
46393
+ margin-top: max(0px, calc((1lh - ${CHECKABLE_SIZE}) / 2));
46394
+ }`,
46395
+ `${sel.check}:has(> :disabled) {
46396
+ cursor: not-allowed;
46397
+ }`
46398
+ ];
46399
+ }
46400
+ function agreementTileCss(sel, input) {
46401
+ const accent = rgbColorValue(solidAccentToken(input.accentToken));
46402
+ return [
46403
+ `${sel.tile} {
46404
+ padding: 0.875rem 1rem;
46405
+ border: 1px solid color-mix(in srgb, currentColor 22%, transparent);
46406
+ border-radius: ${TILE_RADIUS[input.corners]};
46407
+ transition: border-color 0.15s ease, background-color 0.15s ease;
46408
+ }`,
46409
+ `${sel.tile}:hover {
46410
+ border-color: color-mix(in srgb, ${accent} 55%, transparent);
46411
+ }`,
46412
+ `${sel.tile}:has(> .form-checkbox:checked) {
46413
+ border-color: ${accent};
46414
+ background-color: color-mix(in srgb, ${accent} 7%, transparent);
46415
+ }`,
46416
+ `${sel.tile}:has(> .form-checkbox[aria-invalid="true"]) {
46417
+ border-color: ${input.errorColor};
46418
+ }`
46419
+ ];
46420
+ }
46421
+ function checkableMediaCss(sel) {
46422
+ return [`@media (prefers-reduced-motion: reduce) {
46423
+ ${sel.checkbox}, ${sel.radio}, ${sel.checkbox}::before, ${sel.radio}::before, ${sel.tile} {
46424
+ transition: none;
46425
+ }
46426
+ }`, `@media (forced-colors: active) {
46427
+ ${sel.checkbox}::before,
46428
+ ${sel.radio}::before {
46429
+ background-color: CanvasText;
46430
+ }
46431
+ }`];
46432
+ }
46433
+ /**
46434
+ * Exposes the accent and mark colours so other choice controls (newsletter
46435
+ * topic chips) match the checkboxes without re-deriving the theme tokens.
46436
+ */
46437
+ function checkableVarsCss(input) {
46438
+ return [`${input.root} {
46439
+ --rb-check-accent: ${rgbColorValue(solidAccentToken(input.accentToken))};
46440
+ --rb-check-mark: ${checkableMarkColor(input.accentToken)};
46441
+ }`];
46442
+ }
46443
+ function generateCheckableCss(input) {
46444
+ const sel = checkableSelectors(input.root);
46445
+ return [
46446
+ ...checkableVarsCss(input),
46447
+ ...controlBaseCss(sel, input),
46448
+ ...controlMarkCss(sel, input.accentToken),
46449
+ ...controlStateCss(sel, input),
46450
+ ...checkRowCss(sel),
46451
+ ...agreementTileCss(sel, input),
46452
+ ...checkableMediaCss(sel)
46453
+ ].join("\n\n");
46454
+ }
46455
+ //#endregion
46456
+ //#region ../theme-core/src/inputs/inputGroup.ts
46457
+ /**
46458
+ * Input group: a field and an action (usually a themed button) sharing one
46459
+ * input-styled shell, e.g. the newsletter email + Sign up row.
46460
+ *
46461
+ * The shell `.form-input-group` takes the theme's `.form-input` rules (the
46462
+ * generators add it to that selector list, plus focus and error), so it
46463
+ * follows the site's input background, border, corners and shadow. This file
46464
+ * only adds the layout overrides and the borderless inner field.
46465
+ */
46466
+ const INPUT_GROUP_SELECTOR = ".form-input-group";
46467
+ /** Shell focus ring follows the field only, not the button beside it. */
46468
+ const INPUT_GROUP_FOCUS_SELECTOR = ".form-input-group:has(> .form-input-group-field:focus-visible)";
46469
+ const INPUT_GROUP_ERROR_SELECTOR = ".form-input-group:has(> .form-input-group-field[aria-invalid=\"true\"])";
46470
+ const GROUP_INSET = "0.25rem";
46471
+ /**
46472
+ * @param root - scoped root selector
46473
+ * @param padding - the theme's input padding shorthand (`block inline`), so the
46474
+ * inner field's text sits where a plain input's text would.
46475
+ */
46476
+ function generateInputGroupCss(root, padding) {
46477
+ const [block = padding, inline = block] = padding.trim().split(/\s+/);
46478
+ return `${root} .form-input-group {
46479
+ display: flex;
46480
+ align-items: stretch;
46481
+ gap: ${GROUP_INSET};
46482
+ padding: ${GROUP_INSET};
46483
+ }
46484
+
46485
+ ${root} .form-input-group-field {
46486
+ flex: 1 1 auto;
46487
+ min-width: 0;
46488
+ margin: 0;
46489
+ border: 0;
46490
+ border-radius: 0;
46491
+ background: transparent;
46492
+ box-shadow: none;
46493
+ outline: none;
46494
+ color: inherit;
46495
+ font: inherit;
46496
+ padding: calc(${block} - ${GROUP_INSET}) calc(${inline} - ${GROUP_INSET});
46497
+ }
46498
+
46499
+ ${root} .form-input-group-field::placeholder {
46500
+ color: inherit;
46501
+ opacity: 0.6;
46502
+ }
46503
+
46504
+ ${root} .form-input-group > :not(.form-input-group-field) {
46505
+ flex-shrink: 0;
46506
+ }`;
46507
+ }
46508
+ //#endregion
46011
46509
  //#region ../theme-core/src/inputs/generateInputCss.ts
46012
46510
  /**
46013
46511
  * Corner radius map (reused from other systems)
@@ -46018,6 +46516,9 @@ const CORNER_MAP$1 = {
46018
46516
  rounded: "1rem",
46019
46517
  pill: "9999px"
46020
46518
  };
46519
+ function inputBackgroundValue(background) {
46520
+ return background.type === "transparent" ? "transparent" : rgbColorValue(background.colorToken);
46521
+ }
46021
46522
  /**
46022
46523
  * Generate CSS for form input styling based on theme configuration
46023
46524
  *
@@ -46035,8 +46536,7 @@ const CORNER_MAP$1 = {
46035
46536
  function generateInputCss({ themeId, theme, inputSystem }) {
46036
46537
  const rootSelector = `:where([data-theme-scope="${themeId}"])`;
46037
46538
  const baseInputRules = [];
46038
- if (inputSystem.base.background.type === "transparent") baseInputRules.push("background-color: transparent");
46039
- else baseInputRules.push(`background-color: ${rgbColorValue(inputSystem.base.background.colorToken)}`);
46539
+ baseInputRules.push(`background-color: ${inputBackgroundValue(inputSystem.base.background)}`);
46040
46540
  baseInputRules.push(`color: ${rgbColorValue(inputSystem.base.textColorToken)}`);
46041
46541
  const borderPx = parseBorderWidth(inputSystem.base.border.widthClass);
46042
46542
  const borderStyle = inputSystem.base.border.style ?? "all";
@@ -46092,7 +46592,8 @@ function generateInputCss({ themeId, theme, inputSystem }) {
46092
46592
  const focusSelectors = [
46093
46593
  `${inputSelector}:focus-visible`,
46094
46594
  `${textareaSelector}:focus-visible`,
46095
- `${selectSelector}:focus-visible`
46595
+ `${selectSelector}:focus-visible`,
46596
+ `${rootSelector} ${INPUT_GROUP_FOCUS_SELECTOR}`
46096
46597
  ];
46097
46598
  const focusRules = [];
46098
46599
  focusRules.push("outline: none");
@@ -46101,7 +46602,8 @@ function generateInputCss({ themeId, theme, inputSystem }) {
46101
46602
  const errorSelectors = [
46102
46603
  `${inputSelector}[aria-invalid="true"]`,
46103
46604
  `${textareaSelector}[aria-invalid="true"]`,
46104
- `${selectSelector}[aria-invalid="true"]`
46605
+ `${selectSelector}[aria-invalid="true"]`,
46606
+ `${rootSelector} ${INPUT_GROUP_ERROR_SELECTOR}`
46105
46607
  ];
46106
46608
  const errorRules = [];
46107
46609
  errorRules.push(`border-color: ${rgbColorValue(inputSystem.error.borderColorToken)}`);
@@ -46116,53 +46618,25 @@ function generateInputCss({ themeId, theme, inputSystem }) {
46116
46618
  disabledRules.push(`color: ${rgbColorValue(inputSystem.disabled.textColorToken)}`);
46117
46619
  disabledRules.push(`opacity: ${inputSystem.disabled.opacity}`);
46118
46620
  disabledRules.push("cursor: not-allowed");
46119
- const checkboxSelector = `${rootSelector} .form-checkbox`;
46120
- const radioSelector = `${rootSelector} .form-radio`;
46121
- const checkableRules = [];
46122
- checkableRules.push("appearance: none");
46123
- checkableRules.push("width: 1.125rem");
46124
- checkableRules.push("height: 1.125rem");
46125
- checkableRules.push("flex-shrink: 0");
46126
- checkableRules.push(`border: ${borderPx} solid ${rgbColorValue(inputSystem.base.border.colorToken)}`);
46127
- if (inputSystem.base.background.type === "transparent") checkableRules.push("background-color: transparent");
46128
- else checkableRules.push(`background-color: ${rgbColorValue(inputSystem.base.background.colorToken)}`);
46129
- checkableRules.push("cursor: pointer");
46130
- checkableRules.push("transition: background-color 0.2s ease, border-color 0.2s ease");
46131
- const checkboxSpecificRules = [...checkableRules];
46132
- checkboxSpecificRules.push(`border-radius: ${CORNER_MAP$1.soft}`);
46133
- const radioSpecificRules = [...checkableRules];
46134
- radioSpecificRules.push("border-radius: 9999px");
46135
- const checkboxCheckedSelector = `${checkboxSelector}:checked`;
46136
- const checkboxCheckedRules = [];
46137
- checkboxCheckedRules.push(`background-color: ${rgbColorValue(inputSystem.focus.ringColorToken)}`);
46138
- checkboxCheckedRules.push(`border-color: ${rgbColorValue(inputSystem.focus.ringColorToken)}`);
46139
- 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\")");
46140
- checkboxCheckedRules.push("background-size: 100% 100%");
46141
- checkboxCheckedRules.push("background-position: center");
46142
- checkboxCheckedRules.push("background-repeat: no-repeat");
46143
- const radioCheckedSelector = `${radioSelector}:checked`;
46144
- const radioCheckedRules = [];
46145
- radioCheckedRules.push(`background-color: ${rgbColorValue(inputSystem.focus.ringColorToken)}`);
46146
- radioCheckedRules.push(`border-color: ${rgbColorValue(inputSystem.focus.ringColorToken)}`);
46147
- radioCheckedRules.push("background-image: radial-gradient(circle, white 40%, transparent 40%)");
46148
- const checkboxFocusSelector = `${checkboxSelector}:focus-visible`;
46149
- const radioFocusSelector = `${radioSelector}:focus-visible`;
46150
- const checkableFocusRules = [];
46151
- checkableFocusRules.push("outline: none");
46152
- checkableFocusRules.push(`box-shadow: 0 0 0 ${inputSystem.focus.ringWidth}px ${rgbColorValue(inputSystem.focus.ringColorToken)}`);
46621
+ const checkableCss = generateCheckableCss({
46622
+ root: rootSelector,
46623
+ borderWidth: borderPx,
46624
+ borderColor: rgbColorValue(inputSystem.base.border.colorToken),
46625
+ background: inputBackgroundValue(inputSystem.base.background),
46626
+ corners: inputSystem.base.corners ?? theme.corners,
46627
+ accentToken: inputSystem.focus.borderColorToken ?? inputSystem.focus.ringColorToken,
46628
+ errorColor: rgbColorValue(inputSystem.error.borderColorToken)
46629
+ });
46153
46630
  const cssBlocks = [];
46154
46631
  cssBlocks.push(`${labelSelector} {\n ${labelRules.join(";\n ")};\n}`);
46155
- cssBlocks.push(`${inputSelector} {\n ${inputRules.join(";\n ")};\n}`);
46632
+ cssBlocks.push(`${inputSelector},\n${rootSelector} ${INPUT_GROUP_SELECTOR} {\n ${inputRules.join(";\n ")};\n}`);
46156
46633
  cssBlocks.push(`${textareaSelector} {\n ${textareaRules.join(";\n ")};\n}`);
46157
46634
  cssBlocks.push(`${selectSelector} {\n ${selectRules.join(";\n ")};\n}`);
46158
46635
  cssBlocks.push(`${focusSelectors.join(",\n")} {\n ${focusRules.join(";\n ")};\n}`);
46159
46636
  cssBlocks.push(`${errorSelectors.join(",\n")} {\n ${errorRules.join(";\n ")};\n}`);
46160
46637
  cssBlocks.push(`${disabledSelectors.join(",\n")} {\n ${disabledRules.join(";\n ")};\n}`);
46161
- cssBlocks.push(`${checkboxSelector} {\n ${checkboxSpecificRules.join(";\n ")};\n}`);
46162
- cssBlocks.push(`${radioSelector} {\n ${radioSpecificRules.join(";\n ")};\n}`);
46163
- cssBlocks.push(`${checkboxCheckedSelector} {\n ${checkboxCheckedRules.join(";\n ")};\n}`);
46164
- cssBlocks.push(`${radioCheckedSelector} {\n ${radioCheckedRules.join(";\n ")};\n}`);
46165
- cssBlocks.push(`${checkboxFocusSelector},\n${radioFocusSelector} {\n ${checkableFocusRules.join(";\n ")};\n}`);
46638
+ cssBlocks.push(generateInputGroupCss(rootSelector, padding));
46639
+ cssBlocks.push(checkableCss);
46166
46640
  return cssBlocks.join("\n\n");
46167
46641
  }
46168
46642
  //#endregion
@@ -52604,13 +53078,13 @@ const hours = stack({
52604
53078
  as: "p",
52605
53079
  className: "rb-caption rb-opacity-70"
52606
53080
  }, bind("module.timeZone"), when("module.timeZone"))], when("module.kind", { equals: "opening-hours" }));
52607
- const socials = inline({ className: "rb-flex rb-flex-wrap rb-gap-x-5 rb-gap-y-3" }, [link({
53081
+ const socials = inline({ className: "rb-footer-socials" }, [link({
52608
53082
  href: { $bind: { from: "social.href" } },
52609
53083
  target: "_blank",
52610
53084
  rel: "noreferrer noopener",
52611
53085
  "aria-label": { $bind: { from: "social.label" } },
52612
- className: "rb-nav-text transition-theme-standard"
52613
- }, [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" }));
53086
+ className: "rb-footer-social-link rb-nav-text transition-theme-standard"
53087
+ }, [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" }));
52614
53088
  const authoredCopy = richText({
52615
53089
  className: "rb-prose rb-prose-sm rb-max-w-none",
52616
53090
  style: textColorStyle("text/80")
@@ -58811,43 +59285,53 @@ function collectNestedPreviewFieldConstraintEntries(field, path) {
58811
59285
  default: return assertNever$21(field);
58812
59286
  }
58813
59287
  }
59288
+ function prepareDefaultBlockRender(manifest, props) {
59289
+ if (!props.theme) throw new Error("Block rendering requires theme tokens; none were provided to makeDefaultBlockComponent");
59290
+ if (!props.registry) throw new Error("Block rendering requires a component registry; none was provided");
59291
+ const content = props.content;
59292
+ const layout = resolveBlockLayout(manifest, content);
59293
+ if (!layout) throw new Error(`Block manifest "${manifest.name}" requires a layout definition`);
59294
+ const mergedContent = mergeContentWithBlockStyleOverrides(content, props.themeConfig, props.blockKind ?? manifest.name);
59295
+ return {
59296
+ registry: props.registry,
59297
+ layout,
59298
+ mergedContent,
59299
+ fieldConstraints: buildPreviewFieldConstraints(manifest),
59300
+ viewModel: buildBlockViewModel({
59301
+ mergedContent,
59302
+ data: props.data,
59303
+ resolvedThemeConfig: resolveThemeConfigForBindings(props.themeConfig),
59304
+ viewModelOverrides: props.viewModelOverrides
59305
+ }),
59306
+ themeForTransforms: withButtonSystem(props.theme, props.themeConfig)
59307
+ };
59308
+ }
58814
59309
  function makeDefaultBlockComponent(args) {
58815
- const { manifest } = args;
58816
- return function DefaultBlockComponent({ content, data, registry, theme, themeConfig, transforms, viewModelOverrides, pathBase, blockId, contentVersionId, blockKind, blockBindings, editableRouteMetadataFieldIds, fragmentRegistry, imageResolveContext, previewAuthoring }) {
59310
+ return function DefaultBlockComponent(props) {
58817
59311
  const perf = beginBlockRenderMeasurement();
58818
- if (!theme) throw new Error("Block rendering requires theme tokens; none were provided to makeDefaultBlockComponent");
58819
- if (!registry) throw new Error("Block rendering requires a component registry; none was provided");
58820
- const layout = resolveBlockLayout(manifest, content);
58821
- if (!layout) throw new Error(`Block manifest "${manifest.name}" requires a layout definition`);
58822
- const fieldConstraints = buildPreviewFieldConstraints(manifest);
58823
- const mergedContent = mergeContentWithBlockStyleOverrides(content, themeConfig, blockKind ?? manifest.name);
58824
- const result = resolveTree(layout, {
58825
- registry,
58826
- viewModel: buildBlockViewModel({
58827
- mergedContent,
58828
- data,
58829
- resolvedThemeConfig: resolveThemeConfigForBindings(themeConfig),
58830
- viewModelOverrides
58831
- }),
58832
- transforms,
58833
- theme: withButtonSystem(theme, themeConfig),
58834
- pathBase,
58835
- blockId,
58836
- contentVersionId,
58837
- blockKind,
58838
- blockContent: mergedContent,
58839
- blockBindings,
58840
- editableRouteMetadataFieldIds,
58841
- fragmentRegistry,
58842
- fieldConstraints,
58843
- imageResolveContext,
58844
- previewAuthoring
59312
+ const prepared = prepareDefaultBlockRender(args.manifest, props);
59313
+ const result = resolveTree(prepared.layout, {
59314
+ registry: prepared.registry,
59315
+ viewModel: prepared.viewModel,
59316
+ transforms: props.transforms,
59317
+ theme: prepared.themeForTransforms,
59318
+ pathBase: props.pathBase,
59319
+ blockId: props.blockId,
59320
+ newsletterBlockSubmission: props.newsletterBlockSubmission,
59321
+ blockKind: props.blockKind,
59322
+ blockContent: prepared.mergedContent,
59323
+ blockBindings: props.blockBindings,
59324
+ editableRouteMetadataFieldIds: props.editableRouteMetadataFieldIds,
59325
+ fragmentRegistry: props.fragmentRegistry,
59326
+ fieldConstraints: prepared.fieldConstraints,
59327
+ imageResolveContext: props.imageResolveContext,
59328
+ previewAuthoring: props.previewAuthoring
58845
59329
  });
58846
59330
  reportSlowBlockRender(perf, {
58847
- content,
58848
- blockId,
58849
- blockKind: blockKind ?? manifest.name,
58850
- manifestName: manifest.name
59331
+ content: props.content,
59332
+ blockId: props.blockId,
59333
+ blockKind: props.blockKind ?? args.manifest.name,
59334
+ manifestName: args.manifest.name
58851
59335
  });
58852
59336
  return result;
58853
59337
  };
@@ -59449,6 +59933,39 @@ function resolveBlockData$1(blockId, dataLoaders, dataContext, routes) {
59449
59933
  return dataLoaders && typeof dataLoaders === "object" && Object.keys(dataLoaders).length > 0 ? {} : void 0;
59450
59934
  }
59451
59935
  //#endregion
59936
+ //#region ../blocks/src/system/runtime/nodes/newsletter-form.block-submission.ts
59937
+ /** Authorise one block source for both public and preview rendering. */
59938
+ function planNewsletterBlockSubmission(placement) {
59939
+ if (placement.stage === "published") {
59940
+ const sourceRef = buildMailingListSignupBlockSourceRef(placement.blockId, placement.selectedContentVersionId);
59941
+ return sourceRef ? {
59942
+ tag: "ready",
59943
+ sourceRef
59944
+ } : { tag: "unavailable" };
59945
+ }
59946
+ if (placement.publishedPlacement) return planNewsletterPreviewSubmission({
59947
+ blockId: placement.blockId,
59948
+ publishedContentId: placement.publishedPlacement.id,
59949
+ renderedContent: placement.renderedContent,
59950
+ publishedContent: placement.publishedPlacement.content
59951
+ });
59952
+ if (placement.stage === "preview") return { tag: "unpublished-form" };
59953
+ return { tag: "unavailable" };
59954
+ }
59955
+ /** Decide whether the visible draft can safely cite the published placement. */
59956
+ function planNewsletterPreviewSubmission(placement) {
59957
+ if (!placement.publishedContentId) return { tag: "unpublished-form" };
59958
+ if (!placement.publishedContent) return { tag: "unpublished-settings" };
59959
+ const draft = parseMailingListPlacementTargeting(placement.renderedContent.targeting ?? { mode: "default" });
59960
+ const published = parseMailingListPlacementTargeting(placement.publishedContent.targeting);
59961
+ if (!draft.ok || !published.ok || !sameMailingListPlacementTargeting(draft.value, published.value)) return { tag: "unpublished-settings" };
59962
+ const sourceRef = buildMailingListSignupBlockSourceRef(placement.blockId, placement.publishedContentId);
59963
+ return sourceRef ? {
59964
+ tag: "ready",
59965
+ sourceRef
59966
+ } : { tag: "unpublished-settings" };
59967
+ }
59968
+ //#endregion
59452
59969
  //#region ../blocks/src/pageRenderPreparation.ts
59453
59970
  /**
59454
59971
  * Stage two of the render plan.
@@ -59577,9 +60094,20 @@ function buildBlockOverrideProps(input) {
59577
60094
  imageResolveContext: input.imageResolveContext,
59578
60095
  blockId: block.id ?? null,
59579
60096
  contentVersionId: block.contentVersionId ?? null,
60097
+ ...newsletterBlockProps(block, input.content, dataContext?.previewStage),
59580
60098
  blockKind: block.kind
59581
60099
  };
59582
60100
  }
60101
+ function newsletterBlockProps(block, renderedContent, stage) {
60102
+ if (block.kind !== "block.newsletter-signup") return {};
60103
+ return { newsletterBlockSubmission: planNewsletterBlockSubmission({
60104
+ blockId: block.id,
60105
+ selectedContentVersionId: block.contentVersionId ?? null,
60106
+ publishedPlacement: block.publishedPlacement ?? null,
60107
+ renderedContent,
60108
+ stage
60109
+ }) };
60110
+ }
59583
60111
  /** Site, transport and session context a block needs to call back to the API. */
59584
60112
  function blockSessionProps(dataContext) {
59585
60113
  return {
@@ -59669,6 +60197,15 @@ function createBlockErrorBoundary() {
59669
60197
  const BlockErrorBoundary = createBlockErrorBoundary();
59670
60198
  //#endregion
59671
60199
  //#region ../blocks/src/pageRenderAdmission.ts
60200
+ /** Pair a published version with the content it authorises at the render boundary. */
60201
+ function readPublishedBlockPlacement(id, content) {
60202
+ if (id == null && content == null) return null;
60203
+ if (id == null || content == null) throw new Error("Published block placement requires both an ID and content");
60204
+ return {
60205
+ id,
60206
+ content
60207
+ };
60208
+ }
59672
60209
  function toPresentationPage(page) {
59673
60210
  if (!page) return null;
59674
60211
  return {
@@ -59679,6 +60216,8 @@ function toPresentationPage(page) {
59679
60216
  kind: block.kind,
59680
60217
  purpose: block.purpose,
59681
60218
  ...block.contentVersionId ? { contentVersionId: block.contentVersionId } : {},
60219
+ ...block.draftContentId !== void 0 ? { draftContentId: block.draftContentId } : {},
60220
+ ...block.publishedPlacement !== void 0 ? { publishedPlacement: block.publishedPlacement } : {},
59682
60221
  ...block.bindings ? { bindings: block.bindings } : {}
59683
60222
  };
59684
60223
  return block.admission.kind === "renderable" ? {
@@ -60424,6 +60963,9 @@ const containerResponsiveThemeCss = `/*
60424
60963
  .rb-h-4 {
60425
60964
  height: 1rem;
60426
60965
  }
60966
+ .rb-h-5 {
60967
+ height: 1.25rem;
60968
+ }
60427
60969
  .rb-h-8 {
60428
60970
  height: 2rem;
60429
60971
  }
@@ -64389,6 +64931,10 @@ const containerResponsiveThemeCss = `/*
64389
64931
  margin-bottom: 0.25rem;
64390
64932
  }
64391
64933
 
64934
+ :where(.theme-scope) :where([data-block='event-registration']) .er-consent-check {
64935
+ margin-top: 0.75rem;
64936
+ }
64937
+
64392
64938
  :where(.theme-scope) :where([data-block='event-registration']) .er-required {
64393
64939
  color: var(--er-required);
64394
64940
  }
@@ -69108,13 +69654,6 @@ const containerResponsiveThemeCss = `/*
69108
69654
  margin: 0;
69109
69655
  }
69110
69656
 
69111
- /* Inline field (checkbox, radio with label) */
69112
- :where(.theme-scope) :where([data-block="form"]) .fb-inline {
69113
- display: flex;
69114
- align-items: center;
69115
- gap: 0.5rem;
69116
- }
69117
-
69118
69657
  /* Success state */
69119
69658
  :where(.theme-scope) :where([data-block="form"]) .fb-success {
69120
69659
  background-color: var(--fb-success-bg);
@@ -71231,9 +71770,11 @@ const containerResponsiveThemeCss = `/*
71231
71770
  */
71232
71771
 
71233
71772
  /* Newsletter copy styling */
71773
+ /* Size only: weight, family and colour come from the theme's heading styles */
71234
71774
  :where(.theme-scope) :where([data-block="newsletter-signup"]) .newsletter-copy-title {
71235
- font-size: 1.5rem;
71236
- font-weight: 600;
71775
+ font-size: clamp(1.75rem, 1.35rem + 1.6vw, 2.5rem);
71776
+ line-height: 1.15;
71777
+ text-wrap: balance;
71237
71778
  }
71238
71779
 
71239
71780
  :where(.theme-scope) :where([data-block="newsletter-signup"]) .newsletter-copy-subtitle {
@@ -71257,37 +71798,150 @@ const containerResponsiveThemeCss = `/*
71257
71798
  gap: var(--rb-gap-sm, 0.75rem);
71258
71799
  }
71259
71800
 
71260
- /* Individual field styling */
71801
+ /* Extra preset fields (name, company...). Labels are visually hidden, so
71802
+ these sit in a row above the email entry. */
71803
+ :where(.theme-scope) .newsletter-extra-fields {
71804
+ display: grid;
71805
+ grid-template-columns: repeat(auto-fit, minmax(min(12rem, 100%), 1fr));
71806
+ gap: 0.5rem;
71807
+ }
71808
+
71261
71809
  :where(.theme-scope) .newsletter-field {
71262
71810
  display: flex;
71263
71811
  flex-direction: column;
71264
71812
  gap: 0.25rem;
71813
+ text-align: left;
71265
71814
  }
71266
71815
 
71267
- /* Topic choices (visitor picks what to hear about). Same treatment as the
71268
- form block's .fb-fieldset / .fb-inline, defined here because the newsletter
71269
- form also renders inside contact-newsletter and the site footer. */
71270
- :where(.theme-scope) .newsletter-topics {
71816
+ /* Email entry: the email field and the themed submit button share one shell.
71817
+ The shell's look (background, border, corners, focus ring) comes from the
71818
+ theme's input system via .form-input-group; this only handles layout. */
71819
+ :where(.theme-scope) .newsletter-entry {
71820
+ container-type: inline-size;
71271
71821
  display: flex;
71272
71822
  flex-direction: column;
71273
- gap: 0.5rem;
71823
+ gap: 0.375rem;
71824
+ text-align: left;
71825
+ }
71826
+
71827
+ :where(.theme-scope) .newsletter-entry-group > button {
71828
+ white-space: nowrap;
71829
+ }
71830
+
71831
+ /* Too narrow for field and button side by side (phones, footer columns):
71832
+ stack them inside the shell and keep pill themes from turning the taller
71833
+ shell into a capsule. */
71834
+ @container (max-width: 22rem) {
71835
+ :where(.theme-scope) .newsletter-entry .newsletter-entry-group {
71836
+ flex-direction: column;
71837
+ border-radius: min(var(--rb-input-radius, 0.5rem), 1rem);
71838
+ }
71839
+
71840
+ :where(.theme-scope) .newsletter-entry .newsletter-entry-group > button {
71841
+ width: 100%;
71842
+ justify-content: center;
71843
+ }
71844
+ }
71845
+
71846
+ /* Topic choices (visitor picks what to hear about) as toggle chips. Each chip
71847
+ is a real checkbox underneath; the chip is its visible face. */
71848
+ :where(.theme-scope) .newsletter-topics {
71274
71849
  border: none;
71275
71850
  padding: 0;
71276
71851
  margin: 0;
71277
71852
  min-width: 0;
71278
71853
  }
71279
71854
 
71280
- :where(.theme-scope) .newsletter-topics > legend {
71855
+ :where(.theme-scope) .newsletter-topics-legend {
71281
71856
  padding: 0;
71282
- margin-bottom: 0.25rem;
71857
+ margin-bottom: 0.625rem;
71858
+ font-size: 0.9375rem;
71859
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
71283
71860
  }
71284
71861
 
71285
- :where(.theme-scope) .newsletter-topic-choice {
71862
+ :where(.theme-scope) .newsletter-topic-chips {
71286
71863
  display: flex;
71287
- align-items: center;
71864
+ flex-wrap: wrap;
71288
71865
  gap: 0.5rem;
71289
71866
  }
71290
71867
 
71868
+ :where(.theme-scope) .newsletter-stacked .newsletter-topics-legend {
71869
+ width: 100%;
71870
+ }
71871
+
71872
+ :where(.theme-scope) .newsletter-stacked .newsletter-topic-chips {
71873
+ justify-content: center;
71874
+ }
71875
+
71876
+ :where(.theme-scope) .newsletter-topic-chip {
71877
+ position: relative;
71878
+ display: inline-flex;
71879
+ }
71880
+
71881
+ :where(.theme-scope) .newsletter-topic-chip > input {
71882
+ position: absolute;
71883
+ inset: 0;
71884
+ width: 100%;
71885
+ height: 100%;
71886
+ margin: 0;
71887
+ opacity: 0;
71888
+ cursor: pointer;
71889
+ }
71890
+
71891
+ :where(.theme-scope) .newsletter-topic-chip > span {
71892
+ display: inline-flex;
71893
+ align-items: center;
71894
+ gap: 0.375rem;
71895
+ padding: 0.4375rem 0.9375rem;
71896
+ border: 1px solid color-mix(in srgb, currentColor 35%, transparent);
71897
+ border-radius: var(--rb-button-radius, var(--rb-input-radius, 9999px));
71898
+ font-size: 0.9375rem;
71899
+ line-height: 1.3;
71900
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
71901
+ transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
71902
+ }
71903
+
71904
+ /* Tick that grows in when the chip is on */
71905
+ :where(.theme-scope) .newsletter-topic-chip > span::before {
71906
+ content: "";
71907
+ width: 0;
71908
+ height: 0.7em;
71909
+ background-color: currentColor;
71910
+ clip-path: polygon(14% 52%, 0 67%, 38% 100%, 100% 22%, 85% 8%, 37% 70%);
71911
+ transition: width 0.15s ease;
71912
+ }
71913
+
71914
+ :where(.theme-scope) .newsletter-topic-chip:hover > span {
71915
+ border-color: currentColor;
71916
+ }
71917
+
71918
+ /* Same accent and mark colours as the theme's checkboxes */
71919
+ :where(.theme-scope) .newsletter-topic-chip > input:checked + span {
71920
+ background-color: var(--rb-check-accent, rgb(var(--tb-primary)));
71921
+ border-color: var(--rb-check-accent, rgb(var(--tb-primary)));
71922
+ color: var(--rb-check-mark, rgb(var(--tb-onPrimary, 255 255 255)));
71923
+ }
71924
+
71925
+ :where(.theme-scope) .newsletter-topic-chip > input:checked + span::before {
71926
+ width: 0.7em;
71927
+ }
71928
+
71929
+ :where(.theme-scope) .newsletter-topic-chip > input:focus-visible + span {
71930
+ outline: 2px solid var(--rb-check-accent, rgb(var(--tb-primary)));
71931
+ outline-offset: 2px;
71932
+ }
71933
+
71934
+ :where(.theme-scope) .newsletter-topic-chip > input:disabled + span {
71935
+ opacity: 0.6;
71936
+ }
71937
+
71938
+ @media (prefers-reduced-motion: reduce) {
71939
+ :where(.theme-scope) .newsletter-topic-chip > span,
71940
+ :where(.theme-scope) .newsletter-topic-chip > span::before {
71941
+ transition: none;
71942
+ }
71943
+ }
71944
+
71291
71945
  /* Error panel and field notes. The form block scopes these to its own
71292
71946
  data-block, so the newsletter form (which also renders in the footer)
71293
71947
  needs its own copy of the treatment. */
@@ -71305,13 +71959,7 @@ const containerResponsiveThemeCss = `/*
71305
71959
  color: var(--fb-error-text);
71306
71960
  }
71307
71961
 
71308
- /* Required indicator */
71309
- :where(.theme-scope) .newsletter-required {
71310
- color: rgb(var(--tb-primary));
71311
- margin-left: 0.125rem;
71312
- }
71313
-
71314
- /* Submit button container */
71962
+ /* Submit button container (only when a preset has no email field) */
71315
71963
  :where(.theme-scope) .newsletter-submit {
71316
71964
  margin-top: 0.5rem;
71317
71965
  }
@@ -71323,52 +71971,29 @@ const containerResponsiveThemeCss = `/*
71323
71971
  justify-content: center;
71324
71972
  }
71325
71973
 
71326
- /* Privacy note */
71974
+ /* Privacy note: quieter than the intro so the entry row leads */
71327
71975
  :where(.theme-scope) .newsletter-privacy-note {
71328
71976
  margin-top: 0.75rem;
71329
- font-size: 1rem;
71330
- line-height: 1.6;
71331
- color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
71977
+ font-size: 0.8125rem;
71978
+ line-height: 1.5;
71979
+ color: var(--rb-surface-supporting-color, var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39))));
71980
+ opacity: 0.85;
71332
71981
  text-align: center;
71333
71982
  }
71334
71983
 
71335
71984
  /* =============================================================================
71336
- * Inline Variant - Horizontal layout
71985
+ * Inline Variant - left-aligned, wider entry row
71337
71986
  * =============================================================================
71338
71987
  */
71339
71988
 
71340
- :where(.theme-scope) .newsletter-inline .newsletter-form-fields {
71341
- flex-direction: row;
71342
- align-items: flex-end;
71343
- flex-wrap: wrap;
71344
- gap: var(--rb-gap-sm, 0.75rem);
71345
- }
71346
-
71347
- :where(.theme-scope) .newsletter-inline .newsletter-field {
71348
- flex: 1 1 auto;
71349
- min-width: 10rem;
71350
- }
71351
-
71352
- :where(.theme-scope) .newsletter-inline .newsletter-submit {
71353
- margin-top: 0;
71354
- flex-shrink: 0;
71355
- }
71356
-
71357
- :where(.theme-scope) .newsletter-inline .newsletter-topics {
71358
- flex-basis: 100%;
71989
+ :where(.theme-scope) .newsletter-inline .newsletter-form {
71990
+ max-width: 40rem;
71991
+ margin-left: 0;
71992
+ margin-right: 0;
71359
71993
  }
71360
71994
 
71361
- /* Mobile fallback for inline variant */
71362
- @container rb-site (max-width: 640px) {
71363
- @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
71364
- :where(.theme-scope) .newsletter-inline .newsletter-form-fields {
71365
- flex-direction: column;
71366
- }
71367
-
71368
- :where(.theme-scope) .newsletter-inline .newsletter-field {
71369
- min-width: 100%;
71370
- }
71371
- }
71995
+ :where(.theme-scope) .newsletter-inline .newsletter-privacy-note {
71996
+ text-align: left;
71372
71997
  }
71373
71998
 
71374
71999
  /* =============================================================================
@@ -71506,12 +72131,6 @@ const containerResponsiveThemeCss = `/*
71506
72131
  margin: 0;
71507
72132
  }
71508
72133
 
71509
- :where(.theme-scope) :where([data-block="contact-newsletter"]) .fb-inline {
71510
- display: flex;
71511
- align-items: center;
71512
- gap: 0.5rem;
71513
- }
71514
-
71515
72134
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .fb-success,
71516
72135
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .fb-error,
71517
72136
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .fb-empty {
@@ -73408,6 +74027,44 @@ const containerResponsiveThemeCss = `/*
73408
74027
  flex: 0 0 auto;
73409
74028
  }
73410
74029
  }
74030
+ }
74031
+
74032
+ /* =============================================================================
74033
+ * Site footer: social links
74034
+ *
74035
+ * Icon links get a 40px tap target with a hairline ring drawn from the link's
74036
+ * own colour, so it follows the footer's text colour on any surface. Links
74037
+ * without an icon (unknown platforms) stay plain text.
74038
+ * =============================================================================
74039
+ */
74040
+
74041
+ :where(.theme-scope) .rb-footer-socials {
74042
+ display: flex;
74043
+ flex-wrap: wrap;
74044
+ align-items: center;
74045
+ gap: 0.75rem 1.25rem;
74046
+ }
74047
+
74048
+ :where(.theme-scope) .rb-footer-social-link:has(> .rb-footer-social-icon) {
74049
+ display: inline-grid;
74050
+ place-items: center;
74051
+ width: 2.5rem;
74052
+ height: 2.5rem;
74053
+ border: 1px solid color-mix(in srgb, currentColor 22%, transparent);
74054
+ border-radius: 9999px;
74055
+ }
74056
+
74057
+ :where(.theme-scope) .rb-footer-socials:has(.rb-footer-social-icon) {
74058
+ gap: 0.5rem;
74059
+ }
74060
+
74061
+ :where(.theme-scope) .rb-footer-social-link:has(> .rb-footer-social-icon):hover {
74062
+ border-color: currentColor;
74063
+ }
74064
+
74065
+ :where(.theme-scope) .rb-footer-social-icon {
74066
+ width: 1.5rem;
74067
+ height: 1.5rem;
73411
74068
  }`;
73412
74069
  //#endregion
73413
74070
  //#region ../theme-core/src/ThemeScopeCore.tsx
@@ -73714,7 +74371,7 @@ function toBlocksCommonProps(props) {
73714
74371
  return {
73715
74372
  page: props.page,
73716
74373
  runtimeJoins: props.runtimeJoins,
73717
- dataContext: props.dataContext ? toBlocksPageRendererDataContext(props.dataContext) : void 0,
74374
+ dataContext: toBlocksPageRendererDataContext(props.dataContext),
73718
74375
  routeMap: props.routeMap,
73719
74376
  wrapBlock: props.wrapBlock,
73720
74377
  registry: props.registry,
@@ -73825,14 +74482,14 @@ function resolveSdkBookingTimeZone(timeZone) {
73825
74482
  }
73826
74483
  function buildPageRouteRenderContext(dataContext) {
73827
74484
  return {
73828
- pathname: dataContext?.pathname,
73829
- occurrenceContext: dataContext?.occurrenceContext ?? null,
73830
- entrySubrouteContext: dataContext?.entrySubrouteContext ?? null,
73831
- contentEntry: dataContext?.contentEntry ?? null,
73832
- pageSurface: dataContext?.pageSurface ?? null,
73833
- subject: dataContext?.subject ?? null,
73834
- editableRouteMetadataFieldIds: dataContext?.editableRouteMetadataFieldIds ?? null,
73835
- previewStage: dataContext?.previewStage
74485
+ pathname: dataContext.pathname,
74486
+ occurrenceContext: dataContext.occurrenceContext ?? null,
74487
+ entrySubrouteContext: dataContext.entrySubrouteContext ?? null,
74488
+ contentEntry: dataContext.contentEntry ?? null,
74489
+ pageSurface: dataContext.pageSurface ?? null,
74490
+ subject: dataContext.subject ?? null,
74491
+ editableRouteMetadataFieldIds: dataContext.editableRouteMetadataFieldIds ?? null,
74492
+ previewStage: dataContext.previewStage
73836
74493
  };
73837
74494
  }
73838
74495
  function PageContent(props) {
@@ -73846,10 +74503,10 @@ function PageContent(props) {
73846
74503
  apiBaseUrl,
73847
74504
  portalToken,
73848
74505
  previewToken,
73849
- readAuthority: readAuthority ?? dataContext?.readAuthority,
74506
+ readAuthority: readAuthority ?? dataContext.readAuthority,
73850
74507
  resolvedData,
73851
74508
  bookingOfferingPresets: bookingOfferingPresets ?? [],
73852
- mailingList: mailingList ?? dataContext?.mailingList,
74509
+ mailingList: mailingList ?? dataContext.mailingList,
73853
74510
  bookingTimeZone: resolveSdkBookingTimeZone(bookingTimeZone),
73854
74511
  routes: routeMap,
73855
74512
  pagesByIdentifier,
@@ -75995,21 +76652,39 @@ function buildSiteRenderSupport(site, mediaAssets) {
75995
76652
  function collectMediaAssetSidecar(mediaAssets) {
75996
76653
  return Array.isArray(mediaAssets) && mediaAssets.length > 0 ? mediaAssets : void 0;
75997
76654
  }
75998
- function convertPageResponseBlock(block) {
76655
+ function readBlockContentId(value, name) {
76656
+ if (value === null || value === void 0) return null;
76657
+ if (typeof value === "string") return value;
76658
+ throw new Error(`Invalid ${name} in page: expected string or null`);
76659
+ }
76660
+ function readTransportedBlockIdentity(block, kind, stage) {
76661
+ return {
76662
+ draftContentId: readBlockContentId(block.draftContentId, "draft content id"),
76663
+ publishedPlacement: stage === "preview" ? readPublishedBlockPlacement(readBlockContentId(block.publishedContentId, "published content id"), sanitizeNullableSdkRuntimeBlockContent(kind, readNestedContentRecord(block.publishedContent))) : null
76664
+ };
76665
+ }
76666
+ function convertPageResponseBlock(block, stage) {
75999
76667
  if (!isRecord$8(block)) throw new Error("Invalid block format in page API response");
76668
+ const header = readTransportedBlockHeader(block);
76669
+ const admission = readInvalidBlockAdmission(block.admission);
76670
+ return {
76671
+ ...header,
76672
+ ...readTransportedBlockIdentity(block, header.kind, stage),
76673
+ content: sanitizeSdkRuntimeBlockContent(header.kind, readContentRecord(block.content) ?? {}),
76674
+ draftContent: sanitizeNullableSdkRuntimeBlockContent(header.kind, readNestedContentRecord(block.draftContent)),
76675
+ ...admission ? { admission } : {}
76676
+ };
76677
+ }
76678
+ function readTransportedBlockHeader(block) {
76000
76679
  if (typeof block.id !== "string" && block.id !== null) throw new Error(`Invalid block id in page: expected string or null, got ${typeof block.id}`);
76001
76680
  if (typeof block.kind !== "string") throw new Error(`Invalid block kind in page: expected string, got ${typeof block.kind}`);
76002
76681
  if (typeof block.purpose !== "string") throw new Error(`Invalid block purpose in page: expected string, got ${typeof block.purpose}`);
76003
76682
  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}`);
76004
- const admission = readInvalidBlockAdmission(block.admission);
76005
76683
  return {
76006
76684
  id: block.id,
76007
76685
  ...block.contentVersionId !== void 0 ? { contentVersionId: block.contentVersionId } : {},
76008
76686
  kind: block.kind,
76009
- purpose: block.purpose,
76010
- content: sanitizeSdkRuntimeBlockContent(block.kind, readContentRecord(block.content) ?? {}),
76011
- draftContent: sanitizeNullableSdkRuntimeBlockContent(block.kind, readNestedContentRecord(block.draftContent)),
76012
- ...admission ? { admission } : {}
76687
+ purpose: block.purpose
76013
76688
  };
76014
76689
  }
76015
76690
  function readInvalidBlockAdmission(value) {
@@ -76022,7 +76697,7 @@ function buildPageOutline(input) {
76022
76697
  name: input.name,
76023
76698
  path: input.path ?? input.fallbackPath,
76024
76699
  purpose: input.purpose,
76025
- blocks: input.blocks.map(convertPageResponseBlock)
76700
+ blocks: input.blocks.map((block) => convertPageResponseBlock(block, input.previewStage))
76026
76701
  };
76027
76702
  }
76028
76703
  function buildRenderablePageOutline(input) {
@@ -76048,6 +76723,8 @@ function projectRenderablePageOutline(page) {
76048
76723
  function admitSdkRuntimePageBlock(block, customBlocks) {
76049
76724
  const base = {
76050
76725
  id: block.id,
76726
+ draftContentId: block.draftContentId,
76727
+ publishedPlacement: block.publishedPlacement,
76051
76728
  ...block.contentVersionId !== void 0 ? { contentVersionId: block.contentVersionId } : {},
76052
76729
  kind: block.kind,
76053
76730
  purpose: block.purpose,
@@ -76118,6 +76795,7 @@ function buildFooterRenderablePageOutline(siteData, blocks) {
76118
76795
  fallbackPath: "/__footer",
76119
76796
  purpose: "footer",
76120
76797
  blocks,
76798
+ previewStage: "published",
76121
76799
  customBlocks: resolveSiteCustomBlocks(siteData)
76122
76800
  });
76123
76801
  }
@@ -77360,6 +78038,13 @@ const EVENT_SERIES_REGISTRATION_ENDPOINT_DEFINITIONS = defineEndpointDefinitions
77360
78038
  errors: [],
77361
78039
  responseKind: "blob"
77362
78040
  },
78041
+ exportEventOfferingRegistrationsCsv: {
78042
+ path: "/sites/{siteId}/bookings/event-offerings/{eventOfferingId}/registrations/export.csv",
78043
+ method: "GET",
78044
+ auth: "user",
78045
+ errors: [],
78046
+ responseKind: "blob"
78047
+ },
77363
78048
  updateEventSeriesRegistration: {
77364
78049
  path: "/sites/{siteId}/bookings/event-series/{seriesId}/registrations/{registrationId}",
77365
78050
  method: "PATCH",
@@ -77370,6 +78055,19 @@ const EVENT_SERIES_REGISTRATION_ENDPOINT_DEFINITIONS = defineEndpointDefinitions
77370
78055
  "resource:not_found",
77371
78056
  "server:internal_error"
77372
78057
  ]
78058
+ },
78059
+ saveEventSeriesRegistrationAnswers: {
78060
+ path: "/sites/{siteId}/bookings/event-series/{seriesId}/registrations/{registrationId}/answers",
78061
+ method: "PUT",
78062
+ auth: "user",
78063
+ responseKind: "json",
78064
+ errors: [
78065
+ "validation:invalid_input",
78066
+ "auth:forbidden",
78067
+ "resource:not_found",
78068
+ "resource:conflict",
78069
+ "server:internal_error"
78070
+ ]
77373
78071
  }
77374
78072
  });
77375
78073
  //#endregion
@@ -77790,6 +78488,30 @@ const NEWSLETTER_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
77790
78488
  responseKind: "json",
77791
78489
  demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
77792
78490
  },
78491
+ scheduleNewsletterCampaign: {
78492
+ path: "/sites/{siteId}/newsletter/campaigns/{campaignId}/schedule",
78493
+ method: "POST",
78494
+ tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
78495
+ auth: "user",
78496
+ responseKind: "json",
78497
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
78498
+ },
78499
+ unscheduleNewsletterCampaign: {
78500
+ path: "/sites/{siteId}/newsletter/campaigns/{campaignId}/unschedule",
78501
+ method: "POST",
78502
+ tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
78503
+ auth: "user",
78504
+ responseKind: "json",
78505
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
78506
+ },
78507
+ stopNewsletterCampaign: {
78508
+ path: "/sites/{siteId}/newsletter/campaigns/{campaignId}/stop",
78509
+ method: "POST",
78510
+ tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
78511
+ auth: "user",
78512
+ responseKind: "json",
78513
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
78514
+ },
77793
78515
  testSendNewsletterCampaign: {
77794
78516
  path: "/sites/{siteId}/newsletter/campaigns/{campaignId}/test-send",
77795
78517
  method: "POST",
@@ -77800,6 +78522,154 @@ const NEWSLETTER_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
77800
78522
  }
77801
78523
  });
77802
78524
  //#endregion
78525
+ //#region ../api/src/sdkEventEndpointDefinitions.ts
78526
+ /**
78527
+ * The SDK's Event graph: the Events themselves and the occurrences of one run.
78528
+ * Extracted from `endpoints.ts` so this family can be read, and added to, on
78529
+ * its own. New entries here must declare `errors`; the
78530
+ * require-api-endpoint-errors lint enforces that here as in endpoints.ts.
78531
+ */
78532
+ const SDK_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
78533
+ sdkListEvents: {
78534
+ path: "/sdk/{siteId}/events",
78535
+ method: "GET",
78536
+ auth: "service",
78537
+ responseKind: "json"
78538
+ },
78539
+ sdkUpsertEvent: {
78540
+ path: "/sdk/{siteId}/events",
78541
+ method: "POST",
78542
+ auth: "service",
78543
+ responseKind: "json",
78544
+ errors: [
78545
+ "validation:invalid_input",
78546
+ "resource:not_found",
78547
+ "resource:conflict",
78548
+ "billing:plan_limit_exceeded",
78549
+ "server:internal_error"
78550
+ ]
78551
+ },
78552
+ sdkGetEvent: {
78553
+ path: "/sdk/{siteId}/events/{identifier}",
78554
+ method: "GET",
78555
+ auth: "service",
78556
+ responseKind: "json"
78557
+ },
78558
+ sdkDeleteEvent: {
78559
+ path: "/sdk/{siteId}/events/{identifier}",
78560
+ method: "DELETE",
78561
+ auth: "service",
78562
+ responseKind: "json",
78563
+ errors: [
78564
+ "resource:not_found",
78565
+ "resource:conflict",
78566
+ "server:internal_error"
78567
+ ]
78568
+ },
78569
+ sdkTakeEventOffline: {
78570
+ path: "/sdk/{siteId}/events/{identifier}/lifecycle",
78571
+ method: "POST",
78572
+ auth: "service",
78573
+ responseKind: "json",
78574
+ errors: [
78575
+ "resource:not_found",
78576
+ "validation:invalid_input",
78577
+ "resource:conflict",
78578
+ "server:internal_error"
78579
+ ]
78580
+ },
78581
+ sdkListEventOccurrences: {
78582
+ path: "/sdk/{siteId}/events/{identifier}/runs/{runIdentifier}/occurrences",
78583
+ method: "GET",
78584
+ auth: "service",
78585
+ responseKind: "json",
78586
+ errors: [
78587
+ "resource:not_found",
78588
+ "validation:invalid_input",
78589
+ "server:internal_error"
78590
+ ]
78591
+ },
78592
+ sdkAddEventOccurrence: {
78593
+ path: "/sdk/{siteId}/events/{identifier}/runs/{runIdentifier}/occurrences",
78594
+ method: "POST",
78595
+ auth: "service",
78596
+ responseKind: "json",
78597
+ errors: [
78598
+ "resource:not_found",
78599
+ "validation:invalid_input",
78600
+ "resource:conflict",
78601
+ "server:internal_error"
78602
+ ]
78603
+ },
78604
+ sdkUpdateEventOccurrence: {
78605
+ path: "/sdk/{siteId}/events/{identifier}/runs/{runIdentifier}/occurrences/{occurrenceId}",
78606
+ method: "PATCH",
78607
+ auth: "service",
78608
+ responseKind: "json",
78609
+ errors: [
78610
+ "resource:not_found",
78611
+ "validation:invalid_input",
78612
+ "resource:conflict",
78613
+ "server:internal_error"
78614
+ ]
78615
+ },
78616
+ sdkCancelEventOccurrence: {
78617
+ path: "/sdk/{siteId}/events/{identifier}/runs/{runIdentifier}/occurrences/{occurrenceId}/cancel",
78618
+ method: "POST",
78619
+ auth: "service",
78620
+ responseKind: "json",
78621
+ errors: [
78622
+ "resource:not_found",
78623
+ "resource:conflict",
78624
+ "server:internal_error"
78625
+ ]
78626
+ },
78627
+ sdkDeleteEventOccurrence: {
78628
+ path: "/sdk/{siteId}/events/{identifier}/runs/{runIdentifier}/occurrences/{occurrenceId}",
78629
+ method: "DELETE",
78630
+ auth: "service",
78631
+ responseKind: "json",
78632
+ errors: [
78633
+ "resource:not_found",
78634
+ "resource:conflict",
78635
+ "server:internal_error"
78636
+ ]
78637
+ }
78638
+ });
78639
+ //#endregion
78640
+ //#region ../api/src/sdkPageDesignEndpointDefinitions.ts
78641
+ /**
78642
+ * SDK management endpoints for a page's draft design (issue 1497), spread into
78643
+ * `ENDPOINT_DEFINITIONS` like the other endpoint-definition modules. New
78644
+ * entries here must declare `errors`, which the require-api-endpoint-errors
78645
+ * lint enforces.
78646
+ */
78647
+ const SDK_PAGE_DESIGN_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
78648
+ sdkGetPageDesign: {
78649
+ path: "/sdk/{siteId}/pages/{identifier}/design",
78650
+ method: "GET",
78651
+ auth: "service",
78652
+ responseKind: "json",
78653
+ errors: [
78654
+ "resource:not_found",
78655
+ "validation:invalid_input",
78656
+ "server:internal_error"
78657
+ ]
78658
+ },
78659
+ sdkSavePageDesign: {
78660
+ path: "/sdk/{siteId}/pages/{identifier}/design",
78661
+ method: "POST",
78662
+ auth: "service",
78663
+ responseKind: "json",
78664
+ errors: [
78665
+ "resource:not_found",
78666
+ "validation:invalid_input",
78667
+ "resource:conflict",
78668
+ "server:internal_error"
78669
+ ]
78670
+ }
78671
+ });
78672
+ //#endregion
77803
78673
  //#region ../api/src/publicEventEndpointDefinitions.ts
77804
78674
  const PUBLIC_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
77805
78675
  checkPublicEventRegistrationNextStep: {
@@ -78044,6 +78914,45 @@ const SITE_API_KEY_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
78044
78914
  }
78045
78915
  });
78046
78916
  //#endregion
78917
+ //#region ../api/src/siteManagementEndpointDefinitions.ts
78918
+ const SITE_MANAGEMENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
78919
+ createSite: {
78920
+ path: "/sites/manage",
78921
+ method: "POST",
78922
+ tags: ["site"],
78923
+ auth: "user",
78924
+ responseKind: "json"
78925
+ },
78926
+ updateSite: {
78927
+ path: "/sites/manage",
78928
+ method: "PUT",
78929
+ tags: ["site"],
78930
+ auth: "user",
78931
+ responseKind: "json"
78932
+ },
78933
+ changeSiteAddress: {
78934
+ path: "/sites/{siteId}/address",
78935
+ method: "PUT",
78936
+ auth: "user",
78937
+ responseKind: "json",
78938
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED
78939
+ },
78940
+ getSiteAddressAvailability: {
78941
+ path: "/sites/{siteId}/address/availability",
78942
+ method: "GET",
78943
+ auth: "user",
78944
+ responseKind: "json"
78945
+ },
78946
+ deleteSite: {
78947
+ path: "/sites/{siteId}",
78948
+ method: "DELETE",
78949
+ tags: ["site", "site-{siteId}"],
78950
+ auth: "user",
78951
+ responseKind: "json",
78952
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
78953
+ }
78954
+ });
78955
+ //#endregion
78047
78956
  //#region ../api/src/eventManagementEndpointDefinitions.ts
78048
78957
  const EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
78049
78958
  listEvents: {
@@ -78091,6 +79000,28 @@ const EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
78091
79000
  "server:internal_error"
78092
79001
  ]
78093
79002
  },
79003
+ /**
79004
+ * The web address of an event's own page. A course page belongs to the
79005
+ * event itself, so its address is written here rather than through a run.
79006
+ */
79007
+ updateEventAddress: {
79008
+ path: "/sites/{siteId}/bookings/events/{eventId}/address",
79009
+ method: "PATCH",
79010
+ tags: [
79011
+ "site-{siteId}",
79012
+ "event-series-{siteId}",
79013
+ TAG_TEMPLATES.siteRoutableContent,
79014
+ TAG_TEMPLATES.siteRedirects
79015
+ ],
79016
+ auth: "user",
79017
+ responseKind: "json",
79018
+ errors: [
79019
+ "validation:invalid_input",
79020
+ "resource:not_found",
79021
+ "resource:conflict",
79022
+ "server:internal_error"
79023
+ ]
79024
+ },
78094
79025
  createWholeSeriesRun: {
78095
79026
  path: "/sites/{siteId}/bookings/events/{eventId}/runs",
78096
79027
  method: "POST",
@@ -78117,6 +79048,20 @@ const EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
78117
79048
  "server:internal_error"
78118
79049
  ]
78119
79050
  },
79051
+ updateCourseBookingSettings: {
79052
+ path: "/sites/{siteId}/bookings/events/{eventId}/booking-settings",
79053
+ method: "PATCH",
79054
+ tags: ["site-{siteId}", "event-series-{siteId}"],
79055
+ auth: "user",
79056
+ responseKind: "json",
79057
+ errors: [
79058
+ "validation:invalid_input",
79059
+ "auth:forbidden",
79060
+ "resource:not_found",
79061
+ "resource:conflict",
79062
+ "server:internal_error"
79063
+ ]
79064
+ },
78120
79065
  cancelWholeSeriesRun: {
78121
79066
  path: "/sites/{siteId}/bookings/events/{eventId}/runs/{runId}/cancellation",
78122
79067
  method: "POST",
@@ -78129,6 +79074,28 @@ const EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
78129
79074
  "resource:conflict",
78130
79075
  "server:internal_error"
78131
79076
  ]
79077
+ },
79078
+ /**
79079
+ * The Content tab's one write: the short introduction, image and
79080
+ * description of an event's page, published without its layout.
79081
+ */
79082
+ saveEventPageWords: {
79083
+ path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/words",
79084
+ method: "PUT",
79085
+ tags: [
79086
+ TAG_TEMPLATES.siteCollection,
79087
+ TAG_TEMPLATES.siteRoutableContent,
79088
+ TAG_TEMPLATES.pageSurfaceById
79089
+ ],
79090
+ auth: "user",
79091
+ responseKind: "json",
79092
+ errors: [
79093
+ "auth:forbidden",
79094
+ "validation:invalid_input",
79095
+ "resource:not_found",
79096
+ "resource:conflict",
79097
+ "server:internal_error"
79098
+ ]
78132
79099
  }
78133
79100
  });
78134
79101
  //#endregion
@@ -78561,19 +79528,56 @@ const BILLING_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
78561
79528
  responseKind: "json"
78562
79529
  }
78563
79530
  });
79531
+ //#endregion
79532
+ //#region ../api/src/clientErrorReporting.ts
79533
+ const CLIENT_ERROR_REPORT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({ reportClientError: {
79534
+ path: "/client/error-report",
79535
+ method: "POST",
79536
+ auth: "user",
79537
+ errors: [],
79538
+ responseKind: "json"
79539
+ } });
79540
+ const CLIENT_ERROR_REPORT_LIMITS = {
79541
+ pathname: 1024,
79542
+ name: 120,
79543
+ message: 2e3,
79544
+ stack: 8e3,
79545
+ digest: 128,
79546
+ componentStack: 8e3,
79547
+ sourceLocation: 1024
79548
+ };
79549
+ const clientErrorEventSchema = z$1.enum([
79550
+ "dashboard:route-error",
79551
+ "dashboard:app-error",
79552
+ "client:error-boundary",
79553
+ "client:window-error",
79554
+ "client:unhandled-rejection"
79555
+ ]);
79556
+ z$1.object({
79557
+ event: clientErrorEventSchema,
79558
+ pathname: z$1.string().startsWith("/").max(CLIENT_ERROR_REPORT_LIMITS.pathname),
79559
+ name: z$1.string().max(CLIENT_ERROR_REPORT_LIMITS.name),
79560
+ message: z$1.string().max(CLIENT_ERROR_REPORT_LIMITS.message),
79561
+ stack: z$1.string().max(CLIENT_ERROR_REPORT_LIMITS.stack).nullable(),
79562
+ digest: z$1.string().max(CLIENT_ERROR_REPORT_LIMITS.digest).nullable(),
79563
+ componentStack: z$1.string().max(CLIENT_ERROR_REPORT_LIMITS.componentStack).nullable(),
79564
+ sourceLocation: z$1.string().max(CLIENT_ERROR_REPORT_LIMITS.sourceLocation).nullable()
79565
+ }).strict();
78564
79566
  ({
79567
+ ...CLIENT_ERROR_REPORT_ENDPOINT_DEFINITIONS,
78565
79568
  ...PUBLIC_NEWSLETTER_ENDPOINT_DEFINITIONS,
78566
79569
  ...ACCOUNT_ENDPOINT_DEFINITIONS,
78567
79570
  ...PUBLIC_ONBOARDING_ATTEMPT_ENDPOINT_DEFINITIONS,
78568
79571
  ...PUBLIC_EVENT_ENDPOINT_DEFINITIONS,
78569
79572
  ...GIFTING_ENDPOINT_DEFINITIONS,
78570
79573
  ...PUBLIC_READ_ENDPOINT_DEFINITIONS,
78571
- ...BILLING_ENDPOINT_DEFINITIONS
79574
+ ...BILLING_ENDPOINT_DEFINITIONS,
79575
+ ...SITE_MANAGEMENT_ENDPOINT_DEFINITIONS
78572
79576
  }), 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, {
78573
79577
  ...NEWSLETTER_ENDPOINT_DEFINITIONS,
78574
79578
  ...APPOINTMENT_ENDPOINT_DEFINITIONS,
78575
79579
  ...EVENT_SERIES_REGISTRATION_ENDPOINT_DEFINITIONS
78576
- }, 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 };
79580
+ }, 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 };
78577
79581
  z$1.object({ refreshToken: z$1.string().min(1).max(4096) }).strict();
78578
79582
  z$1.object({
78579
79583
  accessToken: z$1.string().min(1).max(4096),
@@ -79179,6 +80183,46 @@ z$1.object({ acceptExtraSiteCharge: z$1.boolean().optional() });
79179
80183
  //#region ../surfaces/src/index.ts
79180
80184
  const SURFACE_IDS = ["core", "macadamia"];
79181
80185
  const DEFAULT_SURFACE_ID = "core";
80186
+ /**
80187
+ * Root hosts for each surface, keyed by deployment tier. The tier-keyed shape
80188
+ * makes it impossible to mis-order entries: callers like
80189
+ * `buildSurfaceAwareDashboardOriginForSurfaceId` look up by tier directly
80190
+ * rather than relying on positional alignment between arrays.
80191
+ */
80192
+ const SURFACE_ROOT_HOSTS = {
80193
+ core: {
80194
+ local: "localhost",
80195
+ prod: "riverbankcms.com"
80196
+ },
80197
+ macadamia: {
80198
+ local: "macadamia.localhost",
80199
+ prod: "macadamia.studio"
80200
+ }
80201
+ };
80202
+ const SURFACE_SITE_ROOT_HOSTS = {
80203
+ core: {
80204
+ local: "localhost",
80205
+ prod: "riverbanksites.com"
80206
+ },
80207
+ macadamia: {
80208
+ local: "macadamia.localhost",
80209
+ prod: "macadamia.studio"
80210
+ }
80211
+ };
80212
+ const SURFACE_SITE_ROOT_HOST_ALIASES = { core: { prod: ["preview.riverbanksites.com"] } };
80213
+ function surfaceHostTableValues(table) {
80214
+ return Object.values(table).flatMap((byTier) => Object.values(byTier).flat());
80215
+ }
80216
+ function siteSlugLabelUnderRoot(host, siteRootHost) {
80217
+ if (!host.endsWith(`.${siteRootHost}`)) return [];
80218
+ return host.slice(0, host.length - siteRootHost.length - 1).split(".").slice(-1);
80219
+ }
80220
+ function deriveSurfaceOwnedSiteSlugs() {
80221
+ const siteRootHosts = [...surfaceHostTableValues(SURFACE_SITE_ROOT_HOSTS), ...surfaceHostTableValues(SURFACE_SITE_ROOT_HOST_ALIASES)];
80222
+ const labels = [...surfaceHostTableValues(SURFACE_ROOT_HOSTS), ...siteRootHosts].flatMap((host) => siteRootHosts.flatMap((root) => siteSlugLabelUnderRoot(host, root)));
80223
+ return [...new Set(labels)].sort();
80224
+ }
80225
+ deriveSurfaceOwnedSiteSlugs();
79182
80226
  [...SURFACE_IDS.filter((surfaceId) => surfaceId !== DEFAULT_SURFACE_ID)];
79183
80227
  //#endregion
79184
80228
  //#region ../api/src/accountApi.ts
@@ -79810,6 +80854,7 @@ function parsePublicProductCategorySelector(value) {
79810
80854
  productCategoryEntryId: record.productCategoryEntryId
79811
80855
  };
79812
80856
  }
80857
+ z$1.enum(["public", "unlisted"], { error: "visibility must be 'public' or 'unlisted'" });
79813
80858
  //#endregion
79814
80859
  //#region ../api/src/bookingPaymentTermSchemas.ts
79815
80860
  const bookingDepositRefundPolicySchema = z$1.enum(["refundable", "non_refundable"]);
@@ -81119,23 +82164,23 @@ async function loadPageWithDeps(deps, params) {
81119
82164
  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.");
81120
82165
  const { page: pageData } = pageResponse;
81121
82166
  const support = buildSiteRenderSupport(site, collectMediaAssetSidecar(pageResponse.mediaAssets));
82167
+ const previewStage = preview ? "preview" : "published";
81122
82168
  const pageOutline = buildRenderablePageOutline({
81123
82169
  name: pageData.name,
81124
82170
  path: pageData.path,
81125
82171
  fallbackPath: path,
81126
82172
  purpose: pageData.purpose,
81127
82173
  blocks: pageData.blocks,
82174
+ previewStage,
81128
82175
  customBlocks: support.customBlocks
81129
82176
  });
81130
- const previewStage = preview ? "preview" : "published";
81131
- const renderTarget = {
81132
- kind: "page",
81133
- pageId: pageId ?? pageData.id
81134
- };
81135
82177
  const resolvedData = await resolveBlockDataWithDeps(deps, {
81136
82178
  page: projectRenderablePageOutline(pageOutline),
81137
82179
  siteId,
81138
- renderTarget,
82180
+ renderTarget: {
82181
+ kind: "page",
82182
+ pageId: pageId ?? pageData.id
82183
+ },
81139
82184
  previewStage,
81140
82185
  policy: createBlockDataLoadPolicy(dataLoaderOverrides, normalizeDataLoaderSearchParams(searchParams)),
81141
82186
  client,
@@ -81148,6 +82193,7 @@ async function loadPageWithDeps(deps, params) {
81148
82193
  sdkConfig: support.sdkConfig,
81149
82194
  siteId,
81150
82195
  resolvedData,
82196
+ dataContext: { previewStage },
81151
82197
  bookingOfferingPresets: support.bookingOfferingPresets,
81152
82198
  mailingList: support.mailingList,
81153
82199
  bookingTimeZone: support.bookingTimeZone,
@@ -83710,7 +84756,8 @@ async function processTemplatePage(input) {
83710
84756
  block,
83711
84757
  bindingContext: input.bindingContext,
83712
84758
  slotContent: input.slotContent,
83713
- customBlocks: input.customBlocks
84759
+ customBlocks: input.customBlocks,
84760
+ previewStage: input.previewStage
83714
84761
  }));
83715
84762
  if (blocks.length === 0) return {
83716
84763
  templatePage: null,
@@ -83741,7 +84788,7 @@ function resolveTemplateBlockSequence(input) {
83741
84788
  if (slotKey) return selectBlocksForDeclaredEntrySlot({
83742
84789
  declaredSlotKey: slotKey,
83743
84790
  entrySlots: input.slotContent ?? []
83744
- }).map((slotBlock) => admitEntrySlotBlock(slotBlock, input.customBlocks));
84791
+ }).map((slotBlock) => admitEntrySlotBlock(slotBlock, input.customBlocks, input.previewStage));
83745
84792
  if (block.blockKind === "system.entry-slot") return [];
83746
84793
  return [resolveTemplateBlock(block, input.bindingContext, input.customBlocks)];
83747
84794
  }
@@ -83775,10 +84822,11 @@ function readEntrySlotKey(block) {
83775
84822
  const parsed = parseSlotKey(block.content?.slotKey);
83776
84823
  return parsed.ok ? parsed.value : null;
83777
84824
  }
83778
- function admitEntrySlotBlock(block, customBlocks) {
84825
+ function admitEntrySlotBlock(block, customBlocks, previewStage) {
83779
84826
  const base = {
83780
84827
  id: block.id ?? block.blockId ?? null,
83781
84828
  contentVersionId: block.contentVersionId,
84829
+ ...entrySlotBlockIdentity(block, previewStage),
83782
84830
  kind: block.kind,
83783
84831
  purpose: block.purpose,
83784
84832
  ...isRecord(block.bindings) ? { bindings: block.bindings } : {}
@@ -83799,6 +84847,12 @@ function admitEntrySlotBlock(block, customBlocks) {
83799
84847
  error: renderable.error
83800
84848
  });
83801
84849
  }
84850
+ function entrySlotBlockIdentity(block, previewStage) {
84851
+ return {
84852
+ draftContentId: block.draftContentId ?? null,
84853
+ publishedPlacement: previewStage === "preview" ? readPublishedBlockPlacement(block.publishedContentId, isRecord(block.publishedContent) && isRecord(block.publishedContent.data) ? block.publishedContent.data : null) : null
84854
+ };
84855
+ }
83802
84856
  //#endregion
83803
84857
  //#region src/rendering/helpers/loadContent.ts
83804
84858
  /**
@@ -83970,15 +85024,18 @@ async function loadContentFromContentResponseWithDeps(deps, params) {
83970
85024
  entry,
83971
85025
  templatePage,
83972
85026
  resolvedData,
83973
- dataContext: { contentEntry: {
83974
- ...entry.content ?? {},
83975
- id: entry.id,
83976
- slug: entry.slug,
83977
- contentTypeSlug: entry.type,
83978
- _entryId: entry.id,
83979
- _entrySlug: entry.slug,
83980
- _contentTypeSlug: entry.type
83981
- } },
85027
+ dataContext: {
85028
+ previewStage,
85029
+ contentEntry: {
85030
+ ...entry.content ?? {},
85031
+ id: entry.id,
85032
+ slug: entry.slug,
85033
+ contentTypeSlug: entry.type,
85034
+ _entryId: entry.id,
85035
+ _entrySlug: entry.slug,
85036
+ _contentTypeSlug: entry.type
85037
+ }
85038
+ },
83982
85039
  ...templateContentSupport
83983
85040
  };
83984
85041
  }
@@ -84039,6 +85096,7 @@ async function loadContentFromContentResponseWithDeps(deps, params) {
84039
85096
  templatePage,
84040
85097
  resolvedData,
84041
85098
  dataContext: {
85099
+ previewStage,
84042
85100
  pageSurface: {
84043
85101
  ...pageSurface.content ?? {},
84044
85102
  id: pageSurface.id,
@@ -84055,13 +85113,13 @@ async function loadContentFromContentResponseWithDeps(deps, params) {
84055
85113
  const { page: pageData } = contentResponse;
84056
85114
  const pageRecord = pageData;
84057
85115
  const canonicalPagePath = pageData.path ?? pageRecord.path ?? "/";
84058
- const draftPagePath = pageRecord.draftPath ?? pageRecord.path ?? canonicalPagePath;
84059
85116
  const pageOutline = buildRenderablePageOutline({
84060
85117
  name: pageData.name,
84061
85118
  path: canonicalPagePath,
84062
85119
  fallbackPath: "/",
84063
85120
  purpose: pageData.purpose,
84064
85121
  blocks: pageData.blocks,
85122
+ previewStage,
84065
85123
  customBlocks: support.customBlocks
84066
85124
  });
84067
85125
  const resolvedData = await resolveBlockDataWithDeps(deps, {
@@ -84080,26 +85138,14 @@ async function loadContentFromContentResponseWithDeps(deps, params) {
84080
85138
  type: "page",
84081
85139
  pageId: pageRecord.id,
84082
85140
  routeId: pageRecord.routeId ?? null,
84083
- pageMetadata: {
84084
- draftTitle: pageRecord.draftTitle ?? pageRecord.name ?? pageData.name,
84085
- draftPath: draftPagePath,
84086
- draftStatus: pageRecord.draftStatus ?? pageRecord.status ?? "draft",
84087
- title: pageRecord.name ?? pageData.name,
84088
- path: canonicalPagePath,
84089
- status: pageRecord.status ?? pageRecord.draftStatus ?? "draft",
84090
- publishedAt: pageRecord.publishedAt ?? null,
84091
- draftMetaTitle: pageRecord.draftMetaTitle ?? null,
84092
- draftMetaDescription: pageRecord.draftMetaDescription ?? null,
84093
- publishedMetaTitle: pageRecord.publishedMetaTitle ?? null,
84094
- publishedMetaDescription: pageRecord.publishedMetaDescription ?? null,
84095
- ogImageId: pageRecord.ogImageId ?? null
84096
- },
85141
+ pageMetadata: projectPagePreviewMetadata(pageRecord, pageData.name, canonicalPagePath),
84097
85142
  page: pageOutline,
84098
85143
  runtimeJoins: pageData.runtimeJoins,
84099
85144
  theme: support.theme,
84100
85145
  siteId,
84101
85146
  ...support.customBlocks ? { customBlocks: support.customBlocks } : {},
84102
85147
  resolvedData,
85148
+ dataContext: { previewStage },
84103
85149
  bookingOfferingPresets: support.bookingOfferingPresets,
84104
85150
  mailingList: support.mailingList,
84105
85151
  bookingTimeZone: support.bookingTimeZone,
@@ -84112,6 +85158,32 @@ async function loadContentFromContentResponseWithDeps(deps, params) {
84112
85158
  ...support.mediaAssets ? { mediaAssets: support.mediaAssets } : {}
84113
85159
  };
84114
85160
  }
85161
+ function projectPagePreviewMetadata(page, pageName, canonicalPath) {
85162
+ return {
85163
+ ...projectDraftPageMetadata(page, pageName, canonicalPath),
85164
+ ...projectPublishedPageMetadata(page, pageName, canonicalPath)
85165
+ };
85166
+ }
85167
+ function projectDraftPageMetadata(page, pageName, canonicalPath) {
85168
+ return {
85169
+ draftTitle: page.draftTitle ?? page.name ?? pageName,
85170
+ draftPath: page.draftPath ?? page.path ?? canonicalPath,
85171
+ draftStatus: page.draftStatus ?? page.status ?? "draft",
85172
+ draftMetaTitle: page.draftMetaTitle ?? null,
85173
+ draftMetaDescription: page.draftMetaDescription ?? null
85174
+ };
85175
+ }
85176
+ function projectPublishedPageMetadata(page, pageName, canonicalPath) {
85177
+ return {
85178
+ title: page.name ?? pageName,
85179
+ path: canonicalPath,
85180
+ status: page.status ?? page.draftStatus ?? "draft",
85181
+ publishedAt: page.publishedAt ?? null,
85182
+ publishedMetaTitle: page.publishedMetaTitle ?? null,
85183
+ publishedMetaDescription: page.publishedMetaDescription ?? null,
85184
+ ogImageId: page.ogImageId ?? null
85185
+ };
85186
+ }
84115
85187
  /**
84116
85188
  * Type guard to check if API response is an entry
84117
85189
  */