@bison-lab/payload-core 3.8.0 → 3.9.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 CHANGED
@@ -22,11 +22,11 @@ lockstep.
22
22
 
23
23
  | Import | Contents | Runs where |
24
24
  | ---------------------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
25
- | `@bison-lab/payload-core` | `seoPlugin`, `createTheme`, `seedTheme`, import-map strings, title and text helpers, types | Node. What `payload.config.ts` imports; it loads the plugin. |
25
+ | `@bison-lab/payload-core` | `seoPlugin`, `createTheme`, `createBrandAssets`, `seedTheme`, import-map strings, title and text helpers, types | Node. What `payload.config.ts` imports; it loads the plugin. |
26
26
  | `@bison-lab/payload-core/metadata` | `pageMetadata`, the title helpers, the same types | Server. What a page route imports; it does not load the plugin. |
27
- | `@bison-lab/payload-core/theme` | `getPublishedTheme`, `themeConfigFromDoc`, `themeHead` | Server. What a root layout imports; it does not load the plugin or React. |
28
- | `@bison-lab/payload-core/admin` | `ColorField`, `FontField`, `ContrastReport` | Admin. Referenced by import-map string; `generate:importmap` writes it. |
29
- | `@bison-lab/payload-core/react` | `ThemePreview` | Client. What the theme-preview route imports; it loads ui and live-preview. |
27
+ | `@bison-lab/payload-core/theme` | `getPublishedTheme`, `getPublishedIdentity`, `themeConfigFromDoc`, `themeHead` | Server. What a root layout imports; it does not load the plugin or React. |
28
+ | `@bison-lab/payload-core/admin` | Theme child fields (color scale, library, gray family, fonts, appearance, publish) | Admin. Referenced by import-map string; `generate:importmap` writes it. |
29
+ | `@bison-lab/payload-core/react` | `ThemePreview` (legacy; Theme has no preview pane) | Client. Kept so an older site import does not break. |
30
30
 
31
31
  ## What editors get
32
32
 
@@ -125,11 +125,12 @@ The sitemap is the site's: filter `meta.noIndex` out of it.
125
125
 
126
126
  ## Adopting the Theme global
127
127
 
128
- Settings → Theme: the five brand colours, grey scale, radius, shadow, motion,
129
- density, default theme, body and heading fonts, and an optional logo. Whoever
130
- holds brand rights edits a draft; publish is deliberate. Contrast is measured
131
- as they type and shown; it is never enforced. `bison.config.json` is the seed
132
- a site starts from, not the source of truth.
128
+ Settings → Theme children: Colors, Typography, Appearance, and Identity. Each
129
+ child has its own Publish publishing Colors updates colors only. Theme has
130
+ no draft mode and no preview pane. Contrast is the automatic label on editable
131
+ fills at 7:1; it is never enforced. `bison.config.json` is the seed a site
132
+ starts from, not the source of truth. Pass `destructive` (or
133
+ `seed.brandDestructive`); there is no package default.
133
134
 
134
135
  **1. Register the Global.** Access is required — the predicates live in the
135
136
  site's `src/platform` until they move here. Pass `canManageBrand` as
@@ -137,17 +138,27 @@ site's `src/platform` until they move here. Pass `canManageBrand` as
137
138
 
138
139
  ```ts
139
140
  // payload.config.ts
140
- import { createTheme } from "@bison-lab/payload-core";
141
+ import { BRAND_ASSETS_SLUG, createBrandAssets, createTheme } from "@bison-lab/payload-core";
141
142
  import bisonConfig from "../bison.config.json";
142
143
  import { canManageBrand, isAuthenticated } from "@/platform/access";
143
144
 
144
145
  export default buildConfig({
146
+ collections: [
147
+ createBrandAssets({
148
+ access: { read: () => true, update: canManageBrand },
149
+ }),
150
+ ],
145
151
  globals: [
146
152
  createTheme({
147
153
  access: { read: isAuthenticated, update: canManageBrand },
148
154
  seed: bisonConfig,
149
- previewPath: "/theme-preview",
150
- logo: { collection: "brand-assets" },
155
+ logo: { collection: BRAND_ASSETS_SLUG },
156
+ identity: {
157
+ fallback: {
158
+ lockup: { url: "/logo-lockup.svg", alt: "Acme" },
159
+ mark: { url: "/logo-mark.svg", alt: "Acme mark" },
160
+ },
161
+ },
151
162
  onPublish: async () => {
152
163
  revalidateTag("theme");
153
164
  },
@@ -156,8 +167,8 @@ export default buildConfig({
156
167
  });
157
168
  ```
