@cogenta/theme-portfolio 1.1.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 +17 -0
  3. package/dist/src/index.d.ts.map +1 -0
  4. package/dist/src/index.js +20 -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 +24 -0
  9. package/dist/src/render/blocks/accordion.js.map +1 -0
  10. package/dist/src/render/blocks/collection-list.d.ts +25 -0
  11. package/dist/src/render/blocks/collection-list.d.ts.map +1 -0
  12. package/dist/src/render/blocks/collection-list.js +77 -0
  13. package/dist/src/render/blocks/collection-list.js.map +1 -0
  14. package/dist/src/render/blocks/cta.d.ts +10 -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 +88 -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 +23 -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 +30 -0
  29. package/dist/src/render/blocks/feature-grid.js.map +1 -0
  30. package/dist/src/render/blocks/gallery.d.ts +18 -0
  31. package/dist/src/render/blocks/gallery.d.ts.map +1 -0
  32. package/dist/src/render/blocks/gallery.js +34 -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 +23 -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 +28 -0
  45. package/dist/src/render/blocks/logos.js.map +1 -0
  46. package/dist/src/render/blocks/media-figure.d.ts +19 -0
  47. package/dist/src/render/blocks/media-figure.d.ts.map +1 -0
  48. package/dist/src/render/blocks/media-figure.js +36 -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 +16 -0
  55. package/dist/src/render/blocks/prose.d.ts.map +1 -0
  56. package/dist/src/render/blocks/prose.js +17 -0
  57. package/dist/src/render/blocks/prose.js.map +1 -0
  58. package/dist/src/render/blocks/quote.d.ts +18 -0
  59. package/dist/src/render/blocks/quote.d.ts.map +1 -0
  60. package/dist/src/render/blocks/quote.js +31 -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 +18 -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 +22 -0
  69. package/dist/src/render/blocks/stats.js.map +1 -0
  70. package/dist/src/render/blocks/testimonial.d.ts +20 -0
  71. package/dist/src/render/blocks/testimonial.d.ts.map +1 -0
  72. package/dist/src/render/blocks/testimonial.js +29 -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 +114 -0
  77. package/dist/src/render/chrome.js.map +1 -0
  78. package/dist/src/render/render-block.d.ts +12 -0
  79. package/dist/src/render/render-block.d.ts.map +1 -0
  80. package/dist/src/render/render-block.js +111 -0
  81. package/dist/src/render/render-block.js.map +1 -0
  82. package/dist/src/render/term-archive.d.ts +14 -0
  83. package/dist/src/render/term-archive.d.ts.map +1 -0
  84. package/dist/src/render/term-archive.js +36 -0
  85. package/dist/src/render/term-archive.js.map +1 -0
  86. package/dist/theme.config.d.ts +26 -0
  87. package/dist/theme.config.d.ts.map +1 -0
  88. package/dist/theme.config.js +56 -0
  89. package/dist/theme.config.js.map +1 -0
  90. package/package.json +57 -0
  91. package/src/index.ts +19 -0
  92. package/src/render/blocks/accordion.ts +64 -0
  93. package/src/render/blocks/collection-list.ts +181 -0
  94. package/src/render/blocks/cta.ts +37 -0
  95. package/src/render/blocks/embed.ts +111 -0
  96. package/src/render/blocks/faq.ts +54 -0
  97. package/src/render/blocks/feature-grid.ts +68 -0
  98. package/src/render/blocks/gallery.ts +55 -0
  99. package/src/render/blocks/hero.ts +55 -0
  100. package/src/render/blocks/logo-strip.ts +38 -0
  101. package/src/render/blocks/logos.ts +63 -0
  102. package/src/render/blocks/media-figure.ts +51 -0
  103. package/src/render/blocks/pricing-table.ts +69 -0
  104. package/src/render/blocks/prose.ts +22 -0
  105. package/src/render/blocks/quote.ts +48 -0
  106. package/src/render/blocks/stat-counter.ts +49 -0
  107. package/src/render/blocks/stats.ts +49 -0
  108. package/src/render/blocks/testimonial.ts +45 -0
  109. package/src/render/chrome.ts +142 -0
  110. package/src/render/render-block.ts +155 -0
  111. package/src/render/term-archive.ts +88 -0
  112. package/src/styles/archive.css +40 -0
  113. package/src/styles/base.css +1056 -0
  114. package/src/styles/blocks.css +1468 -0
  115. package/src/styles/theme.css +20 -0
  116. package/src/styles/tokens.css +363 -0
  117. package/tokens.json +36 -0
