@bison-lab/payload-core 3.9.0 → 3.11.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 +16 -9
- package/dist/admin.d.mts +34 -13
- package/dist/admin.d.mts.map +1 -1
- package/dist/admin.mjs +726 -371
- package/dist/admin.mjs.map +1 -1
- package/dist/identity-DZOb3_Gk.mjs +383 -0
- package/dist/identity-DZOb3_Gk.mjs.map +1 -0
- package/dist/index.d.mts +30 -6
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +285 -196
- package/dist/index.mjs.map +1 -1
- package/dist/{map-BUDkX8g1.mjs → looks-BbL309kO.mjs} +94 -6
- package/dist/looks-BbL309kO.mjs.map +1 -0
- package/dist/{library-BGq4wGif.d.mts → looks-DsizRfFV.d.mts} +62 -8
- package/dist/looks-DsizRfFV.d.mts.map +1 -0
- package/dist/react.mjs +28 -3
- package/dist/react.mjs.map +1 -1
- package/dist/theme.d.mts +11 -2
- package/dist/theme.d.mts.map +1 -1
- package/dist/theme.mjs +40 -4
- package/dist/theme.mjs.map +1 -1
- package/package.json +4 -3
- package/dist/identity-D1X0Om4Z.mjs +0 -198
- package/dist/identity-D1X0Om4Z.mjs.map +0 -1
- package/dist/library-BGq4wGif.d.mts.map +0 -1
- package/dist/map-BUDkX8g1.mjs.map +0 -1
package/dist/admin.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { r as
|
|
3
|
-
import { FieldDescription, FieldError, FieldLabel, useField, useForm, useFormFields } from "@payloadcms/ui";
|
|
4
|
-
import { GREY_SCALES, SHADE_STEPS, contrastForeground, contrastRatio, createColorScale, hexToHSL, hslToString, includedShadeSteps, isThemeHex, presetHints,
|
|
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";
|
|
4
|
+
import { GREY_SCALES, SHADE_STEPS, contrastForeground, contrastRatio, createColorScale, deriveDarkPalette, deriveLightPalette, hexToHSL, hslToString, includedShadeSteps, isThemeHex, presetHints, setColorScaleInclude } from "@bison-lab/tokens";
|
|
5
5
|
import { useEffect, useId, useMemo, useRef, useState } from "react";
|
|
6
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { createPortal } from "react-dom";
|
|
7
8
|
import { findFont, fontFaceCss, isFontId } from "@bison-lab/fonts";
|
|
8
9
|
//#region src/admin/color-field.tsx
|
|
9
10
|
const HEX_ERROR = "Enter a six-digit hex colour like #1e3a5f";
|
|
@@ -40,7 +41,7 @@ const ColorField = ({ field, path, readOnly }) => {
|
|
|
40
41
|
/* @__PURE__ */ jsx("style", {
|
|
41
42
|
href: "bl-color-field",
|
|
42
43
|
precedence: "default",
|
|
43
|
-
children: CSS$
|
|
44
|
+
children: CSS$4
|
|
44
45
|
}),
|
|
45
46
|
/* @__PURE__ */ jsx(FieldLabel, {
|
|
46
47
|
htmlFor: hexId,
|
|
@@ -99,7 +100,7 @@ const ColorField = ({ field, path, readOnly }) => {
|
|
|
99
100
|
]
|
|
100
101
|
});
|
|
101
102
|
};
|
|
102
|
-
const CSS$
|
|
103
|
+
const CSS$4 = `
|
|
103
104
|
.bl-color-field__control{display:flex;align-items:center;gap:calc(var(--base) * .4)}
|
|
104
105
|
.bl-color-field__swatch{flex:none;width:calc(var(--base) * 1.6);height:calc(var(--base) * 1.6);border:1px solid var(--theme-elevation-150);border-radius:var(--style-radius-s);background:var(--theme-elevation-50)}
|
|
105
106
|
.bl-color-field__picker{flex:none;width:calc(var(--base) * 2);height:calc(var(--base) * 2);padding:0;border:1px solid var(--theme-elevation-150);border-radius:var(--style-radius-s);background:transparent;cursor:pointer}
|
|
@@ -246,12 +247,12 @@ const SYSTEM_COLOR_COPY = {
|
|
|
246
247
|
},
|
|
247
248
|
success: {
|
|
248
249
|
label: "Success",
|
|
249
|
-
hint: "
|
|
250
|
+
hint: "Success messages and confirmations",
|
|
250
251
|
group: "status"
|
|
251
252
|
},
|
|
252
253
|
destructive: {
|
|
253
254
|
label: "Destructive",
|
|
254
|
-
hint: "
|
|
255
|
+
hint: "Errors, dangerous actions, and destructive confirmations",
|
|
255
256
|
group: "status"
|
|
256
257
|
}
|
|
257
258
|
};
|
|
@@ -312,10 +313,6 @@ function destructiveHueWarning(hex) {
|
|
|
312
313
|
if (h <= 30 || h >= 330) return null;
|
|
313
314
|
return "Keep destructive colors recognizable — stay in a red family.";
|
|
314
315
|
}
|
|
315
|
-
function automaticLabel(hex) {
|
|
316
|
-
if (!isThemeHex(hex)) return null;
|
|
317
|
-
return contrastForeground(hexToHSL(hex));
|
|
318
|
-
}
|
|
319
316
|
function hslCss(value) {
|
|
320
317
|
return `hsl(${value})`;
|
|
321
318
|
}
|
|
@@ -348,33 +345,138 @@ function readabilityRatioLine(sample, target = 7) {
|
|
|
348
345
|
const READABILITY_FIX = "Darken or lighten the hex, then regenerate the scale. The site picks light or dark type for you.";
|
|
349
346
|
const READABILITY_PUBLISH_NOTE = "You can still publish. To improve a color, darken or lighten it and regenerate.";
|
|
350
347
|
//#endregion
|
|
348
|
+
//#region src/admin/colors-layout.ts
|
|
349
|
+
/**
|
|
350
|
+
* Theme Colors tab chrome. Payload group-in-group draws a left gutter;
|
|
351
|
+
* the mockup does not. Brand cards sit two-up. Light / Dark lives on the
|
|
352
|
+
* cards only — the field list stays Payload chrome.
|
|
353
|
+
*/
|
|
354
|
+
const THEME_COLORS_LAYOUT_CSS = `
|
|
355
|
+
.group-field--gutter:has(.bl-scale-field),
|
|
356
|
+
.group-field--gutter:has(.bl-section-heading),
|
|
357
|
+
.group-field--gutter:has(.bl-grey),
|
|
358
|
+
.group-field--gutter:has(.bl-library){
|
|
359
|
+
border-left:none;
|
|
360
|
+
padding-left:0;
|
|
361
|
+
}
|
|
362
|
+
.render-fields:has(> .bl-scale-field),
|
|
363
|
+
.render-fields:has(> .field-type.bl-scale-field){
|
|
364
|
+
display:grid;
|
|
365
|
+
grid-template-columns:minmax(0,1fr) minmax(0,1fr);
|
|
366
|
+
gap:1rem;
|
|
367
|
+
align-items:start;
|
|
368
|
+
}
|
|
369
|
+
.render-fields:has(> .bl-scale-field) > .bl-section-heading,
|
|
370
|
+
.render-fields:has(> .field-type.bl-scale-field) > .bl-section-heading,
|
|
371
|
+
.render-fields:has(> .bl-scale-field) > :has(.bl-section-heading),
|
|
372
|
+
.render-fields:has(> .field-type.bl-scale-field) > :has(.bl-section-heading),
|
|
373
|
+
.render-fields:has(> .bl-scale-field) > .bl-library,
|
|
374
|
+
.render-fields:has(> .field-type.bl-scale-field) > .field-type.bl-library,
|
|
375
|
+
.render-fields:has(> .bl-scale-field) > :has(.bl-library),
|
|
376
|
+
.render-fields:has(> .field-type.bl-scale-field) > :has(.bl-library),
|
|
377
|
+
.render-fields:has(> .bl-scale-field) > :has(.bl-grey),
|
|
378
|
+
.render-fields:has(> .field-type.bl-scale-field) > :has(.bl-grey){
|
|
379
|
+
grid-column:1/-1;
|
|
380
|
+
}
|
|
381
|
+
@media (max-width:860px){
|
|
382
|
+
.render-fields:has(> .bl-scale-field),
|
|
383
|
+
.render-fields:has(> .field-type.bl-scale-field){
|
|
384
|
+
grid-template-columns:1fr;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
`;
|
|
388
|
+
//#endregion
|
|
389
|
+
//#region src/admin/portal.tsx
|
|
390
|
+
/** Theme overlays must leave Payload's transformed/clipped admin tree. */
|
|
391
|
+
function ThemePortal({ children }) {
|
|
392
|
+
if (typeof document === "undefined") return null;
|
|
393
|
+
return createPortal(children, document.body);
|
|
394
|
+
}
|
|
395
|
+
//#endregion
|
|
351
396
|
//#region src/admin/preview-mode.tsx
|
|
352
397
|
const ATTR = "data-bl-theme-preview";
|
|
353
398
|
const EVENT = "bl-theme-preview";
|
|
399
|
+
const PREVIEW_VARS = [
|
|
400
|
+
"--bl-preview-bg",
|
|
401
|
+
"--bl-preview-card",
|
|
402
|
+
"--bl-preview-border",
|
|
403
|
+
"--bl-preview-text",
|
|
404
|
+
"--bl-preview-muted",
|
|
405
|
+
"--bl-preview-input"
|
|
406
|
+
];
|
|
407
|
+
/** Brand hexes do not affect grey-driven surfaces; derive still requires them. */
|
|
408
|
+
const PREVIEW_BRAND = {
|
|
409
|
+
primary: "#111111",
|
|
410
|
+
secondary: "#111111",
|
|
411
|
+
success: "#111111"
|
|
412
|
+
};
|
|
413
|
+
let currentMode = "light";
|
|
354
414
|
function readMode() {
|
|
355
|
-
|
|
356
|
-
return document.documentElement.getAttribute(ATTR) === "dark" ? "dark" : "light";
|
|
415
|
+
return currentMode;
|
|
357
416
|
}
|
|
358
|
-
|
|
417
|
+
/** Drop leftovers from the old html-wide preview so Payload chrome stays Payload. */
|
|
418
|
+
function clearDocumentPreview() {
|
|
359
419
|
if (typeof document === "undefined") return;
|
|
360
|
-
document.documentElement.
|
|
361
|
-
|
|
420
|
+
document.documentElement.removeAttribute(ATTR);
|
|
421
|
+
for (const name of PREVIEW_VARS) document.documentElement.style.removeProperty(name);
|
|
422
|
+
}
|
|
423
|
+
function setThemePreviewMode(mode) {
|
|
424
|
+
currentMode = mode;
|
|
425
|
+
clearDocumentPreview();
|
|
426
|
+
if (typeof window !== "undefined") window.dispatchEvent(new Event(EVENT));
|
|
362
427
|
}
|
|
363
428
|
function useThemePreviewMode() {
|
|
364
429
|
const [mode, setMode] = useState(readMode);
|
|
365
430
|
useEffect(() => {
|
|
431
|
+
clearDocumentPreview();
|
|
366
432
|
const sync = () => setMode(readMode());
|
|
433
|
+
sync();
|
|
367
434
|
window.addEventListener(EVENT, sync);
|
|
368
435
|
return () => window.removeEventListener(EVENT, sync);
|
|
369
436
|
}, []);
|
|
370
437
|
return mode;
|
|
371
438
|
}
|
|
439
|
+
function previewVarsFor(grey, mode) {
|
|
440
|
+
const palette = mode === "dark" ? deriveDarkPalette({
|
|
441
|
+
...PREVIEW_BRAND,
|
|
442
|
+
grey
|
|
443
|
+
}) : deriveLightPalette({
|
|
444
|
+
...PREVIEW_BRAND,
|
|
445
|
+
grey
|
|
446
|
+
});
|
|
447
|
+
return {
|
|
448
|
+
"--bl-preview-bg": `hsl(${palette.background})`,
|
|
449
|
+
"--bl-preview-card": `hsl(${palette.card})`,
|
|
450
|
+
"--bl-preview-border": `hsl(${palette.border})`,
|
|
451
|
+
"--bl-preview-text": `hsl(${palette.foreground})`,
|
|
452
|
+
"--bl-preview-muted": `hsl(${palette["muted-foreground"]})`,
|
|
453
|
+
"--bl-preview-input": `hsl(${palette.input})`
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
function useGreyScale() {
|
|
457
|
+
return useFormFields(([fields]) => {
|
|
458
|
+
const value = fields["colors.greyScale"]?.value;
|
|
459
|
+
return value === "gray" || value === "zinc" || value === "neutral" || value === "stone" || value === "slate" ? value : "slate";
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Light / Dark + the live grey family, applied on each Theme field canvas.
|
|
464
|
+
* Never writes to `documentElement` — nav, tabs, and Publish stay Payload.
|
|
465
|
+
*/
|
|
466
|
+
function usePreviewCanvas() {
|
|
467
|
+
const mode = useThemePreviewMode();
|
|
468
|
+
return {
|
|
469
|
+
mode,
|
|
470
|
+
className: "bl-preview-canvas",
|
|
471
|
+
style: previewVarsFor(useGreyScale(), mode)
|
|
472
|
+
};
|
|
473
|
+
}
|
|
372
474
|
function ThemePreviewToggle() {
|
|
373
475
|
const mode = useThemePreviewMode();
|
|
374
476
|
return /* @__PURE__ */ jsxs("div", {
|
|
375
477
|
className: "bl-preview-toggle",
|
|
376
478
|
role: "group",
|
|
377
|
-
"aria-label": "Preview
|
|
479
|
+
"aria-label": "Preview theme in",
|
|
378
480
|
children: [/* @__PURE__ */ jsx("button", {
|
|
379
481
|
type: "button",
|
|
380
482
|
"data-on": mode === "light" ? "" : void 0,
|
|
@@ -391,7 +493,7 @@ function ThemePreviewToggle() {
|
|
|
391
493
|
const THEME_PREVIEW_TOGGLE_CSS = `
|
|
392
494
|
.bl-preview-toggle{display:inline-flex;padding:3px;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:10px;background:var(--theme-elevation-0,#fff)}
|
|
393
495
|
.bl-preview-toggle button{min-height:2rem;padding:.25rem .75rem;border:0;border-radius:7px;background:transparent;color:var(--theme-elevation-600,#475569);font:inherit;font-size:13px;font-weight:600;cursor:pointer}
|
|
394
|
-
.bl-preview-toggle button[data-on]{background:var(--theme-
|
|
496
|
+
.bl-preview-toggle button[data-on]{background:var(--theme-text,#0f172a);color:var(--theme-bg,#fff)}
|
|
395
497
|
`;
|
|
396
498
|
//#endregion
|
|
397
499
|
//#region src/admin/readability-list.tsx
|
|
@@ -431,7 +533,7 @@ function ReadabilityDetail({ item, target = 7 }) {
|
|
|
431
533
|
}
|
|
432
534
|
function ReadabilityList({ warnings, target = 7 }) {
|
|
433
535
|
const failing = warnings.filter((item) => !item.meets).length;
|
|
434
|
-
return /* @__PURE__ */ jsxs("
|
|
536
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
435
537
|
className: "bl-readability",
|
|
436
538
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
437
539
|
className: "bl-readability__head",
|
|
@@ -472,31 +574,74 @@ const READABILITY_LIST_CSS = `
|
|
|
472
574
|
`;
|
|
473
575
|
//#endregion
|
|
474
576
|
//#region src/admin/color-scale-card.tsx
|
|
577
|
+
const STATUS_COPY = {
|
|
578
|
+
success: {
|
|
579
|
+
title: "Keep success colors recognizable",
|
|
580
|
+
body: "Success states should stay in a green or teal family so users can quickly recognize positive outcomes and confirmations.",
|
|
581
|
+
drift: "This color may no longer read as a success state."
|
|
582
|
+
},
|
|
583
|
+
destructive: {
|
|
584
|
+
title: "Keep destructive colors recognizable",
|
|
585
|
+
body: "Destructive actions should stay in a red or crimson family so users can quickly recognize errors and dangerous actions.",
|
|
586
|
+
drift: "This color may no longer read as a destructive or error state."
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
function IncludeMark({ on }) {
|
|
590
|
+
return /* @__PURE__ */ jsx("span", {
|
|
591
|
+
className: "bl-scale-card__status",
|
|
592
|
+
"aria-hidden": "true",
|
|
593
|
+
children: /* @__PURE__ */ jsx("svg", {
|
|
594
|
+
viewBox: "0 0 16 16",
|
|
595
|
+
children: on ? /* @__PURE__ */ jsx("path", {
|
|
596
|
+
d: "M3.5 8.5 6.5 11.5 12.5 4.5",
|
|
597
|
+
fill: "none",
|
|
598
|
+
stroke: "currentColor",
|
|
599
|
+
strokeWidth: "2.4",
|
|
600
|
+
strokeLinecap: "round",
|
|
601
|
+
strokeLinejoin: "round"
|
|
602
|
+
}) : /* @__PURE__ */ jsx("path", {
|
|
603
|
+
d: "M4.5 4.5 11.5 11.5M11.5 4.5 4.5 11.5",
|
|
604
|
+
fill: "none",
|
|
605
|
+
stroke: "currentColor",
|
|
606
|
+
strokeWidth: "2.4",
|
|
607
|
+
strokeLinecap: "round"
|
|
608
|
+
})
|
|
609
|
+
})
|
|
610
|
+
});
|
|
611
|
+
}
|
|
475
612
|
function ColorScaleCard({ id, name, hint, required, custom, state, onChange, onDelete, readOnly, role }) {
|
|
476
|
-
const label = automaticLabel(state.hex);
|
|
477
613
|
const warning = fillLabelWarning(id ?? name.toLowerCase(), name, state.hex);
|
|
478
|
-
const
|
|
479
|
-
const
|
|
480
|
-
const [
|
|
614
|
+
const canvas = usePreviewCanvas();
|
|
615
|
+
const [attentionOpen, setAttentionOpen] = useState(false);
|
|
616
|
+
const [shakeStep, setShakeStep] = useState(null);
|
|
617
|
+
const [hexDraft, setHexDraft] = useState(state.hex);
|
|
481
618
|
const titleId = useId();
|
|
482
|
-
const hueWarning = role === "success" ? successHueWarning(state.hex) : role === "destructive" ? destructiveHueWarning(state.hex) : null;
|
|
483
619
|
const included = new Set(includedShadeSteps(state));
|
|
484
|
-
|
|
485
|
-
|
|
620
|
+
const hueDrift = role === "success" ? Boolean(successHueWarning(state.hex)) : role === "destructive" ? Boolean(destructiveHueWarning(state.hex)) : false;
|
|
621
|
+
useEffect(() => {
|
|
622
|
+
setHexDraft(state.hex);
|
|
623
|
+
}, [state.hex]);
|
|
624
|
+
function commitHex(hex) {
|
|
625
|
+
onChange(createColorScale(hex, state.sourceStep, state.include));
|
|
486
626
|
}
|
|
487
|
-
function
|
|
488
|
-
onChange(
|
|
627
|
+
function commitStep(step) {
|
|
628
|
+
onChange(createColorScale(state.hex, step, state.include));
|
|
489
629
|
}
|
|
490
630
|
function toggleStep(step) {
|
|
491
|
-
if (step === state.sourceStep)
|
|
631
|
+
if (step === state.sourceStep) {
|
|
632
|
+
setShakeStep(step);
|
|
633
|
+
window.setTimeout(() => setShakeStep((was) => was === step ? null : was), 180);
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
492
636
|
const next = new Set(included);
|
|
493
637
|
if (next.has(step)) next.delete(step);
|
|
494
638
|
else next.add(step);
|
|
495
639
|
onChange(setColorScaleInclude(state, SHADE_STEPS.filter((item) => next.has(item))));
|
|
496
640
|
}
|
|
497
641
|
return /* @__PURE__ */ jsxs("article", {
|
|
498
|
-
className:
|
|
499
|
-
"data-preview":
|
|
642
|
+
className: `bl-scale-card ${canvas.className}`,
|
|
643
|
+
"data-preview": canvas.mode,
|
|
644
|
+
style: canvas.style,
|
|
500
645
|
children: [
|
|
501
646
|
/* @__PURE__ */ jsxs("header", {
|
|
502
647
|
className: "bl-scale-card__head",
|
|
@@ -515,26 +660,11 @@ function ColorScaleCard({ id, name, hint, required, custom, state, onChange, onD
|
|
|
515
660
|
className: "bl-scale-card__badge",
|
|
516
661
|
children: "Optional"
|
|
517
662
|
}) : null,
|
|
518
|
-
warning
|
|
519
|
-
className: "bl-scale-card__status",
|
|
520
|
-
"data-ok": "",
|
|
521
|
-
title: `Text on ${name} looks readable`,
|
|
522
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
523
|
-
"aria-hidden": "true",
|
|
524
|
-
children: "✓"
|
|
525
|
-
}), /* @__PURE__ */ jsxs("span", {
|
|
526
|
-
className: "bl-scale-card__sr",
|
|
527
|
-
children: [
|
|
528
|
-
"Text on ",
|
|
529
|
-
name,
|
|
530
|
-
" looks readable"
|
|
531
|
-
]
|
|
532
|
-
})]
|
|
533
|
-
}) : /* @__PURE__ */ jsx("button", {
|
|
663
|
+
warning && !warning.meets ? /* @__PURE__ */ jsx("button", {
|
|
534
664
|
type: "button",
|
|
535
665
|
className: "bl-scale-card__badge bl-scale-card__badge--attention",
|
|
536
666
|
"aria-haspopup": "dialog",
|
|
537
|
-
onClick: () =>
|
|
667
|
+
onClick: () => setAttentionOpen(true),
|
|
538
668
|
children: "Needs attention"
|
|
539
669
|
}) : null
|
|
540
670
|
]
|
|
@@ -551,7 +681,7 @@ function ColorScaleCard({ id, name, hint, required, custom, state, onChange, onD
|
|
|
551
681
|
}),
|
|
552
682
|
/* @__PURE__ */ jsxs("div", {
|
|
553
683
|
className: "bl-scale-card__row",
|
|
554
|
-
children: [/* @__PURE__ */ jsxs("
|
|
684
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
555
685
|
className: "bl-scale-card__field",
|
|
556
686
|
children: [/* @__PURE__ */ jsx("span", { children: "Brand hex" }), /* @__PURE__ */ jsxs("span", {
|
|
557
687
|
className: "bl-scale-card__hex-wrap",
|
|
@@ -559,17 +689,32 @@ function ColorScaleCard({ id, name, hint, required, custom, state, onChange, onD
|
|
|
559
689
|
type: "color",
|
|
560
690
|
"aria-label": `${name} picker`,
|
|
561
691
|
disabled: readOnly,
|
|
562
|
-
value: state.hex,
|
|
563
|
-
|
|
692
|
+
value: isThemeHex(state.hex) ? state.hex : "#000000",
|
|
693
|
+
onPointerDown: (event) => {
|
|
694
|
+
const input = event.currentTarget;
|
|
695
|
+
if (typeof input.showPicker !== "function") return;
|
|
696
|
+
event.preventDefault();
|
|
697
|
+
try {
|
|
698
|
+
input.showPicker();
|
|
699
|
+
} catch {
|
|
700
|
+
input.click();
|
|
701
|
+
}
|
|
702
|
+
},
|
|
703
|
+
onChange: (event) => commitHex(event.target.value)
|
|
564
704
|
}), /* @__PURE__ */ jsx("input", {
|
|
565
705
|
type: "text",
|
|
566
706
|
spellCheck: false,
|
|
567
707
|
autoComplete: "off",
|
|
568
708
|
disabled: readOnly,
|
|
569
|
-
|
|
709
|
+
"aria-label": `${name} hex`,
|
|
710
|
+
value: hexDraft,
|
|
570
711
|
onChange: (event) => {
|
|
571
712
|
const next = event.target.value.trim();
|
|
572
|
-
|
|
713
|
+
setHexDraft(next);
|
|
714
|
+
if (isThemeHex(next)) commitHex(next);
|
|
715
|
+
},
|
|
716
|
+
onBlur: () => {
|
|
717
|
+
if (!isThemeHex(hexDraft)) setHexDraft(state.hex);
|
|
573
718
|
}
|
|
574
719
|
})]
|
|
575
720
|
})]
|
|
@@ -578,7 +723,7 @@ function ColorScaleCard({ id, name, hint, required, custom, state, onChange, onD
|
|
|
578
723
|
children: [/* @__PURE__ */ jsx("span", { children: "This color is" }), /* @__PURE__ */ jsx("select", {
|
|
579
724
|
disabled: readOnly,
|
|
580
725
|
value: String(state.sourceStep),
|
|
581
|
-
onChange: (event) =>
|
|
726
|
+
onChange: (event) => commitStep(Number(event.target.value)),
|
|
582
727
|
children: SHADE_STEPS.map((step) => /* @__PURE__ */ jsx("option", {
|
|
583
728
|
value: step,
|
|
584
729
|
children: step
|
|
@@ -586,49 +731,29 @@ function ColorScaleCard({ id, name, hint, required, custom, state, onChange, onD
|
|
|
586
731
|
})]
|
|
587
732
|
})]
|
|
588
733
|
}),
|
|
589
|
-
/* @__PURE__ */ jsxs("div", {
|
|
590
|
-
className: "bl-scale-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
734
|
+
role ? /* @__PURE__ */ jsxs("div", {
|
|
735
|
+
className: "bl-scale-card__family",
|
|
736
|
+
"data-role": role,
|
|
737
|
+
"data-drift": hueDrift ? "" : void 0,
|
|
738
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
739
|
+
className: "bl-scale-card__family-mark",
|
|
740
|
+
"aria-hidden": "true",
|
|
741
|
+
children: "!"
|
|
742
|
+
}), /* @__PURE__ */ jsxs("div", { children: [
|
|
743
|
+
/* @__PURE__ */ jsx("div", {
|
|
744
|
+
className: "bl-scale-card__family-title",
|
|
745
|
+
children: STATUS_COPY[role].title
|
|
746
|
+
}),
|
|
747
|
+
/* @__PURE__ */ jsx("p", { children: STATUS_COPY[role].body }),
|
|
748
|
+
hueDrift ? /* @__PURE__ */ jsx("p", {
|
|
749
|
+
className: "bl-scale-card__family-drift",
|
|
750
|
+
children: STATUS_COPY[role].drift
|
|
751
|
+
}) : null
|
|
752
|
+
] })]
|
|
607
753
|
}) : null,
|
|
608
|
-
/* @__PURE__ */ jsx("button", {
|
|
609
|
-
type: "button",
|
|
610
|
-
className: "bl-scale-card__regen",
|
|
611
|
-
disabled: readOnly || !state.stale,
|
|
612
|
-
onClick: () => onChange(regenerateColorScale(state)),
|
|
613
|
-
children: "Regenerate scale"
|
|
614
|
-
}),
|
|
615
754
|
/* @__PURE__ */ jsxs("div", {
|
|
616
755
|
className: "bl-scale-card__scale-head",
|
|
617
|
-
children: [/* @__PURE__ */ jsx("span", { children: "Generated scale" }), /* @__PURE__ */ jsxs("span", { children: [
|
|
618
|
-
/* @__PURE__ */ jsx("button", {
|
|
619
|
-
type: "button",
|
|
620
|
-
disabled: readOnly,
|
|
621
|
-
onClick: () => onChange(setColorScaleInclude(state, "all")),
|
|
622
|
-
children: "Include all"
|
|
623
|
-
}),
|
|
624
|
-
" · ",
|
|
625
|
-
/* @__PURE__ */ jsx("button", {
|
|
626
|
-
type: "button",
|
|
627
|
-
disabled: readOnly,
|
|
628
|
-
onClick: () => onChange(setColorScaleInclude(state, "source")),
|
|
629
|
-
children: "Source only"
|
|
630
|
-
})
|
|
631
|
-
] })]
|
|
756
|
+
children: [/* @__PURE__ */ jsx("span", { children: "Generated scale" }), /* @__PURE__ */ jsxs("span", { children: [SHADE_STEPS.length, " shades"] })]
|
|
632
757
|
}),
|
|
633
758
|
/* @__PURE__ */ jsx("div", {
|
|
634
759
|
className: "bl-scale-card__steps",
|
|
@@ -642,12 +767,22 @@ function ColorScaleCard({ id, name, hint, required, custom, state, onChange, onD
|
|
|
642
767
|
className: "bl-scale-card__step",
|
|
643
768
|
"data-source": source ? "" : void 0,
|
|
644
769
|
"data-excluded": on ? void 0 : "",
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
770
|
+
"data-shake": shakeStep === step ? "" : void 0,
|
|
771
|
+
disabled: readOnly,
|
|
772
|
+
"aria-pressed": on,
|
|
773
|
+
"aria-label": source ? `Source step ${step} cannot be excluded` : on ? `Shade ${step}, available — click to exclude from the palette` : `Shade ${step}, excluded — click to include in the palette`,
|
|
774
|
+
title: source ? `Source step ${step} cannot be excluded` : on ? "Available to page editors — click to exclude" : "Excluded from page editors — click to include",
|
|
775
|
+
onClick: (event) => {
|
|
776
|
+
event.preventDefault();
|
|
777
|
+
event.stopPropagation();
|
|
778
|
+
toggleStep(step);
|
|
779
|
+
},
|
|
780
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
781
|
+
className: "bl-scale-card__chip-wrap",
|
|
782
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
783
|
+
className: "bl-scale-card__chip",
|
|
784
|
+
style: { backgroundColor: hslCss(state.scale[step]) }
|
|
785
|
+
}), /* @__PURE__ */ jsx(IncludeMark, { on })]
|
|
651
786
|
}), /* @__PURE__ */ jsx("span", {
|
|
652
787
|
className: "bl-scale-card__step-label",
|
|
653
788
|
children: step
|
|
@@ -655,13 +790,32 @@ function ColorScaleCard({ id, name, hint, required, custom, state, onChange, onD
|
|
|
655
790
|
}, step);
|
|
656
791
|
})
|
|
657
792
|
}),
|
|
658
|
-
|
|
793
|
+
/* @__PURE__ */ jsxs("div", {
|
|
794
|
+
className: "bl-scale-card__editors",
|
|
795
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", { children: "Available to page editors" }), /* @__PURE__ */ jsxs("p", { children: [
|
|
796
|
+
included.size,
|
|
797
|
+
" of ",
|
|
798
|
+
SHADE_STEPS.length,
|
|
799
|
+
" shades available · Choose which shades editors can select when building pages."
|
|
800
|
+
] })] }), /* @__PURE__ */ jsxs("span", { children: [/* @__PURE__ */ jsx("button", {
|
|
801
|
+
type: "button",
|
|
802
|
+
disabled: readOnly,
|
|
803
|
+
onClick: () => onChange(setColorScaleInclude(state, "all")),
|
|
804
|
+
children: "Include all"
|
|
805
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
806
|
+
type: "button",
|
|
807
|
+
disabled: readOnly,
|
|
808
|
+
onClick: () => onChange(setColorScaleInclude(state, "source")),
|
|
809
|
+
children: "Source only"
|
|
810
|
+
})] })]
|
|
811
|
+
}),
|
|
812
|
+
attentionOpen && warning ? /* @__PURE__ */ jsx(ThemePortal, { children: /* @__PURE__ */ jsx("div", {
|
|
659
813
|
className: "bl-scale-card__modal",
|
|
660
814
|
role: "dialog",
|
|
661
815
|
"aria-modal": "true",
|
|
662
816
|
"aria-labelledby": titleId,
|
|
663
817
|
onClick: (event) => {
|
|
664
|
-
if (event.target === event.currentTarget)
|
|
818
|
+
if (event.target === event.currentTarget) setAttentionOpen(false);
|
|
665
819
|
},
|
|
666
820
|
children: /* @__PURE__ */ jsxs("div", {
|
|
667
821
|
className: "bl-scale-card__panel",
|
|
@@ -673,7 +827,7 @@ function ColorScaleCard({ id, name, hint, required, custom, state, onChange, onD
|
|
|
673
827
|
children: readabilityHeadline(warning)
|
|
674
828
|
}), /* @__PURE__ */ jsx("button", {
|
|
675
829
|
type: "button",
|
|
676
|
-
onClick: () =>
|
|
830
|
+
onClick: () => setAttentionOpen(false),
|
|
677
831
|
"aria-label": "Close",
|
|
678
832
|
children: "×"
|
|
679
833
|
})]
|
|
@@ -682,67 +836,90 @@ function ColorScaleCard({ id, name, hint, required, custom, state, onChange, onD
|
|
|
682
836
|
/* @__PURE__ */ jsx("button", {
|
|
683
837
|
type: "button",
|
|
684
838
|
className: "bl-scale-card__panel-done",
|
|
685
|
-
onClick: () =>
|
|
839
|
+
onClick: () => setAttentionOpen(false),
|
|
686
840
|
children: "Keep editing this color"
|
|
687
841
|
})
|
|
688
842
|
]
|
|
689
843
|
})
|
|
690
|
-
}) : null
|
|
844
|
+
}) }) : null
|
|
691
845
|
]
|
|
692
846
|
});
|
|
693
847
|
}
|
|
694
848
|
const COLOR_SCALE_CARD_CSS = `
|
|
695
|
-
.bl-scale-card{padding:calc(var(--base,16px) * .8);border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:var(--style-radius-m,12px);background:var(--theme-elevation-0,#fff)}
|
|
849
|
+
.bl-scale-card{padding:calc(var(--base,16px) * .8);border:1px solid var(--bl-preview-border,var(--theme-elevation-150,#e2e8f0));border-radius:var(--style-radius-m,12px);background:var(--bl-preview-card,var(--theme-elevation-0,#fff));color:var(--bl-preview-text,inherit)}
|
|
696
850
|
.bl-scale-card__head{display:flex;justify-content:space-between;gap:1rem;align-items:flex-start}
|
|
697
851
|
.bl-scale-card__title-row{position:relative;display:flex;align-items:center;flex-wrap:wrap;gap:.5rem}
|
|
698
852
|
.bl-scale-card__title{margin:0;font-size:1rem}
|
|
699
|
-
.bl-scale-card__badge{font:inherit;font-size:10px;text-transform:uppercase;letter-spacing:.04em;padding:.15rem .45rem;border-radius:999px;border:0;background
|
|
853
|
+
.bl-scale-card__badge{font:inherit;font-size:10px;text-transform:uppercase;letter-spacing:.04em;padding:.15rem .45rem;border-radius:999px;border:0;background:#e2e8f0;color:#0f172a}
|
|
700
854
|
.bl-scale-card__badge--attention{background:#fff1f2;color:#be123c;cursor:pointer}
|
|
701
|
-
.bl-scale-
|
|
702
|
-
.bl-scale-card__status[data-ok]{background:#ecfdf5;color:#047857}
|
|
703
|
-
.bl-scale-card__sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
|
|
704
|
-
.bl-scale-card__hint{margin:.35rem 0 0;color:var(--theme-elevation-500,#64748b);font-size:12px}
|
|
855
|
+
.bl-scale-card__hint{margin:.35rem 0 0;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b));font-size:12px}
|
|
705
856
|
.bl-scale-card__delete{border:0;background:none;color:#be123c;font:inherit;font-size:13px;font-weight:600;cursor:pointer}
|
|
706
857
|
.bl-scale-card__row{display:grid;grid-template-columns:1fr 8rem;gap:.75rem;margin-top:1rem}
|
|
707
|
-
.bl-scale-card__field{display:flex;flex-direction:column;gap:.35rem;font-size:12px;font-weight:600;color:var(--theme-elevation-600,#475569)}
|
|
708
|
-
.bl-scale-card__hex-wrap{display:flex;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:8px;
|
|
709
|
-
.bl-scale-card__hex-wrap input[type=color]{width:2.75rem;height:2.25rem;padding:0;border:0;border-right:1px solid var(--theme-elevation-150,#e2e8f0);background:transparent;cursor:pointer}
|
|
710
|
-
.bl-scale-card__hex-wrap input[type=
|
|
711
|
-
.bl-scale-
|
|
712
|
-
.bl-scale-
|
|
713
|
-
.bl-scale-
|
|
714
|
-
.bl-scale-
|
|
715
|
-
.bl-scale-
|
|
716
|
-
.bl-scale-
|
|
717
|
-
.bl-scale-
|
|
718
|
-
.bl-scale-
|
|
719
|
-
.bl-scale-
|
|
720
|
-
.bl-scale-
|
|
721
|
-
.bl-scale-
|
|
858
|
+
.bl-scale-card__field{display:flex;flex-direction:column;gap:.35rem;font-size:12px;font-weight:600;color:var(--bl-preview-muted,var(--theme-elevation-600,#475569))}
|
|
859
|
+
.bl-scale-card__hex-wrap{display:flex;border:1px solid var(--bl-preview-border,var(--theme-elevation-150,#e2e8f0));border-radius:8px;background:var(--bl-preview-card,var(--theme-input-bg,#fff))}
|
|
860
|
+
.bl-scale-card__hex-wrap input[type=color]{width:2.75rem;height:2.25rem;padding:0;border:0;border-right:1px solid var(--bl-preview-border,var(--theme-elevation-150,#e2e8f0));border-radius:8px 0 0 8px;background:transparent;cursor:pointer;color-scheme:light;appearance:none;-webkit-appearance:none}
|
|
861
|
+
.bl-scale-card__hex-wrap input[type=color]::-webkit-color-swatch-wrapper{padding:0}
|
|
862
|
+
.bl-scale-card__hex-wrap input[type=color]::-webkit-color-swatch{border:0;border-radius:0;width:100%;height:100%}
|
|
863
|
+
.bl-scale-card__hex-wrap input[type=text]{flex:1;min-width:0;border:0;padding:.4rem .7rem;font-family:var(--font-mono,ui-monospace,monospace);font-size:13px;background:transparent;color:inherit;border-radius:0 8px 8px 0}
|
|
864
|
+
.bl-scale-card__field select{min-height:2.25rem;border:1px solid var(--bl-preview-border,var(--theme-elevation-150,#e2e8f0));border-radius:8px;padding:.35rem .5rem;background:var(--bl-preview-card,var(--theme-input-bg,#fff));color:inherit}
|
|
865
|
+
.bl-scale-card__family{display:flex;gap:.75rem;align-items:flex-start;margin-top:1rem;padding:.75rem .85rem;border-radius:8px}
|
|
866
|
+
.bl-scale-card__family[data-role=success]{border:1px solid #a7f3d0;background:#ecfdf5;color:#065f46}
|
|
867
|
+
.bl-scale-card__family[data-role=destructive]{border:1px solid #fecdd3;background:#fff1f2;color:#9f1239}
|
|
868
|
+
.bl-scale-card__family[data-drift]{box-shadow:0 0 0 2px #fbbf24}
|
|
869
|
+
.bl-scale-card__family-mark{flex:none;width:1.25rem;height:1.25rem;border-radius:999px;display:grid;place-items:center;font-size:11px;font-weight:700}
|
|
870
|
+
.bl-scale-card__family[data-role=success] .bl-scale-card__family-mark{background:#d1fae5;color:#047857}
|
|
871
|
+
.bl-scale-card__family[data-role=destructive] .bl-scale-card__family-mark{background:#ffe4e6;color:#be123c}
|
|
872
|
+
.bl-scale-card__family-title{font-size:12px;font-weight:600}
|
|
873
|
+
.bl-scale-card__family p{margin:.25rem 0 0;font-size:11px;line-height:1.45;opacity:.85}
|
|
874
|
+
.bl-scale-card__family-drift{font-weight:600;opacity:1}
|
|
875
|
+
.bl-scale-card__scale-head{display:flex;justify-content:space-between;margin:1rem 0 .4rem;font-size:12px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}
|
|
722
876
|
.bl-scale-card__steps{display:grid;grid-template-columns:repeat(11,minmax(0,1fr));gap:.45rem 3px}
|
|
723
877
|
.bl-scale-card__step{display:flex;flex-direction:column;align-items:center;gap:.3rem;border:0;padding:0;background:transparent;cursor:pointer}
|
|
724
|
-
.bl-scale-card__chip{display:block;width:100
|
|
878
|
+
.bl-scale-card__chip-wrap{position:relative;display:block;width:100%}
|
|
879
|
+
.bl-scale-card__chip{display:block;width:100%;height:2.15rem;border-radius:6px;overflow:hidden}
|
|
880
|
+
.bl-scale-card__status{position:absolute;top:3px;right:3px;width:16px;height:16px;border-radius:999px;display:grid;place-items:center;pointer-events:none;background:rgba(255,255,255,.94);color:#0f172a;box-shadow:0 1px 3px rgba(15,23,42,.18)}
|
|
881
|
+
.bl-scale-card__status svg{display:block;width:10px;height:10px}
|
|
725
882
|
.bl-scale-card__step-label{font-size:10px;line-height:1;color:var(--theme-elevation-600,#475569)}
|
|
726
883
|
.bl-scale-card__step[data-source] .bl-scale-card__chip{box-shadow:0 0 0 2px #0f172a}
|
|
727
|
-
.bl-scale-card__step[data-excluded]{opacity:.
|
|
884
|
+
.bl-scale-card__step[data-excluded] .bl-scale-card__chip{opacity:.28;background-image:linear-gradient(45deg,transparent 44%,rgba(15,23,42,.8) 45%,rgba(15,23,42,.8) 55%,transparent 56%)}
|
|
885
|
+
.bl-scale-card__step[data-excluded] .bl-scale-card__status{color:#991b1b;background:rgba(255,255,255,.96)}
|
|
886
|
+
.bl-scale-card__step[data-excluded] .bl-scale-card__step-label{opacity:.35}
|
|
887
|
+
@keyframes bl-scale-shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-3px)}75%{transform:translateX(3px)}}
|
|
888
|
+
.bl-scale-card__step[data-shake]{animation:bl-scale-shake .18s}
|
|
728
889
|
.bl-scale-card__step:disabled{cursor:default}
|
|
729
|
-
.bl-scale-
|
|
730
|
-
.bl-scale-
|
|
890
|
+
.bl-scale-card__editors{display:flex;flex-wrap:wrap;justify-content:space-between;gap:.75rem;align-items:flex-end;margin-top:.75rem;padding:.65rem .75rem;border:1px solid var(--bl-preview-border,var(--theme-elevation-150,#e2e8f0));border-radius:8px;background:var(--bl-preview-bg,var(--theme-elevation-50,#f8fafc))}
|
|
891
|
+
.bl-scale-card__editors > div > div{font-size:12px;font-weight:600;color:var(--bl-preview-text,var(--theme-elevation-700,#334155))}
|
|
892
|
+
.bl-scale-card__editors p{margin:.2rem 0 0;font-size:11px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}
|
|
893
|
+
.bl-scale-card__editors button{border:0;background:none;padding:0;margin-left:.75rem;font:inherit;font-size:12px;font-weight:600;color:var(--theme-success-500,#1587ba);text-decoration:underline;cursor:pointer}
|
|
894
|
+
.bl-scale-card__editors span{display:flex;gap:0}
|
|
895
|
+
.bl-scale-card__modal{position:fixed;inset:0;z-index:10000;display:grid;place-items:center;padding:1rem;background:rgba(15,23,42,.45)}
|
|
896
|
+
.bl-scale-card__panel{width:min(32rem,100%);padding:1.15rem 1.2rem;border-radius:16px;background:#fff;color:#0f172a;color-scheme:light}
|
|
731
897
|
.bl-scale-card__panel-head{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem}
|
|
732
898
|
.bl-scale-card__panel-head h4{margin:0;font-size:1rem}
|
|
733
899
|
.bl-scale-card__panel-head button{border:0;background:none;font:inherit;font-size:1.25rem;line-height:1;color:#64748b;cursor:pointer}
|
|
734
900
|
.bl-scale-card__panel-done{margin-top:1rem;min-height:2.1rem;padding:.35rem .85rem;border:0;border-radius:8px;background:#0f172a;color:#fff;font:inherit;font-weight:600;cursor:pointer}
|
|
735
|
-
[data-
|
|
736
|
-
|
|
737
|
-
[data-bl-theme-preview=dark] .bl-scale-card__hex-wrap,[data-bl-theme-preview=dark] .bl-scale-card__field select{background:#1e293b;border-color:#334155;color:#f8fafc}
|
|
738
|
-
[data-bl-theme-preview=dark] .bl-scale-card__step[data-source] .bl-scale-card__chip{box-shadow:0 0 0 2px #f8fafc}
|
|
739
|
-
` + READABILITY_LIST_CSS;
|
|
901
|
+
.bl-scale-card[data-preview=dark] .bl-scale-card__step[data-source] .bl-scale-card__chip{box-shadow:0 0 0 2px var(--bl-preview-text,#fafafa)}
|
|
902
|
+
` + READABILITY_LIST_CSS + THEME_COLORS_LAYOUT_CSS;
|
|
740
903
|
//#endregion
|
|
741
904
|
//#region src/admin/color-scale-field.tsx
|
|
742
905
|
const SYSTEM_ROLES = new Set(Object.keys(SYSTEM_COLOR_COPY));
|
|
743
906
|
/**
|
|
744
|
-
*
|
|
745
|
-
*
|
|
907
|
+
* Payload's hasMany select often stores a count on the field path and the
|
|
908
|
+
* chosen values at `path.0`, `path.1`, … — same shape as an array field.
|
|
909
|
+
*/
|
|
910
|
+
function includedStepsFromForm(path, value, getDataByPath) {
|
|
911
|
+
if (Array.isArray(value)) return value;
|
|
912
|
+
const stored = getDataByPath?.(path);
|
|
913
|
+
if (Array.isArray(stored)) return stored;
|
|
914
|
+
const count = typeof value === "number" ? value : typeof stored === "number" ? stored : 0;
|
|
915
|
+
if (count <= 0) return void 0;
|
|
916
|
+
const steps = Array.from({ length: count }, (_, index) => getDataByPath?.(`${path}.${index}`));
|
|
917
|
+
if (steps.every((step) => step == null)) return void 0;
|
|
918
|
+
return steps.filter((step) => step != null).map(String);
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* One system (or library row) color: hex, source step, include/exclude.
|
|
922
|
+
* Writes the group's stored fields. A committed hex or step rebuilds the scale.
|
|
746
923
|
*/
|
|
747
924
|
const ColorScaleField = ({ field, path, readOnly }) => {
|
|
748
925
|
const hex = useField({ path: `${path}.hex` });
|
|
@@ -751,15 +928,17 @@ const ColorScaleField = ({ field, path, readOnly }) => {
|
|
|
751
928
|
const stale = useField({ path: `${path}.stale` });
|
|
752
929
|
const include = useField({ path: `${path}.include` });
|
|
753
930
|
const includedSteps = useField({ path: `${path}.includedSteps` });
|
|
931
|
+
const { getDataByPath } = useForm();
|
|
754
932
|
const key = path.split(".").pop() ?? "";
|
|
755
933
|
const copy = SYSTEM_ROLES.has(key) ? SYSTEM_COLOR_COPY[key] : void 0;
|
|
934
|
+
const stepList = includedStepsFromForm(`${path}.includedSteps`, includedSteps.value, getDataByPath);
|
|
756
935
|
const state = stateFromColorDoc({
|
|
757
936
|
hex: hex.value,
|
|
758
937
|
sourceStep: sourceStep.value,
|
|
759
938
|
scale: scale.value,
|
|
760
939
|
stale: stale.value,
|
|
761
940
|
include: include.value === "source" || include.value === "custom" || include.value === "all" ? include.value : "all",
|
|
762
|
-
includedSteps:
|
|
941
|
+
includedSteps: stepList
|
|
763
942
|
});
|
|
764
943
|
function write(next) {
|
|
765
944
|
const doc = colorDocFromState(next);
|
|
@@ -768,7 +947,7 @@ const ColorScaleField = ({ field, path, readOnly }) => {
|
|
|
768
947
|
scale.setValue(doc.scale);
|
|
769
948
|
stale.setValue(doc.stale);
|
|
770
949
|
include.setValue(doc.include);
|
|
771
|
-
includedSteps.setValue(doc.includedSteps ?? (doc.include === "source" ? [doc.sourceStep] : [...SHADE_STEPS]));
|
|
950
|
+
includedSteps.setValue((doc.includedSteps ?? (doc.include === "source" ? [doc.sourceStep] : [...SHADE_STEPS])).map(String));
|
|
772
951
|
}
|
|
773
952
|
const label = copy?.label ?? (typeof field.label === "string" ? field.label : key);
|
|
774
953
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -793,17 +972,17 @@ const ColorScaleField = ({ field, path, readOnly }) => {
|
|
|
793
972
|
});
|
|
794
973
|
};
|
|
795
974
|
//#endregion
|
|
796
|
-
//#region src/theme/
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
975
|
+
//#region src/theme/library.ts
|
|
976
|
+
/**
|
|
977
|
+
* Payload's array form state stores the row count (`0`, `2`, …), not the
|
|
978
|
+
* rows. A custom Field that treats that number as the list will throw
|
|
979
|
+
* `rows.filter is not a function` on an empty Theme library.
|
|
980
|
+
*/
|
|
981
|
+
function asLibraryRows(value) {
|
|
982
|
+
return Array.isArray(value) ? value : [];
|
|
983
|
+
}
|
|
805
984
|
function themeColorKeys(doc) {
|
|
806
|
-
const custom = (doc?.colors?.library
|
|
985
|
+
const custom = asLibraryRows(doc?.colors?.library).map((row) => row.key?.trim()).filter((key) => Boolean(key));
|
|
807
986
|
return [...SYSTEM_COLOR_KEYS, ...custom];
|
|
808
987
|
}
|
|
809
988
|
/**
|
|
@@ -813,7 +992,7 @@ function themeColorKeys(doc) {
|
|
|
813
992
|
* has `key`.
|
|
814
993
|
*/
|
|
815
994
|
function deleteLibraryColor(doc, key, replacement) {
|
|
816
|
-
const library = [...doc.colors?.library
|
|
995
|
+
const library = [...asLibraryRows(doc.colors?.library)];
|
|
817
996
|
const index = library.findIndex((row) => row.key === key);
|
|
818
997
|
if (index === -1) throw new Error(`No custom color named ${JSON.stringify(key)}`);
|
|
819
998
|
library.splice(index, 1);
|
|
@@ -836,43 +1015,42 @@ function slugify(value) {
|
|
|
836
1015
|
return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
837
1016
|
}
|
|
838
1017
|
/**
|
|
839
|
-
* Custom colors: the same scale controls as system colors
|
|
840
|
-
*
|
|
1018
|
+
* Custom colors: the same scale controls as system colors. A row that is
|
|
1019
|
+
* not referenced on a page deletes immediately. Rewriting in-use tokens
|
|
1020
|
+
* (`rewriteColorToken`) waits on a site usage lookup — Theme cannot see
|
|
1021
|
+
* page assignments by itself.
|
|
841
1022
|
*/
|
|
842
|
-
const LibraryField = ({ path, readOnly }) => {
|
|
843
|
-
const
|
|
844
|
-
const
|
|
1023
|
+
const LibraryField = ({ field, path, readOnly }) => {
|
|
1024
|
+
const dataPath = typeof field.admin?.custom?.dataPath === "string" ? field.admin.custom.dataPath : path;
|
|
1025
|
+
const { value, setValue } = useField({
|
|
1026
|
+
path: dataPath,
|
|
1027
|
+
hasRows: true
|
|
1028
|
+
});
|
|
1029
|
+
const { getDataByPath } = useForm();
|
|
1030
|
+
const rows = asLibraryRows(value).length > 0 ? asLibraryRows(value) : asLibraryRows(getDataByPath?.(dataPath));
|
|
845
1031
|
const [adding, setAdding] = useState(false);
|
|
846
1032
|
const [name, setName] = useState("");
|
|
847
|
-
const [hex, setHex] = useState("
|
|
848
|
-
const [
|
|
849
|
-
const [replacement, setReplacement] = useState("");
|
|
1033
|
+
const [hex, setHex] = useState("");
|
|
1034
|
+
const [sourceStep, setSourceStep] = useState(500);
|
|
850
1035
|
function write(next) {
|
|
851
1036
|
setValue(next);
|
|
852
1037
|
}
|
|
853
1038
|
function add() {
|
|
854
1039
|
const key = slugify(name);
|
|
855
|
-
if (!key || rows.some((row) => row.key === key)) return;
|
|
1040
|
+
if (!key || !isThemeHex(hex) || rows.some((row) => row.key === key)) return;
|
|
856
1041
|
write([...rows, {
|
|
857
1042
|
key,
|
|
858
1043
|
label: name.trim(),
|
|
859
|
-
...colorDocFromState(createColorScale(hex,
|
|
1044
|
+
...colorDocFromState(createColorScale(hex, sourceStep))
|
|
860
1045
|
}]);
|
|
861
1046
|
setName("");
|
|
1047
|
+
setHex("");
|
|
1048
|
+
setSourceStep(500);
|
|
862
1049
|
setAdding(false);
|
|
863
1050
|
}
|
|
864
|
-
function remove(row
|
|
865
|
-
write(deleteLibraryColor({ colors: { library: rows } }, row.key ?? ""
|
|
866
|
-
setPendingDelete(null);
|
|
867
|
-
setReplacement("");
|
|
1051
|
+
function remove(row) {
|
|
1052
|
+
write(deleteLibraryColor({ colors: { library: rows } }, row.key ?? "").colors?.library ?? []);
|
|
868
1053
|
}
|
|
869
|
-
const replacements = [...SYSTEM_COLOR_KEYS.map((key) => ({
|
|
870
|
-
value: key,
|
|
871
|
-
label: key[0].toUpperCase() + key.slice(1)
|
|
872
|
-
})), ...rows.filter((row) => row.key && row.key !== pendingDelete?.key).map((row) => ({
|
|
873
|
-
value: row.key ?? "",
|
|
874
|
-
label: row.label ?? row.key ?? ""
|
|
875
|
-
}))];
|
|
876
1054
|
return /* @__PURE__ */ jsxs("div", {
|
|
877
1055
|
className: "field-type bl-library",
|
|
878
1056
|
children: [
|
|
@@ -884,41 +1062,80 @@ const LibraryField = ({ path, readOnly }) => {
|
|
|
884
1062
|
/* @__PURE__ */ jsx("style", {
|
|
885
1063
|
href: "bl-library",
|
|
886
1064
|
precedence: "default",
|
|
887
|
-
children: CSS$
|
|
1065
|
+
children: CSS$3
|
|
888
1066
|
}),
|
|
889
1067
|
/* @__PURE__ */ jsxs("div", {
|
|
890
1068
|
className: "bl-library__head",
|
|
891
|
-
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h2", { children: "
|
|
1069
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h2", { children: "Additional colors" }), /* @__PURE__ */ jsx("p", { children: "Add optional named colors for special sections, campaigns, or components." })] }), /* @__PURE__ */ jsx("button", {
|
|
892
1070
|
type: "button",
|
|
893
1071
|
disabled: readOnly,
|
|
894
|
-
onClick: () =>
|
|
1072
|
+
onClick: (event) => {
|
|
1073
|
+
event.preventDefault();
|
|
1074
|
+
event.stopPropagation();
|
|
1075
|
+
setAdding(true);
|
|
1076
|
+
},
|
|
895
1077
|
children: "Add color"
|
|
896
1078
|
})]
|
|
897
1079
|
}),
|
|
898
|
-
adding ? /* @__PURE__ */
|
|
899
|
-
className: "bl-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
1080
|
+
adding ? /* @__PURE__ */ jsx(ThemePortal, { children: /* @__PURE__ */ jsx("div", {
|
|
1081
|
+
className: "bl-library__modal",
|
|
1082
|
+
role: "dialog",
|
|
1083
|
+
"aria-modal": "true",
|
|
1084
|
+
"aria-labelledby": "bl-library-add-title",
|
|
1085
|
+
onClick: (event) => {
|
|
1086
|
+
if (event.target === event.currentTarget) setAdding(false);
|
|
1087
|
+
},
|
|
1088
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1089
|
+
className: "bl-library__panel",
|
|
1090
|
+
children: [
|
|
1091
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1092
|
+
className: "bl-library__panel-head",
|
|
1093
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h2", {
|
|
1094
|
+
id: "bl-library-add-title",
|
|
1095
|
+
children: "New color"
|
|
1096
|
+
}), /* @__PURE__ */ jsx("p", { children: "Give it a useful name, enter your brand hex, then say which scale step that hex is." })] }), /* @__PURE__ */ jsx("button", {
|
|
1097
|
+
type: "button",
|
|
1098
|
+
onClick: () => setAdding(false),
|
|
1099
|
+
"aria-label": "Close",
|
|
1100
|
+
children: "×"
|
|
1101
|
+
})]
|
|
1102
|
+
}),
|
|
1103
|
+
/* @__PURE__ */ jsxs("label", { children: ["Name", /* @__PURE__ */ jsx("input", {
|
|
1104
|
+
value: name,
|
|
1105
|
+
placeholder: "e.g. Coral",
|
|
1106
|
+
onChange: (event) => setName(event.target.value)
|
|
1107
|
+
})] }),
|
|
1108
|
+
/* @__PURE__ */ jsxs("label", { children: ["Brand hex", /* @__PURE__ */ jsx("input", {
|
|
1109
|
+
value: hex,
|
|
1110
|
+
placeholder: "#DB0082",
|
|
1111
|
+
spellCheck: false,
|
|
1112
|
+
autoComplete: "off",
|
|
1113
|
+
onChange: (event) => setHex(event.target.value.trim())
|
|
1114
|
+
})] }),
|
|
1115
|
+
/* @__PURE__ */ jsxs("label", { children: ["This color is", /* @__PURE__ */ jsx("select", {
|
|
1116
|
+
value: String(sourceStep),
|
|
1117
|
+
onChange: (event) => setSourceStep(Number(event.target.value)),
|
|
1118
|
+
children: SHADE_STEPS.map((step) => /* @__PURE__ */ jsx("option", {
|
|
1119
|
+
value: step,
|
|
1120
|
+
children: step
|
|
1121
|
+
}, step))
|
|
1122
|
+
})] }),
|
|
1123
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1124
|
+
className: "bl-library__actions",
|
|
1125
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
1126
|
+
type: "button",
|
|
1127
|
+
onClick: () => setAdding(false),
|
|
1128
|
+
children: "Cancel"
|
|
1129
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
1130
|
+
type: "button",
|
|
1131
|
+
disabled: !slugify(name) || !isThemeHex(hex),
|
|
1132
|
+
onClick: add,
|
|
1133
|
+
children: "Create color scale"
|
|
1134
|
+
})]
|
|
1135
|
+
})
|
|
1136
|
+
]
|
|
1137
|
+
})
|
|
1138
|
+
}) }) : null,
|
|
922
1139
|
/* @__PURE__ */ jsx("div", {
|
|
923
1140
|
className: "bl-library__list",
|
|
924
1141
|
children: rows.map((row, index) => /* @__PURE__ */ jsx(ColorScaleCard, {
|
|
@@ -935,84 +1152,30 @@ const LibraryField = ({ path, readOnly }) => {
|
|
|
935
1152
|
};
|
|
936
1153
|
write(copy);
|
|
937
1154
|
},
|
|
938
|
-
onDelete: readOnly ? void 0 : () =>
|
|
1155
|
+
onDelete: readOnly ? void 0 : () => remove(row),
|
|
939
1156
|
readOnly
|
|
940
1157
|
}, row.key ?? index))
|
|
941
|
-
})
|
|
942
|
-
pendingDelete ? /* @__PURE__ */ jsx("div", {
|
|
943
|
-
className: "bl-library__modal",
|
|
944
|
-
role: "dialog",
|
|
945
|
-
"aria-modal": "true",
|
|
946
|
-
"aria-labelledby": "bl-library-delete-title",
|
|
947
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
948
|
-
className: "bl-library__panel",
|
|
949
|
-
children: [
|
|
950
|
-
/* @__PURE__ */ jsxs("h2", {
|
|
951
|
-
id: "bl-library-delete-title",
|
|
952
|
-
children: ["Delete ", pendingDelete.label ?? pendingDelete.key]
|
|
953
|
-
}),
|
|
954
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
955
|
-
"Unused custom colors delete immediately. If this scale is in use, pick one replacement — every",
|
|
956
|
-
" ",
|
|
957
|
-
/* @__PURE__ */ jsxs("code", { children: [pendingDelete.key, "-400"] }),
|
|
958
|
-
" becomes ",
|
|
959
|
-
/* @__PURE__ */ jsxs("code", { children: [replacement || "…", "-400"] }),
|
|
960
|
-
"."
|
|
961
|
-
] }),
|
|
962
|
-
/* @__PURE__ */ jsxs("label", { children: ["Replacement scale", /* @__PURE__ */ jsxs("select", {
|
|
963
|
-
value: replacement,
|
|
964
|
-
onChange: (event) => setReplacement(event.target.value),
|
|
965
|
-
children: [/* @__PURE__ */ jsx("option", {
|
|
966
|
-
value: "",
|
|
967
|
-
children: "Choose a scale…"
|
|
968
|
-
}), replacements.map((option) => /* @__PURE__ */ jsx("option", {
|
|
969
|
-
value: option.value,
|
|
970
|
-
children: option.label
|
|
971
|
-
}, option.value))]
|
|
972
|
-
})] }),
|
|
973
|
-
/* @__PURE__ */ jsxs("div", {
|
|
974
|
-
className: "bl-library__actions",
|
|
975
|
-
children: [
|
|
976
|
-
/* @__PURE__ */ jsx("button", {
|
|
977
|
-
type: "button",
|
|
978
|
-
onClick: () => setPendingDelete(null),
|
|
979
|
-
children: "Cancel"
|
|
980
|
-
}),
|
|
981
|
-
/* @__PURE__ */ jsx("button", {
|
|
982
|
-
type: "button",
|
|
983
|
-
onClick: () => remove(pendingDelete),
|
|
984
|
-
children: "Delete immediately"
|
|
985
|
-
}),
|
|
986
|
-
/* @__PURE__ */ jsx("button", {
|
|
987
|
-
type: "button",
|
|
988
|
-
disabled: !replacement,
|
|
989
|
-
onClick: () => remove(pendingDelete, replacement),
|
|
990
|
-
children: "Replace & delete"
|
|
991
|
-
})
|
|
992
|
-
]
|
|
993
|
-
})
|
|
994
|
-
]
|
|
995
|
-
})
|
|
996
|
-
}) : null
|
|
1158
|
+
})
|
|
997
1159
|
]
|
|
998
1160
|
});
|
|
999
1161
|
};
|
|
1000
|
-
const CSS$
|
|
1162
|
+
const CSS$3 = `
|
|
1001
1163
|
.bl-library__head{display:flex;justify-content:space-between;gap:1rem;align-items:flex-start;margin-bottom:.85rem}
|
|
1002
1164
|
.bl-library__head h2{margin:0;font-size:1.1rem}
|
|
1003
|
-
.bl-library__head p{margin:.35rem 0 0;font-size:13px;color:var(--theme-
|
|
1004
|
-
.bl-library__head button,.bl-
|
|
1165
|
+
.bl-library__head p{margin:.35rem 0 0;font-size:13px;color:color-mix(in srgb,var(--theme-text,#f8fafc) 92%,transparent)}
|
|
1166
|
+
.bl-library__head button,.bl-library__actions button{min-height:2.1rem;padding:.35rem .75rem;border-radius:8px;border:1px solid var(--theme-elevation-150,#e2e8f0);background:var(--theme-elevation-0,#fff);color:var(--theme-text,#0f172a);font:inherit;cursor:pointer}
|
|
1005
1167
|
.bl-library__list{display:grid;gap:.85rem}
|
|
1006
|
-
.bl-
|
|
1007
|
-
.bl-
|
|
1008
|
-
.bl-
|
|
1009
|
-
.bl-
|
|
1010
|
-
.bl-library__panel{width:min(28rem,100%);padding:1.2rem;border-radius:16px;background:#fff;color:#0f172a}
|
|
1168
|
+
.bl-library__modal{position:fixed;inset:0;z-index:10000;display:grid;place-items:center;padding:1rem;background:rgba(15,23,42,.45)}
|
|
1169
|
+
.bl-library__panel{width:min(28rem,100%);padding:1.2rem;border-radius:16px;background:#fff;color:#0f172a;color-scheme:light;box-shadow:0 24px 48px rgba(15,23,42,.22)}
|
|
1170
|
+
.bl-library__panel-head{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem}
|
|
1171
|
+
.bl-library__panel-head button{border:0;background:none;font:inherit;font-size:1.25rem;line-height:1;color:#94a3b8;cursor:pointer}
|
|
1011
1172
|
.bl-library__panel h2{margin:0}
|
|
1012
1173
|
.bl-library__panel p{margin:.5rem 0 0;color:#475569;font-size:14px}
|
|
1013
1174
|
.bl-library__panel label{display:flex;flex-direction:column;gap:.4rem;margin-top:1rem;font-size:13px;font-weight:600}
|
|
1014
|
-
.bl-library__panel select{min-height:2.25rem;border:1px solid #cbd5e1;border-radius:8px;padding:.35rem .5rem}
|
|
1175
|
+
.bl-library__panel input,.bl-library__panel select{min-height:2.25rem;border:1px solid #cbd5e1;border-radius:8px;padding:.35rem .5rem;background:#fff;color:#0f172a}
|
|
1015
1176
|
.bl-library__actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:.5rem;margin-top:1rem}
|
|
1177
|
+
.bl-library__actions button:last-child{border:0;background:#0f172a;color:#fff;font-weight:600}
|
|
1178
|
+
.bl-library__actions button:last-child:disabled{opacity:.4;cursor:not-allowed}
|
|
1016
1179
|
`;
|
|
1017
1180
|
//#endregion
|
|
1018
1181
|
//#region src/admin/typography-pairing.tsx
|
|
@@ -1082,23 +1245,23 @@ function TypographyPairing({ headingFamily, bodyFamily }) {
|
|
|
1082
1245
|
});
|
|
1083
1246
|
}
|
|
1084
1247
|
const TYPOGRAPHY_PAIRING_CSS = `
|
|
1085
|
-
.bl-font-role{padding:1.1rem 1.15rem;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:12px;background:var(--theme-elevation-0,#fff)}
|
|
1248
|
+
.bl-font-role{padding:1.1rem 1.15rem;border:1px solid var(--bl-preview-border,var(--theme-elevation-150,#e2e8f0));border-radius:12px;background:var(--bl-preview-card,var(--theme-elevation-0,#fff));color:var(--bl-preview-text,inherit)}
|
|
1086
1249
|
.bl-font-role__head{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem}
|
|
1087
1250
|
.bl-font-role__head h3{margin:0;font-size:1rem}
|
|
1088
|
-
.bl-font-role__head p{margin:.3rem 0 0;font-size:12px;color:var(--theme-elevation-500,#64748b)}
|
|
1089
|
-
.bl-font-role__badge{font-size:10px;text-transform:uppercase;letter-spacing:.04em;padding:.15rem .45rem;border-radius:999px;background
|
|
1090
|
-
.bl-font-role__preview{margin-top:1rem;padding:.85rem .9rem;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:12px;background:var(--theme-elevation-50,#f8fafc)}
|
|
1091
|
-
.bl-font-role__preview > span{display:block;margin-bottom:.4rem;font-size:11px;color:var(--theme-elevation-500,#64748b)}
|
|
1251
|
+
.bl-font-role__head p{margin:.3rem 0 0;font-size:12px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}
|
|
1252
|
+
.bl-font-role__badge{font-size:10px;text-transform:uppercase;letter-spacing:.04em;padding:.15rem .45rem;border-radius:999px;background:#e2e8f0;color:#0f172a}
|
|
1253
|
+
.bl-font-role__preview{margin-top:1rem;padding:.85rem .9rem;border:1px solid var(--bl-preview-border,var(--theme-elevation-150,#e2e8f0));border-radius:12px;background:var(--bl-preview-bg,var(--theme-elevation-50,#f8fafc))}
|
|
1254
|
+
.bl-font-role__preview > span{display:block;margin-bottom:.4rem;font-size:11px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}
|
|
1092
1255
|
.bl-font-role__heading{margin:0;font-size:1.5rem;line-height:1.2;font-weight:600}
|
|
1093
|
-
.bl-font-role__body{margin:0;font-size:1rem;line-height:1.6;color:var(--theme-elevation-600,#475569)}
|
|
1094
|
-
.bl-pairing{padding:0;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:12px;background:var(--theme-elevation-0,#fff);overflow:hidden}
|
|
1095
|
-
.bl-pairing > header{padding:1rem 1.15rem;border-bottom:1px solid var(--theme-elevation-150,#e2e8f0)}
|
|
1256
|
+
.bl-font-role__body{margin:0;font-size:1rem;line-height:1.6;color:var(--bl-preview-muted,var(--theme-elevation-600,#475569))}
|
|
1257
|
+
.bl-pairing{padding:0;border:1px solid var(--bl-preview-border,var(--theme-elevation-150,#e2e8f0));border-radius:12px;background:var(--bl-preview-card,var(--theme-elevation-0,#fff));color:var(--bl-preview-text,inherit);overflow:hidden}
|
|
1258
|
+
.bl-pairing > header{padding:1rem 1.15rem;border-bottom:1px solid var(--bl-preview-border,var(--theme-elevation-150,#e2e8f0))}
|
|
1096
1259
|
.bl-pairing > header h2{margin:0;font-size:1rem}
|
|
1097
|
-
.bl-pairing > header p{margin:.3rem 0 0;font-size:12px;color:var(--theme-elevation-500,#64748b)}
|
|
1098
|
-
.bl-pairing__page{padding:1.35rem 1.4rem 1.5rem}
|
|
1260
|
+
.bl-pairing > header p{margin:.3rem 0 0;font-size:12px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}
|
|
1261
|
+
.bl-pairing__page{padding:1.35rem 1.4rem 1.5rem;background:var(--bl-preview-bg,transparent)}
|
|
1099
1262
|
.bl-pairing__eyebrow{margin:0;font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:#7c1fa2}
|
|
1100
1263
|
.bl-pairing__title{margin:.5rem 0 0;font-size:2rem;line-height:1.1;font-weight:600}
|
|
1101
|
-
.bl-pairing__copy{margin:.75rem 0 0;max-width:36rem;font-size:1rem;line-height:1.6;color:var(--theme-elevation-600,#475569)}
|
|
1264
|
+
.bl-pairing__copy{margin:.75rem 0 0;max-width:36rem;font-size:1rem;line-height:1.6;color:var(--bl-preview-muted,var(--theme-elevation-600,#475569))}
|
|
1102
1265
|
.bl-pairing__actions{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:1.1rem}
|
|
1103
1266
|
.bl-pairing__btn{display:inline-flex;align-items:center;min-height:2.15rem;padding:.4rem .85rem;border-radius:8px;background:#db0082;color:#fff;font-size:14px;font-weight:600}
|
|
1104
1267
|
.bl-pairing__btn--ghost{background:#fff;color:#0f172a;border:1px solid #cbd5e1}
|
|
@@ -1206,8 +1369,11 @@ const FontField = ({ field, path, readOnly }) => {
|
|
|
1206
1369
|
}
|
|
1207
1370
|
const activeId = active >= 0 && open ? `${id}-option-${active}` : void 0;
|
|
1208
1371
|
const faceIds = faces ? ids : isFontId(value) ? [value] : [];
|
|
1372
|
+
const canvas = usePreviewCanvas();
|
|
1209
1373
|
return /* @__PURE__ */ jsxs("div", {
|
|
1210
|
-
className:
|
|
1374
|
+
className: `field-type bl-font-field ${canvas.className}`,
|
|
1375
|
+
"data-preview": canvas.mode,
|
|
1376
|
+
style: canvas.style,
|
|
1211
1377
|
children: [
|
|
1212
1378
|
/* @__PURE__ */ jsx("style", {
|
|
1213
1379
|
href: "bl-pairing",
|
|
@@ -1217,7 +1383,7 @@ const FontField = ({ field, path, readOnly }) => {
|
|
|
1217
1383
|
/* @__PURE__ */ jsx("style", {
|
|
1218
1384
|
href: "bl-font-field",
|
|
1219
1385
|
precedence: "default",
|
|
1220
|
-
children: CSS$
|
|
1386
|
+
children: CSS$2
|
|
1221
1387
|
}),
|
|
1222
1388
|
faceIds.length > 0 ? /* @__PURE__ */ jsx("style", {
|
|
1223
1389
|
"data-bl-font-faces": "",
|
|
@@ -1343,7 +1509,7 @@ const FontField = ({ field, path, readOnly }) => {
|
|
|
1343
1509
|
]
|
|
1344
1510
|
});
|
|
1345
1511
|
};
|
|
1346
|
-
const CSS$
|
|
1512
|
+
const CSS$2 = `
|
|
1347
1513
|
.bl-font-field{margin-bottom:1rem}
|
|
1348
1514
|
.bl-font-field .field-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
|
|
1349
1515
|
.bl-font-field__trigger{display:flex;align-items:center;justify-content:space-between;width:100%;margin-top:1rem;min-height:3.25rem;padding:.7rem 1rem;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:12px;background:var(--theme-input-bg,#fff);color:inherit;font:inherit;text-align:left;cursor:pointer}
|
|
@@ -1351,7 +1517,7 @@ const CSS$1 = `
|
|
|
1351
1517
|
.bl-font-field__trigger:disabled{color:var(--theme-elevation-400,#94a3b8);cursor:not-allowed}
|
|
1352
1518
|
.bl-font-field__selected-label{display:block;font-size:11px;color:var(--theme-elevation-500,#64748b)}
|
|
1353
1519
|
.bl-font-field__selected-name{display:block;margin-top:.15rem;font-weight:600}
|
|
1354
|
-
.bl-font-field__modal{position:fixed;inset:0;z-index:
|
|
1520
|
+
.bl-font-field__modal{position:fixed;inset:0;z-index:10000;display:grid;place-items:center;padding:1rem;background:rgba(15,23,42,.45)}
|
|
1355
1521
|
.bl-font-field__panel{width:min(36rem,100%);max-height:min(36rem,90vh);display:flex;flex-direction:column;padding:1.15rem 1.2rem;border-radius:16px;background:#fff;color:#0f172a}
|
|
1356
1522
|
.bl-font-field__panel-head{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem}
|
|
1357
1523
|
.bl-font-field__panel-head p{margin:0;font-size:12px;color:#64748b}
|
|
@@ -1387,8 +1553,11 @@ const PairingField = ({ field }) => {
|
|
|
1387
1553
|
const bodyFont = findFont(body);
|
|
1388
1554
|
const headingFont = findFont(headingId);
|
|
1389
1555
|
const ids = [body, headingId].filter(Boolean);
|
|
1556
|
+
const canvas = usePreviewCanvas();
|
|
1390
1557
|
return /* @__PURE__ */ jsxs("div", {
|
|
1391
|
-
className:
|
|
1558
|
+
className: `field-type bl-pairing-field ${canvas.className}`,
|
|
1559
|
+
"data-preview": canvas.mode,
|
|
1560
|
+
style: canvas.style,
|
|
1392
1561
|
children: [
|
|
1393
1562
|
/* @__PURE__ */ jsx("style", {
|
|
1394
1563
|
href: "bl-pairing",
|
|
@@ -1490,18 +1659,18 @@ function AppearanceChoices({ values, onChange, readOnly }) {
|
|
|
1490
1659
|
});
|
|
1491
1660
|
}
|
|
1492
1661
|
const APPEARANCE_CHOICES_CSS = `
|
|
1493
|
-
.bl-appearance{display:flex;flex-direction:column;gap:1.25rem}
|
|
1662
|
+
.bl-appearance{display:flex;flex-direction:column;gap:1.25rem;color:var(--bl-preview-text,inherit)}
|
|
1494
1663
|
.bl-appearance__intro h2{margin:0;font-size:1.1rem}
|
|
1495
|
-
.bl-appearance__intro p{margin:.35rem 0 0;font-size:13px;color:var(--theme-elevation-500,#64748b);max-width:40rem}
|
|
1496
|
-
.bl-appearance__family{margin:0;padding:1rem 1.1rem 1.15rem;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:12px;background:var(--theme-elevation-0,#fff)}
|
|
1664
|
+
.bl-appearance__intro p{margin:.35rem 0 0;font-size:13px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b));max-width:40rem}
|
|
1665
|
+
.bl-appearance__family{margin:0;padding:1rem 1.1rem 1.15rem;border:1px solid var(--bl-preview-border,var(--theme-elevation-150,#e2e8f0));border-radius:12px;background:var(--bl-preview-card,var(--theme-elevation-0,#fff))}
|
|
1497
1666
|
.bl-appearance__family legend{padding:0;margin-bottom:.85rem}
|
|
1498
1667
|
.bl-appearance__family legend strong{display:block;font-size:14px}
|
|
1499
|
-
.bl-appearance__family legend span{display:block;margin-top:.25rem;font-size:12px;color:var(--theme-elevation-500,#64748b);font-weight:400}
|
|
1668
|
+
.bl-appearance__family legend span{display:block;margin-top:.25rem;font-size:12px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b));font-weight:400}
|
|
1500
1669
|
.bl-appearance__choices{display:grid;gap:.6rem}
|
|
1501
1670
|
.bl-appearance__choices[data-family=defaultTheme],.bl-appearance__choices[data-family=shadow],.bl-appearance__choices[data-family=motion],.bl-appearance__choices[data-family=density]{grid-template-columns:repeat(3,minmax(0,1fr))}
|
|
1502
1671
|
.bl-appearance__choices[data-family=radius]{grid-template-columns:repeat(4,minmax(0,1fr))}
|
|
1503
|
-
.bl-appearance__choice{display:flex;flex-direction:column;gap:.65rem;padding:.75rem;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:12px;background:var(--theme-elevation-0,#fff);cursor:pointer}
|
|
1504
|
-
.bl-appearance__choice[data-selected]{box-shadow:inset 0 0 0 2px
|
|
1672
|
+
.bl-appearance__choice{display:flex;flex-direction:column;gap:.65rem;padding:.75rem;border:1px solid var(--bl-preview-border,var(--theme-elevation-150,#e2e8f0));border-radius:12px;background:var(--bl-preview-bg,var(--theme-elevation-0,#fff));cursor:pointer}
|
|
1673
|
+
.bl-appearance__choice[data-selected]{box-shadow:inset 0 0 0 2px var(--bl-preview-text,#0f172a);border-color:var(--bl-preview-text,#0f172a)}
|
|
1505
1674
|
.bl-appearance__choice input{position:absolute;opacity:0;pointer-events:none}
|
|
1506
1675
|
.bl-appearance__copy{display:flex;flex-direction:column;gap:.2rem}
|
|
1507
1676
|
.bl-appearance__copy strong{display:flex;justify-content:space-between;align-items:center;gap:.4rem;font-size:14px}
|
|
@@ -1574,11 +1743,14 @@ const AppearanceField = ({ path, readOnly }) => {
|
|
|
1574
1743
|
motion,
|
|
1575
1744
|
density
|
|
1576
1745
|
};
|
|
1746
|
+
const canvas = usePreviewCanvas();
|
|
1577
1747
|
function onChange(name, value) {
|
|
1578
1748
|
fields[name].setValue(value);
|
|
1579
1749
|
}
|
|
1580
1750
|
return /* @__PURE__ */ jsxs("div", {
|
|
1581
|
-
className:
|
|
1751
|
+
className: `field-type bl-appearance-field ${canvas.className}`,
|
|
1752
|
+
"data-preview": canvas.mode,
|
|
1753
|
+
style: canvas.style,
|
|
1582
1754
|
children: [/* @__PURE__ */ jsx("style", {
|
|
1583
1755
|
href: "bl-appearance",
|
|
1584
1756
|
precedence: "default",
|
|
@@ -1607,53 +1779,63 @@ const SWATCHES = [
|
|
|
1607
1779
|
"950"
|
|
1608
1780
|
];
|
|
1609
1781
|
function GreyScaleChoices({ value, onChange, readOnly }) {
|
|
1782
|
+
const canvas = usePreviewCanvas();
|
|
1610
1783
|
return /* @__PURE__ */ jsxs("section", {
|
|
1611
|
-
className:
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1784
|
+
className: `bl-grey ${canvas.className}`,
|
|
1785
|
+
"data-preview": canvas.mode,
|
|
1786
|
+
style: canvas.style,
|
|
1787
|
+
children: [
|
|
1788
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1789
|
+
className: "bl-grey__section",
|
|
1790
|
+
children: [/* @__PURE__ */ jsx("h2", { children: "Neutrals" }), /* @__PURE__ */ jsx("p", { children: "Choose the gray family used for backgrounds, borders, cards, inputs, and muted text." })]
|
|
1791
|
+
}),
|
|
1792
|
+
/* @__PURE__ */ jsxs("header", {
|
|
1793
|
+
className: "bl-grey__head",
|
|
1794
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h2", { children: "Gray family" }), /* @__PURE__ */ jsx("p", { children: "Choose the neutral family used for page backgrounds, cards, borders, inputs, and muted text. Readability for these system neutrals is handled automatically." })] }), /* @__PURE__ */ jsx("span", {
|
|
1795
|
+
className: "bl-grey__badge",
|
|
1796
|
+
children: "Required"
|
|
1797
|
+
})]
|
|
1798
|
+
}),
|
|
1799
|
+
/* @__PURE__ */ jsx("div", {
|
|
1800
|
+
className: "bl-grey__choices",
|
|
1801
|
+
children: FAMILIES.map((id) => {
|
|
1802
|
+
const copy = presetHints.greyScale[id];
|
|
1803
|
+
const selected = value === id;
|
|
1804
|
+
return /* @__PURE__ */ jsxs("label", {
|
|
1805
|
+
className: "bl-grey__choice",
|
|
1806
|
+
"data-selected": selected ? "" : void 0,
|
|
1807
|
+
children: [
|
|
1808
|
+
/* @__PURE__ */ jsx("input", {
|
|
1809
|
+
type: "radio",
|
|
1810
|
+
name: "greyScale",
|
|
1811
|
+
value: id,
|
|
1812
|
+
checked: selected,
|
|
1813
|
+
disabled: readOnly,
|
|
1814
|
+
onChange: () => onChange(id)
|
|
1815
|
+
}),
|
|
1816
|
+
/* @__PURE__ */ jsx("span", {
|
|
1817
|
+
className: "bl-grey__ramp",
|
|
1818
|
+
"aria-hidden": "true",
|
|
1819
|
+
children: SWATCHES.map((step) => /* @__PURE__ */ jsx("i", { style: { background: `hsl(${GREY_SCALES[id][step]})` } }, step))
|
|
1820
|
+
}),
|
|
1821
|
+
/* @__PURE__ */ jsxs("strong", { children: [copy.label, selected ? /* @__PURE__ */ jsx("em", {
|
|
1822
|
+
"aria-hidden": "true",
|
|
1823
|
+
children: "✓"
|
|
1824
|
+
}) : null] }),
|
|
1825
|
+
/* @__PURE__ */ jsx("span", { children: copy.hint })
|
|
1826
|
+
]
|
|
1827
|
+
}, id);
|
|
1828
|
+
})
|
|
1647
1829
|
})
|
|
1648
|
-
|
|
1830
|
+
]
|
|
1649
1831
|
});
|
|
1650
1832
|
}
|
|
1651
1833
|
/**
|
|
1652
1834
|
* Visual picker over the five grey-scale presets. Replaces the stock select
|
|
1653
1835
|
* on Colors; the stored value is still `colors.greyScale`.
|
|
1654
1836
|
*/
|
|
1655
|
-
const GreyScaleField = ({ path, readOnly }) => {
|
|
1656
|
-
const { value, setValue } = useField({ path });
|
|
1837
|
+
const GreyScaleField = ({ field, path, readOnly }) => {
|
|
1838
|
+
const { value, setValue } = useField({ path: typeof field.admin?.custom?.dataPath === "string" ? field.admin.custom.dataPath : path });
|
|
1657
1839
|
return /* @__PURE__ */ jsxs("div", {
|
|
1658
1840
|
className: "field-type bl-grey-field",
|
|
1659
1841
|
children: [/* @__PURE__ */ jsx("style", {
|
|
@@ -1669,23 +1851,22 @@ const GreyScaleField = ({ path, readOnly }) => {
|
|
|
1669
1851
|
};
|
|
1670
1852
|
const GREY_SCALE_FIELD_CSS = `
|
|
1671
1853
|
.bl-grey{margin:0 0 1.75rem}
|
|
1672
|
-
.bl-
|
|
1854
|
+
.bl-grey__section{margin:1.25rem 0 .85rem}
|
|
1855
|
+
.bl-grey__section h2{margin:0;font-size:1.1rem}
|
|
1856
|
+
.bl-grey__section p{margin:.35rem 0 0;max-width:40rem;font-size:13px;color:color-mix(in srgb,var(--theme-text,#f8fafc) 92%,transparent)}
|
|
1857
|
+
.bl-grey__head{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem;margin:0;padding:1.1rem 1.15rem .85rem;border:1px solid var(--bl-preview-border,var(--theme-elevation-150,#e2e8f0));border-bottom:0;border-radius:12px 12px 0 0;background:var(--bl-preview-card,var(--theme-elevation-0,#fff));color:var(--bl-preview-text,inherit)}
|
|
1673
1858
|
.bl-grey__head h2{margin:0;font-size:1.1rem}
|
|
1674
|
-
.bl-grey__head p{margin:.35rem 0 0;max-width:40rem;font-size:13px;color:var(--theme-elevation-500,#64748b)}
|
|
1675
|
-
.bl-grey__badge{font:inherit;font-size:10px;text-transform:uppercase;letter-spacing:.04em;padding:.15rem .45rem;border-radius:999px;background
|
|
1676
|
-
.bl-grey__choices{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:.6rem}
|
|
1677
|
-
.bl-grey__choice{display:flex;flex-direction:column;gap:.45rem;padding:.75rem;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:12px;background:var(--theme-elevation-0,#fff);cursor:pointer}
|
|
1678
|
-
.bl-grey__choice[data-selected]{box-shadow:inset 0 0 0 2px
|
|
1859
|
+
.bl-grey__head p{margin:.35rem 0 0;max-width:40rem;font-size:13px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}
|
|
1860
|
+
.bl-grey__badge{font:inherit;font-size:10px;text-transform:uppercase;letter-spacing:.04em;padding:.15rem .45rem;border-radius:999px;background:#e2e8f0;color:#0f172a}
|
|
1861
|
+
.bl-grey__choices{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:.6rem;padding:0 1.15rem 1.15rem;border:1px solid var(--bl-preview-border,var(--theme-elevation-150,#e2e8f0));border-top:0;border-radius:0 0 12px 12px;background:var(--bl-preview-card,var(--theme-elevation-0,#fff));color:var(--bl-preview-text,inherit)}
|
|
1862
|
+
.bl-grey__choice{display:flex;flex-direction:column;gap:.45rem;padding:.75rem;border:1px solid var(--bl-preview-border,var(--theme-elevation-150,#e2e8f0));border-radius:12px;background:var(--bl-preview-bg,var(--theme-elevation-0,#fff));color:inherit;cursor:pointer}
|
|
1863
|
+
.bl-grey__choice[data-selected]{box-shadow:inset 0 0 0 2px var(--bl-preview-text,#0f172a);border-color:var(--bl-preview-text,#0f172a)}
|
|
1679
1864
|
.bl-grey__choice input{position:absolute;opacity:0;pointer-events:none}
|
|
1680
1865
|
.bl-grey__ramp{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:3px}
|
|
1681
1866
|
.bl-grey__ramp i{display:block;height:2rem;border-radius:6px}
|
|
1682
1867
|
.bl-grey__choice strong{display:flex;justify-content:space-between;align-items:center;gap:.4rem;font-size:14px}
|
|
1683
1868
|
.bl-grey__choice em{font-style:normal}
|
|
1684
|
-
.bl-grey__choice > span{font-size:12px;color:var(--theme-elevation-500,#64748b)}
|
|
1685
|
-
[data-bl-theme-preview=dark] .bl-grey__head p,[data-bl-theme-preview=dark] .bl-grey__choice > span{color:#94a3b8}
|
|
1686
|
-
[data-bl-theme-preview=dark] .bl-grey__choice{background:#0f172a;border-color:#334155;color:#f8fafc}
|
|
1687
|
-
[data-bl-theme-preview=dark] .bl-grey__choice[data-selected]{box-shadow:inset 0 0 0 2px #f8fafc;border-color:#f8fafc}
|
|
1688
|
-
[data-bl-theme-preview=dark] .bl-grey__badge{background:#1e293b;color:#94a3b8}
|
|
1869
|
+
.bl-grey__choice > span{font-size:12px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}
|
|
1689
1870
|
@media (max-width:720px){.bl-grey__choices{grid-template-columns:1fr}}
|
|
1690
1871
|
`;
|
|
1691
1872
|
//#endregion
|
|
@@ -1730,6 +1911,11 @@ const ContrastReport = ({ field }) => {
|
|
|
1730
1911
|
precedence: "default",
|
|
1731
1912
|
children: READABILITY_LIST_CSS
|
|
1732
1913
|
}),
|
|
1914
|
+
/* @__PURE__ */ jsx("style", {
|
|
1915
|
+
href: "bl-theme-colors-layout",
|
|
1916
|
+
precedence: "default",
|
|
1917
|
+
children: THEME_COLORS_LAYOUT_CSS
|
|
1918
|
+
}),
|
|
1733
1919
|
stale ? /* @__PURE__ */ jsx("p", {
|
|
1734
1920
|
className: "bl-contrast-report__stale",
|
|
1735
1921
|
children: "Showing the last complete audit while a colour is being typed."
|
|
@@ -1755,21 +1941,30 @@ const SectionHeading = ({ field }) => {
|
|
|
1755
1941
|
/* @__PURE__ */ jsx("style", {
|
|
1756
1942
|
href: "bl-section-heading",
|
|
1757
1943
|
precedence: "default",
|
|
1758
|
-
children: CSS
|
|
1944
|
+
children: CSS$1
|
|
1945
|
+
}),
|
|
1946
|
+
/* @__PURE__ */ jsx("style", {
|
|
1947
|
+
href: "bl-theme-colors-layout",
|
|
1948
|
+
precedence: "default",
|
|
1949
|
+
children: THEME_COLORS_LAYOUT_CSS
|
|
1759
1950
|
}),
|
|
1760
1951
|
/* @__PURE__ */ jsx("h2", { children: custom.title }),
|
|
1761
1952
|
custom.hint ? /* @__PURE__ */ jsx("p", { children: custom.hint }) : null
|
|
1762
1953
|
]
|
|
1763
1954
|
});
|
|
1764
1955
|
};
|
|
1765
|
-
const CSS = `
|
|
1956
|
+
const CSS$1 = `
|
|
1766
1957
|
.bl-section-heading{margin:1.25rem 0 .65rem}
|
|
1767
1958
|
.bl-section-heading:first-child{margin-top:0}
|
|
1768
1959
|
.bl-section-heading h2{margin:0;font-size:1.1rem}
|
|
1769
|
-
.bl-section-heading p{margin:.35rem 0 0;font-size:13px;color:var(--theme-
|
|
1960
|
+
.bl-section-heading p{margin:.35rem 0 0;font-size:13px;color:color-mix(in srgb,var(--theme-text,#f8fafc) 92%,transparent);max-width:40rem}
|
|
1770
1961
|
`;
|
|
1771
1962
|
//#endregion
|
|
1772
1963
|
//#region src/theme/changes.ts
|
|
1964
|
+
/** Payload may hand an empty array field as `{}`. `.map` on that crashes the Theme form. */
|
|
1965
|
+
function libraryRows(value) {
|
|
1966
|
+
return Array.isArray(value) ? value : [];
|
|
1967
|
+
}
|
|
1773
1968
|
function colorLine(name, before, after) {
|
|
1774
1969
|
const a = before && typeof before === "object" ? before : { hex: before };
|
|
1775
1970
|
const b = after && typeof after === "object" ? after : { hex: after };
|
|
@@ -1789,8 +1984,8 @@ function themeChildChanges(child, published, incoming) {
|
|
|
1789
1984
|
const line = colorLine(key[0].toUpperCase() + key.slice(1), published.colors?.brand?.[key], incoming.colors?.brand?.[key]);
|
|
1790
1985
|
if (line) lines.push(line);
|
|
1791
1986
|
}
|
|
1792
|
-
const beforeKeys = (published.colors?.library
|
|
1793
|
-
const afterKeys = (incoming.colors?.library
|
|
1987
|
+
const beforeKeys = libraryRows(published.colors?.library).map((row) => row.key).join(", ");
|
|
1988
|
+
const afterKeys = libraryRows(incoming.colors?.library).map((row) => row.key).join(", ");
|
|
1794
1989
|
if (beforeKeys !== afterKeys) lines.push(`Custom colors: ${beforeKeys || "none"} → ${afterKeys || "none"}`);
|
|
1795
1990
|
if ((published.colors?.greyScale ?? "") !== (incoming.colors?.greyScale ?? "")) lines.push(`Gray family: ${published.colors?.greyScale ?? "—"} → ${incoming.colors?.greyScale ?? "—"}`);
|
|
1796
1991
|
return lines;
|
|
@@ -1844,7 +2039,7 @@ const OTHER_CHILDREN = {
|
|
|
1844
2039
|
};
|
|
1845
2040
|
function PublishConfirm({ childLabel, changes, shorts, onKeepEditing, onPublish, busy }) {
|
|
1846
2041
|
const remaining = shorts?.filter((item) => !item.meets) ?? [];
|
|
1847
|
-
return /* @__PURE__ */ jsx("div", {
|
|
2042
|
+
return /* @__PURE__ */ jsx(ThemePortal, { children: /* @__PURE__ */ jsx("div", {
|
|
1848
2043
|
className: "bl-publish",
|
|
1849
2044
|
role: "dialog",
|
|
1850
2045
|
"aria-modal": "true",
|
|
@@ -1892,10 +2087,12 @@ function PublishConfirm({ childLabel, changes, shorts, onKeepEditing, onPublish,
|
|
|
1892
2087
|
className: "bl-publish__actions",
|
|
1893
2088
|
children: [/* @__PURE__ */ jsx("button", {
|
|
1894
2089
|
type: "button",
|
|
2090
|
+
className: "bl-publish__cancel",
|
|
1895
2091
|
onClick: onKeepEditing,
|
|
1896
|
-
children: "
|
|
2092
|
+
children: "Cancel"
|
|
1897
2093
|
}), /* @__PURE__ */ jsx("button", {
|
|
1898
2094
|
type: "button",
|
|
2095
|
+
className: "bl-publish__go",
|
|
1899
2096
|
disabled: busy || changes.length === 0,
|
|
1900
2097
|
onClick: onPublish,
|
|
1901
2098
|
children: remaining.length > 0 ? "Publish anyway" : "Publish"
|
|
@@ -1903,24 +2100,25 @@ function PublishConfirm({ childLabel, changes, shorts, onKeepEditing, onPublish,
|
|
|
1903
2100
|
})
|
|
1904
2101
|
]
|
|
1905
2102
|
})
|
|
1906
|
-
});
|
|
2103
|
+
}) });
|
|
1907
2104
|
}
|
|
1908
2105
|
const PUBLISH_CONFIRM_CSS = `
|
|
1909
|
-
.bl-publish{position:fixed;inset:0;z-index:
|
|
1910
|
-
.bl-publish__panel{width:min(36rem,100%);padding:1.25rem 1.35rem;border-radius:16px;background:#fff;color:#0f172a;box-shadow:0 24px 60px rgba(15,23,42,.2)}
|
|
1911
|
-
.bl-publish__panel h2{margin:0}
|
|
2106
|
+
.bl-publish{position:fixed;inset:0;z-index:10000;display:grid;place-items:center;padding:1rem;background:rgba(15,23,42,.45)}
|
|
2107
|
+
.bl-publish__panel{width:min(36rem,100%);padding:1.25rem 1.35rem;border-radius:16px;background:#fff;color:#0f172a;color-scheme:light;box-shadow:0 24px 60px rgba(15,23,42,.2)}
|
|
2108
|
+
.bl-publish__panel h2{margin:0;color:#0f172a}
|
|
1912
2109
|
.bl-publish__panel p{margin:.5rem 0 0;color:#475569}
|
|
1913
|
-
.bl-publish__empty{font-style:italic}
|
|
1914
|
-
.bl-publish__panel > ul{margin:.75rem 0 0;padding-left:1.1rem}
|
|
1915
|
-
.bl-publish__shorts{margin-top:1rem;padding:.85rem .9rem;border-radius:10px;background:#fffbeb}
|
|
2110
|
+
.bl-publish__empty{font-style:italic;color:#64748b}
|
|
2111
|
+
.bl-publish__panel > ul{margin:.75rem 0 0;padding-left:1.1rem;color:#0f172a}
|
|
2112
|
+
.bl-publish__shorts{margin-top:1rem;padding:.85rem .9rem;border-radius:10px;background:#fffbeb;color:#0f172a}
|
|
1916
2113
|
.bl-publish__shorts strong{display:block}
|
|
1917
2114
|
.bl-publish__shorts ul{margin:.65rem 0 0;padding:0;list-style:none}
|
|
1918
|
-
.bl-publish__shorts li{display:flex;gap:.65rem;align-items:center;margin-top:.45rem;font-size:13px}
|
|
2115
|
+
.bl-publish__shorts li{display:flex;gap:.65rem;align-items:center;margin-top:.45rem;font-size:13px;color:#0f172a}
|
|
1919
2116
|
.bl-publish__swatch{flex:none;display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:1.6rem;border-radius:6px;font-weight:700;font-size:12px}
|
|
1920
|
-
.bl-publish__shorts p{margin:.65rem 0 0;font-size:13px}
|
|
2117
|
+
.bl-publish__shorts p{margin:.65rem 0 0;font-size:13px;color:#475569}
|
|
1921
2118
|
.bl-publish__actions{display:flex;justify-content:flex-end;gap:.6rem;margin-top:1.1rem}
|
|
1922
|
-
.bl-publish__actions button{min-height:2.25rem;padding:.4rem .9rem;border-radius:8px;
|
|
1923
|
-
.bl-
|
|
2119
|
+
.bl-publish__actions button{min-height:2.25rem;padding:.4rem .9rem;border-radius:8px;font:inherit;cursor:pointer}
|
|
2120
|
+
.bl-publish__cancel{border:1px solid #cbd5e1;background:#fff;color:#0f172a}
|
|
2121
|
+
.bl-publish__go{border:0;background:#0f172a;color:#fff;font-weight:600}
|
|
1924
2122
|
.bl-publish__actions button:disabled{opacity:.45;cursor:not-allowed}
|
|
1925
2123
|
`;
|
|
1926
2124
|
//#endregion
|
|
@@ -1942,7 +2140,7 @@ function formDoc(fields) {
|
|
|
1942
2140
|
hex: fields[`colors.brand.${key}.hex`]?.value,
|
|
1943
2141
|
sourceStep: fields[`colors.brand.${key}.sourceStep`]?.value
|
|
1944
2142
|
}])),
|
|
1945
|
-
library: fields["colors.library"]?.value
|
|
2143
|
+
library: Array.isArray(fields["colors.library"]?.value) ? fields["colors.library"]?.value : [],
|
|
1946
2144
|
greyScale: fields["colors.greyScale"]?.value
|
|
1947
2145
|
},
|
|
1948
2146
|
typography: {
|
|
@@ -1977,13 +2175,13 @@ function shortsFrom(doc) {
|
|
|
1977
2175
|
})];
|
|
1978
2176
|
}
|
|
1979
2177
|
/**
|
|
1980
|
-
* Per-child Publish.
|
|
1981
|
-
*
|
|
1982
|
-
*
|
|
2178
|
+
* Per-child Publish. Lives in the document Save slot so Payload's
|
|
2179
|
+
* `--doc-controls-height` row is the action row, not an empty gap.
|
|
2180
|
+
* Sets `publishChild` then submits; `beforeChange` writes only that slice.
|
|
2181
|
+
* On Colors, remaining automatic-label shorts open in this modal only.
|
|
1983
2182
|
*/
|
|
1984
|
-
|
|
1985
|
-
const
|
|
1986
|
-
const label = isThemeChild(child) ? LABELS[child] : "Theme";
|
|
2183
|
+
function ThemePublishActions({ child }) {
|
|
2184
|
+
const label = LABELS[child];
|
|
1987
2185
|
const { submit } = useForm();
|
|
1988
2186
|
const publishChild = useField({ path: "publishChild" });
|
|
1989
2187
|
const snapshot = useFormFields(([fields]) => {
|
|
@@ -1995,10 +2193,9 @@ const PublishChild = ({ field }) => {
|
|
|
1995
2193
|
});
|
|
1996
2194
|
const [open, setOpen] = useState(false);
|
|
1997
2195
|
const [busy, setBusy] = useState(false);
|
|
1998
|
-
const changes = useMemo(() =>
|
|
2196
|
+
const changes = useMemo(() => themeChildChanges(child, snapshot.published, snapshot.incoming), [child, snapshot]);
|
|
1999
2197
|
const shorts = child === "colors" ? shortsFrom(snapshot.incoming) : void 0;
|
|
2000
2198
|
async function publish() {
|
|
2001
|
-
if (!isThemeChild(child)) return;
|
|
2002
2199
|
setBusy(true);
|
|
2003
2200
|
publishChild.setValue(child);
|
|
2004
2201
|
try {
|
|
@@ -2009,7 +2206,7 @@ const PublishChild = ({ field }) => {
|
|
|
2009
2206
|
}
|
|
2010
2207
|
}
|
|
2011
2208
|
return /* @__PURE__ */ jsxs("div", {
|
|
2012
|
-
className: "
|
|
2209
|
+
className: "bl-publish-child",
|
|
2013
2210
|
children: [
|
|
2014
2211
|
/* @__PURE__ */ jsx("style", {
|
|
2015
2212
|
href: "bl-publish",
|
|
@@ -2019,9 +2216,9 @@ const PublishChild = ({ field }) => {
|
|
|
2019
2216
|
/* @__PURE__ */ jsx("style", {
|
|
2020
2217
|
href: "bl-publish-child",
|
|
2021
2218
|
precedence: "default",
|
|
2022
|
-
children: `${THEME_PREVIEW_TOGGLE_CSS}.bl-publish-child{
|
|
2219
|
+
children: `${THEME_PREVIEW_TOGGLE_CSS}.bl-publish-child{display:flex;align-items:center;justify-content:flex-end;gap:.5rem}.bl-publish-child__button{min-height:2.25rem;padding:.4rem 1rem;border:0;border-radius:8px;background:var(--theme-text,#0f172a);color:var(--theme-bg,#fff);font:inherit;font-weight:600;cursor:pointer}`
|
|
2023
2220
|
}),
|
|
2024
|
-
child
|
|
2221
|
+
child !== "identity" ? /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(ThemePreviewToggle, {}) }) : null,
|
|
2025
2222
|
/* @__PURE__ */ jsxs("button", {
|
|
2026
2223
|
type: "button",
|
|
2027
2224
|
className: "bl-publish-child__button",
|
|
@@ -2040,17 +2237,175 @@ const PublishChild = ({ field }) => {
|
|
|
2040
2237
|
}) : null
|
|
2041
2238
|
]
|
|
2042
2239
|
});
|
|
2240
|
+
}
|
|
2241
|
+
/** @deprecated Alias — Theme pages use ThemePublishActions; tabbed Save used this name. */
|
|
2242
|
+
const ThemePublishControls = ThemePublishActions;
|
|
2243
|
+
const PublishChild = ({ field }) => {
|
|
2244
|
+
const child = (field.admin?.custom)?.child;
|
|
2245
|
+
if (!isThemeChild(child)) return null;
|
|
2246
|
+
return /* @__PURE__ */ jsx(ThemePublishActions, { child });
|
|
2247
|
+
};
|
|
2248
|
+
//#endregion
|
|
2249
|
+
//#region src/admin/theme-tab.ts
|
|
2250
|
+
const THEME_TAB_LABELS = {
|
|
2251
|
+
colors: "Colors",
|
|
2252
|
+
typography: "Typography",
|
|
2253
|
+
appearance: "Appearance",
|
|
2254
|
+
identity: "Identity"
|
|
2043
2255
|
};
|
|
2256
|
+
/**
|
|
2257
|
+
* The selected Payload field tab on Theme. Defaults to Colors when the
|
|
2258
|
+
* tabs have not painted yet (SSR, first paint).
|
|
2259
|
+
*/
|
|
2260
|
+
function readActiveThemeTab(root = typeof document === "undefined" ? null : document) {
|
|
2261
|
+
if (!root) return "colors";
|
|
2262
|
+
const text = (root.querySelector(".tabs-field__tab-button[aria-selected=\"true\"]") ?? root.querySelector(".tabs-field__tab-button--active") ?? root.querySelector("[role=\"tab\"][aria-selected=\"true\"]"))?.textContent?.replace(/\s+/g, " ").trim();
|
|
2263
|
+
return THEME_CHILDREN.find((id) => THEME_TAB_LABELS[id] === text) ?? "colors";
|
|
2264
|
+
}
|
|
2044
2265
|
//#endregion
|
|
2045
2266
|
//#region src/admin/save-button.tsx
|
|
2046
2267
|
/**
|
|
2047
|
-
*
|
|
2048
|
-
*
|
|
2268
|
+
* Light/Dark preview for Colors, Typography, and Appearance. Lives in
|
|
2269
|
+
* `beforeDocumentControls` so Payload's Save stays in the Save slot.
|
|
2270
|
+
* Save writes that page's slice onto the stored Theme row.
|
|
2271
|
+
*/
|
|
2272
|
+
function ThemeDocumentControls() {
|
|
2273
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("style", {
|
|
2274
|
+
href: "bl-doc-controls",
|
|
2275
|
+
precedence: "default",
|
|
2276
|
+
children: THEME_PREVIEW_TOGGLE_CSS
|
|
2277
|
+
}), /* @__PURE__ */ jsx(ThemePreviewToggle, {})] });
|
|
2278
|
+
}
|
|
2279
|
+
/**
|
|
2280
|
+
* Import-map Save slot used by the older single-Global Theme. Theme pages
|
|
2281
|
+
* keep Payload's Save and put Light/Dark in `ThemeDocumentControls`.
|
|
2049
2282
|
*/
|
|
2283
|
+
function ThemeSaveButton() {
|
|
2284
|
+
const [child, setChild] = useState("colors");
|
|
2285
|
+
useEffect(() => {
|
|
2286
|
+
const sync = () => setChild(readActiveThemeTab());
|
|
2287
|
+
sync();
|
|
2288
|
+
const target = document.querySelector(".tabs-field") ?? document.body;
|
|
2289
|
+
const observer = new MutationObserver(sync);
|
|
2290
|
+
observer.observe(target, {
|
|
2291
|
+
subtree: true,
|
|
2292
|
+
attributes: true,
|
|
2293
|
+
attributeFilter: ["aria-selected", "class"],
|
|
2294
|
+
childList: true
|
|
2295
|
+
});
|
|
2296
|
+
target.addEventListener("click", sync);
|
|
2297
|
+
return () => {
|
|
2298
|
+
observer.disconnect();
|
|
2299
|
+
target.removeEventListener("click", sync);
|
|
2300
|
+
};
|
|
2301
|
+
}, []);
|
|
2302
|
+
return /* @__PURE__ */ jsx(ThemePublishControls, { child });
|
|
2303
|
+
}
|
|
2304
|
+
/** @deprecated Import map alias — ThemeDocumentControls is the Save-adjacent slot. */
|
|
2050
2305
|
function HiddenSaveButton() {
|
|
2051
|
-
return
|
|
2306
|
+
return /* @__PURE__ */ jsx(ThemeDocumentControls, {});
|
|
2052
2307
|
}
|
|
2053
2308
|
//#endregion
|
|
2054
|
-
|
|
2309
|
+
//#region src/admin/identity-fallback.tsx
|
|
2310
|
+
/**
|
|
2311
|
+
* Identity child when the site has not registered a cupboard yet.
|
|
2312
|
+
* Shows the fallback lockup and mark; uploads wait on `logo.collection`.
|
|
2313
|
+
*/
|
|
2314
|
+
const IdentityFallback = ({ field }) => {
|
|
2315
|
+
const fallback = (field.admin?.custom)?.fallback;
|
|
2316
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
2317
|
+
className: "bl-identity-fallback",
|
|
2318
|
+
children: [
|
|
2319
|
+
/* @__PURE__ */ jsx("style", {
|
|
2320
|
+
href: "bl-identity-fallback",
|
|
2321
|
+
precedence: "default",
|
|
2322
|
+
children: CSS
|
|
2323
|
+
}),
|
|
2324
|
+
/* @__PURE__ */ jsxs("header", { children: [/* @__PURE__ */ jsx("h2", { children: "Site identity" }), /* @__PURE__ */ jsx("p", { children: "Today's lockup and mark until a brand editor uploads replacements." })] }),
|
|
2325
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2326
|
+
className: "bl-identity-fallback__grid",
|
|
2327
|
+
children: [fallback?.lockup ? /* @__PURE__ */ jsxs("figure", { children: [/* @__PURE__ */ jsx("img", {
|
|
2328
|
+
src: fallback.lockup.url,
|
|
2329
|
+
alt: fallback.lockup.alt
|
|
2330
|
+
}), /* @__PURE__ */ jsx("figcaption", { children: "Lockup" })] }) : null, fallback?.mark ? /* @__PURE__ */ jsxs("figure", { children: [/* @__PURE__ */ jsx("img", {
|
|
2331
|
+
src: fallback.mark.url,
|
|
2332
|
+
alt: fallback.mark.alt
|
|
2333
|
+
}), /* @__PURE__ */ jsx("figcaption", { children: "Mark" })] }) : null]
|
|
2334
|
+
})
|
|
2335
|
+
]
|
|
2336
|
+
});
|
|
2337
|
+
};
|
|
2338
|
+
const CSS = `
|
|
2339
|
+
.bl-identity-fallback header h2{margin:0;font-size:1.1rem}
|
|
2340
|
+
.bl-identity-fallback header p{margin:.35rem 0 1rem;color:var(--theme-elevation-600,#475569)}
|
|
2341
|
+
.bl-identity-fallback__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(12rem,1fr));gap:1rem}
|
|
2342
|
+
.bl-identity-fallback figure{margin:0;padding:1rem;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:10px;background:var(--theme-elevation-50,#f8fafc)}
|
|
2343
|
+
.bl-identity-fallback img{display:block;max-width:100%;height:4rem;object-fit:contain}
|
|
2344
|
+
.bl-identity-fallback figcaption{margin-top:.5rem;font-size:.8rem;color:var(--theme-elevation-600,#475569)}
|
|
2345
|
+
`;
|
|
2346
|
+
//#endregion
|
|
2347
|
+
//#region src/admin/look-field.tsx
|
|
2348
|
+
/**
|
|
2349
|
+
* Loads the Theme global and offers page-editor looks or included steps.
|
|
2350
|
+
* A custom scale published on Colors appears here on the next load.
|
|
2351
|
+
*/
|
|
2352
|
+
const LookField = ({ field, path, readOnly }) => {
|
|
2353
|
+
const { value, setValue, showError, errorMessage } = useField({ path });
|
|
2354
|
+
const { config } = useConfig();
|
|
2355
|
+
const mode = (field.admin?.custom)?.mode ?? "look";
|
|
2356
|
+
const [options, setOptions] = useState(mode === "token" ? pageEditorTokens(null) : pageEditorLooks(null));
|
|
2357
|
+
const id = useId();
|
|
2358
|
+
const required = Boolean(field.required);
|
|
2359
|
+
useEffect(() => {
|
|
2360
|
+
const serverURL = config.serverURL ?? "";
|
|
2361
|
+
const api = config.routes?.api ?? "/api";
|
|
2362
|
+
const controller = new AbortController();
|
|
2363
|
+
fetch(`${serverURL}${api}/globals/theme?depth=0`, {
|
|
2364
|
+
signal: controller.signal,
|
|
2365
|
+
credentials: "include"
|
|
2366
|
+
}).then((response) => response.ok ? response.json() : null).then((doc) => {
|
|
2367
|
+
setOptions(mode === "token" ? pageEditorTokens(doc) : pageEditorLooks(doc));
|
|
2368
|
+
}).catch(() => {});
|
|
2369
|
+
return () => controller.abort();
|
|
2370
|
+
}, [
|
|
2371
|
+
config.routes?.api,
|
|
2372
|
+
config.serverURL,
|
|
2373
|
+
mode
|
|
2374
|
+
]);
|
|
2375
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2376
|
+
className: "field-type",
|
|
2377
|
+
children: [
|
|
2378
|
+
/* @__PURE__ */ jsx(FieldLabel, {
|
|
2379
|
+
htmlFor: id,
|
|
2380
|
+
label: field.label,
|
|
2381
|
+
required
|
|
2382
|
+
}),
|
|
2383
|
+
/* @__PURE__ */ jsxs("select", {
|
|
2384
|
+
id,
|
|
2385
|
+
disabled: readOnly,
|
|
2386
|
+
value: value ?? "",
|
|
2387
|
+
onChange: (event) => setValue(event.target.value || void 0),
|
|
2388
|
+
children: [/* @__PURE__ */ jsx("option", {
|
|
2389
|
+
value: "",
|
|
2390
|
+
children: required ? "Select…" : "None"
|
|
2391
|
+
}), options.map((option) => /* @__PURE__ */ jsx("option", {
|
|
2392
|
+
value: option.value,
|
|
2393
|
+
children: option.label
|
|
2394
|
+
}, option.value))]
|
|
2395
|
+
}),
|
|
2396
|
+
/* @__PURE__ */ jsx(FieldDescription, {
|
|
2397
|
+
description: field.admin?.description,
|
|
2398
|
+
path
|
|
2399
|
+
}),
|
|
2400
|
+
/* @__PURE__ */ jsx(FieldError, {
|
|
2401
|
+
path,
|
|
2402
|
+
showError,
|
|
2403
|
+
message: errorMessage
|
|
2404
|
+
})
|
|
2405
|
+
]
|
|
2406
|
+
});
|
|
2407
|
+
};
|
|
2408
|
+
//#endregion
|
|
2409
|
+
export { AppearanceField, ColorField, ColorScaleField, ContrastReport, FontField, GreyScaleField, HiddenSaveButton, IdentityFallback, LibraryField, LookField, PairingField, PublishChild, SectionHeading, ThemeDocumentControls, ThemeSaveButton };
|
|
2055
2410
|
|
|
2056
2411
|
//# sourceMappingURL=admin.mjs.map
|