@riverbankcms/sdk 0.128.0 → 0.129.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +33 -0
  2. package/dist/{PreviewEditorSidebar-Dbvb7GIr.mjs → PreviewEditorSidebar-B43CJ0g_.mjs} +3 -3
  3. package/dist/{PreviewEditorUI-e9O9l20X.mjs → PreviewEditorUI-DHirVkeM.mjs} +2 -2
  4. package/dist/{SdkPreviewModeRuntime-BZHt6e9w.mjs → SdkPreviewModeRuntime-BJumZy1B.mjs} +495 -292
  5. package/dist/{SiteChromeCustomizeContext-CvuGbHJX.mjs → SiteChromeCustomizeContext-D9SlpwEj.mjs} +140 -140
  6. package/dist/_dts/blocks/src/PageRenderer.d.ts +20 -10
  7. package/dist/_dts/blocks/src/index.d.ts +2 -1
  8. package/dist/_dts/blocks/src/pageRendererBoundaries.d.ts +30 -0
  9. package/dist/_dts/blocks/src/pageRenderingMode.d.ts +37 -0
  10. package/dist/_dts/blocks/src/server.d.ts +1 -1
  11. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +14 -0
  12. package/dist/_dts/preview-next/src/client/blocks/pageDesignRuntimePreview.d.ts +2 -0
  13. package/dist/_dts/preview-next/src/client/index.d.ts +47 -47
  14. package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +18 -6
  15. package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +30 -21
  16. package/dist/_dts/preview-next/src/client/preview/PreviewThemedSiteDocument.d.ts +18 -5
  17. package/dist/_dts/preview-next/src/client/preview/themeRuntime.d.ts +9 -0
  18. package/dist/_dts/preview-next/src/client/sdk/SdkPreviewMode.d.ts +21 -6
  19. package/dist/_dts/preview-next/src/client/sdk-runtime.d.ts +8 -8
  20. package/dist/_dts/sdk/src/next/catch-all.d.ts +6 -0
  21. package/dist/_dts/sdk/src/next/index.d.ts +2 -1
  22. package/dist/_dts/sdk/src/next/renderSdkContent.d.ts +33 -0
  23. package/dist/_dts/sdk/src/next/types.d.ts +23 -9
  24. package/dist/_dts/sdk/src/preview-next/before-render.d.ts +4 -6
  25. package/dist/_dts/sdk/src/preview-next/client/index.d.ts +3 -3
  26. package/dist/_dts/sdk/src/preview-next/client/runtime.d.ts +1 -1
  27. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +25 -3
  28. package/dist/_dts/sdk/src/rendering/components/Block.shared.d.ts +13 -2
  29. package/dist/_dts/sdk/src/rendering/components/Layout.d.ts +31 -18
  30. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +20 -9
  31. package/dist/_dts/sdk/src/rendering/index.d.ts +4 -2
  32. package/dist/_dts/sdk/src/rendering/renderingMode.d.ts +23 -0
  33. package/dist/_dts/sdk/src/rendering/server.d.ts +5 -3
  34. package/dist/_dts/sdk/src/rendering/themeRuntime.d.ts +6 -0
  35. package/dist/_dts/sdk/src/version.d.ts +1 -1
  36. package/dist/cli/index.mjs +237 -211
  37. package/dist/cli/init-docs/content/workflow-preview-mode.md +24 -11
  38. package/dist/client/client.mjs +420 -337
  39. package/dist/client/rendering.mjs +503 -358
  40. package/dist/preview-next/before-render.mjs +10 -3
  41. package/dist/preview-next/client/runtime.mjs +3 -3
  42. package/dist/{sdk-runtime-Cn_QSCOg.mjs → sdk-runtime-CfZd5pAm.mjs} +1 -1
  43. package/dist/{separator-CEoGABRc.mjs → separator-DkTe68HE.mjs} +1 -1
  44. package/dist/server/components.mjs +478 -351
  45. package/dist/server/index.mjs +1 -1
  46. package/dist/server/next.mjs +640 -500
  47. package/dist/server/prebuild.mjs +1 -1
  48. package/dist/server/rendering/server.mjs +499 -355
  49. package/dist/server/rendering.mjs +499 -355
  50. package/dist/server/server.mjs +1 -1
  51. package/package.json +1 -1
@@ -51671,6 +51671,213 @@ function collectConstrainedVideoMediaValues(options) {
51671
51671
  return values;
51672
51672
  }
51673
51673
  //#endregion