@@ -0,0 +1,88 @@
1
+ import { aspectRatio, h } from '@cogenta/theme-kit';
2
+ /**
3
+ * Nothing here contacts a third party before the visitor has consented.
4
+ *
5
+ * When `consentRequired` is true the block renders a self-contained card and
6
+ * an outbound link — no `<iframe>`, no script tag, no preconnect, no poster
7
+ * image fetched from the provider. An embed that "only" loads a thumbnail has
8
+ * already handed the visitor's IP address and a cookie to the provider,
9
+ * which is the exact transfer consent was supposed to gate.
10
+ *
11
+ * The theme ships no consent *button*, because it ships no JavaScript:
12
+ * granting consent is a site-wide decision that belongs to the consent
13
+ * layer, not to a block. The card carries a bracketed provider tag in the
14
+ * mono register — `[ youtube ]` — the theme's own visual shorthand for
15
+ * "something external belongs here".
16
+ */
17
+ /** `null` means "this provider has no embeddable frame we trust". */
18
+ function frameSource(provider, rawUrl) {
19
+ const url = URL.parse(rawUrl);
20
+ if (url === null)
21
+ return null;
22
+ const segments = url.pathname.split('/').filter((segment) => segment !== '');
23
+ switch (provider) {
24
+ case 'youtube': {
25
+ // `youtube-nocookie.com` is the privacy-preserving host, and the only one
26
+ // this theme will point an iframe at.
27
+ const id = url.hostname.endsWith('youtu.be')
28
+ ? segments[0]
29
+ : (url.searchParams.get('v') ?? segments[1]);
30
+ return id === undefined || id === null ? null : `https://www.youtube-nocookie.com/embed/${id}`;
31
+ }
32
+ case 'vimeo': {
33
+ const id = segments.find((segment) => /^\d+$/.test(segment));
34
+ return id === undefined ? null : `https://player.vimeo.com/video/${id}`;
35
+ }
36
+ case 'dailymotion': {
37
+ const id = url.hostname.endsWith('dai.ly') ? segments[0] : segments[segments.length - 1];
38
+ return id === undefined ? null : `https://geo.dailymotion.com/player.html?video=${id}`;
39
+ }
40
+ case 'spotify': {
41
+ const [kind, id] = segments;
42
+ return kind === undefined || id === undefined
43
+ ? null
44
+ : `https://open.spotify.com/embed/${kind}/${id}`;
45
+ }
46
+ case 'soundcloud':
47
+ return `https://w.soundcloud.com/player/?url=${encodeURIComponent(rawUrl)}`;
48
+ default:
49
+ // bluesky, mastodon, other: a post embed is a script tag, which this
50
+ // theme does not load. The link card is the rendering.
51
+ return null;
52
+ }
53
+ }
54
+ function consentCard(block, ctx, reason) {
55
+ return h('div', { class: 'cg-embed__placeholder' }, h('span', { class: 'cg-embed__tag' }, `[ ${block.provider} ]`), h('p', { class: 'cg-embed__notice' }, reason), h('a', {
56
+ class: 'cg-embed__link',
57
+ href: ctx.link(block.url),
58
+ rel: 'noopener noreferrer nofollow',
59
+ }, ctx.t('embed.open', { provider: block.provider })));
60
+ }
61
+ export function renderEmbed(block, ctx) {
62
+ const source = block.consentRequired ? null : frameSource(block.provider, block.url);
63
+ // Video providers are 16:9 unless the editor framed them otherwise; without a
64
+ // ratio the frame would collapse and shift the layout as it loads.
65
+ const ratio = aspectRatio(block.ratio) ?? '16 / 9';
66
+ return h('div', {
67
+ class: 'cg-block cg-embed',
68
+ 'data-block': 'embed',
69
+ 'data-provider': block.provider,
70
+ 'data-consent': block.consentRequired ? 'required' : 'not-required',
71
+ style: `--cg-ratio:${ratio}`,
72
+ }, source === null
73
+ ? consentCard(block, ctx, block.consentRequired
74
+ ? ctx.t('embed.consentRequired', { provider: block.provider })
75
+ : ctx.t('embed.unsupported', { provider: block.provider }))
76
+ : h('iframe', {
77
+ class: 'cg-embed__frame',
78
+ src: source,
79
+ // An iframe with no accessible name is announced as "frame" and
80
+ // nothing else. WCAG 4.1.2, and the single most common embed defect.
81
+ title: ctx.t('embed.title', { provider: block.provider }),
82
+ loading: 'lazy',
83
+ referrerpolicy: 'strict-origin-when-cross-origin',
84
+ allow: 'accelerometer; clipboard-write; encrypted-media; picture-in-picture; fullscreen',
85
+ allowfullscreen: true,
86
+ }));
87
+ }
88
+ //# sourceMappingURL=embed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embed.js","sourceRoot":"","sources":["../../../../src/render/blocks/embed.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { FaqBlock } from '@cogenta/blocks';
2
+ import { type HtmlElement, type RenderContext } from '@cogenta/theme-kit';
3
+ export declare function renderFaq(block: FaqBlock, ctx: RenderContext): HtmlElement;
4
+ //# sourceMappingURL=faq.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"faq.d.ts","sourceRoot":"","sources":["../../../../src/render/blocks/faq.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAW,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAEL,KAAK,WAAW,EAGhB,KAAK,aAAa,EAEnB,MAAM,oBAAoB,CAAA;AA4B3B,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,GAAG,WAAW,CAiB1E"}
@@ -0,0 +1,23 @@
1
+ import { blockHeadingTag, h, heading, renderRichText, } from '@cogenta/theme-kit';
2
+ /**
3
+ * `<details>`/`<summary>` rather than a scripted accordion: expanding,
4
+ * keyboard operation, the expanded state announced to assistive technology
5
+ * and in-page search all come from the browser, at zero bytes of
6
+ * JavaScript.
7
+ *
8
+ * The question is plain text inside `<summary>`, not a heading: a heading
9
+ * nested in a summary is rendered inconsistently across screen readers, and
10
+ * the questions are already reachable as a list under the block's own
11
+ * heading. A CSS-drawn plus mark (rotated to a cross on `[open]`) replaces
12
+ * the native marker rather than a chevron — the theme's own vocabulary of
13
+ * shapes, kept purely visual.
14
+ */
15
+ function renderItem(item, ctx) {
16
+ return h('li', { class: 'cg-faq__item' }, h('details', { class: 'cg-faq__details' }, h('summary', { class: 'cg-faq__question' }, h('span', {}, item.question)), h('div', { class: 'cg-faq__answer' }, renderRichText(ctx, item.answer))));
17
+ }
18
+ export function renderFaq(block, ctx) {
19
+ return h('section', { class: 'cg-block cg-faq', 'data-block': 'faq' }, block.title === undefined
20
+ ? null
21
+ : heading(blockHeadingTag('faq') ?? 'h2', { class: 'cg-faq__title', 'data-field': 'title' }, block.title), h('ul', { class: 'cg-faq__items' }, block.items.map((item) => renderItem(item, ctx))));
22
+ }
23
+ //# sourceMappingURL=faq.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"faq.js","sourceRoot":"","sources":["../../../../src/render/blocks/faq.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EAEf,CAAC,EACD,OAAO,EAEP,cAAc,GACf,MAAM,oBAAoB,CAAA;AAE3B;;;;;;;;;;;;GAYG;AACH,SAAS,UAAU,CAAC,IAAa,EAAE,GAAkB;IACnD,OAAO,CAAC,CACN,IAAI,EACJ,EAAE,KAAK,EAAE,cAAc,EAAE,EACzB,CAAC,CACC,SAAS,EACT,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAC5B,CAAC,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,EACzE,CAAC,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CACxE,CACF,CAAA;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAe,EAAE,GAAkB;IAC3D,OAAO,CAAC,CACN,SAAS,EACT,EAAE,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,KAAK,EAAE,EACjD,KAAK,CAAC,KAAK,KAAK,SAAS;QACvB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,OAAO,CACL,eAAe,CAAC,KAAK,CAAC,IAAI,IAAI,EAC9B,EAAE,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,OAAO,EAAE,EACjD,KAAK,CAAC,KAAK,CACZ,EACL,CAAC,CACC,IAAI,EACJ,EAAE,KAAK,EAAE,eAAe,EAAE,EAC1B,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CACjD,CACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { FeatureGridBlock } from '@cogenta/blocks';
2
+ import { type HtmlElement, type RenderContext } from '@cogenta/theme-kit';
3
+ export declare function renderFeatureGrid(block: FeatureGridBlock, ctx: RenderContext): HtmlElement;
4
+ //# sourceMappingURL=feature-grid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-grid.d.ts","sourceRoot":"","sources":["../../../../src/render/blocks/feature-grid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAe,MAAM,iBAAiB,CAAA;AACpE,OAAO,EAGL,KAAK,WAAW,EAKhB,KAAK,aAAa,EAEnB,MAAM,oBAAoB,CAAA;AAqC3B,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAE,aAAa,GAAG,WAAW,CAmB1F"}
@@ -0,0 +1,30 @@
1
+ import { blockHeadingTag, h, heading, href, nestedHeadingTag, renderIcon, } from '@cogenta/theme-kit';
2
+ /**
3
+ * The item's title is the link, so the link's accessible name is the
4
+ * feature's name — a bare "learn more" repeated across a grid is the
5
+ * classic failure of WCAG 2.4.4, and the block carries no label field to
6
+ * write one anyway.
7
+ *
8
+ * `icon` names a symbol (`renderIcon`, `theme@1.4`) — drawn small and
9
+ * accent-coloured, decorative (`aria-hidden`, the title already carries the
10
+ * accessible name) — sitting *above* the running index numeral this theme
11
+ * has always drawn from a CSS counter, never replacing it: the numeral is
12
+ * this theme's own editorial device, the icon is the shared vocabulary's.
13
+ * An item with no icon, or one whose name this theme does not recognise,
14
+ * keeps exactly the pre-1.4 numeral-only card.
15
+ */
16
+ function renderItem(item, ctx, tag) {
17
+ const title = item.link === undefined
18
+ ? heading(tag, { class: 'cg-feature__title' }, item.title)
19
+ : heading(tag, { class: 'cg-feature__title' }, h('a', { class: 'cg-feature__link', href: href(ctx, item.link) }, item.title));
20
+ const icon = item.icon === undefined ? null : renderIcon(item.icon, { className: 'cg-feature__icon' });
21
+ return h('li', { class: 'cg-feature', 'data-icon': item.icon }, icon, h('span', { class: 'cg-feature__index', 'aria-hidden': 'true' }), title, item.text === undefined ? null : h('p', { class: 'cg-feature__text' }, item.text));
22
+ }
23
+ export function renderFeatureGrid(block, ctx) {
24
+ const hasTitle = block.title !== undefined;
25
+ const itemTag = nestedHeadingTag('featureGrid', hasTitle);
26
+ return h('section', { class: 'cg-block cg-features', 'data-block': 'featureGrid' }, hasTitle
27
+ ? heading(blockHeadingTag('featureGrid') ?? 'h2', { class: 'cg-features__title', 'data-field': 'title' }, block.title ?? '')
28
+ : null, h('ul', { class: 'cg-features__items' }, block.items.map((item) => renderItem(item, ctx, itemTag))));
29
+ }
30
+ //# sourceMappingURL=feature-grid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-grid.js","sourceRoot":"","sources":["../../../../src/render/blocks/feature-grid.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EAGf,CAAC,EACD,OAAO,EACP,IAAI,EACJ,gBAAgB,EAEhB,UAAU,GACX,MAAM,oBAAoB,CAAA;AAE3B;;;;;;;;;;;;;GAaG;AACH,SAAS,UAAU,CAAC,IAAiB,EAAE,GAAkB,EAAE,GAAe;IACxE,MAAM,KAAK,GACT,IAAI,CAAC,IAAI,KAAK,SAAS;QACrB,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC;QAC1D,CAAC,CAAC,OAAO,CACL,GAAG,EACH,EAAE,KAAK,EAAE,mBAAmB,EAAE,EAC9B,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAC9E,CAAA;IACP,MAAM,IAAI,GACR,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,CAAA;IAC3F,OAAO,CAAC,CACN,IAAI,EACJ,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,IAAI,CAAC,IAAI,EAAE,EAC/C,IAAI,EACJ,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,EAChE,KAAK,EACL,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAClF,CAAA;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAuB,EAAE,GAAkB;IAC3E,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,KAAK,SAAS,CAAA;IAC1C,MAAM,OAAO,GAAG,gBAAgB,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAA;IACzD,OAAO,CAAC,CACN,SAAS,EACT,EAAE,KAAK,EAAE,sBAAsB,EAAE,YAAY,EAAE,aAAa,EAAE,EAC9D,QAAQ;QACN,CAAC,CAAC,OAAO,CACL,eAAe,CAAC,aAAa,CAAC,IAAI,IAAI,EACtC,EAAE,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,OAAO,EAAE,EACtD,KAAK,CAAC,KAAK,IAAI,EAAE,CAClB;QACH,CAAC,CAAC,IAAI,EACR,CAAC,CACC,IAAI,EACJ,EAAE,KAAK,EAAE,oBAAoB,EAAE,EAC/B,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAC1D,CACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { GalleryBlock } from '@cogenta/blocks';
2
+ import { type HtmlElement, type RenderContext } from '@cogenta/theme-kit';
3
+ /**
4
+ * The carousel ships **no JavaScript**. It is a scroll-snapping list, which
5
+ * gives touch swiping, trackpad scrolling and — because the list is focusable
6
+ * and labelled — arrow-key scrolling, with none of the failure modes of a
7
+ * scripted carousel: no auto-advance to fight (WCAG 2.2.2), no focus stolen
8
+ * from an off-screen slide, and it still works before hydration.
9
+ *
10
+ * Every tile carries a decorative index badge (`aria-hidden`, a CSS counter)
11
+ * — a numbered contact sheet rather than a plain image wall, and never a
12
+ * second name for the picture a screen reader would announce.
13
+ *
14
+ * A focusable scrollable region needs an accessible name, or a screen reader
15
+ * announces an unlabelled tab stop; that is WCAG 2.4.3 and 4.1.2 both.
16
+ */
17
+ export declare function renderGallery(block: GalleryBlock, ctx: RenderContext): HtmlElement;
18
+ //# sourceMappingURL=gallery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gallery.d.ts","sourceRoot":"","sources":["../../../../src/render/blocks/gallery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,KAAK,WAAW,EAAY,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAEnF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,aAAa,GAAG,WAAW,CAqClF"}
@@ -0,0 +1,34 @@
1
+ import { h, image } from '@cogenta/theme-kit';
2
+ /**
3
+ * The carousel ships **no JavaScript**. It is a scroll-snapping list, which
4
+ * gives touch swiping, trackpad scrolling and — because the list is focusable
5
+ * and labelled — arrow-key scrolling, with none of the failure modes of a
6
+ * scripted carousel: no auto-advance to fight (WCAG 2.2.2), no focus stolen
7
+ * from an off-screen slide, and it still works before hydration.
8
+ *
9
+ * Every tile carries a decorative index badge (`aria-hidden`, a CSS counter)
10
+ * — a numbered contact sheet rather than a plain image wall, and never a
11
+ * second name for the picture a screen reader would announce.
12
+ *
13
+ * A focusable scrollable region needs an accessible name, or a screen reader
14
+ * announces an unlabelled tab stop; that is WCAG 2.4.3 and 4.1.2 both.
15
+ */
16
+ export function renderGallery(block, ctx) {
17
+ const items = h('ul', { class: 'cg-gallery__items' }, block.items.map((item) => h('li', { class: 'cg-gallery__item' }, h('span', { class: 'cg-gallery__index', 'aria-hidden': 'true' }), image(ctx, item.media, {
18
+ className: 'cg-gallery__image',
19
+ sizes: '(min-width: 48rem) 22rem, 60vw',
20
+ }))));
21
+ return h('section', {
22
+ class: 'cg-block cg-gallery',
23
+ 'data-block': 'gallery',
24
+ 'data-layout': block.layout,
25
+ }, block.layout === 'carousel'
26
+ ? h('div', {
27
+ class: 'cg-gallery__viewport',
28
+ role: 'region',
29
+ 'aria-label': ctx.t('gallery.carousel'),
30
+ tabindex: '0',
31
+ }, items)
32
+ : items);
33
+ }
34
+ //# sourceMappingURL=gallery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gallery.js","sourceRoot":"","sources":["../../../../src/render/blocks/gallery.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,CAAC,EAAE,KAAK,EAAsB,MAAM,oBAAoB,CAAA;AAEnF;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,aAAa,CAAC,KAAmB,EAAE,GAAkB;IACnE,MAAM,KAAK,GAAG,CAAC,CACb,IAAI,EACJ,EAAE,KAAK,EAAE,mBAAmB,EAAE,EAC9B,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACvB,CAAC,CACC,IAAI,EACJ,EAAE,KAAK,EAAE,kBAAkB,EAAE,EAC7B,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,EAChE,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE;QACrB,SAAS,EAAE,mBAAmB;QAC9B,KAAK,EAAE,gCAAgC;KACxC,CAAC,CACH,CACF,CACF,CAAA;IAED,OAAO,CAAC,CACN,SAAS,EACT;QACE,KAAK,EAAE,qBAAqB;QAC5B,YAAY,EAAE,SAAS;QACvB,aAAa,EAAE,KAAK,CAAC,MAAM;KAC5B,EACD,KAAK,CAAC,MAAM,KAAK,UAAU;QACzB,CAAC,CAAC,CAAC,CACC,KAAK,EACL;YACE,KAAK,EAAE,sBAAsB;YAC7B,IAAI,EAAE,QAAQ;YACd,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,kBAAkB,CAAC;YACvC,QAAQ,EAAE,GAAG;SACd,EACD,KAAK,CACN;QACH,CAAC,CAAC,KAAK,CACV,CAAA;AACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { HeroBlock } from '@cogenta/blocks';
2
+ import { type HtmlElement, type RenderContext } from '@cogenta/theme-kit';
3
+ /**
4
+ * The hero carries the page's `h1` — contract B declares `headingLevel: 'h1'`
5
+ * for it, and `renderPage` relies on that to avoid emitting a second one.
6
+ *
7
+ * Structurally distinct from a centred banner: the eyebrow becomes a running
8
+ * index mark set in the mono register (`— eyebrow`), the title is a display
9
+ * headline that overflows its own column on wide screens (`blocks.css` gives
10
+ * it a fluid `clamp()`), and the media is offset into the title's own
11
+ * negative margin rather than sitting in a tidy second column — the overlap
12
+ * is what makes this a poster, not a slide.
13
+ */
14
+ export declare function renderHero(block: HeroBlock, ctx: RenderContext): HtmlElement;
15
+ //# sourceMappingURL=hero.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hero.d.ts","sourceRoot":"","sources":["../../../../src/render/blocks/hero.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAGL,KAAK,WAAW,EAIhB,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAA;AAE3B;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,GAAG,WAAW,CAgC5E"}
@@ -0,0 +1,31 @@
1
+ import { actionList, blockHeadingTag, h, heading, image, } from '@cogenta/theme-kit';
2
+ /**
3
+ * The hero carries the page's `h1` — contract B declares `headingLevel: 'h1'`
4
+ * for it, and `renderPage` relies on that to avoid emitting a second one.
5
+ *
6
+ * Structurally distinct from a centred banner: the eyebrow becomes a running
7
+ * index mark set in the mono register (`— eyebrow`), the title is a display
8
+ * headline that overflows its own column on wide screens (`blocks.css` gives
9
+ * it a fluid `clamp()`), and the media is offset into the title's own
10
+ * negative margin rather than sitting in a tidy second column — the overlap
11
+ * is what makes this a poster, not a slide.
12
+ */
13
+ export function renderHero(block, ctx) {
14
+ const tag = blockHeadingTag('hero') ?? 'h1';
15
+ return h('section', { class: 'cg-block cg-hero', 'data-block': 'hero' }, h('div', { class: 'cg-hero__frame' }, block.eyebrow === undefined
16
+ ? null
17
+ : h('p', { class: 'cg-hero__eyebrow', 'data-field': 'eyebrow' }, block.eyebrow), heading(tag, { class: 'cg-hero__title', 'data-field': 'title' }, block.title), block.subtitle === undefined
18
+ ? null
19
+ : h('p', { class: 'cg-hero__subtitle', 'data-field': 'subtitle' }, block.subtitle), actionList(ctx, block.actions, ctx.t('hero.actions'))), block.media === undefined
20
+ ? null
21
+ : h('div', { class: 'cg-hero__media' },
22
+ // The only image on the page that is above the fold by construction,
23
+ // so the only one that must not be lazy: lazy-loading the LCP element
24
+ // is a measured Lighthouse regression, not a theoretical one.
25
+ image(ctx, block.media, {
26
+ className: 'cg-hero__image',
27
+ loading: 'eager',
28
+ sizes: '(min-width: 64rem) 46vw, 100vw',
29
+ })));
30
+ }
31
+ //# sourceMappingURL=hero.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hero.js","sourceRoot":"","sources":["../../../../src/render/blocks/hero.ts"],"names":[],"mappings":"AACA,OAAO,EACL,UAAU,EACV,eAAe,EAEf,CAAC,EACD,OAAO,EACP,KAAK,GAEN,MAAM,oBAAoB,CAAA;AAE3B;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,KAAgB,EAAE,GAAkB;IAC7D,MAAM,GAAG,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,IAAI,CAAA;IAC3C,OAAO,CAAC,CACN,SAAS,EACT,EAAE,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,EAAE,EACnD,CAAC,CACC,KAAK,EACL,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAC3B,KAAK,CAAC,OAAO,KAAK,SAAS;QACzB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,EACjF,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,EAC7E,KAAK,CAAC,QAAQ,KAAK,SAAS;QAC1B,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,KAAK,CAAC,QAAQ,CAAC,EACpF,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CACtD,EACD,KAAK,CAAC,KAAK,KAAK,SAAS;QACvB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,CAAC,CACC,KAAK,EACL,EAAE,KAAK,EAAE,gBAAgB,EAAE;QAC3B,qEAAqE;QACrE,sEAAsE;QACtE,8DAA8D;QAC9D,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,EAAE;YACtB,SAAS,EAAE,gBAAgB;YAC3B,OAAO,EAAE,OAAO;YAChB,KAAK,EAAE,gCAAgC;SACxC,CAAC,CACH,CACN,CAAA;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LogoStripBlock } from '@cogenta/blocks';
2
+ import { type HtmlElement, type RenderContext } from '@cogenta/theme-kit';
3
+ export declare function renderLogoStrip(block: LogoStripBlock, ctx: RenderContext): HtmlElement;
4
+ //# sourceMappingURL=logo-strip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logo-strip.d.ts","sourceRoot":"","sources":["../../../../src/render/blocks/logo-strip.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,iBAAiB,CAAA;AACpE,OAAO,EAAE,KAAK,WAAW,EAAY,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAuBnF,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,aAAa,GAAG,WAAW,CAatF"}
@@ -0,0 +1,23 @@
1
+ import { h, image } from '@cogenta/theme-kit';
2
+ /**
3
+ * Lighter-weight than `logos` on purpose (RFC 0001): no per-mark `name`/
4
+ * `url`, so no link, no accessible-name field to write, and no numbered
5
+ * ledger row — this is the quieter "as seen in" strip, marks set edge to
6
+ * edge with no dividers, desaturated exactly like `logos.ts`'s own marks
7
+ * (the theme's one visual language for "a logo not currently in focus").
8
+ * The image's own alt text (set once, in the media library) is what names
9
+ * each mark, same as `logos.ts` falls back to when a link is absent — never
10
+ * invented here, which is why `image` is called with no `altFrom`.
11
+ */
12
+ function renderItem(item, ctx) {
13
+ return h('li', { class: 'cg-logostrip__item' }, image(ctx, item.media, {
14
+ className: 'cg-logostrip__image',
15
+ variant: { fit: 'contain' },
16
+ }));
17
+ }
18
+ export function renderLogoStrip(block, ctx) {
19
+ return h('figure', { class: 'cg-block cg-logostrip', 'data-block': 'logoStrip' }, h('ul', { class: 'cg-logostrip__items' }, block.logos.map((item) => renderItem(item, ctx))), block.caption === undefined
20
+ ? null
21
+ : h('figcaption', { class: 'cg-logostrip__caption', 'data-field': 'caption' }, block.caption));
22
+ }
23
+ //# sourceMappingURL=logo-strip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logo-strip.js","sourceRoot":"","sources":["../../../../src/render/blocks/logo-strip.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,CAAC,EAAE,KAAK,EAAsB,MAAM,oBAAoB,CAAA;AAEnF;;;;;;;;;GASG;AACH,SAAS,UAAU,CAAC,IAAmB,EAAE,GAAkB;IACzD,OAAO,CAAC,CACN,IAAI,EACJ,EAAE,KAAK,EAAE,oBAAoB,EAAE,EAC/B,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE;QACrB,SAAS,EAAE,qBAAqB;QAChC,OAAO,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE;KAC5B,CAAC,CACH,CAAA;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAqB,EAAE,GAAkB;IACvE,OAAO,CAAC,CACN,QAAQ,EACR,EAAE,KAAK,EAAE,uBAAuB,EAAE,YAAY,EAAE,WAAW,EAAE,EAC7D,CAAC,CACC,IAAI,EACJ,EAAE,KAAK,EAAE,qBAAqB,EAAE,EAChC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CACjD,EACD,KAAK,CAAC,OAAO,KAAK,SAAS;QACzB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,CAChG,CAAA;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LogosBlock } from '@cogenta/blocks';
2
+ import { type HtmlElement, type RenderContext } from '@cogenta/theme-kit';
3
+ export declare function renderLogos(block: LogosBlock, ctx: RenderContext): HtmlElement;
4
+ //# sourceMappingURL=logos.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logos.d.ts","sourceRoot":"","sources":["../../../../src/render/blocks/logos.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAY,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC3D,OAAO,EAEL,KAAK,WAAW,EAIhB,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAA;AAqC3B,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,WAAW,CAiB9E"}
@@ -0,0 +1,28 @@
1
+ import { blockHeadingTag, h, heading, image, } from '@cogenta/theme-kit';
2
+ /**
3
+ * Contract B says the organisation's name **is** the accessible name of the
4
+ * link. So the logo image carries it as alt text when the media entity has
5
+ * none, and no visually hidden duplicate is added: a link whose only content
6
+ * is an image with alt text is already named.
7
+ *
8
+ * Rendered as a single-row ledger rather than a grid of tiles — a running
9
+ * mono index beside each mark, in a desaturated register that resolves to
10
+ * full ink only on hover or focus (`blocks.css`), which is the theme's own
11
+ * take on the "selected clients" strip.
12
+ */
13
+ function renderItem(item, ctx, index) {
14
+ const logo = image(ctx, item.media, {
15
+ className: 'cg-logo__image',
16
+ altFrom: item.name,
17
+ variant: { fit: 'contain' },
18
+ });
19
+ return h('li', { class: 'cg-logo' }, h('span', { class: 'cg-logo__index', 'aria-hidden': 'true' }, String(index + 1).padStart(2, '0')), item.url === undefined
20
+ ? logo
21
+ : h('a', { class: 'cg-logo__link', href: ctx.link(item.url), rel: 'noopener noreferrer' }, logo));
22
+ }
23
+ export function renderLogos(block, ctx) {
24
+ return h('section', { class: 'cg-block cg-logos', 'data-block': 'logos' }, block.title === undefined
25
+ ? null
26
+ : heading(blockHeadingTag('logos') ?? 'h2', { class: 'cg-logos__title', 'data-field': 'title' }, block.title), h('ul', { class: 'cg-logos__items' }, block.items.map((item, index) => renderItem(item, ctx, index))));
27
+ }
28
+ //# sourceMappingURL=logos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logos.js","sourceRoot":"","sources":["../../../../src/render/blocks/logos.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EAEf,CAAC,EACD,OAAO,EACP,KAAK,GAEN,MAAM,oBAAoB,CAAA;AAE3B;;;;;;;;;;GAUG;AACH,SAAS,UAAU,CAAC,IAAc,EAAE,GAAkB,EAAE,KAAa;IACnE,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE;QAClC,SAAS,EAAE,gBAAgB;QAC3B,OAAO,EAAE,IAAI,CAAC,IAAI;QAClB,OAAO,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE;KAC5B,CAAC,CAAA;IACF,OAAO,CAAC,CACN,IAAI,EACJ,EAAE,KAAK,EAAE,SAAS,EAAE,EACpB,CAAC,CACC,MAAM,EACN,EAAE,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,EAAE,EAClD,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CACnC,EACD,IAAI,CAAC,GAAG,KAAK,SAAS;QACpB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,CAAC,CACC,GAAG,EACH,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,qBAAqB,EAAE,EAChF,IAAI,CACL,CACN,CAAA;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAiB,EAAE,GAAkB;IAC/D,OAAO,CAAC,CACN,SAAS,EACT,EAAE,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,OAAO,EAAE,EACrD,KAAK,CAAC,KAAK,KAAK,SAAS;QACvB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,OAAO,CACL,eAAe,CAAC,OAAO,CAAC,IAAI,IAAI,EAChC,EAAE,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,OAAO,EAAE,EACnD,KAAK,CAAC,KAAK,CACZ,EACL,CAAC,CACC,IAAI,EACJ,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAC5B,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAC/D,CACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { MediaFigureBlock } from '@cogenta/blocks';
2
+ import { type HtmlElement, type RenderContext } from '@cogenta/theme-kit';
3
+ /**
4
+ * `<figure>`/`<figcaption>` rather than a div and a paragraph: the
5
+ * association between the picture and its caption is then in the markup,
6
+ * and a screen reader announces the caption as belonging to the image
7
+ * instead of as loose text after it.
8
+ *
9
+ * The "Fig. 01" plate number that precedes the caption is drawn entirely
10
+ * from a CSS counter (`counter-increment: cg-figure` in `blocks.css`) — it
11
+ * is not stored data, so it renumbers itself as figures are added or
12
+ * removed and never needs updating here.
13
+ *
14
+ * `align` is written as a data attribute, never as a class: contract B's
15
+ * values are `start`/`end`, an intent that mirrors in right-to-left
16
+ * locales, and the skin decides what it means.
17
+ */
18
+ export declare function renderMediaFigure(block: MediaFigureBlock, ctx: RenderContext): HtmlElement;
19
+ //# sourceMappingURL=media-figure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-figure.d.ts","sourceRoot":"","sources":["../../../../src/render/blocks/media-figure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACvD,OAAO,EAAe,KAAK,WAAW,EAAY,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAEhG;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAE,aAAa,GAAG,WAAW,CAgC1F"}
@@ -0,0 +1,36 @@
1
+ import { aspectRatio, h, image } from '@cogenta/theme-kit';
2
+ /**
3
+ * `<figure>`/`<figcaption>` rather than a div and a paragraph: the
4
+ * association between the picture and its caption is then in the markup,
5
+ * and a screen reader announces the caption as belonging to the image
6
+ * instead of as loose text after it.
7
+ *
8
+ * The "Fig. 01" plate number that precedes the caption is drawn entirely
9
+ * from a CSS counter (`counter-increment: cg-figure` in `blocks.css`) — it
10
+ * is not stored data, so it renumbers itself as figures are added or
11
+ * removed and never needs updating here.
12
+ *
13
+ * `align` is written as a data attribute, never as a class: contract B's
14
+ * values are `start`/`end`, an intent that mirrors in right-to-left
15
+ * locales, and the skin decides what it means.
16
+ */
17
+ export function renderMediaFigure(block, ctx) {
18
+ const ratio = aspectRatio(block.ratio);
19
+ const hasCaption = block.caption !== undefined || block.credit !== undefined;
20
+ return h('figure', {
21
+ class: 'cg-block cg-figure',
22
+ 'data-block': 'mediaFigure',
23
+ 'data-align': block.align ?? 'center',
24
+ style: ratio === undefined ? undefined : `--cg-ratio:${ratio}`,
25
+ }, h('div', { class: 'cg-figure__frame' }, image(ctx, block.media, {
26
+ className: 'cg-figure__media',
27
+ sizes: '(min-width: 48rem) 42rem, 100vw',
28
+ })), hasCaption
29
+ ? h('figcaption', { class: 'cg-figure__caption' }, block.caption === undefined
30
+ ? null
31
+ : h('span', { class: 'cg-figure__plate' }, block.caption), block.credit === undefined
32
+ ? null
33
+ : h('span', { class: 'cg-figure__credit', 'data-field': 'credit' }, block.credit))
34
+ : null);
35
+ }
36
+ //# sourceMappingURL=media-figure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-figure.js","sourceRoot":"","sources":["../../../../src/render/blocks/media-figure.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAoB,CAAC,EAAE,KAAK,EAAsB,MAAM,oBAAoB,CAAA;AAEhG;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAuB,EAAE,GAAkB;IAC3E,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IACtC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,CAAA;IAC5E,OAAO,CAAC,CACN,QAAQ,EACR;QACE,KAAK,EAAE,oBAAoB;QAC3B,YAAY,EAAE,aAAa;QAC3B,YAAY,EAAE,KAAK,CAAC,KAAK,IAAI,QAAQ;QACrC,KAAK,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,KAAK,EAAE;KAC/D,EACD,CAAC,CACC,KAAK,EACL,EAAE,KAAK,EAAE,kBAAkB,EAAE,EAC7B,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,EAAE;QACtB,SAAS,EAAE,kBAAkB;QAC7B,KAAK,EAAE,iCAAiC;KACzC,CAAC,CACH,EACD,UAAU;QACR,CAAC,CAAC,CAAC,CACC,YAAY,EACZ,EAAE,KAAK,EAAE,oBAAoB,EAAE,EAC/B,KAAK,CAAC,OAAO,KAAK,SAAS;YACzB,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,EAC3D,KAAK,CAAC,MAAM,KAAK,SAAS;YACxB,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,CACpF;QACH,CAAC,CAAC,IAAI,CACT,CAAA;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { PricingTableBlock } from '@cogenta/blocks';
2
+ import { type HtmlElement, type RenderContext } from '@cogenta/theme-kit';
3
+ export declare function renderPricingTable(block: PricingTableBlock, ctx: RenderContext): HtmlElement;
4
+ //# sourceMappingURL=pricing-table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing-table.d.ts","sourceRoot":"","sources":["../../../../src/render/blocks/pricing-table.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAe,MAAM,iBAAiB,CAAA;AACrE,OAAO,EAIL,KAAK,WAAW,EAIhB,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAA;AAuC3B,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,aAAa,GAAG,WAAW,CAmB5F"}
@@ -0,0 +1,29 @@
1
+ import { actionLink, blockHeadingTag, h, heading, nestedHeadingTag, } from '@cogenta/theme-kit';
2
+ /**
3
+ * `highlighted` is an editorial signal, never a colour (RFC 0001's own
4
+ * comment on the field): it is written as `data-highlighted="true"` for the
5
+ * skin to key off, and the tier additionally carries `aria-current="true"`
6
+ * — the closest native semantic for "the one the author means you to pick"
7
+ * among a set of siblings.
8
+ */
9
+ function renderTier(tier, ctx, tag) {
10
+ return h('li', {
11
+ class: 'cg-pricing__tier',
12
+ 'data-highlighted': tier.highlighted === true ? 'true' : undefined,
13
+ 'aria-current': tier.highlighted === true ? 'true' : undefined,
14
+ }, heading(tag, { class: 'cg-pricing__name' }, tier.name), h('p', { class: 'cg-pricing__price' }, tier.price, tier.interval === undefined
15
+ ? null
16
+ : h('span', { class: 'cg-pricing__interval' }, tier.interval)), tier.features.length === 0
17
+ ? null
18
+ : h('ul', { class: 'cg-pricing__features' }, tier.features.map((feature) => h('li', {}, feature))), tier.action === undefined
19
+ ? null
20
+ : h('div', { class: 'cg-pricing__action' }, actionLink(ctx, tier.action)));
21
+ }
22
+ export function renderPricingTable(block, ctx) {
23
+ const hasTitle = block.title !== undefined;
24
+ const tierTag = nestedHeadingTag('pricingTable', hasTitle);
25
+ return h('section', { class: 'cg-block cg-pricing', 'data-block': 'pricingTable' }, hasTitle
26
+ ? heading(blockHeadingTag('pricingTable') ?? 'h2', { class: 'cg-pricing__title', 'data-field': 'title' }, block.title ?? '')
27
+ : null, h('ul', { class: 'cg-pricing__tiers' }, block.tiers.map((tier) => renderTier(tier, ctx, tierTag))));
28
+ }
29
+ //# sourceMappingURL=pricing-table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing-table.js","sourceRoot":"","sources":["../../../../src/render/blocks/pricing-table.ts"],"names":[],"mappings":"AACA,OAAO,EACL,UAAU,EACV,eAAe,EAGf,CAAC,EACD,OAAO,EACP,gBAAgB,GAEjB,MAAM,oBAAoB,CAAA;AAE3B;;;;;;GAMG;AACH,SAAS,UAAU,CAAC,IAAiB,EAAE,GAAkB,EAAE,GAAe;IACxE,OAAO,CAAC,CACN,IAAI,EACJ;QACE,KAAK,EAAE,kBAAkB;QACzB,kBAAkB,EAAE,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QAClE,cAAc,EAAE,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;KAC/D,EACD,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,EACtD,CAAC,CACC,GAAG,EACH,EAAE,KAAK,EAAE,mBAAmB,EAAE,EAC9B,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,QAAQ,KAAK,SAAS;QACzB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,sBAAsB,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,CAChE,EACD,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QACxB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,CAAC,CACC,IAAI,EACJ,EAAE,KAAK,EAAE,sBAAsB,EAAE,EACjC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC,CACrD,EACL,IAAI,CAAC,MAAM,KAAK,SAAS;QACvB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,EAAE,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAC5E,CAAA;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAwB,EAAE,GAAkB;IAC7E,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,KAAK,SAAS,CAAA;IAC1C,MAAM,OAAO,GAAG,gBAAgB,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAA;IAC1D,OAAO,CAAC,CACN,SAAS,EACT,EAAE,KAAK,EAAE,qBAAqB,EAAE,YAAY,EAAE,cAAc,EAAE,EAC9D,QAAQ;QACN,CAAC,CAAC,OAAO,CACL,eAAe,CAAC,cAAc,CAAC,IAAI,IAAI,EACvC,EAAE,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,OAAO,EAAE,EACrD,KAAK,CAAC,KAAK,IAAI,EAAE,CAClB;QACH,CAAC,CAAC,IAAI,EACR,CAAC,CACC,IAAI,EACJ,EAAE,KAAK,EAAE,mBAAmB,EAAE,EAC9B,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAC1D,CACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { ProseBlock } from '@cogenta/blocks';
2
+ import { type HtmlElement, type RenderContext } from '@cogenta/theme-kit';
3
+ /**
4
+ * `prose` declares `headingLevel: 'none'`: it contributes no heading of its
5
+ * own. Whatever headings appear come from the rich text document, whose
6
+ * vocabulary starts at `h2`.
7
+ *
8
+ * The wrapper is deliberately plain — a rich text document is arbitrary
9
+ * editorial content, and the only honest DOM shape for arbitrary content is
10
+ * "here it is". The distinctive editorial treatment (a dropped first
11
+ * capital, an oversized `h2`, a hairline-and-number rule before each
12
+ * heading) lives entirely in `blocks.css`, driven off the very structure
13
+ * `renderRichText` already produces.
14
+ */
15
+ export declare function renderProse(block: ProseBlock, ctx: RenderContext): HtmlElement;
16
+ //# sourceMappingURL=prose.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prose.d.ts","sourceRoot":"","sources":["../../../../src/render/blocks/prose.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,KAAK,WAAW,EAAK,KAAK,aAAa,EAAkB,MAAM,oBAAoB,CAAA;AAE5F;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,WAAW,CAM9E"}
@@ -0,0 +1,17 @@
1
+ import { h, renderRichText } from '@cogenta/theme-kit';
2
+ /**
3
+ * `prose` declares `headingLevel: 'none'`: it contributes no heading of its
4
+ * own. Whatever headings appear come from the rich text document, whose
5
+ * vocabulary starts at `h2`.
6
+ *
7
+ * The wrapper is deliberately plain — a rich text document is arbitrary
8
+ * editorial content, and the only honest DOM shape for arbitrary content is
9
+ * "here it is". The distinctive editorial treatment (a dropped first
10
+ * capital, an oversized `h2`, a hairline-and-number rule before each
11
+ * heading) lives entirely in `blocks.css`, driven off the very structure
12
+ * `renderRichText` already produces.
13
+ */
14
+ export function renderProse(block, ctx) {
15
+ return h('div', { class: 'cg-block cg-prose', 'data-block': 'prose' }, renderRichText(ctx, block.body));
16
+ }
17
+ //# sourceMappingURL=prose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prose.js","sourceRoot":"","sources":["../../../../src/render/blocks/prose.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,CAAC,EAAsB,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAE5F;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,WAAW,CAAC,KAAiB,EAAE,GAAkB;IAC/D,OAAO,CAAC,CACN,KAAK,EACL,EAAE,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,OAAO,EAAE,EACrD,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAChC,CAAA;AACH,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { QuoteBlock } from '@cogenta/blocks';
2
+ import { type HtmlElement, type RenderContext } from '@cogenta/theme-kit';
3
+ /**
4
+ * `<figure><blockquote>…</blockquote><figcaption>` is the attribution
5
+ * pattern the HTML spec prescribes: putting the author inside the
6
+ * `<blockquote>` would claim the author's name is part of what was said.
7
+ *
8
+ * Set left-aligned at display scale rather than centred — a pull quote that
9
+ * fills the column edge to edge, the way a magazine breaks one out of a
10
+ * feature. The attribution is set in the mono register, the theme's
11
+ * register for credits and metadata.
12
+ *
13
+ * The avatar is decorative here — the name is right beside it in text — so
14
+ * its media entity's alt text is expected to be empty. `image` still writes
15
+ * the attribute either way.
16
+ */
17
+ export declare function renderQuote(block: QuoteBlock, ctx: RenderContext): HtmlElement;
18
+ //# sourceMappingURL=quote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quote.d.ts","sourceRoot":"","sources":["../../../../src/render/blocks/quote.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,KAAK,WAAW,EAAY,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAEnF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,WAAW,CA8B9E"}
@@ -0,0 +1,31 @@
1
+ import { h, image } from '@cogenta/theme-kit';
2
+ /**
3
+ * `<figure><blockquote>…</blockquote><figcaption>` is the attribution
4
+ * pattern the HTML spec prescribes: putting the author inside the
5
+ * `<blockquote>` would claim the author's name is part of what was said.
6
+ *
7
+ * Set left-aligned at display scale rather than centred — a pull quote that
8
+ * fills the column edge to edge, the way a magazine breaks one out of a
9
+ * feature. The attribution is set in the mono register, the theme's
10
+ * register for credits and metadata.
11
+ *
12
+ * The avatar is decorative here — the name is right beside it in text — so
13
+ * its media entity's alt text is expected to be empty. `image` still writes
14
+ * the attribute either way.
15
+ */
16
+ export function renderQuote(block, ctx) {
17
+ const hasAttribution = block.author !== undefined || block.role !== undefined || block.avatar !== undefined;
18
+ return h('figure', { class: 'cg-block cg-quote', 'data-block': 'quote' }, h('blockquote', { class: 'cg-quote__text' }, h('p', { 'data-field': 'text' }, block.text)), hasAttribution
19
+ ? h('figcaption', { class: 'cg-quote__attribution' }, block.avatar === undefined
20
+ ? null
21
+ : image(ctx, block.avatar, {
22
+ className: 'cg-quote__avatar',
23
+ variant: { width: 96, height: 96, fit: 'cover' },
24
+ }), h('span', { class: 'cg-quote__names' }, block.author === undefined
25
+ ? null
26
+ : h('span', { class: 'cg-quote__author', 'data-field': 'author' }, block.author), block.role === undefined
27
+ ? null
28
+ : h('span', { class: 'cg-quote__role', 'data-field': 'role' }, block.role)))
29
+ : null);
30
+ }
31
+ //# sourceMappingURL=quote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quote.js","sourceRoot":"","sources":["../../../../src/render/blocks/quote.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,CAAC,EAAE,KAAK,EAAsB,MAAM,oBAAoB,CAAA;AAEnF;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,WAAW,CAAC,KAAiB,EAAE,GAAkB;IAC/D,MAAM,cAAc,GAClB,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,CAAA;IACtF,OAAO,CAAC,CACN,QAAQ,EACR,EAAE,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,OAAO,EAAE,EACrD,CAAC,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,EAC1F,cAAc;QACZ,CAAC,CAAC,CAAC,CACC,YAAY,EACZ,EAAE,KAAK,EAAE,uBAAuB,EAAE,EAClC,KAAK,CAAC,MAAM,KAAK,SAAS;YACxB,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,EAAE;gBACvB,SAAS,EAAE,kBAAkB;gBAC7B,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE;aACjD,CAAC,EACN,CAAC,CACC,MAAM,EACN,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAC5B,KAAK,CAAC,MAAM,KAAK,SAAS;YACxB,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,EAClF,KAAK,CAAC,IAAI,KAAK,SAAS;YACtB,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,CAC7E,CACF;QACH,CAAC,CAAC,IAAI,CACT,CAAA;AACH,CAAC"}