@contentrain/astro-kit 0.31.0 → 0.32.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 +2531 -345
- package/components/_shared/measured.ts +10 -0
- package/components/contact-form/ContactForm.astro +48 -12
- package/components/contact-form/fixtures.json +169 -9
- package/components/contact-form/meta.json +283 -15
- package/components/cta/Cta.astro +52 -12
- package/components/cta/fixtures.json +5 -1
- package/components/cta/meta.json +11 -2
- package/components/faq/Faq.astro +60 -17
- package/components/faq/fixtures.json +75 -0
- package/components/faq/meta.json +7 -1
- package/components/feature-list/FeatureList.astro +28 -4
- package/components/feature-list/meta.json +15 -3
- package/components/gallery/Gallery.astro +47 -13
- package/components/gallery/fixtures.json +275 -0
- package/components/gallery/meta.json +266 -14
- package/components/logo-cloud/LogoCloud.astro +85 -21
- package/components/logo-cloud/fixtures.json +239 -0
- package/components/logo-cloud/meta.json +144 -5
- package/components/post-card/PostCard.astro +4 -2
- package/components/post-card/meta.json +2 -1
- package/components/post-list/PostList.astro +114 -0
- package/components/post-list/fixtures.json +387 -0
- package/components/post-list/meta.json +308 -0
- package/components/pricing/Pricing.astro +128 -24
- package/components/pricing/fixtures.json +288 -4
- package/components/pricing/meta.json +187 -1
- package/components/split/Split.astro +76 -14
- package/components/split/fixtures.json +8 -1
- package/components/split/meta.json +225 -4
- package/components/stats/Stats.astro +42 -10
- package/components/stats/fixtures.json +173 -0
- package/components/stats/meta.json +150 -4
- package/components/steps/Steps.astro +36 -8
- package/components/steps/fixtures.json +217 -5
- package/components/steps/meta.json +156 -3
- package/components/team/Team.astro +52 -8
- package/components/team/fixtures.json +217 -4
- package/components/team/meta.json +167 -3
- package/components/team/team.ts +9 -0
- package/components/testimonial/Testimonial.astro +71 -21
- package/components/testimonial/fixtures.json +73 -0
- package/components/testimonial/meta.json +166 -3
- package/mapping/classic.json +7 -1
- package/mapping/divi.json +21 -4
- package/mapping/elementor.json +33 -8
- package/mapping/gutenberg.json +20 -4
- package/package.json +1 -1
|
@@ -135,5 +135,244 @@
|
|
|
135
135
|
"tone": "accent",
|
|
136
136
|
"style": "grayscale"
|
|
137
137
|
}
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"name": "row-start-large",
|
|
141
|
+
"props": {
|
|
142
|
+
"heading": "Trusted by",
|
|
143
|
+
"items": [
|
|
144
|
+
{
|
|
145
|
+
"image": "/kit-fixtures/logo.svg",
|
|
146
|
+
"imageAlt": "Company 1",
|
|
147
|
+
"href": "https://example.com"
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"image": "/kit-fixtures/logo.svg",
|
|
151
|
+
"imageAlt": "Company 2"
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"image": "/kit-fixtures/logo.svg",
|
|
155
|
+
"imageAlt": "Company 3",
|
|
156
|
+
"href": "https://example.com"
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"image": "/kit-fixtures/logo.svg",
|
|
160
|
+
"imageAlt": "Company 4"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"image": "/kit-fixtures/logo.svg",
|
|
164
|
+
"imageAlt": "Company 5",
|
|
165
|
+
"href": "https://example.com"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"image": "/kit-fixtures/logo.svg",
|
|
169
|
+
"imageAlt": "Company 6"
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
"layout": "row",
|
|
173
|
+
"align": "start",
|
|
174
|
+
"logoHeight": "lg"
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"name": "row-small-mono-inverse",
|
|
179
|
+
"props": {
|
|
180
|
+
"heading": "Trusted by",
|
|
181
|
+
"items": [
|
|
182
|
+
{
|
|
183
|
+
"image": "/kit-fixtures/logo.svg",
|
|
184
|
+
"imageAlt": "Company 1",
|
|
185
|
+
"href": "https://example.com"
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"image": "/kit-fixtures/logo.svg",
|
|
189
|
+
"imageAlt": "Company 2"
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"image": "/kit-fixtures/logo.svg",
|
|
193
|
+
"imageAlt": "Company 3",
|
|
194
|
+
"href": "https://example.com"
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"image": "/kit-fixtures/logo.svg",
|
|
198
|
+
"imageAlt": "Company 4"
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"image": "/kit-fixtures/logo.svg",
|
|
202
|
+
"imageAlt": "Company 5",
|
|
203
|
+
"href": "https://example.com"
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"image": "/kit-fixtures/logo.svg",
|
|
207
|
+
"imageAlt": "Company 6"
|
|
208
|
+
}
|
|
209
|
+
],
|
|
210
|
+
"layout": "row",
|
|
211
|
+
"logoHeight": "sm",
|
|
212
|
+
"style": "mono-light",
|
|
213
|
+
"tone": "inverse"
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"name": "marquee",
|
|
218
|
+
"props": {
|
|
219
|
+
"heading": "Trusted by",
|
|
220
|
+
"items": [
|
|
221
|
+
{
|
|
222
|
+
"image": "/kit-fixtures/logo.svg",
|
|
223
|
+
"imageAlt": "Company 1",
|
|
224
|
+
"href": "https://example.com"
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"image": "/kit-fixtures/logo.svg",
|
|
228
|
+
"imageAlt": "Company 2"
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
"image": "/kit-fixtures/logo.svg",
|
|
232
|
+
"imageAlt": "Company 3",
|
|
233
|
+
"href": "https://example.com"
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
"image": "/kit-fixtures/logo.svg",
|
|
237
|
+
"imageAlt": "Company 4"
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"image": "/kit-fixtures/logo.svg",
|
|
241
|
+
"imageAlt": "Company 5",
|
|
242
|
+
"href": "https://example.com"
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"image": "/kit-fixtures/logo.svg",
|
|
246
|
+
"imageAlt": "Company 6"
|
|
247
|
+
}
|
|
248
|
+
],
|
|
249
|
+
"layout": "marquee",
|
|
250
|
+
"tone": "muted"
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
"name": "five-columns",
|
|
255
|
+
"props": {
|
|
256
|
+
"heading": "Trusted by",
|
|
257
|
+
"items": [
|
|
258
|
+
{
|
|
259
|
+
"image": "/kit-fixtures/logo.svg",
|
|
260
|
+
"imageAlt": "Company 1",
|
|
261
|
+
"href": "https://example.com"
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
"image": "/kit-fixtures/logo.svg",
|
|
265
|
+
"imageAlt": "Company 2"
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"image": "/kit-fixtures/logo.svg",
|
|
269
|
+
"imageAlt": "Company 3",
|
|
270
|
+
"href": "https://example.com"
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"image": "/kit-fixtures/logo.svg",
|
|
274
|
+
"imageAlt": "Company 4"
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"image": "/kit-fixtures/logo.svg",
|
|
278
|
+
"imageAlt": "Company 5",
|
|
279
|
+
"href": "https://example.com"
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"image": "/kit-fixtures/logo.svg",
|
|
283
|
+
"imageAlt": "Company 6"
|
|
284
|
+
}
|
|
285
|
+
],
|
|
286
|
+
"columns": "5"
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"name": "six-columns",
|
|
291
|
+
"props": {
|
|
292
|
+
"heading": "Trusted by",
|
|
293
|
+
"items": [
|
|
294
|
+
{
|
|
295
|
+
"image": "/kit-fixtures/logo.svg",
|
|
296
|
+
"imageAlt": "Company 1",
|
|
297
|
+
"href": "https://example.com"
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"image": "/kit-fixtures/logo.svg",
|
|
301
|
+
"imageAlt": "Company 2"
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
"image": "/kit-fixtures/logo.svg",
|
|
305
|
+
"imageAlt": "Company 3",
|
|
306
|
+
"href": "https://example.com"
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
"image": "/kit-fixtures/logo.svg",
|
|
310
|
+
"imageAlt": "Company 4"
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
"image": "/kit-fixtures/logo.svg",
|
|
314
|
+
"imageAlt": "Company 5",
|
|
315
|
+
"href": "https://example.com"
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
"image": "/kit-fixtures/logo.svg",
|
|
319
|
+
"imageAlt": "Company 6"
|
|
320
|
+
}
|
|
321
|
+
],
|
|
322
|
+
"columns": "6"
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
"name": "measured-columns",
|
|
327
|
+
"props": {
|
|
328
|
+
"heading": "Trusted by",
|
|
329
|
+
"items": [
|
|
330
|
+
{
|
|
331
|
+
"image": "/kit-fixtures/logo.svg",
|
|
332
|
+
"imageAlt": "Company 1",
|
|
333
|
+
"href": "https://example.com"
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
"image": "/kit-fixtures/logo.svg",
|
|
337
|
+
"imageAlt": "Company 2"
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
"image": "/kit-fixtures/logo.svg",
|
|
341
|
+
"imageAlt": "Company 3",
|
|
342
|
+
"href": "https://example.com"
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
"image": "/kit-fixtures/logo.svg",
|
|
346
|
+
"imageAlt": "Company 4"
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
"image": "/kit-fixtures/logo.svg",
|
|
350
|
+
"imageAlt": "Company 5",
|
|
351
|
+
"href": "https://example.com"
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
"image": "/kit-fixtures/logo.svg",
|
|
355
|
+
"imageAlt": "Company 6"
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
"image": "/kit-fixtures/logo.svg",
|
|
359
|
+
"imageAlt": "Company 7",
|
|
360
|
+
"href": "https://example.com"
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
"image": "/kit-fixtures/logo.svg",
|
|
364
|
+
"imageAlt": "Company 8"
|
|
365
|
+
}
|
|
366
|
+
],
|
|
367
|
+
"measured": {
|
|
368
|
+
"columns": {
|
|
369
|
+
"390": 2,
|
|
370
|
+
"768": 3,
|
|
371
|
+
"1280": 6
|
|
372
|
+
},
|
|
373
|
+
"gap": 32,
|
|
374
|
+
"padY": 48
|
|
375
|
+
}
|
|
376
|
+
}
|
|
138
377
|
}
|
|
139
378
|
]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "logo-cloud",
|
|
3
3
|
"name": "Logo cloud",
|
|
4
|
-
"description": "A grid of client or partner logos, each optionally linked, under an optional heading (\"Trusted by\").",
|
|
4
|
+
"description": "A grid, a row or an endless strip of client or partner logos, each optionally linked, under an optional heading (\"Trusted by\").",
|
|
5
5
|
"category": "section",
|
|
6
6
|
"uses": [],
|
|
7
7
|
"shared": [
|
|
@@ -12,22 +12,51 @@
|
|
|
12
12
|
"types.ts"
|
|
13
13
|
],
|
|
14
14
|
"variants": {
|
|
15
|
+
"layout": {
|
|
16
|
+
"options": [
|
|
17
|
+
"grid",
|
|
18
|
+
"row",
|
|
19
|
+
"marquee"
|
|
20
|
+
],
|
|
21
|
+
"default": "grid",
|
|
22
|
+
"description": "grid: logos in columns. row: one line that wraps. marquee: an endless CSS-only strip that stands still for reduced motion."
|
|
23
|
+
},
|
|
15
24
|
"columns": {
|
|
16
25
|
"options": [
|
|
17
26
|
"2",
|
|
18
27
|
"3",
|
|
19
|
-
"4"
|
|
28
|
+
"4",
|
|
29
|
+
"5",
|
|
30
|
+
"6"
|
|
20
31
|
],
|
|
21
32
|
"default": "4",
|
|
22
|
-
"description": "Logos per row on wide screens; two on phones, three on tablets."
|
|
33
|
+
"description": "Logos per row on wide screens (grid layout); two on phones, three on tablets."
|
|
34
|
+
},
|
|
35
|
+
"logoHeight": {
|
|
36
|
+
"options": [
|
|
37
|
+
"sm",
|
|
38
|
+
"md",
|
|
39
|
+
"lg"
|
|
40
|
+
],
|
|
41
|
+
"default": "md",
|
|
42
|
+
"description": "Height of every logo (the width follows): small, medium or large."
|
|
23
43
|
},
|
|
24
44
|
"style": {
|
|
25
45
|
"options": [
|
|
26
46
|
"plain",
|
|
27
|
-
"grayscale"
|
|
47
|
+
"grayscale",
|
|
48
|
+
"mono-light"
|
|
28
49
|
],
|
|
29
50
|
"default": "plain",
|
|
30
|
-
"description": "plain: logos in their own colours. grayscale: muted grey, full colour on hover or focus."
|
|
51
|
+
"description": "plain: logos in their own colours. grayscale: muted grey, full colour on hover or focus. mono-light: drawn white, for a dark band."
|
|
52
|
+
},
|
|
53
|
+
"align": {
|
|
54
|
+
"options": [
|
|
55
|
+
"center",
|
|
56
|
+
"start"
|
|
57
|
+
],
|
|
58
|
+
"default": "center",
|
|
59
|
+
"description": "Alignment of the heading and of the logos in a row."
|
|
31
60
|
},
|
|
32
61
|
"tone": {
|
|
33
62
|
"options": [
|
|
@@ -74,6 +103,116 @@
|
|
|
74
103
|
},
|
|
75
104
|
"description": "The logos, in order (a Gutenberg gallery or columns of logos, Elementor image carousel/gallery of logos, Divi images)."
|
|
76
105
|
},
|
|
106
|
+
"measured": {
|
|
107
|
+
"type": "object",
|
|
108
|
+
"content": false,
|
|
109
|
+
"description": "The source section's measured style (MeasuredStyle): frame width, padding, fill, image, columns per width, gap, text tone, radius, minimum height — all in pixels. Absent, the site's tokens; present, it wins over tone and columns. Values that are not a number, a colour or a known keyword are dropped.",
|
|
110
|
+
"fields": {
|
|
111
|
+
"containerPx": {
|
|
112
|
+
"type": "integer",
|
|
113
|
+
"min": 0,
|
|
114
|
+
"max": 2560,
|
|
115
|
+
"description": "The frame's content width."
|
|
116
|
+
},
|
|
117
|
+
"padY": {
|
|
118
|
+
"type": "integer",
|
|
119
|
+
"min": 0,
|
|
120
|
+
"max": 400,
|
|
121
|
+
"description": "Top and bottom padding."
|
|
122
|
+
},
|
|
123
|
+
"padX": {
|
|
124
|
+
"type": "integer",
|
|
125
|
+
"min": 0,
|
|
126
|
+
"max": 200,
|
|
127
|
+
"description": "The frame's side padding (gutter)."
|
|
128
|
+
},
|
|
129
|
+
"bg": {
|
|
130
|
+
"type": "object",
|
|
131
|
+
"description": "The section's background.",
|
|
132
|
+
"fields": {
|
|
133
|
+
"color": {
|
|
134
|
+
"type": "string",
|
|
135
|
+
"description": "Fill colour: hex, rgb(a) or hsl(a)."
|
|
136
|
+
},
|
|
137
|
+
"image": {
|
|
138
|
+
"type": "string",
|
|
139
|
+
"description": "Background image address (http(s) or root-relative), drawn behind the content."
|
|
140
|
+
},
|
|
141
|
+
"overlay": {
|
|
142
|
+
"type": "string",
|
|
143
|
+
"description": "Colour or linear/radial gradient laid over the image or the fill."
|
|
144
|
+
},
|
|
145
|
+
"size": {
|
|
146
|
+
"type": "string",
|
|
147
|
+
"description": "cover, contain or auto; anything else draws as cover."
|
|
148
|
+
},
|
|
149
|
+
"position": {
|
|
150
|
+
"type": "string",
|
|
151
|
+
"description": "One or two of center/top/bottom/left/right or percentages."
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"columns": {
|
|
156
|
+
"type": "object",
|
|
157
|
+
"description": "Item columns at 390 (base), 768 (md) and 1280 (lg) px; a missing width follows the narrower one.",
|
|
158
|
+
"fields": {
|
|
159
|
+
"390": {
|
|
160
|
+
"type": "integer",
|
|
161
|
+
"min": 1,
|
|
162
|
+
"max": 6,
|
|
163
|
+
"description": "Phone."
|
|
164
|
+
},
|
|
165
|
+
"768": {
|
|
166
|
+
"type": "integer",
|
|
167
|
+
"min": 1,
|
|
168
|
+
"max": 6,
|
|
169
|
+
"description": "Tablet."
|
|
170
|
+
},
|
|
171
|
+
"1280": {
|
|
172
|
+
"type": "integer",
|
|
173
|
+
"min": 1,
|
|
174
|
+
"max": 6,
|
|
175
|
+
"description": "Desktop."
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
"gap": {
|
|
180
|
+
"type": "integer",
|
|
181
|
+
"min": 0,
|
|
182
|
+
"max": 200,
|
|
183
|
+
"description": "Gap between items."
|
|
184
|
+
},
|
|
185
|
+
"tone": {
|
|
186
|
+
"type": "select",
|
|
187
|
+
"options": [
|
|
188
|
+
"light",
|
|
189
|
+
"dark"
|
|
190
|
+
],
|
|
191
|
+
"description": "What the text is set for: dark = light text on a dark band. Without it, a fill's own lightness decides."
|
|
192
|
+
},
|
|
193
|
+
"align": {
|
|
194
|
+
"type": "select",
|
|
195
|
+
"options": [
|
|
196
|
+
"start",
|
|
197
|
+
"center",
|
|
198
|
+
"end"
|
|
199
|
+
],
|
|
200
|
+
"description": "Where the heading and lead sit; read by a component whose own align is not set."
|
|
201
|
+
},
|
|
202
|
+
"radius": {
|
|
203
|
+
"type": "integer",
|
|
204
|
+
"min": 0,
|
|
205
|
+
"max": 200,
|
|
206
|
+
"description": "Card and item corner radius."
|
|
207
|
+
},
|
|
208
|
+
"minHeight": {
|
|
209
|
+
"type": "integer",
|
|
210
|
+
"min": 0,
|
|
211
|
+
"max": 2000,
|
|
212
|
+
"description": "The section's minimum height."
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
},
|
|
77
216
|
"id": {
|
|
78
217
|
"type": "string",
|
|
79
218
|
"content": false,
|
|
@@ -50,6 +50,8 @@ interface Props {
|
|
|
50
50
|
layout?: 'vertical' | 'horizontal' | 'minimal' | undefined
|
|
51
51
|
surface?: 'plain' | 'card' | undefined
|
|
52
52
|
byline?: 'inline' | 'below' | undefined
|
|
53
|
+
/** Clamp the excerpt to this many lines; absent, the layout's own (3 vertical, 2 otherwise). */
|
|
54
|
+
excerptLines?: 2 | 3 | 4 | undefined
|
|
53
55
|
/** The title in the site's link colour, as themes that colour every link do (Hello Elementor). */
|
|
54
56
|
linkTitle?: boolean | undefined
|
|
55
57
|
/** The image's `sizes` hint; absent, the card's own guess. A list passes the slot its columns give. */
|
|
@@ -60,7 +62,7 @@ interface Props {
|
|
|
60
62
|
imageAspect?: string | undefined
|
|
61
63
|
}
|
|
62
64
|
|
|
63
|
-
const { title, href, excerpt, date: rawDate, locale = 'en', image, category, author, headingLevel = 2, layout, surface, byline, linkTitle, sizes, imageHeight, imageAspect } = Astro.props
|
|
65
|
+
const { title, href, excerpt, date: rawDate, locale = 'en', image, category, author, headingLevel = 2, layout, surface, byline, linkTitle, excerptLines, sizes, imageHeight, imageAspect } = Astro.props
|
|
64
66
|
const date = rawDate === undefined ? undefined : new Date(rawDate)
|
|
65
67
|
const slots = card({ layout, surface, byline })
|
|
66
68
|
const below = byline === 'below'
|
|
@@ -97,7 +99,7 @@ const Heading = `h${headingLevel}` as 'h2' | 'h3'
|
|
|
97
99
|
{date && <time datetime={date.toISOString()}>{shown}</time>}
|
|
98
100
|
</p>
|
|
99
101
|
)}
|
|
100
|
-
{excerpt && <p class={slots.excerpt()}>{excerpt}</p>}
|
|
102
|
+
{excerpt && <p class={slots.excerpt({ class: excerptLines ? { 2: 'line-clamp-2', 3: 'line-clamp-3', 4: 'line-clamp-4' }[excerptLines] : undefined })}>{excerpt}</p>}
|
|
101
103
|
{!below && author && <p class="text-sm text-ink-muted">{author}</p>}
|
|
102
104
|
</div>
|
|
103
105
|
</article>
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
"linkTitle": { "type": "boolean", "default": false, "description": "The title in the site's link colour (--color-link), as themes that colour every link do." },
|
|
24
24
|
"sizes": { "type": "string", "description": "The image's `sizes` hint; absent, the card's own guess. A list passes the slot its columns give." },
|
|
25
25
|
"imageHeight": { "type": "string", "description": "The image block's height as the source sets it (a CSS length or clamp()), cropped to fit; wins over imageAspect." },
|
|
26
|
-
"imageAspect": { "type": "string", "description": "The image block's aspect ratio (16 / 9) where the source sets an aspect ratio; absent, 16 / 9." }
|
|
26
|
+
"imageAspect": { "type": "string", "description": "The image block's aspect ratio (16 / 9) where the source sets an aspect ratio; absent, 16 / 9." },
|
|
27
|
+
"excerptLines": { "type": "integer", "min": 2, "max": 4, "content": false, "description": "Clamp the excerpt to this many lines; absent, the layout's own (3 vertical, 2 otherwise)." }
|
|
27
28
|
},
|
|
28
29
|
"slots": {},
|
|
29
30
|
"js": "none",
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
// A list of posts as cards: a grid, stacked rows, a featured first post over a
|
|
3
|
+
// grid, or a compact title-and-date list. The posts are the site's own — fed
|
|
4
|
+
// by the Contentrain query SDK, never copied from a page — and the `show*`
|
|
5
|
+
// switches decide which parts of each card the design displays.
|
|
6
|
+
import { tv } from 'tailwind-variants'
|
|
7
|
+
import Section from '../_shared/Section.astro'
|
|
8
|
+
import { measuredGrid } from '../_shared/measured'
|
|
9
|
+
import type { MeasuredStyle } from '../_shared/types'
|
|
10
|
+
import PostCard from '../post-card/PostCard.astro'
|
|
11
|
+
import type { ImageInput, LinkInput } from '../_shared/types'
|
|
12
|
+
|
|
13
|
+
export interface PostItem {
|
|
14
|
+
title: string
|
|
15
|
+
href: string
|
|
16
|
+
excerpt?: string | undefined
|
|
17
|
+
date?: Date | string | undefined
|
|
18
|
+
image?: ImageInput | undefined
|
|
19
|
+
category?: LinkInput | undefined
|
|
20
|
+
author?: string | undefined
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const list = tv({
|
|
24
|
+
slots: {
|
|
25
|
+
header: 'mb-10 flex max-w-2xl flex-col gap-3',
|
|
26
|
+
heading: 'text-3xl [font-weight:var(--font-weight-heading,700)] tracking-tight text-balance md:text-4xl',
|
|
27
|
+
intro: 'text-lg opacity-80',
|
|
28
|
+
items: 'grid gap-8',
|
|
29
|
+
more: 'mt-10',
|
|
30
|
+
},
|
|
31
|
+
variants: {
|
|
32
|
+
layout: {
|
|
33
|
+
grid: { items: 'sm:grid-cols-2' },
|
|
34
|
+
list: { items: 'gap-6' },
|
|
35
|
+
// The first post spans the whole row, image beside text; the others fill the grid under it.
|
|
36
|
+
featured: { items: 'sm:grid-cols-2 [&>li:first-child]:sm:col-span-2' },
|
|
37
|
+
compact: { items: 'gap-4' },
|
|
38
|
+
},
|
|
39
|
+
columns: { '2': {}, '3': {}, '4': {} },
|
|
40
|
+
},
|
|
41
|
+
compoundVariants: [
|
|
42
|
+
{ layout: ['grid', 'featured'], columns: '3', class: { items: 'lg:grid-cols-3 [&>li:first-child]:lg:col-span-3' } },
|
|
43
|
+
{ layout: ['grid', 'featured'], columns: '4', class: { items: 'md:grid-cols-2 lg:grid-cols-4 [&>li:first-child]:lg:col-span-4' } },
|
|
44
|
+
],
|
|
45
|
+
defaultVariants: { layout: 'grid', columns: '3' },
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
interface Props {
|
|
49
|
+
heading?: string | undefined
|
|
50
|
+
intro?: string | undefined
|
|
51
|
+
posts: PostItem[]
|
|
52
|
+
layout?: 'grid' | 'list' | 'featured' | 'compact' | undefined
|
|
53
|
+
/** Cards per row on wide screens (grid and featured). */
|
|
54
|
+
columns?: '2' | '3' | '4' | undefined
|
|
55
|
+
/** Which parts of a card the design shows. */
|
|
56
|
+
showImage?: boolean | undefined
|
|
57
|
+
showExcerpt?: boolean | undefined
|
|
58
|
+
showAuthor?: boolean | undefined
|
|
59
|
+
showCategory?: boolean | undefined
|
|
60
|
+
excerptLines?: 2 | 3 | 4 | undefined
|
|
61
|
+
/** BCP 47 locale the dates are written in. */
|
|
62
|
+
locale?: string | undefined
|
|
63
|
+
/** Card surface: none, or each post its own card. */
|
|
64
|
+
surface?: 'plain' | 'card' | undefined
|
|
65
|
+
/** Where the full archive lives; with `moreLabel` a link follows the list. */
|
|
66
|
+
moreHref?: string | undefined
|
|
67
|
+
moreLabel?: string | undefined
|
|
68
|
+
tone?: 'default' | 'muted' | 'inverse' | 'accent' | undefined
|
|
69
|
+
/** The source section's measured style (`MeasuredStyle`): frame, padding, fill, background image, columns per width, gap. Absent, the site's tokens; present, it wins over tone and columns. */
|
|
70
|
+
measured?: MeasuredStyle | undefined
|
|
71
|
+
id?: string | undefined
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const { heading, intro, posts, layout = 'grid', columns, showImage = true, showExcerpt = true, showAuthor = true, showCategory = true, excerptLines, locale, surface, moreHref, moreLabel, tone, measured, id = 'posts' } = Astro.props
|
|
75
|
+
const s = list({ layout, columns })
|
|
76
|
+
const headingId = heading ? `${id}-title` : undefined
|
|
77
|
+
// Cards sit one heading level under the section's; with no section heading they are the page's h2s.
|
|
78
|
+
const headingLevel = heading ? 3 : 2
|
|
79
|
+
const sizes = layout === 'list' || layout === 'compact' ? '256px' : columns === '4' ? '(min-width: 1024px) 25vw, 50vw' : columns === '2' ? '(min-width: 640px) 50vw, 100vw' : '(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw'
|
|
80
|
+
// A featured first post is read as a horizontal card; the rest take the grid's vertical one.
|
|
81
|
+
const cardLayout = (i: number) => layout === 'compact' ? 'minimal' : layout === 'list' || (layout === 'featured' && i === 0) ? 'horizontal' : 'vertical'
|
|
82
|
+
---
|
|
83
|
+
{posts.length > 0 && (
|
|
84
|
+
<Section measured={measured} tone={tone} id={id} aria-labelledby={headingId}>
|
|
85
|
+
{(heading || intro) && (
|
|
86
|
+
<header class={s.header()}>
|
|
87
|
+
{heading && <h2 id={headingId} class={s.heading()}>{heading}</h2>}
|
|
88
|
+
{intro && <p class={s.intro()} data-kit-text>{intro}</p>}
|
|
89
|
+
</header>
|
|
90
|
+
)}
|
|
91
|
+
<ul class={s.items({ class: layout === 'grid' || layout === 'featured' ? measuredGrid(measured) : undefined })}>
|
|
92
|
+
{posts.map((post, i) => (
|
|
93
|
+
<li>
|
|
94
|
+
<PostCard
|
|
95
|
+
title={post.title}
|
|
96
|
+
href={post.href}
|
|
97
|
+
excerpt={showExcerpt && layout !== 'compact' ? post.excerpt : undefined}
|
|
98
|
+
date={post.date}
|
|
99
|
+
locale={locale}
|
|
100
|
+
image={showImage && layout !== 'compact' ? post.image : undefined}
|
|
101
|
+
category={showCategory && layout !== 'compact' ? post.category : undefined}
|
|
102
|
+
author={showAuthor && layout !== 'compact' ? post.author : undefined}
|
|
103
|
+
headingLevel={headingLevel}
|
|
104
|
+
layout={cardLayout(i)}
|
|
105
|
+
surface={surface}
|
|
106
|
+
excerptLines={excerptLines}
|
|
107
|
+
sizes={sizes}
|
|
108
|
+
/>
|
|
109
|
+
</li>
|
|
110
|
+
))}
|
|
111
|
+
</ul>
|
|
112
|
+
{moreHref && moreLabel && <p class={s.more()}><a href={moreHref} class="font-medium text-accent-text underline underline-offset-4">{moreLabel}</a></p>}
|
|
113
|
+
</Section>
|
|
114
|
+
)}
|