@contentrain/astro-kit 0.24.0 → 0.25.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/catalog.json CHANGED
@@ -1711,6 +1711,15 @@
1711
1711
  ],
1712
1712
  "default": "default",
1713
1713
  "description": "default: the layout's own type scale. theme: the heading takes the site's size for its level (`--text-heading-1` for the page-opening hero, `-2` otherwise), as the source's own h1 does under a block theme."
1714
+ },
1715
+ "headingSize": {
1716
+ "options": [
1717
+ "own",
1718
+ "h1",
1719
+ "h2"
1720
+ ],
1721
+ "default": "own",
1722
+ "description": "The level whose site size the heading takes when it is not the level it is written at: h1 on an h2 heading keeps a source's second h1 at the h1 size under a page that keeps one h1. own: the heading's own level under headingScale theme, nothing otherwise. Any other value than own sets the size by itself."
1714
1723
  }
1715
1724
  },
1716
1725
  "props": {
@@ -39,6 +39,8 @@ const hero = tv({
39
39
  width: { full: {}, content: {} },
40
40
  // The heading's size: the layout's own scale, or the site's size for its level (set inline, see ./hero).
41
41
  headingScale: { default: {}, theme: {} },
42
+ // The level whose site size the heading takes when it is not the level it is written at (set inline, see ./hero).
43
+ headingSize: { own: {}, h1: {}, h2: {} },
42
44
  },
43
45
  compoundVariants: [
44
46
  // After the layout's own heights, so a boxed cover keeps WordPress's 430px default.
@@ -48,7 +50,7 @@ const hero = tv({
48
50
  { leadAlign: 'start', class: { lead: 'mx-0 max-w-none self-stretch text-start' } },
49
51
  { actionsAlign: 'start', class: { actions: 'justify-start self-stretch' } },
50
52
  ],
51
- defaultVariants: { layout: 'split', tone: 'default', align: 'center', leadAlign: 'inherit', actionsAlign: 'inherit', width: 'full', headingScale: 'default' },
53
+ defaultVariants: { layout: 'split', tone: 'default', align: 'center', leadAlign: 'inherit', actionsAlign: 'inherit', width: 'full', headingScale: 'default', headingSize: 'own' },
52
54
  })
53
55
 
54
56
  interface Props {
@@ -74,16 +76,18 @@ interface Props {
74
76
  minHeight?: number | undefined
75
77
  /** `theme`: the heading takes the site's size for its level (the source's own `h1` size), not the layout's scale. */
76
78
  headingScale?: 'default' | 'theme' | undefined
79
+ /** The level whose site size the heading takes, when it is not the level it is written at (`h1` size on an `h2`: a page keeps one `h1`). `own` (absent): the heading's own level under `theme`, as before. */
80
+ headingSize?: 'own' | 'h1' | 'h2' | undefined
77
81
  }
78
82
 
79
83
 
80
- const { heading, level = 1, eyebrow, lead, actions = [], image, layout = 'split', align, leadAlign, actionsAlign, width = 'full', tone, id, minHeight, headingScale } = Astro.props
81
- const s = hero({ layout, align, leadAlign, actionsAlign, width, tone, headingScale })
84
+ const { heading, level = 1, eyebrow, lead, actions = [], image, layout = 'split', align, leadAlign, actionsAlign, width = 'full', tone, id, minHeight, headingScale, headingSize } = Astro.props
85
+ const s = hero({ layout, align, leadAlign, actionsAlign, width, tone, headingScale, headingSize })
82
86
  const Heading = level === 1 ? 'h1' : 'h2'
83
87
  const headingId = id ? `${id}-title` : undefined
84
88
  const cover = layout === 'cover' && image
85
89
  const coverHeight = cover ? heightOf(minHeight) : undefined
86
- const headingStyle = styleOf(headingScale, level)
90
+ const headingStyle = styleOf(headingScale, level, headingSize)
87
91
  ---
88
92
  {cover && width === 'content'
89
93
  ? (
@@ -191,5 +191,53 @@
191
191
  "minHeight": 520,
192
192
  "headingScale": "theme"
193
193
  }
194
+ },
195
+ {
196
+ "name": "cover-content-size-h1",
197
+ "props": {
198
+ "heading": "Independent cinema, a neighbourhood hall",
199
+ "lead": "A hundred and twenty seats, fresh popcorn.",
200
+ "layout": "cover",
201
+ "actions": [
202
+ {
203
+ "label": "This week's programme",
204
+ "href": "/programme/"
205
+ }
206
+ ],
207
+ "image": {
208
+ "src": "/kit-fixtures/photo-1.svg",
209
+ "alt": "",
210
+ "width": 1600,
211
+ "height": 900
212
+ },
213
+ "width": "content",
214
+ "level": 2,
215
+ "minHeight": 520,
216
+ "headingScale": "theme",
217
+ "headingSize": "h1"
218
+ }
219
+ },
220
+ {
221
+ "name": "centered-size-h2",
222
+ "props": {
223
+ "heading": "Plan a calmer trip",
224
+ "lead": "Our guides pick fewer places and give each one more time.",
225
+ "layout": "centered",
226
+ "tone": "muted",
227
+ "level": 2,
228
+ "actions": [
229
+ {
230
+ "label": "Browse guides",
231
+ "href": "/category/guides/"
232
+ }
233
+ ],
234
+ "image": {
235
+ "src": "/kit-fixtures/photo-2.svg",
236
+ "alt": "",
237
+ "width": 1600,
238
+ "height": 700
239
+ },
240
+ "headingSize": "h2"
241
+ }
194
242
  }
195
243
  ]
@@ -4,6 +4,12 @@ export const coverHeight = (value: number | undefined): string | undefined => (N
4
4
  /**
5
5
  * `theme`: the heading's size is the site's for its level, the one the source's own `h1`/`h2` has (`--text-heading-1`,
6
6
  * fluid where the theme's is); the layout's scale is the fallback while the site declares none.
7
+ * `size` names the level whose size the heading takes when that is not the level it is written at: a page keeps one
8
+ * `h1`, so a source's second `h1` is written as an `h2` and still drawn at the `h1` size. A `size` alone is enough; with
9
+ * none, the result is what it was before (the heading's own level under `theme`, nothing otherwise).
7
10
  */
8
- export const headingStyle = (scale: 'default' | 'theme' | undefined, level: 1 | 2): string | undefined =>
9
- scale === 'theme' ? `font-size: var(--text-heading-${level}, var(--text-5xl)); line-height: var(--leading-heading, 1.2)` : undefined
11
+ export const headingStyle = (scale: 'default' | 'theme' | undefined, level: 1 | 2, size?: 'own' | 'h1' | 'h2' | undefined): string | undefined => {
12
+ if (scale !== 'theme' && (!size || size === 'own')) return undefined
13
+ const used = size === 'h1' ? 1 : size === 'h2' ? 2 : level
14
+ return `font-size: var(--text-heading-${used}, var(--text-5xl)); line-height: var(--leading-heading, 1.2)`
15
+ }
@@ -69,6 +69,15 @@
69
69
  ],
70
70
  "default": "default",
71
71
  "description": "default: the layout's own type scale. theme: the heading takes the site's size for its level (`--text-heading-1` for the page-opening hero, `-2` otherwise), as the source's own h1 does under a block theme."
72
+ },
73
+ "headingSize": {
74
+ "options": [
75
+ "own",
76
+ "h1",
77
+ "h2"
78
+ ],
79
+ "default": "own",
80
+ "description": "The level whose site size the heading takes when it is not the level it is written at: h1 on an h2 heading keeps a source's second h1 at the h1 size under a page that keeps one h1. own: the heading's own level under headingScale theme, nothing otherwise. Any other value than own sets the size by itself."
72
81
  }
73
82
  },
74
83
  "props": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentrain/astro-kit",
3
- "version": "0.24.0",
3
+ "version": "0.25.0",
4
4
  "license": "MIT",
5
5
  "description": "Copy-in Astro components for Contentrain sites (shadcn model): typed props, tailwind-variants, zero JavaScript by default — with a machine-readable catalog",
6
6
  "type": "module",
@@ -42,7 +42,7 @@
42
42
  "mapping"
43
43
  ],
44
44
  "dependencies": {
45
- "@contentrain/types": "1.48.0"
45
+ "@contentrain/types": "1.49.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/node": "^22.10.0",