@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.
Files changed (117) hide show
  1. package/LICENSE +373 -0
  2. package/dist/src/index.d.ts +21 -0
  3. package/dist/src/index.d.ts.map +1 -0
  4. package/dist/src/index.js +21 -0
  5. package/dist/src/index.js.map +1 -0
  6. package/dist/src/render/blocks/accordion.d.ts +4 -0
  7. package/dist/src/render/blocks/accordion.d.ts.map +1 -0
  8. package/dist/src/render/blocks/accordion.js +16 -0
  9. package/dist/src/render/blocks/accordion.js.map +1 -0
  10. package/dist/src/render/blocks/collection-list.d.ts +12 -0
  11. package/dist/src/render/blocks/collection-list.d.ts.map +1 -0
  12. package/dist/src/render/blocks/collection-list.js +64 -0
  13. package/dist/src/render/blocks/collection-list.js.map +1 -0
  14. package/dist/src/render/blocks/cta.d.ts +9 -0
  15. package/dist/src/render/blocks/cta.d.ts.map +1 -0
  16. package/dist/src/render/blocks/cta.js +16 -0
  17. package/dist/src/render/blocks/cta.js.map +1 -0
  18. package/dist/src/render/blocks/embed.d.ts +4 -0
  19. package/dist/src/render/blocks/embed.d.ts.map +1 -0
  20. package/dist/src/render/blocks/embed.js +76 -0
  21. package/dist/src/render/blocks/embed.js.map +1 -0
  22. package/dist/src/render/blocks/faq.d.ts +4 -0
  23. package/dist/src/render/blocks/faq.d.ts.map +1 -0
  24. package/dist/src/render/blocks/faq.js +21 -0
  25. package/dist/src/render/blocks/faq.js.map +1 -0
  26. package/dist/src/render/blocks/feature-grid.d.ts +4 -0
  27. package/dist/src/render/blocks/feature-grid.d.ts.map +1 -0
  28. package/dist/src/render/blocks/feature-grid.js +27 -0
  29. package/dist/src/render/blocks/feature-grid.js.map +1 -0
  30. package/dist/src/render/blocks/gallery.d.ts +14 -0
  31. package/dist/src/render/blocks/gallery.d.ts.map +1 -0
  32. package/dist/src/render/blocks/gallery.js +27 -0
  33. package/dist/src/render/blocks/gallery.js.map +1 -0
  34. package/dist/src/render/blocks/hero.d.ts +15 -0
  35. package/dist/src/render/blocks/hero.d.ts.map +1 -0
  36. package/dist/src/render/blocks/hero.js +31 -0
  37. package/dist/src/render/blocks/hero.js.map +1 -0
  38. package/dist/src/render/blocks/logo-strip.d.ts +4 -0
  39. package/dist/src/render/blocks/logo-strip.d.ts.map +1 -0
  40. package/dist/src/render/blocks/logo-strip.js +16 -0
  41. package/dist/src/render/blocks/logo-strip.js.map +1 -0
  42. package/dist/src/render/blocks/logos.d.ts +4 -0
  43. package/dist/src/render/blocks/logos.d.ts.map +1 -0
  44. package/dist/src/render/blocks/logos.js +22 -0
  45. package/dist/src/render/blocks/logos.js.map +1 -0
  46. package/dist/src/render/blocks/media-figure.d.ts +12 -0
  47. package/dist/src/render/blocks/media-figure.d.ts.map +1 -0
  48. package/dist/src/render/blocks/media-figure.js +27 -0
  49. package/dist/src/render/blocks/media-figure.js.map +1 -0
  50. package/dist/src/render/blocks/pricing-table.d.ts +4 -0
  51. package/dist/src/render/blocks/pricing-table.d.ts.map +1 -0
  52. package/dist/src/render/blocks/pricing-table.js +29 -0
  53. package/dist/src/render/blocks/pricing-table.js.map +1 -0
  54. package/dist/src/render/blocks/prose.d.ts +9 -0
  55. package/dist/src/render/blocks/prose.d.ts.map +1 -0
  56. package/dist/src/render/blocks/prose.js +10 -0
  57. package/dist/src/render/blocks/prose.js.map +1 -0
  58. package/dist/src/render/blocks/quote.d.ts +13 -0
  59. package/dist/src/render/blocks/quote.d.ts.map +1 -0
  60. package/dist/src/render/blocks/quote.js +26 -0
  61. package/dist/src/render/blocks/quote.js.map +1 -0
  62. package/dist/src/render/blocks/stat-counter.d.ts +4 -0
  63. package/dist/src/render/blocks/stat-counter.d.ts.map +1 -0
  64. package/dist/src/render/blocks/stat-counter.js +14 -0
  65. package/dist/src/render/blocks/stat-counter.js.map +1 -0
  66. package/dist/src/render/blocks/stats.d.ts +4 -0
  67. package/dist/src/render/blocks/stats.d.ts.map +1 -0
  68. package/dist/src/render/blocks/stats.js +18 -0
  69. package/dist/src/render/blocks/stats.js.map +1 -0
  70. package/dist/src/render/blocks/testimonial.d.ts +11 -0
  71. package/dist/src/render/blocks/testimonial.d.ts.map +1 -0
  72. package/dist/src/render/blocks/testimonial.js +20 -0
  73. package/dist/src/render/blocks/testimonial.js.map +1 -0
  74. package/dist/src/render/chrome.d.ts +3 -0
  75. package/dist/src/render/chrome.d.ts.map +1 -0
  76. package/dist/src/render/chrome.js +106 -0
  77. package/dist/src/render/chrome.js.map +1 -0
  78. package/dist/src/render/render-block.d.ts +21 -0
  79. package/dist/src/render/render-block.d.ts.map +1 -0
  80. package/dist/src/render/render-block.js +104 -0
  81. package/dist/src/render/render-block.js.map +1 -0
  82. package/dist/src/render/term-archive.d.ts +3 -0
  83. package/dist/src/render/term-archive.d.ts.map +1 -0
  84. package/dist/src/render/term-archive.js +42 -0
  85. package/dist/src/render/term-archive.js.map +1 -0
  86. package/dist/theme.config.d.ts +15 -0
  87. package/dist/theme.config.d.ts.map +1 -0
  88. package/dist/theme.config.js +45 -0
  89. package/dist/theme.config.js.map +1 -0
  90. package/package.json +57 -0
  91. package/src/index.ts +20 -0
  92. package/src/render/blocks/accordion.ts +47 -0
  93. package/src/render/blocks/collection-list.ts +144 -0
  94. package/src/render/blocks/cta.ts +37 -0
  95. package/src/render/blocks/embed.ts +98 -0
  96. package/src/render/blocks/faq.ts +52 -0
  97. package/src/render/blocks/feature-grid.ts +67 -0
  98. package/src/render/blocks/gallery.ts +47 -0
  99. package/src/render/blocks/hero.ts +60 -0
  100. package/src/render/blocks/logo-strip.ts +31 -0
  101. package/src/render/blocks/logos.ts +52 -0
  102. package/src/render/blocks/media-figure.ts +38 -0
  103. package/src/render/blocks/pricing-table.ts +73 -0
  104. package/src/render/blocks/prose.ts +15 -0
  105. package/src/render/blocks/quote.ts +39 -0
  106. package/src/render/blocks/stat-counter.ts +36 -0
  107. package/src/render/blocks/stats.ts +45 -0
  108. package/src/render/blocks/testimonial.ts +36 -0
  109. package/src/render/chrome.ts +134 -0
  110. package/src/render/render-block.ts +140 -0
  111. package/src/render/term-archive.ts +92 -0
  112. package/src/styles/archive.css +129 -0
  113. package/src/styles/base.css +842 -0
  114. package/src/styles/blocks.css +1002 -0
  115. package/src/styles/theme.css +31 -0
  116. package/src/styles/tokens.css +332 -0
  117. 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,3 @@
1
+ import { type ChromeInput, type ChromeResult } from '@cogenta/theme-kit';
2
+ export declare function renderChrome(input: ChromeInput): ChromeResult;
3
+ //# sourceMappingURL=chrome.d.ts.map
@@ -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":"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"}
@@ -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,3 @@
1
+ import { type HtmlElement, type TermArchiveInput } from '@cogenta/theme-kit';
2
+ export declare function renderTermArchive(input: TermArchiveInput): HtmlElement;
3
+ //# sourceMappingURL=term-archive.d.ts.map
@@ -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
+ }