@bison-lab/payload-core 3.7.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
@@ -13,17 +13,20 @@ pnpm add @bison-lab/payload-core @payloadcms/plugin-seo @bison-lab/tokens @bison
13
13
 
14
14
  Peers: `payload` and `@payloadcms/plugin-seo` are required. `@bison-lab/tokens`
15
15
  and `@bison-lab/fonts` are needed to adopt the Theme Global; `@payloadcms/ui`
16
- and `react` are needed for its admin fields. Pin the plugin to the same
17
- version as `payload`; Payload releases them in lockstep.
16
+ and `react` are needed for its admin fields; `@bison-lab/ui` and
17
+ `@payloadcms/live-preview-react` are needed for the live theme preview.
18
+ Pin the plugin to the same version as `payload`; Payload releases them in
19
+ lockstep.
18
20
 
19
- ## Four entry points, and why
21
+ ## Five entry points, and why
20
22
 
21
23
  | Import | Contents | Runs where |
22
24
  | ---------------------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
23
- | `@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. |
24
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. |
25
- | `@bison-lab/payload-core/theme` | `getPublishedTheme`, `themeConfigFromDoc`, `themeHead` | Server. What a root layout imports; it does not load the plugin or React. |
26
- | `@bison-lab/payload-core/admin` | `ColorField`, `FontField`, `ContrastReport` | Admin. Referenced by import-map string; `generate:importmap` writes it. |
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. |
27
30
 
28
31
  ## What editors get
29
32
 
@@ -122,11 +125,12 @@ The sitemap is the site's: filter `meta.noIndex` out of it.
122
125
 
123
126
  ## Adopting the Theme global
124
127
 
125
- Settings → Theme: the five brand colours, grey scale, radius, shadow, motion,
126
- density, default theme, body and heading fonts, and an optional logo. Whoever
127
- holds brand rights edits a draft; publish is deliberate. Contrast is measured
128
- as they type and shown; it is never enforced. `bison.config.json` is the seed
129
- 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.
130
134
 
131
135
  **1. Register the Global.** Access is required — the predicates live in the
132
136
  site's `src/platform` until they move here. Pass `canManageBrand` as
@@ -134,16 +138,27 @@ site's `src/platform` until they move here. Pass `canManageBrand` as
134
138
 
135
139
  ```ts
136
140
  // payload.config.ts
137
- import { createTheme } from "@bison-lab/payload-core";
141
+ import { BRAND_ASSETS_SLUG, createBrandAssets, createTheme } from "@bison-lab/payload-core";
138
142
  import bisonConfig from "../bison.config.json";
139
143
  import { canManageBrand, isAuthenticated } from "@/platform/access";
140
144
 
141
145
  export default buildConfig({
146
+ collections: [
147
+ createBrandAssets({
148
+ access: { read: () => true, update: canManageBrand },
149
+ }),
150
+ ],
142
151
  globals: [
143
152
  createTheme({
144
153
  access: { read: isAuthenticated, update: canManageBrand },
145
154
  seed: bisonConfig,
146
- 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
+ },
147
162
  onPublish: async () => {
148
163
  revalidateTag("theme");
149
164
  },
@@ -152,8 +167,8 @@ export default buildConfig({
152
167
  });
153
168
  ```
154
169
 
155
- Then `payload generate:importmap` (the colour, font and contrast fields
156
- 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
157
172
  `payload migrate:create`.
158
173
 
159
174
  **2. Seed the row on deploy.** A migration `up()` writes a published version
@@ -177,20 +192,39 @@ you pass as `fontsBaseUrl` (default `/fonts`).
177
192
 
178
193
  ```ts
179
194
  // app/layout.tsx
180
- import { getPublishedTheme, themeHead } from "@bison-lab/payload-core/theme";
195
+ import { getPublishedIdentity, getPublishedTheme, themeHead } from "@bison-lab/payload-core/theme";
181
196
  import bisonConfig from "../bison.config.json";
182
197
 
183
198
  const theme = await getPublishedTheme(payload, bisonConfig);
184
- 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 });
185
204
 
186
205
  // <link rel="preload" as="font" type="font/woff2" crossOrigin="" href={href} />
187
206
  // <style dangerouslySetInnerHTML={{ __html: css }} />
207
+ // identity.lockup / identity.mark / identity.favicon — uploaded file or the fallback
188
208
  ```
189
209
 
190
210
  If the admin layout renders the same head, the admin panel restyles too.
191
211
 
192
- `getPublishedTheme` reads `draft: false` and falls back to the seed when
193
- 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.
215
+
216
+ ## Brand assets
217
+
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.
225
+
226
+ Each row carries a label, usage notes, and required alt text so a logo
227
+ has its accessible name. Then `payload migrate:create`.
194
228
 
195
229
  ## No generated types
196
230
 
@@ -202,6 +236,7 @@ to a type that has one.
202
236
 
203
237
  ## Changing a field
204
238
 
205
- `noIndexField`, the plugin's own fields, and the Theme Global fields are
206
- columns in every consuming site. A change to them is a schema change: say
207
- "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"}