@cogenta/theme-association 0.3.2
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/LICENSE +373 -0
- 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/blocks/accordion.d.ts +4 -0
- package/dist/src/render/blocks/accordion.d.ts.map +1 -0
- package/dist/src/render/blocks/accordion.js +16 -0
- package/dist/src/render/blocks/accordion.js.map +1 -0
- package/dist/src/render/blocks/collection-list.d.ts +12 -0
- package/dist/src/render/blocks/collection-list.d.ts.map +1 -0
- package/dist/src/render/blocks/collection-list.js +64 -0
- package/dist/src/render/blocks/collection-list.js.map +1 -0
- package/dist/src/render/blocks/cta.d.ts +9 -0
- package/dist/src/render/blocks/cta.d.ts.map +1 -0
- package/dist/src/render/blocks/cta.js +16 -0
- package/dist/src/render/blocks/cta.js.map +1 -0
- package/dist/src/render/blocks/embed.d.ts +4 -0
- package/dist/src/render/blocks/embed.d.ts.map +1 -0
- package/dist/src/render/blocks/embed.js +76 -0
- package/dist/src/render/blocks/embed.js.map +1 -0
- package/dist/src/render/blocks/faq.d.ts +4 -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 +4 -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 +14 -0
- package/dist/src/render/blocks/gallery.d.ts.map +1 -0
- package/dist/src/render/blocks/gallery.js +27 -0
- package/dist/src/render/blocks/gallery.js.map +1 -0
- package/dist/src/render/blocks/hero.d.ts +15 -0
- package/dist/src/render/blocks/hero.d.ts.map +1 -0
- package/dist/src/render/blocks/hero.js +31 -0
- package/dist/src/render/blocks/hero.js.map +1 -0
- package/dist/src/render/blocks/logo-strip.d.ts +4 -0
- package/dist/src/render/blocks/logo-strip.d.ts.map +1 -0
- package/dist/src/render/blocks/logo-strip.js +16 -0
- package/dist/src/render/blocks/logo-strip.js.map +1 -0
- package/dist/src/render/blocks/logos.d.ts +4 -0
- package/dist/src/render/blocks/logos.d.ts.map +1 -0
- package/dist/src/render/blocks/logos.js +22 -0
- package/dist/src/render/blocks/logos.js.map +1 -0
- package/dist/src/render/blocks/media-figure.d.ts +12 -0
- package/dist/src/render/blocks/media-figure.d.ts.map +1 -0
- package/dist/src/render/blocks/media-figure.js +27 -0
- package/dist/src/render/blocks/media-figure.js.map +1 -0
- package/dist/src/render/blocks/pricing-table.d.ts +4 -0
- package/dist/src/render/blocks/pricing-table.d.ts.map +1 -0
- package/dist/src/render/blocks/pricing-table.js +29 -0
- package/dist/src/render/blocks/pricing-table.js.map +1 -0
- package/dist/src/render/blocks/prose.d.ts +9 -0
- package/dist/src/render/blocks/prose.d.ts.map +1 -0
- package/dist/src/render/blocks/prose.js +10 -0
- package/dist/src/render/blocks/prose.js.map +1 -0
- package/dist/src/render/blocks/quote.d.ts +13 -0
- package/dist/src/render/blocks/quote.d.ts.map +1 -0
- package/dist/src/render/blocks/quote.js +26 -0
- package/dist/src/render/blocks/quote.js.map +1 -0
- package/dist/src/render/blocks/stat-counter.d.ts +4 -0
- package/dist/src/render/blocks/stat-counter.d.ts.map +1 -0
- package/dist/src/render/blocks/stat-counter.js +14 -0
- package/dist/src/render/blocks/stat-counter.js.map +1 -0
- package/dist/src/render/blocks/stats.d.ts +4 -0
- package/dist/src/render/blocks/stats.d.ts.map +1 -0
- package/dist/src/render/blocks/stats.js +18 -0
- package/dist/src/render/blocks/stats.js.map +1 -0
- package/dist/src/render/blocks/testimonial.d.ts +11 -0
- package/dist/src/render/blocks/testimonial.d.ts.map +1 -0
- package/dist/src/render/blocks/testimonial.js +20 -0
- package/dist/src/render/blocks/testimonial.js.map +1 -0
- package/dist/src/render/chrome.d.ts +3 -0
- package/dist/src/render/chrome.d.ts.map +1 -0
- package/dist/src/render/chrome.js +106 -0
- package/dist/src/render/chrome.js.map +1 -0
- package/dist/src/render/render-block.d.ts +21 -0
- package/dist/src/render/render-block.d.ts.map +1 -0
- package/dist/src/render/render-block.js +104 -0
- package/dist/src/render/render-block.js.map +1 -0
- package/dist/src/render/term-archive.d.ts +3 -0
- package/dist/src/render/term-archive.d.ts.map +1 -0
- package/dist/src/render/term-archive.js +42 -0
- package/dist/src/render/term-archive.js.map +1 -0
- package/dist/theme.config.d.ts +15 -0
- package/dist/theme.config.d.ts.map +1 -0
- package/dist/theme.config.js +45 -0
- package/dist/theme.config.js.map +1 -0
- package/package.json +57 -0
- package/src/index.ts +20 -0
- package/src/render/blocks/accordion.ts +47 -0
- package/src/render/blocks/collection-list.ts +144 -0
- package/src/render/blocks/cta.ts +37 -0
- package/src/render/blocks/embed.ts +98 -0
- package/src/render/blocks/faq.ts +52 -0
- package/src/render/blocks/feature-grid.ts +67 -0
- package/src/render/blocks/gallery.ts +47 -0
- package/src/render/blocks/hero.ts +60 -0
- package/src/render/blocks/logo-strip.ts +31 -0
- package/src/render/blocks/logos.ts +52 -0
- package/src/render/blocks/media-figure.ts +38 -0
- package/src/render/blocks/pricing-table.ts +73 -0
- package/src/render/blocks/prose.ts +15 -0
- package/src/render/blocks/quote.ts +39 -0
- package/src/render/blocks/stat-counter.ts +36 -0
- package/src/render/blocks/stats.ts +45 -0
- package/src/render/blocks/testimonial.ts +36 -0
- package/src/render/chrome.ts +134 -0
- package/src/render/render-block.ts +140 -0
- package/src/render/term-archive.ts +92 -0
- package/src/styles/archive.css +129 -0
- package/src/styles/base.css +842 -0
- package/src/styles/blocks.css +1002 -0
- package/src/styles/theme.css +31 -0
- package/src/styles/tokens.css +332 -0
- package/tokens.json +36 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TestimonialBlock } from '@cogenta/blocks';
|
|
2
|
+
import { type HtmlElement, type RenderContext } from '@cogenta/theme-kit';
|
|
3
|
+
/**
|
|
4
|
+
* `blocks@2.0` (RFC 0001). A volunteer's own words — the same
|
|
5
|
+
* `<figure><blockquote>…</blockquote><figcaption>` pattern `quote` uses, but
|
|
6
|
+
* the quote itself is rich text and the attribution is the block's single
|
|
7
|
+
* grouped `attribution` field. The avatar sits in a round frame, echoing the
|
|
8
|
+
* hero's own rounded, friendly treatment.
|
|
9
|
+
*/
|
|
10
|
+
export declare function renderTestimonial(block: TestimonialBlock, ctx: RenderContext): HtmlElement;
|
|
11
|
+
//# sourceMappingURL=testimonial.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testimonial.d.ts","sourceRoot":"","sources":["../../../../src/render/blocks/testimonial.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACvD,OAAO,EAAE,KAAK,WAAW,EAAY,KAAK,aAAa,EAAkB,MAAM,oBAAoB,CAAA;AAEnG;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAE,aAAa,GAAG,WAAW,CAyB1F"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { h, image, renderRichText } from '@cogenta/theme-kit';
|
|
2
|
+
/**
|
|
3
|
+
* `blocks@2.0` (RFC 0001). A volunteer's own words — the same
|
|
4
|
+
* `<figure><blockquote>…</blockquote><figcaption>` pattern `quote` uses, but
|
|
5
|
+
* the quote itself is rich text and the attribution is the block's single
|
|
6
|
+
* grouped `attribution` field. The avatar sits in a round frame, echoing the
|
|
7
|
+
* hero's own rounded, friendly treatment.
|
|
8
|
+
*/
|
|
9
|
+
export function renderTestimonial(block, ctx) {
|
|
10
|
+
const { attribution } = block;
|
|
11
|
+
return h('figure', { class: 'cg-block cg-testimonial', 'data-block': 'testimonial' }, h('blockquote', { class: 'cg-testimonial__quote' }, renderRichText(ctx, block.quote)), h('figcaption', { class: 'cg-testimonial__attribution' }, attribution.avatar === undefined
|
|
12
|
+
? null
|
|
13
|
+
: image(ctx, attribution.avatar, {
|
|
14
|
+
className: 'cg-testimonial__avatar',
|
|
15
|
+
variant: { width: 96, height: 96, fit: 'cover' },
|
|
16
|
+
}), h('span', { class: 'cg-testimonial__who' }, h('span', { class: 'cg-testimonial__name' }, attribution.name), attribution.role === undefined
|
|
17
|
+
? null
|
|
18
|
+
: h('span', { class: 'cg-testimonial__role' }, attribution.role))));
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=testimonial.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testimonial.js","sourceRoot":"","sources":["../../../../src/render/blocks/testimonial.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,CAAC,EAAE,KAAK,EAAsB,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEnG;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAuB,EAAE,GAAkB;IAC3E,MAAM,EAAE,WAAW,EAAE,GAAG,KAAK,CAAA;IAC7B,OAAO,CAAC,CACN,QAAQ,EACR,EAAE,KAAK,EAAE,yBAAyB,EAAE,YAAY,EAAE,aAAa,EAAE,EACjE,CAAC,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE,EAAE,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EACrF,CAAC,CACC,YAAY,EACZ,EAAE,KAAK,EAAE,6BAA6B,EAAE,EACxC,WAAW,CAAC,MAAM,KAAK,SAAS;QAC9B,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,WAAW,CAAC,MAAM,EAAE;YAC7B,SAAS,EAAE,wBAAwB;YACnC,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE;SACjD,CAAC,EACN,CAAC,CACC,MAAM,EACN,EAAE,KAAK,EAAE,qBAAqB,EAAE,EAChC,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,sBAAsB,EAAE,EAAE,WAAW,CAAC,IAAI,CAAC,EAC9D,WAAW,CAAC,IAAI,KAAK,SAAS;QAC5B,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,sBAAsB,EAAE,EAAE,WAAW,CAAC,IAAI,CAAC,CACnE,CACF,CACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chrome.d.ts","sourceRoot":"","sources":["../../../src/render/chrome.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,YAAY,EAOlB,MAAM,oBAAoB,CAAA;AAgE3B,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,CA2D7D"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { escapeAttribute, escapeText, renderBrandMark, renderSocialLinks, renderThemeToggle, serialize, } from '@cogenta/theme-kit';
|
|
2
|
+
/**
|
|
3
|
+
* This theme's own header and footer — a warm, community-notice-board read
|
|
4
|
+
* rather than a corporate one: a sticky header with a pill-shaped nav and a
|
|
5
|
+
* rounded, filled action button, and a four-column footer (brand+tagline,
|
|
6
|
+
* navigation, social, a short note) on a tinted band, closing with Cogenta's
|
|
7
|
+
* own credit.
|
|
8
|
+
*
|
|
9
|
+
* The mobile nav is a `<details>`/`<summary>` disclosure — the same
|
|
10
|
+
* zero-JavaScript mechanism `faq`/`accordion` already use — rather than a
|
|
11
|
+
* scripted hamburger: expanding, keyboard operation and the open state
|
|
12
|
+
* announced to assistive technology all come from the browser. The same
|
|
13
|
+
* links are rendered twice (once inside the disclosure, once as a plain
|
|
14
|
+
* inline row) and `src/styles/base.css` shows exactly one of the two at any
|
|
15
|
+
* given width via `display:none` — which also removes the hidden copy from
|
|
16
|
+
* the accessibility tree, so nothing is ever announced twice.
|
|
17
|
+
*
|
|
18
|
+
* `theme@1.4` (L25 D2) fields — `headerAction`, `tagline`, `social`,
|
|
19
|
+
* `footerNote` — are each rendered only when present; a render with none of
|
|
20
|
+
* them set still produces a complete header/footer, exactly the additive
|
|
21
|
+
* guarantee the contract promises.
|
|
22
|
+
*
|
|
23
|
+
* The manual light/dark toggle (`renderThemeToggle`, `@cogenta/theme-kit`,
|
|
24
|
+
* L26) is unconditional — it sits between the desktop nav and the header
|
|
25
|
+
* action, outside the `<details>` mobile disclosure so it stays reachable at
|
|
26
|
+
* every width rather than one tap deep inside the hamburger menu.
|
|
27
|
+
*/
|
|
28
|
+
function navItems(links) {
|
|
29
|
+
return links
|
|
30
|
+
.filter((link) => link.href !== null || link.kind === 'submenu-placeholder')
|
|
31
|
+
.map((link) => {
|
|
32
|
+
const label = escapeText(link.label);
|
|
33
|
+
const titleAttr = link.title === null ? '' : ` title="${escapeAttribute(link.title)}"`;
|
|
34
|
+
if (link.href === null)
|
|
35
|
+
return `<li><span${titleAttr}>${label}</span></li>`;
|
|
36
|
+
const href = escapeAttribute(link.href);
|
|
37
|
+
const target = link.openInNewTab ? ' target="_blank" rel="noopener"' : '';
|
|
38
|
+
return `<li><a href="${href}"${target}${titleAttr}>${label}</a></li>`;
|
|
39
|
+
})
|
|
40
|
+
.join('');
|
|
41
|
+
}
|
|
42
|
+
function renderNav(links, className, label) {
|
|
43
|
+
const items = navItems(links);
|
|
44
|
+
if (items === '')
|
|
45
|
+
return '';
|
|
46
|
+
return `<nav class="${className}" aria-label="${escapeAttribute(label)}"><ul class="cg-nav__items">${items}</ul></nav>`;
|
|
47
|
+
}
|
|
48
|
+
/** The header's own call-to-action link (`theme@1.4`) — a filled, rounded button, the "Donate"/"Volunteer" treatment. */
|
|
49
|
+
function renderHeaderAction(action) {
|
|
50
|
+
if (action === undefined)
|
|
51
|
+
return '';
|
|
52
|
+
return (`<a class="cg-action cg-site-header__action" data-emphasis="primary" ` +
|
|
53
|
+
`href="${escapeAttribute(action.href)}">${escapeText(action.label)}</a>`);
|
|
54
|
+
}
|
|
55
|
+
/** A plain hamburger glyph — three bars, drawn as `<path>`s so nothing here needs the icon set's closed vocabulary. */
|
|
56
|
+
const MENU_GLYPH = '<svg class="cg-nav-toggle__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">' +
|
|
57
|
+
'<path d="M4 7h16M4 12h16M4 17h16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>' +
|
|
58
|
+
'</svg>';
|
|
59
|
+
export function renderChrome(input) {
|
|
60
|
+
const siteNameText = escapeText(input.site.name);
|
|
61
|
+
const headerNavDesktop = renderNav(input.headerNav, 'cg-nav cg-nav--desktop', 'Primary');
|
|
62
|
+
const headerNavMobile = navItems(input.headerNav);
|
|
63
|
+
const footerNav = renderNav(input.footerNav, 'cg-site-footer__nav', 'Footer');
|
|
64
|
+
const mark = renderBrandMark(input.brand, { className: 'cg-site-header__logo' }) ?? siteNameText;
|
|
65
|
+
const headerAction = renderHeaderAction(input.headerAction);
|
|
66
|
+
const themeToggle = serialize(renderThemeToggle(input.locale, { className: 'cg-theme-toggle' }));
|
|
67
|
+
const mobileToggle = headerNavMobile === ''
|
|
68
|
+
? ''
|
|
69
|
+
: `<details class="cg-nav-toggle">` +
|
|
70
|
+
`<summary class="cg-nav-toggle__button" aria-label="Menu">${MENU_GLYPH}</summary>` +
|
|
71
|
+
`<nav class="cg-nav cg-nav--mobile" aria-label="Primary"><ul class="cg-nav__items">${headerNavMobile}</ul></nav>` +
|
|
72
|
+
`</details>`;
|
|
73
|
+
const header = `<header class="cg-site-header"><div class="cg-site-header__inner">` +
|
|
74
|
+
`<a class="cg-site-header__home" href="${escapeAttribute(input.homeHref)}">${mark}</a>` +
|
|
75
|
+
`${headerNavDesktop}` +
|
|
76
|
+
`${themeToggle}` +
|
|
77
|
+
`${headerAction}` +
|
|
78
|
+
`${mobileToggle}` +
|
|
79
|
+
`</div></header>`;
|
|
80
|
+
const tagline = input.tagline === undefined
|
|
81
|
+
? ''
|
|
82
|
+
: `<p class="cg-site-footer__tagline">${escapeText(input.tagline)}</p>`;
|
|
83
|
+
const social = input.social === undefined
|
|
84
|
+
? ''
|
|
85
|
+
: serialize(renderSocialLinks(input.social, {
|
|
86
|
+
className: 'cg-site-footer__social',
|
|
87
|
+
itemClassName: 'cg-site-footer__social-item',
|
|
88
|
+
}) ?? { kind: 'text', value: '' });
|
|
89
|
+
const footerNote = input.footerNote === undefined
|
|
90
|
+
? ''
|
|
91
|
+
: `<p class="cg-site-footer__note">${escapeText(input.footerNote)}</p>`;
|
|
92
|
+
const footer = `<footer class="cg-site-footer">` +
|
|
93
|
+
`<div class="cg-site-footer__grid">` +
|
|
94
|
+
`<div class="cg-site-footer__brand">` +
|
|
95
|
+
`<a class="cg-site-footer__brand-link" href="${escapeAttribute(input.homeHref)}">${siteNameText}</a>` +
|
|
96
|
+
`${tagline}` +
|
|
97
|
+
`</div>` +
|
|
98
|
+
`<div class="cg-site-footer__col">${footerNav}</div>` +
|
|
99
|
+
`<div class="cg-site-footer__col">${social}</div>` +
|
|
100
|
+
`<div class="cg-site-footer__col">${footerNote}</div>` +
|
|
101
|
+
`</div>` +
|
|
102
|
+
`<div class="cg-site-footer__bottom"><span>${siteNameText}</span>${input.brandingHtml}</div>` +
|
|
103
|
+
`</footer>`;
|
|
104
|
+
return { header, footer };
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=chrome.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chrome.js","sourceRoot":"","sources":["../../../src/render/chrome.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,eAAe,EACf,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,SAAS,GACV,MAAM,oBAAoB,CAAA;AAE3B;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,SAAS,QAAQ,CAAC,KAA+B;IAC/C,OAAO,KAAK;SACT,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,qBAAqB,CAAC;SAC3E,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACpC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAA;QACtF,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO,YAAY,SAAS,IAAI,KAAK,cAAc,CAAA;QAC3E,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,EAAE,CAAA;QACzE,OAAO,gBAAgB,IAAI,IAAI,MAAM,GAAG,SAAS,IAAI,KAAK,WAAW,CAAA;IACvE,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAA;AACb,CAAC;AAED,SAAS,SAAS,CAAC,KAA+B,EAAE,SAAiB,EAAE,KAAa;IAClF,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC7B,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,EAAE,CAAA;IAC3B,OAAO,eAAe,SAAS,iBAAiB,eAAe,CAAC,KAAK,CAAC,+BAA+B,KAAK,aAAa,CAAA;AACzH,CAAC;AAED,yHAAyH;AACzH,SAAS,kBAAkB,CAAC,MAAmC;IAC7D,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,CAAA;IACnC,OAAO,CACL,sEAAsE;QACtE,SAAS,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CACzE,CAAA;AACH,CAAC;AAED,uHAAuH;AACvH,MAAM,UAAU,GACd,4FAA4F;IAC5F,+GAA+G;IAC/G,QAAQ,CAAA;AAEV,MAAM,UAAU,YAAY,CAAC,KAAkB;IAC7C,MAAM,YAAY,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAChD,MAAM,gBAAgB,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,EAAE,wBAAwB,EAAE,SAAS,CAAC,CAAA;IACxF,MAAM,eAAe,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IACjD,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,EAAE,qBAAqB,EAAE,QAAQ,CAAC,CAAA;IAC7E,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,sBAAsB,EAAE,CAAC,IAAI,YAAY,CAAA;IAChG,MAAM,YAAY,GAAG,kBAAkB,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;IAC3D,MAAM,WAAW,GAAG,SAAS,CAAC,iBAAiB,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAA;IAEhG,MAAM,YAAY,GAChB,eAAe,KAAK,EAAE;QACpB,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,iCAAiC;YACjC,4DAA4D,UAAU,YAAY;YAClF,qFAAqF,eAAe,aAAa;YACjH,YAAY,CAAA;IAElB,MAAM,MAAM,GACV,oEAAoE;QACpE,yCAAyC,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,IAAI,MAAM;QACvF,GAAG,gBAAgB,EAAE;QACrB,GAAG,WAAW,EAAE;QAChB,GAAG,YAAY,EAAE;QACjB,GAAG,YAAY,EAAE;QACjB,iBAAiB,CAAA;IAEnB,MAAM,OAAO,GACX,KAAK,CAAC,OAAO,KAAK,SAAS;QACzB,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,sCAAsC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAA;IAC3E,MAAM,MAAM,GACV,KAAK,CAAC,MAAM,KAAK,SAAS;QACxB,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,SAAS,CACP,iBAAiB,CAAC,KAAK,CAAC,MAAM,EAAE;YAC9B,SAAS,EAAE,wBAAwB;YACnC,aAAa,EAAE,6BAA6B;SAC7C,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAClC,CAAA;IACP,MAAM,UAAU,GACd,KAAK,CAAC,UAAU,KAAK,SAAS;QAC5B,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,mCAAmC,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAA;IAE3E,MAAM,MAAM,GACV,iCAAiC;QACjC,oCAAoC;QACpC,qCAAqC;QACrC,+CAA+C,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,YAAY,MAAM;QACrG,GAAG,OAAO,EAAE;QACZ,QAAQ;QACR,oCAAoC,SAAS,QAAQ;QACrD,oCAAoC,MAAM,QAAQ;QAClD,oCAAoC,UAAU,QAAQ;QACtD,QAAQ;QACR,6CAA6C,YAAY,UAAU,KAAK,CAAC,YAAY,QAAQ;QAC7F,WAAW,CAAA;IAEb,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAA;AAC3B,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type BlockRegistry, type VocabularyBlock } from '@cogenta/blocks';
|
|
2
|
+
import { type FetchedEntries, type HtmlElement, type PageContent, pageHasOwnHeading, type RenderContext, renderEntryHeader, withBlockKey } from '@cogenta/theme-kit';
|
|
3
|
+
export type { FetchedEntries, PageContent };
|
|
4
|
+
export { pageHasOwnHeading, renderEntryHeader, withBlockKey };
|
|
5
|
+
export declare function renderBlock(block: VocabularyBlock, ctx: RenderContext, entries?: FetchedEntries, registry?: BlockRegistry): HtmlElement | null;
|
|
6
|
+
/**
|
|
7
|
+
* `<main id="cg-main">` is mandatory: it is the skip-link's target, written
|
|
8
|
+
* once by `@cogenta/cli`'s `theme-render.ts` outside any theme's control.
|
|
9
|
+
*
|
|
10
|
+
* `theme@1.4` (L25 D2): `renderEntryHeader` returns `null` both for a page
|
|
11
|
+
* with no `entry` meta and for one whose blocks already draw their own
|
|
12
|
+
* heading (a `hero`) — the bare `<h1 class="cg-page__title">` fallback below
|
|
13
|
+
* is the right markup in both of those cases and only those, so the page
|
|
14
|
+
* always carries exactly one `<h1>`.
|
|
15
|
+
*
|
|
16
|
+
* `withBlockKey` stamps every rendered block with its contract-B `_key` —
|
|
17
|
+
* required so the visual page builder (L16) can map a clicked element in the
|
|
18
|
+
* rendered iframe back to the block that produced it.
|
|
19
|
+
*/
|
|
20
|
+
export declare function renderPage(page: PageContent, ctx: RenderContext, entries?: FetchedEntries, registry?: BlockRegistry): HtmlElement;
|
|
21
|
+
//# sourceMappingURL=render-block.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-block.d.ts","sourceRoot":"","sources":["../../../src/render/render-block.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAoB,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAC5F,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,WAAW,EAEhB,KAAK,WAAW,EAChB,iBAAiB,EACjB,KAAK,aAAa,EAClB,iBAAiB,EAEjB,YAAY,EAEb,MAAM,oBAAoB,CAAA;AAmB3B,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,CAAA;AAC3C,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,YAAY,EAAE,CAAA;AAE7D,wBAAgB,WAAW,CACzB,KAAK,EAAE,eAAe,EACtB,GAAG,EAAE,aAAa,EAClB,OAAO,GAAE,cAAmB,EAC5B,QAAQ,CAAC,EAAE,aAAa,GACvB,WAAW,GAAG,IAAI,CAYpB;AAwDD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,aAAa,EAClB,OAAO,GAAE,cAAmB,EAC5B,QAAQ,CAAC,EAAE,aAAa,GACvB,WAAW,CAab"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { VOCABULARY_NAMES } from '@cogenta/blocks';
|
|
2
|
+
import { h, pageHasOwnHeading, renderEntryHeader, resolveBlockForRender, withBlockKey, withBlockVariant, } from '@cogenta/theme-kit';
|
|
3
|
+
import { renderAccordion } from './blocks/accordion.js';
|
|
4
|
+
import { renderCollectionList } from './blocks/collection-list.js';
|
|
5
|
+
import { renderCta } from './blocks/cta.js';
|
|
6
|
+
import { renderEmbed } from './blocks/embed.js';
|
|
7
|
+
import { renderFaq } from './blocks/faq.js';
|
|
8
|
+
import { renderFeatureGrid } from './blocks/feature-grid.js';
|
|
9
|
+
import { renderGallery } from './blocks/gallery.js';
|
|
10
|
+
import { renderHero } from './blocks/hero.js';
|
|
11
|
+
import { renderLogoStrip } from './blocks/logo-strip.js';
|
|
12
|
+
import { renderLogos } from './blocks/logos.js';
|
|
13
|
+
import { renderMediaFigure } from './blocks/media-figure.js';
|
|
14
|
+
import { renderPricingTable } from './blocks/pricing-table.js';
|
|
15
|
+
import { renderProse } from './blocks/prose.js';
|
|
16
|
+
import { renderQuote } from './blocks/quote.js';
|
|
17
|
+
import { renderStatCounter } from './blocks/stat-counter.js';
|
|
18
|
+
import { renderStats } from './blocks/stats.js';
|
|
19
|
+
import { renderTestimonial } from './blocks/testimonial.js';
|
|
20
|
+
export { pageHasOwnHeading, renderEntryHeader, withBlockKey };
|
|
21
|
+
export function renderBlock(block, ctx, entries = {}, registry) {
|
|
22
|
+
// `block`'s type says `VocabularyBlock`, but the value crossing this
|
|
23
|
+
// boundary from stored content is not always literally one of the shared
|
|
24
|
+
// vocabulary — resolving here is what turns an unimplemented theme-private
|
|
25
|
+
// block into its declared fallback instead of a silently blank slot.
|
|
26
|
+
const resolved = resolveBlockForRender(block, VOCABULARY_NAMES, registry);
|
|
27
|
+
if (resolved === null)
|
|
28
|
+
return null;
|
|
29
|
+
const known = resolved;
|
|
30
|
+
// `withBlockVariant` (blocks@2.0, RFC 0002) is applied once here, after
|
|
31
|
+
// dispatch, rather than inside each of the seventeen block renderers —
|
|
32
|
+
// `variant` is envelope data every block carries identically.
|
|
33
|
+
return withBlockVariant(renderKnownBlock(known, ctx, entries), known.variant);
|
|
34
|
+
}
|
|
35
|
+
function renderKnownBlock(known, ctx, entries) {
|
|
36
|
+
switch (known._type) {
|
|
37
|
+
case 'hero':
|
|
38
|
+
return renderHero(known, ctx);
|
|
39
|
+
case 'prose':
|
|
40
|
+
return renderProse(known, ctx);
|
|
41
|
+
case 'mediaFigure':
|
|
42
|
+
return renderMediaFigure(known, ctx);
|
|
43
|
+
case 'featureGrid':
|
|
44
|
+
return renderFeatureGrid(known, ctx);
|
|
45
|
+
case 'cta':
|
|
46
|
+
return renderCta(known, ctx);
|
|
47
|
+
case 'gallery':
|
|
48
|
+
return renderGallery(known, ctx);
|
|
49
|
+
case 'quote':
|
|
50
|
+
return renderQuote(known, ctx);
|
|
51
|
+
case 'faq':
|
|
52
|
+
return renderFaq(known, ctx);
|
|
53
|
+
case 'stats':
|
|
54
|
+
return renderStats(known, ctx);
|
|
55
|
+
case 'logos':
|
|
56
|
+
return renderLogos(known, ctx);
|
|
57
|
+
case 'collectionList':
|
|
58
|
+
return renderCollectionList(known, ctx, entries[known._key] ?? []);
|
|
59
|
+
case 'embed':
|
|
60
|
+
return renderEmbed(known, ctx);
|
|
61
|
+
case 'testimonial':
|
|
62
|
+
return renderTestimonial(known, ctx);
|
|
63
|
+
case 'pricingTable':
|
|
64
|
+
return renderPricingTable(known, ctx);
|
|
65
|
+
case 'accordion':
|
|
66
|
+
return renderAccordion(known, ctx);
|
|
67
|
+
case 'statCounter':
|
|
68
|
+
return renderStatCounter(known, ctx);
|
|
69
|
+
case 'logoStrip':
|
|
70
|
+
return renderLogoStrip(known, ctx);
|
|
71
|
+
default: {
|
|
72
|
+
// Exhaustive over contract B's vocabulary: `known` is `never` here, so
|
|
73
|
+
// a block this package does not implement stops it compiling until it
|
|
74
|
+
// is. Returning null rather than throwing is deliberate — a theme has
|
|
75
|
+
// no access to `@cogenta/core`'s error types (contract D refuses the
|
|
76
|
+
// import), and choosing a fallback block is the render layer's job,
|
|
77
|
+
// not the theme's.
|
|
78
|
+
const unreachable = known;
|
|
79
|
+
void unreachable;
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* `<main id="cg-main">` is mandatory: it is the skip-link's target, written
|
|
86
|
+
* once by `@cogenta/cli`'s `theme-render.ts` outside any theme's control.
|
|
87
|
+
*
|
|
88
|
+
* `theme@1.4` (L25 D2): `renderEntryHeader` returns `null` both for a page
|
|
89
|
+
* with no `entry` meta and for one whose blocks already draw their own
|
|
90
|
+
* heading (a `hero`) — the bare `<h1 class="cg-page__title">` fallback below
|
|
91
|
+
* is the right markup in both of those cases and only those, so the page
|
|
92
|
+
* always carries exactly one `<h1>`.
|
|
93
|
+
*
|
|
94
|
+
* `withBlockKey` stamps every rendered block with its contract-B `_key` —
|
|
95
|
+
* required so the visual page builder (L16) can map a clicked element in the
|
|
96
|
+
* rendered iframe back to the block that produced it.
|
|
97
|
+
*/
|
|
98
|
+
export function renderPage(page, ctx, entries = {}, registry) {
|
|
99
|
+
const entryHeader = renderEntryHeader(page, ctx);
|
|
100
|
+
return h('main', { class: 'cg-main', id: 'cg-main' }, entryHeader, entryHeader === null && !pageHasOwnHeading(page.blocks)
|
|
101
|
+
? h('h1', { class: 'cg-page__title' }, page.title)
|
|
102
|
+
: null, page.blocks.map((block) => withBlockKey(renderBlock(block, ctx, entries, registry), block._key)));
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=render-block.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-block.js","sourceRoot":"","sources":["../../../src/render/render-block.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"term-archive.d.ts","sourceRoot":"","sources":["../../../src/render/term-archive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAK,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AA2B/E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAkDtE"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { h } from '@cogenta/theme-kit';
|
|
2
|
+
/**
|
|
3
|
+
* The taxonomy-term archive (contract D `theme@1.3`) — a card grid, the same
|
|
4
|
+
* register the home page's "Upcoming events" `collectionList` uses: a
|
|
5
|
+
* rounded, shadowed card per entry, with a big day/month badge when the
|
|
6
|
+
* entry carries a publication date, title and summary underneath. There is
|
|
7
|
+
* no `entryImage` here (`TermArchiveEntry` carries no image field), so the
|
|
8
|
+
* card leans on the date badge and warm surface colour for shape instead of
|
|
9
|
+
* a missing photo.
|
|
10
|
+
*/
|
|
11
|
+
function dateBadge(publishedAt) {
|
|
12
|
+
if (publishedAt === null)
|
|
13
|
+
return null;
|
|
14
|
+
const date = new Date(publishedAt);
|
|
15
|
+
if (Number.isNaN(date.getTime()))
|
|
16
|
+
return null;
|
|
17
|
+
return h('time', { class: 'cg-archive-card__date', datetime: publishedAt }, h('span', { class: 'cg-archive-card__day' }, String(date.getUTCDate())), h('span', { class: 'cg-archive-card__month' }, new Intl.DateTimeFormat('en', { month: 'short' }).format(date)));
|
|
18
|
+
}
|
|
19
|
+
export function renderTermArchive(input) {
|
|
20
|
+
const cards = input.entries.map((entry) => h('li', { class: 'cg-archive-card' }, dateBadge(entry.publishedAt), h('div', { class: 'cg-archive-card__body' }, h('h2', { class: 'cg-archive-card__title' }, entry.href === null
|
|
21
|
+
? entry.title
|
|
22
|
+
: h('a', { class: 'cg-archive-card__link', href: entry.href }, entry.title)), entry.summary === null
|
|
23
|
+
? null
|
|
24
|
+
: h('p', { class: 'cg-archive-card__excerpt' }, entry.summary))));
|
|
25
|
+
return h('main', { class: 'cg-main cg-archive', id: 'cg-main' }, input.ancestors.length === 0
|
|
26
|
+
? null
|
|
27
|
+
: h('nav', { class: 'cg-archive__breadcrumb', 'aria-label': input.labels.breadcrumb }, h('ol', {}, ...input.ancestors.map((link) => h('li', {}, h('a', { href: link.href }, link.label))))), h('h1', { class: 'cg-archive__title' }, input.term.label), input.children.length === 0
|
|
28
|
+
? null
|
|
29
|
+
: h('ul', { class: 'cg-archive__children', 'aria-label': input.labels.subterms }, ...input.children.map((child) => h('li', {}, h('a', { href: child.href }, child.label)))), cards.length === 0
|
|
30
|
+
? h('p', { class: 'cg-archive__empty' }, input.labels.empty)
|
|
31
|
+
: h('ul', { class: 'cg-archive__grid' }, ...cards), pager(input));
|
|
32
|
+
}
|
|
33
|
+
function pager(input) {
|
|
34
|
+
if (input.page.previousHref === null && input.page.nextHref === null)
|
|
35
|
+
return null;
|
|
36
|
+
return h('nav', { class: 'cg-archive__pager', 'aria-label': input.labels.pagination }, input.page.previousHref === null
|
|
37
|
+
? null
|
|
38
|
+
: h('a', { rel: 'prev', href: input.page.previousHref }, input.labels.previous), input.page.nextHref === null
|
|
39
|
+
? null
|
|
40
|
+
: h('a', { rel: 'next', href: input.page.nextHref }, input.labels.next));
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=term-archive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"term-archive.js","sourceRoot":"","sources":["../../../src/render/term-archive.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract D — Thème, `theme@1.4`.
|
|
3
|
+
*
|
|
4
|
+
* `implements` lists the seventeen blocks of contract B (`blocks@2.0`, RFC
|
|
5
|
+
* 0001) in the order the contract lists them — installation refuses an
|
|
6
|
+
* incomplete theme.
|
|
7
|
+
*
|
|
8
|
+
* `runtime: 'static'` describes what this theme package itself needs; the
|
|
9
|
+
* one block in the vocabulary that reads at request time (`collectionList`)
|
|
10
|
+
* still declares `runtime: 'server'` on its own, in the vocabulary — that is
|
|
11
|
+
* a property of the block, not of the theme rendering it.
|
|
12
|
+
*/
|
|
13
|
+
declare const _default: import("@cogenta/render").ThemeManifest;
|
|
14
|
+
export default _default;
|
|
15
|
+
//# sourceMappingURL=theme.config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.config.d.ts","sourceRoot":"","sources":["../theme.config.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { defineTheme } from '@cogenta/render';
|
|
2
|
+
/**
|
|
3
|
+
* Contract D — Thème, `theme@1.4`.
|
|
4
|
+
*
|
|
5
|
+
* `implements` lists the seventeen blocks of contract B (`blocks@2.0`, RFC
|
|
6
|
+
* 0001) in the order the contract lists them — installation refuses an
|
|
7
|
+
* incomplete theme.
|
|
8
|
+
*
|
|
9
|
+
* `runtime: 'static'` describes what this theme package itself needs; the
|
|
10
|
+
* one block in the vocabulary that reads at request time (`collectionList`)
|
|
11
|
+
* still declares `runtime: 'server'` on its own, in the vocabulary — that is
|
|
12
|
+
* a property of the block, not of the theme rendering it.
|
|
13
|
+
*/
|
|
14
|
+
export default defineTheme({
|
|
15
|
+
name: 'association',
|
|
16
|
+
version: '1.0.0',
|
|
17
|
+
description: 'A warm, human theme for a nonprofit or community group: dated event cards, an impact band, and a genuine dark mode.',
|
|
18
|
+
author: 'Cogenta',
|
|
19
|
+
engine: '^1.0.0',
|
|
20
|
+
blocks: '^2.0.0',
|
|
21
|
+
implements: [
|
|
22
|
+
'hero',
|
|
23
|
+
'prose',
|
|
24
|
+
'mediaFigure',
|
|
25
|
+
'featureGrid',
|
|
26
|
+
'cta',
|
|
27
|
+
'gallery',
|
|
28
|
+
'quote',
|
|
29
|
+
'faq',
|
|
30
|
+
'stats',
|
|
31
|
+
'logos',
|
|
32
|
+
'collectionList',
|
|
33
|
+
'embed',
|
|
34
|
+
'testimonial',
|
|
35
|
+
'pricingTable',
|
|
36
|
+
'accordion',
|
|
37
|
+
'statCounter',
|
|
38
|
+
'logoStrip',
|
|
39
|
+
],
|
|
40
|
+
collections: ['event', 'page'],
|
|
41
|
+
runtime: 'static',
|
|
42
|
+
tokens: './tokens.json',
|
|
43
|
+
a11y: { verified: 'WCAG-2.2-AA' },
|
|
44
|
+
});
|
|
45
|
+
//# sourceMappingURL=theme.config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.config.js","sourceRoot":"","sources":["../theme.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAE7C;;;;;;;;;;;GAWG;AACH,eAAe,WAAW,CAAC;IACzB,IAAI,EAAE,aAAa;IACnB,OAAO,EAAE,OAAO;IAChB,WAAW,EACT,qHAAqH;IACvH,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,UAAU,EAAE;QACV,MAAM;QACN,OAAO;QACP,aAAa;QACb,aAAa;QACb,KAAK;QACL,SAAS;QACT,OAAO;QACP,KAAK;QACL,OAAO;QACP,OAAO;QACP,gBAAgB;QAChB,OAAO;QACP,aAAa;QACb,cAAc;QACd,WAAW;QACX,aAAa;QACb,WAAW;KACZ;IACD,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;IAC9B,OAAO,EAAE,QAAQ;IACjB,MAAM,EAAE,eAAe;IACvB,IAAI,EAAE,EAAE,QAAQ,EAAE,aAAa,EAAE;CAClC,CAAC,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cogenta/theme-association",
|
|
3
|
+
"version": "0.3.2",
|
|
4
|
+
"description": "A warm, human theme for a nonprofit or association: dated event cards, an impact band, and a genuine dark mode, with zero client JavaScript.",
|
|
5
|
+
"license": "MPL-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/src/index.d.ts",
|
|
11
|
+
"default": "./dist/src/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./theme.config": {
|
|
14
|
+
"types": "./dist/theme.config.d.ts",
|
|
15
|
+
"default": "./dist/theme.config.js"
|
|
16
|
+
},
|
|
17
|
+
"./tokens.json": "./tokens.json",
|
|
18
|
+
"./styles/theme.css": "./src/styles/theme.css",
|
|
19
|
+
"./styles/*.css": "./src/styles/*.css"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"src",
|
|
24
|
+
"tokens.json"
|
|
25
|
+
],
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=22.11.0"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public",
|
|
31
|
+
"provenance": true
|
|
32
|
+
},
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/cogenta-cms/cogenta.git",
|
|
36
|
+
"directory": "packages/theme-association"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@cogenta/blocks": "1.0.3",
|
|
40
|
+
"@cogenta/render": "0.2.3",
|
|
41
|
+
"@cogenta/theme-kit": "0.3.2"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"astro": "^7.2.1"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"astro": "^7.2.1",
|
|
48
|
+
"typescript": "^7.0.2",
|
|
49
|
+
"vitest": "^4.1.10"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "tsc -p tsconfig.json",
|
|
53
|
+
"typecheck": "tsc -p tsconfig.typecheck.json",
|
|
54
|
+
"test": "vitest run --passWithNoTests",
|
|
55
|
+
"test:integration": "vitest run --config vitest.integration.config.ts --passWithNoTests"
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export * from './render/blocks/accordion.js'
|
|
2
|
+
export * from './render/blocks/collection-list.js'
|
|
3
|
+
export * from './render/blocks/cta.js'
|
|
4
|
+
export * from './render/blocks/embed.js'
|
|
5
|
+
export * from './render/blocks/faq.js'
|
|
6
|
+
export * from './render/blocks/feature-grid.js'
|
|
7
|
+
export * from './render/blocks/gallery.js'
|
|
8
|
+
export * from './render/blocks/hero.js'
|
|
9
|
+
export * from './render/blocks/logo-strip.js'
|
|
10
|
+
export * from './render/blocks/logos.js'
|
|
11
|
+
export * from './render/blocks/media-figure.js'
|
|
12
|
+
export * from './render/blocks/pricing-table.js'
|
|
13
|
+
export * from './render/blocks/prose.js'
|
|
14
|
+
export * from './render/blocks/quote.js'
|
|
15
|
+
export * from './render/blocks/stat-counter.js'
|
|
16
|
+
export * from './render/blocks/stats.js'
|
|
17
|
+
export * from './render/blocks/testimonial.js'
|
|
18
|
+
export * from './render/chrome.js'
|
|
19
|
+
export * from './render/render-block.js'
|
|
20
|
+
export * from './render/term-archive.js'
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { AccordionBlock, AccordionItem } from '@cogenta/blocks'
|
|
2
|
+
import {
|
|
3
|
+
blockHeadingTag,
|
|
4
|
+
type HtmlElement,
|
|
5
|
+
h,
|
|
6
|
+
heading,
|
|
7
|
+
type RenderContext,
|
|
8
|
+
renderRichText,
|
|
9
|
+
} from '@cogenta/theme-kit'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* `blocks@2.0` (RFC 0001). Shares `faq`'s `<details>`/`<summary>` mechanics —
|
|
13
|
+
* the same zero-JavaScript disclosure this theme's own mobile nav toggle
|
|
14
|
+
* uses — but is its own block, since "accordion" and "frequently asked
|
|
15
|
+
* question" are different editorial intents even when the shape coincides.
|
|
16
|
+
*/
|
|
17
|
+
function renderItem(item: AccordionItem, ctx: RenderContext): HtmlElement {
|
|
18
|
+
return h(
|
|
19
|
+
'li',
|
|
20
|
+
{ class: 'cg-accordion__item' },
|
|
21
|
+
h(
|
|
22
|
+
'details',
|
|
23
|
+
{ class: 'cg-accordion__details' },
|
|
24
|
+
h('summary', { class: 'cg-accordion__question' }, item.question),
|
|
25
|
+
h('div', { class: 'cg-accordion__answer' }, renderRichText(ctx, item.answer)),
|
|
26
|
+
),
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function renderAccordion(block: AccordionBlock, ctx: RenderContext): HtmlElement {
|
|
31
|
+
return h(
|
|
32
|
+
'section',
|
|
33
|
+
{ class: 'cg-block cg-accordion', 'data-block': 'accordion' },
|
|
34
|
+
block.title === undefined
|
|
35
|
+
? null
|
|
36
|
+
: heading(
|
|
37
|
+
blockHeadingTag('accordion') ?? 'h2',
|
|
38
|
+
{ class: 'cg-accordion__title', 'data-field': 'title' },
|
|
39
|
+
block.title,
|
|
40
|
+
),
|
|
41
|
+
h(
|
|
42
|
+
'ul',
|
|
43
|
+
{ class: 'cg-accordion__items' },
|
|
44
|
+
block.items.map((item) => renderItem(item, ctx)),
|
|
45
|
+
),
|
|
46
|
+
)
|
|
47
|
+
}
|