@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
@@ -7,12 +7,11 @@ import { type ComponentRegistry } from '../blocks-page-renderer';
7
7
  import { type SdkThemeRuntime } from '../themeRuntime';
8
8
  import type { BlockOverrides } from '../overrides';
9
9
  import type { SdkCustomBlock } from '../../config/types';
10
- export type PageProps = {
10
+ import type { SdkRenderingMode } from '../renderingMode';
11
+ type PageCommonProps = {
11
12
  page: PageOutline;
12
13
  runtimeBoundaries?: readonly PageRuntimeBoundary[];
13
- theme: Theme;
14
14
  siteId: string;
15
- themeTokens?: ThemeTokens;
16
15
  resolvedData?: ResolvedBlockData;
17
16
  bookingOfferingPresets?: readonly SiteBookingOfferingPresetSummary[];
18
17
  routeMap?: RouteMap;
@@ -82,17 +81,29 @@ export type PageProps = {
82
81
  * Keys can be full block kind ("block.hero") or short form ("hero").
83
82
  */
84
83
  blockOverrides?: BlockOverrides;
85
- /**
86
- * Controls the runtime wrapper around page content.
87
- *
88
- * @default { kind: 'none' }
89
- */
84
+ };
85
+ type ThemedPageProps = PageCommonProps & {
86
+ rendering?: never;
87
+ theme: Theme;
88
+ themeTokens?: ThemeTokens;
89
+ /** @default { kind: 'none' } */
90
90
  themeRuntime?: SdkThemeRuntime;
91
91
  };
92
+ type OverrideOnlyPageProps = PageCommonProps & {
93
+ rendering: Extract<SdkRenderingMode, {
94
+ kind: 'overrides-only';
95
+ }>;
96
+ theme?: never;
97
+ themeTokens?: never;
98
+ themeRuntime?: never;
99
+ blockOverrides: BlockOverrides;
100
+ };
101
+ export type PageProps = ThemedPageProps | OverrideOnlyPageProps;
92
102
  export type PageHydrationBootstrapConfig = {
93
103
  siteId: string;
94
104
  supabaseUrl?: string;
95
105
  mediaAssets?: readonly MediaAssetIndexItem[];
96
106
  };
97
107
  export declare function toPageHydrationBootstrapConfig(props: Pick<PageProps, 'siteId' | 'supabaseUrl' | 'mediaAssets'>): PageHydrationBootstrapConfig;
98
- export declare function PageContent({ page, runtimeBoundaries, theme, themeTokens: providedTokens, siteId, resolvedData, bookingOfferingPresets, routeMap, pagesByIdentifier, entriesByIdentifier, wrapBlock, registry, usePlaceholders, blockOverrides, sdkConfig, customBlocks, supabaseUrl, mediaAssets, apiBaseUrl, portalToken, previewToken, dataContext, themeRuntime, }: PageProps): ReactElement;
108
+ export declare function PageContent(props: PageProps): ReactElement;
109
+ export {};
@@ -7,8 +7,10 @@
7
7
  export { Page } from './components/Page';
8
8
  export type { PageProps } from './components/Page';
9
9
  export { Layout } from './components/Layout';
10
- export type { LayoutProps, HeaderData, FooterData } from './components/Layout';
10
+ export type { LayoutProps, HeaderData, FooterData, CustomHeaderData, CustomFooterData, } from './components/Layout';
11
+ export { UnsupportedOverrideOnlyLayoutChromeError } from './components/Layout';
11
12
  export type { SdkThemeResponsiveMode, SdkThemeRuntime } from './themeRuntime';
13
+ export type { SdkOverrideOnlyRendering, SdkOverrideOnlyRuntime, SdkRenderingMode, } from './renderingMode';
12
14
  export { Block } from './components/Block';
13
15
  export type { BlockProps } from './components/Block';
14
16
  export { loadPage } from './helpers/loadPage';
@@ -20,7 +22,7 @@ export type { AppointmentBookingContent, BlogListingContent, BlogPostContent, Bo
20
22
  export { ImagePresets } from '../contracts';
21
23
  export { RichText } from './primitives/RichText';
22
24
  export { resolveImageUrl, resolveImageUrlWithContext, resolveImageSourceSetWithContext, } from './image';
23
- export { PageRenderer, toBlocksPageRendererDataContext, } from './blocks-page-renderer';
25
+ export { MissingBlockOverrideError, PageRenderer, toBlocksPageRendererDataContext, } from './blocks-page-renderer';
24
26
  export { ThemeScope } from './blocks-theme-scope';
25
27
  export { buildThemeRuntime } from './blocks-theme-runtime';
26
28
  export { toBlocksImageResolveContextInput, toBlocksMediaAssets, } from './mediaAssets';
@@ -0,0 +1,23 @@
1
+ import type { SdkThemeRuntime } from './themeRuntime';
2
+ export type SdkOverrideOnlyRuntime = Extract<SdkThemeRuntime, {
3
+ kind: 'responsive-only' | 'none';
4
+ }>;
5
+ export type SdkOverrideOnlyRendering = Readonly<{
6
+ kind: 'overrides-only';
7
+ runtime?: SdkOverrideOnlyRuntime;
8
+ }>;
9
+ export type SdkRenderingMode = Readonly<{
10
+ kind: 'themed';
11
+ themeRuntime: SdkThemeRuntime;
12
+ }> | Readonly<{
13
+ kind: 'overrides-only';
14
+ runtime: SdkOverrideOnlyRuntime;
15
+ }>;
16
+ export declare const defaultOverrideOnlyRuntime: {
17
+ readonly kind: "responsive-only";
18
+ };
19
+ export declare function normalizeSdkRenderingMode(input: Readonly<{
20
+ rendering?: SdkOverrideOnlyRendering;
21
+ themeRuntime: SdkThemeRuntime;
22
+ }>): SdkRenderingMode;
23
+ export declare function themeRuntimeForRendering(rendering: SdkRenderingMode): SdkThemeRuntime;
@@ -4,11 +4,13 @@
4
4
  */
5
5
  export { Page } from './components/Page.server';
6
6
  export type { PageProps } from './components/Page.server';
7
- export { Layout } from './components/Layout';
8
- export type { LayoutProps, HeaderData, FooterData } from './components/Layout';
9
- export type { SdkThemeResponsiveMode, SdkThemeRuntime, } from './themeRuntime';
7
+ export { Layout, UnsupportedOverrideOnlyLayoutChromeError, } from './components/Layout';
8
+ export type { LayoutProps, HeaderData, FooterData, CustomHeaderData, CustomFooterData, } from './components/Layout';
9
+ export type { SdkThemeResponsiveMode, SdkThemeRuntime } from './themeRuntime';
10
+ export type { SdkOverrideOnlyRendering, SdkOverrideOnlyRuntime, SdkRenderingMode, } from './renderingMode';
10
11
  export { Block } from './components/Block.server';
11
12
  export type { BlockProps } from './components/Block.server';
13
+ export { MissingBlockOverrideError } from './blocks-page-renderer';
12
14
  export { defineBlockOverrideRegistrations, defineBlockOverrides, defineLazyBlockOverride, } from './overrides';
13
15
  export { buildPageBlockKindIndex, collectUsedBlockKindsFromPageOutline, resolveBlockOverridesForPage, } from './overrideResolution';
14
16
  export type { PageBlockKindIndex } from './overrideResolution';
@@ -24,3 +24,9 @@ export declare function renderWithSdkThemeRuntime({ themeRuntime, theme, childre
24
24
  theme: Theme;
25
25
  children: React.ReactNode;
26
26
  }): React.ReactElement;
27
+ export declare function renderWithOverrideOnlyRuntime({ runtime, children, }: {
28
+ runtime: Extract<SdkThemeRuntime, {
29
+ kind: 'responsive-only' | 'none';
30
+ }>;
31
+ children: React.ReactNode;
32
+ }): React.ReactElement;
@@ -8,4 +8,4 @@
8
8
  * 1. This constant
9
9
  * 2. The "version" field in package.json
10
10
  */
11
- export declare const SDK_VERSION = "0.128.0";
11
+ export declare const SDK_VERSION = "0.129.0";
@@ -63041,6 +63041,216 @@ init_node();
63041
63041
  init_fragments();
63042
63042
  init_defineBlock();
63043
63043
  //#endregion
63044
+ //#region ../blocks/src/system/manifest/hydrateLinks.ts
63045
+ init_typeGuards();
63046
+ /**
63047
+ * Hydrates link objects within block content using the provided route map. Returns
63048
+ * the original content reference when no mutations are required to avoid unnecessary renders.
63049
+ */
63050
+ function hydrateManifestLinks(manifest, content, routes, pagesByIdentifier, entriesByIdentifier) {
63051
+ if (!routes || !manifest?.fields?.length) return content;
63052
+ return hydrateValue(content, {
63053
+ routes,
63054
+ pagesByIdentifier,
63055
+ entriesByIdentifier
63056
+ });
63057
+ }
63058
+ function hydrateValue(value, context) {
63059
+ try {
63060
+ if (Array.isArray(value)) {
63061
+ const resolvedItems = value.map((item) => hydrateValue(item, context));
63062
+ return resolvedItems.every((item, index) => item === value[index]) ? value : resolvedItems;
63063
+ }
63064
+ if (isRecord$44(value)) {
63065
+ if (isInternalLink$1(value)) return hydrateInternalLink(value, context.routes);
63066
+ if (isPageLink$1(value)) return hydratePageLink(value, context);
63067
+ if (isEntryLink$1(value)) return hydrateEntryLink(value, context);
63068
+ const resolvedEntries = Object.entries(value).map(([key, entry]) => [key, hydrateValue(entry, context)]);
63069
+ return resolvedEntries.every(([key, entry]) => entry === value[key]) ? value : Object.fromEntries(resolvedEntries);
63070
+ }
63071
+ return value;
63072
+ } catch (err) {
63073
+ console.error("[hydrateLinks] Error hydrating value:", err, value);
63074
+ return value;
63075
+ }
63076
+ }
63077
+ function hydrateInternalLink(link, routes) {
63078
+ const resolved = resolveRouteTarget(link.routeId, routes);
63079
+ if (!resolved) return link;
63080
+ const nextHref = resolved.href;
63081
+ const currentHref = typeof link.href === "string" && link.href.length > 0 ? link.href : null;
63082
+ const nextUpdatedAt = resolved.updatedAt;
63083
+ const updates = {};
63084
+ if (nextHref && nextHref !== currentHref) updates.href = nextHref;
63085
+ if (nextUpdatedAt && link.updatedAt !== nextUpdatedAt) updates.updatedAt = nextUpdatedAt;
63086
+ return Object.keys(updates).length > 0 ? {
63087
+ ...link,
63088
+ ...updates
63089
+ } : link;
63090
+ }
63091
+ function isInternalLink$1(value) {
63092
+ if (value.kind !== "internal") return false;
63093
+ if (typeof value.routeId !== "string" || value.routeId.length === 0) return false;
63094
+ return true;
63095
+ }
63096
+ function isPageLink$1(value) {
63097
+ if (value.kind !== "page") return false;
63098
+ if (typeof value.identifier !== "string" || value.identifier.length === 0) return false;
63099
+ return true;
63100
+ }
63101
+ function hydratePageLink(link, context) {
63102
+ const resolved = resolvePageRouteTarget(link, context);
63103
+ if (!resolved) return link;
63104
+ return {
63105
+ ...link,
63106
+ href: resolved.href,
63107
+ routeId: resolved.routeId
63108
+ };
63109
+ }
63110
+ function isEntryLink$1(value) {
63111
+ if (value.kind !== "entry") return false;
63112
+ if (typeof value.contentType !== "string" || value.contentType.length === 0) return false;
63113
+ if (typeof value.identifier !== "string" || value.identifier.length === 0) return false;
63114
+ return true;
63115
+ }
63116
+ function hydrateEntryLink(link, context) {
63117
+ const resolved = resolveEntryRouteTarget(link, context);
63118
+ if (!resolved) return link;
63119
+ return {
63120
+ ...link,
63121
+ href: resolved.href,
63122
+ routeId: resolved.routeId
63123
+ };
63124
+ }
63125
+ //#endregion
63126
+ //#region ../blocks/src/sdkBlockTransform.ts
63127
+ init_augmentManifest();
63128
+ /**
63129
+ * Transforms an SDK custom block into a BlockManifest.
63130
+ *
63131
+ * If the block has a `layout`, it can be rendered declaratively without React code.
63132
+ * If no layout, the block MUST use blockOverrides for rendering.
63133
+ */
63134
+ function transformSdkBlockToManifest(sdkBlock) {
63135
+ const hasLayout = Boolean(sdkBlock.layout) || Boolean(sdkBlock.variants && Object.keys(sdkBlock.variants).length > 0);
63136
+ return augmentManifest({
63137
+ name: sdkBlock.id,
63138
+ version: "1.0.0",
63139
+ title: sdkBlock.title,
63140
+ titleSource: sdkBlock.titleSource,
63141
+ description: sdkBlock.description,
63142
+ component: sdkBlock.id,
63143
+ fields: sdkBlock.fields,
63144
+ slots: [],
63145
+ category: sdkBlock.category,
63146
+ tags: sdkBlock.tags,
63147
+ icon: sdkBlock.icon,
63148
+ layout: sdkBlock.layout,
63149
+ variants: sdkBlock.variants,
63150
+ defaultVariant: sdkBlock.defaultVariant,
63151
+ variantOptions: sdkBlock.variantOptions,
63152
+ previewCustomize: sdkBlock.previewCustomize,
63153
+ behaviours: {
63154
+ supportsThemeSwitching: true,
63155
+ inlineEditing: hasLayout,
63156
+ animation: hasLayout,
63157
+ paletteHidden: false
63158
+ }
63159
+ });
63160
+ }
63161
+ /**
63162
+ * Transforms an SDK custom block into a SystemBlockDefinition.
63163
+ *
63164
+ * This creates a minimal definition with just the manifest - no data loaders
63165
+ * or content normalizers since SDK blocks handle their own rendering.
63166
+ */
63167
+ function transformSdkBlockToDefinition(sdkBlock) {
63168
+ return {
63169
+ manifest: transformSdkBlockToManifest(sdkBlock),
63170
+ dataLoaders: sdkBlock.dataLoaders
63171
+ };
63172
+ }
63173
+ //#endregion
63174
+ //#region ../blocks/src/customBlockRegistry.ts
63175
+ init_src$3();
63176
+ const defaultCustomBlockSourcePolicy = { kind: "canonical-db-fallback-sdk" };
63177
+ function isCustomBlockKind(blockKind) {
63178
+ return blockKind.startsWith("custom.");
63179
+ }
63180
+ function transformToBlockDescriptor(sdkBlock, source = "sdk") {
63181
+ return {
63182
+ name: sdkBlock.id,
63183
+ title: sdkBlock.title,
63184
+ description: sdkBlock.description,
63185
+ category: sdkBlock.category,
63186
+ tags: sdkBlock.tags,
63187
+ icon: sdkBlock.icon,
63188
+ definition: transformSdkBlockToDefinition(sdkBlock),
63189
+ source
63190
+ };
63191
+ }
63192
+ function toResolvedCustomBlock(manifest, source) {
63193
+ return {
63194
+ blockKind: manifest.id,
63195
+ manifest: transformSdkBlockToManifest(manifest),
63196
+ source,
63197
+ descriptor: transformToBlockDescriptor(manifest, source.kind === "managed-database" ? "database" : "sdk")
63198
+ };
63199
+ }
63200
+ function planCustomBlockRegistryResolution({ sdkConfig, customBlocks = [], policy = defaultCustomBlockSourcePolicy }) {
63201
+ switch (policy.kind) {
63202
+ case "canonical-db-fallback-sdk": {
63203
+ const entriesByKind = /* @__PURE__ */ new Map();
63204
+ const conflicts = [];
63205
+ for (const customBlock of customBlocks) entriesByKind.set(customBlock.manifest.id, toResolvedCustomBlock(customBlock.manifest, customBlock.source));
63206
+ for (const sdkBlock of sdkConfig?.customBlocks ?? []) {
63207
+ const existing = entriesByKind.get(sdkBlock.id);
63208
+ if (existing) {
63209
+ conflicts.push({
63210
+ kind: "conflict",
63211
+ blockKind: existing.blockKind,
63212
+ winner: existing.source,
63213
+ loser: { kind: "sdk-config" },
63214
+ reason: "db-canonical-sdk-fallback"
63215
+ });
63216
+ continue;
63217
+ }
63218
+ entriesByKind.set(sdkBlock.id, toResolvedCustomBlock(sdkBlock, { kind: "sdk-config" }));
63219
+ }
63220
+ return {
63221
+ policy,
63222
+ entries: Array.from(entriesByKind.values()),
63223
+ conflicts
63224
+ };
63225
+ }
63226
+ }
63227
+ }
63228
+ function createCustomBlockRegistry({ sdkConfig, customBlocks = [], policy = defaultCustomBlockSourcePolicy, onConflict }) {
63229
+ const plan = planCustomBlockRegistryResolution({
63230
+ sdkConfig,
63231
+ customBlocks,
63232
+ policy
63233
+ });
63234
+ const entriesByKind = new Map(plan.entries.map((entry) => [entry.blockKind, entry]));
63235
+ for (const conflict of plan.conflicts) onConflict?.(`Using ${sourceLabel(conflict.winner)} custom block "${conflict.blockKind}" - ${sourceLabel(conflict.loser)} block is fallback only`);
63236
+ return {
63237
+ entries: plan.entries,
63238
+ conflicts: plan.conflicts,
63239
+ findManifest: (blockKind) => {
63240
+ if (!isCustomBlockKind(blockKind)) return void 0;
63241
+ return entriesByKind.get(blockKind);
63242
+ }
63243
+ };
63244
+ }
63245
+ function sourceLabel(source) {
63246
+ switch (source.kind) {
63247
+ case "managed-database": return "DB";
63248
+ case "sdk-synced": return "SDK-synced DB";
63249
+ case "sdk-config": return "SDK config";
63250
+ default: return assertNever$24(source);
63251
+ }
63252
+ }
63253
+ //#endregion
63044
63254
  //#region ../theme-core/src/styles/shadow.ts
63045
63255
  init_colorStyles();
63046
63256
  //#endregion
@@ -63801,215 +64011,31 @@ init_generateCardCss();
63801
64011
  init_tokens();
63802
64012
  init_colorStyles();
63803
64013
  //#endregion
63804
- //#region ../blocks/src/system/manifest/hydrateLinks.ts
63805
- init_typeGuards();
63806
- /**
63807
- * Hydrates link objects within block content using the provided route map. Returns
63808
- * the original content reference when no mutations are required to avoid unnecessary renders.
63809
- */
63810
- function hydrateManifestLinks(manifest, content, routes, pagesByIdentifier, entriesByIdentifier) {
63811
- if (!routes || !manifest?.fields?.length) return content;
63812
- return hydrateValue(content, {
63813
- routes,
63814
- pagesByIdentifier,
63815
- entriesByIdentifier
63816
- });
63817
- }
63818
- function hydrateValue(value, context) {
63819
- try {
63820
- if (Array.isArray(value)) {
63821
- const resolvedItems = value.map((item) => hydrateValue(item, context));
63822
- return resolvedItems.every((item, index) => item === value[index]) ? value : resolvedItems;
63823
- }
63824
- if (isRecord$44(value)) {
63825
- if (isInternalLink$1(value)) return hydrateInternalLink(value, context.routes);
63826
- if (isPageLink$1(value)) return hydratePageLink(value, context);
63827
- if (isEntryLink$1(value)) return hydrateEntryLink(value, context);
63828
- const resolvedEntries = Object.entries(value).map(([key, entry]) => [key, hydrateValue(entry, context)]);
63829
- return resolvedEntries.every(([key, entry]) => entry === value[key]) ? value : Object.fromEntries(resolvedEntries);
63830
- }
63831
- return value;
63832
- } catch (err) {
63833
- console.error("[hydrateLinks] Error hydrating value:", err, value);
63834
- return value;
64014
+ //#region ../blocks/src/pageRenderingMode.ts
64015
+ var MissingBlockOverrideError$1 = class extends Error {
64016
+ constructor(blockKind) {
64017
+ super(`Override-only rendering requires an override for block kind "${blockKind}".`);
64018
+ this.blockKind = blockKind;
64019
+ this.code = "missing_block_override";
64020
+ this.name = "MissingBlockOverrideError";
63835
64021
  }
64022
+ };
64023
+ function requireBlockOverride(resources, override, blockKind) {
64024
+ if (resources.kind === "unavailable" && !override) throw new MissingBlockOverrideError$1(blockKind);
63836
64025
  }
63837
- function hydrateInternalLink(link, routes) {
63838
- const resolved = resolveRouteTarget(link.routeId, routes);
63839
- if (!resolved) return link;
63840
- const nextHref = resolved.href;
63841
- const currentHref = typeof link.href === "string" && link.href.length > 0 ? link.href : null;
63842
- const nextUpdatedAt = resolved.updatedAt;
63843
- const updates = {};
63844
- if (nextHref && nextHref !== currentHref) updates.href = nextHref;
63845
- if (nextUpdatedAt && link.updatedAt !== nextUpdatedAt) updates.updatedAt = nextUpdatedAt;
63846
- return Object.keys(updates).length > 0 ? {
63847
- ...link,
63848
- ...updates
63849
- } : link;
63850
- }
63851
- function isInternalLink$1(value) {
63852
- if (value.kind !== "internal") return false;
63853
- if (typeof value.routeId !== "string" || value.routeId.length === 0) return false;
63854
- return true;
63855
- }
63856
- function isPageLink$1(value) {
63857
- if (value.kind !== "page") return false;
63858
- if (typeof value.identifier !== "string" || value.identifier.length === 0) return false;
63859
- return true;
63860
- }
63861
- function hydratePageLink(link, context) {
63862
- const resolved = resolvePageRouteTarget(link, context);
63863
- if (!resolved) return link;
63864
- return {
63865
- ...link,
63866
- href: resolved.href,
63867
- routeId: resolved.routeId
63868
- };
63869
- }
63870
- function isEntryLink$1(value) {
63871
- if (value.kind !== "entry") return false;
63872
- if (typeof value.contentType !== "string" || value.contentType.length === 0) return false;
63873
- if (typeof value.identifier !== "string" || value.identifier.length === 0) return false;
63874
- return true;
63875
- }
63876
- function hydrateEntryLink(link, context) {
63877
- const resolved = resolveEntryRouteTarget(link, context);
63878
- if (!resolved) return link;
63879
- return {
63880
- ...link,
63881
- href: resolved.href,
63882
- routeId: resolved.routeId
63883
- };
63884
- }
63885
- //#endregion
63886
- //#region ../blocks/src/sdkBlockTransform.ts
63887
- init_augmentManifest();
63888
- /**
63889
- * Transforms an SDK custom block into a BlockManifest.
63890
- *
63891
- * If the block has a `layout`, it can be rendered declaratively without React code.
63892
- * If no layout, the block MUST use blockOverrides for rendering.
63893
- */
63894
- function transformSdkBlockToManifest(sdkBlock) {
63895
- const hasLayout = Boolean(sdkBlock.layout) || Boolean(sdkBlock.variants && Object.keys(sdkBlock.variants).length > 0);
63896
- return augmentManifest({
63897
- name: sdkBlock.id,
63898
- version: "1.0.0",
63899
- title: sdkBlock.title,
63900
- titleSource: sdkBlock.titleSource,
63901
- description: sdkBlock.description,
63902
- component: sdkBlock.id,
63903
- fields: sdkBlock.fields,
63904
- slots: [],
63905
- category: sdkBlock.category,
63906
- tags: sdkBlock.tags,
63907
- icon: sdkBlock.icon,
63908
- layout: sdkBlock.layout,
63909
- variants: sdkBlock.variants,
63910
- defaultVariant: sdkBlock.defaultVariant,
63911
- variantOptions: sdkBlock.variantOptions,
63912
- previewCustomize: sdkBlock.previewCustomize,
63913
- behaviours: {
63914
- supportsThemeSwitching: true,
63915
- inlineEditing: hasLayout,
63916
- animation: hasLayout,
63917
- paletteHidden: false
63918
- }
63919
- });
64026
+ function overrideThemeProps(resources) {
64027
+ return resources.kind === "available" ? {
64028
+ theme: resources.tokens,
64029
+ themeConfig: resources.config
64030
+ } : {};
63920
64031
  }
63921
- /**
63922
- * Transforms an SDK custom block into a SystemBlockDefinition.
63923
- *
63924
- * This creates a minimal definition with just the manifest - no data loaders
63925
- * or content normalizers since SDK blocks handle their own rendering.
63926
- */
63927
- function transformSdkBlockToDefinition(sdkBlock) {
63928
- return {
63929
- manifest: transformSdkBlockToManifest(sdkBlock),
63930
- dataLoaders: sdkBlock.dataLoaders
63931
- };
64032
+ function requireThemeResources(resources, blockKind) {
64033
+ if (resources.kind === "unavailable") throw new MissingBlockOverrideError$1(blockKind);
64034
+ return resources;
63932
64035
  }
63933
64036
  //#endregion
63934
- //#region ../blocks/src/customBlockRegistry.ts
63935
- init_src$3();
63936
- const defaultCustomBlockSourcePolicy = { kind: "canonical-db-fallback-sdk" };
63937
- function isCustomBlockKind(blockKind) {
63938
- return blockKind.startsWith("custom.");
63939
- }
63940
- function transformToBlockDescriptor(sdkBlock, source = "sdk") {
63941
- return {
63942
- name: sdkBlock.id,
63943
- title: sdkBlock.title,
63944
- description: sdkBlock.description,
63945
- category: sdkBlock.category,
63946
- tags: sdkBlock.tags,
63947
- icon: sdkBlock.icon,
63948
- definition: transformSdkBlockToDefinition(sdkBlock),
63949
- source
63950
- };
63951
- }
63952
- function toResolvedCustomBlock(manifest, source) {
63953
- return {
63954
- blockKind: manifest.id,
63955
- manifest: transformSdkBlockToManifest(manifest),
63956
- source,
63957
- descriptor: transformToBlockDescriptor(manifest, source.kind === "managed-database" ? "database" : "sdk")
63958
- };
63959
- }
63960
- function planCustomBlockRegistryResolution({ sdkConfig, customBlocks = [], policy = defaultCustomBlockSourcePolicy }) {
63961
- switch (policy.kind) {
63962
- case "canonical-db-fallback-sdk": {
63963
- const entriesByKind = /* @__PURE__ */ new Map();
63964
- const conflicts = [];
63965
- for (const customBlock of customBlocks) entriesByKind.set(customBlock.manifest.id, toResolvedCustomBlock(customBlock.manifest, customBlock.source));
63966
- for (const sdkBlock of sdkConfig?.customBlocks ?? []) {
63967
- const existing = entriesByKind.get(sdkBlock.id);
63968
- if (existing) {
63969
- conflicts.push({
63970
- kind: "conflict",
63971
- blockKind: existing.blockKind,
63972
- winner: existing.source,
63973
- loser: { kind: "sdk-config" },
63974
- reason: "db-canonical-sdk-fallback"
63975
- });
63976
- continue;
63977
- }
63978
- entriesByKind.set(sdkBlock.id, toResolvedCustomBlock(sdkBlock, { kind: "sdk-config" }));
63979
- }
63980
- return {
63981
- policy,
63982
- entries: Array.from(entriesByKind.values()),
63983
- conflicts
63984
- };
63985
- }
63986
- }
63987
- }
63988
- function createCustomBlockRegistry({ sdkConfig, customBlocks = [], policy = defaultCustomBlockSourcePolicy, onConflict }) {
63989
- const plan = planCustomBlockRegistryResolution({
63990
- sdkConfig,
63991
- customBlocks,
63992
- policy
63993
- });
63994
- const entriesByKind = new Map(plan.entries.map((entry) => [entry.blockKind, entry]));
63995
- for (const conflict of plan.conflicts) onConflict?.(`Using ${sourceLabel(conflict.winner)} custom block "${conflict.blockKind}" - ${sourceLabel(conflict.loser)} block is fallback only`);
63996
- return {
63997
- entries: plan.entries,
63998
- conflicts: plan.conflicts,
63999
- findManifest: (blockKind) => {
64000
- if (!isCustomBlockKind(blockKind)) return void 0;
64001
- return entriesByKind.get(blockKind);
64002
- }
64003
- };
64004
- }
64005
- function sourceLabel(source) {
64006
- switch (source.kind) {
64007
- case "managed-database": return "DB";
64008
- case "sdk-synced": return "SDK-synced DB";
64009
- case "sdk-config": return "SDK config";
64010
- default: return assertNever$24(source);
64011
- }
64012
- }
64037
+ //#region ../blocks/src/pageRendererBoundaries.tsx
64038
+ init_typeGuards();
64013
64039
  //#endregion
64014
64040
  //#region ../blocks/src/PageRenderer.tsx
64015
64041
  init_fragments();
@@ -64075,7 +64101,7 @@ function getCachedValidator(manifest, flavour) {
64075
64101
  perFlavour.set(flavour, created);
64076
64102
  return created;
64077
64103
  }
64078
- React$1.memo(function MemoBlockSection({ themeTokens, themeConfig, block, usePlaceholders, dataContext, registry, routeMap, wrapBlock, blockOverrides, sdkConfig, customBlocks, imageResolveContext, previewAuthoring }) {
64104
+ React$1.memo(function MemoBlockSection({ themeResources, block, usePlaceholders, dataContext, registry, routeMap, wrapBlock, blockOverrides, sdkConfig, customBlocks, imageResolveContext, previewAuthoring }) {
64079
64105
  const perfStart = globalThis.process?.env?.DEBUG_PERF === "1" && typeof window === "undefined" ? Date.now() : 0;
64080
64106
  const fallbackImageResolveContext = getCurrentResolveImageUrlContext();
64081
64107
  const resolvedImageResolveContext = imageResolveContext ?? fallbackImageResolveContext;
@@ -64096,6 +64122,7 @@ React$1.memo(function MemoBlockSection({ themeTokens, themeConfig, block, usePla
64096
64122
  return node;
64097
64123
  }
64098
64124
  const OverrideComponent = getBlockOverride(block.kind, blockOverrides);
64125
+ requireBlockOverride(themeResources, OverrideComponent, block.kind);
64099
64126
  let definition = getBlockDefinition(block.kind);
64100
64127
  if (!definition && block.kind.startsWith("custom.")) definition = createCustomBlockRegistry({
64101
64128
  sdkConfig,
@@ -64108,8 +64135,7 @@ React$1.memo(function MemoBlockSection({ themeTokens, themeConfig, block, usePla
64108
64135
  if (OverrideComponent) {
64109
64136
  const rendered = /* @__PURE__ */ jsx(OverrideComponent, {
64110
64137
  content: getRenderableContent(block, dataContext?.previewStage),
64111
- theme: themeTokens,
64112
- themeConfig,
64138
+ ...overrideThemeProps(themeResources),
64113
64139
  data: void 0,
64114
64140
  siteId: dataContext?.siteId,
64115
64141
  apiBaseUrl: dataContext?.apiBaseUrl,
@@ -64208,8 +64234,7 @@ React$1.memo(function MemoBlockSection({ themeTokens, themeConfig, block, usePla
64208
64234
  const hasResolvedData = !!resolved && typeof resolved === "object" && Object.keys(resolved).length > 0;
64209
64235
  const baseProps = {
64210
64236
  content: hydratedContent,
64211
- theme: themeTokens,
64212
- themeConfig,
64237
+ ...overrideThemeProps(themeResources),
64213
64238
  data: resolved,
64214
64239
  siteId: dataContext?.siteId,
64215
64240
  apiBaseUrl: dataContext?.apiBaseUrl,
@@ -64229,6 +64254,7 @@ React$1.memo(function MemoBlockSection({ themeTokens, themeConfig, block, usePla
64229
64254
  let rendered;
64230
64255
  if (OverrideComponent) rendered = /* @__PURE__ */ jsx(OverrideComponent, { ...baseProps });
64231
64256
  else {
64257
+ requireThemeResources(themeResources, block.kind);
64232
64258
  const BlockComponent = getCachedBlockComponent(definition.manifest);
64233
64259
  const pathBase = typeof block.id === "string" && block.id.length > 0 ? `blocks.${block.id}.` : void 0;
64234
64260
  const rootContext = { $root: {
@@ -64278,7 +64304,7 @@ React$1.memo(function MemoBlockSection({ themeTokens, themeConfig, block, usePla
64278
64304
  });
64279
64305
  }
64280
64306
  }, (prev, next) => {
64281
- 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;
64307
+ 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;
64282
64308
  });
64283
64309
  function fallback(message) {
64284
64310
  return /* @__PURE__ */ jsx("div", {
@@ -153413,7 +153439,7 @@ var SimpleCache = class {
153413
153439
  * 1. This constant
153414
153440
  * 2. The "version" field in package.json
153415
153441
  */
153416
- const SDK_VERSION = "0.128.0";
153442
+ const SDK_VERSION = "0.129.0";
153417
153443
  //#endregion
153418
153444
  //#region src/client/error.ts
153419
153445
  /**