@bison-lab/payload-core 3.16.0 → 3.17.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,7 +22,7 @@ lockstep.
22
22
 
23
23
  | Import | Contents | Runs where |
24
24
  | ---------------------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
25
- | `@bison-lab/payload-core` | `seoPlugin`, `createTheme`, `createBrandAssets`, `createRoles`, `createFeatures`, `createPages`, `createUsers`, `createMedia`, `adminOnlyApiTab`, `seedTheme`, `seedRoles`, `seedFeatures`, predicates, `lookField`, `colorTokenField`, 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`, `createRoles`, `createFeatures`, `createPages`, `createUsers`, `createMedia`, `adminOnlyApiTab`, `documentTitleActions`, `seedTheme`, `seedRoles`, `seedFeatures`, predicates, `lookField`, `colorTokenField`, 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
27
  | `@bison-lab/payload-core/theme` | `getPublishedTheme`, `getPublishedIdentity`, `themeConfigFromDoc`, `themeHead`, `themeHeadFromDoc` | Server. What a root layout imports; it does not load the plugin or React. |
28
28
  | `@bison-lab/payload-core/admin` | Theme fields, the Roles and Features matrices, and the Users Roles checklist | Admin. Referenced by import-map string; `generate:importmap` writes it. |
@@ -318,8 +318,9 @@ read from the live Features and Roles Globals) so Payload's
318
318
 
319
319
  ## Pages, users, and media
320
320
 
321
- `createPages`, `createUsers`, `createMedia`, `slugField`, and
322
- `adminOnlyApiTab` ship from the same React-free entry. Pages take the
321
+ `createPages`, `createUsers`, `createMedia`, `slugField`,
322
+ `adminOnlyApiTab`, and `documentTitleActions` ship from the same
323
+ React-free entry. Pages take the
323
324
  site's hero and layout blocks, reserved-slug predicate, and preview
324
325
  path. Create follows the Content tick. Update without Publish is
325
326
  constrained to `_status: draft` — an Author can save a draft and cannot
@@ -327,7 +328,12 @@ publish or edit a live page. Users sit under Settings next to Roles,
327
328
  take `secureCookies`, and offer whatever rows the Global (or the seed
328
329
  plus the same `extras`) has. `users.roles` and `users.allowedFeatures`
329
330
  set `saveToJWT: true`. The checklist labels are the editable names.
330
- `adminOnlyApiTab` shows the document API tab only to Developer. Overlay
331
+ `adminOnlyApiTab` shows the document API tab only to Developer.
332
+ `documentTitleActions` is one admin provider that puts every document's
333
+ primary actions on the title row — the same slot collection lists use
334
+ for Create New — and hides the dead Edit tab when it has no sibling.
335
+ One-list Globals pass `documentCreateNew("roles")` (or a site field
336
+ path) so Create New uses those same words, with no icon. Overlay
331
337
  settings (Better Editor) take `developerOnlyAccess` and
332
338
  `hideUnlessDeveloper` on the site — the package does not add that
333
339
  plugin as a peer.
package/dist/admin.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
 
2
2
  import { ThemeConfig } from "@bison-lab/tokens";
3
+ import { ReactNode } from "react";
3
4
  import * as react_jsx_runtime0 from "react/jsx-runtime";
4
5
  import { ArrayFieldClientComponent, GroupFieldClientComponent, JSONFieldClientComponent, SelectFieldClientComponent, TextFieldClientComponent, UIFieldClientComponent } from "payload";
5
6
 
@@ -155,5 +156,19 @@ declare const RolesGrantsField: JSONFieldClientComponent;
155
156
  */
156
157
  declare const FeaturesMatrixField: ArrayFieldClientComponent;
157
158
  //#endregion
158
- export { AppearanceField, ColorField, ColorScaleField, ContrastReport, FeaturesMatrixField, FontField, GreyScaleField, HiddenSaveButton, IdentityFallback, LibraryField, LookField, PairingField, PublishChild, RoleNameField, RoleSlugField, RolesField, RolesGrantsField, RolesMatrixField, RolesRowLabel, SectionHeading, ThemeDocumentControls, ThemeSaveButton };
159
+ //#region src/admin/document-title-actions.d.ts
160
+ declare function DocumentTitleActions({
161
+ children
162
+ }: {
163
+ children?: ReactNode;
164
+ }): react_jsx_runtime0.JSX.Element;
165
+ //#endregion
166
+ //#region src/admin/document-create-new.d.ts
167
+ declare function DocumentCreateNew({
168
+ path
169
+ }: {
170
+ path: string;
171
+ }): react_jsx_runtime0.JSX.Element;
172
+ //#endregion
173
+ export { AppearanceField, ColorField, ColorScaleField, ContrastReport, DocumentCreateNew, DocumentTitleActions, FeaturesMatrixField, FontField, GreyScaleField, HiddenSaveButton, IdentityFallback, LibraryField, LookField, PairingField, PublishChild, RoleNameField, RoleSlugField, RolesField, RolesGrantsField, RolesMatrixField, RolesRowLabel, SectionHeading, ThemeDocumentControls, ThemeSaveButton };
159
174
  //# sourceMappingURL=admin.d.mts.map
@@ -1 +1 @@
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","../src/admin/look-field.tsx","../src/admin/roles-matrix-field.tsx","../src/admin/roles-row-label.tsx","../src/admin/role-slug-field.tsx","../src/admin/role-name-field.tsx","../src/admin/roles-field.tsx","../src/admin/roles-grants-field.tsx","../src/admin/features-matrix-field.tsx"],"mappings":";;;;;;;;;;cAWa,UAAA,EAAY,wBAAA;;;;;;;cCsBZ,eAAA,EAAiB,yBAAA;;;;;;;;ADtB9B;cEgBa,YAAA,EAAc,yBAAA;;;;;;;;AFhB3B;cGOa,SAAA,EAAW,0BAAA;;;;;;;cCNX,YAAA,EAAc,sBAAA;;;;;;;cCCd,eAAA,EAAiB,yBAAA;;;;;;;cCuDjB,cAAA,EAAgB,0BAAA;;;;;;;cChDhB,cAAA,EAAgB,sBAAA;;;;;;cCbhB,cAAA,EAAgB,sBAAA;;;cCgJhB,YAAA,EAAc,sBAAA;;;;;;;;iBC3IX,qBAAA,CAAA,GAAqB,kBAAA,CAAA,GAAA,CAAA,OAAA;AVDrC;;;;AAAA,iBUgBgB,eAAA,CAAA,GAAe,kBAAA,CAAA,GAAA,CAAA,OAAA;;iBA0Bf,gBAAA,CAAA,GAAgB,kBAAA,CAAA,GAAA,CAAA,OAAA;;;;;;;cC7CnB,gBAAA,EAAkB,sBAAA;;;;;;;cCIlB,SAAA,EAAW,wBAAA;;;;;;;;cCsBX,gBAAA,EAAkB,yBAAA;;;;;;iBC3Bf,aAAA,CAAA,GAAa,kBAAA,CAAA,GAAA,CAAA,OAAA;;;;;;cCChB,aAAA,EAAe,wBAAA;;;;;;;cCCf,aAAA,EAAe,wBAAA;;;;;;;;cC8Cf,UAAA,EAAY,0BAAA;;;;;;;;cChCZ,gBAAA,EAAkB,wBAAA;;;;;;;;AlBZ/B;;;cmB0Ca,mBAAA,EAAqB,yBAAA"}
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","../src/admin/look-field.tsx","../src/admin/roles-matrix-field.tsx","../src/admin/roles-row-label.tsx","../src/admin/role-slug-field.tsx","../src/admin/role-name-field.tsx","../src/admin/roles-field.tsx","../src/admin/roles-grants-field.tsx","../src/admin/features-matrix-field.tsx","../src/admin/document-title-actions.tsx","../src/admin/document-create-new.tsx"],"mappings":";;;;;;;;;;;cAWa,UAAA,EAAY,wBAAA;;;;;;;cCsBZ,eAAA,EAAiB,yBAAA;;;;;;;;;cCNjB,YAAA,EAAc,yBAAA;;;;;;;;;cCTd,SAAA,EAAW,0BAAA;;;;;;;cCNX,YAAA,EAAc,sBAAA;;;;;;;cCCd,eAAA,EAAiB,yBAAA;;;ALF9B;;;;AAAA,cMyDa,cAAA,EAAgB,0BAAA;;;;;;;cChDhB,cAAA,EAAgB,sBAAA;;;;;;cCbhB,cAAA,EAAgB,sBAAA;;;cCgJhB,YAAA,EAAc,sBAAA;;;;;;;;iBC3IX,qBAAA,CAAA,GAAqB,kBAAA,CAAA,GAAA,CAAA,OAAA;;AVDrC;;;iBUgBgB,eAAA,CAAA,GAAe,kBAAA,CAAA,GAAA,CAAA,OAAA;;iBA0Bf,gBAAA,CAAA,GAAgB,kBAAA,CAAA,GAAA,CAAA,OAAA;;;;;;;cC7CnB,gBAAA,EAAkB,sBAAA;;;;;;;cCIlB,SAAA,EAAW,wBAAA;;;;;;;;cCsBX,gBAAA,EAAkB,yBAAA;;;;;;iBC3Bf,aAAA,CAAA,GAAa,kBAAA,CAAA,GAAA,CAAA,OAAA;;;;;;cCChB,aAAA,EAAe,wBAAA;;;;;;;cCCf,aAAA,EAAe,wBAAA;;;;;;;;cC8Cf,UAAA,EAAY,0BAAA;;;;;;;;cChCZ,gBAAA,EAAkB,wBAAA;;;;;;;;;AlBZ/B;;cmB0Ca,mBAAA,EAAqB,yBAAA;;;iBCjBlB,oBAAA,CAAA;EAAuB;AAAA;EAAc,QAAA,GAAW,SAAA;AAAA,IAAW,kBAAA,CAAA,GAAA,CAAA,OAAA;;;iBCtB3D,iBAAA,CAAA;EAAoB;AAAA;EAAU,IAAA;AAAA,IAAc,kBAAA,CAAA,GAAA,CAAA,OAAA"}
package/dist/admin.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import { a as colorDocFromState, i as SYSTEM_COLOR_KEYS, n as pageEditorLooks, r as pageEditorTokens, s as stateFromColorDoc } from "./looks-BbL309kO.mjs";
3
- import { ArrayField, CheckboxInput, FieldDescription, FieldError, FieldLabel, fieldBaseClass, useAuth, useConfig, useField, useForm, useFormFields, useRowLabel } from "@payloadcms/ui";
3
+ import { ArrayField, Button, CheckboxInput, FieldDescription, FieldError, FieldLabel, fieldBaseClass, useAuth, useConfig, useField, useForm, useFormFields, useRowLabel } from "@payloadcms/ui";
4
4
  import { GREY_SCALES, SHADE_STEPS, contrastForeground, contrastRatio, createColorScale, deriveDarkPalette, deriveLightPalette, hexToHSL, hslToString, includedShadeSteps, isThemeHex, presetHints, setColorScaleInclude } from "@bison-lab/tokens";
5
- import { useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
5
+ import { useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
6
6
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
7
  import { createPortal } from "react-dom";
8
8
  import { findFont, fontFaceCss, isFontId } from "@bison-lab/fonts";
@@ -2842,7 +2842,7 @@ function resetRolesMatrix(current) {
2842
2842
  }
2843
2843
  //#endregion
2844
2844
  //#region src/admin/roles-matrix-field.tsx
2845
- const HIDE_ROW_CHROME = `.bl-roles-matrix .array-actions__add,.bl-roles-matrix .array-actions__duplicate,.bl-roles-matrix .array-actions__copy{display:none}.bl-roles-matrix .array-field__add-row{display:none}.bl-roles-matrix--hide-developer .array-field__row:has([data-role-seed="developer"]),.bl-roles-matrix--hide-developer .collapsible:has([data-role-seed="developer"]){display:none}.bl-roles-matrix__toolbar{display:flex;justify-content:flex-end;gap:.5rem;margin-block-end:.75rem}.bl-roles-matrix__reset,.bl-roles-matrix__add{min-height:2.25rem;padding:.35rem .9rem;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:8px;background:transparent;color:inherit;font:inherit;cursor:pointer}body.bl-roles-matrix-seed-menu .array-actions__remove{display:none}`;
2845
+ const HIDE_ROW_CHROME = `.bl-roles-matrix .array-actions__add,.bl-roles-matrix .array-actions__duplicate,.bl-roles-matrix .array-actions__copy{display:none}.bl-roles-matrix .array-field__add-row{display:none}.bl-roles-matrix--hide-developer .array-field__row:has([data-role-seed="developer"]),.bl-roles-matrix--hide-developer .collapsible:has([data-role-seed="developer"]){display:none}.bl-roles-matrix__toolbar{display:flex;justify-content:flex-end;gap:.5rem;margin-block-end:.75rem}.bl-roles-matrix__reset{min-height:2.25rem;padding:.35rem .9rem;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:8px;background:transparent;color:inherit;font:inherit;cursor:pointer}body.bl-roles-matrix-seed-menu .array-actions__remove{display:none}`;
2846
2846
  function seedRoleFromTrigger(trigger) {
2847
2847
  let node = trigger.parentElement;
2848
2848
  while (node) {
@@ -2894,19 +2894,14 @@ const RolesMatrixField = (props) => {
2894
2894
  precedence: "default",
2895
2895
  children: HIDE_ROW_CHROME
2896
2896
  }),
2897
- /* @__PURE__ */ jsxs("div", {
2897
+ /* @__PURE__ */ jsx("div", {
2898
2898
  className: "bl-roles-matrix__toolbar",
2899
- children: [/* @__PURE__ */ jsx("button", {
2900
- type: "button",
2901
- className: "bl-roles-matrix__add",
2902
- onClick: () => rootRef.current?.querySelector(".array-field__add-row")?.click(),
2903
- children: "Add Role"
2904
- }), /* @__PURE__ */ jsx("button", {
2899
+ children: /* @__PURE__ */ jsx("button", {
2905
2900
  type: "button",
2906
2901
  className: "bl-roles-matrix__reset",
2907
2902
  onClick: () => setValue(resetRolesMatrix(value)),
2908
2903
  children: "Reset to defaults"
2909
- })]
2904
+ })
2910
2905
  }),
2911
2906
  /* @__PURE__ */ jsx(ArrayField, { ...props })
2912
2907
  ]
@@ -3321,6 +3316,85 @@ const FeaturesMatrixField = (props) => {
3321
3316
  });
3322
3317
  };
3323
3318
  //#endregion
3324
- export { AppearanceField, ColorField, ColorScaleField, ContrastReport, FeaturesMatrixField, FontField, GreyScaleField, HiddenSaveButton, IdentityFallback, LibraryField, LookField, PairingField, PublishChild, RoleNameField, RoleSlugField, RolesField, RolesGrantsField, RolesMatrixField, RolesRowLabel, SectionHeading, ThemeDocumentControls, ThemeSaveButton };
3319
+ //#region src/admin/document-title-actions.tsx
3320
+ /**
3321
+ * Shared document header: title on the left, primary actions on the
3322
+ * right — the same slot collection lists use for Create New.
3323
+ *
3324
+ * Payload parks Edit / Versions / API in that slot and puts Save one
3325
+ * row down. This moves `.doc-controls__controls-wrapper` (Save,
3326
+ * Preview, Create New, and the kebab) onto the title row, hides the
3327
+ * active Edit tab (you are already on the form), and collapses the
3328
+ * leftover controls band when it has no meta.
3329
+ *
3330
+ * Mounted as `admin.components.providers` so Account and every
3331
+ * collection / global share one lift. A MutationObserver re-applies
3332
+ * after Payload redraws the controls.
3333
+ */
3334
+ const TITLE_ACTIONS_CSS = `
3335
+ .doc-header__header{display:flex;align-items:center;justify-content:flex-start;width:100%;gap:10px}
3336
+ .doc-header__title{flex:0 1 auto;min-width:0}
3337
+ .doc-header__header > .doc-controls__controls-wrapper{margin-left:auto;display:flex;align-items:center;gap:8px}
3338
+ .doc-tab.doc-tab--active.btn--disabled{display:none}
3339
+ .doc-tabs:not(:has(.doc-tab:not(.doc-tab--active))){display:none}
3340
+ .doc-controls:has(.doc-controls__meta:empty):not(:has(.doc-controls__controls-wrapper)){height:0;min-height:0;padding:0;overflow:hidden}
3341
+ .doc-controls:has(.doc-controls__meta:empty):not(:has(.doc-controls__controls-wrapper)) .doc-controls__divider{display:none}
3342
+ `;
3343
+ function liftTitleActions() {
3344
+ const header = document.querySelector(".doc-header__header");
3345
+ const wrapper = document.querySelector(".doc-controls__controls-wrapper");
3346
+ if (!header || !wrapper) return;
3347
+ if (wrapper.parentElement === header) return;
3348
+ header.appendChild(wrapper);
3349
+ }
3350
+ function DocumentTitleActions({ children }) {
3351
+ useLayoutEffect(() => {
3352
+ liftTitleActions();
3353
+ const observer = new MutationObserver(liftTitleActions);
3354
+ observer.observe(document.body, {
3355
+ childList: true,
3356
+ subtree: true
3357
+ });
3358
+ return () => observer.disconnect();
3359
+ }, []);
3360
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("style", {
3361
+ href: "bl-doc-title-actions",
3362
+ precedence: "default",
3363
+ children: TITLE_ACTIONS_CSS
3364
+ }), children] });
3365
+ }
3366
+ //#endregion
3367
+ //#region src/admin/document-create-new.tsx
3368
+ /**
3369
+ * Same words as a collection list Create New — no icon, no "Area" or
3370
+ * "Role." The page title already says what is created. Primary so a
3371
+ * site's admin skin can paint it with Theme `--primary`.
3372
+ *
3373
+ * Hides the array's own Add while this control is mounted so the
3374
+ * action is not offered twice.
3375
+ */
3376
+ const HIDE_FIELD_ADD = `.array-field__add-row{display:none}`;
3377
+ function DocumentCreateNew({ path }) {
3378
+ const { addFieldRow, disabled } = useForm();
3379
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("style", {
3380
+ href: "bl-doc-create-new",
3381
+ precedence: "default",
3382
+ children: HIDE_FIELD_ADD
3383
+ }), /* @__PURE__ */ jsx(Button, {
3384
+ buttonStyle: "primary",
3385
+ size: "medium",
3386
+ type: "button",
3387
+ disabled,
3388
+ onClick: () => {
3389
+ addFieldRow({
3390
+ path,
3391
+ schemaPath: path
3392
+ });
3393
+ },
3394
+ children: "Create New"
3395
+ })] });
3396
+ }
3397
+ //#endregion
3398
+ export { AppearanceField, ColorField, ColorScaleField, ContrastReport, DocumentCreateNew, DocumentTitleActions, FeaturesMatrixField, FontField, GreyScaleField, HiddenSaveButton, IdentityFallback, LibraryField, LookField, PairingField, PublishChild, RoleNameField, RoleSlugField, RolesField, RolesGrantsField, RolesMatrixField, RolesRowLabel, SectionHeading, ThemeDocumentControls, ThemeSaveButton };
3325
3399
 
3326
3400
  //# sourceMappingURL=admin.mjs.map