@bison-lab/payload-blocks 3.3.0 → 3.4.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/dist/react.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- import { C as BlockImageProps, S as BlockImageComponent, _ as BlockLinkComponent, a as NavLinkBlockData, b as newTabAttributes, c as ShowcasePanelsBlockData, d as BlockLike, f as BlockRegistryFor, g as RenderBlocksProps, h as RenderBlocks, i as NapBlockData, l as StatsBandBlockData, m as DEFAULT_CONTAINER, n as HeroBlockData, o as ProcessStepsBlockData, p as BlockRendererProps, r as MegaMenuBlockData, t as FaqColumnsBlockData, u as TestimonialMasonryBlockData, v as BlockLinkProps, w as DefaultBlockImage, x as renderLinkWith, y as DefaultBlockLink } from "./types-D9rg0BoW.mjs";
2
+ import { A as BlockImageProps, C as resolveLink, D as newTabAttributes, E as DefaultBlockLink, O as renderLinkWith, S as linkTypeOf, T as BlockLinkProps, _ as RenderBlocksProps, a as NavLinkBlockData, b as LinkValue, c as ShowcasePanelsBlockData, d as BLOCK_ID_ATTRIBUTE, f as BlockLike, g as RenderBlocks, h as DEFAULT_CONTAINER, i as NapBlockData, j as DefaultBlockImage, k as BlockImageComponent, l as StatsBandBlockData, m as BlockRendererProps, n as HeroBlockData, o as ProcessStepsBlockData, p as BlockRegistryFor, r as MegaMenuBlockData, t as FaqColumnsBlockData, u as TestimonialMasonryBlockData, v as LinkDestination, w as BlockLinkComponent, x as ResolveLink, y as LinkPageDoc } from "./types-ODMRyOpH.mjs";
3
3
  import * as react_jsx_runtime0 from "react/jsx-runtime";
4
4
  import { FloatingNavItem, MegaMenuIcons, MegaMenuPanelData, MegaMenuVariants } from "@bison-lab/ui";
5
5
 
@@ -54,7 +54,8 @@ declare function HeroBlockRenderer({
54
54
  overlapBelow,
55
55
  containerClassName,
56
56
  imageComponent: Image,
57
- linkComponent: Link
57
+ linkComponent: Link,
58
+ resolveLink: resolve
58
59
  }: BlockRendererProps<HeroBlockData>): react_jsx_runtime0.JSX.Element;
59
60
  //#endregion
60
61
  //#region src/blocks/showcase-panels/component.d.ts
@@ -82,7 +83,8 @@ declare function FaqColumnsBlockRenderer({
82
83
  overlapAbove,
83
84
  overlapBelow,
84
85
  containerClassName,
85
- linkComponent
86
+ linkComponent,
87
+ resolveLink: resolve
86
88
  }: BlockRendererProps<FaqColumnsBlockData>): react_jsx_runtime0.JSX.Element | null;
87
89
  //#endregion
88
90
  //#region src/blocks/testimonial-masonry/component.d.ts
@@ -91,7 +93,8 @@ declare function TestimonialMasonryBlockRenderer({
91
93
  overlapAbove,
92
94
  overlapBelow,
93
95
  containerClassName,
94
- linkComponent
96
+ linkComponent,
97
+ resolveLink: resolve
95
98
  }: BlockRendererProps<TestimonialMasonryBlockData>): react_jsx_runtime0.JSX.Element | null;
96
99
  //#endregion
97
100
  //#region src/blocks/nap/component.d.ts
