@bison-lab/payload-core 3.11.0 → 3.12.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 +41 -16
- package/dist/admin.d.mts +16 -1
- package/dist/admin.d.mts.map +1 -1
- package/dist/admin.mjs +236 -3
- package/dist/admin.mjs.map +1 -1
- package/dist/identity-DZOb3_Gk.mjs.map +1 -1
- package/dist/index.d.mts +251 -5
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +658 -3
- package/dist/index.mjs.map +1 -1
- package/dist/looks-BbL309kO.mjs.map +1 -1
- package/dist/{looks-DsizRfFV.d.mts → looks-CLxXwASa.d.mts} +3 -4
- package/dist/{looks-DsizRfFV.d.mts.map → looks-CLxXwASa.d.mts.map} +1 -1
- package/dist/theme.d.mts +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# `@bison-lab/payload-core`
|
|
2
2
|
|
|
3
3
|
Site-agnostic Payload CMS configuration for Bison Lab sites: the SEO tab on
|
|
4
|
-
a collection, the Theme Global, and the readers a page
|
|
5
|
-
layout use.
|
|
6
|
-
|
|
4
|
+
a collection, the Theme Global, the Roles Global, and the readers a page
|
|
5
|
+
route and a root layout use. Collection factories join it here as they
|
|
6
|
+
are extracted.
|
|
7
7
|
|
|
8
8
|
Full guide: <https://payload.bisonlab.ai/site/seo/>
|
|
9
9
|
|
|
@@ -22,10 +22,10 @@ lockstep.
|
|
|
22
22
|
|
|
23
23
|
| Import | Contents | Runs where |
|
|
24
24
|
| ---------------------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
|
|
25
|
-
| `@bison-lab/payload-core` | `seoPlugin`, `createTheme`, `createBrandAssets`, `seedTheme`, `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`, `createPages`, `createUsers`, `createMedia`, `adminOnlyApiTab`, `seedTheme`, `seedRoles`, 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
|
-
| `@bison-lab/payload-core/admin` | Theme child fields
|
|
28
|
+
| `@bison-lab/payload-core/admin` | Theme child fields, the Roles matrix field, and the Users Roles checklist | Admin. Referenced by import-map string; `generate:importmap` writes it. |
|
|
29
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
|
|
@@ -137,15 +137,20 @@ is never enforced and lives in the Needs-attention modal, not on the page.
|
|
|
137
137
|
Pass `destructive` (or `seed.brandDestructive`); otherwise Theme uses the
|
|
138
138
|
library’s `DESTRUCTIVE_SCALE_HEX` (`#ef4444`). Success falls back to `#22c55e`.
|
|
139
139
|
|
|
140
|
-
**1. Register the Global.** Access is required —
|
|
141
|
-
|
|
142
|
-
`update`.
|
|
140
|
+
**1. Register the Global.** Access is required — Theme does not read the
|
|
141
|
+
Roles Global. Pass `canManageBrand` as `update`.
|
|
143
142
|
|
|
144
143
|
```ts
|
|
145
144
|
// payload.config.ts
|
|
146
|
-
import {
|
|
145
|
+
import {
|
|
146
|
+
BRAND_ASSETS_SLUG,
|
|
147
|
+
canManageBrand,
|
|
148
|
+
createBrandAssets,
|
|
149
|
+
createRoles,
|
|
150
|
+
createTheme,
|
|
151
|
+
isAuthenticated,
|
|
152
|
+
} from "@bison-lab/payload-core";
|
|
147
153
|
import bisonConfig from "../bison.config.json";
|
|
148
|
-
import { canManageBrand, isAuthenticated } from "@/platform/access";
|
|
149
154
|
|
|
150
155
|
export default buildConfig({
|
|
151
156
|
collections: [
|
|
@@ -154,6 +159,7 @@ export default buildConfig({
|
|
|
154
159
|
}),
|
|
155
160
|
],
|
|
156
161
|
globals: [
|
|
162
|
+
createRoles(),
|
|
157
163
|
...createTheme({
|
|
158
164
|
access: { read: isAuthenticated, update: canManageBrand },
|
|
159
165
|
seed: bisonConfig,
|
|
@@ -181,11 +187,12 @@ so the site renders what `bison-theme.css` rendered before anyone opens the
|
|
|
181
187
|
admin:
|
|
182
188
|
|
|
183
189
|
```ts
|
|
184
|
-
import { seedTheme } from "@bison-lab/payload-core";
|
|
190
|
+
import { seedRoles, seedTheme } from "@bison-lab/payload-core";
|
|
185
191
|
import bisonConfig from "../bison.config.json";
|
|
186
192
|
|
|
187
193
|
export async function up({ payload }) {
|
|
188
194
|
await seedTheme(payload, bisonConfig);
|
|
195
|
+
await seedRoles(payload);
|
|
189
196
|
}
|
|
190
197
|
```
|
|
191
198
|
|
|
@@ -233,17 +240,35 @@ Versions stay on so a replaced file can be rolled back.
|
|
|
233
240
|
Each row carries a label, usage notes, and required alt text so a logo
|
|
234
241
|
has its accessible name. Then `payload migrate:create`.
|
|
235
242
|
|
|
243
|
+
## Roles
|
|
244
|
+
|
|
245
|
+
Settings → Roles is an Admin-editable array. Rank is drag-to-reorder.
|
|
246
|
+
Ticks are Content, Brand, Publish, and Users. The API tab is locked to
|
|
247
|
+
Developer — it is not a column. Defaults ship in the package (Brand on
|
|
248
|
+
Designer only; Admin + Designer both store; Developer is exclusive).
|
|
249
|
+
`canManageBrand` and the other predicates read the saved Global and fall
|
|
250
|
+
back to that seed. The package never writes `developer` onto a user row.
|
|
251
|
+
|
|
252
|
+
## Pages, users, and media
|
|
253
|
+
|
|
254
|
+
`createPages`, `createUsers`, `createMedia`, `slugField`, and
|
|
255
|
+
`adminOnlyApiTab` ship from the same React-free entry. Pages take the
|
|
256
|
+
site's hero and layout blocks, reserved-slug predicate, and preview
|
|
257
|
+
path. Users take `secureCookies`; the Roles checklist reads the Global
|
|
258
|
+
(or the seed) and has no second ORDER / WHAT list. `adminOnlyApiTab`
|
|
259
|
+
shows the document API tab only to Developer.
|
|
260
|
+
|
|
236
261
|
## No generated types
|
|
237
262
|
|
|
238
263
|
The package cannot import a site's `payload-types`, so the shapes it reads
|
|
239
|
-
(`SeoMeta`, `SeoImageDoc`, `SeoPage`, `ThemeDoc`) are hand-written and
|
|
264
|
+
(`SeoMeta`, `SeoImageDoc`, `SeoPage`, `ThemeDoc`, `RolesDoc`) are hand-written and
|
|
240
265
|
structural. A generated `Page`, `Media` or Theme Global is assignable to
|
|
241
266
|
them; nothing carries an index signature, since an interface will not assign
|
|
242
267
|
to a type that has one.
|
|
243
268
|
|
|
244
269
|
## Changing a field
|
|
245
270
|
|
|
246
|
-
`noIndexField`, the plugin's own fields, the Theme Global fields,
|
|
247
|
-
brand-assets collection fields are columns
|
|
248
|
-
change to them is a schema change: say "run
|
|
249
|
-
the changeset.
|
|
271
|
+
`noIndexField`, the plugin's own fields, the Theme Global fields, the
|
|
272
|
+
Roles Global fields, and the brand-assets collection fields are columns
|
|
273
|
+
in every consuming site. A change to them is a schema change: say "run
|
|
274
|
+
`payload migrate:create`" in the changeset.
|
package/dist/admin.d.mts
CHANGED
|
@@ -101,5 +101,20 @@ declare const IdentityFallback: UIFieldClientComponent;
|
|
|
101
101
|
*/
|
|
102
102
|
declare const LookField: TextFieldClientComponent;
|
|
103
103
|
//#endregion
|
|
104
|
-
|
|
104
|
+
//#region src/admin/roles-matrix-field.d.ts
|
|
105
|
+
/**
|
|
106
|
+
* Payload's array field: drag rank stays, add/remove go away. Reset writes
|
|
107
|
+
* the package seed back onto the field.
|
|
108
|
+
*/
|
|
109
|
+
declare const RolesMatrixField: ArrayFieldClientComponent;
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region src/admin/roles-field.d.ts
|
|
112
|
+
/**
|
|
113
|
+
* Users Roles checklist. Order and labels come from the field options (the
|
|
114
|
+
* Roles Global, or the seed). Copy is `roleDescription`. Developer is
|
|
115
|
+
* exclusive; Admin does not swallow Designer.
|
|
116
|
+
*/
|
|
117
|
+
declare const RolesField: SelectFieldClientComponent;
|
|
118
|
+
//#endregion
|
|
119
|
+
export { AppearanceField, ColorField, ColorScaleField, ContrastReport, FontField, GreyScaleField, HiddenSaveButton, IdentityFallback, LibraryField, LookField, PairingField, PublishChild, RolesField, RolesMatrixField, SectionHeading, ThemeDocumentControls, ThemeSaveButton };
|
|
105
120
|
//# sourceMappingURL=admin.d.mts.map
|
package/dist/admin.d.mts.map
CHANGED
|
@@ -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"],"mappings":";;;;;;;;;;cAWa,UAAA,EAAY,wBAAA;;;;;;;cCsBZ,eAAA,EAAiB,yBAAA;;;;;;;;ADtB9B;cEca,YAAA,EAAc,yBAAA;;;;;;;;AFd3B;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"}
|
|
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-field.tsx"],"mappings":";;;;;;;;;;cAWa,UAAA,EAAY,wBAAA;;;;;;;cCsBZ,eAAA,EAAiB,yBAAA;;;;;;;;ADtB9B;cEca,YAAA,EAAc,yBAAA;;;;;;;;AFd3B;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;;;;;;;cCDX,gBAAA,EAAkB,yBAAA;;;;;;;;cCkBlB,UAAA,EAAY,0BAAA"}
|
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 { FieldDescription, FieldError, FieldLabel, useConfig, useField, useForm, useFormFields } from "@payloadcms/ui";
|
|
3
|
+
import { ArrayField, CheckboxInput, FieldDescription, FieldError, FieldLabel, fieldBaseClass, useConfig, useField, useForm, useFormFields } 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 { useEffect, useId, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { useCallback, useEffect, useId, 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";
|
|
@@ -2406,6 +2406,239 @@ const LookField = ({ field, path, readOnly }) => {
|
|
|
2406
2406
|
});
|
|
2407
2407
|
};
|
|
2408
2408
|
//#endregion
|
|
2409
|
-
|
|
2409
|
+
//#region src/roles/types.ts
|
|
2410
|
+
/**
|
|
2411
|
+
* The Roles Global a site's generated types will describe. Optional and
|
|
2412
|
+
* nullable, no index signature: a generated Global is assignable to this,
|
|
2413
|
+
* never the reverse.
|
|
2414
|
+
*/
|
|
2415
|
+
const ROLES = [
|
|
2416
|
+
"developer",
|
|
2417
|
+
"admin",
|
|
2418
|
+
"designer",
|
|
2419
|
+
"author"
|
|
2420
|
+
];
|
|
2421
|
+
const ROLE_LABELS = {
|
|
2422
|
+
developer: "Developer",
|
|
2423
|
+
admin: "Admin",
|
|
2424
|
+
designer: "Designer",
|
|
2425
|
+
author: "Author"
|
|
2426
|
+
};
|
|
2427
|
+
const CAPABILITIES = [
|
|
2428
|
+
"content",
|
|
2429
|
+
"brand",
|
|
2430
|
+
"publish",
|
|
2431
|
+
"users"
|
|
2432
|
+
];
|
|
2433
|
+
function isRole(value) {
|
|
2434
|
+
return typeof value === "string" && ROLES.includes(value);
|
|
2435
|
+
}
|
|
2436
|
+
//#endregion
|
|
2437
|
+
//#region src/roles/matrix.ts
|
|
2438
|
+
/**
|
|
2439
|
+
* Default rank and ticks. Brand is Designer only. The API tab is not a
|
|
2440
|
+
* column — it is locked to Developer in `isDeveloper`.
|
|
2441
|
+
*/
|
|
2442
|
+
const DEFAULT_ROLE_MATRIX = [
|
|
2443
|
+
{
|
|
2444
|
+
role: "developer",
|
|
2445
|
+
content: true,
|
|
2446
|
+
brand: true,
|
|
2447
|
+
publish: true,
|
|
2448
|
+
users: true
|
|
2449
|
+
},
|
|
2450
|
+
{
|
|
2451
|
+
role: "admin",
|
|
2452
|
+
content: true,
|
|
2453
|
+
brand: false,
|
|
2454
|
+
publish: true,
|
|
2455
|
+
users: true
|
|
2456
|
+
},
|
|
2457
|
+
{
|
|
2458
|
+
role: "designer",
|
|
2459
|
+
content: false,
|
|
2460
|
+
brand: true,
|
|
2461
|
+
publish: false,
|
|
2462
|
+
users: false
|
|
2463
|
+
},
|
|
2464
|
+
{
|
|
2465
|
+
role: "author",
|
|
2466
|
+
content: true,
|
|
2467
|
+
brand: false,
|
|
2468
|
+
publish: false,
|
|
2469
|
+
users: false
|
|
2470
|
+
}
|
|
2471
|
+
];
|
|
2472
|
+
const DEVELOPER_DESCRIPTION = "Everything Admin can do, plus the document API tab.";
|
|
2473
|
+
const CAPABILITY_LABELS = {
|
|
2474
|
+
content: "Content",
|
|
2475
|
+
brand: "Brand",
|
|
2476
|
+
publish: "Publish",
|
|
2477
|
+
users: "Users"
|
|
2478
|
+
};
|
|
2479
|
+
function defaultRolesFieldValue() {
|
|
2480
|
+
return DEFAULT_ROLE_MATRIX.map((row) => ({
|
|
2481
|
+
id: row.role,
|
|
2482
|
+
...row
|
|
2483
|
+
}));
|
|
2484
|
+
}
|
|
2485
|
+
function roleSelectOptions(matrix = DEFAULT_ROLE_MATRIX) {
|
|
2486
|
+
return matrix.map((row) => ({
|
|
2487
|
+
label: ROLE_LABELS[row.role],
|
|
2488
|
+
value: row.role
|
|
2489
|
+
}));
|
|
2490
|
+
}
|
|
2491
|
+
/** Capability copy only. Developer names the API tab; nothing about MCP or seed. */
|
|
2492
|
+
function roleDescription(role, matrix = DEFAULT_ROLE_MATRIX) {
|
|
2493
|
+
if (role === "developer") return DEVELOPER_DESCRIPTION;
|
|
2494
|
+
const row = matrix.find((entry) => entry.role === role);
|
|
2495
|
+
if (!row) return "No capabilities";
|
|
2496
|
+
return CAPABILITIES.filter((capability) => row[capability]).map((capability) => CAPABILITY_LABELS[capability]).join(", ") || "No capabilities";
|
|
2497
|
+
}
|
|
2498
|
+
//#endregion
|
|
2499
|
+
//#region src/admin/roles-matrix-field.tsx
|
|
2500
|
+
const HIDE_ROW_CHROME = `.bl-roles-matrix .array-field__add-row,.bl-roles-matrix .array-actions__add,.bl-roles-matrix .array-actions__remove,.bl-roles-matrix .array-actions__duplicate,.bl-roles-matrix .array-actions__copy{display:none}.bl-roles-matrix__toolbar{display:flex;justify-content:flex-end;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}`;
|
|
2501
|
+
/**
|
|
2502
|
+
* Payload's array field: drag rank stays, add/remove go away. Reset writes
|
|
2503
|
+
* the package seed back onto the field.
|
|
2504
|
+
*/
|
|
2505
|
+
const RolesMatrixField = (props) => {
|
|
2506
|
+
const { setValue } = useField({ path: props.path });
|
|
2507
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2508
|
+
className: "bl-roles-matrix",
|
|
2509
|
+
children: [
|
|
2510
|
+
/* @__PURE__ */ jsx("style", {
|
|
2511
|
+
href: "bl-roles-matrix",
|
|
2512
|
+
precedence: "default",
|
|
2513
|
+
children: HIDE_ROW_CHROME
|
|
2514
|
+
}),
|
|
2515
|
+
/* @__PURE__ */ jsx("div", {
|
|
2516
|
+
className: "bl-roles-matrix__toolbar",
|
|
2517
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
2518
|
+
type: "button",
|
|
2519
|
+
className: "bl-roles-matrix__reset",
|
|
2520
|
+
onClick: () => setValue(defaultRolesFieldValue()),
|
|
2521
|
+
children: "Reset to defaults"
|
|
2522
|
+
})
|
|
2523
|
+
}),
|
|
2524
|
+
/* @__PURE__ */ jsx(ArrayField, { ...props })
|
|
2525
|
+
]
|
|
2526
|
+
});
|
|
2527
|
+
};
|
|
2528
|
+
//#endregion
|
|
2529
|
+
//#region src/admin/roles-field.tsx
|
|
2530
|
+
const GRID_CSS = `.bl-roles__grid{display:grid;gap:.75rem;grid-template-columns:repeat(auto-fit,minmax(12rem,1fr));margin-block:.35rem 0}.bl-roles__option{display:flex;flex-direction:column;gap:.25rem;padding:.65rem .75rem;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:8px}.bl-roles__option.is-checked{border-color:var(--theme-elevation-400,#94a3b8)}.bl-roles__option.is-included{opacity:.7}.bl-roles__what{font-size:.8rem;line-height:1.35;color:var(--theme-elevation-500,#64748b)}`;
|
|
2531
|
+
function optionValue(option) {
|
|
2532
|
+
return typeof option === "string" ? option : String(option.value);
|
|
2533
|
+
}
|
|
2534
|
+
function optionLabel(option) {
|
|
2535
|
+
return typeof option === "string" ? option : String(option.label);
|
|
2536
|
+
}
|
|
2537
|
+
/**
|
|
2538
|
+
* Users Roles checklist. Order and labels come from the field options (the
|
|
2539
|
+
* Roles Global, or the seed). Copy is `roleDescription`. Developer is
|
|
2540
|
+
* exclusive; Admin does not swallow Designer.
|
|
2541
|
+
*/
|
|
2542
|
+
const RolesField = ({ field, path: pathFromProps, readOnly, validate }) => {
|
|
2543
|
+
const { admin: { description } = {}, label, localized, options = [], required } = field;
|
|
2544
|
+
const offered = (options.length ? options : roleSelectOptions()).map((option) => ({
|
|
2545
|
+
value: optionValue(option),
|
|
2546
|
+
label: optionLabel(option)
|
|
2547
|
+
}));
|
|
2548
|
+
const { disabled, errorMessage, path, setValue, showError, value } = useField({
|
|
2549
|
+
potentiallyStalePath: pathFromProps,
|
|
2550
|
+
validate: useCallback((value, validationOptions) => {
|
|
2551
|
+
if (typeof validate === "function") return validate(value, {
|
|
2552
|
+
...validationOptions,
|
|
2553
|
+
hasMany: true,
|
|
2554
|
+
options,
|
|
2555
|
+
required
|
|
2556
|
+
});
|
|
2557
|
+
return true;
|
|
2558
|
+
}, [
|
|
2559
|
+
validate,
|
|
2560
|
+
options,
|
|
2561
|
+
required
|
|
2562
|
+
])
|
|
2563
|
+
});
|
|
2564
|
+
const selected = Array.isArray(value) ? value : [];
|
|
2565
|
+
const exclusive = selected.includes("developer") ? "developer" : null;
|
|
2566
|
+
const locked = Boolean(readOnly) || disabled;
|
|
2567
|
+
function toggle(role) {
|
|
2568
|
+
if (locked) return;
|
|
2569
|
+
if (role === "developer") {
|
|
2570
|
+
setValue(selected.includes(role) ? [] : ["developer"]);
|
|
2571
|
+
return;
|
|
2572
|
+
}
|
|
2573
|
+
if (exclusive) return;
|
|
2574
|
+
setValue(selected.includes(role) ? selected.filter((entry) => entry !== role) : [...selected, role]);
|
|
2575
|
+
}
|
|
2576
|
+
const groupLabel = typeof label === "string" ? label : "Roles";
|
|
2577
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2578
|
+
className: [
|
|
2579
|
+
fieldBaseClass,
|
|
2580
|
+
"select",
|
|
2581
|
+
"bl-roles",
|
|
2582
|
+
showError && "error",
|
|
2583
|
+
locked && "read-only"
|
|
2584
|
+
].filter(Boolean).join(" "),
|
|
2585
|
+
id: `field-${path.replace(/\./g, "__")}`,
|
|
2586
|
+
children: [
|
|
2587
|
+
/* @__PURE__ */ jsx("style", {
|
|
2588
|
+
href: "bl-roles",
|
|
2589
|
+
precedence: "default",
|
|
2590
|
+
children: GRID_CSS
|
|
2591
|
+
}),
|
|
2592
|
+
/* @__PURE__ */ jsx(FieldLabel, {
|
|
2593
|
+
as: "span",
|
|
2594
|
+
label,
|
|
2595
|
+
localized,
|
|
2596
|
+
path,
|
|
2597
|
+
required
|
|
2598
|
+
}),
|
|
2599
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2600
|
+
className: `${fieldBaseClass}__wrap`,
|
|
2601
|
+
children: [/* @__PURE__ */ jsx(FieldError, {
|
|
2602
|
+
message: errorMessage,
|
|
2603
|
+
path,
|
|
2604
|
+
showError
|
|
2605
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
2606
|
+
"aria-label": groupLabel,
|
|
2607
|
+
className: "bl-roles__grid",
|
|
2608
|
+
role: "group",
|
|
2609
|
+
children: offered.map((option) => {
|
|
2610
|
+
const role = isRole(option.value) ? option.value : null;
|
|
2611
|
+
if (!role) return null;
|
|
2612
|
+
const included = exclusive !== null && role !== exclusive;
|
|
2613
|
+
const checked = selected.includes(role);
|
|
2614
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2615
|
+
className: [
|
|
2616
|
+
"bl-roles__option",
|
|
2617
|
+
checked && "is-checked",
|
|
2618
|
+
included && "is-included"
|
|
2619
|
+
].filter(Boolean).join(" "),
|
|
2620
|
+
children: [/* @__PURE__ */ jsx(CheckboxInput, {
|
|
2621
|
+
checked,
|
|
2622
|
+
id: `${path}-${role}`,
|
|
2623
|
+
label: option.label || ROLE_LABELS[role],
|
|
2624
|
+
onToggle: () => toggle(role),
|
|
2625
|
+
readOnly: locked || included
|
|
2626
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
2627
|
+
className: "bl-roles__what",
|
|
2628
|
+
children: included ? "Included in Developer" : roleDescription(role)
|
|
2629
|
+
})]
|
|
2630
|
+
}, role);
|
|
2631
|
+
})
|
|
2632
|
+
})]
|
|
2633
|
+
}),
|
|
2634
|
+
/* @__PURE__ */ jsx(FieldDescription, {
|
|
2635
|
+
description,
|
|
2636
|
+
path
|
|
2637
|
+
})
|
|
2638
|
+
]
|
|
2639
|
+
});
|
|
2640
|
+
};
|
|
2641
|
+
//#endregion
|
|
2642
|
+
export { AppearanceField, ColorField, ColorScaleField, ContrastReport, FontField, GreyScaleField, HiddenSaveButton, IdentityFallback, LibraryField, LookField, PairingField, PublishChild, RolesField, RolesMatrixField, SectionHeading, ThemeDocumentControls, ThemeSaveButton };
|
|
2410
2643
|
|
|
2411
2644
|
//# sourceMappingURL=admin.mjs.map
|