@riverbankcms/sdk 0.127.0 → 0.129.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 (178) hide show
  1. package/README.md +33 -0
  2. package/dist/{PreviewEditorSidebar-BXtfF7tp.mjs → PreviewEditorSidebar-B43CJ0g_.mjs} +9 -33
  3. package/dist/{PreviewEditorUI-Dou73Q0K.mjs → PreviewEditorUI-DHirVkeM.mjs} +3 -3
  4. package/dist/{PreviewQueryProvider-DgFDIwvK.mjs → PreviewQueryProvider-B1kbhaJD.mjs} +1 -1
  5. package/dist/SdkPreviewModeRuntime-BJumZy1B.mjs +11209 -0
  6. package/dist/{SiteChromeCustomizeContext-DZiDBAYu.mjs → SiteChromeCustomizeContext-D9SlpwEj.mjs} +31757 -1621
  7. package/dist/_dts/ai/src/contracts/proposals.d.ts +288 -36
  8. package/dist/_dts/api/src/bookingClosures.d.ts +19 -3
  9. package/dist/_dts/api/src/bookingManagementEndpoints.d.ts +4 -3
  10. package/dist/_dts/api/src/bookingRecords.d.ts +0 -13
  11. package/dist/_dts/api/src/commercePortalEndpoints.d.ts +2 -2
  12. package/dist/_dts/api/src/communications.d.ts +2 -1
  13. package/dist/_dts/api/src/contactFormSummary.d.ts +15 -0
  14. package/dist/_dts/api/src/contentRuntime.d.ts +2 -5
  15. package/dist/_dts/api/src/endpoints.d.ts +1 -1
  16. package/dist/_dts/api/src/footerSettings.d.ts +11 -0
  17. package/dist/_dts/api/src/index.d.ts +2 -1
  18. package/dist/_dts/api/src/occurrenceScheduling.d.ts +48 -0
  19. package/dist/_dts/api/src/participantMessaging.d.ts +5 -3
  20. package/dist/_dts/api/src/publicExperience/siteEndpoints.d.ts +7 -0
  21. package/dist/_dts/api/src/sdkContracts.d.ts +7 -5
  22. package/dist/_dts/api/src/siteOperations.d.ts +12 -3
  23. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +3 -2
  24. package/dist/_dts/blocks/src/PageRenderer.d.ts +20 -10
  25. package/dist/_dts/blocks/src/client/form.d.ts +1 -0
  26. package/dist/_dts/blocks/src/client/newsletter-form.d.ts +1 -0
  27. package/dist/_dts/blocks/src/client/site-chrome.d.ts +1 -0
  28. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +4 -8
  29. package/dist/_dts/blocks/src/index.d.ts +2 -1
  30. package/dist/_dts/blocks/src/pageRendererBoundaries.d.ts +30 -0
  31. package/dist/_dts/blocks/src/pageRenderingMode.d.ts +37 -0
  32. package/dist/_dts/blocks/src/rendering/server.d.ts +1 -1
  33. package/dist/_dts/blocks/src/server.d.ts +1 -1
  34. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +41 -0
  35. package/dist/_dts/blocks/src/system/blocks/newsletter-signup-destination.d.ts +14 -23
  36. package/dist/_dts/blocks/src/system/blocks/newsletter-signup.d.ts +1 -1
  37. package/dist/_dts/blocks/src/system/blocks/site-footer-runtime.d.ts +109 -23
  38. package/dist/_dts/blocks/src/system/data/loaderEndpoints.d.ts +1 -1
  39. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +42 -108
  40. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +21 -54
  41. package/dist/_dts/blocks/src/system/runtime/nodes/event-details/logic.d.ts +1 -1
  42. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationSurface.d.ts +26 -0
  43. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +8 -0
  44. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +21 -0
  45. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.interactive.d.ts +29 -78
  46. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.server.d.ts +1 -1
  47. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.submission.d.ts +3 -6
  48. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.types.d.ts +27 -8
  49. package/dist/_dts/content-editor/src/FooterComposerOverview.d.ts +21 -0
  50. package/dist/_dts/content-editor/src/FooterComposerPanel.d.ts +3 -1
  51. package/dist/_dts/content-editor/src/FooterEngagementEditorFields.d.ts +31 -0
  52. package/dist/_dts/content-editor/src/FooterEngagementEditorPanel.d.ts +17 -0
  53. package/dist/_dts/content-editor/src/footerComposer.d.ts +3 -0
  54. package/dist/_dts/content-editor/src/footerEngagementDraft.d.ts +57 -0
  55. package/dist/_dts/content-editor/src/footerEngagementEditor.d.ts +11 -0
  56. package/dist/_dts/content-editor/src/footerPreviewRuntime.d.ts +13 -0
  57. package/dist/_dts/content-editor/src/index.d.ts +1 -0
  58. package/dist/_dts/content-editor/src/useFooterComposerState.d.ts +35 -0
  59. package/dist/_dts/core/src/footer-arrangement.d.ts +2 -0
  60. package/dist/_dts/core/src/footer-composition-types.d.ts +118 -0
  61. package/dist/_dts/core/src/footer-composition.d.ts +7 -116
  62. package/dist/_dts/core/src/footer-engagement.d.ts +30 -0
  63. package/dist/_dts/core/src/index.d.ts +4 -0
  64. package/dist/_dts/core/src/newsletter-signup-destination.d.ts +38 -0
  65. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +73 -6
  66. package/dist/_dts/db/src/index.d.ts +1 -0
  67. package/dist/_dts/db/src/schemas/forms.d.ts +72 -2
  68. package/dist/_dts/db/src/schemas/standard-contact.d.ts +114 -0
  69. package/dist/_dts/preview-next/src/client/blocks/pageDesignRuntimePreview.d.ts +2 -0
  70. package/dist/_dts/preview-next/src/client/blocks/previewBatchLoaderParams.d.ts +6 -0
  71. package/dist/_dts/preview-next/src/client/index.d.ts +47 -47
  72. package/dist/_dts/preview-next/src/client/preview/EntryEditorPanel.d.ts +2 -5
  73. package/dist/_dts/preview-next/src/client/preview/EntrySlotBlockEditorPanel.d.ts +2 -5
  74. package/dist/_dts/preview-next/src/client/preview/PageBlockEditorPanel.d.ts +2 -5
  75. package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +2 -4
  76. package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +19 -7
  77. package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +30 -23
  78. package/dist/_dts/preview-next/src/client/preview/PreviewThemedSiteDocument.d.ts +18 -5
  79. package/dist/_dts/preview-next/src/client/preview/themeRuntime.d.ts +9 -0
  80. package/dist/_dts/preview-next/src/client/sdk/SdkPreviewMode.d.ts +21 -6
  81. package/dist/_dts/preview-next/src/client/sdk-runtime.d.ts +8 -8
  82. package/dist/_dts/preview-next/src/client/widgets/widgetOverrides.d.ts +6 -5
  83. package/dist/_dts/sdk/src/cli/commands/push/execute/footer.d.ts +9 -0
  84. package/dist/_dts/sdk/src/cli/content/footerFile.d.ts +10 -0
  85. package/dist/_dts/sdk/src/cli/content/reader.d.ts +3 -5
  86. package/dist/_dts/sdk/src/cli/site-commands/footerCommands.d.ts +15 -3
  87. package/dist/_dts/sdk/src/client/combineAbortSignals.d.ts +2 -0
  88. package/dist/_dts/sdk/src/client/management/types.d.ts +6 -15
  89. package/dist/_dts/sdk/src/client/types.d.ts +10 -2
  90. package/dist/_dts/sdk/src/client/wholeSeriesReadOperations.d.ts +11 -0
  91. package/dist/_dts/sdk/src/config/types.d.ts +1 -1
  92. package/dist/_dts/sdk/src/config/validation.d.ts +3 -0
  93. package/dist/_dts/sdk/src/contracts/event-registration-content.d.ts +16 -0
  94. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +4 -15
  95. package/dist/_dts/sdk/src/next/catch-all.d.ts +6 -0
  96. package/dist/_dts/sdk/src/next/index.d.ts +2 -1
  97. package/dist/_dts/sdk/src/next/renderSdkContent.d.ts +33 -0
  98. package/dist/_dts/sdk/src/next/types.d.ts +23 -9
  99. package/dist/_dts/sdk/src/preview-next/before-render.d.ts +4 -6
  100. package/dist/_dts/sdk/src/preview-next/client/index.d.ts +3 -3
  101. package/dist/_dts/sdk/src/preview-next/client/runtime.d.ts +1 -1
  102. package/dist/_dts/sdk/src/public-api/contracts.d.ts +4 -18
  103. package/dist/_dts/sdk/src/public-api/teamMemberContracts.d.ts +17 -0
  104. package/dist/_dts/sdk/src/public-api/wholeSeriesContracts.d.ts +2 -0
  105. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +32 -3
  106. package/dist/_dts/sdk/src/rendering/components/Block.shared.d.ts +13 -2
  107. package/dist/_dts/sdk/src/rendering/components/Layout.d.ts +31 -18
  108. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +20 -9
  109. package/dist/_dts/sdk/src/rendering/index.d.ts +8 -4
  110. package/dist/_dts/sdk/src/rendering/mediaAssets.d.ts +8 -2
  111. package/dist/_dts/sdk/src/rendering/renderingMode.d.ts +23 -0
  112. package/dist/_dts/sdk/src/rendering/server.d.ts +5 -3
  113. package/dist/_dts/sdk/src/rendering/themeRuntime.d.ts +6 -0
  114. package/dist/_dts/sdk/src/version.d.ts +1 -1
  115. package/dist/_dts/site-commands/src/commandContract.d.ts +8 -1
  116. package/dist/_dts/site-commands/src/commands.d.ts +16 -2
  117. package/dist/_dts/theme-core/src/header/paintTargets.d.ts +10 -4
  118. package/dist/_dts/theme-core/src/header/surfaceRules.d.ts +2 -3
  119. package/dist/cli/index.mjs +5535 -4835
  120. package/dist/cli/init-docs/content/workflow-preview-mode.md +24 -11
  121. package/dist/client/{courseRegistration-DTEYWL6Z.mjs → CourseRegistrationWizard-xRmA7REV.mjs} +329 -49
  122. package/dist/client/{DiscountCodeDisclosure-BDFRp8Y7.mjs → DiscountCodeDisclosure-B9vriL5C.mjs} +1 -1
  123. package/dist/client/{EventCombined.client-DJgF1_lf.mjs → EventCombined.client-BgVnVTlz.mjs} +2 -2
  124. package/dist/client/{EventListing.client-CnWGNjOr.mjs → EventListing.client-CqdsO7jO.mjs} +2 -2
  125. package/dist/client/{LeafletStaticMap-BISs9Bl7.mjs → LeafletStaticMap-CKPxot9M.mjs} +1 -1
  126. package/dist/client/{StepIndicator-D8gVYkK-.mjs → StepIndicator-DGCYuBJ1.mjs} +2 -2
  127. package/dist/client/{accordion-DFDajgDz.mjs → accordion-BfN5Eqd-.mjs} +1 -1
  128. package/dist/client/{bookingForm-Bdqj9-52.mjs → bookingForm-DOvCpBFP.mjs} +5 -5
  129. package/dist/client/{carousel-Cvqf-kN8.mjs → carousel-DPNmiH0f.mjs} +1 -1
  130. package/dist/client/{cart-CuH2TJXP.mjs → cart--egVXlrR.mjs} +3 -3
  131. package/dist/client/{checkout-CMNPpejZ.mjs → checkout-DywWtMcq.mjs} +3 -3
  132. package/dist/client/client.mjs +5324 -4942
  133. package/dist/client/courseRegistration-Dk9qFVwt.mjs +46 -0
  134. package/dist/client/{eventCalendar-BW-XoxZ0.mjs → eventCalendar-Bkz2HjlS.mjs} +4 -4
  135. package/dist/client/{eventCombined-Bpn7s0y9.mjs → eventCombined-D4kipYWg.mjs} +2 -2
  136. package/dist/client/{eventDetails-D2uUSTMH.mjs → eventDetails-Dz_5ix2Q.mjs} +56 -35
  137. package/dist/client/{eventListing-CVr1c094.mjs → eventListing-D0vm-zST.mjs} +2 -2
  138. package/dist/client/{eventRegistration-Dv4AvkMw.mjs → eventRegistration-Cw1E4Q4p.mjs} +58 -6
  139. package/dist/client/{form-DxdKf9fs.mjs → form-C2Zf1n3K.mjs} +1 -1
  140. package/dist/client/{headerSection-BaXI5Sro.mjs → headerSection-CP05gzdc.mjs} +2 -2
  141. package/dist/client/hooks.mjs +212 -61
  142. package/dist/client/{locationMap-BEtW2fKz.mjs → locationMap-Cl3x9PYJ.mjs} +2 -2
  143. package/dist/client/{newsletterForm-BKKs0S4R.mjs → newsletterForm-DyEJoClm.mjs} +26 -20
  144. package/dist/client/{pricing-ClkqcElA.mjs → pricing-DGuNR1W4.mjs} +1 -1
  145. package/dist/client/{productDetail-H-ru8dyy.mjs → productDetail-Cq-HrGew.mjs} +3 -3
  146. package/dist/client/{productList-Buyi5c0C.mjs → productList-DbB3jwqd.mjs} +3 -3
  147. package/dist/client/{propsDecoder-BF7i6Ijg.mjs → propsDecoder-CiTuhUwY.mjs} +130 -87
  148. package/dist/client/rendering/client.mjs +416 -208
  149. package/dist/client/rendering/islands.mjs +18 -18
  150. package/dist/client/rendering.mjs +6026 -5596
  151. package/dist/client/{scrollToBlock-D_7t8yWb.mjs → scrollToBlock-CShkRqab.mjs} +1 -1
  152. package/dist/client/{shop-CF7SZQNX.mjs → shop-Cu4Ib-ZA.mjs} +5 -5
  153. package/dist/client/{shop-commerce-DA7_Rq5p.mjs → shop-commerce-BzpsOdh7.mjs} +4 -4
  154. package/dist/client/{shop-commerce-store-BmLqW7Gh.mjs → shop-commerce-store-DaE7Fhj8.mjs} +1 -1
  155. package/dist/client/{shopShared-WL-E1znM.mjs → shopShared-cF0c20vB.mjs} +2 -2
  156. package/dist/client/{useEventFilters-rc8VLeLV.mjs → useEventFilters-QZ3HMgaJ.mjs} +2 -2
  157. package/dist/client/{usePolling-1ncrfd4S.mjs → usePolling-BKf0GcE-.mjs} +2 -2
  158. package/dist/preview-next/before-render.mjs +11 -4
  159. package/dist/preview-next/client/runtime.mjs +4 -4
  160. package/dist/preview-next/middleware.mjs +1 -1
  161. package/dist/{previewAuthStore-Dev9CdG9.mjs → previewAuthStore-BesgU5Xu.mjs} +1 -1
  162. package/dist/{sdk-runtime-BnrCCFJq.mjs → sdk-runtime-CfZd5pAm.mjs} +2 -2
  163. package/dist/{separator-CFvBx2yl.mjs → separator-DkTe68HE.mjs} +1 -1
  164. package/dist/server/components.mjs +950 -639
  165. package/dist/server/config-validation.mjs +209 -61
  166. package/dist/server/config.mjs +209 -61
  167. package/dist/server/data.mjs +212 -61
  168. package/dist/server/index.mjs +40 -16
  169. package/dist/server/next.mjs +1181 -835
  170. package/dist/server/page-converter.mjs +211 -64
  171. package/dist/server/prebuild.mjs +1 -1
  172. package/dist/server/rendering/server.mjs +974 -637
  173. package/dist/server/rendering.mjs +980 -644
  174. package/dist/server/routing.mjs +254 -80
  175. package/dist/server/server.mjs +252 -77
  176. package/package.json +1 -1
  177. package/dist/SdkPreviewModeRuntime-B0HPXr-l.mjs +0 -39546
  178. package/dist/client/MagicLinkForm-b5E_HoG9.mjs +0 -327