158
169
 
159
- Then `payload generate:importmap` (the colour, font and contrast fields
160
- resolve from `@bison-lab/payload-core/admin`), `payload generate:types`, and
170
+ Then `payload generate:importmap` (the Theme child fields resolve from
171
+ `@bison-lab/payload-core/admin`), `payload generate:types`, and
161
172
  `payload migrate:create`.
162
173
 
163
174
  **2. Seed the row on deploy.** A migration `up()` writes a published version
@@ -181,51 +192,39 @@ you pass as `fontsBaseUrl` (default `/fonts`).
181
192
 
182
193
  ```ts
183
194
  // app/layout.tsx
184
- import { getPublishedTheme, themeHead } from "@bison-lab/payload-core/theme";
195
+ import { getPublishedIdentity, getPublishedTheme, themeHead } from "@bison-lab/payload-core/theme";
185
196
  import bisonConfig from "../bison.config.json";
186
197
 
187
198
  const theme = await getPublishedTheme(payload, bisonConfig);
188
- const { css, preloads } = themeHead(theme);
199
+ const identity = await getPublishedIdentity(payload, {
200
+ lockup: { url: "/logo-lockup.svg", alt: "Acme" },
201
+ mark: { url: "/logo-mark.svg", alt: "Acme mark" },
202
+ });
203
+ const { css, preloads } = themeHead(theme, { identity });
189
204
 
190
205
  // <link rel="preload" as="font" type="font/woff2" crossOrigin="" href={href} />
191
206
  // <style dangerouslySetInnerHTML={{ __html: css }} />
207
+ // identity.lockup / identity.mark / identity.favicon — uploaded file or the fallback
192
208
  ```
193
209
 
194
210
  If the admin layout renders the same head, the admin panel restyles too.
195
211
 
196
- `getPublishedTheme` reads `draft: false` and falls back to the seed when
197
- nothing has been published. A newer draft never reaches the public site.
212
+ `getPublishedTheme` reads the live row and falls back to the seed when
213
+ the Global is empty. Empty logo, favicon, and mobile-menu mark use the
214
+ fallback the site passed into `createTheme`. There is no Theme preview pane.
198
215
 
199
- **5. Own the preview route.** The path is code-owned (in the site's
200
- `ENDPOINTS`), never a nav link, never in the sitemap, reserved from CMS
201
- slugs, and gated to an authenticated user. It renders `ThemePreview` with
202
- no site chrome. `createTheme({ previewPath })` points Payload's live-preview
203
- pane at that path; omit `previewPath` and the pane stays closed.
216
+ ## Brand assets
204
217
 
205
- ```ts
206
- // app/theme-preview/page.tsx
207
- import { ThemePreview } from "@bison-lab/payload-core/react";
208
- import { getPublishedTheme } from "@bison-lab/payload-core/theme";
209
- import bisonConfig from "../../../bison.config.json";
210
-
211
- const theme = await getPublishedTheme(payload, bisonConfig);
212
-
213
- return (
214
- <ThemePreview
215
- theme={theme}
216
- seed={bisonConfig}
217
- fontsBaseUrl="/fonts"
218
- serverURL={absoluteSiteUrl}
219
- />
220
- );
221
- ```
218
+ Logo, favicon, and mobile-menu mark live in a locked cupboard, not in
219
+ ordinary Media. Call `createBrandAssets` and point Theme at
220
+ `BRAND_ASSETS_SLUG`. Access is the same shape as `createTheme`: `read` is
221
+ typically public so the live site can load the file; `update` is
222
+ `canManageBrand` and covers create, update, delete, and version history.
223
+ SVG preferred, PNG and ICO allowed; an SVG is sanitized on upload.
224
+ Versions stay on so a replaced file can be rolled back.
222
225
 
