@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.
- package/README.md +48 -108
- package/bin/{aci → aci-darwin-arm64} +0 -0
- package/bin/aci.js +99 -6
- package/dist/assets/index.d.ts +3 -3
- package/dist/assets/index.js +3 -3
- package/dist/astro/index.d.ts +12 -3
- package/dist/astro/index.js +20 -5
- package/dist/content/assets.d.ts +17 -0
- package/dist/content/assets.js +65 -0
- package/dist/content/index.d.ts +1 -0
- package/dist/content/index.js +1 -0
- package/dist/define-component.d.ts +1 -2
- package/dist/define-component.js +73 -5
- package/dist/dev/content-watch.d.ts +37 -0
- package/dist/dev/content-watch.js +154 -0
- package/dist/dev/index.d.ts +24 -43
- package/dist/dev/index.js +4 -169
- package/dist/index.d.ts +14 -6
- package/dist/index.js +8 -9
- package/dist/next/asset-route.js +2 -2
- package/dist/next/config.d.ts +2 -2
- package/dist/next/config.js +5 -5
- package/dist/next/content-watch.js +6 -1
- package/dist/next/index.d.ts +2 -2
- package/dist/next/index.js +2 -2
- package/dist/next/middleware.d.ts +1 -0
- package/dist/next/middleware.js +49 -8
- package/dist/next/page.d.ts +1 -1
- package/dist/next/page.js +14 -12
- package/dist/next/render.d.ts +3 -3
- package/dist/next/render.js +11 -9
- package/dist/next/server.d.ts +12 -12
- package/dist/next/server.js +1 -1
- package/dist/preview/core.d.ts +5 -0
- package/dist/preview/core.js +1 -1
- package/dist/react/Media.d.ts +24 -0
- package/dist/react/Media.js +30 -0
- package/dist/react/Picture.d.ts +12 -0
- package/dist/react/Picture.js +11 -0
- package/dist/react/VideoPlayer.d.ts +13 -0
- package/dist/react/{GradialVideoPlayer.js → VideoPlayer.js} +6 -5
- package/dist/react/index.d.ts +333 -3
- package/dist/react/index.js +89 -3
- package/dist/registry.d.ts +2 -2
- package/dist/registry.js +3 -3
- package/dist/types/block-ref.d.ts +26 -0
- package/dist/types/block-ref.js +28 -0
- package/dist/types/component.d.ts +36 -32
- package/dist/types/config.d.ts +1 -1
- package/dist/types/image.d.ts +33 -20
- package/dist/types/image.js +42 -50
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/link.d.ts +38 -0
- package/dist/types/link.js +58 -0
- package/dist/types/media.d.ts +16 -35
- package/dist/types/media.js +15 -84
- package/dist/types/renderer.d.ts +1 -1
- package/dist/types/rich-text.d.ts +40 -0
- package/dist/types/rich-text.js +39 -0
- package/dist/types/video.d.ts +7 -13
- package/dist/types/video.js +3 -3
- package/package.json +29 -76
- package/src/cli/compile-registry.mjs +120 -63
- package/src/cli/validate-content.mjs +38 -75
- package/src/types/block-ref.ts +74 -0
- package/src/types/image.ts +79 -60
- package/templates/astro/template/.aci.yaml +28 -0
- package/templates/astro/template/.storybook/main.ts +79 -0
- package/templates/astro/template/.storybook/manager.ts +6 -0
- package/templates/astro/template/.storybook/preview.ts +33 -0
- package/templates/astro/template/astro.config.mjs +37 -0
- package/templates/astro/template/package.json.tmpl +41 -0
- package/templates/astro/template/src/cms/contracts/layouts/index.ts +18 -0
- package/templates/astro/template/src/cms/registry.ts +28 -0
- package/templates/astro/template/src/components/chrome/Footer.astro +107 -0
- package/templates/astro/template/src/components/chrome/Header.astro +94 -0
- package/templates/astro/template/src/components/elements/AtomicBlock.astro +15 -0
- package/templates/astro/template/src/components/elements/AtomicBlocks.astro +16 -0
- package/templates/astro/template/src/components/elements/Button.astro +51 -0
- package/templates/astro/template/src/components/elements/ButtonBlock.astro +25 -0
- package/templates/astro/template/src/components/elements/Container.astro +11 -0
- package/templates/astro/template/src/components/elements/Icon.astro +31 -0
- package/templates/astro/template/src/components/elements/Logo.astro +29 -0
- package/templates/astro/template/src/components/elements/RemoteImage.astro +41 -0
- package/templates/astro/template/src/components/sections/ContainerSection.astro +32 -0
- package/templates/astro/template/src/components/sections/FeatureCard.astro +23 -0
- package/templates/astro/template/src/components/sections/FeatureGrid.astro +35 -0
- package/templates/astro/template/src/components/sections/HomeHero.astro +51 -0
- package/templates/astro/template/src/components/sections/StatsBar.astro +33 -0
- package/templates/astro/template/src/design-system/styles.css +399 -0
- package/templates/astro/template/src/design-system/tokens/colors.css +60 -0
- package/templates/astro/template/src/design-system/tokens/components.css +69 -0
- package/templates/astro/template/src/design-system/tokens/index.css +6 -0
- package/templates/astro/template/src/design-system/tokens/radii.css +5 -0
- package/templates/astro/template/src/design-system/tokens/shadows.css +5 -0
- package/templates/astro/template/src/design-system/tokens/spacing.css +13 -0
- package/templates/astro/template/src/design-system/tokens/typography.css +24 -0
- package/templates/astro/template/src/env.d.ts +1 -0
- package/templates/astro/template/src/fixtures/atomicBlocks.ts +33 -0
- package/templates/astro/template/src/fixtures/composition.ts +31 -0
- package/templates/astro/template/src/fixtures/index.ts +17 -0
- package/templates/astro/template/src/fixtures/sections.ts +39 -0
- package/templates/astro/template/src/layouts/SiteLayout.astro +30 -0
- package/templates/astro/template/src/pages/[...slug].astro +61 -0
- package/templates/astro/template/src/render/RenderPage.astro +66 -0
- package/templates/astro/template/src/stories/CompositionStoryFrame.astro +15 -0
- package/templates/astro/template/src/stories/HomeHero.stories.ts +24 -0
- package/templates/astro/template/src/stories/SectionStoryFrame.astro +16 -0
- package/templates/astro/template/src/stories/StoryDocFrame.astro +31 -0
- package/templates/astro/template/tsconfig.json +11 -0
- package/templates/common/.agents/AGENTS.md +37 -0
- package/templates/common/.agents/skills/aci/SKILL.md +162 -0
- package/templates/common/.agents/skills/authoring/SKILL.md +590 -0
- package/templates/common/.agents/skills/authoring/references/block-registry.md +151 -0
- package/templates/common/.agents/skills/authoring/references/contracts.md +153 -0
- package/templates/common/.agents/skills/authoring/references/design-system.md +171 -0
- package/templates/common/.agents/skills/authoring/references/image-assets.md +73 -0
- package/templates/common/.agents/skills/authoring/references/repo-structure.md +157 -0
- package/templates/common/.agents/skills/migration/SKILL.md +160 -0
- package/templates/common/.agents/skills/migration/references/analyzing-source.md +215 -0
- package/templates/common/.agents/skills/migration/references/component-migration.md +200 -0
- package/templates/common/.agents/skills/migration/references/selector-map.md +31 -0
- package/templates/common/.content/.gradial-dam/blobs/sha256/7f/bf/7fbfc7fe230ff12688c496f660119e41d9725c4504d82e310c15665c73c09292 +0 -0
- package/templates/common/.content/.gradial-dam/blobs/sha256/a0/f5/a0f506689de9b15a7055f70103a3f02cd3ba105771ae2de6754df2ede1210d3a +0 -0
- package/templates/common/.content/.gradial-dam/blobs/sha256/dd/b7/ddb7e9642be08317bcd4b2bd26b58ba8d0d34dd7239e03e684a4f3634fa3845b +0 -0
- package/templates/common/.content/.gradial-dam/blobs/sha256/fb/32/fb3260e8286ea8231ea1c77b9c0be92d6edd9026565731eb14cfdcfd6b1b75b3 +0 -0
- package/templates/common/.content/config/site.json +192 -0
- package/templates/common/.content/dam/folders/seed/ast_site_about_hero/asset.json +9 -0
- package/templates/common/.content/dam/folders/seed/ast_site_about_hero/editorial.json +14 -0
- package/templates/common/.content/dam/folders/seed/ast_site_about_hero/governance.json +23 -0
- package/templates/common/.content/dam/folders/seed/ast_site_about_hero/versions/v0001.json +37 -0
- package/templates/common/.content/dam/folders/seed/ast_site_home_hero/asset.json +9 -0
- package/templates/common/.content/dam/folders/seed/ast_site_home_hero/editorial.json +14 -0
- package/templates/common/.content/dam/folders/seed/ast_site_home_hero/governance.json +23 -0
- package/templates/common/.content/dam/folders/seed/ast_site_home_hero/versions/v0001.json +37 -0
- package/templates/common/.content/fragments/navbar/_index.json +25 -0
- package/templates/common/.content/fragments/site-footer/_index.json +62 -0
- package/templates/common/.content/pages/about/_index.json +51 -0
- package/templates/common/.content/pages/home/_index.json +112 -0
- package/templates/common/.content/schemas/site.schema.json +123 -0
- package/templates/common/README.md.tmpl +45 -0
- package/templates/common/contracts/components/button.contract.ts +19 -0
- package/templates/common/contracts/components/container.contract.ts +19 -0
- package/templates/common/contracts/components/featureCard.contract.ts +15 -0
- package/templates/common/contracts/components/featureGrid.contract.ts +16 -0
- package/templates/common/contracts/components/homeHero.contract.ts +36 -0
- package/templates/common/contracts/components/index.ts +21 -0
- package/templates/common/contracts/components/siteFooter.contract.ts +45 -0
- package/templates/common/contracts/components/siteNavigation.contract.ts +30 -0
- package/templates/common/contracts/components/statsBar.contract.ts +19 -0
- package/templates/common/design-system/styles.css +346 -0
- package/templates/common/design-system/tokens/colors.css +110 -0
- package/templates/common/design-system/tokens/components.css +86 -0
- package/templates/common/design-system/tokens/index.css +6 -0
- package/templates/common/design-system/tokens/radii.css +5 -0
- package/templates/common/design-system/tokens/shadows.css +9 -0
- package/templates/common/design-system/tokens/spacing.css +26 -0
- package/templates/common/design-system/tokens/typography.css +32 -0
- package/templates/common/eslint-rules/no-raw-tailwind-values.js +127 -0
- package/templates/common/public/assets/Dwire-model.png +0 -0
- package/templates/common/public/assets/bare-metal-logo.png +0 -0
- package/templates/common/public/assets/meridian-logo.svg +8 -0
- package/templates/common/public/assets/seattle.avif +0 -0
- package/templates/nextjs/template/.aci.yaml +26 -0
- package/templates/nextjs/template/.storybook/main.ts +13 -0
- package/templates/nextjs/template/.storybook/preview.ts +34 -0
- package/templates/nextjs/template/eslint.config.mjs +36 -0
- package/templates/nextjs/template/next-env.d.ts +6 -0
- package/templates/nextjs/template/next.config.ts +8 -0
- package/templates/nextjs/template/package.json.tmpl +46 -0
- package/templates/nextjs/template/postcss.config.mjs +7 -0
- package/templates/nextjs/template/src/app/[[...slug]]/page.tsx +8 -0
- package/templates/nextjs/template/src/app/gradial/assets/[releaseId]/[...path]/route.ts +31 -0
- package/templates/nextjs/template/src/app/layout.tsx +29 -0
- package/templates/nextjs/template/src/cms/contracts/components/button.contract.ts +19 -0
- package/templates/nextjs/template/src/cms/contracts/components/container.contract.ts +20 -0
- package/templates/nextjs/template/src/cms/contracts/components/homeHero.contract.ts +36 -0
- package/templates/nextjs/template/src/cms/contracts/components/index.ts +15 -0
- package/templates/nextjs/template/src/cms/contracts/components/siteFooter.contract.ts +45 -0
- package/templates/nextjs/template/src/cms/contracts/components/siteNavigation.contract.ts +30 -0
- package/templates/nextjs/template/src/cms/contracts/layouts/index.ts +16 -0
- package/templates/nextjs/template/src/cms/registry.ts +28 -0
- package/templates/nextjs/template/src/components/chrome/Footer.tsx +86 -0
- package/templates/nextjs/template/src/components/chrome/Header.tsx +74 -0
- package/templates/nextjs/template/src/components/elements/AtomicBlock.tsx +13 -0
- package/templates/nextjs/template/src/components/elements/Button.tsx +40 -0
- package/templates/nextjs/template/src/components/elements/ButtonBlock.tsx +18 -0
- package/templates/nextjs/template/src/components/elements/Container.tsx +14 -0
- package/templates/nextjs/template/src/components/elements/Icon.tsx +29 -0
- package/templates/nextjs/template/src/components/elements/Logo.tsx +38 -0
- package/templates/nextjs/template/src/components/sections/ContainerSection.tsx +28 -0
- package/templates/nextjs/template/src/components/sections/FeatureCard.tsx +25 -0
- package/templates/nextjs/template/src/components/sections/FeatureGrid.tsx +36 -0
- package/templates/nextjs/template/src/components/sections/HomeHero.tsx +62 -0
- package/templates/nextjs/template/src/components/sections/StatsBar.tsx +30 -0
- package/templates/nextjs/template/src/middleware.ts +4 -0
- package/templates/nextjs/template/src/stories/Button.stories.tsx +38 -0
- package/templates/nextjs/template/src/stories/Header.stories.tsx +30 -0
- package/templates/nextjs/template/src/stories/HomeHero.stories.tsx +33 -0
- package/templates/nextjs/template/tsconfig.json +23 -0
- package/templates/nextjs/template/vercel.json +6 -0
- package/dist/content/contract.d.ts +0 -83
- package/dist/content/contract.js +0 -104
- package/dist/content/tailwind-validator.d.ts +0 -6
- package/dist/content/tailwind-validator.js +0 -31
- package/dist/content/validation.d.ts +0 -108
- package/dist/content/validation.js +0 -183
- package/dist/react/GradialMedia.d.ts +0 -24
- package/dist/react/GradialMedia.js +0 -31
- package/dist/react/GradialPicture.d.ts +0 -14
- package/dist/react/GradialPicture.js +0 -30
- package/dist/react/GradialVideoPlayer.d.ts +0 -13
- package/dist/sveltekit/index.d.ts +0 -25
- package/dist/sveltekit/index.js +0 -66
- package/dist/sveltekit/preview.d.ts +0 -5
- package/dist/sveltekit/preview.js +0 -33
- package/src/types/component.ts +0 -49
- package/src/types/config.ts +0 -37
- package/src/types/data.ts +0 -47
- package/src/types/index.ts +0 -10
- package/src/types/layout.ts +0 -29
- package/src/types/media.ts +0 -125
- package/src/types/page.ts +0 -47
- package/src/types/render-mode.ts +0 -10
- package/src/types/renderer.ts +0 -83
- package/src/types/video.ts +0 -66
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
const UNIT = '(?:px|rem|em|vh|vw|dvh|dvw|svh|svw|ch|ex|cap|ic|lh|rlh|cm|mm|in|pt|pc|%)';
|
|
2
|
+
const HEX_OR_LENGTH = new RegExp(`#[0-9a-fA-F]{3,8}\\b|\\d+(?:\\.\\d+)?${UNIT}`);
|
|
3
|
+
const RATIO_ONLY = /^\d+\/\d+$/;
|
|
4
|
+
const VARIANT_PREFIX = /^(!)?(?:(?: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+):)*/;
|
|
5
|
+
|
|
6
|
+
function extractArbitrary(token) {
|
|
7
|
+
const bare = token.replace(VARIANT_PREFIX, '');
|
|
8
|
+
const open = bare.indexOf('[');
|
|
9
|
+
if (open === -1) return null;
|
|
10
|
+
const close = bare.lastIndexOf(']');
|
|
11
|
+
if (close <= open) return null;
|
|
12
|
+
return bare.slice(open + 1, close);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function isBadArbitrary(content) {
|
|
16
|
+
// Allow anything containing a CSS variable reference.
|
|
17
|
+
if (content.includes('var(--')) return false;
|
|
18
|
+
// Allow values with no digits (selectors, keywords like `&>div`).
|
|
19
|
+
if (!/\d/.test(content) && !content.includes('#')) return false;
|
|
20
|
+
// Strip a leading data-type hint like `length:` or `color:`.
|
|
21
|
+
const value = content.replace(/^[a-z-]+:/, '');
|
|
22
|
+
if (RATIO_ONLY.test(value)) return false;
|
|
23
|
+
if (HEX_OR_LENGTH.test(value)) return true;
|
|
24
|
+
// Unitless numeric value (e.g. z-[60], w-[300]). Flag.
|
|
25
|
+
if (/\d/.test(value)) return true;
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function findBadClassTokens(classString) {
|
|
30
|
+
const tokens = classString.trim().split(/\s+/).filter(Boolean);
|
|
31
|
+
const bad = [];
|
|
32
|
+
for (const token of tokens) {
|
|
33
|
+
const arb = extractArbitrary(token);
|
|
34
|
+
if (arb !== null && isBadArbitrary(arb)) {
|
|
35
|
+
bad.push(token);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return bad;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function findBadStyleMatches(styleString) {
|
|
42
|
+
// Strip var(--...) references so legitimate token names containing digits don't match.
|
|
43
|
+
const stripped = styleString.replace(/var\([^)]*\)/g, '');
|
|
44
|
+
const matches = stripped.match(new RegExp(HEX_OR_LENGTH.source, 'g'));
|
|
45
|
+
return matches || [];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function reportClass(context, node, value) {
|
|
49
|
+
if (typeof value !== 'string' || !value.includes('[')) return;
|
|
50
|
+
const bad = findBadClassTokens(value);
|
|
51
|
+
if (bad.length > 0) {
|
|
52
|
+
context.report({
|
|
53
|
+
node,
|
|
54
|
+
message: `Raw arbitrary Tailwind values are not allowed: ${bad.join(', ')}. Use design system tokens (var(--...)) instead.`
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function reportStyle(context, node, value) {
|
|
60
|
+
if (typeof value !== 'string') return;
|
|
61
|
+
const bad = findBadStyleMatches(value);
|
|
62
|
+
if (bad.length > 0) {
|
|
63
|
+
context.report({
|
|
64
|
+
node,
|
|
65
|
+
message: `Raw values are not allowed in inline style: ${bad.join(', ')}. Use design system tokens (var(--...)) instead.`
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** @type {import('eslint').Rule.RuleModule} */
|
|
71
|
+
const noRawTailwindValues = {
|
|
72
|
+
meta: {
|
|
73
|
+
type: 'suggestion',
|
|
74
|
+
docs: {
|
|
75
|
+
description: 'Disallow raw hex/length values in Tailwind arbitrary values and inline style attributes; require design tokens via var(--...).'
|
|
76
|
+
},
|
|
77
|
+
schema: []
|
|
78
|
+
},
|
|
79
|
+
create(context) {
|
|
80
|
+
function handleClassNode(node, value) {
|
|
81
|
+
reportClass(context, node, value);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function handleStyleStringNode(node, value) {
|
|
85
|
+
reportStyle(context, node, value);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function visitClassLiteral(node) {
|
|
89
|
+
handleClassNode(node, node.value);
|
|
90
|
+
}
|
|
91
|
+
function visitClassTemplate(node) {
|
|
92
|
+
for (const quasi of node.quasis) handleClassNode(node, quasi.value.raw);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
// JSX/Astro class attribute
|
|
97
|
+
[`JSXAttribute[name.name=/^(class|className)$/] > Literal`]: visitClassLiteral,
|
|
98
|
+
[`JSXAttribute[name.name=/^(class|className)$/] > TemplateLiteral`]: visitClassTemplate,
|
|
99
|
+
|
|
100
|
+
// Object-form { class: '...' } (e.g. clsx args, defineProps defaults)
|
|
101
|
+
'Property[key.name="class"] > Literal'(node) {
|
|
102
|
+
handleClassNode(node, node.value);
|
|
103
|
+
},
|
|
104
|
+
'Property[key.name="class"] > TemplateLiteral'(node) {
|
|
105
|
+
for (const quasi of node.quasis) handleClassNode(node, quasi.value.raw);
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
// JSX/Astro style="..." (string form, common in Astro and HTML)
|
|
109
|
+
'JSXAttribute[name.name="style"] > Literal'(node) {
|
|
110
|
+
handleStyleStringNode(node, node.value);
|
|
111
|
+
},
|
|
112
|
+
'JSXAttribute[name.name="style"] > TemplateLiteral'(node) {
|
|
113
|
+
for (const quasi of node.quasis) handleStyleStringNode(node, quasi.value.raw);
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
// React style={{ color: '#fff', padding: '10px' }}
|
|
117
|
+
'JSXAttribute[name.name="style"] JSXExpressionContainer > ObjectExpression > Property > Literal'(node) {
|
|
118
|
+
if (typeof node.value === 'string') handleStyleStringNode(node, node.value);
|
|
119
|
+
},
|
|
120
|
+
'JSXAttribute[name.name="style"] JSXExpressionContainer > ObjectExpression > Property > TemplateLiteral'(node) {
|
|
121
|
+
for (const quasi of node.quasis) handleStyleStringNode(node, quasi.value.raw);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export default noRawTailwindValues;
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 40" fill="#0f172a">
|
|
2
|
+
<g aria-label="Meridian">
|
|
3
|
+
<circle cx="16" cy="20" r="6" fill="#0f172a"/>
|
|
4
|
+
<path d="M16 6v6M16 28v6M6 20h6M20 20h6" stroke="#0f172a" stroke-width="3" stroke-linecap="round"/>
|
|
5
|
+
<ellipse cx="16" cy="20" rx="14" ry="5" fill="none" stroke="#0f172a" stroke-width="2" transform="rotate(-30 16 20)"/>
|
|
6
|
+
</g>
|
|
7
|
+
<text x="42" y="26" font-family="Space Grotesk, Inter, sans-serif" font-size="22" font-weight="700" letter-spacing="-0.02em" fill="#0f172a">Meridian</text>
|
|
8
|
+
</svg>
|
|
Binary file
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
version: "1"
|
|
2
|
+
siteId: "site_nextjs"
|
|
3
|
+
domain: "meridian.local"
|
|
4
|
+
framework: next
|
|
5
|
+
|
|
6
|
+
source:
|
|
7
|
+
root: "./"
|
|
8
|
+
|
|
9
|
+
componentRegistry: ./src/cms/contracts/components/index.ts
|
|
10
|
+
layoutRegistry: ./src/cms/contracts/layouts/index.ts
|
|
11
|
+
|
|
12
|
+
capabilities:
|
|
13
|
+
staticRender: true
|
|
14
|
+
ssr: true
|
|
15
|
+
ssrIslands: true
|
|
16
|
+
clientIslands: true
|
|
17
|
+
fragmentRender: true
|
|
18
|
+
|
|
19
|
+
routes:
|
|
20
|
+
cmsManaged: "/[...slug]"
|
|
21
|
+
frameworkOwned:
|
|
22
|
+
- "/api/*"
|
|
23
|
+
- "/_next/*"
|
|
24
|
+
- "/.gradial-dam/*"
|
|
25
|
+
|
|
26
|
+
rendererProtocol: stdio-json
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { StorybookConfig } from '@storybook/nextjs';
|
|
2
|
+
|
|
3
|
+
const config: StorybookConfig = {
|
|
4
|
+
stories: ['../src/**/*.stories.@(ts|tsx|mdx)'],
|
|
5
|
+
addons: ['@storybook/addon-docs'],
|
|
6
|
+
framework: {
|
|
7
|
+
name: '@storybook/nextjs',
|
|
8
|
+
options: {}
|
|
9
|
+
},
|
|
10
|
+
staticDirs: ['../public'],
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default config;
|
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
// Storybook decorator types are verbose; keep the starter example focused.
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
+
(Story: any, context: any) => {
|
|
19
|
+
const theme = context.globals.theme || 'light';
|
|
20
|
+
document.body.className = `theme-${theme} min-h-screen bg-[var(--color-surface-default)]`;
|
|
21
|
+
return Story();
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
parameters: {
|
|
25
|
+
layout: 'fullscreen',
|
|
26
|
+
options: {
|
|
27
|
+
storySort: {
|
|
28
|
+
order: ['Core Atomic Blocks', 'Composition', '*']
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default preview;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { dirname, resolve } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { includeIgnoreFile } from '@eslint/compat';
|
|
4
|
+
import { FlatCompat } from '@eslint/eslintrc';
|
|
5
|
+
import eslintPlugin from 'eslint-plugin-import';
|
|
6
|
+
import noRawTailwind from './eslint-rules/no-raw-tailwind-values.js';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
10
|
+
const compat = new FlatCompat({ baseDirectory: __dirname });
|
|
11
|
+
const gitignorePath = resolve(__dirname, '.gitignore');
|
|
12
|
+
|
|
13
|
+
const eslintConfig = [
|
|
14
|
+
includeIgnoreFile(gitignorePath),
|
|
15
|
+
{ ignores: ['next-env.d.ts'] },
|
|
16
|
+
...compat.extends('next/core-web-vitals', 'next/typescript'),
|
|
17
|
+
{
|
|
18
|
+
plugins: {
|
|
19
|
+
import: eslintPlugin,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
plugins: {
|
|
24
|
+
'aci-rules': {
|
|
25
|
+
rules: {
|
|
26
|
+
'no-raw-tailwind-values': noRawTailwind,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
rules: {
|
|
31
|
+
'aci-rules/no-raw-tailwind-values': 'warn',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
export default eslintConfig;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/// <reference types="next" />
|
|
2
|
+
/// <reference types="next/image-types/global" />
|
|
3
|
+
/// <reference path="./.next/types/routes.d.ts" />
|
|
4
|
+
|
|
5
|
+
// NOTE: This file should not be edited
|
|
6
|
+
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{siteName}}",
|
|
3
|
+
"version": "{{version}}",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "ACI_CONTENT_PROVIDER=file next dev -H 0.0.0.0",
|
|
8
|
+
"build": "next build",
|
|
9
|
+
"preview": "next start -H 0.0.0.0",
|
|
10
|
+
"typecheck": "tsc --noEmit",
|
|
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
|
+
"lint": "eslint .",
|
|
17
|
+
"storybook": "storybook dev -p 6006",
|
|
18
|
+
"build:storybook": "storybook build"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@gradial/aci": "0.2.0-rc.0",
|
|
22
|
+
"js-yaml": "^4.1.1",
|
|
23
|
+
"next": "^15.1.6",
|
|
24
|
+
"react": "^19.0.0",
|
|
25
|
+
"react-dom": "^19.0.0",
|
|
26
|
+
"zod": "^4.0.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/js-yaml": "^4.0.9",
|
|
30
|
+
"@types/node": "^24.10.1",
|
|
31
|
+
"@types/react": "^19.0.0",
|
|
32
|
+
"@types/react-dom": "^19.0.0",
|
|
33
|
+
"@eslint/compat": "^1.2.0",
|
|
34
|
+
"@eslint/eslintrc": "^3.2.0",
|
|
35
|
+
"eslint": "^9.18.0",
|
|
36
|
+
"eslint-config-next": "^15.1.6",
|
|
37
|
+
"eslint-plugin-import": "^2.29.1",
|
|
38
|
+
"tailwindcss": "^4.2.4",
|
|
39
|
+
"@tailwindcss/postcss": "^4.2.4",
|
|
40
|
+
"tsx": "^4.20.0",
|
|
41
|
+
"typescript": "5.9.3",
|
|
42
|
+
"storybook": "^9.0.0",
|
|
43
|
+
"@storybook/nextjs": "^9.0.0",
|
|
44
|
+
"@storybook/addon-docs": "^9.0.0"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { getReleaseAssetResponse } from '@gradial/aci/content';
|
|
2
|
+
import { FileContentProvider } from '@gradial/aci/providers/file';
|
|
3
|
+
|
|
4
|
+
const LOCAL_RELEASE_ID = 'local';
|
|
5
|
+
|
|
6
|
+
type AssetRouteContext = {
|
|
7
|
+
params: Promise<{
|
|
8
|
+
releaseId?: string;
|
|
9
|
+
path?: string[];
|
|
10
|
+
}>;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const runtime = 'nodejs';
|
|
14
|
+
export const dynamic = 'force-dynamic';
|
|
15
|
+
|
|
16
|
+
export async function GET(_request: Request, { params }: AssetRouteContext): Promise<Response> {
|
|
17
|
+
const resolvedParams = await params;
|
|
18
|
+
const releaseId = resolvedParams.releaseId || '';
|
|
19
|
+
const assetPath = '/' + (resolvedParams.path || []).join('/');
|
|
20
|
+
if (!releaseId || assetPath === '/') {
|
|
21
|
+
return new Response('asset not found', { status: 404 });
|
|
22
|
+
}
|
|
23
|
+
if (releaseId === LOCAL_RELEASE_ID) {
|
|
24
|
+
return new FileContentProvider().fetchRaw(assetPath);
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
return await getReleaseAssetResponse({ releaseId, assetPath });
|
|
28
|
+
} catch {
|
|
29
|
+
return new Response('asset not found', { status: 404 });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { Inter, Space_Grotesk } from 'next/font/google';
|
|
3
|
+
import { DevRefresh } from '@gradial/aci/next';
|
|
4
|
+
import '@/design-system/styles.css';
|
|
5
|
+
|
|
6
|
+
const inter = Inter({
|
|
7
|
+
subsets: ['latin'],
|
|
8
|
+
variable: '--font-inter',
|
|
9
|
+
display: 'swap',
|
|
10
|
+
weight: ['400', '500', '600', '700'],
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const spaceGrotesk = Space_Grotesk({
|
|
14
|
+
subsets: ['latin'],
|
|
15
|
+
variable: '--font-space-grotesk',
|
|
16
|
+
display: 'swap',
|
|
17
|
+
weight: ['400', '500', '600', '700'],
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export default function Layout({ children }: { children: ReactNode }) {
|
|
21
|
+
return (
|
|
22
|
+
<html lang="en" className={`${inter.variable} ${spaceGrotesk.variable}`}>
|
|
23
|
+
<body>
|
|
24
|
+
{children}
|
|
25
|
+
<DevRefresh />
|
|
26
|
+
</body>
|
|
27
|
+
</html>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineComponentContract } from '@gradial/aci';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
export const schema = z.object({
|
|
5
|
+
label: z.string().min(1),
|
|
6
|
+
href: z.string().min(1),
|
|
7
|
+
variant: z.enum(['primary', 'secondary', 'tertiary', 'outline', 'ghost']).optional(),
|
|
8
|
+
newWindow: z.boolean().optional(),
|
|
9
|
+
icon: z.string().optional(),
|
|
10
|
+
iconPosition: z.enum(['before', 'after']).optional(),
|
|
11
|
+
className: z.string().optional(),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export type ContentProps = z.infer<typeof schema>;
|
|
15
|
+
|
|
16
|
+
export const buttonContract = defineComponentContract({
|
|
17
|
+
id: 'button',
|
|
18
|
+
props: schema,
|
|
19
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { defineComponentContract } from '@gradial/aci';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
export const schema = z.object({
|
|
5
|
+
theme: z.enum(['auto', 'light', 'dark']).optional(),
|
|
6
|
+
className: z.string().optional(),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export type ContentProps = z.infer<typeof schema>;
|
|
10
|
+
|
|
11
|
+
export const containerContract = defineComponentContract({
|
|
12
|
+
id: 'container',
|
|
13
|
+
props: schema,
|
|
14
|
+
slots: {
|
|
15
|
+
content: {
|
|
16
|
+
allowed: ['button'],
|
|
17
|
+
multiple: true,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { defineComponentContract, ImageSchema } from '@gradial/aci';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
export const schema = z.object({
|
|
5
|
+
eyebrow: z.string().optional(),
|
|
6
|
+
headline: z.string().min(1),
|
|
7
|
+
description: z.string().optional(),
|
|
8
|
+
ctaLabel: z.string().min(1),
|
|
9
|
+
ctaHref: z.string().min(1),
|
|
10
|
+
image: ImageSchema,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export type ContentProps = z.infer<typeof schema>;
|
|
14
|
+
|
|
15
|
+
export const homeHeroContract = defineComponentContract({
|
|
16
|
+
id: 'home_hero',
|
|
17
|
+
props: schema,
|
|
18
|
+
imageSlots: {
|
|
19
|
+
image: {
|
|
20
|
+
formats: ['image/avif', 'image/webp', 'image/jpeg'],
|
|
21
|
+
sizes: '100vw',
|
|
22
|
+
outputs: [
|
|
23
|
+
{
|
|
24
|
+
aspectRatio: '16:9',
|
|
25
|
+
widths: [768, 1280, 1920],
|
|
26
|
+
media: '(min-width: 768px)',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
aspectRatio: '3:4',
|
|
30
|
+
widths: [480, 720, 960],
|
|
31
|
+
media: '(max-width: 767px)',
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { buttonContract } from './button.contract';
|
|
2
|
+
import { containerContract } from './container.contract';
|
|
3
|
+
import { homeHeroContract } from './homeHero.contract';
|
|
4
|
+
import { siteNavigationContract } from './siteNavigation.contract';
|
|
5
|
+
import { siteFooterContract } from './siteFooter.contract';
|
|
6
|
+
|
|
7
|
+
const componentContracts = [
|
|
8
|
+
homeHeroContract,
|
|
9
|
+
containerContract,
|
|
10
|
+
buttonContract,
|
|
11
|
+
siteNavigationContract,
|
|
12
|
+
siteFooterContract,
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
export default componentContracts;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { defineComponentContract } from '@gradial/aci';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
const linkSchema = z.object({
|
|
5
|
+
id: z.string().min(1),
|
|
6
|
+
label: z.string().min(1),
|
|
7
|
+
href: z.string().min(1),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const groupSchema = z.object({
|
|
11
|
+
id: z.string().min(1),
|
|
12
|
+
title: z.string(),
|
|
13
|
+
links: z.array(linkSchema),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const columnSchema = z.object({
|
|
17
|
+
id: z.string().min(1),
|
|
18
|
+
title: z.string().optional(),
|
|
19
|
+
links: z.array(linkSchema).optional(),
|
|
20
|
+
groups: z.array(groupSchema).optional(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const socialSchema = linkSchema.extend({
|
|
24
|
+
icon: z.string().optional(),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export const schema = z.object({
|
|
28
|
+
brandHref: z.string().min(1),
|
|
29
|
+
brandLabel: z.string().min(1),
|
|
30
|
+
brandLogo: z.object({
|
|
31
|
+
src: z.string(),
|
|
32
|
+
alt: z.string(),
|
|
33
|
+
}).nullable().optional(),
|
|
34
|
+
columns: z.array(columnSchema),
|
|
35
|
+
social: z.array(socialSchema).optional(),
|
|
36
|
+
legalLinks: z.array(linkSchema).optional(),
|
|
37
|
+
copyright: z.string().optional(),
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export type ContentProps = z.infer<typeof schema>;
|
|
41
|
+
|
|
42
|
+
export const siteFooterContract = defineComponentContract({
|
|
43
|
+
id: 'site-footer',
|
|
44
|
+
props: schema,
|
|
45
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { defineComponentContract } from '@gradial/aci';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
const linkSchema = z.object({
|
|
5
|
+
id: z.string().min(1),
|
|
6
|
+
label: z.string().min(1),
|
|
7
|
+
href: z.string().min(1),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const utilitySchema = linkSchema.extend({
|
|
11
|
+
variant: z.enum(['primary', 'secondary', 'tertiary', 'outline', 'ghost']).optional(),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export const schema = z.object({
|
|
15
|
+
brandHref: z.string().min(1),
|
|
16
|
+
brandLabel: z.string().min(1),
|
|
17
|
+
brandLogo: z.object({
|
|
18
|
+
src: z.string(),
|
|
19
|
+
alt: z.string(),
|
|
20
|
+
}).nullable().optional(),
|
|
21
|
+
navigation: z.array(linkSchema),
|
|
22
|
+
utilities: z.array(utilitySchema).optional(),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export type ContentProps = z.infer<typeof schema>;
|
|
26
|
+
|
|
27
|
+
export const siteNavigationContract = defineComponentContract({
|
|
28
|
+
id: 'site-navigation',
|
|
29
|
+
props: schema,
|
|
30
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const layoutContracts = [
|
|
2
|
+
{
|
|
3
|
+
name: 'default',
|
|
4
|
+
slots: [
|
|
5
|
+
{ name: 'header', required: false },
|
|
6
|
+
{ name: 'main', required: true },
|
|
7
|
+
{ name: 'footer', required: false },
|
|
8
|
+
],
|
|
9
|
+
defaults: {
|
|
10
|
+
header: [{ kind: 'fragment-ref', fragmentId: 'navbar', inline: true }],
|
|
11
|
+
footer: [{ kind: 'fragment-ref', fragmentId: 'site-footer', inline: true }],
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
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';
|
|
11
|
+
import { ContainerSection } from '@/components/sections/ContainerSection';
|
|
12
|
+
import { ButtonBlock } from '@/components/elements/ButtonBlock';
|
|
13
|
+
import { Header } from '@/components/chrome/Header';
|
|
14
|
+
import { Footer } from '@/components/chrome/Footer';
|
|
15
|
+
import { FeatureGrid } from '@/components/sections/FeatureGrid';
|
|
16
|
+
import { FeatureCard } from '@/components/sections/FeatureCard';
|
|
17
|
+
import { StatsBar } from '@/components/sections/StatsBar';
|
|
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
|
+
]);
|