@bison-lab/payload-core 3.8.0 → 3.10.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 is one Global with field tabs: Colors, Typography, Appearance,
129
+ and Identity. Publish in the document Save slot writes the open tab only.
130
+ Theme has no draft mode and no preview pane. Contrast is the automatic label
131
+ on editable fills at 7:1; it is never enforced. `bison.config.json` is the seed
132
+ a site 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,7 @@
1
1
 
2
- import { SelectFieldClientComponent, TextFieldClientComponent, UIFieldClientComponent } from "payload";
2
+ import { ThemeConfig } from "@bison-lab/tokens";
3
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
4
+ import { ArrayFieldClientComponent, GroupFieldClientComponent, SelectFieldClientComponent, TextFieldClientComponent, UIFieldClientComponent } from "payload";
3
5
 
4
6
  //#region src/admin/color-field.d.ts
5
7
  /**
@@ -8,21 +10,84 @@ import { SelectFieldClientComponent, TextFieldClientComponent, UIFieldClientComp
8
10
  */
9
11
  declare const ColorField: TextFieldClientComponent;
10
12
  //#endregion
13
+ //#region src/admin/color-scale-field.d.ts
14
+ /**
15
+ * One system (or library row) color: hex, source step, regenerate, stale,
16
+ * include/exclude, automatic label. Writes the group's stored fields.
17
+ */
18
+ declare const ColorScaleField: GroupFieldClientComponent;
19
+ //#endregion
20
+ //#region src/admin/library-field.d.ts
21
+ /**
22
+ * Custom colors: the same scale controls as system colors, plus add and
23
+ * in-use delete (one replacement scale; unused rows delete immediately).
24
+ */
25
+ declare const LibraryField: ArrayFieldClientComponent;
26
+ //#endregion
11
27
  //#region src/admin/font-field.d.ts
12
28
  /**
13
29
  * Listbox over the catalogue ids in `admin.custom.ids`. Each option is the
14
30
  * 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.
31
+ * from the site's font route for the selected family, and for every
32
+ * catalogue id once the picker opens.
16
33
  */
17
34
  declare const FontField: SelectFieldClientComponent;
18
35
  //#endregion
36
+ //#region src/admin/pairing-field.d.ts
37
+ /**
38
+ * Pairing sample only — no weight, letter-spacing, line-height, or health
39
+ * scores. Faces load from the site's font route.
40
+ */
41
+ declare const PairingField: UIFieldClientComponent;
42
+ //#endregion
43
+ //#region src/admin/appearance-field.d.ts
44
+ /**
45
+ * Named appearance choices. Soft → pill, Gentle → minimal, Balanced →
46
+ * default, Follow device → system. No rem or ms.
47
+ */
48
+ declare const AppearanceField: GroupFieldClientComponent;
49
+ //#endregion
50
+ //#region src/admin/grey-scale-field.d.ts
51
+ /**
52
+ * Visual picker over the five grey-scale presets. Replaces the stock select
53
+ * on Colors; the stored value is still `colors.greyScale`.
54
+ */
55
+ declare const GreyScaleField: SelectFieldClientComponent;
56
+ //#endregion
19
57
  //#region src/admin/contrast-report.d.ts
20
58
  /**
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.
59
+ * Contrast used to be a Colors-tab list. Readability now lives on each
60
+ * color card: Needs attention opens a popup. This field stays in the
61
+ * schema so `contrastTarget` is still a Theme option; it paints nothing.
24
62
  */
25
63
  declare const ContrastReport: UIFieldClientComponent;
26
64
  //#endregion
27
- export { ColorField, ContrastReport, FontField };
65
+ //#region src/admin/section-heading.d.ts
66
+ /**
67
+ * Unnamed UI heading between Theme fields. No document path.
68
+ */
69
+ declare const SectionHeading: UIFieldClientComponent;
70
+ //#endregion
71
+ //#region src/admin/publish-child.d.ts
72
+ /** @deprecated Theme publish is the document Save button */
73
+ declare const PublishChild: UIFieldClientComponent;
74
+ //#endregion
75
+ //#region src/admin/save-button.d.ts
76
+ /**
77
+ * Payload's document Save slot — the same control row as Pages'
78
+ * "Publish changes". Theme has no drafts; this publishes only the
79
+ * open field tab. The tab is read after mount so SSR matches.
80
+ */
81
+ declare function ThemeSaveButton(): react_jsx_runtime0.JSX.Element;
82
+ /** Import-map alias — Theme still points `SaveButton` at this name. */
83
+ declare const HiddenSaveButton: typeof ThemeSaveButton;
84
+ //#endregion
85
+ //#region src/admin/identity-fallback.d.ts
86
+ /**
87
+ * Identity child when the site has not registered a cupboard yet.
88
+ * Shows the fallback lockup and mark; uploads wait on `logo.collection`.
89
+ */
90
+ declare const IdentityFallback: UIFieldClientComponent;
91
+ //#endregion
92
+ export { AppearanceField, ColorField, ColorScaleField, ContrastReport, FontField, GreyScaleField, HiddenSaveButton, IdentityFallback, LibraryField, PairingField, PublishChild, SectionHeading, ThemeSaveButton };
28
93
  //# 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","../src/admin/identity-fallback.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;;;;;;;;cCtDhB,cAAA,EAAgB,sBAAA;;;;;;cCFhB,cAAA,EAAgB,sBAAA;;;;cCmIhB,YAAA,EAAc,sBAAA;;;;;;;;iBC7HX,eAAA,CAAA,GAAe,kBAAA,CAAA,GAAA,CAAA,OAAA;AVA/B;AAAA,cU0Ba,gBAAA,SAAgB,eAAA;;;;;;;cC7BhB,gBAAA,EAAkB,sBAAA"}