51674
+ //#region ../blocks/src/system/manifest/hydrateLinks.ts
51675
+ /**
51676
+ * Hydrates link objects within block content using the provided route map. Returns
51677
+ * the original content reference when no mutations are required to avoid unnecessary renders.
51678
+ */
51679
+ function hydrateManifestLinks(manifest, content, routes, pagesByIdentifier, entriesByIdentifier) {
51680
+ if (!routes || !manifest?.fields?.length) return content;
51681
+ return hydrateValue(content, {
51682
+ routes,
51683
+ pagesByIdentifier,
51684
+ entriesByIdentifier
51685
+ });
51686
+ }
51687
+ function hydrateValue(value, context) {
51688
+ try {
51689
+ if (Array.isArray(value)) {
51690
+ const resolvedItems = value.map((item) => hydrateValue(item, context));
51691
+ return resolvedItems.every((item, index) => item === value[index]) ? value : resolvedItems;
51692
+ }
51693
+ if (isRecord$27(value)) {
51694
+ if (isInternalLink$1(value)) return hydrateInternalLink(value, context.routes);
51695
+ if (isPageLink$1(value)) return hydratePageLink(value, context);
51696
+ if (isEntryLink$1(value)) return hydrateEntryLink(value, context);
51697
+ const resolvedEntries = Object.entries(value).map(([key, entry]) => [key, hydrateValue(entry, context)]);
51698
+ return resolvedEntries.every(([key, entry]) => entry === value[key]) ? value : Object.fromEntries(resolvedEntries);
51699
+ }
51700
+ return value;
51701
+ } catch (err) {
51702
+ console.error("[hydrateLinks] Error hydrating value:", err, value);
51703
+ return value;
51704
+ }
51705
+ }
51706
+ function hydrateInternalLink(link, routes) {
51707
+ const resolved = resolveRouteTarget(link.routeId, routes);
51708
+ if (!resolved) return link;
51709
+ const nextHref = resolved.href;
51710
+ const currentHref = typeof link.href === "string" && link.href.length > 0 ? link.href : null;
51711
+ const nextUpdatedAt = resolved.updatedAt;
51712
+ const updates = {};
51713
+ if (nextHref && nextHref !== currentHref) updates.href = nextHref;
51714
+ if (nextUpdatedAt && link.updatedAt !== nextUpdatedAt) updates.updatedAt = nextUpdatedAt;
51715
+ return Object.keys(updates).length > 0 ? {
51716
+ ...link,
51717
+ ...updates
51718
+ } : link;
51719
+ }
51720
+ function isInternalLink$1(value) {
51721
+ if (value.kind !== "internal") return false;
51722
+ if (typeof value.routeId !== "string" || value.routeId.length === 0) return false;
51723
+ return true;
51724
+ }
51725
+ function isPageLink$1(value) {
51726
+ if (value.kind !== "page") return false;
51727
+ if (typeof value.identifier !== "string" || value.identifier.length === 0) return false;
51728
+ return true;
51729
+ }
51730
+ function hydratePageLink(link, context) {
51731
+ const resolved = resolvePageRouteTarget(link, context);
51732
+ if (!resolved) return link;
51733
+ return {
51734
+ ...link,
51735
+ href: resolved.href,
51736
+ routeId: resolved.routeId
51737
+ };
51738
+ }
51739
+ function isEntryLink$1(value) {
51740
+ if (value.kind !== "entry") return false;
51741
+ if (typeof value.contentType !== "string" || value.contentType.length === 0) return false;
51742
+ if (typeof value.identifier !== "string" || value.identifier.length === 0) return false;
51743
+ return true;
51744
+ }
51745
+ function hydrateEntryLink(link, context) {
51746
+ const resolved = resolveEntryRouteTarget(link, context);
51747
+ if (!resolved) return link;
51748
+ return {
51749
+ ...link,
51750
+ href: resolved.href,
51751
+ routeId: resolved.routeId
51752
+ };
51753
+ }
51754
+ //#endregion
51755
+ //#region ../blocks/src/sdkBlockTransform.ts
51756
+ /**
51757
+ * Transforms an SDK custom block into a BlockManifest.
51758
+ *
51759
+ * If the block has a `layout`, it can be rendered declaratively without React code.
51760
+ * If no layout, the block MUST use blockOverrides for rendering.
51761
+ */
51762
+ function transformSdkBlockToManifest(sdkBlock) {
51763
+ const hasLayout = Boolean(sdkBlock.layout) || Boolean(sdkBlock.variants && Object.keys(sdkBlock.variants).length > 0);
51764
+ return augmentManifest({
51765
+ name: sdkBlock.id,
51766
+ version: "1.0.0",
51767
+ title: sdkBlock.title,
51768
+ titleSource: sdkBlock.titleSource,
51769
+ description: sdkBlock.description,
51770
+ component: sdkBlock.id,
51771
+ fields: sdkBlock.fields,
51772
+ slots: [],
51773
+ category: sdkBlock.category,
51774
+ tags: sdkBlock.tags,
51775
+ icon: sdkBlock.icon,
51776
+ layout: sdkBlock.layout,
51777
+ variants: sdkBlock.variants,
51778
+ defaultVariant: sdkBlock.defaultVariant,
51779
+ variantOptions: sdkBlock.variantOptions,
51780
+ previewCustomize: sdkBlock.previewCustomize,
51781
+ behaviours: {
51782
+ supportsThemeSwitching: true,
51783
+ inlineEditing: hasLayout,
51784
+ animation: hasLayout,
51785
+ paletteHidden: false
51786
+ }
51787
+ });
51788
+ }
51789
+ /**
51790
+ * Transforms an SDK custom block into a SystemBlockDefinition.
51791
+ *
51792
+ * This creates a minimal definition with just the manifest - no data loaders
51793
+ * or content normalizers since SDK blocks handle their own rendering.
51794
+ */
51795
+ function transformSdkBlockToDefinition(sdkBlock) {
51796
+ return {
51797
+ manifest: transformSdkBlockToManifest(sdkBlock),
51798
+ dataLoaders: sdkBlock.dataLoaders
51799
+ };
51800
+ }
51801
+ //#endregion
51802
+ //#region ../blocks/src/customBlockRegistry.ts
51803
+ const defaultCustomBlockSourcePolicy = { kind: "canonical-db-fallback-sdk" };
51804
+ function isCustomBlockKind(blockKind) {
51805
+ return blockKind.startsWith("custom.");
51806
+ }
51807
+ function transformToBlockDescriptor(sdkBlock, source = "sdk") {
51808
+ return {
51809
+ name: sdkBlock.id,
51810
+ title: sdkBlock.title,
51811
+ description: sdkBlock.description,
51812
+ category: sdkBlock.category,
51813
+ tags: sdkBlock.tags,
51814
+ icon: sdkBlock.icon,
51815
+ definition: transformSdkBlockToDefinition(sdkBlock),
51816
+ source
51817
+ };
51818
+ }
51819
+ function toResolvedCustomBlock(manifest, source) {
51820
+ return {
51821
+ blockKind: manifest.id,
51822
+ manifest: transformSdkBlockToManifest(manifest),
51823
+ source,
51824
+ descriptor: transformToBlockDescriptor(manifest, source.kind === "managed-database" ? "database" : "sdk")
51825
+ };
51826
+ }
51827
+ function planCustomBlockRegistryResolution({ sdkConfig, customBlocks = [], policy = defaultCustomBlockSourcePolicy }) {
51828
+ switch (policy.kind) {
51829
+ case "canonical-db-fallback-sdk": {
51830
+ const entriesByKind = /* @__PURE__ */ new Map();
51831
+ const conflicts = [];
51832
+ for (const customBlock of customBlocks) entriesByKind.set(customBlock.manifest.id, toResolvedCustomBlock(customBlock.manifest, customBlock.source));
51833
+ for (const sdkBlock of sdkConfig?.customBlocks ?? []) {
51834
+ const existing = entriesByKind.get(sdkBlock.id);
51835
+ if (existing) {
51836
+ conflicts.push({
51837
+ kind: "conflict",
51838
+ blockKind: existing.blockKind,
51839
+ winner: existing.source,
51840
+ loser: { kind: "sdk-config" },
51841
+ reason: "db-canonical-sdk-fallback"
51842
+ });
51843
+ continue;
51844
+ }
51845
+ entriesByKind.set(sdkBlock.id, toResolvedCustomBlock(sdkBlock, { kind: "sdk-config" }));
51846
+ }
51847
+ return {
51848
+ policy,
51849
+ entries: Array.from(entriesByKind.values()),
51850
+ conflicts
51851
+ };
51852
+ }
51853
+ }
51854
+ }
51855
+ function createCustomBlockRegistry({ sdkConfig, customBlocks = [], policy = defaultCustomBlockSourcePolicy, onConflict }) {
51856
+ const plan = planCustomBlockRegistryResolution({
51857
+ sdkConfig,
51858
+ customBlocks,
51859
+ policy
51860
+ });
51861
+ const entriesByKind = new Map(plan.entries.map((entry) => [entry.blockKind, entry]));
51862
+ for (const conflict of plan.conflicts) onConflict?.(`Using ${sourceLabel(conflict.winner)} custom block "${conflict.blockKind}" - ${sourceLabel(conflict.loser)} block is fallback only`);
51863
+ return {
51864
+ entries: plan.entries,
51865
+ conflicts: plan.conflicts,
51866
+ findManifest: (blockKind) => {
51867
+ if (!isCustomBlockKind(blockKind)) return void 0;
51868
+ return entriesByKind.get(blockKind);
51869
+ }
51870
+ };
51871
+ }
51872
+ function sourceLabel(source) {
51873
+ switch (source.kind) {
51874
+ case "managed-database": return "DB";
51875
+ case "sdk-synced": return "SDK-synced DB";
51876
+ case "sdk-config": return "SDK config";
51877
+ default: return assertNever$24(source);
51878
+ }
51879
+ }
51880
+ //#endregion
51674
51881
  //#region ../theme-core/src/runtime/fontFamily.ts
