@gradial/aci 0.1.20-preview.3 → 0.1.21

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 (227) hide show
  1. package/README.md +48 -108
  2. package/bin/{aci → aci-darwin-arm64} +0 -0
  3. package/bin/aci.js +99 -6
  4. package/dist/assets/index.d.ts +3 -3
  5. package/dist/assets/index.js +3 -3
  6. package/dist/astro/index.d.ts +12 -3
  7. package/dist/astro/index.js +20 -5
  8. package/dist/content/assets.d.ts +17 -0
  9. package/dist/content/assets.js +65 -0
  10. package/dist/content/index.d.ts +1 -0
  11. package/dist/content/index.js +1 -0
  12. package/dist/define-component.d.ts +1 -2
  13. package/dist/define-component.js +73 -5
  14. package/dist/dev/content-watch.d.ts +37 -0
  15. package/dist/dev/content-watch.js +154 -0
  16. package/dist/dev/index.d.ts +24 -43
  17. package/dist/dev/index.js +4 -169
  18. package/dist/index.d.ts +14 -6
  19. package/dist/index.js +8 -9
  20. package/dist/next/asset-route.js +2 -2
  21. package/dist/next/config.d.ts +2 -2
  22. package/dist/next/config.js +5 -5
  23. package/dist/next/content-watch.js +6 -1
  24. package/dist/next/index.d.ts +2 -2
  25. package/dist/next/index.js +2 -2
  26. package/dist/next/middleware.d.ts +1 -0
  27. package/dist/next/middleware.js +49 -8
  28. package/dist/next/page.d.ts +1 -1
  29. package/dist/next/page.js +14 -12
  30. package/dist/next/render.d.ts +3 -3
  31. package/dist/next/render.js +11 -9
  32. package/dist/next/server.d.ts +12 -12
  33. package/dist/next/server.js +1 -1
  34. package/dist/preview/core.d.ts +5 -0
  35. package/dist/preview/core.js +1 -1
  36. package/dist/react/Media.d.ts +24 -0
  37. package/dist/react/Media.js +30 -0
  38. package/dist/react/Picture.d.ts +12 -0
  39. package/dist/react/Picture.js +11 -0
  40. package/dist/react/VideoPlayer.d.ts +13 -0
  41. package/dist/react/{GradialVideoPlayer.js → VideoPlayer.js} +6 -5
  42. package/dist/react/index.d.ts +333 -3
  43. package/dist/react/index.js +89 -3
  44. package/dist/registry.d.ts +2 -2
  45. package/dist/registry.js +3 -3
  46. package/dist/types/block-ref.d.ts +26 -0
  47. package/dist/types/block-ref.js +28 -0
  48. package/dist/types/component.d.ts +36 -32
  49. package/dist/types/config.d.ts +1 -1
  50. package/dist/types/image.d.ts +33 -20
  51. package/dist/types/image.js +42 -50
  52. package/dist/types/index.d.ts +1 -0
  53. package/dist/types/index.js +1 -0
  54. package/dist/types/link.d.ts +38 -0
  55. package/dist/types/link.js +58 -0
  56. package/dist/types/media.d.ts +16 -35
  57. package/dist/types/media.js +15 -84
  58. package/dist/types/renderer.d.ts +1 -1
  59. package/dist/types/rich-text.d.ts +40 -0
  60. package/dist/types/rich-text.js +39 -0
  61. package/dist/types/video.d.ts +7 -13
  62. package/dist/types/video.js +3 -3
  63. package/package.json +29 -76
  64. package/src/cli/compile-registry.mjs +120 -63
  65. package/src/cli/validate-content.mjs +38 -75
  66. package/src/types/block-ref.ts +74 -0
  67. package/src/types/image.ts +79 -60
  68. package/templates/astro/template/.aci.yaml +28 -0
  69. package/templates/astro/template/.storybook/main.ts +79 -0
  70. package/templates/astro/template/.storybook/manager.ts +6 -0
  71. package/templates/astro/template/.storybook/preview.ts +33 -0
  72. package/templates/astro/template/astro.config.mjs +37 -0
  73. package/templates/astro/template/package.json.tmpl +41 -0
  74. package/templates/astro/template/src/cms/contracts/layouts/index.ts +18 -0
  75. package/templates/astro/template/src/cms/registry.ts +28 -0
  76. package/templates/astro/template/src/components/chrome/Footer.astro +107 -0
  77. package/templates/astro/template/src/components/chrome/Header.astro +94 -0
  78. package/templates/astro/template/src/components/elements/AtomicBlock.astro +15 -0
  79. package/templates/astro/template/src/components/elements/AtomicBlocks.astro +16 -0
  80. package/templates/astro/template/src/components/elements/Button.astro +51 -0
  81. package/templates/astro/template/src/components/elements/ButtonBlock.astro +25 -0
  82. package/templates/astro/template/src/components/elements/Container.astro +11 -0
  83. package/templates/astro/template/src/components/elements/Icon.astro +31 -0
  84. package/templates/astro/template/src/components/elements/Logo.astro +29 -0
  85. package/templates/astro/template/src/components/elements/RemoteImage.astro +41 -0
  86. package/templates/astro/template/src/components/sections/ContainerSection.astro +32 -0
  87. package/templates/astro/template/src/components/sections/FeatureCard.astro +23 -0
  88. package/templates/astro/template/src/components/sections/FeatureGrid.astro +35 -0
  89. package/templates/astro/template/src/components/sections/HomeHero.astro +51 -0
  90. package/templates/astro/template/src/components/sections/StatsBar.astro +33 -0
  91. package/templates/astro/template/src/design-system/styles.css +399 -0
  92. package/templates/astro/template/src/design-system/tokens/colors.css +60 -0
  93. package/templates/astro/template/src/design-system/tokens/components.css +69 -0
  94. package/templates/astro/template/src/design-system/tokens/index.css +6 -0
  95. package/templates/astro/template/src/design-system/tokens/radii.css +5 -0
  96. package/templates/astro/template/src/design-system/tokens/shadows.css +5 -0
  97. package/templates/astro/template/src/design-system/tokens/spacing.css +13 -0
  98. package/templates/astro/template/src/design-system/tokens/typography.css +24 -0
  99. package/templates/astro/template/src/env.d.ts +1 -0
  100. package/templates/astro/template/src/fixtures/atomicBlocks.ts +33 -0
  101. package/templates/astro/template/src/fixtures/composition.ts +31 -0
  102. package/templates/astro/template/src/fixtures/index.ts +17 -0
  103. package/templates/astro/template/src/fixtures/sections.ts +39 -0
  104. package/templates/astro/template/src/layouts/SiteLayout.astro +30 -0
  105. package/templates/astro/template/src/pages/[...slug].astro +61 -0
  106. package/templates/astro/template/src/render/RenderPage.astro +66 -0
  107. package/templates/astro/template/src/stories/CompositionStoryFrame.astro +15 -0
  108. package/templates/astro/template/src/stories/HomeHero.stories.ts +24 -0
  109. package/templates/astro/template/src/stories/SectionStoryFrame.astro +16 -0
  110. package/templates/astro/template/src/stories/StoryDocFrame.astro +31 -0
  111. package/templates/astro/template/tsconfig.json +11 -0
  112. package/templates/common/.agents/AGENTS.md +37 -0
  113. package/templates/common/.agents/skills/aci/SKILL.md +162 -0
  114. package/templates/common/.agents/skills/authoring/SKILL.md +590 -0
  115. package/templates/common/.agents/skills/authoring/references/block-registry.md +151 -0
  116. package/templates/common/.agents/skills/authoring/references/contracts.md +153 -0
  117. package/templates/common/.agents/skills/authoring/references/design-system.md +171 -0
  118. package/templates/common/.agents/skills/authoring/references/image-assets.md +73 -0
  119. package/templates/common/.agents/skills/authoring/references/repo-structure.md +157 -0
  120. package/templates/common/.agents/skills/migration/SKILL.md +160 -0
  121. package/templates/common/.agents/skills/migration/references/analyzing-source.md +215 -0
  122. package/templates/common/.agents/skills/migration/references/component-migration.md +200 -0
  123. package/templates/common/.agents/skills/migration/references/selector-map.md +31 -0
  124. package/templates/common/.content/.gradial-dam/blobs/sha256/7f/bf/7fbfc7fe230ff12688c496f660119e41d9725c4504d82e310c15665c73c09292 +0 -0
  125. package/templates/common/.content/.gradial-dam/blobs/sha256/a0/f5/a0f506689de9b15a7055f70103a3f02cd3ba105771ae2de6754df2ede1210d3a +0 -0
  126. package/templates/common/.content/.gradial-dam/blobs/sha256/dd/b7/ddb7e9642be08317bcd4b2bd26b58ba8d0d34dd7239e03e684a4f3634fa3845b +0 -0
  127. package/templates/common/.content/.gradial-dam/blobs/sha256/fb/32/fb3260e8286ea8231ea1c77b9c0be92d6edd9026565731eb14cfdcfd6b1b75b3 +0 -0
  128. package/templates/common/.content/config/site.json +192 -0
  129. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/asset.json +9 -0
  130. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/editorial.json +14 -0
  131. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/governance.json +23 -0
  132. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/versions/v0001.json +37 -0
  133. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/asset.json +9 -0
  134. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/editorial.json +14 -0
  135. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/governance.json +23 -0
  136. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/versions/v0001.json +37 -0
  137. package/templates/common/.content/fragments/navbar/_index.json +25 -0
  138. package/templates/common/.content/fragments/site-footer/_index.json +62 -0
  139. package/templates/common/.content/pages/about/_index.json +51 -0
  140. package/templates/common/.content/pages/home/_index.json +112 -0
  141. package/templates/common/.content/schemas/site.schema.json +123 -0
  142. package/templates/common/README.md.tmpl +45 -0
  143. package/templates/common/contracts/components/button.contract.ts +19 -0
  144. package/templates/common/contracts/components/container.contract.ts +19 -0
  145. package/templates/common/contracts/components/featureCard.contract.ts +15 -0
  146. package/templates/common/contracts/components/featureGrid.contract.ts +16 -0
  147. package/templates/common/contracts/components/homeHero.contract.ts +36 -0
  148. package/templates/common/contracts/components/index.ts +21 -0
  149. package/templates/common/contracts/components/siteFooter.contract.ts +45 -0
  150. package/templates/common/contracts/components/siteNavigation.contract.ts +30 -0
  151. package/templates/common/contracts/components/statsBar.contract.ts +19 -0
  152. package/templates/common/design-system/styles.css +346 -0
  153. package/templates/common/design-system/tokens/colors.css +110 -0
  154. package/templates/common/design-system/tokens/components.css +86 -0
  155. package/templates/common/design-system/tokens/index.css +6 -0
  156. package/templates/common/design-system/tokens/radii.css +5 -0
  157. package/templates/common/design-system/tokens/shadows.css +9 -0
  158. package/templates/common/design-system/tokens/spacing.css +26 -0
  159. package/templates/common/design-system/tokens/typography.css +32 -0
  160. package/templates/common/eslint-rules/no-raw-tailwind-values.js +127 -0
  161. package/templates/common/public/assets/Dwire-model.png +0 -0
  162. package/templates/common/public/assets/bare-metal-logo.png +0 -0
  163. package/templates/common/public/assets/meridian-logo.svg +8 -0
  164. package/templates/common/public/assets/seattle.avif +0 -0
  165. package/templates/nextjs/template/.aci.yaml +26 -0
  166. package/templates/nextjs/template/.storybook/main.ts +13 -0
  167. package/templates/nextjs/template/.storybook/preview.ts +34 -0
  168. package/templates/nextjs/template/eslint.config.mjs +36 -0
  169. package/templates/nextjs/template/next-env.d.ts +6 -0
  170. package/templates/nextjs/template/next.config.ts +8 -0
  171. package/templates/nextjs/template/package.json.tmpl +46 -0
  172. package/templates/nextjs/template/postcss.config.mjs +7 -0
  173. package/templates/nextjs/template/src/app/[[...slug]]/page.tsx +8 -0
  174. package/templates/nextjs/template/src/app/gradial/assets/[releaseId]/[...path]/route.ts +31 -0
  175. package/templates/nextjs/template/src/app/layout.tsx +29 -0
  176. package/templates/nextjs/template/src/cms/contracts/components/button.contract.ts +19 -0
  177. package/templates/nextjs/template/src/cms/contracts/components/container.contract.ts +20 -0
  178. package/templates/nextjs/template/src/cms/contracts/components/homeHero.contract.ts +36 -0
  179. package/templates/nextjs/template/src/cms/contracts/components/index.ts +15 -0
  180. package/templates/nextjs/template/src/cms/contracts/components/siteFooter.contract.ts +45 -0
  181. package/templates/nextjs/template/src/cms/contracts/components/siteNavigation.contract.ts +30 -0
  182. package/templates/nextjs/template/src/cms/contracts/layouts/index.ts +16 -0
  183. package/templates/nextjs/template/src/cms/registry.ts +28 -0
  184. package/templates/nextjs/template/src/components/chrome/Footer.tsx +86 -0
  185. package/templates/nextjs/template/src/components/chrome/Header.tsx +74 -0
  186. package/templates/nextjs/template/src/components/elements/AtomicBlock.tsx +13 -0
  187. package/templates/nextjs/template/src/components/elements/Button.tsx +40 -0
  188. package/templates/nextjs/template/src/components/elements/ButtonBlock.tsx +18 -0
  189. package/templates/nextjs/template/src/components/elements/Container.tsx +14 -0
  190. package/templates/nextjs/template/src/components/elements/Icon.tsx +29 -0
  191. package/templates/nextjs/template/src/components/elements/Logo.tsx +38 -0
  192. package/templates/nextjs/template/src/components/sections/ContainerSection.tsx +28 -0
  193. package/templates/nextjs/template/src/components/sections/FeatureCard.tsx +25 -0
  194. package/templates/nextjs/template/src/components/sections/FeatureGrid.tsx +36 -0
  195. package/templates/nextjs/template/src/components/sections/HomeHero.tsx +62 -0
  196. package/templates/nextjs/template/src/components/sections/StatsBar.tsx +30 -0
  197. package/templates/nextjs/template/src/middleware.ts +4 -0
  198. package/templates/nextjs/template/src/stories/Button.stories.tsx +38 -0
  199. package/templates/nextjs/template/src/stories/Header.stories.tsx +30 -0
  200. package/templates/nextjs/template/src/stories/HomeHero.stories.tsx +33 -0
  201. package/templates/nextjs/template/tsconfig.json +23 -0
  202. package/templates/nextjs/template/vercel.json +6 -0
  203. package/dist/content/contract.d.ts +0 -83
  204. package/dist/content/contract.js +0 -104
  205. package/dist/content/tailwind-validator.d.ts +0 -6
  206. package/dist/content/tailwind-validator.js +0 -31
  207. package/dist/content/validation.d.ts +0 -108
  208. package/dist/content/validation.js +0 -183
  209. package/dist/react/GradialMedia.d.ts +0 -24
  210. package/dist/react/GradialMedia.js +0 -31
  211. package/dist/react/GradialPicture.d.ts +0 -14
  212. package/dist/react/GradialPicture.js +0 -30
  213. package/dist/react/GradialVideoPlayer.d.ts +0 -13
  214. package/dist/sveltekit/index.d.ts +0 -25
  215. package/dist/sveltekit/index.js +0 -66
  216. package/dist/sveltekit/preview.d.ts +0 -5
  217. package/dist/sveltekit/preview.js +0 -33
  218. package/src/types/component.ts +0 -49
  219. package/src/types/config.ts +0 -37
  220. package/src/types/data.ts +0 -47
  221. package/src/types/index.ts +0 -10
  222. package/src/types/layout.ts +0 -29
  223. package/src/types/media.ts +0 -125
  224. package/src/types/page.ts +0 -47
  225. package/src/types/render-mode.ts +0 -10
  226. package/src/types/renderer.ts +0 -83
  227. package/src/types/video.ts +0 -66