@@ -68,11 +68,11 @@ var UnsafePathSegmentError = class extends Error {
68
68
  function assertSafePathSegments(segments) {
69
69
  for (const segment of segments) if (typeof segment === "string" && UNSAFE_PATH_SEGMENTS.has(segment)) throw new UnsafePathSegmentError(segment);
70
70
  }
71
- function isRecord$37(value) {
71
+ function isRecord$39(value) {
72
72
  return typeof value === "object" && value !== null && !Array.isArray(value);
73
73
  }
74
74
  function isPathContainer(value) {
75
- return Array.isArray(value) || isRecord$37(value);
75
+ return Array.isArray(value) || isRecord$39(value);
76
76
  }
77
77
  function getContainerValue(container, segment) {
78
78
  if (typeof segment === "number") return Array.isArray(container) ? container[segment] : void 0;
@@ -7857,7 +7857,7 @@ const API_ENDPOINTS$1 = {
7857
7857
  path: "/sites/{siteId}/shop/orders/{orderId}/digital-fulfillment",
7858
7858
  method: "POST",
7859
7859
  auth: "user",
7860
- responseKind: "void",
7860
+ responseKind: "json",
7861
7861
  errors: [
7862
7862
  "resource:not_found",
7863
7863
  "validation:invalid_input",
@@ -7903,20 +7903,20 @@ function isApiError(result) {
7903
7903
  function isApiSuccess(result) {
7904
7904
  return result.success === true;
7905
7905
  }
7906
- function isRecord$36(value) {
7906
+ function isRecord$38(value) {
7907
7907
  return typeof value === "object" && value !== null && !Array.isArray(value);
7908
7908
  }
7909
7909
  function isFieldError(value) {
7910
- return isRecord$36(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
7910
+ return isRecord$38(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
7911
7911
  }
7912
7912
  function fieldErrorsFromUnknown(value) {
7913
7913
  if (!Array.isArray(value)) return null;
7914
7914
  return value.every(isFieldError) ? value : null;
7915
7915
  }
7916
7916
  function extractEnvelopeErrorObject(body) {
7917
- if (!isRecord$36(body)) return null;
7917
+ if (!isRecord$38(body)) return null;
7918
7918
  const error = body.error;
7919
- if (!isRecord$36(error)) return null;
7919
+ if (!isRecord$38(error)) return null;
7920
7920
  if ("success" in body && body.success !== false) return null;
7921
7921
  return error;
7922
7922
  }
@@ -8125,7 +8125,7 @@ function formatEventPricing(pricing, options = {}) {
8125
8125
  //#endregion
8126
8126
  //#region ../core/src/event-page-surface-subject.ts
8127
8127
  function parseEventPageSurfaceSubject(value) {
8128
- if (!isRecord$35(value)) return err$3({ kind: "notObject" });
8128
+ if (!isRecord$37(value)) return err$3({ kind: "notObject" });
8129
8129
  switch (value.kind) {
8130
8130
  case "eventSeries": {
8131
8131
  const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
@@ -8168,7 +8168,7 @@ function parseEventPageSurfaceSubject(value) {
8168
8168
  });
8169
8169
  }
8170
8170
  }
8171
- function isRecord$35(value) {
8171
+ function isRecord$37(value) {
8172
8172
  return typeof value === "object" && value !== null && !Array.isArray(value);
8173
8173
  }
8174
8174
  //#endregion
@@ -8402,7 +8402,7 @@ function toLocationCoordinates(value) {
8402
8402
  }
8403
8403
  //#endregion
8404
8404
  //#region ../core/src/rich-text.ts
8405
- function isRecord$33(value) {
8405
+ function isRecord$35(value) {
8406
8406
  return typeof value === "object" && value !== null && !Array.isArray(value);
8407
8407
  }
8408
8408
  function hasOnlyKeys(value, allowed) {
@@ -8421,13 +8421,16 @@ function isDenseArrayOf(value, predicate) {
8421
8421
  return true;
8422
8422
  }
8423
8423
  function isTipTapMark(value) {
8424
- return isRecord$33(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$33(value.attrs));
8424
+ return isRecord$35(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$35(value.attrs));
8425
8425
  }
8426
8426
  function isTipTapNode(value) {
8427
- if (!isRecord$33(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$33(value.attrs) || value.marks !== void 0 && (!Array.isArray(value.marks) || !isDenseArrayOf(value.marks, isTipTapMark)) || value.content !== void 0 && (!Array.isArray(value.content) || !isDenseArrayOf(value.content, isTipTapNode))) return false;
8427
+ if (!isRecord$35(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$35(value.attrs) || value.marks !== void 0 && (!Array.isArray(value.marks) || !isDenseArrayOf(value.marks, isTipTapMark)) || value.content !== void 0 && (!Array.isArray(value.content) || !isDenseArrayOf(value.content, isTipTapNode))) return false;
8428
8428
  if (value.type === "text") return typeof value.text === "string" && value.text.length > 0 && value.content === void 0;
8429
8429
  return value.text === void 0;
8430
8430
  }
8431
+ function parseNewsletterSignupDestinationProvider(value) {
8432
+ return value === "riverbank" || value === "mailchimp" ? value : null;
8433
+ }
8431
8434
  new Map([
8432
8435
  "brand",
8433
8436
  "supporting-text",
@@ -8436,6 +8439,7 @@ new Map([
8436
8439
  "business-address",
8437
8440
  "contact",
8438
8441
  "opening-hours",
8442
+ "engagement",
8439
8443
  "legal-navigation",
8440
8444
  "legal"
8441
8445
  ].map((kind, index) => [kind, index]));
@@ -8748,9 +8752,9 @@ function formatKeyAsLabel(key) {
8748
8752
  }
8749
8753
  //#endregion
8750
8754
  //#region ../media-core/src/fileSafety.ts
8751
- const CONTROL_CHARACTER_PATTERN$1 = /[\u0000-\u001f\u007f]/u;
8755
+ const CONTROL_CHARACTER_PATTERN = /[\u0000-\u001f\u007f]/u;
8752
8756
  function containsUnsafePathSegmentCharacter(value) {
8753
- return value.includes("/") || value.includes("\\") || CONTROL_CHARACTER_PATTERN$1.test(value);
8757
+ return value.includes("/") || value.includes("\\") || CONTROL_CHARACTER_PATTERN.test(value);
8754
8758
  }
8755
8759
  function isReservedPathSegment(value) {
8756
8760
  return value === "." || value === "..";
@@ -25462,10 +25466,16 @@ function getHeaderPaintTargets(variant, themeId, state = "base") {
25462
25466
  ownerSelector: desktopOwner,
25463
25467
  selector: `${desktopOwner}::before`,
25464
25468
  mediaQuery: MQ_MD_UP,
25465
- topExtension: {
25466
- customProperty: "--rb-header-floating-top-gap",
25467
- value: "1rem",
25468
- ownerProperty: "top"
25469
+ extent: {
25470
+ top: {
25471
+ customProperty: "--rb-header-floating-top-gap",
25472
+ value: "1rem",
25473
+ ownerProperty: "top"
25474
+ },
25475
+ bottom: {
25476
+ customProperty: "--rb-header-floating-bottom-extension",
25477
+ value: "0.75rem"
25478
+ }
25469
25479
  },
25470
25480
  ownerNeedsPositioning: false
25471
25481
  }, {
@@ -25474,10 +25484,16 @@ function getHeaderPaintTargets(variant, themeId, state = "base") {
25474
25484
  ownerSelector: mobileOwner,
25475
25485
  selector: `${mobileOwner}::before`,
25476
25486
  mediaQuery: MQ_MD_DOWN,
25477
- topExtension: {
25478
- customProperty: "--rb-header-floating-top-gap",
25479
- value: "0.75rem",
25480
- ownerProperty: "margin-top"
25487
+ extent: {
25488
+ top: {
25489
+ customProperty: "--rb-header-floating-top-gap",
25490
+ value: "0.75rem",
25491
+ ownerProperty: "margin-top"
25492
+ },
25493
+ bottom: {
25494
+ customProperty: "--rb-header-floating-bottom-extension",
25495
+ value: "0.75rem"
25496
+ }
25481
25497
  },
25482
25498
  ownerNeedsPositioning: true
25483
25499
  }];
@@ -25518,10 +25534,11 @@ function renderHeaderPaintTargetRule(target, rules) {
25518
25534
  return `${target.selector} {\n ${[...pseudoElementSetup, ...rules].join("\n ")}\n}`;
25519
25535
  }
25520
25536
  case "viewport-band": {
25521
- const gap = target.topExtension;
25537
+ const { top, bottom } = target.extent;
25522
25538
  const ownerRules = [
25523
- `${gap.customProperty}: ${gap.value};`,
25524
- `${gap.ownerProperty}: var(${gap.customProperty});`,
25539
+ `${top.customProperty}: ${top.value};`,
25540
+ `${bottom.customProperty}: ${bottom.value};`,
25541
+ `${top.ownerProperty}: var(${top.customProperty});`,
25525
25542
  ...target.ownerNeedsPositioning ? ["position: relative;"] : [],
25526
25543
  "isolation: isolate;",
25527
25544
  "background: none;",
@@ -25533,8 +25550,8 @@ function renderHeaderPaintTargetRule(target, rules) {
25533
25550
  const bandRules = [
25534
25551
  "content: \"\";",
25535
25552
  "position: absolute;",
25536
- `top: calc(-1 * var(${gap.customProperty}));`,
25537
- "bottom: 0;",
25553
+ `top: calc(-1 * var(${top.customProperty}));`,
25554
+ `bottom: calc(-1 * var(${bottom.customProperty}));`,
25538
25555
  "left: 50%;",
25539
25556
  "width: 100vw;",
25540
25557
  "transform: translateX(-50%);",
@@ -25553,6 +25570,7 @@ const headerScrollTreatmentSchema = z$1.discriminatedUnion("kind", [z$1.object({
25553
25570
  kind: z$1.literal("contrast-glass"),
25554
25571
  backgroundTone: z$1.enum(["light", "dark"])
25555
25572
  })]).optional();
25573
+ const CONTRAST_GLASS_BLUR = "blur(12px)";
25556
25574
  function generateMobileOverlayBackdropFilterFix(themeId, variant) {
25557
25575
  const root = `:where([data-theme-scope="${themeId}"]) .header-root:has([data-nav-mobile-overlay][aria-hidden="false"])`;
25558
25576
  return `\n${(variant === "floating" ? [`${root} .header-mobile-bar`, `${root} .header-mobile-bar::before`] : [`${root}::before`]).join(",\n")} {\n backdrop-filter: none !important;\n -webkit-backdrop-filter: none !important;\n}\n`;
@@ -25562,7 +25580,12 @@ function generateHeaderScrollTreatmentStyles(treatment, themeId, variant, surfac
25562
25580
  switch (treatment.kind) {
25563
25581
  case "contrast-glass": {
25564
25582
  const backgroundChannels = treatment.backgroundTone === "dark" ? "0 0 0" : "255 255 255";
25565
- return renderHeaderPaintTargetRules(getHeaderPaintTargets(variant, themeId, "scrolled"), [`background-color: rgb(${backgroundChannels} / 0.60);`, ...surfaceRules]);
25583
+ return renderHeaderPaintTargetRules(getHeaderPaintTargets(variant, themeId, "scrolled"), [
25584
+ `background-color: rgb(${backgroundChannels} / 0.60);`,
25585
+ `backdrop-filter: ${CONTRAST_GLASS_BLUR};`,
25586
+ `-webkit-backdrop-filter: ${CONTRAST_GLASS_BLUR};`,
25587
+ ...surfaceRules
25588
+ ]);
25566
25589
  }
25567
25590
  }
25568
25591
  }
@@ -33889,6 +33912,7 @@ const newsletterFormFragment = defineFragment({
33889
33912
  }
33890
33913
  ],
33891
33914
  layout: [el("newsletter-form", withApiBindings({
33915
+ source: "block",
33892
33916
  destinationProvider: { $bind: { from: "destinationProvider" } },
33893
33917
  listId: { $bind: { from: "listId" } },
33894
33918
  preset: { $bind: { from: "preset" } },
@@ -35411,6 +35435,7 @@ const contactNewsletterLayout = styledSection({
35411
35435
  as: "h2",
35412
35436
  className: "newsletter-copy-title"
35413
35437
  }, when("newsletterTitle"), bind("newsletterTitle")), richText({ className: "newsletter-copy-subtitle rb-prose rb-max-w-none" }, when("newsletterSubtitle"), bind("newsletterSubtitle"))]), el("newsletter-form", withApiBindings({
35438
+ source: "block",
35414
35439
  listId: { $bind: { from: "listId" } },
35415
35440
  preset: { $bind: { from: "preset" } },
35416
35441
  includePhone: { $bind: { from: "includePhone" } },
@@ -37408,6 +37433,22 @@ const footerNavGroupsLayout = stack({
37408
37433
  }, [text({ as: "span" }, bind("entry.label"))], repeat("group.children", "entry"))])], repeat("footerMenu.groups", "group"))], whenCollectionHasItems("footerMenu.groups"));
37409
37434
  //#endregion
37410
37435
  //#region ../blocks/src/system/blocks/site-footer.ts
37436
+ const footerStandardContactBindings = {
37437
+ value: { $bind: { from: "module.engagement.runtime.value" } },
37438
+ submitLabel: { $bind: { from: "module.engagement.runtime.submitLabel" } },
37439
+ successMessage: { $bind: { from: "module.engagement.runtime.successMessage" } }
37440
+ };
37441
+ const footerMailingListBindings = {
37442
+ source: { $bind: { from: "module.engagement.runtime.source" } },
37443
+ destinationRef: { $bind: { from: "module.engagement.runtime.destinationRef" } },
37444
+ listId: { $bind: { from: "module.engagement.runtime.listId" } },
37445
+ preset: { $bind: { from: "module.engagement.runtime.preset" } },
37446
+ includePhone: { $bind: { from: "module.engagement.runtime.includePhone" } },
37447
+ buttonLabel: { $bind: { from: "module.engagement.runtime.buttonLabel" } },
37448
+ successMessage: { $bind: { from: "module.engagement.runtime.successMessage" } },
37449
+ privacyNote: { $bind: { from: "module.engagement.runtime.privacyNote" } }
37450
+ };
37451
+ const footerSpamProtectionBinding = { spamProtectionEnabled: { $bind: { from: "$root.spamProtectionEnabled" } } };
37411
37452
  const brandLogo = link({
37412
37453
  href: "/",
37413
37454
  className: { $bind: {
@@ -37485,6 +37526,23 @@ const authoredCopy = richText({
37485
37526
  id: "content.interpolateRichTextTokens",
37486
37527
  options: { tokens: ["year", "site_name"] }
37487
37528
  }] }));
37529
+ const footerEngagement = stack({
37530
+ gap: "md",
37531
+ className: "rb-w-full"
37532
+ }, [
37533
+ text({
37534
+ as: "p",
37535
+ className: "rb-body rb-opacity-80"
37536
+ }, bind("module.engagement.intro"), when("module.engagement.intro")),
37537
+ form(withApiBindings({
37538
+ ...footerStandardContactBindings,
37539
+ ...footerSpamProtectionBinding
37540
+ }), [], when("module.engagement.kind", { equals: "standard-contact" })),
37541
+ el("newsletter-form", withApiBindings({
37542
+ ...footerMailingListBindings,
37543
+ ...footerSpamProtectionBinding
37544
+ }), [], when("module.engagement.kind", { equals: "mailing-list" }))
37545
+ ], when("module.kind", { equals: "engagement" }));
37488
37546
  const footerGroup = stack({
37489
37547
  gap: "md",
37490
37548
  align: "stretch",
@@ -37510,6 +37568,7 @@ const footerGroup = stack({
37510
37568
  contact,
37511
37569
  hours,
37512
37570
  socials,
37571
+ footerEngagement,
37513
37572
  stack({ className: "rb-w-full" }, [authoredCopy], when("module.kind", { equals: "supporting-text" })),
37514
37573
  stack({ className: "rb-w-full rb-lg-col-span-3" }, [authoredCopy], when("module.kind", { equals: "legal" }))
37515
37574
  ], repeat("group.modules", "module"))], repeat("region.groups", "group"));
@@ -37517,6 +37576,10 @@ const footerMainRegion = stack({
37517
37576
  className: { $bind: { from: "region.className" } },
37518
37577
  "data-footer-region": { $bind: { from: "region.kind" } }
37519
37578
  }, [footerGroup], when("region.kind", { equals: "main" }), repeat("content.footerRuntime.regions", "region"));
37579
+ const footerEngagementRegion = stack({
37580
+ className: { $bind: { from: "region.className" } },
37581
+ "data-footer-region": "engagement-row"
37582
+ }, [footerGroup], when("region.kind", { equals: "engagement-row" }), repeat("content.footerRuntime.regions", "region"));
37520
37583
  const footerBottomRegion = stack({ className: { $bind: {
37521
37584
  from: "$root.theme.footer",
37522
37585
  transforms: [{ id: "layout.footerBottomBarContainerClass" }],
@@ -37552,7 +37615,11 @@ const siteFooterBlockDefinition = { manifest: createBlockManifest({
37552
37615
  fallback: mergeStyles(backgroundColorStyle("surface"), surfaceForegroundStyle({ text: "rgb(var(--tb-text))" }), borderColorStyle("border"))
37553
37616
  } },
37554
37617
  "data-footer-membership": { $bind: { from: "content.footerRuntime.membershipKey" } }
37555
- }, [footerMainRegion, footerBottomRegion]),
37618
+ }, [
37619
+ footerEngagementRegion,
37620
+ footerMainRegion,
37621
+ footerBottomRegion
37622
+ ]),
37556
37623
  description: "Site-wide composed footer with canonical shared details.",
37557
37624
  styleTokens: { spacing: "md" },
37558
37625
  paletteHidden: true
@@ -40135,7 +40202,7 @@ const publicMembershipProductCollectionSchema = z$1.object({ memberships: z$1.ar
40135
40202
  * Kept in a shared module so the block definition and runtime contracts can
40136
40203
  * depend on the same schema without creating an initialization cycle.
40137
40204
  */
40138
- const occurrenceContextSchema$1 = z$1.object({
40205
+ const occurrenceContextSchema = z$1.object({
40139
40206
  id: z$1.string(),
40140
40207
  seriesId: z$1.string(),
40141
40208
  startsAt: z$1.string(),
@@ -40535,28 +40602,37 @@ const EVENT_REGISTRATION_SHELL_STEP_LABELS = [
40535
40602
  "Payment"
40536
40603
  ];
40537
40604
  const eventRegistrationPublicEventSchema = z$1.preprocess(normalizeEventRegistrationEventInput, publicEventSchema);
40538
- const eventRegistrationSourceSchema = z$1.object({
40539
- siteId: z$1.string().optional(),
40540
- apiBaseUrl: z$1.string().optional(),
40541
- portalToken: z$1.string().nullable().optional(),
40542
- previewToken: z$1.string().nullable().optional(),
40543
- occurrenceContext: occurrenceContextSchema$1.optional(),
40605
+ const eventRegistrationHydrationSchemaShape = {
40606
+ occurrenceContext: occurrenceContextSchema.optional(),
40544
40607
  subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
40545
40608
  events: z$1.array(eventRegistrationPublicEventSchema).nullable().optional(),
40546
- className: z$1.string().nullable().optional(),
40547
- buttonText: z$1.string().nullable().optional(),
40548
- maxTickets: z$1.string().nullable().optional(),
40609
+ wholeSeriesOfferings: publicCoursesArraySchema.nullable().optional(),
40610
+ wholeSeriesOffering: publicCourseSchema.nullable().optional(),
40611
+ maxTickets: z$1.string().optional(),
40549
40612
  showVenue: z$1.boolean().optional(),
40550
40613
  showCapacity: z$1.boolean().optional(),
40614
+ showSessions: z$1.boolean().optional(),
40615
+ showPrice: z$1.boolean().optional(),
40551
40616
  successMessage: z$1.string().optional(),
40552
40617
  waitlistMessage: z$1.string().optional(),
40618
+ membershipMessage: z$1.string().optional(),
40553
40619
  buttonVariant: registrationButtonVariantSchema.optional(),
40554
40620
  overlayEnabled: z$1.boolean().optional(),
40555
40621
  spamProtectionEnabled: z$1.boolean().optional(),
40556
- stage: previewStageSchema.optional(),
40557
40622
  supportEmail: z$1.string().optional(),
40558
40623
  sitePasses: publicPassProductCollectionSchema.nullable().optional(),
40559
40624
  siteMemberships: publicMembershipProductCollectionSchema.nullable().optional()
40625
+ };
40626
+ const eventRegistrationSourceSchema = z$1.object({
40627
+ siteId: z$1.string().optional(),
40628
+ apiBaseUrl: z$1.string().optional(),
40629
+ portalToken: z$1.string().nullable().optional(),
40630
+ previewToken: z$1.string().nullable().optional(),
40631
+ ...eventRegistrationHydrationSchemaShape,
40632
+ className: z$1.string().nullable().optional(),
40633
+ buttonText: z$1.string().nullable().optional(),
40634
+ maxTickets: z$1.string().nullable().optional(),
40635
+ stage: previewStageSchema.optional()
40560
40636
  });
40561
40637
  const eventRegistrationDisplaySchema = z$1.object({
40562
40638
  kind: z$1.literal("event-registration"),
@@ -40567,22 +40643,7 @@ const eventRegistrationDisplaySchema = z$1.object({
40567
40643
  stepLabels: z$1.array(z$1.enum(EVENT_REGISTRATION_SHELL_STEP_LABELS)).min(1),
40568
40644
  summaryButtonText: z$1.string()
40569
40645
  });
40570
- const eventRegistrationHydrationSchema = z$1.object({
40571
- occurrenceContext: occurrenceContextSchema$1.optional(),
40572
- subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
40573
- events: z$1.array(eventRegistrationPublicEventSchema).nullable().optional(),
40574
- maxTickets: z$1.string().optional(),
40575
- showVenue: z$1.boolean().optional(),
40576
- showCapacity: z$1.boolean().optional(),
40577
- successMessage: z$1.string().optional(),
40578
- waitlistMessage: z$1.string().optional(),
40579
- buttonVariant: registrationButtonVariantSchema.optional(),
40580
- overlayEnabled: z$1.boolean().optional(),
40581
- spamProtectionEnabled: z$1.boolean().optional(),
40582
- supportEmail: z$1.string().optional(),
40583
- sitePasses: publicPassProductCollectionSchema.nullable().optional(),
40584
- siteMemberships: publicMembershipProductCollectionSchema.nullable().optional()
40585
- });
40646
+ const eventRegistrationHydrationSchema = z$1.object(eventRegistrationHydrationSchemaShape);
40586
40647
  const eventRegistrationRenderSchema = z$1.object({
40587
40648
  display: eventRegistrationDisplaySchema,
40588
40649
  hydration: eventRegistrationHydrationSchema
@@ -40662,11 +40723,16 @@ const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
40662
40723
  occurrenceContext: source.occurrenceContext ?? null,
40663
40724
  subject: source.subject ?? null,
40664
40725
  events: source.events ?? null,
40726
+ wholeSeriesOfferings: source.wholeSeriesOfferings ?? null,
40727
+ wholeSeriesOffering: source.wholeSeriesOffering ?? null,
40665
40728
  maxTickets: source.maxTickets ?? void 0,
40666
40729
  showVenue: source.showVenue,
40667
40730
  showCapacity: source.showCapacity,
40731
+ showSessions: source.showSessions,
40732
+ showPrice: source.showPrice,
40668
40733
  successMessage: source.successMessage,
40669
40734
  waitlistMessage: source.waitlistMessage,
40735
+ membershipMessage: source.membershipMessage,
40670
40736
  buttonVariant: source.buttonVariant,
40671
40737
  overlayEnabled: source.overlayEnabled,
40672
40738
  spamProtectionEnabled: source.spamProtectionEnabled,
@@ -40701,202 +40767,6 @@ function buildEventRegistrationInteractiveIslandProps(props) {
40701
40767
  source: props
40702
40768
  });
40703
40769
  }
40704
- const eventRegistrationBlockDefinition = {
40705
- manifest: createBlockManifest({
40706
- id: "block.event-registration",
40707
- version: "1.0.0",
40708
- title: "Event Registration",
40709
- titleSource: "heading",
40710
- description: "Multi-step event registration form",
40711
- category: "interactive",
40712
- contentSource: { kind: "inline" },
40713
- tags: [
40714
- "events",
40715
- "registration",
40716
- "booking",
40717
- "form",
40718
- "signup"
40719
- ],
40720
- icon: "ClipboardList",
40721
- styleTokens: {
40722
- background: "surface",
40723
- typography: "body",
40724
- spacing: "md"
40725
- },
40726
- behaviours: {
40727
- supportsThemeSwitching: true,
40728
- inlineEditing: false,
40729
- animation: false,
40730
- paletteHidden: false
40731
- },
40732
- additionalFields: [
40733
- {
40734
- id: "heading",
40735
- type: "text",
40736
- label: "Heading",
40737
- description: "Main heading for the registration form",
40738
- required: false,
40739
- multiline: false,
40740
- defaultValue: "Register for this event"
40741
- },
40742
- {
40743
- id: "description",
40744
- type: "richText",
40745
- label: "Description",
40746
- description: "Optional introductory text",
40747
- required: false
40748
- },
40749
- {
40750
- id: "maxTickets",
40751
- type: "select",
40752
- label: "Max tickets per registration",
40753
- description: "Maximum tickets a person can register for",
40754
- required: false,
40755
- multiple: false,
40756
- defaultValue: "5",
40757
- options: [
40758
- {
40759
- value: "1",
40760
- label: "1 ticket"
40761
- },
40762
- {
40763
- value: "2",
40764
- label: "2 tickets"
40765
- },
40766
- {
40767
- value: "3",
40768
- label: "3 tickets"
40769
- },
40770
- {
40771
- value: "5",
40772
- label: "5 tickets"
40773
- },
40774
- {
40775
- value: "10",
40776
- label: "10 tickets"
40777
- }
40778
- ],
40779
- ui: { intent: "display" }
40780
- },
40781
- {
40782
- id: "showVenue",
40783
- type: "boolean",
40784
- label: "Show venue",
40785
- description: "Display venue information",
40786
- required: false,
40787
- defaultValue: true,
40788
- ui: { intent: "display" }
40789
- },
40790
- {
40791
- id: "showCapacity",
40792
- type: "boolean",
40793
- label: "Show available spots",
40794
- description: "Display remaining capacity",
40795
- required: false,
40796
- defaultValue: true,
40797
- ui: { intent: "display" }
40798
- },
40799
- {
40800
- id: "successMessage",
40801
- type: "text",
40802
- label: "Success message",
40803
- description: "Message shown after successful registration",
40804
- required: false,
40805
- multiline: true,
40806
- defaultValue: "Thank you for registering! Check your email for confirmation details.",
40807
- maxLength: 500
40808
- },
40809
- {
40810
- id: "buttonText",
40811
- type: "text",
40812
- label: "Submit button text",
40813
- description: "Text for the registration submit button",
40814
- required: false,
40815
- multiline: false,
40816
- defaultValue: "Complete Registration",
40817
- maxLength: 40
40818
- },
40819
- createButtonVariantField()
40820
- ],
40821
- layout: [styledSection({
40822
- baseClass: "",
40823
- spacing: "spacious",
40824
- children: sectionContainer([
40825
- text({ as: "h2" }, bind("content.heading"), when("content.heading")),
40826
- richText({ className: "rb-prose rb-max-w-none" }, bind("content.description"), when("content.description")),
40827
- eventRegistration(withApiBindings({
40828
- occurrenceContext: { $bind: { from: "$root.occurrenceContext" } },
40829
- subject: { $bind: { from: "$root.subject" } },
40830
- portalToken: { $bind: {
40831
- from: "$root.portalToken",
40832
- fallback: null
40833
- } },
40834
- maxTickets: { $bind: {
40835
- from: "content.maxTickets",
40836
- fallback: "5"
40837
- } },
40838
- showVenue: { $bind: { from: "content.showVenue" } },
40839
- showCapacity: { $bind: { from: "content.showCapacity" } },
40840
- successMessage: { $bind: { from: "content.successMessage" } },
40841
- waitlistMessage: { $bind: { from: "content.waitlistMessage" } },
40842
- buttonText: { $bind: {
40843
- from: "content.buttonText",
40844
- fallback: "Complete Registration"
40845
- } },
40846
- buttonVariant: { $bind: {
40847
- from: "content.buttonVariant",
40848
- fallback: "primary"
40849
- } },
40850
- overlayEnabled: { $bind: {
40851
- from: "$root.eventRegistrationOverlayEnabled",
40852
- fallback: false
40853
- } },
40854
- events: { $bind: { from: "data.events" } },
40855
- sitePasses: { $bind: { from: "data.sitePasses" } },
40856
- siteMemberships: { $bind: { from: "data.siteMemberships" } },
40857
- stage: { $bind: {
40858
- from: "$root.previewStage",
40859
- fallback: "published"
40860
- } }
40861
- }))
40862
- ], { gap: "lg" })
40863
- })]
40864
- }),
40865
- runtime: eventRegistrationBlockRuntime,
40866
- dataSchemas: {
40867
- events: publicEventsArraySchema.optional(),
40868
- sitePasses: publicPassProductCollectionSchema.optional(),
40869
- siteMemberships: publicMembershipProductCollectionSchema.optional(),
40870
- occurrenceContext: occurrenceContextSchema$1.optional()
40871
- },
40872
- dataLoaders: {
40873
- events: {
40874
- endpoint: "listPublicEvents",
40875
- params: {
40876
- siteId: { $bind: { from: "$root.siteId" } },
40877
- limit: "50",
40878
- stage: { $bind: {
40879
- from: "$root.previewStage",
40880
- fallback: "published"
40881
- } },
40882
- readProfile: "registration",
40883
- seriesId: { $bind: { from: "$root.occurrenceContext.seriesId" } },
40884
- includeOccurrenceId: { $bind: { from: "$root.occurrenceContext.id" } }
40885
- },
40886
- mode: "server"
40887
- },
40888
- sitePasses: {
40889
- endpoint: "listPublicPasses",
40890
- params: { siteId: { $bind: { from: "$root.siteId" } } },
40891
- mode: "server"
40892
- },
40893
- siteMemberships: {
40894
- endpoint: "listPublicMemberships",
40895
- params: { siteId: { $bind: { from: "$root.siteId" } } },
40896
- mode: "server"
40897
- }
40898
- }
40899
- };
40900
40770
  //#endregion
40901
40771
  //#region ../blocks/src/system/blocks/courses/shared/pricing.ts
40902
40772
  function isSaleWindowOpen(option, now) {
@@ -41050,6 +40920,257 @@ function formatCoursePriceAmount(amount, currency, locale) {
41050
40920
  currency
41051
40921
  }, locale);
41052
40922
  }
40923
+ const eventRegistrationBlockDefinition = {
40924
+ manifest: createBlockManifest({
40925
+ id: "block.event-registration",
40926
+ version: "1.0.0",
40927
+ title: "Event Registration",
40928
+ titleSource: "heading",
40929
+ description: "Multi-step event registration form",
40930
+ category: "interactive",
40931
+ contentSource: { kind: "inline" },
40932
+ tags: [
40933
+ "events",
40934
+ "registration",
40935
+ "booking",
40936
+ "form",
40937
+ "signup"
40938
+ ],
40939
+ icon: "ClipboardList",
40940
+ styleTokens: {
40941
+ background: "surface",
40942
+ typography: "body",
40943
+ spacing: "md"
40944
+ },
40945
+ behaviours: {
40946
+ supportsThemeSwitching: true,
40947
+ inlineEditing: false,
40948
+ animation: false,
40949
+ paletteHidden: false
40950
+ },
40951
+ additionalFields: [
40952
+ {
40953
+ id: "heading",
40954
+ type: "text",
40955
+ label: "Heading",
40956
+ description: "Main heading for the registration form",
40957
+ required: false,
40958
+ multiline: false,
40959
+ defaultValue: "Register for this event"
40960
+ },
40961
+ {
40962
+ id: "description",
40963
+ type: "richText",
40964
+ label: "Description",
40965
+ description: "Optional introductory text",
40966
+ required: false
40967
+ },
40968
+ {
40969
+ id: "maxTickets",
40970
+ type: "select",
40971
+ label: "Max tickets per registration",
40972
+ description: "Maximum tickets a person can register for",
40973
+ required: false,
40974
+ multiple: false,
40975
+ defaultValue: "5",
40976
+ options: [
40977
+ {
40978
+ value: "1",
40979
+ label: "1 ticket"
40980
+ },
40981
+ {
40982
+ value: "2",
40983
+ label: "2 tickets"
40984
+ },
40985
+ {
40986
+ value: "3",
40987
+ label: "3 tickets"
40988
+ },
40989
+ {
40990
+ value: "5",
40991
+ label: "5 tickets"
40992
+ },
40993
+ {
40994
+ value: "10",
40995
+ label: "10 tickets"
40996
+ }
40997
+ ],
40998
+ ui: { intent: "display" }
40999
+ },
41000
+ {
41001
+ id: "showVenue",
41002
+ type: "boolean",
41003
+ label: "Show venue",
41004
+ description: "Display venue information",
41005
+ required: false,
41006
+ defaultValue: true,
41007
+ ui: { intent: "display" }
41008
+ },
41009
+ {
41010
+ id: "showCapacity",
41011
+ type: "boolean",
41012
+ label: "Show available spots",
41013
+ description: "Display remaining capacity",
41014
+ required: false,
41015
+ defaultValue: true,
41016
+ ui: { intent: "display" }
41017
+ },
41018
+ {
41019
+ id: "showSessions",
41020
+ type: "boolean",
41021
+ label: "Show complete schedule",
41022
+ description: "Display every session for whole-series registrations",
41023
+ required: false,
41024
+ defaultValue: true,
41025
+ ui: { intent: "display" }
41026
+ },
41027
+ {
41028
+ id: "showPrice",
41029
+ type: "boolean",
41030
+ label: "Show price",
41031
+ description: "Display the whole-series price",
41032
+ required: false,
41033
+ defaultValue: true,
41034
+ ui: { intent: "display" }
41035
+ },
41036
+ {
41037
+ id: "successMessage",
41038
+ type: "text",
41039
+ label: "Success message",
41040
+ description: "Message shown after successful registration",
41041
+ required: false,
41042
+ multiline: true,
41043
+ defaultValue: "Thank you for registering! Check your email for confirmation details.",
41044
+ maxLength: 500
41045
+ },
41046
+ {
41047
+ id: "waitlistMessage",
41048
+ type: "text",
41049
+ label: "Waitlist message",
41050
+ description: "Message shown after joining a whole-series waitlist",
41051
+ required: false,
41052
+ multiline: true,
41053
+ defaultValue: "You've been added to the waitlist. We'll email you if a place becomes available.",
41054
+ maxLength: 500
41055
+ },
41056
+ {
41057
+ id: "membershipMessage",
41058
+ type: "text",
41059
+ label: "Membership registration message",
41060
+ description: "Message shown when a whole-series place is covered by membership",
41061
+ required: false,
41062
+ multiline: true,
41063
+ defaultValue: "Registered using your membership. Check your email for session details.",
41064
+ maxLength: 500
41065
+ },
41066
+ {
41067
+ id: "buttonText",
41068
+ type: "text",
41069
+ label: "Submit button text",
41070
+ description: "Text for the registration submit button",
41071
+ required: false,
41072
+ multiline: false,
41073
+ defaultValue: "Complete Registration",
41074
+ maxLength: 40
41075
+ },
41076
+ createButtonVariantField()
41077
+ ],
41078
+ layout: [styledSection({
41079
+ baseClass: "",
41080
+ spacing: "spacious",
41081
+ children: sectionContainer([
41082
+ text({ as: "h2" }, bind("content.heading"), when("content.heading")),
41083
+ richText({ className: "rb-prose rb-max-w-none" }, bind("content.description"), when("content.description")),
41084
+ eventRegistration(withApiBindings({
41085
+ occurrenceContext: { $bind: { from: "$root.occurrenceContext" } },
41086
+ subject: { $bind: { from: "$root.subject" } },
41087
+ portalToken: { $bind: {
41088
+ from: "$root.portalToken",
41089
+ fallback: null
41090
+ } },
41091
+ maxTickets: { $bind: {
41092
+ from: "content.maxTickets",
41093
+ fallback: "5"
41094
+ } },
41095
+ showVenue: { $bind: { from: "content.showVenue" } },
41096
+ showCapacity: { $bind: { from: "content.showCapacity" } },
41097
+ showSessions: { $bind: { from: "content.showSessions" } },
41098
+ showPrice: { $bind: { from: "content.showPrice" } },
41099
+ successMessage: { $bind: { from: "content.successMessage" } },
41100
+ waitlistMessage: { $bind: { from: "content.waitlistMessage" } },
41101
+ membershipMessage: { $bind: { from: "content.membershipMessage" } },
41102
+ buttonText: { $bind: {
41103
+ from: "content.buttonText",
41104
+ fallback: "Complete Registration"
41105
+ } },
41106
+ buttonVariant: { $bind: {
41107
+ from: "content.buttonVariant",
41108
+ fallback: "primary"
41109
+ } },
41110
+ overlayEnabled: { $bind: {
41111
+ from: "$root.eventRegistrationOverlayEnabled",
41112
+ fallback: false
41113
+ } },
41114
+ events: { $bind: { from: "data.events" } },
41115
+ wholeSeriesOffering: { $bind: { from: "data.wholeSeriesOffering.offering" } },
41116
+ sitePasses: { $bind: { from: "data.sitePasses" } },
41117
+ siteMemberships: { $bind: { from: "data.siteMemberships" } },
41118
+ stage: { $bind: {
41119
+ from: "$root.previewStage",
41120
+ fallback: "published"
41121
+ } }
41122
+ }))
41123
+ ], { gap: "lg" })
41124
+ })]
41125
+ }),
41126
+ runtime: eventRegistrationBlockRuntime,
41127
+ dataSchemas: {
41128
+ events: publicEventsArraySchema.optional(),
41129
+ wholeSeriesOffering: z$1.object({ offering: publicCourseSchema }).optional(),
41130
+ sitePasses: publicPassProductCollectionSchema.optional(),
41131
+ siteMemberships: publicMembershipProductCollectionSchema.optional(),
41132
+ occurrenceContext: occurrenceContextSchema.optional()
41133
+ },
41134
+ dataLoaders: {
41135
+ events: {
41136
+ endpoint: "listPublicEvents",
41137
+ params: {
41138
+ siteId: { $bind: { from: "$root.siteId" } },
41139
+ limit: "50",
41140
+ stage: { $bind: {
41141
+ from: "$root.previewStage",
41142
+ fallback: "published"
41143
+ } },
41144
+ readProfile: "registration",
41145
+ seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
41146
+ includeOccurrenceId: { $bind: { from: "$root.occurrenceContext.id" } }
41147
+ },
41148
+ mode: "server"
41149
+ },
41150
+ wholeSeriesOffering: {
41151
+ endpoint: "getPublicWholeSeriesOffering",
41152
+ params: {
41153
+ siteId: { $bind: { from: "$root.siteId" } },
41154
+ eventSeriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
41155
+ stage: { $bind: {
41156
+ from: "$root.previewStage",
41157
+ fallback: "published"
41158
+ } }
41159
+ },
41160
+ mode: "server"
41161
+ },
41162
+ sitePasses: {
41163
+ endpoint: "listPublicPasses",
41164
+ params: { siteId: { $bind: { from: "$root.siteId" } } },
41165
+ mode: "server"
41166
+ },
41167
+ siteMemberships: {
41168
+ endpoint: "listPublicMemberships",
41169
+ params: { siteId: { $bind: { from: "$root.siteId" } } },
41170
+ mode: "server"
41171
+ }
41172
+ }
41173
+ };
41053
41174
  //#endregion
41054
41175
  //#region ../blocks/src/system/runtime/nodes/course-registration.interactive.ts
41055
41176
  const courseRegistrationSourceSchema = z$1.object({
@@ -41485,15 +41606,6 @@ const eventDetailsManifest = createBlockManifest({
41485
41606
  })], { gap: "lg" })
41486
41607
  })]
41487
41608
  });
41488
- const occurrenceContextSchema = z$1.object({
41489
- id: z$1.string(),
41490
- seriesId: z$1.string(),
41491
- startsAt: z$1.string(),
41492
- endsAt: z$1.string(),
41493
- timeZone: z$1.string(),
41494
- capacityOverride: z$1.number().nullable().optional(),
41495
- overrides: z$1.record(z$1.string(), z$1.unknown()).nullable().optional()
41496
- }).nullable();
41497
41609
  const eventAutoApplyDiscountPreviewBaseSchema = z$1.object({
41498
41610
  id: z$1.string(),
41499
41611
  publicLabel: z$1.string(),
@@ -41528,8 +41640,9 @@ const eventDetailsBlockDefinition = {
41528
41640
  from: "$root.previewStage",
41529
41641
  fallback: "published"
41530
41642
  } },
41531
- limit: "25",
41532
- seriesId: { $bind: { from: "$root.occurrenceContext.seriesId" } },
41643
+ limit: "100",
41644
+ readProfile: "details",
41645
+ seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
41533
41646
  includeOccurrenceId: { $bind: { from: "$root.occurrenceContext.id" } }
41534
41647
  },
41535
41648
  mode: "server"
@@ -50294,9 +50407,6 @@ function parseSignedNewsletterDestinationRef(value) {
50294
50407
  const trimmed = parseTrimmedString$1(value);
50295
50408
  return trimmed && SIGNED_DESTINATION_REF_PATTERN.test(trimmed) ? trimmed : null;
50296
50409
  }
50297
- function parseNewsletterSignupDestinationProvider(value) {
50298
- return value === "riverbank" || value === "mailchimp" ? value : null;
50299
- }
50300
50410
  function buildNewsletterSignupBlockRef(blockId) {
50301
50411
  const parsed = parseNewsletterSignupBlockId(blockId);
50302
50412
  return parsed ? {
@@ -50463,19 +50573,9 @@ const newsletterFieldSchema = z$1.object({
50463
50573
  });
50464
50574
  const newsletterSignupBlockIdSchema = z$1.string().trim().min(1).transform(parseRequiredNewsletterSignupBlockId);
50465
50575
  const signedNewsletterDestinationRefSchema = z$1.string().trim().min(1).transform(parseRequiredSignedNewsletterDestinationRef);
50466
- const newsletterPublicDestinationRefSchema = z$1.discriminatedUnion("tag", [z$1.object({
50467
- tag: z$1.literal("block_ref"),
50468
- blockId: newsletterSignupBlockIdSchema
50469
- }), z$1.object({
50470
- tag: z$1.literal("signed_destination_ref"),
50471
- token: signedNewsletterDestinationRefSchema
50472
- })]);
50473
- const newsletterSourceSchema = z$1.object({
50474
- blockId: z$1.string().nullable().optional(),
50576
+ const newsletterSourceCommonSchema = z$1.object({
50475
50577
  siteId: z$1.string().optional(),
50476
50578
  apiBaseUrl: z$1.string().optional(),
50477
- listId: z$1.string().nullable().optional(),
50478
- destinationProvider: newsletterDestinationProviderSchema.nullable().optional(),
50479
50579
  preset: newsletterPresetSchema.optional(),
50480
50580
  includePhone: z$1.boolean().optional(),
50481
50581
  buttonLabel: z$1.string().nullable().optional(),
@@ -50486,6 +50586,25 @@ const newsletterSourceSchema = z$1.object({
50486
50586
  spamProtectionEnabled: z$1.boolean().optional(),
50487
50587
  className: z$1.string().nullable().optional()
50488
50588
  });
50589
+ const newsletterSourceSchema = z$1.discriminatedUnion("source", [
50590
+ newsletterSourceCommonSchema.extend({
50591
+ source: z$1.literal("block"),
50592
+ blockId: z$1.string().nullable().optional(),
50593
+ listId: z$1.string().nullable().optional(),
50594
+ destinationProvider: newsletterDestinationProviderSchema.nullable().optional()
50595
+ }),
50596
+ newsletterSourceCommonSchema.extend({
50597
+ source: z$1.literal("signed-footer"),
50598
+ destinationRef: z$1.object({
50599
+ tag: z$1.literal("signed_destination_ref"),
50600
+ token: signedNewsletterDestinationRefSchema
50601
+ })
50602
+ }),
50603
+ newsletterSourceCommonSchema.extend({
50604
+ source: z$1.literal("legacy-direct-list"),
50605
+ listId: z$1.string().nullable()
50606
+ })
50607
+ ]);
50489
50608
  const newsletterDisplaySchema = z$1.object({
50490
50609
  kind: z$1.literal("newsletter-form"),
50491
50610
  className: z$1.string().nullable(),
@@ -50496,8 +50615,26 @@ const newsletterDisplaySchema = z$1.object({
50496
50615
  fields: z$1.array(newsletterFieldSchema)
50497
50616
  });
50498
50617
  const newsletterHydrationSchema = z$1.object({
50499
- destinationRef: newsletterPublicDestinationRefSchema.nullable().optional(),
50500
- listId: z$1.string().nullable().optional(),
50618
+ target: z$1.discriminatedUnion("tag", [
50619
+ z$1.object({
50620
+ tag: z$1.literal("block-source"),
50621
+ destinationRef: z$1.object({
50622
+ tag: z$1.literal("block_ref"),
50623
+ blockId: newsletterSignupBlockIdSchema
50624
+ }).nullable()
50625
+ }),
50626
+ z$1.object({
50627
+ tag: z$1.literal("signed-footer-source"),
50628
+ destinationRef: z$1.object({
50629
+ tag: z$1.literal("signed_destination_ref"),
50630
+ token: signedNewsletterDestinationRefSchema
50631
+ })
50632
+ }),
50633
+ z$1.object({
50634
+ tag: z$1.literal("legacy-direct-list"),
50635
+ listId: z$1.string().nullable()
50636
+ })
50637
+ ]),
50501
50638
  preset: newsletterPresetSchema,
50502
50639
  includePhone: z$1.boolean(),
50503
50640
  tags: z$1.string().nullable().optional(),
@@ -50531,20 +50668,43 @@ const newsletterFormBlockRuntime = defineProgressiveBlockRuntime({
50531
50668
  render: createZodCodec(newsletterRenderSchema)
50532
50669
  },
50533
50670
  buildRender: (source) => {
50534
- const runtimeSource = deriveNewsletterSignupRuntimeSource(source);
50671
+ const runtimeSource = source.source === "block" ? deriveNewsletterSignupRuntimeSource(source) : null;
50535
50672
  return {
50536
50673
  display: buildNewsletterDisplay(source),
50537
50674
  hydration: {
50538
- destinationRef: buildNewsletterSignupBlockRef(source.blockId),
50539
- listId: runtimeSource.listId,
50675
+ target: projectNewsletterFormHydrationTarget(source),
50540
50676
  preset: source.preset ?? "emailOnly",
50541
50677
  includePhone: source.includePhone ?? false,
50542
- tags: runtimeSource.tags,
50678
+ tags: runtimeSource ? runtimeSource.tags : source.tags,
50543
50679
  spamProtectionEnabled: source.spamProtectionEnabled
50544
50680
  }
50545
50681
  };
50546
50682
  }
50547
50683
  });
50684
+ function projectNewsletterFormHydrationTarget(source) {
50685
+ switch (source.source) {
50686
+ case "block": {
50687
+ const destinationRef = buildNewsletterSignupBlockRef(source.blockId);
50688
+ if (destinationRef?.tag === "block_ref") return {
50689
+ tag: "block-source",
50690
+ destinationRef
50691
+ };
50692
+ return {
50693
+ tag: "legacy-direct-list",
50694
+ listId: source.listId ?? null
50695
+ };
50696
+ }
50697
+ case "signed-footer": return {
50698
+ tag: "signed-footer-source",
50699
+ destinationRef: source.destinationRef
50700
+ };
50701
+ case "legacy-direct-list": return {
50702
+ tag: "legacy-direct-list",
50703
+ listId: source.listId
50704
+ };
50705
+ default: return assertNever$24(source);
50706
+ }
50707
+ }
50548
50708
  function buildNewsletterFormInteractiveIslandProps(props) {
50549
50709
  return buildInteractiveIslandProps({
50550
50710
  runtime: newsletterFormBlockRuntime,
@@ -54870,6 +55030,33 @@ function uniqByOccurrenceId(events) {
54870
55030
  }
54871
55031
  return out;
54872
55032
  }
55033
+ function selectFromOccurrenceContext(events, occurrenceContext) {
55034
+ if (!occurrenceContext) return null;
55035
+ const byId = events.find((event) => event.occurrenceId === occurrenceContext.id || event.id === occurrenceContext.id);
55036
+ if (byId) return byId;
55037
+ const contextDate = getBookingLocalDateKey(toScheduledBookingDateTime({
55038
+ startsAt: occurrenceContext.startsAt,
55039
+ timeZone: occurrenceContext.timeZone
55040
+ }));
55041
+ return events.find((event) => getBookingLocalDateKey(toScheduledBookingDateTime({
55042
+ startsAt: event.startsAt,
55043
+ timeZone: event.timeZone
55044
+ })) === contextDate) ?? null;
55045
+ }
55046
+ function selectNextUpcoming(events, nowIso) {
55047
+ return [...events].filter((event) => isFutureOrNow(event.startsAt, nowIso)).sort((left, right) => Date.parse(left.startsAt) - Date.parse(right.startsAt))[0] ?? null;
55048
+ }
55049
+ function selectCompletedWholeSeries(events) {
55050
+ if (events.length === 0 || !events.every((event) => event.bookingScope === "whole_series")) return null;
55051
+ return [...events].sort((left, right) => Date.parse(right.startsAt) - Date.parse(left.startsAt))[0] ?? null;
55052
+ }
55053
+ function selectRelatedDates(input) {
55054
+ if (!input.seriesId) return [];
55055
+ const isWholeSeries = input.selected?.bookingScope === "whole_series";
55056
+ const selectedOccurrenceId = input.selected ? input.selected.occurrenceId || input.selected.id : null;
55057
+ const dates = input.events.filter((event) => event.seriesId === input.seriesId).filter((event) => isWholeSeries || isFutureOrNow(event.startsAt, input.nowIso)).filter((event) => !selectedOccurrenceId || (event.occurrenceId || event.id) !== selectedOccurrenceId).sort((left, right) => Date.parse(left.startsAt) - Date.parse(right.startsAt));
55058
+ return isWholeSeries ? dates : dates.slice(0, input.limit);
55059
+ }
54873
55060
  function selectEventDetails(args) {
54874
55061
  const all = uniqByOccurrenceId(resolveEventRegistrationScopedEvents((args.events ?? []).filter(Boolean), {
54875
55062
  occurrenceContext: args.occurrenceContext,
@@ -54877,37 +55064,22 @@ function selectEventDetails(args) {
54877
55064
  }));
54878
55065
  const occurrenceContext = args.occurrenceContext ?? null;
54879
55066
  const otherLimit = parseLimit$1(args.otherDatesLimit, 5);
54880
- const selectedFromContext = (() => {
54881
- if (!occurrenceContext) return null;
54882
- const byId = all.find((e) => e.occurrenceId === occurrenceContext.id || e.id === occurrenceContext.id) ?? null;
54883
- if (byId) return byId;
54884
- const ctxDate = getBookingLocalDateKey(toScheduledBookingDateTime({
54885
- startsAt: occurrenceContext.startsAt,
54886
- timeZone: occurrenceContext.timeZone
54887
- }));
54888
- return all.find((e) => getBookingLocalDateKey(toScheduledBookingDateTime({
54889
- startsAt: e.startsAt,
54890
- timeZone: e.timeZone
54891
- })) === ctxDate) ?? null;
54892
- })();
54893
- const nextUpcoming = (() => {
54894
- const upcoming = all.filter((e) => isFutureOrNow(e.startsAt, args.nowIso));
54895
- upcoming.sort((a, b) => Date.parse(a.startsAt) - Date.parse(b.startsAt));
54896
- return upcoming[0] ?? null;
54897
- })();
54898
- const mode = selectedFromContext ? "selected" : "next";
54899
- const selected = selectedFromContext ?? nextUpcoming;
55067
+ const selectedFromContext = selectFromOccurrenceContext(all, occurrenceContext);
55068
+ const nextUpcoming = selectNextUpcoming(all, args.nowIso);
55069
+ const completedWholeSeries = selectCompletedWholeSeries(all);
55070
+ const selected = selectedFromContext ?? nextUpcoming ?? completedWholeSeries;
55071
+ const mode = selectedFromContext ? "selected" : nextUpcoming ? "next" : completedWholeSeries ? "completed" : "next";
54900
55072
  const timeZone = toBookingTimeZone(selected?.timeZone ?? all[0]?.timeZone ?? null);
54901
- const seriesId = occurrenceContext?.seriesId ?? selected?.seriesId ?? all[0]?.seriesId ?? null;
54902
- const selectedOccurrenceId = selected?.occurrenceId ?? null;
54903
55073
  return {
54904
55074
  mode,
54905
55075
  selected,
54906
- otherDates: seriesId ? all.filter((e) => e.seriesId === seriesId).filter((e) => isFutureOrNow(e.startsAt, args.nowIso)).filter((e) => {
54907
- const occId = e.occurrenceId || e.id;
54908
- if (selectedOccurrenceId && occId === selectedOccurrenceId) return false;
54909
- return true;
54910
- }).slice(0, otherLimit) : [],
55076
+ otherDates: selectRelatedDates({
55077
+ events: all,
55078
+ seriesId: occurrenceContext?.seriesId ?? selected?.seriesId ?? all[0]?.seriesId ?? null,
55079
+ selected,
55080
+ nowIso: args.nowIso,
55081
+ limit: otherLimit
55082
+ }),
54911
55083
  timeZone
54912
55084
  };
54913
55085
  }
@@ -55029,7 +55201,7 @@ function EventFacts({ selection, selected, venue, teamMembers, pricing }) {
55029
55201
  /* @__PURE__ */ jsxs("div", { children: [
55030
55202
  /* @__PURE__ */ jsx("div", {
55031
55203
  className: "rb-label rb-mb-2",
55032
- children: selection.mode === "next" ? "Next date" : "Date"
55204
+ children: selected.bookingScope === "whole_series" ? selection.mode === "next" ? "Next session" : "Selected session" : selection.mode === "next" ? "Next date" : "Date"
55033
55205
  }),
55034
55206
  /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: date }) }),
55035
55207
  /* @__PURE__ */ jsx("p", {
@@ -55067,18 +55239,27 @@ function EventFacts({ selection, selected, venue, teamMembers, pricing }) {
55067
55239
  }) : null] }, member.id))
55068
55240
  })]
55069
55241
  }) : null,
55070
- pricing
55242
+ pricing,
55243
+ selected.bookingScope === "whole_series" ? /* @__PURE__ */ jsxs("div", {
55244
+ className: "rb-mt-6",
55245
+ children: [/* @__PURE__ */ jsx("div", {
55246
+ className: "rb-label rb-mb-2",
55247
+ children: "Registration"
55248
+ }), /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: selected.wholeSeries?.enrollmentOpen ? "Open" : "Closed" }) })]
55249
+ }) : null
55071
55250
  ]
55072
55251
  });
55073
55252
  }
55074
55253
  function OtherEventDates({ selection }) {
55075
- if (selection.otherDates.length === 0) return null;
55254
+ const isWholeSeries = selection.selected?.bookingScope === "whole_series";
55255
+ const dates = isWholeSeries && selection.selected ? [selection.selected, ...selection.otherDates].sort((left, right) => Date.parse(left.startsAt) - Date.parse(right.startsAt)) : selection.otherDates;
55256
+ if (dates.length === 0) return null;
55076
55257
  return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
55077
55258
  className: "rb-label",
55078
- children: "Other dates"
55259
+ children: isWholeSeries ? "Session schedule" : "Other dates"
55079
55260
  }), /* @__PURE__ */ jsx("div", {
55080
55261
  className: "rb-mt-2 rb-tiles-grid",
55081
- children: selection.otherDates.map((event) => /* @__PURE__ */ jsx("a", {
55262
+ children: dates.map((event) => /* @__PURE__ */ jsx("a", {
55082
55263
  className: "rb-tile rb-tile--interactive",
55083
55264
  ...resolveEventLinkProps(event),
55084
55265
  children: /* @__PURE__ */ jsx(DateTimeTile, {
@@ -58277,13 +58458,13 @@ const FormNodeSSR = ({ blockId, value, submitLabel, successMessage, className, o
58277
58458
  * Renders the newsletter signup form for SSR with hydration support.
58278
58459
  * Uses the islands architecture pattern to hydrate on the client.
58279
58460
  */
58280
- function NewsletterFormSSR({ blockId, siteId, apiBaseUrl, listId, destinationProvider, preset = "emailOnly", includePhone, buttonLabel = "Subscribe", buttonVariant = "primary", successMessage, privacyNote, tags, spamProtectionEnabled, className }) {
58461
+ function NewsletterFormSSR(props) {
58462
+ const { siteId, apiBaseUrl, preset = "emailOnly", includePhone, buttonLabel = "Subscribe", buttonVariant = "primary", successMessage, privacyNote, tags, spamProtectionEnabled, className } = props;
58463
+ const blockId = props.source === "block" ? props.blockId : null;
58281
58464
  const islandProps = buildNewsletterFormInteractiveIslandProps({
58282
- blockId,
58465
+ ...props,
58283
58466
  siteId,
58284
58467
  apiBaseUrl,
58285
- listId,
58286
- destinationProvider,
58287
58468
  preset,
58288
58469
  includePhone,
58289
58470
  buttonLabel,
@@ -59911,6 +60092,213 @@ function collectConstrainedVideoMediaValues(options) {
59911
60092
  return values;
59912
60093
  }
59913
60094
  //#endregion
60095
+ //#region ../blocks/src/system/manifest/hydrateLinks.ts
60096
+ /**
60097
+ * Hydrates link objects within block content using the provided route map. Returns
60098
+ * the original content reference when no mutations are required to avoid unnecessary renders.
60099
+ */
60100
+ function hydrateManifestLinks(manifest, content, routes, pagesByIdentifier, entriesByIdentifier) {
60101
+ if (!routes || !manifest?.fields?.length) return content;
60102
+ return hydrateValue(content, {
60103
+ routes,
60104
+ pagesByIdentifier,
60105
+ entriesByIdentifier
60106
+ });
60107
+ }
60108
+ function hydrateValue(value, context) {
60109
+ try {
60110
+ if (Array.isArray(value)) {
60111
+ const resolvedItems = value.map((item) => hydrateValue(item, context));
60112
+ return resolvedItems.every((item, index) => item === value[index]) ? value : resolvedItems;
60113
+ }
60114
+ if (isRecord$26(value)) {
60115
+ if (isInternalLink$1(value)) return hydrateInternalLink(value, context.routes);
60116
+ if (isPageLink$1(value)) return hydratePageLink(value, context);
60117
+ if (isEntryLink$1(value)) return hydrateEntryLink(value, context);
60118
+ const resolvedEntries = Object.entries(value).map(([key, entry]) => [key, hydrateValue(entry, context)]);
60119
+ return resolvedEntries.every(([key, entry]) => entry === value[key]) ? value : Object.fromEntries(resolvedEntries);
60120
+ }
60121
+ return value;
60122
+ } catch (err) {
60123
+ console.error("[hydrateLinks] Error hydrating value:", err, value);
60124
+ return value;
60125
+ }
60126
+ }
60127
+ function hydrateInternalLink(link, routes) {
60128
+ const resolved = resolveRouteTarget(link.routeId, routes);
60129
+ if (!resolved) return link;
60130
+ const nextHref = resolved.href;
60131
+ const currentHref = typeof link.href === "string" && link.href.length > 0 ? link.href : null;
60132
+ const nextUpdatedAt = resolved.updatedAt;
60133
+ const updates = {};
60134
+ if (nextHref && nextHref !== currentHref) updates.href = nextHref;
60135
+ if (nextUpdatedAt && link.updatedAt !== nextUpdatedAt) updates.updatedAt = nextUpdatedAt;
60136
+ return Object.keys(updates).length > 0 ? {
60137
+ ...link,
60138
+ ...updates
60139
+ } : link;
60140
+ }
60141
+ function isInternalLink$1(value) {
60142
+ if (value.kind !== "internal") return false;
60143
+ if (typeof value.routeId !== "string" || value.routeId.length === 0) return false;
60144
+ return true;
60145
+ }
60146
+ function isPageLink$1(value) {
60147
+ if (value.kind !== "page") return false;
60148
+ if (typeof value.identifier !== "string" || value.identifier.length === 0) return false;
60149
+ return true;
60150
+ }
60151
+ function hydratePageLink(link, context) {
60152
+ const resolved = resolvePageRouteTarget(link, context);
60153
+ if (!resolved) return link;
60154
+ return {
60155
+ ...link,
60156
+ href: resolved.href,
60157
+ routeId: resolved.routeId
60158
+ };
60159
+ }
60160
+ function isEntryLink$1(value) {
60161
+ if (value.kind !== "entry") return false;
60162
+ if (typeof value.contentType !== "string" || value.contentType.length === 0) return false;
60163
+ if (typeof value.identifier !== "string" || value.identifier.length === 0) return false;
60164
+ return true;
60165
+ }
60166
+ function hydrateEntryLink(link, context) {
60167
+ const resolved = resolveEntryRouteTarget(link, context);
60168
+ if (!resolved) return link;
60169
+ return {
60170
+ ...link,
60171
+ href: resolved.href,
60172
+ routeId: resolved.routeId
60173
+ };
60174
+ }
60175
+ //#endregion
60176
+ //#region ../blocks/src/sdkBlockTransform.ts
60177
+ /**
60178
+ * Transforms an SDK custom block into a BlockManifest.
60179
+ *
60180
+ * If the block has a `layout`, it can be rendered declaratively without React code.
60181
+ * If no layout, the block MUST use blockOverrides for rendering.
60182
+ */
60183
+ function transformSdkBlockToManifest(sdkBlock) {
60184
+ const hasLayout = Boolean(sdkBlock.layout) || Boolean(sdkBlock.variants && Object.keys(sdkBlock.variants).length > 0);
60185
+ return augmentManifest({
60186
+ name: sdkBlock.id,
60187
+ version: "1.0.0",
60188
+ title: sdkBlock.title,
60189
+ titleSource: sdkBlock.titleSource,
60190
+ description: sdkBlock.description,
60191
+ component: sdkBlock.id,
60192
+ fields: sdkBlock.fields,
60193
+ slots: [],
60194
+ category: sdkBlock.category,
60195
+ tags: sdkBlock.tags,
60196
+ icon: sdkBlock.icon,
60197
+ layout: sdkBlock.layout,
60198
+ variants: sdkBlock.variants,
60199
+ defaultVariant: sdkBlock.defaultVariant,
60200
+ variantOptions: sdkBlock.variantOptions,
60201
+ previewCustomize: sdkBlock.previewCustomize,
60202
+ behaviours: {
60203
+ supportsThemeSwitching: true,
60204
+ inlineEditing: hasLayout,
60205
+ animation: hasLayout,
60206
+ paletteHidden: false
60207
+ }
60208
+ });
60209
+ }
60210
+ /**
60211
+ * Transforms an SDK custom block into a SystemBlockDefinition.
60212
+ *
60213
+ * This creates a minimal definition with just the manifest - no data loaders
60214
+ * or content normalizers since SDK blocks handle their own rendering.
60215
+ */
60216
+ function transformSdkBlockToDefinition(sdkBlock) {
60217
+ return {
60218
+ manifest: transformSdkBlockToManifest(sdkBlock),
60219
+ dataLoaders: sdkBlock.dataLoaders
60220
+ };
60221
+ }
60222
+ //#endregion
60223
+ //#region ../blocks/src/customBlockRegistry.ts
60224
+ const defaultCustomBlockSourcePolicy = { kind: "canonical-db-fallback-sdk" };
60225
+ function isCustomBlockKind(blockKind) {
60226
+ return blockKind.startsWith("custom.");
60227
+ }
60228
+ function transformToBlockDescriptor(sdkBlock, source = "sdk") {
60229
+ return {
60230
+ name: sdkBlock.id,
60231
+ title: sdkBlock.title,
60232
+ description: sdkBlock.description,
60233
+ category: sdkBlock.category,
60234
+ tags: sdkBlock.tags,
60235
+ icon: sdkBlock.icon,
60236
+ definition: transformSdkBlockToDefinition(sdkBlock),
60237
+ source
60238
+ };
60239
+ }
60240
+ function toResolvedCustomBlock(manifest, source) {
60241
+ return {
60242
+ blockKind: manifest.id,
60243
+ manifest: transformSdkBlockToManifest(manifest),
60244
+ source,
60245
+ descriptor: transformToBlockDescriptor(manifest, source.kind === "managed-database" ? "database" : "sdk")
60246
+ };
60247
+ }
60248
+ function planCustomBlockRegistryResolution({ sdkConfig, customBlocks = [], policy = defaultCustomBlockSourcePolicy }) {
60249
+ switch (policy.kind) {
60250
+ case "canonical-db-fallback-sdk": {
60251
+ const entriesByKind = /* @__PURE__ */ new Map();
60252
+ const conflicts = [];
60253
+ for (const customBlock of customBlocks) entriesByKind.set(customBlock.manifest.id, toResolvedCustomBlock(customBlock.manifest, customBlock.source));
60254
+ for (const sdkBlock of sdkConfig?.customBlocks ?? []) {
60255
+ const existing = entriesByKind.get(sdkBlock.id);
60256
+ if (existing) {
60257
+ conflicts.push({
60258
+ kind: "conflict",
60259
+ blockKind: existing.blockKind,
60260
+ winner: existing.source,
60261
+ loser: { kind: "sdk-config" },
60262
+ reason: "db-canonical-sdk-fallback"
60263
+ });
60264
+ continue;
60265
+ }
60266
+ entriesByKind.set(sdkBlock.id, toResolvedCustomBlock(sdkBlock, { kind: "sdk-config" }));
60267
+ }
60268
+ return {
60269
+ policy,
60270
+ entries: Array.from(entriesByKind.values()),
60271
+ conflicts
60272
+ };
60273
+ }
60274
+ }
60275
+ }
60276
+ function createCustomBlockRegistry({ sdkConfig, customBlocks = [], policy = defaultCustomBlockSourcePolicy, onConflict }) {
60277
+ const plan = planCustomBlockRegistryResolution({
60278
+ sdkConfig,
60279
+ customBlocks,
60280
+ policy
60281
+ });
60282
+ const entriesByKind = new Map(plan.entries.map((entry) => [entry.blockKind, entry]));
60283
+ for (const conflict of plan.conflicts) onConflict?.(`Using ${sourceLabel(conflict.winner)} custom block "${conflict.blockKind}" - ${sourceLabel(conflict.loser)} block is fallback only`);
60284
+ return {
60285
+ entries: plan.entries,
60286
+ conflicts: plan.conflicts,
60287
+ findManifest: (blockKind) => {
60288
+ if (!isCustomBlockKind(blockKind)) return void 0;
60289
+ return entriesByKind.get(blockKind);
60290
+ }
60291
+ };
60292
+ }
60293
+ function sourceLabel(source) {
60294
+ switch (source.kind) {
60295
+ case "managed-database": return "DB";
60296
+ case "sdk-synced": return "SDK-synced DB";
60297
+ case "sdk-config": return "SDK config";
60298
+ default: return assertNever$24(source);
60299
+ }
60300
+ }
60301
+ //#endregion
59914
60302
  //#region ../theme-core/src/runtime/fontFamily.ts
59915
60303
  /**
59916
60304
  * Font Family Formatting Utilities
@@ -60585,30 +60973,24 @@ const NAV_DROPDOWN_CONTAINER_RAIL_CSS_RULES = [
60585
60973
  ];
60586
60974
  //#endregion
60587
60975
  //#region ../theme-core/src/header/surfaceRules.ts
60588
- /** Compile the visual surface declarations independently of paint geometry. */
60589
- function buildHeaderSurfaceRules(header, tokens, blur) {
60976
+ /** Compile the at-rest surface independently of scroll treatment and paint geometry. */
60977
+ function buildHeaderSurfaceRules(header, tokens) {
60590
60978
  const base = [];
60591
- const scrolled = [];
60592
60979
  const background = header.background;
60593
60980
  if (background.type === "color") base.push(`background-color: ${tokens.getColor(background.color || "surface")};`);
60594
60981
  else if (background.type === "gradient" && background.gradient) {
60595
60982
  const stops = background.gradient.stops.map((stop) => tokens.getColor(stop.color)).join(", ");
60596
60983
  base.push(`background-image: linear-gradient(${background.gradient.angle ?? 180}deg, ${stops});`);
60597
60984
  }
60598
- const blurRules = [`backdrop-filter: ${blur};`, `-webkit-backdrop-filter: ${blur};`];
60599
- base.push(...blurRules);
60600
- scrolled.push(...blurRules);
60601
60985
  const borderWidth = getComponentBorderWidthPx(header.border?.width ?? "none");
60602
60986
  if (!header.border || borderWidth === "0") return {
60603
60987
  base,
60604
- scrolled,
60605
60988
  border: []
60606
60989
  };
60607
60990
  const color = rgbColorValue(header.border.colorToken?.trim() || "border");
60608
60991
  const style = header.border.style === "dashed" ? "dashed" : "solid";
60609
60992
  return {
60610
60993
  base,
60611
- scrolled,
60612
60994
  border: header.border.position === "both" ? [`border-top: ${borderWidth} ${style} ${color};`, `border-bottom: ${borderWidth} ${style} ${color};`] : [`border-${header.border.position}: ${borderWidth} ${style} ${color};`]
60613
60995
  };
60614
60996
  }
@@ -60918,13 +61300,12 @@ function generateHeaderRootStyles(header, themeId, tokens) {
60918
61300
  rules.push("isolation: isolate;");
60919
61301
  const surfaceRules = isContainedNav ? {
60920
61302
  base: [],
60921
- scrolled: [],
60922
61303
  border: []
60923
- } : buildHeaderSurfaceRules(header, tokens, HEADER_BLUR);
61304
+ } : buildHeaderSurfaceRules(header, tokens);
60924
61305
  const floatingSurfaceBorder = header.variant === "floating";
60925
61306
  if (!floatingSurfaceBorder) rules.push(...surfaceRules.border);
60926
61307
  const basePaintRules = floatingSurfaceBorder ? [...surfaceRules.base, ...surfaceRules.border] : surfaceRules.base;
60927
- const scrolledPaintRules = floatingSurfaceBorder ? [...surfaceRules.scrolled, ...surfaceRules.border] : surfaceRules.scrolled;
61308
+ const scrolledPaintRules = floatingSurfaceBorder ? surfaceRules.border : [];
60928
61309
  if (header.positioning === "sticky" || header.positioning === "fixed") {
60929
61310
  const shadowVar = getComponentShadowVar(header.shadow?.elevation ?? "none");
60930
61311
  if (shadowVar) rules.push(`box-shadow: ${shadowVar};`);
@@ -63655,215 +64036,115 @@ function mapFontStyle(italic) {
63655
64036
  return italic ? "italic" : "normal";
63656
64037
  }
63657
64038
  //#endregion
63658
- //#region ../blocks/src/system/manifest/hydrateLinks.ts
63659
- /**
63660
- * Hydrates link objects within block content using the provided route map. Returns
63661
- * the original content reference when no mutations are required to avoid unnecessary renders.
63662
- */
63663
- function hydrateManifestLinks(manifest, content, routes, pagesByIdentifier, entriesByIdentifier) {
63664
- if (!routes || !manifest?.fields?.length) return content;
63665
- return hydrateValue(content, {
63666
- routes,
63667
- pagesByIdentifier,
63668
- entriesByIdentifier
63669
- });
63670
- }
63671
- function hydrateValue(value, context) {
63672
- try {
63673
- if (Array.isArray(value)) {
63674
- const resolvedItems = value.map((item) => hydrateValue(item, context));
63675
- return resolvedItems.every((item, index) => item === value[index]) ? value : resolvedItems;
63676
- }
63677
- if (isRecord$26(value)) {
63678
- if (isInternalLink$1(value)) return hydrateInternalLink(value, context.routes);
63679
- if (isPageLink$1(value)) return hydratePageLink(value, context);
63680
- if (isEntryLink$1(value)) return hydrateEntryLink(value, context);
63681
- const resolvedEntries = Object.entries(value).map(([key, entry]) => [key, hydrateValue(entry, context)]);
63682
- return resolvedEntries.every(([key, entry]) => entry === value[key]) ? value : Object.fromEntries(resolvedEntries);
63683
- }
63684
- return value;
63685
- } catch (err) {
63686
- console.error("[hydrateLinks] Error hydrating value:", err, value);
63687
- return value;
64039
+ //#region ../blocks/src/pageRenderingMode.ts
64040
+ var MissingBlockOverrideError$1 = class extends Error {
64041
+ constructor(blockKind) {
64042
+ super(`Override-only rendering requires an override for block kind "${blockKind}".`);
64043
+ this.blockKind = blockKind;
64044
+ this.code = "missing_block_override";
64045
+ this.name = "MissingBlockOverrideError";
63688
64046
  }
64047
+ };
64048
+ function isOverrideOnlyResourceInput(props) {
64049
+ return props.rendering?.kind === "overrides-only";
63689
64050
  }
63690
- function hydrateInternalLink(link, routes) {
63691
- const resolved = resolveRouteTarget(link.routeId, routes);
63692
- if (!resolved) return link;
63693
- const nextHref = resolved.href;
63694
- const currentHref = typeof link.href === "string" && link.href.length > 0 ? link.href : null;
63695
- const nextUpdatedAt = resolved.updatedAt;
63696
- const updates = {};
63697
- if (nextHref && nextHref !== currentHref) updates.href = nextHref;
63698
- if (nextUpdatedAt && link.updatedAt !== nextUpdatedAt) updates.updatedAt = nextUpdatedAt;
63699
- return Object.keys(updates).length > 0 ? {
63700
- ...link,
63701
- ...updates
63702
- } : link;
63703
- }
63704
- function isInternalLink$1(value) {
63705
- if (value.kind !== "internal") return false;
63706
- if (typeof value.routeId !== "string" || value.routeId.length === 0) return false;
63707
- return true;
63708
- }
63709
- function isPageLink$1(value) {
63710
- if (value.kind !== "page") return false;
63711
- if (typeof value.identifier !== "string" || value.identifier.length === 0) return false;
63712
- return true;
63713
- }
63714
- function hydratePageLink(link, context) {
63715
- const resolved = resolvePageRouteTarget(link, context);
63716
- if (!resolved) return link;
64051
+ function resolvePageThemeResources(props) {
64052
+ if (isOverrideOnlyResourceInput(props)) return { kind: "unavailable" };
63717
64053
  return {
63718
- ...link,
63719
- href: resolved.href,
63720
- routeId: resolved.routeId
64054
+ kind: "available",
64055
+ tokens: props.themeTokens ?? buildThemeRuntime$1(props.theme).tokens,
64056
+ config: props.theme
63721
64057
  };
63722
64058
  }
63723
- function isEntryLink$1(value) {
63724
- if (value.kind !== "entry") return false;
63725
- if (typeof value.contentType !== "string" || value.contentType.length === 0) return false;
63726
- if (typeof value.identifier !== "string" || value.identifier.length === 0) return false;
63727
- return true;
64059
+ function requireBlockOverride(resources, override, blockKind) {
64060
+ if (resources.kind === "unavailable" && !override) throw new MissingBlockOverrideError$1(blockKind);
63728
64061
  }
63729
- function hydrateEntryLink(link, context) {
63730
- const resolved = resolveEntryRouteTarget(link, context);
63731
- if (!resolved) return link;
63732
- return {
63733
- ...link,
63734
- href: resolved.href,
63735
- routeId: resolved.routeId
63736
- };
64062
+ function overrideThemeProps(resources) {
64063
+ return resources.kind === "available" ? {
64064
+ theme: resources.tokens,
64065
+ themeConfig: resources.config
64066
+ } : {};
64067
+ }
64068
+ function requireThemeResources(resources, blockKind) {
64069
+ if (resources.kind === "unavailable") throw new MissingBlockOverrideError$1(blockKind);
64070
+ return resources;
63737
64071
  }
63738
64072
  //#endregion
63739
- //#region ../blocks/src/sdkBlockTransform.ts
63740
- /**
63741
- * Transforms an SDK custom block into a BlockManifest.
63742
- *
63743
- * If the block has a `layout`, it can be rendered declaratively without React code.
63744
- * If no layout, the block MUST use blockOverrides for rendering.
63745
- */
63746
- function transformSdkBlockToManifest(sdkBlock) {
63747
- const hasLayout = Boolean(sdkBlock.layout) || Boolean(sdkBlock.variants && Object.keys(sdkBlock.variants).length > 0);
63748
- return augmentManifest({
63749
- name: sdkBlock.id,
63750
- version: "1.0.0",
63751
- title: sdkBlock.title,
63752
- titleSource: sdkBlock.titleSource,
63753
- description: sdkBlock.description,
63754
- component: sdkBlock.id,
63755
- fields: sdkBlock.fields,
63756
- slots: [],
63757
- category: sdkBlock.category,
63758
- tags: sdkBlock.tags,
63759
- icon: sdkBlock.icon,
63760
- layout: sdkBlock.layout,
63761
- variants: sdkBlock.variants,
63762
- defaultVariant: sdkBlock.defaultVariant,
63763
- variantOptions: sdkBlock.variantOptions,
63764
- previewCustomize: sdkBlock.previewCustomize,
63765
- behaviours: {
63766
- supportsThemeSwitching: true,
63767
- inlineEditing: hasLayout,
63768
- animation: hasLayout,
63769
- paletteHidden: false
63770
- }
63771
- });
64073
+ //#region ../blocks/src/pageRendererBoundaries.tsx
64074
+ const boundaryKey = (previousBlockId, nextBlockId) => `${previousBlockId}\u0000${nextBlockId}`;
64075
+ function isSiteStyleTransitionStyleGroup(value) {
64076
+ return value?.startsWith("site-style-transition-") === true;
63772
64077
  }
63773
- /**
63774
- * Transforms an SDK custom block into a SystemBlockDefinition.
63775
- *
63776
- * This creates a minimal definition with just the manifest - no data loaders
63777
- * or content normalizers since SDK blocks handle their own rendering.
63778
- */
63779
- function transformSdkBlockToDefinition(sdkBlock) {
63780
- return {
63781
- manifest: transformSdkBlockToManifest(sdkBlock),
63782
- dataLoaders: sdkBlock.dataLoaders
63783
- };
64078
+ function boundaryMapForAdjacentBlockIds(boundaries) {
64079
+ return new Map(boundaries.map((boundary) => [boundaryKey(boundary.previousBlockId, boundary.nextBlockId), boundary]));
63784
64080
  }
63785
- //#endregion
63786
- //#region ../blocks/src/customBlockRegistry.ts
63787
- const defaultCustomBlockSourcePolicy = { kind: "canonical-db-fallback-sdk" };
63788
- function isCustomBlockKind(blockKind) {
63789
- return blockKind.startsWith("custom.");
64081
+ function boundaryBetweenBlocks(previousBlock, nextBlock, boundaries) {
64082
+ const previousBlockId = previousBlock?.id ?? null;
64083
+ const nextBlockId = nextBlock?.id ?? null;
64084
+ if (!previousBlockId || !nextBlockId) return null;
64085
+ return boundaries.get(boundaryKey(previousBlockId, nextBlockId)) ?? null;
63790
64086
  }
63791
- function transformToBlockDescriptor(sdkBlock, source = "sdk") {
64087
+ function renderBoundaryAfterBlock(input) {
64088
+ const previousBlockId = input.block.id;
64089
+ const nextBlockId = input.nextBlock?.id ?? null;
64090
+ if (!previousBlockId || !nextBlockId) return null;
64091
+ const boundary = input.boundaryByAdjacentBlockIds.get(boundaryKey(previousBlockId, nextBlockId));
64092
+ if (!boundary) return null;
64093
+ const rendered = /* @__PURE__ */ jsx("div", {
64094
+ "aria-hidden": "true",
64095
+ "data-block-boundary": "",
64096
+ "data-boundary-id": boundary.boundaryId,
64097
+ "data-boundary-previous-block-id": boundary.previousBlockId,
64098
+ "data-boundary-next-block-id": boundary.nextBlockId,
64099
+ "data-style-group": boundary.styleGroup,
64100
+ style: boundaryCssVarsStyle(boundary)
64101
+ }, `${input.blockKey}:boundary`);
64102
+ return input.wrapBoundary ? input.wrapBoundary(boundary, rendered) : rendered;
64103
+ }
64104
+ function boundaryCssVarsStyle(boundary) {
63792
64105
  return {
63793
- name: sdkBlock.id,
63794
- title: sdkBlock.title,
63795
- description: sdkBlock.description,
63796
- category: sdkBlock.category,
63797
- tags: sdkBlock.tags,
63798
- icon: sdkBlock.icon,
63799
- definition: transformSdkBlockToDefinition(sdkBlock),
63800
- source
64106
+ "--site-style-transition-from": boundary.cssVars.from,
64107
+ "--site-style-transition-to": boundary.cssVars.to
63801
64108
  };
63802
64109
  }
63803
- function toResolvedCustomBlock(manifest, source) {
64110
+ function boundaryReserveCssVarsStyle(input) {
64111
+ const before = input.before?.metrics.reserveCss ?? null;
64112
+ const after = input.after?.metrics.reserveCss ?? null;
64113
+ if (!before && !after) return void 0;
63804
64114
  return {
63805
- blockKind: manifest.id,
63806
- manifest: transformSdkBlockToManifest(manifest),
63807
- source,
63808
- descriptor: transformToBlockDescriptor(manifest, source.kind === "managed-database" ? "database" : "sdk")
64115
+ ...before ? { "--site-style-boundary-before-reserve": before } : {},
64116
+ ...after ? { "--site-style-boundary-after-reserve": after } : {}
63809
64117
  };
63810
64118
  }
63811
- function planCustomBlockRegistryResolution({ sdkConfig, customBlocks = [], policy = defaultCustomBlockSourcePolicy }) {
63812
- switch (policy.kind) {
63813
- case "canonical-db-fallback-sdk": {
63814
- const entriesByKind = /* @__PURE__ */ new Map();
63815
- const conflicts = [];
63816
- for (const customBlock of customBlocks) entriesByKind.set(customBlock.manifest.id, toResolvedCustomBlock(customBlock.manifest, customBlock.source));
63817
- for (const sdkBlock of sdkConfig?.customBlocks ?? []) {
63818
- const existing = entriesByKind.get(sdkBlock.id);
63819
- if (existing) {
63820
- conflicts.push({
63821
- kind: "conflict",
63822
- blockKind: existing.blockKind,
63823
- winner: existing.source,
63824
- loser: { kind: "sdk-config" },
63825
- reason: "db-canonical-sdk-fallback"
63826
- });
63827
- continue;
63828
- }
63829
- entriesByKind.set(sdkBlock.id, toResolvedCustomBlock(sdkBlock, { kind: "sdk-config" }));
63830
- }
63831
- return {
63832
- policy,
63833
- entries: Array.from(entriesByKind.values()),
63834
- conflicts
63835
- };
63836
- }
63837
- }
64119
+ function transitionCssVarsStyle(content) {
64120
+ const transitionStyles = isObjectRecord$1(content._transitionStyles) ? content._transitionStyles : null;
64121
+ const cssVars = isObjectRecord$1(transitionStyles?.cssVars) ? transitionStyles.cssVars : null;
64122
+ const from = typeof cssVars?.from === "string" ? cssVars.from : null;
64123
+ const to = typeof cssVars?.to === "string" ? cssVars.to : null;
64124
+ if (!from && !to) return void 0;
64125
+ return {
64126
+ ...from ? { "--site-style-transition-from": from } : {},
64127
+ ...to ? { "--site-style-transition-to": to } : {}
64128
+ };
63838
64129
  }
63839
- function createCustomBlockRegistry({ sdkConfig, customBlocks = [], policy = defaultCustomBlockSourcePolicy, onConflict }) {
63840
- const plan = planCustomBlockRegistryResolution({
63841
- sdkConfig,
63842
- customBlocks,
63843
- policy
63844
- });
63845
- const entriesByKind = new Map(plan.entries.map((entry) => [entry.blockKind, entry]));
63846
- for (const conflict of plan.conflicts) onConflict?.(`Using ${sourceLabel(conflict.winner)} custom block "${conflict.blockKind}" - ${sourceLabel(conflict.loser)} block is fallback only`);
64130
+ function mergeStyleObjects(left, right) {
64131
+ if (!left) return right;
64132
+ if (!right) return left;
63847
64133
  return {
63848
- entries: plan.entries,
63849
- conflicts: plan.conflicts,
63850
- findManifest: (blockKind) => {
63851
- if (!isCustomBlockKind(blockKind)) return void 0;
63852
- return entriesByKind.get(blockKind);
63853
- }
64134
+ ...left,
64135
+ ...right
63854
64136
  };
63855
64137
  }
63856
- function sourceLabel(source) {
63857
- switch (source.kind) {
63858
- case "managed-database": return "DB";
63859
- case "sdk-synced": return "SDK-synced DB";
63860
- case "sdk-config": return "SDK config";
63861
- default: return assertNever$24(source);
63862
- }
64138
+ function pageBlockPosition(index, blockCount) {
64139
+ if (blockCount <= 1) return "only";
64140
+ if (index === 0) return "first";
64141
+ if (index === blockCount - 1) return "last";
64142
+ return "middle";
63863
64143
  }
63864
64144
  //#endregion
63865
64145
  //#region ../blocks/src/PageRenderer.tsx
63866
- function PageRenderer$1({ theme, page, runtimeBoundaries, usePlaceholders = false, dataContext, wrapBlock, wrapBoundary, registry, themeTokens: providedThemeTokens, routeMap, blockOverrides, sdkConfig, customBlocks, previewAuthoring }) {
64146
+ function PageRenderer$1(props) {
64147
+ const { page, runtimeBoundaries, usePlaceholders = false, dataContext, wrapBlock, wrapBoundary, registry, routeMap, blockOverrides, sdkConfig, customBlocks, previewAuthoring } = props;
63867
64148
  const imageResolveContext = React$1.useMemo(() => resolvePageRendererImageResolveContext(dataContext), [
63868
64149
  dataContext?.imageResolveContext,
63869
64150
  dataContext?.mediaAssets,
@@ -63872,12 +64153,16 @@ function PageRenderer$1({ theme, page, runtimeBoundaries, usePlaceholders = fals
63872
64153
  ]);
63873
64154
  const boundaryByAdjacentBlockIds = React$1.useMemo(() => boundaryMapForAdjacentBlockIds(runtimeBoundaries ?? []), [runtimeBoundaries]);
63874
64155
  const usesRuntimeBoundaries = runtimeBoundaries !== void 0;
64156
+ const themeResources = React$1.useMemo(() => resolvePageThemeResources(props), [
64157
+ props.rendering,
64158
+ props.theme,
64159
+ props.themeTokens
64160
+ ]);
63875
64161
  if (!page || page.blocks.length === 0) return /* @__PURE__ */ jsx("div", {
63876
64162
  className: "rb-p-6 rb-caption",
63877
64163
  style: textColorStyle("mutedText"),
63878
64164
  children: "No blocks found."
63879
64165
  });
63880
- const themeTokens = providedThemeTokens ?? buildThemeRuntime$1(theme).tokens;
63881
64166
  const resolvedRegistry = registry ?? getDefaultComponentRegistry();
63882
64167
  setContextResolveImageUrlContext(imageResolveContext);
63883
64168
  return /* @__PURE__ */ jsx("div", { children: page.blocks.map((block, index) => {
@@ -63900,22 +64185,14 @@ function PageRenderer$1({ theme, page, runtimeBoundaries, usePlaceholders = fals
63900
64185
  const renderableContent = getRenderableContent(block, dataContext?.previewStage);
63901
64186
  const variantKey = definition?.manifest ? resolveVariantKey(definition.manifest, renderableContent) : null;
63902
64187
  const shouldUseWrapper = !managesOwnWrapper || Boolean(wrapBlock);
63903
- const blockSectionProps = {
63904
- themeTokens,
63905
- themeConfig: theme,
64188
+ const blockSectionProps = buildBlockSectionProps({
64189
+ props,
64190
+ themeResources,
63906
64191
  block,
63907
- usePlaceholders,
63908
- dataContext,
63909
64192
  blockKey,
63910
- registry: resolvedRegistry,
63911
- routeMap,
63912
- wrapBlock,
63913
- blockOverrides,
63914
- sdkConfig,
63915
- customBlocks,
63916
64193
  imageResolveContext,
63917
- previewAuthoring
63918
- };
64194
+ registry: resolvedRegistry
64195
+ });
63919
64196
  if (!shouldUseWrapper) {
63920
64197
  const rendered = /* @__PURE__ */ jsx(MemoBlockSection, { ...blockSectionProps }, `${blockKey}:block`);
63921
64198
  return boundaryElement ? /* @__PURE__ */ jsxs(React$1.Fragment, { children: [rendered, boundaryElement] }, blockKey) : rendered;
@@ -63957,81 +64234,6 @@ function PageRenderer$1({ theme, page, runtimeBoundaries, usePlaceholders = fals
63957
64234
  })] }, blockKey);
63958
64235
  }) });
63959
64236
  }
63960
- function isSiteStyleTransitionStyleGroup(value) {
63961
- return value?.startsWith("site-style-transition-") === true;
63962
- }
63963
- function boundaryMapForAdjacentBlockIds(boundaries) {
63964
- return new Map(boundaries.map((boundary) => [boundaryKey(boundary.previousBlockId, boundary.nextBlockId), boundary]));
63965
- }
63966
- function boundaryKey(previousBlockId, nextBlockId) {
63967
- return `${previousBlockId}\u0000${nextBlockId}`;
63968
- }
63969
- function boundaryBetweenBlocks(previousBlock, nextBlock, boundaryByAdjacentBlockIds) {
63970
- const previousBlockId = previousBlock?.id ?? null;
63971
- const nextBlockId = nextBlock?.id ?? null;
63972
- if (!previousBlockId || !nextBlockId) return null;
63973
- return boundaryByAdjacentBlockIds.get(boundaryKey(previousBlockId, nextBlockId)) ?? null;
63974
- }
63975
- function renderBoundaryAfterBlock(input) {
63976
- const previousBlockId = input.block.id;
63977
- const nextBlockId = input.nextBlock?.id ?? null;
63978
- if (!previousBlockId || !nextBlockId) return null;
63979
- const boundary = input.boundaryByAdjacentBlockIds.get(boundaryKey(previousBlockId, nextBlockId));
63980
- if (!boundary) return null;
63981
- const rendered = /* @__PURE__ */ jsx("div", {
63982
- "aria-hidden": "true",
63983
- "data-block-boundary": "",
63984
- "data-boundary-id": boundary.boundaryId,
63985
- "data-boundary-previous-block-id": boundary.previousBlockId,
63986
- "data-boundary-next-block-id": boundary.nextBlockId,
63987
- "data-style-group": boundary.styleGroup,
63988
- style: boundaryCssVarsStyle(boundary)
63989
- }, `${input.blockKey}:boundary`);
63990
- return input.wrapBoundary ? input.wrapBoundary(boundary, rendered) : rendered;
63991
- }
63992
- function boundaryCssVarsStyle(boundary) {
63993
- return {
63994
- "--site-style-transition-from": boundary.cssVars.from,
63995
- "--site-style-transition-to": boundary.cssVars.to
63996
- };
63997
- }
63998
- function boundaryReserveCssVarsStyle(input) {
63999
- const before = input.before ? boundaryReserveValueForTreatment(input.before) : null;
64000
- const after = input.after ? boundaryReserveValueForTreatment(input.after) : null;
64001
- if (!before && !after) return void 0;
64002
- return {
64003
- ...before ? { "--site-style-boundary-before-reserve": before } : {},
64004
- ...after ? { "--site-style-boundary-after-reserve": after } : {}
64005
- };
64006
- }
64007
- function boundaryReserveValueForTreatment(boundary) {
64008
- return boundary.metrics.reserveCss;
64009
- }
64010
- function transitionCssVarsStyle(content) {
64011
- const transitionStyles = isObjectRecord$1(content._transitionStyles) ? content._transitionStyles : null;
64012
- const cssVars = isObjectRecord$1(transitionStyles?.cssVars) ? transitionStyles.cssVars : null;
64013
- const from = typeof cssVars?.from === "string" ? cssVars.from : null;
64014
- const to = typeof cssVars?.to === "string" ? cssVars.to : null;
64015
- if (!from && !to) return void 0;
64016
- return {
64017
- ...from ? { "--site-style-transition-from": from } : {},
64018
- ...to ? { "--site-style-transition-to": to } : {}
64019
- };
64020
- }
64021
- function mergeStyleObjects(left, right) {
64022
- if (!left) return right;
64023
- if (!right) return left;
64024
- return {
64025
- ...left,
64026
- ...right
64027
- };
64028
- }
64029
- function pageBlockPosition(index, blockCount) {
64030
- if (blockCount <= 1) return "only";
64031
- if (index === 0) return "first";
64032
- if (index === blockCount - 1) return "last";
64033
- return "middle";
64034
- }
64035
64237
  function resolvePageRendererImageResolveContext(dataContext) {
64036
64238
  const input = dataContext?.imageResolveContext;
64037
64239
  return buildResolveImageUrlContext({
@@ -64041,6 +64243,23 @@ function resolvePageRendererImageResolveContext(dataContext) {
64041
64243
  mediaAssets: input?.mediaAssets ?? dataContext?.mediaAssets
64042
64244
  });
64043
64245
  }
64246
+ function buildBlockSectionProps(input) {
64247
+ return {
64248
+ themeResources: input.themeResources,
64249
+ block: input.block,
64250
+ usePlaceholders: input.props.usePlaceholders ?? false,
64251
+ dataContext: input.props.dataContext,
64252
+ blockKey: input.blockKey,
64253
+ registry: input.registry,
64254
+ routeMap: input.props.routeMap,
64255
+ wrapBlock: input.props.wrapBlock,
64256
+ blockOverrides: input.props.blockOverrides,
64257
+ sdkConfig: input.props.sdkConfig,
64258
+ customBlocks: input.props.customBlocks,
64259
+ imageResolveContext: input.imageResolveContext,
64260
+ previewAuthoring: input.props.previewAuthoring
64261
+ };
64262
+ }
64044
64263
  /**
64045
64264
  * Look up a block override component by block kind.
64046
64265
  * Supports both full ("block.hero") and short ("hero") keys.
@@ -64107,7 +64326,7 @@ function getCachedValidator(manifest, flavour) {
64107
64326
  * referential equality of all props that affect rendering. Standard React.memo
64108
64327
  * wouldn't catch all the render triggers from the editor store.
64109
64328
  */
64110
- const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, themeConfig, block, usePlaceholders, dataContext, registry, routeMap, wrapBlock, blockOverrides, sdkConfig, customBlocks, imageResolveContext, previewAuthoring }) {
64329
+ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeResources, block, usePlaceholders, dataContext, registry, routeMap, wrapBlock, blockOverrides, sdkConfig, customBlocks, imageResolveContext, previewAuthoring }) {
64111
64330
  const perfStart = globalThis.process?.env?.DEBUG_PERF === "1" && typeof window === "undefined" ? Date.now() : 0;
64112
64331
  const fallbackImageResolveContext = getCurrentResolveImageUrlContext();
64113
64332
  const resolvedImageResolveContext = imageResolveContext ?? fallbackImageResolveContext;
@@ -64128,6 +64347,7 @@ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, t
64128
64347
  return node;
64129
64348
  }
64130
64349
  const OverrideComponent = getBlockOverride(block.kind, blockOverrides);
64350
+ requireBlockOverride(themeResources, OverrideComponent, block.kind);
64131
64351
  let definition = getBlockDefinition(block.kind);
64132
64352
  if (!definition && block.kind.startsWith("custom.")) definition = createCustomBlockRegistry({
64133
64353
  sdkConfig,
@@ -64140,8 +64360,7 @@ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, t
64140
64360
  if (OverrideComponent) {
64141
64361
  const rendered = /* @__PURE__ */ jsx(OverrideComponent, {
64142
64362
  content: getRenderableContent(block, dataContext?.previewStage),
64143
- theme: themeTokens,
64144
- themeConfig,
64363
+ ...overrideThemeProps(themeResources),
64145
64364
  data: void 0,
64146
64365
  siteId: dataContext?.siteId,
64147
64366
  apiBaseUrl: dataContext?.apiBaseUrl,
@@ -64240,8 +64459,7 @@ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, t
64240
64459
  const hasResolvedData = !!resolved && typeof resolved === "object" && Object.keys(resolved).length > 0;
64241
64460
  const baseProps = {
64242
64461
  content: hydratedContent,
64243
- theme: themeTokens,
64244
- themeConfig,
64462
+ ...overrideThemeProps(themeResources),
64245
64463
  data: resolved,
64246
64464
  siteId: dataContext?.siteId,
64247
64465
  apiBaseUrl: dataContext?.apiBaseUrl,
@@ -64261,6 +64479,7 @@ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, t
64261
64479
  let rendered;
64262
64480
  if (OverrideComponent) rendered = /* @__PURE__ */ jsx(OverrideComponent, { ...baseProps });
64263
64481
  else {
64482
+ requireThemeResources(themeResources, block.kind);
64264
64483
  const BlockComponent = getCachedBlockComponent(definition.manifest);
64265
64484
  const pathBase = typeof block.id === "string" && block.id.length > 0 ? `blocks.${block.id}.` : void 0;
64266
64485
  const rootContext = { $root: {
@@ -64310,7 +64529,7 @@ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, t
64310
64529
  });
64311
64530
  }
64312
64531
  }, (prev, next) => {
64313
- return prev.block === next.block && prev.registry === next.registry && prev.dataContext === next.dataContext && prev.themeTokens === next.themeTokens && prev.themeConfig === next.themeConfig && prev.routeMap === next.routeMap && prev.usePlaceholders === next.usePlaceholders && prev.wrapBlock === next.wrapBlock && prev.blockOverrides === next.blockOverrides && prev.sdkConfig === next.sdkConfig && prev.customBlocks === next.customBlocks && prev.imageResolveContext === next.imageResolveContext && prev.previewAuthoring === next.previewAuthoring;
64532
+ return prev.block === next.block && prev.registry === next.registry && prev.dataContext === next.dataContext && prev.themeResources === next.themeResources && prev.routeMap === next.routeMap && prev.usePlaceholders === next.usePlaceholders && prev.wrapBlock === next.wrapBlock && prev.blockOverrides === next.blockOverrides && prev.sdkConfig === next.sdkConfig && prev.customBlocks === next.customBlocks && prev.imageResolveContext === next.imageResolveContext && prev.previewAuthoring === next.previewAuthoring;
64314
64533
  });
64315
64534
  function fallback(message) {
64316
64535
  return /* @__PURE__ */ jsx("div", {
@@ -77774,6 +77993,7 @@ const SUPPORTED_LOADER_ENDPOINTS$1 = [
77774
77993
  "listPublicRecurringSchedule",
77775
77994
  "getPublicEventDetails",
77776
77995
  "listPublicWholeSeriesOfferings",
77996
+ "getPublicWholeSeriesOffering",
77777
77997
  "listPublicRouteCandidates",
77778
77998
  "listPublicTeamMembers",
77779
77999
  "listPublicProducts",
@@ -79423,6 +79643,7 @@ const loaderAdapters = {
79423
79643
  listPublicEvents,
79424
79644
  listPublicRecurringSchedule,
79425
79645
  getPublicEventDetails,
79646
+ getPublicWholeSeriesOffering,
79426
79647
  listPublicRouteCandidates,
79427
79648
  listPublicTeamMembers,
79428
79649
  listPublicProducts,
@@ -79517,6 +79738,13 @@ async function listPublicEvents({ client, params }) {
79517
79738
  async function listPublicRecurringSchedule(input) {
79518
79739
  return projectRecurringSchedule(await listPublicEvents(input));
79519
79740
  }
79741
+ async function getPublicWholeSeriesOffering({ client, params }) {
79742
+ return await client.getPublicWholeSeriesOffering({
79743
+ siteId: requireStringParam(params, "siteId", "getPublicWholeSeriesOffering"),
79744
+ eventSeriesId: requireStringParam(params, "eventSeriesId", "getPublicWholeSeriesOffering"),
79745
+ stage: readStringParam(params, "stage")
79746
+ });
79747
+ }
79520
79748
  async function getPublicEventDetails({ client, params }) {
79521
79749
  return await client.getPublicEventDetails({
79522
79750
  siteId: requireStringParam(params, "siteId", "getPublicEventDetails"),
@@ -82827,8 +83055,9 @@ function toBlocksImageResolveContextInput(context) {
82827
83055
  mediaAssets: toBlocksMediaAssets(context.mediaAssets)
82828
83056
  };
82829
83057
  }
82830
- //#endregion
82831
- //#region src/rendering/blocks-page-renderer.ts
83058
+ function isOverrideOnlyPageRenderer(props) {
83059
+ return props.rendering?.kind === "overrides-only";
83060
+ }
82832
83061
  function normalizeSdkCustomBlocks(customBlocks) {
82833
83062
  if (!customBlocks) return void 0;
82834
83063
  return customBlocks.map((block) => {
@@ -82850,8 +83079,7 @@ function toBlocksBlockOverrides(overrides) {
82850
83079
  };
82851
83080
  return result;
82852
83081
  }
82853
- function toBlocksDataContext(dataContext) {
82854
- if (!dataContext) return void 0;
83082
+ function toBlocksPageRendererDataContext(dataContext) {
82855
83083
  return {
82856
83084
  ...dataContext,
82857
83085
  mediaAssets: toBlocksMediaAssets(dataContext.mediaAssets),
@@ -82860,15 +83088,23 @@ function toBlocksDataContext(dataContext) {
82860
83088
  }
82861
83089
  function PageRenderer(props) {
82862
83090
  const blocksSdkConfig = props.sdkConfig ? { customBlocks: normalizeSdkCustomBlocks(props.sdkConfig.customBlocks) } : props.sdkConfig;
82863
- const blocksTheme = parseBlocksTheme(props.theme);
82864
- const blocksProps = {
82865
- ...props,
82866
- theme: blocksTheme,
82867
- dataContext: toBlocksDataContext(props.dataContext),
83091
+ const { rendering: _rendering, theme: _theme, themeTokens: _themeTokens, ...commonProps } = props;
83092
+ const commonBlocksProps = {
83093
+ ...commonProps,
83094
+ dataContext: props.dataContext ? toBlocksPageRendererDataContext(props.dataContext) : void 0,
82868
83095
  blockOverrides: toBlocksBlockOverrides(props.blockOverrides),
82869
83096
  sdkConfig: blocksSdkConfig,
82870
83097
  customBlocks: normalizeSdkCustomBlocks(props.customBlocks)
82871
83098
  };
83099
+ const blocksProps = isOverrideOnlyPageRenderer(props) ? {
83100
+ ...commonBlocksProps,
83101
+ rendering: { kind: "overrides-only" },
83102
+ blockOverrides: toBlocksBlockOverrides(props.blockOverrides) ?? {}
83103
+ } : {
83104
+ ...commonBlocksProps,
83105
+ theme: parseBlocksTheme(props.theme),
83106
+ themeTokens: props.themeTokens
83107
+ };
82872
83108
  return React$1.createElement(PageRenderer$1, blocksProps);
82873
83109
  }
82874
83110
  //#endregion
@@ -82899,8 +83135,31 @@ function renderWithSdkThemeRuntime({ themeRuntime, theme, children }) {
82899
83135
  default: return assertNever$24(themeRuntime);
82900
83136
  }
82901
83137
  }
83138
+ function renderWithOverrideOnlyRuntime({ runtime, children }) {
83139
+ switch (runtime.kind) {
83140
+ case "responsive-only": return /* @__PURE__ */ jsx(ResponsiveScope, {
83141
+ responsiveMode: runtime.responsiveMode,
83142
+ children
83143
+ });
83144
+ case "none": return /* @__PURE__ */ jsx(Fragment, { children });
83145
+ default: return assertNever$24(runtime);
83146
+ }
83147
+ }
82902
83148
  //#endregion
82903
83149
  //#region src/rendering/components/pageShared.tsx
83150
+ function isOverrideOnlyPage(props) {
83151
+ return props.rendering?.kind === "overrides-only";
83152
+ }
83153
+ function resolvePageThemeTokens(props) {
83154
+ const baseTokens = props.themeTokens ?? buildThemeRuntime(props.theme).tokens;
83155
+ return props.sdkConfig?.theme?.palette ? {
83156
+ ...baseTokens,
83157
+ palette: {
83158
+ ...baseTokens.palette,
83159
+ ...props.sdkConfig.theme.palette
83160
+ }
83161
+ } : baseTokens;
83162
+ }
82904
83163
  function toPageHydrationBootstrapConfig(props) {
82905
83164
  return {
82906
83165
  siteId: props.siteId,
@@ -82908,150 +83167,76 @@ function toPageHydrationBootstrapConfig(props) {
82908
83167
  mediaAssets: props.mediaAssets
82909
83168
  };
82910
83169
  }
82911
- function PageContent({ page, runtimeBoundaries, theme, themeTokens: providedTokens, siteId, resolvedData, bookingOfferingPresets, routeMap, pagesByIdentifier, entriesByIdentifier, wrapBlock, registry, usePlaceholders = false, blockOverrides, sdkConfig, customBlocks, supabaseUrl, mediaAssets, apiBaseUrl, portalToken, previewToken, dataContext, themeRuntime = defaultPageThemeRuntime }) {
82912
- const baseTokens = providedTokens ?? buildThemeRuntime(theme).tokens;
82913
- return renderWithSdkThemeRuntime({
82914
- themeRuntime,
82915
- theme,
82916
- children: /* @__PURE__ */ jsx(PageRenderer, {
82917
- theme,
82918
- page,
82919
- runtimeBoundaries,
82920
- themeTokens: sdkConfig?.theme?.palette ? {
82921
- ...baseTokens,
82922
- palette: {
82923
- ...baseTokens.palette,
82924
- ...sdkConfig.theme.palette
82925
- }
82926
- } : baseTokens,
82927
- usePlaceholders,
82928
- dataContext: {
83170
+ function PageContent(props) {
83171
+ const { page, runtimeBoundaries, siteId, resolvedData, bookingOfferingPresets, routeMap, pagesByIdentifier, entriesByIdentifier, wrapBlock, registry, usePlaceholders = false, blockOverrides, sdkConfig, customBlocks, supabaseUrl, mediaAssets, apiBaseUrl, portalToken, previewToken, dataContext } = props;
83172
+ const rendererCommonProps = {
83173
+ page,
83174
+ runtimeBoundaries,
83175
+ usePlaceholders,
83176
+ dataContext: {
83177
+ siteId,
83178
+ apiBaseUrl,
83179
+ portalToken,
83180
+ previewToken,
83181
+ resolvedData,
83182
+ bookingOfferingPresets: bookingOfferingPresets ?? [],
83183
+ routes: routeMap,
83184
+ pagesByIdentifier,
83185
+ entriesByIdentifier,
83186
+ occurrenceContext: dataContext?.occurrenceContext ?? null,
83187
+ entrySubrouteContext: dataContext?.entrySubrouteContext ?? null,
83188
+ contentEntry: dataContext?.contentEntry ?? null,
83189
+ pageSurface: dataContext?.pageSurface ?? null,
83190
+ subject: dataContext?.subject ?? null,
83191
+ editableRouteMetadataFieldIds: dataContext?.editableRouteMetadataFieldIds ?? null,
83192
+ previewStage: dataContext?.previewStage,
83193
+ supabaseUrl,
83194
+ mediaAssets,
83195
+ imageResolveContext: {
82929
83196
  siteId,
82930
- apiBaseUrl,
82931
- portalToken,
82932
- previewToken,
82933
- resolvedData,
82934
- bookingOfferingPresets: bookingOfferingPresets ?? [],
82935
- routes: routeMap,
82936
- pagesByIdentifier,
82937
- entriesByIdentifier,
82938
- occurrenceContext: dataContext?.occurrenceContext ?? null,
82939
- entrySubrouteContext: dataContext?.entrySubrouteContext ?? null,
82940
- contentEntry: dataContext?.contentEntry ?? null,
82941
- pageSurface: dataContext?.pageSurface ?? null,
82942
- subject: dataContext?.subject ?? null,
82943
- editableRouteMetadataFieldIds: dataContext?.editableRouteMetadataFieldIds ?? null,
82944
- previewStage: dataContext?.previewStage,
82945
83197
  supabaseUrl,
82946
- mediaAssets,
82947
- imageResolveContext: {
82948
- siteId,
82949
- supabaseUrl,
82950
- mediaAssets
82951
- }
82952
- },
82953
- routeMap,
82954
- wrapBlock,
82955
- registry,
82956
- blockOverrides,
82957
- sdkConfig: sdkConfig ? { customBlocks: sdkConfig.customBlocks } : null,
82958
- customBlocks
82959
- })
83198
+ mediaAssets
83199
+ }
83200
+ },
83201
+ routeMap,
83202
+ wrapBlock,
83203
+ registry,
83204
+ sdkConfig: sdkConfig ? { customBlocks: sdkConfig.customBlocks } : null,
83205
+ customBlocks
83206
+ };
83207
+ const content = isOverrideOnlyPage(props) ? /* @__PURE__ */ jsx(PageRenderer, {
83208
+ ...rendererCommonProps,
83209
+ rendering: { kind: "overrides-only" },
83210
+ blockOverrides: props.blockOverrides
83211
+ }) : /* @__PURE__ */ jsx(PageRenderer, {
83212
+ ...rendererCommonProps,
83213
+ theme: props.theme,
83214
+ themeTokens: resolvePageThemeTokens(props),
83215
+ blockOverrides
83216
+ });
83217
+ return isOverrideOnlyPage(props) ? renderWithOverrideOnlyRuntime({
83218
+ runtime: props.rendering.runtime,
83219
+ children: content
83220
+ }) : renderWithSdkThemeRuntime({
83221
+ themeRuntime: props.themeRuntime ?? defaultPageThemeRuntime,
83222
+ theme: props.theme,
83223
+ children: content
82960
83224
  });
82961
83225
  }
82962
83226
  //#endregion
82963
- //#region src/rendering/components/Page.server.tsx
82964
- function Page(props) {
82965
- return /* @__PURE__ */ jsx(PageContent, { ...props });
82966
- }
82967
- //#endregion
82968
- //#region src/rendering/overrides.ts
82969
- const lazyBlockOverrideSymbol = Symbol.for("riverbankcms.sdk.lazyBlockOverride");
82970
- //#endregion
82971
- //#region src/rendering/overrideResolution.ts
82972
- function isRecord(value) {
82973
- return typeof value === "object" && value !== null;
82974
- }
82975
- function isBlockOutlineLike(value) {
82976
- const id = value.id;
82977
- return typeof value.kind === "string" && (typeof id === "string" || id === null) && (typeof value.purpose === "string" || isRecord(value.content) || isRecord(value.draftContent) || isRecord(value.bindings));
82978
- }
82979
- /**
82980
- * Walk a page's block tree and collect override candidate kinds.
82981
- *
82982
- * The CMS block contract is structural at this boundary: nested blocks can live
82983
- * inside custom block content, so traversal cannot rely on a fixed property
82984
- * name. To avoid matching arbitrary content such as `{ kind: "video" }`, only
82985
- * objects with a block identity (`id` plus `kind`) and at least one block
82986
- * contract field (`purpose`, `content`, `draftContent`, or `bindings`) count.
82987
- */
82988
- function collectBlockKindsFromValue(value, usedKinds, seen) {
82989
- if (!isRecord(value)) return;
82990
- if (seen.has(value)) return;
82991
- seen.add(value);
82992
- if (isBlockOutlineLike(value)) usedKinds.add(value.kind);
82993
- for (const child of Object.values(value)) {
82994
- if (Array.isArray(child)) {
82995
- for (const item of child) collectBlockKindsFromValue(item, usedKinds, seen);
82996
- continue;
82997
- }
82998
- collectBlockKindsFromValue(child, usedKinds, seen);
82999
- }
83000
- }
83001
- function collectUsedBlockKindsFromPageOutline(page) {
83002
- const usedKinds = /* @__PURE__ */ new Set();
83003
- const seen = /* @__PURE__ */ new WeakSet();
83004
- for (const block of page?.blocks ?? []) collectBlockKindsFromValue(block, usedKinds, seen);
83005
- return usedKinds;
83006
- }
83007
- function buildPageBlockKindIndex(page) {
83008
- return {
83009
- kind: "page-block-kind-index",
83010
- blockKinds: collectUsedBlockKindsFromPageOutline(page)
83227
+ //#region src/rendering/renderingMode.ts
83228
+ const defaultOverrideOnlyRuntime = { kind: "responsive-only" };
83229
+ function normalizeSdkRenderingMode(input) {
83230
+ return input.rendering?.kind === "overrides-only" ? {
83231
+ kind: "overrides-only",
83232
+ runtime: input.rendering.runtime ?? defaultOverrideOnlyRuntime
83233
+ } : {
83234
+ kind: "themed",
83235
+ themeRuntime: input.themeRuntime
83011
83236
  };
83012
83237
  }
83013
- function shortBlockKind(blockKind) {
83014
- return blockKind.replace(/^block\./, "");
83015
- }
83016
- function selectOverrideKeysForUsedKinds(usedKinds, entries) {
83017
- const availableKeys = new Set(entries.map(([key]) => key));
83018
- const selectedKeys = /* @__PURE__ */ new Set();
83019
- for (const blockKind of usedKinds) {
83020
- if (availableKeys.has(blockKind)) {
83021
- selectedKeys.add(blockKind);
83022
- continue;
83023
- }
83024
- const shortKind = shortBlockKind(blockKind);
83025
- if (availableKeys.has(shortKind)) selectedKeys.add(shortKind);
83026
- }
83027
- return selectedKeys;
83028
- }
83029
- function isLazyRegistration(registration) {
83030
- return isRecord(registration) && registration[lazyBlockOverrideSymbol] === true;
83031
- }
83032
- async function resolveOverrideComponent(registration) {
83033
- if (isLazyRegistration(registration)) return registration.load();
83034
- return registration;
83035
- }
83036
- /**
83037
- * Resolve only override registrations used by the current page or template.
83038
- *
83039
- * Eager components are passed through unchanged. Lazy registrations created
83040
- * with `defineLazyBlockOverride()` are loaded only after their block kind is
83041
- * found in the rendered block tree.
83042
- */
83043
- async function resolveBlockOverridesForPage(registrations, page) {
83044
- if (!registrations) return void 0;
83045
- const entries = Object.entries(registrations);
83046
- if (entries.length === 0) return void 0;
83047
- const selectedKeys = selectOverrideKeysForUsedKinds(buildPageBlockKindIndex(page).blockKinds, entries);
83048
- if (selectedKeys.size === 0) return void 0;
83049
- const resolved = {};
83050
- for (const [key, registration] of entries) {
83051
- if (!selectedKeys.has(key)) continue;
83052
- resolved[key] = await resolveOverrideComponent(registration);
83053
- }
83054
- return resolved;
83238
+ function themeRuntimeForRendering(rendering) {
83239
+ return rendering.kind === "themed" ? rendering.themeRuntime : rendering.runtime;
83055
83240
  }
83056
83241
  //#endregion
83057
83242
  //#region src/metadata/generatePageMetadata.ts
@@ -84124,7 +84309,7 @@ var CircuitOpenError = class extends Error {
84124
84309
  * 1. This constant
84125
84310
  * 2. The "version" field in package.json
84126
84311
  */
84127
- const SDK_VERSION = "0.127.0";
84312
+ const SDK_VERSION = "0.129.0";
84128
84313
  //#endregion
84129
84314
  //#region src/next/content-load-failure.ts
84130
84315
  const SdkContentLoadError = RiverbankContentLoadError;
@@ -84285,6 +84470,159 @@ function appendSearchToRedirectDestination(destination, incomingSearch) {
84285
84470
  return `${destination.slice(0, hashIndex)}?${search}${destination.slice(hashIndex)}`;
84286
84471
  }
84287
84472
  //#endregion
84473
+ //#region src/rendering/components/Page.server.tsx
84474
+ function Page(props) {
84475
+ return /* @__PURE__ */ jsx(PageContent, { ...props });
84476
+ }
84477
+ //#endregion
84478
+ //#region src/rendering/overrides.ts
84479
+ const lazyBlockOverrideSymbol = Symbol.for("riverbankcms.sdk.lazyBlockOverride");
84480
+ //#endregion
84481
+ //#region src/rendering/overrideResolution.ts
84482
+ function isRecord(value) {
84483
+ return typeof value === "object" && value !== null;
84484
+ }
84485
+ function isBlockOutlineLike(value) {
84486
+ const id = value.id;
84487
+ return typeof value.kind === "string" && (typeof id === "string" || id === null) && (typeof value.purpose === "string" || isRecord(value.content) || isRecord(value.draftContent) || isRecord(value.bindings));
84488
+ }
84489
+ /**
84490
+ * Walk a page's block tree and collect override candidate kinds.
84491
+ *
84492
+ * The CMS block contract is structural at this boundary: nested blocks can live
84493
+ * inside custom block content, so traversal cannot rely on a fixed property
84494
+ * name. To avoid matching arbitrary content such as `{ kind: "video" }`, only
84495
+ * objects with a block identity (`id` plus `kind`) and at least one block
84496
+ * contract field (`purpose`, `content`, `draftContent`, or `bindings`) count.
84497
+ */
84498
+ function collectBlockKindsFromValue(value, usedKinds, seen) {
84499
+ if (!isRecord(value)) return;
84500
+ if (seen.has(value)) return;
84501
+ seen.add(value);
84502
+ if (isBlockOutlineLike(value)) usedKinds.add(value.kind);
84503
+ for (const child of Object.values(value)) {
84504
+ if (Array.isArray(child)) {
84505
+ for (const item of child) collectBlockKindsFromValue(item, usedKinds, seen);
84506
+ continue;
84507
+ }
84508
+ collectBlockKindsFromValue(child, usedKinds, seen);
84509
+ }
84510
+ }
84511
+ function collectUsedBlockKindsFromPageOutline(page) {
84512
+ const usedKinds = /* @__PURE__ */ new Set();
84513
+ const seen = /* @__PURE__ */ new WeakSet();
84514
+ for (const block of page?.blocks ?? []) collectBlockKindsFromValue(block, usedKinds, seen);
84515
+ return usedKinds;
84516
+ }
84517
+ function buildPageBlockKindIndex(page) {
84518
+ return {
84519
+ kind: "page-block-kind-index",
84520
+ blockKinds: collectUsedBlockKindsFromPageOutline(page)
84521
+ };
84522
+ }
84523
+ function shortBlockKind(blockKind) {
84524
+ return blockKind.replace(/^block\./, "");
84525
+ }
84526
+ function selectOverrideKeysForUsedKinds(usedKinds, entries) {
84527
+ const availableKeys = new Set(entries.map(([key]) => key));
84528
+ const selectedKeys = /* @__PURE__ */ new Set();
84529
+ for (const blockKind of usedKinds) {
84530
+ if (availableKeys.has(blockKind)) {
84531
+ selectedKeys.add(blockKind);
84532
+ continue;
84533
+ }
84534
+ const shortKind = shortBlockKind(blockKind);
84535
+ if (availableKeys.has(shortKind)) selectedKeys.add(shortKind);
84536
+ }
84537
+ return selectedKeys;
84538
+ }
84539
+ function isLazyRegistration(registration) {
84540
+ return isRecord(registration) && registration[lazyBlockOverrideSymbol] === true;
84541
+ }
84542
+ async function resolveOverrideComponent(registration) {
84543
+ if (isLazyRegistration(registration)) return registration.load();
84544
+ return registration;
84545
+ }
84546
+ /**
84547
+ * Resolve only override registrations used by the current page or template.
84548
+ *
84549
+ * Eager components are passed through unchanged. Lazy registrations created
84550
+ * with `defineLazyBlockOverride()` are loaded only after their block kind is
84551
+ * found in the rendered block tree.
84552
+ */
84553
+ async function resolveBlockOverridesForPage(registrations, page) {
84554
+ if (!registrations) return void 0;
84555
+ const entries = Object.entries(registrations);
84556
+ if (entries.length === 0) return void 0;
84557
+ const selectedKeys = selectOverrideKeysForUsedKinds(buildPageBlockKindIndex(page).blockKinds, entries);
84558
+ if (selectedKeys.size === 0) return void 0;
84559
+ const resolved = {};
84560
+ for (const [key, registration] of entries) {
84561
+ if (!selectedKeys.has(key)) continue;
84562
+ resolved[key] = await resolveOverrideComponent(registration);
84563
+ }
84564
+ return resolved;
84565
+ }
84566
+ //#endregion
84567
+ //#region src/next/renderSdkContent.tsx
84568
+ async function renderPage(input, page, dataContext) {
84569
+ const resolvedOverrides = await resolveBlockOverridesForPage(input.blockOverrides, page);
84570
+ const commonProps = {
84571
+ page,
84572
+ siteId: input.content.siteId,
84573
+ apiBaseUrl: input.apiBaseUrl,
84574
+ portalToken: input.portalToken,
84575
+ resolvedData: input.content.resolvedData,
84576
+ bookingOfferingPresets: input.content.bookingOfferingPresets,
84577
+ sdkConfig: input.content.sdkConfig,
84578
+ supabaseUrl: input.content.supabaseUrl,
84579
+ mediaAssets: input.content.mediaAssets,
84580
+ dataContext
84581
+ };
84582
+ return input.kind === "overrides-only" ? /* @__PURE__ */ jsx(Page, {
84583
+ ...commonProps,
84584
+ rendering: input.rendering,
84585
+ blockOverrides: resolvedOverrides ?? {}
84586
+ }) : /* @__PURE__ */ jsx(Page, {
84587
+ ...commonProps,
84588
+ theme: input.theme,
84589
+ themeRuntime: input.themeRuntime,
84590
+ blockOverrides: resolvedOverrides
84591
+ });
84592
+ }
84593
+ async function renderSdkContent(input) {
84594
+ const previewStage = input.preview ? "preview" : "published";
84595
+ const occurrenceContext = input.entrySubrouteContext?.kind === "event-occurrence" ? input.entrySubrouteContext.occurrence : null;
84596
+ const render = (page, dataContext) => renderPage(input, page, dataContext);
84597
+ if (isPageContent(input.content)) return {
84598
+ kind: "rendered",
84599
+ node: await render(input.content.page, { previewStage })
84600
+ };
84601
+ if (isEntryContent(input.content)) {
84602
+ if (!input.content.templatePage) return { kind: "not-found" };
84603
+ return {
84604
+ kind: "rendered",
84605
+ node: await render(input.content.templatePage, {
84606
+ contentEntry: input.content.dataContext.contentEntry,
84607
+ occurrenceContext,
84608
+ entrySubrouteContext: input.entrySubrouteContext,
84609
+ previewStage
84610
+ })
84611
+ };
84612
+ }
84613
+ if (!isPageSurfaceContent(input.content) || !input.content.templatePage) return { kind: "not-found" };
84614
+ return {
84615
+ kind: "rendered",
84616
+ node: await render(input.content.templatePage, {
84617
+ occurrenceContext,
84618
+ entrySubrouteContext: input.entrySubrouteContext,
84619
+ pageSurface: input.content.dataContext.pageSurface,
84620
+ subject: input.content.dataContext.subject,
84621
+ previewStage
84622
+ })
84623
+ };
84624
+ }
84625
+ //#endregion
84288
84626
  //#region src/next/catch-all.tsx
84289
84627
  function throwUpstreamContentError(path, resolution) {
84290
84628
  throw new RiverbankContentLoadError(`Riverbank content load failed for ${path}: ${resolution.error.message}`, {
@@ -84294,14 +84632,34 @@ function throwUpstreamContentError(path, resolution) {
84294
84632
  });
84295
84633
  }
84296
84634
  function createCatchAllRuntime(options) {
84635
+ validateCatchAllRenderingOptions(options);
84636
+ const preview = options.preview ?? detectPreviewFromClient(options.getClient);
84637
+ const rendering = normalizeSdkRenderingMode({
84638
+ rendering: options.rendering,
84639
+ themeRuntime: options.themeRuntime ?? defaultCatchAllThemeRuntime
84640
+ });
84297
84641
  return {
84298
84642
  options,
84299
- preview: options.preview ?? detectPreviewFromClient(options.getClient),
84643
+ preview,
84300
84644
  enablePortal: options.enablePortal ?? options.config.enablePortal ?? false,
84301
84645
  contentTypes: (options.config.content?.contentTypes ?? []).map(toRoutingInfo),
84302
- themeRuntime: options.themeRuntime ?? defaultCatchAllThemeRuntime
84646
+ rendering,
84647
+ themeRuntime: themeRuntimeForRendering(rendering)
84303
84648
  };
84304
84649
  }
84650
+ var InvalidCatchAllRenderingOptionsError = class extends Error {
84651
+ constructor(code) {
84652
+ super(code === "missing_block_overrides" ? "Override-only rendering requires blockOverrides." : code === "theme_runtime_in_overrides_only" ? "Override-only rendering owns its runtime wrapper; remove themeRuntime." : "Override-only rendering cannot be combined with theme resolution options.");
84653
+ this.code = code;
84654
+ this.name = "InvalidCatchAllRenderingOptionsError";
84655
+ }
84656
+ };
84657
+ function validateCatchAllRenderingOptions(options) {
84658
+ if (options.rendering?.kind !== "overrides-only") return;
84659
+ if (!options.blockOverrides) throw new InvalidCatchAllRenderingOptionsError("missing_block_overrides");
84660
+ if ("themeRuntime" in options) throw new InvalidCatchAllRenderingOptionsError("theme_runtime_in_overrides_only");
84661
+ if ("theme" in options || "themes" in options || "themeSwitch" in options || "getTheme" in options) throw new InvalidCatchAllRenderingOptionsError("theme_option_in_overrides_only");
84662
+ }
84305
84663
  const pageNotFoundMetadata = () => ({
84306
84664
  title: "Page Not Found",
84307
84665
  robots: {
@@ -84439,6 +84797,7 @@ async function resolveCatchAllTheme(runtime, input) {
84439
84797
  path: input.path,
84440
84798
  preview: runtime.preview,
84441
84799
  themeRuntime: runtime.themeRuntime,
84800
+ rendering: runtime.rendering,
84442
84801
  searchParams: input.searchParams,
84443
84802
  config: runtime.options.config,
84444
84803
  themeKey: requestedThemeKey(runtime, input.searchParams)
@@ -84455,60 +84814,6 @@ async function resolveCatchAllTheme(runtime, input) {
84455
84814
  context
84456
84815
  });
84457
84816
  }
84458
- async function renderPageComponent(runtime, input) {
84459
- const resolvedBlockOverrides = await resolveBlockOverridesForPage(runtime.options.blockOverrides, input.page);
84460
- return /* @__PURE__ */ jsx(Page, {
84461
- page: input.page,
84462
- theme: input.theme,
84463
- siteId: input.content.siteId,
84464
- apiBaseUrl: input.apiBaseUrl,
84465
- portalToken: input.portalToken,
84466
- resolvedData: input.content.resolvedData,
84467
- bookingOfferingPresets: input.content.bookingOfferingPresets,
84468
- blockOverrides: resolvedBlockOverrides,
84469
- sdkConfig: input.content.sdkConfig,
84470
- supabaseUrl: input.content.supabaseUrl,
84471
- mediaAssets: input.content.mediaAssets,
84472
- themeRuntime: runtime.themeRuntime,
84473
- dataContext: input.dataContext
84474
- });
84475
- }
84476
- async function renderSdkContent(runtime, input) {
84477
- const previewStage = runtime.preview ? "preview" : "published";
84478
- const occurrenceContext = input.entrySubrouteContext?.kind === "event-occurrence" ? input.entrySubrouteContext.occurrence : null;
84479
- const render = (page, dataContext) => renderPageComponent(runtime, {
84480
- ...input,
84481
- page,
84482
- dataContext
84483
- });
84484
- if (isPageContent(input.content)) return {
84485
- kind: "rendered",
84486
- node: await render(input.content.page, { previewStage })
84487
- };
84488
- if (isEntryContent(input.content)) {
84489
- if (!input.content.templatePage) return { kind: "not-found" };
84490
- return {
84491
- kind: "rendered",
84492
- node: await render(input.content.templatePage, {
84493
- contentEntry: input.content.dataContext.contentEntry,
84494
- occurrenceContext,
84495
- entrySubrouteContext: input.entrySubrouteContext,
84496
- previewStage
84497
- })
84498
- };
84499
- }
84500
- if (!isPageSurfaceContent(input.content) || !input.content.templatePage) return { kind: "not-found" };
84501
- return {
84502
- kind: "rendered",
84503
- node: await render(input.content.templatePage, {
84504
- occurrenceContext,
84505
- entrySubrouteContext: input.entrySubrouteContext,
84506
- pageSurface: input.content.dataContext.pageSurface,
84507
- subject: input.content.dataContext.subject,
84508
- previewStage
84509
- })
84510
- };
84511
- }
84512
84817
  async function renderResolvedCatchAllPage(runtime, input) {
84513
84818
  if (runtime.options.beforeRender) {
84514
84819
  const intercepted = await runtime.options.beforeRender({
@@ -84516,20 +84821,36 @@ async function renderResolvedCatchAllPage(runtime, input) {
84516
84821
  path: input.path,
84517
84822
  preview: runtime.preview,
84518
84823
  themeRuntime: runtime.themeRuntime,
84824
+ rendering: runtime.rendering,
84519
84825
  searchParams: input.searchParams
84520
84826
  });
84521
84827
  if (intercepted !== null) return wrapCatchAllNode(runtime, intercepted);
84522
84828
  }
84523
- const themeResult = await resolveCatchAllTheme(runtime, input);
84524
- if (themeResult.kind === "not-found") return notFound();
84525
- if (themeResult.warning) console.warn(themeResult.warning);
84526
- const rendered = await renderSdkContent(runtime, {
84829
+ const commonRenderInput = {
84527
84830
  apiBaseUrl: input.apiBaseUrl,
84528
84831
  content: input.content,
84529
84832
  entrySubrouteContext: input.entrySubrouteContext,
84530
- portalToken: input.portalToken,
84531
- theme: themeResult.theme
84532
- });
84833
+ portalToken: input.portalToken
84834
+ };
84835
+ const rendered = runtime.rendering.kind === "overrides-only" ? await renderSdkContent({
84836
+ ...commonRenderInput,
84837
+ blockOverrides: runtime.options.blockOverrides,
84838
+ kind: "overrides-only",
84839
+ preview: runtime.preview,
84840
+ rendering: runtime.rendering
84841
+ }) : await (async () => {
84842
+ const themeResult = await resolveCatchAllTheme(runtime, input);
84843
+ if (themeResult.kind === "not-found") return notFound();
84844
+ if (themeResult.warning) console.warn(themeResult.warning);
84845
+ return renderSdkContent({
84846
+ ...commonRenderInput,
84847
+ blockOverrides: runtime.options.blockOverrides,
84848
+ kind: "themed",
84849
+ preview: runtime.preview,
84850
+ theme: themeResult.theme,
84851
+ themeRuntime: runtime.themeRuntime
84852
+ });
84853
+ })();
84533
84854
  if (rendered.kind === "not-found") return notFound();
84534
84855
  return wrapCatchAllNode(runtime, /* @__PURE__ */ jsxs("main", { children: [/* @__PURE__ */ jsx(BlocksIslandsHydrator, { ...toPageHydrationBootstrapConfig({
84535
84856
  siteId: input.content.siteId,
@@ -84594,6 +84915,7 @@ async function resolveCatchAllMetadata(runtime, input) {
84594
84915
  path: input.path,
84595
84916
  preview: runtime.preview,
84596
84917
  themeRuntime: runtime.themeRuntime,
84918
+ rendering: runtime.rendering,
84597
84919
  searchParams: input.searchParams
84598
84920
  });
84599
84921
  const resolvedUrl = runtime.options.siteUrl ?? (runtime.preview ? runtime.options.config.previewUrl : runtime.options.config.liveUrl) ?? "";
@@ -85309,6 +85631,39 @@ function createContentReadOperations(input) {
85309
85631
  };
85310
85632
  }
85311
85633
  //#endregion
85634
+ //#region src/client/wholeSeriesReadOperations.ts
85635
+ function createWholeSeriesReadOperations(deps) {
85636
+ return { async getPublicWholeSeriesOffering(params) {
85637
+ const { siteId, eventSeriesId, stage, signal } = params;
85638
+ if (!siteId) throw new Error("getPublicWholeSeriesOffering() requires siteId");
85639
+ if (!eventSeriesId) throw new Error("getPublicWholeSeriesOffering() requires eventSeriesId");
85640
+ const cacheKey = `public-whole-series-offering:${siteId}:${eventSeriesId}:${stage ?? ""}`;
85641
+ return deps.resilientFetchData(cacheKey, (requestSignal) => deps.apiClient({
85642
+ endpoint: "getPublicWholeSeriesOffering",
85643
+ params: {
85644
+ siteId,
85645
+ eventSeriesId,
85646
+ ...stage && { stage }
85647
+ },
85648
+ options: { signal: requestSignal }
85649
+ }), { signal });
85650
+ } };
85651
+ }
85652
+ //#endregion
85653
+ //#region src/client/combineAbortSignals.ts
85654
+ /** Combine signals into one that aborts when any input aborts. */
85655
+ function combineAbortSignals(...signals) {
85656
+ const controller = new AbortController();
85657
+ for (const signal of signals) {
85658
+ if (signal.aborted) {
85659
+ controller.abort(signal.reason);
85660
+ break;
85661
+ }
85662
+ signal.addEventListener("abort", () => controller.abort(signal.reason), { once: true });
85663
+ }
85664
+ return controller.signal;
85665
+ }
85666
+ //#endregion
85312
85667
  //#region src/client/index.ts
85313
85668
  let prebuildModule = null;
85314
85669
  function tryRequire(modulePath) {
@@ -85814,25 +86169,15 @@ function createRiverbankClientWithDeps(deps, config) {
85814
86169
  async function resilientFetchData(cacheKey, fetcher, options) {
85815
86170
  return (await resilientFetch(cacheKey, fetcher, options)).data;
85816
86171
  }
85817
- /**
85818
- * Combine multiple AbortSignals into one that aborts when any input aborts
85819
- */
85820
- function combineAbortSignals(...signals) {
85821
- const controller = new AbortController();
85822
- for (const signal of signals) {
85823
- if (signal.aborted) {
85824
- controller.abort(signal.reason);
85825
- break;
85826
- }
85827
- signal.addEventListener("abort", () => controller.abort(signal.reason), { once: true });
85828
- }
85829
- return controller.signal;
85830
- }
85831
86172
  const contentReads = createContentReadOperations({
85832
86173
  apiClient,
85833
86174
  resilientFetch,
85834
86175
  prebuildLoader
85835
86176
  });
86177
+ const wholeSeriesReads = createWholeSeriesReadOperations({
86178
+ apiClient,
86179
+ resilientFetchData
86180
+ });
85836
86181
  async function getEntriesInternal(params) {
85837
86182
  const { siteId, contentType, limit, offset, order, preview = false, mode, entryIds, includeMeta, signal } = params;
85838
86183
  const entryIdsCacheKey = mode === "manual" && entryIds?.length ? entryIds.join(",") : "";
@@ -85866,6 +86211,7 @@ function createRiverbankClientWithDeps(deps, config) {
85866
86211
  });
85867
86212
  }
85868
86213
  return {
86214
+ ...wholeSeriesReads,
85869
86215
  async getSite(params) {
85870
86216
  return (await contentReads.getSiteWithResilience(params)).data;
85871
86217
  },
@@ -86588,4 +86934,4 @@ function getISRConfig() {
86588
86934
  };
86589
86935
  }
86590
86936
  //#endregion
86591
- export { ISR_REVALIDATE_SECONDS, RiverbankContentLoadError, SdkContentLoadError, classifyContentLoadError, createCatchAllPage, createGenerateStaticParams, createRobots, createSitemap, generateAllStaticParams, getISRConfig, isSdkContentLoadError, normalizeStaticRoutePath, pathToSlugArray, routesToStaticParams, toContentLoadFailureLogFields, validateStaticParamsEnv };
86937
+ export { ISR_REVALIDATE_SECONDS, InvalidCatchAllRenderingOptionsError, RiverbankContentLoadError, SdkContentLoadError, classifyContentLoadError, createCatchAllPage, createGenerateStaticParams, createRobots, createSitemap, generateAllStaticParams, getISRConfig, isSdkContentLoadError, normalizeStaticRoutePath, pathToSlugArray, routesToStaticParams, toContentLoadFailureLogFields, validateStaticParamsEnv };