@cogenta/theme-canonical 0.1.0
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/dist/src/index.d.ts +21 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +21 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/render/actions.d.ts +17 -0
- package/dist/src/render/actions.d.ts.map +1 -0
- package/dist/src/render/actions.js +43 -0
- package/dist/src/render/actions.js.map +1 -0
- package/dist/src/render/blocks/collection-list.d.ts +16 -0
- package/dist/src/render/blocks/collection-list.d.ts.map +1 -0
- package/dist/src/render/blocks/collection-list.js +54 -0
- package/dist/src/render/blocks/collection-list.js.map +1 -0
- package/dist/src/render/blocks/cta.d.ts +5 -0
- package/dist/src/render/blocks/cta.d.ts.map +1 -0
- package/dist/src/render/blocks/cta.js +10 -0
- package/dist/src/render/blocks/cta.js.map +1 -0
- package/dist/src/render/blocks/embed.d.ts +5 -0
- package/dist/src/render/blocks/embed.d.ts.map +1 -0
- package/dist/src/render/blocks/embed.js +88 -0
- package/dist/src/render/blocks/embed.js.map +1 -0
- package/dist/src/render/blocks/faq.d.ts +5 -0
- package/dist/src/render/blocks/faq.d.ts.map +1 -0
- package/dist/src/render/blocks/faq.js +21 -0
- package/dist/src/render/blocks/faq.js.map +1 -0
- package/dist/src/render/blocks/feature-grid.d.ts +5 -0
- package/dist/src/render/blocks/feature-grid.d.ts.map +1 -0
- package/dist/src/render/blocks/feature-grid.js +27 -0
- package/dist/src/render/blocks/feature-grid.js.map +1 -0
- package/dist/src/render/blocks/gallery.d.ts +15 -0
- package/dist/src/render/blocks/gallery.d.ts.map +1 -0
- package/dist/src/render/blocks/gallery.js +28 -0
- package/dist/src/render/blocks/gallery.js.map +1 -0
- package/dist/src/render/blocks/hero.d.ts +12 -0
- package/dist/src/render/blocks/hero.d.ts.map +1 -0
- package/dist/src/render/blocks/hero.js +25 -0
- package/dist/src/render/blocks/hero.js.map +1 -0
- package/dist/src/render/blocks/logos.d.ts +5 -0
- package/dist/src/render/blocks/logos.d.ts.map +1 -0
- package/dist/src/render/blocks/logos.js +25 -0
- package/dist/src/render/blocks/logos.js.map +1 -0
- package/dist/src/render/blocks/media-figure.d.ts +15 -0
- package/dist/src/render/blocks/media-figure.d.ts.map +1 -0
- package/dist/src/render/blocks/media-figure.js +30 -0
- package/dist/src/render/blocks/media-figure.js.map +1 -0
- package/dist/src/render/blocks/prose.d.ts +10 -0
- package/dist/src/render/blocks/prose.d.ts.map +1 -0
- package/dist/src/render/blocks/prose.js +11 -0
- package/dist/src/render/blocks/prose.js.map +1 -0
- package/dist/src/render/blocks/quote.d.ts +14 -0
- package/dist/src/render/blocks/quote.d.ts.map +1 -0
- package/dist/src/render/blocks/quote.js +25 -0
- package/dist/src/render/blocks/quote.js.map +1 -0
- package/dist/src/render/blocks/stats.d.ts +5 -0
- package/dist/src/render/blocks/stats.d.ts.map +1 -0
- package/dist/src/render/blocks/stats.js +23 -0
- package/dist/src/render/blocks/stats.js.map +1 -0
- package/dist/src/render/entry.d.ts +7 -0
- package/dist/src/render/entry.d.ts.map +1 -0
- package/dist/src/render/entry.js +35 -0
- package/dist/src/render/entry.js.map +1 -0
- package/dist/src/render/heading.d.ts +14 -0
- package/dist/src/render/heading.d.ts.map +1 -0
- package/dist/src/render/heading.js +34 -0
- package/dist/src/render/heading.js.map +1 -0
- package/dist/src/render/html.d.ts +44 -0
- package/dist/src/render/html.d.ts.map +1 -0
- package/dist/src/render/html.js +96 -0
- package/dist/src/render/html.js.map +1 -0
- package/dist/src/render/media.d.ts +32 -0
- package/dist/src/render/media.d.ts.map +1 -0
- package/dist/src/render/media.js +42 -0
- package/dist/src/render/media.js.map +1 -0
- package/dist/src/render/render-block.d.ts +26 -0
- package/dist/src/render/render-block.d.ts.map +1 -0
- package/dist/src/render/render-block.js +66 -0
- package/dist/src/render/render-block.js.map +1 -0
- package/dist/src/render/rich-text.d.ts +5 -0
- package/dist/src/render/rich-text.d.ts.map +1 -0
- package/dist/src/render/rich-text.js +105 -0
- package/dist/src/render/rich-text.js.map +1 -0
- package/dist/src/theme-contract.d.ts +165 -0
- package/dist/src/theme-contract.d.ts.map +1 -0
- package/dist/src/theme-contract.js +21 -0
- package/dist/src/theme-contract.js.map +1 -0
- package/dist/theme.config.d.ts +31 -0
- package/dist/theme.config.d.ts.map +1 -0
- package/dist/theme.config.js +42 -0
- package/dist/theme.config.js.map +1 -0
- package/package.json +57 -0
- package/src/blocks/CollectionList.astro +20 -0
- package/src/blocks/Cta.astro +11 -0
- package/src/blocks/Embed.astro +18 -0
- package/src/blocks/Faq.astro +16 -0
- package/src/blocks/FeatureGrid.astro +11 -0
- package/src/blocks/Gallery.astro +17 -0
- package/src/blocks/Hero.astro +25 -0
- package/src/blocks/Logos.astro +11 -0
- package/src/blocks/MediaFigure.astro +11 -0
- package/src/blocks/Prose.astro +11 -0
- package/src/blocks/Quote.astro +11 -0
- package/src/blocks/Stats.astro +11 -0
- package/src/components/BlockZone.astro +62 -0
- package/src/index.ts +20 -0
- package/src/layouts/Base.astro +63 -0
- package/src/render/actions.ts +57 -0
- package/src/render/blocks/collection-list.ts +98 -0
- package/src/render/blocks/cta.ts +17 -0
- package/src/render/blocks/embed.ts +111 -0
- package/src/render/blocks/faq.ts +42 -0
- package/src/render/blocks/feature-grid.ts +54 -0
- package/src/render/blocks/gallery.ts +49 -0
- package/src/render/blocks/hero.ts +42 -0
- package/src/render/blocks/logos.ts +45 -0
- package/src/render/blocks/media-figure.ts +42 -0
- package/src/render/blocks/prose.ts +17 -0
- package/src/render/blocks/quote.ts +39 -0
- package/src/render/blocks/stats.ts +41 -0
- package/src/render/entry.ts +40 -0
- package/src/render/heading.ts +44 -0
- package/src/render/html.ts +122 -0
- package/src/render/media.ts +62 -0
- package/src/render/render-block.ts +97 -0
- package/src/render/rich-text.ts +150 -0
- package/src/styles/theme.css +606 -0
- package/src/theme-contract.ts +159 -0
- package/tokens.json +36 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract D — Thème, frozen at `theme@1.0` on 2026-08-13.
|
|
3
|
+
*
|
|
4
|
+
* TEMPORARY HOME. These types and `defineTheme` belong to `@cogenta/render`,
|
|
5
|
+
* which is being written in parallel (tasks 1–3 of L3). They live here so the
|
|
6
|
+
* canonical theme can be written, typechecked and tested today, and must be
|
|
7
|
+
* replaced by an import from `@cogenta/render` at merge time — not duplicated.
|
|
8
|
+
*
|
|
9
|
+
* Nothing below adds to `ctx`. Two shapes the contract names but does not spell
|
|
10
|
+
* out — `MediaReference` and `ContentEntry` — are given the narrowest reading
|
|
11
|
+
* that matches what is already frozen elsewhere; both are flagged in the code.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Contract B stores a media field as the media library's identifier, never as
|
|
16
|
+
* an URL and never as a rendition (`f.media` in `@cogenta/blocks`). So a
|
|
17
|
+
* reference the theme can hold is that identifier.
|
|
18
|
+
*/
|
|
19
|
+
export type MediaReference = string
|
|
20
|
+
|
|
21
|
+
export interface ImageOptions {
|
|
22
|
+
readonly width?: number
|
|
23
|
+
readonly height?: number
|
|
24
|
+
readonly format?: 'avif' | 'webp' | 'jpeg' | 'png'
|
|
25
|
+
readonly fit?: 'cover' | 'contain'
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ImageSource {
|
|
29
|
+
readonly src: string
|
|
30
|
+
readonly srcset: string
|
|
31
|
+
readonly width: number
|
|
32
|
+
readonly height: number
|
|
33
|
+
/** Alt text and focal point come from the media entity, never invented here. */
|
|
34
|
+
readonly alt: string
|
|
35
|
+
readonly focal: { readonly x: number; readonly y: number } | null
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Contract A, "Champs système". A theme only ever sees published entries — the
|
|
40
|
+
* read token carries the `public` role — so `status` is narrow in practice but
|
|
41
|
+
* kept whole here rather than guessed at.
|
|
42
|
+
*
|
|
43
|
+
* The schema-defined fields are open: which of them exist depends on the
|
|
44
|
+
* collection, and a theme must not assume one is present. `entryTitle` in
|
|
45
|
+
* `src/render/entry.ts` is the only place that reaches for one.
|
|
46
|
+
*/
|
|
47
|
+
export interface ContentEntry {
|
|
48
|
+
readonly id: string
|
|
49
|
+
readonly collection: string
|
|
50
|
+
readonly locale: string
|
|
51
|
+
readonly status: 'draft' | 'scheduled' | 'published' | 'archived'
|
|
52
|
+
readonly [field: string]: unknown
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface QueryRequest {
|
|
56
|
+
readonly collection: string
|
|
57
|
+
readonly filter?: Readonly<Record<string, unknown>>
|
|
58
|
+
readonly sort?: { readonly field: string; readonly direction: 'asc' | 'desc' }
|
|
59
|
+
readonly limit?: number
|
|
60
|
+
readonly cursor?: string
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface Page<T> {
|
|
64
|
+
readonly items: readonly T[]
|
|
65
|
+
readonly nextCursor: string | null
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface ContentClient {
|
|
69
|
+
entry(collection: string, id: string): Promise<ContentEntry | null>
|
|
70
|
+
byPath(path: string): Promise<ContentEntry | null>
|
|
71
|
+
list(request: QueryRequest): Promise<Page<ContentEntry>>
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export type LinkTargetInput = { collection: string; id: string } | { path: string } | string
|
|
75
|
+
|
|
76
|
+
export interface RenderContext {
|
|
77
|
+
readonly site: {
|
|
78
|
+
readonly name: string
|
|
79
|
+
readonly url: string
|
|
80
|
+
readonly locales: readonly string[]
|
|
81
|
+
readonly defaultLocale: string
|
|
82
|
+
}
|
|
83
|
+
/** The locale being rendered. */
|
|
84
|
+
readonly locale: string
|
|
85
|
+
/** The URL being rendered, already resolved. */
|
|
86
|
+
readonly url: URL
|
|
87
|
+
|
|
88
|
+
/** Translation. An unknown key returns the key, never an empty string. */
|
|
89
|
+
t(key: string, values?: Readonly<Record<string, string | number>>): string
|
|
90
|
+
|
|
91
|
+
/** Image variants. Returns what a responsive `<img>` needs, nothing more. */
|
|
92
|
+
image(media: MediaReference, options?: ImageOptions): ImageSource
|
|
93
|
+
|
|
94
|
+
/** URL of an entry, of a path, or of an external target. Locale-aware. */
|
|
95
|
+
link(target: LinkTargetInput): string
|
|
96
|
+
|
|
97
|
+
/** Read-only content access. The only door to data a theme has. */
|
|
98
|
+
readonly content: ContentClient
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Contract D, "Besoins runtime". */
|
|
102
|
+
export type ThemeRuntime = 'static' | 'server' | 'edge'
|
|
103
|
+
|
|
104
|
+
export interface ThemeManifest {
|
|
105
|
+
readonly name: string
|
|
106
|
+
readonly version: string
|
|
107
|
+
/** Version of the theme contract. */
|
|
108
|
+
readonly engine: string
|
|
109
|
+
/** Version of the block vocabulary supported. */
|
|
110
|
+
readonly blocks: string
|
|
111
|
+
/** Every vocabulary block the theme renders. A gap fails installation. */
|
|
112
|
+
readonly implements: readonly string[]
|
|
113
|
+
/** Content types expected, or `'*'`. */
|
|
114
|
+
readonly collections: readonly string[] | '*'
|
|
115
|
+
readonly runtime: ThemeRuntime
|
|
116
|
+
/** Path to the default skin, relative to the manifest. */
|
|
117
|
+
readonly tokens: string
|
|
118
|
+
readonly a11y: { readonly verified: 'WCAG-2.2-AA' | 'WCAG-2.2-AAA' | 'none' }
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Identity function. It exists for the inference and for the single place a
|
|
123
|
+
* manifest is recognised, not to validate: validation happens at installation,
|
|
124
|
+
* on the theme's sources, where a lie can actually be caught.
|
|
125
|
+
*/
|
|
126
|
+
export function defineTheme<const M extends ThemeManifest>(manifest: M): M {
|
|
127
|
+
return manifest
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Contract D, "Tokens de skin". The set is **closed and complete**: a skin that
|
|
132
|
+
* omits a token is refused. Rendered as `--cogenta-<group>-<name>` into a single
|
|
133
|
+
* stylesheet, so changing skin rewrites one file and needs no build.
|
|
134
|
+
*/
|
|
135
|
+
export interface SkinTokens {
|
|
136
|
+
readonly color: {
|
|
137
|
+
readonly bg: string
|
|
138
|
+
readonly fg: string
|
|
139
|
+
readonly accent: string
|
|
140
|
+
readonly accentFg: string
|
|
141
|
+
readonly muted: string
|
|
142
|
+
readonly mutedFg: string
|
|
143
|
+
readonly border: string
|
|
144
|
+
}
|
|
145
|
+
readonly font: {
|
|
146
|
+
readonly sans: string
|
|
147
|
+
readonly serif: string
|
|
148
|
+
readonly mono: string
|
|
149
|
+
readonly scale: number
|
|
150
|
+
readonly baseSize: string
|
|
151
|
+
}
|
|
152
|
+
readonly space: {
|
|
153
|
+
readonly unit: string
|
|
154
|
+
readonly density: 'compact' | 'comfortable' | 'spacious'
|
|
155
|
+
}
|
|
156
|
+
readonly radius: { readonly sm: string; readonly md: string; readonly lg: string }
|
|
157
|
+
readonly motion: { readonly duration: string; readonly easing: string; readonly reduced: boolean }
|
|
158
|
+
readonly shadow: { readonly sm: string; readonly md: string }
|
|
159
|
+
}
|
package/tokens.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"color": {
|
|
3
|
+
"bg": "#ffffff",
|
|
4
|
+
"fg": "#16181d",
|
|
5
|
+
"accent": "#1d4ed8",
|
|
6
|
+
"accentFg": "#ffffff",
|
|
7
|
+
"muted": "#f2f4f7",
|
|
8
|
+
"mutedFg": "#3f4655",
|
|
9
|
+
"border": "#d7dbe2"
|
|
10
|
+
},
|
|
11
|
+
"font": {
|
|
12
|
+
"sans": "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
|
|
13
|
+
"serif": "ui-serif, Georgia, Cambria, 'Times New Roman', serif",
|
|
14
|
+
"mono": "ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace",
|
|
15
|
+
"scale": 1.25,
|
|
16
|
+
"baseSize": "1rem"
|
|
17
|
+
},
|
|
18
|
+
"space": {
|
|
19
|
+
"unit": "0.25rem",
|
|
20
|
+
"density": "comfortable"
|
|
21
|
+
},
|
|
22
|
+
"radius": {
|
|
23
|
+
"sm": "0.25rem",
|
|
24
|
+
"md": "0.5rem",
|
|
25
|
+
"lg": "1rem"
|
|
26
|
+
},
|
|
27
|
+
"motion": {
|
|
28
|
+
"duration": "180ms",
|
|
29
|
+
"easing": "cubic-bezier(0.2, 0, 0, 1)",
|
|
30
|
+
"reduced": true
|
|
31
|
+
},
|
|
32
|
+
"shadow": {
|
|
33
|
+
"sm": "0 1px 2px rgba(22, 24, 29, 0.08)",
|
|
34
|
+
"md": "0 6px 24px rgba(22, 24, 29, 0.12)"
|
|
35
|
+
}
|
|
36
|
+
}
|