223
- `ThemePreview` rebuilds the stylesheet in the browser from each live-preview
224
- message. A half-typed hex keeps the last complete theme so the iframe does
225
- not go blank. The light / dark toggle sets `data-theme` on the preview root,
226
- not the document. Pages that later grow a live-preview pane should import
227
- `THEME_PREVIEW_BREAKPOINTS` from `@bison-lab/payload-core` so the toolbars
228
- match.
226
+ Each row carries a label, usage notes, and required alt text so a logo
227
+ has its accessible name. Then `payload migrate:create`.
229
228
 
230
229
  ## No generated types
231
230
 
@@ -237,6 +236,7 @@ to a type that has one.
237
236
 
238
237
  ## Changing a field
239
238
 
240
- `noIndexField`, the plugin's own fields, and the Theme Global fields are
241
- columns in every consuming site. A change to them is a schema change: say
242
- "run `payload migrate:create`" in the changeset.
239
+ `noIndexField`, the plugin's own fields, the Theme Global fields, and the
240
+ brand-assets collection fields are columns in every consuming site. A
241
+ change to them is a schema change: say "run `payload migrate:create`" in
242
+ the changeset.
package/dist/admin.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- import { SelectFieldClientComponent, TextFieldClientComponent, UIFieldClientComponent } from "payload";
2
+ import { ArrayFieldClientComponent, GroupFieldClientComponent, SelectFieldClientComponent, TextFieldClientComponent, UIFieldClientComponent } from "payload";
3
3
 
4
4
  //#region src/admin/color-field.d.ts
5
5
  /**
@@ -8,21 +8,77 @@ import { SelectFieldClientComponent, TextFieldClientComponent, UIFieldClientComp
8
8
  */
9
9
  declare const ColorField: TextFieldClientComponent;
10
10
  //#endregion
11
+ //#region src/admin/color-scale-field.d.ts
12
+ /**
13
+ * One system (or library row) color: hex, source step, regenerate, stale,
14
+ * include/exclude, automatic label. Writes the group's stored fields.
15
+ */
16
+ declare const ColorScaleField: GroupFieldClientComponent;
17
+ //#endregion
18
+ //#region src/admin/library-field.d.ts
19
+ /**
20
+ * Custom colors: the same scale controls as system colors, plus add and
21
+ * in-use delete (one replacement scale; unused rows delete immediately).
22
+ */
23
+ declare const LibraryField: ArrayFieldClientComponent;
24
+ //#endregion
11
25
  //#region src/admin/font-field.d.ts
12
26
  /**
13
27
  * Listbox over the catalogue ids in `admin.custom.ids`. Each option is the
14
28
  * family name in that face, with the catalogue hint beneath. Faces load
15
- * from the site's font route the first time the picker opens.
29
+ * from the site's font route for the selected family, and for every
30
+ * catalogue id once the picker opens.
16
31
  */
17
32
  declare const FontField: SelectFieldClientComponent;
18
33
  //#endregion
