@riverbankcms/sdk 0.147.0 → 0.149.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 (442) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +1 -1
  3. package/dist/{PreviewEditorSidebar-DtpB3_sS.mjs → PreviewEditorSidebar-DBKln68M.mjs} +301 -205
  4. package/dist/{PreviewEditorUI-DxTLgaHo.mjs → PreviewEditorUI-DpRX4Mum.mjs} +68 -63
  5. package/dist/{PreviewQueryProvider-Dd4dxOiU.mjs → PreviewQueryProvider-C0mndwHB.mjs} +3 -3
  6. package/dist/{SdkPreviewModeRuntime-DMMNCngt.mjs → SdkPreviewModeRuntime-DJPmPY-r.mjs} +1247 -541
  7. package/dist/{SiteChromeCustomizeContext-DQXZXiqS.mjs → SiteChromeCustomizeContext-JYA0cJ_Z.mjs} +209720 -204978
  8. package/dist/_dts/ai/src/contracts/proposals.d.ts +0 -33
  9. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +0 -3
  10. package/dist/_dts/api/src/accessAdmin.d.ts +0 -4
  11. package/dist/_dts/api/src/accountApi.d.ts +1 -1
  12. package/dist/_dts/api/src/admin.d.ts +22 -22
  13. package/dist/_dts/api/src/aiPatch.d.ts +2 -2
  14. package/dist/_dts/api/src/aiPlayground.d.ts +1 -0
  15. package/dist/_dts/api/src/analytics.d.ts +2 -2
  16. package/dist/_dts/api/src/apiEndpointTypes.d.ts +2 -0
  17. package/dist/_dts/api/src/appointmentSetup.d.ts +2 -2
  18. package/dist/_dts/api/src/auth.d.ts +10 -10
  19. package/dist/_dts/api/src/availability.d.ts +6 -6
  20. package/dist/_dts/api/src/billing.d.ts +42 -15
  21. package/dist/_dts/api/src/billingEndpointDefinitions.d.ts +8 -0
  22. package/dist/_dts/api/src/billingEndpointTypes.d.ts +15 -6
  23. package/dist/_dts/api/src/blocks.d.ts +15 -14
  24. package/dist/_dts/api/src/blocksKeys.d.ts +2 -0
  25. package/dist/_dts/api/src/bookingConfig.d.ts +33 -50
  26. package/dist/_dts/api/src/bookingManagementEndpoints.d.ts +2 -6
  27. package/dist/_dts/api/src/bookingOperations.d.ts +9 -11
  28. package/dist/_dts/api/src/bookingRecords.d.ts +16 -11
  29. package/dist/_dts/api/src/bookingRefundOutcomes.d.ts +5 -5
  30. package/dist/_dts/api/src/bookings.d.ts +7 -7
  31. package/dist/_dts/api/src/calendar.d.ts +9 -9
  32. package/dist/_dts/api/src/clientErrorReporting.d.ts +11 -0
  33. package/dist/_dts/api/src/commercePortalEndpoints.d.ts +7 -8
  34. package/dist/_dts/api/src/common/cancellation.d.ts +23 -0
  35. package/dist/_dts/api/src/common/envelope.d.ts +2 -2
  36. package/dist/_dts/api/src/content-editor.d.ts +2 -2
  37. package/dist/_dts/api/src/contentEntries.d.ts +17 -48
  38. package/dist/_dts/api/src/contentRuntime.d.ts +51 -37
  39. package/dist/_dts/api/src/contentTypes.d.ts +11 -11
  40. package/dist/_dts/api/src/contentVersionHistoryClient.d.ts +6 -6
  41. package/dist/_dts/api/src/customerMembershipOutcomes.d.ts +1 -1
  42. package/dist/_dts/api/src/documentLifecycle.d.ts +67 -0
  43. package/dist/_dts/api/src/domains.d.ts +16 -16
  44. package/dist/_dts/api/src/editLeaseEndpoints.d.ts +72 -0
  45. package/dist/_dts/api/src/emailSettings.d.ts +4 -4
  46. package/dist/_dts/api/src/endpoints.d.ts +135 -51
  47. package/dist/_dts/api/src/eventEmailTemplates.d.ts +2 -2
  48. package/dist/_dts/api/src/eventManagementContracts.d.ts +29 -7
  49. package/dist/_dts/api/src/eventManagementEndpointDefinitions.d.ts +0 -8
  50. package/dist/_dts/api/src/eventPageWords.d.ts +7 -12
  51. package/dist/_dts/api/src/footerSettings.d.ts +6 -6
  52. package/dist/_dts/api/src/index.d.ts +8 -7
  53. package/dist/_dts/api/src/indexCoreTypes.d.ts +1 -0
  54. package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -1
  55. package/dist/_dts/api/src/navigation.d.ts +5 -5
  56. package/dist/_dts/api/src/pageSurfaceEditorEndpoints.d.ts +55 -0
  57. package/dist/_dts/api/src/pageSurfaceEndpoints.d.ts +28 -7
  58. package/dist/_dts/api/src/pages.d.ts +7 -7
  59. package/dist/_dts/api/src/performance.d.ts +1 -1
  60. package/dist/_dts/api/src/public/index.d.ts +1 -1
  61. package/dist/_dts/api/src/publicAppointmentBookingContracts.d.ts +4 -2
  62. package/dist/_dts/api/src/publicExperience/commerceEndpoints.d.ts +6 -29
  63. package/dist/_dts/api/src/redirects.d.ts +3 -3
  64. package/dist/_dts/api/src/request.d.ts +11 -2
  65. package/dist/_dts/api/src/resources.d.ts +4 -4
  66. package/dist/_dts/api/src/routes.d.ts +8 -3
  67. package/dist/_dts/api/src/sdk-event-upsert.d.ts +1 -2
  68. package/dist/_dts/api/src/sdkBlockUpsertContracts.d.ts +21 -0
  69. package/dist/_dts/api/src/sdkContracts.d.ts +5 -28
  70. package/dist/_dts/api/src/sdkEventEndpointDefinitions.d.ts +1 -1
  71. package/dist/_dts/api/src/sdkEventOccurrenceRequestContracts.d.ts +43 -0
  72. package/dist/_dts/api/src/sdkManagedEventContracts.d.ts +4 -2
  73. package/dist/_dts/api/src/sdkPullEventContracts.d.ts +9 -2
  74. package/dist/_dts/api/src/seo.d.ts +4 -4
  75. package/dist/_dts/api/src/services.d.ts +4 -4
  76. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +15 -8
  77. package/dist/_dts/api/src/siteMembers.d.ts +10 -10
  78. package/dist/_dts/api/src/siteOnboarding.d.ts +14 -0
  79. package/dist/_dts/api/src/siteOperations.d.ts +6 -2
  80. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +7 -3
  81. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +5 -12
  82. package/dist/_dts/api/src/siteRuntimeEntry.d.ts +31 -0
  83. package/dist/_dts/billing/src/checkout/platform.d.ts +77 -0
  84. package/dist/_dts/billing/src/components/index.d.ts +25 -40
  85. package/dist/_dts/billing/src/membership/index.d.ts +1 -3
  86. package/dist/_dts/billing/src/plans/entitlements.d.ts +80 -0
  87. package/dist/_dts/billing/src/plans/registry.d.ts +16 -16
  88. package/dist/_dts/billing/src/plans/standing.d.ts +9 -2
  89. package/dist/_dts/billing/src/plans/types.d.ts +5 -15
  90. package/dist/_dts/billing/src/site-arrangements.d.ts +2 -2
  91. package/dist/_dts/billing/src/subscriptions/standingEvidence.d.ts +2 -4
  92. package/dist/_dts/billing/src/subscriptions/store.d.ts +17 -11
  93. package/dist/_dts/block-form/src/backend/store-backend.d.ts +6 -7
  94. package/dist/_dts/block-form/src/backend/types.d.ts +7 -0
  95. package/dist/_dts/block-form/src/widgets/FieldFrame.d.ts +3 -1
  96. package/dist/_dts/blocks/src/client/events.d.ts +3 -0
  97. package/dist/_dts/blocks/src/contracts/index.d.ts +1 -1
  98. package/dist/_dts/blocks/src/contracts/non-block-islands.d.ts +2 -2
  99. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +54 -14
  100. package/dist/_dts/blocks/src/pageRenderAdmission.d.ts +4 -13
  101. package/dist/_dts/blocks/src/pageRendererContracts.d.ts +2 -0
  102. package/dist/_dts/blocks/src/portal/types.d.ts +9 -8
  103. package/dist/_dts/blocks/src/system/blocks/contact-newsletter.d.ts +2 -1
  104. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +3 -1
  105. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +28 -28
  106. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +7 -2
  107. package/dist/_dts/blocks/src/system/blocks/shared/bookingPaymentTerms.d.ts +84 -160
  108. package/dist/_dts/blocks/src/system/blocks/shop.d.ts +2 -2
  109. package/dist/_dts/blocks/src/system/blocks/shop.shared.d.ts +31 -4
  110. package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +2 -2
  111. package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
  112. package/dist/_dts/blocks/src/system/runtime/api/types/appointments.d.ts +4 -2
  113. package/dist/_dts/blocks/src/system/runtime/api/types/core.d.ts +3 -1
  114. package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +6 -0
  115. package/dist/_dts/blocks/src/system/runtime/api/types/portal.d.ts +6 -0
  116. package/dist/_dts/blocks/src/system/runtime/api/types/shop.d.ts +4 -0
  117. package/dist/_dts/blocks/src/system/runtime/components/booking/SuccessMessage.d.ts +4 -1
  118. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +72 -12
  119. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +36 -6
  120. package/dist/_dts/blocks/src/system/runtime/hooks/useBookingNowIso.d.ts +8 -0
  121. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.d.ts +3 -0
  122. package/dist/_dts/blocks/src/system/runtime/hooks/usePaymentVerification.d.ts +2 -1
  123. package/dist/_dts/blocks/src/system/runtime/hooks/usePolling.d.ts +7 -48
  124. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.checkout-return-context.d.ts +7 -0
  125. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.completion.d.ts +3 -1
  126. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +4 -0
  127. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.interactive.d.ts +9 -0
  128. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.payment-confirmation.d.ts +13 -0
  129. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.state.d.ts +17 -2
  130. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.submit-actions.d.ts +8 -0
  131. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.submit-handler.d.ts +1 -0
  132. package/dist/_dts/blocks/src/system/runtime/nodes/booking-runtime-sources.d.ts +1 -0
  133. package/dist/_dts/blocks/src/system/runtime/nodes/checkout.server.d.ts +2 -1
  134. package/dist/_dts/blocks/src/system/runtime/nodes/commerce/shared/display.d.ts +9 -2
  135. package/dist/_dts/blocks/src/system/runtime/nodes/event-details/presentation.d.ts +14 -2
  136. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationSurface.d.ts +2 -1
  137. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationWizard.d.ts +5 -0
  138. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/PaymentSelectionStep.d.ts +2 -0
  139. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/SuccessStep.d.ts +4 -1
  140. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventPaymentOptions.d.ts +3 -3
  141. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +2 -0
  142. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +2 -5
  143. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +4 -0
  144. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +9 -5
  145. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventListing.interactive.d.ts +6 -0
  146. package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/dates.d.ts +37 -3
  147. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventCard.client.d.ts +1 -1
  148. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventCard.d.ts +16 -1
  149. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCardPresentations.d.ts +13 -0
  150. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +29 -29
  151. package/dist/_dts/blocks/src/system/runtime/nodes/shared/MagicLinkForm.d.ts +1 -14
  152. package/dist/_dts/blocks/src/system/runtime/nodes/shared/MagicLinkForm.state.d.ts +12 -0
  153. package/dist/_dts/blocks/src/system/runtime/nodes/shop.interactive.d.ts +54 -6
  154. package/dist/_dts/blocks/src/system/runtime/shared/bookingPaymentOptions.d.ts +7 -2
  155. package/dist/_dts/blocks/src/system/runtime/shared/components/DemoBookingPortalAccess.d.ts +22 -0
  156. package/dist/_dts/blocks/src/system/runtime/shared/components/DemoPortalSignInLink.d.ts +4 -0
  157. package/dist/_dts/blocks/src/system/runtime/shared/components/index.d.ts +1 -0
  158. package/dist/_dts/blocks/src/system/runtime/shared/utils/demoBookingPassStorage.d.ts +10 -0
  159. package/dist/_dts/blocks/src/system/runtime/shared/utils/demoPortalMagicLink.d.ts +29 -0
  160. package/dist/_dts/commerce/src/purchase/bookingPaymentSelection.d.ts +54 -0
  161. package/dist/_dts/commerce/src/purchase/checkoutCommitPlan.d.ts +58 -13
  162. package/dist/_dts/commerce/src/purchase/checkoutErrorCodes.d.ts +1 -1
  163. package/dist/_dts/commerce/src/purchase/checkoutPaymentPlanPlanning.d.ts +16 -21
  164. package/dist/_dts/commerce/src/purchase/checkoutPaymentTerms.d.ts +23 -40
  165. package/dist/_dts/commerce/src/purchase/checkoutSessionMetadata.d.ts +2 -2
  166. package/dist/_dts/commerce/src/purchase/checkoutStripeSessionPlanning.d.ts +5 -4
  167. package/dist/_dts/commerce/src/purchase/event-registration-errors.d.ts +4 -0
  168. package/dist/_dts/commerce/src/purchase/index.d.ts +1 -3
  169. package/dist/_dts/commerce/src/purchase/membershipOrderItemMetadata.d.ts +4 -0
  170. package/dist/_dts/commerce/src/purchase/oneTimeCheckoutPlanning.d.ts +9 -4
  171. package/dist/_dts/commerce/src/purchase/orderInstalmentClosure.d.ts +13 -1
  172. package/dist/_dts/commerce/src/purchase/orderInstalmentLifecycle.d.ts +5 -0
  173. package/dist/_dts/commerce/src/purchase/orderItemMetadata.d.ts +3 -1
  174. package/dist/_dts/commerce/src/purchase/orderTypes.d.ts +7 -1
  175. package/dist/_dts/commerce/src/purchase/refundRailSplit.d.ts +1 -1
  176. package/dist/_dts/commerce/src/purchase/stateTransitions.d.ts +2 -2
  177. package/dist/_dts/commerce/src/purchase/stripeMinimumCharge.d.ts +6 -0
  178. package/dist/_dts/commerce/src/purchase/types.d.ts +2 -1
  179. package/dist/_dts/content-editor/src/components/ContentFieldsForm.d.ts +2 -7
  180. package/dist/_dts/content-editor/src/controller/EditLeaseController.d.ts +39 -0
  181. package/dist/_dts/content-editor/src/controller/EditorWriteGate.d.ts +38 -0
  182. package/dist/_dts/content-editor/src/controller/EntryControllerProvider.d.ts +25 -61
  183. package/dist/_dts/content-editor/src/controller/LinkedEntryLeaseBanner.d.ts +7 -0
  184. package/dist/_dts/content-editor/src/controller/LinkedEntryLeaseControllers.d.ts +14 -0
  185. package/dist/_dts/content-editor/src/controller/deriveEditorUnpublishedState.d.ts +6 -0
  186. package/dist/_dts/content-editor/src/controller/documentValueBaseline.d.ts +25 -0
  187. package/dist/_dts/content-editor/src/controller/editLeaseHandover.d.ts +30 -0
  188. package/dist/_dts/content-editor/src/controller/editLeaseLossSignal.d.ts +6 -0
  189. package/dist/_dts/content-editor/src/controller/editLeaseNotice.d.ts +28 -0
  190. package/dist/_dts/content-editor/src/controller/editorClientId.d.ts +2 -0
  191. package/dist/_dts/content-editor/src/controller/editorEditability.d.ts +38 -0
  192. package/dist/_dts/content-editor/src/controller/editorLeaseParticipation.d.ts +34 -0
  193. package/dist/_dts/content-editor/src/controller/normalizedMetadataBaseline.d.ts +29 -0
  194. package/dist/_dts/content-editor/src/controller/pageSurfaceDocumentBaselines.d.ts +14 -0
  195. package/dist/_dts/content-editor/src/controller/pageSurfaceLifecycle.d.ts +11 -0
  196. package/dist/_dts/content-editor/src/controller/planDocumentBaselineRefresh.d.ts +19 -0
  197. package/dist/_dts/content-editor/src/controller/readDocumentLeaseBaselines.d.ts +19 -0
  198. package/dist/_dts/content-editor/src/controller/refreshDocumentLeaseBaseline.d.ts +12 -0
  199. package/dist/_dts/content-editor/src/controller/refreshLinkedEntry.d.ts +17 -0
  200. package/dist/_dts/content-editor/src/controller/replayRestoredEditorEffects.d.ts +2 -3
  201. package/dist/_dts/content-editor/src/controller/routeWrites.d.ts +26 -0
  202. package/dist/_dts/content-editor/src/controller/useAutosaveTriggers.d.ts +16 -17
  203. package/dist/_dts/content-editor/src/controller/useBlockedPublishPlan.d.ts +6 -2
  204. package/dist/_dts/content-editor/src/controller/useBlocksList.d.ts +3 -3
  205. package/dist/_dts/content-editor/src/controller/useEntryValueAutosaves.d.ts +21 -0
  206. package/dist/_dts/content-editor/src/controller/useInitialEditorUiStore.d.ts +24 -0
  207. package/dist/_dts/content-editor/src/controller/useServerBaselineReconciliation.d.ts +17 -0
  208. package/dist/_dts/content-editor/src/footerComposerPanelTypes.d.ts +1 -1
  209. package/dist/_dts/content-editor/src/hooks/applyBlockedPublishPlan.d.ts +5 -1
  210. package/dist/_dts/content-editor/src/hooks/blockDraftLifecycle.d.ts +8 -47
  211. package/dist/_dts/content-editor/src/hooks/editLeaseMachine.d.ts +120 -0
  212. package/dist/_dts/content-editor/src/hooks/publishability.d.ts +6 -10
  213. package/dist/_dts/content-editor/src/hooks/useAutosaveStatus.d.ts +3 -0
  214. package/dist/_dts/content-editor/src/hooks/useBlockAutosave.d.ts +5 -15
  215. package/dist/_dts/content-editor/src/hooks/useDebouncedLatestSave.d.ts +7 -5
  216. package/dist/_dts/content-editor/src/hooks/useEditLease.d.ts +28 -0
  217. package/dist/_dts/content-editor/src/hooks/useEntryActions.d.ts +25 -39
  218. package/dist/_dts/content-editor/src/hooks/useEntryMutations.d.ts +17 -19
  219. package/dist/_dts/content-editor/src/hooks/useLinkedEntryAutosave.d.ts +5 -8
  220. package/dist/_dts/content-editor/src/hooks/useValueAutosave.d.ts +64 -0
  221. package/dist/_dts/content-editor/src/hooks/validateBlocksForPublish.d.ts +0 -7
  222. package/dist/_dts/content-editor/src/index.d.ts +26 -7
  223. package/dist/_dts/content-editor/src/lib/browserStorage.d.ts +5 -0
  224. package/dist/_dts/content-editor/src/linkedEntries/domain.d.ts +12 -0
  225. package/dist/_dts/content-editor/src/linkedEntries/owner.d.ts +9 -0
  226. package/dist/_dts/content-editor/src/liveDrafts/draftProjection.d.ts +66 -0
  227. package/dist/_dts/content-editor/src/liveDrafts/linkedSaveHandovers.d.ts +37 -0
  228. package/dist/_dts/content-editor/src/liveDrafts/remoteDraftOverlay.d.ts +113 -0
  229. package/dist/_dts/content-editor/src/liveDrafts/useLiveDrafts.d.ts +32 -0
  230. package/dist/_dts/content-editor/src/liveDrafts/useRetentionTicks.d.ts +7 -0
  231. package/dist/_dts/content-editor/src/primitives/shared/activePreviewField.d.ts +6 -0
  232. package/dist/_dts/content-editor/src/primitives/shared/storeBinding.d.ts +1 -0
  233. package/dist/_dts/content-editor/src/services/contentEntryServices.d.ts +96 -19
  234. package/dist/_dts/content-editor/src/services/editorApiClient.d.ts +13 -0
  235. package/dist/_dts/content-editor/src/services/index.d.ts +2 -0
  236. package/dist/_dts/content-editor/src/services/pageSurfaceEditorServices.d.ts +23 -0
  237. package/dist/_dts/content-editor/src/sync/flushValues.d.ts +13 -0
  238. package/dist/_dts/content-editor/src/sync/lifecycleFailure.d.ts +51 -0
  239. package/dist/_dts/content-editor/src/sync/runLifecycle.d.ts +64 -0
  240. package/dist/_dts/content-editor/src/sync/schedulerValues.d.ts +27 -0
  241. package/dist/_dts/content-editor/src/sync/sendPlanning.d.ts +104 -0
  242. package/dist/_dts/content-editor/src/sync/valueSync.d.ts +114 -0
  243. package/dist/_dts/content-editor/src/ui/blockCollection.d.ts +8 -0
  244. package/dist/_dts/content-editor/src/ui/documentLifecycle.d.ts +18 -0
  245. package/dist/_dts/content-editor/src/ui/editorLeaseUiState.d.ts +7 -0
  246. package/dist/_dts/content-editor/src/ui/editorRefresh.d.ts +82 -0
  247. package/dist/_dts/content-editor/src/ui/editorSnapshot.d.ts +102 -127
  248. package/dist/_dts/content-editor/src/ui/editorTransactionState.d.ts +1 -1
  249. package/dist/_dts/content-editor/src/ui/editorUiStore.d.ts +126 -72
  250. package/dist/_dts/content-editor/src/ui/editorValueSnapshot.d.ts +18 -0
  251. package/dist/_dts/content-editor/src/ui/serverBlockAdmission.d.ts +26 -0
  252. package/dist/_dts/content-editor/src/ui/stores/autosaveStore.d.ts +16 -27
  253. package/dist/_dts/content-editor/src/ui/stores/blockVersionsStore.d.ts +24 -0
  254. package/dist/_dts/content-editor/src/ui/stores/linkedEntryLeaseStore.d.ts +54 -0
  255. package/dist/_dts/content-editor/src/ui/stores/linkedSaveHandoversStore.d.ts +11 -0
  256. package/dist/_dts/content-editor/src/ui/stores/remoteDraftsStore.d.ts +10 -0
  257. package/dist/_dts/content-editor/src/ui/stores/types.d.ts +63 -3
  258. package/dist/_dts/content-editor/src/useFooterComposerState.d.ts +2 -2
  259. package/dist/_dts/content-editor/src/useFooterNavigationLayout.d.ts +1 -1
  260. package/dist/_dts/content-model/src/content-types/builtin-schemas.d.ts +4 -4
  261. package/dist/_dts/content-model/src/content-types/builtins.d.ts +4 -4
  262. package/dist/_dts/content-model/src/definitions/shared.d.ts +11 -2
  263. package/dist/_dts/content-model/src/entry-slots/index.d.ts +1 -0
  264. package/dist/_dts/content-model/src/entry-slots/serializeAllowedBlocks.d.ts +2 -0
  265. package/dist/_dts/content-model/src/metadataConfig.d.ts +10 -38
  266. package/dist/_dts/content-model/src/templates/defaults.d.ts +0 -1
  267. package/dist/_dts/content-model/src/types.d.ts +0 -1
  268. package/dist/_dts/core/src/block-content-identity.d.ts +49 -1
  269. package/dist/_dts/core/src/booking-flexible-balance.d.ts +2 -2
  270. package/dist/_dts/core/src/booking-instalment-deposit.d.ts +20 -0
  271. package/dist/_dts/core/src/booking-live-payment-terms.d.ts +72 -0
  272. package/dist/_dts/core/src/booking-payment-options.d.ts +24 -0
  273. package/dist/_dts/core/src/booking-payment-schemas.d.ts +522 -0
  274. package/dist/_dts/core/src/branded.d.ts +15 -0
  275. package/dist/_dts/core/src/currency-format.d.ts +8 -2
  276. package/dist/_dts/core/src/demo-lifecycle-status.d.ts +2 -2
  277. package/dist/_dts/core/src/demo-warm-pool-target.d.ts +8 -0
  278. package/dist/_dts/core/src/edit-lease.d.ts +60 -0
  279. package/dist/_dts/core/src/editor-state.d.ts +38 -13
  280. package/dist/_dts/core/src/editor-value-sync.d.ts +79 -0
  281. package/dist/_dts/core/src/html-entities.d.ts +6 -0
  282. package/dist/_dts/core/src/index.d.ts +7 -0
  283. package/dist/_dts/core/src/uuid.d.ts +7 -5
  284. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +456 -189
  285. package/dist/_dts/editor/src/EditorProvider.d.ts +5 -0
  286. package/dist/_dts/editor/src/chrome/EditorChrome.d.ts +14 -0
  287. package/dist/_dts/editor/src/chrome/EditorStatusBar.d.ts +1 -0
  288. package/dist/_dts/editor/src/chrome/statusBarPresentation.d.ts +0 -1
  289. package/dist/_dts/editor/src/index.d.ts +1 -1
  290. package/dist/_dts/editor-blocks/src/BlockEditor.d.ts +10 -9
  291. package/dist/_dts/editor-blocks/src/BlockForm.d.ts +1 -1
  292. package/dist/_dts/editor-blocks/src/block-editor/BlockCard.d.ts +1 -1
  293. package/dist/_dts/editor-blocks/src/block-editor/BlockCardFrame.d.ts +1 -1
  294. package/dist/_dts/editor-blocks/src/block-editor/BlockSettingsModal.d.ts +1 -1
  295. package/dist/_dts/editor-blocks/src/block-editor/applyExtendedFieldDefaults.d.ts +3 -4
  296. package/dist/_dts/editor-blocks/src/block-editor/blockDraftBaselineSeed.d.ts +4 -8
  297. package/dist/_dts/editor-blocks/src/block-editor/editorBlockItem.d.ts +23 -0
  298. package/dist/_dts/editor-blocks/src/block-editor/generatedIconApplyCoordination.d.ts +2 -7
  299. package/dist/_dts/editor-blocks/src/block-editor/hooks/applyBlockStructureChange.d.ts +4 -0
  300. package/dist/_dts/editor-blocks/src/block-editor/hooks/buildInsertBlockHistoryCommand.d.ts +14 -5
  301. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockBaselineSync.d.ts +21 -19
  302. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockCreation.d.ts +2 -10
  303. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockDuplication.d.ts +8 -16
  304. package/dist/_dts/editor-blocks/src/block-editor/owner.d.ts +6 -16
  305. package/dist/_dts/editor-blocks/src/block-editor/types.d.ts +37 -9
  306. package/dist/_dts/editor-blocks/src/index.d.ts +2 -1
  307. package/dist/_dts/editor-blocks/src/widgets/entry-picker/loaders.d.ts +1 -1
  308. package/dist/_dts/editor-blocks/src/widgets/link/loaders.d.ts +1 -1
  309. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/loaders.d.ts +1 -1
  310. package/dist/_dts/editor-blocks/src/widgets/reference/loaders.d.ts +1 -1
  311. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/loaders.d.ts +3 -2
  312. package/dist/_dts/media-core/src/fileStorage.d.ts +4 -0
  313. package/dist/_dts/media-editor/src/MediaPickerDialog.d.ts +3 -1
  314. package/dist/_dts/media-editor/src/MediaPickerMiniDialog.d.ts +10 -0
  315. package/dist/_dts/media-editor/src/context.d.ts +1 -1
  316. package/dist/_dts/media-editor/src/createMediaEditorProvider.d.ts +1 -2
  317. package/dist/_dts/media-editor/src/index.d.ts +2 -0
  318. package/dist/_dts/media-editor/src/provider.d.ts +3 -2
  319. package/dist/_dts/media-react/src/hooks/internal/classification.d.ts +1 -1
  320. package/dist/_dts/media-react/src/hooks/useApiMediaUploader.d.ts +3 -1
  321. package/dist/_dts/preview-next/src/client/blocks/composer/mergeDrafts.d.ts +8 -3
  322. package/dist/_dts/preview-next/src/client/blocks/composer/types.d.ts +6 -3
  323. package/dist/_dts/preview-next/src/client/blocks/linkedEntryRenderOverlay.d.ts +22 -2
  324. package/dist/_dts/preview-next/src/client/blocks/previewProjection/entryFieldRebinding.d.ts +13 -0
  325. package/dist/_dts/preview-next/src/client/blocks/previewProjection/index.d.ts +2 -1
  326. package/dist/_dts/preview-next/src/client/blocks/previewProjection/types.d.ts +11 -1
  327. package/dist/_dts/preview-next/src/client/blocks/renderPrecedence.d.ts +17 -0
  328. package/dist/_dts/preview-next/src/client/blocks/useLinkedSaveHandoverRetention.d.ts +20 -0
  329. package/dist/_dts/preview-next/src/client/index.d.ts +1 -1
  330. package/dist/_dts/preview-next/src/client/preview/EntryEditorPanel.d.ts +2 -1
  331. package/dist/_dts/preview-next/src/client/preview/EntrySlotBlockEditorPanel.d.ts +2 -1
  332. package/dist/_dts/preview-next/src/client/preview/PreviewAccessBanners.d.ts +7 -0
  333. package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +2 -1
  334. package/dist/_dts/preview-next/src/client/preview/PreviewEntryControllerProvider.d.ts +23 -14
  335. package/dist/_dts/preview-next/src/client/preview/PreviewLeaseEditingMode.d.ts +2 -0
  336. package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +9 -2
  337. package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +1 -0
  338. package/dist/_dts/preview-next/src/client/preview/previewCustomizeAutosave.d.ts +5 -0
  339. package/dist/_dts/preview-next/src/client/preview/previewCustomizeWorkflowState.d.ts +3 -4
  340. package/dist/_dts/preview-next/src/client/preview/sdkConfig.d.ts +1 -0
  341. package/dist/_dts/preview-next/src/client/preview/usePreviewCustomizeWorkflowState.d.ts +4 -0
  342. package/dist/_dts/preview-next/src/client/previewAuthStore.d.ts +7 -0
  343. package/dist/_dts/preview-next/src/constants.d.ts +4 -0
  344. package/dist/_dts/preview-next/src/keepAlive.d.ts +1 -0
  345. package/dist/_dts/realtime/src/client.d.ts +3 -0
  346. package/dist/_dts/realtime/src/draftChannel.d.ts +91 -0
  347. package/dist/_dts/realtime/src/drafts.d.ts +210 -0
  348. package/dist/_dts/realtime/src/index.d.ts +3 -0
  349. package/dist/_dts/realtime/src/leaseChangeSubscriptions.d.ts +8 -0
  350. package/dist/_dts/realtime/src/types.d.ts +113 -0
  351. package/dist/_dts/realtime/src/useDraftChannel.d.ts +34 -0
  352. package/dist/_dts/realtime/src/useSiteRealtimeReload.d.ts +27 -0
  353. package/dist/_dts/sdk/src/public-api/contracts.d.ts +6 -55
  354. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +1 -0
  355. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +1 -0
  356. package/dist/_dts/sdk/src/rendering/helpers/pageRuntimeSupport.d.ts +2 -0
  357. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +2 -12
  358. package/dist/_dts/sdk/src/version.d.ts +1 -1
  359. package/dist/_dts/surfaces/src/index.d.ts +1 -0
  360. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +2 -2
  361. package/dist/_dts/theme-core/src/site-styles/pageDesignIntent.d.ts +0 -5
  362. package/dist/_dts/ui/src/color-picker.d.ts +1 -1
  363. package/dist/_dts/ui/src/palette/useHexDraft.d.ts +7 -0
  364. package/dist/client/{BookingMailingListNote-1n4Ch_u_.mjs → BookingMailingListNote-Cr3EeTP5.mjs} +504 -163
  365. package/dist/client/DemoBookingPortalAccess-BFGB1Fay.mjs +344 -0
  366. package/dist/client/{EventCombined.client-C0pgma9y.mjs → EventCombined.client-DKYV0_ft.mjs} +6 -6
  367. package/dist/client/{EventListing.client-4fhLOvHP.mjs → EventListing.client-B9UIcEYc.mjs} +2 -2
  368. package/dist/client/{LeafletStaticMap-DScC4F3w.mjs → LeafletStaticMap-CFLPkP0K.mjs} +1 -1
  369. package/dist/client/{TerminalPanel-B5ZUsYhe.mjs → TerminalPanel-JjmgxEsR.mjs} +1 -1
  370. package/dist/client/{ThemedButton-DoVIV1Ao.mjs → ThemedButton-CKV1Jh2m.mjs} +1 -1
  371. package/dist/client/{accordion-CoT5g7zo.mjs → accordion-DXWIfT3T.mjs} +1 -1
  372. package/dist/client/{bookingForm-BWxB46xD.mjs → bookingForm-CjZgHNvv.mjs} +216 -63
  373. package/dist/client/bookings.mjs +1187 -692
  374. package/dist/client/{carousel-DtNYWFd3.mjs → carousel-DSLikmvZ.mjs} +1 -1
  375. package/dist/client/{cart-z4qZih1Y.mjs → cart-HDjWReFt.mjs} +3 -3
  376. package/dist/client/{checkout-DpL7euFH.mjs → checkout-CUvRZA3W.mjs} +3 -3
  377. package/dist/client/{checkoutUrls-BEfR7kVu.mjs → checkoutUrls-CXhko2Rv.mjs} +1 -1
  378. package/dist/client/client.mjs +2711 -1684
  379. package/dist/client/{context-C8TinPJc.mjs → context-DFmaZa-Q.mjs} +4 -3
  380. package/dist/client/{dates-vwwxTeB0.mjs → dates-BBep1JnF.mjs} +56 -11
  381. package/dist/client/{eventCalendar-DIbHfJXO.mjs → eventCalendar-zEobhxo4.mjs} +9 -9
  382. package/dist/client/{eventCombined-DoGMJ6cg.mjs → eventCombined-Dp7bz5k-.mjs} +4 -4
  383. package/dist/client/{eventDetails-BjN9v6a1.mjs → eventDetails-FE-zqTt7.mjs} +4 -4
  384. package/dist/client/{eventListing-DajjWgOv.mjs → eventListing-BMt5snal.mjs} +4 -4
  385. package/dist/client/{eventRegistration-DMq9gMA-.mjs → eventRegistration-O6ZxHfOb.mjs} +422 -570
  386. package/dist/client/{form-Qf6qTbos.mjs → form-DFa1D8vt.mjs} +3 -3
  387. package/dist/client/{headerSection-D7qJrqFX.mjs → headerSection-CmjHLR-N.mjs} +3 -3
  388. package/dist/client/hooks.mjs +414 -182
  389. package/dist/client/{locationMap-CCF9-t_0.mjs → locationMap-BXKP_lGh.mjs} +3 -3
  390. package/dist/client/{media-CwBGetqC.mjs → media-Cl38iOMI.mjs} +10 -3
  391. package/dist/client/{newsletterForm-DzCLSP4S.mjs → newsletterForm-CU-HmxGx.mjs} +3 -3
  392. package/dist/client/{pricing-Cgxv2KLC.mjs → pricing-KEAEsibq.mjs} +1 -1
  393. package/dist/client/{productDetail-ru9w5GHx.mjs → productDetail-Ckp7MGnt.mjs} +3 -3
  394. package/dist/client/{productList-zaapKSl-.mjs → productList-D91V0sYa.mjs} +3 -3
  395. package/dist/client/{propsDecoder-CwvvNOHx.mjs → propsDecoder-DZd6RJeA.mjs} +244 -94
  396. package/dist/client/rendering/client.mjs +2656 -1705
  397. package/dist/client/rendering/islands.mjs +18 -18
  398. package/dist/client/rendering.mjs +3430 -2352
  399. package/dist/client/{routeIslandApiConfig-BwVFo0Y4.mjs → routeIslandApiConfig-E1EkhhYY.mjs} +1 -1
  400. package/dist/client/{shop-mktkXvbV.mjs → shop-4F2jLQPI.mjs} +131 -85
  401. package/dist/client/{shop-commerce-De7gEnkA.mjs → shop-commerce-BbfCJjB3.mjs} +25 -13
  402. package/dist/client/{shop-commerce-store-B3MCxIBW.mjs → shop-commerce-store-vicweP2K.mjs} +1 -1
  403. package/dist/client/{shopShared-TqExh235.mjs → shopShared-DlONJt0T.mjs} +4 -4
  404. package/dist/client/{useEventFilters-n_OjkIjX.mjs → useEventFilters-COYyL3m7.mjs} +32 -17
  405. package/dist/preview-next/before-render.mjs +207 -105
  406. package/dist/preview-next/client/runtime.mjs +4 -4
  407. package/dist/preview-next/constants.mjs +5 -1
  408. package/dist/preview-next/index.mjs +5 -1
  409. package/dist/preview-next/keepAlive.mjs +341 -165
  410. package/dist/preview-next/middleware.mjs +207 -105
  411. package/dist/{previewAuthStore-C_EHQ5XA.mjs → previewAuthStore-BBmV7UsW.mjs} +243 -112
  412. package/dist/{sdk-runtime-BIkJg5y1.mjs → sdk-runtime-CwvFFjB-.mjs} +2 -2
  413. package/dist/{separator-C9qDP95Z.mjs → separator-ByL72zUT.mjs} +1 -1
  414. package/dist/server/components.mjs +1839 -1475
  415. package/dist/server/config-validation.mjs +381 -166
  416. package/dist/server/config.mjs +381 -166
  417. package/dist/server/data.mjs +381 -166
  418. package/dist/server/index.mjs +214 -110
  419. package/dist/server/next.mjs +663 -351
  420. package/dist/server/page-converter.mjs +198 -79
  421. package/dist/server/prebuild.mjs +1 -1
  422. package/dist/server/rendering/server.mjs +1536 -1169
  423. package/dist/server/rendering.mjs +2432 -2068
  424. package/dist/server/routing.mjs +456 -173
  425. package/dist/server/server.mjs +447 -267
  426. package/package.json +1 -1
  427. package/dist/_dts/api/src/bookingPaymentTermSchemas.d.ts +0 -123
  428. package/dist/_dts/billing/src/plans/display.d.ts +0 -15
  429. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.mailing-list-note.d.ts +0 -3
  430. package/dist/_dts/commerce/src/purchase/checkoutPaymentTermPlanning.d.ts +0 -10
  431. package/dist/_dts/commerce/src/purchase/checkoutValidatedItemPlanning.d.ts +0 -55
  432. package/dist/_dts/commerce/src/purchase/orderInstalmentPayoff.d.ts +0 -24
  433. package/dist/_dts/content-editor/src/controller/buildBlockPublishedBaselines.d.ts +0 -4
  434. package/dist/_dts/content-editor/src/controller/buildPublishSuccessTransition.d.ts +0 -16
  435. package/dist/_dts/content-editor/src/controller/driver.d.ts +0 -14
  436. package/dist/_dts/content-editor/src/controller/seedDraftBaselinesFromBlocks.d.ts +0 -7
  437. package/dist/_dts/content-editor/src/controller/useEntrySyncHelpers.d.ts +0 -29
  438. package/dist/_dts/content-editor/src/hooks/autosaveScopePlanning.d.ts +0 -26
  439. package/dist/_dts/content-editor/src/hooks/useSimpleAutosave.d.ts +0 -64
  440. package/dist/_dts/content-editor/src/hooks/useStoreAutosave.d.ts +0 -48
  441. package/dist/_dts/content-editor/src/types.d.ts +0 -44
  442. package/dist/client/DiscountCodeDisclosure-CKJtz0mY.mjs +0 -137
