@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
@@ -220,7 +220,7 @@ function formatEventPricing(pricing, options = {}) {
220
220
  //#endregion
221
221
  //#region ../core/src/event-page-surface-subject.ts
222
222
  function parseEventPageSurfaceSubject(value) {
223
- if (!isRecord$36(value)) return err$3({ kind: "notObject" });
223
+ if (!isRecord$38(value)) return err$3({ kind: "notObject" });
224
224
  switch (value.kind) {
225
225
  case "eventSeries": {
226
226
  const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
@@ -263,7 +263,7 @@ function parseEventPageSurfaceSubject(value) {
263
263
  });
264
264
  }
265
265
  }
266
- function isRecord$36(value) {
266
+ function isRecord$38(value) {
267
267
  return typeof value === "object" && value !== null && !Array.isArray(value);
268
268
  }
269
269
  //#endregion
@@ -497,7 +497,7 @@ function toLocationCoordinates(value) {
497
497
  }
498
498
  //#endregion
499
499
  //#region ../core/src/rich-text.ts
500
- function isRecord$34(value) {
500
+ function isRecord$36(value) {
501
501
  return typeof value === "object" && value !== null && !Array.isArray(value);
502
502
  }
503
503
  function hasOnlyKeys(value, allowed) {
@@ -516,13 +516,16 @@ function isDenseArrayOf(value, predicate) {
516
516
  return true;
517
517
  }
518
518
  function isTipTapMark(value) {
519
- return isRecord$34(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$34(value.attrs));
519
+ return isRecord$36(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$36(value.attrs));
520
520
  }
521
521
  function isTipTapNode(value) {
522
- if (!isRecord$34(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$34(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;
522
+ if (!isRecord$36(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$36(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;
523
523
  if (value.type === "text") return typeof value.text === "string" && value.text.length > 0 && value.content === void 0;
524
524
  return value.text === void 0;
525
525
  }
526
+ function parseNewsletterSignupDestinationProvider(value) {
527
+ return value === "riverbank" || value === "mailchimp" ? value : null;
528
+ }
526
529
  new Map([
527
530
  "brand",
528
531
  "supporting-text",
@@ -531,6 +534,7 @@ new Map([
531
534
  "business-address",
532
535
  "contact",
533
536
  "opening-hours",
537
+ "engagement",
534
538
  "legal-navigation",
535
539
  "legal"
536
540
  ].map((kind, index) => [kind, index]));
@@ -568,9 +572,9 @@ function resolvePlanningDateInput(input = {}) {
568
572
  }
569
573
  //#endregion
570
574
  //#region ../media-core/src/fileSafety.ts
571
- const CONTROL_CHARACTER_PATTERN$1 = /[\u0000-\u001f\u007f]/u;
575
+ const CONTROL_CHARACTER_PATTERN = /[\u0000-\u001f\u007f]/u;
572
576
  function containsUnsafePathSegmentCharacter(value) {
573
- return value.includes("/") || value.includes("\\") || CONTROL_CHARACTER_PATTERN$1.test(value);
577
+ return value.includes("/") || value.includes("\\") || CONTROL_CHARACTER_PATTERN.test(value);
574
578
  }
575
579
  function isReservedPathSegment(value) {
576
580
  return value === "." || value === "..";
@@ -17282,10 +17286,16 @@ function getHeaderPaintTargets(variant, themeId, state = "base") {
17282
17286
  ownerSelector: desktopOwner,
17283
17287
  selector: `${desktopOwner}::before`,
17284
17288
  mediaQuery: MQ_MD_UP,
17285
- topExtension: {
17286
- customProperty: "--rb-header-floating-top-gap",
17287
- value: "1rem",
17288
- ownerProperty: "top"
17289
+ extent: {
17290
+ top: {
17291
+ customProperty: "--rb-header-floating-top-gap",
17292
+ value: "1rem",
17293
+ ownerProperty: "top"
17294
+ },
17295
+ bottom: {
17296
+ customProperty: "--rb-header-floating-bottom-extension",
17297
+ value: "0.75rem"
17298
+ }
17289
17299
  },
17290
17300
  ownerNeedsPositioning: false
17291
17301
  }, {
@@ -17294,10 +17304,16 @@ function getHeaderPaintTargets(variant, themeId, state = "base") {
17294
17304
  ownerSelector: mobileOwner,
17295
17305
  selector: `${mobileOwner}::before`,
17296
17306
  mediaQuery: MQ_MD_DOWN,
17297
- topExtension: {
17298
- customProperty: "--rb-header-floating-top-gap",
17299
- value: "0.75rem",
17300
- ownerProperty: "margin-top"
17307
+ extent: {
17308
+ top: {
17309
+ customProperty: "--rb-header-floating-top-gap",
17310
+ value: "0.75rem",
17311
+ ownerProperty: "margin-top"
17312
+ },
17313
+ bottom: {
17314
+ customProperty: "--rb-header-floating-bottom-extension",
17315
+ value: "0.75rem"
17316
+ }
17301
17317
  },
17302
17318
  ownerNeedsPositioning: true
17303
17319
  }];
@@ -17338,10 +17354,11 @@ function renderHeaderPaintTargetRule(target, rules) {
17338
17354
  return `${target.selector} {\n ${[...pseudoElementSetup, ...rules].join("\n ")}\n}`;
17339
17355
  }
17340
17356
  case "viewport-band": {
17341
- const gap = target.topExtension;
17357
+ const { top, bottom } = target.extent;
17342
17358
  const ownerRules = [
17343
- `${gap.customProperty}: ${gap.value};`,
17344
- `${gap.ownerProperty}: var(${gap.customProperty});`,
17359
+ `${top.customProperty}: ${top.value};`,
17360
+ `${bottom.customProperty}: ${bottom.value};`,
17361
+ `${top.ownerProperty}: var(${top.customProperty});`,
17345
17362
  ...target.ownerNeedsPositioning ? ["position: relative;"] : [],
17346
17363
  "isolation: isolate;",
17347
17364
  "background: none;",
@@ -17353,8 +17370,8 @@ function renderHeaderPaintTargetRule(target, rules) {
17353
17370
  const bandRules = [
17354
17371
  "content: \"\";",
17355
17372
  "position: absolute;",
17356
- `top: calc(-1 * var(${gap.customProperty}));`,
17357
- "bottom: 0;",
17373
+ `top: calc(-1 * var(${top.customProperty}));`,
17374
+ `bottom: calc(-1 * var(${bottom.customProperty}));`,
17358
17375
  "left: 50%;",
17359
17376
  "width: 100vw;",
17360
17377
  "transform: translateX(-50%);",
@@ -17373,6 +17390,7 @@ const headerScrollTreatmentSchema = z$1.discriminatedUnion("kind", [z$1.object({
17373
17390
  kind: z$1.literal("contrast-glass"),
17374
17391
  backgroundTone: z$1.enum(["light", "dark"])
17375
17392
  })]).optional();
17393
+ const CONTRAST_GLASS_BLUR = "blur(12px)";
17376
17394
  function generateMobileOverlayBackdropFilterFix(themeId, variant) {
17377
17395
  const root = `:where([data-theme-scope="${themeId}"]) .header-root:has([data-nav-mobile-overlay][aria-hidden="false"])`;
17378
17396
  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`;
@@ -17382,7 +17400,12 @@ function generateHeaderScrollTreatmentStyles(treatment, themeId, variant, surfac
17382
17400
  switch (treatment.kind) {
17383
17401
  case "contrast-glass": {
17384
17402
  const backgroundChannels = treatment.backgroundTone === "dark" ? "0 0 0" : "255 255 255";
17385
- return renderHeaderPaintTargetRules(getHeaderPaintTargets(variant, themeId, "scrolled"), [`background-color: rgb(${backgroundChannels} / 0.60);`, ...surfaceRules]);
17403
+ return renderHeaderPaintTargetRules(getHeaderPaintTargets(variant, themeId, "scrolled"), [
17404
+ `background-color: rgb(${backgroundChannels} / 0.60);`,
17405
+ `backdrop-filter: ${CONTRAST_GLASS_BLUR};`,
17406
+ `-webkit-backdrop-filter: ${CONTRAST_GLASS_BLUR};`,
17407
+ ...surfaceRules
17408
+ ]);
17386
17409
  }
17387
17410
  }
17388
17411
  }
@@ -25709,6 +25732,7 @@ const newsletterFormFragment = defineFragment({
25709
25732
  }
25710
25733
  ],
25711
25734
  layout: [el("newsletter-form", withApiBindings({
25735
+ source: "block",
25712
25736
  destinationProvider: { $bind: { from: "destinationProvider" } },
25713
25737
  listId: { $bind: { from: "listId" } },
25714
25738
  preset: { $bind: { from: "preset" } },
@@ -27231,6 +27255,7 @@ const contactNewsletterLayout = styledSection({
27231
27255
  as: "h2",
27232
27256
  className: "newsletter-copy-title"
27233
27257
  }, when("newsletterTitle"), bind("newsletterTitle")), richText({ className: "newsletter-copy-subtitle rb-prose rb-max-w-none" }, when("newsletterSubtitle"), bind("newsletterSubtitle"))]), el("newsletter-form", withApiBindings({
27258
+ source: "block",
27234
27259
  listId: { $bind: { from: "listId" } },
27235
27260
  preset: { $bind: { from: "preset" } },
27236
27261
  includePhone: { $bind: { from: "includePhone" } },
@@ -29229,6 +29254,22 @@ const footerNavGroupsLayout = stack({
29229
29254
  }, [text({ as: "span" }, bind("entry.label"))], repeat("group.children", "entry"))])], repeat("footerMenu.groups", "group"))], whenCollectionHasItems("footerMenu.groups"));
29230
29255
  //#endregion
29231
29256
  //#region ../blocks/src/system/blocks/site-footer.ts
29257
+ const footerStandardContactBindings = {
29258
+ value: { $bind: { from: "module.engagement.runtime.value" } },
29259
+ submitLabel: { $bind: { from: "module.engagement.runtime.submitLabel" } },
29260
+ successMessage: { $bind: { from: "module.engagement.runtime.successMessage" } }
29261
+ };
29262
+ const footerMailingListBindings = {
29263
+ source: { $bind: { from: "module.engagement.runtime.source" } },
29264
+ destinationRef: { $bind: { from: "module.engagement.runtime.destinationRef" } },
29265
+ listId: { $bind: { from: "module.engagement.runtime.listId" } },
29266
+ preset: { $bind: { from: "module.engagement.runtime.preset" } },
29267
+ includePhone: { $bind: { from: "module.engagement.runtime.includePhone" } },
29268
+ buttonLabel: { $bind: { from: "module.engagement.runtime.buttonLabel" } },
29269
+ successMessage: { $bind: { from: "module.engagement.runtime.successMessage" } },
29270
+ privacyNote: { $bind: { from: "module.engagement.runtime.privacyNote" } }
29271
+ };
29272
+ const footerSpamProtectionBinding = { spamProtectionEnabled: { $bind: { from: "$root.spamProtectionEnabled" } } };
29232
29273
  const brandLogo = link({
29233
29274
  href: "/",
29234
29275
  className: { $bind: {
@@ -29306,6 +29347,23 @@ const authoredCopy = richText({
29306
29347
  id: "content.interpolateRichTextTokens",
29307
29348
  options: { tokens: ["year", "site_name"] }
29308
29349
  }] }));
29350
+ const footerEngagement = stack({
29351
+ gap: "md",
29352
+ className: "rb-w-full"
29353
+ }, [
29354
+ text({
29355
+ as: "p",
29356
+ className: "rb-body rb-opacity-80"
29357
+ }, bind("module.engagement.intro"), when("module.engagement.intro")),
29358
+ form(withApiBindings({
29359
+ ...footerStandardContactBindings,
29360
+ ...footerSpamProtectionBinding
29361
+ }), [], when("module.engagement.kind", { equals: "standard-contact" })),
29362
+ el("newsletter-form", withApiBindings({
29363
+ ...footerMailingListBindings,
29364
+ ...footerSpamProtectionBinding
29365
+ }), [], when("module.engagement.kind", { equals: "mailing-list" }))
29366
+ ], when("module.kind", { equals: "engagement" }));
29309
29367
  const footerGroup = stack({
29310
29368
  gap: "md",
29311
29369
  align: "stretch",
@@ -29331,6 +29389,7 @@ const footerGroup = stack({
29331
29389
  contact,
29332
29390
  hours,
29333
29391
  socials,
29392
+ footerEngagement,
29334
29393
  stack({ className: "rb-w-full" }, [authoredCopy], when("module.kind", { equals: "supporting-text" })),
29335
29394
  stack({ className: "rb-w-full rb-lg-col-span-3" }, [authoredCopy], when("module.kind", { equals: "legal" }))
29336
29395
  ], repeat("group.modules", "module"))], repeat("region.groups", "group"));
@@ -29338,6 +29397,10 @@ const footerMainRegion = stack({
29338
29397
  className: { $bind: { from: "region.className" } },
29339
29398
  "data-footer-region": { $bind: { from: "region.kind" } }
29340
29399
  }, [footerGroup], when("region.kind", { equals: "main" }), repeat("content.footerRuntime.regions", "region"));
29400
+ const footerEngagementRegion = stack({
29401
+ className: { $bind: { from: "region.className" } },
29402
+ "data-footer-region": "engagement-row"
29403
+ }, [footerGroup], when("region.kind", { equals: "engagement-row" }), repeat("content.footerRuntime.regions", "region"));
29341
29404
  const footerBottomRegion = stack({ className: { $bind: {
29342
29405
  from: "$root.theme.footer",
29343
29406
  transforms: [{ id: "layout.footerBottomBarContainerClass" }],
@@ -29373,7 +29436,11 @@ const siteFooterManifest = createBlockManifest({
29373
29436
  fallback: mergeStyles(backgroundColorStyle("surface"), surfaceForegroundStyle({ text: "rgb(var(--tb-text))" }), borderColorStyle("border"))
29374
29437
  } },
29375
29438
  "data-footer-membership": { $bind: { from: "content.footerRuntime.membershipKey" } }
29376
- }, [footerMainRegion, footerBottomRegion]),
29439
+ }, [
29440
+ footerEngagementRegion,
29441
+ footerMainRegion,
29442
+ footerBottomRegion
29443
+ ]),
29377
29444
  description: "Site-wide composed footer with canonical shared details.",
29378
29445
  styleTokens: { spacing: "md" },
29379
29446
  paletteHidden: true
@@ -31957,7 +32024,7 @@ const publicMembershipProductCollectionSchema = z$1.object({ memberships: z$1.ar
31957
32024
  * Kept in a shared module so the block definition and runtime contracts can
31958
32025
  * depend on the same schema without creating an initialization cycle.
31959
32026
  */
31960
- const occurrenceContextSchema$1 = z$1.object({
32027
+ const occurrenceContextSchema = z$1.object({
31961
32028
  id: z$1.string(),
31962
32029
  seriesId: z$1.string(),
31963
32030
  startsAt: z$1.string(),
@@ -32357,28 +32424,37 @@ const EVENT_REGISTRATION_SHELL_STEP_LABELS = [
32357
32424
  "Payment"
32358
32425
  ];
32359
32426
  const eventRegistrationPublicEventSchema = z$1.preprocess(normalizeEventRegistrationEventInput, publicEventSchema);
32360
- const eventRegistrationSourceSchema = z$1.object({
32361
- siteId: z$1.string().optional(),
32362
- apiBaseUrl: z$1.string().optional(),
32363
- portalToken: z$1.string().nullable().optional(),
32364
- previewToken: z$1.string().nullable().optional(),
32365
- occurrenceContext: occurrenceContextSchema$1.optional(),
32427
+ const eventRegistrationHydrationSchemaShape = {
32428
+ occurrenceContext: occurrenceContextSchema.optional(),
32366
32429
  subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
32367
32430
  events: z$1.array(eventRegistrationPublicEventSchema).nullable().optional(),
32368
- className: z$1.string().nullable().optional(),
32369
- buttonText: z$1.string().nullable().optional(),
32370
- maxTickets: z$1.string().nullable().optional(),
32431
+ wholeSeriesOfferings: publicCoursesArraySchema.nullable().optional(),
32432
+ wholeSeriesOffering: publicCourseSchema.nullable().optional(),
32433
+ maxTickets: z$1.string().optional(),
32371
32434
  showVenue: z$1.boolean().optional(),
32372
32435
  showCapacity: z$1.boolean().optional(),
32436
+ showSessions: z$1.boolean().optional(),
32437
+ showPrice: z$1.boolean().optional(),
32373
32438
  successMessage: z$1.string().optional(),
32374
32439
  waitlistMessage: z$1.string().optional(),
32440
+ membershipMessage: z$1.string().optional(),
32375
32441
  buttonVariant: registrationButtonVariantSchema.optional(),
32376
32442
  overlayEnabled: z$1.boolean().optional(),
32377
32443
  spamProtectionEnabled: z$1.boolean().optional(),
32378
- stage: previewStageSchema.optional(),
32379
32444
  supportEmail: z$1.string().optional(),
32380
32445
  sitePasses: publicPassProductCollectionSchema.nullable().optional(),
32381
32446
  siteMemberships: publicMembershipProductCollectionSchema.nullable().optional()
32447
+ };
32448
+ const eventRegistrationSourceSchema = z$1.object({
32449
+ siteId: z$1.string().optional(),
32450
+ apiBaseUrl: z$1.string().optional(),
32451
+ portalToken: z$1.string().nullable().optional(),
32452
+ previewToken: z$1.string().nullable().optional(),
32453
+ ...eventRegistrationHydrationSchemaShape,
32454
+ className: z$1.string().nullable().optional(),
32455
+ buttonText: z$1.string().nullable().optional(),
32456
+ maxTickets: z$1.string().nullable().optional(),
32457
+ stage: previewStageSchema.optional()
32382
32458
  });
32383
32459
  const eventRegistrationDisplaySchema = z$1.object({
32384
32460
  kind: z$1.literal("event-registration"),
@@ -32389,22 +32465,7 @@ const eventRegistrationDisplaySchema = z$1.object({
32389
32465
  stepLabels: z$1.array(z$1.enum(EVENT_REGISTRATION_SHELL_STEP_LABELS)).min(1),
32390
32466
  summaryButtonText: z$1.string()
32391
32467
  });
32392
- const eventRegistrationHydrationSchema = z$1.object({
32393
- occurrenceContext: occurrenceContextSchema$1.optional(),
32394
- subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
32395
- events: z$1.array(eventRegistrationPublicEventSchema).nullable().optional(),
32396
- maxTickets: z$1.string().optional(),
32397
- showVenue: z$1.boolean().optional(),
32398
- showCapacity: z$1.boolean().optional(),
32399
- successMessage: z$1.string().optional(),
32400
- waitlistMessage: z$1.string().optional(),
32401
- buttonVariant: registrationButtonVariantSchema.optional(),
32402
- overlayEnabled: z$1.boolean().optional(),
32403
- spamProtectionEnabled: z$1.boolean().optional(),
32404
- supportEmail: z$1.string().optional(),
32405
- sitePasses: publicPassProductCollectionSchema.nullable().optional(),
32406
- siteMemberships: publicMembershipProductCollectionSchema.nullable().optional()
32407
- });
32468
+ const eventRegistrationHydrationSchema = z$1.object(eventRegistrationHydrationSchemaShape);
32408
32469
  const eventRegistrationRenderSchema = z$1.object({
32409
32470
  display: eventRegistrationDisplaySchema,
32410
32471
  hydration: eventRegistrationHydrationSchema
@@ -32484,11 +32545,16 @@ const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
32484
32545
  occurrenceContext: source.occurrenceContext ?? null,
32485
32546
  subject: source.subject ?? null,
32486
32547
  events: source.events ?? null,
32548
+ wholeSeriesOfferings: source.wholeSeriesOfferings ?? null,
32549
+ wholeSeriesOffering: source.wholeSeriesOffering ?? null,
32487
32550
  maxTickets: source.maxTickets ?? void 0,
32488
32551
  showVenue: source.showVenue,
32489
32552
  showCapacity: source.showCapacity,
32553
+ showSessions: source.showSessions,
32554
+ showPrice: source.showPrice,
32490
32555
  successMessage: source.successMessage,
32491
32556
  waitlistMessage: source.waitlistMessage,
32557
+ membershipMessage: source.membershipMessage,
32492
32558
  buttonVariant: source.buttonVariant,
32493
32559
  overlayEnabled: source.overlayEnabled,
32494
32560
  spamProtectionEnabled: source.spamProtectionEnabled,
@@ -32523,6 +32589,159 @@ function buildEventRegistrationInteractiveIslandProps(props) {
32523
32589
  source: props
32524
32590
  });
32525
32591
  }
32592
+ //#endregion
32593
+ //#region ../blocks/src/system/blocks/courses/shared/pricing.ts
32594
+ function isSaleWindowOpen(option, now) {
32595
+ if (!option.isActive) return false;
32596
+ if (option.saleStartsAt && new Date(option.saleStartsAt) > now) return false;
32597
+ if (option.saleEndsAt && new Date(option.saleEndsAt) < now) return false;
32598
+ return true;
32599
+ }
32600
+ function toExactOrFreeDisplay(amount, currency) {
32601
+ if (amount <= 0) return {
32602
+ kind: "free",
32603
+ currency
32604
+ };
32605
+ return {
32606
+ kind: "exact",
32607
+ amount,
32608
+ currency
32609
+ };
32610
+ }
32611
+ function getSelectableCoursePricingOptionsForNow(course, now) {
32612
+ if (course.pricing.pricingStrategy !== "tiered") return [];
32613
+ return [...course.pricing.options].filter((option) => isSaleWindowOpen(option, now)).sort((left, right) => {
32614
+ if (left.sortOrder !== right.sortOrder) return left.sortOrder - right.sortOrder;
32615
+ if (left.priceAmount !== right.priceAmount) return left.priceAmount - right.priceAmount;
32616
+ return left.name.localeCompare(right.name);
32617
+ });
32618
+ }
32619
+ function resolveCoursePricingState(course, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
32620
+ const selectedSlidingAmount = typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null;
32621
+ const effectiveNowInput = typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? selectedSlidingAmountOrNowInput : nowInput;
32622
+ const currency = course.pricing.currency;
32623
+ switch (course.pricing.pricingStrategy) {
32624
+ case "free": return {
32625
+ currency,
32626
+ display: {
32627
+ kind: "free",
32628
+ currency
32629
+ },
32630
+ selectableOptions: [],
32631
+ requiresSelection: false,
32632
+ selectedOption: null,
32633
+ slidingScale: null,
32634
+ selectedSlidingAmount: null,
32635
+ selectedPriceAmount: 0,
32636
+ selectedRequiresPayment: false,
32637
+ hasPaidSelection: false,
32638
+ hasFreeSelection: true
32639
+ };
32640
+ case "single": {
32641
+ const amount = course.pricing.singlePriceAmount ?? 0;
32642
+ return {
32643
+ currency,
32644
+ display: toExactOrFreeDisplay(amount, currency),
32645
+ selectableOptions: [],
32646
+ requiresSelection: false,
32647
+ selectedOption: null,
32648
+ slidingScale: null,
32649
+ selectedSlidingAmount: null,
32650
+ selectedPriceAmount: amount,
32651
+ selectedRequiresPayment: amount > 0,
32652
+ hasPaidSelection: amount > 0,
32653
+ hasFreeSelection: amount <= 0
32654
+ };
32655
+ }
32656
+ case "tiered": {
32657
+ const selectableOptions = getSelectableCoursePricingOptionsForNow(course, resolvePlanningDateInput(effectiveNowInput));
32658
+ const selectedOption = (selectedPricingOptionId ? selectableOptions.find((option) => option.id === selectedPricingOptionId) : null) ?? (selectableOptions.length === 1 ? selectableOptions[0] ?? null : null);
32659
+ const lowestAmount = selectableOptions.reduce((lowest, option) => {
32660
+ if (lowest === null || option.priceAmount < lowest) return option.priceAmount;
32661
+ return lowest;
32662
+ }, null);
32663
+ return {
32664
+ currency,
32665
+ display: lowestAmount === null ? {
32666
+ kind: "unavailable",
32667
+ currency
32668
+ } : selectableOptions.length > 1 && lowestAmount > 0 ? {
32669
+ kind: "from",
32670
+ amount: lowestAmount,
32671
+ currency
32672
+ } : toExactOrFreeDisplay(lowestAmount, currency),
32673
+ selectableOptions,
32674
+ requiresSelection: selectableOptions.length > 1,
32675
+ selectedOption,
32676
+ slidingScale: null,
32677
+ selectedSlidingAmount: null,
32678
+ selectedPriceAmount: selectedOption?.priceAmount ?? null,
32679
+ selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
32680
+ hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
32681
+ hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
32682
+ };
32683
+ }
32684
+ case "sliding_scale": {
32685
+ const minAmount = course.pricing.slidingMinAmount ?? null;
32686
+ const maxAmount = course.pricing.slidingMaxAmount ?? null;
32687
+ if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) return {
32688
+ currency,
32689
+ display: {
32690
+ kind: "unavailable",
32691
+ currency
32692
+ },
32693
+ selectableOptions: [],
32694
+ requiresSelection: true,
32695
+ selectedOption: null,
32696
+ slidingScale: null,
32697
+ selectedSlidingAmount: null,
32698
+ selectedPriceAmount: null,
32699
+ selectedRequiresPayment: false,
32700
+ hasPaidSelection: false,
32701
+ hasFreeSelection: false
32702
+ };
32703
+ const normalizedSelectedAmount = typeof selectedSlidingAmount === "number" && Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
32704
+ return {
32705
+ currency,
32706
+ display: {
32707
+ kind: "range",
32708
+ minAmount,
32709
+ maxAmount,
32710
+ currency
32711
+ },
32712
+ selectableOptions: [],
32713
+ requiresSelection: normalizedSelectedAmount === null,
32714
+ selectedOption: null,
32715
+ slidingScale: {
32716
+ minAmount,
32717
+ maxAmount,
32718
+ suggestedAmount: course.pricing.slidingSuggestedAmount ?? null
32719
+ },
32720
+ selectedSlidingAmount: normalizedSelectedAmount,
32721
+ selectedPriceAmount: normalizedSelectedAmount,
32722
+ selectedRequiresPayment: (normalizedSelectedAmount ?? 0) > 0,
32723
+ hasPaidSelection: maxAmount > 0,
32724
+ hasFreeSelection: minAmount === 0
32725
+ };
32726
+ }
32727
+ }
32728
+ }
32729
+ function formatCoursePriceDisplay(display, locale) {
32730
+ return formatBookingPriceDisplay(display, {
32731
+ decimals: "exact",
32732
+ locale
32733
+ });
32734
+ }
32735
+ function formatCoursePriceAmount(amount, currency, locale) {
32736
+ return formatCoursePriceDisplay(amount > 0 ? {
32737
+ kind: "exact",
32738
+ amount,
32739
+ currency
32740
+ } : {
32741
+ kind: "free",
32742
+ currency
32743
+ }, locale);
32744
+ }
32526
32745
  const eventRegistrationBlockDefinition = {
32527
32746
  manifest: createBlockManifest({
32528
32747
  id: "block.event-registration",
@@ -32618,6 +32837,24 @@ const eventRegistrationBlockDefinition = {
32618
32837
  defaultValue: true,
32619
32838
  ui: { intent: "display" }
32620
32839
  },
32840
+ {
32841
+ id: "showSessions",
32842
+ type: "boolean",
32843
+ label: "Show complete schedule",
32844
+ description: "Display every session for whole-series registrations",
32845
+ required: false,
32846
+ defaultValue: true,
32847
+ ui: { intent: "display" }
32848
+ },
32849
+ {
32850
+ id: "showPrice",
32851
+ type: "boolean",
32852
+ label: "Show price",
32853
+ description: "Display the whole-series price",
32854
+ required: false,
32855
+ defaultValue: true,
32856
+ ui: { intent: "display" }
32857
+ },
32621
32858
  {
32622
32859
  id: "successMessage",
32623
32860
  type: "text",
@@ -32628,6 +32865,26 @@ const eventRegistrationBlockDefinition = {
32628
32865
  defaultValue: "Thank you for registering! Check your email for confirmation details.",
32629
32866
  maxLength: 500
32630
32867
  },
32868
+ {
32869
+ id: "waitlistMessage",
32870
+ type: "text",
32871
+ label: "Waitlist message",
32872
+ description: "Message shown after joining a whole-series waitlist",
32873
+ required: false,
32874
+ multiline: true,
32875
+ defaultValue: "You've been added to the waitlist. We'll email you if a place becomes available.",
32876
+ maxLength: 500
32877
+ },
32878
+ {
32879
+ id: "membershipMessage",
32880
+ type: "text",
32881
+ label: "Membership registration message",
32882
+ description: "Message shown when a whole-series place is covered by membership",
32883
+ required: false,
32884
+ multiline: true,
32885
+ defaultValue: "Registered using your membership. Check your email for session details.",
32886
+ maxLength: 500
32887
+ },
32631
32888
  {
32632
32889
  id: "buttonText",
32633
32890
  type: "text",
@@ -32659,8 +32916,11 @@ const eventRegistrationBlockDefinition = {
32659
32916
  } },
32660
32917
  showVenue: { $bind: { from: "content.showVenue" } },
32661
32918
  showCapacity: { $bind: { from: "content.showCapacity" } },
32919
+ showSessions: { $bind: { from: "content.showSessions" } },
32920
+ showPrice: { $bind: { from: "content.showPrice" } },
32662
32921
  successMessage: { $bind: { from: "content.successMessage" } },
32663
32922
  waitlistMessage: { $bind: { from: "content.waitlistMessage" } },
32923
+ membershipMessage: { $bind: { from: "content.membershipMessage" } },
32664
32924
  buttonText: { $bind: {
32665
32925
  from: "content.buttonText",
32666
32926
  fallback: "Complete Registration"
@@ -32674,6 +32934,7 @@ const eventRegistrationBlockDefinition = {
32674
32934
  fallback: false
32675
32935
  } },
32676
32936
  events: { $bind: { from: "data.events" } },
32937
+ wholeSeriesOffering: { $bind: { from: "data.wholeSeriesOffering.offering" } },
32677
32938
  sitePasses: { $bind: { from: "data.sitePasses" } },
32678
32939
  siteMemberships: { $bind: { from: "data.siteMemberships" } },
32679
32940
  stage: { $bind: {
@@ -32687,9 +32948,10 @@ const eventRegistrationBlockDefinition = {
32687
32948
  runtime: eventRegistrationBlockRuntime,
32688
32949
  dataSchemas: {
32689
32950
  events: publicEventsArraySchema.optional(),
32951
+ wholeSeriesOffering: z$1.object({ offering: publicCourseSchema }).optional(),
32690
32952
  sitePasses: publicPassProductCollectionSchema.optional(),
32691
32953
  siteMemberships: publicMembershipProductCollectionSchema.optional(),
32692
- occurrenceContext: occurrenceContextSchema$1.optional()
32954
+ occurrenceContext: occurrenceContextSchema.optional()
32693
32955
  },
32694
32956
  dataLoaders: {
32695
32957
  events: {
@@ -32702,11 +32964,23 @@ const eventRegistrationBlockDefinition = {
32702
32964
  fallback: "published"
32703
32965
  } },
32704
32966
  readProfile: "registration",
32705
- seriesId: { $bind: { from: "$root.occurrenceContext.seriesId" } },
32967
+ seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
32706
32968
  includeOccurrenceId: { $bind: { from: "$root.occurrenceContext.id" } }
32707
32969
  },
32708
32970
  mode: "server"
32709
32971
  },
32972
+ wholeSeriesOffering: {
32973
+ endpoint: "getPublicWholeSeriesOffering",
32974
+ params: {
32975
+ siteId: { $bind: { from: "$root.siteId" } },
32976
+ eventSeriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
32977
+ stage: { $bind: {
32978
+ from: "$root.previewStage",
32979
+ fallback: "published"
32980
+ } }
32981
+ },
32982
+ mode: "server"
32983
+ },
32710
32984
  sitePasses: {
32711
32985
  endpoint: "listPublicPasses",
32712
32986
  params: { siteId: { $bind: { from: "$root.siteId" } } },
@@ -32720,159 +32994,6 @@ const eventRegistrationBlockDefinition = {
32720
32994
  }
32721
32995
  };
32722
32996
  //#endregion
32723
- //#region ../blocks/src/system/blocks/courses/shared/pricing.ts
32724
- function isSaleWindowOpen(option, now) {
32725
- if (!option.isActive) return false;
32726
- if (option.saleStartsAt && new Date(option.saleStartsAt) > now) return false;
32727
- if (option.saleEndsAt && new Date(option.saleEndsAt) < now) return false;
32728
- return true;
32729
- }
32730
- function toExactOrFreeDisplay(amount, currency) {
32731
- if (amount <= 0) return {
32732
- kind: "free",
32733
- currency
32734
- };
32735
- return {
32736
- kind: "exact",
32737
- amount,
32738
- currency
32739
- };
32740
- }
32741
- function getSelectableCoursePricingOptionsForNow(course, now) {
32742
- if (course.pricing.pricingStrategy !== "tiered") return [];
32743
- return [...course.pricing.options].filter((option) => isSaleWindowOpen(option, now)).sort((left, right) => {
32744
- if (left.sortOrder !== right.sortOrder) return left.sortOrder - right.sortOrder;
32745
- if (left.priceAmount !== right.priceAmount) return left.priceAmount - right.priceAmount;
32746
- return left.name.localeCompare(right.name);
32747
- });
32748
- }
32749
- function resolveCoursePricingState(course, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
32750
- const selectedSlidingAmount = typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null;
32751
- const effectiveNowInput = typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? selectedSlidingAmountOrNowInput : nowInput;
32752
- const currency = course.pricing.currency;
32753
- switch (course.pricing.pricingStrategy) {
32754
- case "free": return {
32755
- currency,
32756
- display: {
32757
- kind: "free",
32758
- currency
32759
- },
32760
- selectableOptions: [],
32761
- requiresSelection: false,
32762
- selectedOption: null,
32763
- slidingScale: null,
32764
- selectedSlidingAmount: null,
32765
- selectedPriceAmount: 0,
32766
- selectedRequiresPayment: false,
32767
- hasPaidSelection: false,
32768
- hasFreeSelection: true
32769
- };
32770
- case "single": {
32771
- const amount = course.pricing.singlePriceAmount ?? 0;
32772
- return {
32773
- currency,
32774
- display: toExactOrFreeDisplay(amount, currency),
32775
- selectableOptions: [],
32776
- requiresSelection: false,
32777
- selectedOption: null,
32778
- slidingScale: null,
32779
- selectedSlidingAmount: null,
32780
- selectedPriceAmount: amount,
32781
- selectedRequiresPayment: amount > 0,
32782
- hasPaidSelection: amount > 0,
32783
- hasFreeSelection: amount <= 0
32784
- };
32785
- }
32786
- case "tiered": {
32787
- const selectableOptions = getSelectableCoursePricingOptionsForNow(course, resolvePlanningDateInput(effectiveNowInput));
32788
- const selectedOption = (selectedPricingOptionId ? selectableOptions.find((option) => option.id === selectedPricingOptionId) : null) ?? (selectableOptions.length === 1 ? selectableOptions[0] ?? null : null);
32789
- const lowestAmount = selectableOptions.reduce((lowest, option) => {
32790
- if (lowest === null || option.priceAmount < lowest) return option.priceAmount;
32791
- return lowest;
32792
- }, null);
32793
- return {
32794
- currency,
32795
- display: lowestAmount === null ? {
32796
- kind: "unavailable",
32797
- currency
32798
- } : selectableOptions.length > 1 && lowestAmount > 0 ? {
32799
- kind: "from",
32800
- amount: lowestAmount,
32801
- currency
32802
- } : toExactOrFreeDisplay(lowestAmount, currency),
32803
- selectableOptions,
32804
- requiresSelection: selectableOptions.length > 1,
32805
- selectedOption,
32806
- slidingScale: null,
32807
- selectedSlidingAmount: null,
32808
- selectedPriceAmount: selectedOption?.priceAmount ?? null,
32809
- selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
32810
- hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
32811
- hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
32812
- };
32813
- }
32814
- case "sliding_scale": {
32815
- const minAmount = course.pricing.slidingMinAmount ?? null;
32816
- const maxAmount = course.pricing.slidingMaxAmount ?? null;
32817
- if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) return {
32818
- currency,
32819
- display: {
32820
- kind: "unavailable",
32821
- currency
32822
- },
32823
- selectableOptions: [],
32824
- requiresSelection: true,
32825
- selectedOption: null,
32826
- slidingScale: null,
32827
- selectedSlidingAmount: null,
32828
- selectedPriceAmount: null,
32829
- selectedRequiresPayment: false,
32830
- hasPaidSelection: false,
32831
- hasFreeSelection: false
32832
- };
32833
- const normalizedSelectedAmount = typeof selectedSlidingAmount === "number" && Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
32834
- return {
32835
- currency,
32836
- display: {
32837
- kind: "range",
32838
- minAmount,
32839
- maxAmount,
32840
- currency
32841
- },
32842
- selectableOptions: [],
32843
- requiresSelection: normalizedSelectedAmount === null,
32844
- selectedOption: null,
32845
- slidingScale: {
32846
- minAmount,
32847
- maxAmount,
32848
- suggestedAmount: course.pricing.slidingSuggestedAmount ?? null
32849
- },
32850
- selectedSlidingAmount: normalizedSelectedAmount,
32851
- selectedPriceAmount: normalizedSelectedAmount,
32852
- selectedRequiresPayment: (normalizedSelectedAmount ?? 0) > 0,
32853
- hasPaidSelection: maxAmount > 0,
32854
- hasFreeSelection: minAmount === 0
32855
- };
32856
- }
32857
- }
32858
- }
32859
- function formatCoursePriceDisplay(display, locale) {
32860
- return formatBookingPriceDisplay(display, {
32861
- decimals: "exact",
32862
- locale
32863
- });
32864
- }
32865
- function formatCoursePriceAmount(amount, currency, locale) {
32866
- return formatCoursePriceDisplay(amount > 0 ? {
32867
- kind: "exact",
32868
- amount,
32869
- currency
32870
- } : {
32871
- kind: "free",
32872
- currency
32873
- }, locale);
32874
- }
32875
- //#endregion
32876
32997
  //#region ../blocks/src/system/runtime/nodes/course-registration.interactive.ts
32877
32998
  const courseRegistrationSourceSchema = z$1.object({
32878
32999
  siteId: z$1.string().optional(),
@@ -33307,15 +33428,6 @@ const eventDetailsManifest = createBlockManifest({
33307
33428
  })], { gap: "lg" })
33308
33429
  })]
33309
33430
  });
33310
- const occurrenceContextSchema = z$1.object({
33311
- id: z$1.string(),
33312
- seriesId: z$1.string(),
33313
- startsAt: z$1.string(),
33314
- endsAt: z$1.string(),
33315
- timeZone: z$1.string(),
33316
- capacityOverride: z$1.number().nullable().optional(),
33317
- overrides: z$1.record(z$1.string(), z$1.unknown()).nullable().optional()
33318
- }).nullable();
33319
33431
  const eventAutoApplyDiscountPreviewBaseSchema = z$1.object({
33320
33432
  id: z$1.string(),
33321
33433
  publicLabel: z$1.string(),
@@ -33350,8 +33462,9 @@ const eventDetailsBlockDefinition = {
33350
33462
  from: "$root.previewStage",
33351
33463
  fallback: "published"
33352
33464
  } },
33353
- limit: "25",
33354
- seriesId: { $bind: { from: "$root.occurrenceContext.seriesId" } },
33465
+ limit: "100",
33466
+ readProfile: "details",
33467
+ seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
33355
33468
  includeOccurrenceId: { $bind: { from: "$root.occurrenceContext.id" } }
33356
33469
  },
33357
33470
  mode: "server"
@@ -41918,9 +42031,6 @@ function parseSignedNewsletterDestinationRef(value) {
41918
42031
  const trimmed = parseTrimmedString$1(value);
41919
42032
  return trimmed && SIGNED_DESTINATION_REF_PATTERN.test(trimmed) ? trimmed : null;
41920
42033
  }
41921
- function parseNewsletterSignupDestinationProvider(value) {
41922
- return value === "riverbank" || value === "mailchimp" ? value : null;
41923
- }
41924
42034
  function buildNewsletterSignupBlockRef(blockId) {
41925
42035
  const parsed = parseNewsletterSignupBlockId(blockId);
41926
42036
  return parsed ? {
@@ -42067,19 +42177,9 @@ const newsletterFieldSchema = z$1.object({
42067
42177
  });
42068
42178
  const newsletterSignupBlockIdSchema = z$1.string().trim().min(1).transform(parseRequiredNewsletterSignupBlockId);
42069
42179
  const signedNewsletterDestinationRefSchema = z$1.string().trim().min(1).transform(parseRequiredSignedNewsletterDestinationRef);
42070
- const newsletterPublicDestinationRefSchema = z$1.discriminatedUnion("tag", [z$1.object({
42071
- tag: z$1.literal("block_ref"),
42072
- blockId: newsletterSignupBlockIdSchema
42073
- }), z$1.object({
42074
- tag: z$1.literal("signed_destination_ref"),
42075
- token: signedNewsletterDestinationRefSchema
42076
- })]);
42077
- const newsletterSourceSchema = z$1.object({
42078
- blockId: z$1.string().nullable().optional(),
42180
+ const newsletterSourceCommonSchema = z$1.object({
42079
42181
  siteId: z$1.string().optional(),
42080
42182
  apiBaseUrl: z$1.string().optional(),
42081
- listId: z$1.string().nullable().optional(),
42082
- destinationProvider: newsletterDestinationProviderSchema.nullable().optional(),
42083
42183
  preset: newsletterPresetSchema.optional(),
42084
42184
  includePhone: z$1.boolean().optional(),
42085
42185
  buttonLabel: z$1.string().nullable().optional(),
@@ -42090,6 +42190,25 @@ const newsletterSourceSchema = z$1.object({
42090
42190
  spamProtectionEnabled: z$1.boolean().optional(),
42091
42191
  className: z$1.string().nullable().optional()
42092
42192
  });
42193
+ const newsletterSourceSchema = z$1.discriminatedUnion("source", [
42194
+ newsletterSourceCommonSchema.extend({
42195
+ source: z$1.literal("block"),
42196
+ blockId: z$1.string().nullable().optional(),
42197
+ listId: z$1.string().nullable().optional(),
42198
+ destinationProvider: newsletterDestinationProviderSchema.nullable().optional()
42199
+ }),
42200
+ newsletterSourceCommonSchema.extend({
42201
+ source: z$1.literal("signed-footer"),
42202
+ destinationRef: z$1.object({
42203
+ tag: z$1.literal("signed_destination_ref"),
42204
+ token: signedNewsletterDestinationRefSchema
42205
+ })
42206
+ }),
42207
+ newsletterSourceCommonSchema.extend({
42208
+ source: z$1.literal("legacy-direct-list"),
42209
+ listId: z$1.string().nullable()
42210
+ })
42211
+ ]);
42093
42212
  const newsletterDisplaySchema = z$1.object({
42094
42213
  kind: z$1.literal("newsletter-form"),
42095
42214
  className: z$1.string().nullable(),
@@ -42100,8 +42219,26 @@ const newsletterDisplaySchema = z$1.object({
42100
42219
  fields: z$1.array(newsletterFieldSchema)
42101
42220
  });
42102
42221
  const newsletterHydrationSchema = z$1.object({
42103
- destinationRef: newsletterPublicDestinationRefSchema.nullable().optional(),
42104
- listId: z$1.string().nullable().optional(),
42222
+ target: z$1.discriminatedUnion("tag", [
42223
+ z$1.object({
42224
+ tag: z$1.literal("block-source"),
42225
+ destinationRef: z$1.object({
42226
+ tag: z$1.literal("block_ref"),
42227
+ blockId: newsletterSignupBlockIdSchema
42228
+ }).nullable()
42229
+ }),
42230
+ z$1.object({
42231
+ tag: z$1.literal("signed-footer-source"),
42232
+ destinationRef: z$1.object({
42233
+ tag: z$1.literal("signed_destination_ref"),
42234
+ token: signedNewsletterDestinationRefSchema
42235
+ })
42236
+ }),
42237
+ z$1.object({
42238
+ tag: z$1.literal("legacy-direct-list"),
42239
+ listId: z$1.string().nullable()
42240
+ })
42241
+ ]),
42105
42242
  preset: newsletterPresetSchema,
42106
42243
  includePhone: z$1.boolean(),
42107
42244
  tags: z$1.string().nullable().optional(),
@@ -42135,20 +42272,43 @@ const newsletterFormBlockRuntime = defineProgressiveBlockRuntime({
42135
42272
  render: createZodCodec(newsletterRenderSchema)
42136
42273
  },
42137
42274
  buildRender: (source) => {
42138
- const runtimeSource = deriveNewsletterSignupRuntimeSource(source);
42275
+ const runtimeSource = source.source === "block" ? deriveNewsletterSignupRuntimeSource(source) : null;
42139
42276
  return {
42140
42277
  display: buildNewsletterDisplay(source),
42141
42278
  hydration: {
42142
- destinationRef: buildNewsletterSignupBlockRef(source.blockId),
42143
- listId: runtimeSource.listId,
42279
+ target: projectNewsletterFormHydrationTarget(source),
42144
42280
  preset: source.preset ?? "emailOnly",
42145
42281
  includePhone: source.includePhone ?? false,
42146
- tags: runtimeSource.tags,
42282
+ tags: runtimeSource ? runtimeSource.tags : source.tags,
42147
42283
  spamProtectionEnabled: source.spamProtectionEnabled
42148
42284
  }
42149
42285
  };
42150
42286
  }
42151
42287
  });
42288
+ function projectNewsletterFormHydrationTarget(source) {
42289
+ switch (source.source) {
42290
+ case "block": {
42291
+ const destinationRef = buildNewsletterSignupBlockRef(source.blockId);
42292
+ if (destinationRef?.tag === "block_ref") return {
42293
+ tag: "block-source",
42294
+ destinationRef
42295
+ };
42296
+ return {
42297
+ tag: "legacy-direct-list",
42298
+ listId: source.listId ?? null
42299
+ };
42300
+ }
42301
+ case "signed-footer": return {
42302
+ tag: "signed-footer-source",
42303
+ destinationRef: source.destinationRef
42304
+ };
42305
+ case "legacy-direct-list": return {
42306
+ tag: "legacy-direct-list",
42307
+ listId: source.listId
42308
+ };
42309
+ default: return assertNever$24(source);
42310
+ }
42311
+ }
42152
42312
  function buildNewsletterFormInteractiveIslandProps(props) {
42153
42313
  return buildInteractiveIslandProps({
42154
42314
  runtime: newsletterFormBlockRuntime,
@@ -46410,6 +46570,33 @@ function uniqByOccurrenceId(events) {
46410
46570
  }
46411
46571
  return out;
46412
46572
  }
46573
+ function selectFromOccurrenceContext(events, occurrenceContext) {
46574
+ if (!occurrenceContext) return null;
46575
+ const byId = events.find((event) => event.occurrenceId === occurrenceContext.id || event.id === occurrenceContext.id);
46576
+ if (byId) return byId;
46577
+ const contextDate = getBookingLocalDateKey(toScheduledBookingDateTime({
46578
+ startsAt: occurrenceContext.startsAt,
46579
+ timeZone: occurrenceContext.timeZone
46580
+ }));
46581
+ return events.find((event) => getBookingLocalDateKey(toScheduledBookingDateTime({
46582
+ startsAt: event.startsAt,
46583
+ timeZone: event.timeZone
46584
+ })) === contextDate) ?? null;
46585
+ }
46586
+ function selectNextUpcoming(events, nowIso) {
46587
+ return [...events].filter((event) => isFutureOrNow(event.startsAt, nowIso)).sort((left, right) => Date.parse(left.startsAt) - Date.parse(right.startsAt))[0] ?? null;
46588
+ }
46589
+ function selectCompletedWholeSeries(events) {
46590
+ if (events.length === 0 || !events.every((event) => event.bookingScope === "whole_series")) return null;
46591
+ return [...events].sort((left, right) => Date.parse(right.startsAt) - Date.parse(left.startsAt))[0] ?? null;
46592
+ }
46593
+ function selectRelatedDates(input) {
46594
+ if (!input.seriesId) return [];
46595
+ const isWholeSeries = input.selected?.bookingScope === "whole_series";
46596
+ const selectedOccurrenceId = input.selected ? input.selected.occurrenceId || input.selected.id : null;
46597
+ 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));
46598
+ return isWholeSeries ? dates : dates.slice(0, input.limit);
46599
+ }
46413
46600
  function selectEventDetails(args) {
46414
46601
  const all = uniqByOccurrenceId(resolveEventRegistrationScopedEvents((args.events ?? []).filter(Boolean), {
46415
46602
  occurrenceContext: args.occurrenceContext,
@@ -46417,37 +46604,22 @@ function selectEventDetails(args) {
46417
46604
  }));
46418
46605
  const occurrenceContext = args.occurrenceContext ?? null;
46419
46606
  const otherLimit = parseLimit$1(args.otherDatesLimit, 5);
46420
- const selectedFromContext = (() => {
46421
- if (!occurrenceContext) return null;
46422
- const byId = all.find((e) => e.occurrenceId === occurrenceContext.id || e.id === occurrenceContext.id) ?? null;
46423
- if (byId) return byId;
46424
- const ctxDate = getBookingLocalDateKey(toScheduledBookingDateTime({
46425
- startsAt: occurrenceContext.startsAt,
46426
- timeZone: occurrenceContext.timeZone
46427
- }));
46428
- return all.find((e) => getBookingLocalDateKey(toScheduledBookingDateTime({
46429
- startsAt: e.startsAt,
46430
- timeZone: e.timeZone
46431
- })) === ctxDate) ?? null;
46432
- })();
46433
- const nextUpcoming = (() => {
46434
- const upcoming = all.filter((e) => isFutureOrNow(e.startsAt, args.nowIso));
46435
- upcoming.sort((a, b) => Date.parse(a.startsAt) - Date.parse(b.startsAt));
46436
- return upcoming[0] ?? null;
46437
- })();
46438
- const mode = selectedFromContext ? "selected" : "next";
46439
- const selected = selectedFromContext ?? nextUpcoming;
46607
+ const selectedFromContext = selectFromOccurrenceContext(all, occurrenceContext);
46608
+ const nextUpcoming = selectNextUpcoming(all, args.nowIso);
46609
+ const completedWholeSeries = selectCompletedWholeSeries(all);
46610
+ const selected = selectedFromContext ?? nextUpcoming ?? completedWholeSeries;
46611
+ const mode = selectedFromContext ? "selected" : nextUpcoming ? "next" : completedWholeSeries ? "completed" : "next";
46440
46612
  const timeZone = toBookingTimeZone(selected?.timeZone ?? all[0]?.timeZone ?? null);
46441
- const seriesId = occurrenceContext?.seriesId ?? selected?.seriesId ?? all[0]?.seriesId ?? null;
46442
- const selectedOccurrenceId = selected?.occurrenceId ?? null;
46443
46613
  return {
46444
46614
  mode,
46445
46615
  selected,
46446
- otherDates: seriesId ? all.filter((e) => e.seriesId === seriesId).filter((e) => isFutureOrNow(e.startsAt, args.nowIso)).filter((e) => {
46447
- const occId = e.occurrenceId || e.id;
46448
- if (selectedOccurrenceId && occId === selectedOccurrenceId) return false;
46449
- return true;
46450
- }).slice(0, otherLimit) : [],
46616
+ otherDates: selectRelatedDates({
46617
+ events: all,
46618
+ seriesId: occurrenceContext?.seriesId ?? selected?.seriesId ?? all[0]?.seriesId ?? null,
46619
+ selected,
46620
+ nowIso: args.nowIso,
46621
+ limit: otherLimit
46622
+ }),
46451
46623
  timeZone
46452
46624
  };
46453
46625
  }
@@ -46569,7 +46741,7 @@ function EventFacts({ selection, selected, venue, teamMembers, pricing }) {
46569
46741
  /* @__PURE__ */ jsxs("div", { children: [
46570
46742
  /* @__PURE__ */ jsx("div", {
46571
46743
  className: "rb-label rb-mb-2",
46572
- children: selection.mode === "next" ? "Next date" : "Date"
46744
+ children: selected.bookingScope === "whole_series" ? selection.mode === "next" ? "Next session" : "Selected session" : selection.mode === "next" ? "Next date" : "Date"
46573
46745
  }),
46574
46746
  /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: date }) }),
46575
46747
  /* @__PURE__ */ jsx("p", {
@@ -46607,18 +46779,27 @@ function EventFacts({ selection, selected, venue, teamMembers, pricing }) {
46607
46779
  }) : null] }, member.id))
46608
46780
  })]
46609
46781
  }) : null,
46610
- pricing
46782
+ pricing,
46783
+ selected.bookingScope === "whole_series" ? /* @__PURE__ */ jsxs("div", {
46784
+ className: "rb-mt-6",
46785
+ children: [/* @__PURE__ */ jsx("div", {
46786
+ className: "rb-label rb-mb-2",
46787
+ children: "Registration"
46788
+ }), /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: selected.wholeSeries?.enrollmentOpen ? "Open" : "Closed" }) })]
46789
+ }) : null
46611
46790
  ]
46612
46791
  });
46613
46792
  }
46614
46793
  function OtherEventDates({ selection }) {
46615
- if (selection.otherDates.length === 0) return null;
46794
+ const isWholeSeries = selection.selected?.bookingScope === "whole_series";
46795
+ const dates = isWholeSeries && selection.selected ? [selection.selected, ...selection.otherDates].sort((left, right) => Date.parse(left.startsAt) - Date.parse(right.startsAt)) : selection.otherDates;
46796
+ if (dates.length === 0) return null;
46616
46797
  return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
46617
46798
  className: "rb-label",
46618
- children: "Other dates"
46799
+ children: isWholeSeries ? "Session schedule" : "Other dates"
46619
46800
  }), /* @__PURE__ */ jsx("div", {
46620
46801
  className: "rb-mt-2 rb-tiles-grid",
46621
- children: selection.otherDates.map((event) => /* @__PURE__ */ jsx("a", {
46802
+ children: dates.map((event) => /* @__PURE__ */ jsx("a", {
46622
46803
  className: "rb-tile rb-tile--interactive",
46623
46804
  ...resolveEventLinkProps(event),
46624
46805
  children: /* @__PURE__ */ jsx(DateTimeTile, {
@@ -49817,13 +49998,13 @@ const FormNodeSSR = ({ blockId, value, submitLabel, successMessage, className, o
49817
49998
  * Renders the newsletter signup form for SSR with hydration support.
49818
49999
  * Uses the islands architecture pattern to hydrate on the client.
49819
50000
  */
49820
- function NewsletterFormSSR({ blockId, siteId, apiBaseUrl, listId, destinationProvider, preset = "emailOnly", includePhone, buttonLabel = "Subscribe", buttonVariant = "primary", successMessage, privacyNote, tags, spamProtectionEnabled, className }) {
50001
+ function NewsletterFormSSR(props) {
50002
+ const { siteId, apiBaseUrl, preset = "emailOnly", includePhone, buttonLabel = "Subscribe", buttonVariant = "primary", successMessage, privacyNote, tags, spamProtectionEnabled, className } = props;
50003
+ const blockId = props.source === "block" ? props.blockId : null;
49821
50004
  const islandProps = buildNewsletterFormInteractiveIslandProps({
49822
- blockId,
50005
+ ...props,
49823
50006
  siteId,
49824
50007
  apiBaseUrl,
49825
- listId,
49826
- destinationProvider,
49827
50008
  preset,
49828
50009
  includePhone,
49829
50010
  buttonLabel,
@@ -51490,6 +51671,213 @@ function collectConstrainedVideoMediaValues(options) {
51490
51671
  return values;
51491
51672
  }
51492
51673
  //#endregion
51674
+ //#region ../blocks/src/system/manifest/hydrateLinks.ts
51675
+ /**
51676
+ * Hydrates link objects within block content using the provided route map. Returns
51677
+ * the original content reference when no mutations are required to avoid unnecessary renders.
51678
+ */
51679
+ function hydrateManifestLinks(manifest, content, routes, pagesByIdentifier, entriesByIdentifier) {
51680
+ if (!routes || !manifest?.fields?.length) return content;
51681
+ return hydrateValue(content, {
51682
+ routes,
51683
+ pagesByIdentifier,
51684
+ entriesByIdentifier
51685
+ });
51686
+ }
51687
+ function hydrateValue(value, context) {
51688
+ try {
51689
+ if (Array.isArray(value)) {
51690
+ const resolvedItems = value.map((item) => hydrateValue(item, context));
51691
+ return resolvedItems.every((item, index) => item === value[index]) ? value : resolvedItems;
51692
+ }
51693
+ if (isRecord$27(value)) {
51694
+ if (isInternalLink$1(value)) return hydrateInternalLink(value, context.routes);
51695
+ if (isPageLink$1(value)) return hydratePageLink(value, context);
51696
+ if (isEntryLink$1(value)) return hydrateEntryLink(value, context);
51697
+ const resolvedEntries = Object.entries(value).map(([key, entry]) => [key, hydrateValue(entry, context)]);
51698
+ return resolvedEntries.every(([key, entry]) => entry === value[key]) ? value : Object.fromEntries(resolvedEntries);
51699
+ }
51700
+ return value;
51701
+ } catch (err) {
51702
+ console.error("[hydrateLinks] Error hydrating value:", err, value);
51703
+ return value;
51704
+ }
51705
+ }
51706
+ function hydrateInternalLink(link, routes) {
51707
+ const resolved = resolveRouteTarget(link.routeId, routes);
51708
+ if (!resolved) return link;
51709
+ const nextHref = resolved.href;
51710
+ const currentHref = typeof link.href === "string" && link.href.length > 0 ? link.href : null;
51711
+ const nextUpdatedAt = resolved.updatedAt;
51712
+ const updates = {};
51713
+ if (nextHref && nextHref !== currentHref) updates.href = nextHref;
51714
+ if (nextUpdatedAt && link.updatedAt !== nextUpdatedAt) updates.updatedAt = nextUpdatedAt;
51715
+ return Object.keys(updates).length > 0 ? {
51716
+ ...link,
51717
+ ...updates
51718
+ } : link;
51719
+ }
51720
+ function isInternalLink$1(value) {
51721
+ if (value.kind !== "internal") return false;
51722
+ if (typeof value.routeId !== "string" || value.routeId.length === 0) return false;
51723
+ return true;
51724
+ }
51725
+ function isPageLink$1(value) {
51726
+ if (value.kind !== "page") return false;
51727
+ if (typeof value.identifier !== "string" || value.identifier.length === 0) return false;
51728
+ return true;
51729
+ }
51730
+ function hydratePageLink(link, context) {
51731
+ const resolved = resolvePageRouteTarget(link, context);
51732
+ if (!resolved) return link;
51733
+ return {
51734
+ ...link,
51735
+ href: resolved.href,
51736
+ routeId: resolved.routeId
51737
+ };
51738
+ }
51739
+ function isEntryLink$1(value) {
51740
+ if (value.kind !== "entry") return false;
51741
+ if (typeof value.contentType !== "string" || value.contentType.length === 0) return false;
51742
+ if (typeof value.identifier !== "string" || value.identifier.length === 0) return false;
51743
+ return true;
51744
+ }
51745
+ function hydrateEntryLink(link, context) {
51746
+ const resolved = resolveEntryRouteTarget(link, context);
51747
+ if (!resolved) return link;
51748
+ return {
51749
+ ...link,
51750
+ href: resolved.href,
51751
+ routeId: resolved.routeId
51752
+ };
51753
+ }
51754
+ //#endregion
51755
+ //#region ../blocks/src/sdkBlockTransform.ts
51756
+ /**
51757
+ * Transforms an SDK custom block into a BlockManifest.
51758
+ *
51759
+ * If the block has a `layout`, it can be rendered declaratively without React code.
51760
+ * If no layout, the block MUST use blockOverrides for rendering.
51761
+ */
51762
+ function transformSdkBlockToManifest(sdkBlock) {
51763
+ const hasLayout = Boolean(sdkBlock.layout) || Boolean(sdkBlock.variants && Object.keys(sdkBlock.variants).length > 0);
51764
+ return augmentManifest({
51765
+ name: sdkBlock.id,
51766
+ version: "1.0.0",
51767
+ title: sdkBlock.title,
51768
+ titleSource: sdkBlock.titleSource,
51769
+ description: sdkBlock.description,
51770
+ component: sdkBlock.id,
51771
+ fields: sdkBlock.fields,
51772
+ slots: [],
51773
+ category: sdkBlock.category,
51774
+ tags: sdkBlock.tags,
51775
+ icon: sdkBlock.icon,
51776
+ layout: sdkBlock.layout,
51777
+ variants: sdkBlock.variants,
51778
+ defaultVariant: sdkBlock.defaultVariant,
51779
+ variantOptions: sdkBlock.variantOptions,
51780
+ previewCustomize: sdkBlock.previewCustomize,
51781
+ behaviours: {
51782
+ supportsThemeSwitching: true,
51783
+ inlineEditing: hasLayout,
51784
+ animation: hasLayout,
51785
+ paletteHidden: false
51786
+ }
51787
+ });
51788
+ }
51789
+ /**
51790
+ * Transforms an SDK custom block into a SystemBlockDefinition.
51791
+ *
51792
+ * This creates a minimal definition with just the manifest - no data loaders
51793
+ * or content normalizers since SDK blocks handle their own rendering.
51794
+ */
51795
+ function transformSdkBlockToDefinition(sdkBlock) {
51796
+ return {
51797
+ manifest: transformSdkBlockToManifest(sdkBlock),
51798
+ dataLoaders: sdkBlock.dataLoaders
51799
+ };
51800
+ }
51801
+ //#endregion
51802
+ //#region ../blocks/src/customBlockRegistry.ts
51803
+ const defaultCustomBlockSourcePolicy = { kind: "canonical-db-fallback-sdk" };
51804
+ function isCustomBlockKind(blockKind) {
51805
+ return blockKind.startsWith("custom.");
51806
+ }
51807
+ function transformToBlockDescriptor(sdkBlock, source = "sdk") {
51808
+ return {
51809
+ name: sdkBlock.id,
51810
+ title: sdkBlock.title,
51811
+ description: sdkBlock.description,
51812
+ category: sdkBlock.category,
51813
+ tags: sdkBlock.tags,
51814
+ icon: sdkBlock.icon,
51815
+ definition: transformSdkBlockToDefinition(sdkBlock),
51816
+ source
51817
+ };
51818
+ }
51819
+ function toResolvedCustomBlock(manifest, source) {
51820
+ return {
51821
+ blockKind: manifest.id,
51822
+ manifest: transformSdkBlockToManifest(manifest),
51823
+ source,
51824
+ descriptor: transformToBlockDescriptor(manifest, source.kind === "managed-database" ? "database" : "sdk")
51825
+ };
51826
+ }
51827
+ function planCustomBlockRegistryResolution({ sdkConfig, customBlocks = [], policy = defaultCustomBlockSourcePolicy }) {
51828
+ switch (policy.kind) {
51829
+ case "canonical-db-fallback-sdk": {
51830
+ const entriesByKind = /* @__PURE__ */ new Map();
51831
+ const conflicts = [];
51832
+ for (const customBlock of customBlocks) entriesByKind.set(customBlock.manifest.id, toResolvedCustomBlock(customBlock.manifest, customBlock.source));
51833
+ for (const sdkBlock of sdkConfig?.customBlocks ?? []) {
51834
+ const existing = entriesByKind.get(sdkBlock.id);
51835
+ if (existing) {
51836
+ conflicts.push({
51837
+ kind: "conflict",
51838
+ blockKind: existing.blockKind,
51839
+ winner: existing.source,
51840
+ loser: { kind: "sdk-config" },
51841
+ reason: "db-canonical-sdk-fallback"
51842
+ });
51843
+ continue;
51844
+ }
51845
+ entriesByKind.set(sdkBlock.id, toResolvedCustomBlock(sdkBlock, { kind: "sdk-config" }));
51846
+ }
51847
+ return {
51848
+ policy,
51849
+ entries: Array.from(entriesByKind.values()),
51850
+ conflicts
51851
+ };
51852
+ }
51853
+ }
51854
+ }
51855
+ function createCustomBlockRegistry({ sdkConfig, customBlocks = [], policy = defaultCustomBlockSourcePolicy, onConflict }) {
51856
+ const plan = planCustomBlockRegistryResolution({
51857
+ sdkConfig,
51858
+ customBlocks,
51859
+ policy
51860
+ });
51861
+ const entriesByKind = new Map(plan.entries.map((entry) => [entry.blockKind, entry]));
51862
+ for (const conflict of plan.conflicts) onConflict?.(`Using ${sourceLabel(conflict.winner)} custom block "${conflict.blockKind}" - ${sourceLabel(conflict.loser)} block is fallback only`);
51863
+ return {
51864
+ entries: plan.entries,
51865
+ conflicts: plan.conflicts,
51866
+ findManifest: (blockKind) => {
51867
+ if (!isCustomBlockKind(blockKind)) return void 0;
51868
+ return entriesByKind.get(blockKind);
51869
+ }
51870
+ };
51871
+ }
51872
+ function sourceLabel(source) {
51873
+ switch (source.kind) {
51874
+ case "managed-database": return "DB";
51875
+ case "sdk-synced": return "SDK-synced DB";
51876
+ case "sdk-config": return "SDK config";
51877
+ default: return assertNever$24(source);
51878
+ }
51879
+ }
51880
+ //#endregion
51493
51881
  //#region ../theme-core/src/runtime/fontFamily.ts
51494
51882
  /**
51495
51883
  * Font Family Formatting Utilities
@@ -52164,30 +52552,24 @@ const NAV_DROPDOWN_CONTAINER_RAIL_CSS_RULES = [
52164
52552
  ];
52165
52553
  //#endregion
52166
52554
  //#region ../theme-core/src/header/surfaceRules.ts
52167
- /** Compile the visual surface declarations independently of paint geometry. */
52168
- function buildHeaderSurfaceRules(header, tokens, blur) {
52555
+ /** Compile the at-rest surface independently of scroll treatment and paint geometry. */
52556
+ function buildHeaderSurfaceRules(header, tokens) {
52169
52557
  const base = [];
52170
- const scrolled = [];
52171
52558
  const background = header.background;
52172
52559
  if (background.type === "color") base.push(`background-color: ${tokens.getColor(background.color || "surface")};`);
52173
52560
  else if (background.type === "gradient" && background.gradient) {
52174
52561
  const stops = background.gradient.stops.map((stop) => tokens.getColor(stop.color)).join(", ");
52175
52562
  base.push(`background-image: linear-gradient(${background.gradient.angle ?? 180}deg, ${stops});`);
52176
52563
  }
52177
- const blurRules = [`backdrop-filter: ${blur};`, `-webkit-backdrop-filter: ${blur};`];
52178
- base.push(...blurRules);
52179
- scrolled.push(...blurRules);
52180
52564
  const borderWidth = getComponentBorderWidthPx(header.border?.width ?? "none");
52181
52565
  if (!header.border || borderWidth === "0") return {
52182
52566
  base,
52183
- scrolled,
52184
52567
  border: []
52185
52568
  };
52186
52569
  const color = rgbColorValue(header.border.colorToken?.trim() || "border");
52187
52570
  const style = header.border.style === "dashed" ? "dashed" : "solid";
52188
52571
  return {
52189
52572
  base,
52190
- scrolled,
52191
52573
  border: header.border.position === "both" ? [`border-top: ${borderWidth} ${style} ${color};`, `border-bottom: ${borderWidth} ${style} ${color};`] : [`border-${header.border.position}: ${borderWidth} ${style} ${color};`]
52192
52574
  };
52193
52575
  }
@@ -52497,13 +52879,12 @@ function generateHeaderRootStyles(header, themeId, tokens) {
52497
52879
  rules.push("isolation: isolate;");
52498
52880
  const surfaceRules = isContainedNav ? {
52499
52881
  base: [],
52500
- scrolled: [],
52501
52882
  border: []
52502
- } : buildHeaderSurfaceRules(header, tokens, HEADER_BLUR);
52883
+ } : buildHeaderSurfaceRules(header, tokens);
52503
52884
  const floatingSurfaceBorder = header.variant === "floating";
52504
52885
  if (!floatingSurfaceBorder) rules.push(...surfaceRules.border);
52505
52886
  const basePaintRules = floatingSurfaceBorder ? [...surfaceRules.base, ...surfaceRules.border] : surfaceRules.base;
52506
- const scrolledPaintRules = floatingSurfaceBorder ? [...surfaceRules.scrolled, ...surfaceRules.border] : surfaceRules.scrolled;
52887
+ const scrolledPaintRules = floatingSurfaceBorder ? surfaceRules.border : [];
52507
52888
  if (header.positioning === "sticky" || header.positioning === "fixed") {
52508
52889
  const shadowVar = getComponentShadowVar(header.shadow?.elevation ?? "none");
52509
52890
  if (shadowVar) rules.push(`box-shadow: ${shadowVar};`);
@@ -55234,215 +55615,115 @@ function mapFontStyle(italic) {
55234
55615
  return italic ? "italic" : "normal";
55235
55616
  }
55236
55617
  //#endregion
55237
- //#region ../blocks/src/system/manifest/hydrateLinks.ts
55238
- /**
55239
- * Hydrates link objects within block content using the provided route map. Returns
55240
- * the original content reference when no mutations are required to avoid unnecessary renders.
55241
- */
55242
- function hydrateManifestLinks(manifest, content, routes, pagesByIdentifier, entriesByIdentifier) {
55243
- if (!routes || !manifest?.fields?.length) return content;
55244
- return hydrateValue(content, {
55245
- routes,
55246
- pagesByIdentifier,
55247
- entriesByIdentifier
55248
- });
55249
- }
55250
- function hydrateValue(value, context) {
55251
- try {
55252
- if (Array.isArray(value)) {
55253
- const resolvedItems = value.map((item) => hydrateValue(item, context));
55254
- return resolvedItems.every((item, index) => item === value[index]) ? value : resolvedItems;
55255
- }
55256
- if (isRecord$27(value)) {
55257
- if (isInternalLink$1(value)) return hydrateInternalLink(value, context.routes);
55258
- if (isPageLink$1(value)) return hydratePageLink(value, context);
55259
- if (isEntryLink$1(value)) return hydrateEntryLink(value, context);
55260
- const resolvedEntries = Object.entries(value).map(([key, entry]) => [key, hydrateValue(entry, context)]);
55261
- return resolvedEntries.every(([key, entry]) => entry === value[key]) ? value : Object.fromEntries(resolvedEntries);
55262
- }
55263
- return value;
55264
- } catch (err) {
55265
- console.error("[hydrateLinks] Error hydrating value:", err, value);
55266
- return value;
55618
+ //#region ../blocks/src/pageRenderingMode.ts
55619
+ var MissingBlockOverrideError$1 = class extends Error {
55620
+ constructor(blockKind) {
55621
+ super(`Override-only rendering requires an override for block kind "${blockKind}".`);
55622
+ this.blockKind = blockKind;
55623
+ this.code = "missing_block_override";
55624
+ this.name = "MissingBlockOverrideError";
55267
55625
  }
55626
+ };
55627
+ function isOverrideOnlyResourceInput(props) {
55628
+ return props.rendering?.kind === "overrides-only";
55268
55629
  }
55269
- function hydrateInternalLink(link, routes) {
55270
- const resolved = resolveRouteTarget(link.routeId, routes);
55271
- if (!resolved) return link;
55272
- const nextHref = resolved.href;
55273
- const currentHref = typeof link.href === "string" && link.href.length > 0 ? link.href : null;
55274
- const nextUpdatedAt = resolved.updatedAt;
55275
- const updates = {};
55276
- if (nextHref && nextHref !== currentHref) updates.href = nextHref;
55277
- if (nextUpdatedAt && link.updatedAt !== nextUpdatedAt) updates.updatedAt = nextUpdatedAt;
55278
- return Object.keys(updates).length > 0 ? {
55279
- ...link,
55280
- ...updates
55281
- } : link;
55282
- }
55283
- function isInternalLink$1(value) {
55284
- if (value.kind !== "internal") return false;
55285
- if (typeof value.routeId !== "string" || value.routeId.length === 0) return false;
55286
- return true;
55287
- }
55288
- function isPageLink$1(value) {
55289
- if (value.kind !== "page") return false;
55290
- if (typeof value.identifier !== "string" || value.identifier.length === 0) return false;
55291
- return true;
55292
- }
55293
- function hydratePageLink(link, context) {
55294
- const resolved = resolvePageRouteTarget(link, context);
55295
- if (!resolved) return link;
55630
+ function resolvePageThemeResources(props) {
55631
+ if (isOverrideOnlyResourceInput(props)) return { kind: "unavailable" };
55296
55632
  return {
55297
- ...link,
55298
- href: resolved.href,
55299
- routeId: resolved.routeId
55633
+ kind: "available",
55634
+ tokens: props.themeTokens ?? buildThemeRuntime$1(props.theme).tokens,
55635
+ config: props.theme
55300
55636
  };
55301
55637
  }
55302
- function isEntryLink$1(value) {
55303
- if (value.kind !== "entry") return false;
55304
- if (typeof value.contentType !== "string" || value.contentType.length === 0) return false;
55305
- if (typeof value.identifier !== "string" || value.identifier.length === 0) return false;
55306
- return true;
55638
+ function requireBlockOverride(resources, override, blockKind) {
55639
+ if (resources.kind === "unavailable" && !override) throw new MissingBlockOverrideError$1(blockKind);
55307
55640
  }
55308
- function hydrateEntryLink(link, context) {
55309
- const resolved = resolveEntryRouteTarget(link, context);
55310
- if (!resolved) return link;
55311
- return {
55312
- ...link,
55313
- href: resolved.href,
55314
- routeId: resolved.routeId
55315
- };
55641
+ function overrideThemeProps(resources) {
55642
+ return resources.kind === "available" ? {
55643
+ theme: resources.tokens,
55644
+ themeConfig: resources.config
55645
+ } : {};
55646
+ }
55647
+ function requireThemeResources(resources, blockKind) {
55648
+ if (resources.kind === "unavailable") throw new MissingBlockOverrideError$1(blockKind);
55649
+ return resources;
55316
55650
  }
55317
55651
  //#endregion
55318
- //#region ../blocks/src/sdkBlockTransform.ts
55319
- /**
55320
- * Transforms an SDK custom block into a BlockManifest.
55321
- *
55322
- * If the block has a `layout`, it can be rendered declaratively without React code.
55323
- * If no layout, the block MUST use blockOverrides for rendering.
55324
- */
55325
- function transformSdkBlockToManifest(sdkBlock) {
55326
- const hasLayout = Boolean(sdkBlock.layout) || Boolean(sdkBlock.variants && Object.keys(sdkBlock.variants).length > 0);
55327
- return augmentManifest({
55328
- name: sdkBlock.id,
55329
- version: "1.0.0",
55330
- title: sdkBlock.title,
55331
- titleSource: sdkBlock.titleSource,
55332
- description: sdkBlock.description,
55333
- component: sdkBlock.id,
55334
- fields: sdkBlock.fields,
55335
- slots: [],
55336
- category: sdkBlock.category,
55337
- tags: sdkBlock.tags,
55338
- icon: sdkBlock.icon,
55339
- layout: sdkBlock.layout,
55340
- variants: sdkBlock.variants,
55341
- defaultVariant: sdkBlock.defaultVariant,
55342
- variantOptions: sdkBlock.variantOptions,
55343
- previewCustomize: sdkBlock.previewCustomize,
55344
- behaviours: {
55345
- supportsThemeSwitching: true,
55346
- inlineEditing: hasLayout,
55347
- animation: hasLayout,
55348
- paletteHidden: false
55349
- }
55350
- });
55652
+ //#region ../blocks/src/pageRendererBoundaries.tsx
55653
+ const boundaryKey = (previousBlockId, nextBlockId) => `${previousBlockId}\u0000${nextBlockId}`;
55654
+ function isSiteStyleTransitionStyleGroup(value) {
55655
+ return value?.startsWith("site-style-transition-") === true;
55351
55656
  }
55352
- /**
55353
- * Transforms an SDK custom block into a SystemBlockDefinition.
55354
- *
55355
- * This creates a minimal definition with just the manifest - no data loaders
55356
- * or content normalizers since SDK blocks handle their own rendering.
55357
- */
55358
- function transformSdkBlockToDefinition(sdkBlock) {
55359
- return {
55360
- manifest: transformSdkBlockToManifest(sdkBlock),
55361
- dataLoaders: sdkBlock.dataLoaders
55362
- };
55657
+ function boundaryMapForAdjacentBlockIds(boundaries) {
55658
+ return new Map(boundaries.map((boundary) => [boundaryKey(boundary.previousBlockId, boundary.nextBlockId), boundary]));
55363
55659
  }
55364
- //#endregion
55365
- //#region ../blocks/src/customBlockRegistry.ts
55366
- const defaultCustomBlockSourcePolicy = { kind: "canonical-db-fallback-sdk" };
55367
- function isCustomBlockKind(blockKind) {
55368
- return blockKind.startsWith("custom.");
55660
+ function boundaryBetweenBlocks(previousBlock, nextBlock, boundaries) {
55661
+ const previousBlockId = previousBlock?.id ?? null;
55662
+ const nextBlockId = nextBlock?.id ?? null;
55663
+ if (!previousBlockId || !nextBlockId) return null;
55664
+ return boundaries.get(boundaryKey(previousBlockId, nextBlockId)) ?? null;
55369
55665
  }
55370
- function transformToBlockDescriptor(sdkBlock, source = "sdk") {
55666
+ function renderBoundaryAfterBlock(input) {
55667
+ const previousBlockId = input.block.id;
55668
+ const nextBlockId = input.nextBlock?.id ?? null;
55669
+ if (!previousBlockId || !nextBlockId) return null;
55670
+ const boundary = input.boundaryByAdjacentBlockIds.get(boundaryKey(previousBlockId, nextBlockId));
55671
+ if (!boundary) return null;
55672
+ const rendered = /* @__PURE__ */ jsx("div", {
55673
+ "aria-hidden": "true",
55674
+ "data-block-boundary": "",
55675
+ "data-boundary-id": boundary.boundaryId,
55676
+ "data-boundary-previous-block-id": boundary.previousBlockId,
55677
+ "data-boundary-next-block-id": boundary.nextBlockId,
55678
+ "data-style-group": boundary.styleGroup,
55679
+ style: boundaryCssVarsStyle(boundary)
55680
+ }, `${input.blockKey}:boundary`);
55681
+ return input.wrapBoundary ? input.wrapBoundary(boundary, rendered) : rendered;
55682
+ }
55683
+ function boundaryCssVarsStyle(boundary) {
55371
55684
  return {
55372
- name: sdkBlock.id,
55373
- title: sdkBlock.title,
55374
- description: sdkBlock.description,
55375
- category: sdkBlock.category,
55376
- tags: sdkBlock.tags,
55377
- icon: sdkBlock.icon,
55378
- definition: transformSdkBlockToDefinition(sdkBlock),
55379
- source
55685
+ "--site-style-transition-from": boundary.cssVars.from,
55686
+ "--site-style-transition-to": boundary.cssVars.to
55380
55687
  };
55381
55688
  }
55382
- function toResolvedCustomBlock(manifest, source) {
55689
+ function boundaryReserveCssVarsStyle(input) {
55690
+ const before = input.before?.metrics.reserveCss ?? null;
55691
+ const after = input.after?.metrics.reserveCss ?? null;
55692
+ if (!before && !after) return void 0;
55383
55693
  return {
55384
- blockKind: manifest.id,
55385
- manifest: transformSdkBlockToManifest(manifest),
55386
- source,
55387
- descriptor: transformToBlockDescriptor(manifest, source.kind === "managed-database" ? "database" : "sdk")
55694
+ ...before ? { "--site-style-boundary-before-reserve": before } : {},
55695
+ ...after ? { "--site-style-boundary-after-reserve": after } : {}
55388
55696
  };
55389
55697
  }
55390
- function planCustomBlockRegistryResolution({ sdkConfig, customBlocks = [], policy = defaultCustomBlockSourcePolicy }) {
55391
- switch (policy.kind) {
55392
- case "canonical-db-fallback-sdk": {
55393
- const entriesByKind = /* @__PURE__ */ new Map();
55394
- const conflicts = [];
55395
- for (const customBlock of customBlocks) entriesByKind.set(customBlock.manifest.id, toResolvedCustomBlock(customBlock.manifest, customBlock.source));
55396
- for (const sdkBlock of sdkConfig?.customBlocks ?? []) {
55397
- const existing = entriesByKind.get(sdkBlock.id);
55398
- if (existing) {
55399
- conflicts.push({
55400
- kind: "conflict",
55401
- blockKind: existing.blockKind,
55402
- winner: existing.source,
55403
- loser: { kind: "sdk-config" },
55404
- reason: "db-canonical-sdk-fallback"
55405
- });
55406
- continue;
55407
- }
55408
- entriesByKind.set(sdkBlock.id, toResolvedCustomBlock(sdkBlock, { kind: "sdk-config" }));
55409
- }
55410
- return {
55411
- policy,
55412
- entries: Array.from(entriesByKind.values()),
55413
- conflicts
55414
- };
55415
- }
55416
- }
55698
+ function transitionCssVarsStyle(content) {
55699
+ const transitionStyles = isObjectRecord$1(content._transitionStyles) ? content._transitionStyles : null;
55700
+ const cssVars = isObjectRecord$1(transitionStyles?.cssVars) ? transitionStyles.cssVars : null;
55701
+ const from = typeof cssVars?.from === "string" ? cssVars.from : null;
55702
+ const to = typeof cssVars?.to === "string" ? cssVars.to : null;
55703
+ if (!from && !to) return void 0;
55704
+ return {
55705
+ ...from ? { "--site-style-transition-from": from } : {},
55706
+ ...to ? { "--site-style-transition-to": to } : {}
55707
+ };
55417
55708
  }
55418
- function createCustomBlockRegistry({ sdkConfig, customBlocks = [], policy = defaultCustomBlockSourcePolicy, onConflict }) {
55419
- const plan = planCustomBlockRegistryResolution({
55420
- sdkConfig,
55421
- customBlocks,
55422
- policy
55423
- });
55424
- const entriesByKind = new Map(plan.entries.map((entry) => [entry.blockKind, entry]));
55425
- for (const conflict of plan.conflicts) onConflict?.(`Using ${sourceLabel(conflict.winner)} custom block "${conflict.blockKind}" - ${sourceLabel(conflict.loser)} block is fallback only`);
55709
+ function mergeStyleObjects(left, right) {
55710
+ if (!left) return right;
55711
+ if (!right) return left;
55426
55712
  return {
55427
- entries: plan.entries,
55428
- conflicts: plan.conflicts,
55429
- findManifest: (blockKind) => {
55430
- if (!isCustomBlockKind(blockKind)) return void 0;
55431
- return entriesByKind.get(blockKind);
55432
- }
55713
+ ...left,
55714
+ ...right
55433
55715
  };
55434
55716
  }
55435
- function sourceLabel(source) {
55436
- switch (source.kind) {
55437
- case "managed-database": return "DB";
55438
- case "sdk-synced": return "SDK-synced DB";
55439
- case "sdk-config": return "SDK config";
55440
- default: return assertNever$24(source);
55441
- }
55717
+ function pageBlockPosition(index, blockCount) {
55718
+ if (blockCount <= 1) return "only";
55719
+ if (index === 0) return "first";
55720
+ if (index === blockCount - 1) return "last";
55721
+ return "middle";
55442
55722
  }
55443
55723
  //#endregion
55444
55724
  //#region ../blocks/src/PageRenderer.tsx
55445
- function PageRenderer$1({ theme, page, runtimeBoundaries, usePlaceholders = false, dataContext, wrapBlock, wrapBoundary, registry, themeTokens: providedThemeTokens, routeMap, blockOverrides, sdkConfig, customBlocks, previewAuthoring }) {
55725
+ function PageRenderer$1(props) {
55726
+ const { page, runtimeBoundaries, usePlaceholders = false, dataContext, wrapBlock, wrapBoundary, registry, routeMap, blockOverrides, sdkConfig, customBlocks, previewAuthoring } = props;
55446
55727
  const imageResolveContext = React$1.useMemo(() => resolvePageRendererImageResolveContext(dataContext), [
55447
55728
  dataContext?.imageResolveContext,
55448
55729
  dataContext?.mediaAssets,
@@ -55451,12 +55732,16 @@ function PageRenderer$1({ theme, page, runtimeBoundaries, usePlaceholders = fals
55451
55732
  ]);
55452
55733
  const boundaryByAdjacentBlockIds = React$1.useMemo(() => boundaryMapForAdjacentBlockIds(runtimeBoundaries ?? []), [runtimeBoundaries]);
55453
55734
  const usesRuntimeBoundaries = runtimeBoundaries !== void 0;
55735
+ const themeResources = React$1.useMemo(() => resolvePageThemeResources(props), [
55736
+ props.rendering,
55737
+ props.theme,
55738
+ props.themeTokens
55739
+ ]);
55454
55740
  if (!page || page.blocks.length === 0) return /* @__PURE__ */ jsx("div", {
55455
55741
  className: "rb-p-6 rb-caption",
55456
55742
  style: textColorStyle("mutedText"),
55457
55743
  children: "No blocks found."
55458
55744
  });
55459
- const themeTokens = providedThemeTokens ?? buildThemeRuntime$1(theme).tokens;
55460
55745
  const resolvedRegistry = registry ?? getDefaultComponentRegistry();
55461
55746
  setContextResolveImageUrlContext(imageResolveContext);
55462
55747
  return /* @__PURE__ */ jsx("div", { children: page.blocks.map((block, index) => {
@@ -55479,22 +55764,14 @@ function PageRenderer$1({ theme, page, runtimeBoundaries, usePlaceholders = fals
55479
55764
  const renderableContent = getRenderableContent(block, dataContext?.previewStage);
55480
55765
  const variantKey = definition?.manifest ? resolveVariantKey(definition.manifest, renderableContent) : null;
55481
55766
  const shouldUseWrapper = !managesOwnWrapper || Boolean(wrapBlock);
55482
- const blockSectionProps = {
55483
- themeTokens,
55484
- themeConfig: theme,
55767
+ const blockSectionProps = buildBlockSectionProps({
55768
+ props,
55769
+ themeResources,
55485
55770
  block,
55486
- usePlaceholders,
55487
- dataContext,
55488
55771
  blockKey,
55489
- registry: resolvedRegistry,
55490
- routeMap,
55491
- wrapBlock,
55492
- blockOverrides,
55493
- sdkConfig,
55494
- customBlocks,
55495
55772
  imageResolveContext,
55496
- previewAuthoring
55497
- };
55773
+ registry: resolvedRegistry
55774
+ });
55498
55775
  if (!shouldUseWrapper) {
55499
55776
  const rendered = /* @__PURE__ */ jsx(MemoBlockSection, { ...blockSectionProps }, `${blockKey}:block`);
55500
55777
  return boundaryElement ? /* @__PURE__ */ jsxs(React$1.Fragment, { children: [rendered, boundaryElement] }, blockKey) : rendered;
@@ -55536,81 +55813,6 @@ function PageRenderer$1({ theme, page, runtimeBoundaries, usePlaceholders = fals
55536
55813
  })] }, blockKey);
55537
55814
  }) });
55538
55815
  }
55539
- function isSiteStyleTransitionStyleGroup(value) {
55540
- return value?.startsWith("site-style-transition-") === true;
55541
- }
55542
- function boundaryMapForAdjacentBlockIds(boundaries) {
55543
- return new Map(boundaries.map((boundary) => [boundaryKey(boundary.previousBlockId, boundary.nextBlockId), boundary]));
55544
- }
55545
- function boundaryKey(previousBlockId, nextBlockId) {
55546
- return `${previousBlockId}\u0000${nextBlockId}`;
55547
- }
55548
- function boundaryBetweenBlocks(previousBlock, nextBlock, boundaryByAdjacentBlockIds) {
55549
- const previousBlockId = previousBlock?.id ?? null;
55550
- const nextBlockId = nextBlock?.id ?? null;
55551
- if (!previousBlockId || !nextBlockId) return null;
55552
- return boundaryByAdjacentBlockIds.get(boundaryKey(previousBlockId, nextBlockId)) ?? null;
55553
- }
55554
- function renderBoundaryAfterBlock(input) {
55555
- const previousBlockId = input.block.id;
55556
- const nextBlockId = input.nextBlock?.id ?? null;
55557
- if (!previousBlockId || !nextBlockId) return null;
55558
- const boundary = input.boundaryByAdjacentBlockIds.get(boundaryKey(previousBlockId, nextBlockId));
55559
- if (!boundary) return null;
55560
- const rendered = /* @__PURE__ */ jsx("div", {
55561
- "aria-hidden": "true",
55562
- "data-block-boundary": "",
55563
- "data-boundary-id": boundary.boundaryId,
55564
- "data-boundary-previous-block-id": boundary.previousBlockId,
55565
- "data-boundary-next-block-id": boundary.nextBlockId,
55566
- "data-style-group": boundary.styleGroup,
55567
- style: boundaryCssVarsStyle(boundary)
55568
- }, `${input.blockKey}:boundary`);
55569
- return input.wrapBoundary ? input.wrapBoundary(boundary, rendered) : rendered;
55570
- }
55571
- function boundaryCssVarsStyle(boundary) {
55572
- return {
55573
- "--site-style-transition-from": boundary.cssVars.from,
55574
- "--site-style-transition-to": boundary.cssVars.to
55575
- };
55576
- }
55577
- function boundaryReserveCssVarsStyle(input) {
55578
- const before = input.before ? boundaryReserveValueForTreatment(input.before) : null;
55579
- const after = input.after ? boundaryReserveValueForTreatment(input.after) : null;
55580
- if (!before && !after) return void 0;
55581
- return {
55582
- ...before ? { "--site-style-boundary-before-reserve": before } : {},
55583
- ...after ? { "--site-style-boundary-after-reserve": after } : {}
55584
- };
55585
- }
55586
- function boundaryReserveValueForTreatment(boundary) {
55587
- return boundary.metrics.reserveCss;
55588
- }
55589
- function transitionCssVarsStyle(content) {
55590
- const transitionStyles = isObjectRecord$1(content._transitionStyles) ? content._transitionStyles : null;
55591
- const cssVars = isObjectRecord$1(transitionStyles?.cssVars) ? transitionStyles.cssVars : null;
55592
- const from = typeof cssVars?.from === "string" ? cssVars.from : null;
55593
- const to = typeof cssVars?.to === "string" ? cssVars.to : null;
55594
- if (!from && !to) return void 0;
55595
- return {
55596
- ...from ? { "--site-style-transition-from": from } : {},
55597
- ...to ? { "--site-style-transition-to": to } : {}
55598
- };
55599
- }
55600
- function mergeStyleObjects(left, right) {
55601
- if (!left) return right;
55602
- if (!right) return left;
55603
- return {
55604
- ...left,
55605
- ...right
55606
- };
55607
- }
55608
- function pageBlockPosition(index, blockCount) {
55609
- if (blockCount <= 1) return "only";
55610
- if (index === 0) return "first";
55611
- if (index === blockCount - 1) return "last";
55612
- return "middle";
55613
- }
55614
55816
  function resolvePageRendererImageResolveContext(dataContext) {
55615
55817
  const input = dataContext?.imageResolveContext;
55616
55818
  return buildResolveImageUrlContext({
@@ -55620,6 +55822,23 @@ function resolvePageRendererImageResolveContext(dataContext) {
55620
55822
  mediaAssets: input?.mediaAssets ?? dataContext?.mediaAssets
55621
55823
  });
55622
55824
  }
55825
+ function buildBlockSectionProps(input) {
55826
+ return {
55827
+ themeResources: input.themeResources,
55828
+ block: input.block,
55829
+ usePlaceholders: input.props.usePlaceholders ?? false,
55830
+ dataContext: input.props.dataContext,
55831
+ blockKey: input.blockKey,
55832
+ registry: input.registry,
55833
+ routeMap: input.props.routeMap,
55834
+ wrapBlock: input.props.wrapBlock,
55835
+ blockOverrides: input.props.blockOverrides,
55836
+ sdkConfig: input.props.sdkConfig,
55837
+ customBlocks: input.props.customBlocks,
55838
+ imageResolveContext: input.imageResolveContext,
55839
+ previewAuthoring: input.props.previewAuthoring
55840
+ };
55841
+ }
55623
55842
  /**
55624
55843
  * Look up a block override component by block kind.
55625
55844
  * Supports both full ("block.hero") and short ("hero") keys.
@@ -55686,7 +55905,7 @@ function getCachedValidator(manifest, flavour) {
55686
55905
  * referential equality of all props that affect rendering. Standard React.memo
55687
55906
  * wouldn't catch all the render triggers from the editor store.
55688
55907
  */
55689
- const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, themeConfig, block, usePlaceholders, dataContext, registry, routeMap, wrapBlock, blockOverrides, sdkConfig, customBlocks, imageResolveContext, previewAuthoring }) {
55908
+ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeResources, block, usePlaceholders, dataContext, registry, routeMap, wrapBlock, blockOverrides, sdkConfig, customBlocks, imageResolveContext, previewAuthoring }) {
55690
55909
  const perfStart = globalThis.process?.env?.DEBUG_PERF === "1" && typeof window === "undefined" ? Date.now() : 0;
55691
55910
  const fallbackImageResolveContext = getCurrentResolveImageUrlContext();
55692
55911
  const resolvedImageResolveContext = imageResolveContext ?? fallbackImageResolveContext;
@@ -55707,6 +55926,7 @@ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, t
55707
55926
  return node;
55708
55927
  }
55709
55928
  const OverrideComponent = getBlockOverride(block.kind, blockOverrides);
55929
+ requireBlockOverride(themeResources, OverrideComponent, block.kind);
55710
55930
  let definition = getBlockDefinition(block.kind);
55711
55931
  if (!definition && block.kind.startsWith("custom.")) definition = createCustomBlockRegistry({
55712
55932
  sdkConfig,
@@ -55719,8 +55939,7 @@ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, t
55719
55939
  if (OverrideComponent) {
55720
55940
  const rendered = /* @__PURE__ */ jsx(OverrideComponent, {
55721
55941
  content: getRenderableContent(block, dataContext?.previewStage),
55722
- theme: themeTokens,
55723
- themeConfig,
55942
+ ...overrideThemeProps(themeResources),
55724
55943
  data: void 0,
55725
55944
  siteId: dataContext?.siteId,
55726
55945
  apiBaseUrl: dataContext?.apiBaseUrl,
@@ -55819,8 +56038,7 @@ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, t
55819
56038
  const hasResolvedData = !!resolved && typeof resolved === "object" && Object.keys(resolved).length > 0;
55820
56039
  const baseProps = {
55821
56040
  content: hydratedContent,
55822
- theme: themeTokens,
55823
- themeConfig,
56041
+ ...overrideThemeProps(themeResources),
55824
56042
  data: resolved,
55825
56043
  siteId: dataContext?.siteId,
55826
56044
  apiBaseUrl: dataContext?.apiBaseUrl,
@@ -55840,6 +56058,7 @@ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, t
55840
56058
  let rendered;
55841
56059
  if (OverrideComponent) rendered = /* @__PURE__ */ jsx(OverrideComponent, { ...baseProps });
55842
56060
  else {
56061
+ requireThemeResources(themeResources, block.kind);
55843
56062
  const BlockComponent = getCachedBlockComponent(definition.manifest);
55844
56063
  const pathBase = typeof block.id === "string" && block.id.length > 0 ? `blocks.${block.id}.` : void 0;
55845
56064
  const rootContext = { $root: {
@@ -55889,7 +56108,7 @@ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, t
55889
56108
  });
55890
56109
  }
55891
56110
  }, (prev, next) => {
55892
- 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;
56111
+ 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;
55893
56112
  });
55894
56113
  function fallback(message) {
55895
56114
  return /* @__PURE__ */ jsx("div", {
@@ -69104,8 +69323,9 @@ function toBlocksImageResolveContextInput(context) {
69104
69323
  mediaAssets: toBlocksMediaAssets(context.mediaAssets)
69105
69324
  };
69106
69325
  }
69107
- //#endregion
69108
- //#region src/rendering/blocks-page-renderer.ts
69326
+ function isOverrideOnlyPageRenderer(props) {
69327
+ return props.rendering?.kind === "overrides-only";
69328
+ }
69109
69329
  function normalizeSdkCustomBlocks(customBlocks) {
69110
69330
  if (!customBlocks) return void 0;
69111
69331
  return customBlocks.map((block) => {
@@ -69127,8 +69347,7 @@ function toBlocksBlockOverrides(overrides) {
69127
69347
  };
69128
69348
  return result;
69129
69349
  }
69130
- function toBlocksDataContext(dataContext) {
69131
- if (!dataContext) return void 0;
69350
+ function toBlocksPageRendererDataContext(dataContext) {
69132
69351
  return {
69133
69352
  ...dataContext,
69134
69353
  mediaAssets: toBlocksMediaAssets(dataContext.mediaAssets),
@@ -69137,15 +69356,23 @@ function toBlocksDataContext(dataContext) {
69137
69356
  }
69138
69357
  function PageRenderer(props) {
69139
69358
  const blocksSdkConfig = props.sdkConfig ? { customBlocks: normalizeSdkCustomBlocks(props.sdkConfig.customBlocks) } : props.sdkConfig;
69140
- const blocksTheme = parseBlocksTheme(props.theme);
69141
- const blocksProps = {
69142
- ...props,
69143
- theme: blocksTheme,
69144
- dataContext: toBlocksDataContext(props.dataContext),
69359
+ const { rendering: _rendering, theme: _theme, themeTokens: _themeTokens, ...commonProps } = props;
69360
+ const commonBlocksProps = {
69361
+ ...commonProps,
69362
+ dataContext: props.dataContext ? toBlocksPageRendererDataContext(props.dataContext) : void 0,
69145
69363
  blockOverrides: toBlocksBlockOverrides(props.blockOverrides),
69146
69364
  sdkConfig: blocksSdkConfig,
69147
69365
  customBlocks: normalizeSdkCustomBlocks(props.customBlocks)
69148
69366
  };
69367
+ const blocksProps = isOverrideOnlyPageRenderer(props) ? {
69368
+ ...commonBlocksProps,
69369
+ rendering: { kind: "overrides-only" },
69370
+ blockOverrides: toBlocksBlockOverrides(props.blockOverrides) ?? {}
69371
+ } : {
69372
+ ...commonBlocksProps,
69373
+ theme: parseBlocksTheme(props.theme),
69374
+ themeTokens: props.themeTokens
69375
+ };
69149
69376
  return React$1.createElement(PageRenderer$1, blocksProps);
69150
69377
  }
69151
69378
  //#endregion
@@ -69187,8 +69414,31 @@ function renderWithSdkThemeRuntime({ themeRuntime, theme, children }) {
69187
69414
  default: return assertNever$24(themeRuntime);
69188
69415
  }
69189
69416
  }
69417
+ function renderWithOverrideOnlyRuntime({ runtime, children }) {
69418
+ switch (runtime.kind) {
69419
+ case "responsive-only": return /* @__PURE__ */ jsx(ResponsiveScope, {
69420
+ responsiveMode: runtime.responsiveMode,
69421
+ children
69422
+ });
69423
+ case "none": return /* @__PURE__ */ jsx(Fragment, { children });
69424
+ default: return assertNever$24(runtime);
69425
+ }
69426
+ }
69190
69427
  //#endregion
69191
69428
  //#region src/rendering/components/pageShared.tsx
69429
+ function isOverrideOnlyPage(props) {
69430
+ return props.rendering?.kind === "overrides-only";
69431
+ }
69432
+ function resolvePageThemeTokens(props) {
69433
+ const baseTokens = props.themeTokens ?? buildThemeRuntime(props.theme).tokens;
69434
+ return props.sdkConfig?.theme?.palette ? {
69435
+ ...baseTokens,
69436
+ palette: {
69437
+ ...baseTokens.palette,
69438
+ ...props.sdkConfig.theme.palette
69439
+ }
69440
+ } : baseTokens;
69441
+ }
69192
69442
  function toPageHydrationBootstrapConfig(props) {
69193
69443
  return {
69194
69444
  siteId: props.siteId,
@@ -69196,55 +69446,60 @@ function toPageHydrationBootstrapConfig(props) {
69196
69446
  mediaAssets: props.mediaAssets
69197
69447
  };
69198
69448
  }
69199
- 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 }) {
69200
- const baseTokens = providedTokens ?? buildThemeRuntime(theme).tokens;
69201
- return renderWithSdkThemeRuntime({
69202
- themeRuntime,
69203
- theme,
69204
- children: /* @__PURE__ */ jsx(PageRenderer, {
69205
- theme,
69206
- page,
69207
- runtimeBoundaries,
69208
- themeTokens: sdkConfig?.theme?.palette ? {
69209
- ...baseTokens,
69210
- palette: {
69211
- ...baseTokens.palette,
69212
- ...sdkConfig.theme.palette
69213
- }
69214
- } : baseTokens,
69215
- usePlaceholders,
69216
- dataContext: {
69449
+ function PageContent(props) {
69450
+ const { page, runtimeBoundaries, siteId, resolvedData, bookingOfferingPresets, routeMap, pagesByIdentifier, entriesByIdentifier, wrapBlock, registry, usePlaceholders = false, blockOverrides, sdkConfig, customBlocks, supabaseUrl, mediaAssets, apiBaseUrl, portalToken, previewToken, dataContext } = props;
69451
+ const rendererCommonProps = {
69452
+ page,
69453
+ runtimeBoundaries,
69454
+ usePlaceholders,
69455
+ dataContext: {
69456
+ siteId,
69457
+ apiBaseUrl,
69458
+ portalToken,
69459
+ previewToken,
69460
+ resolvedData,
69461
+ bookingOfferingPresets: bookingOfferingPresets ?? [],
69462
+ routes: routeMap,
69463
+ pagesByIdentifier,
69464
+ entriesByIdentifier,
69465
+ occurrenceContext: dataContext?.occurrenceContext ?? null,
69466
+ entrySubrouteContext: dataContext?.entrySubrouteContext ?? null,
69467
+ contentEntry: dataContext?.contentEntry ?? null,
69468
+ pageSurface: dataContext?.pageSurface ?? null,
69469
+ subject: dataContext?.subject ?? null,
69470
+ editableRouteMetadataFieldIds: dataContext?.editableRouteMetadataFieldIds ?? null,
69471
+ previewStage: dataContext?.previewStage,
69472
+ supabaseUrl,
69473
+ mediaAssets,
69474
+ imageResolveContext: {
69217
69475
  siteId,
69218
- apiBaseUrl,
69219
- portalToken,
69220
- previewToken,
69221
- resolvedData,
69222
- bookingOfferingPresets: bookingOfferingPresets ?? [],
69223
- routes: routeMap,
69224
- pagesByIdentifier,
69225
- entriesByIdentifier,
69226
- occurrenceContext: dataContext?.occurrenceContext ?? null,
69227
- entrySubrouteContext: dataContext?.entrySubrouteContext ?? null,
69228
- contentEntry: dataContext?.contentEntry ?? null,
69229
- pageSurface: dataContext?.pageSurface ?? null,
69230
- subject: dataContext?.subject ?? null,
69231
- editableRouteMetadataFieldIds: dataContext?.editableRouteMetadataFieldIds ?? null,
69232
- previewStage: dataContext?.previewStage,
69233
69476
  supabaseUrl,
69234
- mediaAssets,
69235
- imageResolveContext: {
69236
- siteId,
69237
- supabaseUrl,
69238
- mediaAssets
69239
- }
69240
- },
69241
- routeMap,
69242
- wrapBlock,
69243
- registry,
69244
- blockOverrides,
69245
- sdkConfig: sdkConfig ? { customBlocks: sdkConfig.customBlocks } : null,
69246
- customBlocks
69247
- })
69477
+ mediaAssets
69478
+ }
69479
+ },
69480
+ routeMap,
69481
+ wrapBlock,
69482
+ registry,
69483
+ sdkConfig: sdkConfig ? { customBlocks: sdkConfig.customBlocks } : null,
69484
+ customBlocks
69485
+ };
69486
+ const content = isOverrideOnlyPage(props) ? /* @__PURE__ */ jsx(PageRenderer, {
69487
+ ...rendererCommonProps,
69488
+ rendering: { kind: "overrides-only" },
69489
+ blockOverrides: props.blockOverrides
69490
+ }) : /* @__PURE__ */ jsx(PageRenderer, {
69491
+ ...rendererCommonProps,
69492
+ theme: props.theme,
69493
+ themeTokens: resolvePageThemeTokens(props),
69494
+ blockOverrides
69495
+ });
69496
+ return isOverrideOnlyPage(props) ? renderWithOverrideOnlyRuntime({
69497
+ runtime: props.rendering.runtime,
69498
+ children: content
69499
+ }) : renderWithSdkThemeRuntime({
69500
+ themeRuntime: props.themeRuntime ?? defaultPageThemeRuntime,
69501
+ theme: props.theme,
69502
+ children: content
69248
69503
  });
69249
69504
  }
69250
69505
  //#endregion
@@ -69767,12 +70022,48 @@ function buildLogo(logo, fallbackAlt) {
69767
70022
  return result;
69768
70023
  }
69769
70024
  //#endregion
70025
+ //#region src/rendering/renderingMode.ts
70026
+ const defaultOverrideOnlyRuntime = { kind: "responsive-only" };
70027
+ //#endregion
69770
70028
  //#region src/rendering/components/Layout.tsx
69771
70029
  /**
69772
70030
  * Layout component with header and footer
69773
70031
  *
69774
70032
  * Renders site header and footer around content. Fetches site data if not provided.
69775
70033
  */
70034
+ function isOverrideOnlyLayout(props) {
70035
+ return props.rendering?.kind === "overrides-only";
70036
+ }
70037
+ var UnsupportedOverrideOnlyLayoutChromeError = class extends Error {
70038
+ constructor(surface) {
70039
+ super(`Override-only Layout requires a custom or disabled ${surface}; SDK default chrome is unavailable.`);
70040
+ this.surface = surface;
70041
+ this.code = "unsupported_override_only_layout_chrome";
70042
+ this.name = "UnsupportedOverrideOnlyLayoutChromeError";
70043
+ }
70044
+ };
70045
+ async function resolveLayoutSiteData(props) {
70046
+ if (props.siteData) return props.siteData;
70047
+ if (!props.client) throw new Error("Layout: must provide either siteData or client");
70048
+ if (!props.siteId && !props.slug && !props.domain) throw new Error("Layout: must provide siteId, slug, or domain when using client");
70049
+ return props.client.getSite({
70050
+ id: props.siteId,
70051
+ slug: props.slug,
70052
+ domain: props.domain
70053
+ });
70054
+ }
70055
+ function renderOverrideOnlyLayout(props, data) {
70056
+ if (data.header === true) throw new UnsupportedOverrideOnlyLayoutChromeError("header");
70057
+ if (data.footer === true) throw new UnsupportedOverrideOnlyLayoutChromeError("footer");
70058
+ return renderWithOverrideOnlyRuntime({
70059
+ runtime: props.rendering.runtime ?? defaultOverrideOnlyRuntime,
70060
+ children: /* @__PURE__ */ jsxs(Fragment, { children: [
70061
+ typeof props.header === "function" ? props.header(data.headerData) : null,
70062
+ props.children,
70063
+ typeof props.footer === "function" ? props.footer(data.footerData) : null
70064
+ ] })
70065
+ });
70066
+ }
69776
70067
  /**
69777
70068
  * Layout component that wraps content with site header and footer.
69778
70069
  *
@@ -69808,20 +70099,13 @@ function buildLogo(logo, fallbackAlt) {
69808
70099
  * </Layout>
69809
70100
  * ```
69810
70101
  */
69811
- async function Layout({ siteData: providedSiteData, client, siteId, slug, domain, children, header = true, footer = true, headerVariant, hasPortalSession = false, previewStage = "published", themeRuntime }) {
69812
- let siteData = providedSiteData;
69813
- if (!siteData) {
69814
- if (!client) throw new Error("Layout: must provide either siteData or client");
69815
- if (!siteId && !slug && !domain) throw new Error("Layout: must provide siteId, slug, or domain when using client");
69816
- siteData = await client.getSite({
69817
- id: siteId,
69818
- slug,
69819
- domain
69820
- });
69821
- }
69822
- const { site, theme, navigation, layout, routes } = siteData;
70102
+ async function Layout(props) {
70103
+ const { children, hasPortalSession = false, previewStage = "published" } = props;
70104
+ const header = props.header ?? true;
70105
+ const footer = props.footer ?? true;
70106
+ const siteData = await resolveLayoutSiteData(props);
70107
+ const { site, navigation, layout, routes } = siteData;
69823
70108
  const footerBlocks = siteData.footerBlocks ?? [];
69824
- const builtThemeRuntime = buildThemeRuntime(theme);
69825
70109
  const navigationOptions = {
69826
70110
  hasPortalSession,
69827
70111
  previewStage,
@@ -69835,22 +70119,38 @@ async function Layout({ siteData: providedSiteData, client, siteId, slug, domain
69835
70119
  const footerMenuViewModel = buildFooterMenu(navigation, routes, navigationOptions);
69836
70120
  const legalFooterMenuViewModel = buildFooterMenuForRole(navigation, routes, "legal-policy", navigationOptions);
69837
70121
  const logoViewModel = buildLogo(layout.logo ?? null, site.title);
69838
- const headerData = {
70122
+ const customHeaderData = {
69839
70123
  menu: menuViewModel,
69840
70124
  logo: logoViewModel,
69841
70125
  site,
69842
- theme,
69843
70126
  routes
69844
70127
  };
69845
- const footerData = {
70128
+ const customFooterData = {
69846
70129
  menu: menuViewModel,
69847
70130
  footerMenu: footerMenuViewModel,
69848
70131
  legalFooterMenu: legalFooterMenuViewModel,
69849
70132
  logo: logoViewModel,
69850
70133
  site,
69851
- theme,
69852
70134
  routes
69853
70135
  };
70136
+ if (isOverrideOnlyLayout(props)) return renderOverrideOnlyLayout(props, {
70137
+ header: props.header ?? true,
70138
+ footer: props.footer ?? true,
70139
+ headerData: customHeaderData,
70140
+ footerData: customFooterData
70141
+ });
70142
+ const { theme } = siteData;
70143
+ const builtThemeRuntime = buildThemeRuntime(theme);
70144
+ const headerVariant = props.headerVariant;
70145
+ const themeRuntime = props.themeRuntime;
70146
+ const headerData = {
70147
+ ...customHeaderData,
70148
+ theme
70149
+ };
70150
+ const footerData = {
70151
+ ...customFooterData,
70152
+ theme
70153
+ };
69854
70154
  const headerContent = headerVariant ? {
69855
70155
  ...layout.header,
69856
70156
  variant: headerVariant
@@ -69868,7 +70168,7 @@ async function Layout({ siteData: providedSiteData, client, siteId, slug, domain
69868
70168
  try {
69869
70169
  apiBaseUrl = getRiverbankEnv().baseUrl;
69870
70170
  } catch {}
69871
- const viewModelOverrides = {
70171
+ const sharedViewModelOverrides = {
69872
70172
  $root: {
69873
70173
  siteId: site.id,
69874
70174
  apiBaseUrl,
@@ -69881,14 +70181,24 @@ async function Layout({ siteData: providedSiteData, client, siteId, slug, domain
69881
70181
  site,
69882
70182
  menu: menuViewModel,
69883
70183
  footerMenu: footerMenuViewModel,
69884
- legalFooterMenu: legalFooterMenuViewModel,
70184
+ legalFooterMenu: legalFooterMenuViewModel
70185
+ };
70186
+ const headerViewModelOverrides = {
70187
+ ...sharedViewModelOverrides,
69885
70188
  content: { logo: logoViewModel }
69886
70189
  };
70190
+ const footerViewModelOverrides = {
70191
+ ...sharedViewModelOverrides,
70192
+ content: {
70193
+ ...layout.footer,
70194
+ logo: logoViewModel
70195
+ }
70196
+ };
69887
70197
  let headerElement = null;
69888
70198
  if (header === true) headerElement = renderBlock(siteHeaderManifest, headerContent, {
69889
70199
  theme: builtThemeRuntime.tokens,
69890
70200
  themeConfig: blocksThemeWithVariant,
69891
- viewModelOverrides
70201
+ viewModelOverrides: headerViewModelOverrides
69892
70202
  });
69893
70203
  else if (typeof header === "function") headerElement = header(headerData);
69894
70204
  let footerElement = null;
@@ -69923,7 +70233,7 @@ async function Layout({ siteData: providedSiteData, client, siteId, slug, domain
69923
70233
  const defaultFooterElement = footerPlan.renderDefaultFooter ? renderBlock(siteFooterManifest, layout.footer, {
69924
70234
  theme: builtThemeRuntime.tokens,
69925
70235
  themeConfig: blocksTheme,
69926
- viewModelOverrides
70236
+ viewModelOverrides: footerViewModelOverrides
69927
70237
  }) : null;
69928
70238
  footerElement = footerPlan.mode === "default+blocks" ? /* @__PURE__ */ jsxs(Fragment, { children: [footerBlocksElement, defaultFooterElement] }) : footerPlan.mode === "blocks" ? footerBlocksElement : footerPlan.mode === "none" ? null : defaultFooterElement;
69929
70239
  } else if (typeof footer === "function") footerElement = footer(footerData);
@@ -70107,6 +70417,7 @@ const SUPPORTED_LOADER_ENDPOINTS$1 = [
70107
70417
  "listPublicRecurringSchedule",
70108
70418
  "getPublicEventDetails",
70109
70419
  "listPublicWholeSeriesOfferings",
70420
+ "getPublicWholeSeriesOffering",
70110
70421
  "listPublicRouteCandidates",
70111
70422
  "listPublicTeamMembers",
70112
70423
  "listPublicProducts",