@@ -119,8 +122,10 @@ declare function StatsBandBlockRenderer({
119
122
  * The row as `MegaMenuPanel` data, or `null` when there is nothing to open:
120
123
  * no columns, or columns whose links are not yet complete. Draft saves skip
121
124
  * validation, so a live preview genuinely hands this half-built rows.
125
+ * `resolve` turns each link's page into a path; the package's own is the
126
+ * default.
122
127
  */
123
- declare function megaMenuPanelFromRow(row: MegaMenuBlockData): MegaMenuPanelData | null;
128
+ declare function megaMenuPanelFromRow(row: MegaMenuBlockData, resolve?: ResolveLink): MegaMenuPanelData | null;
124
129
  interface MegaMenuBlockRendererProps extends BlockRendererProps<MegaMenuBlockData> {
125
130
  /** The look behind each `variants` value the site passed to `megaMenuBlock`. */
126
131
  variants?: MegaMenuVariants;
@@ -134,6 +139,7 @@ interface MegaMenuBlockRendererProps extends BlockRendererProps<MegaMenuBlockDat
134
139
  declare function MegaMenuBlockRenderer({
135
140
  block,
136
141
  linkComponent,
142
+ resolveLink: resolve,
137
143
  variants,
138
144
  icons
139
145
  }: MegaMenuBlockRendererProps): react_jsx_runtime0.JSX.Element | null;
@@ -148,6 +154,8 @@ interface HeaderItemsOptions {
148
154
  isActive?: (href: string) => boolean;
149
155
  /** The site's link adapter, applied to every link inside the panels. */
150
156
  linkComponent?: BlockLinkComponent;
157
+ /** The site's resolver for page links; defaults to the package's `resolveLink`. */
158
+ resolveLink?: ResolveLink;
151
159
  }
152
160
  /**
153
161
  * A global's `items` as `FloatingNavBlock` items, so a site's header is one
@@ -156,14 +164,17 @@ interface HeaderItemsOptions {
156
164
  * site added that this package does not know.
157
165
  *
158
166
  * A `navLink` row's `newTab` is not carried: `FloatingNavItem` has no such
159
- * field, because the bar renders its own links.
167
+ * field, because the bar renders its own links. A bar item whose page is
168
+ * missing or unpublished is dropped, like a panel link. A mega menu's own
169
+ * `href` (the trigger's landing page) is plain text, not a picked page.
160
170
  */
161
171
  declare function headerItemsFromBlocks(blocks: HeaderBlockRow[], {
162
172
  variants,
163
173
  icons,
164
174
  isActive,
165
- linkComponent
175
+ linkComponent,
176
+ resolveLink: resolve
166
177
  }?: HeaderItemsOptions): FloatingNavItem[];
167
178
  //#endregion
168
- export { type BlockImageComponent, type BlockImageProps, type BlockLike, type BlockLinkComponent, type BlockLinkProps, type BlockRegistryFor, type BlockRendererProps, DEFAULT_CONTAINER, DefaultBlockImage, DefaultBlockLink, FaqColumnsBlockRenderer, type HeaderBlockRow, type HeaderItemsOptions, HeroBlockRenderer, MegaMenuBlockRenderer, type MegaMenuBlockRendererProps, NapBlockRenderer, OVERLAP_ABOVE_CLEARANCE, OVERLAP_BELOW_CLEARANCE, ProcessStepsBlockRenderer, RenderBlocks, type RenderBlocksProps, SEAM_PULL_DOWN, SEAM_PULL_UP, ShowcasePanelsBlockRenderer, StatsBandBlockRenderer, TestimonialMasonryBlockRenderer, headerItemsFromBlocks, megaMenuPanelFromRow, newTabAttributes, overlapsSeam, renderLinkWith, seamClasses };
179
+ export { BLOCK_ID_ATTRIBUTE, type BlockImageComponent, type BlockImageProps, type BlockLike, type BlockLinkComponent, type BlockLinkProps, type BlockRegistryFor, type BlockRendererProps, DEFAULT_CONTAINER, DefaultBlockImage, DefaultBlockLink, FaqColumnsBlockRenderer, type HeaderBlockRow, type HeaderItemsOptions, HeroBlockRenderer, type LinkDestination, type LinkPageDoc, type LinkValue, MegaMenuBlockRenderer, type MegaMenuBlockRendererProps, NapBlockRenderer, OVERLAP_ABOVE_CLEARANCE, OVERLAP_BELOW_CLEARANCE, ProcessStepsBlockRenderer, RenderBlocks, type RenderBlocksProps, type ResolveLink, SEAM_PULL_DOWN, SEAM_PULL_UP, ShowcasePanelsBlockRenderer, StatsBandBlockRenderer, TestimonialMasonryBlockRenderer, headerItemsFromBlocks, linkTypeOf, megaMenuPanelFromRow, newTabAttributes, overlapsSeam, renderLinkWith, resolveLink, seamClasses };
169
180
  //# sourceMappingURL=react.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"react.d.mts","names":[],"sources":["../src/seam.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/stats-band/component.tsx","../src/blocks/mega-menu/component.tsx","../src/blocks/mega-menu/header.tsx"],"mappings":";;;;;;;;;;AAqBA;;;;;AAGA;;;;;AAGA;;cANa,YAAA;;cAGA,cAAA;AAMb;AAAA,cAHa,uBAAA;;cAGA,uBAAA;;AAOb;;;;iBAAgB,YAAA,CAAa,KAAA,EAAO,SAAA;AAQpC;AAAA,iBAAgB,WAAA,CAAA;EACd,YAAA;EACA;AAAA,GACC,IAAA,CAAK,kBAAA;;;;;;AA3BR;;;;iBCKgB,iBAAA,CAAA;EACd,KAAA;EACA,KAAA;EACA,YAAA;EACA,YAAA;EACA,kBAAA;EACA,cAAA,EAAgB,KAAA;EAChB,aAAA,EAAe;AAAA,GACd,kBAAA,CAAmB,aAAA,IAAc,kBAAA,CAAA,GAAA,CAAA,OAAA;;;iBCzBpB,2BAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,YAAA;EACA,kBAAA;EACA,cAAA,EAAgB,KAAA;EAChB;AAAA,GACC,kBAAA,CAAmB,uBAAA,IAAwB,kBAAA,CAAA,GAAA,CAAA,OAAA;;;iBCR9B,yBAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,YAAA;EACA,kBAAA;EACA,cAAA,EAAgB;AAAA,GACf,kBAAA,CAAmB,qBAAA,IAAsB,kBAAA,CAAA,GAAA,CAAA,OAAA;;;iBCN5B,uBAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,YAAA;EACA,kBAAA;EACA;AAAA,GACC,kBAAA,CAAmB,mBAAA,IAAoB,kBAAA,CAAA,GAAA,CAAA,OAAA;;;iBCL1B,+BAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,YAAA;EACA,kBAAA;EACA;AAAA,GACC,kBAAA,CAAmB,2BAAA,IAA4B,kBAAA,CAAA,GAAA,CAAA,OAAA;;;iBCFlC,gBAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,YAAA;EACA,kBAAA;EACA;AAAA,GACC,kBAAA,CAAmB,YAAA,IAAa,kBAAA,CAAA,GAAA,CAAA,OAAA;;;iBCDnB,sBAAA,CAAA;EACd,KAAA;EACA,KAAA;EACA,MAAA;EACA,YAAA;EACA,YAAA;EACA,kBAAA;EACA;AAAA,GACC,kBAAA,CAAmB,kBAAA,IAAmB,kBAAA,CAAA,GAAA,CAAA,OAAA;;;;;APLzC;;;iBQYgB,oBAAA,CACd,GAAA,EAAK,iBAAA,GACJ,iBAAA;AAAA,UA8Dc,0BAAA,SACP,kBAAA,CAAmB,iBAAA;ER1EhB;EQ4EX,QAAA,GAAW,gBAAA;;EAEX,KAAA,GAAQ,aAAA;AAAA;AR3EV;;;;AAAA,iBQkFgB,qBAAA,CAAA;EACd,KAAA;EACA,aAAA;EACA,QAAA;EACA;AAAA,GACC,0BAAA,GAA0B,kBAAA,CAAA,GAAA,CAAA,OAAA;;;;KCrGjB,cAAA,GAAiB,iBAAA,GAAoB,gBAAA;AAAA,UAEhC,kBAAA;EACf,QAAA,GAAW,gBAAA;EACX,KAAA,GAAQ,aAAA;ETIe;ESFvB,QAAA,IAAY,IAAA;ETKD;ESHX,aAAA,GAAgB,kBAAA;AAAA;;;ATMlB;;;;;AAGA;;iBSGgB,qBAAA,CACd,MAAA,EAAQ,cAAA;EACN,QAAA;EAAU,KAAA;EAAO,QAAA;EAAU;AAAA,IAAiB,kBAAA,GAC7C,eAAA"}
1
+ {"version":3,"file":"react.d.mts","names":[],"sources":["../src/seam.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/stats-band/component.tsx","../src/blocks/mega-menu/component.tsx","../src/blocks/mega-menu/header.tsx"],"mappings":";;;;;;;;;;AAqBA;;;;;AAGA;;;;;AAGA;;cANa,YAAA;;cAGA,cAAA;AAMb;AAAA,cAHa,uBAAA;;cAGA,uBAAA;;AAOb;;;;iBAAgB,YAAA,CAAa,KAAA,EAAO,SAAA;AAQpC;AAAA,iBAAgB,WAAA,CAAA;EACd,YAAA;EACA;AAAA,GACC,IAAA,CAAK,kBAAA;;;;;;AA3BR;;;;iBCKgB,iBAAA,CAAA;EACd,KAAA;EACA,KAAA;EACA,YAAA;EACA,YAAA;EACA,kBAAA;EACA,cAAA,EAAgB,KAAA;EAChB,aAAA,EAAe,IAAA;EACf,WAAA,EAAa;AAAA,GACZ,kBAAA,CAAmB,aAAA,IAAc,kBAAA,CAAA,GAAA,CAAA,OAAA;;;iBC1BpB,2BAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,YAAA;EACA,kBAAA;EACA,cAAA,EAAgB,KAAA;EAChB;AAAA,GACC,kBAAA,CAAmB,uBAAA,IAAwB,kBAAA,CAAA,GAAA,CAAA,OAAA;;;iBCR9B,yBAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,YAAA;EACA,kBAAA;EACA,cAAA,EAAgB;AAAA,GACf,kBAAA,CAAmB,qBAAA,IAAsB,kBAAA,CAAA,GAAA,CAAA,OAAA;;;iBCN5B,uBAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,YAAA;EACA,kBAAA;EACA,aAAA;EACA,WAAA,EAAa;AAAA,GACZ,kBAAA,CAAmB,mBAAA,IAAoB,kBAAA,CAAA,GAAA,CAAA,OAAA;;;iBCN1B,+BAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,YAAA;EACA,kBAAA;EACA,aAAA;EACA,WAAA,EAAa;AAAA,GACZ,kBAAA,CAAmB,2BAAA,IAA4B,kBAAA,CAAA,GAAA,CAAA,OAAA;;;iBCHlC,gBAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,YAAA;EACA,kBAAA;EACA;AAAA,GACC,kBAAA,CAAmB,YAAA,IAAa,kBAAA,CAAA,GAAA,CAAA,OAAA;;;iBCDnB,sBAAA,CAAA;EACd,KAAA;EACA,KAAA;EACA,MAAA;EACA,YAAA;EACA,YAAA;EACA,kBAAA;EACA;AAAA,GACC,kBAAA,CAAmB,kBAAA,IAAmB,kBAAA,CAAA,GAAA,CAAA,OAAA;;;;APLzC;;;;;AAGA;iBQqBgB,oBAAA,CACd,GAAA,EAAK,iBAAA,EACL,OAAA,GAAS,WAAA,GACR,iBAAA;AAAA,UA4Dc,0BAAA,SACP,kBAAA,CAAmB,iBAAA;ERrFF;EQuFzB,QAAA,GAAW,gBAAA;ERpFA;EQsFX,KAAA,GAAQ,aAAA;AAAA;;;ARnFV;;iBQ0FgB,qBAAA,CAAA;EACd,KAAA;EACA,aAAA;EACA,WAAA,EAAa,OAAA;EACb,QAAA;EACA;AAAA,GACC,0BAAA,GAA0B,kBAAA,CAAA,GAAA,CAAA,OAAA;;;;KChHjB,cAAA,GAAiB,iBAAA,GAAoB,gBAAA;AAAA,UAEhC,kBAAA;EACf,QAAA,GAAW,gBAAA;EACX,KAAA,GAAQ,aAAA;ETGe;ESDvB,QAAA,IAAY,IAAA;ETIa;ESFzB,aAAA,GAAgB,kBAAA;ETES;ESAzB,WAAA,GAAc,WAAA;AAAA;;;;;ATMhB;;;;;AAOA;;iBSCgB,qBAAA,CACd,MAAA,EAAQ,cAAA;EAEN,QAAA;EACA,KAAA;EACA,QAAA;EACA,aAAA;EACA,WAAA,EAAa;AAAA,IACZ,kBAAA,GACF,eAAA"}
package/dist/react.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  "use client";
2
- import { a as overlapsSeam, i as SEAM_PULL_UP, n as OVERLAP_BELOW_CLEARANCE, o as seamClasses, r as SEAM_PULL_DOWN, s as cx, t as OVERLAP_ABOVE_CLEARANCE } from "./seam-BDFZlV3F.mjs";
2
+ import { a as overlapsSeam, c as DefaultBlockLink, i as SEAM_PULL_UP, l as newTabAttributes, n as OVERLAP_BELOW_CLEARANCE, o as seamClasses, r as SEAM_PULL_DOWN, s as cx, t as OVERLAP_ABOVE_CLEARANCE, u as renderLinkWith } from "./seam-CmLb3BSo.mjs";
3
+ import { n as resolveLink, t as linkTypeOf } from "./link-CnwLtm47.mjs";
3
4
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
5
  import { Button, FAQColumnsBlock, JsonLd, MegaMenuPanel, NapBlock, ProcessStepsBlock, ShowcasePanelsBlock, StatsBandBlock, TestimonialMasonry, megaMenuToFloatingNavItems } from "@bison-lab/ui";
5
6
  //#region src/image.tsx
@@ -21,46 +22,18 @@ function DefaultBlockImage({ src, alt, width, height, className, sizes, priority
21
22
  });
22
23
  }
23
24
  //#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
60
25
  //#region src/render-blocks.tsx
61
26
  /** Fallback page measure for a site that does not pass its own. */
62
27
  const DEFAULT_CONTAINER = "mx-auto w-full max-w-7xl px-6";
63
28
  /**
29
+ * The attribute a block editor in the Payload admin (payload-better-editor)
30
+ * walks up to from a click in its preview iframe, to find which row was
31
+ * clicked. `RenderBlocks` puts it on a wrapper around every block, so a site
32
+ * adopting the editor has nothing to add per block; a site's tests can assert
33
+ * against the name here rather than retype it.
34
+ */
35
+ const BLOCK_ID_ATTRIBUTE = "data-better-editor-id";
36
+ /**
64
37
  * A row saved against a block that has since left the config has no renderer.
65
38
  * It is dropped before anything is counted, so its neighbours see each other,
66
39
  * not a gap: the block after it gets the real `prevType`, a run of one type is
@@ -85,22 +58,33 @@ function runIndexes(blocks) {
85
58
  /**
86
59
  * Renders a page's blocks in order through the registry. A Server Component:
87
60
  * it only maps and looks up, and each renderer decides its own nature.
61
+ *
62
+ * Each block sits inside an unstyled block-level `<div>` carrying
63
+ * `BLOCK_ID_ATTRIBUTE`, which is what a click-to-edit overlay resolves and
64
+ * what its hover outline paints on. A row with no `id` (a fixture, a row the
65
+ * form has not saved) gets no attribute: there is no form-state path for an
66
+ * editor to open. The band's own `<section>` and its full-bleed background
67
+ * are unchanged by the wrapper.
88
68
  */
89
- function RenderBlocks({ blocks, registry, containerClassName = DEFAULT_CONTAINER, imageComponent = DefaultBlockImage, linkComponent = DefaultBlockLink, floats = overlapsSeam }) {
69
+ function RenderBlocks({ blocks, registry, containerClassName = DEFAULT_CONTAINER, imageComponent = DefaultBlockImage, linkComponent = DefaultBlockLink, floats = overlapsSeam, resolveLink: resolveLink$1 = resolveLink }) {
90
70
  const rows = renderable(blocks, registry);
91
71
  const runs = runIndexes(rows.map((row) => row.block));
92
72
  const floating = rows.map((row) => floats(row.block));
93
- return /* @__PURE__ */ jsx(Fragment, { children: rows.map(({ block, Renderer }, index) => /* @__PURE__ */ jsx(Renderer, {
94
- block,
95
- index,
96
- prevType: index > 0 ? rows[index - 1].block.blockType : void 0,
97
- runIndex: runs[index],
98
- isLast: index === rows.length - 1,
99
- overlapAbove: index > 0 && floating[index - 1],
100
- overlapBelow: index < rows.length - 1 && floating[index + 1],
101
- containerClassName,
102
- imageComponent,
103
- linkComponent
73
+ return /* @__PURE__ */ jsx(Fragment, { children: rows.map(({ block, Renderer }, index) => /* @__PURE__ */ jsx("div", {
74
+ ...block.id ? { [BLOCK_ID_ATTRIBUTE]: block.id } : {},
75
+ children: /* @__PURE__ */ jsx(Renderer, {
76
+ block,
77
+ index,
78
+ prevType: index > 0 ? rows[index - 1].block.blockType : void 0,
79
+ runIndex: runs[index],
80
+ isLast: index === rows.length - 1,
81
+ overlapAbove: index > 0 && floating[index - 1],
82
+ overlapBelow: index < rows.length - 1 && floating[index + 1],
83
+ containerClassName,
84
+ imageComponent,
85
+ linkComponent,
86
+ resolveLink: resolveLink$1
87
+ })
104
88
  }, block.id ?? index)) });
105
89
  }
106
90
  //#endregion
@@ -149,9 +133,13 @@ const TONES = {
149
133
  * render at all, not to be the final answer. A site overrides this one registry
150
134
  * entry with its own and keeps every other block.
151
135
  */
152
- function HeroBlockRenderer({ block, index, overlapAbove, overlapBelow, containerClassName, imageComponent: Image, linkComponent: Link }) {
136
+ function HeroBlockRenderer({ block, index, overlapAbove, overlapBelow, containerClassName, imageComponent: Image, linkComponent: Link, resolveLink: resolve }) {
153
137
  const image = resolveMedia(block.image);
154
- const links = (block.links ?? []).filter((link) => link.href && link.label);
138
+ const links = (block.links ?? []).flatMap((link) => link.label ? [{
139
+ label: link.label,
140
+ href: resolve(link),
141
+ newTab: link.newTab ?? false
142
+ }] : []);
155
143
  const tone = TONES[block.tone ?? "sweep"];
156
144
  return /* @__PURE__ */ jsxs("section", {
157
145
  className: cx("relative isolate overflow-hidden", tone, seamClasses({
@@ -191,13 +179,13 @@ function HeroBlockRenderer({ block, index, overlapAbove, overlapBelow, container
191
179
  children: links.map((link, i) => /* @__PURE__ */ jsx(Button, {
192
180
  asChild: true,
193
181
  variant: i === 0 ? "default" : "outline",
194
- children: /* @__PURE__ */ jsx(Link, {
182
+ children: link.href ? /* @__PURE__ */ jsx(Link, {
195
183
  href: link.href,
196
- newTab: link.newTab ?? false,
184
+ newTab: link.newTab,
197
185
  ...newTabAttributes(link.newTab),
198
186
  children: link.label
199
- })
200
- }, `${link.href}-${i}`))
187
+ }) : /* @__PURE__ */ jsx("span", { children: link.label })
188
+ }, `${link.href ?? link.label}-${i}`))
201
189
  }) : null
202
190
  ]
203
191
  })
@@ -298,7 +286,7 @@ function ProcessStepsBlockRenderer({ block, overlapAbove, overlapBelow, containe
298
286
  }
299
287
  //#endregion
300
288
  //#region src/blocks/faq-columns/component.tsx
301
- function FaqColumnsBlockRenderer({ block, overlapAbove, overlapBelow, containerClassName, linkComponent }) {
289
+ function FaqColumnsBlockRenderer({ block, overlapAbove, overlapBelow, containerClassName, linkComponent, resolveLink: resolve }) {
302
290
  const items = (block.items ?? []).filter((row) => row.question && row.answer).map((row, i) => ({
303
291
  id: row.id ?? String(i),
304
292
  question: row.question,
@@ -309,7 +297,8 @@ function FaqColumnsBlockRenderer({ block, overlapAbove, overlapBelow, containerC
309
297
  }));
310
298
  if (items.length === 0) return null;
311
299
  const cta = block.cta;
312
- const hasCta = Boolean(cta?.href && cta?.linkText);
300
+ const hasCta = Boolean(cta?.linkText);
301
+ const ctaHref = cta ? resolve(cta) : null;
313
302
  return /* @__PURE__ */ jsx("section", {
314
303
  className: seamClasses({
315
304
  overlapAbove,
@@ -331,7 +320,7 @@ function FaqColumnsBlockRenderer({ block, overlapAbove, overlapBelow, containerC
331
320
  ...hasCta && cta ? { cta: {
332
321
  title: cta.title ?? "",
333
322
  linkText: cta.linkText,
334
- href: cta.href,
323
+ href: ctaHref ?? "",
335
324
  newTab: cta.newTab ?? false
336
325
  } } : {}
337
326
  })
@@ -340,7 +329,7 @@ function FaqColumnsBlockRenderer({ block, overlapAbove, overlapBelow, containerC
340
329
  }
341
330
  //#endregion
342
331
  //#region src/blocks/testimonial-masonry/component.tsx
343
- function TestimonialMasonryBlockRenderer({ block, overlapAbove, overlapBelow, containerClassName, linkComponent }) {
332
+ function TestimonialMasonryBlockRenderer({ block, overlapAbove, overlapBelow, containerClassName, linkComponent, resolveLink: resolve }) {
344
333
  const items = (block.items ?? []).filter((row) => row.content && row.author?.name).map((row, i) => {
345
334
  const avatar = resolveMedia(row.author?.avatar);
346
335
  return {
@@ -355,7 +344,8 @@ function TestimonialMasonryBlockRenderer({ block, overlapAbove, overlapBelow, co
355
344
  });
356
345
  if (items.length === 0) return null;
357
346
  const link = block.link;
358
- const hasLink = Boolean(link?.href && link?.label);
347
+ const hasLink = Boolean(link?.label);
348
+ const linkHref = link ? resolve(link) : null;
359
349
  return /* @__PURE__ */ jsx("section", {
360
350
  className: cx("bg-accent", seamClasses({
361
351
  overlapAbove,
@@ -375,7 +365,7 @@ function TestimonialMasonryBlockRenderer({ block, overlapAbove, overlapBelow, co
375
365
  ...typeof block.maxVisibleRows === "number" ? { maxVisibleRows: block.maxVisibleRows } : {},
376
366
  ...hasLink && link ? { link: {
377
367
  label: link.label,
378
- href: link.href,
368
+ href: linkHref ?? "",
379
369
  newTab: link.newTab ?? false
380
370
  } } : {}
381
371
  })
@@ -482,11 +472,17 @@ function remWidth(value) {
482
472
  }
483
473
  //#endregion
484
474
  //#region src/blocks/mega-menu/component.tsx
485
- function completeLink(row) {
486
- if (!row.label || !row.href) return null;
475
+ /**
476
+ * A menu link needs both halves. Unlike a call to action, a link whose page
477
+ * is missing or unpublished is dropped rather than shown as text: a menu
478
+ * item that goes nowhere is worse than one fewer item.
479
+ */
480
+ function completeLink(row, resolve) {
481
+ const href = resolve(row);
482
+ if (!row.label || !href) return null;
487
483
  return {
488
484
  label: row.label,
489
- href: row.href,
485
+ href,
490
486
  ...row.description ? { description: row.description } : {},
491
487
  ...row.variant ? { variant: row.variant } : {},
492
488
  ...row.icon ? { icon: row.icon } : {},
@@ -497,8 +493,10 @@ function completeLink(row) {
497
493
  * The row as `MegaMenuPanel` data, or `null` when there is nothing to open:
498
494
  * no columns, or columns whose links are not yet complete. Draft saves skip
499
495
  * validation, so a live preview genuinely hands this half-built rows.
496
+ * `resolve` turns each link's page into a path; the package's own is the
497
+ * default.
500
498
  */
501
- function megaMenuPanelFromRow(row) {
499
+ function megaMenuPanelFromRow(row, resolve = resolveLink) {
502
500
  const panel = row.panel;
503
501
  if (!panel?.columns?.length) return null;
504
502
  const custom = Boolean(panel.customWidths);
@@ -506,7 +504,7 @@ function megaMenuPanelFromRow(row) {
506
504
  for (const column of panel.columns) {
507
505
  const sections = [];
508
506
  for (const section of column.sections ?? []) {
509
- const links = (section.links ?? []).map(completeLink).filter((link) => link !== null);
507
+ const links = (section.links ?? []).map((link) => completeLink(link, resolve)).filter((link) => link !== null);
510
508
  if (!links.length) continue;
511
509
  sections.push({
512
510
  ...section.eyebrow ? { eyebrow: section.eyebrow } : {},
@@ -522,31 +520,33 @@ function megaMenuPanelFromRow(row) {
522
520
  });
523
521
  }
524
522
  if (!columns.some((column) => column.sections.length)) return null;
525
- const overview = panel.footer?.overview;
526
- const cta = panel.footer?.cta;
523
+ const overview = footerLink(panel.footer?.overview, resolve);
524
+ const cta = footerLink(panel.footer?.cta, resolve);
527
525
  return {
528
526
  maxWidth: remWidth(panel.customMaxWidth) ?? panel.maxWidth ?? "standard",
529
527
  columns,
530
528
  footer: {
531
- ...overview?.label && overview.href ? { overview: {
532
- label: overview.label,
533
- href: overview.href,
534
- ...overview.newTab ? { newTab: true } : {}
535
- } } : {},
536
- ...cta?.label && cta.href ? { cta: {
537
- label: cta.label,
538
- href: cta.href,
539
- ...cta.newTab ? { newTab: true } : {}
540
- } } : {}
529
+ ...overview ? { overview } : {},
530
+ ...cta ? { cta } : {}
541
531
  }
542
532
  };
543
533
  }
534
+ /** A footer link, complete, or nothing: same rule as `completeLink`. */
535
+ function footerLink(row, resolve) {
536
+ const href = row ? resolve(row) : null;
537
+ if (!row?.label || !href) return null;
538
+ return {
539
+ label: row.label,
540
+ href,
541
+ ...row.newTab ? { newTab: true } : {}
542
+ };
543
+ }
544
544
  /**
545
545
  * One panel, standing alone: what a live preview shows while the row is being
546
546
  * edited. A whole header goes through `headerItemsFromBlocks` instead.
547
547
  */
548
- function MegaMenuBlockRenderer({ block, linkComponent, variants, icons }) {
549
- const panel = megaMenuPanelFromRow(block);
548
+ function MegaMenuBlockRenderer({ block, linkComponent, resolveLink: resolve, variants, icons }) {
549
+ const panel = megaMenuPanelFromRow(block, resolve);
550
550
  if (!panel) return null;
551
551
  return /* @__PURE__ */ jsx(MegaMenuPanel, {
552
552
  ...panel,
@@ -564,20 +564,23 @@ function MegaMenuBlockRenderer({ block, linkComponent, variants, icons }) {
564
564
  * site added that this package does not know.
565
565
  *
566
566
  * A `navLink` row's `newTab` is not carried: `FloatingNavItem` has no such
567
- * field, because the bar renders its own links.
567
+ * field, because the bar renders its own links. A bar item whose page is
568
+ * missing or unpublished is dropped, like a panel link. A mega menu's own
569
+ * `href` (the trigger's landing page) is plain text, not a picked page.
568
570
  */
569
- function headerItemsFromBlocks(blocks, { variants, icons, isActive, linkComponent } = {}) {
571
+ function headerItemsFromBlocks(blocks, { variants, icons, isActive, linkComponent, resolveLink: resolve = resolveLink } = {}) {
570
572
  const items = [];
571
573
  for (const row of blocks) {
572
574
  if (!row.label) continue;
573
575
  if (row.blockType === "navLink") {
574
- if (!row.href) continue;
576
+ const href = resolve(row);
577
+ if (!href) continue;
575
578
  items.push({
576
579
  label: row.label,
577
- href: row.href
580
+ href
578
581
  });
579
582
  } else if (row.blockType === "megaMenu") {
580
- const panel = megaMenuPanelFromRow(row);
583
+ const panel = megaMenuPanelFromRow(row, resolve);
581
584
  if (!panel) continue;
582
585
  items.push({
583
586
  label: row.label,
@@ -594,6 +597,6 @@ function headerItemsFromBlocks(blocks, { variants, icons, isActive, linkComponen
594
597
  });
595
598
  }
596
599
  //#endregion
597
- export { DEFAULT_CONTAINER, DefaultBlockImage, DefaultBlockLink, FaqColumnsBlockRenderer, HeroBlockRenderer, MegaMenuBlockRenderer, NapBlockRenderer, OVERLAP_ABOVE_CLEARANCE, OVERLAP_BELOW_CLEARANCE, ProcessStepsBlockRenderer, RenderBlocks, SEAM_PULL_DOWN, SEAM_PULL_UP, ShowcasePanelsBlockRenderer, StatsBandBlockRenderer, TestimonialMasonryBlockRenderer, headerItemsFromBlocks, megaMenuPanelFromRow, newTabAttributes, overlapsSeam, renderLinkWith, seamClasses };
600
+ export { BLOCK_ID_ATTRIBUTE, DEFAULT_CONTAINER, DefaultBlockImage, DefaultBlockLink, FaqColumnsBlockRenderer, HeroBlockRenderer, MegaMenuBlockRenderer, NapBlockRenderer, OVERLAP_ABOVE_CLEARANCE, OVERLAP_BELOW_CLEARANCE, ProcessStepsBlockRenderer, RenderBlocks, SEAM_PULL_DOWN, SEAM_PULL_UP, ShowcasePanelsBlockRenderer, StatsBandBlockRenderer, TestimonialMasonryBlockRenderer, headerItemsFromBlocks, linkTypeOf, megaMenuPanelFromRow, newTabAttributes, overlapsSeam, renderLinkWith, resolveLink, seamClasses };
598
601
 
599
602
  //# sourceMappingURL=react.mjs.map