@gradial/aci 0.1.20-preview.2 → 0.1.20

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 (249) hide show
  1. package/README.md +48 -110
  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 +14 -3
  7. package/dist/astro/index.js +24 -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 +2 -0
  11. package/dist/content/index.js +2 -0
  12. package/dist/content/provider.d.ts +19 -0
  13. package/dist/content/provider.js +7 -0
  14. package/dist/content/resolve-slots.d.ts +9 -0
  15. package/dist/content/resolve-slots.js +24 -0
  16. package/dist/content/types.d.ts +1 -1
  17. package/dist/define-component.d.ts +1 -2
  18. package/dist/define-component.js +73 -11
  19. package/dist/define-layout.d.ts +2 -0
  20. package/dist/define-layout.js +3 -0
  21. package/dist/dev/content-watch.d.ts +37 -0
  22. package/dist/dev/content-watch.js +154 -0
  23. package/dist/dev/index.d.ts +24 -43
  24. package/dist/dev/index.js +4 -169
  25. package/dist/index.d.ts +14 -5
  26. package/dist/index.js +8 -8
  27. package/dist/next/asset-route.d.ts +2 -0
  28. package/dist/next/asset-route.js +12 -4
  29. package/dist/next/config.d.ts +2 -2
  30. package/dist/next/config.js +6 -6
  31. package/dist/next/content-watch.js +6 -1
  32. package/dist/next/index.d.ts +2 -2
  33. package/dist/next/index.js +2 -2
  34. package/dist/next/middleware.d.ts +7 -3
  35. package/dist/next/middleware.js +12 -7
  36. package/dist/next/page.d.ts +16 -15
  37. package/dist/next/page.js +30 -10
  38. package/dist/next/render.d.ts +5 -0
  39. package/dist/next/render.js +17 -0
  40. package/dist/next/root-layout.d.ts +4 -0
  41. package/dist/next/root-layout.js +5 -0
  42. package/dist/next/server.d.ts +14 -13
  43. package/dist/next/server.js +13 -3
  44. package/dist/providers/file.d.ts +2 -0
  45. package/dist/providers/file.js +61 -1
  46. package/dist/providers/s3.d.ts +1 -0
  47. package/dist/providers/s3.js +14 -1
  48. package/dist/react/Media.d.ts +24 -0
  49. package/dist/react/Media.js +30 -0
  50. package/dist/react/Picture.d.ts +12 -0
  51. package/dist/react/Picture.js +11 -0
  52. package/dist/react/VideoPlayer.d.ts +13 -0
  53. package/dist/react/{GradialVideoPlayer.js → VideoPlayer.js} +6 -5
  54. package/dist/react/index.d.ts +333 -3
  55. package/dist/react/index.js +89 -3
  56. package/dist/registry.d.ts +15 -0
  57. package/dist/registry.js +10 -0
  58. package/dist/testing/index.d.ts +3 -0
  59. package/dist/testing/index.js +15 -2
  60. package/dist/types/block-ref.d.ts +26 -0
  61. package/dist/types/block-ref.js +28 -0
  62. package/dist/types/component.d.ts +36 -41
  63. package/dist/types/config.d.ts +1 -2
  64. package/dist/types/image.d.ts +33 -20
  65. package/dist/types/image.js +42 -50
  66. package/dist/types/index.d.ts +1 -0
  67. package/dist/types/index.js +1 -0
  68. package/dist/types/link.d.ts +38 -0
  69. package/dist/types/link.js +58 -0
  70. package/dist/types/media.d.ts +16 -35
  71. package/dist/types/media.js +15 -84
  72. package/dist/types/page.d.ts +1 -2
  73. package/dist/types/render-mode.d.ts +0 -1
  74. package/dist/types/renderer.d.ts +1 -1
  75. package/dist/types/rich-text.d.ts +40 -0
  76. package/dist/types/rich-text.js +39 -0
  77. package/dist/types/video.d.ts +7 -13
  78. package/dist/types/video.js +3 -3
  79. package/package.json +32 -74
  80. package/src/cli/compile-registry.mjs +236 -59
  81. package/src/cli/validate-content.mjs +38 -75
  82. package/src/types/image.ts +79 -60
  83. package/templates/astro/template/.aci.yaml +27 -0
  84. package/templates/astro/template/.storybook/main.ts +79 -0
  85. package/templates/astro/template/.storybook/manager.ts +6 -0
  86. package/templates/astro/template/.storybook/preview.ts +33 -0
  87. package/templates/astro/template/astro.config.mjs +37 -0
  88. package/templates/astro/template/package.json.tmpl +41 -0
  89. package/templates/astro/template/src/cms/contracts/layouts/index.ts +18 -0
  90. package/templates/astro/template/src/cms/registry.ts +28 -0
  91. package/templates/astro/template/src/components/chrome/Footer.astro +107 -0
  92. package/templates/astro/template/src/components/chrome/Header.astro +94 -0
  93. package/templates/astro/template/src/components/elements/AtomicBlock.astro +15 -0
  94. package/templates/astro/template/src/components/elements/AtomicBlocks.astro +16 -0
  95. package/templates/astro/template/src/components/elements/Button.astro +51 -0
  96. package/templates/astro/template/src/components/elements/ButtonBlock.astro +25 -0
  97. package/templates/astro/template/src/components/elements/Container.astro +11 -0
  98. package/templates/astro/template/src/components/elements/Icon.astro +31 -0
  99. package/templates/astro/template/src/components/elements/Logo.astro +29 -0
  100. package/templates/astro/template/src/components/elements/RemoteImage.astro +41 -0
  101. package/templates/astro/template/src/components/sections/ContainerSection.astro +32 -0
  102. package/templates/astro/template/src/components/sections/FeatureCard.astro +23 -0
  103. package/templates/astro/template/src/components/sections/FeatureGrid.astro +35 -0
  104. package/templates/astro/template/src/components/sections/HomeHero.astro +51 -0
  105. package/templates/astro/template/src/components/sections/StatsBar.astro +33 -0
  106. package/templates/astro/template/src/design-system/styles.css +399 -0
  107. package/templates/astro/template/src/design-system/tokens/colors.css +60 -0
  108. package/templates/astro/template/src/design-system/tokens/components.css +69 -0
  109. package/templates/astro/template/src/design-system/tokens/index.css +6 -0
  110. package/templates/astro/template/src/design-system/tokens/radii.css +5 -0
  111. package/templates/astro/template/src/design-system/tokens/shadows.css +5 -0
  112. package/templates/astro/template/src/design-system/tokens/spacing.css +13 -0
  113. package/templates/astro/template/src/design-system/tokens/typography.css +24 -0
  114. package/templates/astro/template/src/env.d.ts +1 -0
  115. package/templates/astro/template/src/fixtures/atomicBlocks.ts +33 -0
  116. package/templates/astro/template/src/fixtures/composition.ts +31 -0
  117. package/templates/astro/template/src/fixtures/index.ts +17 -0
  118. package/templates/astro/template/src/fixtures/sections.ts +39 -0
  119. package/templates/astro/template/src/layouts/SiteLayout.astro +30 -0
  120. package/templates/astro/template/src/pages/[...slug].astro +61 -0
  121. package/templates/astro/template/src/render/RenderPage.astro +66 -0
  122. package/templates/astro/template/src/stories/CompositionStoryFrame.astro +15 -0
  123. package/templates/astro/template/src/stories/HomeHero.stories.ts +24 -0
  124. package/templates/astro/template/src/stories/SectionStoryFrame.astro +16 -0
  125. package/templates/astro/template/src/stories/StoryDocFrame.astro +31 -0
  126. package/templates/astro/template/tsconfig.json +11 -0
  127. package/templates/common/.agents/AGENTS.md +37 -0
  128. package/templates/common/.agents/skills/aci/SKILL.md +162 -0
  129. package/templates/common/.agents/skills/authoring/SKILL.md +590 -0
  130. package/templates/common/.agents/skills/authoring/references/block-registry.md +151 -0
  131. package/templates/common/.agents/skills/authoring/references/contracts.md +153 -0
  132. package/templates/common/.agents/skills/authoring/references/design-system.md +171 -0
  133. package/templates/common/.agents/skills/authoring/references/image-assets.md +73 -0
  134. package/templates/common/.agents/skills/authoring/references/repo-structure.md +157 -0
  135. package/templates/common/.agents/skills/migration/SKILL.md +160 -0
  136. package/templates/common/.agents/skills/migration/references/analyzing-source.md +215 -0
  137. package/templates/common/.agents/skills/migration/references/component-migration.md +200 -0
  138. package/templates/common/.agents/skills/migration/references/selector-map.md +31 -0
  139. package/templates/common/.content/.gradial-dam/blobs/sha256/7f/bf/7fbfc7fe230ff12688c496f660119e41d9725c4504d82e310c15665c73c09292 +0 -0
  140. package/templates/common/.content/.gradial-dam/blobs/sha256/a0/f5/a0f506689de9b15a7055f70103a3f02cd3ba105771ae2de6754df2ede1210d3a +0 -0
  141. package/templates/common/.content/.gradial-dam/blobs/sha256/dd/b7/ddb7e9642be08317bcd4b2bd26b58ba8d0d34dd7239e03e684a4f3634fa3845b +0 -0
  142. package/templates/common/.content/.gradial-dam/blobs/sha256/fb/32/fb3260e8286ea8231ea1c77b9c0be92d6edd9026565731eb14cfdcfd6b1b75b3 +0 -0
  143. package/templates/common/.content/config/site.json +192 -0
  144. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/asset.json +9 -0
  145. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/editorial.json +14 -0
  146. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/governance.json +23 -0
  147. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/versions/v0001.json +37 -0
  148. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/asset.json +9 -0
  149. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/editorial.json +14 -0
  150. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/governance.json +23 -0
  151. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/versions/v0001.json +37 -0
  152. package/templates/common/.content/fragments/navbar/_index.json +25 -0
  153. package/templates/common/.content/fragments/site-footer/_index.json +62 -0
  154. package/templates/common/.content/pages/about/_index.json +51 -0
  155. package/templates/common/.content/pages/home/_index.json +112 -0
  156. package/templates/common/.content/schemas/site.schema.json +123 -0
  157. package/templates/common/README.md.tmpl +45 -0
  158. package/templates/common/contracts/components/button.contract.ts +19 -0
  159. package/templates/common/contracts/components/container.contract.ts +19 -0
  160. package/templates/common/contracts/components/featureCard.contract.ts +15 -0
  161. package/templates/common/contracts/components/featureGrid.contract.ts +16 -0
  162. package/templates/common/contracts/components/homeHero.contract.ts +36 -0
  163. package/templates/common/contracts/components/index.ts +21 -0
  164. package/templates/common/contracts/components/siteFooter.contract.ts +45 -0
  165. package/templates/common/contracts/components/siteNavigation.contract.ts +30 -0
  166. package/templates/common/contracts/components/statsBar.contract.ts +19 -0
  167. package/templates/common/design-system/styles.css +346 -0
  168. package/templates/common/design-system/tokens/colors.css +110 -0
  169. package/templates/common/design-system/tokens/components.css +86 -0
  170. package/templates/common/design-system/tokens/index.css +6 -0
  171. package/templates/common/design-system/tokens/radii.css +5 -0
  172. package/templates/common/design-system/tokens/shadows.css +9 -0
  173. package/templates/common/design-system/tokens/spacing.css +26 -0
  174. package/templates/common/design-system/tokens/typography.css +32 -0
  175. package/templates/common/eslint-rules/no-raw-tailwind-values.js +127 -0
  176. package/templates/common/public/assets/Dwire-model.png +0 -0
  177. package/templates/common/public/assets/bare-metal-logo.png +0 -0
  178. package/templates/common/public/assets/meridian-logo.svg +8 -0
  179. package/templates/common/public/assets/seattle.avif +0 -0
  180. package/templates/nextjs/template/.aci.yaml +25 -0
  181. package/templates/nextjs/template/.storybook/main.ts +13 -0
  182. package/templates/nextjs/template/.storybook/preview.ts +34 -0
  183. package/templates/nextjs/template/eslint.config.mjs +36 -0
  184. package/templates/nextjs/template/next-env.d.ts +6 -0
  185. package/templates/nextjs/template/next.config.ts +8 -0
  186. package/templates/nextjs/template/package.json.tmpl +46 -0
  187. package/templates/nextjs/template/postcss.config.mjs +7 -0
  188. package/templates/nextjs/template/src/app/[[...slug]]/page.tsx +8 -0
  189. package/templates/nextjs/template/src/app/gradial/assets/[releaseId]/[...path]/route.ts +31 -0
  190. package/templates/nextjs/template/src/app/layout.tsx +29 -0
  191. package/templates/nextjs/template/src/cms/contracts/components/button.contract.ts +19 -0
  192. package/templates/nextjs/template/src/cms/contracts/components/container.contract.ts +20 -0
  193. package/templates/nextjs/template/src/cms/contracts/components/homeHero.contract.ts +36 -0
  194. package/templates/nextjs/template/src/cms/contracts/components/index.ts +15 -0
  195. package/templates/nextjs/template/src/cms/contracts/components/siteFooter.contract.ts +45 -0
  196. package/templates/nextjs/template/src/cms/contracts/components/siteNavigation.contract.ts +30 -0
  197. package/templates/nextjs/template/src/cms/contracts/layouts/index.ts +16 -0
  198. package/templates/nextjs/template/src/cms/registry.ts +28 -0
  199. package/templates/nextjs/template/src/components/chrome/Footer.tsx +86 -0
  200. package/templates/nextjs/template/src/components/chrome/Header.tsx +74 -0
  201. package/templates/nextjs/template/src/components/elements/AtomicBlock.tsx +13 -0
  202. package/templates/nextjs/template/src/components/elements/Button.tsx +40 -0
  203. package/templates/nextjs/template/src/components/elements/ButtonBlock.tsx +18 -0
  204. package/templates/nextjs/template/src/components/elements/Container.tsx +14 -0
  205. package/templates/nextjs/template/src/components/elements/Icon.tsx +29 -0
  206. package/templates/nextjs/template/src/components/elements/Logo.tsx +38 -0
  207. package/templates/nextjs/template/src/components/sections/ContainerSection.tsx +28 -0
  208. package/templates/nextjs/template/src/components/sections/FeatureCard.tsx +25 -0
  209. package/templates/nextjs/template/src/components/sections/FeatureGrid.tsx +36 -0
  210. package/templates/nextjs/template/src/components/sections/HomeHero.tsx +62 -0
  211. package/templates/nextjs/template/src/components/sections/StatsBar.tsx +30 -0
  212. package/templates/nextjs/template/src/middleware.ts +4 -0
  213. package/templates/nextjs/template/src/stories/Button.stories.tsx +38 -0
  214. package/templates/nextjs/template/src/stories/Header.stories.tsx +30 -0
  215. package/templates/nextjs/template/src/stories/HomeHero.stories.tsx +33 -0
  216. package/templates/nextjs/template/tsconfig.json +23 -0
  217. package/templates/nextjs/template/vercel.json +6 -0
  218. package/dist/content/cache.test.d.ts +0 -1
  219. package/dist/content/cache.test.js +0 -86
  220. package/dist/content/contract.d.ts +0 -83
  221. package/dist/content/contract.js +0 -104
  222. package/dist/content/tailwind-validator.d.ts +0 -6
  223. package/dist/content/tailwind-validator.js +0 -31
  224. package/dist/content/validation.d.ts +0 -108
  225. package/dist/content/validation.js +0 -184
  226. package/dist/next/preview-banner.d.ts +0 -4
  227. package/dist/next/preview-banner.js +0 -51
  228. package/dist/next/preview.d.ts +0 -7
  229. package/dist/next/preview.js +0 -37
  230. package/dist/react/GradialMedia.d.ts +0 -24
  231. package/dist/react/GradialMedia.js +0 -31
  232. package/dist/react/GradialPicture.d.ts +0 -14
  233. package/dist/react/GradialPicture.js +0 -30
  234. package/dist/react/GradialVideoPlayer.d.ts +0 -13
  235. package/dist/sveltekit/index.d.ts +0 -23
  236. package/dist/sveltekit/index.js +0 -62
  237. package/dist/sveltekit/preview.d.ts +0 -5
  238. package/dist/sveltekit/preview.js +0 -33
  239. package/src/cli/verify-renderer.mjs +0 -73
  240. package/src/types/component.ts +0 -59
  241. package/src/types/config.ts +0 -38
  242. package/src/types/data.ts +0 -47
  243. package/src/types/index.ts +0 -10
  244. package/src/types/layout.ts +0 -29
  245. package/src/types/media.ts +0 -125
  246. package/src/types/page.ts +0 -48
  247. package/src/types/render-mode.ts +0 -18
  248. package/src/types/renderer.ts +0 -83
  249. package/src/types/video.ts +0 -66
