@bison-lab/payload-blocks 2.0.0 → 3.1.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 +81 -6
- package/dist/admin.d.mts +27 -0
- package/dist/admin.d.mts.map +1 -0
- package/dist/admin.mjs +82 -0
- package/dist/admin.mjs.map +1 -0
- package/dist/index.d.mts +78 -12
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +473 -44
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +1 -1
- package/dist/react.mjs +1 -12
- package/dist/react.mjs.map +1 -1
- package/dist/rich-text.d.mts +1 -1
- package/dist/{types-BvRvDCDT.d.mts → types-BBumyFd-.d.mts} +1 -12
- package/dist/{types-BvRvDCDT.d.mts.map → types-BBumyFd-.d.mts.map} +1 -1
- package/package.json +12 -3
package/README.md
CHANGED
|
@@ -12,15 +12,17 @@ pnpm add @bison-lab/payload-blocks
|
|
|
12
12
|
|
|
13
13
|
Peers: `payload` (required); `react`, `react-dom`, `@bison-lab/ui` and
|
|
14
14
|
`@payloadcms/richtext-lexical` (needed by the renderer entries, optional if you
|
|
15
|
-
only use the configs)
|
|
15
|
+
only use the configs); `@payloadcms/ui` (needed by the admin entry, which every
|
|
16
|
+
Payload site already has).
|
|
16
17
|
|
|
17
|
-
##
|
|
18
|
+
## Four entry points, and why
|
|
18
19
|
|
|
19
20
|
| Import | Contents | Runs where |
|
|
20
21
|
| --- | --- | --- |
|
|
21
22
|
| `@bison-lab/payload-blocks` | Block configs, field builders, row types, `resolveMedia` | Node. This is what `payload.config.ts` imports, and it touches no React. |
|
|
22
23
|
| `@bison-lab/payload-blocks/react` | Renderers, `RenderBlocks`, the rendering types | Client (`"use client"`). |
|
|
23
24
|
| `@bison-lab/payload-blocks/rich-text` | The `richText` renderer, alone | Client. Split out because it is the only thing that needs `@payloadcms/richtext-lexical`. |
|
|
25
|
+
| `@bison-lab/payload-blocks/admin` | `MinRowsArrayField`, the admin field the configs reference by path | Client, inside the Payload admin. Resolved through the site's import map, never imported by hand. |
|
|
24
26
|
|
|
25
27
|
The renderers are client components because the blocks they render are: every
|
|
26
28
|
`@bison-lab/ui` export is a client reference, and these blocks are interactive
|
|
@@ -62,7 +64,30 @@ export const Pages: CollectionConfig = {
|
|
|
62
64
|
}
|
|
63
65
|
```
|
|
64
66
|
|
|
65
|
-
Then `payload generate:types
|
|
67
|
+
Then `payload generate:types`, `payload generate:importmap` and
|
|
68
|
+
`payload migrate:create`.
|
|
69
|
+
|
|
70
|
+
The import map step is what wires the admin field. Every array in this package
|
|
71
|
+
with a `minRows` opens with that many empty rows and names
|
|
72
|
+
`@bison-lab/payload-blocks/admin#MinRowsArrayField` as its field component,
|
|
73
|
+
which refuses to remove a row once the count is down to the minimum (Payload
|
|
74
|
+
gates Add on `maxRows` but never Remove on `minRows`). Until the import map
|
|
75
|
+
has the entry Payload logs the miss and renders its stock array field, so an
|
|
76
|
+
upgrade that forgets the step degrades to the old behaviour rather than
|
|
77
|
+
breaking. A site can put the same field on its own arrays:
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import { MIN_ROWS_ARRAY_FIELD, emptyRows } from '@bison-lab/payload-blocks'
|
|
81
|
+
|
|
82
|
+
{
|
|
83
|
+
name: 'links',
|
|
84
|
+
type: 'array',
|
|
85
|
+
minRows: 2,
|
|
86
|
+
defaultValue: emptyRows(2),
|
|
87
|
+
admin: { components: { Field: MIN_ROWS_ARRAY_FIELD } },
|
|
88
|
+
fields: [...],
|
|
89
|
+
}
|
|
90
|
+
```
|
|
66
91
|
|
|
67
92
|
**2. Own the registry.**
|
|
68
93
|
|
|
@@ -137,8 +162,8 @@ renders.
|
|
|
137
162
|
| --- | --- | --- |
|
|
138
163
|
| `hero` | plain markup | No `@bison-lab/ui` counterpart. Override this entry with your own. |
|
|
139
164
|
| `richText` | `RichText` (Lexical) | From `/rich-text`. |
|
|
140
|
-
| `showcasePanels` | `ShowcasePanelsBlock` | 3–6 panels, each with a required image. |
|
|
141
|
-
| `processSteps` | `ProcessStepsBlock` | 3–6 ordered steps; advances on a timer. |
|
|
165
|
+
| `showcasePanels` | `ShowcasePanelsBlock` | 3–6 panels, each with a required image. Opens with three. |
|
|
166
|
+
| `processSteps` | `ProcessStepsBlock` | 3–6 ordered steps, numbered by position; advances on a timer. Opens with three. |
|
|
142
167
|
| `faqColumns` | `FAQColumnsBlock` | Answers are plain text, not Lexical — see the config for why. |
|
|
143
168
|
| `testimonialMasonry` | `TestimonialMasonry` | Avatars fall back to initials. |
|
|
144
169
|
| `nap` | `NapBlock` + `JsonLd` | Emits schema.org `LocalBusiness`; `phoneE164` is what the `tel:` link uses. |
|
|
@@ -147,6 +172,44 @@ A row whose upload has not resolved is dropped rather than rendered empty, and a
|
|
|
147
172
|
block left with nothing to show renders nothing at all. Draft saves skip Payload
|
|
148
173
|
validation, so live preview genuinely hands renderers incomplete rows.
|
|
149
174
|
|
|
175
|
+
## Samples
|
|
176
|
+
|
|
177
|
+
Every block ships a sample row, so it can be rendered with no CMS behind it:
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
import { blockSamples } from '@bison-lab/payload-blocks'
|
|
181
|
+
|
|
182
|
+
blockSamples.showcasePanels // a ShowcasePanelsBlockData with three panels
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
`blockSamples` is one map keyed by `blockType`, typed per block
|
|
186
|
+
(`BlockSamples`) and assignable to `Record<BisonBlockType, BisonBlockData>`.
|
|
187
|
+
It comes from the main entry and is React-free, so a Global's field config and
|
|
188
|
+
a route handler can both read it. The Block library page that renders these
|
|
189
|
+
live for an admin is a separate piece of work (BIS-52); this package ships the
|
|
190
|
+
data, not the page.
|
|
191
|
+
|
|
192
|
+
Each sample has realistic copy at the length the layout was designed for
|
|
193
|
+
(three showcase panels, four process steps, six testimonials), and sets every
|
|
194
|
+
field its config has at least once, so a preview shows the block's full range.
|
|
195
|
+
|
|
196
|
+
**Images travel with the sample.** No site media exists in a preview, so every
|
|
197
|
+
upload in a sample is an inline SVG `data:` URL in the `MediaDoc` shape, with
|
|
198
|
+
`width` and `height` set. `resolveMedia` accepts it as-is, and the `data:`
|
|
199
|
+
scheme is how an adapter knows what it has: `next/image` marks a `data:` src
|
|
200
|
+
`unoptimized` by itself, so the adapter above needs no special case. A site
|
|
201
|
+
that wants the same placeholders for its own blocks can build them with
|
|
202
|
+
`sampleImage({ label, width, height, alt })`.
|
|
203
|
+
|
|
204
|
+
The `nap` sample sets `emitJsonLd: false`. The block emits schema.org
|
|
205
|
+
`LocalBusiness` by default, and a preview must not put a fictional clinic into
|
|
206
|
+
a site's structured data.
|
|
207
|
+
|
|
208
|
+
Only what this package ships has a sample here. A site's own blocks supply
|
|
209
|
+
theirs through the Block library factory, whose option BIS-52 names. The hero
|
|
210
|
+
family (BIS-45) adds a sample per hero as each one lands; the plain `hero`
|
|
211
|
+
renderer's is here.
|
|
212
|
+
|
|
150
213
|
## Conventions for contributors
|
|
151
214
|
|
|
152
215
|
- **No generated types.** `src/types.ts` hand-writes each block's row shape to
|
|
@@ -155,9 +218,21 @@ validation, so live preview genuinely hands renderers incomplete rows.
|
|
|
155
218
|
interface here has an index signature — TypeScript will not assign an
|
|
156
219
|
interface to a type that does.
|
|
157
220
|
- **`src/index.ts` stays React-free.** Payload loads a site's config outside the
|
|
158
|
-
bundler, in `migrate`, `generate:types` and the admin server.
|
|
221
|
+
bundler, in `migrate`, `generate:types` and the admin server. An admin
|
|
222
|
+
component is referenced from a config by its import-map string
|
|
223
|
+
(`MIN_ROWS_ARRAY_FIELD`), never imported.
|
|
224
|
+
- **`src/admin.tsx` is the only entry that loads `@payloadcms/ui`.** It wraps
|
|
225
|
+
Payload's stock fields rather than re-implementing them, so an upgrade
|
|
226
|
+
carries every upstream behaviour along. Editor-facing copy, accessible names
|
|
227
|
+
and control text are not config fields: the `@bison-lab/ui` defaults stand.
|
|
159
228
|
- **`cn()` is off limits.** It is a client-only export of `@bison-lab/ui`; use
|
|
160
229
|
the local `cx()`.
|
|
161
230
|
- **Changing a field is a schema change in every consuming site.** Update
|
|
162
231
|
`src/types.ts` and the field-name lock in `src/__tests__/configs.test.ts` in
|
|
163
232
|
the same change, and say "run `payload migrate:create`" in the changeset.
|
|
233
|
+
- **Every block ships a sample.** A new block adds `src/blocks/<slug>/sample.ts`
|
|
234
|
+
beside its `config.ts` and `component.tsx`, typed to its row shape, using
|
|
235
|
+
`sampleImage` for every upload, and registers it in `src/samples.ts`.
|
|
236
|
+
`src/__tests__/samples.test.tsx` fails until it does, and again if the sample
|
|
237
|
+
leaves a config field unset. A new field on an existing block means its
|
|
238
|
+
sample sets that field too.
|
package/dist/admin.d.mts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
|
|
2
|
+
import { ArrayFieldClientComponent } from "payload";
|
|
3
|
+
|
|
4
|
+
//#region src/admin/min-rows-array-field.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Payload's array field, with *Remove* refused once the rows are down to
|
|
7
|
+
* `minRows`.
|
|
8
|
+
*
|
|
9
|
+
* This wraps the stock `ArrayField` rather than re-implementing it, so every
|
|
10
|
+
* upstream behaviour (sorting, copy/paste, collapse, localisation) stays put
|
|
11
|
+
* and a Payload upgrade carries it along. The catch is where the row menu
|
|
12
|
+
* lives: Payload portals it into `document.body`, out of reach of any CSS or
|
|
13
|
+
* form context this wrapper could scope. What still reaches the wrapper is
|
|
14
|
+
* the React event: synthetic events bubble through portals along the
|
|
15
|
+
* component tree, so a capture handler here sees the click on *Remove*
|
|
16
|
+
* before the menu's own handler does, and can stop it.
|
|
17
|
+
*
|
|
18
|
+
* Because the menu is portaled, the DOM cannot say whether a given *Remove*
|
|
19
|
+
* belongs to this array or to an array nested inside one of its rows. The
|
|
20
|
+
* trigger that opened the menu *is* in the DOM, though, and every menu opens
|
|
21
|
+
* from its trigger. So the handler remembers, per menu opening, whether the
|
|
22
|
+
* trigger sat directly in this field, and only gates the *Remove* that follows.
|
|
23
|
+
*/
|
|
24
|
+
declare const MinRowsArrayField: ArrayFieldClientComponent;
|
|
25
|
+
//#endregion
|
|
26
|
+
export { MinRowsArrayField };
|
|
27
|
+
//# sourceMappingURL=admin.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.d.mts","names":[],"sources":["../src/admin/min-rows-array-field.tsx"],"mappings":";;;;;;AAuBA;;;;;;;;;;;;;;;;;cAAa,iBAAA,EAAmB,yBAAA"}
|
package/dist/admin.mjs
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { ArrayField, toast, useField, useTranslation } from "@payloadcms/ui";
|
|
4
|
+
import { useCallback, useRef } from "react";
|
|
5
|
+
//#region src/admin/min-rows-array-field.tsx
|
|
6
|
+
/**
|
|
7
|
+
* Payload's array field, with *Remove* refused once the rows are down to
|
|
8
|
+
* `minRows`.
|
|
9
|
+
*
|
|
10
|
+
* This wraps the stock `ArrayField` rather than re-implementing it, so every
|
|
11
|
+
* upstream behaviour (sorting, copy/paste, collapse, localisation) stays put
|
|
12
|
+
* and a Payload upgrade carries it along. The catch is where the row menu
|
|
13
|
+
* lives: Payload portals it into `document.body`, out of reach of any CSS or
|
|
14
|
+
* form context this wrapper could scope. What still reaches the wrapper is
|
|
15
|
+
* the React event: synthetic events bubble through portals along the
|
|
16
|
+
* component tree, so a capture handler here sees the click on *Remove*
|
|
17
|
+
* before the menu's own handler does, and can stop it.
|
|
18
|
+
*
|
|
19
|
+
* Because the menu is portaled, the DOM cannot say whether a given *Remove*
|
|
20
|
+
* belongs to this array or to an array nested inside one of its rows. The
|
|
21
|
+
* trigger that opened the menu *is* in the DOM, though, and every menu opens
|
|
22
|
+
* from its trigger. So the handler remembers, per menu opening, whether the
|
|
23
|
+
* trigger sat directly in this field, and only gates the *Remove* that follows.
|
|
24
|
+
*/
|
|
25
|
+
const MinRowsArrayField = (props) => {
|
|
26
|
+
const { field, path: pathFromProps } = props;
|
|
27
|
+
const minRows = field.minRows ?? (field.required ? 1 : 0);
|
|
28
|
+
const { rows = [] } = useField({
|
|
29
|
+
hasRows: true,
|
|
30
|
+
potentiallyStalePath: pathFromProps
|
|
31
|
+
});
|
|
32
|
+
const { i18n, t } = useTranslation();
|
|
33
|
+
const rootRef = useRef(null);
|
|
34
|
+
const menuIsOurs = useRef(false);
|
|
35
|
+
return /* @__PURE__ */ jsx("div", {
|
|
36
|
+
ref: rootRef,
|
|
37
|
+
onClickCapture: useCallback((event) => {
|
|
38
|
+
const target = event.target;
|
|
39
|
+
if (!(target instanceof Element)) return;
|
|
40
|
+
const trigger = target.closest(".array-actions__button");
|
|
41
|
+
if (trigger) {
|
|
42
|
+
const owner = trigger.closest(".array-field, .blocks-field");
|
|
43
|
+
menuIsOurs.current = owner !== null && owner === rootRef.current?.querySelector(".array-field");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (!target.closest(".array-actions__remove")) return;
|
|
47
|
+
if (!menuIsOurs.current || rows.length > minRows) return;
|
|
48
|
+
event.preventDefault();
|
|
49
|
+
event.stopPropagation();
|
|
50
|
+
toast.error(t("validation:requiresAtLeast", {
|
|
51
|
+
count: minRows,
|
|
52
|
+
label: rowLabel(field, minRows, i18n.language) ?? t(minRows > 1 ? "general:rows" : "general:row")
|
|
53
|
+
}));
|
|
54
|
+
}, [
|
|
55
|
+
field,
|
|
56
|
+
i18n.language,
|
|
57
|
+
minRows,
|
|
58
|
+
rows.length,
|
|
59
|
+
t
|
|
60
|
+
]),
|
|
61
|
+
children: /* @__PURE__ */ jsx(ArrayField, { ...props })
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* The word for a row, as Payload's own "requires at least" banner picks it:
|
|
66
|
+
* the plural label above one, the singular otherwise, the field label failing
|
|
67
|
+
* both. Client-side labels are static — a string or a per-language record.
|
|
68
|
+
*/
|
|
69
|
+
function rowLabel(field, minRows, language) {
|
|
70
|
+
return staticLabel(minRows > 1 ? field.labels?.plural : field.labels?.singular, language) ?? staticLabel(field.label, language);
|
|
71
|
+
}
|
|
72
|
+
function staticLabel(label, language) {
|
|
73
|
+
if (typeof label === "string") return label;
|
|
74
|
+
if (label && typeof label === "object") {
|
|
75
|
+
const byLanguage = label;
|
|
76
|
+
return byLanguage[language] ?? byLanguage.en ?? Object.values(byLanguage)[0];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
export { MinRowsArrayField };
|
|
81
|
+
|
|
82
|
+
//# sourceMappingURL=admin.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.mjs","names":[],"sources":["../src/admin/min-rows-array-field.tsx"],"sourcesContent":["import { ArrayField, toast, useField, useTranslation } from \"@payloadcms/ui\";\nimport type { ArrayFieldClientComponent, ArrayFieldClientProps } from \"payload\";\nimport { useCallback, useRef } from \"react\";\n\n/**\n * Payload's array field, with *Remove* refused once the rows are down to\n * `minRows`.\n *\n * This wraps the stock `ArrayField` rather than re-implementing it, so every\n * upstream behaviour (sorting, copy/paste, collapse, localisation) stays put\n * and a Payload upgrade carries it along. The catch is where the row menu\n * lives: Payload portals it into `document.body`, out of reach of any CSS or\n * form context this wrapper could scope. What still reaches the wrapper is\n * the React event: synthetic events bubble through portals along the\n * component tree, so a capture handler here sees the click on *Remove*\n * before the menu's own handler does, and can stop it.\n *\n * Because the menu is portaled, the DOM cannot say whether a given *Remove*\n * belongs to this array or to an array nested inside one of its rows. The\n * trigger that opened the menu *is* in the DOM, though, and every menu opens\n * from its trigger. So the handler remembers, per menu opening, whether the\n * trigger sat directly in this field, and only gates the *Remove* that follows.\n */\nexport const MinRowsArrayField: ArrayFieldClientComponent = (props) => {\n const { field, path: pathFromProps } = props;\n const minRows = field.minRows ?? (field.required ? 1 : 0);\n\n const { rows = [] } = useField({\n hasRows: true,\n potentiallyStalePath: pathFromProps,\n });\n const { i18n, t } = useTranslation();\n\n const rootRef = useRef<HTMLDivElement>(null);\n const menuIsOurs = useRef(false);\n\n const onClickCapture = useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const trigger = target.closest(\".array-actions__button\");\n if (trigger) {\n // The nearest array or blocks field around the trigger is the field\n // whose menu is opening. Ours is the first one inside the wrapper.\n const owner = trigger.closest(\".array-field, .blocks-field\");\n menuIsOurs.current =\n owner !== null && owner === rootRef.current?.querySelector(\".array-field\");\n return;\n }\n\n if (!target.closest(\".array-actions__remove\")) return;\n if (!menuIsOurs.current || rows.length > minRows) return;\n\n event.preventDefault();\n event.stopPropagation();\n toast.error(\n t(\"validation:requiresAtLeast\", {\n count: minRows,\n label: rowLabel(field, minRows, i18n.language) ??\n t(minRows > 1 ? \"general:rows\" : \"general:row\"),\n }),\n );\n },\n [field, i18n.language, minRows, rows.length, t],\n );\n\n return (\n <div ref={rootRef} onClickCapture={onClickCapture}>\n <ArrayField {...props} />\n </div>\n );\n};\n\n/**\n * The word for a row, as Payload's own \"requires at least\" banner picks it:\n * the plural label above one, the singular otherwise, the field label failing\n * both. Client-side labels are static — a string or a per-language record.\n */\nfunction rowLabel(\n field: ArrayFieldClientProps[\"field\"],\n minRows: number,\n language: string,\n): string | undefined {\n const label = minRows > 1 ? field.labels?.plural : field.labels?.singular;\n return staticLabel(label, language) ?? staticLabel(field.label, language);\n}\n\nfunction staticLabel(label: unknown, language: string): string | undefined {\n if (typeof label === \"string\") return label;\n if (label && typeof label === \"object\") {\n const byLanguage = label as Record<string, string | undefined>;\n return byLanguage[language] ?? byLanguage.en ?? Object.values(byLanguage)[0];\n }\n return undefined;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAuBA,MAAa,qBAAgD,UAAU;CACrE,MAAM,EAAE,OAAO,MAAM,kBAAkB;CACvC,MAAM,UAAU,MAAM,YAAY,MAAM,WAAW,IAAI;CAEvD,MAAM,EAAE,OAAO,EAAE,KAAK,SAAS;EAC7B,SAAS;EACT,sBAAsB;EACvB,CAAC;CACF,MAAM,EAAE,MAAM,MAAM,gBAAgB;CAEpC,MAAM,UAAU,OAAuB,KAAK;CAC5C,MAAM,aAAa,OAAO,MAAM;AAiChC,QACE,oBAAC,OAAD;EAAK,KAAK;EAAS,gBAhCE,aACpB,UAA4C;GAC3C,MAAM,SAAS,MAAM;AACrB,OAAI,EAAE,kBAAkB,SAAU;GAElC,MAAM,UAAU,OAAO,QAAQ,yBAAyB;AACxD,OAAI,SAAS;IAGX,MAAM,QAAQ,QAAQ,QAAQ,8BAA8B;AAC5D,eAAW,UACT,UAAU,QAAQ,UAAU,QAAQ,SAAS,cAAc,eAAe;AAC5E;;AAGF,OAAI,CAAC,OAAO,QAAQ,yBAAyB,CAAE;AAC/C,OAAI,CAAC,WAAW,WAAW,KAAK,SAAS,QAAS;AAElD,SAAM,gBAAgB;AACtB,SAAM,iBAAiB;AACvB,SAAM,MACJ,EAAE,8BAA8B;IAC9B,OAAO;IACP,OAAO,SAAS,OAAO,SAAS,KAAK,SAAS,IAC5C,EAAE,UAAU,IAAI,iBAAiB,cAAc;IAClD,CAAC,CACH;KAEH;GAAC;GAAO,KAAK;GAAU;GAAS,KAAK;GAAQ;GAAE,CAChD;YAIG,oBAAC,YAAD,EAAY,GAAI,OAAS,CAAA;EACrB,CAAA;;;;;;;AASV,SAAS,SACP,OACA,SACA,UACoB;AAEpB,QAAO,YADO,UAAU,IAAI,MAAM,QAAQ,SAAS,MAAM,QAAQ,UACvC,SAAS,IAAI,YAAY,MAAM,OAAO,SAAS;;AAG3E,SAAS,YAAY,OAAgB,UAAsC;AACzE,KAAI,OAAO,UAAU,SAAU,QAAO;AACtC,KAAI,SAAS,OAAO,UAAU,UAAU;EACtC,MAAM,aAAa;AACnB,SAAO,WAAW,aAAa,WAAW,MAAM,OAAO,OAAO,WAAW,CAAC"}
|
package/dist/index.d.mts
CHANGED
|
@@ -132,6 +132,29 @@ declare function headingFields({
|
|
|
132
132
|
eyebrowDescription
|
|
133
133
|
}?: HeadingFieldsOptions): Field[];
|
|
134
134
|
//#endregion
|
|
135
|
+
//#region src/fields/min-rows.d.ts
|
|
136
|
+
/**
|
|
137
|
+
* The import-map path of the array field that refuses to go below `minRows`.
|
|
138
|
+
*
|
|
139
|
+
* Payload gates *Add* on `maxRows` but never gates *Remove* on `minRows`: an
|
|
140
|
+
* editor can delete the third showcase panel, see a "requires 3 panels"
|
|
141
|
+
* note, and only learn on publish that the section is invalid. Payload has no
|
|
142
|
+
* option for this, so it is an admin component (`@bison-lab/payload-blocks/admin`)
|
|
143
|
+
* referenced here by package specifier. Every array in this package with a
|
|
144
|
+
* `minRows` uses it, and a site can put it on its own arrays:
|
|
145
|
+
*
|
|
146
|
+
* ```ts
|
|
147
|
+
* { name: 'items', type: 'array', minRows: 2,
|
|
148
|
+
* admin: { components: { Field: MIN_ROWS_ARRAY_FIELD } }, fields: [...] }
|
|
149
|
+
* ```
|
|
150
|
+
*
|
|
151
|
+
* Consuming sites pick it up by re-running `payload generate:importmap`. Until
|
|
152
|
+
* they do, Payload logs the missing entry and falls back to its stock field.
|
|
153
|
+
*/
|
|
154
|
+
declare const MIN_ROWS_ARRAY_FIELD = "@bison-lab/payload-blocks/admin#MinRowsArrayField";
|
|
155
|
+
/** Empty rows for an array's `defaultValue`, so a block opens at its minimum. */
|
|
156
|
+
declare function emptyRows(count: number): Record<string, never>[];
|
|
157
|
+
//#endregion
|
|
135
158
|
//#region src/media.d.ts
|
|
136
159
|
/**
|
|
137
160
|
* The upload side of the boundary.
|
|
@@ -248,17 +271,11 @@ interface ShowcasePanelsBlockData extends BlockRow<"showcasePanels"> {
|
|
|
248
271
|
watermark?: string | null;
|
|
249
272
|
spineVariant?: ("numbered" | "volume" | "minimal") | null;
|
|
250
273
|
defaultActiveIndex?: number | null;
|
|
251
|
-
ariaLabel?: string | null;
|
|
252
|
-
labels?: {
|
|
253
|
-
selected?: string | null;
|
|
254
|
-
preview?: string | null;
|
|
255
|
-
};
|
|
256
274
|
}
|
|
257
275
|
interface ProcessStepsItemData {
|
|
258
276
|
title?: string | null;
|
|
259
277
|
description?: string | null;
|
|
260
278
|
image?: MediaValue;
|
|
261
|
-
step?: number | null;
|
|
262
279
|
id?: string | null;
|
|
263
280
|
}
|
|
264
281
|
interface ProcessStepsBlockData extends BlockRow<"processSteps"> {
|
|
@@ -267,11 +284,6 @@ interface ProcessStepsBlockData extends BlockRow<"processSteps"> {
|
|
|
267
284
|
autoAdvance?: boolean | null;
|
|
268
285
|
autoAdvanceDuration?: number | null;
|
|
269
286
|
pauseOnHover?: boolean | null;
|
|
270
|
-
ariaLabel?: string | null;
|
|
271
|
-
labels?: {
|
|
272
|
-
pause?: string | null;
|
|
273
|
-
resume?: string | null;
|
|
274
|
-
};
|
|
275
287
|
}
|
|
276
288
|
interface FaqColumnsItemData {
|
|
277
289
|
question?: string | null;
|
|
@@ -340,5 +352,59 @@ type BisonBlockData = HeroBlockData | RichTextBlockData | ShowcasePanelsBlockDat
|
|
|
340
352
|
/** The `blockType` of every block this package ships. */
|
|
341
353
|
type BisonBlockType = BisonBlockData["blockType"];
|
|
342
354
|
//#endregion
|
|
343
|
-
|
|
355
|
+
//#region src/samples.d.ts
|
|
356
|
+
/**
|
|
357
|
+
* One sample row per block, each typed to its own row shape. Assignable to
|
|
358
|
+
* `Record<BisonBlockType, BisonBlockData>` wherever the wider type is wanted.
|
|
359
|
+
*/
|
|
360
|
+
type BlockSamples = { [K in BisonBlockType]: Extract<BisonBlockData, {
|
|
361
|
+
blockType: K;
|
|
362
|
+
}> };
|
|
363
|
+
/**
|
|
364
|
+
* Every block the package ships, rendered without a CMS row.
|
|
365
|
+
*
|
|
366
|
+
* A Block library page (BIS-52) renders these live so an admin can see each
|
|
367
|
+
* block before enabling it. Each sample lives beside its block's `config.ts`
|
|
368
|
+
* and `component.tsx` as `sample.ts`, and `src/__tests__/samples.test.tsx`
|
|
369
|
+
* locks the contract: one entry per slug, `blockType` matching the key, every
|
|
370
|
+
* config field exercised at least once, and every image self-contained.
|
|
371
|
+
*
|
|
372
|
+
* React-free on purpose: it is read from a Global's field config, which
|
|
373
|
+
* Payload loads in plain Node like the rest of this entry, as well as from a
|
|
374
|
+
* route handler. Only what this package ships is here; a site supplies samples
|
|
375
|
+
* for its own blocks through the Block library factory, whose option BIS-52
|
|
376
|
+
* names.
|
|
377
|
+
*/
|
|
378
|
+
declare const blockSamples: BlockSamples;
|
|
379
|
+
//#endregion
|
|
380
|
+
//#region src/sample-image.d.ts
|
|
381
|
+
interface SampleImageOptions {
|
|
382
|
+
/** Text drawn across the placeholder, e.g. "Panel 1 · 1400 × 1000". */
|
|
383
|
+
label: string;
|
|
384
|
+
width: number;
|
|
385
|
+
height: number;
|
|
386
|
+
/** Alt text for the document. Defaults to the label. */
|
|
387
|
+
alt?: string;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* A placeholder upload document for a block sample.
|
|
391
|
+
*
|
|
392
|
+
* A preview has no site media behind it, so the image has to travel with the
|
|
393
|
+
* sample. This is an inline SVG as a `data:` URL, in the `MediaDoc` shape
|
|
394
|
+
* `resolveMedia` already narrows, with `width` and `height` set so an image
|
|
395
|
+
* adapter can reserve the box. The scheme is what tells an adapter which kind
|
|
396
|
+
* of source it has: `next/image` treats a `data:` src as `unoptimized` on its
|
|
397
|
+
* own, so a site's adapter needs no special case for samples.
|
|
398
|
+
*
|
|
399
|
+
* Neutral greys rather than theme tokens: the SVG is a standalone document
|
|
400
|
+
* and cannot see the page's custom properties.
|
|
401
|
+
*/
|
|
402
|
+
declare function sampleImage({
|
|
403
|
+
label,
|
|
404
|
+
width,
|
|
405
|
+
height,
|
|
406
|
+
alt
|
|
407
|
+
}: SampleImageOptions): MediaDoc;
|
|
408
|
+
//#endregion
|
|
409
|
+
export { type BisonBlockData, type BisonBlockType, type BlockSamples, FaqColumnsBlock, type FaqColumnsBlockData, type FaqColumnsItemData, type HeadingFieldsOptions, HeroBlock, type HeroBlockData, type ImageFieldOptions, type LinkFieldOptions, type LinkFieldsOptions, type LinkValue, MIN_ROWS_ARRAY_FIELD, type MediaDoc, type MediaValue, NapBlock, type NapBlockData, type NapDepartmentData, 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, resolveMedia, sampleImage };
|
|
344
410
|
//# 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/fields/image.ts","../src/fields/link.ts","../src/fields/heading.ts","../src/media.ts","../src/types.ts"],"mappings":";;;;;AAcA;;;;;;;cAAa,SAAA,EAAW,KAAA;;;;cCXX,aAAA,EAAe,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/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/sample-image.ts"],"mappings":"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"}
|