@riverbankcms/sdk 0.144.0 → 0.145.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 (162) hide show
  1. package/dist/{PreviewEditorSidebar-CQZNnFiM.mjs → PreviewEditorSidebar-O-V6Pl5a.mjs} +4 -4
  2. package/dist/{PreviewEditorUI-DCNxnmI0.mjs → PreviewEditorUI-1UlX_9cw.mjs} +3 -3
  3. package/dist/{PreviewQueryProvider-BCYICImX.mjs → PreviewQueryProvider-BxGwdOCV.mjs} +1 -1
  4. package/dist/{SdkPreviewModeRuntime-BJolUbr1.mjs → SdkPreviewModeRuntime-DYbA_4iv.mjs} +419 -348
  5. package/dist/{SiteChromeCustomizeContext-CKgEpoxi.mjs → SiteChromeCustomizeContext-CNTKQ9nx.mjs} +2081 -1313
  6. package/dist/_dts/ai/src/contracts/proposals.d.ts +4719 -66
  7. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +429 -6
  8. package/dist/_dts/api/src/appointmentEndpointDefinitions.d.ts +49 -0
  9. package/dist/_dts/api/src/appointmentServiceCategoryEndpoints.d.ts +75 -0
  10. package/dist/_dts/api/src/appointmentServiceContracts.d.ts +80 -0
  11. package/dist/_dts/api/src/appointmentSetup.d.ts +8 -1
  12. package/dist/_dts/api/src/bookingManagementEndpoints.d.ts +2 -12
  13. package/dist/_dts/api/src/communications.d.ts +14 -22
  14. package/dist/_dts/api/src/contentRuntime.d.ts +2 -0
  15. package/dist/_dts/api/src/endpoints.d.ts +105 -58
  16. package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -1
  17. package/dist/_dts/api/src/launchReadiness.d.ts +2 -0
  18. package/dist/_dts/api/src/newsletterEndpointDefinitions.d.ts +0 -23
  19. package/dist/_dts/api/src/onboarding/confirmationResend.d.ts +3 -0
  20. package/dist/_dts/api/src/publicBookingService.d.ts +35 -1
  21. package/dist/_dts/api/src/publicExperience/newsletterEndpoints.d.ts +13 -0
  22. package/dist/_dts/api/src/publicNewsletterEndpointDefinitions.d.ts +58 -0
  23. package/dist/_dts/api/src/schemas/admin-observability-logs.d.ts +3 -3
  24. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +2 -6
  25. package/dist/_dts/api/src/types.d.ts +2 -1
  26. package/dist/_dts/blocks/src/PageRenderer.d.ts +4 -4
  27. package/dist/_dts/blocks/src/bindings/index.d.ts +2 -2
  28. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +24 -0
  29. package/dist/_dts/blocks/src/index.d.ts +1 -1
  30. package/dist/_dts/blocks/src/pageRenderJoins.d.ts +68 -0
  31. package/dist/_dts/blocks/src/pageRenderPlan.d.ts +8 -27
  32. package/dist/_dts/blocks/src/pageRenderPreparation.d.ts +7 -4
  33. package/dist/_dts/blocks/src/pageRendererBoundaries.d.ts +40 -23
  34. package/dist/_dts/blocks/src/server.d.ts +1 -1
  35. package/dist/_dts/blocks/src/system/blocks/appointment-services.d.ts +2 -0
  36. package/dist/_dts/blocks/src/system/blocks/events/eventSelectionFields.d.ts +2 -2
  37. package/dist/_dts/blocks/src/system/blocks/events/shared/calendarWindow.d.ts +1 -1
  38. package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +2 -2
  39. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +47 -47
  40. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +29 -3
  41. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.d.ts +8 -1
  42. package/dist/_dts/blocks/src/system/runtime/nodes/appointment-services.d.ts +22 -2
  43. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +3 -1
  44. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.interactive.d.ts +57 -2
  45. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.service-categories.d.ts +29 -0
  46. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.service-choices.d.ts +13 -0
  47. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.state.d.ts +3 -3
  48. package/dist/_dts/blocks/src/system/runtime/nodes/booking-runtime-sources.d.ts +13 -1
  49. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventSourceRecovery.d.ts +1 -1
  50. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +3 -3
  51. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.submission.d.ts +20 -1
  52. package/dist/_dts/content-editor/src/ui/editorSnapshot.d.ts +2 -0
  53. package/dist/_dts/content-model/src/content-types/schema.d.ts +1 -1
  54. package/dist/_dts/core/src/appointment-service-categories.d.ts +108 -0
  55. package/dist/_dts/core/src/editor-state.d.ts +6 -0
  56. package/dist/_dts/core/src/index.d.ts +1 -0
  57. package/dist/_dts/core/src/public-profile.d.ts +9 -0
  58. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +663 -241
  59. package/dist/_dts/editor-blocks/src/block-editor/types.d.ts +6 -0
  60. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/loaders.d.ts +16 -1
  61. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/types.d.ts +13 -0
  62. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/utils.d.ts +29 -0
  63. package/dist/_dts/preview-next/src/client/blocks/BoundaryControl.d.ts +7 -2
  64. package/dist/_dts/preview-next/src/client/blocks/composer/mergeDrafts.d.ts +1 -1
  65. package/dist/_dts/preview-next/src/client/blocks/composer/types.d.ts +1 -0
  66. package/dist/_dts/preview-next/src/client/blocks/previewProjection/applyPreviewProjections.d.ts +1 -3
  67. package/dist/_dts/preview-next/src/client/blocks/previewProjection/runtimeContentDecoration.d.ts +2 -2
  68. package/dist/_dts/preview-next/src/client/blocks/previewProjection/types.d.ts +2 -2
  69. package/dist/_dts/preview-next/src/client/preview/PreviewEntryControllerProvider.d.ts +1 -0
  70. package/dist/_dts/sdk/src/client/runtimeCacheKeys.d.ts +8 -0
  71. package/dist/_dts/sdk/src/client/types.d.ts +1 -1
  72. package/dist/_dts/sdk/src/contracts/index.d.ts +1 -1
  73. package/dist/_dts/sdk/src/contracts/page.d.ts +7 -2
  74. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +5 -0
  75. package/dist/_dts/sdk/src/manifest/passes/pass1-fields.d.ts +2 -2
  76. package/dist/_dts/sdk/src/public-api/contracts.d.ts +6 -8
  77. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +2 -2
  78. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +2 -2
  79. package/dist/_dts/sdk/src/rendering/helpers/loadContent.d.ts +1 -1
  80. package/dist/_dts/sdk/src/rendering/hooks/useContent.d.ts +1 -1
  81. package/dist/_dts/sdk/src/version.d.ts +1 -1
  82. package/dist/_dts/surfaces/src/index.d.ts +1 -0
  83. package/dist/_dts/theme-core/src/layout/boundaryCss.d.ts +3 -0
  84. package/dist/_dts/theme-core/src/site-styles/compositionBudget.d.ts +8 -0
  85. package/dist/_dts/theme-core/src/site-styles/contentTemplateRuntimeCompiler.d.ts +3 -2
  86. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +1 -3
  87. package/dist/_dts/theme-core/src/site-styles/generatedDesignPipeline.d.ts +3 -0
  88. package/dist/_dts/theme-core/src/site-styles/index.d.ts +3 -0
  89. package/dist/_dts/theme-core/src/site-styles/joinTreatment.d.ts +132 -0
  90. package/dist/_dts/theme-core/src/site-styles/pageDesignEditorBoundaries.d.ts +31 -0
  91. package/dist/_dts/theme-core/src/site-styles/pageDesignEditorModel.d.ts +33 -29
  92. package/dist/_dts/theme-core/src/site-styles/pageDesignIntent.d.ts +4 -4
  93. package/dist/_dts/theme-core/src/site-styles/pageFlowPresets.d.ts +36 -0
  94. package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +4 -10
  95. package/dist/_dts/theme-core/src/site-styles/rawStyleFields.d.ts +17 -4
  96. package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +20 -74
  97. package/dist/_dts/theme-core/src/site-styles/sectionBoundaryComposition.d.ts +95 -0
  98. package/dist/_dts/theme-core/src/site-styles/sectionTransitions.d.ts +80 -518
  99. package/dist/_dts/theme-core/src/site-styles/siteStyleBlockPolicies.d.ts +9 -4
  100. package/dist/_dts/theme-core/src/site-styles/transitionCatalogue.d.ts +320 -0
  101. package/dist/_dts/theme-core/src/site-styles/types.d.ts +3 -18
  102. package/dist/client/{BookingConsentAgreement-DoAILrkN.mjs → BookingConsentAgreement-DlVOmpW4.mjs} +2 -2
  103. package/dist/client/{DiscountCodeDisclosure-X528hUTf.mjs → DiscountCodeDisclosure-T9q623PQ.mjs} +1 -1
  104. package/dist/client/{EventCombined.client-DSBVwq5m.mjs → EventCombined.client-DnsUeONl.mjs} +6 -6
  105. package/dist/client/{EventListing.client-DmFAX7Vb.mjs → EventListing.client-CNBFqJS4.mjs} +2 -2
  106. package/dist/client/{LeafletStaticMap-BAqXdfhq.mjs → LeafletStaticMap-C7higg52.mjs} +1 -1
  107. package/dist/client/{ThemedButton-BwNFVwi4.mjs → ThemedButton-LAJTNrS8.mjs} +1 -1
  108. package/dist/client/{accordion-DRhMdkbd.mjs → accordion-BcNF9TjX.mjs} +1 -1
  109. package/dist/client/{bookingForm-iJ_nCsNF.mjs → bookingForm-BUaQ3S03.mjs} +142 -50
  110. package/dist/client/bookings.mjs +191 -64
  111. package/dist/client/{carousel-D8zuffZr.mjs → carousel-CTdF6e0V.mjs} +1 -1
  112. package/dist/client/{cart-DeMGJViN.mjs → cart-pGtyf_XU.mjs} +3 -3
  113. package/dist/client/{checkout-DXc06Km2.mjs → checkout-Da9WSn7Y.mjs} +3 -3
  114. package/dist/client/client.mjs +1630 -816
  115. package/dist/client/{context-CDLCfDep.mjs → context-BFeY_Wbm.mjs} +1 -1
  116. package/dist/client/{dates-ClFx7Epy.mjs → dates-BhwVSxDg.mjs} +2 -2
  117. package/dist/client/{eventCalendar-BaGpnOGN.mjs → eventCalendar-BAtdnR4s.mjs} +9 -9
  118. package/dist/client/{eventCombined-ywONOx2m.mjs → eventCombined-RksA3tRC.mjs} +4 -4
  119. package/dist/client/{eventDetails-B2LlOTYY.mjs → eventDetails-BB9hB4wR.mjs} +4 -4
  120. package/dist/client/{eventListing-CMgxWpqP.mjs → eventListing-BpJBkviM.mjs} +4 -4
  121. package/dist/client/{eventRegistration-BarLDNHR.mjs → eventRegistration-B18jFq_o.mjs} +8 -8
  122. package/dist/client/{form-BjqKaBJ7.mjs → form-Dodt8Y8t.mjs} +3 -3
  123. package/dist/client/{headerSection-CP4XDwz1.mjs → headerSection-B0qj9ttg.mjs} +3 -3
  124. package/dist/client/hooks.mjs +550 -99
  125. package/dist/client/{locationMap-C5gW-d-w.mjs → locationMap-gn-iMk7a.mjs} +3 -3
  126. package/dist/client/{newsletterForm-afXlVSA0.mjs → newsletterForm-oByLdFkr.mjs} +26 -5
  127. package/dist/client/{pricing-Bl1CAl28.mjs → pricing-BOU0_Hai.mjs} +1 -1
  128. package/dist/client/{productDetail-CvQ3jWQe.mjs → productDetail-D9v1zH2j.mjs} +3 -3
  129. package/dist/client/{productList-U874PGO7.mjs → productList-D-mItx1n.mjs} +3 -3
  130. package/dist/client/{propsDecoder-DPXtCZWP.mjs → propsDecoder-C3TP_z4x.mjs} +72 -33
  131. package/dist/client/rendering/client.mjs +900 -266
  132. package/dist/client/rendering/islands.mjs +17 -17
  133. package/dist/client/rendering.mjs +1637 -788
  134. package/dist/client/{routeIslandApiConfig-NGYiUWXu.mjs → routeIslandApiConfig-DzN1W0sq.mjs} +1 -1
  135. package/dist/client/{scrollToBlock-0-C3DVhK.mjs → scrollToBlock-CWs8EIdo.mjs} +1 -1
  136. package/dist/client/{shop-BXjXhM9P.mjs → shop-Dufw7N7o.mjs} +7 -7
  137. package/dist/client/{shop-commerce-BZ6UlWJ7.mjs → shop-commerce-gklw_hLF.mjs} +6 -6
  138. package/dist/client/{shop-commerce-store-DlSBXb3D.mjs → shop-commerce-store-Sf1eyTaZ.mjs} +1 -1
  139. package/dist/client/{shopShared-kkEOiLPA.mjs → shopShared-B5nyA41S.mjs} +4 -4
  140. package/dist/client/{useEventFilters-zvnnE1ro.mjs → useEventFilters-CLL829vy.mjs} +6 -6
  141. package/dist/preview-next/before-render.mjs +147 -77
  142. package/dist/preview-next/client/runtime.mjs +4 -4
  143. package/dist/preview-next/keepAlive.mjs +147 -77
  144. package/dist/preview-next/middleware.mjs +147 -77
  145. package/dist/{previewAuthStore-JA6-I_sL.mjs → previewAuthStore-BxAFlu-j.mjs} +147 -77
  146. package/dist/{sdk-runtime-DFJlQt3q.mjs → sdk-runtime-D0uZFev7.mjs} +2 -2
  147. package/dist/{separator-o8GHb1xh.mjs → separator-EvdCAn4V.mjs} +1 -1
  148. package/dist/server/components.mjs +1727 -991
  149. package/dist/server/config-validation.mjs +537 -97
  150. package/dist/server/config.mjs +537 -97
  151. package/dist/server/data.mjs +549 -98
  152. package/dist/server/index.mjs +159 -81
  153. package/dist/server/next.mjs +1460 -748
  154. package/dist/server/page-converter.mjs +384 -54
  155. package/dist/server/prebuild.mjs +1 -1
  156. package/dist/server/rendering/server.mjs +1712 -973
  157. package/dist/server/rendering.mjs +1748 -1001
  158. package/dist/server/routing.mjs +624 -131
  159. package/dist/server/server.mjs +554 -138
  160. package/dist/server/theme-bridge.mjs +1192 -27
  161. package/dist/server/theme.mjs +6 -4
  162. package/package.json +2 -1
