@cogenta/theme-magazine 1.1.3 → 1.3.4
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 +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/render/article.d.ts +32 -0
- package/dist/src/render/article.d.ts.map +1 -0
- package/dist/src/render/article.js +137 -0
- package/dist/src/render/article.js.map +1 -0
- package/dist/src/render/blocks/accordion.d.ts.map +1 -1
- package/dist/src/render/blocks/accordion.js +9 -13
- package/dist/src/render/blocks/accordion.js.map +1 -1
- package/dist/src/render/blocks/collection-list.d.ts.map +1 -1
- package/dist/src/render/blocks/collection-list.js +91 -118
- package/dist/src/render/blocks/collection-list.js.map +1 -1
- package/dist/src/render/blocks/cta.d.ts +4 -4
- package/dist/src/render/blocks/cta.d.ts.map +1 -1
- package/dist/src/render/blocks/cta.js +7 -9
- package/dist/src/render/blocks/cta.js.map +1 -1
- package/dist/src/render/blocks/embed.d.ts.map +1 -1
- package/dist/src/render/blocks/embed.js +17 -20
- package/dist/src/render/blocks/embed.js.map +1 -1
- package/dist/src/render/blocks/faq.d.ts.map +1 -1
- package/dist/src/render/blocks/faq.js +12 -11
- package/dist/src/render/blocks/faq.js.map +1 -1
- package/dist/src/render/blocks/feature-grid.d.ts.map +1 -1
- package/dist/src/render/blocks/feature-grid.js +13 -20
- package/dist/src/render/blocks/feature-grid.js.map +1 -1
- package/dist/src/render/blocks/gallery.d.ts +6 -6
- package/dist/src/render/blocks/gallery.d.ts.map +1 -1
- package/dist/src/render/blocks/gallery.js +15 -13
- package/dist/src/render/blocks/gallery.js.map +1 -1
- package/dist/src/render/blocks/hero.d.ts +6 -5
- package/dist/src/render/blocks/hero.d.ts.map +1 -1
- package/dist/src/render/blocks/hero.js +15 -14
- package/dist/src/render/blocks/hero.js.map +1 -1
- package/dist/src/render/blocks/logo-strip.d.ts.map +1 -1
- package/dist/src/render/blocks/logo-strip.js +8 -11
- package/dist/src/render/blocks/logo-strip.js.map +1 -1
- package/dist/src/render/blocks/logos.d.ts.map +1 -1
- package/dist/src/render/blocks/logos.js +16 -16
- package/dist/src/render/blocks/logos.js.map +1 -1
- package/dist/src/render/blocks/media-figure.d.ts +8 -8
- package/dist/src/render/blocks/media-figure.d.ts.map +1 -1
- package/dist/src/render/blocks/media-figure.js +23 -19
- package/dist/src/render/blocks/media-figure.js.map +1 -1
- package/dist/src/render/blocks/pricing-table.d.ts.map +1 -1
- package/dist/src/render/blocks/pricing-table.js +19 -22
- package/dist/src/render/blocks/pricing-table.js.map +1 -1
- package/dist/src/render/blocks/prose.d.ts +6 -10
- package/dist/src/render/blocks/prose.d.ts.map +1 -1
- package/dist/src/render/blocks/prose.js +8 -11
- package/dist/src/render/blocks/prose.js.map +1 -1
- package/dist/src/render/blocks/quote.d.ts +6 -9
- package/dist/src/render/blocks/quote.d.ts.map +1 -1
- package/dist/src/render/blocks/quote.js +11 -13
- package/dist/src/render/blocks/quote.js.map +1 -1
- package/dist/src/render/blocks/stat-counter.d.ts.map +1 -1
- package/dist/src/render/blocks/stat-counter.js +9 -10
- package/dist/src/render/blocks/stat-counter.js.map +1 -1
- package/dist/src/render/blocks/stats.d.ts.map +1 -1
- package/dist/src/render/blocks/stats.js +9 -12
- package/dist/src/render/blocks/stats.js.map +1 -1
- package/dist/src/render/blocks/testimonial.d.ts +4 -13
- package/dist/src/render/blocks/testimonial.d.ts.map +1 -1
- package/dist/src/render/blocks/testimonial.js +7 -15
- package/dist/src/render/blocks/testimonial.js.map +1 -1
- package/dist/src/render/chrome.d.ts.map +1 -1
- package/dist/src/render/chrome.js +109 -97
- package/dist/src/render/chrome.js.map +1 -1
- package/dist/src/render/layout.d.ts +28 -0
- package/dist/src/render/layout.d.ts.map +1 -0
- package/dist/src/render/layout.js +72 -0
- package/dist/src/render/layout.js.map +1 -0
- package/dist/src/render/render-block.d.ts +15 -13
- package/dist/src/render/render-block.d.ts.map +1 -1
- package/dist/src/render/render-block.js +53 -29
- package/dist/src/render/render-block.js.map +1 -1
- package/dist/src/render/story.d.ts +41 -0
- package/dist/src/render/story.d.ts.map +1 -0
- package/dist/src/render/story.js +65 -0
- package/dist/src/render/story.js.map +1 -0
- package/dist/src/render/term-archive.d.ts +0 -10
- package/dist/src/render/term-archive.d.ts.map +1 -1
- package/dist/src/render/term-archive.js +42 -19
- package/dist/src/render/term-archive.js.map +1 -1
- package/dist/src/render/widget-areas.d.ts +12 -0
- package/dist/src/render/widget-areas.d.ts.map +1 -0
- package/dist/src/render/widget-areas.js +19 -0
- package/dist/src/render/widget-areas.js.map +1 -0
- package/dist/theme.config.js +2 -2
- package/dist/theme.config.js.map +1 -1
- package/package.json +5 -5
- package/src/index.ts +3 -0
- package/src/render/article.ts +239 -0
- package/src/render/blocks/accordion.ts +23 -30
- package/src/render/blocks/collection-list.ts +161 -225
- package/src/render/blocks/cta.ts +19 -13
- package/src/render/blocks/embed.ts +40 -36
- package/src/render/blocks/faq.ts +31 -36
- package/src/render/blocks/feature-grid.ts +26 -36
- package/src/render/blocks/gallery.ts +24 -18
- package/src/render/blocks/hero.ts +32 -32
- package/src/render/blocks/logo-strip.ts +17 -17
- package/src/render/blocks/logos.ts +23 -31
- package/src/render/blocks/media-figure.ts +36 -20
- package/src/render/blocks/pricing-table.ts +29 -34
- package/src/render/blocks/prose.ts +13 -13
- package/src/render/blocks/quote.ts +24 -24
- package/src/render/blocks/stat-counter.ts +16 -24
- package/src/render/blocks/stats.ts +14 -24
- package/src/render/blocks/testimonial.ts +12 -17
- package/src/render/chrome.ts +123 -104
- package/src/render/layout.ts +105 -0
- package/src/render/render-block.ts +61 -33
- package/src/render/story.ts +139 -0
- package/src/render/term-archive.ts +111 -58
- package/src/render/widget-areas.ts +22 -0
- package/src/styles/archive.css +114 -17
- package/src/styles/article.css +237 -0
- package/src/styles/base.css +848 -591
- package/src/styles/blocks.css +903 -921
- package/src/styles/stories.css +593 -0
- package/src/styles/theme.css +28 -9
- package/src/styles/tokens.css +200 -185
- package/src/styles/widgets.css +614 -0
- package/tokens.json +18 -18
|
@@ -1,50 +1,43 @@
|
|
|
1
1
|
import type { AccordionBlock, AccordionItem } from '@cogenta/blocks'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
type HtmlElement,
|
|
5
|
-
h,
|
|
6
|
-
heading,
|
|
7
|
-
type RenderContext,
|
|
8
|
-
renderRichText,
|
|
9
|
-
} from '@cogenta/theme-kit'
|
|
2
|
+
import { type HtmlElement, h, type RenderContext, renderRichText } from '@cogenta/theme-kit'
|
|
3
|
+
import { section, sectionHead } from '../layout.js'
|
|
10
4
|
|
|
11
5
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* of a numeral, so the two blocks can diverge visually later without one
|
|
18
|
-
* depending on the other. "Accordion" and "frequently asked question" are
|
|
19
|
-
* different editorial intents even where the question/answer shape coincides.
|
|
6
|
+
* A set of collapsible notes on a ruled list: each question on its own row
|
|
7
|
+
* in the interface face, a plus drawn from two hairlines that turns into a
|
|
8
|
+
* minus when the row is open, and the answer in the reading face. Opening,
|
|
9
|
+
* keyboard behaviour and the announced state are all native `<details>`. No
|
|
10
|
+
* script.
|
|
20
11
|
*/
|
|
21
12
|
function renderItem(item: AccordionItem, ctx: RenderContext): HtmlElement {
|
|
22
13
|
return h(
|
|
23
14
|
'li',
|
|
24
|
-
{ class: 'cg-
|
|
15
|
+
{ class: 'cg-notes__item' },
|
|
25
16
|
h(
|
|
26
17
|
'details',
|
|
27
|
-
{ class: 'cg-
|
|
28
|
-
h(
|
|
29
|
-
|
|
18
|
+
{ class: 'cg-notes__details' },
|
|
19
|
+
h(
|
|
20
|
+
'summary',
|
|
21
|
+
{ class: 'cg-notes__question' },
|
|
22
|
+
h('span', { class: 'cg-notes__question-text' }, item.question),
|
|
23
|
+
h('span', { class: 'cg-notes__mark', 'aria-hidden': 'true' }),
|
|
24
|
+
),
|
|
25
|
+
h('div', { class: 'cg-notes__answer' }, renderRichText(ctx, item.answer)),
|
|
30
26
|
),
|
|
31
27
|
)
|
|
32
28
|
}
|
|
33
29
|
|
|
34
30
|
export function renderAccordion(block: AccordionBlock, ctx: RenderContext): HtmlElement {
|
|
35
|
-
return
|
|
31
|
+
return section(
|
|
36
32
|
'section',
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
{ class: 'cg-dossier__title', 'data-field': 'title' },
|
|
43
|
-
block.title,
|
|
44
|
-
),
|
|
33
|
+
'accordion',
|
|
34
|
+
'cg-notes',
|
|
35
|
+
{},
|
|
36
|
+
'div',
|
|
37
|
+
sectionHead('accordion', block.title),
|
|
45
38
|
h(
|
|
46
39
|
'ul',
|
|
47
|
-
{ class: 'cg-
|
|
40
|
+
{ class: 'cg-notes__items' },
|
|
48
41
|
block.items.map((item) => renderItem(item, ctx)),
|
|
49
42
|
),
|
|
50
43
|
)
|
|
@@ -1,239 +1,178 @@
|
|
|
1
1
|
import type { CollectionListBlock } from '@cogenta/blocks'
|
|
2
2
|
import {
|
|
3
|
-
blockHeadingTag,
|
|
4
3
|
buildCollectionListQuery,
|
|
5
4
|
type ContentEntry,
|
|
6
|
-
entryDate,
|
|
7
|
-
entryExcerpt,
|
|
8
|
-
entryHref,
|
|
9
|
-
entryImage,
|
|
10
|
-
entryTitle,
|
|
11
5
|
type HeadingTag,
|
|
12
6
|
type HtmlElement,
|
|
13
7
|
h,
|
|
14
|
-
heading,
|
|
15
8
|
nestedHeadingTag,
|
|
16
9
|
type RenderContext,
|
|
17
|
-
renderImageSource,
|
|
18
10
|
} from '@cogenta/theme-kit'
|
|
11
|
+
import { section, sectionHead } from '../layout.js'
|
|
12
|
+
import { renderStory, type Story, storyFromEntry } from '../story.js'
|
|
19
13
|
|
|
20
14
|
export { buildCollectionListQuery as query }
|
|
21
15
|
|
|
22
16
|
/**
|
|
23
|
-
* A
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
17
|
+
* A listing, set in one of four newspaper forms chosen from what the editor
|
|
18
|
+
* already decided in contract B (the layout, and whether the list has a
|
|
19
|
+
* title), never from a setting this theme invents:
|
|
20
|
+
*
|
|
21
|
+
* - `grid` without a title is **the front**: the first story across eight
|
|
22
|
+
* columns with its photograph, a column of three briefs beside it behind a
|
|
23
|
+
* vertical rule, and every further story in a row of four below, divided
|
|
24
|
+
* by hairlines. This is the opening of a front page.
|
|
25
|
+
* - `grid` with a title is **a rail**: the section label on a heavy rule,
|
|
26
|
+
* its newest story large with a photograph, and the rest as a column of
|
|
27
|
+
* headlines beside it.
|
|
28
|
+
* - `carousel` is **a strip**: stories side by side between column rules,
|
|
29
|
+
* scrolling on a narrow screen. It is how the opinion columns are set,
|
|
30
|
+
* with the columnist's name in the kicker.
|
|
31
|
+
* - `list` is **a ranked list**: numbered, the numerals in the display face,
|
|
32
|
+
* side by side on a wide screen.
|
|
33
|
+
*
|
|
34
|
+
* An empty list keeps its head and says so in one line.
|
|
33
35
|
*/
|
|
34
|
-
const SECTION_FIELDS = ['section', 'category', 'topic', 'department'] as const
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
for (const field of SECTION_FIELDS) {
|
|
38
|
-
const value = entry[field]
|
|
39
|
-
if (typeof value === 'string' && value.trim() !== '') return value
|
|
40
|
-
}
|
|
41
|
-
return undefined
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function formatDate(iso: string, ctx: RenderContext, style: 'long' | 'medium'): string {
|
|
45
|
-
try {
|
|
46
|
-
return new Intl.DateTimeFormat(ctx.locale, { dateStyle: style }).format(new Date(iso))
|
|
47
|
-
} catch {
|
|
48
|
-
return iso
|
|
49
|
-
}
|
|
50
|
-
}
|
|
37
|
+
const FRONT_BRIEFS = 3
|
|
51
38
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
* first entry, per the L25 pro-pass brief.
|
|
57
|
-
*/
|
|
58
|
-
function renderLead(entry: ContentEntry, ctx: RenderContext, tag: HeadingTag): HtmlElement {
|
|
59
|
-
const date = entryDate(entry)
|
|
60
|
-
const excerpt = entryExcerpt(entry)
|
|
61
|
-
const section = entrySection(entry)
|
|
62
|
-
const cover = entryImage(entry, ctx, { width: 1200, height: 675, fit: 'cover' })
|
|
39
|
+
function frontStories(stories: readonly Story[], tag: HeadingTag): HtmlElement {
|
|
40
|
+
const [lead, ...others] = stories
|
|
41
|
+
const briefs = others.slice(0, FRONT_BRIEFS)
|
|
42
|
+
const more = others.slice(FRONT_BRIEFS)
|
|
63
43
|
return h(
|
|
64
|
-
'
|
|
65
|
-
{ class: 'cg-
|
|
66
|
-
|
|
44
|
+
'div',
|
|
45
|
+
{ class: 'cg-front', 'data-briefs': String(briefs.length), 'data-more': String(more.length) },
|
|
46
|
+
lead === undefined
|
|
67
47
|
? null
|
|
68
48
|
: h(
|
|
69
|
-
'
|
|
70
|
-
{ class: 'cg-
|
|
71
|
-
|
|
72
|
-
|
|
49
|
+
'div',
|
|
50
|
+
{ class: 'cg-front__lead' },
|
|
51
|
+
renderStory(lead, {
|
|
52
|
+
tag,
|
|
53
|
+
variant: 'lead',
|
|
54
|
+
image: true,
|
|
55
|
+
standfirst: true,
|
|
56
|
+
sizes: '(min-width: 64rem) 52rem, 100vw',
|
|
73
57
|
loading: 'eager',
|
|
74
|
-
sizes: '(min-width: 64rem) 76rem, 100vw',
|
|
75
58
|
}),
|
|
76
59
|
),
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
heading(
|
|
80
|
-
tag,
|
|
81
|
-
{ class: 'cg-issue__lead-title' },
|
|
82
|
-
h('a', { class: 'cg-issue__link', href: entryHref(entry, ctx) }, entryTitle(entry, ctx)),
|
|
83
|
-
),
|
|
84
|
-
excerpt === undefined ? null : h('p', { class: 'cg-issue__lead-excerpt' }, excerpt),
|
|
85
|
-
date === undefined
|
|
86
|
-
? null
|
|
87
|
-
: h(
|
|
88
|
-
'time',
|
|
89
|
-
{ class: 'cg-issue__lead-date', datetime: date },
|
|
90
|
-
formatDate(date, ctx, 'long'),
|
|
91
|
-
),
|
|
92
|
-
]),
|
|
93
|
-
)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/** A card in the "rest" 3-column grid: cover, section eyebrow, title, date — no excerpt (the lead alone carries one). */
|
|
97
|
-
function renderCard(entry: ContentEntry, ctx: RenderContext, tag: HeadingTag): HtmlElement {
|
|
98
|
-
const date = entryDate(entry)
|
|
99
|
-
const section = entrySection(entry)
|
|
100
|
-
const cover = entryImage(entry, ctx, { width: 480, height: 320, fit: 'cover' })
|
|
101
|
-
return h(
|
|
102
|
-
'li',
|
|
103
|
-
{ class: 'cg-issue__card-item' },
|
|
104
|
-
h(
|
|
105
|
-
'article',
|
|
106
|
-
{ class: 'cg-issue__card' },
|
|
107
|
-
cover === undefined
|
|
108
|
-
? null
|
|
109
|
-
: h(
|
|
110
|
-
'a',
|
|
111
|
-
{ class: 'cg-issue__card-cover-link', href: entryHref(entry, ctx), tabindex: -1 },
|
|
112
|
-
renderImageSource(cover, {
|
|
113
|
-
className: 'cg-issue__card-cover',
|
|
114
|
-
sizes: '(min-width: 64rem) 24rem, (min-width: 48rem) 45vw, 100vw',
|
|
115
|
-
}),
|
|
116
|
-
),
|
|
117
|
-
section === undefined ? null : h('p', { class: 'cg-issue__card-eyebrow' }, section),
|
|
118
|
-
heading(
|
|
119
|
-
tag,
|
|
120
|
-
{ class: 'cg-issue__card-title' },
|
|
121
|
-
h('a', { class: 'cg-issue__link', href: entryHref(entry, ctx) }, entryTitle(entry, ctx)),
|
|
122
|
-
),
|
|
123
|
-
date === undefined
|
|
124
|
-
? null
|
|
125
|
-
: h(
|
|
126
|
-
'time',
|
|
127
|
-
{ class: 'cg-issue__card-date', datetime: date },
|
|
128
|
-
formatDate(date, ctx, 'medium'),
|
|
129
|
-
),
|
|
130
|
-
),
|
|
131
|
-
)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* A rail row for `layout: 'list'` — a small square thumbnail (when the entry
|
|
136
|
-
* has one) beside the title and date, the "rubric rail" treatment; a plain
|
|
137
|
-
* numbered row (this theme's original front-page-index look) when the entry
|
|
138
|
-
* carries no image, so a collection with no cover field still reads as a
|
|
139
|
-
* considered contents strip rather than a broken thumbnail.
|
|
140
|
-
*/
|
|
141
|
-
function renderRow(
|
|
142
|
-
entry: ContentEntry,
|
|
143
|
-
ctx: RenderContext,
|
|
144
|
-
tag: HeadingTag,
|
|
145
|
-
index: number,
|
|
146
|
-
): HtmlElement {
|
|
147
|
-
const date = entryDate(entry)
|
|
148
|
-
const cover = entryImage(entry, ctx, { width: 112, height: 112, fit: 'cover' })
|
|
149
|
-
return h(
|
|
150
|
-
'li',
|
|
151
|
-
{ class: 'cg-issue__row' },
|
|
152
|
-
cover === undefined
|
|
153
|
-
? h(
|
|
154
|
-
'span',
|
|
155
|
-
{ class: 'cg-issue__row-number', 'aria-hidden': 'true' },
|
|
156
|
-
String(index).padStart(2, '0'),
|
|
157
|
-
)
|
|
60
|
+
briefs.length === 0
|
|
61
|
+
? null
|
|
158
62
|
: h(
|
|
159
|
-
'
|
|
160
|
-
{ class: 'cg-
|
|
161
|
-
|
|
63
|
+
'ul',
|
|
64
|
+
{ class: 'cg-front__briefs' },
|
|
65
|
+
briefs.map((story) =>
|
|
66
|
+
h(
|
|
67
|
+
'li',
|
|
68
|
+
{ class: 'cg-front__brief' },
|
|
69
|
+
renderStory(story, { tag, variant: 'brief', standfirst: true }),
|
|
70
|
+
),
|
|
71
|
+
),
|
|
162
72
|
),
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
73
|
+
more.length === 0
|
|
74
|
+
? null
|
|
75
|
+
: h(
|
|
76
|
+
'ul',
|
|
77
|
+
{ class: 'cg-front__more' },
|
|
78
|
+
more.map((story) =>
|
|
79
|
+
h(
|
|
80
|
+
'li',
|
|
81
|
+
{ class: 'cg-front__item' },
|
|
82
|
+
renderStory(story, {
|
|
83
|
+
tag,
|
|
84
|
+
variant: 'secondary',
|
|
85
|
+
image: true,
|
|
86
|
+
sizes: '(min-width: 64rem) 18rem, (min-width: 40rem) 45vw, 100vw',
|
|
87
|
+
}),
|
|
88
|
+
),
|
|
177
89
|
),
|
|
178
|
-
|
|
90
|
+
),
|
|
179
91
|
)
|
|
180
92
|
}
|
|
181
93
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
const date = entryDate(entry)
|
|
185
|
-
const excerpt = entryExcerpt(entry)
|
|
186
|
-
const section = entrySection(entry)
|
|
187
|
-
const cover = entryImage(entry, ctx, { width: 480, height: 320, fit: 'cover' })
|
|
94
|
+
function railStories(stories: readonly Story[], tag: HeadingTag): HtmlElement {
|
|
95
|
+
const [lead, ...others] = stories
|
|
188
96
|
return h(
|
|
189
|
-
'
|
|
190
|
-
{ class: 'cg-
|
|
191
|
-
|
|
97
|
+
'div',
|
|
98
|
+
{ class: 'cg-rail', 'data-count': String(stories.length) },
|
|
99
|
+
lead === undefined
|
|
192
100
|
? null
|
|
193
101
|
: h(
|
|
194
|
-
'
|
|
195
|
-
{ class: 'cg-
|
|
196
|
-
|
|
102
|
+
'div',
|
|
103
|
+
{ class: 'cg-rail__lead' },
|
|
104
|
+
renderStory(lead, {
|
|
105
|
+
tag,
|
|
106
|
+
variant: 'rail',
|
|
107
|
+
image: true,
|
|
108
|
+
standfirst: true,
|
|
109
|
+
date: true,
|
|
110
|
+
sizes: '(min-width: 64rem) 34rem, 100vw',
|
|
111
|
+
}),
|
|
197
112
|
),
|
|
198
|
-
|
|
199
|
-
heading(
|
|
200
|
-
tag,
|
|
201
|
-
{ class: 'cg-issue__frame-title' },
|
|
202
|
-
h('a', { class: 'cg-issue__link', href: entryHref(entry, ctx) }, entryTitle(entry, ctx)),
|
|
203
|
-
),
|
|
204
|
-
date === undefined
|
|
113
|
+
others.length === 0
|
|
205
114
|
? null
|
|
206
115
|
: h(
|
|
207
|
-
'
|
|
208
|
-
{ class: 'cg-
|
|
209
|
-
|
|
116
|
+
'ul',
|
|
117
|
+
{ class: 'cg-rail__list' },
|
|
118
|
+
others.map((story) =>
|
|
119
|
+
h(
|
|
120
|
+
'li',
|
|
121
|
+
{ class: 'cg-rail__item' },
|
|
122
|
+
renderStory(story, {
|
|
123
|
+
tag,
|
|
124
|
+
variant: 'column',
|
|
125
|
+
image: true,
|
|
126
|
+
standfirst: true,
|
|
127
|
+
date: true,
|
|
128
|
+
sizes: '(min-width: 64rem) 9rem, 30vw',
|
|
129
|
+
}),
|
|
130
|
+
),
|
|
131
|
+
),
|
|
210
132
|
),
|
|
211
|
-
excerpt === undefined ? null : h('p', { class: 'cg-issue__frame-excerpt' }, excerpt),
|
|
212
133
|
)
|
|
213
134
|
}
|
|
214
135
|
|
|
215
|
-
function
|
|
216
|
-
|
|
217
|
-
|
|
136
|
+
function stripStories(
|
|
137
|
+
stories: readonly Story[],
|
|
138
|
+
tag: HeadingTag,
|
|
139
|
+
label: string,
|
|
140
|
+
count: number,
|
|
141
|
+
): HtmlElement {
|
|
218
142
|
return h(
|
|
219
143
|
'div',
|
|
220
|
-
{
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
:
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
144
|
+
{
|
|
145
|
+
class: 'cg-strip',
|
|
146
|
+
role: 'region',
|
|
147
|
+
'aria-label': label,
|
|
148
|
+
tabindex: '0',
|
|
149
|
+
'data-count': String(Math.min(count, 4)),
|
|
150
|
+
},
|
|
151
|
+
h(
|
|
152
|
+
'ul',
|
|
153
|
+
{ class: 'cg-strip__items' },
|
|
154
|
+
stories.map((story) =>
|
|
155
|
+
h(
|
|
156
|
+
'li',
|
|
157
|
+
{ class: 'cg-strip__item' },
|
|
158
|
+
renderStory(story, { tag, variant: 'strip', standfirst: true }),
|
|
228
159
|
),
|
|
160
|
+
),
|
|
161
|
+
),
|
|
229
162
|
)
|
|
230
163
|
}
|
|
231
164
|
|
|
232
|
-
function
|
|
165
|
+
function rankedStories(stories: readonly Story[], tag: HeadingTag): HtmlElement {
|
|
233
166
|
return h(
|
|
234
|
-
'
|
|
235
|
-
{ class: 'cg-
|
|
236
|
-
|
|
167
|
+
'ol',
|
|
168
|
+
{ class: 'cg-ranked', 'data-count': String(Math.min(stories.length, 5)) },
|
|
169
|
+
stories.map((story, index) =>
|
|
170
|
+
h(
|
|
171
|
+
'li',
|
|
172
|
+
{ class: 'cg-ranked__item' },
|
|
173
|
+
renderStory(story, { tag, variant: 'ranked', numeral: String(index + 1) }),
|
|
174
|
+
),
|
|
175
|
+
),
|
|
237
176
|
)
|
|
238
177
|
}
|
|
239
178
|
|
|
@@ -242,45 +181,42 @@ export function renderCollectionList(
|
|
|
242
181
|
ctx: RenderContext,
|
|
243
182
|
entries: readonly ContentEntry[],
|
|
244
183
|
): HtmlElement {
|
|
245
|
-
const
|
|
246
|
-
const
|
|
184
|
+
const titled = block.title !== undefined
|
|
185
|
+
const tag = nestedHeadingTag('collectionList', titled)
|
|
186
|
+
const form =
|
|
187
|
+
block.layout === 'grid'
|
|
188
|
+
? titled
|
|
189
|
+
? 'rail'
|
|
190
|
+
: 'front'
|
|
191
|
+
: block.layout === 'carousel'
|
|
192
|
+
? 'strip'
|
|
193
|
+
: 'ranked'
|
|
194
|
+
const imageWidth = form === 'front' ? 1200 : form === 'rail' ? 800 : 480
|
|
195
|
+
const stories = entries.map((entry) => storyFromEntry(entry, ctx, imageWidth))
|
|
247
196
|
|
|
248
197
|
const body =
|
|
249
|
-
|
|
250
|
-
? h('p', { class: 'cg-
|
|
251
|
-
:
|
|
252
|
-
?
|
|
253
|
-
:
|
|
254
|
-
?
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
'ul',
|
|
264
|
-
{ class: 'cg-issue__frames' },
|
|
265
|
-
entries.map((entry) => renderFrame(entry, ctx, entryTag)),
|
|
266
|
-
),
|
|
267
|
-
)
|
|
268
|
-
: renderList(entries, ctx, entryTag)
|
|
198
|
+
stories.length === 0
|
|
199
|
+
? h('p', { class: 'cg-empty' }, ctx.t('collection.empty'))
|
|
200
|
+
: form === 'front'
|
|
201
|
+
? frontStories(stories, tag)
|
|
202
|
+
: form === 'rail'
|
|
203
|
+
? railStories(stories, tag)
|
|
204
|
+
: form === 'strip'
|
|
205
|
+
? stripStories(
|
|
206
|
+
stories,
|
|
207
|
+
tag,
|
|
208
|
+
block.title ?? ctx.t('collection.carousel'),
|
|
209
|
+
stories.length,
|
|
210
|
+
)
|
|
211
|
+
: rankedStories(stories, tag)
|
|
269
212
|
|
|
270
|
-
return
|
|
213
|
+
return section(
|
|
271
214
|
'section',
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
hasTitle
|
|
278
|
-
? heading(
|
|
279
|
-
blockHeadingTag('collectionList') ?? 'h2',
|
|
280
|
-
{ class: 'cg-issue__title', 'data-field': 'title' },
|
|
281
|
-
block.title ?? '',
|
|
282
|
-
)
|
|
283
|
-
: null,
|
|
215
|
+
'collectionList',
|
|
216
|
+
'cg-listing',
|
|
217
|
+
{ 'data-layout': block.layout, 'data-form': form },
|
|
218
|
+
'div',
|
|
219
|
+
sectionHead('collectionList', block.title),
|
|
284
220
|
body,
|
|
285
221
|
)
|
|
286
222
|
}
|
package/src/render/blocks/cta.ts
CHANGED
|
@@ -7,27 +7,33 @@ import {
|
|
|
7
7
|
heading,
|
|
8
8
|
type RenderContext,
|
|
9
9
|
} from '@cogenta/theme-kit'
|
|
10
|
+
import { section } from '../layout.js'
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
|
-
*
|
|
13
|
-
* a
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* An appeal, set like the subscription panel a newspaper runs between two
|
|
14
|
+
* sections: a double rule above, the title large in the display face across
|
|
15
|
+
* the left seven columns, the text and the actions in the right five. No
|
|
16
|
+
* coloured box: the rules and the type carry it.
|
|
16
17
|
*/
|
|
17
18
|
export function renderCta(block: CtaBlock, ctx: RenderContext): HtmlElement {
|
|
18
|
-
return
|
|
19
|
+
return section(
|
|
19
20
|
'section',
|
|
20
|
-
|
|
21
|
+
'cta',
|
|
22
|
+
'cg-appeal',
|
|
23
|
+
{},
|
|
24
|
+
'div',
|
|
21
25
|
heading(
|
|
22
26
|
blockHeadingTag('cta') ?? 'h2',
|
|
23
|
-
{ class: 'cg-
|
|
27
|
+
{ class: 'cg-appeal__title', 'data-field': 'title' },
|
|
24
28
|
block.title,
|
|
25
29
|
),
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
h(
|
|
31
|
+
'div',
|
|
32
|
+
{ class: 'cg-appeal__body' },
|
|
33
|
+
block.text === undefined
|
|
34
|
+
? null
|
|
35
|
+
: h('p', { class: 'cg-appeal__text', 'data-field': 'text' }, block.text),
|
|
36
|
+
actionList(ctx, block.actions, block.title),
|
|
37
|
+
),
|
|
32
38
|
)
|
|
33
39
|
}
|