@@ -1,86 +0,0 @@
1
- import { describe, it, expect, beforeEach } from '@jest/globals';
2
- import { getCachedSiteConfig, getCachedManifest, clearProviderCache, getCacheStats, resetCacheStats } from './cache.js';
3
- describe('Content Cache', () => {
4
- let mockProvider;
5
- let getSiteConfigCallCount = 0;
6
- let manifestCallCount = 0;
7
- beforeEach(() => {
8
- getSiteConfigCallCount = 0;
9
- manifestCallCount = 0;
10
- resetCacheStats();
11
- mockProvider = {
12
- getSiteConfig: async () => {
13
- getSiteConfigCallCount++;
14
- return { title: 'Test Site' };
15
- },
16
- manifest: async () => {
17
- manifestCallCount++;
18
- return {
19
- routes: {},
20
- fragments: {},
21
- siteConfigRef: 'site.json'
22
- };
23
- },
24
- getPage: async () => ({}),
25
- getFragment: async () => ({}),
26
- listRoutes: async () => []
27
- };
28
- });
29
- it('should cache siteConfig across multiple calls', async () => {
30
- const result1 = await getCachedSiteConfig(mockProvider);
31
- const result2 = await getCachedSiteConfig(mockProvider);
32
- expect(getSiteConfigCallCount).toBe(1); // Only called once
33
- expect(result1).toEqual(result2);
34
- const stats = getCacheStats();
35
- expect(stats.siteConfig.hits).toBe(1);
36
- expect(stats.siteConfig.misses).toBe(1);
37
- });
38
- it('should cache manifest across multiple calls', async () => {
39
- const result1 = await getCachedManifest(mockProvider);
40
- const result2 = await getCachedManifest(mockProvider);
41
- expect(manifestCallCount).toBe(1); // Only called once
42
- expect(result1).toEqual(result2);
43
- const stats = getCacheStats();
44
- expect(stats.manifest.hits).toBe(1);
45
- expect(stats.manifest.misses).toBe(1);
46
- });
47
- it('should clear cache for a provider', async () => {
48
- await getCachedSiteConfig(mockProvider);
49
- expect(getSiteConfigCallCount).toBe(1);
50
- clearProviderCache(mockProvider);
51
- await getCachedSiteConfig(mockProvider);
52
- expect(getSiteConfigCallCount).toBe(2); // Called again after clear
53
- const stats = getCacheStats();
54
- expect(stats.siteConfig.misses).toBe(2);
55
- });
56
- it('should not cache rejected promises', async () => {
57
- const errorProvider = {
58
- getSiteConfig: async () => {
59
- getSiteConfigCallCount++;
60
- throw new Error('S3 timeout');
61
- },
62
- getPage: async () => ({}),
63
- getFragment: async () => ({}),
64
- listRoutes: async () => []
65
- };
66
- await expect(getCachedSiteConfig(errorProvider)).rejects.toThrow('S3 timeout');
67
- expect(getSiteConfigCallCount).toBe(1);
68
- // Second call should retry (not cached)
69
- await expect(getCachedSiteConfig(errorProvider)).rejects.toThrow('S3 timeout');
70
- expect(getSiteConfigCallCount).toBe(2);
71
- });
72
- it('should cache separately per provider instance', async () => {
73
- const provider2 = {
74
- getSiteConfig: async () => ({ title: 'Site 2' }),
75
- getPage: async () => ({}),
76
- getFragment: async () => ({}),
77
- listRoutes: async () => []
78
- };
79
- const result1 = await getCachedSiteConfig(mockProvider);
80
- const result2 = await getCachedSiteConfig(provider2);
81
- expect(result1).toEqual({ title: 'Test Site' });
82
- expect(result2).toEqual({ title: 'Site 2' });
83
- const stats = getCacheStats();
84
- expect(stats.siteConfig.misses).toBe(2); // Both are cache misses
85
- });
86
- });
@@ -1,83 +0,0 @@
1
- export declare const themeValues: readonly ["auto", "light", "dark"];
2
- export declare const buttonVariantValues: readonly ["primary", "secondary", "tertiary", "outline", "ghost"];
3
- export declare const iconPositionValues: readonly ["before", "after"];
4
- export type ContractField = {
5
- kind: 'array';
6
- items: ContractField;
7
- optional?: boolean;
8
- } | {
9
- kind: 'enum';
10
- values: readonly [string, ...string[]];
11
- optional?: boolean;
12
- } | {
13
- kind: 'atomicBlocks';
14
- optional?: boolean;
15
- } | {
16
- kind: 'boolean';
17
- optional?: boolean;
18
- } | {
19
- kind: 'className';
20
- optional?: boolean;
21
- } | {
22
- kind: 'componentClassName';
23
- optional?: boolean;
24
- } | {
25
- kind: 'image';
26
- optional?: boolean;
27
- } | {
28
- kind: 'object';
29
- fields: Record<string, ContractField>;
30
- optional?: boolean;
31
- } | {
32
- kind: 'richText';
33
- optional?: boolean;
34
- } | {
35
- kind: 'string';
36
- minLength?: number;
37
- optional?: boolean;
38
- };
39
- export interface BlockContract {
40
- component: string;
41
- displayName: string;
42
- description: string;
43
- props: Record<string, ContractField>;
44
- }
45
- export interface AtomicBlockContract extends BlockContract {
46
- }
47
- export declare const stringField: (options?: {
48
- minLength?: number;
49
- optional?: boolean;
50
- }) => ContractField;
51
- export declare const booleanField: (options?: {
52
- optional?: boolean;
53
- }) => ContractField;
54
- export declare const imageField: (options?: {
55
- optional?: boolean;
56
- }) => ContractField;
57
- export declare const enumField: (values: readonly [string, ...string[]], options?: {
58
- optional?: boolean;
59
- }) => ContractField;
60
- export declare const arrayField: (items: ContractField, options?: {
61
- optional?: boolean;
62
- }) => ContractField;
63
- export declare const objectField: (fields: Record<string, ContractField>, options?: {
64
- optional?: boolean;
65
- }) => ContractField;
66
- export declare const richTextField: (options?: {
67
- optional?: boolean;
68
- }) => ContractField;
69
- export declare const atomicBlocksField: (options?: {
70
- optional?: boolean;
71
- }) => ContractField;
72
- export declare const classNameField: (options?: {
73
- optional?: boolean;
74
- }) => ContractField;
75
- export declare const componentClassNameField: (options?: {
76
- optional?: boolean;
77
- }) => ContractField;
78
- export declare const defaultAtomicBlockContracts: AtomicBlockContract[];
79
- export declare const defaultBlockContracts: BlockContract[];
80
- export declare const blockContracts: BlockContract[];
81
- export declare const atomicBlockContracts: AtomicBlockContract[];
82
- export declare const supportedBlockComponents: string[];
83
- export declare const supportedAtomicBlockComponents: string[];
@@ -1,104 +0,0 @@
1
- export const themeValues = ['auto', 'light', 'dark'];
2
- export const buttonVariantValues = ['primary', 'secondary', 'tertiary', 'outline', 'ghost'];
3
- export const iconPositionValues = ['before', 'after'];
4
- export const stringField = (options = {}) => ({
5
- kind: 'string',
6
- ...options,
7
- });
8
- export const booleanField = (options = {}) => ({
9
- kind: 'boolean',
10
- ...options,
11
- });
12
- export const imageField = (options = {}) => ({
13
- kind: 'image',
14
- ...options,
15
- });
16
- export const enumField = (values, options = {}) => ({
17
- kind: 'enum',
18
- values,
19
- ...options,
20
- });
21
- export const arrayField = (items, options = {}) => ({
22
- kind: 'array',
23
- items,
24
- ...options,
25
- });
26
- export const objectField = (fields, options = {}) => ({
27
- kind: 'object',
28
- fields,
29
- ...options,
30
- });
31
- export const richTextField = (options = {}) => ({
32
- kind: 'richText',
33
- ...options,
34
- });
35
- export const atomicBlocksField = (options = {}) => ({
36
- kind: 'atomicBlocks',
37
- ...options,
38
- });
39
- export const classNameField = (options = {}) => ({
40
- kind: 'className',
41
- ...options,
42
- });
43
- export const componentClassNameField = (options = {}) => ({
44
- kind: 'componentClassName',
45
- ...options,
46
- });
47
- const themeFields = {
48
- theme: enumField(themeValues, { optional: true }),
49
- className: componentClassNameField({ optional: true }),
50
- };
51
- export const defaultAtomicBlockContracts = [
52
- {
53
- component: 'button',
54
- displayName: 'Button',
55
- description: 'Inline link styled as a button.',
56
- props: {
57
- label: stringField({ minLength: 1 }),
58
- href: stringField({ minLength: 1 }),
59
- variant: enumField(buttonVariantValues, { optional: true }),
60
- newWindow: booleanField({ optional: true }),
61
- icon: stringField({ optional: true }),
62
- iconPosition: enumField(iconPositionValues, { optional: true }),
63
- className: componentClassNameField({ optional: true }),
64
- },
65
- },
66
- ];
67
- export const defaultBlockContracts = [
68
- {
69
- component: 'home_hero',
70
- displayName: 'Home Hero',
71
- description: 'Full-width hero section with headline, description, CTA, and image.',
72
- props: {
73
- eyebrow: stringField({ optional: true }),
74
- headline: stringField({ minLength: 1 }),
75
- description: stringField({ optional: true }),
76
- ctaLabel: stringField({ minLength: 1 }),
77
- ctaHref: stringField({ minLength: 1 }),
78
- image: imageField(),
79
- },
80
- },
81
- {
82
- component: 'container',
83
- displayName: 'Container',
84
- description: 'Themed section wrapper that renders a stack of atomic content blocks.',
85
- props: {
86
- ...themeFields,
87
- blocks: atomicBlocksField(),
88
- },
89
- },
90
- {
91
- component: 'ssr_probe',
92
- displayName: 'SSR Probe',
93
- description: 'Server-rendered proof section used by render/publish smoke tests.',
94
- props: {
95
- label: stringField({ optional: true }),
96
- message: stringField({ optional: true }),
97
- mode: stringField({ optional: true }),
98
- },
99
- },
100
- ];
101
- export const blockContracts = defaultBlockContracts;
102
- export const atomicBlockContracts = defaultAtomicBlockContracts;
103
- export const supportedBlockComponents = defaultBlockContracts.map((block) => block.component);
104
- export const supportedAtomicBlockComponents = defaultAtomicBlockContracts.map((block) => block.component);
@@ -1,6 +0,0 @@
1
- export interface ClassNameValidationResult {
2
- valid: boolean;
3
- invalidClasses: string[];
4
- }
5
- export declare function validateContentClassName(value: string): ClassNameValidationResult;
6
- export declare function validateComponentClassName(value: string): ClassNameValidationResult;
@@ -1,31 +0,0 @@
1
- const MODIFIER_PATTERN = /^(!)?(?:(?:hover|focus|focus-within|focus-visible|active|disabled|visited|checked|first|last|odd|even|sm|md|lg|xl|2xl|dark|light|motion-safe|motion-reduce|portrait|landscape|print|rtl|ltr|open|placeholder|before|after|first-line|first-letter|selection|marker|group-hover|group-focus|peer-hover|peer-focus|has|not|aria-\w+|data-\w+):)*/;
2
- const RAW_VALUE_PATTERN = /\[(?:#|.*?\d+(?:px|rem|em|vh|vw|dvh|dvw|svh|svw|ch|ex|cap|ic|lh|rlh|cm|mm|in|pt|pc|%))/;
3
- function parseToken(token) {
4
- return token.replace(MODIFIER_PATTERN, '');
5
- }
6
- function hasArbitraryBracket(bare) {
7
- return bare.includes('[');
8
- }
9
- function hasRawArbitraryValue(bare) {
10
- if (!hasArbitraryBracket(bare)) {
11
- return false;
12
- }
13
- return RAW_VALUE_PATTERN.test(bare);
14
- }
15
- function validate(value, isInvalid) {
16
- const tokens = value.trim().split(/\s+/).filter(Boolean);
17
- const invalidClasses = [];
18
- for (const token of tokens) {
19
- const bare = parseToken(token);
20
- if (isInvalid(bare)) {
21
- invalidClasses.push(token);
22
- }
23
- }
24
- return { valid: invalidClasses.length === 0, invalidClasses };
25
- }
26
- export function validateContentClassName(value) {
27
- return validate(value, hasArbitraryBracket);
28
- }
29
- export function validateComponentClassName(value) {
30
- return validate(value, hasRawArbitraryValue);
31
- }
@@ -1,108 +0,0 @@
1
- import { z } from 'zod';
2
- import { type AtomicBlockContract, type BlockContract, type ContractField } from './contract.js';
3
- import type { KernelPage, KernelSiteConfig } from './types.js';
4
- export interface ContentValidationContracts {
5
- blockContracts?: readonly BlockContract[];
6
- atomicBlockContracts?: readonly AtomicBlockContract[];
7
- }
8
- export interface ContentSchemas {
9
- siteConfigSchema: z.ZodTypeAny;
10
- atomicBlockSchema: z.ZodTypeAny;
11
- pageBlockSchema: z.ZodTypeAny;
12
- pageSchema: z.ZodTypeAny;
13
- schemaFromContractField(field: ContractField): z.ZodTypeAny;
14
- schemaFromContractFields(fields: Record<string, ContractField>): z.ZodTypeAny;
15
- parseKernelSiteConfig(value: unknown, source?: string): KernelSiteConfig;
16
- parseKernelPage(value: unknown, source?: string): KernelPage;
17
- }
18
- export declare const linkSchema: z.ZodObject<{
19
- id: z.ZodString;
20
- label: z.ZodString;
21
- href: z.ZodString;
22
- }, z.core.$loose>;
23
- export declare const imageSchema: z.ZodObject<{
24
- src: z.ZodString;
25
- alt: z.ZodString;
26
- }, z.core.$loose>;
27
- export declare const optionalImageSchema: z.ZodObject<{
28
- src: z.ZodString;
29
- alt: z.ZodOptional<z.ZodString>;
30
- }, z.core.$loose>;
31
- export declare const siteConfigSchema: z.ZodObject<{
32
- id: z.ZodString;
33
- $type: z.ZodLiteral<"site">;
34
- status: z.ZodString;
35
- title: z.ZodString;
36
- domain: z.ZodString;
37
- defaultLocale: z.ZodString;
38
- brandHref: z.ZodOptional<z.ZodString>;
39
- brandLogo: z.ZodOptional<z.ZodObject<{
40
- src: z.ZodString;
41
- alt: z.ZodOptional<z.ZodString>;
42
- }, z.core.$loose>>;
43
- navigation: z.ZodOptional<z.ZodArray<z.ZodObject<{
44
- id: z.ZodString;
45
- label: z.ZodString;
46
- href: z.ZodString;
47
- }, z.core.$loose>>>;
48
- utilities: z.ZodOptional<z.ZodArray<z.ZodObject<{
49
- variant: z.ZodOptional<z.ZodEnum<{
50
- primary: "primary";
51
- secondary: "secondary";
52
- tertiary: "tertiary";
53
- outline: "outline";
54
- ghost: "ghost";
55
- }>>;
56
- id: z.ZodString;
57
- label: z.ZodString;
58
- href: z.ZodString;
59
- }, z.core.$loose>>>;
60
- promo: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
61
- footer: z.ZodOptional<z.ZodObject<{
62
- columns: z.ZodOptional<z.ZodArray<z.ZodObject<{
63
- id: z.ZodString;
64
- title: z.ZodOptional<z.ZodString>;
65
- groups: z.ZodOptional<z.ZodArray<z.ZodObject<{
66
- id: z.ZodString;
67
- title: z.ZodString;
68
- links: z.ZodArray<z.ZodObject<{
69
- id: z.ZodString;
70
- label: z.ZodString;
71
- href: z.ZodString;
72
- }, z.core.$loose>>;
73
- }, z.core.$loose>>>;
74
- links: z.ZodOptional<z.ZodArray<z.ZodObject<{
75
- id: z.ZodString;
76
- label: z.ZodString;
77
- href: z.ZodString;
78
- }, z.core.$loose>>>;
79
- }, z.core.$loose>>>;
80
- social: z.ZodOptional<z.ZodArray<z.ZodObject<{
81
- icon: z.ZodOptional<z.ZodString>;
82
- id: z.ZodString;
83
- label: z.ZodString;
84
- href: z.ZodString;
85
- }, z.core.$loose>>>;
86
- legalLinks: z.ZodOptional<z.ZodArray<z.ZodObject<{
87
- id: z.ZodString;
88
- label: z.ZodString;
89
- href: z.ZodString;
90
- }, z.core.$loose>>>;
91
- copyright: z.ZodOptional<z.ZodString>;
92
- }, z.core.$loose>>;
93
- seo: z.ZodOptional<z.ZodObject<{
94
- title: z.ZodOptional<z.ZodString>;
95
- description: z.ZodOptional<z.ZodString>;
96
- siteName: z.ZodOptional<z.ZodString>;
97
- }, z.core.$loose>>;
98
- }, z.core.$loose>;
99
- export declare function createContentSchemas(contracts?: ContentValidationContracts): ContentSchemas;
100
- export declare function formatZodError(source: string, error: z.ZodError): string;
101
- export declare function parseWithSchema(schema: z.ZodTypeAny, value: unknown, source: string): unknown;
102
- export declare const atomicBlockSchema: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
103
- export declare const pageBlockSchema: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
104
- export declare const pageSchema: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
105
- export declare const schemaFromContractField: (field: ContractField) => z.ZodTypeAny;
106
- export declare const schemaFromContractFields: (fields: Record<string, ContractField>) => z.ZodTypeAny;
107
- export declare const parseKernelSiteConfig: (value: unknown, source?: string) => KernelSiteConfig;
108
- export declare const parseKernelPage: (value: unknown, source?: string) => KernelPage;
@@ -1,184 +0,0 @@
1
- import { z } from 'zod';
2
- import { defaultAtomicBlockContracts, defaultBlockContracts, } from './contract.js';
3
- import { validateContentClassName, validateComponentClassName } from './tailwind-validator.js';
4
- const linkFields = {
5
- id: z.string().min(1),
6
- label: z.string().min(1),
7
- href: z.string().min(1),
8
- };
9
- export const linkSchema = z.looseObject(linkFields);
10
- export const imageSchema = z.looseObject({
11
- src: z.string().min(1),
12
- alt: z.string().min(1),
13
- });
14
- export const optionalImageSchema = z.looseObject({
15
- src: z.string().min(1),
16
- alt: z.string().optional(),
17
- });
18
- export const siteConfigSchema = z.looseObject({
19
- id: z.string().min(1),
20
- $type: z.literal('site'),
21
- status: z.string().min(1),
22
- title: z.string().min(1),
23
- domain: z.string().min(1),
24
- defaultLocale: z.string().min(1),
25
- brandHref: z.string().optional(),
26
- brandLogo: optionalImageSchema.optional(),
27
- navigation: z.array(linkSchema).optional(),
28
- utilities: z.array(z.looseObject({
29
- ...linkFields,
30
- variant: z.enum(['primary', 'secondary', 'tertiary', 'outline', 'ghost']).optional(),
31
- })).optional(),
32
- promo: z.record(z.string(), z.unknown()).optional(),
33
- footer: z.looseObject({
34
- columns: z.array(z.looseObject({
35
- id: z.string().min(1),
36
- title: z.string().optional(),
37
- groups: z.array(z.looseObject({
38
- id: z.string().min(1),
39
- title: z.string(),
40
- links: z.array(linkSchema),
41
- })).optional(),
42
- links: z.array(linkSchema).optional(),
43
- })).optional(),
44
- social: z.array(z.looseObject({
45
- ...linkFields,
46
- icon: z.string().optional(),
47
- })).optional(),
48
- legalLinks: z.array(linkSchema).optional(),
49
- copyright: z.string().optional(),
50
- }).optional(),
51
- seo: z.looseObject({
52
- title: z.string().optional(),
53
- description: z.string().optional(),
54
- siteName: z.string().optional(),
55
- }).optional(),
56
- });
57
- function withOptional(schema, field) {
58
- return field.optional ? schema.optional() : schema;
59
- }
60
- export function createContentSchemas(contracts = {}) {
61
- const blockContracts = contracts.blockContracts ?? defaultBlockContracts;
62
- const atomicBlockContracts = contracts.atomicBlockContracts ?? defaultAtomicBlockContracts;
63
- let atomicBlockSchema;
64
- function schemaFromContractField(field) {
65
- switch (field.kind) {
66
- case 'atomicBlocks':
67
- return withOptional(z.array(atomicBlockSchema), field);
68
- case 'array':
69
- return withOptional(z.array(schemaFromContractField(field.items)), field);
70
- case 'boolean':
71
- return withOptional(z.boolean(), field);
72
- case 'className': {
73
- const schema = z.string().check((ctx) => {
74
- const result = validateContentClassName(ctx.value);
75
- if (!result.valid) {
76
- ctx.issues.push({
77
- code: 'custom',
78
- message: `Invalid Tailwind classes: ${result.invalidClasses.join(', ')}. Use standard utilities only; arbitrary bracket values are not allowed in content.`,
79
- input: ctx.value,
80
- });
81
- }
82
- });
83
- return withOptional(schema, field);
84
- }
85
- case 'componentClassName': {
86
- const schema = z.string().check((ctx) => {
87
- const result = validateComponentClassName(ctx.value);
88
- if (!result.valid) {
89
- ctx.issues.push({
90
- code: 'custom',
91
- message: `Invalid Tailwind classes: ${result.invalidClasses.join(', ')}. Raw dimension/color bracket values (for example [12px] or [#fff]) are not allowed.`,
92
- input: ctx.value,
93
- });
94
- }
95
- });
96
- return withOptional(schema, field);
97
- }
98
- case 'enum':
99
- return withOptional(z.enum(field.values), field);
100
- case 'image':
101
- return withOptional(imageSchema, field);
102
- case 'object':
103
- return withOptional(schemaFromContractFields(field.fields), field);
104
- case 'richText':
105
- return withOptional(z.string(), field);
106
- case 'string': {
107
- const schema = typeof field.minLength === 'number'
108
- ? z.string().min(field.minLength)
109
- : z.string();
110
- return withOptional(schema, field);
111
- }
112
- }
113
- }
114
- function schemaFromContractFields(fields) {
115
- return z.looseObject(Object.fromEntries(Object.entries(fields).map(([key, field]) => [key, schemaFromContractField(field)])));
116
- }
117
- atomicBlockSchema = discriminatedContractUnion('atomic block', atomicBlockContracts, schemaFromContractFields);
118
- const pageBlockSchema = discriminatedContractUnion('page block', blockContracts, schemaFromContractFields);
119
- const pageSchema = z.looseObject({
120
- id: z.string().min(1),
121
- $type: z.literal('page'),
122
- status: z.string().min(1),
123
- layout: z.string().min(1),
124
- renderMode: z.string().min(1),
125
- metadata: z.looseObject({
126
- title: z.string().optional(),
127
- description: z.string().optional(),
128
- canonical: z.string().optional(),
129
- }),
130
- regions: z.record(z.string(), z.array(pageBlockSchema)),
131
- });
132
- return {
133
- siteConfigSchema,
134
- atomicBlockSchema,
135
- pageBlockSchema,
136
- pageSchema,
137
- schemaFromContractField,
138
- schemaFromContractFields,
139
- parseKernelSiteConfig(value, source = 'site.json') {
140
- return parseWithSchema(siteConfigSchema, value, source);
141
- },
142
- parseKernelPage(value, source = '_index.json') {
143
- return parseWithSchema(pageSchema, value, source);
144
- },
145
- };
146
- }
147
- function discriminatedContractUnion(label, contracts, schemaFromContractFields) {
148
- if (contracts.length === 0) {
149
- throw new Error(`At least one ${label} contract is required`);
150
- }
151
- const schemas = contracts.map((block) => z.looseObject({
152
- id: z.string().min(1),
153
- component: z.literal(block.component),
154
- props: schemaFromContractFields(block.props),
155
- }));
156
- if (schemas.length === 1) {
157
- return schemas[0];
158
- }
159
- return z.discriminatedUnion('component', schemas);
160
- }
161
- export function formatZodError(source, error) {
162
- const issues = error.issues
163
- .map((issue) => {
164
- const path = issue.path.length ? issue.path.join('.') : '<root>';
165
- return `- ${path}: ${issue.message}`;
166
- })
167
- .join('\n');
168
- return `Invalid Gradial content in ${source}:\n${issues}`;
169
- }
170
- export function parseWithSchema(schema, value, source) {
171
- const parsed = schema.safeParse(value);
172
- if (!parsed.success) {
173
- throw new Error(formatZodError(source, parsed.error));
174
- }
175
- return parsed.data;
176
- }
177
- const defaultContentSchemas = createContentSchemas();
178
- export const atomicBlockSchema = defaultContentSchemas.atomicBlockSchema;
179
- export const pageBlockSchema = defaultContentSchemas.pageBlockSchema;
180
- export const pageSchema = defaultContentSchemas.pageSchema;
181
- export const schemaFromContractField = defaultContentSchemas.schemaFromContractField;
182
- export const schemaFromContractFields = defaultContentSchemas.schemaFromContractFields;
183
- export const parseKernelSiteConfig = defaultContentSchemas.parseKernelSiteConfig;
184
- export const parseKernelPage = defaultContentSchemas.parseKernelPage;
@@ -1,4 +0,0 @@
1
- export interface PreviewBannerProps {
2
- releaseId?: string;
3
- }
4
- export declare function PreviewBanner({ releaseId }: PreviewBannerProps): import("react").JSX.Element | null;
@@ -1,51 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- export function PreviewBanner({ releaseId }) {
3
- if (!releaseId)
4
- return null;
5
- const shortId = releaseId.length > 20
6
- ? `${releaseId.slice(0, 8)}\u2026${releaseId.slice(-6)}`
7
- : releaseId;
8
- return (_jsxs("div", { role: "alert", style: {
9
- position: 'fixed',
10
- top: 0,
11
- left: 0,
12
- right: 0,
13
- zIndex: 9999,
14
- display: 'flex',
15
- alignItems: 'center',
16
- justifyContent: 'center',
17
- gap: '12px',
18
- padding: '8px 16px',
19
- backgroundColor: '#1a1a2e',
20
- color: '#fff',
21
- fontSize: '13px',
22
- fontFamily: 'system-ui, -apple-system, sans-serif',
23
- boxShadow: '0 2px 8px rgba(0,0,0,0.3)',
24
- }, children: [_jsx("span", { "aria-hidden": "true", style: {
25
- display: 'inline-flex',
26
- alignItems: 'center',
27
- justifyContent: 'center',
28
- width: '18px',
29
- height: '18px',
30
- borderRadius: '50%',
31
- backgroundColor: '#f59e0b',
32
- color: '#1a1a2e',
33
- fontWeight: 700,
34
- fontSize: '11px',
35
- flexShrink: 0,
36
- }, children: "P" }), _jsx("span", { style: { fontWeight: 500 }, children: "Release Preview" }), _jsx("span", { style: {
37
- fontFamily: 'monospace',
38
- opacity: 0.7,
39
- fontSize: '12px',
40
- }, title: releaseId, children: shortId }), _jsx("a", { href: "?leave_preview=1", style: {
41
- marginLeft: 'auto',
42
- padding: '4px 12px',
43
- borderRadius: '6px',
44
- backgroundColor: '#dc2626',
45
- color: '#fff',
46
- textDecoration: 'none',
47
- fontSize: '12px',
48
- fontWeight: 600,
49
- whiteSpace: 'nowrap',
50
- }, children: "Exit Preview" })] }));
51
- }
@@ -1,7 +0,0 @@
1
- export interface PreviewClaims {
2
- releaseId?: string;
3
- siteId?: string;
4
- expiresAt?: string;
5
- scope?: string;
6
- }
7
- export declare function validatePreviewToken(token: string, signKey: string): Promise<PreviewClaims | null>;