@@ -61,6 +61,19 @@ const CURRENCY_LOCALE_BY_CODE = {
61
61
  function resolveCurrencyLocale(currencyCode, override) {
62
62
  return override ?? CURRENCY_LOCALE_BY_CODE[currencyCode] ?? "en";
63
63
  }
64
+ function fractionDigitsFor(decimals, exactFormatter) {
65
+ switch (decimals) {
66
+ case "exact": return {};
67
+ case "auto": return {
68
+ minimumFractionDigits: 0,
69
+ maximumFractionDigits: exactFormatter.resolvedOptions().maximumFractionDigits
70
+ };
71
+ case "whole": return {
72
+ minimumFractionDigits: 0,
73
+ maximumFractionDigits: 0
74
+ };
75
+ }
76
+ }
64
77
  /**
65
78
  * The single currency-amount formatter for the product: minor units in,
66
79
  * localized string out.
@@ -71,6 +84,13 @@ function resolveCurrencyLocale(currencyCode, override) {
71
84
  * own `Intl.NumberFormat`.
72
85
  */
73
86
  function formatCurrencyAmount(amountCents, currency, options) {
87
+ return formatCurrencyMajorUnits(amountCents / 100, currency, options);
88
+ }
89
+ /**
90
+ * `formatCurrencyAmount` for an amount already in MAJOR units (29.99 = £29.99),
91
+ * such as a registrar price. Prefer minor units everywhere else.
92
+ */
93
+ function formatCurrencyMajorUnits(amount, currency, options) {
74
94
  const currencyCode = currency.toUpperCase();
75
95
  const locale = resolveCurrencyLocale(currencyCode, options?.locale);
76
96
  try {
@@ -78,17 +98,13 @@ function formatCurrencyAmount(amountCents, currency, options) {
78
98
  style: "currency",
79
99
  currency: currencyCode
80
100
  });
81
- const fractionDigits = options?.decimals === "auto" ? {
82
- minimumFractionDigits: 0,
83
- maximumFractionDigits: exactFormatter.resolvedOptions().maximumFractionDigits
84
- } : {};
85
101
  return new Intl.NumberFormat(locale, {
86
102
  style: "currency",
87
103
  currency: currencyCode,
88
- ...fractionDigits
89
- }).format(amountCents / 100);
104
+ ...fractionDigitsFor(options?.decimals ?? "exact", exactFormatter)
105
+ }).format(amount);
90
106
  } catch {
91
- return `${(amountCents / 100).toFixed(2)} ${currencyCode}`;
107
+ return `${amount.toFixed(2)} ${currencyCode}`;
92
108
  }
93
109
  }
94
110
  //#endregion
@@ -374,6 +390,16 @@ function isRecord$22(value) {
374
390
  return typeof value === "object" && value !== null && !Array.isArray(value);
375
391
  }
376
392
  //#endregion
393
+ //#region ../core/src/booking-payment-options.ts
394
+ /** Automatic instalments and a flexible balance cannot share one booking offer. */
395
+ function validateBookingPaymentOptionKinds(kinds) {
396
+ if (kinds.length === 0) return err("no_options");
397
+ const uniqueKinds = new Set(kinds);
398
+ if (uniqueKinds.size !== kinds.length) return err("duplicate_kind");
399
+ if (uniqueKinds.has("instalment_plan") && uniqueKinds.has("flexible_balance")) return err("incompatible_collection_options");
400
+ return ok$1(void 0);
401
+ }
402
+ //#endregion
377
403
  //#region ../core/src/booking-time-zone.ts
378
404
  const TIME_ZONE_VALIDITY_CACHE_LIMIT = 100;
379
405
  const timeZoneValidityCache = /* @__PURE__ */ new Map();
@@ -681,6 +707,26 @@ function toLocationCoordinates(value) {
681
707
  };
682
708
  }
683
709
  //#endregion
710
+ //#region ../core/src/block-content-identity.ts
711
+ function readContentVersionId(value) {
712
+ const parsed = parseContentVersionId(value);
713
+ return parsed.ok ? parsed.value : null;
714
+ }
715
+ /** The one pairing of a published id with its content. */
716
+ function readPublishedBlockPlacement(id, content) {
717
+ if (id == null && content == null) return null;
718
+ const versionId = readContentVersionId(id);
719
+ return versionId !== null && content != null ? {
720
+ kind: "published",
721
+ id: versionId,
722
+ content
723
+ } : {
724
+ kind: "incomplete",
725
+ id: id ?? null,
726
+ content: content ?? null
727
+ };
728
+ }
729
+ //#endregion
684
730
  //#region ../core/src/mailing-list-identifiers.ts
685
731
  const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
686
732
  const OPAQUE_ID_PATTERN = /^[A-Za-z0-9_-]{1,100}$/u;
