@bison-lab/payload-blocks 3.1.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +102 -1
- package/dist/index.d.mts +102 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +425 -2
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +64 -7
- package/dist/react.d.mts.map +1 -1
- package/dist/react.mjs +182 -15
- package/dist/react.mjs.map +1 -1
- package/dist/rich-text.d.mts +1 -1
- package/dist/{types-BBumyFd-.d.mts → types-CJAvoZMk.d.mts} +97 -7
- package/dist/types-CJAvoZMk.d.mts.map +1 -0
- package/package.json +2 -2
- package/dist/types-BBumyFd-.d.mts.map +0 -1
package/dist/react.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { t as cx } from "./cx-BKHSv3xT.mjs";
|
|
3
3
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
-
import { Button, FAQColumnsBlock, JsonLd, NapBlock, ProcessStepsBlock, ShowcasePanelsBlock, TestimonialMasonry } from "@bison-lab/ui";
|
|
4
|
+
import { Button, FAQColumnsBlock, JsonLd, MegaMenuPanel, NapBlock, ProcessStepsBlock, ShowcasePanelsBlock, TestimonialMasonry, megaMenuToFloatingNavItems } from "@bison-lab/ui";
|
|
5
5
|
//#region src/image.tsx
|
|
6
6
|
/**
|
|
7
7
|
* The fallback when no `imageComponent` is supplied: a plain `<img>`. Correct
|
|
@@ -21,6 +21,42 @@ function DefaultBlockImage({ src, alt, width, height, className, sizes, priority
|
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
23
|
//#endregion
|
|
24
|
+
//#region src/link.tsx
|
|
25
|
+
/** `target` and `rel` together, or neither: a bare `target` is a tabnabbing hole. */
|
|
26
|
+
function newTabAttributes(newTab) {
|
|
27
|
+
return newTab ? {
|
|
28
|
+
target: "_blank",
|
|
29
|
+
rel: "noopener noreferrer"
|
|
30
|
+
} : {};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The fallback when no `linkComponent` is supplied: a plain `<a>`. Correct
|
|
34
|
+
* everywhere and client-side nowhere, which is the right default for a package
|
|
35
|
+
* that cannot know what router it landed in.
|
|
36
|
+
*/
|
|
37
|
+
function DefaultBlockLink({ href, newTab, children, ...rest }) {
|
|
38
|
+
return /* @__PURE__ */ jsx("a", {
|
|
39
|
+
href,
|
|
40
|
+
...rest,
|
|
41
|
+
...newTabAttributes(newTab),
|
|
42
|
+
children
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
DefaultBlockLink.displayName = "DefaultBlockLink";
|
|
46
|
+
/**
|
|
47
|
+
* Adapts the seam to the `renderLink` prop every `@bison-lab/ui` block takes.
|
|
48
|
+
* The ui blocks hand over `target`/`rel` already expanded, so `newTab` is
|
|
49
|
+
* read back off `target` to keep the flag and the attributes in step.
|
|
50
|
+
*/
|
|
51
|
+
function renderLinkWith(Link) {
|
|
52
|
+
return ({ href, children, ...rest }) => /* @__PURE__ */ jsx(Link, {
|
|
53
|
+
href,
|
|
54
|
+
newTab: rest.target === "_blank",
|
|
55
|
+
...rest,
|
|
56
|
+
children
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
24
60
|
//#region src/render-blocks.tsx
|
|
25
61
|
/** Fallback page measure for a site that does not pass its own. */
|
|
26
62
|
const DEFAULT_CONTAINER = "mx-auto w-full max-w-7xl px-6";
|
|
@@ -50,7 +86,7 @@ function runIndexes(blocks) {
|
|
|
50
86
|
* Renders a page's blocks in order through the registry. A Server Component:
|
|
51
87
|
* it only maps and looks up, and each renderer decides its own nature.
|
|
52
88
|
*/
|
|
53
|
-
function RenderBlocks({ blocks, registry, containerClassName = DEFAULT_CONTAINER, imageComponent = DefaultBlockImage }) {
|
|
89
|
+
function RenderBlocks({ blocks, registry, containerClassName = DEFAULT_CONTAINER, imageComponent = DefaultBlockImage, linkComponent = DefaultBlockLink }) {
|
|
54
90
|
const rows = renderable(blocks, registry);
|
|
55
91
|
const runs = runIndexes(rows.map((row) => row.block));
|
|
56
92
|
return /* @__PURE__ */ jsx(Fragment, { children: rows.map(({ block, Renderer }, index) => /* @__PURE__ */ jsx(Renderer, {
|
|
@@ -60,7 +96,8 @@ function RenderBlocks({ blocks, registry, containerClassName = DEFAULT_CONTAINER
|
|
|
60
96
|
runIndex: runs[index],
|
|
61
97
|
isLast: index === rows.length - 1,
|
|
62
98
|
containerClassName,
|
|
63
|
-
imageComponent
|
|
99
|
+
imageComponent,
|
|
100
|
+
linkComponent
|
|
64
101
|
}, block.id ?? index)) });
|
|
65
102
|
}
|
|
66
103
|
//#endregion
|
|
@@ -109,7 +146,7 @@ const TONES = {
|
|
|
109
146
|
* render at all, not to be the final answer. A site overrides this one registry
|
|
110
147
|
* entry with its own and keeps every other block.
|
|
111
148
|
*/
|
|
112
|
-
function HeroBlockRenderer({ block, index, containerClassName, imageComponent: Image }) {
|
|
149
|
+
function HeroBlockRenderer({ block, index, containerClassName, imageComponent: Image, linkComponent: Link }) {
|
|
113
150
|
const image = resolveMedia(block.image);
|
|
114
151
|
const links = (block.links ?? []).filter((link) => link.href && link.label);
|
|
115
152
|
const tone = TONES[block.tone ?? "sweep"];
|
|
@@ -148,12 +185,10 @@ function HeroBlockRenderer({ block, index, containerClassName, imageComponent: I
|
|
|
148
185
|
children: links.map((link, i) => /* @__PURE__ */ jsx(Button, {
|
|
149
186
|
asChild: true,
|
|
150
187
|
variant: i === 0 ? "default" : "outline",
|
|
151
|
-
children: /* @__PURE__ */ jsx(
|
|
188
|
+
children: /* @__PURE__ */ jsx(Link, {
|
|
152
189
|
href: link.href,
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
rel: "noreferrer noopener"
|
|
156
|
-
} : {},
|
|
190
|
+
newTab: link.newTab ?? false,
|
|
191
|
+
...newTabAttributes(link.newTab),
|
|
157
192
|
children: link.label
|
|
158
193
|
})
|
|
159
194
|
}, `${link.href}-${i}`))
|
|
@@ -165,7 +200,7 @@ function HeroBlockRenderer({ block, index, containerClassName, imageComponent: I
|
|
|
165
200
|
}
|
|
166
201
|
//#endregion
|
|
167
202
|
//#region src/blocks/showcase-panels/component.tsx
|
|
168
|
-
function ShowcasePanelsBlockRenderer({ block, containerClassName, imageComponent: Image }) {
|
|
203
|
+
function ShowcasePanelsBlockRenderer({ block, containerClassName, imageComponent: Image, linkComponent }) {
|
|
169
204
|
const dims = [];
|
|
170
205
|
const items = [];
|
|
171
206
|
for (const [i, row] of (block.items ?? []).entries()) {
|
|
@@ -192,6 +227,7 @@ function ShowcasePanelsBlockRenderer({ block, containerClassName, imageComponent
|
|
|
192
227
|
spineVariant: block.spineVariant ?? "numbered",
|
|
193
228
|
defaultActiveIndex: Math.min(Math.max(block.defaultActiveIndex ?? 0, 0), items.length - 1),
|
|
194
229
|
...block.watermark ? { watermark: block.watermark } : {},
|
|
230
|
+
renderLink: renderLinkWith(linkComponent),
|
|
195
231
|
renderImage: (item, i) => /* @__PURE__ */ jsx(Image, {
|
|
196
232
|
src: item.image.src,
|
|
197
233
|
alt: item.image.alt ?? "",
|
|
@@ -244,7 +280,7 @@ function ProcessStepsBlockRenderer({ block, containerClassName, imageComponent:
|
|
|
244
280
|
}
|
|
245
281
|
//#endregion
|
|
246
282
|
//#region src/blocks/faq-columns/component.tsx
|
|
247
|
-
function FaqColumnsBlockRenderer({ block, containerClassName }) {
|
|
283
|
+
function FaqColumnsBlockRenderer({ block, containerClassName, linkComponent }) {
|
|
248
284
|
const items = (block.items ?? []).filter((row) => row.question && row.answer).map((row, i) => ({
|
|
249
285
|
id: row.id ?? String(i),
|
|
250
286
|
question: row.question,
|
|
@@ -268,6 +304,7 @@ function FaqColumnsBlockRenderer({ block, containerClassName }) {
|
|
|
268
304
|
sticky: block.sticky ?? true,
|
|
269
305
|
type: block.type ?? "single",
|
|
270
306
|
collapsible: block.collapsible ?? true,
|
|
307
|
+
renderLink: renderLinkWith(linkComponent),
|
|
271
308
|
...hasCta && cta ? { cta: {
|
|
272
309
|
title: cta.title ?? "",
|
|
273
310
|
linkText: cta.linkText,
|
|
@@ -279,7 +316,7 @@ function FaqColumnsBlockRenderer({ block, containerClassName }) {
|
|
|
279
316
|
}
|
|
280
317
|
//#endregion
|
|
281
318
|
//#region src/blocks/testimonial-masonry/component.tsx
|
|
282
|
-
function TestimonialMasonryBlockRenderer({ block, containerClassName }) {
|
|
319
|
+
function TestimonialMasonryBlockRenderer({ block, containerClassName, linkComponent }) {
|
|
283
320
|
const items = (block.items ?? []).filter((row) => row.content && row.author?.name).map((row, i) => {
|
|
284
321
|
const avatar = resolveMedia(row.author?.avatar);
|
|
285
322
|
return {
|
|
@@ -304,6 +341,7 @@ function TestimonialMasonryBlockRenderer({ block, containerClassName }) {
|
|
|
304
341
|
containerClassName: "max-w-none px-0 py-0 sm:py-0 md:px-0 md:py-0",
|
|
305
342
|
items,
|
|
306
343
|
title: block.title ?? "",
|
|
344
|
+
renderLink: renderLinkWith(linkComponent),
|
|
307
345
|
...block.eyebrow ? { eyebrow: block.eyebrow } : {},
|
|
308
346
|
...block.description ? { description: block.description } : {},
|
|
309
347
|
...typeof block.minItemsForFade === "number" ? { minItemsForFade: block.minItemsForFade } : {},
|
|
@@ -319,7 +357,7 @@ function TestimonialMasonryBlockRenderer({ block, containerClassName }) {
|
|
|
319
357
|
}
|
|
320
358
|
//#endregion
|
|
321
359
|
//#region src/blocks/nap/component.tsx
|
|
322
|
-
function NapBlockRenderer({ block, containerClassName }) {
|
|
360
|
+
function NapBlockRenderer({ block, containerClassName, linkComponent }) {
|
|
323
361
|
const address = block.address;
|
|
324
362
|
const departments = (block.departments ?? []).filter((row) => row.name && row.phoneE164).map((row, i) => ({
|
|
325
363
|
id: row.id ?? String(i),
|
|
@@ -349,11 +387,140 @@ function NapBlockRenderer({ block, containerClassName }) {
|
|
|
349
387
|
children: [/* @__PURE__ */ jsx(NapBlock, {
|
|
350
388
|
record,
|
|
351
389
|
showName: block.showName ?? true,
|
|
352
|
-
headingLevel: block.headingLevel ?? "h2"
|
|
390
|
+
headingLevel: block.headingLevel ?? "h2",
|
|
391
|
+
renderLink: renderLinkWith(linkComponent)
|
|
353
392
|
}), block.emitJsonLd === false ? null : /* @__PURE__ */ jsx(JsonLd, { data: record })]
|
|
354
393
|
}) });
|
|
355
394
|
}
|
|
356
395
|
//#endregion
|
|
357
|
-
|
|
396
|
+
//#region src/blocks/mega-menu/rem-width.ts
|
|
397
|
+
/**
|
|
398
|
+
* The one rule for a typed panel width, shared by the config's validator and
|
|
399
|
+
* the renderer's reader so the two cannot drift: if the validator accepted a
|
|
400
|
+
* value the renderer dropped, the editor would be back to a width that
|
|
401
|
+
* silently does nothing. React-free, because `config.ts` ships from the Node
|
|
402
|
+
* entry.
|
|
403
|
+
*/
|
|
404
|
+
const REM_WIDTH = /^\s*(\d+(?:\.\d+)?)\s*(rem)?\s*$/;
|
|
405
|
+
/** "30" and "30rem" both mean 30rem; anything else is not a width. */
|
|
406
|
+
function remWidth(value) {
|
|
407
|
+
const match = REM_WIDTH.exec(value ?? "");
|
|
408
|
+
return match ? `${Number(match[1])}rem` : null;
|
|
409
|
+
}
|
|
410
|
+
//#endregion
|
|
411
|
+
//#region src/blocks/mega-menu/component.tsx
|
|
412
|
+
function completeLink(row) {
|
|
413
|
+
if (!row.label || !row.href) return null;
|
|
414
|
+
return {
|
|
415
|
+
label: row.label,
|
|
416
|
+
href: row.href,
|
|
417
|
+
...row.description ? { description: row.description } : {},
|
|
418
|
+
...row.variant ? { variant: row.variant } : {},
|
|
419
|
+
...row.icon ? { icon: row.icon } : {},
|
|
420
|
+
...row.newTab ? { newTab: true } : {}
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* The row as `MegaMenuPanel` data, or `null` when there is nothing to open:
|
|
425
|
+
* no columns, or columns whose links are not yet complete. Draft saves skip
|
|
426
|
+
* validation, so a live preview genuinely hands this half-built rows.
|
|
427
|
+
*/
|
|
428
|
+
function megaMenuPanelFromRow(row) {
|
|
429
|
+
const panel = row.panel;
|
|
430
|
+
if (!panel?.columns?.length) return null;
|
|
431
|
+
const custom = Boolean(panel.customWidths);
|
|
432
|
+
const columns = [];
|
|
433
|
+
for (const column of panel.columns) {
|
|
434
|
+
const sections = [];
|
|
435
|
+
for (const section of column.sections ?? []) {
|
|
436
|
+
const links = (section.links ?? []).map(completeLink).filter((link) => link !== null);
|
|
437
|
+
if (!links.length) continue;
|
|
438
|
+
sections.push({
|
|
439
|
+
...section.eyebrow ? { eyebrow: section.eyebrow } : {},
|
|
440
|
+
display: section.display ?? "list",
|
|
441
|
+
hideDescriptionsOnMobile: section.hideDescriptionsOnMobile ?? true,
|
|
442
|
+
links
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
columns.push({
|
|
446
|
+
...custom && column.customWidth ? { customWidth: column.customWidth } : { width: Number(column.width ?? "100") },
|
|
447
|
+
...column.divider ? { divider: true } : {},
|
|
448
|
+
sections
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
if (!columns.some((column) => column.sections.length)) return null;
|
|
452
|
+
const overview = panel.footer?.overview;
|
|
453
|
+
const cta = panel.footer?.cta;
|
|
454
|
+
return {
|
|
455
|
+
maxWidth: remWidth(panel.customMaxWidth) ?? panel.maxWidth ?? "standard",
|
|
456
|
+
columns,
|
|
457
|
+
footer: {
|
|
458
|
+
...overview?.label && overview.href ? { overview: {
|
|
459
|
+
label: overview.label,
|
|
460
|
+
href: overview.href,
|
|
461
|
+
...overview.newTab ? { newTab: true } : {}
|
|
462
|
+
} } : {},
|
|
463
|
+
...cta?.label && cta.href ? { cta: {
|
|
464
|
+
label: cta.label,
|
|
465
|
+
href: cta.href,
|
|
466
|
+
...cta.newTab ? { newTab: true } : {}
|
|
467
|
+
} } : {}
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* One panel, standing alone: what a live preview shows while the row is being
|
|
473
|
+
* edited. A whole header goes through `headerItemsFromBlocks` instead.
|
|
474
|
+
*/
|
|
475
|
+
function MegaMenuBlockRenderer({ block, linkComponent, variants, icons }) {
|
|
476
|
+
const panel = megaMenuPanelFromRow(block);
|
|
477
|
+
if (!panel) return null;
|
|
478
|
+
return /* @__PURE__ */ jsx(MegaMenuPanel, {
|
|
479
|
+
...panel,
|
|
480
|
+
variants,
|
|
481
|
+
icons,
|
|
482
|
+
renderLink: renderLinkWith(linkComponent)
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
//#endregion
|
|
486
|
+
//#region src/blocks/mega-menu/header.tsx
|
|
487
|
+
/**
|
|
488
|
+
* A global's `items` as `FloatingNavBlock` items, so a site's header is one
|
|
489
|
+
* call. Rows the bar cannot show are dropped rather than rendered broken: a
|
|
490
|
+
* row with no label, a mega menu with nothing to open, and any block type a
|
|
491
|
+
* site added that this package does not know.
|
|
492
|
+
*
|
|
493
|
+
* A `navLink` row's `newTab` is not carried: `FloatingNavItem` has no such
|
|
494
|
+
* field, because the bar renders its own links.
|
|
495
|
+
*/
|
|
496
|
+
function headerItemsFromBlocks(blocks, { variants, icons, isActive, linkComponent } = {}) {
|
|
497
|
+
const items = [];
|
|
498
|
+
for (const row of blocks) {
|
|
499
|
+
if (!row.label) continue;
|
|
500
|
+
if (row.blockType === "navLink") {
|
|
501
|
+
if (!row.href) continue;
|
|
502
|
+
items.push({
|
|
503
|
+
label: row.label,
|
|
504
|
+
href: row.href
|
|
505
|
+
});
|
|
506
|
+
} else if (row.blockType === "megaMenu") {
|
|
507
|
+
const panel = megaMenuPanelFromRow(row);
|
|
508
|
+
if (!panel) continue;
|
|
509
|
+
items.push({
|
|
510
|
+
label: row.label,
|
|
511
|
+
...row.href ? { href: row.href } : {},
|
|
512
|
+
panel
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
return megaMenuToFloatingNavItems({ items }, {
|
|
517
|
+
isActive,
|
|
518
|
+
variants,
|
|
519
|
+
icons,
|
|
520
|
+
...linkComponent ? { renderLink: renderLinkWith(linkComponent) } : {}
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
//#endregion
|
|
524
|
+
export { DEFAULT_CONTAINER, DefaultBlockImage, DefaultBlockLink, FaqColumnsBlockRenderer, HeroBlockRenderer, MegaMenuBlockRenderer, NapBlockRenderer, ProcessStepsBlockRenderer, RenderBlocks, ShowcasePanelsBlockRenderer, TestimonialMasonryBlockRenderer, headerItemsFromBlocks, megaMenuPanelFromRow, newTabAttributes, renderLinkWith };
|
|
358
525
|
|
|
359
526
|
//# sourceMappingURL=react.mjs.map
|
package/dist/react.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.mjs","names":[],"sources":["../src/image.tsx","../src/render-blocks.tsx","../src/media.ts","../src/blocks/hero/component.tsx","../src/blocks/showcase-panels/component.tsx","../src/blocks/process-steps/component.tsx","../src/blocks/faq-columns/component.tsx","../src/blocks/testimonial-masonry/component.tsx","../src/blocks/nap/component.tsx"],"sourcesContent":["import type { ComponentType } from \"react\";\n\n/**\n * The image injection point.\n *\n * The package deliberately does not depend on `next` — a Payload site is not\n * necessarily a Next.js site, and `next/image` needs per-site configuration\n * (`remotePatterns` for the media route) that a package cannot supply. So\n * renderers never construct an image element themselves; they render the\n * component they were handed. A Next site writes one adapter around\n * `next/image` and every block gets optimisation from it.\n *\n * This is a *component type*, not a render function, on purpose: a Server\n * Component may pass a client component reference across the boundary, but not\n * a closure. `imageComponent` therefore survives the trip from a server page\n * into these client renderers, where a `renderImage` callback would not.\n */\n\nexport interface BlockImageProps {\n src: string;\n /** Always a string — see `resolveMedia`. Empty means decorative. */\n alt: string;\n width?: number;\n height?: number;\n className?: string;\n /** Passed through to `next/image`'s `sizes`; ignored by the default. */\n sizes?: string;\n /** Set on the one image above the fold, typically the hero's. */\n priority?: boolean;\n}\n\nexport type BlockImageComponent = ComponentType<BlockImageProps>;\n\n/**\n * The fallback when no `imageComponent` is supplied: a plain `<img>`. Correct\n * everywhere and optimised nowhere, which is the right default for a package\n * that cannot know what framework it landed in.\n */\nexport function DefaultBlockImage({\n src,\n alt,\n width,\n height,\n className,\n sizes,\n priority,\n}: BlockImageProps) {\n return (\n <img\n src={src}\n alt={alt}\n width={width}\n height={height}\n className={className}\n sizes={sizes}\n loading={priority ? \"eager\" : \"lazy\"}\n decoding=\"async\"\n />\n );\n}\n","import type { ComponentType, ReactElement } from \"react\";\n\nimport { type BlockImageComponent, DefaultBlockImage } from \"./image\";\n\n/** The minimum a row must be for the dispatch to place it. */\nexport interface BlockLike {\n blockType: string;\n id?: string | null;\n}\n\n/**\n * What every renderer is handed.\n *\n * The neighbour props let a block adapt to what sits around it: `prevType` to\n * close a seam against the block above, `runIndex` to alternate surfaces across\n * back-to-back blocks of one type, `isLast` because the final block sits\n * against the site footer.\n *\n * `containerClassName` and `imageComponent` are the two things a package block\n * cannot decide for itself — the site's page measure, and how an image gets\n * optimised. Both arrive already defaulted, so a renderer never checks them.\n */\nexport interface BlockRendererProps<B extends BlockLike = BlockLike> {\n block: B;\n /** Position on the page, hero included. */\n index: number;\n /** The type of the block before this one; absent on the first block. */\n prevType?: string;\n /** Position within a run of consecutive same-type blocks, from 0. */\n runIndex: number;\n isLast: boolean;\n /** The site's page measure, for the band wrapper. */\n containerClassName: string;\n /** How this block turns a resolved image into an element. */\n imageComponent: BlockImageComponent;\n}\n\n/**\n * One renderer per block type, each typed to its own block.\n *\n * Written as a mapped type over the union so `hero` gets `HeroBlockData`, not\n * the whole union. A site writes `satisfies BlockRegistryFor<AnyBlock>` where\n * `AnyBlock` comes off its *generated* `Page` type — that is the compile-time\n * layout lock, and it has to stay in the site, because only the site has\n * generated types. The registry is a parameter here for exactly that reason.\n */\nexport type BlockRegistryFor<B extends BlockLike> = {\n [K in B[\"blockType\"]]: ComponentType<\n BlockRendererProps<Extract<B, { blockType: K }>>\n >;\n};\n\n/** Fallback page measure for a site that does not pass its own. */\nexport const DEFAULT_CONTAINER = \"mx-auto w-full max-w-7xl px-6\";\n\ntype LooseRenderer = ComponentType<BlockRendererProps<BlockLike>>;\n\n/**\n * A row saved against a block that has since left the config has no renderer.\n * It is dropped before anything is counted, so its neighbours see each other,\n * not a gap: the block after it gets the real `prevType`, a run of one type is\n * not broken by it, and the block before it is still `isLast` when it ends the\n * page.\n */\nfunction renderable(\n blocks: BlockLike[],\n registry: Record<string, LooseRenderer | undefined>,\n): { block: BlockLike; Renderer: LooseRenderer }[] {\n return blocks.flatMap((block) => {\n const Renderer = registry[block.blockType];\n return Renderer ? [{ block, Renderer }] : [];\n });\n}\n\n/** Position of each block within its run of consecutive same-type blocks. */\nfunction runIndexes(blocks: BlockLike[]): number[] {\n const out: number[] = [];\n for (let i = 0; i < blocks.length; i += 1) {\n out.push(\n i > 0 && blocks[i - 1].blockType === blocks[i].blockType\n ? out[i - 1] + 1\n : 0,\n );\n }\n return out;\n}\n\nexport interface RenderBlocksProps<B extends BlockLike> {\n /** Pass `[...page.hero, ...page.layout]`, so the hero counts as index 0. */\n blocks: B[];\n registry: BlockRegistryFor<B>;\n /** The site's page measure. Defaults to `DEFAULT_CONTAINER`. */\n containerClassName?: string;\n /** Defaults to a plain `<img>`; a Next site passes a `next/image` adapter. */\n imageComponent?: BlockImageComponent;\n}\n\n/**\n * Renders a page's blocks in order through the registry. A Server Component:\n * it only maps and looks up, and each renderer decides its own nature.\n */\nexport function RenderBlocks<B extends BlockLike>({\n blocks,\n registry,\n containerClassName = DEFAULT_CONTAINER,\n imageComponent = DefaultBlockImage,\n}: RenderBlocksProps<B>): ReactElement {\n const rows = renderable(\n blocks,\n // The mapped registry type is per-block, and the dispatch is not; the\n // lookup below is what guarantees each renderer only ever sees its own\n // block type, and no signature can express that to the compiler.\n registry as unknown as Record<string, LooseRenderer | undefined>,\n );\n const runs = runIndexes(rows.map((row) => row.block));\n return (\n <>\n {rows.map(({ block, Renderer }, index) => (\n <Renderer\n key={block.id ?? index}\n block={block}\n index={index}\n prevType={index > 0 ? rows[index - 1].block.blockType : undefined}\n runIndex={runs[index]}\n isLast={index === rows.length - 1}\n containerClassName={containerClassName}\n imageComponent={imageComponent}\n />\n ))}\n </>\n );\n}\n","/**\n * The upload side of the boundary.\n *\n * A Payload upload field holds either the row's id or, once depth resolves it,\n * the whole document. Neither shape can be imported from here: `Media` is\n * generated per site, and this package must never reach for a site's\n * `payload-types`. So the doc is described structurally, and every renderer\n * goes through `resolveMedia` rather than reading `.url` itself.\n */\n\n/**\n * The subset of a Payload upload document a block renderer actually reads.\n * Every site's generated `Media` interface is assignable to this, whatever\n * else it carries.\n *\n * Deliberately no index signature: TypeScript refuses to assign an interface\n * to a type with one, and a site's generated `Media` is always an interface.\n * An index signature here would break exactly the structural match this type\n * exists to provide.\n */\nexport interface MediaDoc {\n url?: string | null;\n alt?: string | null;\n width?: number | null;\n height?: number | null;\n}\n\n/** What an upload field holds before and after `depth` populates it. */\nexport type MediaValue = number | string | MediaDoc | null | undefined;\n\n/** A resolved image, in the shape every `@bison-lab/ui` block asks for. */\nexport interface ResolvedMedia {\n src: string;\n alt: string;\n width?: number;\n height?: number;\n}\n\nfunction isMediaDoc(value: MediaValue): value is MediaDoc {\n return typeof value === \"object\" && value !== null;\n}\n\n/**\n * Narrows an upload value to something renderable, or `undefined`.\n *\n * `undefined` covers three cases a renderer must treat identically: the field\n * is empty, `depth: 0` left it as a bare id, or the document exists but has no\n * `url` yet (an upload mid-flight). A renderer that gets `undefined` omits the\n * image rather than emitting a broken `<img>`.\n *\n * `alt` is always a string: the media collection requires it, but a draft saved\n * before that validation ran can still reach a renderer, and an `alt` of\n * `undefined` would silently drop the attribute entirely.\n */\nexport function resolveMedia(value: MediaValue): ResolvedMedia | undefined {\n if (!isMediaDoc(value)) return undefined;\n const { url, alt, width, height } = value;\n if (typeof url !== \"string\" || url.length === 0) return undefined;\n return {\n src: url,\n alt: typeof alt === \"string\" ? alt : \"\",\n ...(typeof width === \"number\" ? { width } : {}),\n ...(typeof height === \"number\" ? { height } : {}),\n };\n}\n","import { Button } from \"@bison-lab/ui\";\n\nimport { cx } from \"../../cx\";\nimport { resolveMedia } from \"../../media\";\nimport type { BlockRendererProps } from \"../../render-blocks\";\nimport type { HeroBlockData } from \"../../types\";\n\n/**\n * How each tone paints. Semantic tokens only — a site's brand reaches these\n * through its theme, never through a class named here.\n */\nconst TONES = {\n sweep: \"bg-primary text-primary-foreground\",\n dark: \"bg-foreground text-background\",\n light: \"bg-background text-foreground\",\n} as const;\n\n/**\n * The package's hero: deliberately plain.\n *\n * A hero is where a site's brand is loudest, so this exists to make a page\n * render at all, not to be the final answer. A site overrides this one registry\n * entry with its own and keeps every other block.\n */\nexport function HeroBlockRenderer({\n block,\n index,\n containerClassName,\n imageComponent: Image,\n}: BlockRendererProps<HeroBlockData>) {\n const image = resolveMedia(block.image);\n const links = (block.links ?? []).filter((link) => link.href && link.label);\n const tone = TONES[block.tone ?? \"sweep\"];\n\n return (\n <section className={cx(\"relative isolate overflow-hidden\", tone)}>\n {image ? (\n <div className=\"absolute inset-0 -z-10 opacity-25\">\n <Image\n src={image.src}\n alt=\"\"\n width={image.width}\n height={image.height}\n className=\"h-full w-full object-cover\"\n sizes=\"100vw\"\n // The hero is the page's LCP element whenever it opens the page.\n priority={index === 0}\n />\n </div>\n ) : null}\n <div className={cx(containerClassName, \"py-20 lg:py-28\")}>\n <div className=\"max-w-3xl\">\n {block.eyebrow ? (\n <p className=\"text-sm font-semibold tracking-widest uppercase opacity-80\">\n {block.eyebrow}\n </p>\n ) : null}\n <h1 className=\"mt-3 text-4xl font-bold tracking-tight text-balance lg:text-5xl\">\n {block.heading}\n </h1>\n {block.body ? (\n <p className=\"mt-6 max-w-2xl text-lg leading-relaxed opacity-90\">\n {block.body}\n </p>\n ) : null}\n {links.length > 0 ? (\n <div className=\"mt-8 flex flex-wrap gap-3\">\n {links.map((link, i) => (\n <Button\n key={`${link.href}-${i}`}\n asChild\n variant={i === 0 ? \"default\" : \"outline\"}\n >\n <a\n href={link.href as string}\n {...(link.newTab\n ? { target: \"_blank\", rel: \"noreferrer noopener\" }\n : {})}\n >\n {link.label}\n </a>\n </Button>\n ))}\n </div>\n ) : null}\n </div>\n </div>\n </section>\n );\n}\n","import { ShowcasePanelsBlock, type ShowcasePanelItem } from \"@bison-lab/ui\";\n\nimport { cx } from \"../../cx\";\nimport { resolveMedia, type ResolvedMedia } from \"../../media\";\nimport type { BlockRendererProps } from \"../../render-blocks\";\nimport type { ShowcasePanelsBlockData } from \"../../types\";\n\nexport function ShowcasePanelsBlockRenderer({\n block,\n containerClassName,\n imageComponent: Image,\n}: BlockRendererProps<ShowcasePanelsBlockData>) {\n // A panel without a picture has nothing to expand into, so a row whose\n // upload has not resolved is dropped rather than rendered empty. `dims`\n // stays index-aligned with `items` so the image callback can reach the\n // width and height the library's own prop shape has no room for.\n const dims: ResolvedMedia[] = [];\n const items: ShowcasePanelItem[] = [];\n for (const [i, row] of (block.items ?? []).entries()) {\n const image = resolveMedia(row.image);\n if (!image) continue;\n dims.push(image);\n items.push({\n id: row.id ?? String(i),\n title: row.title ?? \"\",\n summary: row.summary ?? \"\",\n image: { src: image.src, alt: image.alt },\n ...(row.href ? { href: row.href } : {}),\n ...(row.numeral ? { numeral: row.numeral } : {}),\n });\n }\n if (items.length === 0) return null;\n\n return (\n <section className={cx(containerClassName, \"py-16 lg:py-24\")}>\n <ShowcasePanelsBlock\n items={items}\n spineVariant={block.spineVariant ?? \"numbered\"}\n defaultActiveIndex={Math.min(\n Math.max(block.defaultActiveIndex ?? 0, 0),\n items.length - 1,\n )}\n {...(block.watermark ? { watermark: block.watermark } : {})}\n renderImage={(item, i) => (\n <Image\n src={item.image.src}\n alt={item.image.alt ?? \"\"}\n width={dims[i]?.width}\n height={dims[i]?.height}\n className=\"absolute inset-0 h-full w-full object-cover\"\n sizes=\"(min-width: 1024px) 50vw, 100vw\"\n />\n )}\n />\n </section>\n );\n}\n","import { ProcessStepsBlock, type ProcessStepItem } from \"@bison-lab/ui\";\n\nimport { cx } from \"../../cx\";\nimport { resolveMedia, type ResolvedMedia } from \"../../media\";\nimport type { BlockRendererProps } from \"../../render-blocks\";\nimport type { ProcessStepsBlockData } from \"../../types\";\n\nexport function ProcessStepsBlockRenderer({\n block,\n containerClassName,\n imageComponent: Image,\n}: BlockRendererProps<ProcessStepsBlockData>) {\n // Same rule as the showcase panels: a step is its picture, so an unresolved\n // upload drops the row instead of rendering a hole in the rail.\n const dims: ResolvedMedia[] = [];\n const items: ProcessStepItem[] = [];\n for (const [i, row] of (block.items ?? []).entries()) {\n const image = resolveMedia(row.image);\n if (!image) continue;\n dims.push(image);\n items.push({\n id: row.id ?? String(i),\n title: row.title ?? \"\",\n description: row.description ?? \"\",\n image: { src: image.src, alt: image.alt },\n });\n }\n if (items.length === 0) return null;\n\n return (\n <section className={cx(containerClassName, \"py-16 lg:py-24\")}>\n <ProcessStepsBlock\n items={items}\n autoAdvance={block.autoAdvance ?? true}\n autoAdvanceDuration={block.autoAdvanceDuration ?? 6000}\n pauseOnHover={block.pauseOnHover ?? true}\n defaultActiveIndex={Math.min(\n Math.max(block.defaultActiveIndex ?? 0, 0),\n items.length - 1,\n )}\n renderImage={(item, i) => (\n <Image\n src={item.image.src}\n alt={item.image.alt ?? \"\"}\n width={dims[i]?.width}\n height={dims[i]?.height}\n className=\"size-full object-cover\"\n sizes=\"(min-width: 768px) 66vw, 100vw\"\n />\n )}\n />\n </section>\n );\n}\n","import { FAQColumnsBlock, type FAQItem } from \"@bison-lab/ui\";\n\nimport { cx } from \"../../cx\";\nimport type { BlockRendererProps } from \"../../render-blocks\";\nimport type { FaqColumnsBlockData } from \"../../types\";\n\nexport function FaqColumnsBlockRenderer({\n block,\n containerClassName,\n}: BlockRendererProps<FaqColumnsBlockData>) {\n const items: FAQItem[] = (block.items ?? [])\n .filter((row) => row.question && row.answer)\n .map((row, i) => ({\n id: row.id ?? String(i),\n question: row.question as string,\n // The field is a textarea, so blank lines are the editor's paragraph\n // breaks and have to survive into the DOM.\n answer: <span className=\"whitespace-pre-line\">{row.answer}</span>,\n }));\n if (items.length === 0) return null;\n\n const cta = block.cta;\n const hasCta = Boolean(cta?.href && cta?.linkText);\n\n return (\n <section>\n <div className={cx(containerClassName, \"py-16 lg:py-24\")}>\n <FAQColumnsBlock\n // The site measure is on the wrapper above; the block's own\n // container and vertical rhythm are reset so they cannot fight it.\n className=\"py-0 md:py-0\"\n containerClassName=\"max-w-none px-0 sm:px-0\"\n items={items}\n title={block.title ?? \"\"}\n {...(block.eyebrow ? { eyebrow: block.eyebrow } : {})}\n {...(block.description ? { description: block.description } : {})}\n sticky={block.sticky ?? true}\n type={block.type ?? \"single\"}\n collapsible={block.collapsible ?? true}\n {...(hasCta && cta\n ? {\n cta: {\n title: cta.title ?? \"\",\n linkText: cta.linkText as string,\n href: cta.href as string,\n newTab: cta.newTab ?? false,\n },\n }\n : {})}\n />\n </div>\n </section>\n );\n}\n","import { TestimonialMasonry, type TestimonialItem } from \"@bison-lab/ui\";\n\nimport { cx } from \"../../cx\";\nimport { resolveMedia } from \"../../media\";\nimport type { BlockRendererProps } from \"../../render-blocks\";\nimport type { TestimonialMasonryBlockData } from \"../../types\";\n\nexport function TestimonialMasonryBlockRenderer({\n block,\n containerClassName,\n}: BlockRendererProps<TestimonialMasonryBlockData>) {\n const items: TestimonialItem[] = (block.items ?? [])\n .filter((row) => row.content && row.author?.name)\n .map((row, i) => {\n const avatar = resolveMedia(row.author?.avatar);\n return {\n id: row.id ?? String(i),\n content: row.content as string,\n author: {\n name: row.author?.name as string,\n ...(row.author?.title ? { title: row.author.title } : {}),\n // The library falls back to initials when this is absent, which is\n // why an unresolved upload must not become an empty string.\n ...(avatar ? { avatarUrl: avatar.src } : {}),\n },\n };\n });\n if (items.length === 0) return null;\n\n const link = block.link;\n const hasLink = Boolean(link?.href && link?.label);\n\n return (\n // The band's surface is full-bleed; only its contents sit at the measure.\n <section className=\"bg-accent\">\n <div className={cx(containerClassName, \"py-16 lg:py-24\")}>\n <TestimonialMasonry\n className=\"bg-transparent px-0 lg:px-0\"\n containerClassName=\"max-w-none px-0 py-0 sm:py-0 md:px-0 md:py-0\"\n items={items}\n title={block.title ?? \"\"}\n {...(block.eyebrow ? { eyebrow: block.eyebrow } : {})}\n {...(block.description ? { description: block.description } : {})}\n {...(typeof block.minItemsForFade === \"number\"\n ? { minItemsForFade: block.minItemsForFade }\n : {})}\n {...(typeof block.maxVisibleRows === \"number\"\n ? { maxVisibleRows: block.maxVisibleRows }\n : {})}\n {...(hasLink && link\n ? {\n link: {\n label: link.label as string,\n href: link.href as string,\n newTab: link.newTab ?? false,\n },\n }\n : {})}\n />\n </div>\n </section>\n );\n}\n","import {\n JsonLd,\n NapBlock,\n type NapDepartment,\n type NapRecord,\n} from \"@bison-lab/ui\";\n\nimport { cx } from \"../../cx\";\nimport type { BlockRendererProps } from \"../../render-blocks\";\nimport type { NapBlockData } from \"../../types\";\n\nexport function NapBlockRenderer({\n block,\n containerClassName,\n}: BlockRendererProps<NapBlockData>) {\n const address = block.address;\n const departments: NapDepartment[] = (block.departments ?? [])\n // `phoneE164` is what becomes the `tel:` href and the structured data's\n // `telephone`, so a department without one is not publishable as a NAP\n // entry at all — dropping it beats emitting an unreachable number.\n .filter((row) => row.name && row.phoneE164)\n .map((row, i) => ({\n id: row.id ?? String(i),\n name: row.name as string,\n ...(row.departmentType ? { type: row.departmentType } : {}),\n phone: {\n e164: row.phoneE164 as string,\n ...(row.phoneDisplay ? { display: row.phoneDisplay } : {}),\n },\n }));\n\n if (!block.businessName || !address?.streetAddress || departments.length === 0)\n return null;\n\n const record: NapRecord = {\n name: block.businessName,\n type: block.businessType ?? \"LocalBusiness\",\n address: {\n streetAddress: address.streetAddress,\n addressLocality: address.addressLocality ?? \"\",\n addressRegion: address.addressRegion ?? \"\",\n postalCode: address.postalCode ?? \"\",\n ...(address.addressCountry\n ? { addressCountry: address.addressCountry }\n : {}),\n },\n departments,\n ...(block.url ? { url: block.url } : {}),\n };\n\n return (\n <section>\n <div className={cx(containerClassName, \"py-16 lg:py-24\")}>\n <NapBlock\n record={record}\n showName={block.showName ?? true}\n headingLevel={block.headingLevel ?? \"h2\"}\n />\n {block.emitJsonLd === false ? null : <JsonLd data={record} />}\n </div>\n </section>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"react.mjs","names":[],"sources":["../src/image.tsx","../src/link.tsx","../src/render-blocks.tsx","../src/media.ts","../src/blocks/hero/component.tsx","../src/blocks/showcase-panels/component.tsx","../src/blocks/process-steps/component.tsx","../src/blocks/faq-columns/component.tsx","../src/blocks/testimonial-masonry/component.tsx","../src/blocks/nap/component.tsx","../src/blocks/mega-menu/rem-width.ts","../src/blocks/mega-menu/component.tsx","../src/blocks/mega-menu/header.tsx"],"sourcesContent":["import type { ComponentType } from \"react\";\n\n/**\n * The image injection point.\n *\n * The package deliberately does not depend on `next` — a Payload site is not\n * necessarily a Next.js site, and `next/image` needs per-site configuration\n * (`remotePatterns` for the media route) that a package cannot supply. So\n * renderers never construct an image element themselves; they render the\n * component they were handed. A Next site writes one adapter around\n * `next/image` and every block gets optimisation from it.\n *\n * This is a *component type*, not a render function, on purpose: a Server\n * Component may pass a client component reference across the boundary, but not\n * a closure. `imageComponent` therefore survives the trip from a server page\n * into these client renderers, where a `renderImage` callback would not.\n */\n\nexport interface BlockImageProps {\n src: string;\n /** Always a string — see `resolveMedia`. Empty means decorative. */\n alt: string;\n width?: number;\n height?: number;\n className?: string;\n /** Passed through to `next/image`'s `sizes`; ignored by the default. */\n sizes?: string;\n /** Set on the one image above the fold, typically the hero's. */\n priority?: boolean;\n}\n\nexport type BlockImageComponent = ComponentType<BlockImageProps>;\n\n/**\n * The fallback when no `imageComponent` is supplied: a plain `<img>`. Correct\n * everywhere and optimised nowhere, which is the right default for a package\n * that cannot know what framework it landed in.\n */\nexport function DefaultBlockImage({\n src,\n alt,\n width,\n height,\n className,\n sizes,\n priority,\n}: BlockImageProps) {\n return (\n <img\n src={src}\n alt={alt}\n width={width}\n height={height}\n className={className}\n sizes={sizes}\n loading={priority ? \"eager\" : \"lazy\"}\n decoding=\"async\"\n />\n );\n}\n","import type { AnchorHTMLAttributes, ComponentType, ReactNode } from \"react\";\nimport type { RenderLink } from \"@bison-lab/ui\";\n\n/**\n * The link injection point, the same shape as `BlockImageComponent`.\n *\n * A renderer never writes `<a>` directly. A site hands in one link component\n * and every CMS link routes through it — Next's `Link`, so navigation stays\n * client-side. It is a *component type*, not a render function, for the same\n * reason the image seam is: a Server Component can pass a client component\n * reference across the boundary, but not a closure.\n *\n * `newTab` is the flag from `linkFields()`; `target` and `rel` are always\n * already expanded from it by the time the component is called, so an adapter\n * that only spreads the anchor attributes onto its router link is still safe.\n * The one thing an adapter must do is drop `newTab` before spreading, or React\n * warns about an unknown DOM attribute — see the README's `next/link` adapter.\n */\nexport interface BlockLinkProps\n extends AnchorHTMLAttributes<HTMLAnchorElement> {\n href: string;\n children: ReactNode;\n newTab?: boolean;\n className?: string;\n}\n\nexport type BlockLinkComponent = ComponentType<BlockLinkProps>;\n\n/** `target` and `rel` together, or neither: a bare `target` is a tabnabbing hole. */\nexport function newTabAttributes(\n newTab: boolean | null | undefined,\n): Pick<AnchorHTMLAttributes<HTMLAnchorElement>, \"target\" | \"rel\"> {\n return newTab ? { target: \"_blank\", rel: \"noopener noreferrer\" } : {};\n}\n\n/**\n * The fallback when no `linkComponent` is supplied: a plain `<a>`. Correct\n * everywhere and client-side nowhere, which is the right default for a package\n * that cannot know what router it landed in.\n */\nexport function DefaultBlockLink({\n href,\n newTab,\n children,\n ...rest\n}: BlockLinkProps) {\n return (\n <a href={href} {...rest} {...newTabAttributes(newTab)}>\n {children}\n </a>\n );\n}\nDefaultBlockLink.displayName = \"DefaultBlockLink\";\n\n/**\n * Adapts the seam to the `renderLink` prop every `@bison-lab/ui` block takes.\n * The ui blocks hand over `target`/`rel` already expanded, so `newTab` is\n * read back off `target` to keep the flag and the attributes in step.\n */\nexport function renderLinkWith(Link: BlockLinkComponent): RenderLink {\n return ({ href, children, ...rest }) => (\n <Link href={href} newTab={rest.target === \"_blank\"} {...rest}>\n {children}\n </Link>\n );\n}\n","import type { ComponentType, ReactElement } from \"react\";\n\nimport { type BlockImageComponent, DefaultBlockImage } from \"./image\";\nimport { type BlockLinkComponent, DefaultBlockLink } from \"./link\";\n\n/** The minimum a row must be for the dispatch to place it. */\nexport interface BlockLike {\n blockType: string;\n id?: string | null;\n}\n\n/**\n * What every renderer is handed.\n *\n * The neighbour props let a block adapt to what sits around it: `prevType` to\n * close a seam against the block above, `runIndex` to alternate surfaces across\n * back-to-back blocks of one type, `isLast` because the final block sits\n * against the site footer.\n *\n * `containerClassName`, `imageComponent` and `linkComponent` are the three\n * things a package block cannot decide for itself — the site's page measure,\n * how an image gets optimised, and which router a link goes through. All three\n * arrive already defaulted, so a renderer never checks them.\n */\nexport interface BlockRendererProps<B extends BlockLike = BlockLike> {\n block: B;\n /** Position on the page, hero included. */\n index: number;\n /** The type of the block before this one; absent on the first block. */\n prevType?: string;\n /** Position within a run of consecutive same-type blocks, from 0. */\n runIndex: number;\n isLast: boolean;\n /** The site's page measure, for the band wrapper. */\n containerClassName: string;\n /** How this block turns a resolved image into an element. */\n imageComponent: BlockImageComponent;\n /** How this block turns an `href` into an element. */\n linkComponent: BlockLinkComponent;\n}\n\n/**\n * One renderer per block type, each typed to its own block.\n *\n * Written as a mapped type over the union so `hero` gets `HeroBlockData`, not\n * the whole union. A site writes `satisfies BlockRegistryFor<AnyBlock>` where\n * `AnyBlock` comes off its *generated* `Page` type — that is the compile-time\n * layout lock, and it has to stay in the site, because only the site has\n * generated types. The registry is a parameter here for exactly that reason.\n */\nexport type BlockRegistryFor<B extends BlockLike> = {\n [K in B[\"blockType\"]]: ComponentType<\n BlockRendererProps<Extract<B, { blockType: K }>>\n >;\n};\n\n/** Fallback page measure for a site that does not pass its own. */\nexport const DEFAULT_CONTAINER = \"mx-auto w-full max-w-7xl px-6\";\n\ntype LooseRenderer = ComponentType<BlockRendererProps<BlockLike>>;\n\n/**\n * A row saved against a block that has since left the config has no renderer.\n * It is dropped before anything is counted, so its neighbours see each other,\n * not a gap: the block after it gets the real `prevType`, a run of one type is\n * not broken by it, and the block before it is still `isLast` when it ends the\n * page.\n */\nfunction renderable(\n blocks: BlockLike[],\n registry: Record<string, LooseRenderer | undefined>,\n): { block: BlockLike; Renderer: LooseRenderer }[] {\n return blocks.flatMap((block) => {\n const Renderer = registry[block.blockType];\n return Renderer ? [{ block, Renderer }] : [];\n });\n}\n\n/** Position of each block within its run of consecutive same-type blocks. */\nfunction runIndexes(blocks: BlockLike[]): number[] {\n const out: number[] = [];\n for (let i = 0; i < blocks.length; i += 1) {\n out.push(\n i > 0 && blocks[i - 1].blockType === blocks[i].blockType\n ? out[i - 1] + 1\n : 0,\n );\n }\n return out;\n}\n\nexport interface RenderBlocksProps<B extends BlockLike> {\n /** Pass `[...page.hero, ...page.layout]`, so the hero counts as index 0. */\n blocks: B[];\n registry: BlockRegistryFor<B>;\n /** The site's page measure. Defaults to `DEFAULT_CONTAINER`. */\n containerClassName?: string;\n /** Defaults to a plain `<img>`; a Next site passes a `next/image` adapter. */\n imageComponent?: BlockImageComponent;\n /** Defaults to a plain `<a>`; a Next site passes a `next/link` adapter. */\n linkComponent?: BlockLinkComponent;\n}\n\n/**\n * Renders a page's blocks in order through the registry. A Server Component:\n * it only maps and looks up, and each renderer decides its own nature.\n */\nexport function RenderBlocks<B extends BlockLike>({\n blocks,\n registry,\n containerClassName = DEFAULT_CONTAINER,\n imageComponent = DefaultBlockImage,\n linkComponent = DefaultBlockLink,\n}: RenderBlocksProps<B>): ReactElement {\n const rows = renderable(\n blocks,\n // The mapped registry type is per-block, and the dispatch is not; the\n // lookup below is what guarantees each renderer only ever sees its own\n // block type, and no signature can express that to the compiler.\n registry as unknown as Record<string, LooseRenderer | undefined>,\n );\n const runs = runIndexes(rows.map((row) => row.block));\n return (\n <>\n {rows.map(({ block, Renderer }, index) => (\n <Renderer\n key={block.id ?? index}\n block={block}\n index={index}\n prevType={index > 0 ? rows[index - 1].block.blockType : undefined}\n runIndex={runs[index]}\n isLast={index === rows.length - 1}\n containerClassName={containerClassName}\n imageComponent={imageComponent}\n linkComponent={linkComponent}\n />\n ))}\n </>\n );\n}\n","/**\n * The upload side of the boundary.\n *\n * A Payload upload field holds either the row's id or, once depth resolves it,\n * the whole document. Neither shape can be imported from here: `Media` is\n * generated per site, and this package must never reach for a site's\n * `payload-types`. So the doc is described structurally, and every renderer\n * goes through `resolveMedia` rather than reading `.url` itself.\n */\n\n/**\n * The subset of a Payload upload document a block renderer actually reads.\n * Every site's generated `Media` interface is assignable to this, whatever\n * else it carries.\n *\n * Deliberately no index signature: TypeScript refuses to assign an interface\n * to a type with one, and a site's generated `Media` is always an interface.\n * An index signature here would break exactly the structural match this type\n * exists to provide.\n */\nexport interface MediaDoc {\n url?: string | null;\n alt?: string | null;\n width?: number | null;\n height?: number | null;\n}\n\n/** What an upload field holds before and after `depth` populates it. */\nexport type MediaValue = number | string | MediaDoc | null | undefined;\n\n/** A resolved image, in the shape every `@bison-lab/ui` block asks for. */\nexport interface ResolvedMedia {\n src: string;\n alt: string;\n width?: number;\n height?: number;\n}\n\nfunction isMediaDoc(value: MediaValue): value is MediaDoc {\n return typeof value === \"object\" && value !== null;\n}\n\n/**\n * Narrows an upload value to something renderable, or `undefined`.\n *\n * `undefined` covers three cases a renderer must treat identically: the field\n * is empty, `depth: 0` left it as a bare id, or the document exists but has no\n * `url` yet (an upload mid-flight). A renderer that gets `undefined` omits the\n * image rather than emitting a broken `<img>`.\n *\n * `alt` is always a string: the media collection requires it, but a draft saved\n * before that validation ran can still reach a renderer, and an `alt` of\n * `undefined` would silently drop the attribute entirely.\n */\nexport function resolveMedia(value: MediaValue): ResolvedMedia | undefined {\n if (!isMediaDoc(value)) return undefined;\n const { url, alt, width, height } = value;\n if (typeof url !== \"string\" || url.length === 0) return undefined;\n return {\n src: url,\n alt: typeof alt === \"string\" ? alt : \"\",\n ...(typeof width === \"number\" ? { width } : {}),\n ...(typeof height === \"number\" ? { height } : {}),\n };\n}\n","import { Button } from \"@bison-lab/ui\";\n\nimport { cx } from \"../../cx\";\nimport { newTabAttributes } from \"../../link\";\nimport { resolveMedia } from \"../../media\";\nimport type { BlockRendererProps } from \"../../render-blocks\";\nimport type { HeroBlockData } from \"../../types\";\n\n/**\n * How each tone paints. Semantic tokens only — a site's brand reaches these\n * through its theme, never through a class named here.\n */\nconst TONES = {\n sweep: \"bg-primary text-primary-foreground\",\n dark: \"bg-foreground text-background\",\n light: \"bg-background text-foreground\",\n} as const;\n\n/**\n * The package's hero: deliberately plain.\n *\n * A hero is where a site's brand is loudest, so this exists to make a page\n * render at all, not to be the final answer. A site overrides this one registry\n * entry with its own and keeps every other block.\n */\nexport function HeroBlockRenderer({\n block,\n index,\n containerClassName,\n imageComponent: Image,\n linkComponent: Link,\n}: BlockRendererProps<HeroBlockData>) {\n const image = resolveMedia(block.image);\n const links = (block.links ?? []).filter((link) => link.href && link.label);\n const tone = TONES[block.tone ?? \"sweep\"];\n\n return (\n <section className={cx(\"relative isolate overflow-hidden\", tone)}>\n {image ? (\n <div className=\"absolute inset-0 -z-10 opacity-25\">\n <Image\n src={image.src}\n alt=\"\"\n width={image.width}\n height={image.height}\n className=\"h-full w-full object-cover\"\n sizes=\"100vw\"\n // The hero is the page's LCP element whenever it opens the page.\n priority={index === 0}\n />\n </div>\n ) : null}\n <div className={cx(containerClassName, \"py-20 lg:py-28\")}>\n <div className=\"max-w-3xl\">\n {block.eyebrow ? (\n <p className=\"text-sm font-semibold tracking-widest uppercase opacity-80\">\n {block.eyebrow}\n </p>\n ) : null}\n <h1 className=\"mt-3 text-4xl font-bold tracking-tight text-balance lg:text-5xl\">\n {block.heading}\n </h1>\n {block.body ? (\n <p className=\"mt-6 max-w-2xl text-lg leading-relaxed opacity-90\">\n {block.body}\n </p>\n ) : null}\n {links.length > 0 ? (\n <div className=\"mt-8 flex flex-wrap gap-3\">\n {links.map((link, i) => (\n <Button\n key={`${link.href}-${i}`}\n asChild\n variant={i === 0 ? \"default\" : \"outline\"}\n >\n <Link\n href={link.href as string}\n newTab={link.newTab ?? false}\n {...newTabAttributes(link.newTab)}\n >\n {link.label}\n </Link>\n </Button>\n ))}\n </div>\n ) : null}\n </div>\n </div>\n </section>\n );\n}\n","import { ShowcasePanelsBlock, type ShowcasePanelItem } from \"@bison-lab/ui\";\n\nimport { cx } from \"../../cx\";\nimport { renderLinkWith } from \"../../link\";\nimport { resolveMedia, type ResolvedMedia } from \"../../media\";\nimport type { BlockRendererProps } from \"../../render-blocks\";\nimport type { ShowcasePanelsBlockData } from \"../../types\";\n\nexport function ShowcasePanelsBlockRenderer({\n block,\n containerClassName,\n imageComponent: Image,\n linkComponent,\n}: BlockRendererProps<ShowcasePanelsBlockData>) {\n // A panel without a picture has nothing to expand into, so a row whose\n // upload has not resolved is dropped rather than rendered empty. `dims`\n // stays index-aligned with `items` so the image callback can reach the\n // width and height the library's own prop shape has no room for.\n const dims: ResolvedMedia[] = [];\n const items: ShowcasePanelItem[] = [];\n for (const [i, row] of (block.items ?? []).entries()) {\n const image = resolveMedia(row.image);\n if (!image) continue;\n dims.push(image);\n items.push({\n id: row.id ?? String(i),\n title: row.title ?? \"\",\n summary: row.summary ?? \"\",\n image: { src: image.src, alt: image.alt },\n ...(row.href ? { href: row.href } : {}),\n ...(row.numeral ? { numeral: row.numeral } : {}),\n });\n }\n if (items.length === 0) return null;\n\n return (\n <section className={cx(containerClassName, \"py-16 lg:py-24\")}>\n <ShowcasePanelsBlock\n items={items}\n spineVariant={block.spineVariant ?? \"numbered\"}\n defaultActiveIndex={Math.min(\n Math.max(block.defaultActiveIndex ?? 0, 0),\n items.length - 1,\n )}\n {...(block.watermark ? { watermark: block.watermark } : {})}\n renderLink={renderLinkWith(linkComponent)}\n renderImage={(item, i) => (\n <Image\n src={item.image.src}\n alt={item.image.alt ?? \"\"}\n width={dims[i]?.width}\n height={dims[i]?.height}\n className=\"absolute inset-0 h-full w-full object-cover\"\n sizes=\"(min-width: 1024px) 50vw, 100vw\"\n />\n )}\n />\n </section>\n );\n}\n","import { ProcessStepsBlock, type ProcessStepItem } from \"@bison-lab/ui\";\n\nimport { cx } from \"../../cx\";\nimport { resolveMedia, type ResolvedMedia } from \"../../media\";\nimport type { BlockRendererProps } from \"../../render-blocks\";\nimport type { ProcessStepsBlockData } from \"../../types\";\n\nexport function ProcessStepsBlockRenderer({\n block,\n containerClassName,\n imageComponent: Image,\n}: BlockRendererProps<ProcessStepsBlockData>) {\n // Same rule as the showcase panels: a step is its picture, so an unresolved\n // upload drops the row instead of rendering a hole in the rail.\n const dims: ResolvedMedia[] = [];\n const items: ProcessStepItem[] = [];\n for (const [i, row] of (block.items ?? []).entries()) {\n const image = resolveMedia(row.image);\n if (!image) continue;\n dims.push(image);\n items.push({\n id: row.id ?? String(i),\n title: row.title ?? \"\",\n description: row.description ?? \"\",\n image: { src: image.src, alt: image.alt },\n });\n }\n if (items.length === 0) return null;\n\n return (\n <section className={cx(containerClassName, \"py-16 lg:py-24\")}>\n <ProcessStepsBlock\n items={items}\n autoAdvance={block.autoAdvance ?? true}\n autoAdvanceDuration={block.autoAdvanceDuration ?? 6000}\n pauseOnHover={block.pauseOnHover ?? true}\n defaultActiveIndex={Math.min(\n Math.max(block.defaultActiveIndex ?? 0, 0),\n items.length - 1,\n )}\n renderImage={(item, i) => (\n <Image\n src={item.image.src}\n alt={item.image.alt ?? \"\"}\n width={dims[i]?.width}\n height={dims[i]?.height}\n className=\"size-full object-cover\"\n sizes=\"(min-width: 768px) 66vw, 100vw\"\n />\n )}\n />\n </section>\n );\n}\n","import { FAQColumnsBlock, type FAQItem } from \"@bison-lab/ui\";\n\nimport { cx } from \"../../cx\";\nimport { renderLinkWith } from \"../../link\";\nimport type { BlockRendererProps } from \"../../render-blocks\";\nimport type { FaqColumnsBlockData } from \"../../types\";\n\nexport function FaqColumnsBlockRenderer({\n block,\n containerClassName,\n linkComponent,\n}: BlockRendererProps<FaqColumnsBlockData>) {\n const items: FAQItem[] = (block.items ?? [])\n .filter((row) => row.question && row.answer)\n .map((row, i) => ({\n id: row.id ?? String(i),\n question: row.question as string,\n // The field is a textarea, so blank lines are the editor's paragraph\n // breaks and have to survive into the DOM.\n answer: <span className=\"whitespace-pre-line\">{row.answer}</span>,\n }));\n if (items.length === 0) return null;\n\n const cta = block.cta;\n const hasCta = Boolean(cta?.href && cta?.linkText);\n\n return (\n <section>\n <div className={cx(containerClassName, \"py-16 lg:py-24\")}>\n <FAQColumnsBlock\n // The site measure is on the wrapper above; the block's own\n // container and vertical rhythm are reset so they cannot fight it.\n className=\"py-0 md:py-0\"\n containerClassName=\"max-w-none px-0 sm:px-0\"\n items={items}\n title={block.title ?? \"\"}\n {...(block.eyebrow ? { eyebrow: block.eyebrow } : {})}\n {...(block.description ? { description: block.description } : {})}\n sticky={block.sticky ?? true}\n type={block.type ?? \"single\"}\n collapsible={block.collapsible ?? true}\n renderLink={renderLinkWith(linkComponent)}\n {...(hasCta && cta\n ? {\n cta: {\n title: cta.title ?? \"\",\n linkText: cta.linkText as string,\n href: cta.href as string,\n newTab: cta.newTab ?? false,\n },\n }\n : {})}\n />\n </div>\n </section>\n );\n}\n","import { TestimonialMasonry, type TestimonialItem } from \"@bison-lab/ui\";\n\nimport { cx } from \"../../cx\";\nimport { renderLinkWith } from \"../../link\";\nimport { resolveMedia } from \"../../media\";\nimport type { BlockRendererProps } from \"../../render-blocks\";\nimport type { TestimonialMasonryBlockData } from \"../../types\";\n\nexport function TestimonialMasonryBlockRenderer({\n block,\n containerClassName,\n linkComponent,\n}: BlockRendererProps<TestimonialMasonryBlockData>) {\n const items: TestimonialItem[] = (block.items ?? [])\n .filter((row) => row.content && row.author?.name)\n .map((row, i) => {\n const avatar = resolveMedia(row.author?.avatar);\n return {\n id: row.id ?? String(i),\n content: row.content as string,\n author: {\n name: row.author?.name as string,\n ...(row.author?.title ? { title: row.author.title } : {}),\n // The library falls back to initials when this is absent, which is\n // why an unresolved upload must not become an empty string.\n ...(avatar ? { avatarUrl: avatar.src } : {}),\n },\n };\n });\n if (items.length === 0) return null;\n\n const link = block.link;\n const hasLink = Boolean(link?.href && link?.label);\n\n return (\n // The band's surface is full-bleed; only its contents sit at the measure.\n <section className=\"bg-accent\">\n <div className={cx(containerClassName, \"py-16 lg:py-24\")}>\n <TestimonialMasonry\n className=\"bg-transparent px-0 lg:px-0\"\n containerClassName=\"max-w-none px-0 py-0 sm:py-0 md:px-0 md:py-0\"\n items={items}\n title={block.title ?? \"\"}\n renderLink={renderLinkWith(linkComponent)}\n {...(block.eyebrow ? { eyebrow: block.eyebrow } : {})}\n {...(block.description ? { description: block.description } : {})}\n {...(typeof block.minItemsForFade === \"number\"\n ? { minItemsForFade: block.minItemsForFade }\n : {})}\n {...(typeof block.maxVisibleRows === \"number\"\n ? { maxVisibleRows: block.maxVisibleRows }\n : {})}\n {...(hasLink && link\n ? {\n link: {\n label: link.label as string,\n href: link.href as string,\n newTab: link.newTab ?? false,\n },\n }\n : {})}\n />\n </div>\n </section>\n );\n}\n","import {\n JsonLd,\n NapBlock,\n type NapDepartment,\n type NapRecord,\n} from \"@bison-lab/ui\";\n\nimport { cx } from \"../../cx\";\nimport { renderLinkWith } from \"../../link\";\nimport type { BlockRendererProps } from \"../../render-blocks\";\nimport type { NapBlockData } from \"../../types\";\n\nexport function NapBlockRenderer({\n block,\n containerClassName,\n linkComponent,\n}: BlockRendererProps<NapBlockData>) {\n const address = block.address;\n const departments: NapDepartment[] = (block.departments ?? [])\n // `phoneE164` is what becomes the `tel:` href and the structured data's\n // `telephone`, so a department without one is not publishable as a NAP\n // entry at all — dropping it beats emitting an unreachable number.\n .filter((row) => row.name && row.phoneE164)\n .map((row, i) => ({\n id: row.id ?? String(i),\n name: row.name as string,\n ...(row.departmentType ? { type: row.departmentType } : {}),\n phone: {\n e164: row.phoneE164 as string,\n ...(row.phoneDisplay ? { display: row.phoneDisplay } : {}),\n },\n }));\n\n if (!block.businessName || !address?.streetAddress || departments.length === 0)\n return null;\n\n const record: NapRecord = {\n name: block.businessName,\n type: block.businessType ?? \"LocalBusiness\",\n address: {\n streetAddress: address.streetAddress,\n addressLocality: address.addressLocality ?? \"\",\n addressRegion: address.addressRegion ?? \"\",\n postalCode: address.postalCode ?? \"\",\n ...(address.addressCountry\n ? { addressCountry: address.addressCountry }\n : {}),\n },\n departments,\n ...(block.url ? { url: block.url } : {}),\n };\n\n return (\n <section>\n <div className={cx(containerClassName, \"py-16 lg:py-24\")}>\n <NapBlock\n record={record}\n showName={block.showName ?? true}\n headingLevel={block.headingLevel ?? \"h2\"}\n renderLink={renderLinkWith(linkComponent)}\n />\n {block.emitJsonLd === false ? null : <JsonLd data={record} />}\n </div>\n </section>\n );\n}\n","/**\n * The one rule for a typed panel width, shared by the config's validator and\n * the renderer's reader so the two cannot drift: if the validator accepted a\n * value the renderer dropped, the editor would be back to a width that\n * silently does nothing. React-free, because `config.ts` ships from the Node\n * entry.\n */\nconst REM_WIDTH = /^\\s*(\\d+(?:\\.\\d+)?)\\s*(rem)?\\s*$/;\n\n/** \"30\" and \"30rem\" both mean 30rem; anything else is not a width. */\nexport function remWidth(\n value: string | null | undefined,\n): `${number}rem` | null {\n const match = REM_WIDTH.exec(value ?? \"\");\n return match ? (`${Number(match[1])}rem` as `${number}rem`) : null;\n}\n","import {\n MegaMenuPanel,\n type MegaMenuColumn,\n type MegaMenuIcons,\n type MegaMenuLink,\n type MegaMenuPanelData,\n type MegaMenuSection,\n type MegaMenuVariants,\n type MegaMenuWidth,\n} from \"@bison-lab/ui\";\n\nimport { renderLinkWith } from \"../../link\";\nimport type { BlockRendererProps } from \"../../render-blocks\";\nimport type { MegaMenuBlockData, MegaMenuLinkData } from \"../../types\";\nimport { remWidth } from \"./rem-width\";\n\nfunction completeLink(row: MegaMenuLinkData): MegaMenuLink | null {\n if (!row.label || !row.href) return null;\n return {\n label: row.label,\n href: row.href,\n ...(row.description ? { description: row.description } : {}),\n ...(row.variant ? { variant: row.variant } : {}),\n ...(row.icon ? { icon: row.icon } : {}),\n ...(row.newTab ? { newTab: true } : {}),\n };\n}\n\n/**\n * The row as `MegaMenuPanel` data, or `null` when there is nothing to open:\n * no columns, or columns whose links are not yet complete. Draft saves skip\n * validation, so a live preview genuinely hands this half-built rows.\n */\nexport function megaMenuPanelFromRow(\n row: MegaMenuBlockData,\n): MegaMenuPanelData | null {\n const panel = row.panel;\n if (!panel?.columns?.length) return null;\n const custom = Boolean(panel.customWidths);\n\n const columns: MegaMenuColumn[] = [];\n for (const column of panel.columns) {\n const sections: MegaMenuSection[] = [];\n for (const section of column.sections ?? []) {\n const links = (section.links ?? [])\n .map(completeLink)\n .filter((link): link is MegaMenuLink => link !== null);\n if (!links.length) continue;\n sections.push({\n ...(section.eyebrow ? { eyebrow: section.eyebrow } : {}),\n display: section.display ?? \"list\",\n hideDescriptionsOnMobile: section.hideDescriptionsOnMobile ?? true,\n links,\n });\n }\n columns.push({\n ...(custom && column.customWidth\n ? { customWidth: column.customWidth }\n : { width: Number(column.width ?? \"100\") as MegaMenuWidth }),\n ...(column.divider ? { divider: true } : {}),\n sections,\n });\n }\n if (!columns.some((column) => column.sections.length)) return null;\n\n const overview = panel.footer?.overview;\n const cta = panel.footer?.cta;\n // Independent of the column checkbox: the config gates only `customWidth`\n // on it, and the help text promises a typed panel width is used.\n const customMax = remWidth(panel.customMaxWidth);\n\n return {\n maxWidth: customMax ?? panel.maxWidth ?? \"standard\",\n columns,\n footer: {\n ...(overview?.label && overview.href\n ? {\n overview: {\n label: overview.label,\n href: overview.href,\n ...(overview.newTab ? { newTab: true } : {}),\n },\n }\n : {}),\n ...(cta?.label && cta.href\n ? {\n cta: {\n label: cta.label,\n href: cta.href,\n ...(cta.newTab ? { newTab: true } : {}),\n },\n }\n : {}),\n },\n };\n}\n\nexport interface MegaMenuBlockRendererProps\n extends BlockRendererProps<MegaMenuBlockData> {\n /** The look behind each `variants` value the site passed to `megaMenuBlock`. */\n variants?: MegaMenuVariants;\n /** The glyph behind each `icons` value the site passed to `megaMenuBlock`. */\n icons?: MegaMenuIcons;\n}\n\n/**\n * One panel, standing alone: what a live preview shows while the row is being\n * edited. A whole header goes through `headerItemsFromBlocks` instead.\n */\nexport function MegaMenuBlockRenderer({\n block,\n linkComponent,\n variants,\n icons,\n}: MegaMenuBlockRendererProps) {\n const panel = megaMenuPanelFromRow(block);\n if (!panel) return null;\n return (\n <MegaMenuPanel\n {...panel}\n variants={variants}\n icons={icons}\n renderLink={renderLinkWith(linkComponent)}\n />\n );\n}\n","import {\n megaMenuToFloatingNavItems,\n type FloatingNavItem,\n type MegaMenuIcons,\n type MegaMenuItem,\n type MegaMenuVariants,\n} from \"@bison-lab/ui\";\n\nimport { renderLinkWith, type BlockLinkComponent } from \"../../link\";\nimport type { MegaMenuBlockData, NavLinkBlockData } from \"../../types\";\nimport { megaMenuPanelFromRow } from \"./component\";\n\n/** A row of a header global's `items`: either block, or whatever else a site added. */\nexport type HeaderBlockRow = MegaMenuBlockData | NavLinkBlockData;\n\nexport interface HeaderItemsOptions {\n variants?: MegaMenuVariants;\n icons?: MegaMenuIcons;\n /** Marks the current section; receives each item's `href`. */\n isActive?: (href: string) => boolean;\n /** The site's link adapter, applied to every link inside the panels. */\n linkComponent?: BlockLinkComponent;\n}\n\n/**\n * A global's `items` as `FloatingNavBlock` items, so a site's header is one\n * call. Rows the bar cannot show are dropped rather than rendered broken: a\n * row with no label, a mega menu with nothing to open, and any block type a\n * site added that this package does not know.\n *\n * A `navLink` row's `newTab` is not carried: `FloatingNavItem` has no such\n * field, because the bar renders its own links.\n */\nexport function headerItemsFromBlocks(\n blocks: HeaderBlockRow[],\n { variants, icons, isActive, linkComponent }: HeaderItemsOptions = {},\n): FloatingNavItem[] {\n const items: MegaMenuItem[] = [];\n for (const row of blocks) {\n if (!row.label) continue;\n if (row.blockType === \"navLink\") {\n if (!row.href) continue;\n items.push({ label: row.label, href: row.href });\n } else if (row.blockType === \"megaMenu\") {\n const panel = megaMenuPanelFromRow(row);\n if (!panel) continue;\n items.push({\n label: row.label,\n ...(row.href ? { href: row.href } : {}),\n panel,\n });\n }\n }\n return megaMenuToFloatingNavItems(\n { items },\n {\n isActive,\n variants,\n icons,\n ...(linkComponent ? { renderLink: renderLinkWith(linkComponent) } : {}),\n },\n );\n}\n"],"mappings":"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"}
|
package/dist/rich-text.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
2
|
+
import { f as BlockRendererProps, s as RichTextBlockData } from "./types-CJAvoZMk.mjs";
|
|
3
3
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
4
4
|
|
|
5
5
|
//#region src/blocks/rich-text/component.d.ts
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
3
|
+
import { RenderLink } from "@bison-lab/ui";
|
|
4
|
+
import { AnchorHTMLAttributes, ComponentType, ReactElement, ReactNode } from "react";
|
|
4
5
|
//#region src/image.d.ts
|
|
5
6
|
/**
|
|
6
7
|
* The image injection point.
|
|
@@ -45,6 +46,52 @@ declare function DefaultBlockImage({
|
|
|
45
46
|
priority
|
|
46
47
|
}: BlockImageProps): react_jsx_runtime0.JSX.Element;
|
|
47
48
|
//#endregion
|
|
49
|
+
//#region src/link.d.ts
|
|
50
|
+
/**
|
|
51
|
+
* The link injection point, the same shape as `BlockImageComponent`.
|
|
52
|
+
*
|
|
53
|
+
* A renderer never writes `<a>` directly. A site hands in one link component
|
|
54
|
+
* and every CMS link routes through it — Next's `Link`, so navigation stays
|
|
55
|
+
* client-side. It is a *component type*, not a render function, for the same
|
|
56
|
+
* reason the image seam is: a Server Component can pass a client component
|
|
57
|
+
* reference across the boundary, but not a closure.
|
|
58
|
+
*
|
|
59
|
+
* `newTab` is the flag from `linkFields()`; `target` and `rel` are always
|
|
60
|
+
* already expanded from it by the time the component is called, so an adapter
|
|
61
|
+
* that only spreads the anchor attributes onto its router link is still safe.
|
|
62
|
+
* The one thing an adapter must do is drop `newTab` before spreading, or React
|
|
63
|
+
* warns about an unknown DOM attribute — see the README's `next/link` adapter.
|
|
64
|
+
*/
|
|
65
|
+
interface BlockLinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
66
|
+
href: string;
|
|
67
|
+
children: ReactNode;
|
|
68
|
+
newTab?: boolean;
|
|
69
|
+
className?: string;
|
|
70
|
+
}
|
|
71
|
+
type BlockLinkComponent = ComponentType<BlockLinkProps>;
|
|
72
|
+
/** `target` and `rel` together, or neither: a bare `target` is a tabnabbing hole. */
|
|
73
|
+
declare function newTabAttributes(newTab: boolean | null | undefined): Pick<AnchorHTMLAttributes<HTMLAnchorElement>, "target" | "rel">;
|
|
74
|
+
/**
|
|
75
|
+
* The fallback when no `linkComponent` is supplied: a plain `<a>`. Correct
|
|
76
|
+
* everywhere and client-side nowhere, which is the right default for a package
|
|
77
|
+
* that cannot know what router it landed in.
|
|
78
|
+
*/
|
|
79
|
+
declare function DefaultBlockLink({
|
|
80
|
+
href,
|
|
81
|
+
newTab,
|
|
82
|
+
children,
|
|
83
|
+
...rest
|
|
84
|
+
}: BlockLinkProps): react_jsx_runtime0.JSX.Element;
|
|
85
|
+
declare namespace DefaultBlockLink {
|
|
86
|
+
var displayName: string;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Adapts the seam to the `renderLink` prop every `@bison-lab/ui` block takes.
|
|
90
|
+
* The ui blocks hand over `target`/`rel` already expanded, so `newTab` is
|
|
91
|
+
* read back off `target` to keep the flag and the attributes in step.
|
|
92
|
+
*/
|
|
93
|
+
declare function renderLinkWith(Link: BlockLinkComponent): RenderLink;
|
|
94
|
+
//#endregion
|
|
48
95
|
//#region src/render-blocks.d.ts
|
|
49
96
|
/** The minimum a row must be for the dispatch to place it. */
|
|
50
97
|
interface BlockLike {
|
|
@@ -59,9 +106,10 @@ interface BlockLike {
|
|
|
59
106
|
* back-to-back blocks of one type, `isLast` because the final block sits
|
|
60
107
|
* against the site footer.
|
|
61
108
|
*
|
|
62
|
-
* `containerClassName` and `
|
|
63
|
-
* cannot decide for itself — the site's page measure,
|
|
64
|
-
*
|
|
109
|
+
* `containerClassName`, `imageComponent` and `linkComponent` are the three
|
|
110
|
+
* things a package block cannot decide for itself — the site's page measure,
|
|
111
|
+
* how an image gets optimised, and which router a link goes through. All three
|
|
112
|
+
* arrive already defaulted, so a renderer never checks them.
|
|
65
113
|
*/
|
|
66
114
|
interface BlockRendererProps<B extends BlockLike = BlockLike> {
|
|
67
115
|
block: B;
|
|
@@ -76,6 +124,8 @@ interface BlockRendererProps<B extends BlockLike = BlockLike> {
|
|
|
76
124
|
containerClassName: string;
|
|
77
125
|
/** How this block turns a resolved image into an element. */
|
|
78
126
|
imageComponent: BlockImageComponent;
|
|
127
|
+
/** How this block turns an `href` into an element. */
|
|
128
|
+
linkComponent: BlockLinkComponent;
|
|
79
129
|
}
|
|
80
130
|
/**
|
|
81
131
|
* One renderer per block type, each typed to its own block.
|
|
@@ -99,6 +149,8 @@ interface RenderBlocksProps<B extends BlockLike> {
|
|
|
99
149
|
containerClassName?: string;
|
|
100
150
|
/** Defaults to a plain `<img>`; a Next site passes a `next/image` adapter. */
|
|
101
151
|
imageComponent?: BlockImageComponent;
|
|
152
|
+
/** Defaults to a plain `<a>`; a Next site passes a `next/link` adapter. */
|
|
153
|
+
linkComponent?: BlockLinkComponent;
|
|
102
154
|
}
|
|
103
155
|
/**
|
|
104
156
|
* Renders a page's blocks in order through the registry. A Server Component:
|
|
@@ -108,7 +160,8 @@ declare function RenderBlocks<B extends BlockLike>({
|
|
|
108
160
|
blocks,
|
|
109
161
|
registry,
|
|
110
162
|
containerClassName,
|
|
111
|
-
imageComponent
|
|
163
|
+
imageComponent,
|
|
164
|
+
linkComponent
|
|
112
165
|
}: RenderBlocksProps<B>): ReactElement;
|
|
113
166
|
//#endregion
|
|
114
167
|
//#region src/fields/link.d.ts
|
|
@@ -291,6 +344,43 @@ interface NapBlockData extends BlockRow<"nap"> {
|
|
|
291
344
|
headingLevel?: ("h2" | "h3" | "h4") | null;
|
|
292
345
|
emitJsonLd?: boolean | null;
|
|
293
346
|
}
|
|
347
|
+
interface MegaMenuLinkData extends LinkValue {
|
|
348
|
+
description?: string | null;
|
|
349
|
+
/** A value from the `variants` the site passed to `megaMenuBlock`. */
|
|
350
|
+
variant?: string | null;
|
|
351
|
+
/** A value from the `icons` the site passed to `megaMenuBlock`. */
|
|
352
|
+
icon?: string | null;
|
|
353
|
+
id?: string | null;
|
|
354
|
+
}
|
|
355
|
+
interface MegaMenuSectionData {
|
|
356
|
+
eyebrow?: string | null;
|
|
357
|
+
display?: ("featured" | "list") | null;
|
|
358
|
+
hideDescriptionsOnMobile?: boolean | null;
|
|
359
|
+
links?: MegaMenuLinkData[] | null;
|
|
360
|
+
id?: string | null;
|
|
361
|
+
}
|
|
362
|
+
interface MegaMenuColumnData {
|
|
363
|
+
width?: ("25" | "33" | "50" | "66" | "75" | "100") | null;
|
|
364
|
+
customWidth?: string | null;
|
|
365
|
+
divider?: boolean | null;
|
|
366
|
+
sections?: MegaMenuSectionData[] | null;
|
|
367
|
+
id?: string | null;
|
|
368
|
+
}
|
|
369
|
+
interface MegaMenuBlockData extends BlockRow<"megaMenu"> {
|
|
370
|
+
label?: string | null;
|
|
371
|
+
href?: string | null;
|
|
372
|
+
panel?: {
|
|
373
|
+
maxWidth?: ("narrow" | "standard" | "wide") | null;
|
|
374
|
+
columns?: MegaMenuColumnData[] | null;
|
|
375
|
+
footer?: {
|
|
376
|
+
overview?: LinkValue;
|
|
377
|
+
cta?: LinkValue;
|
|
378
|
+
};
|
|
379
|
+
customWidths?: boolean | null; /** In rem: "30" or "30rem". */
|
|
380
|
+
customMaxWidth?: string | null;
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
interface NavLinkBlockData extends BlockRow<"navLink">, LinkValue {}
|
|
294
384
|
//#endregion
|
|
295
|
-
export {
|
|
296
|
-
//# sourceMappingURL=types-
|
|
385
|
+
export { DefaultBlockImage as C, BlockImageProps as S, BlockLinkProps as _, NavLinkBlockData as a, renderLinkWith as b, ShowcasePanelsBlockData as c, BlockRegistryFor as d, BlockRendererProps as f, BlockLinkComponent as g, RenderBlocksProps as h, NapBlockData as i, TestimonialMasonryBlockData as l, RenderBlocks as m, HeroBlockData as n, ProcessStepsBlockData as o, DEFAULT_CONTAINER as p, MegaMenuBlockData as r, RichTextBlockData as s, FaqColumnsBlockData as t, BlockLike as u, DefaultBlockLink as v, BlockImageComponent as x, newTabAttributes as y };
|
|
386
|
+
//# sourceMappingURL=types-CJAvoZMk.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-CJAvoZMk.d.mts","names":[],"sources":["../src/image.tsx","../src/link.tsx","../src/render-blocks.tsx","../src/fields/link.ts","../src/media.ts","../src/types.ts"],"mappings":"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"}
|