34
+ //#region src/admin/pairing-field.d.ts
35
+ /**
36
+ * Pairing sample only — no weight, letter-spacing, line-height, or health
37
+ * scores. Faces load from the site's font route.
38
+ */
39
+ declare const PairingField: UIFieldClientComponent;
40
+ //#endregion
41
+ //#region src/admin/appearance-field.d.ts
42
+ /**
43
+ * Named appearance choices. Soft → pill, Gentle → minimal, Balanced →
44
+ * default, Follow device → system. No rem or ms.
45
+ */
46
+ declare const AppearanceField: GroupFieldClientComponent;
47
+ //#endregion
48
+ //#region src/admin/grey-scale-field.d.ts
49
+ /**
50
+ * Visual picker over the five grey-scale presets. Replaces the stock select
51
+ * on Colors; the stored value is still `colors.greyScale`.
52
+ */
53
+ declare const GreyScaleField: SelectFieldClientComponent;
54
+ //#endregion
19
55
  //#region src/admin/contrast-report.d.ts
20
56
  /**
21
- * Reads the five brand colours and grey scale from the form, runs
22
- * `auditTheme` client-side, and paints its own rows. Warn only: nothing
23
- * here touches validity.
57
+ * Fill + automatic label only. Target 7:1, Light and Dark. No gray
58
+ * ContrastStrip. Warnings do not block save.
24
59
  */
25
60
  declare const ContrastReport: UIFieldClientComponent;
26
61
  //#endregion
27
- export { ColorField, ContrastReport, FontField };
62
+ //#region src/admin/section-heading.d.ts
63
+ /**
64
+ * Unnamed UI heading between Theme fields. No document path.
65
+ */
66
+ declare const SectionHeading: UIFieldClientComponent;
67
+ //#endregion
68
+ //#region src/admin/publish-child.d.ts
69
+ /**
70
+ * Per-child Publish. Sets `publishChild` then submits; `beforeChange`
71
+ * writes only that slice. Confirmation lists this child's changes and,
72
+ * on Colors, remaining automatic-label shorts.
73
+ */
74
+ declare const PublishChild: UIFieldClientComponent;
75
+ //#endregion
76
+ //#region src/admin/save-button.d.ts
77
+ /**
78
+ * Theme children publish themselves. The stock Save would write every
79
+ * dirty tab at once, so it is hidden.
80
+ */
81
+ declare function HiddenSaveButton(): null;
82
+ //#endregion
83
+ export { AppearanceField, ColorField, ColorScaleField, ContrastReport, FontField, GreyScaleField, HiddenSaveButton, LibraryField, PairingField, PublishChild, SectionHeading };
28
84
  //# sourceMappingURL=admin.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"admin.d.mts","names":[],"sources":["../src/admin/color-field.tsx","../src/admin/font-field.tsx","../src/admin/contrast-report.tsx"],"mappings":";;;;;;AAWA;;cAAa,UAAA,EAAY,wBAAA;;;;;AAAzB;;;cCGa,SAAA,EAAW,0BAAA;;;;;ADHxB;;;cEqEa,cAAA,EAAgB,sBAAA"}
1
+ {"version":3,"file":"admin.d.mts","names":[],"sources":["../src/admin/color-field.tsx","../src/admin/color-scale-field.tsx","../src/admin/library-field.tsx","../src/admin/font-field.tsx","../src/admin/pairing-field.tsx","../src/admin/appearance-field.tsx","../src/admin/grey-scale-field.tsx","../src/admin/contrast-report.tsx","../src/admin/section-heading.tsx","../src/admin/publish-child.tsx","../src/admin/save-button.tsx"],"mappings":";;;;;;;;cAWa,UAAA,EAAY,wBAAA;;;;;;;cCGZ,eAAA,EAAiB,yBAAA;;;;;;;cCQjB,YAAA,EAAc,yBAAA;;;;;;;AFX3B;;cGMa,SAAA,EAAW,0BAAA;;;;;;;cCNX,YAAA,EAAc,sBAAA;;;;;;;cCCd,eAAA,EAAiB,yBAAA;;;;;;;cCiDjB,cAAA,EAAgB,0BAAA;;;;;;;cC1ChB,cAAA,EAAgB,sBAAA;;;;;;cCdhB,cAAA,EAAgB,sBAAA;;;;;;;ARM7B;cS0Ea,YAAA,EAAc,sBAAA;;;;;;;iBCjFX,gBAAA,CAAA"}