51675
51882
  /**
51676
51883
  * Font Family Formatting Utilities
@@ -55408,215 +55615,115 @@ function mapFontStyle(italic) {
55408
55615
  return italic ? "italic" : "normal";
55409
55616
  }
55410
55617
  //#endregion
55411
- //#region ../blocks/src/system/manifest/hydrateLinks.ts
55412
- /**
55413
- * Hydrates link objects within block content using the provided route map. Returns
55414
- * the original content reference when no mutations are required to avoid unnecessary renders.
55415
- */
55416
- function hydrateManifestLinks(manifest, content, routes, pagesByIdentifier, entriesByIdentifier) {
55417
- if (!routes || !manifest?.fields?.length) return content;
55418
- return hydrateValue(content, {
55419
- routes,
55420
- pagesByIdentifier,
55421
- entriesByIdentifier
55422
- });
55423
- }
55424
- function hydrateValue(value, context) {
55425
- try {
55426
- if (Array.isArray(value)) {
55427
- const resolvedItems = value.map((item) => hydrateValue(item, context));
55428
- return resolvedItems.every((item, index) => item === value[index]) ? value : resolvedItems;
55429
- }
55430
- if (isRecord$27(value)) {
55431
- if (isInternalLink$1(value)) return hydrateInternalLink(value, context.routes);
55432
- if (isPageLink$1(value)) return hydratePageLink(value, context);
55433
- if (isEntryLink$1(value)) return hydrateEntryLink(value, context);
55434
- const resolvedEntries = Object.entries(value).map(([key, entry]) => [key, hydrateValue(entry, context)]);
55435
- return resolvedEntries.every(([key, entry]) => entry === value[key]) ? value : Object.fromEntries(resolvedEntries);
55436
- }
55437
- return value;
55438
- } catch (err) {
55439
- console.error("[hydrateLinks] Error hydrating value:", err, value);
55440
- return value;
55618
+ //#region ../blocks/src/pageRenderingMode.ts
55619
+ var MissingBlockOverrideError$1 = class extends Error {
55620
+ constructor(blockKind) {
55621
+ super(`Override-only rendering requires an override for block kind "${blockKind}".`);
55622
+ this.blockKind = blockKind;
55623
+ this.code = "missing_block_override";
55624
+ this.name = "MissingBlockOverrideError";
55441
55625
  }
55626
+ };
55627
+ function isOverrideOnlyResourceInput(props) {
55628
+ return props.rendering?.kind === "overrides-only";
55442
55629
  }
55443
- function hydrateInternalLink(link, routes) {
55444
- const resolved = resolveRouteTarget(link.routeId, routes);
55445
- if (!resolved) return link;
55446
- const nextHref = resolved.href;
55447
- const currentHref = typeof link.href === "string" && link.href.length > 0 ? link.href : null;
55448
- const nextUpdatedAt = resolved.updatedAt;
55449
- const updates = {};
55450
- if (nextHref && nextHref !== currentHref) updates.href = nextHref;
55451
- if (nextUpdatedAt && link.updatedAt !== nextUpdatedAt) updates.updatedAt = nextUpdatedAt;
55452
- return Object.keys(updates).length > 0 ? {
55453
- ...link,
55454
- ...updates
55455
- } : link;
55456
- }
55457
- function isInternalLink$1(value) {
55458
- if (value.kind !== "internal") return false;
55459
- if (typeof value.routeId !== "string" || value.routeId.length === 0) return false;
55460
- return true;
55461
- }
55462
- function isPageLink$1(value) {
55463
- if (value.kind !== "page") return false;
55464
- if (typeof value.identifier !== "string" || value.identifier.length === 0) return false;
55465
- return true;
55466
- }
55467
- function hydratePageLink(link, context) {
55468
- const resolved = resolvePageRouteTarget(link, context);
55469
- if (!resolved) return link;
55630
+ function resolvePageThemeResources(props) {
55631
+ if (isOverrideOnlyResourceInput(props)) return { kind: "unavailable" };
55470
55632
  return {
55471
- ...link,
55472
- href: resolved.href,
55473
- routeId: resolved.routeId
55633
+ kind: "available",
55634
+ tokens: props.themeTokens ?? buildThemeRuntime$1(props.theme).tokens,
55635
+ config: props.theme
55474
55636
  };
55475
55637
  }
55476
- function isEntryLink$1(value) {
55477
- if (value.kind !== "entry") return false;
55478
- if (typeof value.contentType !== "string" || value.contentType.length === 0) return false;
55479
- if (typeof value.identifier !== "string" || value.identifier.length === 0) return false;
55480
- return true;
55481
- }
55482
- function hydrateEntryLink(link, context) {
55483
- const resolved = resolveEntryRouteTarget(link, context);
55484
- if (!resolved) return link;
55485
- return {
55486
- ...link,
55487
- href: resolved.href,
55488
- routeId: resolved.routeId
55489
- };
55638
+ function requireBlockOverride(resources, override, blockKind) {
55639
+ if (resources.kind === "unavailable" && !override) throw new MissingBlockOverrideError$1(blockKind);
55490
55640
  }
55491
- //#endregion
55492
- //#region ../blocks/src/sdkBlockTransform.ts
55493
- /**
55494
- * Transforms an SDK custom block into a BlockManifest.
55495
- *
55496
- * If the block has a `layout`, it can be rendered declaratively without React code.
55497
- * If no layout, the block MUST use blockOverrides for rendering.
55498
- */
55499
- function transformSdkBlockToManifest(sdkBlock) {
55500
- const hasLayout = Boolean(sdkBlock.layout) || Boolean(sdkBlock.variants && Object.keys(sdkBlock.variants).length > 0);
55501
- return augmentManifest({
55502
- name: sdkBlock.id,
55503
- version: "1.0.0",
55504
- title: sdkBlock.title,
55505
- titleSource: sdkBlock.titleSource,
55506
- description: sdkBlock.description,
55507
- component: sdkBlock.id,
55508
- fields: sdkBlock.fields,
55509
- slots: [],
55510
- category: sdkBlock.category,
55511
- tags: sdkBlock.tags,
55512
- icon: sdkBlock.icon,
55513
- layout: sdkBlock.layout,
55514
- variants: sdkBlock.variants,
55515
- defaultVariant: sdkBlock.defaultVariant,
55516
- variantOptions: sdkBlock.variantOptions,
55517
- previewCustomize: sdkBlock.previewCustomize,
55518
- behaviours: {
55519
- supportsThemeSwitching: true,
55520
- inlineEditing: hasLayout,
55521
- animation: hasLayout,
55522
- paletteHidden: false
55523
- }
55524
- });
55641
+ function overrideThemeProps(resources) {
55642
+ return resources.kind === "available" ? {
55643
+ theme: resources.tokens,
55644
+ themeConfig: resources.config
55645
+ } : {};
55525
55646
  }
55526
- /**
55527
- * Transforms an SDK custom block into a SystemBlockDefinition.
55528
- *
55529
- * This creates a minimal definition with just the manifest - no data loaders
55530
- * or content normalizers since SDK blocks handle their own rendering.
55531
- */
55532
- function transformSdkBlockToDefinition(sdkBlock) {
55533
- return {
55534
- manifest: transformSdkBlockToManifest(sdkBlock),
55535
- dataLoaders: sdkBlock.dataLoaders
55536
- };
55647
+ function requireThemeResources(resources, blockKind) {
55648
+ if (resources.kind === "unavailable") throw new MissingBlockOverrideError$1(blockKind);
55649
+ return resources;
55537
55650
  }
55538
55651
  //#endregion
55539
- //#region ../blocks/src/customBlockRegistry.ts
55540
- const defaultCustomBlockSourcePolicy = { kind: "canonical-db-fallback-sdk" };
55541
- function isCustomBlockKind(blockKind) {
55542
- return blockKind.startsWith("custom.");
55652
+ //#region ../blocks/src/pageRendererBoundaries.tsx
55653
+ const boundaryKey = (previousBlockId, nextBlockId) => `${previousBlockId}\u0000${nextBlockId}`;
55654
+ function isSiteStyleTransitionStyleGroup(value) {
55655
+ return value?.startsWith("site-style-transition-") === true;
55543
55656
  }
55544
- function transformToBlockDescriptor(sdkBlock, source = "sdk") {
55657
+ function boundaryMapForAdjacentBlockIds(boundaries) {
55658
+ return new Map(boundaries.map((boundary) => [boundaryKey(boundary.previousBlockId, boundary.nextBlockId), boundary]));
55659
+ }
55660
+ function boundaryBetweenBlocks(previousBlock, nextBlock, boundaries) {
55661
+ const previousBlockId = previousBlock?.id ?? null;
55662
+ const nextBlockId = nextBlock?.id ?? null;
55663
+ if (!previousBlockId || !nextBlockId) return null;
55664
+ return boundaries.get(boundaryKey(previousBlockId, nextBlockId)) ?? null;
55665
+ }
55666
+ function renderBoundaryAfterBlock(input) {
55667
+ const previousBlockId = input.block.id;
55668
+ const nextBlockId = input.nextBlock?.id ?? null;
55669
+ if (!previousBlockId || !nextBlockId) return null;
55670
+ const boundary = input.boundaryByAdjacentBlockIds.get(boundaryKey(previousBlockId, nextBlockId));
55671
+ if (!boundary) return null;
55672
+ const rendered = /* @__PURE__ */ jsx("div", {
55673
+ "aria-hidden": "true",
55674
+ "data-block-boundary": "",
55675
+ "data-boundary-id": boundary.boundaryId,
55676
+ "data-boundary-previous-block-id": boundary.previousBlockId,
55677
+ "data-boundary-next-block-id": boundary.nextBlockId,
55678
+ "data-style-group": boundary.styleGroup,
55679
+ style: boundaryCssVarsStyle(boundary)
55680
+ }, `${input.blockKey}:boundary`);
55681
+ return input.wrapBoundary ? input.wrapBoundary(boundary, rendered) : rendered;
55682
+ }
55683
+ function boundaryCssVarsStyle(boundary) {
55545
55684
  return {
55546
- name: sdkBlock.id,
55547
- title: sdkBlock.title,
55548
- description: sdkBlock.description,
55549
- category: sdkBlock.category,
55550
- tags: sdkBlock.tags,
55551
- icon: sdkBlock.icon,
55552
- definition: transformSdkBlockToDefinition(sdkBlock),
55553
- source
55685
+ "--site-style-transition-from": boundary.cssVars.from,
55686
+ "--site-style-transition-to": boundary.cssVars.to
55554
55687
  };
55555
55688
  }
55556
- function toResolvedCustomBlock(manifest, source) {
55689
+ function boundaryReserveCssVarsStyle(input) {
55690
+ const before = input.before?.metrics.reserveCss ?? null;
55691
+ const after = input.after?.metrics.reserveCss ?? null;
55692
+ if (!before && !after) return void 0;
55557
55693
  return {
55558
- blockKind: manifest.id,
55559
- manifest: transformSdkBlockToManifest(manifest),
55560
- source,
55561
- descriptor: transformToBlockDescriptor(manifest, source.kind === "managed-database" ? "database" : "sdk")
55694
+ ...before ? { "--site-style-boundary-before-reserve": before } : {},
55695
+ ...after ? { "--site-style-boundary-after-reserve": after } : {}
55562
55696
  };
55563
55697
  }
55564
- function planCustomBlockRegistryResolution({ sdkConfig, customBlocks = [], policy = defaultCustomBlockSourcePolicy }) {
55565
- switch (policy.kind) {
55566
- case "canonical-db-fallback-sdk": {
55567
- const entriesByKind = /* @__PURE__ */ new Map();
55568
- const conflicts = [];
55569
- for (const customBlock of customBlocks) entriesByKind.set(customBlock.manifest.id, toResolvedCustomBlock(customBlock.manifest, customBlock.source));
55570
- for (const sdkBlock of sdkConfig?.customBlocks ?? []) {
55571
- const existing = entriesByKind.get(sdkBlock.id);
55572
- if (existing) {
55573
- conflicts.push({
55574
- kind: "conflict",
55575
- blockKind: existing.blockKind,
55576
- winner: existing.source,
55577
- loser: { kind: "sdk-config" },
55578
- reason: "db-canonical-sdk-fallback"
55579
- });
55580
- continue;
55581
- }
55582
- entriesByKind.set(sdkBlock.id, toResolvedCustomBlock(sdkBlock, { kind: "sdk-config" }));
55583
- }
55584
- return {
55585
- policy,
55586
- entries: Array.from(entriesByKind.values()),
55587
- conflicts
55588
- };
55589
- }
55590
- }
55698
+ function transitionCssVarsStyle(content) {
55699
+ const transitionStyles = isObjectRecord$1(content._transitionStyles) ? content._transitionStyles : null;
55700
+ const cssVars = isObjectRecord$1(transitionStyles?.cssVars) ? transitionStyles.cssVars : null;
55701
+ const from = typeof cssVars?.from === "string" ? cssVars.from : null;
55702
+ const to = typeof cssVars?.to === "string" ? cssVars.to : null;
55703
+ if (!from && !to) return void 0;
55704
+ return {
55705
+ ...from ? { "--site-style-transition-from": from } : {},
55706
+ ...to ? { "--site-style-transition-to": to } : {}
55707
+ };
55591
55708
  }
55592
- function createCustomBlockRegistry({ sdkConfig, customBlocks = [], policy = defaultCustomBlockSourcePolicy, onConflict }) {
55593
- const plan = planCustomBlockRegistryResolution({
55594
- sdkConfig,
55595
- customBlocks,
55596
- policy
55597
- });
55598
- const entriesByKind = new Map(plan.entries.map((entry) => [entry.blockKind, entry]));
55599
- for (const conflict of plan.conflicts) onConflict?.(`Using ${sourceLabel(conflict.winner)} custom block "${conflict.blockKind}" - ${sourceLabel(conflict.loser)} block is fallback only`);
55709
+ function mergeStyleObjects(left, right) {
55710
+ if (!left) return right;
55711
+ if (!right) return left;
55600
55712
  return {
55601
- entries: plan.entries,
55602
- conflicts: plan.conflicts,
55603
- findManifest: (blockKind) => {
55604
- if (!isCustomBlockKind(blockKind)) return void 0;
55605
- return entriesByKind.get(blockKind);
55606
- }
55713
+ ...left,
55714
+ ...right
55607
55715
  };
55608
55716
  }
55609
- function sourceLabel(source) {
55610
- switch (source.kind) {
55611
- case "managed-database": return "DB";
55612
- case "sdk-synced": return "SDK-synced DB";
55613
- case "sdk-config": return "SDK config";
55614
- default: return assertNever$24(source);
55615
- }
55717
+ function pageBlockPosition(index, blockCount) {
55718
+ if (blockCount <= 1) return "only";
55719
+ if (index === 0) return "first";
55720
+ if (index === blockCount - 1) return "last";
55721
+ return "middle";
55616
55722
  }
55617
55723
  //#endregion
55618
55724
  //#region ../blocks/src/PageRenderer.tsx
55619
- function PageRenderer$1({ theme, page, runtimeBoundaries, usePlaceholders = false, dataContext, wrapBlock, wrapBoundary, registry, themeTokens: providedThemeTokens, routeMap, blockOverrides, sdkConfig, customBlocks, previewAuthoring }) {
55725
+ function PageRenderer$1(props) {
55726
+ const { page, runtimeBoundaries, usePlaceholders = false, dataContext, wrapBlock, wrapBoundary, registry, routeMap, blockOverrides, sdkConfig, customBlocks, previewAuthoring } = props;
55620
55727
  const imageResolveContext = React$1.useMemo(() => resolvePageRendererImageResolveContext(dataContext), [
55621
55728
  dataContext?.imageResolveContext,
55622
55729
  dataContext?.mediaAssets,
@@ -55625,12 +55732,16 @@ function PageRenderer$1({ theme, page, runtimeBoundaries, usePlaceholders = fals
55625
55732
  ]);
55626
55733
  const boundaryByAdjacentBlockIds = React$1.useMemo(() => boundaryMapForAdjacentBlockIds(runtimeBoundaries ?? []), [runtimeBoundaries]);
55627
55734
  const usesRuntimeBoundaries = runtimeBoundaries !== void 0;
55735
+ const themeResources = React$1.useMemo(() => resolvePageThemeResources(props), [
55736
+ props.rendering,
55737
+ props.theme,
55738
+ props.themeTokens
55739
+ ]);
55628
55740
  if (!page || page.blocks.length === 0) return /* @__PURE__ */ jsx("div", {
55629
55741
  className: "rb-p-6 rb-caption",
55630
55742
  style: textColorStyle("mutedText"),
55631
55743
  children: "No blocks found."
55632
55744
  });
55633
- const themeTokens = providedThemeTokens ?? buildThemeRuntime$1(theme).tokens;
55634
55745
  const resolvedRegistry = registry ?? getDefaultComponentRegistry();
55635
55746
  setContextResolveImageUrlContext(imageResolveContext);
55636
55747
  return /* @__PURE__ */ jsx("div", { children: page.blocks.map((block, index) => {
@@ -55653,22 +55764,14 @@ function PageRenderer$1({ theme, page, runtimeBoundaries, usePlaceholders = fals
55653
55764
  const renderableContent = getRenderableContent(block, dataContext?.previewStage);
55654
55765
  const variantKey = definition?.manifest ? resolveVariantKey(definition.manifest, renderableContent) : null;
55655
55766
  const shouldUseWrapper = !managesOwnWrapper || Boolean(wrapBlock);
55656
- const blockSectionProps = {
55657
- themeTokens,
55658
- themeConfig: theme,
55767
+ const blockSectionProps = buildBlockSectionProps({
55768
+ props,
55769
+ themeResources,
55659
55770
  block,
55660
- usePlaceholders,
55661
- dataContext,
55662
55771
  blockKey,
55663
- registry: resolvedRegistry,
55664
- routeMap,
55665
- wrapBlock,
55666
- blockOverrides,
55667
- sdkConfig,
55668
- customBlocks,
55669
55772
  imageResolveContext,
55670
- previewAuthoring
55671
- };
55773
+ registry: resolvedRegistry
55774
+ });
55672
55775
  if (!shouldUseWrapper) {
55673
55776
  const rendered = /* @__PURE__ */ jsx(MemoBlockSection, { ...blockSectionProps }, `${blockKey}:block`);
55674
55777
  return boundaryElement ? /* @__PURE__ */ jsxs(React$1.Fragment, { children: [rendered, boundaryElement] }, blockKey) : rendered;
@@ -55710,81 +55813,6 @@ function PageRenderer$1({ theme, page, runtimeBoundaries, usePlaceholders = fals
55710
55813
  })] }, blockKey);
55711
55814
  }) });
55712
55815
  }
55713
- function isSiteStyleTransitionStyleGroup(value) {
55714
- return value?.startsWith("site-style-transition-") === true;
55715
- }
55716
- function boundaryMapForAdjacentBlockIds(boundaries) {
55717
- return new Map(boundaries.map((boundary) => [boundaryKey(boundary.previousBlockId, boundary.nextBlockId), boundary]));
55718
- }
55719
- function boundaryKey(previousBlockId, nextBlockId) {
55720
- return `${previousBlockId}\u0000${nextBlockId}`;
55721
- }
55722
- function boundaryBetweenBlocks(previousBlock, nextBlock, boundaryByAdjacentBlockIds) {
55723
- const previousBlockId = previousBlock?.id ?? null;
55724
- const nextBlockId = nextBlock?.id ?? null;
55725
- if (!previousBlockId || !nextBlockId) return null;
55726
- return boundaryByAdjacentBlockIds.get(boundaryKey(previousBlockId, nextBlockId)) ?? null;
55727
- }
55728
- function renderBoundaryAfterBlock(input) {
55729
- const previousBlockId = input.block.id;
55730
- const nextBlockId = input.nextBlock?.id ?? null;
55731
- if (!previousBlockId || !nextBlockId) return null;
55732
- const boundary = input.boundaryByAdjacentBlockIds.get(boundaryKey(previousBlockId, nextBlockId));
55733
- if (!boundary) return null;
55734
- const rendered = /* @__PURE__ */ jsx("div", {
55735
- "aria-hidden": "true",
55736
- "data-block-boundary": "",
55737
- "data-boundary-id": boundary.boundaryId,
55738
- "data-boundary-previous-block-id": boundary.previousBlockId,
55739
- "data-boundary-next-block-id": boundary.nextBlockId,
55740
- "data-style-group": boundary.styleGroup,
55741
- style: boundaryCssVarsStyle(boundary)
55742
- }, `${input.blockKey}:boundary`);
55743
- return input.wrapBoundary ? input.wrapBoundary(boundary, rendered) : rendered;
55744
- }
55745
- function boundaryCssVarsStyle(boundary) {
55746
- return {
55747
- "--site-style-transition-from": boundary.cssVars.from,
55748
- "--site-style-transition-to": boundary.cssVars.to
55749
- };
55750
- }
55751
- function boundaryReserveCssVarsStyle(input) {
55752
- const before = input.before ? boundaryReserveValueForTreatment(input.before) : null;
55753
- const after = input.after ? boundaryReserveValueForTreatment(input.after) : null;
55754
- if (!before && !after) return void 0;
55755
- return {
55756
- ...before ? { "--site-style-boundary-before-reserve": before } : {},
55757
- ...after ? { "--site-style-boundary-after-reserve": after } : {}
55758
- };
55759
- }
55760
- function boundaryReserveValueForTreatment(boundary) {
55761
- return boundary.metrics.reserveCss;
55762
- }
55763
- function transitionCssVarsStyle(content) {
55764
- const transitionStyles = isObjectRecord$1(content._transitionStyles) ? content._transitionStyles : null;
55765
- const cssVars = isObjectRecord$1(transitionStyles?.cssVars) ? transitionStyles.cssVars : null;
55766
- const from = typeof cssVars?.from === "string" ? cssVars.from : null;
55767
- const to = typeof cssVars?.to === "string" ? cssVars.to : null;
55768
- if (!from && !to) return void 0;
55769
- return {
55770
- ...from ? { "--site-style-transition-from": from } : {},
55771
- ...to ? { "--site-style-transition-to": to } : {}
55772
- };
55773
- }
55774
- function mergeStyleObjects(left, right) {
55775
- if (!left) return right;
55776
- if (!right) return left;
55777
- return {
55778
- ...left,
55779
- ...right
55780
- };
55781
- }
55782
- function pageBlockPosition(index, blockCount) {
55783
- if (blockCount <= 1) return "only";
55784
- if (index === 0) return "first";
55785
- if (index === blockCount - 1) return "last";
55786
- return "middle";
55787
- }
55788
55816
  function resolvePageRendererImageResolveContext(dataContext) {
55789
55817
  const input = dataContext?.imageResolveContext;
55790
55818
  return buildResolveImageUrlContext({
@@ -55794,6 +55822,23 @@ function resolvePageRendererImageResolveContext(dataContext) {
55794
55822
  mediaAssets: input?.mediaAssets ?? dataContext?.mediaAssets
55795
55823
  });
55796
55824
  }
55825
+ function buildBlockSectionProps(input) {
55826
+ return {
55827
+ themeResources: input.themeResources,
55828
+ block: input.block,
55829
+ usePlaceholders: input.props.usePlaceholders ?? false,
55830
+ dataContext: input.props.dataContext,
55831
+ blockKey: input.blockKey,
55832
+ registry: input.registry,
55833
+ routeMap: input.props.routeMap,
55834
+ wrapBlock: input.props.wrapBlock,
55835
+ blockOverrides: input.props.blockOverrides,
55836
+ sdkConfig: input.props.sdkConfig,
55837
+ customBlocks: input.props.customBlocks,
55838
+ imageResolveContext: input.imageResolveContext,
55839
+ previewAuthoring: input.props.previewAuthoring
55840
+ };
55841
+ }
55797
55842
  /**
55798
55843
  * Look up a block override component by block kind.
55799
55844
  * Supports both full ("block.hero") and short ("hero") keys.
@@ -55860,7 +55905,7 @@ function getCachedValidator(manifest, flavour) {
55860
55905
  * referential equality of all props that affect rendering. Standard React.memo
55861
55906
  * wouldn't catch all the render triggers from the editor store.
55862
55907
  */
55863
- const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, themeConfig, block, usePlaceholders, dataContext, registry, routeMap, wrapBlock, blockOverrides, sdkConfig, customBlocks, imageResolveContext, previewAuthoring }) {
55908
+ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeResources, block, usePlaceholders, dataContext, registry, routeMap, wrapBlock, blockOverrides, sdkConfig, customBlocks, imageResolveContext, previewAuthoring }) {
55864
55909
  const perfStart = globalThis.process?.env?.DEBUG_PERF === "1" && typeof window === "undefined" ? Date.now() : 0;
55865
55910
  const fallbackImageResolveContext = getCurrentResolveImageUrlContext();
55866
55911
  const resolvedImageResolveContext = imageResolveContext ?? fallbackImageResolveContext;
@@ -55881,6 +55926,7 @@ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, t
55881
55926
  return node;
55882
55927
  }
55883
55928
  const OverrideComponent = getBlockOverride(block.kind, blockOverrides);
55929
+ requireBlockOverride(themeResources, OverrideComponent, block.kind);
55884
55930
  let definition = getBlockDefinition(block.kind);
55885
55931
  if (!definition && block.kind.startsWith("custom.")) definition = createCustomBlockRegistry({
55886
55932
  sdkConfig,
@@ -55893,8 +55939,7 @@ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, t
55893
55939
  if (OverrideComponent) {
55894
55940
  const rendered = /* @__PURE__ */ jsx(OverrideComponent, {
55895
55941
  content: getRenderableContent(block, dataContext?.previewStage),
55896
- theme: themeTokens,
55897
- themeConfig,
55942
+ ...overrideThemeProps(themeResources),
55898
55943
  data: void 0,
55899
55944
  siteId: dataContext?.siteId,
55900
55945
  apiBaseUrl: dataContext?.apiBaseUrl,
@@ -55993,8 +56038,7 @@ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, t
55993
56038
  const hasResolvedData = !!resolved && typeof resolved === "object" && Object.keys(resolved).length > 0;
55994
56039
  const baseProps = {
55995
56040
  content: hydratedContent,
55996
- theme: themeTokens,
55997
- themeConfig,
56041
+ ...overrideThemeProps(themeResources),
55998
56042
  data: resolved,
55999
56043
  siteId: dataContext?.siteId,
56000
56044
  apiBaseUrl: dataContext?.apiBaseUrl,
@@ -56014,6 +56058,7 @@ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, t
56014
56058
  let rendered;
56015
56059
  if (OverrideComponent) rendered = /* @__PURE__ */ jsx(OverrideComponent, { ...baseProps });
56016
56060
  else {
56061
+ requireThemeResources(themeResources, block.kind);
56017
56062
  const BlockComponent = getCachedBlockComponent(definition.manifest);
56018
56063
  const pathBase = typeof block.id === "string" && block.id.length > 0 ? `blocks.${block.id}.` : void 0;
56019
56064
  const rootContext = { $root: {
@@ -56063,7 +56108,7 @@ const MemoBlockSection = React$1.memo(function MemoBlockSection({ themeTokens, t
56063
56108
  });
56064
56109
  }
56065
56110
  }, (prev, next) => {
56066
- return prev.block === next.block && prev.registry === next.registry && prev.dataContext === next.dataContext && prev.themeTokens === next.themeTokens && prev.themeConfig === next.themeConfig && prev.routeMap === next.routeMap && prev.usePlaceholders === next.usePlaceholders && prev.wrapBlock === next.wrapBlock && prev.blockOverrides === next.blockOverrides && prev.sdkConfig === next.sdkConfig && prev.customBlocks === next.customBlocks && prev.imageResolveContext === next.imageResolveContext && prev.previewAuthoring === next.previewAuthoring;
56111
+ return prev.block === next.block && prev.registry === next.registry && prev.dataContext === next.dataContext && prev.themeResources === next.themeResources && prev.routeMap === next.routeMap && prev.usePlaceholders === next.usePlaceholders && prev.wrapBlock === next.wrapBlock && prev.blockOverrides === next.blockOverrides && prev.sdkConfig === next.sdkConfig && prev.customBlocks === next.customBlocks && prev.imageResolveContext === next.imageResolveContext && prev.previewAuthoring === next.previewAuthoring;
56067
56112
  });
56068
56113
  function fallback(message) {
56069
56114
  return /* @__PURE__ */ jsx("div", {
@@ -69278,8 +69323,9 @@ function toBlocksImageResolveContextInput(context) {
69278
69323
  mediaAssets: toBlocksMediaAssets(context.mediaAssets)
69279
69324
  };
69280
69325
  }
69281
- //#endregion
69282
- //#region src/rendering/blocks-page-renderer.ts
69326
+ function isOverrideOnlyPageRenderer(props) {
69327
+ return props.rendering?.kind === "overrides-only";
69328
+ }
69283
69329
  function normalizeSdkCustomBlocks(customBlocks) {
69284
69330
  if (!customBlocks) return void 0;
69285
69331
  return customBlocks.map((block) => {
@@ -69310,15 +69356,23 @@ function toBlocksPageRendererDataContext(dataContext) {
69310
69356
  }
69311
69357
  function PageRenderer(props) {
69312
69358
  const blocksSdkConfig = props.sdkConfig ? { customBlocks: normalizeSdkCustomBlocks(props.sdkConfig.customBlocks) } : props.sdkConfig;
69313
- const blocksTheme = parseBlocksTheme(props.theme);
69314
- const blocksProps = {
69315
- ...props,
69316
- theme: blocksTheme,
69359
+ const { rendering: _rendering, theme: _theme, themeTokens: _themeTokens, ...commonProps } = props;
69360
+ const commonBlocksProps = {
69361
+ ...commonProps,
69317
69362
  dataContext: props.dataContext ? toBlocksPageRendererDataContext(props.dataContext) : void 0,
69318
69363
  blockOverrides: toBlocksBlockOverrides(props.blockOverrides),
69319
69364
  sdkConfig: blocksSdkConfig,
69320
69365
  customBlocks: normalizeSdkCustomBlocks(props.customBlocks)
69321
69366
  };
69367
+ const blocksProps = isOverrideOnlyPageRenderer(props) ? {
69368
+ ...commonBlocksProps,
69369
+ rendering: { kind: "overrides-only" },
69370
+ blockOverrides: toBlocksBlockOverrides(props.blockOverrides) ?? {}
69371
+ } : {
69372
+ ...commonBlocksProps,
69373
+ theme: parseBlocksTheme(props.theme),
69374
+ themeTokens: props.themeTokens
69375
+ };
69322
69376
  return React$1.createElement(PageRenderer$1, blocksProps);
69323
69377
  }
69324
69378
  //#endregion
@@ -69360,8 +69414,31 @@ function renderWithSdkThemeRuntime({ themeRuntime, theme, children }) {
69360
69414
  default: return assertNever$24(themeRuntime);
69361
69415
  }
69362
69416
  }
69417
+ function renderWithOverrideOnlyRuntime({ runtime, children }) {
69418
+ switch (runtime.kind) {
69419
+ case "responsive-only": return /* @__PURE__ */ jsx(ResponsiveScope, {
69420
+ responsiveMode: runtime.responsiveMode,
69421
+ children
69422
+ });
69423
+ case "none": return /* @__PURE__ */ jsx(Fragment, { children });
69424
+ default: return assertNever$24(runtime);
69425
+ }
69426
+ }
69363
69427
  //#endregion
69364
69428
  //#region src/rendering/components/pageShared.tsx
69429
+ function isOverrideOnlyPage(props) {
69430
+ return props.rendering?.kind === "overrides-only";
69431
+ }
69432
+ function resolvePageThemeTokens(props) {
69433
+ const baseTokens = props.themeTokens ?? buildThemeRuntime(props.theme).tokens;
69434
+ return props.sdkConfig?.theme?.palette ? {
69435
+ ...baseTokens,
69436
+ palette: {
69437
+ ...baseTokens.palette,
69438
+ ...props.sdkConfig.theme.palette
69439
+ }
69440
+ } : baseTokens;
69441
+ }
69365
69442
  function toPageHydrationBootstrapConfig(props) {
69366
69443
  return {
69367
69444
  siteId: props.siteId,
@@ -69369,55 +69446,60 @@ function toPageHydrationBootstrapConfig(props) {
69369
69446
  mediaAssets: props.mediaAssets
69370
69447
  };
69371
69448
  }
69372
- function PageContent({ page, runtimeBoundaries, theme, themeTokens: providedTokens, siteId, resolvedData, bookingOfferingPresets, routeMap, pagesByIdentifier, entriesByIdentifier, wrapBlock, registry, usePlaceholders = false, blockOverrides, sdkConfig, customBlocks, supabaseUrl, mediaAssets, apiBaseUrl, portalToken, previewToken, dataContext, themeRuntime = defaultPageThemeRuntime }) {
69373
- const baseTokens = providedTokens ?? buildThemeRuntime(theme).tokens;
69374
- return renderWithSdkThemeRuntime({
69375
- themeRuntime,
69376
- theme,
69377
- children: /* @__PURE__ */ jsx(PageRenderer, {
69378
- theme,
69379
- page,
69380
- runtimeBoundaries,
69381
- themeTokens: sdkConfig?.theme?.palette ? {
69382
- ...baseTokens,
69383
- palette: {
69384
- ...baseTokens.palette,
69385
- ...sdkConfig.theme.palette
69386
- }
69387
- } : baseTokens,
69388
- usePlaceholders,
69389
- dataContext: {
69449
+ function PageContent(props) {
69450
+ const { page, runtimeBoundaries, siteId, resolvedData, bookingOfferingPresets, routeMap, pagesByIdentifier, entriesByIdentifier, wrapBlock, registry, usePlaceholders = false, blockOverrides, sdkConfig, customBlocks, supabaseUrl, mediaAssets, apiBaseUrl, portalToken, previewToken, dataContext } = props;
69451
+ const rendererCommonProps = {
69452
+ page,
69453
+ runtimeBoundaries,
69454
+ usePlaceholders,
69455
+ dataContext: {
69456
+ siteId,
69457
+ apiBaseUrl,
69458
+ portalToken,
69459
+ previewToken,
69460
+ resolvedData,
69461
+ bookingOfferingPresets: bookingOfferingPresets ?? [],
69462
+ routes: routeMap,
69463
+ pagesByIdentifier,
69464
+ entriesByIdentifier,
69465
+ occurrenceContext: dataContext?.occurrenceContext ?? null,
69466
+ entrySubrouteContext: dataContext?.entrySubrouteContext ?? null,
69467
+ contentEntry: dataContext?.contentEntry ?? null,
69468
+ pageSurface: dataContext?.pageSurface ?? null,
69469
+ subject: dataContext?.subject ?? null,
69470
+ editableRouteMetadataFieldIds: dataContext?.editableRouteMetadataFieldIds ?? null,
69471
+ previewStage: dataContext?.previewStage,
69472
+ supabaseUrl,
69473
+ mediaAssets,
69474
+ imageResolveContext: {
69390
69475
  siteId,
69391
- apiBaseUrl,
69392
- portalToken,
69393
- previewToken,
69394
- resolvedData,
69395
- bookingOfferingPresets: bookingOfferingPresets ?? [],
69396
- routes: routeMap,
69397
- pagesByIdentifier,
69398
- entriesByIdentifier,
69399
- occurrenceContext: dataContext?.occurrenceContext ?? null,
69400
- entrySubrouteContext: dataContext?.entrySubrouteContext ?? null,
69401
- contentEntry: dataContext?.contentEntry ?? null,
69402
- pageSurface: dataContext?.pageSurface ?? null,
69403
- subject: dataContext?.subject ?? null,
69404
- editableRouteMetadataFieldIds: dataContext?.editableRouteMetadataFieldIds ?? null,
69405
- previewStage: dataContext?.previewStage,
69406
69476
  supabaseUrl,
69407
- mediaAssets,
69408
- imageResolveContext: {
69409
- siteId,
69410
- supabaseUrl,
69411
- mediaAssets
69412
- }
69413
- },
69414
- routeMap,
69415
- wrapBlock,
69416
- registry,
69417
- blockOverrides,
69418
- sdkConfig: sdkConfig ? { customBlocks: sdkConfig.customBlocks } : null,
69419
- customBlocks
69420
- })
69477
+ mediaAssets
69478
+ }
69479
+ },
69480
+ routeMap,
69481
+ wrapBlock,
69482
+ registry,
69483
+ sdkConfig: sdkConfig ? { customBlocks: sdkConfig.customBlocks } : null,
69484
+ customBlocks
69485
+ };
69486
+ const content = isOverrideOnlyPage(props) ? /* @__PURE__ */ jsx(PageRenderer, {
69487
+ ...rendererCommonProps,
69488
+ rendering: { kind: "overrides-only" },
69489
+ blockOverrides: props.blockOverrides
69490
+ }) : /* @__PURE__ */ jsx(PageRenderer, {
69491
+ ...rendererCommonProps,
69492
+ theme: props.theme,
69493
+ themeTokens: resolvePageThemeTokens(props),
69494
+ blockOverrides
69495
+ });
69496
+ return isOverrideOnlyPage(props) ? renderWithOverrideOnlyRuntime({
69497
+ runtime: props.rendering.runtime,
69498
+ children: content
69499
+ }) : renderWithSdkThemeRuntime({
69500
+ themeRuntime: props.themeRuntime ?? defaultPageThemeRuntime,
69501
+ theme: props.theme,
69502
+ children: content
69421
69503
  });
69422
69504
  }
69423
69505
  //#endregion
@@ -69940,12 +70022,48 @@ function buildLogo(logo, fallbackAlt) {
69940
70022
  return result;
69941
70023
  }
69942
70024
  //#endregion
70025
+ //#region src/rendering/renderingMode.ts
70026
+ const defaultOverrideOnlyRuntime = { kind: "responsive-only" };
70027
+ //#endregion
69943
70028
  //#region src/rendering/components/Layout.tsx
69944
70029
  /**
69945
70030
  * Layout component with header and footer
69946
70031
  *
69947
70032
  * Renders site header and footer around content. Fetches site data if not provided.
69948
70033
  */
70034
+ function isOverrideOnlyLayout(props) {
70035
+ return props.rendering?.kind === "overrides-only";
70036
+ }
70037
+ var UnsupportedOverrideOnlyLayoutChromeError = class extends Error {
70038
+ constructor(surface) {
70039
+ super(`Override-only Layout requires a custom or disabled ${surface}; SDK default chrome is unavailable.`);
70040
+ this.surface = surface;
70041
+ this.code = "unsupported_override_only_layout_chrome";
70042
+ this.name = "UnsupportedOverrideOnlyLayoutChromeError";
70043
+ }
70044
+ };
70045
+ async function resolveLayoutSiteData(props) {
70046
+ if (props.siteData) return props.siteData;
70047
+ if (!props.client) throw new Error("Layout: must provide either siteData or client");
70048
+ if (!props.siteId && !props.slug && !props.domain) throw new Error("Layout: must provide siteId, slug, or domain when using client");
70049
+ return props.client.getSite({
70050
+ id: props.siteId,
70051
+ slug: props.slug,
70052
+ domain: props.domain
70053
+ });
70054
+ }
70055
+ function renderOverrideOnlyLayout(props, data) {
70056
+ if (data.header === true) throw new UnsupportedOverrideOnlyLayoutChromeError("header");
70057
+ if (data.footer === true) throw new UnsupportedOverrideOnlyLayoutChromeError("footer");
70058
+ return renderWithOverrideOnlyRuntime({
70059
+ runtime: props.rendering.runtime ?? defaultOverrideOnlyRuntime,
70060
+ children: /* @__PURE__ */ jsxs(Fragment, { children: [
70061
+ typeof props.header === "function" ? props.header(data.headerData) : null,
70062
+ props.children,
70063
+ typeof props.footer === "function" ? props.footer(data.footerData) : null
70064
+ ] })
70065
+ });
70066
+ }
69949
70067
  /**
69950
70068
  * Layout component that wraps content with site header and footer.
69951
70069
  *
@@ -69981,20 +70099,13 @@ function buildLogo(logo, fallbackAlt) {
69981
70099
  * </Layout>
69982
70100
  * ```
69983
70101
  */
69984
- async function Layout({ siteData: providedSiteData, client, siteId, slug, domain, children, header = true, footer = true, headerVariant, hasPortalSession = false, previewStage = "published", themeRuntime }) {
69985
- let siteData = providedSiteData;
69986
- if (!siteData) {
69987
- if (!client) throw new Error("Layout: must provide either siteData or client");
69988
- if (!siteId && !slug && !domain) throw new Error("Layout: must provide siteId, slug, or domain when using client");
69989
- siteData = await client.getSite({
69990
- id: siteId,
69991
- slug,
69992
- domain
69993
- });
69994
- }
69995
- const { site, theme, navigation, layout, routes } = siteData;
70102
+ async function Layout(props) {
70103
+ const { children, hasPortalSession = false, previewStage = "published" } = props;
70104
+ const header = props.header ?? true;
70105
+ const footer = props.footer ?? true;
70106
+ const siteData = await resolveLayoutSiteData(props);
70107
+ const { site, navigation, layout, routes } = siteData;
69996
70108
  const footerBlocks = siteData.footerBlocks ?? [];
69997
- const builtThemeRuntime = buildThemeRuntime(theme);
69998
70109
  const navigationOptions = {
69999
70110
  hasPortalSession,
70000
70111
  previewStage,
@@ -70008,22 +70119,38 @@ async function Layout({ siteData: providedSiteData, client, siteId, slug, domain
70008
70119
  const footerMenuViewModel = buildFooterMenu(navigation, routes, navigationOptions);
70009
70120
  const legalFooterMenuViewModel = buildFooterMenuForRole(navigation, routes, "legal-policy", navigationOptions);
70010
70121
  const logoViewModel = buildLogo(layout.logo ?? null, site.title);
70011
- const headerData = {
70122
+ const customHeaderData = {
70012
70123
  menu: menuViewModel,
70013
70124
  logo: logoViewModel,
70014
70125
  site,
70015
- theme,
70016
70126
  routes
70017
70127
  };
70018
- const footerData = {
70128
+ const customFooterData = {
70019
70129
  menu: menuViewModel,
70020
70130
  footerMenu: footerMenuViewModel,
70021
70131
  legalFooterMenu: legalFooterMenuViewModel,
70022
70132
  logo: logoViewModel,
70023
70133
  site,
70024
- theme,
70025
70134
  routes
70026
70135
  };
70136
+ if (isOverrideOnlyLayout(props)) return renderOverrideOnlyLayout(props, {
70137
+ header: props.header ?? true,
70138
+ footer: props.footer ?? true,
70139
+ headerData: customHeaderData,
70140
+ footerData: customFooterData
70141
+ });
70142
+ const { theme } = siteData;
70143
+ const builtThemeRuntime = buildThemeRuntime(theme);
70144
+ const headerVariant = props.headerVariant;
70145
+ const themeRuntime = props.themeRuntime;
70146
+ const headerData = {
70147
+ ...customHeaderData,
70148
+ theme
70149
+ };
70150
+ const footerData = {
70151
+ ...customFooterData,
70152
+ theme
70153
+ };
70027
70154
  const headerContent = headerVariant ? {
70028
70155
  ...layout.header,
70029
70156
  variant: headerVariant