@bison-lab/payload-blocks 3.2.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 +48 -0
- package/dist/index.d.mts +40 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +227 -24
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +61 -2
- package/dist/react.d.mts.map +1 -1
- package/dist/react.mjs +142 -69
- 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-CJAvoZMk.d.mts → types-D9rg0BoW.d.mts} +38 -4
- 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-CJAvoZMk.d.mts.map +0 -1
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Payload CMS block configs and renderers for the Bison Lab marketing blocks.
|
|
4
4
|
|
|
5
|
+
Full guide, with every block rendered live: <https://payload.bisonlab.ai/>
|
|
6
|
+
|
|
5
7
|
Install it in a Payload site and editors get the same sections `@bison-lab/ui`
|
|
6
8
|
ships as React props — showcase panels, process steps, FAQ columns, testimonial
|
|
7
9
|
masonry, NAP — as blocks they can add to a page.
|
|
@@ -175,6 +177,51 @@ export const NextBlockLink: BlockLinkComponent = ({ newTab, ...props }) => <Link
|
|
|
175
177
|
Without one, `DefaultBlockLink` renders a plain anchor and sets `target` and
|
|
176
178
|
`rel` together whenever `newTab` is on.
|
|
177
179
|
|
|
180
|
+
### The seam
|
|
181
|
+
|
|
182
|
+
One block floats across the join between two bands: the stats band with
|
|
183
|
+
`overlap` on. It pulls itself up over the block above and down over the block
|
|
184
|
+
below with negative margins, and each neighbour adds the same distance on its
|
|
185
|
+
own side so the band sits across the seam without covering copy. Nothing is
|
|
186
|
+
configured for this: `RenderBlocks` works out which rows float and hands every
|
|
187
|
+
renderer two booleans, `overlapAbove` and `overlapBelow`, the same kind of
|
|
188
|
+
derived neighbour fact as `runIndex` and `isLast`. Every package renderer's
|
|
189
|
+
band wrapper adds `seamClasses(props)`; a renderer never reads a neighbour's
|
|
190
|
+
row.
|
|
191
|
+
|
|
192
|
+
A site's own renderer does the same. The usual case is the hero, which keeps
|
|
193
|
+
symmetric padding until an editor drops an overlapping band under it:
|
|
194
|
+
|
|
195
|
+
```tsx
|
|
196
|
+
export function SiteHeroRenderer(props: BlockRendererProps<HeroBlockData>) {
|
|
197
|
+
return <PageHero overlap={props.overlapBelow} … />
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Which rows float is `RenderBlocks`' `floats` prop, defaulting to
|
|
202
|
+
`overlapsSeam` (the package's stats band with `overlap` on). A site with a
|
|
203
|
+
floating block of its own composes it:
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
<RenderBlocks … floats={(row) => overlapsSeam(row) || row.blockType === 'bookingCard'} />
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
`SEAM_PULL_UP` / `SEAM_PULL_DOWN` are the floating block's negative margins
|
|
210
|
+
and `OVERLAP_ABOVE_CLEARANCE` / `OVERLAP_BELOW_CLEARANCE` the matching
|
|
211
|
+
padding, all from `./react`, so a site block that floats uses the same
|
|
212
|
+
distance the neighbours clear. A floating block that is first on the page
|
|
213
|
+
keeps its top padding, and one that is last keeps its bottom padding rather
|
|
214
|
+
than pulling the footer up.
|
|
215
|
+
|
|
216
|
+
**Tailwind has to see the renderers.** The padding and margins above are
|
|
217
|
+
utilities in this package's output, not in `@bison-lab/ui`, so a site's
|
|
218
|
+
stylesheet scans both packages:
|
|
219
|
+
|
|
220
|
+
```css
|
|
221
|
+
@source '../../../node_modules/@bison-lab/ui/dist';
|
|
222
|
+
@source '../../../node_modules/@bison-lab/payload-blocks/dist';
|
|
223
|
+
```
|
|
224
|
+
|
|
178
225
|
## Wiring a header
|
|
179
226
|
|
|
180
227
|
Two more blocks build a header rather than a page: `megaMenuBlock` and
|
|
@@ -258,6 +305,7 @@ renders nothing, and `headerItemsFromBlocks` drops it.
|
|
|
258
305
|
| `faqColumns` | `FAQColumnsBlock` | Answers are plain text, not Lexical — see the config for why. |
|
|
259
306
|
| `testimonialMasonry` | `TestimonialMasonry` | Avatars fall back to initials. |
|
|
260
307
|
| `nap` | `NapBlock` + `JsonLd` | Emits schema.org `LocalBusiness`; `phoneE164` is what the `tel:` link uses. |
|
|
308
|
+
| `statsBand` | `StatsBandBlock` | 2–6 figures. Phones show two per row, tablets three, `columns` from `lg`. `overlap` floats it over the seam with its neighbours — see "The seam". |
|
|
261
309
|
| `megaMenu` | `MegaMenuPanel` | A header block, from `megaMenuBlock({ variants, icons })`. See "Wiring a header". |
|
|
262
310
|
| `navLink` | — | A header block: a plain bar item. `headerItemsFromBlocks` maps it. |
|
|
263
311
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ArrayFieldValidation, Block, CollectionSlug, Field, GroupField, TextFieldSingleValidation, UploadField } from "payload";
|
|
1
|
+
import { ArrayFieldValidation, Block, CollectionSlug, Condition, Field, GroupField, TextFieldSingleValidation, UploadField } from "payload";
|
|
2
2
|
|
|
3
3
|
//#region src/blocks/hero/config.d.ts
|
|
4
4
|
/**
|
|
@@ -43,6 +43,17 @@ declare const TestimonialMasonryBlock: Block;
|
|
|
43
43
|
*/
|
|
44
44
|
declare const NapBlock: Block;
|
|
45
45
|
//#endregion
|
|
46
|
+
//#region src/blocks/stats-band/config.d.ts
|
|
47
|
+
/**
|
|
48
|
+
* A strip of figures: the facts a visitor should take in at a glance.
|
|
49
|
+
*
|
|
50
|
+
* The count, the order and the desktop column count are the editor's. The
|
|
51
|
+
* phone and tablet layouts are the library's: two per row and three per row,
|
|
52
|
+
* with `wide` naming the one stat that takes a full phone row when the count
|
|
53
|
+
* is odd.
|
|
54
|
+
*/
|
|
55
|
+
declare const StatsBandBlock: Block;
|
|
56
|
+
//#endregion
|
|
46
57
|
//#region src/blocks/mega-menu/config.d.ts
|
|
47
58
|
/**
|
|
48
59
|
* The blocks a header global's `items` array takes.
|
|
@@ -163,6 +174,12 @@ interface HeadingFieldsOptions {
|
|
|
163
174
|
required?: boolean;
|
|
164
175
|
/** Description shown under the eyebrow input. */
|
|
165
176
|
eyebrowDescription?: string;
|
|
177
|
+
/**
|
|
178
|
+
* Show the three fields only when this holds, e.g. unless the block floats.
|
|
179
|
+
* Pair it with `required: false`: a hidden required field can never be
|
|
180
|
+
* satisfied, and the block could not publish.
|
|
181
|
+
*/
|
|
182
|
+
condition?: Condition;
|
|
166
183
|
}
|
|
167
184
|
/**
|
|
168
185
|
* The eyebrow / title / description trio every marketing band opens with.
|
|
@@ -174,7 +191,8 @@ interface HeadingFieldsOptions {
|
|
|
174
191
|
*/
|
|
175
192
|
declare function headingFields({
|
|
176
193
|
required,
|
|
177
|
-
eyebrowDescription
|
|
194
|
+
eyebrowDescription,
|
|
195
|
+
condition
|
|
178
196
|
}?: HeadingFieldsOptions): Field[];
|
|
179
197
|
//#endregion
|
|
180
198
|
//#region src/fields/min-rows.d.ts
|
|
@@ -369,6 +387,24 @@ interface TestimonialMasonryBlockData extends BlockRow<"testimonialMasonry"> {
|
|
|
369
387
|
minItemsForFade?: number | null;
|
|
370
388
|
maxVisibleRows?: number | null;
|
|
371
389
|
}
|
|
390
|
+
interface StatsBandItemData {
|
|
391
|
+
value?: string | null;
|
|
392
|
+
label?: string | null;
|
|
393
|
+
href?: string | null;
|
|
394
|
+
wide?: boolean | null;
|
|
395
|
+
id?: string | null;
|
|
396
|
+
}
|
|
397
|
+
interface StatsBandBlockData extends BlockRow<"statsBand"> {
|
|
398
|
+
eyebrow?: string | null;
|
|
399
|
+
title?: string | null;
|
|
400
|
+
description?: string | null;
|
|
401
|
+
items?: StatsBandItemData[] | null;
|
|
402
|
+
/** A select, so the value is the digit as a string. */
|
|
403
|
+
columns?: ("2" | "3" | "4" | "5" | "6") | null;
|
|
404
|
+
tone?: ("card" | "plain") | null;
|
|
405
|
+
align?: ("start" | "center") | null;
|
|
406
|
+
overlap?: boolean | null;
|
|
407
|
+
}
|
|
372
408
|
interface NapDepartmentData {
|
|
373
409
|
name?: string | null;
|
|
374
410
|
departmentType?: string | null;
|
|
@@ -430,7 +466,7 @@ interface MegaMenuBlockData extends BlockRow<"megaMenu"> {
|
|
|
430
466
|
}
|
|
431
467
|
interface NavLinkBlockData extends BlockRow<"navLink">, LinkValue {}
|
|
432
468
|
/** Every block this package ships, as one union. */
|
|
433
|
-
type BisonBlockData = HeroBlockData | RichTextBlockData | ShowcasePanelsBlockData | ProcessStepsBlockData | FaqColumnsBlockData | TestimonialMasonryBlockData | NapBlockData | MegaMenuBlockData | NavLinkBlockData;
|
|
469
|
+
type BisonBlockData = HeroBlockData | RichTextBlockData | ShowcasePanelsBlockData | ProcessStepsBlockData | FaqColumnsBlockData | TestimonialMasonryBlockData | NapBlockData | StatsBandBlockData | MegaMenuBlockData | NavLinkBlockData;
|
|
434
470
|
/** The `blockType` of every block this package ships. */
|
|
435
471
|
type BisonBlockType = BisonBlockData["blockType"];
|
|
436
472
|
//#endregion
|
|
@@ -505,5 +541,5 @@ declare function sampleImage({
|
|
|
505
541
|
alt
|
|
506
542
|
}: SampleImageOptions): MediaDoc;
|
|
507
543
|
//#endregion
|
|
508
|
-
export { type BisonBlockData, type BisonBlockType, type BlockSamples, FaqColumnsBlock, type FaqColumnsBlockData, type FaqColumnsItemData, type HeadingFieldsOptions, HeroBlock, type HeroBlockData, type ImageFieldOptions, LinkBlock, type LinkFieldOptions, type LinkFieldsOptions, type LinkValue, MEGA_MENU_WIDTHS, MIN_ROWS_ARRAY_FIELD, type MediaDoc, type MediaValue, type MegaMenuBlockData, type MegaMenuBlockOptions, type MegaMenuColumnData, type MegaMenuLinkData, type MegaMenuOption, type MegaMenuSectionData, type MegaMenuWidthValue, NapBlock, type NapBlockData, type NapDepartmentData, type NavLinkBlockData, ProcessStepsBlock, type ProcessStepsBlockData, type ProcessStepsItemData, type ResolvedMedia, RichTextBlock, type RichTextBlockData, type RichTextContent, type SampleImageOptions, ShowcasePanelsBlock, type ShowcasePanelsBlockData, type ShowcasePanelsItemData, TestimonialMasonryBlock, type TestimonialMasonryBlockData, type TestimonialMasonryItemData, blockSamples, emptyRows, headingFields, imageField, linkField, linkFields, megaMenuBlock, megaMenuSampleOptions, resolveMedia, sampleImage, validateColumnWidths, validateRemWidth };
|
|
544
|
+
export { type BisonBlockData, type BisonBlockType, type BlockSamples, FaqColumnsBlock, type FaqColumnsBlockData, type FaqColumnsItemData, type HeadingFieldsOptions, HeroBlock, type HeroBlockData, type ImageFieldOptions, LinkBlock, type LinkFieldOptions, type LinkFieldsOptions, type LinkValue, MEGA_MENU_WIDTHS, MIN_ROWS_ARRAY_FIELD, type MediaDoc, type MediaValue, type MegaMenuBlockData, type MegaMenuBlockOptions, type MegaMenuColumnData, type MegaMenuLinkData, type MegaMenuOption, type MegaMenuSectionData, type MegaMenuWidthValue, NapBlock, type NapBlockData, type NapDepartmentData, type NavLinkBlockData, ProcessStepsBlock, type ProcessStepsBlockData, type ProcessStepsItemData, type ResolvedMedia, RichTextBlock, type RichTextBlockData, type RichTextContent, type SampleImageOptions, ShowcasePanelsBlock, type ShowcasePanelsBlockData, type ShowcasePanelsItemData, StatsBandBlock, type StatsBandBlockData, type StatsBandItemData, TestimonialMasonryBlock, type TestimonialMasonryBlockData, type TestimonialMasonryItemData, blockSamples, emptyRows, headingFields, imageField, linkField, linkFields, megaMenuBlock, megaMenuSampleOptions, resolveMedia, sampleImage, validateColumnWidths, validateRemWidth };
|
|
509
545
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/blocks/hero/config.ts","../src/blocks/rich-text/config.ts","../src/blocks/showcase-panels/config.ts","../src/blocks/process-steps/config.ts","../src/blocks/faq-columns/config.ts","../src/blocks/testimonial-masonry/config.ts","../src/blocks/nap/config.ts","../src/blocks/mega-menu/config.ts","../src/fields/image.ts","../src/fields/link.ts","../src/fields/heading.ts","../src/fields/min-rows.ts","../src/media.ts","../src/types.ts","../src/samples.ts","../src/blocks/mega-menu/sample.ts","../src/sample-image.ts"],"mappings":";;;;;AAcA;;;;;;;cAAa,SAAA,EAAW,KAAA;;;;cCXX,aAAA,EAAe,KAAA;;;;cCGf,mBAAA,EAAqB,KAAA;;;;cCArB,iBAAA,EAAmB,KAAA;;;;cCAnB,eAAA,EAAiB,KAAA;;;;cCEjB,uBAAA,EAAyB,KAAA;;;;;ALMtC;;;;;;cMFa,QAAA,EAAU,KAAA;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/blocks/hero/config.ts","../src/blocks/rich-text/config.ts","../src/blocks/showcase-panels/config.ts","../src/blocks/process-steps/config.ts","../src/blocks/faq-columns/config.ts","../src/blocks/testimonial-masonry/config.ts","../src/blocks/nap/config.ts","../src/blocks/stats-band/config.ts","../src/blocks/mega-menu/config.ts","../src/fields/image.ts","../src/fields/link.ts","../src/fields/heading.ts","../src/fields/min-rows.ts","../src/media.ts","../src/types.ts","../src/samples.ts","../src/blocks/mega-menu/sample.ts","../src/sample-image.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -323,21 +323,27 @@ const ProcessStepsBlock = {
|
|
|
323
323
|
* puts the least-optional copy behind a click. The field names match the
|
|
324
324
|
* `@bison-lab/ui` prop names so the renderers stay a pass-through.
|
|
325
325
|
*/
|
|
326
|
-
function headingFields({ required = true, eyebrowDescription = "Small label above the heading. Leave empty to hide the row." } = {}) {
|
|
326
|
+
function headingFields({ required = true, eyebrowDescription = "Small label above the heading. Leave empty to hide the row.", condition } = {}) {
|
|
327
|
+
const when = condition ? { condition } : {};
|
|
327
328
|
return [
|
|
328
329
|
{
|
|
329
330
|
name: "eyebrow",
|
|
330
331
|
type: "text",
|
|
331
|
-
admin: {
|
|
332
|
+
admin: {
|
|
333
|
+
description: eyebrowDescription,
|
|
334
|
+
...when
|
|
335
|
+
}
|
|
332
336
|
},
|
|
333
337
|
{
|
|
334
338
|
name: "title",
|
|
335
339
|
type: "text",
|
|
336
|
-
required
|
|
340
|
+
required,
|
|
341
|
+
admin: when
|
|
337
342
|
},
|
|
338
343
|
{
|
|
339
344
|
name: "description",
|
|
340
|
-
type: "textarea"
|
|
345
|
+
type: "textarea",
|
|
346
|
+
admin: when
|
|
341
347
|
}
|
|
342
348
|
];
|
|
343
349
|
}
|
|
@@ -641,6 +647,177 @@ const NapBlock = {
|
|
|
641
647
|
]
|
|
642
648
|
};
|
|
643
649
|
//#endregion
|
|
650
|
+
//#region src/fields/row-limits.ts
|
|
651
|
+
/**
|
|
652
|
+
* A custom `validate` replaces Payload's stock array check, so any array
|
|
653
|
+
* with its own rule re-applies the row limits first or `minRows` and
|
|
654
|
+
* `maxRows` stop being enforced. Same messages as the stock check, through
|
|
655
|
+
* the request's translator when the admin supplies one.
|
|
656
|
+
*/
|
|
657
|
+
function rowLimits(value, { minRows, maxRows, required, req }) {
|
|
658
|
+
const count = value?.length ?? 0;
|
|
659
|
+
const t = req?.t;
|
|
660
|
+
if (required && count === 0) return t ? t("validation:required") : "This field is required.";
|
|
661
|
+
if (minRows && count < minRows) return t ? t("validation:requiresAtLeast", {
|
|
662
|
+
count: minRows,
|
|
663
|
+
label: t("general:rows")
|
|
664
|
+
}) : `This field requires at least ${minRows} rows.`;
|
|
665
|
+
if (maxRows && count > maxRows) return t ? t("validation:requiresNoMoreThan", {
|
|
666
|
+
count: maxRows,
|
|
667
|
+
label: t("general:rows")
|
|
668
|
+
}) : `This field requires no more than ${maxRows} rows.`;
|
|
669
|
+
return true;
|
|
670
|
+
}
|
|
671
|
+
//#endregion
|
|
672
|
+
//#region src/blocks/stats-band/config.ts
|
|
673
|
+
/**
|
|
674
|
+
* The rule on `wide`: on phones the band is two per row, so only an odd
|
|
675
|
+
* count has a stat on a row of its own, only one stat can take it, and it
|
|
676
|
+
* has to be a stat that starts a row (the 1st, 3rd or 5th), since a full-row
|
|
677
|
+
* cell beside another cell would leave a hole. The array's own `validate`,
|
|
678
|
+
* so the editor sees the message as they build, and Payload runs it again on
|
|
679
|
+
* publish.
|
|
680
|
+
*/
|
|
681
|
+
const validateWideFlag = (value, options) => {
|
|
682
|
+
const limits = rowLimits(value, options);
|
|
683
|
+
if (limits !== true) return limits;
|
|
684
|
+
const rows = value ?? [];
|
|
685
|
+
const wide = rows.flatMap((row, i) => row?.wide ? [i] : []);
|
|
686
|
+
if (wide.length > 1) return "Only one stat can be full width on phones.";
|
|
687
|
+
if (wide.length === 0) return true;
|
|
688
|
+
if (rows.length % 2 === 0) return "Full width on phones only applies to an odd number of stats. With an even count every row is already full.";
|
|
689
|
+
if (wide[0] % 2 !== 0) return "Only a stat that starts a phone row can be full width: the 1st, 3rd or 5th. Move it up or down one place, or flag another.";
|
|
690
|
+
return true;
|
|
691
|
+
};
|
|
692
|
+
/**
|
|
693
|
+
* An overlapping band is headless: it floats across the seam as a card, and a
|
|
694
|
+
* heading pulled up into the block above would land on the wrong surface.
|
|
695
|
+
* The heading fields disappear from the admin the moment `overlap` is on,
|
|
696
|
+
* and the renderer ignores them if they were filled in first.
|
|
697
|
+
*/
|
|
698
|
+
const unlessOverlap = (_data, siblingData) => !siblingData?.overlap;
|
|
699
|
+
/**
|
|
700
|
+
* A strip of figures: the facts a visitor should take in at a glance.
|
|
701
|
+
*
|
|
702
|
+
* The count, the order and the desktop column count are the editor's. The
|
|
703
|
+
* phone and tablet layouts are the library's: two per row and three per row,
|
|
704
|
+
* with `wide` naming the one stat that takes a full phone row when the count
|
|
705
|
+
* is odd.
|
|
706
|
+
*/
|
|
707
|
+
const StatsBandBlock = {
|
|
708
|
+
slug: "statsBand",
|
|
709
|
+
interfaceName: "StatsBandBlock",
|
|
710
|
+
labels: {
|
|
711
|
+
singular: "Stats Band",
|
|
712
|
+
plural: "Stats Bands"
|
|
713
|
+
},
|
|
714
|
+
fields: [
|
|
715
|
+
...headingFields({
|
|
716
|
+
required: false,
|
|
717
|
+
eyebrowDescription: "Small label above the heading. The heading and eyebrow are optional; without them the band stands alone.",
|
|
718
|
+
condition: unlessOverlap
|
|
719
|
+
}),
|
|
720
|
+
{
|
|
721
|
+
name: "items",
|
|
722
|
+
type: "array",
|
|
723
|
+
required: true,
|
|
724
|
+
minRows: 2,
|
|
725
|
+
maxRows: 6,
|
|
726
|
+
defaultValue: emptyRows(2),
|
|
727
|
+
labels: {
|
|
728
|
+
singular: "Stat",
|
|
729
|
+
plural: "Stats"
|
|
730
|
+
},
|
|
731
|
+
admin: { components: { Field: MIN_ROWS_ARRAY_FIELD } },
|
|
732
|
+
validate: validateWideFlag,
|
|
733
|
+
fields: [
|
|
734
|
+
{
|
|
735
|
+
name: "value",
|
|
736
|
+
type: "text",
|
|
737
|
+
required: true,
|
|
738
|
+
admin: { description: "The figure, as it should read: \"98%\", \"12,000+\", \"L1–S1\"." }
|
|
739
|
+
},
|
|
740
|
+
{
|
|
741
|
+
name: "label",
|
|
742
|
+
type: "textarea",
|
|
743
|
+
required: true
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
name: "href",
|
|
747
|
+
type: "text",
|
|
748
|
+
admin: { description: "Optional. Makes the whole stat a link: a site path (\"/outcomes\") or a full URL." }
|
|
749
|
+
},
|
|
750
|
+
{
|
|
751
|
+
name: "wide",
|
|
752
|
+
type: "checkbox",
|
|
753
|
+
label: "Full width on phones",
|
|
754
|
+
defaultValue: false,
|
|
755
|
+
admin: { description: "Phones show two per row. With an odd number of stats, this one takes a row to itself. Only the 1st, 3rd or 5th stat can." }
|
|
756
|
+
}
|
|
757
|
+
]
|
|
758
|
+
},
|
|
759
|
+
{
|
|
760
|
+
name: "columns",
|
|
761
|
+
type: "select",
|
|
762
|
+
defaultValue: "4",
|
|
763
|
+
options: [
|
|
764
|
+
{
|
|
765
|
+
label: "2",
|
|
766
|
+
value: "2"
|
|
767
|
+
},
|
|
768
|
+
{
|
|
769
|
+
label: "3",
|
|
770
|
+
value: "3"
|
|
771
|
+
},
|
|
772
|
+
{
|
|
773
|
+
label: "4",
|
|
774
|
+
value: "4"
|
|
775
|
+
},
|
|
776
|
+
{
|
|
777
|
+
label: "5",
|
|
778
|
+
value: "5"
|
|
779
|
+
},
|
|
780
|
+
{
|
|
781
|
+
label: "6",
|
|
782
|
+
value: "6"
|
|
783
|
+
}
|
|
784
|
+
],
|
|
785
|
+
admin: { description: "From large screens up, and never more than there are stats. Phones show two per row and tablets three." }
|
|
786
|
+
},
|
|
787
|
+
{
|
|
788
|
+
name: "tone",
|
|
789
|
+
type: "select",
|
|
790
|
+
defaultValue: "card",
|
|
791
|
+
options: [{
|
|
792
|
+
label: "Card (bordered, raised)",
|
|
793
|
+
value: "card"
|
|
794
|
+
}, {
|
|
795
|
+
label: "Plain (dividers only)",
|
|
796
|
+
value: "plain"
|
|
797
|
+
}]
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
name: "align",
|
|
801
|
+
type: "select",
|
|
802
|
+
defaultValue: "start",
|
|
803
|
+
options: [{
|
|
804
|
+
label: "Left",
|
|
805
|
+
value: "start"
|
|
806
|
+
}, {
|
|
807
|
+
label: "Centred",
|
|
808
|
+
value: "center"
|
|
809
|
+
}]
|
|
810
|
+
},
|
|
811
|
+
{
|
|
812
|
+
name: "overlap",
|
|
813
|
+
type: "checkbox",
|
|
814
|
+
label: "Float over the seam with the block above",
|
|
815
|
+
defaultValue: false,
|
|
816
|
+
admin: { description: "The band sits across the join between the block above and the block below. Both make room for it automatically. A floating band is headless: the heading fields above are hidden while this is on." }
|
|
817
|
+
}
|
|
818
|
+
]
|
|
819
|
+
};
|
|
820
|
+
//#endregion
|
|
644
821
|
//#region src/blocks/mega-menu/rem-width.ts
|
|
645
822
|
/**
|
|
646
823
|
* The one rule for a typed panel width, shared by the config's validator and
|
|
@@ -676,25 +853,6 @@ const TWELFTHS = {
|
|
|
676
853
|
"100": 12
|
|
677
854
|
};
|
|
678
855
|
/**
|
|
679
|
-
* A custom `validate` replaces Payload's stock array check, so the row limits
|
|
680
|
-
* are re-applied here or five columns would pass. Same messages as the stock
|
|
681
|
-
* check, through the request's translator when the admin supplies one.
|
|
682
|
-
*/
|
|
683
|
-
function rowLimits(value, { minRows, maxRows, required, req }) {
|
|
684
|
-
const count = value?.length ?? 0;
|
|
685
|
-
const t = req?.t;
|
|
686
|
-
if (required && count === 0) return t ? t("validation:required") : "This field is required.";
|
|
687
|
-
if (minRows && count < minRows) return t ? t("validation:requiresAtLeast", {
|
|
688
|
-
count: minRows,
|
|
689
|
-
label: t("general:rows")
|
|
690
|
-
}) : `This field requires at least ${minRows} rows.`;
|
|
691
|
-
if (maxRows && count > maxRows) return t ? t("validation:requiresNoMoreThan", {
|
|
692
|
-
count: maxRows,
|
|
693
|
-
label: t("general:rows")
|
|
694
|
-
}) : `This field requires no more than ${maxRows} rows.`;
|
|
695
|
-
return true;
|
|
696
|
-
}
|
|
697
|
-
/**
|
|
698
856
|
* The rule on `columns`: read as fractions, the widths must total 100%. It is
|
|
699
857
|
* the array's own `validate`, so the editor sees the message as they build,
|
|
700
858
|
* and Payload runs field validation again on publish (only draft saves skip
|
|
@@ -1422,6 +1580,50 @@ const showcasePanelsSample = {
|
|
|
1422
1580
|
defaultActiveIndex: 0
|
|
1423
1581
|
};
|
|
1424
1582
|
//#endregion
|
|
1583
|
+
//#region src/blocks/stats-band/sample.ts
|
|
1584
|
+
/**
|
|
1585
|
+
* Four figures, the count the strip was designed around: one row on a
|
|
1586
|
+
* desktop, two by two on a tablet and a phone. `wide` is set (to `false`) so
|
|
1587
|
+
* the preview exercises the field, and an even count is where it is ignored.
|
|
1588
|
+
* `overlap` is off so the heading shows: a floating band is headless, and a
|
|
1589
|
+
* preview page has no hero for it to float over.
|
|
1590
|
+
*/
|
|
1591
|
+
const statsBandSample = {
|
|
1592
|
+
id: "sample-stats-band",
|
|
1593
|
+
blockType: "statsBand",
|
|
1594
|
+
eyebrow: "At a glance",
|
|
1595
|
+
title: "The clinic in numbers",
|
|
1596
|
+
description: "What a year looks like across our two rooms, counted from the front desk rather than estimated.",
|
|
1597
|
+
items: [
|
|
1598
|
+
{
|
|
1599
|
+
id: "sample-stat-pain",
|
|
1600
|
+
value: "94%",
|
|
1601
|
+
label: "of patients report less pain by their sixth session.",
|
|
1602
|
+
href: "/outcomes",
|
|
1603
|
+
wide: false
|
|
1604
|
+
},
|
|
1605
|
+
{
|
|
1606
|
+
id: "sample-stat-visits",
|
|
1607
|
+
value: "4,200+",
|
|
1608
|
+
label: "appointments a year across two treatment rooms."
|
|
1609
|
+
},
|
|
1610
|
+
{
|
|
1611
|
+
id: "sample-stat-wait",
|
|
1612
|
+
value: "15 min",
|
|
1613
|
+
label: "average wait from the front desk to the treatment room."
|
|
1614
|
+
},
|
|
1615
|
+
{
|
|
1616
|
+
id: "sample-stat-years",
|
|
1617
|
+
value: "12",
|
|
1618
|
+
label: "years in the same building, on the same street."
|
|
1619
|
+
}
|
|
1620
|
+
],
|
|
1621
|
+
columns: "4",
|
|
1622
|
+
tone: "card",
|
|
1623
|
+
align: "start",
|
|
1624
|
+
overlap: false
|
|
1625
|
+
};
|
|
1626
|
+
//#endregion
|
|
1425
1627
|
//#region src/blocks/testimonial-masonry/sample.ts
|
|
1426
1628
|
function avatar(name) {
|
|
1427
1629
|
return sampleImage({
|
|
@@ -1520,10 +1722,11 @@ const blockSamples = {
|
|
|
1520
1722
|
maxVisibleRows: 2
|
|
1521
1723
|
},
|
|
1522
1724
|
nap: napSample,
|
|
1725
|
+
statsBand: statsBandSample,
|
|
1523
1726
|
megaMenu: megaMenuSample,
|
|
1524
1727
|
navLink: navLinkSample
|
|
1525
1728
|
};
|
|
1526
1729
|
//#endregion
|
|
1527
|
-
export { FaqColumnsBlock, HeroBlock, LinkBlock, MEGA_MENU_WIDTHS, MIN_ROWS_ARRAY_FIELD, NapBlock, ProcessStepsBlock, RichTextBlock, ShowcasePanelsBlock, TestimonialMasonryBlock, blockSamples, emptyRows, headingFields, imageField, linkField, linkFields, megaMenuBlock, megaMenuSampleOptions, resolveMedia, sampleImage, validateColumnWidths, validateRemWidth };
|
|
1730
|
+
export { FaqColumnsBlock, HeroBlock, LinkBlock, MEGA_MENU_WIDTHS, MIN_ROWS_ARRAY_FIELD, NapBlock, ProcessStepsBlock, RichTextBlock, ShowcasePanelsBlock, StatsBandBlock, TestimonialMasonryBlock, blockSamples, emptyRows, headingFields, imageField, linkField, linkFields, megaMenuBlock, megaMenuSampleOptions, resolveMedia, sampleImage, validateColumnWidths, validateRemWidth };
|
|
1528
1731
|
|
|
1529
1732
|
//# sourceMappingURL=index.mjs.map
|