@@ -1,7 +1,7 @@
1
1
  "use client";
2
- import { $i as mapCurrentValueForSelect, $n as coerceLinkedContentEntriesPayload, $r as runTransforms, Ai as makeBoundaryId, An as containerResponsiveThemeCss, Ar as compileTransitionRuntime, At as RichTextField, Ba as Button, Bi as parseThemeForPersistence, Bn as compileManifestContentContract, Bt as getBlockManifestFromSdkConfig, Ca as Dialog, Ci as isObjectRecord, Cn as deriveLaunchReadiness, Cr as retargetCompiledRuntimeFieldsForContentAdjacency, Ct as ButtonVariantField, Da as DialogHeader, Di as pageDesignEditorBackgroundOverrideOwner, Dn as useApiMediaUploader, Dt as ReferenceField, Ea as DialogFooter, Ei as isThemeV2NormalEditorRawStyleFieldName, En as useMediaEditorOptional, Er as componentRuntimeRulesForTheme, Et as MediaField, Fn as SITE_CHROME_VISIBLE_HEADER_SELECTOR, Fr as gradientToCss, Ft as LinkWidgetProvider, G as confirmAutosaveBatch, Gi as paletteModeSchema, Gn as escapeStyleContent, Gr as backgroundAppearanceColorTokenNames, Gt as canRedoHistory, Ha as cn, Hn as buildThemeRuntime, Hr as sectionTransitionFamilies, Ht as useEditorUiStore, In as SITE_OVERLAY_HEADER_CLEARANCE_CSS_VAR, Ir as GRADIENT_PRESETS, J as idleEditorTransactionQueueState, Ji as getFieldIntent, Jn as defaultTransforms, Jr as ctaButton, Jt as pushHistoryEntry, K as deriveTransactionCapabilities, Ki as resolveSdkFooterMode, Kn as readBlockComposition, Kr as backgroundAppearanceQuickColorTokenNames, Kt as canUndoHistory, Ln as planSiteOverlayHeaderClearance, Lr as GRADIENT_PRESET_IDS, Lt as hideThemeV2RawStyleFields, Mn as makeDefaultBlockComponent, Mt as EditorProvider, Nn as getBlockDefinition, Nt as useEditor, Oa as DialogTitle, Oi as asDesignBlockId, On as isSupportedLoaderEndpoint, Or as designRuntimeRulesForTheme, Ot as ReferenceWidgetProvider, Pn as projectRecurringSchedule, Pt as LinkField, Q as resolvePreviewSidebarTab, Qi as hasEmptyOption, Qn as LINKED_CONTENT_ENTRY_META_KEY, Qr as parseBackgroundContent, Qt as recordsEqual, Ri as textColorStyle, Rn as visibleHeaderClearancePx, Rr as getGradientPreset, Rt as prepareBlockEditorManifest, Sa as TabsTrigger, Si as bookingConsentCarrierSchema, Sn as DEFAULT_LAUNCH_READINESS_INPUT, Sr as retargetCompiledBoundaryRuntimeForContentAdjacency, St as EntryPickerWidgetProvider, Ta as DialogDescription, Ti as corners, Tn as MediaEditorContextProvider, Tr as planPageDesignLayoutLookCompatibility, Tt as FileField, Ua as X, Un as DEFAULT_THEME_RESPONSIVE_MODE, Ur as sectionTransitionFamilyForBoundaryOptionId, Ut as useEditorUiStoreInstance, Vi as ORDINARY_TEXT_MIN_CONTRAST_RATIO, Vn as validateManifestDraft, Vr as defaultSectionTransitionVariantForFamily, W as beginAutosaveBatch, Wa as Upload, Wi as paletteColorsSchema, Wn as getResponsiveScopeSpec, Wr as sectionTransitionVariantForBoundaryOptionId, Wt as useOptionalEditorUiStoreInstance, Xi as SdkConfigProvider, Xn as resolvePageRouteTarget, Xt as undoHistory, Y as rejectAutosaveBatch, Yi as isHeaderField, Yn as resolveEntryRouteTarget, Yr as bindingSchema, Yt as redoHistory, Za as RotateCcw, Zi as useSdkConfig, Zn as resolveRouteTarget, Zr as planSiteChromePlacement, Zt as unsafeAsLinkedContentEntryId, _ as reportPreviewDesignError, _i as siblingPath, _n as MediaEditor, _o as expectParsedBrandedId, _r as heroCopyFragment, _t as loadMailingListAuthoringContext, ai as logger, an as parseReferenceKind, ao as Image, ar as cardFragment, at as useUISelector, ba as TabsContent, bi as eventCalendarListLayoutCompatibleDisplayModeValues, bo as __exportAll, br as applyCompiledRuntimeFieldsToContent, bt as IconPickerField, ca as SelectContent, ci as isInlineTextEmpty, cr as blogFeaturedPostFragment, d as PreviewDesignCoordinatorProvider, da as SelectValue, di as buildResolveImageUrlContext, dr as formCopyFragment, dt as createSiteOptionWidgetAdapters, ea as mapOptionValueForSelect, ei as parseBlockIconValue, en as useDebouncedLatestSave, er as getLinkedContentEntryMeta, et as renderSiteChromeBlock, fi as getCurrentResolveImageUrlContext, fn as createManifestFormAdapter, fr as testimonialsCarouselFragment, ft as SiteOptionPickerField, g as PREVIEW_DESIGN_SAVE_ERROR_MESSAGE, gi as getAtPath, gn as createStoreBackend, go as assertNever$2, gr as ctaRowFragment, gt as MailingListTargetingField, h as PREVIEW_DESIGN_LOAD_ERROR_MESSAGE, hi as SECTION_BACKGROUND_MIN_SOURCE_WIDTH, hn as evaluateVisibility, ho as unsafeAsEditorBlockValues, hr as heroCtaRowFragment, ht as OfferingsPreviewWidgetProvider, i as usePreviewDesignHistoryOrder, ii as renderInlineText, ir as headingFragment, jn as createCustomBlockRegistry, jr as surfaceResolutionContextFromTheme, jt as RichTextWidgetProvider, ki as assertNever$1, kn as ThemeScope, kt as useRichTextImagePicker, la as SelectItem, li as Text$1, ln as PaletteProvider, lo as ChevronRight, lr as singleButtonFragment, lt as useEntryEditorController, m as usePreviewThemeOverlay, mi as setContextResolveImageUrlContext, mn as FormRenderer, mo as unsafeAsEditorBlockId, mr as ctaCopyFragment, mt as OfferingsPreviewGroupOrderField, n as useSiteChromeCustomizeOptional, na as FieldFrame, ni as parseGeneratedIconSetId, nn as createSnapshotFromPageRecord, nr as ImageResolveContextProvider, nt as PreviewInlineTextEditor, oi as coerceInlineTextWithFallback, oo as GripVertical, or as faqAccordionFragment, ot as EditableBlockProvider, p as PreviewThemeOverlayProvider, pi as resolveImageUrlWithContext, po as parseFooterModuleId, pr as testimonialsHeadingFragment, pt as SiteOptionWidgetProvider, q as enqueueTransaction, qi as attachRenderableMediaAssetFields, qn as getDefaultComponentRegistry, qr as parseBackgroundAppearanceColorToken, qt as createHistoryState, r as PreviewDesignHistoryOrderProvider, ra as useField, rn as BUILT_IN_REFERENCE_KINDS, rr as richTextFragment, rt as PreviewTextEditor, sa as Select, si as inlineTextToPlainText, sr as faqHeadingFragment, st as EntryControllerProvider, t as SiteChromeCustomizeProvider, ta as unmapValueFromSelect, ti as parseGeneratedIconAssetId, tn as createRoutingHelpers, tr as clientComponentRegistry, tt as PreviewRichTextEditor, ua as SelectTrigger, ui as RichText$1, un as usePalette, uo as ChevronLeft, ur as formEmbedFragment, ut as createSiteOptionApiLoader, vi as BlockApiProvider, vn as applyPageDesignEditorAction, vo as parseMediaAssetId, vr as bodyCopyFragment, vt as MailingListTargetingProvider, wa as DialogContent, wi as isRecord$13, wn as AMBIENT_BACKGROUND_ROLES, wr as formatSiteChromeBackgroundTokenLabel, wt as ButtonWidgetProvider, xa as TabsList, xi as eventCalendarListLayoutOptions, xn as decodePublicProductCategorySelectorQuery, xr as compileEditorModelRuntime, xt as EntryPickerField, ya as Tabs, yi as calendarWindowQuerySchema, yn as getPageDesignEditorState, yo as parseSiteId, yr as defineFragment, yt as InlineTextField, zi as defaultThemeTokens, zn as resolveVariantKey, zr as parseGradientPresetId, zt as stripTopLevelRoutingUi } from "./SiteChromeCustomizeContext-CKgEpoxi.mjs";
3
- import { i as useOptionalPreviewLayout, t as PreviewQueryProvider } from "./PreviewQueryProvider-BCYICImX.mjs";
4
- import { _ as API_ENDPOINTS, a as usePreviewToken, c as createBearerAPIClient, d as unwrapResponse, g as resolveSurfaceDocumentAttributes, h as SURFACE_IDS, i as usePreviewAuthFetch, m as SURFACE_DOCUMENT_DATA_ATTRIBUTE, n as markPreviewAuthExpired, o as isPreviewRuntimeSessionEditable, r as usePreviewAuth, s as ApiRequestError, t as initPreviewAuth } from "./previewAuthStore-JA6-I_sL.mjs";
2
+ import { $i as attachRenderableMediaAssetFields, $n as LINKED_CONTENT_ENTRY_META_KEY, $r as ctaButton, Aa as DialogContent, Ai as corners, An as containerResponsiveThemeCss, Ar as surfaceResolutionContextFromTheme, At as RichTextField, Bn as compileManifestContentContract, Br as autoDesignChoice, Bt as getBlockManifestFromSdkConfig, Ci as BlockApiProvider, Cn as deriveLaunchReadiness, Co as expectParsedBrandedId, Cr as formatSiteChromeBackgroundTokenLabel, Ct as ButtonVariantField, Da as TabsList, Di as bookingConsentCarrierSchema, Dn as useApiMediaUploader, Dt as ReferenceField, Ea as TabsContent, Ei as eventCalendarListLayoutOptions, En as useMediaEditorOptional, Eo as __exportAll, Er as componentRuntimeRulesForTheme, Et as MediaField, Fi as assertNever$1, Fn as SITE_CHROME_VISIBLE_HEADER_SELECTOR, Fr as GRADIENT_PRESETS, Ft as LinkWidgetProvider, G as confirmAutosaveBatch, Gi as defaultThemeTokens, Gn as escapeStyleContent, Gr as boundaryTreatmentForBoundaryOptionId, Gt as canRedoHistory, Hn as buildThemeRuntime, Hr as boundaryLayout, Ht as useEditorUiStore, Ii as makeBoundaryId, In as SITE_OVERLAY_HEADER_CLEARANCE_CSS_VAR, Ir as GRADIENT_PRESET_IDS, J as idleEditorTransactionQueueState, Ja as cn, Jn as getDefaultComponentRegistry, Jr as sectionTransitionFamilyForBoundaryOptionId, Jt as pushHistoryEntry, K as deriveTransactionCapabilities, Ka as Button, Ki as parseThemeForPersistence, Kn as mergeContentWithBlockStyleOverrides, Kr as defaultSectionTransitionVariantForFamily, Kt as canUndoHistory, Ln as planSiteOverlayHeaderClearance, Lr as getGradientPreset, Lt as hideThemeV2RawStyleFields, Ma as DialogFooter, Mi as pageDesignEditorBackgroundOverrideOwner, Mn as makeDefaultBlockComponent, Mt as EditorProvider, Na as DialogHeader, Ni as stripStaleTransitionStyleGroup, Nn as getBlockDefinition, Nt as useEditor, Oa as TabsTrigger, Oi as isObjectRecord, On as isSupportedLoaderEndpoint, Or as designRuntimeRulesForTheme, Ot as ReferenceWidgetProvider, Pa as DialogTitle, Pi as asDesignBlockId, Pn as projectRecurringSchedule, Pr as gradientToCss, Pt as LinkField, Q as resolvePreviewSidebarTab, Qi as resolveSdkFooterMode, Qn as resolveRouteTarget, Qr as parseBackgroundAppearanceColorToken, Qt as recordsEqual, Rn as visibleHeaderClearancePx, Rr as parseGradientPresetId, Rt as prepareBlockEditorManifest, Si as siblingPath, Sn as DEFAULT_LAUNCH_READINESS_INPUT, So as assertNever$2, Sr as compileEditorModelRuntime, St as EntryPickerWidgetProvider, Ta as Tabs, Ti as eventCalendarListLayoutCompatibleDisplayModeValues, Tn as MediaEditorContextProvider, To as parseSiteId, Tr as resolvePageDesignEditorBoundaryForChoice, Tt as FileField, Un as DEFAULT_THEME_RESPONSIVE_MODE, Ur as composeBoundary, Ut as useEditorUiStoreInstance, Vn as validateManifestDraft, Vr as userPinnedDesignChoice, W as beginAutosaveBatch, Wi as textColorStyle, Wn as getResponsiveScopeSpec, Wr as sectionFactsForContent, Wt as useOptionalEditorUiStoreInstance, Xa as Upload, Xi as paletteColorsSchema, Xn as resolveEntryRouteTarget, Xr as backgroundAppearanceColorTokenNames, Xt as undoHistory, Y as rejectAutosaveBatch, Ya as X, Yn as defaultTransforms, Yr as sectionTransitionVariantForBoundaryOptionId, Yt as redoHistory, Zi as paletteModeSchema, Zn as resolvePageRouteTarget, Zr as backgroundAppearanceQuickColorTokenNames, Zt as unsafeAsLinkedContentEntryId, _ as reportPreviewDesignError, _a as SelectValue, _i as getCurrentResolveImageUrlContext, _n as MediaEditor, _r as ctaRowFragment, _t as loadMailingListAuthoringContext, aa as mapCurrentValueForSelect, ai as parseBlockIconValue, an as parseReferenceKind, ar as headingFragment, at as useUISelector, bi as SECTION_BACKGROUND_MIN_SOURCE_WIDTH, bo as unsafeAsEditorBlockId, br as defineFragment, bt as IconPickerField, ca as FieldFrame, cr as faqHeadingFragment, d as PreviewDesignCoordinatorProvider, di as coerceInlineTextWithFallback, do as Image, dr as formEmbedFragment, dt as createSiteOptionWidgetAdapters, ea as getFieldIntent, ei as bindingSchema, en as useDebouncedLatestSave, er as coerceLinkedContentEntriesPayload, et as renderSiteChromeBlock, fi as inlineTextToPlainText, fn as createManifestFormAdapter, fo as GripVertical, fr as formCopyFragment, ft as SiteOptionPickerField, g as PREVIEW_DESIGN_SAVE_ERROR_MESSAGE, ga as SelectTrigger, gi as buildResolveImageUrlContext, gn as createStoreBackend, go as ChevronLeft, gr as heroCtaRowFragment, gt as MailingListTargetingField, h as PREVIEW_DESIGN_LOAD_ERROR_MESSAGE, ha as SelectItem, hi as RichText$1, hn as evaluateVisibility, ho as ChevronRight, hr as ctaCopyFragment, ht as OfferingsPreviewWidgetProvider, i as usePreviewDesignHistoryOrder, ia as hasEmptyOption, ii as runTransforms, ir as richTextFragment, ja as DialogDescription, ji as isThemeV2NormalEditorRawStyleFieldName, jn as createCustomBlockRegistry, jt as RichTextWidgetProvider, ka as Dialog, ki as isRecord$11, kn as ThemeScope, kt as useRichTextImagePicker, la as useField, li as renderInlineText, ln as PaletteProvider, lr as blogFeaturedPostFragment, lt as useEntryEditorController, m as usePreviewThemeOverlay, ma as SelectContent, mi as Text$1, mn as FormRenderer, mr as testimonialsHeadingFragment, mt as OfferingsPreviewGroupOrderField, n as useSiteChromeCustomizeOptional, na as SdkConfigProvider, ni as planSiteChromePlacement, nn as createSnapshotFromPageRecord, nr as clientComponentRegistry, nt as PreviewInlineTextEditor, oa as mapOptionValueForSelect, oi as parseGeneratedIconAssetId, or as cardFragment, ot as EditableBlockProvider, p as PreviewThemeOverlayProvider, pa as Select, pi as isInlineTextEmpty, pr as testimonialsCarouselFragment, pt as SiteOptionWidgetProvider, q as enqueueTransaction, qi as ORDINARY_TEXT_MIN_CONTRAST_RATIO, qn as readBlockComposition, qr as sectionTransitionFamilies, qt as createHistoryState, r as PreviewDesignHistoryOrderProvider, ra as useSdkConfig, ri as parseBackgroundContent, rn as BUILT_IN_REFERENCE_KINDS, ro as RotateCcw, rr as ImageResolveContextProvider, rt as PreviewTextEditor, sa as unmapValueFromSelect, si as parseGeneratedIconSetId, sr as faqAccordionFragment, st as EntryControllerProvider, t as SiteChromeCustomizeProvider, ta as isHeaderField, tn as createRoutingHelpers, tr as getLinkedContentEntryMeta, tt as PreviewRichTextEditor, ui as logger, un as usePalette, ur as singleButtonFragment, ut as createSiteOptionApiLoader, vi as resolveImageUrlWithContext, vn as applyPageDesignEditorAction, vr as heroCopyFragment, vt as MailingListTargetingProvider, wi as calendarWindowQuerySchema, wn as AMBIENT_BACKGROUND_ROLES, wo as parseMediaAssetId, wr as planPageDesignLayoutLookCompatibility, wt as ButtonWidgetProvider, xi as getAtPath, xn as decodePublicProductCategorySelectorQuery, xo as unsafeAsEditorBlockValues, xr as applyCompiledRuntimeFieldsToContent, xt as EntryPickerField, yi as setContextResolveImageUrlContext, yn as getPageDesignEditorState, yo as parseFooterModuleId, yr as bodyCopyFragment, yt as InlineTextField, zn as resolveVariantKey, zt as stripTopLevelRoutingUi } from "./SiteChromeCustomizeContext-CNTKQ9nx.mjs";
3
+ import { i as useOptionalPreviewLayout, t as PreviewQueryProvider } from "./PreviewQueryProvider-BxGwdOCV.mjs";
4
+ import { _ as API_ENDPOINTS, a as usePreviewToken, c as createBearerAPIClient, d as unwrapResponse, g as resolveSurfaceDocumentAttributes, h as SURFACE_IDS, i as usePreviewAuthFetch, m as SURFACE_DOCUMENT_DATA_ATTRIBUTE, n as markPreviewAuthExpired, o as isPreviewRuntimeSessionEditable, r as usePreviewAuth, s as ApiRequestError, t as initPreviewAuth } from "./previewAuthStore-BxAFlu-j.mjs";
5
5
  import * as React$1 from "react";
