@gradial/aci 0.1.20-preview.3 → 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 (224) 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 +2 -2
  27. package/dist/next/middleware.js +6 -6
  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/react/Media.d.ts +24 -0
  35. package/dist/react/Media.js +30 -0
  36. package/dist/react/Picture.d.ts +12 -0
  37. package/dist/react/Picture.js +11 -0
  38. package/dist/react/VideoPlayer.d.ts +13 -0
  39. package/dist/react/{GradialVideoPlayer.js → VideoPlayer.js} +6 -5
  40. package/dist/react/index.d.ts +333 -3
  41. package/dist/react/index.js +89 -3
  42. package/dist/registry.d.ts +2 -2
  43. package/dist/registry.js +3 -3
  44. package/dist/types/block-ref.d.ts +26 -0
  45. package/dist/types/block-ref.js +28 -0
  46. package/dist/types/component.d.ts +36 -32
  47. package/dist/types/config.d.ts +1 -1
  48. package/dist/types/image.d.ts +33 -20
  49. package/dist/types/image.js +42 -50
  50. package/dist/types/index.d.ts +1 -0
  51. package/dist/types/index.js +1 -0
  52. package/dist/types/link.d.ts +38 -0
  53. package/dist/types/link.js +58 -0
  54. package/dist/types/media.d.ts +16 -35
  55. package/dist/types/media.js +15 -84
  56. package/dist/types/renderer.d.ts +1 -1
  57. package/dist/types/rich-text.d.ts +40 -0
  58. package/dist/types/rich-text.js +39 -0
  59. package/dist/types/video.d.ts +7 -13
  60. package/dist/types/video.js +3 -3
  61. package/package.json +28 -76
  62. package/src/cli/compile-registry.mjs +120 -63
  63. package/src/cli/validate-content.mjs +38 -75
  64. package/src/types/image.ts +79 -60
  65. package/templates/astro/template/.aci.yaml +27 -0
  66. package/templates/astro/template/.storybook/main.ts +79 -0
  67. package/templates/astro/template/.storybook/manager.ts +6 -0
  68. package/templates/astro/template/.storybook/preview.ts +33 -0
  69. package/templates/astro/template/astro.config.mjs +37 -0
  70. package/templates/astro/template/package.json.tmpl +41 -0
  71. package/templates/astro/template/src/cms/contracts/layouts/index.ts +18 -0
  72. package/templates/astro/template/src/cms/registry.ts +28 -0
  73. package/templates/astro/template/src/components/chrome/Footer.astro +107 -0
  74. package/templates/astro/template/src/components/chrome/Header.astro +94 -0
  75. package/templates/astro/template/src/components/elements/AtomicBlock.astro +15 -0
  76. package/templates/astro/template/src/components/elements/AtomicBlocks.astro +16 -0
  77. package/templates/astro/template/src/components/elements/Button.astro +51 -0
  78. package/templates/astro/template/src/components/elements/ButtonBlock.astro +25 -0
  79. package/templates/astro/template/src/components/elements/Container.astro +11 -0
  80. package/templates/astro/template/src/components/elements/Icon.astro +31 -0
  81. package/templates/astro/template/src/components/elements/Logo.astro +29 -0
  82. package/templates/astro/template/src/components/elements/RemoteImage.astro +41 -0
  83. package/templates/astro/template/src/components/sections/ContainerSection.astro +32 -0
  84. package/templates/astro/template/src/components/sections/FeatureCard.astro +23 -0
  85. package/templates/astro/template/src/components/sections/FeatureGrid.astro +35 -0
  86. package/templates/astro/template/src/components/sections/HomeHero.astro +51 -0
  87. package/templates/astro/template/src/components/sections/StatsBar.astro +33 -0
  88. package/templates/astro/template/src/design-system/styles.css +399 -0
  89. package/templates/astro/template/src/design-system/tokens/colors.css +60 -0
  90. package/templates/astro/template/src/design-system/tokens/components.css +69 -0
  91. package/templates/astro/template/src/design-system/tokens/index.css +6 -0
  92. package/templates/astro/template/src/design-system/tokens/radii.css +5 -0
  93. package/templates/astro/template/src/design-system/tokens/shadows.css +5 -0
  94. package/templates/astro/template/src/design-system/tokens/spacing.css +13 -0
  95. package/templates/astro/template/src/design-system/tokens/typography.css +24 -0
  96. package/templates/astro/template/src/env.d.ts +1 -0
  97. package/templates/astro/template/src/fixtures/atomicBlocks.ts +33 -0
  98. package/templates/astro/template/src/fixtures/composition.ts +31 -0
  99. package/templates/astro/template/src/fixtures/index.ts +17 -0
  100. package/templates/astro/template/src/fixtures/sections.ts +39 -0
  101. package/templates/astro/template/src/layouts/SiteLayout.astro +30 -0
  102. package/templates/astro/template/src/pages/[...slug].astro +61 -0
  103. package/templates/astro/template/src/render/RenderPage.astro +66 -0
  104. package/templates/astro/template/src/stories/CompositionStoryFrame.astro +15 -0
  105. package/templates/astro/template/src/stories/HomeHero.stories.ts +24 -0
  106. package/templates/astro/template/src/stories/SectionStoryFrame.astro +16 -0
  107. package/templates/astro/template/src/stories/StoryDocFrame.astro +31 -0
  108. package/templates/astro/template/tsconfig.json +11 -0
  109. package/templates/common/.agents/AGENTS.md +37 -0
  110. package/templates/common/.agents/skills/aci/SKILL.md +162 -0
  111. package/templates/common/.agents/skills/authoring/SKILL.md +590 -0
  112. package/templates/common/.agents/skills/authoring/references/block-registry.md +151 -0
  113. package/templates/common/.agents/skills/authoring/references/contracts.md +153 -0
  114. package/templates/common/.agents/skills/authoring/references/design-system.md +171 -0
  115. package/templates/common/.agents/skills/authoring/references/image-assets.md +73 -0
  116. package/templates/common/.agents/skills/authoring/references/repo-structure.md +157 -0
  117. package/templates/common/.agents/skills/migration/SKILL.md +160 -0
  118. package/templates/common/.agents/skills/migration/references/analyzing-source.md +215 -0
  119. package/templates/common/.agents/skills/migration/references/component-migration.md +200 -0
  120. package/templates/common/.agents/skills/migration/references/selector-map.md +31 -0
  121. package/templates/common/.content/.gradial-dam/blobs/sha256/7f/bf/7fbfc7fe230ff12688c496f660119e41d9725c4504d82e310c15665c73c09292 +0 -0
  122. package/templates/common/.content/.gradial-dam/blobs/sha256/a0/f5/a0f506689de9b15a7055f70103a3f02cd3ba105771ae2de6754df2ede1210d3a +0 -0
  123. package/templates/common/.content/.gradial-dam/blobs/sha256/dd/b7/ddb7e9642be08317bcd4b2bd26b58ba8d0d34dd7239e03e684a4f3634fa3845b +0 -0
  124. package/templates/common/.content/.gradial-dam/blobs/sha256/fb/32/fb3260e8286ea8231ea1c77b9c0be92d6edd9026565731eb14cfdcfd6b1b75b3 +0 -0
  125. package/templates/common/.content/config/site.json +192 -0
  126. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/asset.json +9 -0
  127. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/editorial.json +14 -0
  128. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/governance.json +23 -0
  129. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/versions/v0001.json +37 -0
  130. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/asset.json +9 -0
  131. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/editorial.json +14 -0
  132. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/governance.json +23 -0
  133. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/versions/v0001.json +37 -0
  134. package/templates/common/.content/fragments/navbar/_index.json +25 -0
  135. package/templates/common/.content/fragments/site-footer/_index.json +62 -0
  136. package/templates/common/.content/pages/about/_index.json +51 -0
  137. package/templates/common/.content/pages/home/_index.json +112 -0
  138. package/templates/common/.content/schemas/site.schema.json +123 -0
  139. package/templates/common/README.md.tmpl +45 -0
  140. package/templates/common/contracts/components/button.contract.ts +19 -0
  141. package/templates/common/contracts/components/container.contract.ts +19 -0
  142. package/templates/common/contracts/components/featureCard.contract.ts +15 -0
  143. package/templates/common/contracts/components/featureGrid.contract.ts +16 -0
  144. package/templates/common/contracts/components/homeHero.contract.ts +36 -0
  145. package/templates/common/contracts/components/index.ts +21 -0
  146. package/templates/common/contracts/components/siteFooter.contract.ts +45 -0
  147. package/templates/common/contracts/components/siteNavigation.contract.ts +30 -0
  148. package/templates/common/contracts/components/statsBar.contract.ts +19 -0
  149. package/templates/common/design-system/styles.css +346 -0
  150. package/templates/common/design-system/tokens/colors.css +110 -0
  151. package/templates/common/design-system/tokens/components.css +86 -0
  152. package/templates/common/design-system/tokens/index.css +6 -0
  153. package/templates/common/design-system/tokens/radii.css +5 -0
  154. package/templates/common/design-system/tokens/shadows.css +9 -0
  155. package/templates/common/design-system/tokens/spacing.css +26 -0
  156. package/templates/common/design-system/tokens/typography.css +32 -0
  157. package/templates/common/eslint-rules/no-raw-tailwind-values.js +127 -0
  158. package/templates/common/public/assets/Dwire-model.png +0 -0
  159. package/templates/common/public/assets/bare-metal-logo.png +0 -0
  160. package/templates/common/public/assets/meridian-logo.svg +8 -0
  161. package/templates/common/public/assets/seattle.avif +0 -0
  162. package/templates/nextjs/template/.aci.yaml +25 -0
  163. package/templates/nextjs/template/.storybook/main.ts +13 -0
  164. package/templates/nextjs/template/.storybook/preview.ts +34 -0
  165. package/templates/nextjs/template/eslint.config.mjs +36 -0
  166. package/templates/nextjs/template/next-env.d.ts +6 -0
  167. package/templates/nextjs/template/next.config.ts +8 -0
  168. package/templates/nextjs/template/package.json.tmpl +46 -0
  169. package/templates/nextjs/template/postcss.config.mjs +7 -0
  170. package/templates/nextjs/template/src/app/[[...slug]]/page.tsx +8 -0
  171. package/templates/nextjs/template/src/app/gradial/assets/[releaseId]/[...path]/route.ts +31 -0
  172. package/templates/nextjs/template/src/app/layout.tsx +29 -0
  173. package/templates/nextjs/template/src/cms/contracts/components/button.contract.ts +19 -0
  174. package/templates/nextjs/template/src/cms/contracts/components/container.contract.ts +20 -0
  175. package/templates/nextjs/template/src/cms/contracts/components/homeHero.contract.ts +36 -0
  176. package/templates/nextjs/template/src/cms/contracts/components/index.ts +15 -0
  177. package/templates/nextjs/template/src/cms/contracts/components/siteFooter.contract.ts +45 -0
  178. package/templates/nextjs/template/src/cms/contracts/components/siteNavigation.contract.ts +30 -0
  179. package/templates/nextjs/template/src/cms/contracts/layouts/index.ts +16 -0
  180. package/templates/nextjs/template/src/cms/registry.ts +28 -0
  181. package/templates/nextjs/template/src/components/chrome/Footer.tsx +86 -0
  182. package/templates/nextjs/template/src/components/chrome/Header.tsx +74 -0
  183. package/templates/nextjs/template/src/components/elements/AtomicBlock.tsx +13 -0
  184. package/templates/nextjs/template/src/components/elements/Button.tsx +40 -0
  185. package/templates/nextjs/template/src/components/elements/ButtonBlock.tsx +18 -0
  186. package/templates/nextjs/template/src/components/elements/Container.tsx +14 -0
  187. package/templates/nextjs/template/src/components/elements/Icon.tsx +29 -0
  188. package/templates/nextjs/template/src/components/elements/Logo.tsx +38 -0
  189. package/templates/nextjs/template/src/components/sections/ContainerSection.tsx +28 -0
  190. package/templates/nextjs/template/src/components/sections/FeatureCard.tsx +25 -0
  191. package/templates/nextjs/template/src/components/sections/FeatureGrid.tsx +36 -0
  192. package/templates/nextjs/template/src/components/sections/HomeHero.tsx +62 -0
  193. package/templates/nextjs/template/src/components/sections/StatsBar.tsx +30 -0
  194. package/templates/nextjs/template/src/middleware.ts +4 -0
  195. package/templates/nextjs/template/src/stories/Button.stories.tsx +38 -0
  196. package/templates/nextjs/template/src/stories/Header.stories.tsx +30 -0
  197. package/templates/nextjs/template/src/stories/HomeHero.stories.tsx +33 -0
  198. package/templates/nextjs/template/tsconfig.json +23 -0
  199. package/templates/nextjs/template/vercel.json +6 -0
  200. package/dist/content/contract.d.ts +0 -83
  201. package/dist/content/contract.js +0 -104
  202. package/dist/content/tailwind-validator.d.ts +0 -6
  203. package/dist/content/tailwind-validator.js +0 -31
  204. package/dist/content/validation.d.ts +0 -108
  205. package/dist/content/validation.js +0 -183
  206. package/dist/react/GradialMedia.d.ts +0 -24
  207. package/dist/react/GradialMedia.js +0 -31
  208. package/dist/react/GradialPicture.d.ts +0 -14
  209. package/dist/react/GradialPicture.js +0 -30
  210. package/dist/react/GradialVideoPlayer.d.ts +0 -13
  211. package/dist/sveltekit/index.d.ts +0 -25
  212. package/dist/sveltekit/index.js +0 -66
  213. package/dist/sveltekit/preview.d.ts +0 -5
  214. package/dist/sveltekit/preview.js +0 -33
  215. package/src/types/component.ts +0 -49
  216. package/src/types/config.ts +0 -37
  217. package/src/types/data.ts +0 -47
  218. package/src/types/index.ts +0 -10
  219. package/src/types/layout.ts +0 -29
  220. package/src/types/media.ts +0 -125
  221. package/src/types/page.ts +0 -47
  222. package/src/types/render-mode.ts +0 -10
  223. package/src/types/renderer.ts +0 -83
  224. package/src/types/video.ts +0 -66
