@gradial/aci 0.1.52-rc.8 → 0.1.52
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/CHANGELOG.md +126 -0
- package/README.md +86 -5
- package/dist/astro/error-page.js +1 -0
- package/dist/astro/index.js +4 -0
- package/dist/astro/page.d.ts +5 -2
- package/dist/astro/page.js +35 -23
- package/dist/astro/preview.js +2 -17
- package/dist/audience-data-models.d.ts +308 -197
- package/dist/audience-data-models.js +313 -51
- package/dist/cli/compile-registry.mjs +6 -34
- package/dist/cli/mintlify-render.mjs +8 -0
- package/dist/collect/aci.js +1 -1
- package/dist/collect/aci.js.sha256 +1 -1
- package/dist/collect/api.d.ts +6 -7
- package/dist/collect/api.js +21 -8
- package/dist/collect/assignments.d.ts +7 -9
- package/dist/collect/assignments.js +23 -32
- package/dist/collect/batcher.d.ts +9 -7
- package/dist/collect/batcher.js +6 -5
- package/dist/collect/consent/envelope.d.ts +7 -1
- package/dist/collect/consent/envelope.js +3 -1
- package/dist/collect/consent/mapping.d.ts +2 -0
- package/dist/collect/consent/mapping.js +1 -0
- package/dist/collect/consenthold.d.ts +38 -0
- package/dist/collect/consenthold.js +82 -0
- package/dist/collect/declarative.js +7 -5
- package/dist/collect/gapbuffer.d.ts +13 -4
- package/dist/collect/gapbuffer.js +21 -10
- package/dist/collect/index.js +78 -21
- package/dist/collect/pageviews.d.ts +11 -11
- package/dist/collect/pageviews.js +27 -22
- package/dist/consent-banner/index.d.ts +17 -0
- package/dist/consent-banner/index.js +23 -0
- package/dist/content/index.d.ts +2 -1
- package/dist/content/index.js +4 -1
- package/dist/content/provider.d.ts +16 -2
- package/dist/content/provider.js +5 -1
- package/dist/content/resolve-slots.d.ts +24 -2
- package/dist/content/resolve-slots.js +127 -21
- package/dist/content/types.d.ts +5 -1
- package/dist/edge/expression-capabilities.v1.d.ts +106 -0
- package/dist/edge/expression-capabilities.v1.js +165 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.js +0 -1
- package/dist/internal/domain/edge/identity.d.ts +47 -4
- package/dist/internal/domain/edge/identity.js +130 -26
- package/dist/internal/domain/edge/index.d.ts +1 -1
- package/dist/internal/domain/edge/index.js +1 -1
- package/dist/internal/domain/edge/mimic_token.d.ts +14 -0
- package/dist/internal/domain/edge/mimic_token.js +125 -0
- package/dist/internal/domain/edge/personalization-core.d.ts +61 -22
- package/dist/internal/domain/edge/personalization-core.js +790 -200
- package/dist/internal/domain/edge/personalization_index.d.ts +17 -0
- package/dist/internal/domain/edge/personalization_index.js +55 -0
- package/dist/internal/domain/edge/resolve.js +76 -39
- package/dist/internal/domain/edge/testdata/flat_only_validator_v1.d.ts +10 -0
- package/dist/internal/domain/edge/testdata/flat_only_validator_v1.js +253 -0
- package/dist/internal/domain/edge/types.d.ts +82 -78
- package/dist/internal/domain/edge/types.js +3 -3
- package/dist/internal/domain/edge/variant_key.d.ts +4 -0
- package/dist/internal/domain/edge/variant_key.js +56 -0
- package/dist/internal/platform/collectionstore/errors.d.ts +24 -0
- package/dist/internal/platform/collectionstore/errors.js +48 -0
- package/dist/mintlify/blocks.d.ts +6 -0
- package/dist/mintlify/blocks.js +201 -0
- package/dist/mintlify/config.d.ts +3 -0
- package/dist/mintlify/config.js +77 -0
- package/dist/mintlify/index.d.ts +3 -0
- package/dist/mintlify/index.js +2 -0
- package/dist/mintlify/json.d.ts +8 -0
- package/dist/mintlify/json.js +37 -0
- package/dist/mintlify/materialize.d.ts +14 -0
- package/dist/mintlify/materialize.js +254 -0
- package/dist/mintlify/types.d.ts +74 -0
- package/dist/mintlify/types.js +1 -0
- package/dist/mintlify/validate.d.ts +7 -0
- package/dist/mintlify/validate.js +256 -0
- package/dist/next/assignments-navigation.d.ts +4 -0
- package/dist/next/assignments-navigation.js +18 -0
- package/dist/next/assignments-script.d.ts +3 -2
- package/dist/next/assignments-script.js +5 -5
- package/dist/next/error-pages.d.ts +4 -0
- package/dist/next/error-pages.js +4 -0
- package/dist/next/error-seat-payload.d.ts +2 -1
- package/dist/next/error-seat-payload.js +14 -24
- package/dist/next/error-seat.js +7 -2
- package/dist/next/index.d.ts +1 -1
- package/dist/next/index.js +3 -1
- package/dist/next/page.d.ts +2 -1
- package/dist/next/page.js +15 -4
- package/dist/next/release-context.d.ts +30 -0
- package/dist/next/release-context.js +56 -0
- package/dist/next/render.d.ts +1 -1
- package/dist/next/render.js +15 -5
- package/dist/next/server.d.ts +9 -3
- package/dist/next/server.js +17 -32
- package/dist/preview/core.d.ts +1 -0
- package/dist/preview/core.js +27 -0
- package/dist/react/VideoPlayer.d.ts +3 -3
- package/dist/react/index.d.ts +3 -3
- package/dist/registry.d.ts +4 -2
- package/dist/testing/conformance/checks.d.ts +2 -2
- package/dist/testing/conformance/checks.js +2 -0
- package/dist/testing/conformance/index.d.ts +1 -0
- package/dist/testing/conformance/index.js +1 -0
- package/dist/testing/conformance/next-stubs.d.ts +6 -0
- package/dist/testing/conformance/next-stubs.js +9 -0
- package/dist/testing/conformance/preset.d.ts +3 -2
- package/dist/testing/conformance/preset.js +15 -8
- package/dist/testing/conformance/root-identity.d.ts +31 -0
- package/dist/testing/conformance/root-identity.js +361 -0
- package/dist/testing/conformance/stubs/next-image.d.ts +7 -0
- package/dist/testing/conformance/stubs/next-image.js +5 -0
- package/dist/testing/conformance/stubs/next-link.d.ts +7 -0
- package/dist/testing/conformance/stubs/next-link.js +4 -0
- package/dist/testing/conformance/types.d.ts +5 -2
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.js +4 -3
- package/dist/types/block-ref.js +2 -2
- package/dist/types/component.d.ts +9 -0
- package/dist/types/config.d.ts +0 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.js +0 -1
- package/dist/types/page.d.ts +0 -1
- package/migrations/conformance-registry.md +22 -0
- package/migrations/experiment-goal-ids.md +43 -0
- package/package.json +21 -7
- package/src/cli/compile-registry.mjs +6 -30
- package/src/cli/mintlify-render.mjs +9 -0
- package/src/types/block-ref.test.ts +16 -1
- package/src/types/block-ref.ts +2 -2
- package/src/types/component.ts +10 -0
- package/src/types/config.ts +0 -1
- package/src/types/index.ts +0 -1
- package/src/types/page.ts +0 -1
- package/templates/astro/starter-content/src/components/chrome/Footer.astro +5 -3
- package/templates/astro/starter-content/src/components/chrome/Header.astro +5 -3
- package/templates/astro/starter-content/src/components/elements/Button.astro +5 -2
- package/templates/astro/starter-content/src/components/elements/ButtonBlock.astro +5 -3
- package/templates/astro/starter-content/src/components/sections/ContainerSection.astro +4 -3
- package/templates/astro/starter-content/src/components/sections/FeatureCard.astro +4 -3
- package/templates/astro/starter-content/src/components/sections/FeatureGrid.astro +4 -3
- package/templates/astro/starter-content/src/components/sections/HomeHero.astro +5 -3
- package/templates/astro/starter-content/src/components/sections/PersonalizationChoice.astro +4 -3
- package/templates/astro/starter-content/src/components/sections/StatsBar.astro +4 -3
- package/templates/astro/starter-content/src/fixtures/sections.ts +1 -1
- package/templates/astro/starter-content/src/stories/CompositionStoryFrame.astro +7 -2
- package/templates/astro/template/.aci.yaml.tmpl +0 -1
- package/templates/astro/template/package.json.tmpl +5 -5
- package/templates/astro/template/src/layouts/SiteLayout.astro +2 -2
- package/templates/common/.agents/skills/aci/SKILL.md +58 -1
- package/templates/common/.agents/skills/authoring/SKILL.md +194 -42
- package/templates/common/.agents/skills/authoring/references/block-registry.md +19 -3
- package/templates/common/.agents/skills/authoring/references/contracts.md +9 -30
- package/templates/common/.agents/skills/authoring/references/repo-structure.md +5 -4
- package/templates/common/.agents/skills/authoring/references/sdk-server-functions.md +3 -3
- package/templates/common/.agents/skills/dam-delivery/SKILL.md +216 -0
- package/templates/common/.agents/skills/dam-delivery/references/permalink-grammar.md +167 -0
- package/templates/common/.agents/skills/migration/references/canon-migration.md +18 -67
- package/templates/common/.agents/skills/migration/references/selector-map.md +1 -1
- package/templates/common/.content/fragments/navbar/_index.json +24 -0
- package/templates/common/.content/fragments/site-footer/_index.json +61 -0
- package/templates/common/.content/pages/404/_index.json +4 -2
- package/templates/common/.content/pages/_index.json +0 -1
- package/templates/common/.content/pages/error/_index.json +4 -2
- package/templates/common/.content/schemas/site.schema.json +11 -1
- package/templates/common/.content/templates/error.json +24 -0
- package/templates/common/.content/templates/home.json +28 -0
- package/templates/common/.content/templates/site.json +8 -0
- package/templates/common/.content/templates/standard.json +24 -0
- package/templates/common/.nvmrc +1 -1
- package/templates/common/starter-content/.content/config/site.json +1 -1
- package/templates/common/starter-content/.content/dam/README.md +74 -0
- package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000101}/asset.json +1 -1
- package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000102}/asset.json +1 -1
- package/templates/common/starter-content/.content/pages/404/_index.json +1 -2
- package/templates/common/starter-content/.content/pages/{home/_index.json → _index.json} +14 -3
- package/templates/common/starter-content/.content/pages/about/_index.json +2 -2
- package/templates/common/starter-content/.content/pages/error/_index.json +1 -2
- package/templates/common/starter-content/.content/patterns/components/button.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/container.json +8 -3
- package/templates/common/starter-content/.content/patterns/components/feature_card.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/feature_grid.json +5 -3
- package/templates/common/starter-content/.content/patterns/components/home_hero.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/personalization_choice.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/site-footer.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/site-navigation.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/stats_bar.json +2 -2
- package/templates/common/starter-content/.content/schemas/site.schema.json +11 -1
- package/templates/nextjs/starter-content/src/components/chrome/Footer.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/chrome/Header.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/elements/Button.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/elements/ButtonBlock.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/sections/ContainerSection.tsx +4 -2
- package/templates/nextjs/starter-content/src/components/sections/FeatureCard.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/sections/FeatureGrid.tsx +4 -2
- package/templates/nextjs/starter-content/src/components/sections/HomeHero.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/sections/PersonalizationChoice.tsx +4 -2
- package/templates/nextjs/starter-content/src/components/sections/StatsBar.tsx +4 -3
- package/templates/nextjs/template/.aci.yaml +0 -1
- package/templates/nextjs/template/.aci.yaml.tmpl +0 -1
- package/templates/nextjs/template/package.json.tmpl +4 -3
- package/templates/nextjs/template/src/app/_components/c15t-bridge.ts +30 -0
- package/templates/nextjs/template/src/app/_components/c15t-consent-ui.tsx +37 -0
- package/templates/nextjs/template/src/app/_components/consent-manager.css +63 -0
- package/templates/nextjs/template/src/app/_components/consent-manager.tsx +76 -0
- package/templates/nextjs/template/src/app/fonts/inter/OFL.txt +93 -0
- package/templates/nextjs/template/src/app/fonts/inter/inter-latin.woff2 +0 -0
- package/templates/nextjs/template/src/app/fonts/space-grotesk/OFL.txt +93 -0
- package/templates/nextjs/template/src/app/fonts/space-grotesk/space-grotesk-latin.woff2 +0 -0
- package/templates/nextjs/template/src/app/layout.tsx +12 -7
- package/templates/nextjs/template/tests/conformance.test.ts.tmpl +1 -0
- package/dist/define-layout.d.ts +0 -6
- package/dist/define-layout.js +0 -14
- package/dist/edge/personalization-core.d.ts +0 -11
- package/dist/edge/personalization-core.js +0 -269
- package/dist/internal/domain/edge/compose.d.ts +0 -24
- package/dist/internal/domain/edge/compose.js +0 -89
- package/dist/internal/domain/edge/record/codec.d.ts +0 -71
- package/dist/internal/domain/edge/record/codec.js +0 -401
- package/dist/next/collect-route.d.ts +0 -19
- package/dist/next/collect-route.js +0 -459
- package/dist/next/edge-config.d.ts +0 -1
- package/dist/next/edge-config.js +0 -92
- package/dist/next/envelope-digest.d.ts +0 -21
- package/dist/next/envelope-digest.js +0 -58
- package/dist/next/middleware.d.ts +0 -40
- package/dist/next/middleware.js +0 -475
- package/dist/next/personalization-host.d.ts +0 -134
- package/dist/next/personalization-host.js +0 -270
- package/dist/next/root-layout.d.ts +0 -4
- package/dist/next/root-layout.js +0 -5
- package/dist/next/vercel-collect-sdk-route.d.ts +0 -27
- package/dist/next/vercel-collect-sdk-route.js +0 -181
- package/dist/next/vercel-edge-projection-v1.d.ts +0 -24
- package/dist/next/vercel-edge-projection-v1.js +0 -880
- package/dist/next/vercel-personalization.d.ts +0 -4
- package/dist/next/vercel-personalization.js +0 -4
- package/dist/next/vercel-s3-personalization.d.ts +0 -79
- package/dist/next/vercel-s3-personalization.js +0 -570
- package/dist/types/layout.d.ts +0 -24
- package/src/types/layout.ts +0 -29
- package/templates/astro/starter-content/src/render/RenderPage.astro +0 -67
- package/templates/astro/template/src/cms/contracts/layouts/index.ts +0 -18
- package/templates/common/starter-content/.content/patterns/layouts/default.json +0 -14
- package/templates/nextjs/starter-content/src/components/elements/AtomicBlock.tsx +0 -13
- package/templates/nextjs/template/src/cms/contracts/layouts/index.ts +0 -16
- /package/dist/{types/layout.js → cli/mintlify-render.d.mts} +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000101}/editorial.json +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000101}/governance.json +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000101}/versions/v0001.json +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000102}/editorial.json +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000102}/governance.json +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000102}/versions/v0001.json +0 -0
|
@@ -27,7 +27,17 @@
|
|
|
27
27
|
},
|
|
28
28
|
"overlayResolution": {
|
|
29
29
|
"type": "array",
|
|
30
|
-
"items": {
|
|
30
|
+
"items": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"minLength": 1,
|
|
33
|
+
"pattern": "^[^;=/\u0009-\u000d\u0020\u0085\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]+$",
|
|
34
|
+
"not": {
|
|
35
|
+
"anyOf": [
|
|
36
|
+
{ "enum": [".", "..", "experiment", "experimentArm"] },
|
|
37
|
+
{ "pattern": "^experiment\\." }
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
31
41
|
},
|
|
32
42
|
"brandHref": { "type": "string" },
|
|
33
43
|
"brandLogo": {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$type": "pageTemplate",
|
|
3
|
+
"name": "error",
|
|
4
|
+
"description": "Error pages are a single hero that points visitors back home.",
|
|
5
|
+
"routes": ["/404", "/error"],
|
|
6
|
+
"regions": [
|
|
7
|
+
{
|
|
8
|
+
"name": "header",
|
|
9
|
+
"defaults": ["navbar"],
|
|
10
|
+
"sequence": [{ "id": "navbar", "fragment": ["navbar"] }]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"name": "main",
|
|
14
|
+
"sequence": [
|
|
15
|
+
{ "id": "hero", "component": "home_hero" }
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"name": "footer",
|
|
20
|
+
"defaults": ["site-footer"],
|
|
21
|
+
"sequence": [{ "id": "site-footer", "fragment": ["site-footer"] }]
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$type": "pageTemplate",
|
|
3
|
+
"name": "home",
|
|
4
|
+
"description": "The home page: a hero, the feature grid, the personalization choice, the stats bar, and the closing call-to-action container, in that order.",
|
|
5
|
+
"routes": ["/"],
|
|
6
|
+
"regions": [
|
|
7
|
+
{
|
|
8
|
+
"name": "header",
|
|
9
|
+
"defaults": ["navbar"],
|
|
10
|
+
"sequence": [{ "id": "navbar", "fragment": ["navbar"] }]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"name": "main",
|
|
14
|
+
"sequence": [
|
|
15
|
+
{ "id": "hero", "component": "home_hero", "lock": "structure" },
|
|
16
|
+
{ "id": "features", "component": "feature_grid" },
|
|
17
|
+
{ "id": "choice", "component": "personalization_choice" },
|
|
18
|
+
{ "id": "stats", "component": "stats_bar" },
|
|
19
|
+
{ "id": "cta", "component": "container" }
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "footer",
|
|
24
|
+
"defaults": ["site-footer"],
|
|
25
|
+
"sequence": [{ "id": "site-footer", "fragment": ["site-footer"] }]
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$type": "pageTemplate",
|
|
3
|
+
"name": "standard",
|
|
4
|
+
"description": "Interior pages declare this template: a hero first, then any blocks the page needs.",
|
|
5
|
+
"regions": [
|
|
6
|
+
{
|
|
7
|
+
"name": "header",
|
|
8
|
+
"defaults": ["navbar"],
|
|
9
|
+
"sequence": [{ "id": "navbar", "fragment": ["navbar"] }]
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": "main",
|
|
13
|
+
"closed": false,
|
|
14
|
+
"sequence": [
|
|
15
|
+
{ "id": "hero", "component": "home_hero" }
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"name": "footer",
|
|
20
|
+
"defaults": ["site-footer"],
|
|
21
|
+
"sequence": [{ "id": "site-footer", "fragment": ["site-footer"] }]
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
package/templates/common/.nvmrc
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
24
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Seed DAM assets
|
|
2
|
+
|
|
3
|
+
This folder is a local, file-based copy of two DAM assets. The sample pages
|
|
4
|
+
reference them so the starter renders images without a running DAM service.
|
|
5
|
+
Copy one of the seed folders to mock a new asset for a page.
|
|
6
|
+
|
|
7
|
+
## How a page references an asset
|
|
8
|
+
|
|
9
|
+
A component prop holds a `dam.assetRef` object. The home page hero uses it:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
"image": {
|
|
13
|
+
"$type": "dam.assetRef",
|
|
14
|
+
"assetId": "000000000000000000000000101",
|
|
15
|
+
"alt": "Light abstract hero background with satellite constellation"
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- `assetId` — must match the `assetId` in one `asset.json` under `folders/`
|
|
20
|
+
- `alt` — optional; omit it to use the `altText` from `editorial.json`
|
|
21
|
+
- `version` — optional; omit it to use the newest approved version
|
|
22
|
+
|
|
23
|
+
The component schema (see `patterns/components/home_hero.json`) declares the
|
|
24
|
+
prop as `gradial.image`, not `dam.assetRef`. That is expected. The content
|
|
25
|
+
build resolves the ref and writes the `gradial.image` shape, with `sources`
|
|
26
|
+
filled in, into the compiled page. You author the ref; the build materializes
|
|
27
|
+
the image.
|
|
28
|
+
|
|
29
|
+
## What one seed asset contains
|
|
30
|
+
|
|
31
|
+
Each asset is one folder under `folders/<group>/<assetId>/` plus one
|
|
32
|
+
content-addressed blob under `blobs/`. The local build scans every
|
|
33
|
+
`asset.json` under `folders/`, so the group name (`seed`) does not matter
|
|
34
|
+
for rendering. `aci content push` does use it: the path under `folders/`
|
|
35
|
+
becomes the folder path in the remote DAM.
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
folders/seed/<assetId>/asset.json dam.asset: id and audit fields
|
|
39
|
+
folders/seed/<assetId>/editorial.json dam.editorial: title, altText, tags
|
|
40
|
+
folders/seed/<assetId>/governance.json dam.governance: asset status and per-version approval
|
|
41
|
+
folders/seed/<assetId>/versions/v0001.json dam.assetVersion: blob key, sha256, mime, dimensions
|
|
42
|
+
blobs/sha256/<aa>/<bb>/<sha256> the raw image bytes
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Add a new mocked asset
|
|
46
|
+
|
|
47
|
+
This is a step-by-step procedure.
|
|
48
|
+
|
|
49
|
+
1. Pick an asset ID. Use 27 base62 characters. The seed IDs pad a small
|
|
50
|
+
number with leading zeros, for example `000000000000000000000000103`.
|
|
51
|
+
2. Compute the SHA-256 of the image file. Copy the file to
|
|
52
|
+
`blobs/sha256/<first 2 hex>/<next 2 hex>/<full sha256>` with no extension.
|
|
53
|
+
3. Copy `folders/seed/000000000000000000000000101/` to a new folder named
|
|
54
|
+
after the new asset ID.
|
|
55
|
+
4. In `asset.json`, set `assetId` to the new ID.
|
|
56
|
+
5. In `versions/v0001.json`, set `blob.sha256`, `blob.key`, `blob.byteSize`,
|
|
57
|
+
`blob.mime`, `blob.originalFilename`, and `technical.dimensions`.
|
|
58
|
+
6. In `editorial.json`, set `altText`. The build fails on an empty alt text
|
|
59
|
+
when the page ref does not supply its own `alt`.
|
|
60
|
+
7. In `governance.json`, keep `asset.status` as `active` and the version
|
|
61
|
+
`status` as `approved`. The build applies the same eligibility gate as
|
|
62
|
+
production and rejects a draft, embargoed, or restricted version.
|
|
63
|
+
8. Reference the new ID from a page prop with `"$type": "dam.assetRef"`.
|
|
64
|
+
|
|
65
|
+
## Serving bytes locally
|
|
66
|
+
|
|
67
|
+
The content build only needs the metadata files to compile a page. To serve
|
|
68
|
+
the image bytes from the local object store, run from the repo root:
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
scripts/seed-local-dam-minio.sh packages/sdk/templates/common/starter-content/.content
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The script uploads every blob referenced by a `versions/*.json` file.
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
"$type": "page",
|
|
3
3
|
"id": "meridian-not-found",
|
|
4
4
|
"status": "published",
|
|
5
|
-
"layout": "default",
|
|
6
5
|
"metadata": {
|
|
7
6
|
"title": "Page not found — Meridian",
|
|
8
7
|
"description": "The page you are looking for does not exist.",
|
|
@@ -22,7 +21,7 @@
|
|
|
22
21
|
"ctaHref": "/",
|
|
23
22
|
"image": {
|
|
24
23
|
"$type": "dam.assetRef",
|
|
25
|
-
"assetId": "
|
|
24
|
+
"assetId": "000000000000000000000000101",
|
|
26
25
|
"alt": "Light abstract background with satellite constellation"
|
|
27
26
|
}
|
|
28
27
|
}
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
"$type": "page",
|
|
3
3
|
"id": "meridian-home",
|
|
4
4
|
"status": "published",
|
|
5
|
-
"layout": "default",
|
|
6
5
|
"metadata": {
|
|
7
|
-
"title": "Meridian
|
|
6
|
+
"title": "Meridian — Global Satellite Internet",
|
|
8
7
|
"description": "Connect from anywhere on Earth. Low-latency satellite internet for homes, businesses, and beyond.",
|
|
9
8
|
"canonical": "https://www.meridian.local/"
|
|
10
9
|
},
|
|
@@ -22,7 +21,7 @@
|
|
|
22
21
|
"ctaHref": "/plans/",
|
|
23
22
|
"image": {
|
|
24
23
|
"$type": "dam.assetRef",
|
|
25
|
-
"assetId": "
|
|
24
|
+
"assetId": "000000000000000000000000101",
|
|
26
25
|
"alt": "Light abstract hero background with satellite constellation"
|
|
27
26
|
}
|
|
28
27
|
}
|
|
@@ -68,6 +67,18 @@
|
|
|
68
67
|
]
|
|
69
68
|
}
|
|
70
69
|
},
|
|
70
|
+
{
|
|
71
|
+
"$type": "component",
|
|
72
|
+
"id": "personalization-choice",
|
|
73
|
+
"component": "personalization_choice",
|
|
74
|
+
"props": {
|
|
75
|
+
"title": "Choose your connection preference",
|
|
76
|
+
"description": "Select a preference, allow the update to process, then refresh personalization.",
|
|
77
|
+
"redLabel": "Choose Red",
|
|
78
|
+
"blueLabel": "Choose Blue",
|
|
79
|
+
"refreshLabel": "Refresh personalization"
|
|
80
|
+
}
|
|
81
|
+
},
|
|
71
82
|
{
|
|
72
83
|
"$type": "component",
|
|
73
84
|
"id": "stats",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$type": "page",
|
|
3
3
|
"id": "meridian-about",
|
|
4
4
|
"status": "published",
|
|
5
|
-
"
|
|
5
|
+
"template": "standard",
|
|
6
6
|
"metadata": {
|
|
7
7
|
"title": "About Meridian",
|
|
8
8
|
"description": "Meridian is building the next generation of satellite internet to connect the unconnected.",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"ctaHref": "/",
|
|
23
23
|
"image": {
|
|
24
24
|
"$type": "dam.assetRef",
|
|
25
|
-
"assetId": "
|
|
25
|
+
"assetId": "000000000000000000000000102",
|
|
26
26
|
"alt": "Meridian network coverage map with soft gradient"
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
"$type": "page",
|
|
3
3
|
"id": "meridian-error",
|
|
4
4
|
"status": "published",
|
|
5
|
-
"layout": "default",
|
|
6
5
|
"metadata": {
|
|
7
6
|
"title": "Something went wrong — Meridian",
|
|
8
7
|
"description": "An unexpected error occurred while serving this page.",
|
|
@@ -22,7 +21,7 @@
|
|
|
22
21
|
"ctaHref": "/",
|
|
23
22
|
"image": {
|
|
24
23
|
"$type": "dam.assetRef",
|
|
25
|
-
"assetId": "
|
|
24
|
+
"assetId": "000000000000000000000000101",
|
|
26
25
|
"alt": "Light abstract background with satellite constellation"
|
|
27
26
|
}
|
|
28
27
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$type": "componentPattern",
|
|
3
|
-
"buildId": "
|
|
4
|
-
"codeDigest": "sha256:
|
|
3
|
+
"buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
|
|
4
|
+
"codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
|
|
5
5
|
"name": "button",
|
|
6
6
|
"schema": {
|
|
7
7
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$type": "componentPattern",
|
|
3
|
-
"buildId": "
|
|
4
|
-
"codeDigest": "sha256:
|
|
3
|
+
"buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
|
|
4
|
+
"codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
|
|
5
5
|
"name": "container",
|
|
6
6
|
"schema": {
|
|
7
7
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
@@ -34,7 +34,12 @@
|
|
|
34
34
|
},
|
|
35
35
|
"component": {
|
|
36
36
|
"type": "string",
|
|
37
|
-
"
|
|
37
|
+
"enum": [
|
|
38
|
+
"button",
|
|
39
|
+
"feature_grid",
|
|
40
|
+
"feature_card",
|
|
41
|
+
"stats_bar"
|
|
42
|
+
]
|
|
38
43
|
},
|
|
39
44
|
"props": {
|
|
40
45
|
"type": "object",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$type": "componentPattern",
|
|
3
|
-
"buildId": "
|
|
4
|
-
"codeDigest": "sha256:
|
|
3
|
+
"buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
|
|
4
|
+
"codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
|
|
5
5
|
"name": "feature_card",
|
|
6
6
|
"schema": {
|
|
7
7
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$type": "componentPattern",
|
|
3
|
-
"buildId": "
|
|
4
|
-
"codeDigest": "sha256:
|
|
3
|
+
"buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
|
|
4
|
+
"codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
|
|
5
5
|
"name": "feature_grid",
|
|
6
6
|
"schema": {
|
|
7
7
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
},
|
|
30
30
|
"component": {
|
|
31
31
|
"type": "string",
|
|
32
|
-
"
|
|
32
|
+
"enum": [
|
|
33
|
+
"feature_card"
|
|
34
|
+
]
|
|
33
35
|
},
|
|
34
36
|
"props": {
|
|
35
37
|
"type": "object",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$type": "componentPattern",
|
|
3
|
-
"buildId": "
|
|
4
|
-
"codeDigest": "sha256:
|
|
3
|
+
"buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
|
|
4
|
+
"codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
|
|
5
5
|
"name": "home_hero",
|
|
6
6
|
"schema": {
|
|
7
7
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
package/templates/common/starter-content/.content/patterns/components/personalization_choice.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$type": "componentPattern",
|
|
3
|
-
"buildId": "
|
|
4
|
-
"codeDigest": "sha256:
|
|
3
|
+
"buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
|
|
4
|
+
"codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
|
|
5
5
|
"name": "personalization_choice",
|
|
6
6
|
"schema": {
|
|
7
7
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$type": "componentPattern",
|
|
3
|
-
"buildId": "
|
|
4
|
-
"codeDigest": "sha256:
|
|
3
|
+
"buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
|
|
4
|
+
"codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
|
|
5
5
|
"name": "site-footer",
|
|
6
6
|
"schema": {
|
|
7
7
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$type": "componentPattern",
|
|
3
|
-
"buildId": "
|
|
4
|
-
"codeDigest": "sha256:
|
|
3
|
+
"buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
|
|
4
|
+
"codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
|
|
5
5
|
"name": "site-navigation",
|
|
6
6
|
"schema": {
|
|
7
7
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$type": "componentPattern",
|
|
3
|
-
"buildId": "
|
|
4
|
-
"codeDigest": "sha256:
|
|
3
|
+
"buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
|
|
4
|
+
"codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
|
|
5
5
|
"name": "stats_bar",
|
|
6
6
|
"schema": {
|
|
7
7
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
@@ -27,7 +27,17 @@
|
|
|
27
27
|
},
|
|
28
28
|
"overlayResolution": {
|
|
29
29
|
"type": "array",
|
|
30
|
-
"items": {
|
|
30
|
+
"items": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"minLength": 1,
|
|
33
|
+
"pattern": "^[^;=/\u0009-\u000d\u0020\u0085\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]+$",
|
|
34
|
+
"not": {
|
|
35
|
+
"anyOf": [
|
|
36
|
+
{ "enum": [".", "..", "experiment", "experimentArm"] },
|
|
37
|
+
{ "pattern": "^experiment\\." }
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
31
41
|
},
|
|
32
42
|
"brandHref": { "type": "string" },
|
|
33
43
|
"brandLogo": {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Container } from '@/components/elements/Container';
|
|
2
|
+
import type { RootIdentityProps } from '@gradial/aci';
|
|
2
3
|
import { Logo } from '@/components/elements/Logo';
|
|
3
4
|
import type { FooterColumn, FooterGroup, FooterLink } from '@gradial/aci/content';
|
|
4
5
|
|
|
5
|
-
interface FooterProps {
|
|
6
|
+
interface FooterProps extends RootIdentityProps {
|
|
6
7
|
brandHref: string;
|
|
7
8
|
brandLabel: string;
|
|
8
9
|
brandLogo?: { src: string; alt?: string } | null;
|
|
@@ -17,9 +18,9 @@ function columnGroups(column: FooterColumn): FooterGroup[] {
|
|
|
17
18
|
return [{ id: column.id, title: column.title || '', links: column.links || [] }];
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
export function Footer({ brandHref, brandLabel, brandLogo = null, columns = [], social = [], legalLinks = [], copyright = '' }: FooterProps) {
|
|
21
|
+
export function Footer({ brandHref, brandLabel, brandLogo = null, columns = [], social = [], legalLinks = [], copyright = '', ...root }: FooterProps) {
|
|
21
22
|
return (
|
|
22
|
-
<footer className="bm-footer relative pt-[var(--spacing-footer-y)]" id="footer">
|
|
23
|
+
<footer {...root} className="bm-footer relative pt-[var(--spacing-footer-y)]" id="footer">
|
|
23
24
|
<div className="absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-[var(--color-brand-500)] to-transparent opacity-50" />
|
|
24
25
|
<Container>
|
|
25
26
|
<div className="footer-main-grid grid grid-cols-1 gap-12 lg:grid-cols-2">
|
|
@@ -2,9 +2,10 @@ import { Button } from '@/components/elements/Button';
|
|
|
2
2
|
import { Container } from '@/components/elements/Container';
|
|
3
3
|
import { Icon } from '@/components/elements/Icon';
|
|
4
4
|
import { Logo } from '@/components/elements/Logo';
|
|
5
|
+
import type { RootIdentityProps } from '@gradial/aci';
|
|
5
6
|
import type { NavItem, UtilityItem } from '@gradial/aci/content';
|
|
6
7
|
|
|
7
|
-
interface HeaderProps {
|
|
8
|
+
interface HeaderProps extends RootIdentityProps {
|
|
8
9
|
brandHref: string;
|
|
9
10
|
brandLabel: string;
|
|
10
11
|
brandLogo?: { src: string; alt?: string } | null;
|
|
@@ -12,9 +13,9 @@ interface HeaderProps {
|
|
|
12
13
|
utilities?: UtilityItem[];
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
export function Header({ brandHref, brandLabel, brandLogo = null, navigation = [], utilities = [] }: HeaderProps) {
|
|
16
|
+
export function Header({ brandHref, brandLabel, brandLogo = null, navigation = [], utilities = [], ...root }: HeaderProps) {
|
|
16
17
|
return (
|
|
17
|
-
<header className="bm-header fixed top-0 left-0 right-0 z-[var(--z-header)] border-b border-[var(--header-border)]">
|
|
18
|
+
<header {...root} className="bm-header fixed top-0 left-0 right-0 z-[var(--z-header)] border-b border-[var(--header-border)]">
|
|
18
19
|
<a href="#content-main" className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-[var(--z-overlay)] focus:rounded-button focus:bg-[var(--color-space-900)] focus:px-4 focus:py-2 focus:text-[var(--color-white)]">
|
|
19
20
|
Skip to main content
|
|
20
21
|
</a>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
1
|
+
import type { AnchorHTMLAttributes, ReactNode } from 'react';
|
|
2
2
|
import type { ButtonVariant } from '@gradial/aci/content';
|
|
3
3
|
|
|
4
4
|
type ButtonSize = 'default' | 'lg';
|
|
5
5
|
|
|
6
|
-
interface ButtonProps {
|
|
6
|
+
interface ButtonProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href' | 'className' | 'target' | 'rel' | 'children'> {
|
|
7
7
|
href: string;
|
|
8
8
|
variant?: ButtonVariant;
|
|
9
9
|
size?: ButtonSize;
|
|
@@ -26,9 +26,10 @@ const sizeClasses: Record<ButtonSize, string> = {
|
|
|
26
26
|
lg: 'px-7 py-3.5 min-h-[3.5rem] text-[length:var(--text-size-body-large)]',
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
export function Button({ href, variant = 'primary', size = 'default', className = '', target, rel, children }: ButtonProps) {
|
|
29
|
+
export function Button({ href, variant = 'primary', size = 'default', className = '', target, rel, children, ...root }: ButtonProps) {
|
|
30
30
|
return (
|
|
31
31
|
<a
|
|
32
|
+
{...root}
|
|
32
33
|
className={`inline-flex items-center justify-center gap-2 rounded-button leading-button font-[var(--font-weight-semibold)] no-underline transition-all duration-[var(--transition-duration-fast)] ${variantClasses[variant]} ${sizeClasses[size]} ${className}`}
|
|
33
34
|
href={href}
|
|
34
35
|
target={target}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { Button } from '@/components/elements/Button';
|
|
2
2
|
import { Icon } from '@/components/elements/Icon';
|
|
3
|
+
import type { RootIdentityProps } from '@gradial/aci';
|
|
3
4
|
import type { ContentProps } from '@/cms/contracts/components/button.contract';
|
|
4
5
|
|
|
5
|
-
export type ButtonBlockProps = ContentProps;
|
|
6
|
+
export type ButtonBlockProps = ContentProps & RootIdentityProps;
|
|
6
7
|
|
|
7
|
-
export function ButtonBlock({ label = '', href = '#', variant = 'primary', newWindow = false, icon = '', iconPosition = 'before', className = '' }: ButtonBlockProps) {
|
|
8
|
+
export function ButtonBlock({ label = '', href = '#', variant = 'primary', newWindow = false, icon = '', iconPosition = 'before', className = '', ...root }: ButtonBlockProps) {
|
|
8
9
|
const target = newWindow ? '_blank' : undefined;
|
|
9
10
|
const rel = newWindow ? 'noreferrer' : undefined;
|
|
10
11
|
|
|
11
12
|
return (
|
|
12
|
-
<Button href={href} variant={variant} target={target} rel={rel} className={className}>
|
|
13
|
+
<Button href={href} variant={variant} target={target} rel={rel} className={className} {...root}>
|
|
13
14
|
{icon && iconPosition === 'before' ? <Icon name={icon} /> : null}
|
|
14
15
|
<span>{label}</span>
|
|
15
16
|
{icon && iconPosition === 'after' ? <Icon name={icon} /> : null}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Container } from '@/components/elements/Container';
|
|
2
2
|
import { type ContentProps } from '@/cms/contracts/components/container.contract';
|
|
3
|
+
import type { RootIdentityProps } from '@gradial/aci';
|
|
3
4
|
import type { RenderChildren } from '@gradial/aci/react';
|
|
4
5
|
|
|
5
6
|
export async function ContainerSection({
|
|
@@ -7,14 +8,15 @@ export async function ContainerSection({
|
|
|
7
8
|
className = '',
|
|
8
9
|
content,
|
|
9
10
|
renderChildren,
|
|
10
|
-
|
|
11
|
+
...root
|
|
12
|
+
}: ContentProps & RootIdentityProps & { renderChildren: RenderChildren<NonNullable<ContentProps['content']>> }) {
|
|
11
13
|
const buttonCount = content?.filter((b) => b.component === 'button').length ?? 0;
|
|
12
14
|
const layout = buttonCount === 1
|
|
13
15
|
? 'flex-col items-center'
|
|
14
16
|
: 'flex-col items-center sm:flex-row sm:justify-center sm:gap-4';
|
|
15
17
|
|
|
16
18
|
return (
|
|
17
|
-
<section className={`theme-${theme} relative overflow-hidden py-[var(--spacing-section-y)] ${className}`}>
|
|
19
|
+
<section className={`theme-${theme} relative overflow-hidden py-[var(--spacing-section-y)] ${className}`} {...root}>
|
|
18
20
|
{theme === 'dark' ? (
|
|
19
21
|
<div className="pointer-events-none absolute inset-0 bg-[image:var(--gradient-hero-base)] opacity-30" />
|
|
20
22
|
) : null}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { Icon } from '@/components/elements/Icon';
|
|
2
|
+
import type { RootIdentityProps } from '@gradial/aci';
|
|
2
3
|
import type { ContentProps } from '@/cms/contracts/components/featureCard.contract';
|
|
3
4
|
|
|
4
|
-
export type FeatureCardProps = ContentProps;
|
|
5
|
+
export type FeatureCardProps = ContentProps & RootIdentityProps;
|
|
5
6
|
|
|
6
|
-
export function FeatureCard({ icon = '', title = '', description = '' }: FeatureCardProps) {
|
|
7
|
+
export function FeatureCard({ icon = '', title = '', description = '', ...root }: FeatureCardProps) {
|
|
7
8
|
return (
|
|
8
|
-
<div className="group relative overflow-hidden rounded-card border border-[var(--color-border-default)] bg-[var(--color-white)] p-[var(--spacing-card)] shadow-[var(--shadow-card-default)] transition-all duration-[var(--transition-duration-fast)] hover:-translate-y-1 hover:border-[var(--color-border-strong)] hover:shadow-[var(--shadow-elevated)]">
|
|
9
|
+
<div {...root} className="group relative overflow-hidden rounded-card border border-[var(--color-border-default)] bg-[var(--color-white)] p-[var(--spacing-card)] shadow-[var(--shadow-card-default)] transition-all duration-[var(--transition-duration-fast)] hover:-translate-y-1 hover:border-[var(--color-border-strong)] hover:shadow-[var(--shadow-elevated)]">
|
|
9
10
|
<div className="absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-[var(--color-brand-500)] to-transparent opacity-0 transition-opacity duration-[var(--transition-duration-fast)] group-hover:opacity-100" />
|
|
10
11
|
{icon ? (
|
|
11
12
|
<div className="mb-6 flex h-12 w-12 items-center justify-center rounded-button border border-[var(--color-border-default)] bg-[var(--color-surface-100)] text-[var(--color-brand-600)] shadow-[var(--shadow-glow-sm)] transition-colors group-hover:border-[var(--color-brand-500)] group-hover:text-[var(--color-brand-500)]">
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Container } from '@/components/elements/Container';
|
|
2
2
|
import { type ContentProps } from '@/cms/contracts/components/featureGrid.contract';
|
|
3
|
+
import type { RootIdentityProps } from '@gradial/aci';
|
|
3
4
|
import type { RenderChildren } from '@gradial/aci/react';
|
|
4
5
|
|
|
5
6
|
export async function FeatureGrid({
|
|
@@ -7,12 +8,13 @@ export async function FeatureGrid({
|
|
|
7
8
|
subtitle = '',
|
|
8
9
|
features,
|
|
9
10
|
renderChildren,
|
|
10
|
-
|
|
11
|
+
...root
|
|
12
|
+
}: ContentProps & RootIdentityProps & { renderChildren: RenderChildren<NonNullable<ContentProps['features']>> }) {
|
|
11
13
|
const count = features?.length ?? 0;
|
|
12
14
|
const cols = count <= 2 ? 'sm:grid-cols-2' : 'sm:grid-cols-2 lg:grid-cols-3';
|
|
13
15
|
|
|
14
16
|
return (
|
|
15
|
-
<section className="theme-light relative overflow-hidden py-[var(--spacing-section-y)] bg-[var(--color-white)]">
|
|
17
|
+
<section className="theme-light relative overflow-hidden py-[var(--spacing-section-y)] bg-[var(--color-white)]" {...root}>
|
|
16
18
|
<div className="pointer-events-none absolute inset-0 bg-[image:var(--gradient-hero-base)] opacity-50" />
|
|
17
19
|
<Container className="relative">
|
|
18
20
|
<div className="mb-14 max-w-[var(--max-width-container-narrow)]">
|