@bison-lab/payload-blocks 3.1.0 → 3.3.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 +150 -1
- package/dist/index.d.mts +139 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +632 -6
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +123 -7
- package/dist/react.d.mts.map +1 -1
- package/dist/react.mjs +312 -72
- package/dist/react.mjs.map +1 -1
- package/dist/rich-text.d.mts +3 -1
- package/dist/rich-text.d.mts.map +1 -1
- package/dist/rich-text.mjs +12 -6
- package/dist/rich-text.mjs.map +1 -1
- package/dist/seam-BDFZlV3F.mjs +54 -0
- package/dist/seam-BDFZlV3F.mjs.map +1 -0
- package/dist/{types-BBumyFd-.d.mts → types-D9rg0BoW.d.mts} +132 -8
- package/dist/types-D9rg0BoW.d.mts.map +1 -0
- package/package.json +2 -2
- package/dist/cx-BKHSv3xT.mjs +0 -17
- package/dist/cx-BKHSv3xT.mjs.map +0 -1
- package/dist/types-BBumyFd-.d.mts.map +0 -1
package/dist/react.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
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";
|
|
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, StatsBandBlock, 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,17 +86,21 @@ 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, floats = overlapsSeam }) {
|
|
54
90
|
const rows = renderable(blocks, registry);
|
|
55
91
|
const runs = runIndexes(rows.map((row) => row.block));
|
|
92
|
+
const floating = rows.map((row) => floats(row.block));
|
|
56
93
|
return /* @__PURE__ */ jsx(Fragment, { children: rows.map(({ block, Renderer }, index) => /* @__PURE__ */ jsx(Renderer, {
|
|
57
94
|
block,
|
|
58
95
|
index,
|
|
59
96
|
prevType: index > 0 ? rows[index - 1].block.blockType : void 0,
|
|
60
97
|
runIndex: runs[index],
|
|
61
98
|
isLast: index === rows.length - 1,
|
|
99
|
+
overlapAbove: index > 0 && floating[index - 1],
|
|
100
|
+
overlapBelow: index < rows.length - 1 && floating[index + 1],
|
|
62
101
|
containerClassName,
|
|
63
|
-
imageComponent
|
|
102
|
+
imageComponent,
|
|
103
|
+
linkComponent
|
|
64
104
|
}, block.id ?? index)) });
|
|
65
105
|
}
|
|
66
106
|
//#endregion
|
|
@@ -109,12 +149,15 @@ const TONES = {
|
|
|
109
149
|
* render at all, not to be the final answer. A site overrides this one registry
|
|
110
150
|
* entry with its own and keeps every other block.
|
|
111
151
|
*/
|
|
112
|
-
function HeroBlockRenderer({ block, index, containerClassName, imageComponent: Image }) {
|
|
152
|
+
function HeroBlockRenderer({ block, index, overlapAbove, overlapBelow, containerClassName, imageComponent: Image, linkComponent: Link }) {
|
|
113
153
|
const image = resolveMedia(block.image);
|
|
114
154
|
const links = (block.links ?? []).filter((link) => link.href && link.label);
|
|
115
155
|
const tone = TONES[block.tone ?? "sweep"];
|
|
116
156
|
return /* @__PURE__ */ jsxs("section", {
|
|
117
|
-
className: cx("relative isolate overflow-hidden", tone
|
|
157
|
+
className: cx("relative isolate overflow-hidden", tone, seamClasses({
|
|
158
|
+
overlapAbove,
|
|
159
|
+
overlapBelow
|
|
160
|
+
})),
|
|
118
161
|
children: [image ? /* @__PURE__ */ jsx("div", {
|
|
119
162
|
className: "absolute inset-0 -z-10 opacity-25",
|
|
120
163
|
children: /* @__PURE__ */ jsx(Image, {
|
|
@@ -148,12 +191,10 @@ function HeroBlockRenderer({ block, index, containerClassName, imageComponent: I
|
|
|
148
191
|
children: links.map((link, i) => /* @__PURE__ */ jsx(Button, {
|
|
149
192
|
asChild: true,
|
|
150
193
|
variant: i === 0 ? "default" : "outline",
|
|
151
|
-
children: /* @__PURE__ */ jsx(
|
|
194
|
+
children: /* @__PURE__ */ jsx(Link, {
|
|
152
195
|
href: link.href,
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
rel: "noreferrer noopener"
|
|
156
|
-
} : {},
|
|
196
|
+
newTab: link.newTab ?? false,
|
|
197
|
+
...newTabAttributes(link.newTab),
|
|
157
198
|
children: link.label
|
|
158
199
|
})
|
|
159
200
|
}, `${link.href}-${i}`))
|
|
@@ -165,7 +206,7 @@ function HeroBlockRenderer({ block, index, containerClassName, imageComponent: I
|
|
|
165
206
|
}
|
|
166
207
|
//#endregion
|
|
167
208
|
//#region src/blocks/showcase-panels/component.tsx
|
|
168
|
-
function ShowcasePanelsBlockRenderer({ block, containerClassName, imageComponent: Image }) {
|
|
209
|
+
function ShowcasePanelsBlockRenderer({ block, overlapAbove, overlapBelow, containerClassName, imageComponent: Image, linkComponent }) {
|
|
169
210
|
const dims = [];
|
|
170
211
|
const items = [];
|
|
171
212
|
for (const [i, row] of (block.items ?? []).entries()) {
|
|
@@ -186,26 +227,33 @@ function ShowcasePanelsBlockRenderer({ block, containerClassName, imageComponent
|
|
|
186
227
|
}
|
|
187
228
|
if (items.length === 0) return null;
|
|
188
229
|
return /* @__PURE__ */ jsx("section", {
|
|
189
|
-
className:
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
230
|
+
className: seamClasses({
|
|
231
|
+
overlapAbove,
|
|
232
|
+
overlapBelow
|
|
233
|
+
}),
|
|
234
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
235
|
+
className: cx(containerClassName, "py-16 lg:py-24"),
|
|
236
|
+
children: /* @__PURE__ */ jsx(ShowcasePanelsBlock, {
|
|
237
|
+
items,
|
|
238
|
+
spineVariant: block.spineVariant ?? "numbered",
|
|
239
|
+
defaultActiveIndex: Math.min(Math.max(block.defaultActiveIndex ?? 0, 0), items.length - 1),
|
|
240
|
+
...block.watermark ? { watermark: block.watermark } : {},
|
|
241
|
+
renderLink: renderLinkWith(linkComponent),
|
|
242
|
+
renderImage: (item, i) => /* @__PURE__ */ jsx(Image, {
|
|
243
|
+
src: item.image.src,
|
|
244
|
+
alt: item.image.alt ?? "",
|
|
245
|
+
width: dims[i]?.width,
|
|
246
|
+
height: dims[i]?.height,
|
|
247
|
+
className: "absolute inset-0 h-full w-full object-cover",
|
|
248
|
+
sizes: "(min-width: 1024px) 50vw, 100vw"
|
|
249
|
+
})
|
|
202
250
|
})
|
|
203
251
|
})
|
|
204
252
|
});
|
|
205
253
|
}
|
|
206
254
|
//#endregion
|
|
207
255
|
//#region src/blocks/process-steps/component.tsx
|
|
208
|
-
function ProcessStepsBlockRenderer({ block, containerClassName, imageComponent: Image }) {
|
|
256
|
+
function ProcessStepsBlockRenderer({ block, overlapAbove, overlapBelow, containerClassName, imageComponent: Image }) {
|
|
209
257
|
const dims = [];
|
|
210
258
|
const items = [];
|
|
211
259
|
for (const [i, row] of (block.items ?? []).entries()) {
|
|
@@ -224,27 +272,33 @@ function ProcessStepsBlockRenderer({ block, containerClassName, imageComponent:
|
|
|
224
272
|
}
|
|
225
273
|
if (items.length === 0) return null;
|
|
226
274
|
return /* @__PURE__ */ jsx("section", {
|
|
227
|
-
className:
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
275
|
+
className: seamClasses({
|
|
276
|
+
overlapAbove,
|
|
277
|
+
overlapBelow
|
|
278
|
+
}),
|
|
279
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
280
|
+
className: cx(containerClassName, "py-16 lg:py-24"),
|
|
281
|
+
children: /* @__PURE__ */ jsx(ProcessStepsBlock, {
|
|
282
|
+
items,
|
|
283
|
+
autoAdvance: block.autoAdvance ?? true,
|
|
284
|
+
autoAdvanceDuration: block.autoAdvanceDuration ?? 6e3,
|
|
285
|
+
pauseOnHover: block.pauseOnHover ?? true,
|
|
286
|
+
defaultActiveIndex: Math.min(Math.max(block.defaultActiveIndex ?? 0, 0), items.length - 1),
|
|
287
|
+
renderImage: (item, i) => /* @__PURE__ */ jsx(Image, {
|
|
288
|
+
src: item.image.src,
|
|
289
|
+
alt: item.image.alt ?? "",
|
|
290
|
+
width: dims[i]?.width,
|
|
291
|
+
height: dims[i]?.height,
|
|
292
|
+
className: "size-full object-cover",
|
|
293
|
+
sizes: "(min-width: 768px) 66vw, 100vw"
|
|
294
|
+
})
|
|
241
295
|
})
|
|
242
296
|
})
|
|
243
297
|
});
|
|
244
298
|
}
|
|
245
299
|
//#endregion
|
|
246
300
|
//#region src/blocks/faq-columns/component.tsx
|
|
247
|
-
function FaqColumnsBlockRenderer({ block, containerClassName }) {
|
|
301
|
+
function FaqColumnsBlockRenderer({ block, overlapAbove, overlapBelow, containerClassName, linkComponent }) {
|
|
248
302
|
const items = (block.items ?? []).filter((row) => row.question && row.answer).map((row, i) => ({
|
|
249
303
|
id: row.id ?? String(i),
|
|
250
304
|
question: row.question,
|
|
@@ -256,30 +310,37 @@ function FaqColumnsBlockRenderer({ block, containerClassName }) {
|
|
|
256
310
|
if (items.length === 0) return null;
|
|
257
311
|
const cta = block.cta;
|
|
258
312
|
const hasCta = Boolean(cta?.href && cta?.linkText);
|
|
259
|
-
return /* @__PURE__ */ jsx("section", {
|
|
260
|
-
className:
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
313
|
+
return /* @__PURE__ */ jsx("section", {
|
|
314
|
+
className: seamClasses({
|
|
315
|
+
overlapAbove,
|
|
316
|
+
overlapBelow
|
|
317
|
+
}),
|
|
318
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
319
|
+
className: cx(containerClassName, "py-16 lg:py-24"),
|
|
320
|
+
children: /* @__PURE__ */ jsx(FAQColumnsBlock, {
|
|
321
|
+
className: "py-0 md:py-0",
|
|
322
|
+
containerClassName: "max-w-none px-0 sm:px-0",
|
|
323
|
+
items,
|
|
324
|
+
title: block.title ?? "",
|
|
325
|
+
...block.eyebrow ? { eyebrow: block.eyebrow } : {},
|
|
326
|
+
...block.description ? { description: block.description } : {},
|
|
327
|
+
sticky: block.sticky ?? true,
|
|
328
|
+
type: block.type ?? "single",
|
|
329
|
+
collapsible: block.collapsible ?? true,
|
|
330
|
+
renderLink: renderLinkWith(linkComponent),
|
|
331
|
+
...hasCta && cta ? { cta: {
|
|
332
|
+
title: cta.title ?? "",
|
|
333
|
+
linkText: cta.linkText,
|
|
334
|
+
href: cta.href,
|
|
335
|
+
newTab: cta.newTab ?? false
|
|
336
|
+
} } : {}
|
|
337
|
+
})
|
|
277
338
|
})
|
|
278
|
-
})
|
|
339
|
+
});
|
|
279
340
|
}
|
|
280
341
|
//#endregion
|
|
281
342
|
//#region src/blocks/testimonial-masonry/component.tsx
|
|
282
|
-
function TestimonialMasonryBlockRenderer({ block, containerClassName }) {
|
|
343
|
+
function TestimonialMasonryBlockRenderer({ block, overlapAbove, overlapBelow, containerClassName, linkComponent }) {
|
|
283
344
|
const items = (block.items ?? []).filter((row) => row.content && row.author?.name).map((row, i) => {
|
|
284
345
|
const avatar = resolveMedia(row.author?.avatar);
|
|
285
346
|
return {
|
|
@@ -296,7 +357,10 @@ function TestimonialMasonryBlockRenderer({ block, containerClassName }) {
|
|
|
296
357
|
const link = block.link;
|
|
297
358
|
const hasLink = Boolean(link?.href && link?.label);
|
|
298
359
|
return /* @__PURE__ */ jsx("section", {
|
|
299
|
-
className: "bg-accent",
|
|
360
|
+
className: cx("bg-accent", seamClasses({
|
|
361
|
+
overlapAbove,
|
|
362
|
+
overlapBelow
|
|
363
|
+
})),
|
|
300
364
|
children: /* @__PURE__ */ jsx("div", {
|
|
301
365
|
className: cx(containerClassName, "py-16 lg:py-24"),
|
|
302
366
|
children: /* @__PURE__ */ jsx(TestimonialMasonry, {
|
|
@@ -304,6 +368,7 @@ function TestimonialMasonryBlockRenderer({ block, containerClassName }) {
|
|
|
304
368
|
containerClassName: "max-w-none px-0 py-0 sm:py-0 md:px-0 md:py-0",
|
|
305
369
|
items,
|
|
306
370
|
title: block.title ?? "",
|
|
371
|
+
renderLink: renderLinkWith(linkComponent),
|
|
307
372
|
...block.eyebrow ? { eyebrow: block.eyebrow } : {},
|
|
308
373
|
...block.description ? { description: block.description } : {},
|
|
309
374
|
...typeof block.minItemsForFade === "number" ? { minItemsForFade: block.minItemsForFade } : {},
|
|
@@ -319,7 +384,7 @@ function TestimonialMasonryBlockRenderer({ block, containerClassName }) {
|
|
|
319
384
|
}
|
|
320
385
|
//#endregion
|
|
321
386
|
//#region src/blocks/nap/component.tsx
|
|
322
|
-
function NapBlockRenderer({ block, containerClassName }) {
|
|
387
|
+
function NapBlockRenderer({ block, overlapAbove, overlapBelow, containerClassName, linkComponent }) {
|
|
323
388
|
const address = block.address;
|
|
324
389
|
const departments = (block.departments ?? []).filter((row) => row.name && row.phoneE164).map((row, i) => ({
|
|
325
390
|
id: row.id ?? String(i),
|
|
@@ -344,16 +409,191 @@ function NapBlockRenderer({ block, containerClassName }) {
|
|
|
344
409
|
departments,
|
|
345
410
|
...block.url ? { url: block.url } : {}
|
|
346
411
|
};
|
|
347
|
-
return /* @__PURE__ */ jsx("section", {
|
|
348
|
-
className:
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
412
|
+
return /* @__PURE__ */ jsx("section", {
|
|
413
|
+
className: seamClasses({
|
|
414
|
+
overlapAbove,
|
|
415
|
+
overlapBelow
|
|
416
|
+
}),
|
|
417
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
418
|
+
className: cx(containerClassName, "py-16 lg:py-24"),
|
|
419
|
+
children: [/* @__PURE__ */ jsx(NapBlock, {
|
|
420
|
+
record,
|
|
421
|
+
showName: block.showName ?? true,
|
|
422
|
+
headingLevel: block.headingLevel ?? "h2",
|
|
423
|
+
renderLink: renderLinkWith(linkComponent)
|
|
424
|
+
}), block.emitJsonLd === false ? null : /* @__PURE__ */ jsx(JsonLd, { data: record })]
|
|
425
|
+
})
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
//#endregion
|
|
429
|
+
//#region src/blocks/stats-band/component.tsx
|
|
430
|
+
/** The select only offers 2–6, but a site can edit the config; fall back to the design's four. */
|
|
431
|
+
function columnsFrom(value) {
|
|
432
|
+
const n = Number(value ?? 4);
|
|
433
|
+
return Number.isInteger(n) && n >= 2 && n <= 6 ? n : 4;
|
|
434
|
+
}
|
|
435
|
+
function StatsBandBlockRenderer({ block, index, isLast, overlapAbove, overlapBelow, containerClassName, linkComponent }) {
|
|
436
|
+
const items = (block.items ?? []).flatMap((row, i) => row.value ? [{
|
|
437
|
+
id: row.id ?? String(i),
|
|
438
|
+
value: row.value,
|
|
439
|
+
label: row.label ?? "",
|
|
440
|
+
...row.href ? { href: row.href } : {},
|
|
441
|
+
...row.wide ? { wide: true } : {}
|
|
442
|
+
}] : []);
|
|
443
|
+
if (items.length < 2) return null;
|
|
444
|
+
const floats = Boolean(block.overlap);
|
|
445
|
+
const overAbove = floats && index > 0 && !overlapAbove;
|
|
446
|
+
const overBelow = floats && !isLast && !overlapBelow;
|
|
447
|
+
return /* @__PURE__ */ jsx("section", {
|
|
448
|
+
className: cx("relative", floats && "z-10", seamClasses({
|
|
449
|
+
overlapAbove,
|
|
450
|
+
overlapBelow
|
|
451
|
+
})),
|
|
452
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
453
|
+
className: cx(containerClassName, overAbove ? SEAM_PULL_UP : "pt-16 lg:pt-24", overBelow ? SEAM_PULL_DOWN : "pb-16 lg:pb-24"),
|
|
454
|
+
children: /* @__PURE__ */ jsx(StatsBandBlock, {
|
|
455
|
+
items,
|
|
456
|
+
columns: columnsFrom(block.columns),
|
|
457
|
+
tone: block.tone ?? "card",
|
|
458
|
+
align: block.align ?? "start",
|
|
459
|
+
eyebrow: !floats && block.eyebrow || void 0,
|
|
460
|
+
title: !floats && block.title || void 0,
|
|
461
|
+
description: !floats && block.description || void 0,
|
|
462
|
+
containerClassName: "max-w-none px-0 sm:px-0",
|
|
463
|
+
renderLink: renderLinkWith(linkComponent)
|
|
464
|
+
})
|
|
465
|
+
})
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
//#endregion
|
|
469
|
+
//#region src/blocks/mega-menu/rem-width.ts
|
|
470
|
+
/**
|
|
471
|
+
* The one rule for a typed panel width, shared by the config's validator and
|
|
472
|
+
* the renderer's reader so the two cannot drift: if the validator accepted a
|
|
473
|
+
* value the renderer dropped, the editor would be back to a width that
|
|
474
|
+
* silently does nothing. React-free, because `config.ts` ships from the Node
|
|
475
|
+
* entry.
|
|
476
|
+
*/
|
|
477
|
+
const REM_WIDTH = /^\s*(\d+(?:\.\d+)?)\s*(rem)?\s*$/;
|
|
478
|
+
/** "30" and "30rem" both mean 30rem; anything else is not a width. */
|
|
479
|
+
function remWidth(value) {
|
|
480
|
+
const match = REM_WIDTH.exec(value ?? "");
|
|
481
|
+
return match ? `${Number(match[1])}rem` : null;
|
|
482
|
+
}
|
|
483
|
+
//#endregion
|
|
484
|
+
//#region src/blocks/mega-menu/component.tsx
|
|
485
|
+
function completeLink(row) {
|
|
486
|
+
if (!row.label || !row.href) return null;
|
|
487
|
+
return {
|
|
488
|
+
label: row.label,
|
|
489
|
+
href: row.href,
|
|
490
|
+
...row.description ? { description: row.description } : {},
|
|
491
|
+
...row.variant ? { variant: row.variant } : {},
|
|
492
|
+
...row.icon ? { icon: row.icon } : {},
|
|
493
|
+
...row.newTab ? { newTab: true } : {}
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* The row as `MegaMenuPanel` data, or `null` when there is nothing to open:
|
|
498
|
+
* no columns, or columns whose links are not yet complete. Draft saves skip
|
|
499
|
+
* validation, so a live preview genuinely hands this half-built rows.
|
|
500
|
+
*/
|
|
501
|
+
function megaMenuPanelFromRow(row) {
|
|
502
|
+
const panel = row.panel;
|
|
503
|
+
if (!panel?.columns?.length) return null;
|
|
504
|
+
const custom = Boolean(panel.customWidths);
|
|
505
|
+
const columns = [];
|
|
506
|
+
for (const column of panel.columns) {
|
|
507
|
+
const sections = [];
|
|
508
|
+
for (const section of column.sections ?? []) {
|
|
509
|
+
const links = (section.links ?? []).map(completeLink).filter((link) => link !== null);
|
|
510
|
+
if (!links.length) continue;
|
|
511
|
+
sections.push({
|
|
512
|
+
...section.eyebrow ? { eyebrow: section.eyebrow } : {},
|
|
513
|
+
display: section.display ?? "list",
|
|
514
|
+
hideDescriptionsOnMobile: section.hideDescriptionsOnMobile ?? true,
|
|
515
|
+
links
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
columns.push({
|
|
519
|
+
...custom && column.customWidth ? { customWidth: column.customWidth } : { width: Number(column.width ?? "100") },
|
|
520
|
+
...column.divider ? { divider: true } : {},
|
|
521
|
+
sections
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
if (!columns.some((column) => column.sections.length)) return null;
|
|
525
|
+
const overview = panel.footer?.overview;
|
|
526
|
+
const cta = panel.footer?.cta;
|
|
527
|
+
return {
|
|
528
|
+
maxWidth: remWidth(panel.customMaxWidth) ?? panel.maxWidth ?? "standard",
|
|
529
|
+
columns,
|
|
530
|
+
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
|
+
} } : {}
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* One panel, standing alone: what a live preview shows while the row is being
|
|
546
|
+
* edited. A whole header goes through `headerItemsFromBlocks` instead.
|
|
547
|
+
*/
|
|
548
|
+
function MegaMenuBlockRenderer({ block, linkComponent, variants, icons }) {
|
|
549
|
+
const panel = megaMenuPanelFromRow(block);
|
|
550
|
+
if (!panel) return null;
|
|
551
|
+
return /* @__PURE__ */ jsx(MegaMenuPanel, {
|
|
552
|
+
...panel,
|
|
553
|
+
variants,
|
|
554
|
+
icons,
|
|
555
|
+
renderLink: renderLinkWith(linkComponent)
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
//#endregion
|
|
559
|
+
//#region src/blocks/mega-menu/header.tsx
|
|
560
|
+
/**
|
|
561
|
+
* A global's `items` as `FloatingNavBlock` items, so a site's header is one
|
|
562
|
+
* call. Rows the bar cannot show are dropped rather than rendered broken: a
|
|
563
|
+
* row with no label, a mega menu with nothing to open, and any block type a
|
|
564
|
+
* site added that this package does not know.
|
|
565
|
+
*
|
|
566
|
+
* A `navLink` row's `newTab` is not carried: `FloatingNavItem` has no such
|
|
567
|
+
* field, because the bar renders its own links.
|
|
568
|
+
*/
|
|
569
|
+
function headerItemsFromBlocks(blocks, { variants, icons, isActive, linkComponent } = {}) {
|
|
570
|
+
const items = [];
|
|
571
|
+
for (const row of blocks) {
|
|
572
|
+
if (!row.label) continue;
|
|
573
|
+
if (row.blockType === "navLink") {
|
|
574
|
+
if (!row.href) continue;
|
|
575
|
+
items.push({
|
|
576
|
+
label: row.label,
|
|
577
|
+
href: row.href
|
|
578
|
+
});
|
|
579
|
+
} else if (row.blockType === "megaMenu") {
|
|
580
|
+
const panel = megaMenuPanelFromRow(row);
|
|
581
|
+
if (!panel) continue;
|
|
582
|
+
items.push({
|
|
583
|
+
label: row.label,
|
|
584
|
+
...row.href ? { href: row.href } : {},
|
|
585
|
+
panel
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
return megaMenuToFloatingNavItems({ items }, {
|
|
590
|
+
isActive,
|
|
591
|
+
variants,
|
|
592
|
+
icons,
|
|
593
|
+
...linkComponent ? { renderLink: renderLinkWith(linkComponent) } : {}
|
|
594
|
+
});
|
|
355
595
|
}
|
|
356
596
|
//#endregion
|
|
357
|
-
export { DEFAULT_CONTAINER, DefaultBlockImage, FaqColumnsBlockRenderer, HeroBlockRenderer, NapBlockRenderer, ProcessStepsBlockRenderer, RenderBlocks, ShowcasePanelsBlockRenderer, TestimonialMasonryBlockRenderer };
|
|
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 };
|
|
358
598
|
|
|
359
599
|
//# sourceMappingURL=react.mjs.map
|