@@ -0,0 +1,27 @@
1
+ version: "1"
2
+ siteId: "site_astro"
3
+ framework: astro
4
+
5
+ source:
6
+ root: "./"
7
+ outDir: "dist"
8
+ publicDir: "public"
9
+
10
+ componentRegistry: ./src/cms/contracts/components/index.ts
11
+ layoutRegistry: ./src/cms/contracts/layouts/index.ts
12
+
13
+ capabilities:
14
+ staticRender: true
15
+ ssr: true
16
+ ssrIslands: true
17
+ clientIslands: true
18
+ fragmentRender: true
19
+
20
+ routes:
21
+ cmsManaged: "/[...slug]"
22
+ frameworkOwned:
23
+ - "/api/*"
24
+ - "/_astro/*"
25
+ - "/storybook/*"
26
+
27
+ rendererProtocol: stdio-json
@@ -0,0 +1,79 @@
1
+ import { dirname, resolve } from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+ import tailwindcss from '@tailwindcss/postcss';
4
+
5
+ const sharedRoot = fileURLToPath(new URL('../src', import.meta.url));
6
+
7
+ function withSharedAlias(alias: any) {
8
+ if (Array.isArray(alias)) {
9
+ return [...alias, { find: '@shared', replacement: sharedRoot }];
10
+ }
11
+
12
+ return {
13
+ ...alias,
14
+ '@shared': sharedRoot
15
+ };
16
+ }
17
+
18
+ const config = {
19
+ stories: ['../src/**/*.stories.@(ts|mdx)'],
20
+ addons: ['@storybook/addon-docs'],
21
+ framework: {
22
+ name: '@storybook-astro/framework',
23
+ options: {}
24
+ },
25
+ core: {
26
+ builder: '@storybook/builder-vite'
27
+ },
28
+ staticDirs: ['../public'],
29
+ viteFinal: async (config: any) => {
30
+ const astroComponentPaths = new Set<string>();
31
+ const buildServerPlugin = config.plugins?.flat().find(
32
+ (p: any) => p?.name === 'storybook-astro:build-server'
33
+ );
34
+
35
+ if (buildServerPlugin) {
36
+ const origWriteBundle = buildServerPlugin.writeBundle;
37
+ buildServerPlugin.writeBundle = async function(this: any, ...args: any[]) {
38
+ for (const componentPath of astroComponentPaths) {
39
+ buildServerPlugin.resolveId?.call(
40
+ this,
41
+ componentPath,
42
+ componentPath
43
+ );
44
+ }
45
+ return origWriteBundle?.apply(this, args);
46
+ };
47
+ }
48
+
49
+ config.plugins = [
50
+ {
51
+ name: 'storybook-astro:resolve-compat',
52
+ enforce: 'pre' as const,
53
+ resolveId(id: string, importer: string | undefined) {
54
+ if (id?.endsWith('.astro') && importer) {
55
+ astroComponentPaths.add(resolve(dirname(importer), id));
56
+ }
57
+ return undefined;
58
+ }
59
+ },
60
+ ...config.plugins
61
+ ];
62
+
63
+ return {
64
+ ...config,
65
+ resolve: {
66
+ ...config.resolve,
67
+ alias: withSharedAlias(config.resolve?.alias)
68
+ },
69
+ css: {
70
+ ...config.css,
71
+ postcss: {
72
+ plugins: [tailwindcss()]
73
+ }
74
+ }
75
+ };
76
+ }
77
+ };
78
+
79
+ export default config;
@@ -0,0 +1,6 @@
1
+ import { addons } from 'storybook/manager-api';
2
+ import { themes } from 'storybook/theming';
3
+
4
+ addons.setConfig({
5
+ theme: themes.dark
6
+ });
@@ -0,0 +1,33 @@
1
+ import '../src/design-system/styles.css';
2
+
3
+ const preview = {
4
+ globalTypes: {
5
+ theme: {
6
+ description: 'Theme for components',
7
+ toolbar: {
8
+ title: 'Theme',
9
+ icon: 'sun',
10
+ items: ['light', 'dark'],
11
+ dynamicTitle: true
12
+ }
13
+ }
14
+ },
15
+ decorators: [
16
+ (storyFn: any, context: any) => {
17
+ const theme = context.globals.theme || 'light';
18
+ document.body.setAttribute('data-visual-root', '');
19
+ document.body.className = `theme-${theme} min-h-screen bg-[var(--color-surface-default)]`;
20
+ return storyFn();
21
+ }
22
+ ],
23
+ parameters: {
24
+ layout: 'fullscreen',
25
+ options: {
26
+ storySort: {
27
+ order: ['Core Atomic Blocks', 'Composition', '*']
28
+ }
29
+ }
30
+ }
31
+ };
32
+
33
+ export default preview;
@@ -0,0 +1,37 @@
1
+ import path from 'node:path';
2
+ import { defineConfig } from 'astro/config';
3
+ import node from '@astrojs/node';
4
+ import tailwindcss from '@tailwindcss/postcss';
5
+ import { withAci } from '@gradial/aci/astro';
6
+
7
+ const pageRuntimeBuild = process.env.ACI_CODE_ARTIFACT_BUILD === '1';
8
+ const rawBasePath = String(process.env.ACI_SITE_BASE_PATH || '').trim().replace(/\/+$/g, '');
9
+ const base = rawBasePath
10
+ ? rawBasePath.startsWith('/') ? rawBasePath : `/${rawBasePath}`
11
+ : '/';
12
+ const rawOutDir = String(process.env.ACI_ASTRO_OUT_DIR || '').trim();
13
+ const rawCacheDir = String(process.env.ACI_ASTRO_CACHE_DIR || '').trim();
14
+ const outDir = rawOutDir
15
+ ? (path.isAbsolute(rawOutDir) ? rawOutDir : `./${rawOutDir}`)
16
+ : 'dist';
17
+
18
+ export default defineConfig({
19
+ adapter: pageRuntimeBuild ? node({ mode: 'middleware' }) : undefined,
20
+ integrations: [withAci()],
21
+ srcDir: './src',
22
+ outDir,
23
+ cacheDir: rawCacheDir
24
+ ? (path.isAbsolute(rawCacheDir) ? rawCacheDir : `./${rawCacheDir}`)
25
+ : undefined,
26
+ output: pageRuntimeBuild ? 'server' : 'static',
27
+ trailingSlash: 'always',
28
+ base,
29
+ devToolbar: { enabled: false },
30
+ vite: {
31
+ css: {
32
+ postcss: {
33
+ plugins: [tailwindcss()],
34
+ },
35
+ },
36
+ },
37
+ });
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "{{siteName}}",
3
+ "version": "{{version}}",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "astro dev --host 0.0.0.0",
8
+ "build": "astro build",
9
+ "preview": "ACI_CONTENT_ROOT=./.aci/compiled astro preview --host 0.0.0.0",
10
+ "typecheck": "ACI_CONTENT_ROOT=./.aci/compiled astro check --tsconfig ./tsconfig.json",
11
+ "aci:compile": "node ./node_modules/@gradial/aci/bin/aci.js build --compile-only",
12
+ "content:compile": "node ./node_modules/@gradial/aci/bin/aci.js build --skip-code --content ./.content --out ./.aci/compiled",
13
+ "aci:build": "node ./node_modules/@gradial/aci/bin/aci.js build --content ./.content",
14
+ "aci:doctor": "node ./node_modules/@gradial/aci/bin/aci.js doctor",
15
+ "aci:validate": "node ./node_modules/@gradial/aci/bin/aci.js build --validate-only",
16
+ "storybook": "storybook dev -p 6006",
17
+ "build:storybook": "storybook build"
18
+ },
19
+ "dependencies": {
20
+ "@gradial/aci": "^0.1.20",
21
+ "js-yaml": "^4.1.0",
22
+ "marked": "^18.0.3",
23
+ "zod": "^4.0.0"
24
+ },
25
+ "devDependencies": {
26
+ "@astrojs/check": "^0.9.8",
27
+ "@astrojs/node": "^10.1.4",
28
+ "@tailwindcss/postcss": "^4.2.4",
29
+ "@types/js-yaml": "^4.0.9",
30
+ "@types/node": "^25.8.0",
31
+ "astro": "^6.1.9",
32
+ "tailwindcss": "^4.2.4",
33
+ "tsx": "^4.20.0",
34
+ "typescript": "5.9.3",
35
+ "vite": "^7.2.7",
36
+ "storybook": "^10.0.0",
37
+ "@storybook-astro/framework": "^1.6.0",
38
+ "@storybook/addon-docs": "^10.0.0",
39
+ "@storybook/builder-vite": "^10.0.0"
40
+ }
41
+ }
@@ -0,0 +1,18 @@
1
+ import { defineLayoutContract, slot, fragmentDefault } from '@gradial/aci';
2
+
3
+ const layoutContracts = [
4
+ defineLayoutContract({
5
+ name: 'default',
6
+ slots: [
7
+ slot('header', false),
8
+ slot('main', true),
9
+ slot('footer', false),
10
+ ],
11
+ defaults: {
12
+ header: [fragmentDefault('navbar')],
13
+ footer: [fragmentDefault('site-footer')],
14
+ },
15
+ }),
16
+ ];
17
+
18
+ export default layoutContracts;
@@ -0,0 +1,28 @@
1
+ import { createRegistry } from '@gradial/aci';
2
+ import { homeHeroContract } from './contracts/components/homeHero.contract';
3
+ import { containerContract } from './contracts/components/container.contract';
4
+ import { buttonContract } from './contracts/components/button.contract';
5
+ import { siteNavigationContract } from './contracts/components/siteNavigation.contract';
6
+ import { siteFooterContract } from './contracts/components/siteFooter.contract';
7
+ import { featureGridContract } from './contracts/components/featureGrid.contract';
8
+ import { featureCardContract } from './contracts/components/featureCard.contract';
9
+ import { statsBarContract } from './contracts/components/statsBar.contract';
10
+ import HomeHero from '../components/sections/HomeHero.astro';
11
+ import ContainerSection from '../components/sections/ContainerSection.astro';
12
+ import ButtonBlock from '../components/elements/ButtonBlock.astro';
13
+ import Header from '../components/chrome/Header.astro';
14
+ import Footer from '../components/chrome/Footer.astro';
15
+ import FeatureGrid from '../components/sections/FeatureGrid.astro';
16
+ import FeatureCard from '../components/sections/FeatureCard.astro';
17
+ import StatsBar from '../components/sections/StatsBar.astro';
18
+
19
+ export const registry = createRegistry([
20
+ [homeHeroContract, HomeHero],
21
+ [containerContract, ContainerSection],
22
+ [buttonContract, ButtonBlock],
23
+ [siteNavigationContract, Header],
24
+ [siteFooterContract, Footer],
25
+ [featureGridContract, FeatureGrid],
26
+ [featureCardContract, FeatureCard],
27
+ [statsBarContract, StatsBar],
28
+ ]);
@@ -0,0 +1,107 @@
1
+ ---
2
+ import Container from '../elements/Container.astro';
3
+ import Logo from '../elements/Logo.astro';
4
+
5
+ interface FooterLink {
6
+ id: string;
7
+ label: string;
8
+ href: string;
9
+ }
10
+
11
+ interface FooterGroup {
12
+ id: string;
13
+ title: string;
14
+ links: FooterLink[];
15
+ }
16
+
17
+ interface FooterColumn {
18
+ id: string;
19
+ title?: string;
20
+ groups?: FooterGroup[];
21
+ links?: FooterLink[];
22
+ }
23
+
24
+ interface Props {
25
+ brandHref: string;
26
+ brandLabel?: string;
27
+ brandLogo?: { src: string; alt?: string } | null;
28
+ social?: Array<FooterLink & { icon?: string }>;
29
+ columns?: FooterColumn[];
30
+ legalLinks?: FooterLink[];
31
+ copyright?: string;
32
+ }
33
+
34
+ const {
35
+ brandHref,
36
+ brandLabel = 'Gradial',
37
+ brandLogo = null,
38
+ social = [],
39
+ columns = [],
40
+ legalLinks = [],
41
+ copyright = ''
42
+ } = Astro.props;
43
+
44
+ function columnGroups(column: FooterColumn): FooterGroup[] {
45
+ if (column.groups?.length) {
46
+ return column.groups;
47
+ }
48
+
49
+ return [{
50
+ id: column.id,
51
+ title: column.title || '',
52
+ links: column.links || []
53
+ }];
54
+ }
55
+ ---
56
+
57
+ <footer class="bm-footer [font-family:var(--font-family-base)] text-fg" id="footer">
58
+ <Container className="py-[var(--spacing-footer-y)]">
59
+ <div class="grid gap-12 pb-24 md:grid-cols-[var(--footer-grid-columns)] lg:gap-24">
60
+ <a href={brandHref} class="self-start">
61
+ <Logo
62
+ label={brandLabel}
63
+ src={brandLogo?.src || ''}
64
+ alt={brandLogo?.alt || brandLabel}
65
+ className="w-[var(--width-logo-footer-mobile)] md:w-[var(--width-logo-footer)]"
66
+ />
67
+ </a>
68
+ <div class="grid gap-10 sm:grid-cols-2 lg:grid-cols-4">
69
+ {columns.map((column) => (
70
+ <div class="space-y-10">
71
+ {columnGroups(column).map((group) => (
72
+ <section class="space-y-5" aria-label={group.title}>
73
+ <h2 class="text-[length:var(--text-size-body-small)] font-[var(--font-weight-semibold)] text-fg-muted">{group.title}</h2>
74
+ <ul class="space-y-4 text-[length:var(--text-size-body-small)] font-[var(--font-weight-semibold)] leading-body text-fg">
75
+ {group.links.map((link) => (
76
+ <li><a class="transition hover:text-link-hover" href={link.href}>{link.label}</a></li>
77
+ ))}
78
+ </ul>
79
+ </section>
80
+ ))}
81
+ </div>
82
+ ))}
83
+ <section class="space-y-5" aria-label="Social">
84
+ <h2 class="text-[length:var(--text-size-body-small)] font-[var(--font-weight-semibold)] text-fg-muted">Social</h2>
85
+ <ul class="space-y-4 text-[length:var(--text-size-body-small)] font-[var(--font-weight-semibold)] text-fg">
86
+ {social.map((item) => (
87
+ <li>
88
+ <a class="inline-flex items-center gap-2 transition hover:text-link-hover" href={item.href}>
89
+ <span class="min-w-5 text-[length:var(--text-size-caption)] text-fg-muted">{item.icon || item.label.slice(0, 1)}</span>
90
+ <span>{item.label}</span>
91
+ </a>
92
+ </li>
93
+ ))}
94
+ </ul>
95
+ </section>
96
+ </div>
97
+ </div>
98
+ <div class="flex flex-col gap-6 border-t border-edge pt-8 text-[length:var(--text-size-caption)] font-[var(--font-weight-semibold)] text-fg-muted md:flex-row md:items-center md:justify-between">
99
+ <ul class="flex flex-wrap gap-x-9 gap-y-3 text-fg">
100
+ {legalLinks.map((link) => (
101
+ <li><a class="transition hover:text-link-hover" href={link.href}>{link.label}</a></li>
102
+ ))}
103
+ </ul>
104
+ <p>{copyright}</p>
105
+ </div>
106
+ </Container>
107
+ </footer>
@@ -0,0 +1,94 @@
1
+ ---
2
+ import Button from '../elements/Button.astro';
3
+ import Container from '../elements/Container.astro';
4
+ import Icon from '../elements/Icon.astro';
5
+ import Logo from '../elements/Logo.astro';
6
+
7
+ interface NavItem {
8
+ id: string;
9
+ label: string;
10
+ href: string;
11
+ }
12
+
13
+ interface UtilityItem extends NavItem {
14
+ variant?: 'primary' | 'secondary' | 'outline' | 'ghost';
15
+ }
16
+
17
+ interface Props {
18
+ brandHref: string;
19
+ brandLabel?: string;
20
+ brandLogo?: { src: string; alt?: string } | null;
21
+ navigation?: NavItem[];
22
+ utilities?: UtilityItem[];
23
+ }
24
+
25
+ const {
26
+ brandHref,
27
+ brandLabel = 'Gradial',
28
+ brandLogo = null,
29
+ navigation = [],
30
+ utilities = []
31
+ } = Astro.props;
32
+ ---
33
+
34
+ <header class="bm-header sticky top-0 z-[var(--z-header)] [font-family:var(--font-family-base)] text-fg">
35
+ <a
36
+ href="#content-main"
37
+ class="sr-only focus:not-sr-only focus:absolute focus:left-4 focus:top-4 focus:z-10 focus:rounded-button focus:bg-white focus:px-4 focus:py-2 focus:text-black"
38
+ >
39
+ Skip to main content
40
+ </a>
41
+ <Container className="flex min-h-[var(--height-header)] items-center justify-between gap-4">
42
+ <a href={brandHref} class="shrink-0">
43
+ <Logo label={brandLabel} src={brandLogo?.src || ''} alt={brandLogo?.alt || brandLabel} />
44
+ </a>
45
+ <nav class="hidden items-center gap-9 text-[length:var(--text-size-body-small)] font-[var(--font-weight-semibold)] text-fg-muted lg:flex" aria-label="Primary">
46
+ {navigation.map((item) => (
47
+ <a class="transition hover:text-link-hover" href={item.href}>{item.label}</a>
48
+ ))}
49
+ </nav>
50
+ <div class="flex shrink-0 items-center gap-3">
51
+ <div class="hidden items-center gap-3 sm:flex">
52
+ {utilities.map((item) => (
53
+ <Button href={item.href} variant={item.variant || 'outline'}>{item.label}</Button>
54
+ ))}
55
+ </div>
56
+ <div class="lg:hidden">
57
+ <input id="site-mobile-nav" class="peer sr-only" type="checkbox" />
58
+ <label
59
+ for="site-mobile-nav"
60
+ class="inline-grid size-11 cursor-pointer place-items-center rounded-button border border-edge text-fg transition hover:text-link-hover"
61
+ aria-label="Open main navigation"
62
+ >
63
+ <Icon name="menu" className="size-6" />
64
+ </label>
65
+ <div class="bm-mobile-nav pointer-events-none fixed inset-0 z-[var(--z-overlay)] flex translate-x-full flex-col px-[var(--spacing-container)] py-5 text-fg opacity-0 transition duration-300 ease-out peer-checked:pointer-events-auto peer-checked:translate-x-0 peer-checked:opacity-100">
66
+ <div class="flex min-h-[var(--height-header)] items-center justify-between gap-4">
67
+ <a href={brandHref} class="shrink-0">
68
+ <Logo label={brandLabel} src={brandLogo?.src || ''} alt={brandLogo?.alt || brandLabel} />
69
+ </a>
70
+ <label
71
+ for="site-mobile-nav"
72
+ class="inline-grid size-11 cursor-pointer place-items-center rounded-button border border-edge text-fg transition hover:text-link-hover"
73
+ aria-label="Close main navigation"
74
+ >
75
+ <Icon name="close" className="size-6" />
76
+ </label>
77
+ </div>
78
+ <nav class="grid flex-1 content-center gap-4 py-10 font-[var(--font-weight-bold)] text-[length:var(--mobile-nav-link-size)] leading-[var(--mobile-nav-link-line-height)] text-fg" aria-label="Mobile main navigation">
79
+ {navigation.map((item) => (
80
+ <a class="transition hover:text-link-hover" href={item.href}>{item.label}</a>
81
+ ))}
82
+ </nav>
83
+ {utilities.length ? (
84
+ <div class="grid gap-3 border-t border-edge pt-5 sm:hidden">
85
+ {utilities.map((item) => (
86
+ <Button href={item.href} variant={item.variant || 'outline'} className="w-full">{item.label}</Button>
87
+ ))}
88
+ </div>
89
+ ) : null}
90
+ </div>
91
+ </div>
92
+ </div>
93
+ </Container>
94
+ </header>
@@ -0,0 +1,15 @@
1
+ ---
2
+ import type { KernelAtomicBlock } from '@gradial/aci/content';
3
+ import ButtonBlock from './ButtonBlock.astro';
4
+
5
+ interface Props {
6
+ block: KernelAtomicBlock;
7
+ }
8
+
9
+ const { block } = Astro.props;
10
+ const props = (block.props || {}) as any;
11
+ ---
12
+
13
+ {block.component === 'button' ? (
14
+ <ButtonBlock {...props} />
15
+ ) : null}
@@ -0,0 +1,16 @@
1
+ ---
2
+ import type { KernelAtomicBlock } from '@gradial/aci/content';
3
+ import AtomicBlock from './AtomicBlock.astro';
4
+
5
+ interface Props {
6
+ blocks?: KernelAtomicBlock[];
7
+ }
8
+
9
+ const { blocks = [] } = Astro.props;
10
+ ---
11
+
12
+ <div class="flex flex-wrap gap-4">
13
+ {blocks.map((block) => (
14
+ <AtomicBlock {block} />
15
+ ))}
16
+ </div>
@@ -0,0 +1,51 @@
1
+ ---
2
+ interface Props {
3
+ href: string;
4
+ variant?: 'primary' | 'secondary' | 'tertiary' | 'outline' | 'ghost';
5
+ className?: string;
6
+ target?: string;
7
+ rel?: string;
8
+ }
9
+
10
+ const { href, variant = 'primary', className = '', target, rel } = Astro.props;
11
+
12
+ const variantTokens = {
13
+ primary: {
14
+ background: 'var(--button-primary-bg)',
15
+ border: 'var(--button-primary-border)',
16
+ color: 'var(--button-primary-text)'
17
+ },
18
+ secondary: {
19
+ background: 'var(--button-secondary-bg)',
20
+ border: 'var(--button-secondary-border)',
21
+ color: 'var(--button-secondary-text)'
22
+ },
23
+ outline: {
24
+ background: 'var(--button-outline-bg)',
25
+ border: 'var(--button-outline-border)',
26
+ color: 'var(--button-outline-text)'
27
+ },
28
+ tertiary: {
29
+ background: 'var(--button-tertiary-bg)',
30
+ border: 'var(--button-tertiary-border)',
31
+ color: 'var(--button-tertiary-text)'
32
+ },
33
+ ghost: {
34
+ background: 'transparent',
35
+ border: 'transparent',
36
+ color: 'var(--color-fg)'
37
+ }
38
+ }[variant];
39
+
40
+ const tokenStyle = `background-color: ${variantTokens.background}; border-color: ${variantTokens.border}; color: ${variantTokens.color};`;
41
+ ---
42
+
43
+ <a
44
+ class={`inline-flex min-h-10 items-center justify-center rounded-button border px-[var(--spacing-button-x)] py-[var(--spacing-button-y)] [font-family:var(--font-family-base)] text-[length:var(--text-button)] font-[var(--font-weight-semibold)] leading-button transition duration-200 hover:opacity-85 ${className}`}
45
+ href={href}
46
+ target={target}
47
+ rel={rel}
48
+ style={tokenStyle}
49
+ >
50
+ <slot />
51
+ </a>
@@ -0,0 +1,25 @@
1
+ ---
2
+ import Button from '../elements/Button.astro';
3
+ import Icon from '../elements/Icon.astro';
4
+ import type { ContentProps } from '../../cms/contracts/components/button.contract';
5
+
6
+ type Props = ContentProps;
7
+
8
+ const {
9
+ label,
10
+ href,
11
+ variant = 'primary',
12
+ newWindow = false,
13
+ icon = '',
14
+ iconPosition = 'before',
15
+ className = ''
16
+ } = Astro.props;
17
+ const target = newWindow ? '_blank' : undefined;
18
+ const rel = newWindow ? 'noreferrer' : undefined;
19
+ ---
20
+
21
+ <Button {href} {variant} {target} {rel} {className}>
22
+ {icon && iconPosition === 'before' ? <Icon name={icon} className="mr-2 size-4" /> : null}
23
+ <span>{label}</span>
24
+ {icon && iconPosition === 'after' ? <Icon name={icon} className="ml-2 size-4" /> : null}
25
+ </Button>
@@ -0,0 +1,11 @@
1
+ ---
2
+ interface Props {
3
+ className?: string;
4
+ }
5
+
6
+ const { className = '' } = Astro.props;
7
+ ---
8
+
9
+ <div class={`mx-auto w-full max-w-container px-[var(--spacing-container)] ${className}`}>
10
+ <slot />
11
+ </div>
@@ -0,0 +1,31 @@
1
+ ---
2
+ interface Props {
3
+ name: 'auto_awesome' | 'hub' | 'speed' | string;
4
+ className?: string;
5
+ }
6
+
7
+ const { name, className = '' } = Astro.props;
8
+
9
+ const paths: Record<string, string> = {
10
+ arrow_forward: 'M647-440H160v-80h487L423-744l57-56 320 320-320 320-57-56 224-224Z',
11
+ auto_awesome: 'M480-80 376-376 80-480l296-104 104-296 104 296 296 104-296 104L480-80Zm0-167 64-177 177-64-177-64-64-177-64 177-177 64 177 64 64 177ZM760-560l-40-120-120-40 120-40 40-120 40 120 120 40-120 40-40 120Z',
12
+ close: 'm256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z',
13
+ globe: 'M480-80q-82 0-155-31.5t-127.5-86q-54.5-54.5-86-127.5T80-480q0-82 31.5-155t86-127.5q54.5-54.5 127.5-86T480-880q82 0 155 31.5t127.5 86q54.5 54.5 86 127.5T880-480q0 82-31.5 155t-86 127.5q-54.5 54.5-127.5 86T480-80Zm0-80q139-36 209.5-131.5T760-480H520v-280q-64 8-117 38.5T320-640h-40q-54 77-87 153.5T160-480q0 131.5 69.5 227T480-160Zm0 80q-83 0-156-31.5t-127-86q-54.5-54.5-86-127T80-480q0-83 31.5-156t86-127q54.5-54.5 127-86T480-880q83 0 156 31.5t127 86q54.5 54.5 86 127T880-480q0 83-31.5 156t-86 127q-54.5 54.5-127 86T480-80Z',
14
+ hub: 'M200-120q-50 0-85-35t-35-85q0-39 22.5-70t57.5-43v-254q-35-12-57.5-43T80-720q0-50 35-85t85-35q39 0 70 22.5t43 57.5h334q12-35 43-57.5t70-22.5q50 0 85 35t35 85q0 39-22.5 70T800-607v254q35 12 57.5 43t22.5 70q0 50-35 85t-85 35q-39 0-70-22.5T647-200H313q-12 35-43 57.5T200-120Zm0-80q17 0 28.5-11.5T240-240q0-17-11.5-28.5T200-280q-17 0-28.5 11.5T160-240q0 17 11.5 28.5T200-200Zm0-480q17 0 28.5-11.5T240-720q0-17-11.5-28.5T200-760q-17 0-28.5 11.5T160-720q0 17 11.5 28.5T200-680Zm560 480q17 0 28.5-11.5T800-240q0-17-11.5-28.5T760-280q-17 0-28.5 11.5T720-240q0 17 11.5 28.5T760-200Zm0-480q17 0 28.5-11.5T800-720q0-17-11.5-28.5T760-760q-17 0-28.5 11.5T720-720q0 17 11.5 28.5T760-680ZM313-280h334q9-26 29-46t44-27v-254q-24-7-44-27t-29-46H313q-9 26-29 46t-44 27v254q24 7 44 27t29 46Z',
15
+ menu: 'M120-240v-80h720v80H120Zm0-200v-80h720v80H120Zm0-200v-80h720v80H120Z',
16
+ setup: 'M480-240 640-96l-40-200 160-120-200-80-80-200-80 200-200 80 160 120-40 200 160-144ZM160-280l120-72 72 120-192-48Z',
17
+ speed: 'M418-340q24 24 62 23.5t56-27.5l224-336-336 224q-27 18-28 55t22 61Zm62-460q59 0 113.5 16.5T696-734l-76 48q-32-17-68-25.5T480-720q-133 0-226.5 93.5T160-400q0 42 11.5 83t32.5 77h552q21-36 32.5-77t11.5-83q0-36-8.5-72T766-540l48-76q33 48 49.5 102.5T880-400q0 57-16.5 110T816-192q-11 17-30 24.5t-40 7.5H214q-21 0-40-7.5T144-192q-31-45-47.5-98T80-400q0-83 31.5-155.5t86-127Q252-737 324.5-768.5T480-800Z'
18
+ };
19
+
20
+ const path = paths[name] || paths.arrow_forward;
21
+ ---
22
+
23
+ <svg
24
+ class={className}
25
+ viewBox="0 -960 960 960"
26
+ aria-hidden="true"
27
+ focusable="false"
28
+ fill="currentColor"
29
+ >
30
+ <path d={path} />
31
+ </svg>
@@ -0,0 +1,29 @@
1
+ ---
2
+ interface Props {
3
+ label?: string;
4
+ src?: string;
5
+ alt?: string;
6
+ className?: string;
7
+ }
8
+
9
+ const { label = 'Gradial', src = '', alt = '', className = '' } = Astro.props;
10
+ const imageClass = className || 'w-[var(--width-logo-mobile)] md:w-[var(--width-logo)]';
11
+ ---
12
+
13
+ {src ? (
14
+ <img
15
+ class={`h-auto max-w-none object-contain ${imageClass}`}
16
+ src={src}
17
+ alt={alt || label}
18
+ loading="eager"
19
+ decoding="async"
20
+ style="filter: var(--logo-filter);"
21
+ />
22
+ ) : (
23
+ <span
24
+ class={`inline-flex items-center [font-family:var(--font-family-heading)] text-[length:var(--text-size-brand)] font-[var(--font-weight-bold)] leading-none text-fg ${className}`}
25
+ aria-label={label}
26
+ >
27
+ <span>{label}</span>
28
+ </span>
29
+ )}