@riverbankcms/sdk 0.8.0 → 0.8.1

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 (168) hide show
  1. package/dist/cli/index.js +583 -147
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/client/client.d.mts +2 -2
  4. package/dist/client/client.d.ts +2 -2
  5. package/dist/client/client.js +126 -30
  6. package/dist/client/client.js.map +1 -1
  7. package/dist/client/client.mjs +126 -30
  8. package/dist/client/client.mjs.map +1 -1
  9. package/dist/client/hooks.d.mts +2 -2
  10. package/dist/client/hooks.d.ts +2 -2
  11. package/dist/client/hooks.js +34 -20
  12. package/dist/client/hooks.js.map +1 -1
  13. package/dist/client/hooks.mjs +34 -20
  14. package/dist/client/hooks.mjs.map +1 -1
  15. package/dist/client/rendering/client.js +182 -123
  16. package/dist/client/rendering/client.js.map +1 -1
  17. package/dist/client/rendering/client.mjs +174 -109
  18. package/dist/client/rendering/client.mjs.map +1 -1
  19. package/dist/client/usePage-Dsi39Exp.d.ts +6915 -0
  20. package/dist/client/usePage-Im82JRRe.d.mts +6915 -0
  21. package/dist/server/{Layout-l2v4Qa6E.d.ts → Layout-CZ-kxKfl.d.ts} +1 -1
  22. package/dist/server/{Layout-D4J009eS.d.mts → Layout-ESG8zvrk.d.mts} +1 -1
  23. package/dist/server/{chunk-4YQJUL5W.mjs → chunk-5GCSRTIU.mjs} +8 -4
  24. package/dist/server/chunk-5GCSRTIU.mjs.map +1 -0
  25. package/dist/server/{chunk-YYO3RIFO.js → chunk-6ERSDFTY.js} +35 -21
  26. package/dist/server/chunk-6ERSDFTY.js.map +1 -0
  27. package/dist/server/{chunk-YXA4GAAQ.mjs → chunk-6VTKALLN.mjs} +2 -6
  28. package/dist/server/{chunk-YXA4GAAQ.mjs.map → chunk-6VTKALLN.mjs.map} +1 -1
  29. package/dist/server/{chunk-BYBJA6SP.mjs → chunk-A3UZ2LDH.mjs} +35 -21
  30. package/dist/server/chunk-A3UZ2LDH.mjs.map +1 -0
  31. package/dist/server/{chunk-OSF34JTQ.mjs → chunk-ADD3O2QO.mjs} +4 -4
  32. package/dist/server/{chunk-C6FIJC7T.mjs → chunk-BNHK7YOC.mjs} +2 -2
  33. package/dist/server/{chunk-TT5JWA4X.js → chunk-DAXWU3S3.js} +9 -9
  34. package/dist/server/{chunk-TT5JWA4X.js.map → chunk-DAXWU3S3.js.map} +1 -1
  35. package/dist/server/{chunk-7UPVCT3K.js → chunk-F2NDLDDA.js} +239 -154
  36. package/dist/server/chunk-F2NDLDDA.js.map +1 -0
  37. package/dist/server/{chunk-LNOUXALA.mjs → chunk-FUFPKTSI.mjs} +96 -11
  38. package/dist/server/chunk-FUFPKTSI.mjs.map +1 -0
  39. package/dist/server/{chunk-65A5HAUZ.mjs → chunk-GRFFJUCO.mjs} +3 -3
  40. package/dist/server/{chunk-65A5HAUZ.mjs.map → chunk-GRFFJUCO.mjs.map} +1 -1
  41. package/dist/server/{chunk-AEFWG657.mjs → chunk-HDHY4236.mjs} +2 -2
  42. package/dist/server/{chunk-2KCF2DNK.js → chunk-HE3RTUDX.js} +8 -8
  43. package/dist/server/{chunk-2KCF2DNK.js.map → chunk-HE3RTUDX.js.map} +1 -1
  44. package/dist/server/{chunk-RVDS7VSP.js → chunk-IJTJH4J3.js} +4 -4
  45. package/dist/server/{chunk-RVDS7VSP.js.map → chunk-IJTJH4J3.js.map} +1 -1
  46. package/dist/server/{chunk-P3NNN73G.js → chunk-K44OPKLA.js} +3 -3
  47. package/dist/server/{chunk-P3NNN73G.js.map → chunk-K44OPKLA.js.map} +1 -1
  48. package/dist/server/{chunk-EIJ27EZQ.js → chunk-KDCVCDW6.js} +10 -6
  49. package/dist/server/chunk-KDCVCDW6.js.map +1 -0
  50. package/dist/server/{chunk-7BVRA5MY.js → chunk-KGORQCHF.js} +9 -9
  51. package/dist/server/{chunk-7BVRA5MY.js.map → chunk-KGORQCHF.js.map} +1 -1
  52. package/dist/server/{chunk-WM646WI3.js → chunk-MFNWLB5G.js} +7 -7
  53. package/dist/server/{chunk-WM646WI3.js.map → chunk-MFNWLB5G.js.map} +1 -1
  54. package/dist/server/{chunk-EIVISR62.js → chunk-P4O3WSAR.js} +2 -6
  55. package/dist/server/chunk-P4O3WSAR.js.map +1 -0
  56. package/dist/server/{chunk-RBJFXNDM.mjs → chunk-PGZJUNCY.mjs} +4 -4
  57. package/dist/server/{chunk-ARNCLSQT.mjs → chunk-T5PAA22U.mjs} +2 -2
  58. package/dist/server/{chunk-T26N3P26.js → chunk-TLZHVGTL.js} +4 -4
  59. package/dist/server/{chunk-T26N3P26.js.map → chunk-TLZHVGTL.js.map} +1 -1
  60. package/dist/server/{chunk-P4K63SBZ.mjs → chunk-TR7MSLWL.mjs} +3 -3
  61. package/dist/server/{chunk-NFEGQTCC.mjs → chunk-WMJKH4XE.mjs} +8 -1
  62. package/dist/server/{chunk-4CV4JOE5.js → chunk-Z6ZWNWWR.js} +9 -2
  63. package/dist/server/chunk-Z6ZWNWWR.js.map +1 -0
  64. package/dist/server/{components-D2uCKCj7.d.ts → components-CE48wJM1.d.ts} +4 -4
  65. package/dist/server/{components-vtYEmmPF.d.mts → components-iEDvl2Yw.d.mts} +4 -4
  66. package/dist/server/components.d.mts +6 -6
  67. package/dist/server/components.d.ts +6 -6
  68. package/dist/server/components.js +7 -7
  69. package/dist/server/components.mjs +6 -6
  70. package/dist/server/config-validation.d.mts +3 -3
  71. package/dist/server/config-validation.d.ts +3 -3
  72. package/dist/server/config-validation.js +6 -6
  73. package/dist/server/config-validation.mjs +5 -5
  74. package/dist/server/config.d.mts +5 -5
  75. package/dist/server/config.d.ts +5 -5
  76. package/dist/server/config.js +6 -6
  77. package/dist/server/config.mjs +5 -5
  78. package/dist/server/data.d.mts +3 -3
  79. package/dist/server/data.d.ts +3 -3
  80. package/dist/server/data.js +4 -4
  81. package/dist/server/data.mjs +3 -3
  82. package/dist/server/env.js +1 -1
  83. package/dist/server/env.mjs +1 -1
  84. package/dist/server/{index-BxrAuL9K.d.ts → index-BHLK2mgQ.d.ts} +2 -2
  85. package/dist/server/{index-DfWg1Qle.d.mts → index-BrH_NIRO.d.mts} +2 -2
  86. package/dist/server/{index-2qnY7VH_.d.mts → index-Cgvb5fVQ.d.mts} +2 -2
  87. package/dist/server/{index-CH_dvF6n.d.ts → index-DTBg8eXj.d.ts} +2 -2
  88. package/dist/server/index.d.mts +6 -6
  89. package/dist/server/index.d.ts +6 -6
  90. package/dist/server/index.js +11 -11
  91. package/dist/server/index.mjs +2 -2
  92. package/dist/server/{loadContent-DECnsp4k.d.ts → loadContent-BUK6IVJf.d.ts} +26 -4
  93. package/dist/server/{loadContent-Du5kS8UM.d.mts → loadContent-au9Weoy0.d.mts} +26 -4
  94. package/dist/server/loadPage-AWYZ2QA2.mjs +11 -0
  95. package/dist/server/loadPage-CMHYAW2J.js +11 -0
  96. package/dist/server/{loadPage-AXNAERDS.js.map → loadPage-CMHYAW2J.js.map} +1 -1
  97. package/dist/server/{loadPage-VBorKlWv.d.mts → loadPage-DiHEl8BA.d.mts} +3 -3
  98. package/dist/server/{loadPage-BZohBxxf.d.ts → loadPage-JOIbF7ih.d.ts} +3 -3
  99. package/dist/server/metadata.d.mts +5 -5
  100. package/dist/server/metadata.d.ts +5 -5
  101. package/dist/server/metadata.js +1 -1
  102. package/dist/server/metadata.mjs +1 -1
  103. package/dist/server/navigation.d.mts +4 -8
  104. package/dist/server/navigation.d.ts +4 -8
  105. package/dist/server/navigation.js +3 -7
  106. package/dist/server/navigation.js.map +1 -1
  107. package/dist/server/navigation.mjs +2 -6
  108. package/dist/server/next/revalidate.js +1 -1
  109. package/dist/server/next/revalidate.mjs +1 -1
  110. package/dist/server/next/tags.js +1 -1
  111. package/dist/server/next/tags.mjs +1 -1
  112. package/dist/server/next.d.mts +7 -7
  113. package/dist/server/next.d.ts +7 -7
  114. package/dist/server/next.js +20 -16
  115. package/dist/server/next.js.map +1 -1
  116. package/dist/server/next.mjs +12 -8
  117. package/dist/server/next.mjs.map +1 -1
  118. package/dist/server/rendering/server.d.mts +5 -5
  119. package/dist/server/rendering/server.d.ts +5 -5
  120. package/dist/server/rendering/server.js +9 -9
  121. package/dist/server/rendering/server.mjs +8 -8
  122. package/dist/server/rendering.d.mts +8 -8
  123. package/dist/server/rendering.d.ts +8 -8
  124. package/dist/server/rendering.js +11 -11
  125. package/dist/server/rendering.mjs +10 -10
  126. package/dist/server/routing.d.mts +5 -5
  127. package/dist/server/routing.d.ts +5 -5
  128. package/dist/server/routing.js +2 -2
  129. package/dist/server/routing.mjs +2 -2
  130. package/dist/server/{schema-Z6-afHJG.d.mts → schema-DYtW0zEu.d.mts} +40 -0
  131. package/dist/server/{schema-Z6-afHJG.d.ts → schema-DYtW0zEu.d.ts} +40 -0
  132. package/dist/server/server.d.mts +6 -6
  133. package/dist/server/server.d.ts +6 -6
  134. package/dist/server/server.js +7 -7
  135. package/dist/server/server.mjs +6 -6
  136. package/dist/server/theme-bridge.js +9 -9
  137. package/dist/server/theme-bridge.mjs +3 -3
  138. package/dist/server/theme.js +1 -1
  139. package/dist/server/theme.mjs +1 -1
  140. package/dist/server/{types-DT30Qy7x.d.mts → types-BAM1kcGA.d.mts} +1 -1
  141. package/dist/server/{types-D0rPF8l5.d.ts → types-CmBB0Osp.d.ts} +2 -2
  142. package/dist/server/{types-BRQ_6yOc.d.mts → types-DDNKxQXw.d.mts} +2 -2
  143. package/dist/server/{types-D8XqwoVd.d.ts → types-DVesWaB7.d.ts} +1 -1
  144. package/dist/server/{types-CJfJwcuL.d.mts → types-M0CviVW2.d.mts} +1 -1
  145. package/dist/server/{types-CgSO0yxg.d.ts → types-_SNCu2ZZ.d.ts} +1 -1
  146. package/dist/server/{validation-Pv3Zs6dP.d.mts → validation-BA1TKthZ.d.mts} +2 -2
  147. package/dist/server/{validation-D1LaY1kQ.d.ts → validation-js7BCPN8.d.ts} +2 -2
  148. package/dist/server/webhooks.js +1 -1
  149. package/dist/server/webhooks.mjs +1 -1
  150. package/package.json +1 -1
  151. package/dist/server/chunk-4CV4JOE5.js.map +0 -1
  152. package/dist/server/chunk-4YQJUL5W.mjs.map +0 -1
  153. package/dist/server/chunk-7UPVCT3K.js.map +0 -1
  154. package/dist/server/chunk-BYBJA6SP.mjs.map +0 -1
  155. package/dist/server/chunk-EIJ27EZQ.js.map +0 -1
  156. package/dist/server/chunk-EIVISR62.js.map +0 -1
  157. package/dist/server/chunk-LNOUXALA.mjs.map +0 -1
  158. package/dist/server/chunk-YYO3RIFO.js.map +0 -1
  159. package/dist/server/loadPage-AXNAERDS.js +0 -11
  160. package/dist/server/loadPage-XR7ORQ2E.mjs +0 -11
  161. /package/dist/server/{chunk-OSF34JTQ.mjs.map → chunk-ADD3O2QO.mjs.map} +0 -0
  162. /package/dist/server/{chunk-C6FIJC7T.mjs.map → chunk-BNHK7YOC.mjs.map} +0 -0
  163. /package/dist/server/{chunk-AEFWG657.mjs.map → chunk-HDHY4236.mjs.map} +0 -0
  164. /package/dist/server/{chunk-RBJFXNDM.mjs.map → chunk-PGZJUNCY.mjs.map} +0 -0
  165. /package/dist/server/{chunk-ARNCLSQT.mjs.map → chunk-T5PAA22U.mjs.map} +0 -0
  166. /package/dist/server/{chunk-P4K63SBZ.mjs.map → chunk-TR7MSLWL.mjs.map} +0 -0
  167. /package/dist/server/{chunk-NFEGQTCC.mjs.map → chunk-WMJKH4XE.mjs.map} +0 -0
  168. /package/dist/server/{loadPage-XR7ORQ2E.mjs.map → loadPage-AWYZ2QA2.mjs.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { buildMenu, buildLogo } from './navigation.js';
3
- import { S as SiteResponse, R as RiverbankClient } from './types-D0rPF8l5.js';
3
+ import { S as SiteResponse, R as RiverbankClient } from './types-CmBB0Osp.js';
4
4
 
5
5
  type HeaderData = {
6
6
  menu: ReturnType<typeof buildMenu>;
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { buildMenu, buildLogo } from './navigation.mjs';
3
- import { S as SiteResponse, R as RiverbankClient } from './types-BRQ_6yOc.mjs';
3
+ import { S as SiteResponse, R as RiverbankClient } from './types-DDNKxQXw.mjs';
4
4
 
5
5
  type HeaderData = {
6
6
  menu: ReturnType<typeof buildMenu>;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  prefetchBlockData
3
- } from "./chunk-AEFWG657.mjs";
3
+ } from "./chunk-HDHY4236.mjs";
4
4
 
5
5
  // src/rendering/helpers/loadContent.ts
6
6
  function isPageContent(result) {
@@ -46,7 +46,9 @@ async function loadContent(params) {
46
46
  dataContext: { contentEntry: entry.content },
47
47
  theme: site.theme,
48
48
  siteId,
49
- site: site.site
49
+ site: site.site,
50
+ sdkConfig: site.sdkConfig ?? null,
51
+ supabaseUrl: site.supabaseUrl
50
52
  };
51
53
  }
52
54
  const { page: pageData } = contentResponse;
@@ -72,7 +74,9 @@ async function loadContent(params) {
72
74
  theme: site.theme,
73
75
  siteId,
74
76
  resolvedData,
75
- site: site.site
77
+ site: site.site,
78
+ sdkConfig: site.sdkConfig ?? null,
79
+ supabaseUrl: site.supabaseUrl
76
80
  };
77
81
  }