@@ -1620,11 +1666,18 @@ function isReservedPathSegment(value) {
1620
1666
  function isUnsafePathSegment(segment) {
1621
1667
  return segment.trim().length === 0 || segment !== segment.trim() || isReservedPathSegment(segment) || containsUnsafePathSegmentCharacter(segment);
1622
1668
  }
1623
- ({
1669
+ //#endregion
1670
+ //#region ../media-core/src/fileStorage.ts
1671
+ const FILE_STORAGE_BUCKETS = {
1624
1672
  publicSite: unsafeAsStorageBucketName("media"),
1625
1673
  privateSite: unsafeAsStorageBucketName("site-files-private"),
1626
- temporary: unsafeAsStorageBucketName("temp-uploads")
1627
- }).publicSite;
1674
+ temporary: unsafeAsStorageBucketName("temp-uploads"),
1675
+ siteAssets: unsafeAsStorageBucketName("site-assets"),
1676
+ siteFonts: unsafeAsStorageBucketName("site-fonts"),
1677
+ bookingRequirementDocuments: unsafeAsStorageBucketName("booking-requirement-documents")
1678
+ };
1679
+ FILE_STORAGE_BUCKETS.publicSite, FILE_STORAGE_BUCKETS.siteAssets, FILE_STORAGE_BUCKETS.siteFonts;
1680
+ FILE_STORAGE_BUCKETS.publicSite, FILE_STORAGE_BUCKETS.privateSite, FILE_STORAGE_BUCKETS.temporary, FILE_STORAGE_BUCKETS.siteAssets, FILE_STORAGE_BUCKETS.siteFonts, FILE_STORAGE_BUCKETS.bookingRequirementDocuments;
1628
1681
  function parseStoragePath(value) {
1629
1682
  return joinStoragePathSegments(value.split("/"));
1630
1683
  }
@@ -28724,68 +28777,115 @@ function isRichTextDoc(value) {
28724
28777
  return RichTextDocSchema.safeParse(value).success;
28725
28778
  }
28726
28779
  //#endregion
28727
- //#region ../blocks/src/system/blocks/shared/bookingPaymentTerms.ts
28728
- const bookingDepositRefundPolicySchema$1 = z.enum(["refundable", "non_refundable"]);
28729
- const bookingInstalmentPlanSchema$1 = z.union([
28730
- z.object({
28731
- kind: z.literal("deposit_plus_one_remainder"),
28732
- depositAmountCents: z.number().int().min(0),
28733
- depositRefundability: bookingDepositRefundPolicySchema$1,
28734
- remainderDueCount: z.number().int().positive(),
28735
- intervalUnit: z.enum([
28736
- "day",
28737
- "week",
28738
- "month"
28739
- ])
28740
- }),
28741
- z.object({
28742
- kind: z.literal("deposit_plus_scheduled_instalments"),
28743
- depositAmountCents: z.number().int().min(0),
28744
- depositRefundability: bookingDepositRefundPolicySchema$1,
28745
- instalmentCount: z.number().int().positive(),
28746
- intervalCount: z.number().int().positive(),
28747
- intervalUnit: z.enum([
28748
- "day",
28749
- "week",
28750
- "month"
28751
- ])
28752
- }),
28753
- z.object({
28754
- kind: z.literal("equal_scheduled_instalments"),
28755
- instalmentCount: z.number().int().positive(),
28756
- intervalCount: z.number().int().positive(),
28757
- intervalUnit: z.enum([
28758
- "day",
28759
- "week",
28760
- "month"
28761
- ])
28762
- })
28763
- ]);
28764
- const bookingFlexibleBalanceDueDateRuleSchema$1 = z.union([z.object({
28765
- kind: z.literal("relative_to_start_date"),
28766
- daysBeforeStart: z.number().int().positive()
28767
- }), z.object({
28768
- kind: z.literal("fixed_calendar_date"),
28769
- dueAt: z.string().datetime()
28770
- })]);
28771
- const bookingFlexibleBalanceConfigSchema$1 = z.object({
28772
- upfrontAmountCents: z.number().int().min(0),
28773
- dueDateRule: bookingFlexibleBalanceDueDateRuleSchema$1,
28774
- depositRefundability: bookingDepositRefundPolicySchema$1
28775
- });
28776
- const blockBookingPaymentCollectionOptionSchema = z.union([
28777
- z.object({ kind: z.literal("upfront") }),
28778
- z.object({ kind: z.literal("deferred_manual") }),
28779
- z.object({
28780
- kind: z.literal("instalment_plan"),
28781
- plan: bookingInstalmentPlanSchema$1
28782
- }),
28783
- z.object({
28784
- kind: z.literal("flexible_balance"),
28785
- config: bookingFlexibleBalanceConfigSchema$1
28786
- })
28780
+ //#region ../core/src/booking-payment-schemas.ts
28781
+ const stripObject = (shape) => z.object(shape);
28782
+ const strictObject = (shape) => z.strictObject(shape);
28783
+ const depositRefundPolicySchema = z.enum(["refundable", "non_refundable"]);
28784
+ const intervalUnitSchema = z.enum([
28785
+ "day",
28786
+ "week",
28787
+ "month"
28787
28788
  ]);
28788
- const blockBookingPaymentTermsSchema = z.object({ allowedOptions: z.array(blockBookingPaymentCollectionOptionSchema).min(1) });
28789
+ const nonNegativeIntegerSchema = z.number().int().nonnegative();
28790
+ const positiveIntegerSchema = z.number().int().positive();
28791
+ function createInstalmentPlanSchema(object) {
28792
+ return z.discriminatedUnion("kind", [
28793
+ object({
28794
+ kind: z.literal("deposit_plus_one_remainder"),
28795
+ depositAmountCents: nonNegativeIntegerSchema,
28796
+ depositRefundability: depositRefundPolicySchema,
28797
+ remainderDueCount: positiveIntegerSchema,
28798
+ intervalUnit: intervalUnitSchema
28799
+ }),
28800
+ object({
28801
+ kind: z.literal("deposit_plus_scheduled_instalments"),
28802
+ depositAmountCents: nonNegativeIntegerSchema,
28803
+ depositRefundability: depositRefundPolicySchema,
28804
+ instalmentCount: positiveIntegerSchema,
28805
+ intervalCount: positiveIntegerSchema,
28806
+ intervalUnit: intervalUnitSchema
28807
+ }),
28808
+ object({
28809
+ kind: z.literal("equal_scheduled_instalments"),
28810
+ instalmentCount: positiveIntegerSchema,
28811
+ intervalCount: positiveIntegerSchema,
28812
+ intervalUnit: intervalUnitSchema
28813
+ })
28814
+ ]);
28815
+ }
28816
+ function createFlexibleBalanceSchemas(object) {
28817
+ const dueDateRule = z.discriminatedUnion("kind", [object({
28818
+ kind: z.literal("relative_to_start_date"),
28819
+ daysBeforeStart: positiveIntegerSchema
28820
+ }), object({
28821
+ kind: z.literal("fixed_calendar_date"),
28822
+ dueAt: z.string().datetime()
28823
+ })]);
28824
+ return {
28825
+ dueDateRule,
28826
+ config: object({
28827
+ upfrontAmountCents: nonNegativeIntegerSchema,
28828
+ dueDateRule,
28829
+ depositRefundability: depositRefundPolicySchema
28830
+ })
28831
+ };
28832
+ }
28833
+ const paymentOptionKindsMessages = {
28834
+ no_options: "Choose at least one way for customers to pay.",
28835
+ duplicate_kind: "Choose each payment option only once.",
28836
+ incompatible_collection_options: "Offer instalments or a deposit with the rest paid later, but not both."
28837
+ };
28838
+ function buildBookingPaymentOptionSchemas(object) {
28839
+ const instalmentPlan = createInstalmentPlanSchema(object);
28840
+ const flexibleBalance = createFlexibleBalanceSchemas(object);
28841
+ const paymentCollectionOption = z.discriminatedUnion("kind", [
28842
+ object({ kind: z.literal("upfront") }),
28843
+ object({ kind: z.literal("deferred_manual") }),
28844
+ object({
28845
+ kind: z.literal("instalment_plan"),
28846
+ plan: instalmentPlan
28847
+ }),
28848
+ object({
28849
+ kind: z.literal("flexible_balance"),
28850
+ config: flexibleBalance.config
28851
+ })
28852
+ ]);
28853
+ const paymentTerms = object({ allowedOptions: z.array(paymentCollectionOption) }).superRefine(({ allowedOptions }, ctx) => {
28854
+ const result = validateBookingPaymentOptionKinds(allowedOptions.map(({ kind }) => kind));
28855
+ if (!result.ok) ctx.addIssue({
28856
+ code: "custom",
28857
+ path: ["allowedOptions"],
28858
+ message: paymentOptionKindsMessages[result.error]
28859
+ });
28860
+ });
28861
+ const paymentOptionsChoice = z.discriminatedUnion("source", [z.strictObject({ source: z.literal("default") }), z.strictObject({
28862
+ source: z.literal("custom"),
28863
+ paymentTerms
28864
+ })]);
28865
+ return {
28866
+ depositRefundPolicy: depositRefundPolicySchema,
28867
+ instalmentPlan,
28868
+ flexibleBalanceDueDateRule: flexibleBalance.dueDateRule,
28869
+ flexibleBalanceConfig: flexibleBalance.config,
28870
+ paymentCollectionOption,
28871
+ paymentTerms,
28872
+ paymentOptionsChoice
28873
+ };
28874
+ }
28875
+ function createBookingPaymentOptionSchemas(mode) {
28876
+ return mode === "strict" ? buildBookingPaymentOptionSchemas(strictObject) : buildBookingPaymentOptionSchemas(stripObject);
28877
+ }
28878
+ const bookingPaymentOptionSchemas = createBookingPaymentOptionSchemas("strip");
28879
+ bookingPaymentOptionSchemas.depositRefundPolicy;
28880
+ bookingPaymentOptionSchemas.instalmentPlan;
28881
+ bookingPaymentOptionSchemas.flexibleBalanceDueDateRule;
28882
+ bookingPaymentOptionSchemas.flexibleBalanceConfig;
28883
+ bookingPaymentOptionSchemas.paymentCollectionOption;
28884
+ const bookingPaymentTermsSchema = bookingPaymentOptionSchemas.paymentTerms;
28885
+ bookingPaymentOptionSchemas.paymentOptionsChoice;
28886
+ //#endregion
28887
+ //#region ../blocks/src/system/blocks/shared/bookingPaymentTerms.ts
28888
+ const blockBookingPaymentTermsSchema = bookingPaymentTermsSchema;
28789
28889
  //#endregion
28790
28890
  //#region ../blocks/src/system/blocks/shared/bookingConsent.ts
28791
28891
  const blockBookingConsentSchema = z.object({
@@ -29031,7 +29131,6 @@ const publicEventBaseSchema = z.object({
29031
29131
  description: z.string().nullable(),
29032
29132
  content: z.object({ body: RichTextDocSchema.nullable().optional() }).optional(),
29033
29133
  presentation: z.object({
29034
- cardTitleOverride: z.string().nullable().optional(),
29035
29134
  summary: z.string().nullable().optional(),
29036
29135
  image: mediaSchema.nullable().optional()
29037
29136
  }).optional(),
@@ -29064,6 +29163,7 @@ const publicEventBaseSchema = z.object({
29064
29163
  "archived"
29065
29164
  ]).optional(),
29066
29165
  timeZone: z.string(),
29166
+ siteTimeZone: z.string().optional(),
29067
29167
  pricing: publicEventPricingSchema,
29068
29168
  paymentTerms: blockBookingPaymentTermsSchema,
29069
29169
  cancellationPolicy: z.object({ refunds: z.object({
@@ -29755,6 +29855,13 @@ const STRUCTURED_KEYS = /* @__PURE__ */ new Set([
29755
29855
  "domainOperationProvider",
29756
29856
  "domainOperationError",
29757
29857
  "domainOperationMetadata",
29858
+ "previewDecision",
29859
+ "previewOutcome",
29860
+ "previewTokenTtlBucket",
29861
+ "previewRefreshCookiePresent",
29862
+ "previewDashboardStatus",
29863
+ "previewProviderResult",
29864
+ "previewUpstreamStatus",
29758
29865
  "durationMs",
29759
29866
  "duration",
29760
29867
  "status",
@@ -33027,6 +33134,7 @@ const bookingMailingListContextSchema = z.unknown().transform((value) => {
33027
33134
  return parsed.ok ? parsed.value : void 0;
33028
33135
  });
33029
33136
  const bookingSourceSchema = z.object({
33137
+ demoEmailSuppressed: z.boolean().optional(),
33030
33138
  mailingList: bookingMailingListContextSchema.optional(),
33031
33139
  siteName: z.string().optional(),
33032
33140
  siteId: z.string().optional(),
@@ -33057,6 +33165,7 @@ const bookingDisplaySchema = z.object({
33057
33165
  message: z.string().nullable()
33058
33166
  });
33059
33167
  const bookingHydrationSchema = z.object({
33168
+ demoEmailSuppressed: z.boolean().optional(),
33060
33169
  mailingList: bookingMailingListContextSchema.optional(),
33061
33170
  siteName: z.string().optional(),
33062
33171
  formId: z.string().nullable(),
@@ -33104,6 +33213,7 @@ const bookingFormBlockRuntime = defineClientOwnedBlockRuntime({
33104
33213
  return {
33105
33214
  display: buildBookingFormDisplay(source, form),
33106
33215
  hydration: {
33216
+ demoEmailSuppressed: source.demoEmailSuppressed,
33107
33217
  mailingList: source.mailingList,
33108
33218
  siteName: source.siteName,
33109
33219
  formId: form?.id ?? source.formId ?? null,
@@ -33940,6 +34050,44 @@ function resolveEventCta(event, buttonText) {
33940
34050
  * timestamps become strings or date buckets. Calendar-grid primitives are
33941
34051
  * re-exported from @riverbankcms/calendar so block code has one import.
33942
34052
  */
34053
+ /**
34054
+ * The English locale a site's public dates are written in, read from the
34055
+ * site's own time zone (Will, 2026-09-26: "date style from site time zone").
34056
+ *
34057
+ * Sites don't store a locale, and every public word around a date is English,
34058
+ * so the only open question is which English conventions to follow: day or
34059
+ * month first, and a 24 or 12-hour clock. The site's time zone is the one
34060
+ * fact every site carries about where it is. It is the site's, never an
34061
+ * event's: a venue left at UTC must not turn a UK site's dates American.
34062
+ * Anywhere this can't place (UTC, the Americas, Asia) keeps US English, which
34063
+ * is what these helpers wrote before sites were placed at all.
34064
+ */
34065
+ function eventDateLocale(siteTimeZone) {
34066
+ if (!siteTimeZone) return "en-US";
34067
+ if (siteTimeZone === "Europe/Dublin") return "en-IE";
34068
+ if (siteTimeZone.startsWith("Europe/")) return "en-GB";
34069
+ if (siteTimeZone.startsWith("Australia/")) return "en-AU";
34070
+ if (siteTimeZone === "Pacific/Auckland" || siteTimeZone === "Pacific/Chatham") return "en-NZ";
34071
+ return "en-US";
34072
+ }
34073
+ /**
34074
+ * Formatting options for an event's dates: the times in the event's own zone,
34075
+ * written in its site's locale. A record from an older server that doesn't
34076
+ * name the site's zone falls back to the event's.
34077
+ */
34078
+ function eventDateOptions(place) {
34079
+ return {
34080
+ timeZone: place.timeZone ?? null,
34081
+ locale: eventDateLocale(place.siteTimeZone ?? place.timeZone)
34082
+ };
34083
+ }
34084
+ /**
34085
+ * Start and end times as cards write them, in the site's locale:
34086
+ * "10:00 to 16:00" in the UK, "10:00 AM to 4:00 PM" in the US.
34087
+ */
34088
+ function formatEventTimeRange$1(times, options) {
34089
+ return `${formatTime(times.startsAt, options)} to ${formatTime(times.endsAt, options)}`;
34090
+ }
33943
34091
  /** Use the event timezone when present, otherwise the calendar/site timezone. */
33944
34092
  function resolveEventTimeZone(event, calendarTimeZone) {
33945
34093
  return event.timeZone || calendarTimeZone;
@@ -33961,18 +34109,25 @@ function formatDate(isoTimestamp, options) {
33961
34109
  });
33962
34110
  }
33963
34111
  /**
33964
- * Format time for display.
33965
- * Returns: "10:00 AM"
34112
+ * Whether the locale reads a 24-hour clock, where hours are written with two
34113
+ * digits ("09:00"), as the dashboard writes them.
34114
+ */
34115
+ function usesTwentyFourHourClock(locale) {
34116
+ return new Intl.DateTimeFormat(locale, { hour: "numeric" }).resolvedOptions().hour12 === false;
34117
+ }
34118
+ /**
34119
+ * Format time for display, on the locale's own clock.
34120
+ * Returns: "9:00 AM" (en-US) or "09:00" (en-GB)
33966
34121
  */
33967
34122
  function formatTime(isoTimestamp, options) {
34123
+ const locale = options?.locale ?? "en-US";
33968
34124
  return formatBookingTime(toScheduledBookingDateTime({
33969
34125
  startsAt: isoTimestamp,
33970
34126
  timeZone: toBookingTimeZone(options?.timeZone ?? "UTC"),
33971
- locale: options?.locale ?? "en-US"
34127
+ locale
33972
34128
  }), {
33973
- hour: "numeric",
33974
- minute: "2-digit",
33975
- hour12: true
34129
+ hour: usesTwentyFourHourClock(locale) ? "2-digit" : "numeric",
34130
+ minute: "2-digit"
33976
34131
  });
33977
34132
  }
33978
34133
  function formatEventDateParts(args) {
@@ -34004,7 +34159,7 @@ function formatEventCompactDateRail(isoTimestamp, options) {
34004
34159
  locale: options?.locale ?? "en-US"
34005
34160
  });
34006
34161
  const weekday = formatBookingDate(dateTime, { weekday: "short" }).toLocaleUpperCase(options?.locale ?? "en-US");
34007
- const month = formatBookingDate(dateTime, { month: "short" }).toLocaleUpperCase(options?.locale ?? "en-US");
34162
+ const month = formatBookingDate(dateTime, { month: "short" }).slice(0, 3).toLocaleUpperCase(options?.locale ?? "en-US");
34008
34163
  return {
34009
34164
  weekday,
34010
34165
  day: formatBookingDate(dateTime, { day: "numeric" }),
@@ -34024,7 +34179,7 @@ function formatEventCompactDateRail(isoTimestamp, options) {
34024
34179
  * keep the fact panel on the same date and timezone rules as event rows.
34025
34180
  */
34026
34181
  function formatEventNextDateFact(event) {
34027
- const rail = formatEventCompactDateRail(event.startsAt, { timeZone: event.timeZone });
34182
+ const rail = formatEventCompactDateRail(event.startsAt, eventDateOptions(event));
34028
34183
  return {
34029
34184
  dateTime: event.startsAt,
34030
34185
  value: `${rail.weekday} ${rail.day} ${rail.month}`,
@@ -34871,6 +35026,13 @@ function CalendarIcon({ className, size = 16, strokeWidth = 2 }) {
34871
35026
  }
34872
35027
  //#endregion
34873
35028
  //#region ../blocks/src/system/runtime/nodes/events/shared/EventCard.tsx
35029
+ /** The category's badge, when the event has a category. */
35030
+ function eventCardCategoryBadge(category) {
35031
+ return category ? {
35032
+ label: category.name,
35033
+ style: getCategoryBadgeStyle(category.color ?? null)
35034
+ } : null;
35035
+ }
34874
35036
  /**
34875
35037
  * EventCard Component
34876
35038
  *
@@ -34879,24 +35041,19 @@ function CalendarIcon({ className, size = 16, strokeWidth = 2 }) {
34879
35041
  *
34880
35042
  * This component is server-safe (uses no client APIs like Intl).
34881
35043
  */
34882
- const EventCard = ({ event, cardRole = "default", buttonVariant = "primary", buttonText, showVenue = true, showMap = true, mapSlot, allowMap = true, showCapacity = true, showImage = true, showCategory = true, showSummary = true, orientation = "vertical", presentation, headingLevel }) => {
35044
+ const EventCard = ({ event, cardRole = "default", buttonVariant = "primary", buttonText, showVenue = true, showMap = true, mapSlot, allowMap = true, showCapacity = true, showImage = true, showCategory = true, showSummary = true, orientation = "vertical", presentation, headingLevel, imageResolveContext }) => {
34883
35045
  const { presentation: cardPresentation, presentationClass, headingLevel: cardHeadingLevel } = resolveEventCardOptions({
34884
35046
  presentation,
34885
35047
  headingLevel
34886
35048
  });
34887
- const timeZone = event.timeZone ?? null;
34888
- const formattedDate = formatDate(event.startsAt, { timeZone });
34889
- const formattedTime = `${formatTime(event.startsAt, { timeZone })} - ${formatTime(event.endsAt, { timeZone })}`;
35049
+ const { formattedDate, formattedTime } = formatEventCardWhen(event);
34890
35050
  const cta = resolveEventCta(event, buttonText);
34891
35051
  const cardClass = boxStyleClassNames({ role: cardRole }, { baseClass: "event-card" });
34892
35052
  const title = event.title;
34893
35053
  const summary = event.presentation?.summary ?? event.description;
34894
35054
  const image = event.presentation?.image ?? null;
34895
35055
  const category = event.eventCategory;
34896
- const categoryBadge = category && showCategory ? {
34897
- label: category.name,
34898
- style: getCategoryBadgeStyle(category.color ?? null)
34899
- } : null;
35056
+ const categoryBadge = showCategory ? eventCardCategoryBadge(category) : null;
34900
35057
  const hasImage = Boolean(showImage && image);
34901
35058
  const dateFact = resolveEventCardDateFact({
34902
35059
  event,
@@ -34915,7 +35072,8 @@ const EventCard = ({ event, cardRole = "default", buttonVariant = "primary", but
34915
35072
  categoryId: category?.id,
34916
35073
  dateFact,
34917
35074
  hasImage,
34918
- image
35075
+ image,
35076
+ imageResolveContext
34919
35077
  }), /* @__PURE__ */ jsx(EventCardContent, {
34920
35078
  allowMap,
34921
35079
  buttonVariant,
@@ -34963,7 +35121,8 @@ function EventCardMedia(props) {
34963
35121
  /* @__PURE__ */ jsx(MediaNodeServer, {
34964
35122
  value: props.image,
34965
35123
  className: "event-card-image",
34966
- size: ImagePresets.card
35124
+ size: ImagePresets.card,
35125
+ imageResolveContext: props.imageResolveContext
34967
35126
  }),
34968
35127
  props.categoryBadge && /* @__PURE__ */ jsx("span", {
34969
35128
  className: "event-category-badge event-category-badge--overlay",
@@ -35078,6 +35237,17 @@ function resolveEventCardOptions(props) {
35078
35237
  headingLevel: props.headingLevel ?? 3
35079
35238
  };
35080
35239
  }
35240
+ /**
35241
+ * The card's date and times, written the way the event's place writes them
35242
+ * ("Friday, 16 October 2026" and "10:00 to 16:00" in the UK).
35243
+ */
35244
+ function formatEventCardWhen(event) {
35245
+ const options = eventDateOptions(event);
35246
+ return {
35247
+ formattedDate: formatDate(event.startsAt, options),
35248
+ formattedTime: formatEventTimeRange$1(event, options)
35249
+ };
35250
+ }
35081
35251
  function resolveEventCardDateFact(props) {
35082
35252
  if (!props.showImage || props.image || props.presentation !== "catalogue") return null;
35083
35253
  return formatEventNextDateFact(props.event);
@@ -36504,6 +36674,34 @@ function buildEventCombinedInteractiveIslandProps(props) {
36504
36674
  });
36505
36675
  }
36506
36676
  //#endregion
36677
+ //#region ../blocks/src/system/runtime/nodes/events/shared/eventCardPresentations.ts
36678
+ /** A booking page's catalogue card: one per series, "See dates" for dated events. */
36679
+ function catalogueEventCardProps(event, buttonVariant = "primary") {
36680
+ return {
36681
+ presentation: "catalogue",
36682
+ headingLevel: 4,
36683
+ buttonVariant,
36684
+ buttonText: event.bookingScope === "single_occurrence" ? "See dates" : void 0,
36685
+ showMap: false,
36686
+ allowMap: false,
36687
+ showCategory: false,
36688
+ orientation: "vertical"
36689
+ };
36690
+ }
36691
+ /** An events listing's card, from the listing's display settings. */
36692
+ function listingEventCardProps(display) {
36693
+ return {
36694
+ cardRole: display.cardRole,
36695
+ buttonVariant: display.buttonVariant,
36696
+ buttonText: display.buttonText,
36697
+ showVenue: display.showVenue,
36698
+ showMap: display.showMap,
36699
+ allowMap: false,
36700
+ showCapacity: display.showCapacity,
36701
+ orientation: display.orientation
36702
+ };
36703
+ }
36704
+ //#endregion
36507
36705
  //#region ../blocks/src/system/runtime/nodes/events/shared/renderEventListItem.tsx
36508
36706
  /**
36509
36707
  * Shared SSR render function for event list items.
@@ -36520,14 +36718,7 @@ function renderEventListItem(event, display) {
36520
36718
  }, event.occurrenceId || event.id);
36521
36719
  return /* @__PURE__ */ jsx(EventCard, {
36522
36720
  event,
36523
- cardRole: display.cardRole,
36524
- buttonVariant: display.buttonVariant,
36525
- buttonText: display.buttonText,
36526
- showVenue: display.showVenue,
36527
- showMap: display.showMap,
36528
- allowMap: false,
36529
- showCapacity: display.showCapacity,
36530
- orientation: display.orientation
36721
+ ...listingEventCardProps(display)
36531
36722
  }, event.occurrenceId || event.id);
36532
36723
  }
36533
36724
  //#endregion
@@ -36933,14 +37124,7 @@ function OfferingsCatalogue(props) {
36933
37124
  style: { gridTemplateColumns: "repeat(auto-fill, minmax(min(100%, 18rem), 1fr))" },
36934
37125
  children: events.map((event) => /* @__PURE__ */ jsx(EventCard, {
36935
37126
  event,
36936
- presentation: "catalogue",
36937
- headingLevel: 4,
36938
- buttonVariant: props.buttonVariant ?? "primary",
36939
- buttonText: event.bookingScope === "single_occurrence" ? "See dates" : void 0,
36940
- showMap: false,
36941
- allowMap: false,
36942
- showCategory: false,
36943
- orientation: "vertical"
37127
+ ...catalogueEventCardProps(event, props.buttonVariant ?? "primary")
36944
37128
  }, event.seriesId))
36945
37129
  })]
36946
37130
  }, group.sourceKey))
@@ -37228,45 +37412,73 @@ function FeaturedOfferingSummary({ item }) {
37228
37412
  }
37229
37413
  function featuredSummaryDetails(item) {
37230
37414
  switch (item.kind) {
37231
- case "event": return formatFeaturedSummary(deriveEventScheduleSummary(item.event), item.event.venue?.name ?? null);
37415
+ case "event": return formatFeaturedSummary(deriveEventScheduleSummary(item.event), {
37416
+ venue: item.event.venue?.name ?? null,
37417
+ siteTimeZone: item.event.siteTimeZone
37418
+ });
37232
37419
  case "run": {
37233
37420
  const schedule = derivePreviewRunSchedule(item.run.run.sessions);
37234
- return schedule.kind === "scheduled" ? formatFeaturedSummary(schedule.summary, item.run.representative.venue?.name ?? null) : null;
37421
+ return schedule.kind === "scheduled" ? formatFeaturedSummary(schedule.summary, {
37422
+ venue: item.run.representative.venue?.name ?? null,
37423
+ siteTimeZone: item.run.representative.siteTimeZone
37424
+ }) : null;
37235
37425
  }
37236
37426
  default: return assertNever$4(item, "Unhandled offerings preview item");
37237
37427
  }
37238
37428
  }
37239
- function formatFeaturedSummary(summary, venue) {
37429
+ function formatFeaturedSummary(summary, place) {
37240
37430
  switch (summary.kind) {
37241
- case "single-occurrence": return detailsFromOccurrences(summary.occurrence, null, venue, null, null);
37242
- case "multi-day-span": return detailsFromOccurrences(summary.occurrence, summary.occurrence, venue, null, null, true);
37243
- case "fixed-recurring-run": return detailsFromOccurrences(summary.first, summary.last, venue, summary.recurrenceLabel, null);
37244
- case "irregular-multi-session-run": return detailsFromOccurrences(summary.first, summary.last, venue, null, `${summary.sessionCount} dates`);
37431
+ case "single-occurrence": return detailsFromOccurrences({
37432
+ first: summary.occurrence,
37433
+ last: null,
37434
+ place
37435
+ });
37436
+ case "multi-day-span": return detailsFromOccurrences({
37437
+ first: summary.occurrence,
37438
+ last: summary.occurrence,
37439
+ place,
37440
+ spanUsesEndDate: true
37441
+ });
37442
+ case "fixed-recurring-run": return detailsFromOccurrences({
37443
+ first: summary.first,
37444
+ last: summary.last,
37445
+ place,
37446
+ recurrence: summary.recurrenceLabel
37447
+ });
37448
+ case "irregular-multi-session-run": return detailsFromOccurrences({
37449
+ first: summary.first,
37450
+ last: summary.last,
37451
+ place,
37452
+ sessionCount: `${summary.sessionCount} dates`
37453
+ });
37245
37454
  default: return assertNever$4(summary, "Unhandled offerings preview schedule summary");
37246
37455
  }
37247
37456
  }
37248
- function detailsFromOccurrences(first, last, venue, recurrence, sessionCount, spanUsesEndDate = false) {
37249
- const endDateTime = spanUsesEndDate ? first.endsAt : last?.startsAt ?? first.startsAt;
37457
+ function detailsFromOccurrences(input) {
37458
+ const { first, last, place } = input;
37459
+ const endDateTime = input.spanUsesEndDate ? first.endsAt : last?.startsAt ?? first.startsAt;
37460
+ const options = eventDateOptions({
37461
+ timeZone: first.timeZone,
37462
+ siteTimeZone: place.siteTimeZone
37463
+ });
37464
+ const summaryDate = (isoTimestamp, timeZone) => formatSummaryDate(isoTimestamp, {
37465
+ timeZone,
37466
+ locale: options.locale
37467
+ });
37250
37468
  return {
37251
- startDate: formatSummaryDate(first.startsAt, first.timeZone),
37469
+ startDate: summaryDate(first.startsAt, first.timeZone),
37252
37470
  startDateTime: first.startsAt,
37253
- endDate: last ? formatSummaryDate(endDateTime, last.timeZone) : null,
37471
+ endDate: last ? summaryDate(endDateTime, last.timeZone) : null,
37254
37472
  endDateTime,
37255
- timeRange: `${formatTime(first.startsAt, {
37256
- timeZone: first.timeZone,
37257
- locale: "en-GB"
37258
- })} – ${formatTime(first.endsAt, {
37259
- timeZone: first.timeZone,
37260
- locale: "en-GB"
37261
- })}`,
37262
- recurrence,
37263
- sessionCount,
37264
- venue
37265
- };
37266
- }
37267
- function formatSummaryDate(isoTimestamp, timeZone) {
37268
- return new Intl.DateTimeFormat("en-GB", {
37269
- timeZone,
37473
+ timeRange: formatEventTimeRange$1(first, options),
37474
+ recurrence: input.recurrence ?? null,
37475
+ sessionCount: input.sessionCount ?? null,
37476
+ venue: place.venue
37477
+ };
37478
+ }
37479
+ function formatSummaryDate(isoTimestamp, options) {
37480
+ return new Intl.DateTimeFormat(options.locale, {
37481
+ timeZone: options.timeZone,
37270
37482
  weekday: "long",
37271
37483
  day: "numeric",
37272
37484
  month: "long",
@@ -37313,9 +37525,12 @@ function WholeSeriesRunCompactRow({ group, path, now }) {
37313
37525
  path
37314
37526
  });
37315
37527
  const { sessionCount: sessionsCount, firstSession } = schedule;
37316
- const timeZone = firstSession.timeZone;
37317
- const dateRail = formatEventCompactDateRail(firstSession.startsAt, { timeZone });
37318
- const timeRange = `${formatTime(firstSession.startsAt, { timeZone })} - ${formatTime(firstSession.endsAt, { timeZone })}`;
37528
+ const options = eventDateOptions({
37529
+ timeZone: firstSession.timeZone,
37530
+ siteTimeZone: group.representative.siteTimeZone
37531
+ });
37532
+ const dateRail = formatEventCompactDateRail(firstSession.startsAt, options);
37533
+ const timeRange = formatEventTimeRange$1(firstSession, options);
37319
37534
  const price = formatEventPriceDisplay(group.representative.pricing);
37320
37535
  const statusLabel = resolveWholeSeriesBookingPhase(group.run, now).kind === "open" ? null : "Registration closed";
37321
37536
  return /* @__PURE__ */ jsxs("article", {
@@ -37395,9 +37610,12 @@ function WholeSeriesRunFeatureCard({ group, now, path, buttonVariant, buttonText
37395
37610
  path
37396
37611
  });
37397
37612
  const { firstSession } = schedule;
37398
- const timeZone = firstSession.timeZone;
37399
- const formattedDate = formatEventCompactDateRail(firstSession.startsAt, { timeZone }).label;
37400
- const timeRange = `${formatTime(firstSession.startsAt, { timeZone })} - ${formatTime(firstSession.endsAt, { timeZone })}`;
37613
+ const options = eventDateOptions({
37614
+ timeZone: firstSession.timeZone,
37615
+ siteTimeZone: group.representative.siteTimeZone
37616
+ });
37617
+ const formattedDate = formatEventCompactDateRail(firstSession.startsAt, options).label;
37618
+ const timeRange = formatEventTimeRange$1(firstSession, options);
37401
37619
  const price = formatEventPriceDisplay(group.representative.pricing);
37402
37620
  const statusLabel = resolveWholeSeriesBookingPhase(group.run, now).kind === "open" ? null : "Registration closed";
37403
37621
  const description = group.representative.description;
@@ -37901,7 +38119,7 @@ const publicPassProductCollectionSchema = z.object({ passes: z.array(publicPassP
37901
38119
  /**
37902
38120
  * Public membership product for shop display
37903
38121
  */
37904
- const publicMembershipProductSchema = z.object({
38122
+ const publicMembershipProductFields = {
37905
38123
  id: z.string(),
37906
38124
  name: z.string(),
37907
38125
  description: z.string().nullable(),
@@ -37910,7 +38128,16 @@ const publicMembershipProductSchema = z.object({
37910
38128
  billingInterval: z.enum(["month", "year"]),
37911
38129
  eligibleCategoryIds: z.array(z.string()),
37912
38130
  eligibleCategoryNames: z.array(z.string())
38131
+ };
38132
+ const purchasablePublicMembershipProductSchema = z.object({
38133
+ ...publicMembershipProductFields,
38134
+ purchaseAvailability: z.literal("purchasable")
37913
38135
  });
38136
+ const publicMembershipProductSchema = z.discriminatedUnion("purchaseAvailability", [purchasablePublicMembershipProductSchema, z.object({
38137
+ ...publicMembershipProductFields,
38138
+ purchaseAvailability: z.literal("display_only"),
38139
+ unavailabilityReason: z.literal("online_payments_unavailable")
38140
+ })]);
37914
38141
  const publicMembershipProductCollectionSchema = z.object({ memberships: z.array(publicMembershipProductSchema) });
37915
38142
  //#endregion
37916
38143
  //#region ../blocks/src/system/blocks/products/shared.ts
@@ -38151,7 +38378,7 @@ function buildPassesMembershipsDisplay(options) {
38151
38378
  product: pass
38152
38379
  } : {
38153
38380
  kind: "unavailable",
38154
- label: "Online purchasing coming soon."
38381
+ label: "Online purchasing is unavailable."
38155
38382
  }
38156
38383
  };
38157
38384
  });
@@ -38161,7 +38388,14 @@ function buildPassesMembershipsDisplay(options) {
38161
38388
  description: options.showDescriptions ? membership.description : null,
38162
38389
  priceLabel: formatCommercePrice(membership.price, membership.currency),
38163
38390
  intervalLabel: formatInterval(membership.billingInterval),
38164
- actionLabel: options.membershipActionLabel
38391
+ action: membership.purchaseAvailability === "purchasable" ? {
38392
+ kind: "purchase",
38393
+ label: options.membershipActionLabel,
38394
+ product: membership
38395
+ } : {
38396
+ kind: "unavailable",
38397
+ label: "Online purchasing is unavailable."
38398
+ }
38165
38399
  }));
38166
38400
  return {
38167
38401
  kind: "passes-memberships",
@@ -38313,6 +38547,7 @@ const shopSourceSchema = z.object({
38313
38547
  memberships: z.array(publicMembershipProductSchema).nullable().optional(),
38314
38548
  products: z.array(publicProductSchema).nullable().optional(),
38315
38549
  siteId: z.string().optional(),
38550
+ demoEmailSuppressed: z.boolean().optional(),
38316
38551
  apiBaseUrl: z.string().optional(),
38317
38552
  readAuthority: browserReadAuthoritySchema.optional(),
38318
38553
  stage: previewStageSchema.optional()
@@ -38380,7 +38615,14 @@ const membershipCardDisplaySchema = z.object({
38380
38615
  description: z.string().nullable(),
38381
38616
  priceLabel: z.string(),
38382
38617
  intervalLabel: z.string(),
38383
- actionLabel: z.string()
38618
+ action: z.discriminatedUnion("kind", [z.object({
38619
+ kind: z.literal("purchase"),
38620
+ label: z.string(),
38621
+ product: purchasablePublicMembershipProductSchema
38622
+ }), z.object({
38623
+ kind: z.literal("unavailable"),
38624
+ label: z.string()
38625
+ })])
38384
38626
  });
38385
38627
  const passesMembershipsDisplaySchema = z.object({
38386
38628
  kind: z.literal("passes-memberships"),
@@ -38432,7 +38674,8 @@ const checkoutDisplaySchema = z.object({
38432
38674
  const passesMembershipsHydrationSchema = z.object({
38433
38675
  memberships: z.array(publicMembershipProductSchema),
38434
38676
  passPurchaseMode: z.enum(["add_to_cart", "buy_now"]),
38435
- buttonVariant: blockButtonRoleSchema
38677
+ buttonVariant: blockButtonRoleSchema,
38678
+ demoEmailSuppressed: z.boolean().optional()
38436
38679
  });
38437
38680
  const productListHydrationSchema = z.object({
38438
38681
  products: z.array(publicProductSchema),
@@ -38454,7 +38697,8 @@ const cartHydrationSchema = z.object({
38454
38697
  });
38455
38698
  const checkoutHydrationSchema = z.object({
38456
38699
  emptyStateText: z.string(),
38457
- submitButtonText: z.string()
38700
+ submitButtonText: z.string(),
38701
+ demoEmailSuppressed: z.boolean().optional()
38458
38702
  });
38459
38703
  const passesMembershipsRenderSchema = z.object({
38460
38704
  display: passesMembershipsDisplaySchema,
@@ -38513,7 +38757,8 @@ const shopBlockRuntime = defineProgressiveBlockRuntime({
38513
38757
  hydration: {
38514
38758
  memberships: source.showMemberships === false ? [] : source.memberships ?? [],
38515
38759
  passPurchaseMode,
38516
- buttonVariant: source.buttonVariant ?? "primary"
38760
+ buttonVariant: source.buttonVariant ?? "primary",
38761
+ demoEmailSuppressed: source.demoEmailSuppressed
38517
38762
  }
38518
38763
  };
38519
38764
  }
@@ -38606,7 +38851,8 @@ const checkoutBlockRuntime = defineClientOwnedBlockRuntime({
38606
38851
  }),
38607
38852
  hydration: {
38608
38853
  emptyStateText: source.emptyStateText ?? "Add something to your cart to continue.",
38609
- submitButtonText: source.submitButtonText ?? "Checkout"
38854
+ submitButtonText: source.submitButtonText ?? "Checkout",
38855
+ demoEmailSuppressed: source.demoEmailSuppressed
38610
38856
  }
38611
38857
  })
38612
38858
  });
@@ -38847,6 +39093,10 @@ const checkoutBlockDefinition = {
38847
39093
  baseClass: "",
38848
39094
  spacing: "spacious",
38849
39095
  children: sectionContainer([checkout(withApiBindings({
39096
+ demoEmailSuppressed: { $bind: {
39097
+ from: "$root.demoEmailSuppressed",
39098
+ fallback: false
39099
+ } },
38850
39100
  readAuthority: { $bind: { from: "$root.readAuthority" } },
38851
39101
  mode: "checkout",
38852
39102
  heading: { $bind: {
@@ -39259,6 +39509,7 @@ const EVENT_REGISTRATION_SHELL_STEP_LABELS = [
39259
39509
  ];
39260
39510
  const eventRegistrationPublicEventSchema = z.preprocess(normalizeEventRegistrationEventInput, publicEventSchema);
39261
39511
  const eventRegistrationHydrationSchemaShape = {
39512
+ demoEmailSuppressed: z.boolean().optional(),
39262
39513
  occurrenceContext: occurrenceContextSchema.optional(),
39263
39514
  subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
39264
39515
  maxTickets: z.string().optional(),
@@ -39439,6 +39690,7 @@ const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
39439
39690
  ...eventSource,
39440
39691
  events: [...scopedSourceEvents]
39441
39692
  } : eventSource,
39693
+ demoEmailSuppressed: source.demoEmailSuppressed,
39442
39694
  maxTickets: source.maxTickets ?? void 0,
39443
39695
  showVenue: source.showVenue,
39444
39696
  showCapacity: source.showCapacity,
@@ -39582,8 +39834,8 @@ const eventRegistrationBlockDefinition = {
39582
39834
  description: "Message shown after successful registration",
39583
39835
  required: false,
39584
39836
  multiline: true,
39585
- defaultValue: "Thank you for registering! Check your email for confirmation details.",
39586
- maxLength: 500
39837
+ maxLength: 500,
39838
+ ui: { placeholder: "Thank you for registering! Check your email for confirmation details." }
39587
39839
  },
39588
39840
  {
39589
39841
  id: "buttonText",
@@ -39604,6 +39856,10 @@ const eventRegistrationBlockDefinition = {
39604
39856
  text({ as: "h2" }, bind("content.heading"), when("content.heading")),
39605
39857
  richText({ className: "rb-prose rb-max-w-none" }, bind("content.description"), when("content.description")),
39606
39858
  eventRegistration(withApiBindings({
39859
+ demoEmailSuppressed: { $bind: {
39860
+ from: "$root.demoEmailSuppressed",
39861
+ fallback: false
39862
+ } },
39607
39863
  readAuthority: { $bind: { from: "$root.readAuthority" } },
39608
39864
  occurrenceContext: { $bind: { from: "$root.occurrenceContext" } },
39609
39865
  subject: { $bind: { from: "$root.subject" } },
@@ -42644,6 +42900,10 @@ const shopBlockDefinition = {
42644
42900
  spacing: "spacious",
42645
42901
  children: sectionContainer([shop(withApiBindings({
42646
42902
  readAuthority: { $bind: { from: "$root.readAuthority" } },
42903
+ demoEmailSuppressed: { $bind: {
42904
+ from: "$root.demoEmailSuppressed",
42905
+ fallback: false
42906
+ } },
42647
42907
  mode: "passes-memberships",
42648
42908
  showPasses: { $bind: {
42649
42909
  from: "content.showPasses",
@@ -43134,11 +43394,12 @@ function CartSSR({ blockId, siteId, apiBaseUrl, stage, children, ...rest }) {
43134
43394
  }
43135
43395
  //#endregion
43136
43396
  //#region ../blocks/src/system/runtime/nodes/checkout.server.tsx
43137
- function CheckoutSSR({ blockId, siteId, apiBaseUrl, stage, children, ...rest }) {
43397
+ function CheckoutSSR({ blockId, siteId, apiBaseUrl, stage, demoEmailSuppressed, children, ...rest }) {
43138
43398
  const islandProps = buildCheckoutInteractiveIslandProps({
43139
43399
  siteId,
43140
43400
  apiBaseUrl,
43141
43401
  stage,
43402
+ demoEmailSuppressed,
43142
43403
  ...rest
43143
43404
  });
43144
43405
  return /* @__PURE__ */ jsxs("div", {
@@ -44956,11 +45217,11 @@ function ShopSSR({ blockId, siteId, apiBaseUrl, stage, children, checkoutEndpoin
44956
45217
  }, pass.id)),
44957
45218
  membershipCards: render.display.memberships.map((membership) => /* @__PURE__ */ jsx(MembershipCardView, {
44958
45219
  display: membership,
44959
- action: /* @__PURE__ */ jsx(ThemedButton, {
45220
+ action: membership.action.kind === "unavailable" ? /* @__PURE__ */ jsx(PassPurchaseUnavailable, { label: membership.action.label }) : /* @__PURE__ */ jsx(ThemedButton, {
44960
45221
  type: "button",
44961
45222
  variant: render.hydration.buttonVariant,
44962
45223
  size: "md",
44963
- label: membership.actionLabel,
45224
+ label: membership.action.label,
44964
45225
  disabled: true,
44965
45226
  "aria-disabled": "true"
44966
45227
  })
@@ -49345,6 +49606,7 @@ function buildPageRendererRootRuntime(dataContext) {
49345
49606
  const { siteId = null, siteName, pageId = null, pathname = null, bookingTimeZone, previewStage = "published", apiBaseUrl = null, portalToken = null, readAuthority, bookingOfferingPresets = [], appointmentServicePathPrefix = null, mailingList = { tag: "not_configured" }, eventRegistrationOverlayEnabled = false, loaderFailures = {} } = dataContext ?? {};
49346
49607
  return {
49347
49608
  siteId,
49609
+ demoEmailSuppressed: resolveDemoEmailSuppression(dataContext),
49348
49610
  siteName,
49349
49611
  pageId,
49350
49612
  pathname,
@@ -49360,6 +49622,9 @@ function buildPageRendererRootRuntime(dataContext) {
49360
49622
  loaderFailures
49361
49623
  };
49362
49624
  }
49625
+ function resolveDemoEmailSuppression(dataContext) {
49626
+ return dataContext?.demoEmailSuppressed === true;
49627
+ }
49363
49628
  //#endregion
49364
49629
  //#region ../blocks/src/pageRenderAudience.tsx
49365
49630
  /**
@@ -53881,6 +54146,10 @@ const bookingDescription = richText({}, bind("content.description"), when("conte
53881
54146
  * that hydration never rewrites.
53882
54147
  */
53883
54148
  const bookingWizard = bookingForm(withApiBindings({
54149
+ demoEmailSuppressed: { $bind: {
54150
+ from: "$root.demoEmailSuppressed",
54151
+ fallback: false
54152
+ } },
53884
54153
  portalToken: { $bind: {
53885
54154
  from: "$root.portalToken",
53886
54155
  fallback: null
@@ -59195,15 +59464,17 @@ function planNewsletterBlockSubmission(placement) {
59195
59464
  sourceRef
59196
59465
  } : { tag: "unavailable" };
59197
59466
  }
59198
- if (placement.publishedPlacement && "kind" in placement.publishedPlacement) return { tag: "unpublished-settings" };
59199
- if (placement.publishedPlacement) return planNewsletterPreviewSubmission({
59200
- blockId: placement.blockId,
59201
- publishedContentId: placement.publishedPlacement.id,
59202
- renderedContent: placement.renderedContent,
59203
- publishedContent: placement.publishedPlacement.content
59204
- });
59205
- if (placement.stage === "preview") return { tag: "unpublished-form" };
59206
- return { tag: "unavailable" };
59467
+ const published = placement.publishedPlacement;
59468
+ if (published === null) return placement.stage === "preview" ? { tag: "unpublished-form" } : { tag: "unavailable" };
59469
+ switch (published.kind) {
59470
+ case "incomplete": return { tag: "unpublished-settings" };
59471
+ case "published": return planNewsletterPreviewSubmission({
59472
+ blockId: placement.blockId,
59473
+ publishedContentId: published.id,
59474
+ renderedContent: placement.renderedContent,
59475
+ publishedContent: published.content
59476
+ });
59477
+ }
59207
59478
  }
59208
59479
  /** Decide whether the visible draft can safely cite the published placement. */
59209
59480
  function planNewsletterPreviewSubmission(placement) {
@@ -59450,19 +59721,6 @@ function createBlockErrorBoundary() {
59450
59721
  const BlockErrorBoundary = createBlockErrorBoundary();
59451
59722
  //#endregion
59452
59723
  //#region ../blocks/src/pageRenderAdmission.ts
59453
- /** Pair a published version with the content it authorises at the render boundary. */
59454
- function readPublishedBlockPlacement(id, content) {
59455
- if (id == null && content == null) return null;
59456
- if (id == null || content == null) return {
59457
- kind: "incomplete",
59458
- id: id ?? null,
59459
- content: content ?? null
59460
- };
59461
- return {
59462
- id,
59463
- content
59464
- };
59465
- }
59466
59724
  function toPresentationPage(page) {
59467
59725
  if (!page) return null;
59468
59726
  return {
@@ -73598,872 +73856,163 @@ function toBlocksImageResolveContextInput(context) {
73598
73856
  };
73599
73857
  }
73600
73858
  //#endregion
73601
- //#region src/rendering/blocks-page-renderer.ts
73602
- const MissingBlockOverrideError = MissingBlockOverrideError$1;
73603
- function isOverrideOnlyPageRenderer(props) {
73604
- return props.rendering?.kind === "overrides-only";
73859
+ //#region ../blocks/src/system/runtime/bindings.ts
73860
+ const shouldLogWarnings = isNonProductionEnv();
73861
+ function isPlainObject(value) {
73862
+ return typeof value === "object" && value !== null && !Array.isArray(value);
73605
73863
  }
73606
- function normalizeSdkCustomBlocks(customBlocks) {
73607
- if (!customBlocks) return void 0;
73608
- return customBlocks.map((block) => {
73609
- return {
73610
- ...block,
73611
- fields: parseFieldDefinitions(block.fields)
73612
- };
73613
- });
73864
+ function isRouteMapEntry(value) {
73865
+ if (typeof value === "string") return true;
73866
+ return isPlainObject(value);
73614
73867
  }
73615
- function toBlocksBlockOverrides(overrides) {
73616
- if (!overrides) return void 0;
73617
- const result = {};
73618
- for (const [key, OverrideComponent] of Object.entries(overrides)) result[key] = function BlocksOverrideAdapter(props) {
73619
- const sdkOverride = OverrideComponent;
73620
- return React$1.createElement(sdkOverride, {
73621
- ...props,
73622
- entrySubrouteContext: props.entrySubrouteContext
73623
- });
73624
- };
73625
- return result;
73868
+ function isRouteMap(value) {
73869
+ if (!isPlainObject(value)) return false;
73870
+ return Object.values(value).every(isRouteMapEntry);
73626
73871
  }
73627
- function toBlocksPageRendererDataContext(dataContext) {
73628
- return {
73629
- ...dataContext,
73630
- mediaAssets: toBlocksMediaAssets(dataContext.mediaAssets),
73631
- imageResolveContext: toBlocksImageResolveContextInput(dataContext.imageResolveContext)
73632
- };
73872
+ function isPageIdentifierMap(value) {
73873
+ if (!isPlainObject(value)) return false;
73874
+ return Object.values(value).every((v) => typeof v === "string");
73633
73875
  }
73634
- function toBlocksCommonProps(props) {
73635
- return {
73636
- page: props.page,
73637
- runtimeJoins: props.runtimeJoins,
73638
- dataContext: toBlocksPageRendererDataContext(props.dataContext),
73639
- routeMap: props.routeMap,
73640
- wrapBlock: props.wrapBlock,
73641
- registry: props.registry,
73642
- blockOverrides: toBlocksBlockOverrides(props.blockOverrides),
73643
- sdkConfig: props.sdkConfig ? { customBlocks: normalizeSdkCustomBlocks(props.sdkConfig.customBlocks) } : props.sdkConfig,
73644
- customBlocks: normalizeSdkCustomBlocks(props.customBlocks)
73645
- };
73876
+ function isEntryIdentifierMap(value) {
73877
+ if (!isPlainObject(value)) return false;
73878
+ for (const v of Object.values(value)) {
73879
+ if (!isPlainObject(v)) return false;
73880
+ if (!Object.values(v).every((inner) => typeof inner === "string")) return false;
73881
+ }
73882
+ return true;
73646
73883
  }
73647
- function PageRenderer(props) {
73648
- const commonBlocksProps = toBlocksCommonProps(props);
73649
- const blocksProps = isOverrideOnlyPageRenderer(props) ? {
73650
- ...commonBlocksProps,
73651
- rendering: { kind: "overrides-only" },
73652
- blockOverrides: toBlocksBlockOverrides(props.blockOverrides) ?? {}
73653
- } : {
73654
- ...commonBlocksProps,
73655
- theme: parseBlocksTheme(props.theme),
73656
- themeTokens: props.themeTokens
73884
+ function buildTransformContext(vm) {
73885
+ const root = vm.$root;
73886
+ const stage = root && isPlainObject(root) && root.previewStage === "preview" ? "preview" : "published";
73887
+ const routes = root && isPlainObject(root) && isRouteMap(root.routes) ? root.routes : void 0;
73888
+ const pagesByIdentifier = root && isPlainObject(root) && isPageIdentifierMap(root.pagesByIdentifier) ? root.pagesByIdentifier : void 0;
73889
+ const entriesByIdentifier = root && isPlainObject(root) && isEntryIdentifierMap(root.entriesByIdentifier) ? root.entriesByIdentifier : void 0;
73890
+ return {
73891
+ theme: defaultThemeTokens,
73892
+ stage,
73893
+ data: vm.content,
73894
+ routes,
73895
+ pagesByIdentifier,
73896
+ entriesByIdentifier
73657
73897
  };
73658
- return React$1.createElement(PageRenderer$1, blocksProps);
73659
- }
73660
- //#endregion
73661
- //#region src/rendering/blocks-theme-scope.ts
73662
- function ThemeScope(props) {
73663
- const { theme, children, ...rest } = props;
73664
- const blocksTheme = parseBlocksTheme(theme);
73665
- return React$1.createElement(ThemeScope$1, {
73666
- ...rest,
73667
- theme: blocksTheme,
73668
- children: children ?? null
73669
- });
73670
73898
  }
73671
- //#endregion
73672
- //#region src/rendering/themeRuntime.tsx
73673
- const defaultLayoutThemeRuntime = { kind: "cms-theme" };
73674
- const defaultSdkChromeThemeRuntime = { kind: "responsive-only" };
73675
- const defaultPageThemeRuntime = { kind: "none" };
73676
- function planLayoutThemeRuntime(input) {
73677
- const requested = input.themeRuntime ?? defaultLayoutThemeRuntime;
73678
- if (requested.kind === "none" && input.usesSdkChrome) {
73679
- if (process.env.NODE_ENV !== "production") console.warn("[sdk] Layout themeRuntime { kind: \"none\" } is not compatible with SDK-managed header/footer chrome; using responsive-only runtime instead.");
73680
- return defaultSdkChromeThemeRuntime;
73899
+ function resolveParamsBindings(input, vm, meta) {
73900
+ if (input === null || typeof input !== "object") return input;
73901
+ if (Array.isArray(input)) return input.map((v) => resolveParamsBindings(v, vm, meta));
73902
+ const maybeBind = input.$bind;
73903
+ if (maybeBind && typeof maybeBind === "object") try {
73904
+ const binding = bindingSchema.parse(maybeBind);
73905
+ const value = resolveBinding(binding.from, vm);
73906
+ const resolved = value === void 0 || value === null ? binding.fallback : runTransforms(value, binding.transforms, buildTransformContext(vm), defaultTransforms);
73907
+ if (resolved === void 0 || resolved === null || resolved === "") return binding.fallback;
73908
+ return resolved;
73909
+ } catch (err) {
73910
+ if (shouldLogWarnings) console.warn(`bindings: failed to parse loader param binding for block "${meta?.blockKind ?? "unknown"}"`, err);
73911
+ return;
73681
73912
  }
73682
- return requested;
73913
+ const out = {};
73914
+ for (const [k, v] of Object.entries(input)) out[k] = resolveParamsBindings(v, vm, meta);
73915
+ return out;
73683
73916
  }
73684
- function renderWithSdkThemeRuntime({ themeRuntime, theme, children }) {
73685
- switch (themeRuntime.kind) {
73686
- case "cms-theme": return /* @__PURE__ */ jsx(ThemeScope, {
73687
- theme,
73688
- responsiveMode: themeRuntime.responsiveMode,
73689
- children
73690
- });
73691
- case "responsive-only": return /* @__PURE__ */ jsx(ResponsiveScope, {
73692
- responsiveMode: themeRuntime.responsiveMode,
73693
- children
73694
- });
73695
- case "none": return /* @__PURE__ */ jsx(Fragment, { children });
73696
- default: return assertNever$4(themeRuntime);
73917
+ function resolveBinding(path, vm) {
73918
+ const segments = splitPath(path);
73919
+ if (!segments.length) return void 0;
73920
+ const [first, ...rest] = segments;
73921
+ let source = vm;
73922
+ if (first === "$root") {
73923
+ source = vm;
73924
+ return readFromSource(source, [first, ...rest]);
73697
73925
  }
73698
- }
73699
- function renderWithOverrideOnlyRuntime({ runtime, children }) {
73700
- switch (runtime.kind) {
73701
- case "responsive-only": return /* @__PURE__ */ jsx(ResponsiveScope, {
73702
- responsiveMode: runtime.responsiveMode,
73703
- children
73704
- });
73705
- case "none": return /* @__PURE__ */ jsx(Fragment, { children });
73706
- default: return assertNever$4(runtime);
73926
+ if (first === "content") {
73927
+ source = vm.content;
73928
+ return readFromSource(source, rest);
73707
73929
  }
73930
+ const contentResult = readFromSource(vm.content, segments);
73931
+ if (contentResult !== void 0) return contentResult;
73932
+ return readFromSource(vm, segments);
73708
73933
  }
73709
- //#endregion
73710
- //#region src/rendering/components/pageShared.tsx
73711
- function isOverrideOnlyPage(props) {
73712
- return props.rendering?.kind === "overrides-only";
73713
- }
73714
- function resolvePageThemeTokens(props) {
73715
- const baseTokens = props.themeTokens ?? buildThemeRuntime(props.theme).tokens;
73716
- return props.sdkConfig?.theme?.palette ? {
73717
- ...baseTokens,
73718
- palette: {
73719
- ...baseTokens.palette,
73720
- ...props.sdkConfig.theme.palette
73934
+ function splitPath(path) {
73935
+ const PATH_SEPARATOR_REGEX = /\./g;
73936
+ const BRACKET_ACCESS_REGEX = /\[(?<token>[^\]]+)\]/g;
73937
+ const segments = [];
73938
+ const parts = path.split(PATH_SEPARATOR_REGEX);
73939
+ for (const raw of parts) {
73940
+ if (!raw) continue;
73941
+ const baseMatch = raw.match(/^([^\[]+)/);
73942
+ if (baseMatch && baseMatch[1]) segments.push(baseMatch[1]);
73943
+ const bracketMatches = raw.matchAll(BRACKET_ACCESS_REGEX);
73944
+ for (const match of bracketMatches) {
73945
+ const token = match.groups?.token ?? "";
73946
+ if (token.startsWith("\"") || token.startsWith("'")) segments.push(token.slice(1, -1));
73947
+ else if (/^\d+$/.test(token)) segments.push(Number(token));
73948
+ else segments.push(token);
73721
73949
  }
73722
- } : baseTokens;
73723
- }
73724
- function resolveSdkBookingTimeZone(timeZone) {
73725
- return timeZone ?? "UTC";
73726
- }
73727
- function buildPageRouteRenderContext(dataContext) {
73728
- return {
73729
- ...buildPageIdentityRenderContext(dataContext),
73730
- occurrenceContext: dataContext.occurrenceContext ?? null,
73731
- entrySubrouteContext: dataContext.entrySubrouteContext ?? null,
73732
- contentEntry: dataContext.contentEntry ?? null,
73733
- pageSurface: dataContext.pageSurface ?? null,
73734
- subject: dataContext.subject ?? null,
73735
- editableRouteMetadataFieldIds: dataContext.editableRouteMetadataFieldIds ?? null,
73736
- previewStage: dataContext.previewStage
73737
- };
73738
- }
73739
- function buildPageIdentityRenderContext(dataContext) {
73740
- return {
73741
- siteName: dataContext.siteName,
73742
- pathname: dataContext.pathname
73743
- };
73950
+ if (!baseMatch && !raw.includes("[")) segments.push(raw);
73951
+ }
73952
+ return segments;
73744
73953
  }
73745
- function PageContent(props) {
73746
- const { page, runtimeJoins, siteId, resolvedData, bookingOfferingPresets, mailingList, bookingTimeZone, routeMap, pagesByIdentifier, entriesByIdentifier, wrapBlock, registry, blockOverrides, sdkConfig, customBlocks, supabaseUrl, mediaAssets, apiBaseUrl, portalToken, previewToken, readAuthority, dataContext } = props;
73747
- const rendererCommonProps = {
73748
- page,
73749
- runtimeJoins,
73750
- dataContext: {
73751
- siteId,
73752
- ...buildPageRouteRenderContext(dataContext),
73753
- apiBaseUrl,
73754
- portalToken,
73755
- previewToken,
73756
- readAuthority: readAuthority ?? dataContext.readAuthority,
73757
- resolvedData,
73758
- bookingOfferingPresets: bookingOfferingPresets ?? [],
73759
- mailingList: mailingList ?? dataContext.mailingList,
73760
- bookingTimeZone: resolveSdkBookingTimeZone(bookingTimeZone),
73761
- routes: routeMap,
73762
- pagesByIdentifier,
73763
- entriesByIdentifier,
73764
- supabaseUrl,
73765
- mediaAssets,
73766
- imageResolveContext: {
73767
- siteId,
73768
- supabaseUrl,
73769
- mediaAssets
73770
- }
73771
- },
73772
- routeMap,
73773
- wrapBlock,
73774
- registry,
73775
- sdkConfig: sdkConfig ? { customBlocks: sdkConfig.customBlocks } : null,
73776
- customBlocks
73777
- };
73778
- const content = isOverrideOnlyPage(props) ? /* @__PURE__ */ jsx(PageRenderer, {
73779
- ...rendererCommonProps,
73780
- rendering: { kind: "overrides-only" },
73781
- blockOverrides: props.blockOverrides
73782
- }) : /* @__PURE__ */ jsx(PageRenderer, {
73783
- ...rendererCommonProps,
73784
- theme: props.theme,
73785
- themeTokens: resolvePageThemeTokens(props),
73786
- blockOverrides
73787
- });
73788
- return isOverrideOnlyPage(props) ? renderWithOverrideOnlyRuntime({
73789
- runtime: props.rendering.runtime,
73790
- children: content
73791
- }) : renderWithSdkThemeRuntime({
73792
- themeRuntime: props.themeRuntime ?? defaultPageThemeRuntime,
73793
- theme: props.theme,
73794
- children: content
73795
- });
73954
+ function readFromSource(source, segments) {
73955
+ return segments.reduce((current, segment) => {
73956
+ if (current === void 0 || current === null) return void 0;
73957
+ if (typeof segment === "number") {
73958
+ if (Array.isArray(current)) return current[segment];
73959
+ return;
73960
+ }
73961
+ if (typeof current === "object" && current !== null && segment in current) return current[segment];
73962
+ }, source);
73796
73963
  }
73797
- //#endregion
73798
- //#region src/rendering/components/Page.server.tsx
73799
- function Page(props) {
73800
- return /* @__PURE__ */ jsx(PageContent, { ...props });
73964
+ function isNonProductionEnv() {
73965
+ if (typeof globalThis === "undefined") return true;
73966
+ return globalThis.process?.env?.NODE_ENV !== "production";
73801
73967
  }
73802
73968
  //#endregion
73803
- //#region src/env.ts
73969
+ //#region ../blocks/src/system/data/utils.ts
73804
73970
  /**
73805
- * Error thrown when required environment variables are missing
73971
+ * Normalize data loaders from block definition
73806
73972
  */
73807
- var RiverbankEnvError = class extends Error {
73808
- constructor(message, missingVars) {
73809
- super(message);
73810
- this.missingVars = missingVars;
73811
- this.name = "RiverbankEnvError";
73812
- }
73813
- };
73973
+ function normalizeDataLoaders(def) {
73974
+ if (!def?.dataLoaders) return [];
73975
+ return Object.entries(def.dataLoaders).map(([key, loader]) => ({
73976
+ key,
73977
+ loader
73978
+ }));
73979
+ }
73814
73980
  /**
73815
- * Get the environment variable prefix based on target
73981
+ * Normalize block content for data loading.
73982
+ * Priority: draftContent > content > publishedContent
73816
73983
  */
73817
- function getEnvPrefix(target) {
73818
- return target === "remote" ? "RIVERBANK_REMOTE" : "RIVERBANK_LOCAL";
73984
+ function normalizeContent(block) {
73985
+ const source = block.draftContent ?? block.content ?? block.publishedContent ?? {};
73986
+ if (!isObjectRecord$1(source)) return {};
73987
+ if ("data" in source) {
73988
+ const data = source.data;
73989
+ if (isObjectRecord$1(data)) return data;
73990
+ if (data === null || data === void 0) return {};
73991
+ }
73992
+ return source;
73819
73993
  }
73820
73994
  /**
73821
- * Detect the environment target from RIVERBANK_ENV
73995
+ * Normalize params for API calls.
73996
+ * Converts supplied values to strings, preserving absent versus explicitly empty params.
73822
73997
  */
73823
- function detectTarget() {
73824
- const env = process.env.RIVERBANK_ENV?.toLowerCase();
73825
- if (env === "remote" || env === "production" || env === "prod") return "remote";
73826
- return "local";
73998
+ function normalizeParams(input) {
73999
+ if (!input || typeof input !== "object") return {};
74000
+ const output = {};
74001
+ for (const [key, value] of Object.entries(input)) if (value !== void 0 && value !== null) output[key] = coerceToString(value);
74002
+ return output;
74003
+ }
74004
+ function isNonArrayObject(value) {
74005
+ return typeof value === "object" && value !== null && !Array.isArray(value);
74006
+ }
74007
+ function safeJsonStringify(value) {
74008
+ try {
74009
+ return JSON.stringify(value);
74010
+ } catch {
74011
+ return;
74012
+ }
73827
74013
  }
73828
74014
  /**
73829
- * Detect if preview mode is enabled.
73830
- * Uses RIVERBANK_PREVIEW_MODE first, then falls back to RIVERBANK_PREVIEW for backward compat.
73831
- */
73832
- function detectPreviewMode() {
73833
- const previewMode = process.env.RIVERBANK_PREVIEW_MODE;
73834
- if (previewMode !== void 0 && previewMode !== "") return previewMode === "true";
73835
- const previewLegacy = process.env.RIVERBANK_PREVIEW;
73836
- if (previewLegacy !== void 0 && previewLegacy !== "") return previewLegacy === "true";
73837
- return process.env.VERCEL_ENV === "preview";
73838
- }
73839
- /**
73840
- * Validate that an API key matches the expected format for its type
73841
- */
73842
- function validateKeyType(key, expectedType) {
73843
- const isPreviewKey = key.startsWith("bld_preview_sk_");
73844
- const isContentKey = key.startsWith("bld_live_sk_");
73845
- if (expectedType === "preview" && !isPreviewKey) {
73846
- if (isContentKey) throw new RiverbankEnvError("Preview mode is enabled (RIVERBANK_PREVIEW_MODE=true) but a content key was provided. Preview mode requires a preview API key (bld_preview_sk_...) to access draft content. Either:\n 1. Set RIVERBANK_*_PREVIEW_API_KEY with your preview key, or\n 2. Set RIVERBANK_PREVIEW_MODE=false to fetch published content instead.", []);
73847
- throw new RiverbankEnvError(`Invalid API key format for preview mode. Expected key starting with bld_preview_sk_`, []);
73848
- }
73849
- if (expectedType === "content" && !isContentKey) {
73850
- if (isPreviewKey) {
73851
- console.debug("[getRiverbankEnv] Using preview key for published content. Consider using a content key (bld_live_sk_...) for production.");
73852
- return;
73853
- }
73854
- throw new RiverbankEnvError(`Invalid API key format for content access. Expected key starting with bld_live_sk_ or bld_preview_sk_`, []);
73855
- }
73856
- }
73857
- /**
73858
- * Get runtime environment configuration with automatic API key selection.
73859
- *
73860
- * This helper reads environment variables and automatically selects the correct
73861
- * API key based on the current environment and preview mode:
73862
- *
73863
- * - When `RIVERBANK_PREVIEW_MODE=true`: Uses preview API key (bld_preview_sk_...)
73864
- * - When `RIVERBANK_PREVIEW_MODE=false` (default): Uses content API key (bld_live_sk_...)
73865
- *
73866
- * Environment variable patterns:
73867
- * - `RIVERBANK_ENV`: 'local' (default) or 'remote'
73868
- * - `RIVERBANK_PREVIEW_MODE`: 'true' or 'false' (default)
73869
- * - `RIVERBANK_{LOCAL|REMOTE}_SITE_ID`: Site ID
73870
- * - `RIVERBANK_{LOCAL|REMOTE}_DASHBOARD_URL`: Dashboard URL
73871
- * - `RIVERBANK_{LOCAL|REMOTE}_API_KEY`: Content/live API key
73872
- * - `RIVERBANK_{LOCAL|REMOTE}_PREVIEW_API_KEY`: Preview API key
73873
- *
73874
- * @returns Environment configuration with auto-selected API key
73875
- * @throws {RiverbankEnvError} If required environment variables are missing
73876
- *
73877
- * @example
73878
- * ```ts
73879
- * // lib/builder-client.ts
73880
- * import { getRiverbankEnv } from '@riverbankcms/sdk/env';
73881
- * import { createRiverbankClient } from '@riverbankcms/sdk';
73882
- *
73883
- * const env = getRiverbankEnv();
73884
- *
73885
- * export const client = createRiverbankClient({
73886
- * apiKey: env.apiKey,
73887
- * baseUrl: env.baseUrl,
73888
- * });
73889
- *
73890
- * export const siteId = env.siteId;
73891
- * ```
73892
- */
73893
- function getRiverbankEnv() {
73894
- const target = detectTarget();
73895
- const previewMode = detectPreviewMode();
73896
- const prefix = getEnvPrefix(target);
73897
- const siteId = process.env[`${prefix}_SITE_ID`];
73898
- const dashboardUrl = process.env[`${prefix}_DASHBOARD_URL`];
73899
- const contentKey = process.env[`${prefix}_API_KEY`];
73900
- const previewKey = process.env[`${prefix}_PREVIEW_API_KEY`];
73901
- const missingVars = [];
73902
- if (!siteId) missingVars.push(`${prefix}_SITE_ID`);
73903
- if (!dashboardUrl) missingVars.push(`${prefix}_DASHBOARD_URL`);
73904
- let apiKey;
73905
- let keyType;
73906
- if (previewMode) {
73907
- apiKey = previewKey;
73908
- keyType = "preview";
73909
- if (!apiKey) missingVars.push(`${prefix}_PREVIEW_API_KEY`);
73910
- } else {
73911
- apiKey = contentKey || previewKey;
73912
- keyType = contentKey ? "content" : "preview";
73913
- if (!apiKey) missingVars.push(`${prefix}_API_KEY`);
73914
- }
73915
- if (missingVars.length > 0) throw new RiverbankEnvError(`Missing required environment variables for Riverbank SDK:\n` + missingVars.map((v) => ` - ${v}`).join("\n") + `\n\nCurrent settings: RIVERBANK_ENV=${process.env.RIVERBANK_ENV || "local"}, RIVERBANK_PREVIEW_MODE=${process.env.RIVERBANK_PREVIEW_MODE || "false"}`, missingVars);
73916
- if (!apiKey || !dashboardUrl || !siteId) throw new RiverbankEnvError("Required environment variables missing", missingVars);
73917
- validateKeyType(apiKey, keyType);
73918
- let baseUrl = dashboardUrl;
73919
- if (!baseUrl.endsWith("/api")) baseUrl = baseUrl.replace(/\/$/, "") + "/api";
73920
- return {
73921
- target,
73922
- previewMode,
73923
- siteId,
73924
- baseUrl,
73925
- apiKey,
73926
- keyType
73927
- };
73928
- }
73929
- //#endregion
73930
- //#region src/navigation/index.ts
73931
- /**
73932
- * Get the fixed main navigation menu object.
73933
- * Returns null when the runtime payload is incomplete.
73934
- *
73935
- * @example
73936
- * ```ts
73937
- * const menu = getPrimaryNavigation(siteData.navigation);
73938
- * console.log(menu?.location); // "main"
73939
- * ```
73940
- */
73941
- function getPrimaryNavigation(navigation) {
73942
- if (!navigation || navigation.length === 0) return null;
73943
- return navigation.find((menu) => menu.location === "main") ?? null;
73944
- }
73945
- function getFooterNavigationByRole(navigation, role) {
73946
- if (!navigation || navigation.length === 0) return null;
73947
- const canonicalLocation = role === "main" ? "footer" : "legal";
73948
- return navigation.find((menu) => menu.location === canonicalLocation) ?? null;
73949
- }
73950
- /**
73951
- * Resolve alt text with fallback.
73952
- * Returns the provided alt if non-empty, otherwise falls back to the provided fallback or 'Site logo'.
73953
- * @internal
73954
- */
73955
- function resolveAltText(alt, fallback) {
73956
- return alt && alt.trim().length > 0 ? alt : fallback ?? "Site logo";
73957
- }
73958
- function readNavigationItemPayload(item) {
73959
- return item.url ?? null;
73960
- }
73961
- function isPortalEnabled(options) {
73962
- return options?.portalEnabled === true;
73963
- }
73964
- function isCommerceEnabled(options) {
73965
- return options?.commerceEnabled === true;
73966
- }
73967
- function resolvePortalHref(link) {
73968
- return link.path?.trim() || "/portal";
73969
- }
73970
- function resolveCheckoutHref(options) {
73971
- if (options?.checkoutHref === null) return null;
73972
- const href = options?.checkoutHref?.trim();
73973
- return href && href.length > 0 ? href : "/checkout";
73974
- }
73975
- function resolvePortalLabel(link, options) {
73976
- const loggedOutLabel = link.labels?.loggedOut?.trim() || PORTAL_NAV_DEFAULT_LABELS.loggedOut;
73977
- const loggedInLabel = link.labels?.loggedIn?.trim() || PORTAL_NAV_DEFAULT_LABELS.loggedIn;
73978
- return options?.hasPortalSession ? loggedInLabel : loggedOutLabel;
73979
- }
73980
- function resolveItemLabel(link, fallbackLabel, options) {
73981
- if (link?.kind === "portal") return resolvePortalLabel(link, options);
73982
- if (link?.kind === "cart") return resolveCartVisibleLabel(link) ?? fallbackLabel;
73983
- return fallbackLabel;
73984
- }
73985
- function resolveCartVisibleLabel(link) {
73986
- if (link.label.kind !== "icon-with-label") return null;
73987
- const label = link.label.label.trim();
73988
- return label.length > 0 ? label : null;
73989
- }
73990
- function resolveCartAriaLabel(link, fallbackLabel) {
73991
- const fallback = fallbackLabel.trim();
73992
- return resolveCartVisibleLabel(link) ?? (fallback.length > 0 ? fallback : "Cart");
73993
- }
73994
- function buildCartNavViewModel(link, fallbackLabel, options) {
73995
- return {
73996
- visibleLabel: resolveCartVisibleLabel(link),
73997
- badge: link.badge,
73998
- ariaLabel: resolveCartAriaLabel(link, fallbackLabel),
73999
- checkoutHref: resolveCheckoutHref(options)
74000
- };
74001
- }
74002
- function deriveRenderableNavigationLink(item, options) {
74003
- const payload = readNavigationItemPayload(item);
74004
- if (!payload) return null;
74005
- if (payload.kind === "portal" && !isPortalEnabled(options)) return null;
74006
- if (payload.kind === "cart" && !isCommerceEnabled(options)) return null;
74007
- return {
74008
- id: item.id,
74009
- label: resolveItemLabel(payload, item.label, options),
74010
- payload,
74011
- isExternal: isExternalLink(payload),
74012
- ...payload.kind === "cart" ? { cart: buildCartNavViewModel(payload, item.label, options) } : {}
74013
- };
74014
- }
74015
- function buildNavLinkFromResolvedHref(item, href) {
74016
- if (!href) return null;
74017
- return {
74018
- kind: "link",
74019
- id: item.id,
74020
- label: item.label,
74021
- href,
74022
- link: { href },
74023
- isExternal: item.isExternal,
74024
- ...item.cart ? { cart: item.cart } : {}
74025
- };
74026
- }
74027
- /**
74028
- * Determines if a navigation item's link is external.
74029
- */
74030
- function isExternalLink(link) {
74031
- if (!link) return false;
74032
- return link.kind === "external";
74033
- }
74034
- /**
74035
- * Build a map of children items by parent ID.
74036
- * Also warns about deeply nested items (grandchildren) which CMS shouldn't allow.
74037
- * @internal
74038
- */
74039
- function buildChildrenByParentId(items) {
74040
- const childrenByParentId = /* @__PURE__ */ new Map();
74041
- const itemsById = /* @__PURE__ */ new Map();
74042
- for (const item of items) itemsById.set(item.id, item);
74043
- for (const item of items) if (item.parentId) {
74044
- if (itemsById.get(item.parentId)?.parentId && typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
74045
- console.warn(`[SDK Navigation] Deeply nested item detected: "${item.label}" (id: ${item.id}). Only 1 level of nesting is supported. This item will be ignored.`);
74046
- continue;
74047
- }
74048
- const siblings = childrenByParentId.get(item.parentId) ?? [];
74049
- siblings.push(item);
74050
- childrenByParentId.set(item.parentId, siblings);
74051
- }
74052
- return childrenByParentId;
74053
- }
74054
- /**
74055
- * Generic nested structure builder.
74056
- * @internal
74057
- */
74058
- function buildNestedStructure(items, options) {
74059
- const childrenByParentId = buildChildrenByParentId(items);
74060
- const rootItems = items.filter((item) => !item.parentId).sort((a, b) => (a.orderIndex ?? a.position ?? 0) - (b.orderIndex ?? b.position ?? 0));
74061
- const result = [];
74062
- let ctaItem = null;
74063
- for (const item of rootItems) {
74064
- if (options.extractCta && !ctaItem && Boolean(item.isCta) && item.urlType !== "dropdown") {
74065
- const link = options.toLink(item);
74066
- if (link) {
74067
- ctaItem = link;
74068
- continue;
74069
- }
74070
- }
74071
- const childRecords = childrenByParentId.get(item.id) ?? [];
74072
- const hasChildren = childRecords.length > 0;
74073
- if (item.urlType === "dropdown" || hasChildren) {
74074
- const children = childRecords.sort((a, b) => (a.orderIndex ?? a.position ?? 0) - (b.orderIndex ?? b.position ?? 0)).map(options.toLink).filter((child) => child !== null);
74075
- if (children.length > 0) result.push(options.createDropdown(item.id, item.label, children));
74076
- continue;
74077
- }
74078
- const link = options.toLink(item);
74079
- if (link) result.push(link);
74080
- }
74081
- return {
74082
- items: result,
74083
- ctaItem
74084
- };
74085
- }
74086
- /**
74087
- * Build a Menu from navigation data with pre-resolved hrefs.
74088
- * Supports dropdown containers with nested children.
74089
- *
74090
- * @param navigation - Navigation menus from site data
74091
- * @param routes - Route map for resolving internal links
74092
- * @param options - Include identifier maps to resolve canonical `page`/`entry` links.
74093
- *
74094
- * @example
74095
- * ```ts
74096
- * const menu = buildMenu(siteData.navigation, siteData.routes, {
74097
- * pagesByIdentifier: siteData.pagesByIdentifier,
74098
- * entriesByIdentifier: siteData.entriesByIdentifier,
74099
- * });
74100
- * menu.items.forEach(item => {
74101
- * if (item.kind === 'dropdown') {
74102
- * console.log(item.children);
74103
- * }
74104
- * });
74105
- * ```
74106
- */
74107
- function buildMenu(navigation, routes, options) {
74108
- const menu = getPrimaryNavigation(navigation);
74109
- if (!menu) return {
74110
- items: [],
74111
- ctaItem: null
74112
- };
74113
- const toNavLink = (item) => {
74114
- const renderable = deriveRenderableNavigationLink(item, options);
74115
- if (!renderable) return null;
74116
- return buildNavLinkFromResolvedHref(renderable, resolveHref(renderable.payload, routes, options));
74117
- };
74118
- const { items, ctaItem } = buildNestedStructure(menu.items, {
74119
- toLink: toNavLink,
74120
- createDropdown: (id, label, children) => ({
74121
- kind: "dropdown",
74122
- id,
74123
- label,
74124
- children
74125
- }),
74126
- extractCta: true
74127
- });
74128
- return {
74129
- items,
74130
- ctaItem: ctaItem ? {
74131
- ...ctaItem,
74132
- variant: "primary"
74133
- } : null
74134
- };
74135
- }
74136
- /**
74137
- * Build a Menu from the footer navigation data.
74138
- * Returns empty menu if no footer menu is designated.
74139
- *
74140
- * @param navigation - Navigation menus from site data
74141
- * @param routes - Route map for resolving internal links
74142
- * @param options - Include identifier maps to resolve canonical `page`/`entry` links.
74143
- *
74144
- * @example
74145
- * ```ts
74146
- * const footerMenu = buildFooterMenu(siteData.navigation, siteData.routes, {
74147
- * pagesByIdentifier: siteData.pagesByIdentifier,
74148
- * entriesByIdentifier: siteData.entriesByIdentifier,
74149
- * });
74150
- * footerMenu.items.forEach(item => {
74151
- * if (item.kind === 'dropdown') {
74152
- * // Footer renders children expanded, not as hover dropdowns
74153
- * console.log(item.children);
74154
- * }
74155
- * });
74156
- * ```
74157
- */
74158
- function buildFooterMenu(navigation, routes, options) {
74159
- return buildFooterMenuForRole(navigation, routes, "main", options);
74160
- }
74161
- function buildFooterMenuForRole(navigation, routes, role, options) {
74162
- const menu = getFooterNavigationByRole(navigation, role);
74163
- if (!menu) return {
74164
- items: [],
74165
- ctaItem: null,
74166
- groups: [],
74167
- links: []
74168
- };
74169
- const toNavLink = (item) => {
74170
- const renderable = deriveRenderableNavigationLink(item, options);
74171
- if (!renderable) return null;
74172
- return buildNavLinkFromResolvedHref(renderable, resolveHref(renderable.payload, routes, options));
74173
- };
74174
- const built = buildNestedStructure(menu.items, {
74175
- toLink: toNavLink,
74176
- createDropdown: (id, label, children) => ({
74177
- kind: "dropdown",
74178
- id,
74179
- label,
74180
- children
74181
- }),
74182
- extractCta: false
74183
- });
74184
- const groups = built.items.filter((item) => item.kind === "dropdown");
74185
- const links = built.items.filter((item) => item.kind === "link");
74186
- return {
74187
- items: built.items,
74188
- ctaItem: null,
74189
- groups,
74190
- links
74191
- };
74192
- }
74193
- /**
74194
- * Resolve href from a link payload using route map.
74195
- * @internal
74196
- */
74197
- function resolveHref(link, routes, options) {
74198
- if (!link) return null;
74199
- if (link.kind === "external" || link.kind === "url") return link.href || null;
74200
- if (link.kind === "portal") return isPortalEnabled(options) ? resolvePortalHref(link) : null;
74201
- if (link.kind === "cart") return isCommerceEnabled(options) ? resolveCheckoutHref(options) : null;
74202
- const stage = normalizeRenderStage(options?.previewStage);
74203
- if (link.kind === "internal") return resolveRouteHrefWithFallback(link.routeId, link.href ?? null, routes, stage);
74204
- if (link.kind === "page") {
74205
- const routeIdFromPayload = readRouteIdFromLink(link);
74206
- const routeIdFromIdentifierMap = options?.pagesByIdentifier?.[link.identifier] ?? null;
74207
- return resolveRouteHrefWithFallback(routeIdFromPayload ?? routeIdFromIdentifierMap, readHrefFromLink(link), routes, stage);
74208
- }
74209
- if (link.kind === "entry") {
74210
- const routeIdFromPayload = readRouteIdFromLink(link);
74211
- const routeIdFromIdentifierMap = readEntryRouteIdFromIdentifierMap(options, link.contentType, link.identifier);
74212
- return resolveRouteHrefWithFallback(routeIdFromPayload ?? routeIdFromIdentifierMap, readHrefFromLink(link), routes, stage);
74213
- }
74214
- return null;
74215
- }
74216
- function resolveRouteHrefWithFallback(routeId, fallbackHref, routes, stage) {
74217
- if (!routeId) return fallbackHref;
74218
- const resolved = resolveRouteHrefForStage(routeId, routes, stage);
74219
- if (resolved) return resolved;
74220
- const route = routes[routeId];
74221
- if (!route) return fallbackHref;
74222
- if (!isRouteVisibleInStage(route, stage)) return null;
74223
- return fallbackHref;
74224
- }
74225
- function readRouteIdFromLink(link) {
74226
- if (!("routeId" in link) || typeof link.routeId !== "string") return null;
74227
- return link.routeId;
74228
- }
74229
- function readHrefFromLink(link) {
74230
- if (!("href" in link) || typeof link.href !== "string") return null;
74231
- return link.href;
74232
- }
74233
- function readEntryRouteIdFromIdentifierMap(options, contentType, identifier) {
74234
- const entryMap = options?.entriesByIdentifier?.[contentType];
74235
- if (!entryMap) return null;
74236
- return entryMap[identifier] ?? null;
74237
- }
74238
- /**
74239
- * Build a Logo from site layout data.
74240
- *
74241
- * @param logo - Logo data from site layout
74242
- * @param fallbackAlt - Fallback alt text (usually site title)
74243
- *
74244
- * @example
74245
- * ```ts
74246
- * const logo = buildLogo(siteData.layout.logo, siteData.site.title);
74247
- * // { src: 'https://...', alt: 'Site Name', width: 200, height: 50 }
74248
- * ```
74249
- */
74250
- function buildLogo(logo, fallbackAlt) {
74251
- if (!logo || !logo.url) return null;
74252
- const alt = resolveAltText(logo.alt, fallbackAlt);
74253
- const result = {
74254
- type: "image",
74255
- src: logo.url,
74256
- alt
74257
- };
74258
- if (logo.width != null) result.width = logo.width;
74259
- if (logo.height != null) result.height = logo.height;
74260
- return result;
74261
- }
74262
- /**
74263
- * Build both site logos from layout data. The default header and footer choose
74264
- * between them by the surface they sit on; custom chrome can do the same.
74265
- *
74266
- * @example
74267
- * ```ts
74268
- * const logoVariants = buildLogoVariants(siteData.layout, siteData.site.title);
74269
- * ```
74270
- */
74271
- function buildLogoVariants(layout, fallbackAlt) {
74272
- return {
74273
- forLightBackgrounds: buildLogo(layout?.logo ?? null, fallbackAlt),
74274
- forDarkBackgrounds: buildLogo(layout?.logoForDarkBackgrounds ?? null, fallbackAlt)
74275
- };
74276
- }
74277
- /**
74278
- * Header/footer block content for the site logos. `logo` stays populated with
74279
- * whichever logo exists so presence checks keep working; `logoVariants` is
74280
- * what the blocks select from at render.
74281
- */
74282
- function buildChromeLogoContent(layout, fallbackAlt) {
74283
- const logoVariants = buildLogoVariants(layout, fallbackAlt);
74284
- return {
74285
- logo: logoVariants.forLightBackgrounds ?? logoVariants.forDarkBackgrounds,
74286
- logoVariants
74287
- };
74288
- }
74289
- //#endregion
74290
- //#region src/rendering/themeAdmission.ts
74291
- const MISSING_SDK_THEME_ERROR_CODE = "missing_sdk_theme";
74292
- var MissingSdkThemeError = class extends Error {
74293
- constructor(siteId, reason = "cms_theme_absent", themeKey) {
74294
- super(`[Riverbank SDK] Site "${siteId}" has no resolvable theme. ` + (themeKey ? `Theme key "${themeKey}" is not present. ` : "") + "Select a CMS theme, provide { theme }, { themes }, or { getTheme }, or use rendering: { kind: 'overrides-only' } with complete block overrides.");
74295
- this.siteId = siteId;
74296
- this.reason = reason;
74297
- this.themeKey = themeKey;
74298
- this.code = MISSING_SDK_THEME_ERROR_CODE;
74299
- this.name = "MissingSdkThemeError";
74300
- }
74301
- };
74302
- function requireSdkTheme(theme, siteId, reason = "cms_theme_absent") {
74303
- if (theme === null || theme === void 0) throw new MissingSdkThemeError(siteId, reason);
74304
- return theme;
74305
- }
74306
- //#endregion
74307
- //#region src/rendering/renderingMode.ts
74308
- const defaultOverrideOnlyRuntime = { kind: "responsive-only" };
74309
- //#endregion
74310
- //#region ../blocks/src/system/runtime/bindings.ts
74311
- const shouldLogWarnings = isNonProductionEnv();
74312
- function isPlainObject(value) {
74313
- return typeof value === "object" && value !== null && !Array.isArray(value);
74314
- }
74315
- function isRouteMapEntry(value) {
74316
- if (typeof value === "string") return true;
74317
- return isPlainObject(value);
74318
- }
74319
- function isRouteMap(value) {
74320
- if (!isPlainObject(value)) return false;
74321
- return Object.values(value).every(isRouteMapEntry);
74322
- }
74323
- function isPageIdentifierMap(value) {
74324
- if (!isPlainObject(value)) return false;
74325
- return Object.values(value).every((v) => typeof v === "string");
74326
- }
74327
- function isEntryIdentifierMap(value) {
74328
- if (!isPlainObject(value)) return false;
74329
- for (const v of Object.values(value)) {
74330
- if (!isPlainObject(v)) return false;
74331
- if (!Object.values(v).every((inner) => typeof inner === "string")) return false;
74332
- }
74333
- return true;
74334
- }
74335
- function buildTransformContext(vm) {
74336
- const root = vm.$root;
74337
- const stage = root && isPlainObject(root) && root.previewStage === "preview" ? "preview" : "published";
74338
- const routes = root && isPlainObject(root) && isRouteMap(root.routes) ? root.routes : void 0;
74339
- const pagesByIdentifier = root && isPlainObject(root) && isPageIdentifierMap(root.pagesByIdentifier) ? root.pagesByIdentifier : void 0;
74340
- const entriesByIdentifier = root && isPlainObject(root) && isEntryIdentifierMap(root.entriesByIdentifier) ? root.entriesByIdentifier : void 0;
74341
- return {
74342
- theme: defaultThemeTokens,
74343
- stage,
74344
- data: vm.content,
74345
- routes,
74346
- pagesByIdentifier,
74347
- entriesByIdentifier
74348
- };
74349
- }
74350
- function resolveParamsBindings(input, vm, meta) {
74351
- if (input === null || typeof input !== "object") return input;
74352
- if (Array.isArray(input)) return input.map((v) => resolveParamsBindings(v, vm, meta));
74353
- const maybeBind = input.$bind;
74354
- if (maybeBind && typeof maybeBind === "object") try {
74355
- const binding = bindingSchema.parse(maybeBind);
74356
- const value = resolveBinding(binding.from, vm);
74357
- const resolved = value === void 0 || value === null ? binding.fallback : runTransforms(value, binding.transforms, buildTransformContext(vm), defaultTransforms);
74358
- if (resolved === void 0 || resolved === null || resolved === "") return binding.fallback;
74359
- return resolved;
74360
- } catch (err) {
74361
- if (shouldLogWarnings) console.warn(`bindings: failed to parse loader param binding for block "${meta?.blockKind ?? "unknown"}"`, err);
74362
- return;
74363
- }
74364
- const out = {};
74365
- for (const [k, v] of Object.entries(input)) out[k] = resolveParamsBindings(v, vm, meta);
74366
- return out;
74367
- }
74368
- function resolveBinding(path, vm) {
74369
- const segments = splitPath(path);
74370
- if (!segments.length) return void 0;
74371
- const [first, ...rest] = segments;
74372
- let source = vm;
74373
- if (first === "$root") {
74374
- source = vm;
74375
- return readFromSource(source, [first, ...rest]);
74376
- }
74377
- if (first === "content") {
74378
- source = vm.content;
74379
- return readFromSource(source, rest);
74380
- }
74381
- const contentResult = readFromSource(vm.content, segments);
74382
- if (contentResult !== void 0) return contentResult;
74383
- return readFromSource(vm, segments);
74384
- }
74385
- function splitPath(path) {
74386
- const PATH_SEPARATOR_REGEX = /\./g;
74387
- const BRACKET_ACCESS_REGEX = /\[(?<token>[^\]]+)\]/g;
74388
- const segments = [];
74389
- const parts = path.split(PATH_SEPARATOR_REGEX);
74390
- for (const raw of parts) {
74391
- if (!raw) continue;
74392
- const baseMatch = raw.match(/^([^\[]+)/);
74393
- if (baseMatch && baseMatch[1]) segments.push(baseMatch[1]);
74394
- const bracketMatches = raw.matchAll(BRACKET_ACCESS_REGEX);
74395
- for (const match of bracketMatches) {
74396
- const token = match.groups?.token ?? "";
74397
- if (token.startsWith("\"") || token.startsWith("'")) segments.push(token.slice(1, -1));
74398
- else if (/^\d+$/.test(token)) segments.push(Number(token));
74399
- else segments.push(token);
74400
- }
74401
- if (!baseMatch && !raw.includes("[")) segments.push(raw);
74402
- }
74403
- return segments;
74404
- }
74405
- function readFromSource(source, segments) {
74406
- return segments.reduce((current, segment) => {
74407
- if (current === void 0 || current === null) return void 0;
74408
- if (typeof segment === "number") {
74409
- if (Array.isArray(current)) return current[segment];
74410
- return;
74411
- }
74412
- if (typeof current === "object" && current !== null && segment in current) return current[segment];
74413
- }, source);
74414
- }
74415
- function isNonProductionEnv() {
74416
- if (typeof globalThis === "undefined") return true;
74417
- return globalThis.process?.env?.NODE_ENV !== "production";
74418
- }
74419
- //#endregion
74420
- //#region ../blocks/src/system/data/utils.ts
74421
- /**
74422
- * Normalize data loaders from block definition
74423
- */
74424
- function normalizeDataLoaders(def) {
74425
- if (!def?.dataLoaders) return [];
74426
- return Object.entries(def.dataLoaders).map(([key, loader]) => ({
74427
- key,
74428
- loader
74429
- }));
74430
- }
74431
- /**
74432
- * Normalize block content for data loading.
74433
- * Priority: draftContent > content > publishedContent
74434
- */
74435
- function normalizeContent(block) {
74436
- const source = block.draftContent ?? block.content ?? block.publishedContent ?? {};
74437
- if (!isObjectRecord$1(source)) return {};
74438
- if ("data" in source) {
74439
- const data = source.data;
74440
- if (isObjectRecord$1(data)) return data;
74441
- if (data === null || data === void 0) return {};
74442
- }
74443
- return source;
74444
- }
74445
- /**
74446
- * Normalize params for API calls.
74447
- * Converts supplied values to strings, preserving absent versus explicitly empty params.
74448
- */
74449
- function normalizeParams(input) {
74450
- if (!input || typeof input !== "object") return {};
74451
- const output = {};
74452
- for (const [key, value] of Object.entries(input)) if (value !== void 0 && value !== null) output[key] = coerceToString(value);
74453
- return output;
74454
- }
74455
- function isNonArrayObject(value) {
74456
- return typeof value === "object" && value !== null && !Array.isArray(value);
74457
- }
74458
- function safeJsonStringify(value) {
74459
- try {
74460
- return JSON.stringify(value);
74461
- } catch {
74462
- return;
74463
- }
74464
- }
74465
- /**
74466
- * Coerce value to string for API params
74015
+ * Coerce value to string for API params
74467
74016
  */
74468
74017
  function coerceToString(value) {
74469
74018
  if (value === null || value === void 0) return "";
@@ -74739,9 +74288,17 @@ function readBlockContentId(value, name) {
74739
74288
  function readTransportedBlockIdentity(block, kind, stage) {
74740
74289
  return {
74741
74290
  draftContentId: readBlockContentId(block.draftContentId, "draft content id"),
74742
- publishedPlacement: stage === "preview" ? readPublishedBlockPlacement(readBlockContentId(block.publishedContentId, "published content id"), sanitizeNullableSdkRuntimeBlockContent(kind, readNestedContentRecord(block.publishedContent))) : null
74291
+ publishedPlacement: stage === "preview" ? readSdkPreviewPublishedPlacement(block, kind) : null
74743
74292
  };
74744
74293
  }
74294
+ /** Pair SDK preview publication data whether it is transported or already admitted. */
74295
+ function readSdkPreviewPublishedPlacement(block, kind) {
74296
+ if (block.publishedPlacement !== void 0 && block.publishedPlacement !== null) {
74297
+ if (!isRecord$3(block.publishedPlacement)) throw new Error("Invalid published placement in page");
74298
+ return readPublishedBlockPlacement(readBlockContentId(block.publishedPlacement.id, "published content id"), sanitizeNullableSdkRuntimeBlockContent(kind, readContentRecord(block.publishedPlacement.content) ?? null));
74299
+ }
74300
+ return readPublishedBlockPlacement(readBlockContentId(block.publishedContentId, "published content id"), sanitizeNullableSdkRuntimeBlockContent(kind, readSdkPublishedContentRecord(block.publishedContent)));
74301
+ }
74745
74302
  function convertPageResponseBlock(block, stage) {
74746
74303
  if (!isRecord$3(block)) throw new Error("Invalid block format in page API response");
74747
74304
  const header = readTransportedBlockHeader(block);
@@ -74754,98 +74311,812 @@ function convertPageResponseBlock(block, stage) {
74754
74311
  ...admission ? { admission } : {}
74755
74312
  };
74756
74313
  }
74757
- function readTransportedBlockHeader(block) {
74758
- if (typeof block.id !== "string" && block.id !== null) throw new Error(`Invalid block id in page: expected string or null, got ${typeof block.id}`);
74759
- if (typeof block.kind !== "string") throw new Error(`Invalid block kind in page: expected string, got ${typeof block.kind}`);
74760
- if (typeof block.purpose !== "string") throw new Error(`Invalid block purpose in page: expected string, got ${typeof block.purpose}`);
74761
- if (block.contentVersionId !== void 0 && block.contentVersionId !== null && typeof block.contentVersionId !== "string") throw new Error(`Invalid content version id in page: expected string or null, got ${typeof block.contentVersionId}`);
74314
+ function readTransportedBlockHeader(block) {
74315
+ if (typeof block.id !== "string" && block.id !== null) throw new Error(`Invalid block id in page: expected string or null, got ${typeof block.id}`);
74316
+ if (typeof block.kind !== "string") throw new Error(`Invalid block kind in page: expected string, got ${typeof block.kind}`);
74317
+ if (typeof block.purpose !== "string") throw new Error(`Invalid block purpose in page: expected string, got ${typeof block.purpose}`);
74318
+ if (block.contentVersionId !== void 0 && block.contentVersionId !== null && typeof block.contentVersionId !== "string") throw new Error(`Invalid content version id in page: expected string or null, got ${typeof block.contentVersionId}`);
74319
+ return {
74320
+ id: block.id,
74321
+ ...block.contentVersionId !== void 0 ? { contentVersionId: block.contentVersionId } : {},
74322
+ kind: block.kind,
74323
+ purpose: block.purpose
74324
+ };
74325
+ }
74326
+ function readInvalidBlockAdmission(value) {
74327
+ if (!isRecord$3(value) || value.kind !== "invalid" || !isRecord$3(value.error)) return null;
74328
+ if (value.error.kind !== "invalid_manifest_content" && value.error.kind !== "manifest_unavailable") return null;
74329
+ return value;
74330
+ }
74331
+ function buildPageOutline(input) {
74332
+ return {
74333
+ name: input.name,
74334
+ path: input.path ?? input.fallbackPath,
74335
+ purpose: input.purpose,
74336
+ blocks: input.blocks.map((block) => convertPageResponseBlock(block, input.previewStage))
74337
+ };
74338
+ }
74339
+ function buildRenderablePageOutline(input) {
74340
+ const page = buildPageOutline(input);
74341
+ return {
74342
+ ...page,
74343
+ blocks: page.blocks.map((block) => admitSdkRuntimePageBlock(block, input.customBlocks))
74344
+ };
74345
+ }
74346
+ function admitSdkRuntimePageBlock(block, customBlocks) {
74347
+ const base = {
74348
+ id: block.id,
74349
+ draftContentId: block.draftContentId,
74350
+ publishedPlacement: block.publishedPlacement,
74351
+ ...block.contentVersionId !== void 0 ? { contentVersionId: block.contentVersionId } : {},
74352
+ kind: block.kind,
74353
+ purpose: block.purpose,
74354
+ ...block.bindings ? { bindings: block.bindings } : {}
74355
+ };
74356
+ const transportedAdmission = readInvalidBlockAdmission(block.admission);
74357
+ if (transportedAdmission) return invalidRenderableBlock(base, transportedAdmission.error);
74358
+ const manifest = resolveSdkBlockManifest(block.kind, customBlocks);
74359
+ if (!manifest) return invalidRenderableBlock(base, { kind: "manifest_unavailable" });
74360
+ const content = block.content ?? {};
74361
+ const renderable = admitTransportedRenderableManifestContent(compileManifestContentContract(manifest), content);
74362
+ if (!renderable.ok) return invalidRenderableBlock(base, {
74363
+ kind: "invalid_manifest_content",
74364
+ error: renderable.error
74365
+ });
74366
+ return {
74367
+ ...base,
74368
+ admission: {
74369
+ kind: "renderable",
74370
+ content: renderable.value
74371
+ }
74372
+ };
74373
+ }
74374
+ function resolveSdkBlockManifest(blockKind, customBlocks) {
74375
+ const customBlock = customBlocks?.find((candidate) => candidate.id === blockKind);
74376
+ return customBlock ? parseFieldDefinitions(customBlock.fields) : getBlockDefinition(blockKind)?.manifest ?? null;
74377
+ }
74378
+ function invalidRenderableBlock(block, error) {
74379
+ return {
74380
+ ...block,
74381
+ admission: {
74382
+ kind: "invalid",
74383
+ error
74384
+ }
74385
+ };
74386
+ }
74387
+ function isRecord$3(value) {
74388
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
74389
+ }
74390
+ function readContentRecord(value) {
74391
+ return isRecord$3(value) ? value : void 0;
74392
+ }
74393
+ function readNestedContentRecord(value) {
74394
+ if (!isRecord$3(value)) return null;
74395
+ return readContentRecord(value.data) ?? null;
74396
+ }
74397
+ function readSdkPublishedContentRecord(value) {
74398
+ if (!isRecord$3(value)) return null;
74399
+ return "data" in value ? readContentRecord(value.data) ?? null : value;
74400
+ }
74401
+ function sanitizeSdkRuntimeBlockContent(blockKind, content) {
74402
+ if (blockKind !== "block.newsletter-signup") return content;
74403
+ const sanitized = sanitizeNewsletterSignupPublicContent(content);
74404
+ return isRecord$3(sanitized) ? sanitized : {};
74405
+ }
74406
+ function sanitizeNullableSdkRuntimeBlockContent(blockKind, content) {
74407
+ return content ? sanitizeSdkRuntimeBlockContent(blockKind, content) : null;
74408
+ }
74409
+ //#endregion
74410
+ //#region src/rendering/blocks-page-renderer.ts
74411
+ const MissingBlockOverrideError = MissingBlockOverrideError$1;
74412
+ function isOverrideOnlyPageRenderer(props) {
74413
+ return props.rendering?.kind === "overrides-only";
74414
+ }
74415
+ function normalizeSdkCustomBlocks(customBlocks) {
74416
+ if (!customBlocks) return void 0;
74417
+ return customBlocks.map((block) => {
74418
+ return {
74419
+ ...block,
74420
+ fields: parseFieldDefinitions(block.fields)
74421
+ };
74422
+ });
74423
+ }
74424
+ function toBlocksBlockOverrides(overrides) {
74425
+ if (!overrides) return void 0;
74426
+ const result = {};
74427
+ for (const [key, OverrideComponent] of Object.entries(overrides)) result[key] = function BlocksOverrideAdapter(props) {
74428
+ const sdkOverride = OverrideComponent;
74429
+ return React$1.createElement(sdkOverride, {
74430
+ ...props,
74431
+ entrySubrouteContext: props.entrySubrouteContext
74432
+ });
74433
+ };
74434
+ return result;
74435
+ }
74436
+ function toBlocksPageRendererDataContext(dataContext) {
74437
+ return {
74438
+ ...dataContext,
74439
+ mediaAssets: toBlocksMediaAssets(dataContext.mediaAssets),
74440
+ imageResolveContext: toBlocksImageResolveContextInput(dataContext.imageResolveContext)
74441
+ };
74442
+ }
74443
+ function toBlocksCommonProps(props) {
74444
+ return {
74445
+ page: props.page,
74446
+ runtimeJoins: props.runtimeJoins,
74447
+ dataContext: toBlocksPageRendererDataContext(props.dataContext),
74448
+ routeMap: props.routeMap,
74449
+ wrapBlock: props.wrapBlock,
74450
+ registry: props.registry,
74451
+ blockOverrides: toBlocksBlockOverrides(props.blockOverrides),
74452
+ sdkConfig: props.sdkConfig ? { customBlocks: normalizeSdkCustomBlocks(props.sdkConfig.customBlocks) } : props.sdkConfig,
74453
+ customBlocks: normalizeSdkCustomBlocks(props.customBlocks)
74454
+ };
74455
+ }
74456
+ function PageRenderer(props) {
74457
+ const commonBlocksProps = toBlocksCommonProps(props);
74458
+ const blocksProps = isOverrideOnlyPageRenderer(props) ? {
74459
+ ...commonBlocksProps,
74460
+ rendering: { kind: "overrides-only" },
74461
+ blockOverrides: toBlocksBlockOverrides(props.blockOverrides) ?? {}
74462
+ } : {
74463
+ ...commonBlocksProps,
74464
+ theme: parseBlocksTheme(props.theme),
74465
+ themeTokens: props.themeTokens
74466
+ };
74467
+ return React$1.createElement(PageRenderer$1, blocksProps);
74468
+ }
74469
+ //#endregion
74470
+ //#region src/rendering/blocks-theme-scope.ts
74471
+ function ThemeScope(props) {
74472
+ const { theme, children, ...rest } = props;
74473
+ const blocksTheme = parseBlocksTheme(theme);
74474
+ return React$1.createElement(ThemeScope$1, {
74475
+ ...rest,
74476
+ theme: blocksTheme,
74477
+ children: children ?? null
74478
+ });
74479
+ }
74480
+ //#endregion
74481
+ //#region src/rendering/themeRuntime.tsx
74482
+ const defaultLayoutThemeRuntime = { kind: "cms-theme" };
74483
+ const defaultSdkChromeThemeRuntime = { kind: "responsive-only" };
74484
+ const defaultPageThemeRuntime = { kind: "none" };
74485
+ function planLayoutThemeRuntime(input) {
74486
+ const requested = input.themeRuntime ?? defaultLayoutThemeRuntime;
74487
+ if (requested.kind === "none" && input.usesSdkChrome) {
74488
+ if (process.env.NODE_ENV !== "production") console.warn("[sdk] Layout themeRuntime { kind: \"none\" } is not compatible with SDK-managed header/footer chrome; using responsive-only runtime instead.");
74489
+ return defaultSdkChromeThemeRuntime;
74490
+ }
74491
+ return requested;
74492
+ }
74493
+ function renderWithSdkThemeRuntime({ themeRuntime, theme, children }) {
74494
+ switch (themeRuntime.kind) {
74495
+ case "cms-theme": return /* @__PURE__ */ jsx(ThemeScope, {
74496
+ theme,
74497
+ responsiveMode: themeRuntime.responsiveMode,
74498
+ children
74499
+ });
74500
+ case "responsive-only": return /* @__PURE__ */ jsx(ResponsiveScope, {
74501
+ responsiveMode: themeRuntime.responsiveMode,
74502
+ children
74503
+ });
74504
+ case "none": return /* @__PURE__ */ jsx(Fragment, { children });
74505
+ default: return assertNever$4(themeRuntime);
74506
+ }
74507
+ }
74508
+ function renderWithOverrideOnlyRuntime({ runtime, children }) {
74509
+ switch (runtime.kind) {
74510
+ case "responsive-only": return /* @__PURE__ */ jsx(ResponsiveScope, {
74511
+ responsiveMode: runtime.responsiveMode,
74512
+ children
74513
+ });
74514
+ case "none": return /* @__PURE__ */ jsx(Fragment, { children });
74515
+ default: return assertNever$4(runtime);
74516
+ }
74517
+ }
74518
+ //#endregion
74519
+ //#region src/rendering/components/pageShared.tsx
74520
+ function isOverrideOnlyPage(props) {
74521
+ return props.rendering?.kind === "overrides-only";
74522
+ }
74523
+ function resolvePageThemeTokens(props) {
74524
+ const baseTokens = props.themeTokens ?? buildThemeRuntime(props.theme).tokens;
74525
+ return props.sdkConfig?.theme?.palette ? {
74526
+ ...baseTokens,
74527
+ palette: {
74528
+ ...baseTokens.palette,
74529
+ ...props.sdkConfig.theme.palette
74530
+ }
74531
+ } : baseTokens;
74532
+ }
74533
+ function resolveSdkBookingTimeZone(timeZone) {
74534
+ return timeZone ?? "UTC";
74535
+ }
74536
+ function buildPageRouteRenderContext(dataContext) {
74537
+ return {
74538
+ ...buildPageIdentityRenderContext(dataContext),
74539
+ occurrenceContext: dataContext.occurrenceContext ?? null,
74540
+ entrySubrouteContext: dataContext.entrySubrouteContext ?? null,
74541
+ contentEntry: dataContext.contentEntry ?? null,
74542
+ pageSurface: dataContext.pageSurface ?? null,
74543
+ subject: dataContext.subject ?? null,
74544
+ editableRouteMetadataFieldIds: dataContext.editableRouteMetadataFieldIds ?? null,
74545
+ previewStage: dataContext.previewStage
74546
+ };
74547
+ }
74548
+ function buildPageIdentityRenderContext(dataContext) {
74549
+ return {
74550
+ demoEmailSuppressed: dataContext.demoEmailSuppressed,
74551
+ siteName: dataContext.siteName,
74552
+ pathname: dataContext.pathname
74553
+ };
74554
+ }
74555
+ function PageContent(props) {
74556
+ const { page, runtimeJoins, siteId, resolvedData, bookingOfferingPresets, mailingList, bookingTimeZone, routeMap, pagesByIdentifier, entriesByIdentifier, wrapBlock, registry, blockOverrides, sdkConfig, customBlocks, supabaseUrl, mediaAssets, apiBaseUrl, portalToken, previewToken, readAuthority, dataContext } = props;
74557
+ const rendererCommonProps = {
74558
+ page,
74559
+ runtimeJoins,
74560
+ dataContext: {
74561
+ siteId,
74562
+ ...buildPageRouteRenderContext(dataContext),
74563
+ apiBaseUrl,
74564
+ portalToken,
74565
+ previewToken,
74566
+ readAuthority: readAuthority ?? dataContext.readAuthority,
74567
+ resolvedData,
74568
+ bookingOfferingPresets: bookingOfferingPresets ?? [],
74569
+ mailingList: mailingList ?? dataContext.mailingList,
74570
+ bookingTimeZone: resolveSdkBookingTimeZone(bookingTimeZone),
74571
+ routes: routeMap,
74572
+ pagesByIdentifier,
74573
+ entriesByIdentifier,
74574
+ supabaseUrl,
74575
+ mediaAssets,
74576
+ imageResolveContext: {
74577
+ siteId,
74578
+ supabaseUrl,
74579
+ mediaAssets
74580
+ }
74581
+ },
74582
+ routeMap,
74583
+ wrapBlock,
74584
+ registry,
74585
+ sdkConfig: sdkConfig ? { customBlocks: sdkConfig.customBlocks } : null,
74586
+ customBlocks
74587
+ };
74588
+ const content = isOverrideOnlyPage(props) ? /* @__PURE__ */ jsx(PageRenderer, {
74589
+ ...rendererCommonProps,
74590
+ rendering: { kind: "overrides-only" },
74591
+ blockOverrides: props.blockOverrides
74592
+ }) : /* @__PURE__ */ jsx(PageRenderer, {
74593
+ ...rendererCommonProps,
74594
+ theme: props.theme,
74595
+ themeTokens: resolvePageThemeTokens(props),
74596
+ blockOverrides
74597
+ });
74598
+ return isOverrideOnlyPage(props) ? renderWithOverrideOnlyRuntime({
74599
+ runtime: props.rendering.runtime,
74600
+ children: content
74601
+ }) : renderWithSdkThemeRuntime({
74602
+ themeRuntime: props.themeRuntime ?? defaultPageThemeRuntime,
74603
+ theme: props.theme,
74604
+ children: content
74605
+ });
74606
+ }
74607
+ //#endregion
74608
+ //#region src/rendering/components/Page.server.tsx
74609
+ function Page(props) {
74610
+ return /* @__PURE__ */ jsx(PageContent, { ...props });
74611
+ }
74612
+ //#endregion
74613
+ //#region src/env.ts
74614
+ /**
74615
+ * Error thrown when required environment variables are missing
74616
+ */
74617
+ var RiverbankEnvError = class extends Error {
74618
+ constructor(message, missingVars) {
74619
+ super(message);
74620
+ this.missingVars = missingVars;
74621
+ this.name = "RiverbankEnvError";
74622
+ }
74623
+ };
74624
+ /**
74625
+ * Get the environment variable prefix based on target
74626
+ */
74627
+ function getEnvPrefix(target) {
74628
+ return target === "remote" ? "RIVERBANK_REMOTE" : "RIVERBANK_LOCAL";
74629
+ }
74630
+ /**
74631
+ * Detect the environment target from RIVERBANK_ENV
74632
+ */
74633
+ function detectTarget() {
74634
+ const env = process.env.RIVERBANK_ENV?.toLowerCase();
74635
+ if (env === "remote" || env === "production" || env === "prod") return "remote";
74636
+ return "local";
74637
+ }
74638
+ /**
74639
+ * Detect if preview mode is enabled.
74640
+ * Uses RIVERBANK_PREVIEW_MODE first, then falls back to RIVERBANK_PREVIEW for backward compat.
74641
+ */
74642
+ function detectPreviewMode() {
74643
+ const previewMode = process.env.RIVERBANK_PREVIEW_MODE;
74644
+ if (previewMode !== void 0 && previewMode !== "") return previewMode === "true";
74645
+ const previewLegacy = process.env.RIVERBANK_PREVIEW;
74646
+ if (previewLegacy !== void 0 && previewLegacy !== "") return previewLegacy === "true";
74647
+ return process.env.VERCEL_ENV === "preview";
74648
+ }
74649
+ /**
74650
+ * Validate that an API key matches the expected format for its type
74651
+ */
74652
+ function validateKeyType(key, expectedType) {
74653
+ const isPreviewKey = key.startsWith("bld_preview_sk_");
74654
+ const isContentKey = key.startsWith("bld_live_sk_");
74655
+ if (expectedType === "preview" && !isPreviewKey) {
74656
+ if (isContentKey) throw new RiverbankEnvError("Preview mode is enabled (RIVERBANK_PREVIEW_MODE=true) but a content key was provided. Preview mode requires a preview API key (bld_preview_sk_...) to access draft content. Either:\n 1. Set RIVERBANK_*_PREVIEW_API_KEY with your preview key, or\n 2. Set RIVERBANK_PREVIEW_MODE=false to fetch published content instead.", []);
74657
+ throw new RiverbankEnvError(`Invalid API key format for preview mode. Expected key starting with bld_preview_sk_`, []);
74658
+ }
74659
+ if (expectedType === "content" && !isContentKey) {
74660
+ if (isPreviewKey) {
74661
+ console.debug("[getRiverbankEnv] Using preview key for published content. Consider using a content key (bld_live_sk_...) for production.");
74662
+ return;
74663
+ }
74664
+ throw new RiverbankEnvError(`Invalid API key format for content access. Expected key starting with bld_live_sk_ or bld_preview_sk_`, []);
74665
+ }
74666
+ }
74667
+ /**
74668
+ * Get runtime environment configuration with automatic API key selection.
74669
+ *
74670
+ * This helper reads environment variables and automatically selects the correct
74671
+ * API key based on the current environment and preview mode:
74672
+ *
74673
+ * - When `RIVERBANK_PREVIEW_MODE=true`: Uses preview API key (bld_preview_sk_...)
74674
+ * - When `RIVERBANK_PREVIEW_MODE=false` (default): Uses content API key (bld_live_sk_...)
74675
+ *
74676
+ * Environment variable patterns:
74677
+ * - `RIVERBANK_ENV`: 'local' (default) or 'remote'
74678
+ * - `RIVERBANK_PREVIEW_MODE`: 'true' or 'false' (default)
74679
+ * - `RIVERBANK_{LOCAL|REMOTE}_SITE_ID`: Site ID
74680
+ * - `RIVERBANK_{LOCAL|REMOTE}_DASHBOARD_URL`: Dashboard URL
74681
+ * - `RIVERBANK_{LOCAL|REMOTE}_API_KEY`: Content/live API key
74682
+ * - `RIVERBANK_{LOCAL|REMOTE}_PREVIEW_API_KEY`: Preview API key
74683
+ *
74684
+ * @returns Environment configuration with auto-selected API key
74685
+ * @throws {RiverbankEnvError} If required environment variables are missing
74686
+ *
74687
+ * @example
74688
+ * ```ts
74689
+ * // lib/builder-client.ts
74690
+ * import { getRiverbankEnv } from '@riverbankcms/sdk/env';
74691
+ * import { createRiverbankClient } from '@riverbankcms/sdk';
74692
+ *
74693
+ * const env = getRiverbankEnv();
74694
+ *
74695
+ * export const client = createRiverbankClient({
74696
+ * apiKey: env.apiKey,
74697
+ * baseUrl: env.baseUrl,
74698
+ * });
74699
+ *
74700
+ * export const siteId = env.siteId;
74701
+ * ```
74702
+ */
74703
+ function getRiverbankEnv() {
74704
+ const target = detectTarget();
74705
+ const previewMode = detectPreviewMode();
74706
+ const prefix = getEnvPrefix(target);
74707
+ const siteId = process.env[`${prefix}_SITE_ID`];
74708
+ const dashboardUrl = process.env[`${prefix}_DASHBOARD_URL`];
74709
+ const contentKey = process.env[`${prefix}_API_KEY`];
74710
+ const previewKey = process.env[`${prefix}_PREVIEW_API_KEY`];
74711
+ const missingVars = [];
74712
+ if (!siteId) missingVars.push(`${prefix}_SITE_ID`);
74713
+ if (!dashboardUrl) missingVars.push(`${prefix}_DASHBOARD_URL`);
74714
+ let apiKey;
74715
+ let keyType;
74716
+ if (previewMode) {
74717
+ apiKey = previewKey;
74718
+ keyType = "preview";
74719
+ if (!apiKey) missingVars.push(`${prefix}_PREVIEW_API_KEY`);
74720
+ } else {
74721
+ apiKey = contentKey || previewKey;
74722
+ keyType = contentKey ? "content" : "preview";
74723
+ if (!apiKey) missingVars.push(`${prefix}_API_KEY`);
74724
+ }
74725
+ if (missingVars.length > 0) throw new RiverbankEnvError(`Missing required environment variables for Riverbank SDK:\n` + missingVars.map((v) => ` - ${v}`).join("\n") + `\n\nCurrent settings: RIVERBANK_ENV=${process.env.RIVERBANK_ENV || "local"}, RIVERBANK_PREVIEW_MODE=${process.env.RIVERBANK_PREVIEW_MODE || "false"}`, missingVars);
74726
+ if (!apiKey || !dashboardUrl || !siteId) throw new RiverbankEnvError("Required environment variables missing", missingVars);
74727
+ validateKeyType(apiKey, keyType);
74728
+ let baseUrl = dashboardUrl;
74729
+ if (!baseUrl.endsWith("/api")) baseUrl = baseUrl.replace(/\/$/, "") + "/api";
74730
+ return {
74731
+ target,
74732
+ previewMode,
74733
+ siteId,
74734
+ baseUrl,
74735
+ apiKey,
74736
+ keyType
74737
+ };
74738
+ }
74739
+ //#endregion
74740
+ //#region src/navigation/index.ts
74741
+ /**
74742
+ * Get the fixed main navigation menu object.
74743
+ * Returns null when the runtime payload is incomplete.
74744
+ *
74745
+ * @example
74746
+ * ```ts
74747
+ * const menu = getPrimaryNavigation(siteData.navigation);
74748
+ * console.log(menu?.location); // "main"
74749
+ * ```
74750
+ */
74751
+ function getPrimaryNavigation(navigation) {
74752
+ if (!navigation || navigation.length === 0) return null;
74753
+ return navigation.find((menu) => menu.location === "main") ?? null;
74754
+ }
74755
+ function getFooterNavigationByRole(navigation, role) {
74756
+ if (!navigation || navigation.length === 0) return null;
74757
+ const canonicalLocation = role === "main" ? "footer" : "legal";
74758
+ return navigation.find((menu) => menu.location === canonicalLocation) ?? null;
74759
+ }
74760
+ /**
74761
+ * Resolve alt text with fallback.
74762
+ * Returns the provided alt if non-empty, otherwise falls back to the provided fallback or 'Site logo'.
74763
+ * @internal
74764
+ */
74765
+ function resolveAltText(alt, fallback) {
74766
+ return alt && alt.trim().length > 0 ? alt : fallback ?? "Site logo";
74767
+ }
74768
+ function readNavigationItemPayload(item) {
74769
+ return item.url ?? null;
74770
+ }
74771
+ function isPortalEnabled(options) {
74772
+ return options?.portalEnabled === true;
74773
+ }
74774
+ function isCommerceEnabled(options) {
74775
+ return options?.commerceEnabled === true;
74776
+ }
74777
+ function resolvePortalHref(link) {
74778
+ return link.path?.trim() || "/portal";
74779
+ }
74780
+ function resolveCheckoutHref(options) {
74781
+ if (options?.checkoutHref === null) return null;
74782
+ const href = options?.checkoutHref?.trim();
74783
+ return href && href.length > 0 ? href : "/checkout";
74784
+ }
74785
+ function resolvePortalLabel(link, options) {
74786
+ const loggedOutLabel = link.labels?.loggedOut?.trim() || PORTAL_NAV_DEFAULT_LABELS.loggedOut;
74787
+ const loggedInLabel = link.labels?.loggedIn?.trim() || PORTAL_NAV_DEFAULT_LABELS.loggedIn;
74788
+ return options?.hasPortalSession ? loggedInLabel : loggedOutLabel;
74789
+ }
74790
+ function resolveItemLabel(link, fallbackLabel, options) {
74791
+ if (link?.kind === "portal") return resolvePortalLabel(link, options);
74792
+ if (link?.kind === "cart") return resolveCartVisibleLabel(link) ?? fallbackLabel;
74793
+ return fallbackLabel;
74794
+ }
74795
+ function resolveCartVisibleLabel(link) {
74796
+ if (link.label.kind !== "icon-with-label") return null;
74797
+ const label = link.label.label.trim();
74798
+ return label.length > 0 ? label : null;
74799
+ }
74800
+ function resolveCartAriaLabel(link, fallbackLabel) {
74801
+ const fallback = fallbackLabel.trim();
74802
+ return resolveCartVisibleLabel(link) ?? (fallback.length > 0 ? fallback : "Cart");
74803
+ }
74804
+ function buildCartNavViewModel(link, fallbackLabel, options) {
74805
+ return {
74806
+ visibleLabel: resolveCartVisibleLabel(link),
74807
+ badge: link.badge,
74808
+ ariaLabel: resolveCartAriaLabel(link, fallbackLabel),
74809
+ checkoutHref: resolveCheckoutHref(options)
74810
+ };
74811
+ }
74812
+ function deriveRenderableNavigationLink(item, options) {
74813
+ const payload = readNavigationItemPayload(item);
74814
+ if (!payload) return null;
74815
+ if (payload.kind === "portal" && !isPortalEnabled(options)) return null;
74816
+ if (payload.kind === "cart" && !isCommerceEnabled(options)) return null;
74762
74817
  return {
74763
- id: block.id,
74764
- ...block.contentVersionId !== void 0 ? { contentVersionId: block.contentVersionId } : {},
74765
- kind: block.kind,
74766
- purpose: block.purpose
74818
+ id: item.id,
74819
+ label: resolveItemLabel(payload, item.label, options),
74820
+ payload,
74821
+ isExternal: isExternalLink(payload),
74822
+ ...payload.kind === "cart" ? { cart: buildCartNavViewModel(payload, item.label, options) } : {}
74767
74823
  };
74768
74824
  }
74769
- function readInvalidBlockAdmission(value) {
74770
- if (!isRecord$3(value) || value.kind !== "invalid" || !isRecord$3(value.error)) return null;
74771
- if (value.error.kind !== "invalid_manifest_content" && value.error.kind !== "manifest_unavailable") return null;
74772
- return value;
74773
- }
74774
- function buildPageOutline(input) {
74825
+ function buildNavLinkFromResolvedHref(item, href) {
74826
+ if (!href) return null;
74775
74827
  return {
74776
- name: input.name,
74777
- path: input.path ?? input.fallbackPath,
74778
- purpose: input.purpose,
74779
- blocks: input.blocks.map((block) => convertPageResponseBlock(block, input.previewStage))
74828
+ kind: "link",
74829
+ id: item.id,
74830
+ label: item.label,
74831
+ href,
74832
+ link: { href },
74833
+ isExternal: item.isExternal,
74834
+ ...item.cart ? { cart: item.cart } : {}
74780
74835
  };
74781
74836
  }
74782
- function buildRenderablePageOutline(input) {
74783
- const page = buildPageOutline(input);
74837
+ /**
74838
+ * Determines if a navigation item's link is external.
74839
+ */
74840
+ function isExternalLink(link) {
74841
+ if (!link) return false;
74842
+ return link.kind === "external";
74843
+ }
74844
+ /**
74845
+ * Build a map of children items by parent ID.
74846
+ * Also warns about deeply nested items (grandchildren) which CMS shouldn't allow.
74847
+ * @internal
74848
+ */
74849
+ function buildChildrenByParentId(items) {
74850
+ const childrenByParentId = /* @__PURE__ */ new Map();
74851
+ const itemsById = /* @__PURE__ */ new Map();
74852
+ for (const item of items) itemsById.set(item.id, item);
74853
+ for (const item of items) if (item.parentId) {
74854
+ if (itemsById.get(item.parentId)?.parentId && typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
74855
+ console.warn(`[SDK Navigation] Deeply nested item detected: "${item.label}" (id: ${item.id}). Only 1 level of nesting is supported. This item will be ignored.`);
74856
+ continue;
74857
+ }
74858
+ const siblings = childrenByParentId.get(item.parentId) ?? [];
74859
+ siblings.push(item);
74860
+ childrenByParentId.set(item.parentId, siblings);
74861
+ }
74862
+ return childrenByParentId;
74863
+ }
74864
+ /**
74865
+ * Generic nested structure builder.
74866
+ * @internal
74867
+ */
74868
+ function buildNestedStructure(items, options) {
74869
+ const childrenByParentId = buildChildrenByParentId(items);
74870
+ const rootItems = items.filter((item) => !item.parentId).sort((a, b) => (a.orderIndex ?? a.position ?? 0) - (b.orderIndex ?? b.position ?? 0));
74871
+ const result = [];
74872
+ let ctaItem = null;
74873
+ for (const item of rootItems) {
74874
+ if (options.extractCta && !ctaItem && Boolean(item.isCta) && item.urlType !== "dropdown") {
74875
+ const link = options.toLink(item);
74876
+ if (link) {
74877
+ ctaItem = link;
74878
+ continue;
74879
+ }
74880
+ }
74881
+ const childRecords = childrenByParentId.get(item.id) ?? [];
74882
+ const hasChildren = childRecords.length > 0;
74883
+ if (item.urlType === "dropdown" || hasChildren) {
74884
+ const children = childRecords.sort((a, b) => (a.orderIndex ?? a.position ?? 0) - (b.orderIndex ?? b.position ?? 0)).map(options.toLink).filter((child) => child !== null);
74885
+ if (children.length > 0) result.push(options.createDropdown(item.id, item.label, children));
74886
+ continue;
74887
+ }
74888
+ const link = options.toLink(item);
74889
+ if (link) result.push(link);
74890
+ }
74784
74891
  return {
74785
- ...page,
74786
- blocks: page.blocks.map((block) => admitSdkRuntimePageBlock(block, input.customBlocks))
74892
+ items: result,
74893
+ ctaItem
74787
74894
  };
74788
74895
  }
74789
- function admitSdkRuntimePageBlock(block, customBlocks) {
74790
- const base = {
74791
- id: block.id,
74792
- draftContentId: block.draftContentId,
74793
- publishedPlacement: block.publishedPlacement,
74794
- ...block.contentVersionId !== void 0 ? { contentVersionId: block.contentVersionId } : {},
74795
- kind: block.kind,
74796
- purpose: block.purpose,
74797
- ...block.bindings ? { bindings: block.bindings } : {}
74896
+ /**
74897
+ * Build a Menu from navigation data with pre-resolved hrefs.
74898
+ * Supports dropdown containers with nested children.
74899
+ *
74900
+ * @param navigation - Navigation menus from site data
74901
+ * @param routes - Route map for resolving internal links
74902
+ * @param options - Include identifier maps to resolve canonical `page`/`entry` links.
74903
+ *
74904
+ * @example
74905
+ * ```ts
74906
+ * const menu = buildMenu(siteData.navigation, siteData.routes, {
74907
+ * pagesByIdentifier: siteData.pagesByIdentifier,
74908
+ * entriesByIdentifier: siteData.entriesByIdentifier,
74909
+ * });
74910
+ * menu.items.forEach(item => {
74911
+ * if (item.kind === 'dropdown') {
74912
+ * console.log(item.children);
74913
+ * }
74914
+ * });
74915
+ * ```
74916
+ */
74917
+ function buildMenu(navigation, routes, options) {
74918
+ const menu = getPrimaryNavigation(navigation);
74919
+ if (!menu) return {
74920
+ items: [],
74921
+ ctaItem: null
74798
74922
  };
74799
- const transportedAdmission = readInvalidBlockAdmission(block.admission);
74800
- if (transportedAdmission) return invalidRenderableBlock(base, transportedAdmission.error);
74801
- const manifest = resolveSdkBlockManifest(block.kind, customBlocks);
74802
- if (!manifest) return invalidRenderableBlock(base, { kind: "manifest_unavailable" });
74803
- const content = block.content ?? {};
74804
- const renderable = admitTransportedRenderableManifestContent(compileManifestContentContract(manifest), content);
74805
- if (!renderable.ok) return invalidRenderableBlock(base, {
74806
- kind: "invalid_manifest_content",
74807
- error: renderable.error
74923
+ const toNavLink = (item) => {
74924
+ const renderable = deriveRenderableNavigationLink(item, options);
74925
+ if (!renderable) return null;
74926
+ return buildNavLinkFromResolvedHref(renderable, resolveHref(renderable.payload, routes, options));
74927
+ };
74928
+ const { items, ctaItem } = buildNestedStructure(menu.items, {
74929
+ toLink: toNavLink,
74930
+ createDropdown: (id, label, children) => ({
74931
+ kind: "dropdown",
74932
+ id,
74933
+ label,
74934
+ children
74935
+ }),
74936
+ extractCta: true
74808
74937
  });
74809
74938
  return {
74810
- ...base,
74811
- admission: {
74812
- kind: "renderable",
74813
- content: renderable.value
74814
- }
74939
+ items,
74940
+ ctaItem: ctaItem ? {
74941
+ ...ctaItem,
74942
+ variant: "primary"
74943
+ } : null
74815
74944
  };
74816
74945
  }
74817
- function resolveSdkBlockManifest(blockKind, customBlocks) {
74818
- const customBlock = customBlocks?.find((candidate) => candidate.id === blockKind);
74819
- return customBlock ? parseFieldDefinitions(customBlock.fields) : getBlockDefinition(blockKind)?.manifest ?? null;
74946
+ /**
74947
+ * Build a Menu from the footer navigation data.
74948
+ * Returns empty menu if no footer menu is designated.
74949
+ *
74950
+ * @param navigation - Navigation menus from site data
74951
+ * @param routes - Route map for resolving internal links
74952
+ * @param options - Include identifier maps to resolve canonical `page`/`entry` links.
74953
+ *
74954
+ * @example
74955
+ * ```ts
74956
+ * const footerMenu = buildFooterMenu(siteData.navigation, siteData.routes, {
74957
+ * pagesByIdentifier: siteData.pagesByIdentifier,
74958
+ * entriesByIdentifier: siteData.entriesByIdentifier,
74959
+ * });
74960
+ * footerMenu.items.forEach(item => {
74961
+ * if (item.kind === 'dropdown') {
74962
+ * // Footer renders children expanded, not as hover dropdowns
74963
+ * console.log(item.children);
74964
+ * }
74965
+ * });
74966
+ * ```
74967
+ */
74968
+ function buildFooterMenu(navigation, routes, options) {
74969
+ return buildFooterMenuForRole(navigation, routes, "main", options);
74820
74970
  }
74821
- function invalidRenderableBlock(block, error) {
74971
+ function buildFooterMenuForRole(navigation, routes, role, options) {
74972
+ const menu = getFooterNavigationByRole(navigation, role);
74973
+ if (!menu) return {
74974
+ items: [],
74975
+ ctaItem: null,
74976
+ groups: [],
74977
+ links: []
74978
+ };
74979
+ const toNavLink = (item) => {
74980
+ const renderable = deriveRenderableNavigationLink(item, options);
74981
+ if (!renderable) return null;
74982
+ return buildNavLinkFromResolvedHref(renderable, resolveHref(renderable.payload, routes, options));
74983
+ };
74984
+ const built = buildNestedStructure(menu.items, {
74985
+ toLink: toNavLink,
74986
+ createDropdown: (id, label, children) => ({
74987
+ kind: "dropdown",
74988
+ id,
74989
+ label,
74990
+ children
74991
+ }),
74992
+ extractCta: false
74993
+ });
74994
+ const groups = built.items.filter((item) => item.kind === "dropdown");
74995
+ const links = built.items.filter((item) => item.kind === "link");
74822
74996
  return {
74823
- ...block,
74824
- admission: {
74825
- kind: "invalid",
74826
- error
74827
- }
74997
+ items: built.items,
74998
+ ctaItem: null,
74999
+ groups,
75000
+ links
74828
75001
  };
74829
75002
  }
74830
- function isRecord$3(value) {
74831
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
75003
+ /**
75004
+ * Resolve href from a link payload using route map.
75005
+ * @internal
75006
+ */
75007
+ function resolveHref(link, routes, options) {
75008
+ if (!link) return null;
75009
+ if (link.kind === "external" || link.kind === "url") return link.href || null;
75010
+ if (link.kind === "portal") return isPortalEnabled(options) ? resolvePortalHref(link) : null;
75011
+ if (link.kind === "cart") return isCommerceEnabled(options) ? resolveCheckoutHref(options) : null;
75012
+ const stage = normalizeRenderStage(options?.previewStage);
75013
+ if (link.kind === "internal") return resolveRouteHrefWithFallback(link.routeId, link.href ?? null, routes, stage);
75014
+ if (link.kind === "page") {
75015
+ const routeIdFromPayload = readRouteIdFromLink(link);
75016
+ const routeIdFromIdentifierMap = options?.pagesByIdentifier?.[link.identifier] ?? null;
75017
+ return resolveRouteHrefWithFallback(routeIdFromPayload ?? routeIdFromIdentifierMap, readHrefFromLink(link), routes, stage);
75018
+ }
75019
+ if (link.kind === "entry") {
75020
+ const routeIdFromPayload = readRouteIdFromLink(link);
75021
+ const routeIdFromIdentifierMap = readEntryRouteIdFromIdentifierMap(options, link.contentType, link.identifier);
75022
+ return resolveRouteHrefWithFallback(routeIdFromPayload ?? routeIdFromIdentifierMap, readHrefFromLink(link), routes, stage);
75023
+ }
75024
+ return null;
74832
75025
  }
74833
- function readContentRecord(value) {
74834
- return isRecord$3(value) ? value : void 0;
75026
+ function resolveRouteHrefWithFallback(routeId, fallbackHref, routes, stage) {
75027
+ if (!routeId) return fallbackHref;
75028
+ const resolved = resolveRouteHrefForStage(routeId, routes, stage);
75029
+ if (resolved) return resolved;
75030
+ const route = routes[routeId];
75031
+ if (!route) return fallbackHref;
75032
+ if (!isRouteVisibleInStage(route, stage)) return null;
75033
+ return fallbackHref;
74835
75034
  }
74836
- function readNestedContentRecord(value) {
74837
- if (!isRecord$3(value)) return null;
74838
- return readContentRecord(value.data) ?? null;
75035
+ function readRouteIdFromLink(link) {
75036
+ if (!("routeId" in link) || typeof link.routeId !== "string") return null;
75037
+ return link.routeId;
74839
75038
  }
74840
- function sanitizeSdkRuntimeBlockContent(blockKind, content) {
74841
- if (blockKind !== "block.newsletter-signup") return content;
74842
- const sanitized = sanitizeNewsletterSignupPublicContent(content);
74843
- return isRecord$3(sanitized) ? sanitized : {};
75039
+ function readHrefFromLink(link) {
75040
+ if (!("href" in link) || typeof link.href !== "string") return null;
75041
+ return link.href;
74844
75042
  }
74845
- function sanitizeNullableSdkRuntimeBlockContent(blockKind, content) {
74846
- return content ? sanitizeSdkRuntimeBlockContent(blockKind, content) : null;
75043
+ function readEntryRouteIdFromIdentifierMap(options, contentType, identifier) {
75044
+ const entryMap = options?.entriesByIdentifier?.[contentType];
75045
+ if (!entryMap) return null;
75046
+ return entryMap[identifier] ?? null;
75047
+ }
75048
+ /**
75049
+ * Build a Logo from site layout data.
75050
+ *
75051
+ * @param logo - Logo data from site layout
75052
+ * @param fallbackAlt - Fallback alt text (usually site title)
75053
+ *
75054
+ * @example
75055
+ * ```ts
75056
+ * const logo = buildLogo(siteData.layout.logo, siteData.site.title);
75057
+ * // { src: 'https://...', alt: 'Site Name', width: 200, height: 50 }
75058
+ * ```
75059
+ */
75060
+ function buildLogo(logo, fallbackAlt) {
75061
+ if (!logo || !logo.url) return null;
75062
+ const alt = resolveAltText(logo.alt, fallbackAlt);
75063
+ const result = {
75064
+ type: "image",
75065
+ src: logo.url,
75066
+ alt
75067
+ };
75068
+ if (logo.width != null) result.width = logo.width;
75069
+ if (logo.height != null) result.height = logo.height;
75070
+ return result;
75071
+ }
75072
+ /**
75073
+ * Build both site logos from layout data. The default header and footer choose
75074
+ * between them by the surface they sit on; custom chrome can do the same.
75075
+ *
75076
+ * @example
75077
+ * ```ts
75078
+ * const logoVariants = buildLogoVariants(siteData.layout, siteData.site.title);
75079
+ * ```
75080
+ */
75081
+ function buildLogoVariants(layout, fallbackAlt) {
75082
+ return {
75083
+ forLightBackgrounds: buildLogo(layout?.logo ?? null, fallbackAlt),
75084
+ forDarkBackgrounds: buildLogo(layout?.logoForDarkBackgrounds ?? null, fallbackAlt)
75085
+ };
75086
+ }
75087
+ /**
75088
+ * Header/footer block content for the site logos. `logo` stays populated with
75089
+ * whichever logo exists so presence checks keep working; `logoVariants` is
75090
+ * what the blocks select from at render.
75091
+ */
75092
+ function buildChromeLogoContent(layout, fallbackAlt) {
75093
+ const logoVariants = buildLogoVariants(layout, fallbackAlt);
75094
+ return {
75095
+ logo: logoVariants.forLightBackgrounds ?? logoVariants.forDarkBackgrounds,
75096
+ logoVariants
75097
+ };
75098
+ }
75099
+ //#endregion
75100
+ //#region src/rendering/themeAdmission.ts
75101
+ const MISSING_SDK_THEME_ERROR_CODE = "missing_sdk_theme";
75102
+ var MissingSdkThemeError = class extends Error {
75103
+ constructor(siteId, reason = "cms_theme_absent", themeKey) {
75104
+ super(`[Riverbank SDK] Site "${siteId}" has no resolvable theme. ` + (themeKey ? `Theme key "${themeKey}" is not present. ` : "") + "Select a CMS theme, provide { theme }, { themes }, or { getTheme }, or use rendering: { kind: 'overrides-only' } with complete block overrides.");
75105
+ this.siteId = siteId;
75106
+ this.reason = reason;
75107
+ this.themeKey = themeKey;
75108
+ this.code = MISSING_SDK_THEME_ERROR_CODE;
75109
+ this.name = "MissingSdkThemeError";
75110
+ }
75111
+ };
75112
+ function requireSdkTheme(theme, siteId, reason = "cms_theme_absent") {
75113
+ if (theme === null || theme === void 0) throw new MissingSdkThemeError(siteId, reason);
75114
+ return theme;
74847
75115
  }
74848
75116
  //#endregion
75117
+ //#region src/rendering/renderingMode.ts
75118
+ const defaultOverrideOnlyRuntime = { kind: "responsive-only" };
75119
+ //#endregion
74849
75120
  //#region src/rendering/helpers/footerPageOutline.ts
74850
75121
  /**
74851
75122
  * Admit footer blocks returned by the site API for public rendering.
@@ -76670,6 +76941,7 @@ const SDK_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
76670
76941
  responseKind: "json",
76671
76942
  errors: [
76672
76943
  "resource:not_found",
76944
+ "validation:invalid_input",
76673
76945
  "resource:conflict",
76674
76946
  "server:internal_error"
76675
76947
  ]
@@ -77124,28 +77396,6 @@ const EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
77124
77396
  "resource:conflict",
77125
77397
  "server:internal_error"
77126
77398
  ]
77127
- },
77128
- /**
77129
- * The Content tab's one write: the short introduction, image and
77130
- * description of an event's page, published without its layout.
77131
- */
77132
- saveEventPageWords: {
77133
- path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/words",
77134
- method: "PUT",
77135
- tags: [
77136
- TAG_TEMPLATES.siteCollection,
77137
- TAG_TEMPLATES.siteRoutableContent,
77138
- TAG_TEMPLATES.pageSurfaceById
77139
- ],
77140
- auth: "user",
77141
- responseKind: "json",
77142
- errors: [
77143
- "auth:forbidden",
77144
- "validation:invalid_input",
77145
- "resource:not_found",
77146
- "resource:conflict",
77147
- "server:internal_error"
77148
- ]
77149
77399
  }
77150
77400
  });
77151
77401
  //#endregion
@@ -77570,6 +77820,15 @@ const BILLING_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
77570
77820
  auth: "user",
77571
77821
  responseKind: "json"
77572
77822
  },
77823
+ /** Continue on Free from the onboarding card page; only the attempt's owner. */
77824
+ continueOnboardingOnFree: {
77825
+ path: "/onboarding/attempts/{attemptToken}/plan/free",
77826
+ method: "POST",
77827
+ tags: ["billing"],
77828
+ auth: "user",
77829
+ errors: [],
77830
+ responseKind: "json"
77831
+ },
77573
77832
  createBillingPortalSession: {
77574
77833
  path: "/billing/portal/session",
77575
77834
  method: "POST",
@@ -77579,6 +77838,161 @@ const BILLING_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
77579
77838
  }
77580
77839
  });
77581
77840
  //#endregion
77841
+ //#region ../api/src/editLeaseEndpoints.ts
77842
+ const path = "/sites/{siteId}/edit-leases/{nodeType}/{nodeId}";
77843
+ const lifecycleErrors = [
77844
+ "auth:lease_required",
77845
+ "auth:forbidden",
77846
+ "resource:not_found",
77847
+ "validation:invalid_input",
77848
+ "server:internal_error"
77849
+ ];
77850
+ const EDIT_LEASE_ENDPOINT_DEFINITIONS = {
77851
+ readEditLease: {
77852
+ path,
77853
+ method: "GET",
77854
+ editLease: "lifecycle",
77855
+ errors: lifecycleErrors,
77856
+ auth: "user",
77857
+ responseKind: "json"
77858
+ },
77859
+ acquireEditLease: {
77860
+ path,
77861
+ method: "POST",
77862
+ editLease: "lifecycle",
77863
+ errors: lifecycleErrors,
77864
+ auth: "user",
77865
+ responseKind: "json"
77866
+ },
77867
+ takeOverEditLease: {
77868
+ path,
77869
+ method: "PUT",
77870
+ editLease: "lifecycle",
77871
+ errors: lifecycleErrors,
77872
+ auth: "user",
77873
+ responseKind: "json"
77874
+ },
77875
+ heartbeatEditLease: {
77876
+ path,
77877
+ method: "PATCH",
77878
+ editLease: "lifecycle",
77879
+ errors: [...lifecycleErrors, "auth:lease_lost"],
77880
+ auth: "user",
77881
+ responseKind: "json"
77882
+ },
77883
+ releaseEditLease: {
77884
+ path,
77885
+ method: "DELETE",
77886
+ editLease: "lifecycle",
77887
+ errors: lifecycleErrors,
77888
+ auth: "user",
77889
+ responseKind: "json"
77890
+ }
77891
+ };
77892
+ //#endregion
77893
+ //#region ../api/src/pageSurfaceEditorEndpoints.ts
77894
+ const surfaceTags = [TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById];
77895
+ const PAGE_SURFACE_EDITOR_ENDPOINT_DEFINITIONS = {
77896
+ getPageSurfaceEditorDocument: {
77897
+ path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/content",
77898
+ method: "GET",
77899
+ errors: [
77900
+ "auth:forbidden",
77901
+ "validation:invalid_input",
77902
+ "resource:not_found",
77903
+ "resource:conflict",
77904
+ "server:internal_error"
77905
+ ],
77906
+ tags: surfaceTags,
77907
+ auth: "user",
77908
+ responseKind: "json"
77909
+ },
77910
+ updatePageSurfaceDraftContent: {
77911
+ editLease: "managed",
77912
+ path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/content",
77913
+ method: "PUT",
77914
+ errors: [
77915
+ "validation:invalid_input",
77916
+ "resource:not_found",
77917
+ "resource:conflict",
77918
+ "server:internal_error"
77919
+ ],
77920
+ tags: surfaceTags,
77921
+ auth: "user",
77922
+ responseKind: "json"
77923
+ },
77924
+ discardPageSurfaceDraftContent: {
77925
+ editLease: "managed",
77926
+ path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/content/draft",
77927
+ method: "DELETE",
77928
+ errors: [
77929
+ "validation:invalid_input",
77930
+ "resource:not_found",
77931
+ "resource:conflict",
77932
+ "server:internal_error"
77933
+ ],
77934
+ tags: surfaceTags,
77935
+ auth: "user",
77936
+ responseKind: "json"
77937
+ },
77938
+ updatePageSurfaceRouteMetadata: {
77939
+ editLease: "managed",
77940
+ path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/metadata",
77941
+ method: "PATCH",
77942
+ errors: [
77943
+ "validation:invalid_input",
77944
+ "resource:not_found",
77945
+ "resource:conflict",
77946
+ "server:internal_error"
77947
+ ],
77948
+ tags: [
77949
+ TAG_TEMPLATES.siteCollection,
77950
+ TAG_TEMPLATES.siteRoutableContent,
77951
+ TAG_TEMPLATES.pageSurfaceById
77952
+ ],
77953
+ auth: "user",
77954
+ responseKind: "json"
77955
+ },
77956
+ publishPageSurface: {
77957
+ editLease: "managed",
77958
+ path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/publication",
77959
+ method: "POST",
77960
+ errors: [
77961
+ "auth:forbidden",
77962
+ "validation:invalid_input",
77963
+ "resource:not_found",
77964
+ "resource:conflict",
77965
+ "server:internal_error"
77966
+ ],
77967
+ tags: [
77968
+ TAG_TEMPLATES.siteCollection,
77969
+ TAG_TEMPLATES.siteRoutableContent,
77970
+ TAG_TEMPLATES.pageSurfaceById
77971
+ ],
77972
+ auth: "user",
77973
+ responseKind: "json"
77974
+ },
77975
+ saveEventContentTab: {
77976
+ editLease: "managed",
77977
+ path: "/sites/{siteId}/page-surfaces/{pageSurfaceId}/event-content",
77978
+ method: "PUT",
77979
+ errors: [
77980
+ "auth:forbidden",
77981
+ "validation:invalid_input",
77982
+ "resource:not_found",
77983
+ "resource:conflict",
77984
+ "server:internal_error"
77985
+ ],
77986
+ tags: [
77987
+ TAG_TEMPLATES.siteCollection,
77988
+ TAG_TEMPLATES.siteRoutableContent,
77989
+ TAG_TEMPLATES.pageSurfaceById
77990
+ ],
77991
+ auth: "user",
77992
+ responseKind: "json"
77993
+ }
77994
+ };
77995
+ //#endregion
77582
77996
  //#region ../api/src/bookingPeopleEndpointDefinitions.ts
77583
77997
  /**
77584
77998
  * People endpoints (#1356): the People list, its CSV export, and deleting a
@@ -77642,7 +78056,8 @@ const CLIENT_ERROR_REPORT_LIMITS = {
77642
78056
  stack: 8e3,
77643
78057
  digest: 128,
77644
78058
  componentStack: 8e3,
77645
- sourceLocation: 1024
78059
+ sourceLocation: 1024,
78060
+ navigationAgeMs: 6e4
77646
78061
  };
77647
78062
  const clientErrorEventSchema = z.enum([
77648
78063
  "dashboard:route-error",
@@ -77659,7 +78074,17 @@ z.object({
77659
78074
  stack: z.string().max(CLIENT_ERROR_REPORT_LIMITS.stack).nullable(),
77660
78075
  digest: z.string().max(CLIENT_ERROR_REPORT_LIMITS.digest).nullable(),
77661
78076
  componentStack: z.string().max(CLIENT_ERROR_REPORT_LIMITS.componentStack).nullable(),
77662
- sourceLocation: z.string().max(CLIENT_ERROR_REPORT_LIMITS.sourceLocation).nullable()
78077
+ sourceLocation: z.string().max(CLIENT_ERROR_REPORT_LIMITS.sourceLocation).nullable(),
78078
+ navigation: z.object({
78079
+ fromPathname: z.string().regex(/^\/[^?#]*$/).max(CLIENT_ERROR_REPORT_LIMITS.pathname),
78080
+ toPathname: z.string().regex(/^\/[^?#]*$/).max(CLIENT_ERROR_REPORT_LIMITS.pathname),
78081
+ type: z.enum([
78082
+ "push",
78083
+ "replace",
78084
+ "traverse"
78085
+ ]),
78086
+ ageMs: z.number().int().min(0).max(CLIENT_ERROR_REPORT_LIMITS.navigationAgeMs)
78087
+ }).strict().nullable().optional()
77663
78088
  }).strict();
77664
78089
  ({
77665
78090
  ...SITE_LIFECYCLE_ENDPOINT_DEFINITIONS,
@@ -77671,12 +78096,14 @@ z.object({
77671
78096
  ...GIFTING_ENDPOINT_DEFINITIONS,
77672
78097
  ...PUBLIC_READ_ENDPOINT_DEFINITIONS,
77673
78098
  ...BILLING_ENDPOINT_DEFINITIONS,
78099
+ ...EDIT_LEASE_ENDPOINT_DEFINITIONS,
78100
+ ...PAGE_SURFACE_EDITOR_ENDPOINT_DEFINITIONS,
77674
78101
  ...SITE_MANAGEMENT_ENDPOINT_DEFINITIONS
77675
78102
  }), TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, { ...SITE_API_KEY_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.site, TAG_TEMPLATES.siteBookingSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteBookingSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, {
77676
78103
  ...NEWSLETTER_ENDPOINT_DEFINITIONS,
77677
78104
  ...APPOINTMENT_ENDPOINT_DEFINITIONS,
77678
78105
  ...EVENT_SERIES_REGISTRATION_ENDPOINT_DEFINITIONS
77679
- }, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.workflowRunById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.routeById, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicBookingServices, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, { ...PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.publicEventFilters, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicShop, TAG_TEMPLATES.publicCheckout, TAG_TEMPLATES.siteRoutableContent, { ...PUBLIC_EVENT_CHECKOUT_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, { ...EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS }, { ...BOOKING_PEOPLE_ENDPOINT_DEFINITIONS }, { ...SDK_MEDIA_ENDPOINT_DEFINITIONS }, { ...SDK_ENDPOINT_DEFINITIONS }, { ...SDK_PAGE_DESIGN_ENDPOINT_DEFINITIONS }, { ...SDK_EVENT_ENDPOINT_DEFINITIONS }, { ...SDK_ENTRY_READ_ENDPOINTS };
78106
+ }, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.workflowRunById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.routeById, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicBookingServices, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, { ...PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.publicEventFilters, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicShop, TAG_TEMPLATES.publicCheckout, TAG_TEMPLATES.siteRoutableContent, { ...PUBLIC_EVENT_CHECKOUT_ENDPOINT_DEFINITIONS }, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, { ...EVENT_MANAGEMENT_ENDPOINT_DEFINITIONS }, { ...BOOKING_PEOPLE_ENDPOINT_DEFINITIONS }, { ...SDK_MEDIA_ENDPOINT_DEFINITIONS }, { ...SDK_ENDPOINT_DEFINITIONS }, { ...SDK_PAGE_DESIGN_ENDPOINT_DEFINITIONS }, { ...SDK_EVENT_ENDPOINT_DEFINITIONS }, { ...SDK_ENTRY_READ_ENDPOINTS };
77680
78107
  z.object({ refreshToken: z.string().min(1).max(4096) }).strict();
77681
78108
  z.object({
77682
78109
  accessToken: z.string().min(1).max(4096),
@@ -78419,6 +78846,7 @@ const CANONICAL_REFUND_PLANNER_ERROR_CODES = [
78419
78846
  "refund_failed"
78420
78847
  ];
78421
78848
  const CANONICAL_ADMIN_REFUND_FAILURE_CODES = [
78849
+ "refund_blocked_by_live_payment_terms",
78422
78850
  ...CANONICAL_REFUND_PLANNER_ERROR_CODES,
78423
78851
  "payment_intent_not_found",
78424
78852
  "stripe_error",
@@ -78434,6 +78862,7 @@ const CANONICAL_ADMIN_REFUND_FAILURE_CODES = [
78434
78862
  //#endregion
78435
78863
  //#region ../api/src/bookingRefundOutcomes.ts
78436
78864
  const STANDARD_LINE_ITEM_REFUND_INVALID_CODES = [
78865
+ "refund_blocked_by_live_payment_terms",
78437
78866
  "missing_amount",
78438
78867
  "invalid_amount",
78439
78868
  "amount_exceeds_remaining",
@@ -78823,68 +79252,6 @@ function parsePublicProductCategorySelector(value) {
78823
79252
  }
78824
79253
  z.enum(["public", "unlisted"], { error: "visibility must be 'public' or 'unlisted'" });
78825
79254
  //#endregion
78826
- //#region ../api/src/bookingPaymentTermSchemas.ts
78827
- const bookingDepositRefundPolicySchema = z.enum(["refundable", "non_refundable"]);
78828
- const bookingInstalmentPlanSchema = z.discriminatedUnion("kind", [
78829
- z.object({
78830
- kind: z.literal("deposit_plus_one_remainder"),
78831
- depositAmountCents: z.number().int().nonnegative(),
78832
- depositRefundability: bookingDepositRefundPolicySchema,
78833
- remainderDueCount: z.number().int().positive(),
78834
- intervalUnit: z.enum([
78835
- "day",
78836
- "week",
78837
- "month"
78838
- ])
78839
- }),
78840
- z.object({
78841
- kind: z.literal("deposit_plus_scheduled_instalments"),
78842
- depositAmountCents: z.number().int().nonnegative(),
78843
- depositRefundability: bookingDepositRefundPolicySchema,
78844
- instalmentCount: z.number().int().positive(),
78845
- intervalCount: z.number().int().positive(),
78846
- intervalUnit: z.enum([
78847
- "day",
78848
- "week",
78849
- "month"
78850
- ])
78851
- }),
78852
- z.object({
78853
- kind: z.literal("equal_scheduled_instalments"),
78854
- instalmentCount: z.number().int().positive(),
78855
- intervalCount: z.number().int().positive(),
78856
- intervalUnit: z.enum([
78857
- "day",
78858
- "week",
78859
- "month"
78860
- ])
78861
- })
78862
- ]);
78863
- const bookingFlexibleBalanceDueDateRuleSchema = z.discriminatedUnion("kind", [z.object({
78864
- kind: z.literal("relative_to_start_date"),
78865
- daysBeforeStart: z.number().int().positive()
78866
- }), z.object({
78867
- kind: z.literal("fixed_calendar_date"),
78868
- dueAt: z.string().datetime()
78869
- })]);
78870
- const bookingFlexibleBalanceConfigSchema = z.object({
78871
- upfrontAmountCents: z.number().int().nonnegative(),
78872
- dueDateRule: bookingFlexibleBalanceDueDateRuleSchema,
78873
- depositRefundability: bookingDepositRefundPolicySchema
78874
- });
78875
- z.discriminatedUnion("kind", [
78876
- z.object({ kind: z.literal("upfront") }),
78877
- z.object({ kind: z.literal("deferred_manual") }),
78878
- z.object({
78879
- kind: z.literal("instalment_plan"),
78880
- plan: bookingInstalmentPlanSchema
78881
- }),
78882
- z.object({
78883
- kind: z.literal("flexible_balance"),
78884
- config: bookingFlexibleBalanceConfigSchema
78885
- })
78886
- ]);
78887
- //#endregion
78888
79255
  //#region ../api/src/aiPlayground.ts
78889
79256
  /**
78890
79257
  * RFC-6902 JSON Patch Operations