@@ -4,7 +4,7 @@ import { PREVIEW_TOKEN_COOKIE, PREVIEW_RELEASE_COOKIE, PREVIEW_HEADER, RELEASE_H
4
4
  const ROUTE_HEADER = 'x-gradial-route';
5
5
  const DISPATCH_HEADER = 'x-gradial-dispatch';
6
6
  export function createGradialMiddleware(config = {}) {
7
- return async function gradialMiddleware(request) {
7
+ return async function middleware(request) {
8
8
  const url = request.nextUrl;
9
9
  // ?leave_preview=1 → clear cookies, redirect to clean URL
10
10
  if (url.searchParams.get('leave_preview') === '1') {
@@ -22,6 +22,19 @@ export function createGradialMiddleware(config = {}) {
22
22
  if (!releaseId) {
23
23
  return NextResponse.next({ request: { headers: requestHeaders } });
24
24
  }
25
+ // Cross-deployment preview: if the token was staged on a different Vercel
26
+ // deployment, rewrite the request to that deployment. This keeps the browser
27
+ // on the production domain while the correct code runtime serves the request.
28
+ const rewriteTarget = preview ? previewRewriteTarget(request, preview, config) : null;
29
+ if (rewriteTarget) {
30
+ const response = NextResponse.rewrite(rewriteTarget, { request: { headers: requestHeaders } });
31
+ if (preview?.token && preview.isPreview) {
32
+ for (const cookie of createPreviewCookies(preview.token, releaseId)) {
33
+ response.cookies.set(cookie.name, cookie.value, cookie.options);
34
+ }
35
+ }
36
+ return response;
37
+ }
25
38
  requestHeaders.set(RELEASE_HEADER, releaseId);
26
39
  requestHeaders.set(ROUTE_HEADER, url.pathname);
27
40
  requestHeaders.set(DISPATCH_HEADER, 'ssr-page');
@@ -38,11 +51,32 @@ export function createGradialMiddleware(config = {}) {
38
51
  return response;
39
52
  };
40
53
  }
41
- export const config = {
42
- matcher: [
43
- '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
44
- ],
45
- };
54
+ function previewRewriteTarget(request, preview, config) {
55
+ const claims = preview.claims;
56
+ if (!claims?.deploymentId || !claims?.deploymentUrl || !preview.token) {
57
+ return null;
58
+ }
59
+ const currentDeploymentId = config.deploymentId || process.env.VERCEL_DEPLOYMENT_ID || '';
60
+ if (!currentDeploymentId || currentDeploymentId === claims.deploymentId) {
61
+ return null;
62
+ }
63
+ const base = buildDeploymentUrl(claims.deploymentUrl);
64
+ const target = new URL(request.nextUrl.pathname + request.nextUrl.search, base);
65
+ if (!target.searchParams.has('preview_token')) {
66
+ target.searchParams.set('preview_token', preview.token);
67
+ }
68
+ const bypass = config.deploymentProtectionBypass || process.env.VERCEL_DEPLOYMENT_PROTECTION_BYPASS;
69
+ if (bypass) {
70
+ target.searchParams.set('x-vercel-protection-bypass', bypass);
71
+ }
72
+ return target;
73
+ }
74
+ function buildDeploymentUrl(value) {
75
+ if (value.startsWith('http://') || value.startsWith('https://')) {
76
+ return value;
77
+ }
78
+ return `https://${value}`;
79
+ }
46
80
  function gradialHeaders(headers) {
47
81
  const next = new Headers(headers);
48
82
  next.delete(RELEASE_HEADER);
@@ -59,9 +93,9 @@ async function resolvePreviewFromRequest(request, config) {
59
93
  });
60
94
  if (!token)
61
95
  return null;
62
- const signKey = previewSignKey();
96
+ const signKey = config.previewSignKey || previewSignKey();
63
97
  if (!signKey) {
64
- console.warn('[gradial/mw] GRADIAL_PREVIEW_SIGN_KEY not set — preview tokens will be ignored');
98
+ console.warn('[aci/mw] GRADIAL_PREVIEW_SIGN_KEY not set — preview tokens will be ignored');
65
99
  return null;
66
100
  }
67
101
  return await resolvePreviewContext({ token, siteId: config.siteId || '', signKey });
@@ -143,3 +177,10 @@ function clampRelease(activeReleaseId, activeSequence, compatibility) {
143
177
  function edgeKeySegment(value) {
144
178
  return value.replace(/[^A-Za-z0-9_-]/g, '_');
145
179
  }
180
+ // Default matcher. _next/static is included so that cross-deployment previews
181
+ // can rewrite static assets to the staged deployment. _next/image is excluded
182
+ // because it is a generic optimization endpoint and does not carry code-specific
183
+ // assets in most configurations. Consumers can override this if needed.
184
+ export const config = {
185
+ matcher: ['/((?!_next/image|favicon.ico|\\.gradial-dam|api/baremetal-assets|gradial/assets).*)'],
186
+ };
@@ -16,7 +16,7 @@ export interface CreatePageOptions {
16
16
  * Usage in `src/app/[[...slug]]/page.tsx`:
17
17
  *
18
18
  * ```tsx
19
- * import { createPage } from '@gradial/aci/next/page';
19
+ * import { createPage } from '@gradial/aci/next';
20
20
  * import { registry } from '@/cms/registry';
21
21
  *
22
22
  * const page = createPage(registry);
package/dist/next/page.js CHANGED
@@ -10,7 +10,7 @@ import { renderBlocks } from './render.js';
10
10
  * Usage in `src/app/[[...slug]]/page.tsx`:
11
11
  *
12
12
  * ```tsx
13
- * import { createPage } from '@gradial/aci/next/page';
13
+ * import { createPage } from '@gradial/aci/next';
14
14
  * import { registry } from '@/cms/registry';
15
15
  *
16
16
  * const page = createPage(registry);
@@ -48,20 +48,22 @@ export function createPage(registry, options) {
48
48
  const route = await routeFromNextParams(params);
49
49
  try {
50
50
  const input = await getRenderInput(route);
51
- if (!input.page || input.page.status !== 'published')
51
+ if (!input.page)
52
52
  notFound();
53
53
  const layout = await getLayout(input.page.layout);
54
54
  const resolvedSlots = await resolveSlots(layout, input.page.regions || {}, (id) => getFragment(id));
55
- return (_jsx(_Fragment, { children: layout.slots.map((slot) => {
56
- const blocks = resolvedSlots[slot.name];
57
- if (!blocks?.length)
58
- return null;
59
- const extraProps = options?.slotProps?.(slot.name, input.page);
60
- if (slot.name === 'main') {
61
- return (_jsx("main", { id: "content-main", children: renderBlocks(blocks, registry, extraProps) }, "main"));
62
- }
63
- return (_jsx(Fragment, { children: renderBlocks(blocks, registry, extraProps) }, slot.name));
64
- }) }));
55
+ const renderedSlots = await Promise.all(layout.slots.map(async (slot) => {
56
+ const blocks = resolvedSlots[slot.name];
57
+ if (!blocks?.length)
58
+ return null;
59
+ const extraProps = options?.slotProps?.(slot.name, input.page);
60
+ const renderedBlocks = await renderBlocks(blocks, registry, extraProps);
61
+ if (slot.name === 'main') {
62
+ return (_jsx("main", { id: "content-main", children: renderedBlocks }, "main"));
63
+ }
64
+ return (_jsx(Fragment, { children: renderedBlocks }, slot.name));
65
+ }));
66
+ return _jsx(_Fragment, { children: renderedSlots.filter(Boolean) });
65
67
  }
66
68
  catch (error) {
67
69
  if (error instanceof PageNotFoundError)
@@ -1,5 +1,5 @@
1
1
  import type { ReactElement } from 'react';
2
- import type { Registry } from '../registry.js';
3
2
  import type { KernelPageBlock } from '../content/types.js';
4
- export declare function renderBlock(block: KernelPageBlock, registry: Registry, extraProps?: Record<string, unknown>): ReactElement | null;
5
- export declare function renderBlocks(blocks: readonly KernelPageBlock[], registry: Registry, extraProps?: Record<string, unknown>): (ReactElement | null)[];
3
+ import type { Registry } from '../registry.js';
4
+ export declare function renderBlock(block: KernelPageBlock, registry: Registry, extraProps?: Record<string, unknown>): Promise<ReactElement>;
5
+ export declare function renderBlocks(blocks: readonly KernelPageBlock[], registry: Registry, extraProps?: Record<string, unknown>): Promise<ReactElement[]>;
@@ -1,15 +1,17 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- export function renderBlock(block, registry, extraProps) {
3
- const entry = registry.find((r) => r.name === block.component);
2
+ export async function renderBlock(block, registry, extraProps) {
3
+ const entry = registry.find((r) => r.id === block.component);
4
4
  if (!entry) {
5
- if (process.env.NODE_ENV !== 'production') {
6
- return (_jsxs("div", { className: "mx-auto my-4 max-w-[var(--max-width-container)] rounded-card border-2 border-red-600 bg-red-50 px-5 py-4 font-mono text-sm leading-relaxed text-red-900", children: [_jsx("strong", { children: "Unknown block:" }), " ", _jsx("code", { children: block.component }), _jsx("br", {}), _jsxs("span", { className: "text-red-800 opacity-70", children: ["id: ", block.id] })] }, block.id));
7
- }
8
- return null;
5
+ return (_jsxs("div", { className: "mx-auto my-4 max-w-[var(--max-width-container)] rounded-card border-2 border-red-600 bg-red-50 px-5 py-4 font-mono text-sm leading-relaxed text-red-900", children: [_jsx("strong", { children: "Unknown block:" }), " ", _jsx("code", { children: block.component }), _jsx("br", {}), _jsxs("span", { className: "text-red-800 opacity-70", children: ["id: ", block.id] })] }, block.id));
9
6
  }
10
7
  const Component = entry.component;
11
- return _jsx(Component, { ...block.props, ...extraProps }, block.id);
8
+ const hasBlockSlots = !!entry.contract.blockSlots;
9
+ const componentProps = { ...block.props, ...extraProps };
10
+ if (hasBlockSlots) {
11
+ componentProps.renderChildren = (blocks) => renderBlocks(blocks, registry, extraProps);
12
+ }
13
+ return _jsx(Component, { ...componentProps }, block.id);
12
14
  }
13
- export function renderBlocks(blocks, registry, extraProps) {
14
- return blocks.map((block) => renderBlock(block, registry, extraProps));
15
+ export async function renderBlocks(blocks, registry, extraProps) {
16
+ return Promise.all(blocks.map((block) => renderBlock(block, registry, extraProps)));
15
17
  }
@@ -1,7 +1,7 @@
1
1
  import { FragmentNotFoundError, LayoutNotFoundError, PageNotFoundError } from '../content/provider.js';
2
2
  import type { RenderInput } from '../content/types.js';
3
3
  export { FragmentNotFoundError, PageNotFoundError, LayoutNotFoundError };
4
- export interface GradialFetchConfig {
4
+ export interface FetchConfig {
5
5
  siteId?: string;
6
6
  bucket?: string;
7
7
  keyPrefix?: string;
@@ -14,7 +14,7 @@ export interface GradialFetchConfig {
14
14
  edgeConfig?: string;
15
15
  deploymentId?: string;
16
16
  }
17
- export interface GradialRenderInput<TPage, TSite extends GradialSiteConfig = GradialSiteConfig> {
17
+ export interface ServerRenderInput<TPage, TSite extends SiteConfig = SiteConfig> {
18
18
  route: string;
19
19
  domain: string;
20
20
  locale: string;
@@ -22,16 +22,16 @@ export interface GradialRenderInput<TPage, TSite extends GradialSiteConfig = Gra
22
22
  page: TPage;
23
23
  fragments?: Record<string, unknown>;
24
24
  }
25
- export interface GradialSiteConfig {
25
+ export interface SiteConfig {
26
26
  domain?: string;
27
27
  defaultLocale?: string;
28
28
  }
29
- export declare function getPage<T = unknown>(route?: string, config?: GradialFetchConfig): Promise<T>;
30
- export declare function getSiteConfig<T extends GradialSiteConfig = GradialSiteConfig>(config?: GradialFetchConfig): Promise<T>;
31
- export declare function getFragment<T = unknown>(name: string, config?: GradialFetchConfig): Promise<T>;
32
- export declare function getLayout<T = unknown>(name: string, config?: GradialFetchConfig): Promise<T>;
33
- export declare function getRoutes(config?: GradialFetchConfig): Promise<string[]>;
34
- export declare function getRenderInput<TPage, TSite extends GradialSiteConfig = GradialSiteConfig>(route?: string, config?: GradialFetchConfig): Promise<GradialRenderInput<TPage, TSite>>;
29
+ export declare function getPage<T = unknown>(route?: string, config?: FetchConfig): Promise<T>;
30
+ export declare function getSiteConfig<T extends SiteConfig = SiteConfig>(config?: FetchConfig): Promise<T>;
31
+ export declare function getFragment<T = unknown>(name: string, config?: FetchConfig): Promise<T>;
32
+ export declare function getLayout<T = unknown>(name: string, config?: FetchConfig): Promise<T>;
33
+ export declare function getRoutes(config?: FetchConfig): Promise<string[]>;
34
+ export declare function getRenderInput<TPage, TSite extends SiteConfig = SiteConfig>(route?: string, config?: FetchConfig): Promise<ServerRenderInput<TPage, TSite>>;
35
35
  export declare function getPageRuntimeRenderInput(): Promise<RenderInput | null>;
36
36
  export { isPreviewMode } from './preview-mode.js';
37
37
  export declare function routeFromNextParams(params?: Promise<{
@@ -39,11 +39,11 @@ export declare function routeFromNextParams(params?: Promise<{
39
39
  }> | {
40
40
  slug?: string[];
41
41
  }): Promise<string>;
42
- export declare function generateGradialStaticParams(): Promise<Array<{
42
+ export declare function generateStaticParams(): Promise<Array<{
43
43
  slug?: string[];
44
44
  }>>;
45
45
  export declare class ReleaseAssetNotFoundError extends Error {
46
46
  constructor(releaseId: string, assetPath: string, cause?: unknown);
47
47
  }
48
- export declare function getReleaseAssetResponse(releaseId: string, assetPath: string, config?: GradialFetchConfig): Promise<Response>;
49
- export declare function resolveReleaseId(config?: GradialFetchConfig): Promise<string>;
48
+ export declare function getReleaseAssetResponse(releaseId: string, assetPath: string, config?: FetchConfig): Promise<Response>;
49
+ export declare function resolveReleaseId(config?: FetchConfig): Promise<string>;
@@ -84,7 +84,7 @@ export async function routeFromNextParams(params) {
84
84
  return '/';
85
85
  return `/${resolved.slug.join('/')}/`;
86
86
  }
87
- export async function generateGradialStaticParams() {
87
+ export async function generateStaticParams() {
88
88
  const { FileContentProvider } = await import('../providers/file.js');
89
89
  const provider = new FileContentProvider();
90
90
  const routes = await provider.listRoutes();
@@ -2,6 +2,10 @@ export interface PreviewClaims {
2
2
  scope?: string;
3
3
  releaseId?: string;
4
4
  siteId?: string;
5
+ codeDigest?: string;
6
+ contentSnapshotId?: string;
7
+ deploymentId?: string;
8
+ deploymentUrl?: string;
5
9
  expiresAt?: string;
6
10
  }
7
11
  export interface PreviewTokenSource {
@@ -18,6 +22,7 @@ export interface PreviewContext {
18
22
  isPreview: boolean;
19
23
  releaseId?: string;
20
24
  token?: string;
25
+ claims?: PreviewClaims;
21
26
  }
22
27
  export interface PreviewCookie {
23
28
  name: string;
@@ -63,7 +63,7 @@ export async function resolvePreviewContext(options) {
63
63
  if (!claims.expiresAt || Date.parse(claims.expiresAt) <= Date.now()) {
64
64
  return { isPreview: false };
65
65
  }
66
- return { isPreview: true, releaseId: claims.releaseId, token };
66
+ return { isPreview: true, releaseId: claims.releaseId, token, claims };
67
67
  }
68
68
  export function createPreviewCookies(token, releaseId) {
69
69
  const common = {
@@ -0,0 +1,24 @@
1
+ import { type CSSProperties, type ImgHTMLAttributes, type VideoHTMLAttributes } from 'react';
2
+ import type { Asset } from '../types/media.js';
3
+ export interface MediaProps {
4
+ /** The compiler-resolved media to render. */
5
+ media: Asset;
6
+ /** CSS class applied to the rendered element. */
7
+ className?: string;
8
+ /** Inline styles applied to the rendered element. */
9
+ style?: CSSProperties;
10
+ /** Loading strategy for images. Defaults to 'lazy'. */
11
+ loading?: 'eager' | 'lazy';
12
+ /** Additional image attributes (only applied when media is an image). */
13
+ imgProps?: Omit<ImgHTMLAttributes<HTMLImageElement>, 'src' | 'alt'>;
14
+ /** Additional video attributes (only applied when media is a video). */
15
+ videoProps?: Omit<VideoHTMLAttributes<HTMLVideoElement>, 'src' | 'poster' | 'width' | 'height'>;
16
+ }
17
+ /**
18
+ * Polymorphic media component — renders an Image or Video as the appropriate
19
+ * HTML element based on $type.
20
+ *
21
+ * - gradial.image → <img> with srcset via Picture
22
+ * - gradial.video → <video> via VideoPlayer
23
+ */
24
+ export declare function Media({ media, className, style, loading, imgProps, videoProps, }: MediaProps): import("react").FunctionComponentElement<import("./VideoPlayer.js").VideoPlayerProps> | import("react").FunctionComponentElement<import("./Picture.js").PictureProps>;
@@ -0,0 +1,30 @@
1
+ import { createElement } from 'react';
2
+ import { Picture } from './Picture.js';
3
+ import { VideoPlayer } from './VideoPlayer.js';
4
+ /**
5
+ * Polymorphic media component — renders an Image or Video as the appropriate
6
+ * HTML element based on $type.
7
+ *
8
+ * - gradial.image → <img> with srcset via Picture
9
+ * - gradial.video → <video> via VideoPlayer
10
+ */
11
+ export function Media({ media, className, style, loading = 'lazy', imgProps, videoProps, }) {
12
+ switch (media.$type) {
13
+ case 'gradial.video':
14
+ return createElement(VideoPlayer, {
15
+ video: media,
16
+ className,
17
+ style,
18
+ ...videoProps,
19
+ });
20
+ case 'gradial.image':
21
+ default:
22
+ return createElement(Picture, {
23
+ image: media,
24
+ className,
25
+ style,
26
+ loading,
27
+ ...imgProps,
28
+ });
29
+ }
30
+ }
@@ -0,0 +1,12 @@
1
+ import { type ImgHTMLAttributes } from 'react';
2
+ import { type Image } from '../types/image.js';
3
+ export interface PictureProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'src' | 'alt' | 'width' | 'height'> {
4
+ image: Image;
5
+ }
6
+ /**
7
+ * Renders an Image as a responsive <img> element.
8
+ *
9
+ * Delegates attribute computation to the shared `imageAttrs()` pure function
10
+ * so React, Astro, and Svelte all produce identical output.
11
+ */
12
+ export declare function Picture({ image, ...attrs }: PictureProps): import("react").DetailedReactHTMLElement<import("../types/image.js").ImageAttrs, HTMLElement>;
@@ -0,0 +1,11 @@
1
+ import { createElement } from 'react';
2
+ import { imageAttrs } from '../types/image.js';
3
+ /**
4
+ * Renders an Image as a responsive <img> element.
5
+ *
6
+ * Delegates attribute computation to the shared `imageAttrs()` pure function
7
+ * so React, Astro, and Svelte all produce identical output.
8
+ */
9
+ export function Picture({ image, ...attrs }) {
10
+ return createElement('img', imageAttrs(image, attrs));
11
+ }
@@ -0,0 +1,13 @@
1
+ import { type VideoHTMLAttributes } from 'react';
2
+ import type { Video } from '../types/video.js';
3
+ export interface VideoPlayerProps extends Omit<VideoHTMLAttributes<HTMLVideoElement>, 'src' | 'poster' | 'width' | 'height'> {
4
+ video: Video;
5
+ }
6
+ /**
7
+ * Renders a Video as a <video> element.
8
+ *
9
+ * - Uses the primary source from poster for the poster attribute.
10
+ * - Includes <source> elements for format variants when available.
11
+ * - Uses the src attribute on <video> when no source variants exist.
12
+ */
13
+ export declare function VideoPlayer({ video, ...attrs }: VideoPlayerProps): import("react").DetailedReactHTMLElement<Record<string, unknown>, HTMLElement>;
@@ -1,13 +1,14 @@
1
1
  import { createElement } from 'react';
2
+ import { primaryImageSource } from '../types/image.js';
2
3
  /**
3
- * Renders a GradialVideo as a <video> element.
4
+ * Renders a Video as a <video> element.
4
5
  *
5
- * - Uses poster.fallback.src for the poster attribute (single URL — browser limitation).
6
+ * - Uses the primary source from poster for the poster attribute.
6
7
  * - Includes <source> elements for format variants when available.
7
- * - Falls back to src attribute on <video> when no source variants exist.
8
+ * - Uses the src attribute on <video> when no source variants exist.
8
9
  */
9
- export function GradialVideoPlayer({ video, ...attrs }) {
10
- const posterSrc = video.poster?.fallback.src;
10
+ export function VideoPlayer({ video, ...attrs }) {
11
+ const posterSrc = video.poster ? primaryImageSource(video.poster).src : undefined;
11
12
  const hasSources = video.sources && video.sources.length > 0;
12
13
  const videoAttrs = {
13
14
  poster: posterSrc,