78
82
  function isEntryResponse(response) {
@@ -141,4 +145,4 @@ export {
141
145
  isEntryContent,
142
146
  loadContent
143
147
  };
144
- //# sourceMappingURL=chunk-4YQJUL5W.mjs.map
148
+ //# sourceMappingURL=chunk-5GCSRTIU.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/rendering/helpers/loadContent.ts"],"sourcesContent":["/**\n * Server-side helper to fetch content (page or entry) by path.\n *\n * Use this for dynamic routing where a path could resolve to either\n * a page or a content entry.\n */\n\nimport type { Theme } from '@riverbankcms/blocks';\nimport type { RiverbankClient, PageResponse, SiteResponse } from '../../client/types';\nimport type { PageProps } from '../components/Page';\nimport { prefetchBlockData } from '../../data/prefetchBlockData';\nimport type { ResolvedBlockData } from '../../data/prefetchBlockData';\nimport type { RuntimeSdkConfig } from './loadPage';\n\n/**\n * Site data included in content results for metadata generation.\n */\nexport type SiteData = SiteResponse['site'];\n\nexport type LoadContentParams = {\n client: RiverbankClient;\n siteId: string;\n path: string;\n /**\n * If true, fetches draft/unpublished content instead of published content.\n * This affects both pages and entries.\n * Requires API key with site access.\n *\n * @default false\n */\n preview?: boolean;\n};\n\n/**\n * Content entry data returned when a path resolves to an entry\n */\nexport type ContentEntryData = {\n id: string;\n /** Content type key (e.g., 'blog-post', 'product') */\n type: string | null;\n title: string;\n slug: string | null;\n path: string | null;\n status: string;\n publishAt: string | null;\n /** The raw content fields - use these to render your own UI */\n content: Record<string, unknown>;\n metaTitle: string | null;\n metaDescription: string | null;\n createdAt: string;\n updatedAt: string;\n};\n\n/**\n * Result when path resolves to a page\n */\nexport type PageContentResult = {\n type: 'page';\n /** Page outline ready for rendering with <Page> component */\n page: PageProps['page'];\n /** Site theme for styling */\n theme: Theme;\n /** Site ID */\n siteId: string;\n /** Pre-fetched block data for data loaders */\n resolvedData: ResolvedBlockData;\n /** Site data for metadata generation */\n site: SiteData;\n /**\n * SDK site configuration containing theme palette overrides.\n * When provided, the SDK palette tokens are merged into the theme tokens,\n * allowing blocks to use SDK-defined color tokens for section backgrounds.\n */\n sdkConfig: RuntimeSdkConfig | null;\n /**\n * Supabase storage URL for direct image access.\n * SDK sites receive this from the API instead of requiring NEXT_PUBLIC_SUPABASE_URL env var.\n */\n supabaseUrl?: string;\n};\n\n/**\n * Result when path resolves to a content entry\n */\nexport type EntryContentResult = {\n type: 'entry';\n /** Raw entry data - render this however you want */\n entry: ContentEntryData;\n /** Template page for rendering the entry (if available) */\n templatePage: PageProps['page'] | null;\n /** Pre-fetched block data for template page data loaders */\n resolvedData: ResolvedBlockData;\n /** Data context for template blocks (includes entry content for bindings) */\n dataContext: { contentEntry: Record<string, unknown> };\n /** Site theme for styling (useful if rendering with SDK components) */\n theme: Theme;\n /** Site ID */\n siteId: string;\n /** Site data for metadata generation */\n site: SiteData;\n /**\n * SDK site configuration containing theme palette overrides.\n * When provided, the SDK palette tokens are merged into the theme tokens,\n * allowing blocks to use SDK-defined color tokens for section backgrounds.\n */\n sdkConfig: RuntimeSdkConfig | null;\n /**\n * Supabase storage URL for direct image access.\n * SDK sites receive this from the API instead of requiring NEXT_PUBLIC_SUPABASE_URL env var.\n */\n supabaseUrl?: string;\n};\n\n/**\n * Discriminated union result from loadContent\n */\nexport type LoadContentResult = PageContentResult | EntryContentResult;\n\n/**\n * Type guard to check if result is a page\n */\nexport function isPageContent(result: LoadContentResult): result is PageContentResult {\n return result.type === 'page';\n}\n\n/**\n * Type guard to check if result is an entry\n */\nexport function isEntryContent(result: LoadContentResult): result is EntryContentResult {\n return result.type === 'entry';\n}\n\n/**\n * Server-side helper to fetch content by path.\n *\n * Returns a discriminated union - either page data (ready for `<Page>` component)\n * or raw entry data (for custom rendering).\n *\n * @example Dynamic routing with both pages and entries\n * ```tsx\n * import { loadContent, Page, isPageContent } from '@riverbankcms/sdk';\n *\n * export default async function DynamicRoute({ params }) {\n * const content = await loadContent({\n * client,\n * siteId: 'site-123',\n * path: `/${params.slug?.join('/') || ''}`,\n * });\n *\n * if (isPageContent(content)) {\n * return <Page {...content} />;\n * }\n *\n * // Render entry with custom UI\n * return (\n * <article>\n * <h1>{content.entry.title}</h1>\n * <div>{content.entry.content.body}</div>\n * </article>\n * );\n * }\n * ```\n *\n * @example Entry-specific rendering based on content type\n * ```tsx\n * const content = await loadContent({ client, siteId, path });\n *\n * if (content.type === 'entry') {\n * switch (content.entry.type) {\n * case 'blog-post':\n * return <BlogPost entry={content.entry} theme={content.theme} />;\n * case 'product':\n * return <ProductPage entry={content.entry} theme={content.theme} />;\n * default:\n * return <GenericEntry entry={content.entry} />;\n * }\n * }\n *\n * return <Page {...content} />;\n * ```\n *\n * @example Preview mode for draft content\n * ```tsx\n * const content = await loadContent({\n * client,\n * siteId,\n * path,\n * preview: true, // Fetches draft content for both pages and entries\n * });\n * ```\n */\nexport async function loadContent(params: LoadContentParams): Promise<LoadContentResult> {\n const { client, siteId, path, preview = false } = params;\n\n // Fetch site and content in parallel\n const [site, contentResponse] = await Promise.all([\n client.getSite({ id: siteId }),\n client.getPage({ siteId, path, preview }),\n ]);\n\n // Check if response is an entry\n if (isEntryResponse(contentResponse)) {\n const entryData = contentResponse.entry;\n\n const entry: ContentEntryData = {\n id: entryData.id,\n type: entryData.type,\n title: entryData.title,\n slug: entryData.slug,\n path: entryData.path,\n status: entryData.status,\n publishAt: entryData.publishAt,\n // Use draft content in preview mode, otherwise use published content\n content: preview\n ? (entryData.draftContent ?? entryData.content)\n : entryData.content,\n metaTitle: preview\n ? (entryData.draftMetaTitle ?? entryData.metaTitle)\n : entryData.metaTitle,\n metaDescription: preview\n ? (entryData.draftMetaDescription ?? entryData.metaDescription)\n : entryData.metaDescription,\n createdAt: entryData.createdAt,\n updatedAt: entryData.updatedAt,\n };\n\n // Process template if available (uses first template from content type)\n const { templatePage, resolvedData } = await processEntryTemplate(\n contentResponse.templates as Template[] | undefined,\n entry,\n { siteId, preview },\n client\n );\n\n return {\n type: 'entry',\n entry,\n templatePage,\n resolvedData,\n dataContext: { contentEntry: entry.content },\n theme: site.theme,\n siteId,\n site: site.site,\n sdkConfig: site.sdkConfig ?? null,\n supabaseUrl: site.supabaseUrl,\n };\n }\n\n // Handle page response\n const { page: pageData } = contentResponse;\n\n // Convert API response blocks to PageOutline format with validation\n const blocks = pageData.blocks.map((block) => validateAndConvertBlock(block, 'page'));\n\n const pageOutline = {\n name: pageData.name,\n path: pageData.path,\n purpose: pageData.purpose,\n blocks,\n };\n\n // Prefetch block data loaders for pages\n const resolvedData = await prefetchBlockData(\n pageOutline,\n {\n siteId,\n pageId: pageData.id,\n previewStage: preview ? 'preview' : 'published',\n },\n client\n );\n\n return {\n type: 'page',\n page: pageOutline,\n theme: site.theme,\n siteId,\n resolvedData,\n site: site.site,\n sdkConfig: site.sdkConfig ?? null,\n supabaseUrl: site.supabaseUrl,\n };\n}\n\n/**\n * Type guard to check if API response is an entry\n */\nfunction isEntryResponse(response: PageResponse): response is Extract<PageResponse, { type: 'entry' }> {\n return 'type' in response && response.type === 'entry';\n}\n\n/**\n * Validates and converts a raw block from API response to PageOutline block format.\n * Used for both page blocks and template blocks to ensure consistent validation.\n */\nfunction validateAndConvertBlock(\n block: unknown,\n source: 'page' | 'template'\n): { id: string | null; kind: string; purpose: string; content?: Record<string, unknown> } {\n if (!block || typeof block !== 'object') {\n throw new Error(`Invalid block format in ${source} API response`);\n }\n\n const blockRecord = block as Record<string, unknown>;\n\n // Template blocks use 'blockKind', page blocks use 'kind'\n const kindField = source === 'template' ? 'blockKind' : 'kind';\n const kindValue = blockRecord[kindField];\n\n if (typeof blockRecord.id !== 'string' && blockRecord.id !== null) {\n throw new Error(`Invalid block id in ${source}: expected string or null, got ${typeof blockRecord.id}`);\n }\n if (typeof kindValue !== 'string') {\n throw new Error(`Invalid block ${kindField} in ${source}: expected string, got ${typeof kindValue}`);\n }\n\n // Template blocks derive purpose from scope, page blocks have explicit purpose\n if (source === 'page') {\n if (typeof blockRecord.purpose !== 'string') {\n throw new Error(`Invalid block purpose in ${source}: expected string, got ${typeof blockRecord.purpose}`);\n }\n // Include content for page blocks - required for data loader binding resolution\n const content = (blockRecord.content as Record<string, unknown> | null) ?? {};\n return {\n id: blockRecord.id as string | null,\n kind: kindValue,\n purpose: blockRecord.purpose,\n content,\n };\n }\n\n // Template block: derive purpose from scope, include content\n const scope = blockRecord.scope as 'entry' | 'template' | undefined;\n const content = (blockRecord.content as Record<string, unknown> | null) ?? {};\n\n return {\n id: blockRecord.id as string | null,\n kind: kindValue,\n purpose: scope === 'entry' ? 'entry-content' : 'template-layout',\n content,\n };\n}\n\n/** Template block structure from API response */\ntype TemplateBlock = {\n id: string;\n blockKind: string;\n scope: 'entry' | 'template';\n content: Record<string, unknown> | null;\n};\n\n/** Template structure from API response */\ntype Template = {\n id: string;\n name: string;\n templateKey: string;\n blocks: TemplateBlock[];\n};\n\n/**\n * Processes an entry's template into a PageOutline format and prefetches block data.\n * Returns null templatePage if no valid template with blocks is available.\n */\nasync function processEntryTemplate(\n templates: Template[] | undefined,\n entry: ContentEntryData,\n context: { siteId: string; preview: boolean },\n client: RiverbankClient\n): Promise<{ templatePage: PageProps['page'] | null; resolvedData: ResolvedBlockData }> {\n const template = templates?.[0];\n\n // Templates without blocks are treated as \"no template\" - the entry should be\n // rendered with custom UI rather than an empty template page\n if (!template || !template.blocks?.length) {\n return { templatePage: null, resolvedData: {} };\n }\n\n // Convert template blocks to PageOutline format with validation\n const blocks = template.blocks.map((block) => validateAndConvertBlock(block, 'template'));\n\n const templatePage: PageProps['page'] = {\n name: template.name || 'Entry Template',\n path: entry.path || '/',\n purpose: 'entry-template',\n blocks,\n };\n\n // Prefetch block data for template\n const resolvedData = await prefetchBlockData(\n templatePage,\n {\n siteId: context.siteId,\n pageId: template.id,\n previewStage: context.preview ? 'preview' : 'published',\n },\n client\n );\n\n return { templatePage, resolvedData };\n}\n"],"mappings":";;;;;AAyHO,SAAS,cAAc,QAAwD;AACpF,SAAO,OAAO,SAAS;AACzB;AAKO,SAAS,eAAe,QAAyD;AACtF,SAAO,OAAO,SAAS;AACzB;AA6DA,eAAsB,YAAY,QAAuD;AACvF,QAAM,EAAE,QAAQ,QAAQ,MAAM,UAAU,MAAM,IAAI;AAGlD,QAAM,CAAC,MAAM,eAAe,IAAI,MAAM,QAAQ,IAAI;AAAA,IAChD,OAAO,QAAQ,EAAE,IAAI,OAAO,CAAC;AAAA,IAC7B,OAAO,QAAQ,EAAE,QAAQ,MAAM,QAAQ,CAAC;AAAA,EAC1C,CAAC;AAGD,MAAI,gBAAgB,eAAe,GAAG;AACpC,UAAM,YAAY,gBAAgB;AAElC,UAAM,QAA0B;AAAA,MAC9B,IAAI,UAAU;AAAA,MACd,MAAM,UAAU;AAAA,MAChB,OAAO,UAAU;AAAA,MACjB,MAAM,UAAU;AAAA,MAChB,MAAM,UAAU;AAAA,MAChB,QAAQ,UAAU;AAAA,MAClB,WAAW,UAAU;AAAA;AAAA,MAErB,SAAS,UACJ,UAAU,gBAAgB,UAAU,UACrC,UAAU;AAAA,MACd,WAAW,UACN,UAAU,kBAAkB,UAAU,YACvC,UAAU;AAAA,MACd,iBAAiB,UACZ,UAAU,wBAAwB,UAAU,kBAC7C,UAAU;AAAA,MACd,WAAW,UAAU;AAAA,MACrB,WAAW,UAAU;AAAA,IACvB;AAGA,UAAM,EAAE,cAAc,cAAAA,cAAa,IAAI,MAAM;AAAA,MAC3C,gBAAgB;AAAA,MAChB;AAAA,MACA,EAAE,QAAQ,QAAQ;AAAA,MAClB;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,cAAAA;AAAA,MACA,aAAa,EAAE,cAAc,MAAM,QAAQ;AAAA,MAC3C,OAAO,KAAK;AAAA,MACZ;AAAA,MACA,MAAM,KAAK;AAAA,MACX,WAAW,KAAK,aAAa;AAAA,MAC7B,aAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAGA,QAAM,EAAE,MAAM,SAAS,IAAI;AAG3B,QAAM,SAAS,SAAS,OAAO,IAAI,CAAC,UAAU,wBAAwB,OAAO,MAAM,CAAC;AAEpF,QAAM,cAAc;AAAA,IAClB,MAAM,SAAS;AAAA,IACf,MAAM,SAAS;AAAA,IACf,SAAS,SAAS;AAAA,IAClB;AAAA,EACF;AAGA,QAAM,eAAe,MAAM;AAAA,IACzB;AAAA,IACA;AAAA,MACE;AAAA,MACA,QAAQ,SAAS;AAAA,MACjB,cAAc,UAAU,YAAY;AAAA,IACtC;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO,KAAK;AAAA,IACZ;AAAA,IACA;AAAA,IACA,MAAM,KAAK;AAAA,IACX,WAAW,KAAK,aAAa;AAAA,IAC7B,aAAa,KAAK;AAAA,EACpB;AACF;AAKA,SAAS,gBAAgB,UAA8E;AACrG,SAAO,UAAU,YAAY,SAAS,SAAS;AACjD;AAMA,SAAS,wBACP,OACA,QACyF;AACzF,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,UAAM,IAAI,MAAM,2BAA2B,MAAM,eAAe;AAAA,EAClE;AAEA,QAAM,cAAc;AAGpB,QAAM,YAAY,WAAW,aAAa,cAAc;AACxD,QAAM,YAAY,YAAY,SAAS;AAEvC,MAAI,OAAO,YAAY,OAAO,YAAY,YAAY,OAAO,MAAM;AACjE,UAAM,IAAI,MAAM,uBAAuB,MAAM,kCAAkC,OAAO,YAAY,EAAE,EAAE;AAAA,EACxG;AACA,MAAI,OAAO,cAAc,UAAU;AACjC,UAAM,IAAI,MAAM,iBAAiB,SAAS,OAAO,MAAM,0BAA0B,OAAO,SAAS,EAAE;AAAA,EACrG;AAGA,MAAI,WAAW,QAAQ;AACrB,QAAI,OAAO,YAAY,YAAY,UAAU;AAC3C,YAAM,IAAI,MAAM,4BAA4B,MAAM,0BAA0B,OAAO,YAAY,OAAO,EAAE;AAAA,IAC1G;AAEA,UAAMC,WAAW,YAAY,WAA8C,CAAC;AAC5E,WAAO;AAAA,MACL,IAAI,YAAY;AAAA,MAChB,MAAM;AAAA,MACN,SAAS,YAAY;AAAA,MACrB,SAAAA;AAAA,IACF;AAAA,EACF;AAGA,QAAM,QAAQ,YAAY;AAC1B,QAAM,UAAW,YAAY,WAA8C,CAAC;AAE5E,SAAO;AAAA,IACL,IAAI,YAAY;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,UAAU,UAAU,kBAAkB;AAAA,IAC/C;AAAA,EACF;AACF;AAsBA,eAAe,qBACb,WACA,OACA,SACA,QACsF;AACtF,QAAM,WAAW,YAAY,CAAC;AAI9B,MAAI,CAAC,YAAY,CAAC,SAAS,QAAQ,QAAQ;AACzC,WAAO,EAAE,cAAc,MAAM,cAAc,CAAC,EAAE;AAAA,EAChD;AAGA,QAAM,SAAS,SAAS,OAAO,IAAI,CAAC,UAAU,wBAAwB,OAAO,UAAU,CAAC;AAExF,QAAM,eAAkC;AAAA,IACtC,MAAM,SAAS,QAAQ;AAAA,IACvB,MAAM,MAAM,QAAQ;AAAA,IACpB,SAAS;AAAA,IACT;AAAA,EACF;AAGA,QAAM,eAAe,MAAM;AAAA,IACzB;AAAA,IACA;AAAA,MACE,QAAQ,QAAQ;AAAA,MAChB,QAAQ,SAAS;AAAA,MACjB,cAAc,QAAQ,UAAU,YAAY;AAAA,IAC9C;AAAA,IACA;AAAA,EACF;AAEA,SAAO,EAAE,cAAc,aAAa;AACtC;","names":["resolvedData","content"]}
@@ -108,7 +108,11 @@ var uiSchema = _zod.z.object({
108
108
  layout: _zod.z.enum(["stack", "grid"]).optional(),
109
109
  columns: _zod.z.number().int().min(2).max(4).optional(),
110
110
  // Entry picker configuration
111
- contentTypeField: _zod.z.string().optional()
111
+ contentTypeField: _zod.z.string().optional(),
112
+ // Extras pattern: fields marked as extras are hidden behind a modal toggle
113
+ extras: _zod.z.boolean().optional(),
114
+ // Render in block header instead of form body (used for section styles)
115
+ renderInHeader: _zod.z.boolean().optional()
112
116
  }).partial();
113
117
  var baseFieldSchema = _zod.z.object({
114
118
  id: _zod.z.string().min(1, "Field id is required"),
@@ -1366,25 +1370,30 @@ function createButtonGroup(options = {}) {
1366
1370
  ui: { colSpan: 2 }
1367
1371
  }
1368
1372
  ];
1369
- const iconsGroup = {
1370
- id: "icons",
1371
- type: "group",
1372
- label: "Icons",
1373
- required: false,
1374
- ui: { preset: "disclosure", colSpan: 2 },
1375
- schema: {
1376
- fields: [
1377
- { id: "iconLeft", type: "media", label: "Left icon", required: false, mediaKinds: ["image"] },
1378
- { id: "iconRight", type: "media", label: "Right icon", required: false, mediaKinds: ["image"] }
1379
- ]
1373
+ const iconFields = [
1374
+ {
1375
+ id: "iconLeft",
1376
+ type: "media",
1377
+ label: "Left icon",
1378
+ required: false,
1379
+ mediaKinds: ["image"],
1380
+ ui: { extras: true }
1381
+ },
1382
+ {
1383
+ id: "iconRight",
1384
+ type: "media",
1385
+ label: "Right icon",
1386
+ required: false,
1387
+ mediaKinds: ["image"],
1388
+ ui: { extras: true }
1380
1389
  }
1381
- };
1390
+ ];
1382
1391
  return {
1383
1392
  id: groupId,
1384
1393
  type: "group",
1385
1394
  label: groupLabel,
1386
1395
  ui: { layout: "grid", columns: 2, flattenInRepeater, hideLabel: !showGroupLabel },
1387
- schema: { fields: [...mainFields, iconsGroup] },
1396
+ schema: { fields: [...mainFields, ...iconFields] },
1388
1397
  required: false
1389
1398
  };
1390
1399
  }
@@ -2705,6 +2714,10 @@ function getAnchorClasses(position) {
2705
2714
  }
2706
2715
 
2707
2716
  // ../blocks/src/system/fields/background.ts
2717
+ var BACKGROUND_WIDGETS = {
2718
+ COLOR: "backgroundColor",
2719
+ GRADIENT: "backgroundGradient"
2720
+ };
2708
2721
  function createBackgroundField(options = {}) {
2709
2722
  const {
2710
2723
  id = "background",
@@ -2730,8 +2743,7 @@ function createBackgroundField(options = {}) {
2730
2743
  required: false,
2731
2744
  multiline: false,
2732
2745
  ui: {
2733
- // Use BackgroundColorWidget via widget override
2734
- widget: "backgroundColor"
2746
+ widget: BACKGROUND_WIDGETS.COLOR
2735
2747
  }
2736
2748
  }
2737
2749
  ]
@@ -2748,11 +2760,11 @@ function createBackgroundField(options = {}) {
2748
2760
  id: "gradient",
2749
2761
  type: "text",
2750
2762
  label: "Gradient",
2751
- description: "CSS gradient value (e.g., linear-gradient(to right, #ff0000, #00ff00)).",
2763
+ description: "Select a gradient from theme presets.",
2752
2764
  required: false,
2753
- multiline: true,
2765
+ multiline: false,
2754
2766
  ui: {
2755
- placeholder: "linear-gradient(to right, #ff0000, #00ff00)"
2767
+ widget: BACKGROUND_WIDGETS.GRADIENT
2756
2768
  }
2757
2769
  }
2758
2770
  ]
@@ -2811,7 +2823,7 @@ function createBackgroundField(options = {}) {
2811
2823
  id: "position",
2812
2824
  type: "presetOrCustom",
2813
2825
  label: "Position",
2814
- description: 'Anchor point for the image. Relevant for "Fill" and "Custom size" options.',
2826
+ description: 'Anchor point for scaled images. For "Fill" mode, the image focus point (if set) takes precedence.',
2815
2827
  required: false,
2816
2828
  presets: [...BACKGROUND_POSITION_PRESETS],
2817
2829
  customInput: {
@@ -2902,6 +2914,8 @@ function sectionStylesField(options = {}) {
2902
2914
  required: false,
2903
2915
  schema: { fields: fields4 },
2904
2916
  ui: {
2917
+ // Render in block header instead of form body
2918
+ renderInHeader: true,
2905
2919
  modalConfig: {
2906
2920
  buttonLabel: label,
2907
2921
  description: "Configure background and spacing for this section.",
@@ -5473,4 +5487,4 @@ function getBlockDefinition(name) {
5473
5487
 
5474
5488
 
5475
5489
  exports.bindingSchema = bindingSchema; exports.fieldSchema = fieldSchema; exports.blockCategoryEnum = blockCategoryEnum; exports.backgroundColorStyle = backgroundColorStyle; exports.textColorStyle = textColorStyle; exports.borderColorStyle = borderColorStyle; exports.mergeStyles = mergeStyles; exports.headingGroup = headingGroup; exports.isSemanticSpacing = isSemanticSpacing; exports.resolveSpacing = resolveSpacing; exports.ctaButton = ctaButton; exports.defineFragment = defineFragment; exports.bodyCopyFragment = bodyCopyFragment; exports.heroCopyFragment = heroCopyFragment; exports.createButtonGroup = createButtonGroup; exports.ctaRowFragment = ctaRowFragment; exports.ctaCopyFragment = ctaCopyFragment; exports.testimonialsHeadingFragment = testimonialsHeadingFragment; exports.testimonialsCarouselFragment = testimonialsCarouselFragment; exports.formCopyFragment = formCopyFragment; exports.formEmbedFragment = formEmbedFragment; exports.footerBottomTextFragment = footerBottomTextFragment; exports.footerLinkGroupsFragment = footerLinkGroupsFragment; exports.blogFeaturedPostFragment = blogFeaturedPostFragment; exports.blogListGridFragment = blogListGridFragment; exports.blogListStackFragment = blogListStackFragment; exports.faqHeadingFragment = faqHeadingFragment; exports.faqAccordionFragment = faqAccordionFragment; exports.cardFragment = cardFragment; exports.headingFragment = headingFragment; exports.richTextFragment = richTextFragment; exports.BACKGROUND_POSITION_PRESET_VALUES = BACKGROUND_POSITION_PRESET_VALUES; exports.getAnchorClasses = getAnchorClasses; exports.formattingTransforms = formattingTransforms; exports.uiTransforms = uiTransforms; exports.hexToRgb = hexToRgb; exports.oklchToHexGamut = oklchToHexGamut; exports.featuresFromHex = featuresFromHex; exports.layoutTransforms = layoutTransforms; exports.mediaTransforms = mediaTransforms; exports.siteHeaderManifest = siteHeaderManifest; exports.siteFooterManifest = siteFooterManifest; exports.getBlockDefinition = getBlockDefinition;
5476
- //# sourceMappingURL=chunk-YYO3RIFO.js.map
5490
+ //# sourceMappingURL=chunk-6ERSDFTY.js.map