6
6
  import React, { Children, Fragment, cloneElement, createContext, isValidElement, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
7
7
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -175,7 +175,7 @@ function ResizableSplitPane({ left, right, defaultSplit = 40, minLeftWidth = 300
175
175
  }
176
176
  //#endregion
177
177
  //#region ../blocks/src/system/icons/generatedAssets.ts
178
- function isRecord$12(value) {
178
+ function isRecord$10(value) {
179
179
  return typeof value === "object" && value !== null && !Array.isArray(value);
180
180
  }
181
181
  function generatedIconAssetRefKey(ref) {
@@ -185,11 +185,11 @@ function collectGeneratedIconAssetRefs(page) {
185
185
  const blocks = [];
186
186
  for (const block of page.blocks) {
187
187
  if (block.kind !== "block.feature-cards" || typeof block.id !== "string") continue;
188
- const content = isRecord$12(block.draftContent) ? block.draftContent : isRecord$12(block.content) ? block.content : null;
188
+ const content = isRecord$10(block.draftContent) ? block.draftContent : isRecord$10(block.content) ? block.content : null;
189
189
  const cards = Array.isArray(content?.cards) ? content.cards : [];
190
190
  const refs = /* @__PURE__ */ new Map();
191
191
  for (const card of cards) {
192
- if (!isRecord$12(card)) continue;
192
+ if (!isRecord$10(card)) continue;
193
193
  const icon = parseBlockIconValue(card.icon);
194
194
  if (icon.kind !== "generated") continue;
195
195
  const ref = {
@@ -386,70 +386,171 @@ function requireThemeResources(resources, blockKind) {
386
386
  return resources;
387
387
  }
388
388
  //#endregion
389
- //#region ../blocks/src/pageRendererBoundaries.tsx
390
- const boundaryKey = (previousBlockId, nextBlockId) => `${previousBlockId}\u0000${nextBlockId}`;
391
- function isSiteStyleTransitionStyleGroup(value) {
392
- return value?.startsWith("site-style-transition-") === true;
389
+ //#region ../blocks/src/pageRenderJoins.ts
390
+ /**
391
+ * Re-points joins across omitted blocks. Pure over joins.
392
+ *
393
+ * Joins are keyed by adjacent block-id pairs, so dropping B from [A, B, C]
394
+ * removes the A→C join as well as B's own, because no A→C join was ever
395
+ * resolved. For each surviving pair the original join is kept when the pair
396
+ * was already adjacent. Across a gap, the treatment comes from the join
397
+ * entering the omitted run (A→first omitted), falling back to the one leaving
398
+ * it (last omitted→C). Nothing visual is carried: the survivors are composed
399
+ * from their own content afterwards.
400
+ *
401
+ * `survivors` are compared by identity against `originalBlocks`.
402
+ */
403
+ function retargetJoinsAcrossOmissions(input) {
404
+ const { joins, originalBlocks, survivingBlocks } = input;
405
+ if (joins.length === 0) return joins;
406
+ if (originalBlocks.every((block) => survivingBlocks.has(block))) return joins;
407
+ const byPair = joinsByPair(joins);
408
+ const retargeted = [];
409
+ let previousSurvivor = null;
410
+ let run = [];
411
+ for (const block of originalBlocks) {
412
+ if (!survivingBlocks.has(block)) {
413
+ run.push(block);
414
+ continue;
415
+ }
416
+ if (previousSurvivor?.id && block.id) {
417
+ const join = run.length === 0 ? byPair.get(pairKey(previousSurvivor.id, block.id)) : joinAcrossRun(byPair, previousSurvivor.id, block.id, run);
418
+ if (join) retargeted.push(join);
419
+ }
420
+ previousSurvivor = block;
421
+ run = [];
422
+ }
423
+ return retargeted;
424
+ }
425
+ function joinAcrossRun(byPair, previousBlockId, nextBlockId, run) {
426
+ const firstOmittedId = run[0]?.id;
427
+ const lastOmittedId = run[run.length - 1]?.id;
428
+ const entering = firstOmittedId ? byPair.get(pairKey(previousBlockId, firstOmittedId)) : void 0;
429
+ const exiting = lastOmittedId ? byPair.get(pairKey(lastOmittedId, nextBlockId)) : void 0;
430
+ const donor = entering ?? exiting;
431
+ return donor ? {
432
+ previousBlockId,
433
+ nextBlockId,
434
+ treatment: donor.treatment
435
+ } : void 0;
393
436
  }
394
- function boundaryMapForAdjacentBlockIds(boundaries) {
395
- return new Map(boundaries.map((boundary) => [boundaryKey(boundary.previousBlockId, boundary.nextBlockId), boundary]));
437
+ /**
438
+ * The single composition site. For every adjacent pair of survivors with ids,
439
+ * finds its join and composes it from both survivors' final content: what
440
+ * each paints with and the frame each draws.
441
+ */
442
+ function composePageJoins(input) {
443
+ const byPair = joinsByPair(input.joins);
444
+ return input.survivors.flatMap((previous, index) => {
445
+ const next = input.survivors[index + 1];
446
+ if (!next || !previous.id || !next.id) return [];
447
+ const join = byPair.get(pairKey(previous.id, next.id));
448
+ return [{
449
+ previousBlockId: previous.id,
450
+ nextBlockId: next.id,
451
+ join: join ? composeJoin(join, previous, next) : null
452
+ }];
453
+ });
454
+ }
455
+ function composeJoin(join, previous, next) {
456
+ return {
457
+ boundaryId: pairKey(join.previousBlockId, join.nextBlockId),
458
+ previousBlockId: join.previousBlockId,
459
+ nextBlockId: join.nextBlockId,
460
+ treatment: join.treatment,
461
+ outcome: composeBoundary(sectionFactsForContent(previous.content), sectionFactsForContent(next.content))
462
+ };
396
463
  }
397
- function boundaryBetweenBlocks(previousBlock, nextBlock, boundaries) {
398
- const previousBlockId = previousBlock?.id ?? null;
399
- const nextBlockId = nextBlock?.id ?? null;
400
- if (!previousBlockId || !nextBlockId) return null;
401
- return boundaries.get(boundaryKey(previousBlockId, nextBlockId)) ?? null;
464
+ /** Placement, reserves and paint for a join that draws; null otherwise. */
465
+ function renderedJoinLayout(join) {
466
+ if (!join || join.outcome.kind !== "shown") return null;
467
+ return boundaryLayout(join.treatment, join.outcome.composition);
468
+ }
469
+ /** Joins with a missing id on either side cannot sit between two blocks. */
470
+ function joinsByPair(joins) {
471
+ return new Map(joins.flatMap((join) => join.previousBlockId && join.nextBlockId ? [[pairKey(join.previousBlockId, join.nextBlockId), join]] : []));
472
+ }
473
+ /** Slot lookup key for an adjacent pair, in the one boundary-id scheme. */
474
+ function joinSlotKey(previousBlockId, nextBlockId) {
475
+ return pairKey(previousBlockId, nextBlockId);
402
476
  }
403
- function renderBoundaryAfterBlock(input) {
404
- const previousBlockId = input.block.id;
405
- const nextBlockId = input.nextBlock?.id ?? null;
477
+ function pairKey(previousBlockId, nextBlockId) {
478
+ return makeBoundaryId(asDesignBlockId(previousBlockId), asDesignBlockId(nextBlockId));
479
+ }
480
+ //#endregion
481
+ //#region ../blocks/src/pageRendererBoundaries.tsx
482
+ function joinSlotsByPair(slots) {
483
+ return new Map(slots.map((slot) => [joinSlotKey(slot.previousBlockId, slot.nextBlockId), slot]));
484
+ }
485
+ function joinSlotBetween(previousBlockId, nextBlockId, slots) {
406
486
  if (!previousBlockId || !nextBlockId) return null;
407
- const boundary = input.boundaryByAdjacentBlockIds.get(boundaryKey(previousBlockId, nextBlockId));
408
- if (!boundary) return null;
409
- const rendered = /* @__PURE__ */ jsx("div", {
487
+ return slots.get(joinSlotKey(previousBlockId, nextBlockId)) ?? null;
488
+ }
489
+ /**
490
+ * The markup at one join: the painted boundary element when the join draws,
491
+ * then whatever `renderJoin` adds. Null when there is nothing to render.
492
+ */
493
+ function renderJoinSlot(input) {
494
+ const { slot } = input;
495
+ if (!slot) return null;
496
+ const layout = renderedJoinLayout(slot.join);
497
+ const painted = slot.join && layout ? /* @__PURE__ */ jsx("div", {
410
498
  "aria-hidden": "true",
411
499
  "data-block-boundary": "",
412
- "data-boundary-id": boundary.boundaryId,
413
- "data-boundary-previous-block-id": boundary.previousBlockId,
414
- "data-boundary-next-block-id": boundary.nextBlockId,
415
- "data-style-group": boundary.styleGroup,
416
- style: boundaryCssVarsStyle(boundary)
417
- }, `${input.blockKey}:boundary`);
418
- return input.wrapBoundary ? input.wrapBoundary(boundary, rendered) : rendered;
419
- }
420
- function boundaryCssVarsStyle(boundary) {
421
- return {
422
- "--site-style-transition-from": boundary.cssVars.from,
423
- "--site-style-transition-to": boundary.cssVars.to
424
- };
500
+ "data-boundary-id": slot.join.boundaryId,
501
+ "data-boundary-previous-block-id": slot.previousBlockId,
502
+ "data-boundary-next-block-id": slot.nextBlockId,
503
+ "data-boundary-treatment": slot.join.treatment,
504
+ "data-boundary-placement": layout.placement,
505
+ style: boundaryPaintStyle(layout.paint)
506
+ }, `${input.blockKey}:boundary`) : null;
507
+ const extra = input.renderJoin?.({
508
+ previousBlockId: slot.previousBlockId,
509
+ nextBlockId: slot.nextBlockId,
510
+ join: slot.join
511
+ });
512
+ if (!painted && (extra === null || extra === void 0)) return null;
513
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [painted, extra] }, `${input.blockKey}:join`);
425
514
  }
426
- function boundaryReserveCssVarsStyle(input) {
427
- const before = input.before?.metrics.reserveCss ?? null;
428
- const after = input.after?.metrics.reserveCss ?? null;
429
- if (!before && !after) return void 0;
430
- return {
431
- ...before ? { "--site-style-boundary-before-reserve": before } : {},
432
- ...after ? { "--site-style-boundary-after-reserve": after } : {}
433
- };
515
+ /**
516
+ * The one render-edge place a theme token becomes CSS.
517
+ */
518
+ function themeTokenCss(token) {
519
+ return `rgb(var(--tb-${token}))`;
434
520
  }
435
- function transitionCssVarsStyle(content) {
436
- const transitionStyles = isObjectRecord(content._transitionStyles) ? content._transitionStyles : null;
437
- const cssVars = isObjectRecord(transitionStyles?.cssVars) ? transitionStyles.cssVars : null;
438
- const from = typeof cssVars?.from === "string" ? cssVars.from : null;
439
- const to = typeof cssVars?.to === "string" ? cssVars.to : null;
440
- if (!from && !to) return void 0;
521
+ function boundaryPaintStyle(paint) {
441
522
  return {
442
- ...from ? { "--site-style-transition-from": from } : {},
443
- ...to ? { "--site-style-transition-to": to } : {}
523
+ "--boundary-shape-paint": themeTokenCss(paint.shape),
524
+ ...paint.band ? { "--boundary-band-paint": themeTokenCss(paint.band) } : {}
444
525
  };
445
526
  }
446
- function mergeStyleObjects(left, right) {
447
- if (!left) return right;
448
- if (!right) return left;
449
- return {
450
- ...left,
451
- ...right
527
+ /**
528
+ * Reserve attributes and variables for a block wrapper, from the joins on
529
+ * either side. A join's `before` reserve sits inside its previous section, so
530
+ * it pads the bottom of the block above the join; its `after` reserve pads the
531
+ * top of the block below. Joins that do not draw reserve nothing.
532
+ */
533
+ function blockBoundaryReserves(input) {
534
+ const top = reserveOnSide(input.before, "after");
535
+ const bottom = reserveOnSide(input.after, "before");
536
+ const style = {
537
+ ...top ? { "--site-style-boundary-before-reserve": top.length } : {},
538
+ ...bottom ? { "--site-style-boundary-after-reserve": bottom.length } : {}
452
539
  };
540
+ return {
541
+ topPlacement: top?.placement,
542
+ bottomPlacement: bottom?.placement,
543
+ style: top || bottom ? style : void 0
544
+ };
545
+ }
546
+ /** The reserve one join needs on one side of itself, if it draws at all. */
547
+ function reserveOnSide(slot, side) {
548
+ const layout = renderedJoinLayout(slot?.join ?? null);
549
+ const length = layout?.reserves[side] ?? null;
550
+ return layout && length ? {
551
+ length,
552
+ placement: layout.placement
553
+ } : null;
453
554
  }
454
555
  function pageBlockPosition(index, blockCount) {
455
556
  if (blockCount <= 1) return "only";
@@ -652,11 +753,10 @@ function buildPageRenderPlan(input) {
652
753
  return {
653
754
  entries,
654
755
  omitted,
655
- runtimeBoundaries: retargetBoundariesAcrossOmissions({
656
- boundaries: input.runtimeBoundaries,
756
+ runtimeJoins: retargetJoinsAcrossOmissions({
757
+ joins: input.runtimeJoins ?? [],
657
758
  originalBlocks: input.page.blocks,
658
- survivingBlocks: new Set(entries.map((entry) => entry.block)),
659
- previewStage: input.previewStage
759
+ survivingBlocks: new Set(entries.map((entry) => entry.block))
660
760
  })
661
761
  };
662
762
  }
@@ -758,86 +858,15 @@ function getBlockOverride(blockKind, overrides) {
758
858
  * For draft/preview: draftContent takes priority over content.
759
859
  * For published: content is the source of truth.
760
860
  */
761
- function getRenderableContent(block, previewStage = "published") {
762
- const source = previewStage === "preview" && block.draftContent ? block.draftContent : block.content ?? {};
763
- return isObjectRecord(source) ? source : {};
764
- }
765
861
  /**
766
- * Re-points section boundaries across omitted blocks.
767
- *
768
- * Boundaries are keyed by adjacent block-id *pairs*, so dropping B from
769
- * [A, B, C] does not merely remove B's boundaries — it removes the boundary
770
- * between the survivors, because no `A→C` key was ever compiled.
771
- *
772
- * Per decision D2 the treatment for a merged gap comes from the boundary
773
- * entering the omitted run (`A→firstOmitted`), falling back to the one leaving
774
- * it (`lastOmitted→C`). The destination surface is a separate question: only
775
- * the exiting boundary knows what C looks like, so the merged boundary ends on
776
- * that endpoint rather than on the omitted block's. In the exiting-only
777
- * fallback the origin remains an approximation: `from` is the omitted block's
778
- * surface, because no compiled boundary carries A's. The hosted path no longer
779
- * needs this at all (site-renderer admits blocks before compiling boundaries);
780
- * it remains the safety net for an SDK whose compiled boundaries predate an
781
- * omission.
862
+ * The content a block renders with. Every render path (public, preview,
863
+ * templates, SDK) chooses content here, so this is also where a stale
864
+ * `site-style-transition-*` styleGroup is dropped; authored values survive.
782
865
  */
783
- function retargetBoundariesAcrossOmissions(input) {
784
- const { boundaries, originalBlocks, survivingBlocks, previewStage } = input;
785
- if (boundaries === void 0) return void 0;
786
- if (boundaries.length === 0) return boundaries;
787
- if (!originalBlocks.some((block) => !survivingBlocks.has(block))) return boundaries;
788
- const byPair = new Map(boundaries.map((boundary) => [pairKey(boundary.previousBlockId, boundary.nextBlockId), boundary]));
789
- const retargeted = [];
790
- let previousSurvivor = null;
791
- let run = [];
792
- for (const block of originalBlocks) {
793
- if (!survivingBlocks.has(block)) {
794
- run.push(block);
795
- continue;
796
- }
797
- if (previousSurvivor?.id && block.id) {
798
- const boundary = run.length === 0 ? byPair.get(pairKey(previousSurvivor.id, block.id)) : mergedBoundary({
799
- byPair,
800
- previousBlock: previousSurvivor,
801
- previousBlockId: previousSurvivor.id,
802
- nextBlock: block,
803
- nextBlockId: block.id,
804
- run,
805
- previewStage
806
- });
807
- if (boundary) retargeted.push(boundary);
808
- }
809
- previousSurvivor = block;
810
- run = [];
811
- }
812
- return retargeted;
813
- }
814
- function mergedBoundary(input) {
815
- const { byPair, previousBlock, previousBlockId, nextBlock, nextBlockId, run, previewStage } = input;
816
- const firstOmittedId = run[0]?.id;
817
- const lastOmittedId = run[run.length - 1]?.id;
818
- const entering = firstOmittedId ? byPair.get(pairKey(previousBlockId, firstOmittedId)) : void 0;
819
- const exiting = lastOmittedId ? byPair.get(pairKey(lastOmittedId, nextBlockId)) : void 0;
820
- const donor = entering ?? exiting;
821
- if (!donor) return void 0;
822
- const transition = compileTransitionRuntime({
823
- treatment: donor.treatment,
824
- from: donor.from,
825
- to: exiting?.to ?? donor.to
826
- });
827
- return retargetCompiledBoundaryRuntimeForContentAdjacency({
828
- ...donor,
829
- boundaryId: makeBoundaryId(asDesignBlockId(previousBlockId), asDesignBlockId(nextBlockId)),
830
- previousBlockId,
831
- nextBlockId,
832
- from: transition.from,
833
- to: transition.to,
834
- cssVars: transition.cssVars
835
- }, {
836
- currentContent: getRenderableContent(previousBlock, previewStage),
837
- nextContent: getRenderableContent(nextBlock, previewStage)
838
- });
866
+ function getRenderableContent(block, previewStage = "published") {
867
+ const source = previewStage === "preview" && block.draftContent ? block.draftContent : block.content ?? {};
868
+ return isObjectRecord(source) ? stripStaleTransitionStyleGroup(source) : {};
839
869
  }
840
- const pairKey = boundaryKey;
841
870
  //#endregion
842
871
  //#region ../blocks/src/system/manifest/hydrateLinks.ts
843
872
  /**
@@ -872,7 +901,7 @@ function hydrateResolvedBookingConsentValue(value, context) {
872
901
  const hydratedItems = value.map((item) => hydrateResolvedBookingConsentValue(item, context));
873
902
  return hydratedItems.every((item, index) => item === value[index]) ? value : hydratedItems;
874
903
  }
875
- if (!isRecord$13(value)) return value;
904
+ if (!isRecord$11(value)) return value;
876
905
  if (isBookingConsentCarrier(value)) {
877
906
  const agreement = hydrateValue(value.agreement, context);
878
907
  return agreement === value.agreement ? value : {
@@ -892,7 +921,7 @@ function hydrateValue(value, context) {
892
921
  const resolvedItems = value.map((item) => hydrateValue(item, context));
893
922
  return resolvedItems.every((item, index) => item === value[index]) ? value : resolvedItems;
894
923
  }
895
- if (isRecord$13(value)) {
924
+ if (isRecord$11(value)) {
896
925
  if (isInternalLink(value)) return hydrateInternalLink(value, context.routes);
897
926
  if (isPageLink(value)) return hydratePageLink(value, context);
898
927
  if (isEntryLink(value)) return hydrateEntryLink(value, context);
@@ -957,7 +986,7 @@ function hydrateEntryLink(link, context) {
957
986
  //#region ../blocks/src/system/manifest/resolveBlockData.ts
958
987
  function resolveBlockData(blockId, dataLoaders, dataContext, routes) {
959
988
  const raw = blockId ? dataContext?.resolvedData?.[blockId] : void 0;
960
- if (isRecord$13(raw)) return routes ? hydrateResolvedBookingConsentLinks(raw, routes, dataContext?.pagesByIdentifier, dataContext?.entriesByIdentifier) : raw;
989
+ if (isRecord$11(raw)) return routes ? hydrateResolvedBookingConsentLinks(raw, routes, dataContext?.pagesByIdentifier, dataContext?.entriesByIdentifier) : raw;
961
990
  return dataLoaders && typeof dataLoaders === "object" && Object.keys(dataLoaders).length > 0 ? {} : void 0;
962
991
  }
963
992
  //#endregion
@@ -992,23 +1021,44 @@ function preparePageRender(input) {
992
1021
  prepared
993
1022
  });
994
1023
  }
995
- if (constructionFailures.length === 0 || input.audience === "authoring") return {
996
- entries,
997
- constructionFailures,
998
- runtimeBoundaries: input.plan.runtimeBoundaries
999
- };
1000
- const survivors = entries.filter((candidate) => candidate.prepared.kind !== "render-threw");
1024
+ const survivors = input.audience === "authoring" ? entries : entries.filter((candidate) => candidate.prepared.kind !== "render-threw");
1001
1025
  return {
1002
1026
  entries: survivors,
1003
1027
  constructionFailures,
1004
- runtimeBoundaries: retargetBoundariesAcrossOmissions({
1005
- boundaries: input.plan.runtimeBoundaries,
1006
- originalBlocks: input.plan.entries.map((planned) => planned.block),
1007
- survivingBlocks: new Set(survivors.map((survivor) => survivor.entry.block)),
1008
- previewStage: input.previewStage
1009
- })
1028
+ joins: composeSurvivorJoins(input.plan, survivors, input.themeResources)
1010
1029
  };
1011
1030
  }
1031
+ /**
1032
+ * The only place joins are composed. Plan-time omissions were already
1033
+ * re-pointed by the plan; construction failures are re-pointed here by the
1034
+ * same primitive, so `[A, B, C]` losing B still gets an A→C join. Each
1035
+ * survivor is then classified from its final content.
1036
+ */
1037
+ function composeSurvivorJoins(plan, survivors, themeResources) {
1038
+ return composePageJoins({
1039
+ joins: retargetJoinsAcrossOmissions({
1040
+ joins: plan.runtimeJoins,
1041
+ originalBlocks: plan.entries.map((planned) => planned.block),
1042
+ survivingBlocks: new Set(survivors.map((survivor) => survivor.entry.block))
1043
+ }),
1044
+ survivors: survivors.map(({ entry }) => ({
1045
+ id: entry.block.id,
1046
+ kind: entry.block.kind,
1047
+ content: boundaryClassificationContent(entry, themeResources)
1048
+ }))
1049
+ });
1050
+ }
1051
+ /**
1052
+ * The content a join is classified from must be the content that paints the
1053
+ * section. The default block renderer layers the theme's per-block style
1054
+ * defaults (`theme.blockOverrides[kind].styles`, background included) under
1055
+ * the block's own `_sectionStyles`, so classify that same projection. An
1056
+ * override component renders its own markup from the unmerged content.
1057
+ */
1058
+ function boundaryClassificationContent(entry, themeResources) {
1059
+ if (entry.kind !== "renderable" || entry.override) return entry.renderableContent;
1060
+ return mergeContentWithBlockStyleOverrides(entry.renderableContent, themeResources.kind === "available" ? themeResources.config : void 0, entry.block.kind);
1061
+ }
1012
1062
  function prepareEntry(entry, input) {
1013
1063
  if (entry.kind !== "renderable") return { kind: "plan-decided" };
1014
1064
  const draftContent = previewableEditorContent(entry);
@@ -1181,7 +1231,7 @@ function EditorPageRenderer(props) {
1181
1231
  });
1182
1232
  }
1183
1233
  function PageRendererCore(props) {
1184
- const { page, audience, runtimeBoundaries, dataContext, routeMap, registry, sdkConfig, customBlocks, blockOverrides } = props;
1234
+ const { page, audience, runtimeJoins, dataContext, routeMap, registry, sdkConfig, customBlocks, blockOverrides } = props;
1185
1235
  const imageResolveContext = React$1.useMemo(() => resolvePageRendererImageResolveContext(dataContext), [
1186
1236
  dataContext?.imageResolveContext,
1187
1237
  dataContext?.mediaAssets,
@@ -1197,7 +1247,7 @@ function PageRendererCore(props) {
1197
1247
  blocks: []
1198
1248
  },
1199
1249
  audience,
1200
- runtimeBoundaries,
1250
+ runtimeJoins,
1201
1251
  previewStage,
1202
1252
  sdkConfig,
1203
1253
  customBlocks,
@@ -1205,7 +1255,7 @@ function PageRendererCore(props) {
1205
1255
  }), [
1206
1256
  page,
1207
1257
  audience,
1208
- runtimeBoundaries,
1258
+ runtimeJoins,
1209
1259
  previewStage,
1210
1260
  sdkConfig,
1211
1261
  customBlocks,
@@ -1222,19 +1272,16 @@ function PageRendererCore(props) {
1222
1272
  dataContext,
1223
1273
  routeMap,
1224
1274
  themeResources,
1225
- imageResolveContext,
1226
- previewStage
1275
+ imageResolveContext
1227
1276
  }), [
1228
1277
  plan,
1229
1278
  audience,
1230
1279
  dataContext,
1231
1280
  routeMap,
1232
1281
  themeResources,
1233
- imageResolveContext,
1234
- previewStage
1282
+ imageResolveContext
1235
1283
  ]);
1236
- const boundaryByAdjacentBlockIds = React$1.useMemo(() => boundaryMapForAdjacentBlockIds(preparation.runtimeBoundaries ?? []), [preparation.runtimeBoundaries]);
1237
- const usesRuntimeBoundaries = preparation.runtimeBoundaries !== void 0;
1284
+ const joinSlots = React$1.useMemo(() => joinSlotsByPair(preparation.joins), [preparation.joins]);
1238
1285
  reportAndReplayOmissions({
1239
1286
  plan,
1240
1287
  preparation,
@@ -1252,10 +1299,9 @@ function PageRendererCore(props) {
1252
1299
  themeResources,
1253
1300
  imageResolveContext,
1254
1301
  resolvedRegistry,
1255
- boundaryByAdjacentBlockIds,
1256
- usesRuntimeBoundaries,
1302
+ joinSlots,
1257
1303
  wrapBlock: props.wrapBlock,
1258
- wrapBoundary: props.wrapBoundary
1304
+ renderJoin: props.renderJoin
1259
1305
  })) });
1260
1306
  }
1261
1307
  /**
@@ -1344,27 +1390,25 @@ function requireEntryBlockOverride(entry, themeResources) {
1344
1390
  }
1345
1391
  /**
1346
1392
  * Renders one planned block: its wrapper, style-group data attributes,
1347
- * boundary reserve space and any boundary or transition sibling that follows.
1393
+ * boundary reserve space and the join markup that follows it.
1348
1394
  *
1349
1395
  * Extracted from PageRendererCore so the component stays about wiring the plan
1350
1396
  * rather than also owning per-block markup.
1351
1397
  */
1352
1398
  function renderPlanEntry(input) {
1353
- const { index, entries, props, themeResources, imageResolveContext, resolvedRegistry, boundaryByAdjacentBlockIds, usesRuntimeBoundaries, wrapBlock, wrapBoundary } = input;
1399
+ const { index, entries, props, themeResources, imageResolveContext, resolvedRegistry, joinSlots, wrapBlock, renderJoin } = input;
1354
1400
  const entry = input.entry.entry;
1355
1401
  const block = entry.block;
1356
1402
  const blockPosition = pageBlockPosition(index, entries.length);
1357
1403
  const blockKey = blockKeyFor(block, index);
1358
1404
  const previousBlock = entries[index - 1]?.entry.block ?? null;
1359
1405
  const nextBlock = entries[index + 1]?.entry.block ?? null;
1360
- const boundaryBefore = boundaryBetweenBlocks(previousBlock, block, boundaryByAdjacentBlockIds);
1361
- const boundaryAfter = boundaryBetweenBlocks(block, nextBlock, boundaryByAdjacentBlockIds);
1362
- const boundaryElement = renderBoundaryAfterBlock({
1363
- block,
1364
- nextBlock,
1406
+ const joinBefore = joinSlotBetween(previousBlock?.id, block.id, joinSlots);
1407
+ const joinAfter = joinSlotBetween(block.id, nextBlock?.id, joinSlots);
1408
+ const boundaryElement = renderJoinSlot({
1409
+ slot: joinAfter,
1365
1410
  blockKey,
1366
- boundaryByAdjacentBlockIds,
1367
- wrapBoundary
1411
+ renderJoin
1368
1412
  });
1369
1413
  const cleanKind = block.kind.replace(/^block\./, "");
1370
1414
  const managesOwnWrapper = entry.kind === "renderable" && entry.managesOwnWrapper;
@@ -1387,11 +1431,10 @@ function renderPlanEntry(input) {
1387
1431
  const styleGroup = typeof renderableContent.styleGroup === "string" ? renderableContent.styleGroup : void 0;
1388
1432
  const blockLook = typeof renderableContent.blockLook === "string" ? renderableContent.blockLook : void 0;
1389
1433
  const blockComposition = readBlockComposition(renderableContent.blockComposition);
1390
- const transitionStyle = transitionCssVarsStyle(renderableContent);
1391
- const blockStyle = mergeStyleObjects(transitionStyle, boundaryReserveCssVarsStyle({
1392
- before: boundaryBefore,
1393
- after: boundaryAfter
1394
- }));
1434
+ const reserves = blockBoundaryReserves({
1435
+ before: joinBefore,
1436
+ after: joinAfter
1437
+ });
1395
1438
  const blockElement = /* @__PURE__ */ jsx("div", {
1396
1439
  className: wrapperClassName,
1397
1440
  "data-block": cleanKind,
@@ -1403,21 +1446,14 @@ function renderPlanEntry(input) {
1403
1446
  "data-block-composition": blockComposition?.treatment,
1404
1447
  "data-block-composition-kind": blockComposition?.kind,
1405
1448
  "data-page-block-position": blockPosition,
1406
- "data-site-style-boundary-before": boundaryBefore?.metrics.size,
1407
- "data-site-style-boundary-after": boundaryAfter?.metrics.size,
1449
+ "data-site-style-boundary-before": reserves.topPlacement,
1450
+ "data-site-style-boundary-after": reserves.bottomPlacement,
1408
1451
  "data-style-group": styleGroup,
1409
- style: blockStyle,
1452
+ style: reserves.style,
1410
1453
  children: /* @__PURE__ */ jsx(MemoBlockSection, { ...blockSectionProps })
1411
1454
  }, blockKey);
1412
1455
  if (boundaryElement) return /* @__PURE__ */ jsxs(React$1.Fragment, { children: [blockElement, boundaryElement] }, blockKey);
1413
- if (usesRuntimeBoundaries || !isSiteStyleTransitionStyleGroup(styleGroup)) return blockElement;
1414
- return /* @__PURE__ */ jsxs(React$1.Fragment, { children: [blockElement, /* @__PURE__ */ jsx("div", {
1415
- "aria-hidden": "true",
1416
- "data-block-transition": "",
1417
- "data-block-transition-for": block.id ?? blockKey,
1418
- "data-style-group": styleGroup,
1419
- style: transitionStyle
1420
- })] }, blockKey);
1456
+ return blockElement;
1421
1457
  }
1422
1458
  function resolvePageRendererImageResolveContext(dataContext) {
1423
1459
  const input = dataContext?.imageResolveContext;
@@ -2063,6 +2099,17 @@ function coerceToString(value) {
2063
2099
  return "";
2064
2100
  }
2065
2101
  /**
2102
+ * The appointment-services catalogue (issue 1403) pairs the services with the
2103
+ * site's ordered categories. Both are needed to group them, so that response
2104
+ * is passed through whole; any other `{ services }` wrapper is unwrapped.
2105
+ */
2106
+ function coerceServicesPayload(record) {
2107
+ return Array.isArray(record.services) && Array.isArray(record.categories) ? {
2108
+ services: record.services,
2109
+ categories: record.categories
2110
+ } : record.services;
2111
+ }
2112
+ /**
2066
2113
  * Extract data from API response.
2067
2114
  * Unwraps common response wrappers: { data }, { form }, { entries }, { services }, { teamMembers }
2068
2115
  *
@@ -2077,7 +2124,7 @@ function coercePayload(payload) {
2077
2124
  if ("data" in record && typeof record.data !== "function") return record.data;
2078
2125
  if ("form" in record && typeof record.form !== "function") return record.form;
2079
2126
  if ("entries" in record && typeof record.entries !== "function") return record.entries;
2080
- if ("services" in record && typeof record.services !== "function") return record.services;
2127
+ if ("services" in record && typeof record.services !== "function") return coerceServicesPayload(record);
2081
2128
  if ("teamMembers" in record && typeof record.teamMembers !== "function") return record.teamMembers;
2082
2129
  }
2083
2130
  return payload;
@@ -2865,7 +2912,7 @@ function assertRelativeStoragePath(value) {
2865
2912
  if (!parsed.ok) throw new Error(`Expected RelativeStoragePath, got ${parsed.error.tag}`);
2866
2913
  return parsed.value;
2867
2914
  }
2868
- function isRecord$11(value) {
2915
+ function isRecord$9(value) {
2869
2916
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2870
2917
  }
2871
2918
  function parseFileKindJson(value) {
@@ -3086,7 +3133,7 @@ function parseEntitledCustomerAccessScopeJson(value) {
3086
3133
  }
3087
3134
  }
3088
3135
  function requireRecord(value) {
3089
- if (!isRecord$11(value)) return err("expected-object");
3136
+ if (!isRecord$9(value)) return err("expected-object");
3090
3137
  return ok(value);
3091
3138
  }
3092
3139
  function requireString(value) {
@@ -3338,7 +3385,7 @@ const DEFAULT_MESSAGES = {
3338
3385
  update: "Failed to update media asset",
3339
3386
  delete: "Failed to delete media asset"
3340
3387
  };
3341
- function isRecord$10(value) {
3388
+ function isRecord$8(value) {
3342
3389
  return typeof value === "object" && value !== null;
3343
3390
  }
3344
3391
  const normalizeLabels = (labels) => labels !== void 0 && labels.length > 0 ? labels.map((label) => label.trim()).filter((label) => label.length > 0).join(",") : void 0;
@@ -3372,7 +3419,7 @@ const filterUpdatePayload = (input) => {
3372
3419
  return payload;
3373
3420
  };
3374
3421
  const extractErrorMessage = (body) => {
3375
- if (!isRecord$10(body)) return typeof body === "string" && body.trim().length > 0 ? body : null;
3422
+ if (!isRecord$8(body)) return typeof body === "string" && body.trim().length > 0 ? body : null;
3376
3423
  for (const key of [
3377
3424
  "error",
3378
3425
  "message",
@@ -3385,11 +3432,11 @@ const extractErrorMessage = (body) => {
3385
3432
  const details = body.details;
3386
3433
  if (Array.isArray(details)) for (const entry of details) {
3387
3434
  if (typeof entry === "string" && entry.trim().length > 0) return entry;
3388
- if (isRecord$10(entry) && typeof entry.message === "string" && entry.message.trim().length > 0) return entry.message;
3435
+ if (isRecord$8(entry) && typeof entry.message === "string" && entry.message.trim().length > 0) return entry.message;
3389
3436
  }
3390
3437
  const errors = body.errors;
3391
3438
  if (Array.isArray(errors)) {
3392
- for (const entry of errors) if (isRecord$10(entry) && typeof entry.message === "string" && entry.message.trim().length > 0) return entry.message;
3439
+ for (const entry of errors) if (isRecord$8(entry) && typeof entry.message === "string" && entry.message.trim().length > 0) return entry.message;
3393
3440
  }
3394
3441
  return null;
3395
3442
  };
@@ -5267,7 +5314,7 @@ function parseBackgroundOverrideFromContent(content) {
5267
5314
  * Only the explicit owner marker can make a background a page-design override.
5268
5315
  */
5269
5316
  function parseCanonicalSectionBackground(content) {
5270
- const background = (isRecord$9(content._sectionStyles) ? content._sectionStyles : null)?.background;
5317
+ const background = (isRecord$7(content._sectionStyles) ? content._sectionStyles : null)?.background;
5271
5318
  if (background === null || background === void 0) return { kind: "none" };
5272
5319
  const canonical = parseBackgroundContent(background);
5273
5320
  if (!canonical) return { kind: "none" };
@@ -5285,7 +5332,7 @@ function parseBackgroundOverride(value) {
5285
5332
  kind: "supported",
5286
5333
  override: DEFAULT_BACKGROUND_OVERRIDE
5287
5334
  };
5288
- if (!isRecord$9(value)) return {
5335
+ if (!isRecord$7(value)) return {
5289
5336
  kind: "unsupported",
5290
5337
  reason: "unsupported-shape",
5291
5338
  background: {}
@@ -5373,7 +5420,7 @@ function parseBackgroundOverride(value) {
5373
5420
  }
5374
5421
  }
5375
5422
  function applyBackgroundOverrideContentPatch(content, override) {
5376
- const sectionStyles = isRecord$9(content._sectionStyles) ? content._sectionStyles : {};
5423
+ const sectionStyles = isRecord$7(content._sectionStyles) ? content._sectionStyles : {};
5377
5424
  const serialized = serializeBackgroundOverride(override);
5378
5425
  if (serialized === null) return withSectionStyles(content, omitRecordKey$1(sectionStyles, "background"));
5379
5426
  return withSectionStyles(content, {
@@ -5597,7 +5644,7 @@ function imageAllowed(mediaId, pool) {
5597
5644
  return pool?.some((item) => item.mediaId === mediaId) ?? false;
5598
5645
  }
5599
5646
  function parseImageMediaAssetId(value) {
5600
- if (!isRecord$9(value)) return { kind: "missing" };
5647
+ if (!isRecord$7(value)) return { kind: "missing" };
5601
5648
  if (value.type !== void 0 && value.type !== "image") return { kind: "missing" };
5602
5649
  const parsed = parseMediaAssetId(value.assetId);
5603
5650
  if (!parsed.ok) return value.assetId === void 0 || value.assetId === null ? { kind: "missing" } : { kind: "invalid" };
@@ -5638,7 +5685,7 @@ function withSectionStyles(content, sectionStyles) {
5638
5685
  function omitRecordKey$1(content, key) {
5639
5686
  return Object.fromEntries(Object.entries(content).filter(([entryKey]) => entryKey !== key));
5640
5687
  }
5641
- function isRecord$9(value) {
5688
+ function isRecord$7(value) {
5642
5689
  return typeof value === "object" && value !== null && !Array.isArray(value);
5643
5690
  }
5644
5691
  //#endregion
@@ -6238,10 +6285,12 @@ function applyPreviewCustomizeActionToLoadedState(state, action) {
6238
6285
  ...state.editorModel,
6239
6286
  boundaries: state.editorModel.boundaries.map((boundary) => {
6240
6287
  if (boundary.previousBlockId !== action.previousBlockId || boundary.nextBlockId !== action.nextBlockId) return boundary;
6241
- return {
6242
- ...boundary,
6243
- breakChoice: optimisticBoundaryBreakChoice(state.editorModel, boundary, action)
6244
- };
6288
+ return resolvePageDesignEditorBoundaryForChoice({
6289
+ editorModel: state.editorModel,
6290
+ previousBlockId: boundary.previousBlockId,
6291
+ nextBlockId: boundary.nextBlockId,
6292
+ choice: optimisticBoundaryChoice(action)
6293
+ }) ?? boundary;
6245
6294
  })
6246
6295
  }
6247
6296
  };
@@ -6274,26 +6323,17 @@ function optimisticLayoutLookState(block, layoutVariantKey) {
6274
6323
  default: return assertNever$1(plan, "Unhandled layout/Look compatibility plan");
6275
6324
  }
6276
6325
  }
6277
- function optimisticBoundaryBreakChoice(editorModel, boundary, action) {
6326
+ /**
6327
+ * The stored choice an action leaves behind. The effective break, its source
6328
+ * and the join are then resolved by theme-core, exactly as the server will.
6329
+ */
6330
+ function optimisticBoundaryChoice(action) {
6278
6331
  switch (action.kind) {
6279
- case "set-boundary": return {
6280
- kind: "user-pinned",
6281
- value: action.boundaryOptionId,
6282
- status: "supported",
6283
- effectiveValue: action.boundaryOptionId
6284
- };
6285
- case "reset-boundary": return {
6286
- kind: "auto",
6287
- effectiveValue: autoBoundaryEffectiveValue(editorModel, boundary)
6288
- };
6332
+ case "set-boundary": return userPinnedDesignChoice(boundaryTreatmentForBoundaryOptionId(action.boundaryOptionId));
6333
+ case "reset-boundary": return autoDesignChoice();
6289
6334
  default: return assertNever$1(action, "Unhandled optimistic boundary action");
6290
6335
  }
6291
6336
  }
6292
- function autoBoundaryEffectiveValue(editorModel, boundary) {
6293
- const preferredBoundaryOptionId = editorModel.pageFlowPresets.find((preset) => preset.id === editorModel.pageFlow.effectiveValue)?.defaultBoundaryOptionId ?? null;
6294
- if (preferredBoundaryOptionId && boundary.availableBreaks.some((option) => option.id === preferredBoundaryOptionId)) return preferredBoundaryOptionId;
6295
- return boundary.availableBreaks[0]?.id ?? null;
6296
- }
6297
6337
  //#endregion
6298
6338
  //#region ../blocks/src/system/customize/facets.ts
6299
6339
  function defineCustomizeFacet(definition) {
@@ -6439,8 +6479,8 @@ function contentWithPreviousLayoutVariant(currentContent, previousContent) {
6439
6479
  return nextContent;
6440
6480
  }
6441
6481
  function contentWithPreviousBackground(currentContent, previousContent) {
6442
- const previousSectionStyles = isRecord$8(previousContent._sectionStyles) ? previousContent._sectionStyles : {};
6443
- const nextSectionStyles = { ...isRecord$8(currentContent._sectionStyles) ? currentContent._sectionStyles : {} };
6482
+ const previousSectionStyles = isRecord$6(previousContent._sectionStyles) ? previousContent._sectionStyles : {};
6483
+ const nextSectionStyles = { ...isRecord$6(currentContent._sectionStyles) ? currentContent._sectionStyles : {} };
6444
6484
  if (Object.prototype.hasOwnProperty.call(previousSectionStyles, "background")) nextSectionStyles.background = previousSectionStyles.background;
6445
6485
  else delete nextSectionStyles.background;
6446
6486
  if (Object.keys(nextSectionStyles).length > 0) return {
@@ -6453,9 +6493,9 @@ function contentWithPreviousBackground(currentContent, previousContent) {
6453
6493
  }
6454
6494
  function withRuntimeBackgroundImageAsset(content, imageAsset) {
6455
6495
  if (!imageAsset) return content;
6456
- const sectionStyles = isRecord$8(content._sectionStyles) ? content._sectionStyles : null;
6457
- const background = isRecord$8(sectionStyles?.background) ? sectionStyles.background : null;
6458
- const image = isRecord$8(background?.image) ? background.image : null;
6496
+ const sectionStyles = isRecord$6(content._sectionStyles) ? content._sectionStyles : null;
6497
+ const background = isRecord$6(sectionStyles?.background) ? sectionStyles.background : null;
6498
+ const image = isRecord$6(background?.image) ? background.image : null;
6459
6499
  if (!sectionStyles || !background || !image || background.type !== "image") return content;
6460
6500
  return {
6461
6501
  ...content,
@@ -6468,7 +6508,7 @@ function withRuntimeBackgroundImageAsset(content, imageAsset) {
6468
6508
  }
6469
6509
  };
6470
6510
  }
6471
- function isRecord$8(value) {
6511
+ function isRecord$6(value) {
6472
6512
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
6473
6513
  }
6474
6514
  //#endregion
@@ -6498,7 +6538,7 @@ function rollbackPreviewCustomizeDraftPatch(uiStore, patch) {
6498
6538
  }
6499
6539
  function currentLocalBlockContent(uiStore, targetBlockId) {
6500
6540
  const current = uiStore.getState().drafts.getCurrentValues(unsafeAsEditorBlockId(targetBlockId));
6501
- return isRecord$7(current) ? current : null;
6541
+ return isRecord$5(current) ? current : null;
6502
6542
  }
6503
6543
  function replaceLocalBlockContentWithoutHistory(input) {
6504
6544
  const editorBlockId = unsafeAsEditorBlockId(input.targetBlockId);
@@ -6551,7 +6591,7 @@ function localRuntimeDraftForBlock(input) {
6551
6591
  }
6552
6592
  };
6553
6593
  }
6554
- function isRecord$7(value) {
6594
+ function isRecord$5(value) {
6555
6595
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
6556
6596
  }
6557
6597
  //#endregion
@@ -7038,6 +7078,7 @@ function PreviewEntryControllerProvider({ children, siteId, pageId, routeId: pro
7038
7078
  const normalizedInitialBlocks = useMemo(() => {
7039
7079
  return (initialBlocks ?? []).map((b, index) => ({
7040
7080
  id: b.id ?? null,
7081
+ contentVersionId: b.contentVersionId ?? null,
7041
7082
  kind: b.kind,
7042
7083
  orderIndex: typeof b.orderIndex === "number" ? b.orderIndex : index,
7043
7084
  content: b.content ?? null,
@@ -7395,25 +7436,25 @@ const INITIAL_ONBOARDING_CONFIRMATION_STATE = {
7395
7436
  resendFeedback: null,
7396
7437
  statusLoadFailed: false
7397
7438
  };
7398
- function isRecord$6(value) {
7439
+ function isRecord$4(value) {
7399
7440
  return value !== null && typeof value === "object";
7400
7441
  }
7401
7442
  function getErrorMessageFromEnvelope(payload, fallback) {
7402
- const error = isRecord$6(payload) ? payload.error : null;
7403
- const message = isRecord$6(error) ? error.message : null;
7443
+ const error = isRecord$4(payload) ? payload.error : null;
7444
+ const message = isRecord$4(error) ? error.message : null;
7404
7445
  return typeof message === "string" && message.trim().length > 0 ? message : fallback;
7405
7446
  }
7406
7447
  function isLaunchReadiness(value) {
7407
- return isRecord$6(value) && Array.isArray(value.requirements) && typeof value.pendingRequiredCount === "number" && typeof value.pendingRecommendedCount === "number" && typeof value.pendingOptionalCount === "number" && isRecord$6(value.goLiveDecision) && (value.goLiveDecision.kind === "allowed" || value.goLiveDecision.kind === "blocked");
7448
+ return isRecord$4(value) && Array.isArray(value.requirements) && typeof value.pendingRequiredCount === "number" && typeof value.pendingRecommendedCount === "number" && typeof value.pendingOptionalCount === "number" && isRecord$4(value.goLiveDecision) && (value.goLiveDecision.kind === "allowed" || value.goLiveDecision.kind === "blocked");
7408
7449
  }
7409
7450
  function isOnboardingPreviewStatusResponse(value) {
7410
- return isRecord$6(value) && typeof value.dashboardUnlocked === "boolean" && typeof value.requiresEmailConfirmation === "boolean" && isLaunchReadiness(value.launchReadiness);
7451
+ return isRecord$4(value) && typeof value.dashboardUnlocked === "boolean" && typeof value.requiresEmailConfirmation === "boolean" && isLaunchReadiness(value.launchReadiness);
7411
7452
  }
7412
7453
  function isResendOnboardingPreviewConfirmationResponse(value) {
7413
- return isRecord$6(value) && (value.result === "resent" || value.result === "already_confirmed") && typeof value.dashboardUnlocked === "boolean" && typeof value.requiresEmailConfirmation === "boolean" && isLaunchReadiness(value.launchReadiness);
7454
+ return isRecord$4(value) && (value.result === "resent" || value.result === "already_confirmed") && typeof value.dashboardUnlocked === "boolean" && typeof value.requiresEmailConfirmation === "boolean" && isLaunchReadiness(value.launchReadiness);
7414
7455
  }
7415
7456
  function getSuccessData(payload, isData) {
7416
- if (!isRecord$6(payload) || payload.success !== true || !isData(payload.data)) return null;
7457
+ if (!isRecord$4(payload) || payload.success !== true || !isData(payload.data)) return null;
7417
7458
  return payload.data;
7418
7459
  }
7419
7460
  function useOnboardingConfirmationCheck(input) {
@@ -9259,10 +9300,10 @@ function resolveShellThemeRoles(props) {
9259
9300
  }
9260
9301
  const previewContainerResponsiveEnabled = process.env.NEXT_PUBLIC_ENABLE_PREVIEW_CONTAINER_RESPONSIVE !== "false";
9261
9302
  const PreviewEditorSidebar = React.lazy(async () => {
9262
- return { default: (await import("./PreviewEditorSidebar-CQZNnFiM.mjs")).PreviewEditorSidebar };
9303
+ return { default: (await import("./PreviewEditorSidebar-O-V6Pl5a.mjs")).PreviewEditorSidebar };
9263
9304
  });
9264
9305
  const PreviewEditorUI = React.lazy(async () => {
9265
- return { default: (await import("./PreviewEditorUI-DCNxnmI0.mjs")).PreviewEditorUI };
9306
+ return { default: (await import("./PreviewEditorUI-1UlX_9cw.mjs")).PreviewEditorUI };
9266
9307
  });
9267
9308
  const previewPaneContainmentStyle = {
9268
9309
  contain: "layout paint",
@@ -9709,11 +9750,11 @@ function resolveShellAccess(input) {
9709
9750
  //#region ../preview-next/src/client/utils/path.ts
9710
9751
  const PATH_SEPARATOR_REGEX = /\./g;
9711
9752
  const BRACKET_ACCESS_REGEX = /\[([^\]]+)\]/g;
9712
- function isRecord$5(value) {
9753
+ function isRecord$3(value) {
9713
9754
  return typeof value === "object" && value !== null && !Array.isArray(value);
9714
9755
  }
9715
9756
  function isPathContainer(value) {
9716
- return Array.isArray(value) || isRecord$5(value);
9757
+ return Array.isArray(value) || isRecord$3(value);
9717
9758
  }
9718
9759
  function createPathContainer(nextIsIndex) {
9719
9760
  return nextIsIndex ? [] : {};
@@ -9876,24 +9917,21 @@ function runtimeContentDecorationProjectionFromEditorModel(editorModel, surfaceR
9876
9917
  kind: "runtime-content-decoration",
9877
9918
  source: "page-design",
9878
9919
  fieldsByBlockId: runtimeFieldsByBlockId(compiled.blocks),
9879
- boundaries: compiled.boundaries
9920
+ joins: compiled.joins
9880
9921
  };
9881
9922
  }
9882
9923
  function runtimeFieldsByBlockId(blocks) {
9883
9924
  return new Map(blocks.map((block) => [block.blockId, block.fields]));
9884
9925
  }
9885
- function applyRuntimeContentDecorationProjection(block, content, projection, adjacency) {
9926
+ function applyRuntimeContentDecorationProjection(block, content, projection) {
9886
9927
  const blockId = designBlockIdFromBlockItem(block);
9887
- const retargetedFields = retargetCompiledRuntimeFieldsForContentAdjacency(blockId ? projection.fieldsByBlockId.get(blockId) : void 0, {
9888
- currentContent: isRecord$4(content) ? content : null,
9889
- nextContent: adjacency?.nextContent
9890
- });
9891
- return applyCompiledRuntimeFieldsToContent(isRecord$4(content) ? content : {}, retargetedFields);
9928
+ const fields = blockId ? projection.fieldsByBlockId.get(blockId) : void 0;
9929
+ return applyCompiledRuntimeFieldsToContent(isRecord$2(content) ? content : {}, fields);
9892
9930
  }
9893
9931
  function designBlockIdFromBlockItem(block) {
9894
9932
  return typeof block.id === "string" && block.id.length > 0 ? asDesignBlockId(block.id) : null;
9895
9933
  }
9896
- function isRecord$4(value) {
9934
+ function isRecord$2(value) {
9897
9935
  return typeof value === "object" && value !== null && !Array.isArray(value);
9898
9936
  }
9899
9937
  //#endregion
@@ -9910,10 +9948,10 @@ function applyPreviewContentFieldProjections(blockId, content, projections) {
9910
9948
  return applyContentFieldOverrideProjection(blockId, current, projection);
9911
9949
  }, content);
9912
9950
  }
9913
- function applyPreviewRuntimeContentProjections(block, content, projections, adjacency) {
9951
+ function applyPreviewRuntimeContentProjections(block, content, projections) {
9914
9952
  return projections.reduce((current, projection) => {
9915
9953
  if (projection.kind !== "runtime-content-decoration") return current;
9916
- return applyRuntimeContentDecorationProjection(block, current, projection, adjacency);
9954
+ return applyRuntimeContentDecorationProjection(block, current, projection);
9917
9955
  }, content);
9918
9956
  }
9919
9957
  function blockHasPreviewContentFieldProjection(blockId, projections) {
@@ -9944,7 +9982,7 @@ function overlayValue(value, overlays) {
9944
9982
  });
9945
9983
  return changed ? next : value;
9946
9984
  }
9947
- if (!isRecord$3(value)) return value;
9985
+ if (!isRecord$1(value)) return value;
9948
9986
  const meta = parseLinkedEntryMeta(value[LINKED_CONTENT_ENTRY_META_KEY]);
9949
9987
  if (meta) {
9950
9988
  const overlay = overlays.get(unsafeAsLinkedContentEntryId(meta.entryId));
@@ -10010,7 +10048,7 @@ function resolveOverlayTitle(content, meta) {
10010
10048
  function parseLinkedEntryMeta(value) {
10011
10049
  return getLinkedContentEntryMeta({ [LINKED_CONTENT_ENTRY_META_KEY]: value });
10012
10050
  }
10013
- function isRecord$3(value) {
10051
+ function isRecord$1(value) {
10014
10052
  return typeof value === "object" && value !== null && !Array.isArray(value);
10015
10053
  }
10016
10054
  //#endregion
@@ -10020,48 +10058,36 @@ function getDraftSnapshots(uiStore) {
10020
10058
  const snapshots = uiStore.getState().drafts.inspect();
10021
10059
  return new Map(snapshots.map((snap) => [snap.id, snap]));
10022
10060
  }
10023
- function mergeBlockWithDraft(block, draftMap, index, projections = [], linkedEntryOverlays = EMPTY_LINKED_ENTRY_OVERLAY, nextBlock = null) {
10061
+ function mergeBlockWithDraft(block, draftMap, index, projections = [], linkedEntryOverlays = EMPTY_LINKED_ENTRY_OVERLAY) {
10024
10062
  const id = block.id ?? null;
10025
10063
  const editorBlockId = id ? unsafeAsEditorBlockId(id) : null;
10026
10064
  const snap = editorBlockId ? draftMap.get(editorBlockId) ?? null : null;
10027
10065
  const draftContent = editorBlockId ? readProjectedDraftRenderContent(block, editorBlockId, snap, projections) : null;
10028
10066
  const baseline = snap?.baseline ?? block.content ?? block.publishedContent ?? null;
10029
- const nextContent = nextBlock ? readBlockRenderContents(nextBlock, draftMap, projections) : null;
10030
10067
  return {
10031
10068
  id,
10069
+ contentVersionId: block.contentVersionId ?? null,
10032
10070
  kind: block.kind,
10033
10071
  purpose: "content",
10034
10072
  orderIndex: block.orderIndex ?? index,
10035
- content: renderContent(block, baseline, projections, linkedEntryOverlays, nextContent?.baseline ?? null),
10036
- draftContent: renderContent(block, draftContent, projections, linkedEntryOverlays, nextContent?.draft ?? null),
10037
- publishedContent: renderContent(block, block.publishedContent ?? null, projections, EMPTY_LINKED_ENTRY_OVERLAY, nextContent?.published ?? null),
10073
+ content: renderContent(block, baseline, projections, linkedEntryOverlays),
10074
+ draftContent: renderContent(block, draftContent, projections, linkedEntryOverlays),
10075
+ publishedContent: renderContent(block, block.publishedContent ?? null, projections, EMPTY_LINKED_ENTRY_OVERLAY),
10038
10076
  bindings: block.bindings ?? null
10039
10077
  };
10040
10078
  }
10041
- function readBlockRenderContents(block, draftMap, projections) {
10042
- const id = block.id ?? null;
10043
- const editorBlockId = id ? unsafeAsEditorBlockId(id) : null;
10044
- const snap = editorBlockId ? draftMap.get(editorBlockId) ?? null : null;
10045
- return {
10046
- baseline: snap?.baseline ?? block.content ?? block.publishedContent ?? null,
10047
- draft: editorBlockId ? readProjectedDraftRenderContent(block, editorBlockId, snap, projections) : null,
10048
- published: block.publishedContent ?? null
10049
- };
10050
- }
10051
10079
  function readProjectedDraftRenderContent(block, editorBlockId, snap, projections) {
10052
10080
  return applyPreviewContentFieldProjections(editorBlockId, snap?.current ?? snap?.baseline ?? block.content ?? block.publishedContent ?? null, projections);
10053
10081
  }
10054
- function renderContent(block, content, projections, linkedEntryOverlays, nextContent) {
10055
- return applyPreviewRuntimeContentProjections(block, applyLinkedEntryRenderOverlay(content, linkedEntryOverlays), projections, { nextContent: isRecord$2(nextContent) ? nextContent : null });
10056
- }
10057
- function isRecord$2(value) {
10058
- return typeof value === "object" && value !== null && !Array.isArray(value);
10082
+ function renderContent(block, content, projections, linkedEntryOverlays) {
10083
+ return applyPreviewRuntimeContentProjections(block, applyLinkedEntryRenderOverlay(content, linkedEntryOverlays), projections);
10059
10084
  }
10060
10085
  //#endregion
10061
10086
  //#region ../preview-next/src/client/blocks/composer/transformBlock.ts
10062
10087
  function transformToPageBlock(enriched) {
10063
10088
  return {
10064
10089
  id: enriched.id,
10090
+ ...enriched.contentVersionId !== null ? { contentVersionId: enriched.contentVersionId } : {},
10065
10091
  kind: enriched.kind,
10066
10092
  purpose: enriched.purpose,
10067
10093
  content: enriched.content ?? {},
@@ -10113,8 +10139,7 @@ function composePreviewRenderPage(args, cacheRef) {
10113
10139
  if (!page) return page;
10114
10140
  if (!blockItems.length) return page;
10115
10141
  const draftMap = draftSnapshotMap(draftSnapshots);
10116
- const projectedBlockItems = applyPreviewStructureProjections(blockItems, projections);
10117
- const renderedBlocks = applyCacheOptimization([...projectedBlockItems.map((block, index) => mergeBlockWithDraft(block, draftMap, index, projections, linkedEntryOverlays, projectedBlockItems[index + 1] ?? null))].sort((a, b) => (a.orderIndex ?? 0) - (b.orderIndex ?? 0)), cacheRef);
10142
+ const renderedBlocks = applyCacheOptimization([...applyPreviewStructureProjections(blockItems, projections).map((block, index) => mergeBlockWithDraft(block, draftMap, index, projections, linkedEntryOverlays))].sort((a, b) => (a.orderIndex ?? 0) - (b.orderIndex ?? 0)), cacheRef);
10118
10143
  return {
10119
10144
  ...page,
10120
10145
  blocks: renderedBlocks
@@ -10276,7 +10301,7 @@ const editorRegistry = {
10276
10301
  };
10277
10302
  //#endregion
10278
10303
  //#region ../preview-next/src/client/blocks/isRecord.ts
10279
- function isRecord$1(value) {
10304
+ function isRecord(value) {
10280
10305
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
10281
10306
  }
10282
10307
  //#endregion
@@ -10450,7 +10475,7 @@ function BlockToolbar({ blockId, blockKind, content, bookingOfferingPresets, the
10450
10475
  const uiStore = useEditorUiStoreInstance();
10451
10476
  const editorBlockId = useMemo(() => unsafeAsEditorBlockId(blockId), [blockId]);
10452
10477
  const draftContent = useEditorUiStore((state) => state.drafts.getCurrentValues(editorBlockId));
10453
- const customizeContent = useMemo(() => isRecord$1(draftContent) ? draftContent : content, [content, draftContent]);
10478
+ const customizeContent = useMemo(() => isRecord(draftContent) ? draftContent : content, [content, draftContent]);
10454
10479
  const customizeSelection = usePreviewBlockCustomizeSelectionOptional();
10455
10480
  const popover = useCustomizePopoverController();
10456
10481
  const focusTarget = useMemo(() => computeDefaultFocus(blockKind, customizeContent), [blockKind, customizeContent]);
@@ -11006,13 +11031,13 @@ function findFirstFieldPath(fields, data, prefix) {
11006
11031
  if (Array.isArray(field.visibleRoles) && !field.visibleRoles.includes("author")) continue;
11007
11032
  const nextPrefix = [...prefix, field.id];
11008
11033
  if (field.type === "group") {
11009
- const groupValue = isRecord$1(data) ? data[field.id] : void 0;
11034
+ const groupValue = isRecord(data) ? data[field.id] : void 0;
11010
11035
  const nested = findFirstFieldPath(field.schema.fields, groupValue, nextPrefix);
11011
11036
  if (nested) return nested;
11012
11037
  continue;
11013
11038
  }
11014
11039
  if (field.type === "repeater" && field.schema) {
11015
- const collection = isRecord$1(data) ? data[field.id] : void 0;
11040
+ const collection = isRecord(data) ? data[field.id] : void 0;
11016
11041
  const items = isUnknownArray(collection) ? collection : [];
11017
11042
  if (items.length > 0) {
11018
11043
  const firstItem = items[0];
@@ -11189,7 +11214,7 @@ function dedupeBackgroundImagePool(items) {
11189
11214
  }
11190
11215
  //#endregion
11191
11216
  //#region ../preview-next/src/client/blocks/BoundaryControl.tsx
11192
- function BoundaryControl({ previousBlockId, nextBlockId, previousBlockKind, nextBlockKind }) {
11217
+ function BoundaryControl({ previousBlockId, nextBlockId, previousBlockKind, nextBlockKind, outcome }) {
11193
11218
  const panelId = useId();
11194
11219
  const panelDescriptionId = `${panelId}-description`;
11195
11220
  const [open, setOpen] = useState(false);
@@ -11217,11 +11242,17 @@ function BoundaryControl({ previousBlockId, nextBlockId, previousBlockKind, next
11217
11242
  }, [hasControls]);
11218
11243
  if (!boundary || !hasControls) return null;
11219
11244
  const display = boundaryBreakDisplay(boundary);
11220
- const panelStatus = display.detail ? {
11221
- id: `${panelId}-status`,
11222
- text: display.detail
11223
- } : null;
11224
- const panelDescribedBy = panelStatus ? `${panelDescriptionId} ${panelStatus.id}` : panelDescriptionId;
11245
+ const panelSummaryId = `${panelId}-summary`;
11246
+ const panelStatuses = boundaryPanelStatuses({
11247
+ panelId,
11248
+ detail: display.detail,
11249
+ outcome
11250
+ });
11251
+ const panelDescribedBy = [
11252
+ panelDescriptionId,
11253
+ panelSummaryId,
11254
+ ...panelStatuses.map((status) => status.id)
11255
+ ].join(" ");
11225
11256
  const openPanel = (event) => {
11226
11257
  event.preventDefault();
11227
11258
  event.stopPropagation();
@@ -11325,15 +11356,9 @@ function BoundaryControl({ previousBlockId, nextBlockId, previousBlockKind, next
11325
11356
  })
11326
11357
  })]
11327
11358
  }),
11328
- /* @__PURE__ */ jsxs("div", {
11329
- className: "rounded-lg border border-slate-200 bg-slate-50 p-2 text-center",
11330
- children: [/* @__PURE__ */ jsx("div", {
11331
- className: "truncate text-sm font-medium",
11332
- children: boundaryBreakLabel(boundary)
11333
- }), /* @__PURE__ */ jsx("div", {
11334
- className: "mt-0.5 text-xs text-slate-500",
11335
- children: boundaryBreakModeLabel(boundary)
11336
- })]
11359
+ /* @__PURE__ */ jsx(BoundaryBreakSummary, {
11360
+ id: panelSummaryId,
11361
+ display
11337
11362
  }),
11338
11363
  /* @__PURE__ */ jsxs("div", {
11339
11364
  className: "mt-3",
@@ -11363,11 +11388,7 @@ function BoundaryControl({ previousBlockId, nextBlockId, previousBlockKind, next
11363
11388
  }, variant.boundaryOption.id))
11364
11389
  })]
11365
11390
  }) : null,
11366
- panelStatus ? /* @__PURE__ */ jsx("p", {
11367
- id: panelStatus.id,
11368
- className: "mt-2 text-xs text-slate-500",
11369
- children: panelStatus.text
11370
- }) : null,
11391
+ /* @__PURE__ */ jsx(BoundaryPanelStatusLines, { statuses: panelStatuses }),
11371
11392
  display.canReset ? /* @__PURE__ */ jsxs("button", {
11372
11393
  type: "button",
11373
11394
  className: "mt-2 inline-flex w-full items-center justify-center gap-2 rounded-md border border-slate-200 px-3 py-2 text-sm font-medium text-slate-700 transition hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-sky-400",
@@ -11391,6 +11412,53 @@ function BoundaryControl({ previousBlockId, nextBlockId, previousBlockKind, next
11391
11412
  })
11392
11413
  });
11393
11414
  }
11415
+ /** Approved copy (issue 1422) for a join the renderer did not draw. */
11416
+ const notShownCopy = {
11417
+ "both-unpainted": "This break won't show here, because both sections have an image or video background. It'll appear if you give one of them a color background.",
11418
+ "flush-panel": "This break won't show here, because one of these sections has an image that runs right to its edge. It'll appear if you pick a different look for that section."
11419
+ };
11420
+ /**
11421
+ * Status lines under the controls, each wired into the dialog's
11422
+ * `aria-describedby`. The not-shown line comes from the same composition as
11423
+ * the painted page, so it appears or clears as backgrounds change.
11424
+ */
11425
+ function boundaryPanelStatuses(input) {
11426
+ return [...input.detail ? [{
11427
+ id: `${input.panelId}-status`,
11428
+ kind: "saved-break-unavailable",
11429
+ text: input.detail
11430
+ }] : [], ...input.outcome?.kind === "not-shown" ? [{
11431
+ id: `${input.panelId}-not-shown`,
11432
+ kind: `not-shown:${input.outcome.reason}`,
11433
+ text: notShownCopy[input.outcome.reason]
11434
+ }] : []];
11435
+ }
11436
+ function BoundaryPanelStatusLines({ statuses }) {
11437
+ return statuses.map((status) => /* @__PURE__ */ jsx("p", {
11438
+ id: status.id,
11439
+ "data-boundary-status": status.kind,
11440
+ className: "mt-2 text-xs text-slate-500",
11441
+ children: status.text
11442
+ }, status.id));
11443
+ }
11444
+ /**
11445
+ * The current break and where it comes from. The source is exposed as data so
11446
+ * the state is inspectable without reading the copy.
11447
+ */
11448
+ function BoundaryBreakSummary({ id, display }) {
11449
+ return /* @__PURE__ */ jsxs("div", {
11450
+ id,
11451
+ "data-boundary-break-source": display.source,
11452
+ className: "rounded-lg border border-slate-200 bg-slate-50 p-2 text-center",
11453
+ children: [/* @__PURE__ */ jsx("div", {
11454
+ className: "truncate text-sm font-medium",
11455
+ children: display.label
11456
+ }), /* @__PURE__ */ jsx("div", {
11457
+ className: "mt-0.5 text-xs text-slate-500",
11458
+ children: display.modeLabel
11459
+ })]
11460
+ });
11461
+ }
11394
11462
  function SectionTransitionFamilyButton({ family, active, onClick }) {
11395
11463
  return /* @__PURE__ */ jsx("button", {
11396
11464
  type: "button",
@@ -11414,24 +11482,13 @@ function SectionTransitionVariantButton({ variant, active, onClick }) {
11414
11482
  function sectionTransitionChoiceClassName(active) {
11415
11483
  return ["min-h-8 flex-1 rounded-md px-2.5 text-xs font-medium transition focus:outline-none focus:ring-2 focus:ring-sky-400", active ? "bg-slate-950 text-white shadow-sm" : "bg-transparent text-slate-600 hover:bg-white hover:text-slate-950"].join(" ");
11416
11484
  }
11417
- function boundaryBreakLabel(boundary) {
11418
- return boundaryBreakDisplay(boundary).label;
11419
- }
11420
- function boundaryBreakModeLabel(boundary) {
11421
- return boundaryBreakDisplay(boundary).modeLabel;
11422
- }
11423
11485
  function boundaryBreakDisplay(boundary) {
11424
11486
  const option = boundary.availableBreaks.find((candidate) => candidate.id === boundary.breakChoice.effectiveValue) ?? null;
11425
11487
  switch (boundary.breakChoice.kind) {
11426
- case "auto": return {
11427
- label: option ? `Default: ${option.label}` : "Default",
11428
- modeLabel: "Page Flow",
11429
- detail: null,
11430
- canReset: false,
11431
- resetLabel: "Default"
11432
- };
11488
+ case "auto": return autoBoundaryBreakDisplay(boundary.breakChoice.source, option ? `Default: ${option.label}` : "Default");
11433
11489
  case "user-pinned":
11434
11490
  if (boundary.breakChoice.status === "supported") return {
11491
+ source: "user-pinned",
11435
11492
  label: option?.label ?? "Selected break",
11436
11493
  modeLabel: "Custom",
11437
11494
  detail: null,
@@ -11439,6 +11496,7 @@ function boundaryBreakDisplay(boundary) {
11439
11496
  resetLabel: "Default"
11440
11497
  };
11441
11498
  return {
11499
+ source: "unavailable",
11442
11500
  label: "Saved break unavailable",
11443
11501
  modeLabel: option ? `Using default: ${option.label}` : "Using Page Flow fallback",
11444
11502
  detail: "This page still has a saved custom break that is no longer available for these sections.",
@@ -11448,6 +11506,31 @@ function boundaryBreakDisplay(boundary) {
11448
11506
  default: return assertNever$1(boundary.breakChoice, "Unhandled boundary break choice");
11449
11507
  }
11450
11508
  }
11509
+ /**
11510
+ * A default break has no reset: there is nothing saved to clear. Picking
11511
+ * another break pins it as a user choice, and reset returns here.
11512
+ */
11513
+ function autoBoundaryBreakDisplay(source, label) {
11514
+ switch (source.kind) {
11515
+ case "site-style-default": return {
11516
+ source: "site-style-default",
11517
+ label,
11518
+ modeLabel: "Set by your site style",
11519
+ detail: null,
11520
+ canReset: false,
11521
+ resetLabel: "Default"
11522
+ };
11523
+ case "page-flow-default": return {
11524
+ source: "page-flow-default",
11525
+ label,
11526
+ modeLabel: "Page Flow",
11527
+ detail: null,
11528
+ canReset: false,
11529
+ resetLabel: "Default"
11530
+ };
11531
+ default: return assertNever$1(source, "Unhandled boundary default source");
11532
+ }
11533
+ }
11451
11534
  function formatBlockKindLabel(blockKind) {
11452
11535
  const blockTitle = getBlockDefinition(blockKind)?.manifest.title;
11453
11536
  if (blockTitle) return blockTitle;
@@ -11682,33 +11765,32 @@ function EditablePageRenderer(props) {
11682
11765
  uiStore,
11683
11766
  renderStateVersion
11684
11767
  ]) ?? pageRendererProps.page;
11685
- const runtimeBoundaries = useMemo(() => retargetRuntimeBoundariesForRenderPage(runtimeProjection?.boundaries ?? pageRendererProps.runtimeBoundaries ?? [], renderPage), [
11686
- pageRendererProps.runtimeBoundaries,
11687
- renderPage,
11688
- runtimeProjection
11689
- ]);
11768
+ const runtimeJoins = editorRuntimeJoins(runtimeProjection, pageRendererProps.runtimeJoins);
11690
11769
  const renderedBlockById = useMemo(() => {
11691
11770
  return new Map((renderPage?.blocks ?? []).filter((block) => Boolean(block.id)).map((block) => [block.id, block]));
11692
11771
  }, [renderPage?.blocks]);
11693
- const wrapBoundaryWithControl = useCallback((boundary, rendered) => {
11694
- const previousBlock = renderedBlockById.get(boundary.previousBlockId);
11695
- const nextBlock = renderedBlockById.get(boundary.nextBlockId);
11772
+ const renderJoinWithControl = useCallback((input) => {
11773
+ const previousBlock = renderedBlockById.get(input.previousBlockId);
11774
+ const nextBlock = renderedBlockById.get(input.nextBlockId);
11696
11775
  const control = !isEntryTemplatePage && previousBlock && nextBlock ? /* @__PURE__ */ jsx(BoundaryControl, {
11697
- previousBlockId: asDesignBlockId(boundary.previousBlockId),
11698
- nextBlockId: asDesignBlockId(boundary.nextBlockId),
11776
+ previousBlockId: asDesignBlockId(input.previousBlockId),
11777
+ nextBlockId: asDesignBlockId(input.nextBlockId),
11699
11778
  previousBlockKind: previousBlock.kind,
11700
- nextBlockKind: nextBlock.kind
11779
+ nextBlockKind: nextBlock.kind,
11780
+ outcome: input.join?.outcome ?? null
11701
11781
  }) : null;
11702
- const wrapped = pageRendererProps.wrapBoundary ? pageRendererProps.wrapBoundary(boundary, rendered) : rendered;
11782
+ const extra = pageRendererProps.renderJoin?.(input) ?? null;
11783
+ if (!control && !extra) return null;
11703
11784
  return /* @__PURE__ */ jsxs("div", {
11704
11785
  className: "relative",
11705
11786
  "data-preview-boundary-wrapper": "",
11706
- "data-boundary-id": boundary.boundaryId,
11707
- children: [wrapped, control]
11787
+ "data-boundary-previous-block-id": input.previousBlockId,
11788
+ "data-boundary-next-block-id": input.nextBlockId,
11789
+ children: [extra, control]
11708
11790
  });
11709
11791
  }, [
11710
11792
  isEntryTemplatePage,
11711
- pageRendererProps.wrapBoundary,
11793
+ pageRendererProps.renderJoin,
11712
11794
  renderedBlockById
11713
11795
  ]);
11714
11796
  const wrapBlockWithProvider = useCallback((blockId, rendered) => {
@@ -11779,32 +11861,20 @@ function EditablePageRenderer(props) {
11779
11861
  return /* @__PURE__ */ jsx(EditorPageRenderer, {
11780
11862
  ...pageRendererProps,
11781
11863
  page: renderPage,
11782
- runtimeBoundaries,
11864
+ runtimeJoins,
11783
11865
  registry: allowInlineEditing ? editorRegistry : pageRendererProps.registry ?? clientComponentRegistry,
11784
11866
  wrapBlock: allowInlineEditing ? wrapBlockWithProvider : pageRendererProps.wrapBlock,
11785
- wrapBoundary: allowInlineEditing ? wrapBoundaryWithControl : pageRendererProps.wrapBoundary,
11867
+ renderJoin: allowInlineEditing ? renderJoinWithControl : pageRendererProps.renderJoin,
11786
11868
  dataContext,
11787
11869
  previewAuthoring
11788
11870
  });
11789
11871
  }
11790
- function retargetRuntimeBoundariesForRenderPage(boundaries, page) {
11791
- if (!boundaries?.length) return boundaries;
11792
- const blockById = new Map(page.blocks.filter((block) => Boolean(block.id)).map((block) => [block.id, block]));
11793
- return boundaries.map((boundary) => {
11794
- const currentBlock = blockById.get(boundary.previousBlockId);
11795
- const nextBlock = blockById.get(boundary.nextBlockId);
11796
- return retargetCompiledBoundaryRuntimeForContentAdjacency(boundary, {
11797
- currentContent: renderableBoundaryContent(currentBlock),
11798
- nextContent: renderableBoundaryContent(nextBlock)
11799
- });
11800
- });
11801
- }
11802
- function renderableBoundaryContent(block) {
11803
- const source = block?.draftContent ?? block?.content ?? null;
11804
- return isRecord(source) ? source : null;
11805
- }
11806
- function isRecord(value) {
11807
- return typeof value === "object" && value !== null && !Array.isArray(value);
11872
+ const emptyRuntimeJoins = [];
11873
+ /**
11874
+ * The editor's joins: its live projection wins, then whatever the caller sent.
11875
+ */
11876
+ function editorRuntimeJoins(projection, fallback) {
11877
+ return projection?.joins ?? fallback ?? emptyRuntimeJoins;
11808
11878
  }
11809
11879
  function usePreviewBlockResolvedData(args) {
11810
11880
  const { page, dataContext, apiClient } = args;
@@ -12144,6 +12214,7 @@ function resolveSdkPreviewRuntimeModel(props) {
12144
12214
  const customBlocks = isSdkCustomBlockArray(content.customBlocks) ? content.customBlocks : null;
12145
12215
  const initialBlocks = (page.blocks ?? []).map((block, index) => ({
12146
12216
  id: block.id ?? null,
12217
+ contentVersionId: typeof block.contentVersionId === "string" ? block.contentVersionId : null,
12147
12218
  kind: block.kind,
12148
12219
  purpose: block.purpose ?? null,
12149
12220
  orderIndex: index,