@bison-lab/payload-core 3.24.0 → 3.25.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 +15 -7
- package/dist/admin.d.mts +8 -1
- package/dist/admin.d.mts.map +1 -1
- package/dist/admin.mjs +87 -2
- package/dist/admin.mjs.map +1 -1
- package/dist/index.d.mts +41 -13
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +219 -37
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -3
package/dist/admin.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.mjs","names":["CSS","CSS","CSS","CSS","CSS","LIST_CSS"],"sources":["../src/admin/color-field.tsx","../src/theme/appearance-labels.ts","../src/theme/readability.ts","../src/admin/portal.tsx","../src/admin/brand-hex-field.tsx","../src/admin/colors-layout.ts","../src/admin/preview-mode.tsx","../src/admin/readability-list.tsx","../src/admin/color-scale-card.tsx","../src/admin/color-scale-field.tsx","../src/theme/library.ts","../src/theme/color-usages.ts","../src/admin/library-field.tsx","../src/admin/typography-pairing.tsx","../src/admin/font-field.tsx","../src/admin/pairing-field.tsx","../src/admin/appearance-choices.tsx","../src/admin/appearance-field.tsx","../src/admin/grey-scale-field.tsx","../src/admin/contrast-report.tsx","../src/admin/section-heading.tsx","../src/theme/changes.ts","../src/theme/publish.ts","../src/admin/publish-confirm.tsx","../src/admin/publish-child.tsx","../src/admin/theme-tab.ts","../src/admin/save-button.tsx","../src/admin/identity-fallback.tsx","../src/admin/look-field.tsx","../src/features/types.ts","../src/features/matrix.ts","../src/roles/types.ts","../src/roles/matrix.ts","../src/admin/roles-matrix-field.tsx","../src/admin/roles-row-label.tsx","../src/admin/role-slug-field.tsx","../src/admin/role-name-field.tsx","../src/admin/roles-field.tsx","../src/admin/roles-grants-field.tsx","../src/admin/features-matrix-field.tsx","../src/admin/theme-kit-accent.tsx","../src/admin/document-title-actions.tsx","../src/admin/document-create-new.tsx","../src/admin-nav/types.ts","../src/admin-nav/resolve.ts","../src/admin/admin-nav.tsx","../src/admin/admin-nav-row-label.tsx","../src/admin-nav/entity-options.ts","../src/admin/admin-nav-item-row-label.tsx","../src/admin/admin-nav-entity-field.tsx"],"sourcesContent":["import { FieldDescription, FieldError, FieldLabel, useField } from \"@payloadcms/ui\";\nimport { isThemeHex } from \"@bison-lab/tokens\";\nimport type { TextFieldClientComponent } from \"payload\";\nimport { useEffect, useId, useState } from \"react\";\n\nconst HEX_ERROR = \"Enter a six-digit hex colour like #1e3a5f\";\n\n/**\n * Swatch, native colour input, and hex text, kept in step. `#rrggbb` on\n * blur; the field's `validate` refuses anything else on save.\n */\nexport const ColorField: TextFieldClientComponent = ({ field, path, readOnly }) => {\n const { value, setValue, showError, errorMessage } = useField<string>({ path });\n const [text, setText] = useState(value ?? \"\");\n const [localError, setLocalError] = useState<string | null>(null);\n const id = useId();\n const hexId = `${id}-hex`;\n const pickerId = `${id}-picker`;\n const required = Boolean(field.required);\n const valid = isThemeHex(value);\n const message = localError ?? errorMessage;\n const show = Boolean(localError) || showError;\n\n useEffect(() => {\n setText(value ?? \"\");\n }, [value]);\n\n function commit(next: string) {\n const trimmed = next.trim();\n if (isThemeHex(trimmed)) {\n setValue(trimmed);\n setLocalError(null);\n return;\n }\n setLocalError(HEX_ERROR);\n }\n\n return (\n <div className=\"field-type bl-color-field\">\n <style href=\"bl-color-field\" precedence=\"default\">\n {CSS}\n </style>\n <FieldLabel htmlFor={hexId} label={field.label} required={required} />\n <div className=\"bl-color-field__control\">\n <span\n className=\"bl-color-field__swatch\"\n aria-hidden=\"true\"\n style={{ background: valid ? value : \"transparent\" }}\n />\n <input\n id={pickerId}\n type=\"color\"\n className=\"bl-color-field__picker\"\n disabled={readOnly}\n value={valid ? value : \"#000000\"}\n aria-label={`${typeof field.label === \"string\" ? field.label : \"Colour\"} picker`}\n onChange={(event) => {\n setValue(event.target.value);\n setText(event.target.value);\n setLocalError(null);\n }}\n />\n <input\n id={hexId}\n type=\"text\"\n className=\"bl-color-field__hex\"\n spellCheck={false}\n autoComplete=\"off\"\n disabled={readOnly}\n value={text}\n onChange={(event) => {\n setText(event.target.value);\n if (isThemeHex(event.target.value.trim())) {\n setValue(event.target.value.trim());\n setLocalError(null);\n }\n }}\n onBlur={() => commit(text)}\n />\n </div>\n <FieldDescription description={field.admin?.description} path={path} />\n <FieldError path={path} showError={show} message={message} />\n </div>\n );\n};\n\nconst CSS = `\n.bl-color-field__control{display:flex;align-items:center;gap:calc(var(--base) * .4)}\n.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)}\n.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}\n.bl-color-field__picker:disabled{cursor:not-allowed;opacity:.6}\n.bl-color-field__hex{flex:1;min-width:0;min-height:calc(var(--base) * 2);padding:calc(var(--base) * .25) calc(var(--base) * .6);border:1px solid var(--theme-elevation-150);border-radius:var(--style-radius-s);background:var(--theme-input-bg);color:var(--theme-elevation-800);font-family:var(--font-mono);font-size:13px}\n.bl-color-field__hex:focus{border-color:var(--theme-elevation-400);outline:none;box-shadow:0 0 0 1px var(--theme-elevation-400)}\n.bl-color-field__hex:disabled{color:var(--theme-elevation-400)}\n`;\n","/**\n * Named choices the Appearance child shows. Values stay the token presets;\n * labels match the mock workflow (Soft → pill, Gentle → minimal, Balanced\n * → default, Follow device → system). No rem, ms, or CSS variable tables.\n */\nexport const APPEARANCE_CHOICES = {\n defaultTheme: {\n light: { label: \"Light\", hint: \"Always opens in light mode\" },\n dark: { label: \"Dark\", hint: \"Always opens in dark mode\" },\n system: { label: \"Follow device\", hint: \"Matches the visitor’s system setting\" },\n },\n radius: {\n sharp: { label: \"Sharp\", hint: \"Crisp and structured\" },\n subtle: { label: \"Subtle\", hint: \"Clean with a little softness\" },\n rounded: { label: \"Rounded\", hint: \"Friendly and contemporary\" },\n pill: { label: \"Soft\", hint: \"Very rounded and expressive\" },\n },\n shadow: {\n flat: { label: \"Flat\", hint: \"Minimal visual depth\" },\n subtle: { label: \"Subtle\", hint: \"Light separation between surfaces\" },\n elevated: { label: \"Elevated\", hint: \"More noticeable layering and depth\" },\n },\n motion: {\n snappy: { label: \"Quick\", hint: \"Fast and responsive\" },\n smooth: { label: \"Smooth\", hint: \"Balanced and natural\" },\n minimal: { label: \"Gentle\", hint: \"Slower and more relaxed\" },\n },\n density: {\n compact: { label: \"Compact\", hint: \"Fits more content on screen\" },\n default: { label: \"Balanced\", hint: \"Comfortable for most sites\" },\n spacious: { label: \"Spacious\", hint: \"More breathing room and larger controls\" },\n },\n} as const;\n\nexport const APPEARANCE_FAMILY_COPY: Record<\n keyof typeof APPEARANCE_CHOICES,\n { title: string; hint: string }\n> = {\n defaultTheme: {\n title: \"Default theme\",\n hint: \"Choose how the public site opens for visitors.\",\n },\n radius: {\n title: \"Corner style\",\n hint: \"Controls the shape of buttons, inputs, cards, and panels across the site.\",\n },\n shadow: {\n title: \"Depth\",\n hint: \"Choose how much cards and floating elements stand out from the page.\",\n },\n motion: {\n title: \"Motion\",\n hint: \"Controls how quickly menus, cards, and interface transitions move.\",\n },\n density: {\n title: \"Spacing\",\n hint: \"Choose how compact or roomy forms, buttons, cards, and page sections feel.\",\n },\n};\n\nexport const FONT_ROLE_COPY = {\n heading: {\n label: \"Heading font\",\n hint: \"Used for page titles, section headings, and cards\",\n },\n body: {\n label: \"Body font\",\n hint: \"Used for paragraphs, navigation, forms, and buttons\",\n },\n} as const;\n\nexport const SYSTEM_COLOR_COPY: Record<\n \"primary\" | \"secondary\" | \"accent\" | \"highlight\" | \"success\" | \"destructive\",\n { label: string; hint: string; group: \"brand\" | \"status\" }\n> = {\n primary: { label: \"Primary\", hint: \"Primary actions and key links\", group: \"brand\" },\n secondary: { label: \"Secondary\", hint: \"Supporting accents and eyebrows\", group: \"brand\" },\n accent: { label: \"Accent\", hint: \"Dark brand surfaces\", group: \"brand\" },\n highlight: { label: \"Highlight\", hint: \"Promotional and emphasis fills\", group: \"brand\" },\n success: {\n label: \"Success\",\n hint: \"Success messages and confirmations\",\n group: \"status\",\n },\n destructive: {\n label: \"Destructive\",\n hint: \"Errors, dangerous actions, and destructive confirmations\",\n group: \"status\",\n },\n};\n","import {\n contrastForeground,\n contrastRatio,\n hexToHSL,\n hslToString,\n isThemeHex,\n type HSL,\n} from \"@bison-lab/tokens\";\n\n/** Same threshold `deriveDarkPalette` uses for brand fills. */\nconst DARK_FILL_LIGHTEN_BELOW = 40;\nconst DARK_FILL_LIGHTEN_BY = 25;\n\nexport const READABILITY_TARGET = 7;\n\nexport interface FillLabelSample {\n ratio: number;\n shortfall: number;\n fill: string;\n label: string;\n}\n\nexport interface FillLabelWarning {\n id: string;\n name: string;\n light: FillLabelSample;\n dark: FillLabelSample;\n /** Both modes at or above the target. */\n meets: boolean;\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\nfunction darkFill(color: HSL): HSL {\n if (color.l < DARK_FILL_LIGHTEN_BELOW) {\n return { ...color, l: clamp(color.l + DARK_FILL_LIGHTEN_BY, 0, 100) };\n }\n return color;\n}\n\nfunction sample(fill: HSL, target: number): FillLabelSample {\n const label = contrastForeground(fill);\n const fillCss = hslToString(fill);\n const ratio = contrastRatio(fillCss, label);\n return {\n ratio,\n shortfall: Math.max(0, Math.round((target - ratio) * 100) / 100),\n fill: fillCss,\n label,\n };\n}\n\n/**\n * Editable fill + the automatic label, Light and Dark. Target 7:1.\n * Meets only when both pass. Warnings do not block save.\n */\nexport function fillLabelWarning(\n id: string,\n name: string,\n hex: string,\n target = READABILITY_TARGET,\n): FillLabelWarning | null {\n if (!isThemeHex(hex)) return null;\n const lightFill = hexToHSL(hex);\n const light = sample(lightFill, target);\n const dark = sample(darkFill(lightFill), target);\n return { id, name, light, dark, meets: light.ratio >= target && dark.ratio >= target };\n}\n\n/** Green/teal family. A warning at admin time, not a schema block. */\nexport function successHueWarning(hex: string): string | null {\n if (!isThemeHex(hex)) return null;\n const { h } = hexToHSL(hex);\n if (h >= 80 && h <= 180) return null;\n return \"Keep success colors recognizable — stay in a green or teal family.\";\n}\n\n/** Red family. A warning at admin time, not a schema block. */\nexport function destructiveHueWarning(hex: string): string | null {\n if (!isThemeHex(hex)) return null;\n const { h } = hexToHSL(hex);\n if (h <= 30 || h >= 330) return null;\n return \"Keep destructive colors recognizable — stay in a red family.\";\n}\n\nexport function automaticLabel(hex: string): string | null {\n if (!isThemeHex(hex)) return null;\n return contrastForeground(hexToHSL(hex));\n}\n\nexport function hslCss(value: string): string {\n return `hsl(${value})`;\n}\n\n/** Which appearances fail, in words. Empty when both pass. */\nexport function hardToReadModes(item: FillLabelWarning): string {\n const light = item.light.shortfall > 0;\n const dark = item.dark.shortfall > 0;\n if (light && dark) return \"in Light and Dark\";\n if (light) return \"in Light\";\n if (dark) return \"in Dark\";\n return \"\";\n}\n\nexport function readabilityHeadline(item: FillLabelWarning): string {\n return item.meets ? `Text on ${item.name} looks readable` : `Text on ${item.name} may be hard to read`;\n}\n\nexport function readabilityModesLine(item: FillLabelWarning): string {\n const modes = hardToReadModes(item);\n return modes ? `Hard to read ${modes}.` : \"Looks good in Light and Dark.\";\n}\n\nexport function readabilityGapPercent(sample: FillLabelSample, target = READABILITY_TARGET): number {\n if (sample.shortfall <= 0) return 0;\n return Math.round((sample.shortfall / target) * 100);\n}\n\nexport function readabilityRatioLine(sample: FillLabelSample, target = READABILITY_TARGET): string {\n const percent = readabilityGapPercent(sample, target);\n if (percent <= 0) return \"Meets the contrast we want\";\n if (percent < 10) return \"A little short of the contrast we want\";\n return `About ${percent}% short of the contrast we want`;\n}\n\nexport const READABILITY_FIX =\n \"Darken or lighten the hex, then regenerate the scale. The site picks light or dark type for you.\";\n\nexport const READABILITY_PUBLISH_NOTE =\n \"You can still publish. To improve a color, darken or lighten it and regenerate.\";\n","import type { ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\n\n/** Theme overlays must leave Payload's transformed/clipped admin tree. */\nexport function ThemePortal({ children }: { children: ReactNode }) {\n if (typeof document === \"undefined\") return null;\n return createPortal(children, document.body);\n}\n","import { Dialog, Field, Input, KitProvider, Label } from \"@bison-lab/admin-ui\";\nimport { isThemeHex } from \"@bison-lab/tokens\";\nimport { useEffect, useState } from \"react\";\nimport { HexColorPicker } from \"react-colorful\";\n\nimport { ThemePortal } from \"./portal\";\n\n/** Keep a leading # and at most six hex digits. Drop everything else. */\nexport function filterThemeHexInput(raw: string): string {\n const trimmed = raw.trim();\n if (trimmed === \"\") return \"\";\n const digits = trimmed\n .replace(/^#/, \"\")\n .replace(/[^0-9a-fA-F]/g, \"\")\n .slice(0, 6);\n return `#${digits}`;\n}\n\nexport function BrandHexField({\n name,\n value,\n onChange,\n readOnly,\n placeholder = \"#DB0082\",\n picker = \"dialog\",\n}: {\n name: string;\n value: string;\n onChange: (hex: string) => void;\n readOnly?: boolean;\n placeholder?: string;\n picker?: \"dialog\" | \"inline\";\n}) {\n const [draft, setDraft] = useState(value);\n const [open, setOpen] = useState(false);\n const [pickerDraft, setPickerDraft] = useState(value);\n\n useEffect(() => {\n setDraft(value);\n }, [value]);\n\n function typeHex(next: string) {\n const filtered = filterThemeHexInput(next);\n setDraft(filtered);\n if (isThemeHex(filtered)) onChange(filtered);\n }\n\n function openPicker() {\n setPickerDraft(isThemeHex(draft) ? draft : value);\n setOpen(true);\n }\n\n function applyPicker() {\n if (!isThemeHex(pickerDraft)) return;\n onChange(pickerDraft);\n setDraft(pickerDraft);\n setOpen(false);\n }\n\n const input = (\n <Input\n aria-label={`${name} hex`}\n value={draft}\n placeholder={placeholder}\n spellCheck={false}\n autoComplete=\"off\"\n disabled={readOnly}\n onChange={(event) => typeHex(event.target.value)}\n onBlur={() => {\n if (!isThemeHex(draft)) setDraft(value);\n }}\n />\n );\n\n return (\n <KitProvider>\n <style href=\"bl-brand-hex\" precedence=\"default\">\n {CSS}\n </style>\n {picker === \"inline\" ? (\n <div className=\"bl-brand-hex bl-brand-hex--inline\">\n <HexColorPicker\n color={isThemeHex(draft) ? draft : \"#000000\"}\n onChange={(hex) => {\n setDraft(hex);\n onChange(hex);\n }}\n />\n <Field as=\"div\">\n <Label>Hex</Label>\n {input}\n </Field>\n </div>\n ) : (\n <div className=\"bl-brand-hex\">\n <button\n type=\"button\"\n className=\"bl-brand-hex__swatch\"\n aria-label={`${name} picker`}\n disabled={readOnly}\n style={{ background: isThemeHex(draft) ? draft : \"transparent\" }}\n onClick={openPicker}\n />\n {input}\n </div>\n )}\n {picker === \"dialog\" ? (\n <ThemePortal>\n <div className=\"bl-theme-dialog\">\n <Dialog\n open={open}\n title={`Pick ${name}`}\n onCancel={() => setOpen(false)}\n confirmLabel=\"Apply\"\n onConfirm={applyPicker}\n confirmDisabled={!isThemeHex(pickerDraft)}\n >\n <div className=\"bl-brand-hex bl-brand-hex--inline\">\n <HexColorPicker\n color={isThemeHex(pickerDraft) ? pickerDraft : \"#000000\"}\n onChange={setPickerDraft}\n />\n <Field as=\"div\">\n <Label>Hex</Label>\n <Input\n aria-label={`${name} picker hex`}\n value={pickerDraft}\n placeholder={placeholder}\n spellCheck={false}\n autoComplete=\"off\"\n onChange={(event) => setPickerDraft(filterThemeHexInput(event.target.value))}\n />\n </Field>\n </div>\n </Dialog>\n </div>\n </ThemePortal>\n ) : null}\n </KitProvider>\n );\n}\n\nconst CSS = `\n.bl-brand-hex{display:flex;align-items:stretch;gap:8px;min-width:0}\n.bl-brand-hex--inline{flex-direction:column;gap:12px}\n.bl-brand-hex .react-colorful{width:100%;height:200px}\n.bl-brand-hex__swatch{flex:none;width:38px;border:1px solid #3a3d46;border-radius:8px;padding:0;cursor:pointer;background:#1d1f24}\n.bl-brand-hex__swatch:disabled{opacity:.5;cursor:not-allowed}\n.bl-brand-hex .bl-nav-kit__input{font-family:var(--font-mono,ui-monospace,monospace)}\n.bl-theme-dialog .bl-nav-kit__modal{z-index:10000}\n`;\n","/**\n * Theme Colors tab chrome. Payload group-in-group draws a left gutter;\n * the mockup does not. Brand cards sit two-up. Light / Dark lives on the\n * cards only — the field list stays Payload chrome.\n */\nexport const THEME_COLORS_LAYOUT_CSS = `\n.group-field--gutter:has(.bl-scale-field),\n.group-field--gutter:has(.bl-section-heading),\n.group-field--gutter:has(.bl-grey),\n.group-field--gutter:has(.bl-library){\n border-left:none;\n padding-left:0;\n}\n.render-fields:has(> .bl-scale-field),\n.render-fields:has(> .field-type.bl-scale-field){\n display:grid;\n grid-template-columns:minmax(0,1fr) minmax(0,1fr);\n gap:1rem;\n align-items:start;\n}\n.render-fields:has(> .bl-scale-field) > .bl-section-heading,\n.render-fields:has(> .field-type.bl-scale-field) > .bl-section-heading,\n.render-fields:has(> .bl-scale-field) > :has(.bl-section-heading),\n.render-fields:has(> .field-type.bl-scale-field) > :has(.bl-section-heading),\n.render-fields:has(> .bl-scale-field) > .bl-library,\n.render-fields:has(> .field-type.bl-scale-field) > .field-type.bl-library,\n.render-fields:has(> .bl-scale-field) > :has(.bl-library),\n.render-fields:has(> .field-type.bl-scale-field) > :has(.bl-library),\n.render-fields:has(> .bl-scale-field) > :has(.bl-grey),\n.render-fields:has(> .field-type.bl-scale-field) > :has(.bl-grey){\n grid-column:1/-1;\n}\n@media (max-width:860px){\n .render-fields:has(> .bl-scale-field),\n .render-fields:has(> .field-type.bl-scale-field){\n grid-template-columns:1fr;\n }\n}\n`;\n","import { useFormFields } from \"@payloadcms/ui\";\nimport {\n deriveDarkPalette,\n deriveLightPalette,\n type GreyScale,\n} from \"@bison-lab/tokens\";\nimport { useEffect, useState, type CSSProperties } from \"react\";\n\nexport type ThemePreviewMode = \"light\" | \"dark\";\n\nconst ATTR = \"data-bl-theme-preview\";\nconst EVENT = \"bl-theme-preview\";\nconst PREVIEW_VARS = [\n \"--bl-preview-bg\",\n \"--bl-preview-card\",\n \"--bl-preview-border\",\n \"--bl-preview-text\",\n \"--bl-preview-muted\",\n \"--bl-preview-input\",\n] as const;\n\n/** Brand hexes do not affect grey-driven surfaces; derive still requires them. */\nconst PREVIEW_BRAND = { primary: \"#111111\", secondary: \"#111111\", success: \"#111111\" } as const;\n\nfunction readDocumentTheme(): ThemePreviewMode {\n if (typeof document === \"undefined\") return \"light\";\n return document.documentElement.getAttribute(\"data-theme\") === \"dark\" ? \"dark\" : \"light\";\n}\n\nlet currentMode: ThemePreviewMode = readDocumentTheme();\n\nfunction readMode(): ThemePreviewMode {\n return currentMode;\n}\n\n/** Drop leftovers from the old html-wide preview so Payload chrome stays Payload. */\nfunction clearDocumentPreview() {\n if (typeof document === \"undefined\") return;\n document.documentElement.removeAttribute(ATTR);\n for (const name of PREVIEW_VARS) document.documentElement.style.removeProperty(name);\n}\n\nexport function setThemePreviewMode(mode: ThemePreviewMode) {\n currentMode = mode;\n clearDocumentPreview();\n if (typeof window !== \"undefined\") window.dispatchEvent(new Event(EVENT));\n}\n\nexport function useThemePreviewMode(): ThemePreviewMode {\n const [mode, setMode] = useState<ThemePreviewMode>(readMode);\n useEffect(() => {\n clearDocumentPreview();\n const sync = () => setMode(readMode());\n sync();\n window.addEventListener(EVENT, sync);\n return () => window.removeEventListener(EVENT, sync);\n }, []);\n return mode;\n}\n\nexport function previewVarsFor(grey: GreyScale, mode: ThemePreviewMode) {\n const palette =\n mode === \"dark\"\n ? deriveDarkPalette({ ...PREVIEW_BRAND, grey })\n : deriveLightPalette({ ...PREVIEW_BRAND, grey });\n return {\n \"--bl-preview-bg\": `hsl(${palette.background})`,\n \"--bl-preview-card\": `hsl(${palette.card})`,\n \"--bl-preview-border\": `hsl(${palette.border})`,\n \"--bl-preview-text\": `hsl(${palette.foreground})`,\n \"--bl-preview-muted\": `hsl(${palette[\"muted-foreground\"]})`,\n \"--bl-preview-input\": `hsl(${palette.input})`,\n // Kit neutrals read Payload elevation tokens. Remap them on the canvas so\n // Required / Optional invert with Light / Dark, not the admin chrome.\n \"--theme-elevation-0\": `hsl(${palette.card})`,\n \"--theme-elevation-150\": `hsl(${palette.border})`,\n \"--theme-elevation-800\": `hsl(${palette.foreground})`,\n };\n}\n\nfunction useGreyScale(): GreyScale {\n return useFormFields(([fields]) => {\n const value = fields[\"colors.greyScale\"]?.value;\n return value === \"gray\" ||\n value === \"zinc\" ||\n value === \"neutral\" ||\n value === \"stone\" ||\n value === \"slate\"\n ? value\n : \"slate\";\n });\n}\n\n/**\n * Light / Dark + the live grey family, applied on each Theme field canvas.\n * Never writes to `documentElement` — nav, tabs, and Publish stay Payload.\n */\nexport function usePreviewCanvas() {\n const mode = useThemePreviewMode();\n const greyScale = useGreyScale();\n return {\n mode,\n className: \"bl-preview-canvas\",\n style: previewVarsFor(greyScale, mode) as CSSProperties,\n };\n}\n\nexport function ThemePreviewToggle() {\n const mode = useThemePreviewMode();\n return (\n <div className=\"bl-preview-toggle\" role=\"group\" aria-label=\"Preview theme in\">\n <button type=\"button\" data-on={mode === \"light\" ? \"\" : undefined} onClick={() => setThemePreviewMode(\"light\")}>\n Light\n </button>\n <button type=\"button\" data-on={mode === \"dark\" ? \"\" : undefined} onClick={() => setThemePreviewMode(\"dark\")}>\n Dark\n </button>\n </div>\n );\n}\n\nexport const THEME_PREVIEW_TOGGLE_CSS = `\n.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)}\n.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}\n.bl-preview-toggle button[data-on]{background:var(--theme-text,#0f172a);color:var(--theme-bg,#fff)}\n`;\n","import type { FillLabelWarning } from \"../theme/readability\";\nimport {\n hslCss,\n READABILITY_FIX,\n READABILITY_TARGET,\n readabilityHeadline,\n readabilityModesLine,\n readabilityRatioLine,\n} from \"../theme/readability\";\n\nexport function ReadabilityDetail({\n item,\n target = READABILITY_TARGET,\n}: {\n item: FillLabelWarning;\n target?: number;\n}) {\n return (\n <div className=\"bl-readability-detail\">\n <p className=\"bl-readability-detail__lead\">{readabilityModesLine(item)}</p>\n <div className=\"bl-readability-detail__modes\">\n {(\n [\n [\"Light\", item.light],\n [\"Dark\", item.dark],\n ] as const\n ).map(([mode, sample]) => (\n <figure key={mode} data-failing={sample.shortfall > 0 ? \"\" : undefined}>\n <span\n aria-hidden=\"true\"\n className=\"bl-readability__swatch\"\n style={{ background: hslCss(sample.fill), color: hslCss(sample.label) }}\n >\n Aa\n </span>\n <figcaption>\n <strong>{mode}</strong>\n <span>{sample.shortfall > 0 ? \"Hard to read\" : \"Looks good\"}</span>\n <span>{readabilityRatioLine(sample, target)}</span>\n </figcaption>\n </figure>\n ))}\n </div>\n {item.meets ? null : <p className=\"bl-readability-detail__fix\">{READABILITY_FIX}</p>}\n </div>\n );\n}\n\nexport function ReadabilityList({\n warnings,\n target = READABILITY_TARGET,\n}: {\n warnings: FillLabelWarning[];\n target?: number;\n}) {\n const failing = warnings.filter((item) => !item.meets).length;\n return (\n <section className=\"bl-readability\">\n <div className=\"bl-readability__head\">\n <div>\n <h2>Readability checks</h2>\n <p>Text the site puts on each fill. Warnings do not block save.</p>\n </div>\n <span data-attention={failing ? \"\" : undefined}>\n {failing === 0 ? \"All look readable\" : `${failing} may be hard to read`}\n </span>\n </div>\n <ul>\n {warnings.map((item) => (\n <li key={item.id} data-failing={item.meets ? undefined : \"\"}>\n <strong>{readabilityHeadline(item)}</strong>\n <ReadabilityDetail item={item} target={target} />\n </li>\n ))}\n </ul>\n </section>\n );\n}\n\nexport const READABILITY_LIST_CSS = `\n.bl-readability{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)}\n.bl-readability__head{display:flex;justify-content:space-between;gap:1rem;align-items:flex-start}\n.bl-readability__head h2{margin:0;font-size:1rem}\n.bl-readability__head p{margin:.35rem 0 0;font-size:12px;color:var(--theme-elevation-500,#64748b)}\n.bl-readability__head span{flex:none;font-size:12px;font-weight:600;padding:.2rem .55rem;border-radius:999px;background:var(--theme-elevation-100,#f1f5f9)}\n.bl-readability__head span[data-attention]{background:#fffbeb;color:#92400e}\n.bl-readability ul{margin:.85rem 0 0;padding:0;list-style:none}\n.bl-readability li{padding:.65rem 0;border-top:1px solid var(--theme-elevation-100,#f1f5f9)}\n.bl-readability li:first-child{border-top:0}\n.bl-readability li[data-failing]{background:#fff7ed;margin:0 -.4rem;padding:.65rem .4rem;border-radius:8px}\n.bl-readability__swatch{flex:none;display:inline-flex;align-items:center;justify-content:center;width:2.75rem;height:2rem;border-radius:6px;font-weight:700;font-size:13px}\n.bl-readability strong{display:block;font-size:13px}\n.bl-readability-detail__lead{margin:0 0 .65rem;font-size:13px;color:var(--theme-elevation-600,#475569)}\n.bl-readability-detail__modes{display:grid;grid-template-columns:1fr 1fr;gap:.65rem}\n.bl-readability-detail__modes figure{display:flex;gap:.6rem;align-items:center;margin:0;padding:.55rem .6rem;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:10px;background:#fff}\n.bl-readability-detail__modes figure[data-failing]{border-color:#fdba74;background:#fff7ed}\n.bl-readability-detail__modes figcaption{display:flex;flex-direction:column;gap:.1rem;min-width:0}\n.bl-readability-detail__modes figcaption strong{font-size:12px}\n.bl-readability-detail__modes figcaption span{font-size:11px;color:var(--theme-elevation-500,#64748b)}\n.bl-readability-detail__fix{margin:.7rem 0 0;font-size:13px;color:var(--theme-elevation-600,#475569)}\n`;\n","import {\n Badge,\n Field,\n KitProvider,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@bison-lab/admin-ui\";\nimport {\n createColorScale,\n includedShadeSteps,\n isThemeHex,\n setColorScaleInclude,\n SHADE_STEPS,\n type ColorScaleState,\n type ShadeStep,\n} from \"@bison-lab/tokens\";\nimport { useId, useState } from \"react\";\n\nimport {\n fillLabelWarning,\n hslCss,\n readabilityHeadline,\n successHueWarning,\n destructiveHueWarning,\n} from \"../theme/readability\";\nimport { BrandHexField } from \"./brand-hex-field\";\nimport { THEME_COLORS_LAYOUT_CSS } from \"./colors-layout\";\nimport { ThemePortal } from \"./portal\";\nimport { usePreviewCanvas } from \"./preview-mode\";\nimport { ReadabilityDetail, READABILITY_LIST_CSS } from \"./readability-list\";\n\nexport interface ColorScaleCardProps {\n id?: string;\n name: string;\n hint?: string;\n required?: boolean;\n custom?: boolean;\n state: ColorScaleState;\n onChange: (next: ColorScaleState) => void;\n onDelete?: () => void;\n readOnly?: boolean;\n role?: \"success\" | \"destructive\" | null;\n}\n\nconst STATUS_COPY = {\n success: {\n title: \"Keep success colors recognizable\",\n body: \"Success states should stay in a green or teal family so users can quickly recognize positive outcomes and confirmations.\",\n drift: \"This color may no longer read as a success state.\",\n },\n destructive: {\n title: \"Keep destructive colors recognizable\",\n body: \"Destructive actions should stay in a red or crimson family so users can quickly recognize errors and dangerous actions.\",\n drift: \"This color may no longer read as a destructive or error state.\",\n },\n} as const;\n\nfunction IncludeMark({ on }: { on: boolean }) {\n return (\n <span className=\"bl-scale-card__status\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 16 16\">\n {on ? (\n <path\n d=\"M3.5 8.5 6.5 11.5 12.5 4.5\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.4\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n ) : (\n <path\n d=\"M4.5 4.5 11.5 11.5M11.5 4.5 4.5 11.5\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.4\"\n strokeLinecap=\"round\"\n />\n )}\n </svg>\n </span>\n );\n}\n\nexport function ColorScaleCard({\n id,\n name,\n hint,\n required,\n custom,\n state,\n onChange,\n onDelete,\n readOnly,\n role,\n}: ColorScaleCardProps) {\n const warning = fillLabelWarning(id ?? name.toLowerCase(), name, state.hex);\n const canvas = usePreviewCanvas();\n const [attentionOpen, setAttentionOpen] = useState(false);\n const [shakeStep, setShakeStep] = useState<ShadeStep | null>(null);\n const titleId = useId();\n const included = new Set(includedShadeSteps(state));\n const hueDrift =\n role === \"success\"\n ? Boolean(successHueWarning(state.hex))\n : role === \"destructive\"\n ? Boolean(destructiveHueWarning(state.hex))\n : false;\n\n function commitHex(hex: string) {\n onChange(createColorScale(hex, state.sourceStep, state.include));\n }\n\n function commitStep(step: ShadeStep) {\n onChange(createColorScale(state.hex, step, state.include));\n }\n\n function toggleStep(step: ShadeStep) {\n if (step === state.sourceStep) {\n setShakeStep(step);\n window.setTimeout(() => setShakeStep((was) => (was === step ? null : was)), 180);\n return;\n }\n const next = new Set(included);\n if (next.has(step)) next.delete(step);\n else next.add(step);\n onChange(setColorScaleInclude(state, SHADE_STEPS.filter((item) => next.has(item))));\n }\n\n return (\n <KitProvider accent={id === \"primary\" && isThemeHex(state.hex) ? state.hex : undefined}>\n <article className={`bl-scale-card ${canvas.className}`} data-preview={canvas.mode} style={canvas.style}>\n <header className=\"bl-scale-card__head\">\n <div>\n <div className=\"bl-scale-card__title-row\">\n <h3 className=\"bl-scale-card__title\">{name}</h3>\n {required ? <Badge>Required</Badge> : null}\n {custom ? <Badge>Optional</Badge> : null}\n {warning && !warning.meets ? (\n <Badge as=\"button\" variant=\"danger\" aria-haspopup=\"dialog\" onClick={() => setAttentionOpen(true)}>\n Needs attention\n </Badge>\n ) : null}\n </div>\n {hint ? <p className=\"bl-scale-card__hint\">{hint}</p> : null}\n </div>\n {onDelete ? (\n <button type=\"button\" className=\"bl-scale-card__delete\" disabled={readOnly} onClick={onDelete}>\n Delete\n </button>\n ) : null}\n </header>\n\n <div className=\"bl-scale-card__row\">\n <Field as=\"div\">\n <Label>Brand hex</Label>\n <BrandHexField name={name} value={state.hex} onChange={commitHex} readOnly={readOnly} />\n </Field>\n <Field as=\"div\">\n <Label>This color is</Label>\n <Select\n value={String(state.sourceStep)}\n onValueChange={(value) => commitStep(Number(value) as ShadeStep)}\n disabled={readOnly}\n >\n <SelectTrigger aria-label=\"This color is\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SHADE_STEPS.map((step) => (\n <SelectItem key={step} value={String(step)}>\n {step}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </Field>\n </div>\n\n {role ? (\n <div className=\"bl-scale-card__family\" data-role={role} data-drift={hueDrift ? \"\" : undefined}>\n <div className=\"bl-scale-card__family-mark\" aria-hidden=\"true\">\n !\n </div>\n <div>\n <div className=\"bl-scale-card__family-title\">{STATUS_COPY[role].title}</div>\n <p>{STATUS_COPY[role].body}</p>\n {hueDrift ? <p className=\"bl-scale-card__family-drift\">{STATUS_COPY[role].drift}</p> : null}\n </div>\n </div>\n ) : null}\n\n <div className=\"bl-scale-card__scale-head\">\n <span>Generated scale</span>\n <span>{SHADE_STEPS.length} shades</span>\n </div>\n <div className=\"bl-scale-card__steps\" role=\"group\" aria-label={`${name} scale steps`}>\n {SHADE_STEPS.map((step) => {\n const source = step === state.sourceStep;\n const on = included.has(step);\n return (\n <button\n key={step}\n type=\"button\"\n className=\"bl-scale-card__step\"\n data-source={source ? \"\" : undefined}\n data-excluded={on ? undefined : \"\"}\n data-shake={shakeStep === step ? \"\" : undefined}\n disabled={readOnly}\n aria-pressed={on}\n aria-label={\n source\n ? `Source step ${step} cannot be excluded`\n : on\n ? `Shade ${step}, available — click to exclude from the palette`\n : `Shade ${step}, excluded — click to include in the palette`\n }\n title={\n source\n ? `Source step ${step} cannot be excluded`\n : on\n ? \"Available to page editors — click to exclude\"\n : \"Excluded from page editors — click to include\"\n }\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n toggleStep(step);\n }}\n >\n <span className=\"bl-scale-card__chip-wrap\">\n <span className=\"bl-scale-card__chip\" style={{ backgroundColor: hslCss(state.scale[step]) }} />\n <IncludeMark on={on} />\n </span>\n <span className=\"bl-scale-card__step-label\">{step}</span>\n </button>\n );\n })}\n </div>\n <div className=\"bl-scale-card__editors\">\n <div>\n <div>Available to page editors</div>\n <p>\n {included.size} of {SHADE_STEPS.length} shades available · Choose which shades editors can select when\n building pages.\n </p>\n </div>\n <span>\n <button type=\"button\" disabled={readOnly} onClick={() => onChange(setColorScaleInclude(state, \"all\"))}>\n Include all\n </button>\n <button type=\"button\" disabled={readOnly} onClick={() => onChange(setColorScaleInclude(state, \"source\"))}>\n Source only\n </button>\n </span>\n </div>\n {attentionOpen && warning ? (\n <ThemePortal>\n <div\n className=\"bl-scale-card__modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n onClick={(event) => {\n if (event.target === event.currentTarget) setAttentionOpen(false);\n }}\n >\n <div className=\"bl-scale-card__panel\">\n <div className=\"bl-scale-card__panel-head\">\n <h4 id={titleId}>{readabilityHeadline(warning)}</h4>\n <button type=\"button\" onClick={() => setAttentionOpen(false)} aria-label=\"Close\">\n ×\n </button>\n </div>\n <ReadabilityDetail item={warning} />\n <button type=\"button\" className=\"bl-scale-card__panel-done\" onClick={() => setAttentionOpen(false)}>\n Keep editing this color\n </button>\n </div>\n </div>\n </ThemePortal>\n ) : null}\n </article>\n </KitProvider>\n );\n}\n\nexport const COLOR_SCALE_CARD_CSS = `\n.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)}\n.bl-scale-card__head{display:flex;justify-content:space-between;gap:1rem;align-items:flex-start}\n.bl-scale-card__title-row{position:relative;display:flex;align-items:center;flex-wrap:wrap;gap:.5rem}\n.bl-scale-card__title{margin:0;font-size:1rem}\n.bl-scale-card__hint{margin:.35rem 0 0;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b));font-size:12px}\n.bl-scale-card__delete{border:0;background:none;color:#be123c;font:inherit;font-size:13px;font-weight:600;cursor:pointer}\n.bl-scale-card__row{display:grid;grid-template-columns:1fr 8rem;gap:.75rem;margin-top:1rem;align-items:start}\n.bl-scale-card__row .bl-nav-kit__field{margin-bottom:0}\n.bl-scale-card__family{display:flex;gap:.75rem;align-items:flex-start;margin-top:1rem;padding:.75rem .85rem;border-radius:8px}\n.bl-scale-card__family[data-role=success]{border:1px solid #a7f3d0;background:#ecfdf5;color:#065f46}\n.bl-scale-card__family[data-role=destructive]{border:1px solid #fecdd3;background:#fff1f2;color:#9f1239}\n.bl-scale-card__family[data-drift]{box-shadow:0 0 0 2px #fbbf24}\n.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}\n.bl-scale-card__family[data-role=success] .bl-scale-card__family-mark{background:#d1fae5;color:#047857}\n.bl-scale-card__family[data-role=destructive] .bl-scale-card__family-mark{background:#ffe4e6;color:#be123c}\n.bl-scale-card__family-title{font-size:12px;font-weight:600}\n.bl-scale-card__family p{margin:.25rem 0 0;font-size:11px;line-height:1.45;opacity:.85}\n.bl-scale-card__family-drift{font-weight:600;opacity:1}\n.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))}\n.bl-scale-card__steps{display:grid;grid-template-columns:repeat(11,minmax(0,1fr));gap:.45rem 3px}\n.bl-scale-card__step{display:flex;flex-direction:column;align-items:center;gap:.3rem;border:0;padding:0;background:transparent;cursor:pointer}\n.bl-scale-card__chip-wrap{position:relative;display:block;width:100%}\n.bl-scale-card__chip{display:block;width:100%;height:2.15rem;border-radius:6px;overflow:hidden}\n.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)}\n.bl-scale-card__status svg{display:block;width:10px;height:10px}\n.bl-scale-card__step-label{font-size:10px;line-height:1;color:var(--theme-elevation-600,#475569)}\n.bl-scale-card__step[data-source] .bl-scale-card__chip{box-shadow:0 0 0 2px #0f172a}\n.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%)}\n.bl-scale-card__step[data-excluded] .bl-scale-card__status{color:#991b1b;background:rgba(255,255,255,.96)}\n.bl-scale-card__step[data-excluded] .bl-scale-card__step-label{opacity:.35}\n@keyframes bl-scale-shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-3px)}75%{transform:translateX(3px)}}\n.bl-scale-card__step[data-shake]{animation:bl-scale-shake .18s}\n.bl-scale-card__step:disabled{cursor:default}\n.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))}\n.bl-scale-card__editors > div > div{font-size:12px;font-weight:600;color:var(--bl-preview-text,var(--theme-elevation-700,#334155))}\n.bl-scale-card__editors p{margin:.2rem 0 0;font-size:11px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}\n.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}\n.bl-scale-card__editors span{display:flex;gap:0}\n.bl-scale-card__modal{position:fixed;inset:0;z-index:10000;display:grid;place-items:center;padding:1rem;background:rgba(15,23,42,.45)}\n.bl-scale-card__panel{width:min(32rem,100%);padding:1.15rem 1.2rem;border-radius:16px;background:#fff;color:#0f172a;color-scheme:light}\n.bl-scale-card__panel-head{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem}\n.bl-scale-card__panel-head h4{margin:0;font-size:1rem}\n.bl-scale-card__panel-head button{border:0;background:none;font:inherit;font-size:1.25rem;line-height:1;color:#64748b;cursor:pointer}\n.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}\n.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)}\n` + READABILITY_LIST_CSS + THEME_COLORS_LAYOUT_CSS;\n","import { useField, useForm } from \"@payloadcms/ui\";\nimport { isThemeHex, SHADE_STEPS, type ColorScaleState, type ShadeStep } from \"@bison-lab/tokens\";\nimport type { GroupFieldClientComponent } from \"payload\";\n\nimport { SYSTEM_COLOR_COPY } from \"../theme/appearance-labels\";\nimport { colorDocFromState, stateFromColorDoc } from \"../theme/map\";\nimport { ColorScaleCard, COLOR_SCALE_CARD_CSS } from \"./color-scale-card\";\n\nconst SYSTEM_ROLES = new Set(Object.keys(SYSTEM_COLOR_COPY));\n\n/**\n * Payload's hasMany select often stores a count on the field path and the\n * chosen values at `path.0`, `path.1`, … — same shape as an array field.\n */\nfunction includedStepsFromForm(\n path: string,\n value: ShadeStep[] | string[] | number | undefined,\n getDataByPath?: (fieldPath: string) => unknown,\n): ShadeStep[] | string[] | undefined {\n if (Array.isArray(value)) return value;\n const stored = getDataByPath?.(path);\n if (Array.isArray(stored)) return stored as ShadeStep[] | string[];\n const count = typeof value === \"number\" ? value : typeof stored === \"number\" ? stored : 0;\n if (count <= 0) return undefined;\n const steps = Array.from({ length: count }, (_, index) => getDataByPath?.(`${path}.${index}`));\n if (steps.every((step) => step == null)) return undefined;\n return steps.filter((step): step is ShadeStep | string => step != null).map(String);\n}\n\n/**\n * One system (or library row) color: hex, source step, include/exclude.\n * Writes the group's stored fields. A committed hex or step rebuilds the scale.\n */\nexport const ColorScaleField: GroupFieldClientComponent = ({ field, path, readOnly }) => {\n const hex = useField<string>({ path: `${path}.hex` });\n const sourceStep = useField<string | number>({ path: `${path}.sourceStep` });\n const scale = useField<ColorScaleState[\"scale\"]>({ path: `${path}.scale` });\n const stale = useField<boolean>({ path: `${path}.stale` });\n const include = useField<string>({ path: `${path}.include` });\n const includedSteps = useField<ShadeStep[] | string[] | number>({ path: `${path}.includedSteps` });\n const { getDataByPath } = useForm();\n const key = path.split(\".\").pop() ?? \"\";\n const copy = SYSTEM_ROLES.has(key) ? SYSTEM_COLOR_COPY[key as keyof typeof SYSTEM_COLOR_COPY] : undefined;\n const stepList = includedStepsFromForm(`${path}.includedSteps`, includedSteps.value, getDataByPath);\n const state = stateFromColorDoc({\n hex: hex.value,\n sourceStep: sourceStep.value as ShadeStep | undefined,\n scale: scale.value,\n stale: stale.value,\n include: include.value === \"source\" || include.value === \"custom\" || include.value === \"all\" ? include.value : \"all\",\n includedSteps: stepList,\n });\n\n function write(next: ColorScaleState) {\n const doc = colorDocFromState(next);\n hex.setValue(doc.hex);\n sourceStep.setValue(String(doc.sourceStep));\n scale.setValue(doc.scale);\n stale.setValue(doc.stale);\n include.setValue(doc.include);\n includedSteps.setValue(\n (doc.includedSteps ?? (doc.include === \"source\" ? [doc.sourceStep] : [...SHADE_STEPS])).map(String),\n );\n }\n\n const label = copy?.label ?? (typeof field.label === \"string\" ? field.label : key);\n\n return (\n <div className=\"field-type bl-scale-field\">\n <style href=\"bl-scale-card\" precedence=\"default\">\n {COLOR_SCALE_CARD_CSS}\n </style>\n <ColorScaleCard\n id={key}\n name={label}\n hint={copy?.hint}\n required={Boolean(copy) || Boolean(\"required\" in field && field.required)}\n state={isThemeHex(state.hex) ? state : { ...state, hex: \"#000000\" }}\n onChange={write}\n readOnly={readOnly}\n role={key === \"success\" || key === \"destructive\" ? key : null}\n />\n </div>\n );\n};\n","import { SHADE_STEPS, type ShadeStep } from \"@bison-lab/tokens\";\n\nimport { SYSTEM_COLOR_KEYS, type ThemeDoc, type ThemeLibraryColorDoc } from \"./types\";\n\n/**\n * Payload's array form state stores the row count (`0`, `2`, …), not the\n * rows. A custom Field that treats that number as the list will throw\n * `rows.filter is not a function` on an empty Theme library.\n */\nexport function asLibraryRows(value: unknown): ThemeLibraryColorDoc[] {\n return Array.isArray(value) ? value : [];\n}\n\nconst STEP_SET = new Set<number>(SHADE_STEPS);\n\n/**\n * Page editors pick `coral-400`, never a raw hex. Rewrite every use of\n * `fromKey` onto `toKey` at the same step: `coral-400` → `highlight-400`.\n * A bare key (`coral`) becomes `toKey`. Anything else is left alone.\n */\nexport function rewriteColorToken(token: string, fromKey: string, toKey: string): string {\n if (token === fromKey) return toKey;\n const dash = token.lastIndexOf(\"-\");\n if (dash <= 0) return token;\n const key = token.slice(0, dash);\n const step = Number(token.slice(dash + 1));\n if (key !== fromKey || !STEP_SET.has(step)) return token;\n return `${toKey}-${step as ShadeStep}`;\n}\n\nexport function themeColorKeys(doc: ThemeDoc | null | undefined): string[] {\n const custom = asLibraryRows(doc?.colors?.library)\n .map((row) => row.key?.trim())\n .filter((key): key is string => Boolean(key));\n return [...SYSTEM_COLOR_KEYS, ...custom];\n}\n\n/**\n * Remove a custom color. Unused: omit `replacement` and the row is gone.\n * In use: pass another system or custom key; the caller rewrites page\n * tokens with `rewriteColorToken`. After this, no library row still\n * has `key`.\n */\nexport function deleteLibraryColor(doc: ThemeDoc, key: string, replacement?: string): ThemeDoc {\n const library = [...asLibraryRows(doc.colors?.library)];\n const index = library.findIndex((row) => row.key === key);\n if (index === -1) {\n throw new Error(`No custom color named ${JSON.stringify(key)}`);\n }\n library.splice(index, 1);\n const next: ThemeDoc = {\n ...doc,\n colors: { ...doc.colors, library },\n };\n if (replacement !== undefined) {\n if (replacement === key) {\n throw new Error(\"Replacement must be a different color\");\n }\n if (!themeColorKeys(next).includes(replacement)) {\n throw new Error(`Replacement ${JSON.stringify(replacement)} is not a system or remaining custom color`);\n }\n }\n return next;\n}\n","import { findColorTokens, rewriteColorTokens } from \"./color-tokens\";\nimport { pageEditorLooks } from \"./looks\";\nimport { THEME_SLUG, type ThemeDoc } from \"./types\";\n\n/** Theme-store REST path. LibraryField calls `/api/globals/theme` + this. */\nexport const COLOR_USAGES_PATH = \"/color-usages\";\n\nexport interface ColorUsagesList {\n collections?: string[];\n globals?: string[];\n}\n\n/**\n * `true` scans every registered collection and global at request time\n * (Payload internals and Theme itself are skipped). A list still names\n * slugs. Omit or pass empty: every additional color is unused.\n */\nexport type ColorUsagesOption = true | ColorUsagesList;\n\nexport interface ColorUsage {\n collection?: string;\n global?: string;\n id?: string | number;\n path: string;\n token: string;\n}\n\ntype FindResult = { docs: Record<string, unknown>[]; totalPages?: number; page?: number };\n\ntype Slugged = { slug?: string };\n\nexport interface ColorUsagePayload {\n find: (args: {\n collection: string;\n draft?: boolean;\n depth?: number;\n limit?: number;\n page?: number;\n overrideAccess?: boolean;\n }) => Promise<FindResult>;\n findGlobal: (args: {\n slug: string;\n draft?: boolean;\n depth?: number;\n overrideAccess?: boolean;\n }) => Promise<Record<string, unknown> | ThemeDoc | null | undefined>;\n update: (args: {\n collection: string;\n id: string | number;\n data: Record<string, unknown>;\n draft?: boolean;\n overrideAccess?: boolean;\n }) => Promise<unknown>;\n updateGlobal: (args: {\n slug: string;\n data: Record<string, unknown>;\n draft?: boolean;\n overrideAccess?: boolean;\n }) => Promise<unknown>;\n collections?: Record<string, unknown>;\n globals?: { config?: Slugged[] };\n config?: {\n collections?: Slugged[];\n globals?: Slugged[];\n };\n}\n\n/**\n * Walk every current document in the resolved collections and globals\n * (drafts included). A color only on an unpublished page is still in use.\n */\nexport async function findColorUsages(\n payload: ColorUsagePayload,\n scopes: ColorUsagesOption | undefined,\n key: string,\n): Promise<ColorUsage[]> {\n const { collections, globals } = resolveScopes(payload, scopes);\n const usages: ColorUsage[] = [];\n for (const collection of collections) {\n for await (const doc of eachCollectionDoc(payload, collection)) {\n for (const hit of findColorTokens(doc, key)) {\n usages.push({ collection, id: idOf(doc), path: hit.path, token: hit.token });\n }\n }\n }\n for (const slug of globals) {\n const doc = await readGlobal(payload, slug);\n if (!doc) continue;\n for (const hit of findColorTokens(doc, key)) {\n usages.push({ global: slug, path: hit.path, token: hit.token });\n }\n }\n return usages;\n}\n\nexport async function rewriteColorUsages(\n payload: ColorUsagePayload,\n scopes: ColorUsagesOption | undefined,\n fromKey: string,\n toKey: string,\n): Promise<void> {\n const { collections, globals } = resolveScopes(payload, scopes);\n for (const collection of collections) {\n for await (const doc of eachCollectionDoc(payload, collection)) {\n if (findColorTokens(doc, fromKey).length === 0) continue;\n const { id: _id, ...data } = rewriteColorTokens(doc, fromKey, toKey);\n const id = idOf(doc);\n if (id == null) continue;\n await payload.update({\n collection,\n id,\n data,\n draft: true,\n overrideAccess: true,\n });\n }\n }\n for (const slug of globals) {\n const doc = await readGlobal(payload, slug);\n if (!doc || findColorTokens(doc, fromKey).length === 0) continue;\n await payload.updateGlobal({\n slug,\n data: rewriteColorTokens(doc, fromKey, toKey) as Record<string, unknown>,\n draft: true,\n overrideAccess: true,\n });\n }\n}\n\nexport async function replacementKeys(payload: ColorUsagePayload, except: string): Promise<string[]> {\n const doc = (await payload.findGlobal({\n slug: THEME_SLUG,\n depth: 0,\n overrideAccess: true,\n })) as ThemeDoc | null;\n return pageEditorLooks(doc)\n .map((look) => look.value)\n .filter((key) => key !== except);\n}\n\nexport function resolveScopes(\n payload: ColorUsagePayload,\n scopes: ColorUsagesOption | undefined,\n): ColorUsagesList & { collections: string[]; globals: string[] } {\n if (scopes === true) return registeredScopes(payload);\n return {\n collections: scopes?.collections ?? [],\n globals: scopes?.globals ?? [],\n };\n}\n\nfunction registeredScopes(payload: ColorUsagePayload): { collections: string[]; globals: string[] } {\n return {\n collections: slugsOf(payload.config?.collections ?? payload.collections).filter(\n (slug) => !slug.startsWith(\"payload-\"),\n ),\n globals: slugsOf(payload.config?.globals ?? payload.globals?.config).filter(\n (slug) => slug !== THEME_SLUG,\n ),\n };\n}\n\nfunction slugsOf(value: Slugged[] | Record<string, unknown> | undefined): string[] {\n if (Array.isArray(value)) {\n return value.map((item) => item?.slug).filter((slug): slug is string => Boolean(slug));\n }\n if (value && typeof value === \"object\") return Object.keys(value);\n return [];\n}\n\nasync function readGlobal(\n payload: ColorUsagePayload,\n slug: string,\n): Promise<Record<string, unknown> | ThemeDoc | null | undefined> {\n try {\n return await payload.findGlobal({ slug, draft: true, depth: 0, overrideAccess: true });\n } catch {\n // A named slug that is not registered must not fail Colors Delete.\n return null;\n }\n}\n\nasync function* eachCollectionDoc(\n payload: ColorUsagePayload,\n collection: string,\n): AsyncGenerator<Record<string, unknown>> {\n let page = 1;\n for (;;) {\n let result: FindResult;\n try {\n result = await payload.find({\n collection,\n draft: true,\n depth: 0,\n limit: 100,\n page,\n overrideAccess: true,\n });\n } catch {\n return;\n }\n for (const doc of result.docs) yield doc;\n const totalPages = result.totalPages ?? (result.docs.length < 100 ? page : page + 1);\n if (page >= totalPages || result.docs.length === 0) break;\n page += 1;\n }\n}\n\nfunction idOf(doc: Record<string, unknown>): string | number | undefined {\n const id = doc.id;\n return typeof id === \"string\" || typeof id === \"number\" ? id : undefined;\n}\n","import {\n Dialog,\n Field,\n Input,\n KitProvider,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@bison-lab/admin-ui\";\nimport { useConfig, useField, useForm } from \"@payloadcms/ui\";\nimport { createColorScale, isThemeHex, SHADE_STEPS, type ShadeStep } from \"@bison-lab/tokens\";\nimport type { ArrayFieldClientComponent } from \"payload\";\nimport { useState } from \"react\";\n\nimport { COLOR_USAGES_PATH, type ColorUsage } from \"../theme/color-usages\";\nimport { asLibraryRows, deleteLibraryColor } from \"../theme/library\";\nimport { pageEditorLooks } from \"../theme/looks\";\nimport { colorDocFromState, stateFromColorDoc } from \"../theme/map\";\nimport { type ThemeDoc, type ThemeLibraryColorDoc } from \"../theme/types\";\nimport { BrandHexField } from \"./brand-hex-field\";\nimport { ColorScaleCard, COLOR_SCALE_CARD_CSS } from \"./color-scale-card\";\nimport { ThemePortal } from \"./portal\";\n\nfunction slugify(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\n/**\n * Custom colors: the same scale controls as system colors. Unused: the\n * Theme store's color-usages endpoint returns nothing and the row is\n * gone. In use: pick a live replacement; confirm rewrites stored tokens\n * then drops the row. Success and Destructive stay off that list.\n */\nexport const LibraryField: ArrayFieldClientComponent = ({ field, path, readOnly }) => {\n const dataPath =\n typeof field.admin?.custom?.dataPath === \"string\" ? field.admin.custom.dataPath : path;\n const { value, setValue } = useField<ThemeLibraryColorDoc[] | number>({ path: dataPath, hasRows: true });\n const { getDataByPath } = useForm();\n const { config } = useConfig();\n const rows = asLibraryRows(value).length > 0 ? asLibraryRows(value) : asLibraryRows(getDataByPath?.(dataPath));\n const [adding, setAdding] = useState(false);\n const [name, setName] = useState(\"\");\n const [hex, setHex] = useState(\"\");\n const [sourceStep, setSourceStep] = useState<ShadeStep>(500);\n const [replacing, setReplacing] = useState<{ row: ThemeLibraryColorDoc; usages: ColorUsage[] } | null>(\n null,\n );\n const [replacement, setReplacement] = useState(\"\");\n const [busy, setBusy] = useState(false);\n\n function write(next: ThemeLibraryColorDoc[]) {\n setValue(next);\n }\n\n function usagesUrl(key: string) {\n const serverURL = config.serverURL ?? \"\";\n const api = config.routes?.api ?? \"/api\";\n return `${serverURL}${api}/globals/theme${COLOR_USAGES_PATH}?key=${encodeURIComponent(key)}`;\n }\n\n function add() {\n const key = slugify(name);\n if (!key || !isThemeHex(hex) || rows.some((row) => row.key === key)) return;\n write([...rows, { key, label: name.trim(), ...colorDocFromState(createColorScale(hex, sourceStep)) }]);\n setName(\"\");\n setHex(\"\");\n setSourceStep(500);\n setAdding(false);\n }\n\n async function remove(row: ThemeLibraryColorDoc) {\n const key = row.key ?? \"\";\n const response = await fetch(usagesUrl(key), { credentials: \"include\" });\n if (!response.ok) return;\n const body = (await response.json()) as { usages?: ColorUsage[] };\n const usages = body.usages ?? [];\n if (usages.length === 0) {\n const doc: ThemeDoc = { colors: { library: rows } };\n write(deleteLibraryColor(doc, key).colors?.library ?? []);\n return;\n }\n setReplacement(\"\");\n setReplacing({ row, usages });\n }\n\n async function confirmReplace() {\n if (!replacing || !replacement || busy) return;\n const key = replacing.row.key ?? \"\";\n setBusy(true);\n try {\n const response = await fetch(usagesUrl(key), {\n method: \"POST\",\n credentials: \"include\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ key, replacement }),\n });\n if (!response.ok) return;\n const doc: ThemeDoc = { colors: { library: rows } };\n write(deleteLibraryColor(doc, key, replacement).colors?.library ?? []);\n setReplacing(null);\n } finally {\n setBusy(false);\n }\n }\n\n const replacementOptions = replacing\n ? pageEditorLooks({\n colors: { library: rows.filter((row) => row.key !== replacing.row.key) },\n })\n : [];\n\n return (\n <div className=\"field-type bl-library\">\n <style href=\"bl-scale-card\" precedence=\"default\">\n {COLOR_SCALE_CARD_CSS}\n </style>\n <style href=\"bl-library\" precedence=\"default\">\n {CSS}\n </style>\n <div className=\"bl-library__head\">\n <div>\n <h2>Additional colors</h2>\n <p>Add optional named colors for special sections, campaigns, or components.</p>\n </div>\n <button\n type=\"button\"\n disabled={readOnly}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n setAdding(true);\n }}\n >\n Add color\n </button>\n </div>\n {adding ? (\n <ThemePortal>\n <div className=\"bl-theme-dialog\">\n <KitProvider>\n <Dialog\n open\n title=\"New color\"\n onCancel={() => {\n setAdding(false);\n setName(\"\");\n setHex(\"\");\n setSourceStep(500);\n }}\n confirmLabel=\"Create color scale\"\n onConfirm={add}\n confirmDisabled={!slugify(name) || !isThemeHex(hex)}\n >\n <p>Give it a useful name, enter your brand hex, then say which scale step that hex is.</p>\n <Field>\n <Label>Name</Label>\n <Input\n aria-label=\"Name\"\n value={name}\n placeholder=\"e.g. Coral\"\n onChange={(event) => setName(event.target.value)}\n />\n </Field>\n <Field as=\"div\">\n <Label>Brand hex</Label>\n <BrandHexField name=\"Brand\" value={hex} onChange={setHex} picker=\"inline\" />\n </Field>\n <Field as=\"div\">\n <Label>This color is</Label>\n <Select\n value={String(sourceStep)}\n onValueChange={(value) => setSourceStep(Number(value) as ShadeStep)}\n >\n <SelectTrigger aria-label=\"This color is\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SHADE_STEPS.map((step) => (\n <SelectItem key={step} value={String(step)}>\n {step}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </Field>\n </Dialog>\n </KitProvider>\n </div>\n </ThemePortal>\n ) : null}\n {replacing ? (\n <ThemePortal>\n <div\n className=\"bl-library__modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"bl-library-replace-title\"\n onClick={(event) => {\n if (event.target === event.currentTarget && !busy) setReplacing(null);\n }}\n >\n <div className=\"bl-library__panel\">\n <div className=\"bl-library__panel-head\">\n <div>\n <h2 id=\"bl-library-replace-title\">Replace {replacing.row.label ?? replacing.row.key}</h2>\n <p>\n {replacing.usages.length === 1\n ? \"1 document uses this color. Pick a replacement at the same step.\"\n : `${replacing.usages.length} documents use this color. Pick a replacement at the same step.`}\n </p>\n </div>\n <button type=\"button\" onClick={() => setReplacing(null)} aria-label=\"Close\" disabled={busy}>\n ×\n </button>\n </div>\n <ul className=\"bl-library__usages\">\n {replacing.usages.map((usage, index) => (\n <li key={`${usage.collection ?? usage.global}-${usage.id ?? \"\"}-${usage.path}-${index}`}>\n {usage.collection ?? usage.global}\n {usage.id != null ? ` #${usage.id}` : \"\"} · {usage.path} · {usage.token}\n </li>\n ))}\n </ul>\n <label>\n Replacement\n <select value={replacement} onChange={(event) => setReplacement(event.target.value)}>\n <option value=\"\">Select a color…</option>\n {replacementOptions.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </label>\n <div className=\"bl-library__actions\">\n <button type=\"button\" onClick={() => setReplacing(null)} disabled={busy}>\n Cancel\n </button>\n <button type=\"button\" disabled={!replacement || busy} onClick={() => void confirmReplace()}>\n Replace and delete\n </button>\n </div>\n </div>\n </div>\n </ThemePortal>\n ) : null}\n <div className=\"bl-library__list\">\n {rows.map((row, index) => (\n <ColorScaleCard\n key={row.key ?? index}\n id={row.key ?? `custom-${index}`}\n name={row.label ?? row.key ?? \"Color\"}\n hint={row.key ? `Key: ${row.key}` : undefined}\n custom\n state={stateFromColorDoc(row)}\n onChange={(next) => {\n const copy = [...rows];\n copy[index] = { ...row, ...colorDocFromState(next) };\n write(copy);\n }}\n onDelete={readOnly ? undefined : () => void remove(row)}\n readOnly={readOnly}\n />\n ))}\n </div>\n </div>\n );\n};\n\nconst CSS = `\n.bl-library__head{display:flex;justify-content:space-between;gap:1rem;align-items:flex-start;margin-bottom:.85rem}\n.bl-library__head h2{margin:0;font-size:1.1rem}\n.bl-library__head p{margin:.35rem 0 0;font-size:13px;color:color-mix(in srgb,var(--theme-text,#f8fafc) 92%,transparent)}\n.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}\n.bl-library__list{display:grid;gap:.85rem}\n.bl-library__modal{position:fixed;inset:0;z-index:10000;display:grid;place-items:center;padding:1rem;background:rgba(15,23,42,.45)}\n.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)}\n.bl-library__panel-head{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem}\n.bl-library__panel-head button{border:0;background:none;font:inherit;font-size:1.25rem;line-height:1;color:#94a3b8;cursor:pointer}\n.bl-library__panel h2{margin:0}\n.bl-library__panel p{margin:.5rem 0 0;color:#475569;font-size:14px}\n.bl-library__panel label,.bl-library__field{display:flex;flex-direction:column;gap:.4rem;margin-top:1rem;font-size:13px;font-weight:600}\n.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}\n.bl-library__usages{margin:1rem 0 0;padding-left:1.1rem;color:#475569;font-size:13px;font-weight:400}\n.bl-library__usages li{margin:.25rem 0}\n.bl-library__actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:.5rem;margin-top:1rem}\n.bl-library__actions button:last-child{border:0;background:#0f172a;color:#fff;font-weight:600}\n.bl-library__actions button:last-child:disabled{opacity:.4;cursor:not-allowed}\n.bl-theme-dialog .bl-nav-kit__modal{z-index:10000}\n`;\n","import { Badge, KitProvider } from \"@bison-lab/admin-ui\";\nimport type { ReactNode } from \"react\";\n\nexport function FontRoleCard({\n title,\n hint,\n required,\n family,\n preview,\n children,\n}: {\n title: string;\n hint: string;\n required?: boolean;\n family: string;\n preview: \"heading\" | \"body\";\n children?: ReactNode;\n}) {\n return (\n <KitProvider>\n <article className=\"bl-font-role\">\n <header className=\"bl-font-role__head\">\n <div>\n <h3>{title}</h3>\n <p>{hint}</p>\n </div>\n {required ? <Badge>Required</Badge> : null}\n </header>\n {children}\n <div className=\"bl-font-role__preview\">\n <span>Preview</span>\n {preview === \"heading\" ? (\n <p className=\"bl-font-role__heading\" style={{ fontFamily: `\"${family}\"` }}>\n Advancing the work with clarity.\n </p>\n ) : (\n <p className=\"bl-font-role__body\" style={{ fontFamily: `\"${family}\"` }}>\n Clear, comfortable text for longer reading across the site.\n </p>\n )}\n </div>\n </article>\n </KitProvider>\n );\n}\n\nexport function TypographyPairing({\n headingFamily,\n bodyFamily,\n}: {\n headingFamily: string;\n bodyFamily: string;\n}) {\n return (\n <section className=\"bl-pairing\" aria-label=\"Font pairing sample\">\n <header>\n <h2>Pairing sample</h2>\n <p>Heading and body from the approved catalogue. Type scale stays with the library.</p>\n </header>\n <div className=\"bl-pairing__page\">\n <p className=\"bl-pairing__eyebrow\" style={{ fontFamily: `\"${bodyFamily}\"` }}>\n For visitors\n </p>\n <p className=\"bl-pairing__title\" style={{ fontFamily: `\"${headingFamily}\"` }}>\n Stay in motion.\n </p>\n <p className=\"bl-pairing__copy\" style={{ fontFamily: `\"${bodyFamily}\"` }}>\n Heading and body come from the catalogue. This is the pairing, not a full site preview.\n </p>\n <div className=\"bl-pairing__actions\">\n <span className=\"bl-pairing__btn\" style={{ fontFamily: `\"${bodyFamily}\"` }}>\n Primary action\n </span>\n <span className=\"bl-pairing__btn bl-pairing__btn--ghost\" style={{ fontFamily: `\"${bodyFamily}\"` }}>\n Learn more\n </span>\n </div>\n </div>\n </section>\n );\n}\n\nexport const TYPOGRAPHY_PAIRING_CSS = `\n.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)}\n.bl-font-role__head{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem}\n.bl-font-role__head h3{margin:0;font-size:1rem}\n.bl-font-role__head p{margin:.3rem 0 0;font-size:12px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}\n.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))}\n.bl-font-role__preview > span{display:block;margin-bottom:.4rem;font-size:11px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}\n.bl-font-role__heading{margin:0;font-size:1.5rem;line-height:1.2;font-weight:600}\n.bl-font-role__body{margin:0;font-size:1rem;line-height:1.6;color:var(--bl-preview-muted,var(--theme-elevation-600,#475569))}\n.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}\n.bl-pairing > header{padding:1rem 1.15rem;border-bottom:1px solid var(--bl-preview-border,var(--theme-elevation-150,#e2e8f0))}\n.bl-pairing > header h2{margin:0;font-size:1rem}\n.bl-pairing > header p{margin:.3rem 0 0;font-size:12px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}\n.bl-pairing__page{padding:1.35rem 1.4rem 1.5rem;background:var(--bl-preview-bg,transparent)}\n.bl-pairing__eyebrow{margin:0;font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:#7c1fa2}\n.bl-pairing__title{margin:.5rem 0 0;font-size:2rem;line-height:1.1;font-weight:600}\n.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))}\n.bl-pairing__actions{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:1.1rem}\n.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}\n.bl-pairing__btn--ghost{background:#fff;color:#0f172a;border:1px solid #cbd5e1}\n`;\n","import { FieldDescription, FieldError, FieldLabel, useField } from \"@payloadcms/ui\";\nimport { findFont, fontFaceCss, isFontId, type FontId } from \"@bison-lab/fonts\";\nimport type { SelectFieldClientComponent } from \"payload\";\nimport { useEffect, useId, useMemo, useRef, useState } from \"react\";\n\nimport { FONT_ROLE_COPY } from \"../theme/appearance-labels\";\nimport { SAME_AS_BODY } from \"../theme/fields\";\nimport { usePreviewCanvas } from \"./preview-mode\";\nimport { FontRoleCard, TYPOGRAPHY_PAIRING_CSS } from \"./typography-pairing\";\n\ntype Option = { value: string; family: string; hint: string; specimen: boolean };\n\n/**\n * Listbox over the catalogue ids in `admin.custom.ids`. Each option is the\n * family name in that face, with the catalogue hint beneath. Faces load\n * from the site's font route for the selected family, and for every\n * catalogue id once the picker opens.\n */\nexport const FontField: SelectFieldClientComponent = ({ field, path, readOnly }) => {\n const { value, setValue, showError, errorMessage } = useField<string>({ path });\n const custom = (field.admin?.custom ?? {}) as {\n fontsBaseUrl?: string;\n ids?: string[];\n sameAsBody?: boolean;\n };\n const ids = custom.ids ?? [];\n const fontsBaseUrl = custom.fontsBaseUrl ?? \"/fonts\";\n const sameAsBody = Boolean(custom.sameAsBody);\n\n const options = useMemo<Option[]>(() => {\n const fromCatalogue: Option[] = ids.flatMap((id) => {\n const font = findFont(id);\n if (!font) return [];\n return [{ value: font.id, family: font.family, hint: font.hint, specimen: true }];\n });\n if (!sameAsBody) return fromCatalogue;\n return [{ value: SAME_AS_BODY, family: \"Same as body\", hint: \"Use the body family for headings\", specimen: false }, ...fromCatalogue];\n }, [ids, sameAsBody]);\n\n const [open, setOpen] = useState(false);\n const [faces, setFaces] = useState(false);\n const [active, setActive] = useState(-1);\n const [query, setQuery] = useState(\"\");\n const [category, setCategory] = useState<\"all\" | \"sans\" | \"serif\" | \"display\" | \"mono\">(\"all\");\n const typed = useRef(\"\");\n const typedAt = useRef(0);\n const id = useId();\n const buttonId = `${id}-button`;\n const listId = `${id}-list`;\n const required = Boolean(field.required);\n\n useEffect(() => {\n if (open) setFaces(true);\n }, [open]);\n\n const selected = options.find((option) => option.value === (value ?? SAME_AS_BODY)) ?? options[0];\n const visible = options.filter((option) => {\n if (query && !option.family.toLowerCase().includes(query.trim().toLowerCase())) return false;\n if (category === \"all\" || !option.specimen) return true;\n const font = findFont(option.value);\n return font?.category === category;\n });\n const role = sameAsBody ? FONT_ROLE_COPY.heading : FONT_ROLE_COPY.body;\n\n function choose(option: Option) {\n setValue(option.value);\n setOpen(false);\n setActive(-1);\n setQuery(\"\");\n setCategory(\"all\");\n }\n\n function onKeyDown(event: React.KeyboardEvent<HTMLButtonElement>) {\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n if (!open) {\n setOpen(true);\n setActive(0);\n return;\n }\n setActive((i) => (options.length ? (i + 1) % options.length : -1));\n } else if (event.key === \"ArrowUp\") {\n event.preventDefault();\n if (!open) {\n setOpen(true);\n setActive(options.length - 1);\n return;\n }\n setActive((i) => (options.length ? (i <= 0 ? options.length - 1 : i - 1) : -1));\n } else if (event.key === \"Enter\") {\n if (!open) return;\n event.preventDefault();\n const pick = options[active] ?? options[0];\n if (pick) choose(pick);\n } else if (event.key === \"Escape\") {\n if (!open) return;\n event.preventDefault();\n event.stopPropagation();\n setOpen(false);\n setActive(-1);\n } else if (event.key.length === 1 && !event.metaKey && !event.ctrlKey && !event.altKey) {\n const now = Date.now();\n typed.current = now - typedAt.current > 600 ? event.key : typed.current + event.key;\n typedAt.current = now;\n const needle = typed.current.toLowerCase();\n const index = options.findIndex((option) => option.family.toLowerCase().startsWith(needle));\n if (index >= 0) {\n if (!open) setOpen(true);\n setActive(index);\n }\n }\n }\n\n const activeId = active >= 0 && open ? `${id}-option-${active}` : undefined;\n const faceIds = (faces ? ids : isFontId(value) ? [value] : []) as FontId[];\n const canvas = usePreviewCanvas();\n\n return (\n <div className={`field-type bl-font-field ${canvas.className}`} data-preview={canvas.mode} style={canvas.style}>\n <style href=\"bl-pairing\" precedence=\"default\">\n {TYPOGRAPHY_PAIRING_CSS}\n </style>\n <style href=\"bl-font-field\" precedence=\"default\">\n {CSS}\n </style>\n {faceIds.length > 0 ? <style data-bl-font-faces=\"\">{fontFaceCss(faceIds, fontsBaseUrl)}</style> : null}\n <FontRoleCard\n title={typeof field.label === \"string\" ? field.label : role.label}\n hint={role.hint}\n required={required}\n family={selected?.family ?? \"Inter\"}\n preview={sameAsBody ? \"heading\" : \"body\"}\n >\n <FieldLabel htmlFor={buttonId} label={field.label} required={required} />\n <button\n id={buttonId}\n type=\"button\"\n className=\"bl-font-field__trigger\"\n disabled={readOnly}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-controls={listId}\n aria-activedescendant={activeId}\n onClick={() => setOpen((was) => !was)}\n onKeyDown={onKeyDown}\n >\n <span>\n <span className=\"bl-font-field__selected-label\">Selected</span>\n <span\n className=\"bl-font-field__selected-name\"\n style={selected?.specimen ? { fontFamily: `\"${selected.family}\"` } : undefined}\n >\n {selected?.family ?? \"Choose a font\"}\n </span>\n </span>\n <span aria-hidden=\"true\">⌄</span>\n </button>\n </FontRoleCard>\n {open ? (\n <div\n className=\"bl-font-field__modal\"\n onClick={(event) => {\n if (event.target === event.currentTarget) setOpen(false);\n }}\n >\n <div className=\"bl-font-field__panel\">\n <div className=\"bl-font-field__panel-head\">\n <div>\n <p>Choose a font</p>\n <h2>{role.label}</h2>\n </div>\n <button type=\"button\" onClick={() => setOpen(false)} aria-label=\"Close\">\n ×\n </button>\n </div>\n <input\n type=\"search\"\n className=\"bl-font-field__search\"\n placeholder=\"Search fonts…\"\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n />\n <div className=\"bl-font-field__filters\">\n {([\"all\", \"sans\", \"serif\", \"display\", \"mono\"] as const).map((item) => (\n <button\n key={item}\n type=\"button\"\n data-on={category === item ? \"\" : undefined}\n onClick={() => setCategory(item)}\n >\n {item === \"all\" ? \"All\" : item === \"sans\" ? \"Sans serif\" : item === \"serif\" ? \"Serif\" : item === \"display\" ? \"Display\" : \"Mono\"}\n </button>\n ))}\n </div>\n <ul id={listId} role=\"listbox\" className=\"bl-font-field__menu\">\n {visible.map((option, i) => (\n <li\n key={option.value || \"same\"}\n id={`${id}-option-${i}`}\n role=\"option\"\n aria-selected={option.value === (value ?? SAME_AS_BODY)}\n className=\"bl-font-field__option\"\n onMouseDown={(event) => {\n event.preventDefault();\n choose(option);\n }}\n onMouseEnter={() => setActive(i)}\n >\n <span\n className=\"bl-font-field__family\"\n style={option.specimen ? { fontFamily: `\"${option.family}\"` } : undefined}\n >\n {option.family}\n </span>\n <span className=\"bl-font-field__hint\">{option.hint}</span>\n <span\n className=\"bl-font-field__specimen\"\n style={option.specimen ? { fontFamily: `\"${option.family}\"` } : undefined}\n >\n The quick brown fox jumps over the lazy dog.\n </span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n ) : null}\n <FieldDescription description={field.admin?.description} path={path} />\n <FieldError path={path} showError={showError} message={errorMessage} />\n </div>\n );\n};\n\nconst CSS = `\n.bl-font-field{margin-bottom:1rem}\n.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}\n.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}\n.bl-font-field__trigger:focus{border-color:var(--theme-elevation-400,#94a3b8);outline:none;box-shadow:0 0 0 1px var(--theme-elevation-400,#94a3b8)}\n.bl-font-field__trigger:disabled{color:var(--theme-elevation-400,#94a3b8);cursor:not-allowed}\n.bl-font-field__selected-label{display:block;font-size:11px;color:var(--theme-elevation-500,#64748b)}\n.bl-font-field__selected-name{display:block;margin-top:.15rem;font-weight:600}\n.bl-font-field__modal{position:fixed;inset:0;z-index:10000;display:grid;place-items:center;padding:1rem;background:rgba(15,23,42,.45)}\n.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}\n.bl-font-field__panel-head{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem}\n.bl-font-field__panel-head p{margin:0;font-size:12px;color:#64748b}\n.bl-font-field__panel-head h2{margin:.2rem 0 0;font-size:1.15rem}\n.bl-font-field__panel-head button{border:0;background:none;font:inherit;font-size:1.25rem;color:#64748b;cursor:pointer}\n.bl-font-field__search{margin-top:.9rem;min-height:2.5rem;padding:.5rem .75rem;border:1px solid #cbd5e1;border-radius:10px;font:inherit}\n.bl-font-field__filters{display:flex;flex-wrap:wrap;gap:.4rem;margin-top:.75rem}\n.bl-font-field__filters button{min-height:1.8rem;padding:.2rem .7rem;border:0;border-radius:999px;background:#f1f5f9;color:#475569;font:inherit;font-size:12px;cursor:pointer}\n.bl-font-field__filters button[data-on]{background:#0f172a;color:#fff}\n.bl-font-field__menu{margin:.75rem 0 0;padding:0;list-style:none;overflow:auto;max-height:18rem}\n.bl-font-field__option{display:flex;flex-direction:column;gap:2px;margin-bottom:.5rem;padding:.75rem .85rem;border:1px solid #e2e8f0;border-radius:12px;cursor:pointer}\n.bl-font-field__option[aria-selected=\"true\"]{border-color:#7c1fa2;background:#f5f3ff}\n.bl-font-field__family{font-weight:600}\n.bl-font-field__hint{color:#64748b;font-size:12px}\n.bl-font-field__specimen{margin-top:.45rem;font-size:1.25rem;line-height:1.3}\n`;\n","import { useFormFields } from \"@payloadcms/ui\";\nimport { findFont, fontFaceCss, type FontId } from \"@bison-lab/fonts\";\nimport type { UIFieldClientComponent } from \"payload\";\n\nimport { SAME_AS_BODY } from \"../theme/fields\";\nimport { usePreviewCanvas } from \"./preview-mode\";\nimport { TypographyPairing, TYPOGRAPHY_PAIRING_CSS } from \"./typography-pairing\";\n\n/**\n * Pairing sample only — no weight, letter-spacing, line-height, or health\n * scores. Faces load from the site's font route.\n */\nexport const PairingField: UIFieldClientComponent = ({ field }) => {\n const custom = (field.admin?.custom ?? {}) as { fontsBaseUrl?: string };\n const fontsBaseUrl = custom.fontsBaseUrl ?? \"/fonts\";\n const { body, heading } = useFormFields(([fields]) => {\n const record = fields as Record<string, { value?: unknown } | undefined>;\n return {\n body: String(record[\"typography.body\"]?.value ?? \"\"),\n heading: String(record[\"typography.heading\"]?.value ?? SAME_AS_BODY),\n };\n });\n const headingId = heading || body;\n const bodyFont = findFont(body);\n const headingFont = findFont(headingId);\n const ids = [body, headingId].filter(Boolean) as FontId[];\n const canvas = usePreviewCanvas();\n\n return (\n <div className={`field-type bl-pairing-field ${canvas.className}`} data-preview={canvas.mode} style={canvas.style}>\n <style href=\"bl-pairing\" precedence=\"default\">\n {TYPOGRAPHY_PAIRING_CSS}\n </style>\n {ids.length > 0 ? <style data-bl-font-faces=\"\">{fontFaceCss(ids, fontsBaseUrl)}</style> : null}\n <TypographyPairing\n headingFamily={headingFont?.family ?? \"Georgia\"}\n bodyFamily={bodyFont?.family ?? \"system-ui\"}\n />\n </div>\n );\n};\n","import { APPEARANCE_CHOICES, APPEARANCE_FAMILY_COPY } from \"../theme/appearance-labels\";\n\ntype Family = keyof typeof APPEARANCE_CHOICES;\n\nfunction ChoicePreview({ family, value }: { family: Family; value: string }) {\n return (\n <div className=\"bl-appearance__preview\" data-family={family} data-value={value} aria-hidden=\"true\">\n {family === \"defaultTheme\" && value === \"system\" ? (\n <>\n <div className=\"bl-appearance__pane bl-appearance__pane--light\">\n <i />\n <b />\n </div>\n <div className=\"bl-appearance__pane bl-appearance__pane--dark\">\n <i />\n <b />\n </div>\n </>\n ) : family === \"motion\" ? (\n <span className=\"bl-appearance__dot\" />\n ) : family === \"shadow\" ? (\n <div className=\"bl-appearance__lift\" />\n ) : family === \"radius\" ? (\n <>\n <b>Button</b>\n <i className=\"bl-appearance__input\" />\n <i className=\"bl-appearance__card\" />\n </>\n ) : family === \"density\" ? (\n <>\n <b />\n <i className=\"bl-appearance__input\" />\n <i className=\"bl-appearance__card\" />\n </>\n ) : (\n <>\n <i />\n <i />\n <b />\n </>\n )}\n </div>\n );\n}\n\nexport function AppearanceChoices({\n values,\n onChange,\n readOnly,\n}: {\n values: Record<Family, string>;\n onChange: (name: Family, value: string) => void;\n readOnly?: boolean;\n}) {\n return (\n <div className=\"bl-appearance\">\n <header className=\"bl-appearance__intro\">\n <h2>Set the overall feel of your site</h2>\n <p>\n Choose how rounded, elevated, animated, and spacious the interface feels. You don’t manage the\n technical values — the system handles those.\n </p>\n </header>\n {(Object.keys(APPEARANCE_CHOICES) as Family[]).map((family) => {\n const choices = APPEARANCE_CHOICES[family];\n const copy = APPEARANCE_FAMILY_COPY[family];\n return (\n <fieldset key={family} className=\"bl-appearance__family\">\n <legend>\n <strong>{copy.title}</strong>\n <span>{copy.hint}</span>\n </legend>\n <div className=\"bl-appearance__choices\" data-family={family}>\n {Object.entries(choices).map(([value, item]) => {\n const selected = values[family] === value;\n return (\n <label\n key={value}\n className=\"bl-appearance__choice\"\n data-selected={selected ? \"\" : undefined}\n >\n <input\n type=\"radio\"\n name={family}\n value={value}\n checked={selected}\n disabled={readOnly}\n onChange={() => onChange(family, value)}\n />\n <ChoicePreview family={family} value={value} />\n <span className=\"bl-appearance__copy\">\n <strong>\n {item.label}\n {selected ? <em aria-hidden=\"true\">✓</em> : null}\n </strong>\n <span>{item.hint}</span>\n </span>\n </label>\n );\n })}\n </div>\n {family === \"motion\" ? (\n <p className=\"bl-appearance__note\">\n Visitors who prefer reduced motion will still see fewer animations automatically.\n </p>\n ) : null}\n </fieldset>\n );\n })}\n </div>\n );\n}\n\nexport const APPEARANCE_CHOICES_CSS = `\n.bl-appearance{display:flex;flex-direction:column;gap:1.25rem;color:var(--bl-preview-text,inherit)}\n.bl-appearance__intro h2{margin:0;font-size:1.1rem}\n.bl-appearance__intro p{margin:.35rem 0 0;font-size:13px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b));max-width:40rem}\n.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))}\n.bl-appearance__family legend{padding:0;margin-bottom:.85rem}\n.bl-appearance__family legend strong{display:block;font-size:14px}\n.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}\n.bl-appearance__choices{display:grid;gap:.6rem}\n.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))}\n.bl-appearance__choices[data-family=radius]{grid-template-columns:repeat(4,minmax(0,1fr))}\n.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}\n.bl-appearance__choice[data-selected]{box-shadow:inset 0 0 0 2px var(--bl-preview-text,#0f172a);border-color:var(--bl-preview-text,#0f172a)}\n.bl-appearance__choice input{position:absolute;opacity:0;pointer-events:none}\n.bl-appearance__copy{display:flex;flex-direction:column;gap:.2rem}\n.bl-appearance__copy strong{display:flex;justify-content:space-between;align-items:center;gap:.4rem;font-size:14px}\n.bl-appearance__copy em{font-style:normal}\n.bl-appearance__copy span{font-size:12px;color:var(--theme-elevation-500,#64748b)}\n.bl-appearance__note{margin:.75rem 0 0;font-size:12px;color:var(--theme-elevation-500,#64748b)}\n.bl-appearance__preview{--bl-preview-brand:#db0082;--bl-preview-radius:8px;border-radius:10px;background:#f8fafc;overflow:hidden}\n.bl-appearance__preview[data-family=defaultTheme]{display:grid;min-height:5.5rem;padding:.65rem}\n.bl-appearance__preview[data-family=defaultTheme][data-value=system]{grid-template-columns:1fr 1fr;padding:0}\n.bl-appearance__preview[data-family=defaultTheme][data-value=dark]{background:#020617}\n.bl-appearance__pane{display:flex;flex-direction:column;gap:.45rem;padding:.65rem}\n.bl-appearance__pane--dark{background:#020617}\n.bl-appearance__pane i,.bl-appearance__preview[data-family=defaultTheme] > i{display:block;height:.4rem;width:42%;border-radius:99px;background:#0f172a}\n.bl-appearance__pane i + i,.bl-appearance__preview[data-family=defaultTheme] > i + i{width:64%;background:#cbd5e1}\n.bl-appearance__pane--dark i{background:#fff}\n.bl-appearance__pane--dark i + i{background:#334155}\n.bl-appearance__preview[data-family=defaultTheme][data-value=dark] > i{background:#fff}\n.bl-appearance__preview[data-family=defaultTheme][data-value=dark] > i + i{background:#334155}\n.bl-appearance__pane b,.bl-appearance__preview[data-family=defaultTheme] > b{display:block;height:1.6rem;margin-top:auto;border-radius:6px;background:var(--bl-preview-brand)}\n.bl-appearance__pane--dark b{background:var(--bl-preview-brand)}\n.bl-appearance__preview[data-family=radius]{display:flex;flex-direction:column;gap:.45rem;padding:.65rem;background:#fff}\n.bl-appearance__preview[data-family=radius] b{display:grid;place-items:center;height:1.85rem;background:var(--bl-preview-brand);color:#fff;font-size:10px;font-weight:600;border-radius:var(--bl-preview-radius)}\n.bl-appearance__input{display:block;height:1.85rem;border:1px solid #cbd5e1;background:#f8fafc;border-radius:var(--bl-preview-radius)}\n.bl-appearance__card{display:block;height:2.4rem;border:1px solid #e2e8f0;background:#fff;border-radius:var(--bl-preview-radius)}\n.bl-appearance__preview[data-value=sharp]{--bl-preview-radius:0}\n.bl-appearance__preview[data-value=subtle]{--bl-preview-radius:6px}\n.bl-appearance__preview[data-value=rounded]{--bl-preview-radius:12px}\n.bl-appearance__preview[data-value=pill]{--bl-preview-radius:999px}\n.bl-appearance__preview[data-value=pill] .bl-appearance__card{--bl-preview-radius:1.25rem}\n.bl-appearance__preview[data-family=shadow]{display:grid;place-items:center;min-height:6.5rem;padding:.85rem}\n.bl-appearance__lift{width:100%;height:3.5rem;border-radius:10px;background:#fff}\n.bl-appearance__preview[data-value=flat] .bl-appearance__lift{border:1px solid #e2e8f0}\n.bl-appearance__preview[data-value=subtle] .bl-appearance__lift{box-shadow:0 1px 2px rgba(15,23,42,.06),0 4px 12px rgba(15,23,42,.06)}\n.bl-appearance__preview[data-value=elevated] .bl-appearance__lift{box-shadow:0 10px 30px rgba(15,23,42,.12)}\n.bl-appearance__preview[data-family=motion]{display:flex;align-items:center;min-height:4.5rem;padding:0 .85rem}\n.bl-appearance__dot{width:1.15rem;height:1.15rem;border-radius:999px;background:var(--bl-preview-brand);animation:bl-appear-dot 1.8s ease-in-out infinite}\n.bl-appearance__preview[data-value=snappy] .bl-appearance__dot{animation-duration:1s}\n.bl-appearance__preview[data-value=minimal] .bl-appearance__dot{animation-duration:2.5s}\n@keyframes bl-appear-dot{0%,100%{transform:translateX(0)}50%{transform:translateX(4.5rem)}}\n.bl-appearance__preview[data-family=density]{display:flex;flex-direction:column;background:#f8fafc}\n.bl-appearance__preview[data-value=compact]{gap:.4rem;padding:.55rem}\n.bl-appearance__preview[data-value=default]{gap:.65rem;padding:.8rem}\n.bl-appearance__preview[data-value=spacious]{gap:.9rem;padding:1.05rem}\n.bl-appearance__preview[data-family=density] b{display:block;height:1.7rem;background:var(--bl-preview-brand);border-radius:6px}\n.bl-appearance__preview[data-value=compact] b,.bl-appearance__preview[data-value=compact] .bl-appearance__input{height:1.45rem}\n.bl-appearance__preview[data-value=spacious] b,.bl-appearance__preview[data-value=spacious] .bl-appearance__input{height:2.1rem}\n@media (max-width:720px){\n .bl-appearance__choices[data-family=defaultTheme],.bl-appearance__choices[data-family=shadow],.bl-appearance__choices[data-family=motion],.bl-appearance__choices[data-family=density],.bl-appearance__choices[data-family=radius]{grid-template-columns:1fr}\n}\n@media (prefers-reduced-motion:reduce){\n .bl-appearance__dot{animation:none}\n}\n`;\n","import { useField } from \"@payloadcms/ui\";\nimport type { GroupFieldClientComponent } from \"payload\";\n\nimport { APPEARANCE_CHOICES } from \"../theme/appearance-labels\";\nimport { AppearanceChoices, APPEARANCE_CHOICES_CSS } from \"./appearance-choices\";\nimport { usePreviewCanvas } from \"./preview-mode\";\n\ntype Family = keyof typeof APPEARANCE_CHOICES;\n\n/**\n * Named appearance choices. Soft → pill, Gentle → minimal, Balanced →\n * default, Follow device → system. No rem or ms.\n */\nexport const AppearanceField: GroupFieldClientComponent = ({ path, readOnly }) => {\n const defaultTheme = useField<string>({ path: `${path}.defaultTheme` });\n const radius = useField<string>({ path: `${path}.radius` });\n const shadow = useField<string>({ path: `${path}.shadow` });\n const motion = useField<string>({ path: `${path}.motion` });\n const density = useField<string>({ path: `${path}.density` });\n const fields = { defaultTheme, radius, shadow, motion, density };\n const canvas = usePreviewCanvas();\n\n function onChange(name: Family, value: string) {\n fields[name].setValue(value);\n }\n\n return (\n <div className={`field-type bl-appearance-field ${canvas.className}`} data-preview={canvas.mode} style={canvas.style}>\n <style href=\"bl-appearance\" precedence=\"default\">\n {APPEARANCE_CHOICES_CSS}\n </style>\n <AppearanceChoices\n values={{\n defaultTheme: defaultTheme.value ?? \"system\",\n radius: radius.value ?? \"rounded\",\n shadow: shadow.value ?? \"subtle\",\n motion: motion.value ?? \"smooth\",\n density: density.value ?? \"default\",\n }}\n onChange={onChange}\n readOnly={readOnly}\n />\n </div>\n );\n};\n","import { Badge, KitProvider } from \"@bison-lab/admin-ui\";\nimport { GREY_SCALES, presetHints, type GreyScale } from \"@bison-lab/tokens\";\nimport { useField } from \"@payloadcms/ui\";\nimport type { SelectFieldClientComponent } from \"payload\";\n\nimport { usePreviewCanvas } from \"./preview-mode\";\n\nconst FAMILIES = Object.keys(presetHints.greyScale) as GreyScale[];\nconst SWATCHES = [\"50\", \"200\", \"400\", \"700\", \"950\"] as const;\n\nexport function GreyScaleChoices({\n value,\n onChange,\n readOnly,\n}: {\n value: GreyScale;\n onChange: (next: GreyScale) => void;\n readOnly?: boolean;\n}) {\n const canvas = usePreviewCanvas();\n return (\n <KitProvider>\n <section className={`bl-grey ${canvas.className}`} data-preview={canvas.mode} style={canvas.style}>\n <div className=\"bl-grey__section\">\n <h2>Neutrals</h2>\n <p>Choose the gray family used for backgrounds, borders, cards, inputs, and muted text.</p>\n </div>\n <header className=\"bl-grey__head\">\n <div>\n <h2>Gray family</h2>\n <p>Choose the neutral family used for page backgrounds, cards, borders, inputs, and muted text. Readability for these system neutrals is handled automatically.</p>\n </div>\n <Badge>Required</Badge>\n </header>\n <div className=\"bl-grey__choices\">\n {FAMILIES.map((id) => {\n const copy = presetHints.greyScale[id];\n const selected = value === id;\n return (\n <label key={id} className=\"bl-grey__choice\" data-selected={selected ? \"\" : undefined}>\n <input\n type=\"radio\"\n name=\"greyScale\"\n value={id}\n checked={selected}\n disabled={readOnly}\n onChange={() => onChange(id)}\n />\n <span className=\"bl-grey__ramp\" aria-hidden=\"true\">\n {SWATCHES.map((step) => (\n <i key={step} style={{ background: `hsl(${GREY_SCALES[id][step]})` }} />\n ))}\n </span>\n <strong>\n {copy.label}\n {selected ? <em aria-hidden=\"true\">✓</em> : null}\n </strong>\n <span>{copy.hint}</span>\n </label>\n );\n })}\n </div>\n </section>\n </KitProvider>\n );\n}\n\n/**\n * Visual picker over the five grey-scale presets. Replaces the stock select\n * on Colors; the stored value is still `colors.greyScale`.\n */\nexport const GreyScaleField: SelectFieldClientComponent = ({ field, path, readOnly }) => {\n const dataPath =\n typeof field.admin?.custom?.dataPath === \"string\" ? field.admin.custom.dataPath : path;\n const { value, setValue } = useField<GreyScale>({ path: dataPath });\n\n return (\n <div className=\"field-type bl-grey-field\">\n <style href=\"bl-grey\" precedence=\"default\">\n {GREY_SCALE_FIELD_CSS}\n </style>\n <GreyScaleChoices value={value ?? \"slate\"} onChange={setValue} readOnly={readOnly} />\n </div>\n );\n};\n\nexport const GREY_SCALE_FIELD_CSS = `\n.bl-grey{margin:0 0 1.75rem}\n.bl-grey__section{margin:1.25rem 0 .85rem}\n.bl-grey__section h2{margin:0;font-size:1.1rem}\n.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)}\n.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)}\n.bl-grey__head h2{margin:0;font-size:1.1rem}\n.bl-grey__head p{margin:.35rem 0 0;max-width:40rem;font-size:13px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}\n.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)}\n.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}\n.bl-grey__choice[data-selected]{box-shadow:inset 0 0 0 2px var(--bl-preview-text,#0f172a);border-color:var(--bl-preview-text,#0f172a)}\n.bl-grey__choice input{position:absolute;opacity:0;pointer-events:none}\n.bl-grey__ramp{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:3px}\n.bl-grey__ramp i{display:block;height:2rem;border-radius:6px}\n.bl-grey__choice strong{display:flex;justify-content:space-between;align-items:center;gap:.4rem;font-size:14px}\n.bl-grey__choice em{font-style:normal}\n.bl-grey__choice > span{font-size:12px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}\n@media (max-width:720px){.bl-grey__choices{grid-template-columns:1fr}}\n`;\n","import { useFormFields } from \"@payloadcms/ui\";\nimport { isThemeHex } from \"@bison-lab/tokens\";\nimport type { UIFieldClientComponent } from \"payload\";\nimport { useRef } from \"react\";\n\nimport { SYSTEM_COLOR_COPY } from \"../theme/appearance-labels\";\nimport { fillLabelWarning, READABILITY_TARGET, type FillLabelWarning } from \"../theme/readability\";\nimport { SYSTEM_COLOR_KEYS } from \"../theme/types\";\nimport { THEME_COLORS_LAYOUT_CSS } from \"./colors-layout\";\nimport { ReadabilityList, READABILITY_LIST_CSS } from \"./readability-list\";\n\nfunction hexAt(fields: Record<string, { value?: unknown } | undefined>, path: string): string {\n const value = fields[path]?.value;\n return typeof value === \"string\" ? value : \"\";\n}\n\n/**\n * Fill + automatic label only. Target 7:1, Light and Dark. No gray\n * ContrastStrip. Warnings do not block save.\n */\nexport const ContrastReport: UIFieldClientComponent = ({ field }) => {\n const target = Number((field.admin?.custom as { target?: number } | undefined)?.target) || READABILITY_TARGET;\n const hexes = useFormFields(([fields]) => {\n const record = fields as Record<string, { value?: unknown } | undefined>;\n const system = Object.fromEntries(\n SYSTEM_COLOR_KEYS.map((key) => [key, hexAt(record, `colors.brand.${key}.hex`)]),\n ) as Record<(typeof SYSTEM_COLOR_KEYS)[number], string>;\n const library = record[\"colors.library\"]?.value;\n const custom = Array.isArray(library)\n ? library.flatMap((row, index) => {\n const hex = typeof row === \"object\" && row && \"hex\" in row ? String(row.hex ?? \"\") : \"\";\n const name =\n typeof row === \"object\" && row && \"label\" in row ? String(row.label ?? row.key ?? \"Custom\") : \"Custom\";\n return hex ? [{ id: `library-${index}`, name, hex }] : [];\n })\n : [];\n return { system, custom };\n });\n\n const last = useRef<FillLabelWarning[] | null>(null);\n const complete = SYSTEM_COLOR_KEYS.every((key) => isThemeHex(hexes.system[key]));\n if (complete) {\n last.current = [\n ...SYSTEM_COLOR_KEYS.map((key) =>\n fillLabelWarning(key, SYSTEM_COLOR_COPY[key].label, hexes.system[key], target),\n ),\n ...hexes.custom.map((row) => fillLabelWarning(row.id, row.name, row.hex, target)),\n ].filter((item): item is FillLabelWarning => item !== null);\n }\n\n const warnings = last.current ?? [];\n const stale = Boolean(last.current) && !complete;\n\n return (\n <div className=\"field-type bl-contrast-report\">\n <style href=\"bl-readability\" precedence=\"default\">\n {READABILITY_LIST_CSS}\n </style>\n <style href=\"bl-theme-colors-layout\" precedence=\"default\">\n {THEME_COLORS_LAYOUT_CSS}\n </style>\n {stale ? (\n <p className=\"bl-contrast-report__stale\">Showing the last complete audit while a colour is being typed.</p>\n ) : null}\n {warnings.length > 0 ? <ReadabilityList warnings={warnings} target={target} /> : (\n <p>Enter hex colours to measure the automatic label on each fill.</p>\n )}\n </div>\n );\n};\n","import type { UIFieldClientComponent } from \"payload\";\n\nimport { THEME_COLORS_LAYOUT_CSS } from \"./colors-layout\";\n\n/**\n * Unnamed UI heading between Theme fields. No document path.\n */\nexport const SectionHeading: UIFieldClientComponent = ({ field }) => {\n const custom = (field.admin?.custom ?? {}) as { title?: string; hint?: string };\n if (!custom.title) return null;\n return (\n <header className=\"bl-section-heading\">\n <style href=\"bl-section-heading\" precedence=\"default\">\n {CSS}\n </style>\n <style href=\"bl-theme-colors-layout\" precedence=\"default\">\n {THEME_COLORS_LAYOUT_CSS}\n </style>\n <h2>{custom.title}</h2>\n {custom.hint ? <p>{custom.hint}</p> : null}\n </header>\n );\n};\n\nconst CSS = `\n.bl-section-heading{margin:1.25rem 0 .65rem}\n.bl-section-heading:first-child{margin-top:0}\n.bl-section-heading h2{margin:0;font-size:1.1rem}\n.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}\n`;\n","import { SYSTEM_COLOR_KEYS, type ThemeDoc, type ThemeLibraryColorDoc } from \"./types\";\nimport type { ThemeChild } from \"./publish\";\n\n/** Payload may hand an empty array field as `{}`. `.map` on that crashes the Theme form. */\nexport function libraryRows(value: unknown): ThemeLibraryColorDoc[] {\n return Array.isArray(value) ? value : [];\n}\n\nfunction colorLine(name: string, before: unknown, after: unknown): string | null {\n const a = before && typeof before === \"object\" ? before : { hex: before };\n const b = after && typeof after === \"object\" ? after : { hex: after };\n const left = a as { hex?: unknown; sourceStep?: unknown };\n const right = b as { hex?: unknown; sourceStep?: unknown };\n if (left.hex === right.hex && String(left.sourceStep) === String(right.sourceStep)) return null;\n return `${name}: ${String(left.hex ?? \"—\")} → ${String(right.hex ?? \"—\")}`;\n}\n\n/**\n * Human lines for the Publish confirmation. Only this child's\n * differences; other responsibilities are not listed.\n */\nexport function themeChildChanges(child: ThemeChild, published: ThemeDoc, incoming: ThemeDoc): string[] {\n if (child === \"colors\") {\n const lines: string[] = [];\n for (const key of SYSTEM_COLOR_KEYS) {\n const line = colorLine(\n key[0].toUpperCase() + key.slice(1),\n published.colors?.brand?.[key],\n incoming.colors?.brand?.[key],\n );\n if (line) lines.push(line);\n }\n const beforeKeys = libraryRows(published.colors?.library)\n .map((row) => row.key)\n .join(\", \");\n const afterKeys = libraryRows(incoming.colors?.library)\n .map((row) => row.key)\n .join(\", \");\n if (beforeKeys !== afterKeys) lines.push(`Custom colors: ${beforeKeys || \"none\"} → ${afterKeys || \"none\"}`);\n if ((published.colors?.greyScale ?? \"\") !== (incoming.colors?.greyScale ?? \"\")) {\n lines.push(`Gray family: ${published.colors?.greyScale ?? \"—\"} → ${incoming.colors?.greyScale ?? \"—\"}`);\n }\n return lines;\n }\n if (child === \"typography\") {\n const lines: string[] = [];\n if ((published.typography?.heading ?? \"\") !== (incoming.typography?.heading ?? \"\")) {\n lines.push(`Heading: ${published.typography?.heading || \"same as body\"} → ${incoming.typography?.heading || \"same as body\"}`);\n }\n if ((published.typography?.body ?? \"\") !== (incoming.typography?.body ?? \"\")) {\n lines.push(`Body: ${published.typography?.body ?? \"—\"} → ${incoming.typography?.body ?? \"—\"}`);\n }\n return lines;\n }\n if (child === \"appearance\") {\n const keys = [\"defaultTheme\", \"radius\", \"shadow\", \"motion\", \"density\"] as const;\n return keys.flatMap((key) => {\n const left = published.appearance?.[key] ?? \"\";\n const right = incoming.appearance?.[key] ?? \"\";\n return left === right ? [] : [`${key}: ${left || \"—\"} → ${right || \"—\"}`];\n });\n }\n const lines: string[] = [];\n if (uploadId(published.logo) !== uploadId(incoming.logo)) lines.push(\"Logo updated\");\n if (uploadId(published.favicon) !== uploadId(incoming.favicon)) lines.push(\"Favicon updated\");\n if (uploadId(published.logoMark) !== uploadId(incoming.logoMark)) lines.push(\"Mobile menu logo updated\");\n return lines;\n}\n\nfunction uploadId(value: ThemeDoc[\"logo\"]): string {\n if (value && typeof value === \"object\" && value.id != null) return String(value.id);\n if (typeof value === \"string\" || typeof value === \"number\") return String(value);\n return \"\";\n}\n","import { THEME_SLUG, type ThemeColorDoc, type ThemeDoc } from \"./types\";\n\nexport const THEME_CHILDREN = [\"colors\", \"typography\", \"appearance\", \"identity\"] as const;\n\nexport type ThemeChild = (typeof THEME_CHILDREN)[number];\n\n/**\n * Publishing a child writes that slice only. Other responsibilities stay\n * as they already are on the stored document. Unsaved form state on a\n * different child never goes live. A first save (no stored row) still\n * writes only the named child; `getPublishedTheme` fills the rest from\n * the seed.\n */\nexport function publishThemeChild(stored: ThemeDoc, incoming: ThemeDoc, child: ThemeChild): ThemeDoc {\n if (child === \"colors\") return { ...stored, colors: incoming.colors };\n if (child === \"typography\") return { ...stored, typography: incoming.typography };\n if (child === \"appearance\") return { ...stored, appearance: incoming.appearance };\n return { ...stored, logo: incoming.logo, favicon: incoming.favicon, logoMark: incoming.logoMark };\n}\n\nexport function isThemeChild(value: unknown): value is ThemeChild {\n return typeof value === \"string\" && (THEME_CHILDREN as readonly string[]).includes(value);\n}\n\nexport function sliceFromTheme(theme: ThemeDoc, child: ThemeChild): ThemeDoc {\n if (child === \"colors\") return { colors: theme.colors };\n if (child === \"typography\") return { typography: theme.typography };\n if (child === \"appearance\") return { appearance: theme.appearance };\n return { logo: theme.logo, favicon: theme.favicon, logoMark: theme.logoMark };\n}\n\nfunction colorHex(color: ThemeColorDoc | string | null | undefined): string | undefined {\n if (typeof color === \"string\") return color;\n return color?.hex ?? undefined;\n}\n\n/**\n * A Theme page is a real Global. Hydrate from the store only when this\n * page has never been saved — otherwise afterRead would overwrite the form.\n */\nexport function hasThemeSlice(doc: ThemeDoc | null | undefined, child: ThemeChild): boolean {\n if (!doc) return false;\n if (child === \"colors\") return Boolean(colorHex(doc.colors?.brand?.primary));\n if (child === \"typography\") return Boolean(doc.typography?.body);\n if (child === \"appearance\") return Boolean(doc.appearance?.radius);\n return Boolean(doc.logo || doc.favicon || doc.logoMark);\n}\n\nexport interface ThemeStorePayload {\n findGlobal: (args: {\n slug: string;\n draft?: boolean;\n depth?: number;\n overrideAccess?: boolean;\n }) => Promise<ThemeDoc | null | undefined>;\n updateGlobal: (args: { slug: string; data: ThemeDoc; draft?: boolean }) => Promise<unknown>;\n}\n\n/**\n * Save on a Theme page writes that slice onto the hidden `theme` row.\n * Other children stay as stored.\n */\nexport async function persistThemeChild(\n payload: ThemeStorePayload,\n incoming: ThemeDoc,\n child: ThemeChild,\n): Promise<ThemeDoc> {\n const stored =\n (await payload.findGlobal({\n slug: THEME_SLUG,\n draft: false,\n overrideAccess: true,\n })) ?? {};\n const next = publishThemeChild(stored, incoming, child);\n await payload.updateGlobal({ slug: THEME_SLUG, data: next, draft: false });\n return next;\n}\n","import type { FillLabelWarning } from \"../theme/readability\";\nimport { ThemePortal } from \"./portal\";\nimport {\n hardToReadModes,\n hslCss,\n READABILITY_PUBLISH_NOTE,\n readabilityHeadline,\n} from \"../theme/readability\";\n\nexport interface PublishConfirmProps {\n childLabel: string;\n changes: string[];\n shorts?: FillLabelWarning[];\n onKeepEditing: () => void;\n onPublish: () => void;\n busy?: boolean;\n}\n\nconst OTHER_CHILDREN: Record<string, string> = {\n Colors: \"Typography, Appearance, and Identity stay as they are.\",\n Typography: \"Colors, Appearance, and Identity stay as they are.\",\n Appearance: \"Colors, Typography, and Identity stay as they are.\",\n Identity: \"Colors, Typography, and Appearance stay as they are.\",\n};\n\nexport function PublishConfirm({\n childLabel,\n changes,\n shorts,\n onKeepEditing,\n onPublish,\n busy,\n}: PublishConfirmProps) {\n const remaining = shorts?.filter((item) => !item.meets) ?? [];\n return (\n <ThemePortal>\n <div className=\"bl-publish\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"bl-publish-title\">\n <div className=\"bl-publish__panel\">\n <h2 id=\"bl-publish-title\">Publish {childLabel}</h2>\n <p>\n These {childLabel.toLowerCase()} changes go live now.{\" \"}\n {OTHER_CHILDREN[childLabel] ?? \"The other Theme sections stay as they are.\"}\n </p>\n {changes.length === 0 ? (\n <p className=\"bl-publish__empty\">No changes to publish.</p>\n ) : (\n <ul>\n {changes.map((change) => (\n <li key={change}>{change}</li>\n ))}\n </ul>\n )}\n {remaining.length > 0 ? (\n <div className=\"bl-publish__shorts\">\n <strong>Some colors may be hard to read</strong>\n <ul>\n {remaining.map((item) => (\n <li key={item.id}>\n <span\n aria-hidden=\"true\"\n className=\"bl-publish__swatch\"\n style={{ background: hslCss(item.light.fill), color: hslCss(item.light.label) }}\n >\n Aa\n </span>\n <span>\n {readabilityHeadline(item).replace(/^Text on /, \"\")} {hardToReadModes(item)}.\n </span>\n </li>\n ))}\n </ul>\n <p>{READABILITY_PUBLISH_NOTE}</p>\n </div>\n ) : null}\n <div className=\"bl-publish__actions\">\n <button type=\"button\" className=\"bl-publish__cancel\" onClick={onKeepEditing}>\n Cancel\n </button>\n <button type=\"button\" className=\"bl-publish__go\" disabled={busy || changes.length === 0} onClick={onPublish}>\n {remaining.length > 0 ? \"Publish anyway\" : \"Publish\"}\n </button>\n </div>\n </div>\n </div>\n </ThemePortal>\n );\n}\n\nexport const PUBLISH_CONFIRM_CSS = `\n.bl-publish{position:fixed;inset:0;z-index:10000;display:grid;place-items:center;padding:1rem;background:rgba(15,23,42,.45)}\n.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)}\n.bl-publish__panel h2{margin:0;color:#0f172a}\n.bl-publish__panel p{margin:.5rem 0 0;color:#475569}\n.bl-publish__empty{font-style:italic;color:#64748b}\n.bl-publish__panel > ul{margin:.75rem 0 0;padding-left:1.1rem;color:#0f172a}\n.bl-publish__shorts{margin-top:1rem;padding:.85rem .9rem;border-radius:10px;background:#fffbeb;color:#0f172a}\n.bl-publish__shorts strong{display:block}\n.bl-publish__shorts ul{margin:.65rem 0 0;padding:0;list-style:none}\n.bl-publish__shorts li{display:flex;gap:.65rem;align-items:center;margin-top:.45rem;font-size:13px;color:#0f172a}\n.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}\n.bl-publish__shorts p{margin:.65rem 0 0;font-size:13px;color:#475569}\n.bl-publish__actions{display:flex;justify-content:flex-end;gap:.6rem;margin-top:1.1rem}\n.bl-publish__actions button{min-height:2.25rem;padding:.4rem .9rem;border-radius:8px;font:inherit;cursor:pointer}\n.bl-publish__cancel{border:1px solid #cbd5e1;background:#fff;color:#0f172a}\n.bl-publish__go{border:0;background:#0f172a;color:#fff;font-weight:600}\n.bl-publish__actions button:disabled{opacity:.45;cursor:not-allowed}\n`;\n","import { useField, useForm, useFormFields } from \"@payloadcms/ui\";\nimport type { UIFieldClientComponent } from \"payload\";\nimport { useMemo, useState } from \"react\";\n\nimport { SYSTEM_COLOR_COPY } from \"../theme/appearance-labels\";\nimport { themeChildChanges } from \"../theme/changes\";\nimport { isThemeChild, type ThemeChild } from \"../theme/publish\";\nimport { fillLabelWarning, type FillLabelWarning } from \"../theme/readability\";\nimport { SYSTEM_COLOR_KEYS, type ThemeColorDoc, type ThemeDoc, type ThemeLibraryColorDoc } from \"../theme/types\";\nimport { PublishConfirm, PUBLISH_CONFIRM_CSS } from \"./publish-confirm\";\n\nconst LABELS: Record<ThemeChild, string> = {\n colors: \"Colors\",\n typography: \"Typography\",\n appearance: \"Appearance\",\n identity: \"Identity\",\n};\n\nfunction asColor(value: unknown): ThemeColorDoc | undefined {\n if (value && typeof value === \"object\") return value as ThemeColorDoc;\n if (typeof value === \"string\") return { hex: value };\n return undefined;\n}\n\nfunction formDoc(fields: Record<string, { value?: unknown } | undefined>): ThemeDoc {\n const brand = Object.fromEntries(\n SYSTEM_COLOR_KEYS.map((key) => [\n key,\n {\n hex: fields[`colors.brand.${key}.hex`]?.value as string | undefined,\n sourceStep: fields[`colors.brand.${key}.sourceStep`]?.value as ThemeColorDoc[\"sourceStep\"],\n },\n ]),\n ) as NonNullable<NonNullable<ThemeDoc[\"colors\"]>[\"brand\"]>;\n return {\n colors: {\n brand,\n library: Array.isArray(fields[\"colors.library\"]?.value)\n ? (fields[\"colors.library\"]?.value as ThemeLibraryColorDoc[])\n : [],\n greyScale: fields[\"colors.greyScale\"]?.value as NonNullable<ThemeDoc[\"colors\"]>[\"greyScale\"],\n },\n typography: {\n body: fields[\"typography.body\"]?.value as string | undefined,\n heading: fields[\"typography.heading\"]?.value as string | undefined,\n },\n appearance: {\n defaultTheme: fields[\"appearance.defaultTheme\"]?.value as NonNullable<ThemeDoc[\"appearance\"]>[\"defaultTheme\"],\n radius: fields[\"appearance.radius\"]?.value as NonNullable<ThemeDoc[\"appearance\"]>[\"radius\"],\n shadow: fields[\"appearance.shadow\"]?.value as NonNullable<ThemeDoc[\"appearance\"]>[\"shadow\"],\n motion: fields[\"appearance.motion\"]?.value as NonNullable<ThemeDoc[\"appearance\"]>[\"motion\"],\n density: fields[\"appearance.density\"]?.value as NonNullable<ThemeDoc[\"appearance\"]>[\"density\"],\n },\n logo: fields.logo?.value as ThemeDoc[\"logo\"],\n favicon: fields.favicon?.value as ThemeDoc[\"favicon\"],\n logoMark: fields.logoMark?.value as ThemeDoc[\"logoMark\"],\n };\n}\n\nfunction publishedDoc(fields: Record<string, { initialValue?: unknown; value?: unknown } | undefined>): ThemeDoc {\n return formDoc(\n Object.fromEntries(Object.entries(fields).map(([path, field]) => [path, { value: field?.initialValue }])),\n );\n}\n\nfunction shortsFrom(doc: ThemeDoc): FillLabelWarning[] {\n const brand = doc.colors?.brand ?? {};\n const custom = doc.colors?.library ?? [];\n return [\n ...SYSTEM_COLOR_KEYS.flatMap((key) => {\n const hex = asColor(brand[key])?.hex;\n const warning = typeof hex === \"string\" ? fillLabelWarning(key, SYSTEM_COLOR_COPY[key].label, hex) : null;\n return warning ? [warning] : [];\n }),\n ...custom.flatMap((row, index) => {\n const warning = row.hex ? fillLabelWarning(`library-${index}`, row.label ?? row.key ?? \"Custom\", row.hex) : null;\n return warning ? [warning] : [];\n }),\n ];\n}\n\n/**\n * Per-child Publish. Lives in the document Save slot so Payload's\n * `--doc-controls-height` row is the action row, not an empty gap.\n * Sets `publishChild` then submits; `beforeChange` writes only that slice.\n * On Colors, remaining automatic-label shorts open in this modal only.\n */\nexport function ThemePublishActions({ child }: { child: ThemeChild }) {\n const label = LABELS[child];\n const { submit } = useForm();\n const publishChild = useField<string>({ path: \"publishChild\" });\n const snapshot = useFormFields(([fields]) => {\n const record = fields as Record<string, { initialValue?: unknown; value?: unknown } | undefined>;\n return { incoming: formDoc(record), published: publishedDoc(record) };\n });\n const [open, setOpen] = useState(false);\n const [busy, setBusy] = useState(false);\n\n const changes = useMemo(\n () => themeChildChanges(child, snapshot.published, snapshot.incoming),\n [child, snapshot],\n );\n const shorts = child === \"colors\" ? shortsFrom(snapshot.incoming) : undefined;\n\n async function publish() {\n setBusy(true);\n publishChild.setValue(child);\n try {\n await submit();\n setOpen(false);\n } finally {\n setBusy(false);\n }\n }\n\n return (\n <div className=\"bl-publish-child\">\n <style href=\"bl-publish\" precedence=\"default\">\n {PUBLISH_CONFIRM_CSS}\n </style>\n <style href=\"bl-publish-child\" precedence=\"default\">\n {`.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}`}\n </style>\n <button type=\"button\" className=\"bl-publish-child__button\" onClick={() => setOpen(true)}>\n Publish {label}\n </button>\n {open ? (\n <PublishConfirm\n childLabel={label}\n changes={changes}\n shorts={shorts}\n busy={busy}\n onKeepEditing={() => setOpen(false)}\n onPublish={() => {\n void publish();\n }}\n />\n ) : null}\n </div>\n );\n}\n\n/** @deprecated Alias — Theme pages use ThemePublishActions; tabbed Save used this name. */\nexport const ThemePublishControls = ThemePublishActions;\n\nexport const PublishChild: UIFieldClientComponent = ({ field }) => {\n const child = (field.admin?.custom as { child?: string } | undefined)?.child;\n if (!isThemeChild(child)) return null;\n return <ThemePublishActions child={child} />;\n};\n","import { THEME_CHILDREN, type ThemeChild } from \"../theme/publish\";\n\nexport const THEME_TAB_LABELS = {\n colors: \"Colors\",\n typography: \"Typography\",\n appearance: \"Appearance\",\n identity: \"Identity\",\n} as const satisfies Record<ThemeChild, string>;\n\n/**\n * The selected Payload field tab on Theme. Defaults to Colors when the\n * tabs have not painted yet (SSR, first paint).\n */\nexport function readActiveThemeTab(root: ParentNode | null | undefined = typeof document === \"undefined\" ? null : document): ThemeChild {\n if (!root) return \"colors\";\n const selected =\n root.querySelector('.tabs-field__tab-button[aria-selected=\"true\"]') ??\n root.querySelector(\".tabs-field__tab-button--active\") ??\n root.querySelector('[role=\"tab\"][aria-selected=\"true\"]');\n const text = selected?.textContent?.replace(/\\s+/g, \" \").trim();\n return THEME_CHILDREN.find((id) => THEME_TAB_LABELS[id] === text) ?? \"colors\";\n}\n","import { useEffect, useState } from \"react\";\n\nimport type { ThemeChild } from \"../theme/publish\";\nimport { ThemePublishControls } from \"./publish-child\";\nimport { readActiveThemeTab } from \"./theme-tab\";\n\n/**\n * Theme used to put a Light/Dark pair here. Admin chrome now follows\n * Payload's own theme from the header sun/moon, so this slot is empty\n * and Save stays in the Save slot.\n */\nexport function ThemeDocumentControls() {\n return null;\n}\n\n/**\n * Import-map Save slot used by the older single-Global Theme. Theme pages\n * keep Payload's Save and put Light/Dark in `ThemeDocumentControls`.\n */\nexport function ThemeSaveButton() {\n const [child, setChild] = useState<ThemeChild>(\"colors\");\n\n useEffect(() => {\n const sync = () => setChild(readActiveThemeTab());\n sync();\n const tabs = document.querySelector(\".tabs-field\");\n const target = tabs ?? document.body;\n const observer = new MutationObserver(sync);\n observer.observe(target, {\n subtree: true,\n attributes: true,\n attributeFilter: [\"aria-selected\", \"class\"],\n childList: true,\n });\n target.addEventListener(\"click\", sync);\n return () => {\n observer.disconnect();\n target.removeEventListener(\"click\", sync);\n };\n }, []);\n\n return <ThemePublishControls child={child} />;\n}\n\n/** @deprecated Import map alias — ThemeDocumentControls is the Save-adjacent slot. */\nexport function HiddenSaveButton() {\n return <ThemeDocumentControls />;\n}\n","import type { UIFieldClientComponent } from \"payload\";\n\nimport type { ThemeIdentityFallback } from \"../theme/identity\";\n\n/**\n * Identity child when the site has not registered a cupboard yet.\n * Shows the fallback lockup and mark; uploads wait on `logo.collection`.\n */\nexport const IdentityFallback: UIFieldClientComponent = ({ field }) => {\n const fallback = (field.admin?.custom as { fallback?: ThemeIdentityFallback } | undefined)?.fallback;\n return (\n <section className=\"bl-identity-fallback\">\n <style href=\"bl-identity-fallback\" precedence=\"default\">\n {CSS}\n </style>\n <header>\n <h2>Site identity</h2>\n <p>Today's lockup and mark until a brand editor uploads replacements.</p>\n </header>\n <div className=\"bl-identity-fallback__grid\">\n {fallback?.lockup ? (\n <figure>\n <img src={fallback.lockup.url} alt={fallback.lockup.alt} />\n <figcaption>Lockup</figcaption>\n </figure>\n ) : null}\n {fallback?.mark ? (\n <figure>\n <img src={fallback.mark.url} alt={fallback.mark.alt} />\n <figcaption>Mark</figcaption>\n </figure>\n ) : null}\n </div>\n </section>\n );\n};\n\nconst CSS = `\n.bl-identity-fallback header h2{margin:0;font-size:1.1rem}\n.bl-identity-fallback header p{margin:.35rem 0 1rem;color:var(--theme-elevation-600,#475569)}\n.bl-identity-fallback__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(12rem,1fr));gap:1rem}\n.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)}\n.bl-identity-fallback img{display:block;max-width:100%;height:4rem;object-fit:contain}\n.bl-identity-fallback figcaption{margin-top:.5rem;font-size:.8rem;color:var(--theme-elevation-600,#475569)}\n`;\n","import { FieldDescription, FieldError, FieldLabel, useConfig, useField } from \"@payloadcms/ui\";\nimport type { TextFieldClientComponent } from \"payload\";\nimport { useEffect, useId, useState } from \"react\";\n\nimport { pageEditorLooks, pageEditorTokens, type LookOption } from \"../theme/looks\";\nimport type { LookFieldMode } from \"../theme/look-field\";\nimport type { ThemeDoc } from \"../theme/types\";\n\n/**\n * Loads the Theme global and offers page-editor looks or included steps.\n * A custom scale published on Colors appears here on the next load.\n */\nexport const LookField: TextFieldClientComponent = ({ field, path, readOnly }) => {\n const { value, setValue, showError, errorMessage } = useField<string>({ path });\n const { config } = useConfig();\n const mode = ((field.admin?.custom as { mode?: LookFieldMode } | undefined)?.mode ?? \"look\") as LookFieldMode;\n const [options, setOptions] = useState<LookOption[]>(\n mode === \"token\" ? pageEditorTokens(null) : pageEditorLooks(null),\n );\n const id = useId();\n const required = Boolean(field.required);\n\n useEffect(() => {\n const serverURL = config.serverURL ?? \"\";\n const api = config.routes?.api ?? \"/api\";\n const controller = new AbortController();\n fetch(`${serverURL}${api}/globals/theme?depth=0`, { signal: controller.signal, credentials: \"include\" })\n .then((response) => (response.ok ? response.json() : null))\n .then((doc: ThemeDoc | null) => {\n setOptions(mode === \"token\" ? pageEditorTokens(doc) : pageEditorLooks(doc));\n })\n .catch(() => {\n /* keep the system-only fallback */\n });\n return () => controller.abort();\n }, [config.routes?.api, config.serverURL, mode]);\n\n return (\n <div className=\"field-type\">\n <FieldLabel htmlFor={id} label={field.label} required={required} />\n <select\n id={id}\n disabled={readOnly}\n value={value ?? \"\"}\n onChange={(event) => setValue(event.target.value || undefined)}\n >\n <option value=\"\">{required ? \"Select…\" : \"None\"}</option>\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n <FieldDescription description={field.admin?.description} path={path} />\n <FieldError path={path} showError={showError} message={errorMessage} />\n </div>\n );\n};\n","export const FEATURES_SLUG = \"features\";\n\nexport const FEATURE_GROUPS = [\"pages\", \"media\", \"theme\", \"users\"] as const;\n\nexport type FeatureGroupId = (typeof FEATURE_GROUPS)[number];\n\nexport const FEATURE_GROUP_LABELS: Record<FeatureGroupId, string> = {\n pages: \"Pages\",\n media: \"Media\",\n theme: \"Theme\",\n users: \"Users\",\n};\n\nexport const PACKAGE_FEATURE_SLUGS = [\n \"content\",\n \"publish\",\n \"media\",\n \"theme-colors\",\n \"theme-typography\",\n \"theme-appearance\",\n \"theme-identity\",\n \"brand-assets\",\n \"users\",\n \"roles\",\n] as const;\n\nexport type PackageFeatureSlug = (typeof PACKAGE_FEATURE_SLUGS)[number];\n\nexport interface PackageFeature {\n slug: PackageFeatureSlug;\n label: string;\n group: FeatureGroupId;\n defaultReleased: boolean;\n}\n\n/**\n * Package catalogue. Features itself is not a row — that screen is\n * Developer-only in code. Empty Global falls back to these defaults.\n */\nexport const PACKAGE_FEATURES: readonly PackageFeature[] = [\n { slug: \"content\", label: \"Content\", group: \"pages\", defaultReleased: true },\n { slug: \"publish\", label: \"Publish\", group: \"pages\", defaultReleased: true },\n { slug: \"media\", label: \"Media\", group: \"media\", defaultReleased: true },\n { slug: \"theme-colors\", label: \"Colors\", group: \"theme\", defaultReleased: true },\n { slug: \"theme-typography\", label: \"Typography\", group: \"theme\", defaultReleased: true },\n { slug: \"theme-appearance\", label: \"Appearance\", group: \"theme\", defaultReleased: true },\n { slug: \"theme-identity\", label: \"Identity\", group: \"theme\", defaultReleased: true },\n { slug: \"brand-assets\", label: \"Brand assets\", group: \"theme\", defaultReleased: true },\n { slug: \"users\", label: \"Users\", group: \"users\", defaultReleased: true },\n { slug: \"roles\", label: \"Roles\", group: \"users\", defaultReleased: true },\n];\n\n/** A site-only row. Other sites never see this slug. */\nexport interface FeatureExtra {\n slug: string;\n label: string;\n group?: FeatureGroupId;\n defaultReleased?: boolean;\n}\n\nexport interface FeatureRow {\n id?: string | null;\n slug: string;\n label?: string | null;\n group?: string | null;\n released: boolean;\n}\n\nexport interface FeaturesDoc {\n features?: FeatureRow[] | null;\n}\n\nexport function isFeatureGroupId(value: unknown): value is FeatureGroupId {\n return typeof value === \"string\" && (FEATURE_GROUPS as readonly string[]).includes(value);\n}\n\nexport function isPackageFeatureSlug(value: unknown): value is PackageFeatureSlug {\n return typeof value === \"string\" && (PACKAGE_FEATURE_SLUGS as readonly string[]).includes(value);\n}\n\nexport function isFeatureSlug(value: unknown): value is string {\n return typeof value === \"string\" && /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/.test(value);\n}\n\n/** @deprecated Locks are gone; the release switch is the valve. */\nexport function isLockedFeature(_slug: string, _locked?: boolean | null): boolean {\n return false;\n}\n","import {\n FEATURE_GROUP_LABELS,\n isFeatureGroupId,\n isFeatureSlug,\n PACKAGE_FEATURES,\n type FeatureExtra,\n type FeatureGroupId,\n type FeatureRow,\n type PackageFeature,\n} from \"./types\";\n\nexport const MISSING_PACKAGE_FEATURES_MESSAGE =\n \"Features must include Content, Publish, Media, Theme screens, Brand assets, Users, and Roles.\";\n\nexport interface FeatureCatalogueEntry {\n slug: string;\n label: string;\n group: FeatureGroupId;\n defaultReleased: boolean;\n}\n\nexport function featureCatalogue(extras: readonly FeatureExtra[] = []): FeatureCatalogueEntry[] {\n return [\n ...PACKAGE_FEATURES.map((feature) => ({ ...feature })),\n ...extras.map((extra) => ({\n slug: extra.slug,\n label: extra.label,\n group: extra.group ?? \"users\",\n defaultReleased: extra.defaultReleased ?? false,\n })),\n ];\n}\n\nexport function defaultFeaturesFieldValue(extras: readonly FeatureExtra[] = []): FeatureRow[] {\n return featureCatalogue(extras).map((feature) => ({\n id: feature.slug,\n slug: feature.slug,\n label: feature.label,\n group: feature.group,\n released: feature.defaultReleased,\n }));\n}\n\nexport function stampFeatureCatalogue(\n value: unknown,\n extras: readonly FeatureExtra[] = [],\n): FeatureRow[] {\n const bySlug = new Map(featureCatalogue(extras).map((feature) => [feature.slug, feature]));\n if (!Array.isArray(value)) return defaultFeaturesFieldValue(extras);\n return value.flatMap((item) => {\n if (!item || typeof item !== \"object\") return [];\n const slug = \"slug\" in item && typeof item.slug === \"string\" ? item.slug : \"\";\n const feature = bySlug.get(slug);\n if (!feature) return [];\n return [\n {\n id: feature.slug,\n slug: feature.slug,\n label: feature.label,\n group: feature.group,\n released: Boolean(\"released\" in item && item.released),\n },\n ];\n });\n}\n\nexport function parseFeaturesMatrix(\n value: unknown,\n): { ok: true; rows: FeatureRow[] } | { ok: false; message: string } {\n if (!Array.isArray(value) || value.length === 0) {\n return { ok: false, message: MISSING_PACKAGE_FEATURES_MESSAGE };\n }\n\n const rows: FeatureRow[] = [];\n const seen = new Set<string>();\n\n for (const item of value) {\n if (!item || typeof item !== \"object\") continue;\n const slug = \"slug\" in item ? item.slug : undefined;\n if (!isFeatureSlug(slug) || seen.has(slug)) continue;\n seen.add(slug);\n const pack = PACKAGE_FEATURES.find((feature) => feature.slug === slug);\n const label =\n \"label\" in item && typeof item.label === \"string\"\n ? item.label\n : (pack?.label ?? slug);\n const group =\n \"group\" in item && isFeatureGroupId(item.group) ? item.group : (pack?.group ?? \"users\");\n rows.push({\n id: slug,\n slug,\n label,\n group,\n released: Boolean(\"released\" in item && item.released),\n });\n }\n\n if (PACKAGE_FEATURES.some((feature) => !seen.has(feature.slug))) {\n return { ok: false, message: MISSING_PACKAGE_FEATURES_MESSAGE };\n }\n return { ok: true, rows };\n}\n\nexport function validateFeaturesMatrix(\n value: unknown,\n extras: readonly FeatureExtra[] = [],\n): true | string {\n const parsed = parseFeaturesMatrix(value);\n if (!parsed.ok) return parsed.message;\n const allowed = new Set(featureCatalogue(extras).map((feature) => feature.slug));\n if (parsed.rows.some((row) => !allowed.has(row.slug))) return MISSING_PACKAGE_FEATURES_MESSAGE;\n return true;\n}\n\nexport function featureGroupLabel(group: string): string {\n return isFeatureGroupId(group) ? FEATURE_GROUP_LABELS[group] : group;\n}\n\nexport function packageFeatureLabel(slug: string, extras: readonly FeatureExtra[] = []): string {\n const pack = PACKAGE_FEATURES.find((feature) => feature.slug === slug);\n if (pack) return pack.label;\n const extra = extras.find((feature) => feature.slug === slug);\n return extra?.label ?? slug;\n}\n\nexport function isGroupOnlySlug(slug: string): boolean {\n return isFeatureGroupId(slug) && !PACKAGE_FEATURES.some((feature) => feature.slug === slug);\n}\n\nexport type { PackageFeature };\n","/**\n * The Roles Global a site's generated types will describe. Optional and\n * nullable, no index signature: a generated Global is assignable to this,\n * never the reverse.\n */\n\nexport const ROLES = [\"developer\", \"admin\", \"designer\", \"author\"] as const;\n\nexport type Role = (typeof ROLES)[number];\n\nexport const ROLE_LABELS: Record<Role, string> = {\n developer: \"Developer\",\n admin: \"Admin\",\n designer: \"Designer\",\n author: \"Author\",\n};\n\n/** Capability aliases over feature grants. Brand is any Theme-group leaf. */\nexport const CAPABILITIES = [\"content\", \"brand\", \"publish\", \"users\"] as const;\n\nexport type Capability = (typeof CAPABILITIES)[number];\n\nexport const THEME_FEATURE_SLUGS = [\n \"theme-colors\",\n \"theme-typography\",\n \"theme-appearance\",\n \"theme-identity\",\n \"brand-assets\",\n] as const;\n\nexport const CAPABILITY_FEATURES: Record<Capability, readonly string[]> = {\n content: [\"content\"],\n publish: [\"publish\"],\n users: [\"users\"],\n brand: THEME_FEATURE_SLUGS,\n};\n\nexport const DEFAULT_ROLE_GRANTS: Record<Role, readonly string[]> = {\n developer: [],\n admin: [\"content\", \"publish\", \"media\", \"users\", \"roles\"],\n designer: [\n \"content\",\n \"media\",\n ...THEME_FEATURE_SLUGS,\n \"users\",\n \"roles\",\n ],\n author: [\"content\", \"media\"],\n};\n\n/**\n * A site-defined row passed into `createRoles({ extras })`. The slug is the\n * stored key; the label is what Settings → Roles and Users show.\n */\nexport interface RoleExtra {\n role: string;\n label: string;\n grants?: readonly string[];\n}\n\nexport interface RoleRow {\n id?: string | null;\n role: string;\n label?: string | null;\n grants: string[];\n}\n\nexport interface RolesDoc {\n roles?: RoleRow[] | null;\n}\n\n/**\n * `req.user` as Payload hands it over. Structural so this module never\n * imports a site's generated `User`. `roles` is optional because a row\n * that predates the field must come back powerless.\n */\nexport type MaybeUser = {\n id?: string | number;\n roles?: readonly string[] | null;\n /** Feature slugs this login may use, stamped onto the JWT at read. */\n allowedFeatures?: readonly string[] | null;\n} | null | undefined;\n\nexport function isRole(value: unknown): value is Role {\n return typeof value === \"string\" && (ROLES as readonly string[]).includes(value);\n}\n\n/** Lowercase slug from a letters-and-spaces name: `designer`, `the-designer`. */\nexport function isRoleSlug(value: unknown): value is string {\n return typeof value === \"string\" && /^[a-z]+(-[a-z]+)*$/.test(value);\n}\n\n/** Display name: letters and single spaces only. `The Greatest Designer`. */\nexport function isRoleName(value: unknown): value is string {\n return typeof value === \"string\" && /^[A-Za-z]+(?: [A-Za-z]+)*$/.test(value.trim());\n}\n\n/** Strip digits and punctuation as the name is typed. Trailing space stays. */\nexport function sanitizeRoleNameInput(value: string): string {\n return value.replace(/[^A-Za-z ]/g, \"\").replace(/ {2,}/g, \" \");\n}\n\n/** Name → stored key. `The Greatest Designer` → `the-greatest-designer`. */\nexport function slugifyRoleName(value: unknown): string {\n if (typeof value !== \"string\") return \"\";\n return value\n .trim()\n .toLowerCase()\n .replace(/[^a-z]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\nexport function roleLabel(role: string, label?: string | null): string {\n const trimmed = typeof label === \"string\" ? label.trim() : \"\";\n if (trimmed) return trimmed;\n return isRole(role) ? ROLE_LABELS[role] : role;\n}\n\nexport function defaultGrantsForRole(role: string, extraGrants?: readonly string[]): string[] {\n if (isRole(role)) return [...DEFAULT_ROLE_GRANTS[role]];\n return extraGrants ? [...extraGrants] : [];\n}\n","import { packageFeatureLabel } from \"../features/matrix\";\nimport { isFeatureSlug } from \"../features/types\";\nimport {\n CAPABILITY_FEATURES,\n defaultGrantsForRole,\n isRole,\n isRoleName,\n isRoleSlug,\n ROLE_LABELS,\n roleLabel,\n ROLES,\n slugifyRoleName,\n THEME_FEATURE_SLUGS,\n type Capability,\n type RoleExtra,\n type RoleRow,\n} from \"./types\";\n\nexport const ROLES_SLUG = \"roles\";\n\nexport const ROLES_GLOBAL_DESCRIPTION = \"Who may do what. Drag to change rank.\";\n\nexport const ROLES_FIELD_DESCRIPTION =\n \"Drag to change rank. Ticks are features released on Features. Developer has the whole catalogue.\"\n\n/**\n * Default rank and grants. Developer is implicit (empty grants). Brand\n * screens default to Designer.\n */\nexport const DEFAULT_ROLE_MATRIX: readonly RoleRow[] = ROLES.map((role) => ({\n role,\n grants: defaultGrantsForRole(role),\n}));\n\nexport const DEVELOPER_DESCRIPTION =\n \"Everything, including features not released for assignment.\";\n\nexport const LAST_USERS_TICK_MESSAGE =\n \"Keep Users granted on at least one of Admin or Developer.\";\n\nexport const MISSING_SEED_ROLES_MESSAGE = \"Roles must include Developer.\";\n\nexport const DUPLICATE_ROLE_SLUG_MESSAGE = \"Each role needs a unique slug.\";\n\nexport const DUPLICATE_ROLE_NAME_MESSAGE = \"Each role needs a unique name.\";\n\nexport const INVALID_ROLE_NAME_MESSAGE = \"Use letters and spaces only.\";\n\nfunction uniqueSlugs(values: readonly unknown[]): string[] {\n const slugs: string[] = [];\n for (const value of values) {\n if (typeof value === \"string\" && isFeatureSlug(value) && !slugs.includes(value)) slugs.push(value);\n }\n return slugs;\n}\n\n/** Read stored grants, or rebuild them from the old capability ticks. */\nexport function grantsFromStoredRole(item: object): string[] {\n if (\"grants\" in item && Array.isArray(item.grants)) return uniqueSlugs(item.grants);\n const grants: string[] = [];\n if (\"content\" in item && item.content) {\n grants.push(\"content\", \"media\");\n }\n if (\"publish\" in item && item.publish) grants.push(\"publish\");\n if (\"users\" in item && item.users) grants.push(\"users\", \"roles\");\n if (\"brand\" in item && item.brand) grants.push(...THEME_FEATURE_SLUGS);\n return uniqueSlugs(grants);\n}\n\nexport function seedRoleRows(extras: readonly RoleExtra[] = []): RoleRow[] {\n return [\n ...DEFAULT_ROLE_MATRIX.map((row) => ({\n ...row,\n grants: [...row.grants],\n label: isRole(row.role) ? ROLE_LABELS[row.role] : row.role,\n })),\n ...extras.map((extra) => ({\n role: extra.role,\n label: extra.label,\n grants: extra.grants ? [...extra.grants] : [],\n })),\n ];\n}\n\nexport function defaultRolesFieldValue(extras: readonly RoleExtra[] = []): RoleRow[] {\n return seedRoleRows(extras).map((row) => ({ id: row.role, ...row }));\n}\n\nfunction readRoleRow(item: object): RoleRow | { error: string } {\n const role = \"role\" in item ? item.role : undefined;\n if (typeof role !== \"string\" || role.trim() === \"\") return { error: DUPLICATE_ROLE_SLUG_MESSAGE };\n if (!isRoleSlug(role)) return { error: DUPLICATE_ROLE_SLUG_MESSAGE };\n const label = \"label\" in item && typeof item.label === \"string\" ? item.label : undefined;\n return {\n id: role,\n role,\n label: roleLabel(role, label),\n grants: grantsFromStoredRole(item),\n };\n}\n\nexport function parseRolesMatrix(\n value: unknown,\n): { ok: true; rows: RoleRow[] } | { ok: false; message: string } {\n if (!Array.isArray(value)) {\n return { ok: false, message: MISSING_SEED_ROLES_MESSAGE };\n }\n\n const rows: RoleRow[] = [];\n const seen = new Set<string>();\n for (const item of value) {\n if (!item || typeof item !== \"object\") continue;\n // An Add Role row starts with no slug. Skip it so form-state can\n // build the fields; the slug field still refuses an empty save.\n const role = \"role\" in item ? item.role : undefined;\n if (typeof role !== \"string\" || role.trim() === \"\") continue;\n const parsed = readRoleRow(item);\n if (\"error\" in parsed) return { ok: false, message: parsed.error };\n if (seen.has(parsed.role)) return { ok: false, message: DUPLICATE_ROLE_SLUG_MESSAGE };\n seen.add(parsed.role);\n rows.push(parsed);\n }\n\n if (!seen.has(\"developer\")) {\n return { ok: false, message: MISSING_SEED_ROLES_MESSAGE };\n }\n return { ok: true, rows };\n}\n\nexport function roleHasGrant(row: RoleRow, slug: string): boolean {\n if (row.role === \"developer\") return true;\n return row.grants.includes(slug);\n}\n\nexport function roleHasCapability(row: RoleRow, capability: Capability): boolean {\n if (row.role === \"developer\") return true;\n return CAPABILITY_FEATURES[capability].some((slug) => row.grants.includes(slug));\n}\n\n/**\n * Mint a slug from the name only when the row has none yet. An existing\n * key — seed or custom — stays put so a rename cannot orphan users.\n */\nexport function applyRoleSlugsFromNames(value: unknown): unknown {\n if (!Array.isArray(value)) return value;\n return value.map((item) => {\n if (!item || typeof item !== \"object\") return item;\n const row = item as RoleRow;\n if (isRoleSlug(row.role)) return item;\n const slug = slugifyRoleName(row.label);\n return isRoleSlug(slug) ? { ...row, role: slug } : item;\n });\n}\n\nfunction hasDuplicateRoleNames(value: unknown): boolean {\n if (!Array.isArray(value)) return false;\n const seen = new Set<string>();\n for (const item of value) {\n if (!item || typeof item !== \"object\") continue;\n const role = \"role\" in item && typeof item.role === \"string\" ? item.role : \"\";\n const raw = \"label\" in item && typeof item.label === \"string\" ? item.label : \"\";\n const name = raw.trim() || (isRole(role) ? ROLE_LABELS[role] : \"\");\n if (!name) continue;\n const key = name.toLowerCase();\n if (seen.has(key)) return true;\n seen.add(key);\n }\n return false;\n}\n\nfunction hasInvalidRoleName(value: unknown): boolean {\n if (!Array.isArray(value)) return false;\n for (const item of value) {\n if (!item || typeof item !== \"object\") continue;\n const label = \"label\" in item && typeof item.label === \"string\" ? item.label.trim() : \"\";\n if (!label) continue;\n if (!isRoleName(label)) return true;\n }\n return false;\n}\n\nexport function validateRolesMatrix(value: unknown): true | string {\n if (hasDuplicateRoleNames(value)) return DUPLICATE_ROLE_NAME_MESSAGE;\n if (hasInvalidRoleName(value)) return INVALID_ROLE_NAME_MESSAGE;\n const parsed = parseRolesMatrix(applyRoleSlugsFromNames(value));\n if (!parsed.ok) return parsed.message;\n return true;\n}\n\n/**\n * Developer is exclusive. Admin does not swallow Designer: both store.\n * Unknown slugs (dropped catalogue keys such as `approver`) fall away unless\n * they appear on the matrix.\n */\nexport function normalizeStoredRoles(\n value: unknown,\n matrix: readonly RoleRow[] = DEFAULT_ROLE_MATRIX,\n): string[] {\n if (!Array.isArray(value)) return [];\n const allowed = new Set(matrix.map((row) => row.role));\n const roles = [...new Set(value.filter((entry): entry is string => typeof entry === \"string\" && allowed.has(entry)))];\n if (roles.includes(\"developer\")) return [\"developer\"];\n return roles;\n}\n\nexport function roleSelectOptions(matrix: readonly RoleRow[] = DEFAULT_ROLE_MATRIX) {\n return matrix.map((row) => ({ label: roleLabel(row.role, row.label), value: row.role }));\n}\n\n/** Grant copy only. Developer names the unreleased catalogue; nothing about MCP or seed. */\nexport function roleDescription(role: string, matrix: readonly RoleRow[] = DEFAULT_ROLE_MATRIX): string {\n if (role === \"developer\") return DEVELOPER_DESCRIPTION;\n const row = matrix.find((entry) => entry.role === role);\n if (!row) return \"No capabilities\";\n const ticks = row.grants.map((slug) => packageFeatureLabel(slug));\n return ticks.join(\", \") || \"No capabilities\";\n}\n\n/**\n * Seed grants and package labels come back; extra rows stay as they are.\n */\nexport function resetRolesMatrix(current: unknown): RoleRow[] {\n const extras: RoleRow[] = [];\n if (Array.isArray(current)) {\n for (const item of current) {\n if (!item || typeof item !== \"object\") continue;\n const parsed = readRoleRow(item);\n if (\"error\" in parsed || isRole(parsed.role)) continue;\n extras.push(parsed);\n }\n }\n return [...defaultRolesFieldValue(), ...extras];\n}\n","import { ArrayField, useAuth, useField } from \"@payloadcms/ui\";\nimport type { ArrayFieldClientComponent } from \"payload\";\nimport { useCallback, useRef } from \"react\";\n\nimport { resetRolesMatrix } from \"../roles/matrix\";\n\nconst HIDE_ROW_CHROME = `.bl-roles-matrix .array-actions__add,.bl-roles-matrix .array-actions__duplicate,.bl-roles-matrix .array-actions__copy{display:none}.bl-roles-matrix .array-field__add-row{display:none}.bl-roles-matrix--hide-developer .array-field__row:has([data-role-seed=\"developer\"]),.bl-roles-matrix--hide-developer .collapsible:has([data-role-seed=\"developer\"]){display:none}.bl-roles-matrix__toolbar{display:flex;justify-content:flex-end;gap:.5rem;margin-block-end:.75rem}.bl-roles-matrix__reset{min-height:2.25rem;padding:.35rem .9rem;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:8px;background:transparent;color:inherit;font:inherit;cursor:pointer}body.bl-roles-matrix-seed-menu .array-actions__remove{display:none}`;\n\nfunction seedRoleFromTrigger(trigger: Element): boolean {\n let node: HTMLElement | null = trigger.parentElement;\n while (node) {\n const slugs = node.querySelectorAll(\"[data-role-slug]\");\n if (slugs.length === 1) {\n const seed = slugs[0]?.getAttribute(\"data-role-seed\") || slugs[0]?.getAttribute(\"data-role-slug\");\n return seed === \"developer\";\n }\n if (slugs.length > 1) return false;\n node = node.parentElement;\n }\n return false;\n}\n\nfunction viewerIsDeveloper(user: unknown): boolean {\n if (!user || typeof user !== \"object\" || !(\"roles\" in user)) return false;\n const roles = (user as { roles?: unknown }).roles;\n return Array.isArray(roles) && roles.includes(\"developer\");\n}\n\n/**\n * Payload's array field: drag rank stays, add is for custom rows.\n * Developer has no remove, stays in the saved array, and is shown only\n * to a Developer. Reset restores the package four and leaves extras.\n */\nexport const RolesMatrixField: ArrayFieldClientComponent = (props) => {\n const { setValue, value } = useField({ path: props.path });\n const { user } = useAuth();\n const hideDeveloper = !viewerIsDeveloper(user);\n const rootRef = useRef<HTMLDivElement>(null);\n const seedMenu = useRef(false);\n\n const onClickCapture = useCallback((event: React.MouseEvent<HTMLDivElement>) => {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const trigger = target.closest(\".array-actions__button\");\n if (trigger) {\n const owner = trigger.closest(\".array-field\");\n const ours = owner !== null && owner === rootRef.current?.querySelector(\".array-field\");\n seedMenu.current = ours && seedRoleFromTrigger(trigger);\n document.body.classList.toggle(\"bl-roles-matrix-seed-menu\", seedMenu.current);\n return;\n }\n\n if (!target.closest(\".array-actions__remove\")) return;\n if (!seedMenu.current) return;\n event.preventDefault();\n event.stopPropagation();\n }, []);\n\n return (\n <div\n className={[\"bl-roles-matrix\", hideDeveloper && \"bl-roles-matrix--hide-developer\"]\n .filter(Boolean)\n .join(\" \")}\n ref={rootRef}\n onClickCapture={onClickCapture}\n >\n <style href=\"bl-roles-matrix\" precedence=\"default\">\n {HIDE_ROW_CHROME}\n </style>\n <div className=\"bl-roles-matrix__toolbar\">\n <button type=\"button\" className=\"bl-roles-matrix__reset\" onClick={() => setValue(resetRolesMatrix(value))}>\n Reset to defaults\n </button>\n </div>\n <ArrayField {...props} />\n </div>\n );\n};\n","import { useRowLabel } from \"@payloadcms/ui\";\n\nimport { isRole, roleLabel } from \"../roles/types\";\n\n/**\n * Array row header. Shows the current display name, not “Role 01”.\n */\nexport function RolesRowLabel() {\n const { data } = useRowLabel<{ label?: string | null; role?: string | null; seed?: string | null }>();\n const role = typeof data.role === \"string\" ? data.role : \"\";\n const seed = typeof data.seed === \"string\" && data.seed ? data.seed : isRole(role) ? role : \"\";\n const label = roleLabel(role, data.label) || \"Role\";\n return (\n <span data-role-slug={role} data-role-seed={seed}>\n {label}\n </span>\n );\n}\n","import { FieldDescription, FieldError, FieldLabel, fieldBaseClass, useField } from \"@payloadcms/ui\";\nimport type { TextFieldClientComponent } from \"payload\";\n\nimport { isRole } from \"../roles/types\";\n\n/**\n * Seed slugs stay read-only. A custom row's slug is typed here.\n */\nexport const RoleSlugField: TextFieldClientComponent = ({ field, path, readOnly }) => {\n const { value, setValue, showError, errorMessage } = useField<string>({ path });\n const locked = Boolean(readOnly) || isRole(value);\n const required = Boolean(field.required);\n const id = `field-${path.replace(/\\./g, \"__\")}`;\n\n return (\n <div className={[fieldBaseClass, \"text\", locked && \"read-only\"].filter(Boolean).join(\" \")}>\n <FieldLabel htmlFor={id} label={field.label} required={required} />\n <div className={`${fieldBaseClass}__wrap`}>\n <FieldError message={errorMessage} path={path} showError={showError} />\n <input\n id={id}\n data-role-slug={value ?? \"\"}\n type=\"text\"\n autoComplete=\"off\"\n spellCheck={false}\n readOnly={locked}\n disabled={locked}\n value={value ?? \"\"}\n onChange={(event) => {\n if (!locked) setValue(event.target.value);\n }}\n />\n </div>\n <FieldDescription description={field.admin?.description} path={path} />\n </div>\n );\n};\n","import { FieldDescription, FieldError, FieldLabel, fieldBaseClass, useField } from \"@payloadcms/ui\";\nimport type { TextFieldClientComponent } from \"payload\";\n\nimport { sanitizeRoleNameInput } from \"../roles/types\";\n\n/**\n * Role name. Letters and spaces only, so the hidden slug stays\n * `the-greatest-designer` from `The Greatest Designer`.\n */\nexport const RoleNameField: TextFieldClientComponent = ({ field, path, readOnly }) => {\n const { value, setValue, showError, errorMessage } = useField<string>({ path });\n const required = Boolean(field.required);\n const id = `field-${path.replace(/\\./g, \"__\")}`;\n\n return (\n <div className={[fieldBaseClass, \"text\", readOnly && \"read-only\"].filter(Boolean).join(\" \")}>\n <FieldLabel htmlFor={id} label={field.label} required={required} />\n <div className={`${fieldBaseClass}__wrap`}>\n <FieldError message={errorMessage} path={path} showError={showError} />\n <input\n id={id}\n type=\"text\"\n autoComplete=\"off\"\n spellCheck={false}\n readOnly={Boolean(readOnly)}\n disabled={Boolean(readOnly)}\n value={value ?? \"\"}\n onChange={(event) => {\n if (!readOnly) setValue(sanitizeRoleNameInput(event.target.value));\n }}\n />\n </div>\n <FieldDescription description={field.admin?.description} path={path} />\n </div>\n );\n};\n","import type { OptionObject, SelectFieldClientComponent, Validate } from \"payload\";\nimport {\n CheckboxInput,\n FieldDescription,\n FieldError,\n FieldLabel,\n fieldBaseClass,\n useConfig,\n useField,\n} from \"@payloadcms/ui\";\nimport { useCallback, useEffect, useState } from \"react\";\n\nimport { parseRolesMatrix, roleDescription, roleSelectOptions, ROLES_SLUG } from \"../roles/matrix\";\nimport { roleLabel } from \"../roles/types\";\n\nconst GRID_CSS = `.bl-roles__grid{display:grid;gap:.75rem;grid-template-columns:repeat(auto-fit,minmax(12rem,1fr));margin-block:.35rem 0}.bl-roles__option{display:flex;flex-direction:column;gap:.25rem;padding:.65rem .75rem;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:8px}.bl-roles__option.is-checked{border-color:var(--theme-elevation-400,#94a3b8)}.bl-roles__option.is-included{opacity:.7}.bl-roles__what{font-size:.8rem;line-height:1.35;color:var(--theme-elevation-500,#64748b)}`;\n\nfunction optionValue(option: string | OptionObject): string {\n return typeof option === \"string\" ? option : String(option.value);\n}\n\nfunction optionLabel(option: string | OptionObject): string {\n return typeof option === \"string\" ? option : String(option.label);\n}\n\nfunction useOfferedRoles(fallback: { value: string; label: string }[]) {\n const { config } = useConfig();\n const [live, setLive] = useState<typeof fallback | null>(null);\n const api = config?.routes?.api;\n const serverURL = config?.serverURL ?? \"\";\n\n useEffect(() => {\n if (!api) return;\n let cancelled = false;\n fetch(`${serverURL}${api}/globals/${ROLES_SLUG}?depth=0`, { credentials: \"include\" })\n .then((response) => (response.ok ? response.json() : null))\n .then((doc: { roles?: unknown } | null) => {\n if (cancelled || !doc) return;\n const parsed = parseRolesMatrix(doc.roles);\n if (parsed.ok) setLive(roleSelectOptions(parsed.rows));\n })\n .catch(() => undefined);\n return () => {\n cancelled = true;\n };\n }, [api, serverURL]);\n\n return live ?? fallback;\n}\n\n/**\n * Users Roles checklist. Order and labels come from the field options (the\n * Roles Global, or the seed plus extras). Copy is `roleDescription`.\n * Developer is exclusive; a custom role does not clear Designer.\n */\nexport const RolesField: SelectFieldClientComponent = ({\n field,\n path: pathFromProps,\n readOnly,\n validate,\n}) => {\n const { admin: { description } = {}, label, localized, options = [], required } = field;\n const fallback = (options.length ? options : roleSelectOptions()).map((option) => ({\n value: optionValue(option),\n label: optionLabel(option),\n }));\n const offered = useOfferedRoles(fallback);\n\n const memoizedValidate = useCallback<Validate>(\n (value, validationOptions) => {\n if (typeof validate === \"function\") {\n return validate(value, {\n ...validationOptions,\n hasMany: true,\n options,\n required,\n } as Parameters<typeof validate>[1]);\n }\n return true;\n },\n [validate, options, required],\n );\n\n const { disabled, errorMessage, path, setValue, showError, value } = useField<string[]>({\n potentiallyStalePath: pathFromProps,\n validate: memoizedValidate,\n });\n\n const selected: string[] = Array.isArray(value) ? value : [];\n const exclusive = selected.includes(\"developer\") ? \"developer\" : null;\n const locked = Boolean(readOnly) || disabled;\n\n function toggle(role: string): void {\n if (locked) return;\n if (role === \"developer\") {\n setValue(selected.includes(role) ? [] : [\"developer\"]);\n return;\n }\n if (exclusive) return;\n setValue(selected.includes(role) ? selected.filter((entry) => entry !== role) : [...selected, role]);\n }\n\n const groupLabel = typeof label === \"string\" ? label : \"Roles\";\n\n return (\n <div\n className={[fieldBaseClass, \"select\", \"bl-roles\", showError && \"error\", locked && \"read-only\"]\n .filter(Boolean)\n .join(\" \")}\n id={`field-${path.replace(/\\./g, \"__\")}`}\n >\n <style href=\"bl-roles\" precedence=\"default\">\n {GRID_CSS}\n </style>\n <FieldLabel as=\"span\" label={label} localized={localized} path={path} required={required} />\n <div className={`${fieldBaseClass}__wrap`}>\n <FieldError message={errorMessage} path={path} showError={showError} />\n <div aria-label={groupLabel} className=\"bl-roles__grid\" role=\"group\">\n {offered.map((option) => {\n const role = option.value;\n if (!role) return null;\n const included = exclusive !== null && role !== exclusive;\n const checked = selected.includes(role);\n return (\n <div\n className={[\"bl-roles__option\", checked && \"is-checked\", included && \"is-included\"]\n .filter(Boolean)\n .join(\" \")}\n key={role}\n >\n <CheckboxInput\n checked={checked}\n id={`${path}-${role}`}\n label={option.label || roleLabel(role)}\n onToggle={() => toggle(role)}\n readOnly={locked || included}\n />\n <span className=\"bl-roles__what\">\n {included ? \"Included in Developer\" : roleDescription(role)}\n </span>\n </div>\n );\n })}\n </div>\n </div>\n <FieldDescription description={description} path={path} />\n </div>\n );\n};\n","import { useConfig, useField } from \"@payloadcms/ui\";\nimport type { JSONFieldClientComponent } from \"payload\";\nimport { useEffect, useState } from \"react\";\n\nimport { defaultFeaturesFieldValue, featureGroupLabel, parseFeaturesMatrix } from \"../features/matrix\";\nimport { FEATURE_GROUPS, FEATURES_SLUG, type FeatureRow } from \"../features/types\";\n\nconst LIST_CSS = `.bl-role-grants{margin-block:.2rem 0;font-size:16px}.bl-role-grants__group{margin-block:.75rem 0}.bl-role-grants__group-title{font-size:13px;letter-spacing:.02em;color:var(--theme-elevation-400,#94a3b8);font-weight:650;margin-block-end:.25rem}.bl-role-grants__row{display:flex;align-items:center;gap:.65rem;padding:.35rem 0}.bl-role-grants__row.is-implicit{opacity:.85}.bl-role-grants input{inline-size:1.15rem;block-size:1.15rem}.bl-role-grants input:disabled{cursor:default}.bl-role-grants__note{margin-block:.35rem 0;font-size:13px;color:var(--theme-elevation-500,#64748b)}`;\n\nfunction asGrants(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.filter((entry): entry is string => typeof entry === \"string\");\n}\n\nfunction rolePathFromGrants(path: string): string {\n return path.replace(/\\.grants$/, \".role\");\n}\n\n/**\n * Released catalogue rows as ticks. Unreleased features do not appear,\n * except on Developer: every catalogue row is shown granted and locked\n * so a new Feature is visibly included.\n */\nexport const RolesGrantsField: JSONFieldClientComponent = (props) => {\n const { setValue, value } = useField({ path: props.path });\n const { value: role } = useField({ path: rolePathFromGrants(props.path) });\n const { config } = useConfig();\n const [catalogue, setCatalogue] = useState<FeatureRow[]>(defaultFeaturesFieldValue());\n const api = config?.routes?.api;\n const serverURL = config?.serverURL ?? \"\";\n const implicitAll = role === \"developer\";\n\n useEffect(() => {\n if (!api) return;\n let cancelled = false;\n fetch(`${serverURL}${api}/globals/${FEATURES_SLUG}?depth=0`, { credentials: \"include\" })\n .then((response) => (response.ok ? response.json() : null))\n .then((doc: { features?: unknown } | null) => {\n if (cancelled || !doc) return;\n const parsed = parseFeaturesMatrix(doc.features);\n if (parsed.ok) setCatalogue(parsed.rows);\n })\n .catch(() => undefined);\n return () => {\n cancelled = true;\n };\n }, [api, serverURL]);\n\n const grants = asGrants(value);\n const shown = implicitAll ? catalogue : catalogue.filter((row) => row.released);\n\n function toggle(slug: string, checked: boolean) {\n if (implicitAll) return;\n const next = new Set(grants);\n if (checked) next.add(slug);\n else next.delete(slug);\n setValue([...next]);\n }\n\n return (\n <div className=\"bl-role-grants\">\n <style href=\"bl-role-grants\" precedence=\"default\">\n {LIST_CSS}\n </style>\n {implicitAll ? (\n <p className=\"bl-role-grants__note\">Always granted, including features not yet released.</p>\n ) : null}\n {FEATURE_GROUPS.map((group) => {\n const members = shown.filter((row) => (row.group ?? \"users\") === group);\n if (members.length === 0) return null;\n return (\n <div key={group} className=\"bl-role-grants__group\">\n <div className=\"bl-role-grants__group-title\">{featureGroupLabel(group)}</div>\n {members.map((row) => (\n <label\n key={row.slug}\n className={[\"bl-role-grants__row\", implicitAll && \"is-implicit\"].filter(Boolean).join(\" \")}\n >\n <input\n type=\"checkbox\"\n aria-label={`${row.label || row.slug}`}\n checked={implicitAll || grants.includes(row.slug)}\n disabled={implicitAll}\n onChange={(event) => toggle(row.slug, event.target.checked)}\n />\n <span>{row.label || row.slug}</span>\n </label>\n ))}\n </div>\n );\n })}\n </div>\n );\n};\n","import { useConfig, useField } from \"@payloadcms/ui\";\nimport type { ArrayFieldClientComponent } from \"payload\";\nimport { useEffect } from \"react\";\n\nimport { featureGroupLabel } from \"../features/matrix\";\nimport { FEATURE_GROUPS, FEATURES_SLUG, type FeatureRow } from \"../features/types\";\n\nconst LIST_CSS = `.bl-features{margin-block:.35rem 0;font-size:16px}.bl-features__group{margin-block:1rem 0}.bl-features__group-title{font-size:14px;letter-spacing:.02em;color:var(--theme-elevation-400,#94a3b8);font-weight:650;margin-block-end:.35rem}.bl-features__row{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:.55rem 0;border-bottom:1px solid var(--theme-elevation-150,#e2e8f0)}.bl-features__row:last-child{border-bottom:0}.bl-features input{inline-size:1.15rem;block-size:1.15rem}`;\n\nfunction asRows(value: unknown): FeatureRow[] {\n return Array.isArray(value) ? (value as FeatureRow[]) : [];\n}\n\nfunction FeatureReleaseRow({\n path,\n index,\n row,\n rows,\n setRows,\n}: {\n path: string;\n index: number;\n row: FeatureRow;\n rows: FeatureRow[];\n setRows: (next: FeatureRow[]) => void;\n}) {\n const { setValue: setReleased } = useField({ path: `${path}.${index}.released` });\n\n return (\n <div className=\"bl-features__row\">\n <span>{row.label || row.slug}</span>\n <input\n type=\"checkbox\"\n aria-label={`Release ${row.label || row.slug}`}\n checked={Boolean(row.released)}\n onChange={(event) => {\n const released = event.target.checked;\n setReleased(released);\n setRows(rows.map((entry) => (entry.slug === row.slug ? { ...entry, released } : entry)));\n }}\n />\n </div>\n );\n}\n\n/**\n * One release switch per catalogue row, grouped. Off hides the tick on\n * Roles; Developer still has the feature.\n *\n * Writes both the array value and each row's `released` checkbox path.\n * Payload still registers those child fields; toggling only the parent\n * array leaves them false and Save stores the old flags.\n */\nexport const FeaturesMatrixField: ArrayFieldClientComponent = (props) => {\n const { setValue, value } = useField({ path: props.path });\n const { config } = useConfig();\n const api = config?.routes?.api;\n const serverURL = config?.serverURL ?? \"\";\n\n useEffect(() => {\n if (!api || asRows(value).length > 0) return;\n let cancelled = false;\n fetch(`${serverURL}${api}/globals/${FEATURES_SLUG}?depth=0`, { credentials: \"include\" })\n .then((response) => (response.ok ? response.json() : null))\n .then((doc: { features?: unknown } | null) => {\n if (cancelled || !doc) return;\n const incoming = asRows(doc.features);\n if (incoming.length > 0) setValue(incoming, true);\n })\n .catch(() => undefined);\n return () => {\n cancelled = true;\n };\n }, [api, serverURL, setValue, value]);\n\n const rows = asRows(value);\n\n return (\n <div className=\"bl-features\">\n <style href=\"bl-features\" precedence=\"default\">\n {LIST_CSS}\n </style>\n {FEATURE_GROUPS.map((group) => {\n const members = rows\n .map((row, index) => ({ row, index }))\n .filter(({ row }) => (row.group ?? \"users\") === group);\n if (members.length === 0) return null;\n return (\n <div key={group} className=\"bl-features__group\">\n <div className=\"bl-features__group-title\">{featureGroupLabel(group)}</div>\n {members.map(({ row, index }) => (\n <FeatureReleaseRow\n key={row.slug}\n path={props.path}\n index={index}\n row={row}\n rows={rows}\n setRows={(next) => setValue(next)}\n />\n ))}\n </div>\n );\n })}\n </div>\n );\n};\n","\"use client\";\n\nimport { KitProvider } from \"@bison-lab/admin-ui\";\nimport { isThemeHex } from \"@bison-lab/tokens\";\nimport { useConfig } from \"@payloadcms/ui\";\nimport { useEffect, useState, type ReactNode } from \"react\";\n\nfunction primaryHex(doc: { colors?: { brand?: { primary?: { hex?: string } } } } | null): string | undefined {\n const hex = doc?.colors?.brand?.primary?.hex;\n return typeof hex === \"string\" && isThemeHex(hex) ? hex : undefined;\n}\n\n/**\n * Site Theme primary → `--bl-kit-accent`. Saved value for the whole\n * admin; the Primary color card also writes the live hex so pickers\n * and kit chrome update as the field is edited.\n */\nexport function ThemeKitAccent({ children }: { children: ReactNode }) {\n const { config } = useConfig();\n const [accent, setAccent] = useState<string | undefined>();\n\n useEffect(() => {\n const url = `${config.serverURL}${config.routes.api}/globals/theme?depth=0`;\n let cancelled = false;\n\n function load() {\n void fetch(url, { credentials: \"include\" })\n .then((response) => (response.ok ? response.json() : null))\n .then((doc) => {\n const hex = primaryHex(doc);\n if (!cancelled && hex) setAccent(hex);\n })\n .catch(() => undefined);\n }\n\n load();\n const onVis = () => {\n if (document.visibilityState === \"visible\") load();\n };\n document.addEventListener(\"visibilitychange\", onVis);\n return () => {\n cancelled = true;\n document.removeEventListener(\"visibilitychange\", onVis);\n };\n }, [config.serverURL, config.routes.api]);\n\n return <KitProvider accent={accent}>{children}</KitProvider>;\n}\n","\"use client\";\n\nimport { useLayoutEffect, type ReactNode } from \"react\";\n\nimport { ThemeKitAccent } from \"./theme-kit-accent\";\n\n/**\n * Shared document header: title on the left, primary actions on the\n * right — the same slot collection lists use for Create New.\n *\n * Payload parks Edit / Versions / API in that slot and puts Save one\n * row down. This moves `.doc-controls__controls-wrapper` (Save,\n * Preview, Create New, and the kebab) onto the title row, hides the\n * active Edit tab (you are already on the form), and collapses the\n * leftover controls band when it has no meta.\n *\n * Mounted as `admin.components.providers` so Account and every\n * collection / global share one lift. A MutationObserver re-applies\n * after Payload redraws the controls.\n */\nconst TITLE_ACTIONS_CSS = `\n.doc-header__header{display:flex;align-items:center;justify-content:flex-start;width:100%;gap:10px}\n.doc-header__title{flex:0 1 auto;min-width:0}\n.doc-header__header > .doc-controls__controls-wrapper{margin-left:auto;display:flex;align-items:center;gap:8px}\n.doc-tab.doc-tab--active.btn--disabled{display:none}\n.doc-tabs:not(:has(.doc-tab:not(.doc-tab--active))){display:none}\n.doc-controls:has(.doc-controls__meta:empty):not(:has(.doc-controls__controls-wrapper)){height:0;min-height:0;padding:0;overflow:hidden}\n.doc-controls:has(.doc-controls__meta:empty):not(:has(.doc-controls__controls-wrapper)) .doc-controls__divider{display:none}\n`;\n\nfunction liftTitleActions() {\n const header = document.querySelector(\".doc-header__header\");\n const wrapper = document.querySelector(\".doc-controls__controls-wrapper\");\n if (!header || !wrapper) return;\n if (wrapper.parentElement === header) return;\n header.appendChild(wrapper);\n}\n\nexport function DocumentTitleActions({ children }: { children?: ReactNode }) {\n useLayoutEffect(() => {\n liftTitleActions();\n const observer = new MutationObserver(liftTitleActions);\n observer.observe(document.body, { childList: true, subtree: true });\n return () => observer.disconnect();\n }, []);\n\n return (\n <ThemeKitAccent>\n <style href=\"bl-doc-title-actions\" precedence=\"default\">\n {TITLE_ACTIONS_CSS}\n </style>\n {children}\n </ThemeKitAccent>\n );\n}\n","\"use client\";\n\nimport { Button, useForm } from \"@payloadcms/ui\";\n\n/**\n * Same words as a collection list Create New — no icon, no \"Area\" or\n * \"Role.\" The page title already says what is created. Primary so a\n * site's admin skin can paint it with Theme `--primary`.\n *\n * Hides the array's own Add while this control is mounted so the\n * action is not offered twice.\n */\nconst HIDE_FIELD_ADD = `.array-field__add-row{display:none}`;\n\nexport function DocumentCreateNew({ path }: { path: string }) {\n const { addFieldRow, disabled } = useForm();\n\n return (\n <>\n <style href=\"bl-doc-create-new\" precedence=\"default\">\n {HIDE_FIELD_ADD}\n </style>\n <Button\n buttonStyle=\"primary\"\n size=\"medium\"\n type=\"button\"\n disabled={disabled}\n onClick={() => {\n addFieldRow({ path, schemaPath: path });\n }}\n >\n Create New\n </Button>\n </>\n );\n}\n","/**\n * Developer-owned admin sidebar. SPI-10 skins this with AppSidebarBlock;\n * this package ships the document and the default Nav. A consuming site\n * waits for SPI-97 after this and BIS-110 publish.\n */\n\nexport const ADMIN_NAV_SLUG = \"admin-nav\";\n\nexport type AdminNavEntityType = \"collection\" | \"global\";\n\nexport interface AdminNavItem {\n type: AdminNavEntityType;\n slug: string;\n label: string;\n}\n\nexport interface AdminNavGroup {\n label: string;\n items: AdminNavItem[];\n}\n\nexport interface AdminNavDoc {\n groups?: Array<{\n id?: string | null;\n label?: string | null;\n items?: Array<{\n id?: string | null;\n type?: string | null;\n slug?: string | null;\n }> | null;\n }> | null;\n}\n\nexport interface AdminNavVisibleEntities {\n collections?: readonly string[];\n globals?: readonly string[];\n}\n\nexport interface AdminNavEntityConfig {\n slug: string;\n admin?: { group?: unknown };\n label?: unknown;\n labels?: { plural?: unknown; singular?: unknown };\n}\n\nexport interface AdminNavConfig {\n collections?: readonly AdminNavEntityConfig[];\n globals?: readonly AdminNavEntityConfig[];\n}\n\nexport interface ResolveAdminNavArgs {\n config: AdminNavConfig;\n doc?: AdminNavDoc | null;\n visibleEntities?: AdminNavVisibleEntities;\n}\n","import type {\n AdminNavConfig,\n AdminNavDoc,\n AdminNavEntityConfig,\n AdminNavEntityType,\n AdminNavGroup,\n AdminNavItem,\n ResolveAdminNavArgs,\n} from \"./types\";\n\nfunction sidebarGroup(group: unknown): string | false {\n if (group === false) return false;\n if (typeof group === \"string\") return group;\n return \"\";\n}\n\nfunction asLabel(value: unknown, fallback: string): string {\n return typeof value === \"string\" && value ? value : fallback;\n}\n\nfunction entityLabel(entity: AdminNavEntityConfig, type: AdminNavEntityType): string {\n if (type === \"collection\") {\n return asLabel(entity.labels?.plural, asLabel(entity.labels?.singular, entity.slug));\n }\n return asLabel(entity.label, entity.slug);\n}\n\nfunction keyOf(type: AdminNavEntityType, slug: string): string {\n return `${type}:${slug}`;\n}\n\ninterface CatalogEntry {\n type: AdminNavEntityType;\n slug: string;\n label: string;\n group: string | false;\n}\n\nfunction catalog(config: AdminNavConfig): CatalogEntry[] {\n const collections = (config.collections ?? []).map((entity) => ({\n type: \"collection\" as const,\n slug: entity.slug,\n label: entityLabel(entity, \"collection\"),\n group: sidebarGroup(entity.admin?.group),\n }));\n const globals = (config.globals ?? []).map((entity) => ({\n type: \"global\" as const,\n slug: entity.slug,\n label: entityLabel(entity, \"global\"),\n group: sidebarGroup(entity.admin?.group),\n }));\n return [...collections, ...globals];\n}\n\nfunction defaultGroups(entities: readonly CatalogEntry[]): AdminNavGroup[] {\n const groups: AdminNavGroup[] = [];\n for (const entity of entities) {\n if (entity.group === false) continue;\n let group = groups.find((entry) => entry.label === entity.group);\n if (!group) {\n group = { label: entity.group, items: [] };\n groups.push(group);\n }\n group.items.push({ type: entity.type, slug: entity.slug, label: entity.label });\n }\n return groups;\n}\n\nfunction itemFromSaved(\n item: { type?: string | null; slug?: string | null },\n byKey: Map<string, CatalogEntry>,\n): AdminNavItem | null {\n const type = item.type === \"global\" || item.type === \"collection\" ? item.type : null;\n const slug = typeof item.slug === \"string\" ? item.slug : \"\";\n if (!type || !slug) return null;\n const entity = byKey.get(keyOf(type, slug));\n if (!entity || entity.group === false) return null;\n return { type, slug, label: entity.label };\n}\n\nfunction fromDocument(doc: AdminNavDoc, entities: readonly CatalogEntry[]): AdminNavGroup[] {\n const byKey = new Map(entities.map((entity) => [keyOf(entity.type, entity.slug), entity]));\n return (doc.groups ?? []).map((row) => ({\n label: typeof row.label === \"string\" ? row.label : \"\",\n items: (row.items ?? []).flatMap((item) => {\n const resolved = itemFromSaved(item ?? {}, byKey);\n return resolved ? [resolved] : [];\n }),\n }));\n}\n\n/**\n * Layout for the package Nav (and later SPI-10). Permissions are\n * `visibleEntities` — this function does not re-derive access.\n */\nexport function resolveAdminNav({ config, doc, visibleEntities }: ResolveAdminNavArgs): AdminNavGroup[] {\n const entities = catalog(config);\n const saved = Array.isArray(doc?.groups) ? doc.groups : [];\n let groups = saved.length === 0 ? defaultGroups(entities) : fromDocument({ groups: saved }, entities);\n\n if (visibleEntities) {\n const collections = new Set(visibleEntities.collections ?? []);\n const globals = new Set(visibleEntities.globals ?? []);\n groups = groups.map((group) => ({\n ...group,\n items: group.items.filter((item) =>\n item.type === \"collection\" ? collections.has(item.slug) : globals.has(item.slug),\n ),\n }));\n }\n\n return groups;\n}\n","import { useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { Link, Logout, NavGroup, NavToggler, useConfig, useNav } from \"@payloadcms/ui\";\n\nimport { ADMIN_NAV_SLUG } from \"../admin-nav/types\";\nimport { resolveAdminNav } from \"../admin-nav/resolve\";\nimport type { AdminNavDoc, AdminNavVisibleEntities } from \"../admin-nav/types\";\n\nexport interface AdminNavProps {\n visibleEntities?: AdminNavVisibleEntities;\n}\n\nconst BASE = \"nav\";\n\n/** Survives AdminNav remounting on every admin route so the first-seen walk does not flash. */\nlet cachedDoc: AdminNavDoc | null | undefined;\n\nexport function resetAdminNavCache() {\n cachedDoc = undefined;\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof DOMException\n ? error.name === \"AbortError\"\n : error instanceof Error && error.name === \"AbortError\";\n}\n\n/**\n * Payload's DefaultNav roots in an `@internal` NavWrapper. Copy the\n * class contract here — this package does not depend on `@payloadcms/next`.\n * Without `nav--nav-open`, Payload's CSS keeps `.nav` at opacity 0.\n */\nfunction AdminNavShell({ children }: { children: ReactNode }) {\n const { hydrated, navOpen, navRef, shouldAnimate } = useNav();\n const className = [\n BASE,\n navOpen && `${BASE}--nav-open`,\n shouldAnimate && `${BASE}--nav-animate`,\n hydrated && `${BASE}--nav-hydrated`,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <aside className={className} inert={navOpen ? undefined : true}>\n <div className={`${BASE}__scroll`} ref={navRef}>\n {children}\n </div>\n </aside>\n );\n}\n\n/**\n * Default admin sidebar. Reads the Admin nav Global and paints\n * `resolveAdminNav`. SPI-10 may replace this component; it should keep\n * calling that function so the document stays the one layout source.\n */\nexport function AdminNav({ visibleEntities }: AdminNavProps) {\n const { config } = useConfig();\n const [doc, setDoc] = useState<AdminNavDoc | null>(() => cachedDoc ?? null);\n const adminRoute = config.routes.admin ?? \"/admin\";\n const apiRoute = config.routes.api ?? \"/api\";\n\n useEffect(() => {\n const controller = new AbortController();\n const url = `${config.serverURL ?? \"\"}${apiRoute}/globals/${ADMIN_NAV_SLUG}`;\n void fetch(url, { credentials: \"include\", signal: controller.signal })\n .then((response) => (response.ok ? response.json() : null))\n .then((payload: AdminNavDoc | null) => {\n if (controller.signal.aborted) return;\n cachedDoc = payload;\n setDoc(payload);\n })\n .catch((error: unknown) => {\n if (isAbortError(error) || controller.signal.aborted) return;\n if (cachedDoc !== undefined) return;\n cachedDoc = null;\n setDoc(null);\n });\n return () => controller.abort();\n }, [apiRoute, config.serverURL]);\n\n const groups = useMemo(\n () => resolveAdminNav({ config, doc, visibleEntities }),\n [config, doc, visibleEntities],\n );\n\n return (\n <AdminNavShell>\n <nav className={`${BASE}__wrap`} aria-label=\"Admin\">\n <div className={`${BASE}__links`}>\n {groups.map((group, index) => {\n const items = group.items.map((item) => {\n const href =\n item.type === \"collection\"\n ? `${adminRoute}/collections/${item.slug}`\n : `${adminRoute}/globals/${item.slug}`;\n return (\n <Link\n key={`${item.type}:${item.slug}`}\n className={`${BASE}__link`}\n href={href}\n prefetch={false}\n >\n <span className={`${BASE}__link-label`}>{item.label}</span>\n </Link>\n );\n });\n if (!group.label) {\n return (\n <div key={`ungrouped-${index}`} className={`${BASE}__ungrouped`}>\n {items}\n </div>\n );\n }\n return (\n <NavGroup key={`${group.label}-${index}`} label={group.label}>\n {items}\n </NavGroup>\n );\n })}\n </div>\n <div className={`${BASE}__controls`}>\n <Logout />\n </div>\n </nav>\n <div className={`${BASE}__header`}>\n <div className={`${BASE}__header-content`}>\n <NavToggler />\n </div>\n </div>\n </AdminNavShell>\n );\n}\n","import { useRowLabel } from \"@payloadcms/ui\";\n\n/**\n * Array row header. Shows the group label, or “Group” when empty.\n */\nexport function AdminNavRowLabel() {\n const { data } = useRowLabel<{ label?: string | null }>();\n const label = typeof data.label === \"string\" && data.label.trim() ? data.label.trim() : \"Group\";\n return <span>{label}</span>;\n}\n","import type { AdminNavConfig, AdminNavEntityType } from \"./types\";\n\nexport interface AdminNavEntityOption {\n value: string;\n label: string;\n}\n\nfunction entityType(type: unknown): AdminNavEntityType {\n return type === \"global\" ? \"global\" : \"collection\";\n}\n\n/**\n * Collections or globals a Developer may pin. Sibling Type decides which\n * list. `group: false` stays off — those entities are not on the sidebar.\n */\nexport function adminNavEntityOptions(\n config: AdminNavConfig,\n type: unknown,\n): AdminNavEntityOption[] {\n const kind = entityType(type);\n const entities = kind === \"global\" ? (config.globals ?? []) : (config.collections ?? []);\n return entities\n .filter((entity) => entity.admin?.group !== false)\n .map((entity) => ({\n value: entity.slug,\n label:\n kind === \"global\"\n ? typeof entity.label === \"string\" && entity.label\n ? entity.label\n : entity.slug\n : typeof entity.labels?.plural === \"string\" && entity.labels.plural\n ? entity.labels.plural\n : entity.slug,\n }));\n}\n\n/** Array row title. Empty slug falls back to “Item”, never “Item 01”. */\nexport function adminNavEntityLabel(config: AdminNavConfig, type: unknown, slug: unknown): string {\n if (typeof slug !== \"string\" || !slug) return \"Item\";\n return adminNavEntityOptions(config, type).find((option) => option.value === slug)?.label ?? slug;\n}\n","import { useConfig, useRowLabel } from \"@payloadcms/ui\";\n\nimport { adminNavEntityLabel } from \"../admin-nav/entity-options\";\n\n/**\n * Item accordion title. Shows the chosen collection or global name\n * (Pages), or “Item” when the row is still empty.\n */\nexport function AdminNavItemRowLabel() {\n const { data } = useRowLabel<{ type?: string | null; slug?: string | null }>();\n const { config } = useConfig();\n return <span>{adminNavEntityLabel(config, data.type, data.slug)}</span>;\n}\n","import { SelectField, useConfig, useField } from \"@payloadcms/ui\";\nimport type { SelectFieldClient, TextFieldClientComponent } from \"payload\";\n\nimport { adminNavEntityOptions } from \"../admin-nav/entity-options\";\n\n/**\n * Payload's select of collections or globals. Subscribes to sibling Type\n * with `useField` so the list updates when Type changes — `getDataByPath`\n * does not re-render this field.\n */\nexport const AdminNavEntityField: TextFieldClientComponent = ({\n field,\n path,\n permissions,\n readOnly,\n schemaPath,\n}) => {\n const { value: type } = useField<string>({ path: path.replace(/\\.slug$/, \".type\") });\n const { config } = useConfig();\n const options = adminNavEntityOptions(config, type);\n\n return (\n <SelectField\n field={\n {\n name: field.name,\n label: field.label,\n required: field.required,\n admin: {\n ...field.admin,\n isClearable: false,\n isSortable: false,\n placeholder: \"Select…\",\n },\n type: \"select\",\n hasMany: false,\n options,\n } as SelectFieldClient\n }\n path={path}\n permissions={permissions}\n readOnly={readOnly}\n schemaPath={schemaPath}\n />\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"admin.mjs","names":["CSS","CSS","CSS","CSS","CSS","Button","LIST_CSS"],"sources":["../src/admin/color-field.tsx","../src/theme/appearance-labels.ts","../src/theme/readability.ts","../src/admin/portal.tsx","../src/admin/brand-hex-field.tsx","../src/admin/colors-layout.ts","../src/admin/preview-mode.tsx","../src/admin/readability-list.tsx","../src/admin/color-scale-card.tsx","../src/admin/color-scale-field.tsx","../src/theme/library.ts","../src/theme/color-usages.ts","../src/admin/library-field.tsx","../src/admin/typography-pairing.tsx","../src/admin/font-field.tsx","../src/admin/pairing-field.tsx","../src/admin/appearance-choices.tsx","../src/admin/appearance-field.tsx","../src/admin/grey-scale-field.tsx","../src/admin/contrast-report.tsx","../src/admin/section-heading.tsx","../src/theme/changes.ts","../src/theme/publish.ts","../src/admin/publish-confirm.tsx","../src/admin/publish-child.tsx","../src/admin/theme-tab.ts","../src/admin/save-button.tsx","../src/admin/identity-fallback.tsx","../src/admin/look-field.tsx","../src/features/types.ts","../src/features/matrix.ts","../src/roles/types.ts","../src/roles/matrix.ts","../src/admin/roles-matrix-field.tsx","../src/admin/roles-row-label.tsx","../src/admin/role-slug-field.tsx","../src/fields/slug.ts","../src/admin/slug-field.tsx","../src/admin/role-name-field.tsx","../src/admin/roles-field.tsx","../src/admin/roles-grants-field.tsx","../src/admin/features-matrix-field.tsx","../src/admin/theme-kit-accent.tsx","../src/admin/document-title-actions.tsx","../src/admin/document-create-new.tsx","../src/admin-nav/types.ts","../src/admin-nav/resolve.ts","../src/admin/admin-nav.tsx","../src/admin/admin-nav-row-label.tsx","../src/admin-nav/entity-options.ts","../src/admin/admin-nav-item-row-label.tsx","../src/admin/admin-nav-entity-field.tsx"],"sourcesContent":["import { FieldDescription, FieldError, FieldLabel, useField } from \"@payloadcms/ui\";\nimport { isThemeHex } from \"@bison-lab/tokens\";\nimport type { TextFieldClientComponent } from \"payload\";\nimport { useEffect, useId, useState } from \"react\";\n\nconst HEX_ERROR = \"Enter a six-digit hex colour like #1e3a5f\";\n\n/**\n * Swatch, native colour input, and hex text, kept in step. `#rrggbb` on\n * blur; the field's `validate` refuses anything else on save.\n */\nexport const ColorField: TextFieldClientComponent = ({ field, path, readOnly }) => {\n const { value, setValue, showError, errorMessage } = useField<string>({ path });\n const [text, setText] = useState(value ?? \"\");\n const [localError, setLocalError] = useState<string | null>(null);\n const id = useId();\n const hexId = `${id}-hex`;\n const pickerId = `${id}-picker`;\n const required = Boolean(field.required);\n const valid = isThemeHex(value);\n const message = localError ?? errorMessage;\n const show = Boolean(localError) || showError;\n\n useEffect(() => {\n setText(value ?? \"\");\n }, [value]);\n\n function commit(next: string) {\n const trimmed = next.trim();\n if (isThemeHex(trimmed)) {\n setValue(trimmed);\n setLocalError(null);\n return;\n }\n setLocalError(HEX_ERROR);\n }\n\n return (\n <div className=\"field-type bl-color-field\">\n <style href=\"bl-color-field\" precedence=\"default\">\n {CSS}\n </style>\n <FieldLabel htmlFor={hexId} label={field.label} required={required} />\n <div className=\"bl-color-field__control\">\n <span\n className=\"bl-color-field__swatch\"\n aria-hidden=\"true\"\n style={{ background: valid ? value : \"transparent\" }}\n />\n <input\n id={pickerId}\n type=\"color\"\n className=\"bl-color-field__picker\"\n disabled={readOnly}\n value={valid ? value : \"#000000\"}\n aria-label={`${typeof field.label === \"string\" ? field.label : \"Colour\"} picker`}\n onChange={(event) => {\n setValue(event.target.value);\n setText(event.target.value);\n setLocalError(null);\n }}\n />\n <input\n id={hexId}\n type=\"text\"\n className=\"bl-color-field__hex\"\n spellCheck={false}\n autoComplete=\"off\"\n disabled={readOnly}\n value={text}\n onChange={(event) => {\n setText(event.target.value);\n if (isThemeHex(event.target.value.trim())) {\n setValue(event.target.value.trim());\n setLocalError(null);\n }\n }}\n onBlur={() => commit(text)}\n />\n </div>\n <FieldDescription description={field.admin?.description} path={path} />\n <FieldError path={path} showError={show} message={message} />\n </div>\n );\n};\n\nconst CSS = `\n.bl-color-field__control{display:flex;align-items:center;gap:calc(var(--base) * .4)}\n.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)}\n.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}\n.bl-color-field__picker:disabled{cursor:not-allowed;opacity:.6}\n.bl-color-field__hex{flex:1;min-width:0;min-height:calc(var(--base) * 2);padding:calc(var(--base) * .25) calc(var(--base) * .6);border:1px solid var(--theme-elevation-150);border-radius:var(--style-radius-s);background:var(--theme-input-bg);color:var(--theme-elevation-800);font-family:var(--font-mono);font-size:13px}\n.bl-color-field__hex:focus{border-color:var(--theme-elevation-400);outline:none;box-shadow:0 0 0 1px var(--theme-elevation-400)}\n.bl-color-field__hex:disabled{color:var(--theme-elevation-400)}\n`;\n","/**\n * Named choices the Appearance child shows. Values stay the token presets;\n * labels match the mock workflow (Soft → pill, Gentle → minimal, Balanced\n * → default, Follow device → system). No rem, ms, or CSS variable tables.\n */\nexport const APPEARANCE_CHOICES = {\n defaultTheme: {\n light: { label: \"Light\", hint: \"Always opens in light mode\" },\n dark: { label: \"Dark\", hint: \"Always opens in dark mode\" },\n system: { label: \"Follow device\", hint: \"Matches the visitor’s system setting\" },\n },\n radius: {\n sharp: { label: \"Sharp\", hint: \"Crisp and structured\" },\n subtle: { label: \"Subtle\", hint: \"Clean with a little softness\" },\n rounded: { label: \"Rounded\", hint: \"Friendly and contemporary\" },\n pill: { label: \"Soft\", hint: \"Very rounded and expressive\" },\n },\n shadow: {\n flat: { label: \"Flat\", hint: \"Minimal visual depth\" },\n subtle: { label: \"Subtle\", hint: \"Light separation between surfaces\" },\n elevated: { label: \"Elevated\", hint: \"More noticeable layering and depth\" },\n },\n motion: {\n snappy: { label: \"Quick\", hint: \"Fast and responsive\" },\n smooth: { label: \"Smooth\", hint: \"Balanced and natural\" },\n minimal: { label: \"Gentle\", hint: \"Slower and more relaxed\" },\n },\n density: {\n compact: { label: \"Compact\", hint: \"Fits more content on screen\" },\n default: { label: \"Balanced\", hint: \"Comfortable for most sites\" },\n spacious: { label: \"Spacious\", hint: \"More breathing room and larger controls\" },\n },\n} as const;\n\nexport const APPEARANCE_FAMILY_COPY: Record<\n keyof typeof APPEARANCE_CHOICES,\n { title: string; hint: string }\n> = {\n defaultTheme: {\n title: \"Default theme\",\n hint: \"Choose how the public site opens for visitors.\",\n },\n radius: {\n title: \"Corner style\",\n hint: \"Controls the shape of buttons, inputs, cards, and panels across the site.\",\n },\n shadow: {\n title: \"Depth\",\n hint: \"Choose how much cards and floating elements stand out from the page.\",\n },\n motion: {\n title: \"Motion\",\n hint: \"Controls how quickly menus, cards, and interface transitions move.\",\n },\n density: {\n title: \"Spacing\",\n hint: \"Choose how compact or roomy forms, buttons, cards, and page sections feel.\",\n },\n};\n\nexport const FONT_ROLE_COPY = {\n heading: {\n label: \"Heading font\",\n hint: \"Used for page titles, section headings, and cards\",\n },\n body: {\n label: \"Body font\",\n hint: \"Used for paragraphs, navigation, forms, and buttons\",\n },\n} as const;\n\nexport const SYSTEM_COLOR_COPY: Record<\n \"primary\" | \"secondary\" | \"accent\" | \"highlight\" | \"success\" | \"destructive\",\n { label: string; hint: string; group: \"brand\" | \"status\" }\n> = {\n primary: { label: \"Primary\", hint: \"Primary actions and key links\", group: \"brand\" },\n secondary: { label: \"Secondary\", hint: \"Supporting accents and eyebrows\", group: \"brand\" },\n accent: { label: \"Accent\", hint: \"Dark brand surfaces\", group: \"brand\" },\n highlight: { label: \"Highlight\", hint: \"Promotional and emphasis fills\", group: \"brand\" },\n success: {\n label: \"Success\",\n hint: \"Success messages and confirmations\",\n group: \"status\",\n },\n destructive: {\n label: \"Destructive\",\n hint: \"Errors, dangerous actions, and destructive confirmations\",\n group: \"status\",\n },\n};\n","import {\n contrastForeground,\n contrastRatio,\n hexToHSL,\n hslToString,\n isThemeHex,\n type HSL,\n} from \"@bison-lab/tokens\";\n\n/** Same threshold `deriveDarkPalette` uses for brand fills. */\nconst DARK_FILL_LIGHTEN_BELOW = 40;\nconst DARK_FILL_LIGHTEN_BY = 25;\n\nexport const READABILITY_TARGET = 7;\n\nexport interface FillLabelSample {\n ratio: number;\n shortfall: number;\n fill: string;\n label: string;\n}\n\nexport interface FillLabelWarning {\n id: string;\n name: string;\n light: FillLabelSample;\n dark: FillLabelSample;\n /** Both modes at or above the target. */\n meets: boolean;\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\nfunction darkFill(color: HSL): HSL {\n if (color.l < DARK_FILL_LIGHTEN_BELOW) {\n return { ...color, l: clamp(color.l + DARK_FILL_LIGHTEN_BY, 0, 100) };\n }\n return color;\n}\n\nfunction sample(fill: HSL, target: number): FillLabelSample {\n const label = contrastForeground(fill);\n const fillCss = hslToString(fill);\n const ratio = contrastRatio(fillCss, label);\n return {\n ratio,\n shortfall: Math.max(0, Math.round((target - ratio) * 100) / 100),\n fill: fillCss,\n label,\n };\n}\n\n/**\n * Editable fill + the automatic label, Light and Dark. Target 7:1.\n * Meets only when both pass. Warnings do not block save.\n */\nexport function fillLabelWarning(\n id: string,\n name: string,\n hex: string,\n target = READABILITY_TARGET,\n): FillLabelWarning | null {\n if (!isThemeHex(hex)) return null;\n const lightFill = hexToHSL(hex);\n const light = sample(lightFill, target);\n const dark = sample(darkFill(lightFill), target);\n return { id, name, light, dark, meets: light.ratio >= target && dark.ratio >= target };\n}\n\n/** Green/teal family. A warning at admin time, not a schema block. */\nexport function successHueWarning(hex: string): string | null {\n if (!isThemeHex(hex)) return null;\n const { h } = hexToHSL(hex);\n if (h >= 80 && h <= 180) return null;\n return \"Keep success colors recognizable — stay in a green or teal family.\";\n}\n\n/** Red family. A warning at admin time, not a schema block. */\nexport function destructiveHueWarning(hex: string): string | null {\n if (!isThemeHex(hex)) return null;\n const { h } = hexToHSL(hex);\n if (h <= 30 || h >= 330) return null;\n return \"Keep destructive colors recognizable — stay in a red family.\";\n}\n\nexport function automaticLabel(hex: string): string | null {\n if (!isThemeHex(hex)) return null;\n return contrastForeground(hexToHSL(hex));\n}\n\nexport function hslCss(value: string): string {\n return `hsl(${value})`;\n}\n\n/** Which appearances fail, in words. Empty when both pass. */\nexport function hardToReadModes(item: FillLabelWarning): string {\n const light = item.light.shortfall > 0;\n const dark = item.dark.shortfall > 0;\n if (light && dark) return \"in Light and Dark\";\n if (light) return \"in Light\";\n if (dark) return \"in Dark\";\n return \"\";\n}\n\nexport function readabilityHeadline(item: FillLabelWarning): string {\n return item.meets ? `Text on ${item.name} looks readable` : `Text on ${item.name} may be hard to read`;\n}\n\nexport function readabilityModesLine(item: FillLabelWarning): string {\n const modes = hardToReadModes(item);\n return modes ? `Hard to read ${modes}.` : \"Looks good in Light and Dark.\";\n}\n\nexport function readabilityGapPercent(sample: FillLabelSample, target = READABILITY_TARGET): number {\n if (sample.shortfall <= 0) return 0;\n return Math.round((sample.shortfall / target) * 100);\n}\n\nexport function readabilityRatioLine(sample: FillLabelSample, target = READABILITY_TARGET): string {\n const percent = readabilityGapPercent(sample, target);\n if (percent <= 0) return \"Meets the contrast we want\";\n if (percent < 10) return \"A little short of the contrast we want\";\n return `About ${percent}% short of the contrast we want`;\n}\n\nexport const READABILITY_FIX =\n \"Darken or lighten the hex, then regenerate the scale. The site picks light or dark type for you.\";\n\nexport const READABILITY_PUBLISH_NOTE =\n \"You can still publish. To improve a color, darken or lighten it and regenerate.\";\n","import type { ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\n\n/** Theme overlays must leave Payload's transformed/clipped admin tree. */\nexport function ThemePortal({ children }: { children: ReactNode }) {\n if (typeof document === \"undefined\") return null;\n return createPortal(children, document.body);\n}\n","import { Dialog, Field, Input, KitProvider, Label } from \"@bison-lab/admin-ui\";\nimport { isThemeHex } from \"@bison-lab/tokens\";\nimport { useEffect, useState } from \"react\";\nimport { HexColorPicker } from \"react-colorful\";\n\nimport { ThemePortal } from \"./portal\";\n\n/** Keep a leading # and at most six hex digits. Drop everything else. */\nexport function filterThemeHexInput(raw: string): string {\n const trimmed = raw.trim();\n if (trimmed === \"\") return \"\";\n const digits = trimmed\n .replace(/^#/, \"\")\n .replace(/[^0-9a-fA-F]/g, \"\")\n .slice(0, 6);\n return `#${digits}`;\n}\n\nexport function BrandHexField({\n name,\n value,\n onChange,\n readOnly,\n placeholder = \"#DB0082\",\n picker = \"dialog\",\n}: {\n name: string;\n value: string;\n onChange: (hex: string) => void;\n readOnly?: boolean;\n placeholder?: string;\n picker?: \"dialog\" | \"inline\";\n}) {\n const [draft, setDraft] = useState(value);\n const [open, setOpen] = useState(false);\n const [pickerDraft, setPickerDraft] = useState(value);\n\n useEffect(() => {\n setDraft(value);\n }, [value]);\n\n function typeHex(next: string) {\n const filtered = filterThemeHexInput(next);\n setDraft(filtered);\n if (isThemeHex(filtered)) onChange(filtered);\n }\n\n function openPicker() {\n setPickerDraft(isThemeHex(draft) ? draft : value);\n setOpen(true);\n }\n\n function applyPicker() {\n if (!isThemeHex(pickerDraft)) return;\n onChange(pickerDraft);\n setDraft(pickerDraft);\n setOpen(false);\n }\n\n const input = (\n <Input\n aria-label={`${name} hex`}\n value={draft}\n placeholder={placeholder}\n spellCheck={false}\n autoComplete=\"off\"\n disabled={readOnly}\n onChange={(event) => typeHex(event.target.value)}\n onBlur={() => {\n if (!isThemeHex(draft)) setDraft(value);\n }}\n />\n );\n\n return (\n <KitProvider>\n <style href=\"bl-brand-hex\" precedence=\"default\">\n {CSS}\n </style>\n {picker === \"inline\" ? (\n <div className=\"bl-brand-hex bl-brand-hex--inline\">\n <HexColorPicker\n color={isThemeHex(draft) ? draft : \"#000000\"}\n onChange={(hex) => {\n setDraft(hex);\n onChange(hex);\n }}\n />\n <Field as=\"div\">\n <Label>Hex</Label>\n {input}\n </Field>\n </div>\n ) : (\n <div className=\"bl-brand-hex\">\n <button\n type=\"button\"\n className=\"bl-brand-hex__swatch\"\n aria-label={`${name} picker`}\n disabled={readOnly}\n style={{ background: isThemeHex(draft) ? draft : \"transparent\" }}\n onClick={openPicker}\n />\n {input}\n </div>\n )}\n {picker === \"dialog\" ? (\n <ThemePortal>\n <div className=\"bl-theme-dialog\">\n <Dialog\n open={open}\n title={`Pick ${name}`}\n onCancel={() => setOpen(false)}\n confirmLabel=\"Apply\"\n onConfirm={applyPicker}\n confirmDisabled={!isThemeHex(pickerDraft)}\n >\n <div className=\"bl-brand-hex bl-brand-hex--inline\">\n <HexColorPicker\n color={isThemeHex(pickerDraft) ? pickerDraft : \"#000000\"}\n onChange={setPickerDraft}\n />\n <Field as=\"div\">\n <Label>Hex</Label>\n <Input\n aria-label={`${name} picker hex`}\n value={pickerDraft}\n placeholder={placeholder}\n spellCheck={false}\n autoComplete=\"off\"\n onChange={(event) => setPickerDraft(filterThemeHexInput(event.target.value))}\n />\n </Field>\n </div>\n </Dialog>\n </div>\n </ThemePortal>\n ) : null}\n </KitProvider>\n );\n}\n\nconst CSS = `\n.bl-brand-hex{display:flex;align-items:stretch;gap:8px;min-width:0}\n.bl-brand-hex--inline{flex-direction:column;gap:12px}\n.bl-brand-hex .react-colorful{width:100%;height:200px}\n.bl-brand-hex__swatch{flex:none;width:38px;border:1px solid #3a3d46;border-radius:8px;padding:0;cursor:pointer;background:#1d1f24}\n.bl-brand-hex__swatch:disabled{opacity:.5;cursor:not-allowed}\n.bl-brand-hex .bl-nav-kit__input{font-family:var(--font-mono,ui-monospace,monospace)}\n.bl-theme-dialog .bl-nav-kit__modal{z-index:10000}\n`;\n","/**\n * Theme Colors tab chrome. Payload group-in-group draws a left gutter;\n * the mockup does not. Brand cards sit two-up. Light / Dark lives on the\n * cards only — the field list stays Payload chrome.\n */\nexport const THEME_COLORS_LAYOUT_CSS = `\n.group-field--gutter:has(.bl-scale-field),\n.group-field--gutter:has(.bl-section-heading),\n.group-field--gutter:has(.bl-grey),\n.group-field--gutter:has(.bl-library){\n border-left:none;\n padding-left:0;\n}\n.render-fields:has(> .bl-scale-field),\n.render-fields:has(> .field-type.bl-scale-field){\n display:grid;\n grid-template-columns:minmax(0,1fr) minmax(0,1fr);\n gap:1rem;\n align-items:start;\n}\n.render-fields:has(> .bl-scale-field) > .bl-section-heading,\n.render-fields:has(> .field-type.bl-scale-field) > .bl-section-heading,\n.render-fields:has(> .bl-scale-field) > :has(.bl-section-heading),\n.render-fields:has(> .field-type.bl-scale-field) > :has(.bl-section-heading),\n.render-fields:has(> .bl-scale-field) > .bl-library,\n.render-fields:has(> .field-type.bl-scale-field) > .field-type.bl-library,\n.render-fields:has(> .bl-scale-field) > :has(.bl-library),\n.render-fields:has(> .field-type.bl-scale-field) > :has(.bl-library),\n.render-fields:has(> .bl-scale-field) > :has(.bl-grey),\n.render-fields:has(> .field-type.bl-scale-field) > :has(.bl-grey){\n grid-column:1/-1;\n}\n@media (max-width:860px){\n .render-fields:has(> .bl-scale-field),\n .render-fields:has(> .field-type.bl-scale-field){\n grid-template-columns:1fr;\n }\n}\n`;\n","import { useFormFields } from \"@payloadcms/ui\";\nimport {\n deriveDarkPalette,\n deriveLightPalette,\n type GreyScale,\n} from \"@bison-lab/tokens\";\nimport { useEffect, useState, type CSSProperties } from \"react\";\n\nexport type ThemePreviewMode = \"light\" | \"dark\";\n\nconst ATTR = \"data-bl-theme-preview\";\nconst EVENT = \"bl-theme-preview\";\nconst PREVIEW_VARS = [\n \"--bl-preview-bg\",\n \"--bl-preview-card\",\n \"--bl-preview-border\",\n \"--bl-preview-text\",\n \"--bl-preview-muted\",\n \"--bl-preview-input\",\n] as const;\n\n/** Brand hexes do not affect grey-driven surfaces; derive still requires them. */\nconst PREVIEW_BRAND = { primary: \"#111111\", secondary: \"#111111\", success: \"#111111\" } as const;\n\nfunction readDocumentTheme(): ThemePreviewMode {\n if (typeof document === \"undefined\") return \"light\";\n return document.documentElement.getAttribute(\"data-theme\") === \"dark\" ? \"dark\" : \"light\";\n}\n\nlet currentMode: ThemePreviewMode = readDocumentTheme();\n\nfunction readMode(): ThemePreviewMode {\n return currentMode;\n}\n\n/** Drop leftovers from the old html-wide preview so Payload chrome stays Payload. */\nfunction clearDocumentPreview() {\n if (typeof document === \"undefined\") return;\n document.documentElement.removeAttribute(ATTR);\n for (const name of PREVIEW_VARS) document.documentElement.style.removeProperty(name);\n}\n\nexport function setThemePreviewMode(mode: ThemePreviewMode) {\n currentMode = mode;\n clearDocumentPreview();\n if (typeof window !== \"undefined\") window.dispatchEvent(new Event(EVENT));\n}\n\nexport function useThemePreviewMode(): ThemePreviewMode {\n const [mode, setMode] = useState<ThemePreviewMode>(readMode);\n useEffect(() => {\n clearDocumentPreview();\n const sync = () => setMode(readMode());\n sync();\n window.addEventListener(EVENT, sync);\n return () => window.removeEventListener(EVENT, sync);\n }, []);\n return mode;\n}\n\nexport function previewVarsFor(grey: GreyScale, mode: ThemePreviewMode) {\n const palette =\n mode === \"dark\"\n ? deriveDarkPalette({ ...PREVIEW_BRAND, grey })\n : deriveLightPalette({ ...PREVIEW_BRAND, grey });\n return {\n \"--bl-preview-bg\": `hsl(${palette.background})`,\n \"--bl-preview-card\": `hsl(${palette.card})`,\n \"--bl-preview-border\": `hsl(${palette.border})`,\n \"--bl-preview-text\": `hsl(${palette.foreground})`,\n \"--bl-preview-muted\": `hsl(${palette[\"muted-foreground\"]})`,\n \"--bl-preview-input\": `hsl(${palette.input})`,\n // Kit neutrals read Payload elevation tokens. Remap them on the canvas so\n // Required / Optional invert with Light / Dark, not the admin chrome.\n \"--theme-elevation-0\": `hsl(${palette.card})`,\n \"--theme-elevation-150\": `hsl(${palette.border})`,\n \"--theme-elevation-800\": `hsl(${palette.foreground})`,\n };\n}\n\nfunction useGreyScale(): GreyScale {\n return useFormFields(([fields]) => {\n const value = fields[\"colors.greyScale\"]?.value;\n return value === \"gray\" ||\n value === \"zinc\" ||\n value === \"neutral\" ||\n value === \"stone\" ||\n value === \"slate\"\n ? value\n : \"slate\";\n });\n}\n\n/**\n * Light / Dark + the live grey family, applied on each Theme field canvas.\n * Never writes to `documentElement` — nav, tabs, and Publish stay Payload.\n */\nexport function usePreviewCanvas() {\n const mode = useThemePreviewMode();\n const greyScale = useGreyScale();\n return {\n mode,\n className: \"bl-preview-canvas\",\n style: previewVarsFor(greyScale, mode) as CSSProperties,\n };\n}\n\nexport function ThemePreviewToggle() {\n const mode = useThemePreviewMode();\n return (\n <div className=\"bl-preview-toggle\" role=\"group\" aria-label=\"Preview theme in\">\n <button type=\"button\" data-on={mode === \"light\" ? \"\" : undefined} onClick={() => setThemePreviewMode(\"light\")}>\n Light\n </button>\n <button type=\"button\" data-on={mode === \"dark\" ? \"\" : undefined} onClick={() => setThemePreviewMode(\"dark\")}>\n Dark\n </button>\n </div>\n );\n}\n\nexport const THEME_PREVIEW_TOGGLE_CSS = `\n.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)}\n.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}\n.bl-preview-toggle button[data-on]{background:var(--theme-text,#0f172a);color:var(--theme-bg,#fff)}\n`;\n","import type { FillLabelWarning } from \"../theme/readability\";\nimport {\n hslCss,\n READABILITY_FIX,\n READABILITY_TARGET,\n readabilityHeadline,\n readabilityModesLine,\n readabilityRatioLine,\n} from \"../theme/readability\";\n\nexport function ReadabilityDetail({\n item,\n target = READABILITY_TARGET,\n}: {\n item: FillLabelWarning;\n target?: number;\n}) {\n return (\n <div className=\"bl-readability-detail\">\n <p className=\"bl-readability-detail__lead\">{readabilityModesLine(item)}</p>\n <div className=\"bl-readability-detail__modes\">\n {(\n [\n [\"Light\", item.light],\n [\"Dark\", item.dark],\n ] as const\n ).map(([mode, sample]) => (\n <figure key={mode} data-failing={sample.shortfall > 0 ? \"\" : undefined}>\n <span\n aria-hidden=\"true\"\n className=\"bl-readability__swatch\"\n style={{ background: hslCss(sample.fill), color: hslCss(sample.label) }}\n >\n Aa\n </span>\n <figcaption>\n <strong>{mode}</strong>\n <span>{sample.shortfall > 0 ? \"Hard to read\" : \"Looks good\"}</span>\n <span>{readabilityRatioLine(sample, target)}</span>\n </figcaption>\n </figure>\n ))}\n </div>\n {item.meets ? null : <p className=\"bl-readability-detail__fix\">{READABILITY_FIX}</p>}\n </div>\n );\n}\n\nexport function ReadabilityList({\n warnings,\n target = READABILITY_TARGET,\n}: {\n warnings: FillLabelWarning[];\n target?: number;\n}) {\n const failing = warnings.filter((item) => !item.meets).length;\n return (\n <section className=\"bl-readability\">\n <div className=\"bl-readability__head\">\n <div>\n <h2>Readability checks</h2>\n <p>Text the site puts on each fill. Warnings do not block save.</p>\n </div>\n <span data-attention={failing ? \"\" : undefined}>\n {failing === 0 ? \"All look readable\" : `${failing} may be hard to read`}\n </span>\n </div>\n <ul>\n {warnings.map((item) => (\n <li key={item.id} data-failing={item.meets ? undefined : \"\"}>\n <strong>{readabilityHeadline(item)}</strong>\n <ReadabilityDetail item={item} target={target} />\n </li>\n ))}\n </ul>\n </section>\n );\n}\n\nexport const READABILITY_LIST_CSS = `\n.bl-readability{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)}\n.bl-readability__head{display:flex;justify-content:space-between;gap:1rem;align-items:flex-start}\n.bl-readability__head h2{margin:0;font-size:1rem}\n.bl-readability__head p{margin:.35rem 0 0;font-size:12px;color:var(--theme-elevation-500,#64748b)}\n.bl-readability__head span{flex:none;font-size:12px;font-weight:600;padding:.2rem .55rem;border-radius:999px;background:var(--theme-elevation-100,#f1f5f9)}\n.bl-readability__head span[data-attention]{background:#fffbeb;color:#92400e}\n.bl-readability ul{margin:.85rem 0 0;padding:0;list-style:none}\n.bl-readability li{padding:.65rem 0;border-top:1px solid var(--theme-elevation-100,#f1f5f9)}\n.bl-readability li:first-child{border-top:0}\n.bl-readability li[data-failing]{background:#fff7ed;margin:0 -.4rem;padding:.65rem .4rem;border-radius:8px}\n.bl-readability__swatch{flex:none;display:inline-flex;align-items:center;justify-content:center;width:2.75rem;height:2rem;border-radius:6px;font-weight:700;font-size:13px}\n.bl-readability strong{display:block;font-size:13px}\n.bl-readability-detail__lead{margin:0 0 .65rem;font-size:13px;color:var(--theme-elevation-600,#475569)}\n.bl-readability-detail__modes{display:grid;grid-template-columns:1fr 1fr;gap:.65rem}\n.bl-readability-detail__modes figure{display:flex;gap:.6rem;align-items:center;margin:0;padding:.55rem .6rem;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:10px;background:#fff}\n.bl-readability-detail__modes figure[data-failing]{border-color:#fdba74;background:#fff7ed}\n.bl-readability-detail__modes figcaption{display:flex;flex-direction:column;gap:.1rem;min-width:0}\n.bl-readability-detail__modes figcaption strong{font-size:12px}\n.bl-readability-detail__modes figcaption span{font-size:11px;color:var(--theme-elevation-500,#64748b)}\n.bl-readability-detail__fix{margin:.7rem 0 0;font-size:13px;color:var(--theme-elevation-600,#475569)}\n`;\n","import {\n Badge,\n Field,\n KitProvider,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@bison-lab/admin-ui\";\nimport {\n createColorScale,\n includedShadeSteps,\n isThemeHex,\n setColorScaleInclude,\n SHADE_STEPS,\n type ColorScaleState,\n type ShadeStep,\n} from \"@bison-lab/tokens\";\nimport { useId, useState } from \"react\";\n\nimport {\n fillLabelWarning,\n hslCss,\n readabilityHeadline,\n successHueWarning,\n destructiveHueWarning,\n} from \"../theme/readability\";\nimport { BrandHexField } from \"./brand-hex-field\";\nimport { THEME_COLORS_LAYOUT_CSS } from \"./colors-layout\";\nimport { ThemePortal } from \"./portal\";\nimport { usePreviewCanvas } from \"./preview-mode\";\nimport { ReadabilityDetail, READABILITY_LIST_CSS } from \"./readability-list\";\n\nexport interface ColorScaleCardProps {\n id?: string;\n name: string;\n hint?: string;\n required?: boolean;\n custom?: boolean;\n state: ColorScaleState;\n onChange: (next: ColorScaleState) => void;\n onDelete?: () => void;\n readOnly?: boolean;\n role?: \"success\" | \"destructive\" | null;\n}\n\nconst STATUS_COPY = {\n success: {\n title: \"Keep success colors recognizable\",\n body: \"Success states should stay in a green or teal family so users can quickly recognize positive outcomes and confirmations.\",\n drift: \"This color may no longer read as a success state.\",\n },\n destructive: {\n title: \"Keep destructive colors recognizable\",\n body: \"Destructive actions should stay in a red or crimson family so users can quickly recognize errors and dangerous actions.\",\n drift: \"This color may no longer read as a destructive or error state.\",\n },\n} as const;\n\nfunction IncludeMark({ on }: { on: boolean }) {\n return (\n <span className=\"bl-scale-card__status\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 16 16\">\n {on ? (\n <path\n d=\"M3.5 8.5 6.5 11.5 12.5 4.5\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.4\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n ) : (\n <path\n d=\"M4.5 4.5 11.5 11.5M11.5 4.5 4.5 11.5\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.4\"\n strokeLinecap=\"round\"\n />\n )}\n </svg>\n </span>\n );\n}\n\nexport function ColorScaleCard({\n id,\n name,\n hint,\n required,\n custom,\n state,\n onChange,\n onDelete,\n readOnly,\n role,\n}: ColorScaleCardProps) {\n const warning = fillLabelWarning(id ?? name.toLowerCase(), name, state.hex);\n const canvas = usePreviewCanvas();\n const [attentionOpen, setAttentionOpen] = useState(false);\n const [shakeStep, setShakeStep] = useState<ShadeStep | null>(null);\n const titleId = useId();\n const included = new Set(includedShadeSteps(state));\n const hueDrift =\n role === \"success\"\n ? Boolean(successHueWarning(state.hex))\n : role === \"destructive\"\n ? Boolean(destructiveHueWarning(state.hex))\n : false;\n\n function commitHex(hex: string) {\n onChange(createColorScale(hex, state.sourceStep, state.include));\n }\n\n function commitStep(step: ShadeStep) {\n onChange(createColorScale(state.hex, step, state.include));\n }\n\n function toggleStep(step: ShadeStep) {\n if (step === state.sourceStep) {\n setShakeStep(step);\n window.setTimeout(() => setShakeStep((was) => (was === step ? null : was)), 180);\n return;\n }\n const next = new Set(included);\n if (next.has(step)) next.delete(step);\n else next.add(step);\n onChange(setColorScaleInclude(state, SHADE_STEPS.filter((item) => next.has(item))));\n }\n\n return (\n <KitProvider accent={id === \"primary\" && isThemeHex(state.hex) ? state.hex : undefined}>\n <article className={`bl-scale-card ${canvas.className}`} data-preview={canvas.mode} style={canvas.style}>\n <header className=\"bl-scale-card__head\">\n <div>\n <div className=\"bl-scale-card__title-row\">\n <h3 className=\"bl-scale-card__title\">{name}</h3>\n {required ? <Badge>Required</Badge> : null}\n {custom ? <Badge>Optional</Badge> : null}\n {warning && !warning.meets ? (\n <Badge as=\"button\" variant=\"danger\" aria-haspopup=\"dialog\" onClick={() => setAttentionOpen(true)}>\n Needs attention\n </Badge>\n ) : null}\n </div>\n {hint ? <p className=\"bl-scale-card__hint\">{hint}</p> : null}\n </div>\n {onDelete ? (\n <button type=\"button\" className=\"bl-scale-card__delete\" disabled={readOnly} onClick={onDelete}>\n Delete\n </button>\n ) : null}\n </header>\n\n <div className=\"bl-scale-card__row\">\n <Field as=\"div\">\n <Label>Brand hex</Label>\n <BrandHexField name={name} value={state.hex} onChange={commitHex} readOnly={readOnly} />\n </Field>\n <Field as=\"div\">\n <Label>This color is</Label>\n <Select\n value={String(state.sourceStep)}\n onValueChange={(value) => commitStep(Number(value) as ShadeStep)}\n disabled={readOnly}\n >\n <SelectTrigger aria-label=\"This color is\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SHADE_STEPS.map((step) => (\n <SelectItem key={step} value={String(step)}>\n {step}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </Field>\n </div>\n\n {role ? (\n <div className=\"bl-scale-card__family\" data-role={role} data-drift={hueDrift ? \"\" : undefined}>\n <div className=\"bl-scale-card__family-mark\" aria-hidden=\"true\">\n !\n </div>\n <div>\n <div className=\"bl-scale-card__family-title\">{STATUS_COPY[role].title}</div>\n <p>{STATUS_COPY[role].body}</p>\n {hueDrift ? <p className=\"bl-scale-card__family-drift\">{STATUS_COPY[role].drift}</p> : null}\n </div>\n </div>\n ) : null}\n\n <div className=\"bl-scale-card__scale-head\">\n <span>Generated scale</span>\n <span>{SHADE_STEPS.length} shades</span>\n </div>\n <div className=\"bl-scale-card__steps\" role=\"group\" aria-label={`${name} scale steps`}>\n {SHADE_STEPS.map((step) => {\n const source = step === state.sourceStep;\n const on = included.has(step);\n return (\n <button\n key={step}\n type=\"button\"\n className=\"bl-scale-card__step\"\n data-source={source ? \"\" : undefined}\n data-excluded={on ? undefined : \"\"}\n data-shake={shakeStep === step ? \"\" : undefined}\n disabled={readOnly}\n aria-pressed={on}\n aria-label={\n source\n ? `Source step ${step} cannot be excluded`\n : on\n ? `Shade ${step}, available — click to exclude from the palette`\n : `Shade ${step}, excluded — click to include in the palette`\n }\n title={\n source\n ? `Source step ${step} cannot be excluded`\n : on\n ? \"Available to page editors — click to exclude\"\n : \"Excluded from page editors — click to include\"\n }\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n toggleStep(step);\n }}\n >\n <span className=\"bl-scale-card__chip-wrap\">\n <span className=\"bl-scale-card__chip\" style={{ backgroundColor: hslCss(state.scale[step]) }} />\n <IncludeMark on={on} />\n </span>\n <span className=\"bl-scale-card__step-label\">{step}</span>\n </button>\n );\n })}\n </div>\n <div className=\"bl-scale-card__editors\">\n <div>\n <div>Available to page editors</div>\n <p>\n {included.size} of {SHADE_STEPS.length} shades available · Choose which shades editors can select when\n building pages.\n </p>\n </div>\n <span>\n <button type=\"button\" disabled={readOnly} onClick={() => onChange(setColorScaleInclude(state, \"all\"))}>\n Include all\n </button>\n <button type=\"button\" disabled={readOnly} onClick={() => onChange(setColorScaleInclude(state, \"source\"))}>\n Source only\n </button>\n </span>\n </div>\n {attentionOpen && warning ? (\n <ThemePortal>\n <div\n className=\"bl-scale-card__modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n onClick={(event) => {\n if (event.target === event.currentTarget) setAttentionOpen(false);\n }}\n >\n <div className=\"bl-scale-card__panel\">\n <div className=\"bl-scale-card__panel-head\">\n <h4 id={titleId}>{readabilityHeadline(warning)}</h4>\n <button type=\"button\" onClick={() => setAttentionOpen(false)} aria-label=\"Close\">\n ×\n </button>\n </div>\n <ReadabilityDetail item={warning} />\n <button type=\"button\" className=\"bl-scale-card__panel-done\" onClick={() => setAttentionOpen(false)}>\n Keep editing this color\n </button>\n </div>\n </div>\n </ThemePortal>\n ) : null}\n </article>\n </KitProvider>\n );\n}\n\nexport const COLOR_SCALE_CARD_CSS = `\n.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)}\n.bl-scale-card__head{display:flex;justify-content:space-between;gap:1rem;align-items:flex-start}\n.bl-scale-card__title-row{position:relative;display:flex;align-items:center;flex-wrap:wrap;gap:.5rem}\n.bl-scale-card__title{margin:0;font-size:1rem}\n.bl-scale-card__hint{margin:.35rem 0 0;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b));font-size:12px}\n.bl-scale-card__delete{border:0;background:none;color:#be123c;font:inherit;font-size:13px;font-weight:600;cursor:pointer}\n.bl-scale-card__row{display:grid;grid-template-columns:1fr 8rem;gap:.75rem;margin-top:1rem;align-items:start}\n.bl-scale-card__row .bl-nav-kit__field{margin-bottom:0}\n.bl-scale-card__family{display:flex;gap:.75rem;align-items:flex-start;margin-top:1rem;padding:.75rem .85rem;border-radius:8px}\n.bl-scale-card__family[data-role=success]{border:1px solid #a7f3d0;background:#ecfdf5;color:#065f46}\n.bl-scale-card__family[data-role=destructive]{border:1px solid #fecdd3;background:#fff1f2;color:#9f1239}\n.bl-scale-card__family[data-drift]{box-shadow:0 0 0 2px #fbbf24}\n.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}\n.bl-scale-card__family[data-role=success] .bl-scale-card__family-mark{background:#d1fae5;color:#047857}\n.bl-scale-card__family[data-role=destructive] .bl-scale-card__family-mark{background:#ffe4e6;color:#be123c}\n.bl-scale-card__family-title{font-size:12px;font-weight:600}\n.bl-scale-card__family p{margin:.25rem 0 0;font-size:11px;line-height:1.45;opacity:.85}\n.bl-scale-card__family-drift{font-weight:600;opacity:1}\n.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))}\n.bl-scale-card__steps{display:grid;grid-template-columns:repeat(11,minmax(0,1fr));gap:.45rem 3px}\n.bl-scale-card__step{display:flex;flex-direction:column;align-items:center;gap:.3rem;border:0;padding:0;background:transparent;cursor:pointer}\n.bl-scale-card__chip-wrap{position:relative;display:block;width:100%}\n.bl-scale-card__chip{display:block;width:100%;height:2.15rem;border-radius:6px;overflow:hidden}\n.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)}\n.bl-scale-card__status svg{display:block;width:10px;height:10px}\n.bl-scale-card__step-label{font-size:10px;line-height:1;color:var(--theme-elevation-600,#475569)}\n.bl-scale-card__step[data-source] .bl-scale-card__chip{box-shadow:0 0 0 2px #0f172a}\n.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%)}\n.bl-scale-card__step[data-excluded] .bl-scale-card__status{color:#991b1b;background:rgba(255,255,255,.96)}\n.bl-scale-card__step[data-excluded] .bl-scale-card__step-label{opacity:.35}\n@keyframes bl-scale-shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-3px)}75%{transform:translateX(3px)}}\n.bl-scale-card__step[data-shake]{animation:bl-scale-shake .18s}\n.bl-scale-card__step:disabled{cursor:default}\n.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))}\n.bl-scale-card__editors > div > div{font-size:12px;font-weight:600;color:var(--bl-preview-text,var(--theme-elevation-700,#334155))}\n.bl-scale-card__editors p{margin:.2rem 0 0;font-size:11px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}\n.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}\n.bl-scale-card__editors span{display:flex;gap:0}\n.bl-scale-card__modal{position:fixed;inset:0;z-index:10000;display:grid;place-items:center;padding:1rem;background:rgba(15,23,42,.45)}\n.bl-scale-card__panel{width:min(32rem,100%);padding:1.15rem 1.2rem;border-radius:16px;background:#fff;color:#0f172a;color-scheme:light}\n.bl-scale-card__panel-head{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem}\n.bl-scale-card__panel-head h4{margin:0;font-size:1rem}\n.bl-scale-card__panel-head button{border:0;background:none;font:inherit;font-size:1.25rem;line-height:1;color:#64748b;cursor:pointer}\n.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}\n.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)}\n` + READABILITY_LIST_CSS + THEME_COLORS_LAYOUT_CSS;\n","import { useField, useForm } from \"@payloadcms/ui\";\nimport { isThemeHex, SHADE_STEPS, type ColorScaleState, type ShadeStep } from \"@bison-lab/tokens\";\nimport type { GroupFieldClientComponent } from \"payload\";\n\nimport { SYSTEM_COLOR_COPY } from \"../theme/appearance-labels\";\nimport { colorDocFromState, stateFromColorDoc } from \"../theme/map\";\nimport { ColorScaleCard, COLOR_SCALE_CARD_CSS } from \"./color-scale-card\";\n\nconst SYSTEM_ROLES = new Set(Object.keys(SYSTEM_COLOR_COPY));\n\n/**\n * Payload's hasMany select often stores a count on the field path and the\n * chosen values at `path.0`, `path.1`, … — same shape as an array field.\n */\nfunction includedStepsFromForm(\n path: string,\n value: ShadeStep[] | string[] | number | undefined,\n getDataByPath?: (fieldPath: string) => unknown,\n): ShadeStep[] | string[] | undefined {\n if (Array.isArray(value)) return value;\n const stored = getDataByPath?.(path);\n if (Array.isArray(stored)) return stored as ShadeStep[] | string[];\n const count = typeof value === \"number\" ? value : typeof stored === \"number\" ? stored : 0;\n if (count <= 0) return undefined;\n const steps = Array.from({ length: count }, (_, index) => getDataByPath?.(`${path}.${index}`));\n if (steps.every((step) => step == null)) return undefined;\n return steps.filter((step): step is ShadeStep | string => step != null).map(String);\n}\n\n/**\n * One system (or library row) color: hex, source step, include/exclude.\n * Writes the group's stored fields. A committed hex or step rebuilds the scale.\n */\nexport const ColorScaleField: GroupFieldClientComponent = ({ field, path, readOnly }) => {\n const hex = useField<string>({ path: `${path}.hex` });\n const sourceStep = useField<string | number>({ path: `${path}.sourceStep` });\n const scale = useField<ColorScaleState[\"scale\"]>({ path: `${path}.scale` });\n const stale = useField<boolean>({ path: `${path}.stale` });\n const include = useField<string>({ path: `${path}.include` });\n const includedSteps = useField<ShadeStep[] | string[] | number>({ path: `${path}.includedSteps` });\n const { getDataByPath } = useForm();\n const key = path.split(\".\").pop() ?? \"\";\n const copy = SYSTEM_ROLES.has(key) ? SYSTEM_COLOR_COPY[key as keyof typeof SYSTEM_COLOR_COPY] : undefined;\n const stepList = includedStepsFromForm(`${path}.includedSteps`, includedSteps.value, getDataByPath);\n const state = stateFromColorDoc({\n hex: hex.value,\n sourceStep: sourceStep.value as ShadeStep | undefined,\n scale: scale.value,\n stale: stale.value,\n include: include.value === \"source\" || include.value === \"custom\" || include.value === \"all\" ? include.value : \"all\",\n includedSteps: stepList,\n });\n\n function write(next: ColorScaleState) {\n const doc = colorDocFromState(next);\n hex.setValue(doc.hex);\n sourceStep.setValue(String(doc.sourceStep));\n scale.setValue(doc.scale);\n stale.setValue(doc.stale);\n include.setValue(doc.include);\n includedSteps.setValue(\n (doc.includedSteps ?? (doc.include === \"source\" ? [doc.sourceStep] : [...SHADE_STEPS])).map(String),\n );\n }\n\n const label = copy?.label ?? (typeof field.label === \"string\" ? field.label : key);\n\n return (\n <div className=\"field-type bl-scale-field\">\n <style href=\"bl-scale-card\" precedence=\"default\">\n {COLOR_SCALE_CARD_CSS}\n </style>\n <ColorScaleCard\n id={key}\n name={label}\n hint={copy?.hint}\n required={Boolean(copy) || Boolean(\"required\" in field && field.required)}\n state={isThemeHex(state.hex) ? state : { ...state, hex: \"#000000\" }}\n onChange={write}\n readOnly={readOnly}\n role={key === \"success\" || key === \"destructive\" ? key : null}\n />\n </div>\n );\n};\n","import { SHADE_STEPS, type ShadeStep } from \"@bison-lab/tokens\";\n\nimport { SYSTEM_COLOR_KEYS, type ThemeDoc, type ThemeLibraryColorDoc } from \"./types\";\n\n/**\n * Payload's array form state stores the row count (`0`, `2`, …), not the\n * rows. A custom Field that treats that number as the list will throw\n * `rows.filter is not a function` on an empty Theme library.\n */\nexport function asLibraryRows(value: unknown): ThemeLibraryColorDoc[] {\n return Array.isArray(value) ? value : [];\n}\n\nconst STEP_SET = new Set<number>(SHADE_STEPS);\n\n/**\n * Page editors pick `coral-400`, never a raw hex. Rewrite every use of\n * `fromKey` onto `toKey` at the same step: `coral-400` → `highlight-400`.\n * A bare key (`coral`) becomes `toKey`. Anything else is left alone.\n */\nexport function rewriteColorToken(token: string, fromKey: string, toKey: string): string {\n if (token === fromKey) return toKey;\n const dash = token.lastIndexOf(\"-\");\n if (dash <= 0) return token;\n const key = token.slice(0, dash);\n const step = Number(token.slice(dash + 1));\n if (key !== fromKey || !STEP_SET.has(step)) return token;\n return `${toKey}-${step as ShadeStep}`;\n}\n\nexport function themeColorKeys(doc: ThemeDoc | null | undefined): string[] {\n const custom = asLibraryRows(doc?.colors?.library)\n .map((row) => row.key?.trim())\n .filter((key): key is string => Boolean(key));\n return [...SYSTEM_COLOR_KEYS, ...custom];\n}\n\n/**\n * Remove a custom color. Unused: omit `replacement` and the row is gone.\n * In use: pass another system or custom key; the caller rewrites page\n * tokens with `rewriteColorToken`. After this, no library row still\n * has `key`.\n */\nexport function deleteLibraryColor(doc: ThemeDoc, key: string, replacement?: string): ThemeDoc {\n const library = [...asLibraryRows(doc.colors?.library)];\n const index = library.findIndex((row) => row.key === key);\n if (index === -1) {\n throw new Error(`No custom color named ${JSON.stringify(key)}`);\n }\n library.splice(index, 1);\n const next: ThemeDoc = {\n ...doc,\n colors: { ...doc.colors, library },\n };\n if (replacement !== undefined) {\n if (replacement === key) {\n throw new Error(\"Replacement must be a different color\");\n }\n if (!themeColorKeys(next).includes(replacement)) {\n throw new Error(`Replacement ${JSON.stringify(replacement)} is not a system or remaining custom color`);\n }\n }\n return next;\n}\n","import { findColorTokens, rewriteColorTokens } from \"./color-tokens\";\nimport { pageEditorLooks } from \"./looks\";\nimport { THEME_SLUG, type ThemeDoc } from \"./types\";\n\n/** Theme-store REST path. LibraryField calls `/api/globals/theme` + this. */\nexport const COLOR_USAGES_PATH = \"/color-usages\";\n\nexport interface ColorUsagesList {\n collections?: string[];\n globals?: string[];\n}\n\n/**\n * `true` scans every registered collection and global at request time\n * (Payload internals and Theme itself are skipped). A list still names\n * slugs. Omit or pass empty: every additional color is unused.\n */\nexport type ColorUsagesOption = true | ColorUsagesList;\n\nexport interface ColorUsage {\n collection?: string;\n global?: string;\n id?: string | number;\n path: string;\n token: string;\n}\n\ntype FindResult = { docs: Record<string, unknown>[]; totalPages?: number; page?: number };\n\ntype Slugged = { slug?: string };\n\nexport interface ColorUsagePayload {\n find: (args: {\n collection: string;\n draft?: boolean;\n depth?: number;\n limit?: number;\n page?: number;\n overrideAccess?: boolean;\n }) => Promise<FindResult>;\n findGlobal: (args: {\n slug: string;\n draft?: boolean;\n depth?: number;\n overrideAccess?: boolean;\n }) => Promise<Record<string, unknown> | ThemeDoc | null | undefined>;\n update: (args: {\n collection: string;\n id: string | number;\n data: Record<string, unknown>;\n draft?: boolean;\n overrideAccess?: boolean;\n }) => Promise<unknown>;\n updateGlobal: (args: {\n slug: string;\n data: Record<string, unknown>;\n draft?: boolean;\n overrideAccess?: boolean;\n }) => Promise<unknown>;\n collections?: Record<string, unknown>;\n globals?: { config?: Slugged[] };\n config?: {\n collections?: Slugged[];\n globals?: Slugged[];\n };\n}\n\n/**\n * Walk every current document in the resolved collections and globals\n * (drafts included). A color only on an unpublished page is still in use.\n */\nexport async function findColorUsages(\n payload: ColorUsagePayload,\n scopes: ColorUsagesOption | undefined,\n key: string,\n): Promise<ColorUsage[]> {\n const { collections, globals } = resolveScopes(payload, scopes);\n const usages: ColorUsage[] = [];\n for (const collection of collections) {\n for await (const doc of eachCollectionDoc(payload, collection)) {\n for (const hit of findColorTokens(doc, key)) {\n usages.push({ collection, id: idOf(doc), path: hit.path, token: hit.token });\n }\n }\n }\n for (const slug of globals) {\n const doc = await readGlobal(payload, slug);\n if (!doc) continue;\n for (const hit of findColorTokens(doc, key)) {\n usages.push({ global: slug, path: hit.path, token: hit.token });\n }\n }\n return usages;\n}\n\nexport async function rewriteColorUsages(\n payload: ColorUsagePayload,\n scopes: ColorUsagesOption | undefined,\n fromKey: string,\n toKey: string,\n): Promise<void> {\n const { collections, globals } = resolveScopes(payload, scopes);\n for (const collection of collections) {\n for await (const doc of eachCollectionDoc(payload, collection)) {\n if (findColorTokens(doc, fromKey).length === 0) continue;\n const { id: _id, ...data } = rewriteColorTokens(doc, fromKey, toKey);\n const id = idOf(doc);\n if (id == null) continue;\n await payload.update({\n collection,\n id,\n data,\n draft: true,\n overrideAccess: true,\n });\n }\n }\n for (const slug of globals) {\n const doc = await readGlobal(payload, slug);\n if (!doc || findColorTokens(doc, fromKey).length === 0) continue;\n await payload.updateGlobal({\n slug,\n data: rewriteColorTokens(doc, fromKey, toKey) as Record<string, unknown>,\n draft: true,\n overrideAccess: true,\n });\n }\n}\n\nexport async function replacementKeys(payload: ColorUsagePayload, except: string): Promise<string[]> {\n const doc = (await payload.findGlobal({\n slug: THEME_SLUG,\n depth: 0,\n overrideAccess: true,\n })) as ThemeDoc | null;\n return pageEditorLooks(doc)\n .map((look) => look.value)\n .filter((key) => key !== except);\n}\n\nexport function resolveScopes(\n payload: ColorUsagePayload,\n scopes: ColorUsagesOption | undefined,\n): ColorUsagesList & { collections: string[]; globals: string[] } {\n if (scopes === true) return registeredScopes(payload);\n return {\n collections: scopes?.collections ?? [],\n globals: scopes?.globals ?? [],\n };\n}\n\nfunction registeredScopes(payload: ColorUsagePayload): { collections: string[]; globals: string[] } {\n return {\n collections: slugsOf(payload.config?.collections ?? payload.collections).filter(\n (slug) => !slug.startsWith(\"payload-\"),\n ),\n globals: slugsOf(payload.config?.globals ?? payload.globals?.config).filter(\n (slug) => slug !== THEME_SLUG,\n ),\n };\n}\n\nfunction slugsOf(value: Slugged[] | Record<string, unknown> | undefined): string[] {\n if (Array.isArray(value)) {\n return value.map((item) => item?.slug).filter((slug): slug is string => Boolean(slug));\n }\n if (value && typeof value === \"object\") return Object.keys(value);\n return [];\n}\n\nasync function readGlobal(\n payload: ColorUsagePayload,\n slug: string,\n): Promise<Record<string, unknown> | ThemeDoc | null | undefined> {\n try {\n return await payload.findGlobal({ slug, draft: true, depth: 0, overrideAccess: true });\n } catch {\n // A named slug that is not registered must not fail Colors Delete.\n return null;\n }\n}\n\nasync function* eachCollectionDoc(\n payload: ColorUsagePayload,\n collection: string,\n): AsyncGenerator<Record<string, unknown>> {\n let page = 1;\n for (;;) {\n let result: FindResult;\n try {\n result = await payload.find({\n collection,\n draft: true,\n depth: 0,\n limit: 100,\n page,\n overrideAccess: true,\n });\n } catch {\n return;\n }\n for (const doc of result.docs) yield doc;\n const totalPages = result.totalPages ?? (result.docs.length < 100 ? page : page + 1);\n if (page >= totalPages || result.docs.length === 0) break;\n page += 1;\n }\n}\n\nfunction idOf(doc: Record<string, unknown>): string | number | undefined {\n const id = doc.id;\n return typeof id === \"string\" || typeof id === \"number\" ? id : undefined;\n}\n","import {\n Dialog,\n Field,\n Input,\n KitProvider,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@bison-lab/admin-ui\";\nimport { useConfig, useField, useForm } from \"@payloadcms/ui\";\nimport { createColorScale, isThemeHex, SHADE_STEPS, type ShadeStep } from \"@bison-lab/tokens\";\nimport type { ArrayFieldClientComponent } from \"payload\";\nimport { useState } from \"react\";\n\nimport { COLOR_USAGES_PATH, type ColorUsage } from \"../theme/color-usages\";\nimport { asLibraryRows, deleteLibraryColor } from \"../theme/library\";\nimport { pageEditorLooks } from \"../theme/looks\";\nimport { colorDocFromState, stateFromColorDoc } from \"../theme/map\";\nimport { type ThemeDoc, type ThemeLibraryColorDoc } from \"../theme/types\";\nimport { BrandHexField } from \"./brand-hex-field\";\nimport { ColorScaleCard, COLOR_SCALE_CARD_CSS } from \"./color-scale-card\";\nimport { ThemePortal } from \"./portal\";\n\nfunction slugify(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\n/**\n * Custom colors: the same scale controls as system colors. Unused: the\n * Theme store's color-usages endpoint returns nothing and the row is\n * gone. In use: pick a live replacement; confirm rewrites stored tokens\n * then drops the row. Success and Destructive stay off that list.\n */\nexport const LibraryField: ArrayFieldClientComponent = ({ field, path, readOnly }) => {\n const dataPath =\n typeof field.admin?.custom?.dataPath === \"string\" ? field.admin.custom.dataPath : path;\n const { value, setValue } = useField<ThemeLibraryColorDoc[] | number>({ path: dataPath, hasRows: true });\n const { getDataByPath } = useForm();\n const { config } = useConfig();\n const rows = asLibraryRows(value).length > 0 ? asLibraryRows(value) : asLibraryRows(getDataByPath?.(dataPath));\n const [adding, setAdding] = useState(false);\n const [name, setName] = useState(\"\");\n const [hex, setHex] = useState(\"\");\n const [sourceStep, setSourceStep] = useState<ShadeStep>(500);\n const [replacing, setReplacing] = useState<{ row: ThemeLibraryColorDoc; usages: ColorUsage[] } | null>(\n null,\n );\n const [replacement, setReplacement] = useState(\"\");\n const [busy, setBusy] = useState(false);\n\n function write(next: ThemeLibraryColorDoc[]) {\n setValue(next);\n }\n\n function usagesUrl(key: string) {\n const serverURL = config.serverURL ?? \"\";\n const api = config.routes?.api ?? \"/api\";\n return `${serverURL}${api}/globals/theme${COLOR_USAGES_PATH}?key=${encodeURIComponent(key)}`;\n }\n\n function add() {\n const key = slugify(name);\n if (!key || !isThemeHex(hex) || rows.some((row) => row.key === key)) return;\n write([...rows, { key, label: name.trim(), ...colorDocFromState(createColorScale(hex, sourceStep)) }]);\n setName(\"\");\n setHex(\"\");\n setSourceStep(500);\n setAdding(false);\n }\n\n async function remove(row: ThemeLibraryColorDoc) {\n const key = row.key ?? \"\";\n const response = await fetch(usagesUrl(key), { credentials: \"include\" });\n if (!response.ok) return;\n const body = (await response.json()) as { usages?: ColorUsage[] };\n const usages = body.usages ?? [];\n if (usages.length === 0) {\n const doc: ThemeDoc = { colors: { library: rows } };\n write(deleteLibraryColor(doc, key).colors?.library ?? []);\n return;\n }\n setReplacement(\"\");\n setReplacing({ row, usages });\n }\n\n async function confirmReplace() {\n if (!replacing || !replacement || busy) return;\n const key = replacing.row.key ?? \"\";\n setBusy(true);\n try {\n const response = await fetch(usagesUrl(key), {\n method: \"POST\",\n credentials: \"include\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ key, replacement }),\n });\n if (!response.ok) return;\n const doc: ThemeDoc = { colors: { library: rows } };\n write(deleteLibraryColor(doc, key, replacement).colors?.library ?? []);\n setReplacing(null);\n } finally {\n setBusy(false);\n }\n }\n\n const replacementOptions = replacing\n ? pageEditorLooks({\n colors: { library: rows.filter((row) => row.key !== replacing.row.key) },\n })\n : [];\n\n return (\n <div className=\"field-type bl-library\">\n <style href=\"bl-scale-card\" precedence=\"default\">\n {COLOR_SCALE_CARD_CSS}\n </style>\n <style href=\"bl-library\" precedence=\"default\">\n {CSS}\n </style>\n <div className=\"bl-library__head\">\n <div>\n <h2>Additional colors</h2>\n <p>Add optional named colors for special sections, campaigns, or components.</p>\n </div>\n <button\n type=\"button\"\n disabled={readOnly}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n setAdding(true);\n }}\n >\n Add color\n </button>\n </div>\n {adding ? (\n <ThemePortal>\n <div className=\"bl-theme-dialog\">\n <KitProvider>\n <Dialog\n open\n title=\"New color\"\n onCancel={() => {\n setAdding(false);\n setName(\"\");\n setHex(\"\");\n setSourceStep(500);\n }}\n confirmLabel=\"Create color scale\"\n onConfirm={add}\n confirmDisabled={!slugify(name) || !isThemeHex(hex)}\n >\n <p>Give it a useful name, enter your brand hex, then say which scale step that hex is.</p>\n <Field>\n <Label>Name</Label>\n <Input\n aria-label=\"Name\"\n value={name}\n placeholder=\"e.g. Coral\"\n onChange={(event) => setName(event.target.value)}\n />\n </Field>\n <Field as=\"div\">\n <Label>Brand hex</Label>\n <BrandHexField name=\"Brand\" value={hex} onChange={setHex} picker=\"inline\" />\n </Field>\n <Field as=\"div\">\n <Label>This color is</Label>\n <Select\n value={String(sourceStep)}\n onValueChange={(value) => setSourceStep(Number(value) as ShadeStep)}\n >\n <SelectTrigger aria-label=\"This color is\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SHADE_STEPS.map((step) => (\n <SelectItem key={step} value={String(step)}>\n {step}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </Field>\n </Dialog>\n </KitProvider>\n </div>\n </ThemePortal>\n ) : null}\n {replacing ? (\n <ThemePortal>\n <div\n className=\"bl-library__modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"bl-library-replace-title\"\n onClick={(event) => {\n if (event.target === event.currentTarget && !busy) setReplacing(null);\n }}\n >\n <div className=\"bl-library__panel\">\n <div className=\"bl-library__panel-head\">\n <div>\n <h2 id=\"bl-library-replace-title\">Replace {replacing.row.label ?? replacing.row.key}</h2>\n <p>\n {replacing.usages.length === 1\n ? \"1 document uses this color. Pick a replacement at the same step.\"\n : `${replacing.usages.length} documents use this color. Pick a replacement at the same step.`}\n </p>\n </div>\n <button type=\"button\" onClick={() => setReplacing(null)} aria-label=\"Close\" disabled={busy}>\n ×\n </button>\n </div>\n <ul className=\"bl-library__usages\">\n {replacing.usages.map((usage, index) => (\n <li key={`${usage.collection ?? usage.global}-${usage.id ?? \"\"}-${usage.path}-${index}`}>\n {usage.collection ?? usage.global}\n {usage.id != null ? ` #${usage.id}` : \"\"} · {usage.path} · {usage.token}\n </li>\n ))}\n </ul>\n <label>\n Replacement\n <select value={replacement} onChange={(event) => setReplacement(event.target.value)}>\n <option value=\"\">Select a color…</option>\n {replacementOptions.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </label>\n <div className=\"bl-library__actions\">\n <button type=\"button\" onClick={() => setReplacing(null)} disabled={busy}>\n Cancel\n </button>\n <button type=\"button\" disabled={!replacement || busy} onClick={() => void confirmReplace()}>\n Replace and delete\n </button>\n </div>\n </div>\n </div>\n </ThemePortal>\n ) : null}\n <div className=\"bl-library__list\">\n {rows.map((row, index) => (\n <ColorScaleCard\n key={row.key ?? index}\n id={row.key ?? `custom-${index}`}\n name={row.label ?? row.key ?? \"Color\"}\n hint={row.key ? `Key: ${row.key}` : undefined}\n custom\n state={stateFromColorDoc(row)}\n onChange={(next) => {\n const copy = [...rows];\n copy[index] = { ...row, ...colorDocFromState(next) };\n write(copy);\n }}\n onDelete={readOnly ? undefined : () => void remove(row)}\n readOnly={readOnly}\n />\n ))}\n </div>\n </div>\n );\n};\n\nconst CSS = `\n.bl-library__head{display:flex;justify-content:space-between;gap:1rem;align-items:flex-start;margin-bottom:.85rem}\n.bl-library__head h2{margin:0;font-size:1.1rem}\n.bl-library__head p{margin:.35rem 0 0;font-size:13px;color:color-mix(in srgb,var(--theme-text,#f8fafc) 92%,transparent)}\n.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}\n.bl-library__list{display:grid;gap:.85rem}\n.bl-library__modal{position:fixed;inset:0;z-index:10000;display:grid;place-items:center;padding:1rem;background:rgba(15,23,42,.45)}\n.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)}\n.bl-library__panel-head{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem}\n.bl-library__panel-head button{border:0;background:none;font:inherit;font-size:1.25rem;line-height:1;color:#94a3b8;cursor:pointer}\n.bl-library__panel h2{margin:0}\n.bl-library__panel p{margin:.5rem 0 0;color:#475569;font-size:14px}\n.bl-library__panel label,.bl-library__field{display:flex;flex-direction:column;gap:.4rem;margin-top:1rem;font-size:13px;font-weight:600}\n.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}\n.bl-library__usages{margin:1rem 0 0;padding-left:1.1rem;color:#475569;font-size:13px;font-weight:400}\n.bl-library__usages li{margin:.25rem 0}\n.bl-library__actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:.5rem;margin-top:1rem}\n.bl-library__actions button:last-child{border:0;background:#0f172a;color:#fff;font-weight:600}\n.bl-library__actions button:last-child:disabled{opacity:.4;cursor:not-allowed}\n.bl-theme-dialog .bl-nav-kit__modal{z-index:10000}\n`;\n","import { Badge, KitProvider } from \"@bison-lab/admin-ui\";\nimport type { ReactNode } from \"react\";\n\nexport function FontRoleCard({\n title,\n hint,\n required,\n family,\n preview,\n children,\n}: {\n title: string;\n hint: string;\n required?: boolean;\n family: string;\n preview: \"heading\" | \"body\";\n children?: ReactNode;\n}) {\n return (\n <KitProvider>\n <article className=\"bl-font-role\">\n <header className=\"bl-font-role__head\">\n <div>\n <h3>{title}</h3>\n <p>{hint}</p>\n </div>\n {required ? <Badge>Required</Badge> : null}\n </header>\n {children}\n <div className=\"bl-font-role__preview\">\n <span>Preview</span>\n {preview === \"heading\" ? (\n <p className=\"bl-font-role__heading\" style={{ fontFamily: `\"${family}\"` }}>\n Advancing the work with clarity.\n </p>\n ) : (\n <p className=\"bl-font-role__body\" style={{ fontFamily: `\"${family}\"` }}>\n Clear, comfortable text for longer reading across the site.\n </p>\n )}\n </div>\n </article>\n </KitProvider>\n );\n}\n\nexport function TypographyPairing({\n headingFamily,\n bodyFamily,\n}: {\n headingFamily: string;\n bodyFamily: string;\n}) {\n return (\n <section className=\"bl-pairing\" aria-label=\"Font pairing sample\">\n <header>\n <h2>Pairing sample</h2>\n <p>Heading and body from the approved catalogue. Type scale stays with the library.</p>\n </header>\n <div className=\"bl-pairing__page\">\n <p className=\"bl-pairing__eyebrow\" style={{ fontFamily: `\"${bodyFamily}\"` }}>\n For visitors\n </p>\n <p className=\"bl-pairing__title\" style={{ fontFamily: `\"${headingFamily}\"` }}>\n Stay in motion.\n </p>\n <p className=\"bl-pairing__copy\" style={{ fontFamily: `\"${bodyFamily}\"` }}>\n Heading and body come from the catalogue. This is the pairing, not a full site preview.\n </p>\n <div className=\"bl-pairing__actions\">\n <span className=\"bl-pairing__btn\" style={{ fontFamily: `\"${bodyFamily}\"` }}>\n Primary action\n </span>\n <span className=\"bl-pairing__btn bl-pairing__btn--ghost\" style={{ fontFamily: `\"${bodyFamily}\"` }}>\n Learn more\n </span>\n </div>\n </div>\n </section>\n );\n}\n\nexport const TYPOGRAPHY_PAIRING_CSS = `\n.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)}\n.bl-font-role__head{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem}\n.bl-font-role__head h3{margin:0;font-size:1rem}\n.bl-font-role__head p{margin:.3rem 0 0;font-size:12px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}\n.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))}\n.bl-font-role__preview > span{display:block;margin-bottom:.4rem;font-size:11px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}\n.bl-font-role__heading{margin:0;font-size:1.5rem;line-height:1.2;font-weight:600}\n.bl-font-role__body{margin:0;font-size:1rem;line-height:1.6;color:var(--bl-preview-muted,var(--theme-elevation-600,#475569))}\n.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}\n.bl-pairing > header{padding:1rem 1.15rem;border-bottom:1px solid var(--bl-preview-border,var(--theme-elevation-150,#e2e8f0))}\n.bl-pairing > header h2{margin:0;font-size:1rem}\n.bl-pairing > header p{margin:.3rem 0 0;font-size:12px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}\n.bl-pairing__page{padding:1.35rem 1.4rem 1.5rem;background:var(--bl-preview-bg,transparent)}\n.bl-pairing__eyebrow{margin:0;font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:#7c1fa2}\n.bl-pairing__title{margin:.5rem 0 0;font-size:2rem;line-height:1.1;font-weight:600}\n.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))}\n.bl-pairing__actions{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:1.1rem}\n.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}\n.bl-pairing__btn--ghost{background:#fff;color:#0f172a;border:1px solid #cbd5e1}\n`;\n","import { FieldDescription, FieldError, FieldLabel, useField } from \"@payloadcms/ui\";\nimport { findFont, fontFaceCss, isFontId, type FontId } from \"@bison-lab/fonts\";\nimport type { SelectFieldClientComponent } from \"payload\";\nimport { useEffect, useId, useMemo, useRef, useState } from \"react\";\n\nimport { FONT_ROLE_COPY } from \"../theme/appearance-labels\";\nimport { SAME_AS_BODY } from \"../theme/fields\";\nimport { usePreviewCanvas } from \"./preview-mode\";\nimport { FontRoleCard, TYPOGRAPHY_PAIRING_CSS } from \"./typography-pairing\";\n\ntype Option = { value: string; family: string; hint: string; specimen: boolean };\n\n/**\n * Listbox over the catalogue ids in `admin.custom.ids`. Each option is the\n * family name in that face, with the catalogue hint beneath. Faces load\n * from the site's font route for the selected family, and for every\n * catalogue id once the picker opens.\n */\nexport const FontField: SelectFieldClientComponent = ({ field, path, readOnly }) => {\n const { value, setValue, showError, errorMessage } = useField<string>({ path });\n const custom = (field.admin?.custom ?? {}) as {\n fontsBaseUrl?: string;\n ids?: string[];\n sameAsBody?: boolean;\n };\n const ids = custom.ids ?? [];\n const fontsBaseUrl = custom.fontsBaseUrl ?? \"/fonts\";\n const sameAsBody = Boolean(custom.sameAsBody);\n\n const options = useMemo<Option[]>(() => {\n const fromCatalogue: Option[] = ids.flatMap((id) => {\n const font = findFont(id);\n if (!font) return [];\n return [{ value: font.id, family: font.family, hint: font.hint, specimen: true }];\n });\n if (!sameAsBody) return fromCatalogue;\n return [{ value: SAME_AS_BODY, family: \"Same as body\", hint: \"Use the body family for headings\", specimen: false }, ...fromCatalogue];\n }, [ids, sameAsBody]);\n\n const [open, setOpen] = useState(false);\n const [faces, setFaces] = useState(false);\n const [active, setActive] = useState(-1);\n const [query, setQuery] = useState(\"\");\n const [category, setCategory] = useState<\"all\" | \"sans\" | \"serif\" | \"display\" | \"mono\">(\"all\");\n const typed = useRef(\"\");\n const typedAt = useRef(0);\n const id = useId();\n const buttonId = `${id}-button`;\n const listId = `${id}-list`;\n const required = Boolean(field.required);\n\n useEffect(() => {\n if (open) setFaces(true);\n }, [open]);\n\n const selected = options.find((option) => option.value === (value ?? SAME_AS_BODY)) ?? options[0];\n const visible = options.filter((option) => {\n if (query && !option.family.toLowerCase().includes(query.trim().toLowerCase())) return false;\n if (category === \"all\" || !option.specimen) return true;\n const font = findFont(option.value);\n return font?.category === category;\n });\n const role = sameAsBody ? FONT_ROLE_COPY.heading : FONT_ROLE_COPY.body;\n\n function choose(option: Option) {\n setValue(option.value);\n setOpen(false);\n setActive(-1);\n setQuery(\"\");\n setCategory(\"all\");\n }\n\n function onKeyDown(event: React.KeyboardEvent<HTMLButtonElement>) {\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n if (!open) {\n setOpen(true);\n setActive(0);\n return;\n }\n setActive((i) => (options.length ? (i + 1) % options.length : -1));\n } else if (event.key === \"ArrowUp\") {\n event.preventDefault();\n if (!open) {\n setOpen(true);\n setActive(options.length - 1);\n return;\n }\n setActive((i) => (options.length ? (i <= 0 ? options.length - 1 : i - 1) : -1));\n } else if (event.key === \"Enter\") {\n if (!open) return;\n event.preventDefault();\n const pick = options[active] ?? options[0];\n if (pick) choose(pick);\n } else if (event.key === \"Escape\") {\n if (!open) return;\n event.preventDefault();\n event.stopPropagation();\n setOpen(false);\n setActive(-1);\n } else if (event.key.length === 1 && !event.metaKey && !event.ctrlKey && !event.altKey) {\n const now = Date.now();\n typed.current = now - typedAt.current > 600 ? event.key : typed.current + event.key;\n typedAt.current = now;\n const needle = typed.current.toLowerCase();\n const index = options.findIndex((option) => option.family.toLowerCase().startsWith(needle));\n if (index >= 0) {\n if (!open) setOpen(true);\n setActive(index);\n }\n }\n }\n\n const activeId = active >= 0 && open ? `${id}-option-${active}` : undefined;\n const faceIds = (faces ? ids : isFontId(value) ? [value] : []) as FontId[];\n const canvas = usePreviewCanvas();\n\n return (\n <div className={`field-type bl-font-field ${canvas.className}`} data-preview={canvas.mode} style={canvas.style}>\n <style href=\"bl-pairing\" precedence=\"default\">\n {TYPOGRAPHY_PAIRING_CSS}\n </style>\n <style href=\"bl-font-field\" precedence=\"default\">\n {CSS}\n </style>\n {faceIds.length > 0 ? <style data-bl-font-faces=\"\">{fontFaceCss(faceIds, fontsBaseUrl)}</style> : null}\n <FontRoleCard\n title={typeof field.label === \"string\" ? field.label : role.label}\n hint={role.hint}\n required={required}\n family={selected?.family ?? \"Inter\"}\n preview={sameAsBody ? \"heading\" : \"body\"}\n >\n <FieldLabel htmlFor={buttonId} label={field.label} required={required} />\n <button\n id={buttonId}\n type=\"button\"\n className=\"bl-font-field__trigger\"\n disabled={readOnly}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-controls={listId}\n aria-activedescendant={activeId}\n onClick={() => setOpen((was) => !was)}\n onKeyDown={onKeyDown}\n >\n <span>\n <span className=\"bl-font-field__selected-label\">Selected</span>\n <span\n className=\"bl-font-field__selected-name\"\n style={selected?.specimen ? { fontFamily: `\"${selected.family}\"` } : undefined}\n >\n {selected?.family ?? \"Choose a font\"}\n </span>\n </span>\n <span aria-hidden=\"true\">⌄</span>\n </button>\n </FontRoleCard>\n {open ? (\n <div\n className=\"bl-font-field__modal\"\n onClick={(event) => {\n if (event.target === event.currentTarget) setOpen(false);\n }}\n >\n <div className=\"bl-font-field__panel\">\n <div className=\"bl-font-field__panel-head\">\n <div>\n <p>Choose a font</p>\n <h2>{role.label}</h2>\n </div>\n <button type=\"button\" onClick={() => setOpen(false)} aria-label=\"Close\">\n ×\n </button>\n </div>\n <input\n type=\"search\"\n className=\"bl-font-field__search\"\n placeholder=\"Search fonts…\"\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n />\n <div className=\"bl-font-field__filters\">\n {([\"all\", \"sans\", \"serif\", \"display\", \"mono\"] as const).map((item) => (\n <button\n key={item}\n type=\"button\"\n data-on={category === item ? \"\" : undefined}\n onClick={() => setCategory(item)}\n >\n {item === \"all\" ? \"All\" : item === \"sans\" ? \"Sans serif\" : item === \"serif\" ? \"Serif\" : item === \"display\" ? \"Display\" : \"Mono\"}\n </button>\n ))}\n </div>\n <ul id={listId} role=\"listbox\" className=\"bl-font-field__menu\">\n {visible.map((option, i) => (\n <li\n key={option.value || \"same\"}\n id={`${id}-option-${i}`}\n role=\"option\"\n aria-selected={option.value === (value ?? SAME_AS_BODY)}\n className=\"bl-font-field__option\"\n onMouseDown={(event) => {\n event.preventDefault();\n choose(option);\n }}\n onMouseEnter={() => setActive(i)}\n >\n <span\n className=\"bl-font-field__family\"\n style={option.specimen ? { fontFamily: `\"${option.family}\"` } : undefined}\n >\n {option.family}\n </span>\n <span className=\"bl-font-field__hint\">{option.hint}</span>\n <span\n className=\"bl-font-field__specimen\"\n style={option.specimen ? { fontFamily: `\"${option.family}\"` } : undefined}\n >\n The quick brown fox jumps over the lazy dog.\n </span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n ) : null}\n <FieldDescription description={field.admin?.description} path={path} />\n <FieldError path={path} showError={showError} message={errorMessage} />\n </div>\n );\n};\n\nconst CSS = `\n.bl-font-field{margin-bottom:1rem}\n.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}\n.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}\n.bl-font-field__trigger:focus{border-color:var(--theme-elevation-400,#94a3b8);outline:none;box-shadow:0 0 0 1px var(--theme-elevation-400,#94a3b8)}\n.bl-font-field__trigger:disabled{color:var(--theme-elevation-400,#94a3b8);cursor:not-allowed}\n.bl-font-field__selected-label{display:block;font-size:11px;color:var(--theme-elevation-500,#64748b)}\n.bl-font-field__selected-name{display:block;margin-top:.15rem;font-weight:600}\n.bl-font-field__modal{position:fixed;inset:0;z-index:10000;display:grid;place-items:center;padding:1rem;background:rgba(15,23,42,.45)}\n.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}\n.bl-font-field__panel-head{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem}\n.bl-font-field__panel-head p{margin:0;font-size:12px;color:#64748b}\n.bl-font-field__panel-head h2{margin:.2rem 0 0;font-size:1.15rem}\n.bl-font-field__panel-head button{border:0;background:none;font:inherit;font-size:1.25rem;color:#64748b;cursor:pointer}\n.bl-font-field__search{margin-top:.9rem;min-height:2.5rem;padding:.5rem .75rem;border:1px solid #cbd5e1;border-radius:10px;font:inherit}\n.bl-font-field__filters{display:flex;flex-wrap:wrap;gap:.4rem;margin-top:.75rem}\n.bl-font-field__filters button{min-height:1.8rem;padding:.2rem .7rem;border:0;border-radius:999px;background:#f1f5f9;color:#475569;font:inherit;font-size:12px;cursor:pointer}\n.bl-font-field__filters button[data-on]{background:#0f172a;color:#fff}\n.bl-font-field__menu{margin:.75rem 0 0;padding:0;list-style:none;overflow:auto;max-height:18rem}\n.bl-font-field__option{display:flex;flex-direction:column;gap:2px;margin-bottom:.5rem;padding:.75rem .85rem;border:1px solid #e2e8f0;border-radius:12px;cursor:pointer}\n.bl-font-field__option[aria-selected=\"true\"]{border-color:#7c1fa2;background:#f5f3ff}\n.bl-font-field__family{font-weight:600}\n.bl-font-field__hint{color:#64748b;font-size:12px}\n.bl-font-field__specimen{margin-top:.45rem;font-size:1.25rem;line-height:1.3}\n`;\n","import { useFormFields } from \"@payloadcms/ui\";\nimport { findFont, fontFaceCss, type FontId } from \"@bison-lab/fonts\";\nimport type { UIFieldClientComponent } from \"payload\";\n\nimport { SAME_AS_BODY } from \"../theme/fields\";\nimport { usePreviewCanvas } from \"./preview-mode\";\nimport { TypographyPairing, TYPOGRAPHY_PAIRING_CSS } from \"./typography-pairing\";\n\n/**\n * Pairing sample only — no weight, letter-spacing, line-height, or health\n * scores. Faces load from the site's font route.\n */\nexport const PairingField: UIFieldClientComponent = ({ field }) => {\n const custom = (field.admin?.custom ?? {}) as { fontsBaseUrl?: string };\n const fontsBaseUrl = custom.fontsBaseUrl ?? \"/fonts\";\n const { body, heading } = useFormFields(([fields]) => {\n const record = fields as Record<string, { value?: unknown } | undefined>;\n return {\n body: String(record[\"typography.body\"]?.value ?? \"\"),\n heading: String(record[\"typography.heading\"]?.value ?? SAME_AS_BODY),\n };\n });\n const headingId = heading || body;\n const bodyFont = findFont(body);\n const headingFont = findFont(headingId);\n const ids = [body, headingId].filter(Boolean) as FontId[];\n const canvas = usePreviewCanvas();\n\n return (\n <div className={`field-type bl-pairing-field ${canvas.className}`} data-preview={canvas.mode} style={canvas.style}>\n <style href=\"bl-pairing\" precedence=\"default\">\n {TYPOGRAPHY_PAIRING_CSS}\n </style>\n {ids.length > 0 ? <style data-bl-font-faces=\"\">{fontFaceCss(ids, fontsBaseUrl)}</style> : null}\n <TypographyPairing\n headingFamily={headingFont?.family ?? \"Georgia\"}\n bodyFamily={bodyFont?.family ?? \"system-ui\"}\n />\n </div>\n );\n};\n","import { APPEARANCE_CHOICES, APPEARANCE_FAMILY_COPY } from \"../theme/appearance-labels\";\n\ntype Family = keyof typeof APPEARANCE_CHOICES;\n\nfunction ChoicePreview({ family, value }: { family: Family; value: string }) {\n return (\n <div className=\"bl-appearance__preview\" data-family={family} data-value={value} aria-hidden=\"true\">\n {family === \"defaultTheme\" && value === \"system\" ? (\n <>\n <div className=\"bl-appearance__pane bl-appearance__pane--light\">\n <i />\n <b />\n </div>\n <div className=\"bl-appearance__pane bl-appearance__pane--dark\">\n <i />\n <b />\n </div>\n </>\n ) : family === \"motion\" ? (\n <span className=\"bl-appearance__dot\" />\n ) : family === \"shadow\" ? (\n <div className=\"bl-appearance__lift\" />\n ) : family === \"radius\" ? (\n <>\n <b>Button</b>\n <i className=\"bl-appearance__input\" />\n <i className=\"bl-appearance__card\" />\n </>\n ) : family === \"density\" ? (\n <>\n <b />\n <i className=\"bl-appearance__input\" />\n <i className=\"bl-appearance__card\" />\n </>\n ) : (\n <>\n <i />\n <i />\n <b />\n </>\n )}\n </div>\n );\n}\n\nexport function AppearanceChoices({\n values,\n onChange,\n readOnly,\n}: {\n values: Record<Family, string>;\n onChange: (name: Family, value: string) => void;\n readOnly?: boolean;\n}) {\n return (\n <div className=\"bl-appearance\">\n <header className=\"bl-appearance__intro\">\n <h2>Set the overall feel of your site</h2>\n <p>\n Choose how rounded, elevated, animated, and spacious the interface feels. You don’t manage the\n technical values — the system handles those.\n </p>\n </header>\n {(Object.keys(APPEARANCE_CHOICES) as Family[]).map((family) => {\n const choices = APPEARANCE_CHOICES[family];\n const copy = APPEARANCE_FAMILY_COPY[family];\n return (\n <fieldset key={family} className=\"bl-appearance__family\">\n <legend>\n <strong>{copy.title}</strong>\n <span>{copy.hint}</span>\n </legend>\n <div className=\"bl-appearance__choices\" data-family={family}>\n {Object.entries(choices).map(([value, item]) => {\n const selected = values[family] === value;\n return (\n <label\n key={value}\n className=\"bl-appearance__choice\"\n data-selected={selected ? \"\" : undefined}\n >\n <input\n type=\"radio\"\n name={family}\n value={value}\n checked={selected}\n disabled={readOnly}\n onChange={() => onChange(family, value)}\n />\n <ChoicePreview family={family} value={value} />\n <span className=\"bl-appearance__copy\">\n <strong>\n {item.label}\n {selected ? <em aria-hidden=\"true\">✓</em> : null}\n </strong>\n <span>{item.hint}</span>\n </span>\n </label>\n );\n })}\n </div>\n {family === \"motion\" ? (\n <p className=\"bl-appearance__note\">\n Visitors who prefer reduced motion will still see fewer animations automatically.\n </p>\n ) : null}\n </fieldset>\n );\n })}\n </div>\n );\n}\n\nexport const APPEARANCE_CHOICES_CSS = `\n.bl-appearance{display:flex;flex-direction:column;gap:1.25rem;color:var(--bl-preview-text,inherit)}\n.bl-appearance__intro h2{margin:0;font-size:1.1rem}\n.bl-appearance__intro p{margin:.35rem 0 0;font-size:13px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b));max-width:40rem}\n.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))}\n.bl-appearance__family legend{padding:0;margin-bottom:.85rem}\n.bl-appearance__family legend strong{display:block;font-size:14px}\n.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}\n.bl-appearance__choices{display:grid;gap:.6rem}\n.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))}\n.bl-appearance__choices[data-family=radius]{grid-template-columns:repeat(4,minmax(0,1fr))}\n.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}\n.bl-appearance__choice[data-selected]{box-shadow:inset 0 0 0 2px var(--bl-preview-text,#0f172a);border-color:var(--bl-preview-text,#0f172a)}\n.bl-appearance__choice input{position:absolute;opacity:0;pointer-events:none}\n.bl-appearance__copy{display:flex;flex-direction:column;gap:.2rem}\n.bl-appearance__copy strong{display:flex;justify-content:space-between;align-items:center;gap:.4rem;font-size:14px}\n.bl-appearance__copy em{font-style:normal}\n.bl-appearance__copy span{font-size:12px;color:var(--theme-elevation-500,#64748b)}\n.bl-appearance__note{margin:.75rem 0 0;font-size:12px;color:var(--theme-elevation-500,#64748b)}\n.bl-appearance__preview{--bl-preview-brand:#db0082;--bl-preview-radius:8px;border-radius:10px;background:#f8fafc;overflow:hidden}\n.bl-appearance__preview[data-family=defaultTheme]{display:grid;min-height:5.5rem;padding:.65rem}\n.bl-appearance__preview[data-family=defaultTheme][data-value=system]{grid-template-columns:1fr 1fr;padding:0}\n.bl-appearance__preview[data-family=defaultTheme][data-value=dark]{background:#020617}\n.bl-appearance__pane{display:flex;flex-direction:column;gap:.45rem;padding:.65rem}\n.bl-appearance__pane--dark{background:#020617}\n.bl-appearance__pane i,.bl-appearance__preview[data-family=defaultTheme] > i{display:block;height:.4rem;width:42%;border-radius:99px;background:#0f172a}\n.bl-appearance__pane i + i,.bl-appearance__preview[data-family=defaultTheme] > i + i{width:64%;background:#cbd5e1}\n.bl-appearance__pane--dark i{background:#fff}\n.bl-appearance__pane--dark i + i{background:#334155}\n.bl-appearance__preview[data-family=defaultTheme][data-value=dark] > i{background:#fff}\n.bl-appearance__preview[data-family=defaultTheme][data-value=dark] > i + i{background:#334155}\n.bl-appearance__pane b,.bl-appearance__preview[data-family=defaultTheme] > b{display:block;height:1.6rem;margin-top:auto;border-radius:6px;background:var(--bl-preview-brand)}\n.bl-appearance__pane--dark b{background:var(--bl-preview-brand)}\n.bl-appearance__preview[data-family=radius]{display:flex;flex-direction:column;gap:.45rem;padding:.65rem;background:#fff}\n.bl-appearance__preview[data-family=radius] b{display:grid;place-items:center;height:1.85rem;background:var(--bl-preview-brand);color:#fff;font-size:10px;font-weight:600;border-radius:var(--bl-preview-radius)}\n.bl-appearance__input{display:block;height:1.85rem;border:1px solid #cbd5e1;background:#f8fafc;border-radius:var(--bl-preview-radius)}\n.bl-appearance__card{display:block;height:2.4rem;border:1px solid #e2e8f0;background:#fff;border-radius:var(--bl-preview-radius)}\n.bl-appearance__preview[data-value=sharp]{--bl-preview-radius:0}\n.bl-appearance__preview[data-value=subtle]{--bl-preview-radius:6px}\n.bl-appearance__preview[data-value=rounded]{--bl-preview-radius:12px}\n.bl-appearance__preview[data-value=pill]{--bl-preview-radius:999px}\n.bl-appearance__preview[data-value=pill] .bl-appearance__card{--bl-preview-radius:1.25rem}\n.bl-appearance__preview[data-family=shadow]{display:grid;place-items:center;min-height:6.5rem;padding:.85rem}\n.bl-appearance__lift{width:100%;height:3.5rem;border-radius:10px;background:#fff}\n.bl-appearance__preview[data-value=flat] .bl-appearance__lift{border:1px solid #e2e8f0}\n.bl-appearance__preview[data-value=subtle] .bl-appearance__lift{box-shadow:0 1px 2px rgba(15,23,42,.06),0 4px 12px rgba(15,23,42,.06)}\n.bl-appearance__preview[data-value=elevated] .bl-appearance__lift{box-shadow:0 10px 30px rgba(15,23,42,.12)}\n.bl-appearance__preview[data-family=motion]{display:flex;align-items:center;min-height:4.5rem;padding:0 .85rem}\n.bl-appearance__dot{width:1.15rem;height:1.15rem;border-radius:999px;background:var(--bl-preview-brand);animation:bl-appear-dot 1.8s ease-in-out infinite}\n.bl-appearance__preview[data-value=snappy] .bl-appearance__dot{animation-duration:1s}\n.bl-appearance__preview[data-value=minimal] .bl-appearance__dot{animation-duration:2.5s}\n@keyframes bl-appear-dot{0%,100%{transform:translateX(0)}50%{transform:translateX(4.5rem)}}\n.bl-appearance__preview[data-family=density]{display:flex;flex-direction:column;background:#f8fafc}\n.bl-appearance__preview[data-value=compact]{gap:.4rem;padding:.55rem}\n.bl-appearance__preview[data-value=default]{gap:.65rem;padding:.8rem}\n.bl-appearance__preview[data-value=spacious]{gap:.9rem;padding:1.05rem}\n.bl-appearance__preview[data-family=density] b{display:block;height:1.7rem;background:var(--bl-preview-brand);border-radius:6px}\n.bl-appearance__preview[data-value=compact] b,.bl-appearance__preview[data-value=compact] .bl-appearance__input{height:1.45rem}\n.bl-appearance__preview[data-value=spacious] b,.bl-appearance__preview[data-value=spacious] .bl-appearance__input{height:2.1rem}\n@media (max-width:720px){\n .bl-appearance__choices[data-family=defaultTheme],.bl-appearance__choices[data-family=shadow],.bl-appearance__choices[data-family=motion],.bl-appearance__choices[data-family=density],.bl-appearance__choices[data-family=radius]{grid-template-columns:1fr}\n}\n@media (prefers-reduced-motion:reduce){\n .bl-appearance__dot{animation:none}\n}\n`;\n","import { useField } from \"@payloadcms/ui\";\nimport type { GroupFieldClientComponent } from \"payload\";\n\nimport { APPEARANCE_CHOICES } from \"../theme/appearance-labels\";\nimport { AppearanceChoices, APPEARANCE_CHOICES_CSS } from \"./appearance-choices\";\nimport { usePreviewCanvas } from \"./preview-mode\";\n\ntype Family = keyof typeof APPEARANCE_CHOICES;\n\n/**\n * Named appearance choices. Soft → pill, Gentle → minimal, Balanced →\n * default, Follow device → system. No rem or ms.\n */\nexport const AppearanceField: GroupFieldClientComponent = ({ path, readOnly }) => {\n const defaultTheme = useField<string>({ path: `${path}.defaultTheme` });\n const radius = useField<string>({ path: `${path}.radius` });\n const shadow = useField<string>({ path: `${path}.shadow` });\n const motion = useField<string>({ path: `${path}.motion` });\n const density = useField<string>({ path: `${path}.density` });\n const fields = { defaultTheme, radius, shadow, motion, density };\n const canvas = usePreviewCanvas();\n\n function onChange(name: Family, value: string) {\n fields[name].setValue(value);\n }\n\n return (\n <div className={`field-type bl-appearance-field ${canvas.className}`} data-preview={canvas.mode} style={canvas.style}>\n <style href=\"bl-appearance\" precedence=\"default\">\n {APPEARANCE_CHOICES_CSS}\n </style>\n <AppearanceChoices\n values={{\n defaultTheme: defaultTheme.value ?? \"system\",\n radius: radius.value ?? \"rounded\",\n shadow: shadow.value ?? \"subtle\",\n motion: motion.value ?? \"smooth\",\n density: density.value ?? \"default\",\n }}\n onChange={onChange}\n readOnly={readOnly}\n />\n </div>\n );\n};\n","import { Badge, KitProvider } from \"@bison-lab/admin-ui\";\nimport { GREY_SCALES, presetHints, type GreyScale } from \"@bison-lab/tokens\";\nimport { useField } from \"@payloadcms/ui\";\nimport type { SelectFieldClientComponent } from \"payload\";\n\nimport { usePreviewCanvas } from \"./preview-mode\";\n\nconst FAMILIES = Object.keys(presetHints.greyScale) as GreyScale[];\nconst SWATCHES = [\"50\", \"200\", \"400\", \"700\", \"950\"] as const;\n\nexport function GreyScaleChoices({\n value,\n onChange,\n readOnly,\n}: {\n value: GreyScale;\n onChange: (next: GreyScale) => void;\n readOnly?: boolean;\n}) {\n const canvas = usePreviewCanvas();\n return (\n <KitProvider>\n <section className={`bl-grey ${canvas.className}`} data-preview={canvas.mode} style={canvas.style}>\n <div className=\"bl-grey__section\">\n <h2>Neutrals</h2>\n <p>Choose the gray family used for backgrounds, borders, cards, inputs, and muted text.</p>\n </div>\n <header className=\"bl-grey__head\">\n <div>\n <h2>Gray family</h2>\n <p>Choose the neutral family used for page backgrounds, cards, borders, inputs, and muted text. Readability for these system neutrals is handled automatically.</p>\n </div>\n <Badge>Required</Badge>\n </header>\n <div className=\"bl-grey__choices\">\n {FAMILIES.map((id) => {\n const copy = presetHints.greyScale[id];\n const selected = value === id;\n return (\n <label key={id} className=\"bl-grey__choice\" data-selected={selected ? \"\" : undefined}>\n <input\n type=\"radio\"\n name=\"greyScale\"\n value={id}\n checked={selected}\n disabled={readOnly}\n onChange={() => onChange(id)}\n />\n <span className=\"bl-grey__ramp\" aria-hidden=\"true\">\n {SWATCHES.map((step) => (\n <i key={step} style={{ background: `hsl(${GREY_SCALES[id][step]})` }} />\n ))}\n </span>\n <strong>\n {copy.label}\n {selected ? <em aria-hidden=\"true\">✓</em> : null}\n </strong>\n <span>{copy.hint}</span>\n </label>\n );\n })}\n </div>\n </section>\n </KitProvider>\n );\n}\n\n/**\n * Visual picker over the five grey-scale presets. Replaces the stock select\n * on Colors; the stored value is still `colors.greyScale`.\n */\nexport const GreyScaleField: SelectFieldClientComponent = ({ field, path, readOnly }) => {\n const dataPath =\n typeof field.admin?.custom?.dataPath === \"string\" ? field.admin.custom.dataPath : path;\n const { value, setValue } = useField<GreyScale>({ path: dataPath });\n\n return (\n <div className=\"field-type bl-grey-field\">\n <style href=\"bl-grey\" precedence=\"default\">\n {GREY_SCALE_FIELD_CSS}\n </style>\n <GreyScaleChoices value={value ?? \"slate\"} onChange={setValue} readOnly={readOnly} />\n </div>\n );\n};\n\nexport const GREY_SCALE_FIELD_CSS = `\n.bl-grey{margin:0 0 1.75rem}\n.bl-grey__section{margin:1.25rem 0 .85rem}\n.bl-grey__section h2{margin:0;font-size:1.1rem}\n.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)}\n.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)}\n.bl-grey__head h2{margin:0;font-size:1.1rem}\n.bl-grey__head p{margin:.35rem 0 0;max-width:40rem;font-size:13px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}\n.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)}\n.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}\n.bl-grey__choice[data-selected]{box-shadow:inset 0 0 0 2px var(--bl-preview-text,#0f172a);border-color:var(--bl-preview-text,#0f172a)}\n.bl-grey__choice input{position:absolute;opacity:0;pointer-events:none}\n.bl-grey__ramp{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:3px}\n.bl-grey__ramp i{display:block;height:2rem;border-radius:6px}\n.bl-grey__choice strong{display:flex;justify-content:space-between;align-items:center;gap:.4rem;font-size:14px}\n.bl-grey__choice em{font-style:normal}\n.bl-grey__choice > span{font-size:12px;color:var(--bl-preview-muted,var(--theme-elevation-500,#64748b))}\n@media (max-width:720px){.bl-grey__choices{grid-template-columns:1fr}}\n`;\n","import { useFormFields } from \"@payloadcms/ui\";\nimport { isThemeHex } from \"@bison-lab/tokens\";\nimport type { UIFieldClientComponent } from \"payload\";\nimport { useRef } from \"react\";\n\nimport { SYSTEM_COLOR_COPY } from \"../theme/appearance-labels\";\nimport { fillLabelWarning, READABILITY_TARGET, type FillLabelWarning } from \"../theme/readability\";\nimport { SYSTEM_COLOR_KEYS } from \"../theme/types\";\nimport { THEME_COLORS_LAYOUT_CSS } from \"./colors-layout\";\nimport { ReadabilityList, READABILITY_LIST_CSS } from \"./readability-list\";\n\nfunction hexAt(fields: Record<string, { value?: unknown } | undefined>, path: string): string {\n const value = fields[path]?.value;\n return typeof value === \"string\" ? value : \"\";\n}\n\n/**\n * Fill + automatic label only. Target 7:1, Light and Dark. No gray\n * ContrastStrip. Warnings do not block save.\n */\nexport const ContrastReport: UIFieldClientComponent = ({ field }) => {\n const target = Number((field.admin?.custom as { target?: number } | undefined)?.target) || READABILITY_TARGET;\n const hexes = useFormFields(([fields]) => {\n const record = fields as Record<string, { value?: unknown } | undefined>;\n const system = Object.fromEntries(\n SYSTEM_COLOR_KEYS.map((key) => [key, hexAt(record, `colors.brand.${key}.hex`)]),\n ) as Record<(typeof SYSTEM_COLOR_KEYS)[number], string>;\n const library = record[\"colors.library\"]?.value;\n const custom = Array.isArray(library)\n ? library.flatMap((row, index) => {\n const hex = typeof row === \"object\" && row && \"hex\" in row ? String(row.hex ?? \"\") : \"\";\n const name =\n typeof row === \"object\" && row && \"label\" in row ? String(row.label ?? row.key ?? \"Custom\") : \"Custom\";\n return hex ? [{ id: `library-${index}`, name, hex }] : [];\n })\n : [];\n return { system, custom };\n });\n\n const last = useRef<FillLabelWarning[] | null>(null);\n const complete = SYSTEM_COLOR_KEYS.every((key) => isThemeHex(hexes.system[key]));\n if (complete) {\n last.current = [\n ...SYSTEM_COLOR_KEYS.map((key) =>\n fillLabelWarning(key, SYSTEM_COLOR_COPY[key].label, hexes.system[key], target),\n ),\n ...hexes.custom.map((row) => fillLabelWarning(row.id, row.name, row.hex, target)),\n ].filter((item): item is FillLabelWarning => item !== null);\n }\n\n const warnings = last.current ?? [];\n const stale = Boolean(last.current) && !complete;\n\n return (\n <div className=\"field-type bl-contrast-report\">\n <style href=\"bl-readability\" precedence=\"default\">\n {READABILITY_LIST_CSS}\n </style>\n <style href=\"bl-theme-colors-layout\" precedence=\"default\">\n {THEME_COLORS_LAYOUT_CSS}\n </style>\n {stale ? (\n <p className=\"bl-contrast-report__stale\">Showing the last complete audit while a colour is being typed.</p>\n ) : null}\n {warnings.length > 0 ? <ReadabilityList warnings={warnings} target={target} /> : (\n <p>Enter hex colours to measure the automatic label on each fill.</p>\n )}\n </div>\n );\n};\n","import type { UIFieldClientComponent } from \"payload\";\n\nimport { THEME_COLORS_LAYOUT_CSS } from \"./colors-layout\";\n\n/**\n * Unnamed UI heading between Theme fields. No document path.\n */\nexport const SectionHeading: UIFieldClientComponent = ({ field }) => {\n const custom = (field.admin?.custom ?? {}) as { title?: string; hint?: string };\n if (!custom.title) return null;\n return (\n <header className=\"bl-section-heading\">\n <style href=\"bl-section-heading\" precedence=\"default\">\n {CSS}\n </style>\n <style href=\"bl-theme-colors-layout\" precedence=\"default\">\n {THEME_COLORS_LAYOUT_CSS}\n </style>\n <h2>{custom.title}</h2>\n {custom.hint ? <p>{custom.hint}</p> : null}\n </header>\n );\n};\n\nconst CSS = `\n.bl-section-heading{margin:1.25rem 0 .65rem}\n.bl-section-heading:first-child{margin-top:0}\n.bl-section-heading h2{margin:0;font-size:1.1rem}\n.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}\n`;\n","import { SYSTEM_COLOR_KEYS, type ThemeDoc, type ThemeLibraryColorDoc } from \"./types\";\nimport type { ThemeChild } from \"./publish\";\n\n/** Payload may hand an empty array field as `{}`. `.map` on that crashes the Theme form. */\nexport function libraryRows(value: unknown): ThemeLibraryColorDoc[] {\n return Array.isArray(value) ? value : [];\n}\n\nfunction colorLine(name: string, before: unknown, after: unknown): string | null {\n const a = before && typeof before === \"object\" ? before : { hex: before };\n const b = after && typeof after === \"object\" ? after : { hex: after };\n const left = a as { hex?: unknown; sourceStep?: unknown };\n const right = b as { hex?: unknown; sourceStep?: unknown };\n if (left.hex === right.hex && String(left.sourceStep) === String(right.sourceStep)) return null;\n return `${name}: ${String(left.hex ?? \"—\")} → ${String(right.hex ?? \"—\")}`;\n}\n\n/**\n * Human lines for the Publish confirmation. Only this child's\n * differences; other responsibilities are not listed.\n */\nexport function themeChildChanges(child: ThemeChild, published: ThemeDoc, incoming: ThemeDoc): string[] {\n if (child === \"colors\") {\n const lines: string[] = [];\n for (const key of SYSTEM_COLOR_KEYS) {\n const line = colorLine(\n key[0].toUpperCase() + key.slice(1),\n published.colors?.brand?.[key],\n incoming.colors?.brand?.[key],\n );\n if (line) lines.push(line);\n }\n const beforeKeys = libraryRows(published.colors?.library)\n .map((row) => row.key)\n .join(\", \");\n const afterKeys = libraryRows(incoming.colors?.library)\n .map((row) => row.key)\n .join(\", \");\n if (beforeKeys !== afterKeys) lines.push(`Custom colors: ${beforeKeys || \"none\"} → ${afterKeys || \"none\"}`);\n if ((published.colors?.greyScale ?? \"\") !== (incoming.colors?.greyScale ?? \"\")) {\n lines.push(`Gray family: ${published.colors?.greyScale ?? \"—\"} → ${incoming.colors?.greyScale ?? \"—\"}`);\n }\n return lines;\n }\n if (child === \"typography\") {\n const lines: string[] = [];\n if ((published.typography?.heading ?? \"\") !== (incoming.typography?.heading ?? \"\")) {\n lines.push(`Heading: ${published.typography?.heading || \"same as body\"} → ${incoming.typography?.heading || \"same as body\"}`);\n }\n if ((published.typography?.body ?? \"\") !== (incoming.typography?.body ?? \"\")) {\n lines.push(`Body: ${published.typography?.body ?? \"—\"} → ${incoming.typography?.body ?? \"—\"}`);\n }\n return lines;\n }\n if (child === \"appearance\") {\n const keys = [\"defaultTheme\", \"radius\", \"shadow\", \"motion\", \"density\"] as const;\n return keys.flatMap((key) => {\n const left = published.appearance?.[key] ?? \"\";\n const right = incoming.appearance?.[key] ?? \"\";\n return left === right ? [] : [`${key}: ${left || \"—\"} → ${right || \"—\"}`];\n });\n }\n const lines: string[] = [];\n if (uploadId(published.logo) !== uploadId(incoming.logo)) lines.push(\"Logo updated\");\n if (uploadId(published.favicon) !== uploadId(incoming.favicon)) lines.push(\"Favicon updated\");\n if (uploadId(published.logoMark) !== uploadId(incoming.logoMark)) lines.push(\"Mobile menu logo updated\");\n return lines;\n}\n\nfunction uploadId(value: ThemeDoc[\"logo\"]): string {\n if (value && typeof value === \"object\" && value.id != null) return String(value.id);\n if (typeof value === \"string\" || typeof value === \"number\") return String(value);\n return \"\";\n}\n","import { THEME_SLUG, type ThemeColorDoc, type ThemeDoc } from \"./types\";\n\nexport const THEME_CHILDREN = [\"colors\", \"typography\", \"appearance\", \"identity\"] as const;\n\nexport type ThemeChild = (typeof THEME_CHILDREN)[number];\n\n/**\n * Publishing a child writes that slice only. Other responsibilities stay\n * as they already are on the stored document. Unsaved form state on a\n * different child never goes live. A first save (no stored row) still\n * writes only the named child; `getPublishedTheme` fills the rest from\n * the seed.\n */\nexport function publishThemeChild(stored: ThemeDoc, incoming: ThemeDoc, child: ThemeChild): ThemeDoc {\n if (child === \"colors\") return { ...stored, colors: incoming.colors };\n if (child === \"typography\") return { ...stored, typography: incoming.typography };\n if (child === \"appearance\") return { ...stored, appearance: incoming.appearance };\n return { ...stored, logo: incoming.logo, favicon: incoming.favicon, logoMark: incoming.logoMark };\n}\n\nexport function isThemeChild(value: unknown): value is ThemeChild {\n return typeof value === \"string\" && (THEME_CHILDREN as readonly string[]).includes(value);\n}\n\nexport function sliceFromTheme(theme: ThemeDoc, child: ThemeChild): ThemeDoc {\n if (child === \"colors\") return { colors: theme.colors };\n if (child === \"typography\") return { typography: theme.typography };\n if (child === \"appearance\") return { appearance: theme.appearance };\n return { logo: theme.logo, favicon: theme.favicon, logoMark: theme.logoMark };\n}\n\nfunction colorHex(color: ThemeColorDoc | string | null | undefined): string | undefined {\n if (typeof color === \"string\") return color;\n return color?.hex ?? undefined;\n}\n\n/**\n * A Theme page is a real Global. Hydrate from the store only when this\n * page has never been saved — otherwise afterRead would overwrite the form.\n */\nexport function hasThemeSlice(doc: ThemeDoc | null | undefined, child: ThemeChild): boolean {\n if (!doc) return false;\n if (child === \"colors\") return Boolean(colorHex(doc.colors?.brand?.primary));\n if (child === \"typography\") return Boolean(doc.typography?.body);\n if (child === \"appearance\") return Boolean(doc.appearance?.radius);\n return Boolean(doc.logo || doc.favicon || doc.logoMark);\n}\n\nexport interface ThemeStorePayload {\n findGlobal: (args: {\n slug: string;\n draft?: boolean;\n depth?: number;\n overrideAccess?: boolean;\n }) => Promise<ThemeDoc | null | undefined>;\n updateGlobal: (args: { slug: string; data: ThemeDoc; draft?: boolean }) => Promise<unknown>;\n}\n\n/**\n * Save on a Theme page writes that slice onto the hidden `theme` row.\n * Other children stay as stored.\n */\nexport async function persistThemeChild(\n payload: ThemeStorePayload,\n incoming: ThemeDoc,\n child: ThemeChild,\n): Promise<ThemeDoc> {\n const stored =\n (await payload.findGlobal({\n slug: THEME_SLUG,\n draft: false,\n overrideAccess: true,\n })) ?? {};\n const next = publishThemeChild(stored, incoming, child);\n await payload.updateGlobal({ slug: THEME_SLUG, data: next, draft: false });\n return next;\n}\n","import type { FillLabelWarning } from \"../theme/readability\";\nimport { ThemePortal } from \"./portal\";\nimport {\n hardToReadModes,\n hslCss,\n READABILITY_PUBLISH_NOTE,\n readabilityHeadline,\n} from \"../theme/readability\";\n\nexport interface PublishConfirmProps {\n childLabel: string;\n changes: string[];\n shorts?: FillLabelWarning[];\n onKeepEditing: () => void;\n onPublish: () => void;\n busy?: boolean;\n}\n\nconst OTHER_CHILDREN: Record<string, string> = {\n Colors: \"Typography, Appearance, and Identity stay as they are.\",\n Typography: \"Colors, Appearance, and Identity stay as they are.\",\n Appearance: \"Colors, Typography, and Identity stay as they are.\",\n Identity: \"Colors, Typography, and Appearance stay as they are.\",\n};\n\nexport function PublishConfirm({\n childLabel,\n changes,\n shorts,\n onKeepEditing,\n onPublish,\n busy,\n}: PublishConfirmProps) {\n const remaining = shorts?.filter((item) => !item.meets) ?? [];\n return (\n <ThemePortal>\n <div className=\"bl-publish\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"bl-publish-title\">\n <div className=\"bl-publish__panel\">\n <h2 id=\"bl-publish-title\">Publish {childLabel}</h2>\n <p>\n These {childLabel.toLowerCase()} changes go live now.{\" \"}\n {OTHER_CHILDREN[childLabel] ?? \"The other Theme sections stay as they are.\"}\n </p>\n {changes.length === 0 ? (\n <p className=\"bl-publish__empty\">No changes to publish.</p>\n ) : (\n <ul>\n {changes.map((change) => (\n <li key={change}>{change}</li>\n ))}\n </ul>\n )}\n {remaining.length > 0 ? (\n <div className=\"bl-publish__shorts\">\n <strong>Some colors may be hard to read</strong>\n <ul>\n {remaining.map((item) => (\n <li key={item.id}>\n <span\n aria-hidden=\"true\"\n className=\"bl-publish__swatch\"\n style={{ background: hslCss(item.light.fill), color: hslCss(item.light.label) }}\n >\n Aa\n </span>\n <span>\n {readabilityHeadline(item).replace(/^Text on /, \"\")} {hardToReadModes(item)}.\n </span>\n </li>\n ))}\n </ul>\n <p>{READABILITY_PUBLISH_NOTE}</p>\n </div>\n ) : null}\n <div className=\"bl-publish__actions\">\n <button type=\"button\" className=\"bl-publish__cancel\" onClick={onKeepEditing}>\n Cancel\n </button>\n <button type=\"button\" className=\"bl-publish__go\" disabled={busy || changes.length === 0} onClick={onPublish}>\n {remaining.length > 0 ? \"Publish anyway\" : \"Publish\"}\n </button>\n </div>\n </div>\n </div>\n </ThemePortal>\n );\n}\n\nexport const PUBLISH_CONFIRM_CSS = `\n.bl-publish{position:fixed;inset:0;z-index:10000;display:grid;place-items:center;padding:1rem;background:rgba(15,23,42,.45)}\n.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)}\n.bl-publish__panel h2{margin:0;color:#0f172a}\n.bl-publish__panel p{margin:.5rem 0 0;color:#475569}\n.bl-publish__empty{font-style:italic;color:#64748b}\n.bl-publish__panel > ul{margin:.75rem 0 0;padding-left:1.1rem;color:#0f172a}\n.bl-publish__shorts{margin-top:1rem;padding:.85rem .9rem;border-radius:10px;background:#fffbeb;color:#0f172a}\n.bl-publish__shorts strong{display:block}\n.bl-publish__shorts ul{margin:.65rem 0 0;padding:0;list-style:none}\n.bl-publish__shorts li{display:flex;gap:.65rem;align-items:center;margin-top:.45rem;font-size:13px;color:#0f172a}\n.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}\n.bl-publish__shorts p{margin:.65rem 0 0;font-size:13px;color:#475569}\n.bl-publish__actions{display:flex;justify-content:flex-end;gap:.6rem;margin-top:1.1rem}\n.bl-publish__actions button{min-height:2.25rem;padding:.4rem .9rem;border-radius:8px;font:inherit;cursor:pointer}\n.bl-publish__cancel{border:1px solid #cbd5e1;background:#fff;color:#0f172a}\n.bl-publish__go{border:0;background:#0f172a;color:#fff;font-weight:600}\n.bl-publish__actions button:disabled{opacity:.45;cursor:not-allowed}\n`;\n","import { useField, useForm, useFormFields } from \"@payloadcms/ui\";\nimport type { UIFieldClientComponent } from \"payload\";\nimport { useMemo, useState } from \"react\";\n\nimport { SYSTEM_COLOR_COPY } from \"../theme/appearance-labels\";\nimport { themeChildChanges } from \"../theme/changes\";\nimport { isThemeChild, type ThemeChild } from \"../theme/publish\";\nimport { fillLabelWarning, type FillLabelWarning } from \"../theme/readability\";\nimport { SYSTEM_COLOR_KEYS, type ThemeColorDoc, type ThemeDoc, type ThemeLibraryColorDoc } from \"../theme/types\";\nimport { PublishConfirm, PUBLISH_CONFIRM_CSS } from \"./publish-confirm\";\n\nconst LABELS: Record<ThemeChild, string> = {\n colors: \"Colors\",\n typography: \"Typography\",\n appearance: \"Appearance\",\n identity: \"Identity\",\n};\n\nfunction asColor(value: unknown): ThemeColorDoc | undefined {\n if (value && typeof value === \"object\") return value as ThemeColorDoc;\n if (typeof value === \"string\") return { hex: value };\n return undefined;\n}\n\nfunction formDoc(fields: Record<string, { value?: unknown } | undefined>): ThemeDoc {\n const brand = Object.fromEntries(\n SYSTEM_COLOR_KEYS.map((key) => [\n key,\n {\n hex: fields[`colors.brand.${key}.hex`]?.value as string | undefined,\n sourceStep: fields[`colors.brand.${key}.sourceStep`]?.value as ThemeColorDoc[\"sourceStep\"],\n },\n ]),\n ) as NonNullable<NonNullable<ThemeDoc[\"colors\"]>[\"brand\"]>;\n return {\n colors: {\n brand,\n library: Array.isArray(fields[\"colors.library\"]?.value)\n ? (fields[\"colors.library\"]?.value as ThemeLibraryColorDoc[])\n : [],\n greyScale: fields[\"colors.greyScale\"]?.value as NonNullable<ThemeDoc[\"colors\"]>[\"greyScale\"],\n },\n typography: {\n body: fields[\"typography.body\"]?.value as string | undefined,\n heading: fields[\"typography.heading\"]?.value as string | undefined,\n },\n appearance: {\n defaultTheme: fields[\"appearance.defaultTheme\"]?.value as NonNullable<ThemeDoc[\"appearance\"]>[\"defaultTheme\"],\n radius: fields[\"appearance.radius\"]?.value as NonNullable<ThemeDoc[\"appearance\"]>[\"radius\"],\n shadow: fields[\"appearance.shadow\"]?.value as NonNullable<ThemeDoc[\"appearance\"]>[\"shadow\"],\n motion: fields[\"appearance.motion\"]?.value as NonNullable<ThemeDoc[\"appearance\"]>[\"motion\"],\n density: fields[\"appearance.density\"]?.value as NonNullable<ThemeDoc[\"appearance\"]>[\"density\"],\n },\n logo: fields.logo?.value as ThemeDoc[\"logo\"],\n favicon: fields.favicon?.value as ThemeDoc[\"favicon\"],\n logoMark: fields.logoMark?.value as ThemeDoc[\"logoMark\"],\n };\n}\n\nfunction publishedDoc(fields: Record<string, { initialValue?: unknown; value?: unknown } | undefined>): ThemeDoc {\n return formDoc(\n Object.fromEntries(Object.entries(fields).map(([path, field]) => [path, { value: field?.initialValue }])),\n );\n}\n\nfunction shortsFrom(doc: ThemeDoc): FillLabelWarning[] {\n const brand = doc.colors?.brand ?? {};\n const custom = doc.colors?.library ?? [];\n return [\n ...SYSTEM_COLOR_KEYS.flatMap((key) => {\n const hex = asColor(brand[key])?.hex;\n const warning = typeof hex === \"string\" ? fillLabelWarning(key, SYSTEM_COLOR_COPY[key].label, hex) : null;\n return warning ? [warning] : [];\n }),\n ...custom.flatMap((row, index) => {\n const warning = row.hex ? fillLabelWarning(`library-${index}`, row.label ?? row.key ?? \"Custom\", row.hex) : null;\n return warning ? [warning] : [];\n }),\n ];\n}\n\n/**\n * Per-child Publish. Lives in the document Save slot so Payload's\n * `--doc-controls-height` row is the action row, not an empty gap.\n * Sets `publishChild` then submits; `beforeChange` writes only that slice.\n * On Colors, remaining automatic-label shorts open in this modal only.\n */\nexport function ThemePublishActions({ child }: { child: ThemeChild }) {\n const label = LABELS[child];\n const { submit } = useForm();\n const publishChild = useField<string>({ path: \"publishChild\" });\n const snapshot = useFormFields(([fields]) => {\n const record = fields as Record<string, { initialValue?: unknown; value?: unknown } | undefined>;\n return { incoming: formDoc(record), published: publishedDoc(record) };\n });\n const [open, setOpen] = useState(false);\n const [busy, setBusy] = useState(false);\n\n const changes = useMemo(\n () => themeChildChanges(child, snapshot.published, snapshot.incoming),\n [child, snapshot],\n );\n const shorts = child === \"colors\" ? shortsFrom(snapshot.incoming) : undefined;\n\n async function publish() {\n setBusy(true);\n publishChild.setValue(child);\n try {\n await submit();\n setOpen(false);\n } finally {\n setBusy(false);\n }\n }\n\n return (\n <div className=\"bl-publish-child\">\n <style href=\"bl-publish\" precedence=\"default\">\n {PUBLISH_CONFIRM_CSS}\n </style>\n <style href=\"bl-publish-child\" precedence=\"default\">\n {`.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}`}\n </style>\n <button type=\"button\" className=\"bl-publish-child__button\" onClick={() => setOpen(true)}>\n Publish {label}\n </button>\n {open ? (\n <PublishConfirm\n childLabel={label}\n changes={changes}\n shorts={shorts}\n busy={busy}\n onKeepEditing={() => setOpen(false)}\n onPublish={() => {\n void publish();\n }}\n />\n ) : null}\n </div>\n );\n}\n\n/** @deprecated Alias — Theme pages use ThemePublishActions; tabbed Save used this name. */\nexport const ThemePublishControls = ThemePublishActions;\n\nexport const PublishChild: UIFieldClientComponent = ({ field }) => {\n const child = (field.admin?.custom as { child?: string } | undefined)?.child;\n if (!isThemeChild(child)) return null;\n return <ThemePublishActions child={child} />;\n};\n","import { THEME_CHILDREN, type ThemeChild } from \"../theme/publish\";\n\nexport const THEME_TAB_LABELS = {\n colors: \"Colors\",\n typography: \"Typography\",\n appearance: \"Appearance\",\n identity: \"Identity\",\n} as const satisfies Record<ThemeChild, string>;\n\n/**\n * The selected Payload field tab on Theme. Defaults to Colors when the\n * tabs have not painted yet (SSR, first paint).\n */\nexport function readActiveThemeTab(root: ParentNode | null | undefined = typeof document === \"undefined\" ? null : document): ThemeChild {\n if (!root) return \"colors\";\n const selected =\n root.querySelector('.tabs-field__tab-button[aria-selected=\"true\"]') ??\n root.querySelector(\".tabs-field__tab-button--active\") ??\n root.querySelector('[role=\"tab\"][aria-selected=\"true\"]');\n const text = selected?.textContent?.replace(/\\s+/g, \" \").trim();\n return THEME_CHILDREN.find((id) => THEME_TAB_LABELS[id] === text) ?? \"colors\";\n}\n","import { useEffect, useState } from \"react\";\n\nimport type { ThemeChild } from \"../theme/publish\";\nimport { ThemePublishControls } from \"./publish-child\";\nimport { readActiveThemeTab } from \"./theme-tab\";\n\n/**\n * Theme used to put a Light/Dark pair here. Admin chrome now follows\n * Payload's own theme from the header sun/moon, so this slot is empty\n * and Save stays in the Save slot.\n */\nexport function ThemeDocumentControls() {\n return null;\n}\n\n/**\n * Import-map Save slot used by the older single-Global Theme. Theme pages\n * keep Payload's Save and put Light/Dark in `ThemeDocumentControls`.\n */\nexport function ThemeSaveButton() {\n const [child, setChild] = useState<ThemeChild>(\"colors\");\n\n useEffect(() => {\n const sync = () => setChild(readActiveThemeTab());\n sync();\n const tabs = document.querySelector(\".tabs-field\");\n const target = tabs ?? document.body;\n const observer = new MutationObserver(sync);\n observer.observe(target, {\n subtree: true,\n attributes: true,\n attributeFilter: [\"aria-selected\", \"class\"],\n childList: true,\n });\n target.addEventListener(\"click\", sync);\n return () => {\n observer.disconnect();\n target.removeEventListener(\"click\", sync);\n };\n }, []);\n\n return <ThemePublishControls child={child} />;\n}\n\n/** @deprecated Import map alias — ThemeDocumentControls is the Save-adjacent slot. */\nexport function HiddenSaveButton() {\n return <ThemeDocumentControls />;\n}\n","import type { UIFieldClientComponent } from \"payload\";\n\nimport type { ThemeIdentityFallback } from \"../theme/identity\";\n\n/**\n * Identity child when the site has not registered a cupboard yet.\n * Shows the fallback lockup and mark; uploads wait on `logo.collection`.\n */\nexport const IdentityFallback: UIFieldClientComponent = ({ field }) => {\n const fallback = (field.admin?.custom as { fallback?: ThemeIdentityFallback } | undefined)?.fallback;\n return (\n <section className=\"bl-identity-fallback\">\n <style href=\"bl-identity-fallback\" precedence=\"default\">\n {CSS}\n </style>\n <header>\n <h2>Site identity</h2>\n <p>Today's lockup and mark until a brand editor uploads replacements.</p>\n </header>\n <div className=\"bl-identity-fallback__grid\">\n {fallback?.lockup ? (\n <figure>\n <img src={fallback.lockup.url} alt={fallback.lockup.alt} />\n <figcaption>Lockup</figcaption>\n </figure>\n ) : null}\n {fallback?.mark ? (\n <figure>\n <img src={fallback.mark.url} alt={fallback.mark.alt} />\n <figcaption>Mark</figcaption>\n </figure>\n ) : null}\n </div>\n </section>\n );\n};\n\nconst CSS = `\n.bl-identity-fallback header h2{margin:0;font-size:1.1rem}\n.bl-identity-fallback header p{margin:.35rem 0 1rem;color:var(--theme-elevation-600,#475569)}\n.bl-identity-fallback__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(12rem,1fr));gap:1rem}\n.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)}\n.bl-identity-fallback img{display:block;max-width:100%;height:4rem;object-fit:contain}\n.bl-identity-fallback figcaption{margin-top:.5rem;font-size:.8rem;color:var(--theme-elevation-600,#475569)}\n`;\n","import { FieldDescription, FieldError, FieldLabel, useConfig, useField } from \"@payloadcms/ui\";\nimport type { TextFieldClientComponent } from \"payload\";\nimport { useEffect, useId, useState } from \"react\";\n\nimport { pageEditorLooks, pageEditorTokens, type LookOption } from \"../theme/looks\";\nimport type { LookFieldMode } from \"../theme/look-field\";\nimport type { ThemeDoc } from \"../theme/types\";\n\n/**\n * Loads the Theme global and offers page-editor looks or included steps.\n * A custom scale published on Colors appears here on the next load.\n */\nexport const LookField: TextFieldClientComponent = ({ field, path, readOnly }) => {\n const { value, setValue, showError, errorMessage } = useField<string>({ path });\n const { config } = useConfig();\n const mode = ((field.admin?.custom as { mode?: LookFieldMode } | undefined)?.mode ?? \"look\") as LookFieldMode;\n const [options, setOptions] = useState<LookOption[]>(\n mode === \"token\" ? pageEditorTokens(null) : pageEditorLooks(null),\n );\n const id = useId();\n const required = Boolean(field.required);\n\n useEffect(() => {\n const serverURL = config.serverURL ?? \"\";\n const api = config.routes?.api ?? \"/api\";\n const controller = new AbortController();\n fetch(`${serverURL}${api}/globals/theme?depth=0`, { signal: controller.signal, credentials: \"include\" })\n .then((response) => (response.ok ? response.json() : null))\n .then((doc: ThemeDoc | null) => {\n setOptions(mode === \"token\" ? pageEditorTokens(doc) : pageEditorLooks(doc));\n })\n .catch(() => {\n /* keep the system-only fallback */\n });\n return () => controller.abort();\n }, [config.routes?.api, config.serverURL, mode]);\n\n return (\n <div className=\"field-type\">\n <FieldLabel htmlFor={id} label={field.label} required={required} />\n <select\n id={id}\n disabled={readOnly}\n value={value ?? \"\"}\n onChange={(event) => setValue(event.target.value || undefined)}\n >\n <option value=\"\">{required ? \"Select…\" : \"None\"}</option>\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n <FieldDescription description={field.admin?.description} path={path} />\n <FieldError path={path} showError={showError} message={errorMessage} />\n </div>\n );\n};\n","export const FEATURES_SLUG = \"features\";\n\nexport const FEATURE_GROUPS = [\"pages\", \"media\", \"theme\", \"users\"] as const;\n\nexport type FeatureGroupId = (typeof FEATURE_GROUPS)[number];\n\nexport const FEATURE_GROUP_LABELS: Record<FeatureGroupId, string> = {\n pages: \"Pages\",\n media: \"Media\",\n theme: \"Theme\",\n users: \"Users\",\n};\n\nexport const PACKAGE_FEATURE_SLUGS = [\n \"content\",\n \"publish\",\n \"media\",\n \"theme-colors\",\n \"theme-typography\",\n \"theme-appearance\",\n \"theme-identity\",\n \"brand-assets\",\n \"users\",\n \"roles\",\n] as const;\n\nexport type PackageFeatureSlug = (typeof PACKAGE_FEATURE_SLUGS)[number];\n\nexport interface PackageFeature {\n slug: PackageFeatureSlug;\n label: string;\n group: FeatureGroupId;\n defaultReleased: boolean;\n}\n\n/**\n * Package catalogue. Features itself is not a row — that screen is\n * Developer-only in code. Empty Global falls back to these defaults.\n */\nexport const PACKAGE_FEATURES: readonly PackageFeature[] = [\n { slug: \"content\", label: \"Content\", group: \"pages\", defaultReleased: true },\n { slug: \"publish\", label: \"Publish\", group: \"pages\", defaultReleased: true },\n { slug: \"media\", label: \"Media\", group: \"media\", defaultReleased: true },\n { slug: \"theme-colors\", label: \"Colors\", group: \"theme\", defaultReleased: true },\n { slug: \"theme-typography\", label: \"Typography\", group: \"theme\", defaultReleased: true },\n { slug: \"theme-appearance\", label: \"Appearance\", group: \"theme\", defaultReleased: true },\n { slug: \"theme-identity\", label: \"Identity\", group: \"theme\", defaultReleased: true },\n { slug: \"brand-assets\", label: \"Brand assets\", group: \"theme\", defaultReleased: true },\n { slug: \"users\", label: \"Users\", group: \"users\", defaultReleased: true },\n { slug: \"roles\", label: \"Roles\", group: \"users\", defaultReleased: true },\n];\n\n/** A site-only row. Other sites never see this slug. */\nexport interface FeatureExtra {\n slug: string;\n label: string;\n group?: FeatureGroupId;\n defaultReleased?: boolean;\n}\n\nexport interface FeatureRow {\n id?: string | null;\n slug: string;\n label?: string | null;\n group?: string | null;\n released: boolean;\n}\n\nexport interface FeaturesDoc {\n features?: FeatureRow[] | null;\n}\n\nexport function isFeatureGroupId(value: unknown): value is FeatureGroupId {\n return typeof value === \"string\" && (FEATURE_GROUPS as readonly string[]).includes(value);\n}\n\nexport function isPackageFeatureSlug(value: unknown): value is PackageFeatureSlug {\n return typeof value === \"string\" && (PACKAGE_FEATURE_SLUGS as readonly string[]).includes(value);\n}\n\nexport function isFeatureSlug(value: unknown): value is string {\n return typeof value === \"string\" && /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/.test(value);\n}\n\n/** @deprecated Locks are gone; the release switch is the valve. */\nexport function isLockedFeature(_slug: string, _locked?: boolean | null): boolean {\n return false;\n}\n","import {\n FEATURE_GROUP_LABELS,\n isFeatureGroupId,\n isFeatureSlug,\n PACKAGE_FEATURES,\n type FeatureExtra,\n type FeatureGroupId,\n type FeatureRow,\n type PackageFeature,\n} from \"./types\";\n\nexport const MISSING_PACKAGE_FEATURES_MESSAGE =\n \"Features must include Content, Publish, Media, Theme screens, Brand assets, Users, and Roles.\";\n\nexport interface FeatureCatalogueEntry {\n slug: string;\n label: string;\n group: FeatureGroupId;\n defaultReleased: boolean;\n}\n\nexport function featureCatalogue(extras: readonly FeatureExtra[] = []): FeatureCatalogueEntry[] {\n return [\n ...PACKAGE_FEATURES.map((feature) => ({ ...feature })),\n ...extras.map((extra) => ({\n slug: extra.slug,\n label: extra.label,\n group: extra.group ?? \"users\",\n defaultReleased: extra.defaultReleased ?? false,\n })),\n ];\n}\n\nexport function defaultFeaturesFieldValue(extras: readonly FeatureExtra[] = []): FeatureRow[] {\n return featureCatalogue(extras).map((feature) => ({\n id: feature.slug,\n slug: feature.slug,\n label: feature.label,\n group: feature.group,\n released: feature.defaultReleased,\n }));\n}\n\nexport function stampFeatureCatalogue(\n value: unknown,\n extras: readonly FeatureExtra[] = [],\n): FeatureRow[] {\n const bySlug = new Map(featureCatalogue(extras).map((feature) => [feature.slug, feature]));\n if (!Array.isArray(value)) return defaultFeaturesFieldValue(extras);\n return value.flatMap((item) => {\n if (!item || typeof item !== \"object\") return [];\n const slug = \"slug\" in item && typeof item.slug === \"string\" ? item.slug : \"\";\n const feature = bySlug.get(slug);\n if (!feature) return [];\n return [\n {\n id: feature.slug,\n slug: feature.slug,\n label: feature.label,\n group: feature.group,\n released: Boolean(\"released\" in item && item.released),\n },\n ];\n });\n}\n\nexport function parseFeaturesMatrix(\n value: unknown,\n): { ok: true; rows: FeatureRow[] } | { ok: false; message: string } {\n if (!Array.isArray(value) || value.length === 0) {\n return { ok: false, message: MISSING_PACKAGE_FEATURES_MESSAGE };\n }\n\n const rows: FeatureRow[] = [];\n const seen = new Set<string>();\n\n for (const item of value) {\n if (!item || typeof item !== \"object\") continue;\n const slug = \"slug\" in item ? item.slug : undefined;\n if (!isFeatureSlug(slug) || seen.has(slug)) continue;\n seen.add(slug);\n const pack = PACKAGE_FEATURES.find((feature) => feature.slug === slug);\n const label =\n \"label\" in item && typeof item.label === \"string\"\n ? item.label\n : (pack?.label ?? slug);\n const group =\n \"group\" in item && isFeatureGroupId(item.group) ? item.group : (pack?.group ?? \"users\");\n rows.push({\n id: slug,\n slug,\n label,\n group,\n released: Boolean(\"released\" in item && item.released),\n });\n }\n\n if (PACKAGE_FEATURES.some((feature) => !seen.has(feature.slug))) {\n return { ok: false, message: MISSING_PACKAGE_FEATURES_MESSAGE };\n }\n return { ok: true, rows };\n}\n\nexport function validateFeaturesMatrix(\n value: unknown,\n extras: readonly FeatureExtra[] = [],\n): true | string {\n const parsed = parseFeaturesMatrix(value);\n if (!parsed.ok) return parsed.message;\n const allowed = new Set(featureCatalogue(extras).map((feature) => feature.slug));\n if (parsed.rows.some((row) => !allowed.has(row.slug))) return MISSING_PACKAGE_FEATURES_MESSAGE;\n return true;\n}\n\nexport function featureGroupLabel(group: string): string {\n return isFeatureGroupId(group) ? FEATURE_GROUP_LABELS[group] : group;\n}\n\nexport function packageFeatureLabel(slug: string, extras: readonly FeatureExtra[] = []): string {\n const pack = PACKAGE_FEATURES.find((feature) => feature.slug === slug);\n if (pack) return pack.label;\n const extra = extras.find((feature) => feature.slug === slug);\n return extra?.label ?? slug;\n}\n\nexport function isGroupOnlySlug(slug: string): boolean {\n return isFeatureGroupId(slug) && !PACKAGE_FEATURES.some((feature) => feature.slug === slug);\n}\n\nexport type { PackageFeature };\n","/**\n * The Roles Global a site's generated types will describe. Optional and\n * nullable, no index signature: a generated Global is assignable to this,\n * never the reverse.\n */\n\nexport const ROLES = [\"developer\", \"admin\", \"designer\", \"author\"] as const;\n\nexport type Role = (typeof ROLES)[number];\n\nexport const ROLE_LABELS: Record<Role, string> = {\n developer: \"Developer\",\n admin: \"Admin\",\n designer: \"Designer\",\n author: \"Author\",\n};\n\n/** Capability aliases over feature grants. Brand is any Theme-group leaf. */\nexport const CAPABILITIES = [\"content\", \"brand\", \"publish\", \"users\"] as const;\n\nexport type Capability = (typeof CAPABILITIES)[number];\n\nexport const THEME_FEATURE_SLUGS = [\n \"theme-colors\",\n \"theme-typography\",\n \"theme-appearance\",\n \"theme-identity\",\n \"brand-assets\",\n] as const;\n\nexport const CAPABILITY_FEATURES: Record<Capability, readonly string[]> = {\n content: [\"content\"],\n publish: [\"publish\"],\n users: [\"users\"],\n brand: THEME_FEATURE_SLUGS,\n};\n\nexport const DEFAULT_ROLE_GRANTS: Record<Role, readonly string[]> = {\n developer: [],\n admin: [\"content\", \"publish\", \"media\", \"users\", \"roles\"],\n designer: [\n \"content\",\n \"media\",\n ...THEME_FEATURE_SLUGS,\n \"users\",\n \"roles\",\n ],\n author: [\"content\", \"media\"],\n};\n\n/**\n * A site-defined row passed into `createRoles({ extras })`. The slug is the\n * stored key; the label is what Settings → Roles and Users show.\n */\nexport interface RoleExtra {\n role: string;\n label: string;\n grants?: readonly string[];\n}\n\nexport interface RoleRow {\n id?: string | null;\n role: string;\n label?: string | null;\n grants: string[];\n}\n\nexport interface RolesDoc {\n roles?: RoleRow[] | null;\n}\n\n/**\n * `req.user` as Payload hands it over. Structural so this module never\n * imports a site's generated `User`. `roles` is optional because a row\n * that predates the field must come back powerless.\n */\nexport type MaybeUser = {\n id?: string | number;\n roles?: readonly string[] | null;\n /** Feature slugs this login may use, stamped onto the JWT at read. */\n allowedFeatures?: readonly string[] | null;\n} | null | undefined;\n\nexport function isRole(value: unknown): value is Role {\n return typeof value === \"string\" && (ROLES as readonly string[]).includes(value);\n}\n\n/** Lowercase slug from a letters-and-spaces name: `designer`, `the-designer`. */\nexport function isRoleSlug(value: unknown): value is string {\n return typeof value === \"string\" && /^[a-z]+(-[a-z]+)*$/.test(value);\n}\n\n/** Display name: letters and single spaces only. `The Greatest Designer`. */\nexport function isRoleName(value: unknown): value is string {\n return typeof value === \"string\" && /^[A-Za-z]+(?: [A-Za-z]+)*$/.test(value.trim());\n}\n\n/** Strip digits and punctuation as the name is typed. Trailing space stays. */\nexport function sanitizeRoleNameInput(value: string): string {\n return value.replace(/[^A-Za-z ]/g, \"\").replace(/ {2,}/g, \" \");\n}\n\n/** Name → stored key. `The Greatest Designer` → `the-greatest-designer`. */\nexport function slugifyRoleName(value: unknown): string {\n if (typeof value !== \"string\") return \"\";\n return value\n .trim()\n .toLowerCase()\n .replace(/[^a-z]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\nexport function roleLabel(role: string, label?: string | null): string {\n const trimmed = typeof label === \"string\" ? label.trim() : \"\";\n if (trimmed) return trimmed;\n return isRole(role) ? ROLE_LABELS[role] : role;\n}\n\nexport function defaultGrantsForRole(role: string, extraGrants?: readonly string[]): string[] {\n if (isRole(role)) return [...DEFAULT_ROLE_GRANTS[role]];\n return extraGrants ? [...extraGrants] : [];\n}\n","import { packageFeatureLabel } from \"../features/matrix\";\nimport { isFeatureSlug } from \"../features/types\";\nimport {\n CAPABILITY_FEATURES,\n defaultGrantsForRole,\n isRole,\n isRoleName,\n isRoleSlug,\n ROLE_LABELS,\n roleLabel,\n ROLES,\n slugifyRoleName,\n THEME_FEATURE_SLUGS,\n type Capability,\n type RoleExtra,\n type RoleRow,\n} from \"./types\";\n\nexport const ROLES_SLUG = \"roles\";\n\nexport const ROLES_GLOBAL_DESCRIPTION = \"Who may do what. Drag to change rank.\";\n\nexport const ROLES_FIELD_DESCRIPTION =\n \"Drag to change rank. Ticks are features released on Features. Developer has the whole catalogue.\"\n\n/**\n * Default rank and grants. Developer is implicit (empty grants). Brand\n * screens default to Designer.\n */\nexport const DEFAULT_ROLE_MATRIX: readonly RoleRow[] = ROLES.map((role) => ({\n role,\n grants: defaultGrantsForRole(role),\n}));\n\nexport const DEVELOPER_DESCRIPTION =\n \"Everything, including features not released for assignment.\";\n\nexport const LAST_USERS_TICK_MESSAGE =\n \"Keep Users granted on at least one of Admin or Developer.\";\n\nexport const MISSING_SEED_ROLES_MESSAGE = \"Roles must include Developer.\";\n\nexport const DUPLICATE_ROLE_SLUG_MESSAGE = \"Each role needs a unique slug.\";\n\nexport const DUPLICATE_ROLE_NAME_MESSAGE = \"Each role needs a unique name.\";\n\nexport const INVALID_ROLE_NAME_MESSAGE = \"Use letters and spaces only.\";\n\nfunction uniqueSlugs(values: readonly unknown[]): string[] {\n const slugs: string[] = [];\n for (const value of values) {\n if (typeof value === \"string\" && isFeatureSlug(value) && !slugs.includes(value)) slugs.push(value);\n }\n return slugs;\n}\n\n/** Read stored grants, or rebuild them from the old capability ticks. */\nexport function grantsFromStoredRole(item: object): string[] {\n if (\"grants\" in item && Array.isArray(item.grants)) return uniqueSlugs(item.grants);\n const grants: string[] = [];\n if (\"content\" in item && item.content) {\n grants.push(\"content\", \"media\");\n }\n if (\"publish\" in item && item.publish) grants.push(\"publish\");\n if (\"users\" in item && item.users) grants.push(\"users\", \"roles\");\n if (\"brand\" in item && item.brand) grants.push(...THEME_FEATURE_SLUGS);\n return uniqueSlugs(grants);\n}\n\nexport function seedRoleRows(extras: readonly RoleExtra[] = []): RoleRow[] {\n return [\n ...DEFAULT_ROLE_MATRIX.map((row) => ({\n ...row,\n grants: [...row.grants],\n label: isRole(row.role) ? ROLE_LABELS[row.role] : row.role,\n })),\n ...extras.map((extra) => ({\n role: extra.role,\n label: extra.label,\n grants: extra.grants ? [...extra.grants] : [],\n })),\n ];\n}\n\nexport function defaultRolesFieldValue(extras: readonly RoleExtra[] = []): RoleRow[] {\n return seedRoleRows(extras).map((row) => ({ id: row.role, ...row }));\n}\n\nfunction readRoleRow(item: object): RoleRow | { error: string } {\n const role = \"role\" in item ? item.role : undefined;\n if (typeof role !== \"string\" || role.trim() === \"\") return { error: DUPLICATE_ROLE_SLUG_MESSAGE };\n if (!isRoleSlug(role)) return { error: DUPLICATE_ROLE_SLUG_MESSAGE };\n const label = \"label\" in item && typeof item.label === \"string\" ? item.label : undefined;\n return {\n id: role,\n role,\n label: roleLabel(role, label),\n grants: grantsFromStoredRole(item),\n };\n}\n\nexport function parseRolesMatrix(\n value: unknown,\n): { ok: true; rows: RoleRow[] } | { ok: false; message: string } {\n if (!Array.isArray(value)) {\n return { ok: false, message: MISSING_SEED_ROLES_MESSAGE };\n }\n\n const rows: RoleRow[] = [];\n const seen = new Set<string>();\n for (const item of value) {\n if (!item || typeof item !== \"object\") continue;\n // An Add Role row starts with no slug. Skip it so form-state can\n // build the fields; the slug field still refuses an empty save.\n const role = \"role\" in item ? item.role : undefined;\n if (typeof role !== \"string\" || role.trim() === \"\") continue;\n const parsed = readRoleRow(item);\n if (\"error\" in parsed) return { ok: false, message: parsed.error };\n if (seen.has(parsed.role)) return { ok: false, message: DUPLICATE_ROLE_SLUG_MESSAGE };\n seen.add(parsed.role);\n rows.push(parsed);\n }\n\n if (!seen.has(\"developer\")) {\n return { ok: false, message: MISSING_SEED_ROLES_MESSAGE };\n }\n return { ok: true, rows };\n}\n\nexport function roleHasGrant(row: RoleRow, slug: string): boolean {\n if (row.role === \"developer\") return true;\n return row.grants.includes(slug);\n}\n\nexport function roleHasCapability(row: RoleRow, capability: Capability): boolean {\n if (row.role === \"developer\") return true;\n return CAPABILITY_FEATURES[capability].some((slug) => row.grants.includes(slug));\n}\n\n/**\n * Mint a slug from the name only when the row has none yet. An existing\n * key — seed or custom — stays put so a rename cannot orphan users.\n */\nexport function applyRoleSlugsFromNames(value: unknown): unknown {\n if (!Array.isArray(value)) return value;\n return value.map((item) => {\n if (!item || typeof item !== \"object\") return item;\n const row = item as RoleRow;\n if (isRoleSlug(row.role)) return item;\n const slug = slugifyRoleName(row.label);\n return isRoleSlug(slug) ? { ...row, role: slug } : item;\n });\n}\n\nfunction hasDuplicateRoleNames(value: unknown): boolean {\n if (!Array.isArray(value)) return false;\n const seen = new Set<string>();\n for (const item of value) {\n if (!item || typeof item !== \"object\") continue;\n const role = \"role\" in item && typeof item.role === \"string\" ? item.role : \"\";\n const raw = \"label\" in item && typeof item.label === \"string\" ? item.label : \"\";\n const name = raw.trim() || (isRole(role) ? ROLE_LABELS[role] : \"\");\n if (!name) continue;\n const key = name.toLowerCase();\n if (seen.has(key)) return true;\n seen.add(key);\n }\n return false;\n}\n\nfunction hasInvalidRoleName(value: unknown): boolean {\n if (!Array.isArray(value)) return false;\n for (const item of value) {\n if (!item || typeof item !== \"object\") continue;\n const label = \"label\" in item && typeof item.label === \"string\" ? item.label.trim() : \"\";\n if (!label) continue;\n if (!isRoleName(label)) return true;\n }\n return false;\n}\n\nexport function validateRolesMatrix(value: unknown): true | string {\n if (hasDuplicateRoleNames(value)) return DUPLICATE_ROLE_NAME_MESSAGE;\n if (hasInvalidRoleName(value)) return INVALID_ROLE_NAME_MESSAGE;\n const parsed = parseRolesMatrix(applyRoleSlugsFromNames(value));\n if (!parsed.ok) return parsed.message;\n return true;\n}\n\n/**\n * Developer is exclusive. Admin does not swallow Designer: both store.\n * Unknown slugs (dropped catalogue keys such as `approver`) fall away unless\n * they appear on the matrix.\n */\nexport function normalizeStoredRoles(\n value: unknown,\n matrix: readonly RoleRow[] = DEFAULT_ROLE_MATRIX,\n): string[] {\n if (!Array.isArray(value)) return [];\n const allowed = new Set(matrix.map((row) => row.role));\n const roles = [...new Set(value.filter((entry): entry is string => typeof entry === \"string\" && allowed.has(entry)))];\n if (roles.includes(\"developer\")) return [\"developer\"];\n return roles;\n}\n\nexport function roleSelectOptions(matrix: readonly RoleRow[] = DEFAULT_ROLE_MATRIX) {\n return matrix.map((row) => ({ label: roleLabel(row.role, row.label), value: row.role }));\n}\n\n/** Grant copy only. Developer names the unreleased catalogue; nothing about MCP or seed. */\nexport function roleDescription(role: string, matrix: readonly RoleRow[] = DEFAULT_ROLE_MATRIX): string {\n if (role === \"developer\") return DEVELOPER_DESCRIPTION;\n const row = matrix.find((entry) => entry.role === role);\n if (!row) return \"No capabilities\";\n const ticks = row.grants.map((slug) => packageFeatureLabel(slug));\n return ticks.join(\", \") || \"No capabilities\";\n}\n\n/**\n * Seed grants and package labels come back; extra rows stay as they are.\n */\nexport function resetRolesMatrix(current: unknown): RoleRow[] {\n const extras: RoleRow[] = [];\n if (Array.isArray(current)) {\n for (const item of current) {\n if (!item || typeof item !== \"object\") continue;\n const parsed = readRoleRow(item);\n if (\"error\" in parsed || isRole(parsed.role)) continue;\n extras.push(parsed);\n }\n }\n return [...defaultRolesFieldValue(), ...extras];\n}\n","import { ArrayField, useAuth, useField } from \"@payloadcms/ui\";\nimport type { ArrayFieldClientComponent } from \"payload\";\nimport { useCallback, useRef } from \"react\";\n\nimport { resetRolesMatrix } from \"../roles/matrix\";\n\nconst HIDE_ROW_CHROME = `.bl-roles-matrix .array-actions__add,.bl-roles-matrix .array-actions__duplicate,.bl-roles-matrix .array-actions__copy{display:none}.bl-roles-matrix .array-field__add-row{display:none}.bl-roles-matrix--hide-developer .array-field__row:has([data-role-seed=\"developer\"]),.bl-roles-matrix--hide-developer .collapsible:has([data-role-seed=\"developer\"]){display:none}.bl-roles-matrix__toolbar{display:flex;justify-content:flex-end;gap:.5rem;margin-block-end:.75rem}.bl-roles-matrix__reset{min-height:2.25rem;padding:.35rem .9rem;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:8px;background:transparent;color:inherit;font:inherit;cursor:pointer}body.bl-roles-matrix-seed-menu .array-actions__remove{display:none}`;\n\nfunction seedRoleFromTrigger(trigger: Element): boolean {\n let node: HTMLElement | null = trigger.parentElement;\n while (node) {\n const slugs = node.querySelectorAll(\"[data-role-slug]\");\n if (slugs.length === 1) {\n const seed = slugs[0]?.getAttribute(\"data-role-seed\") || slugs[0]?.getAttribute(\"data-role-slug\");\n return seed === \"developer\";\n }\n if (slugs.length > 1) return false;\n node = node.parentElement;\n }\n return false;\n}\n\nfunction viewerIsDeveloper(user: unknown): boolean {\n if (!user || typeof user !== \"object\" || !(\"roles\" in user)) return false;\n const roles = (user as { roles?: unknown }).roles;\n return Array.isArray(roles) && roles.includes(\"developer\");\n}\n\n/**\n * Payload's array field: drag rank stays, add is for custom rows.\n * Developer has no remove, stays in the saved array, and is shown only\n * to a Developer. Reset restores the package four and leaves extras.\n */\nexport const RolesMatrixField: ArrayFieldClientComponent = (props) => {\n const { setValue, value } = useField({ path: props.path });\n const { user } = useAuth();\n const hideDeveloper = !viewerIsDeveloper(user);\n const rootRef = useRef<HTMLDivElement>(null);\n const seedMenu = useRef(false);\n\n const onClickCapture = useCallback((event: React.MouseEvent<HTMLDivElement>) => {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const trigger = target.closest(\".array-actions__button\");\n if (trigger) {\n const owner = trigger.closest(\".array-field\");\n const ours = owner !== null && owner === rootRef.current?.querySelector(\".array-field\");\n seedMenu.current = ours && seedRoleFromTrigger(trigger);\n document.body.classList.toggle(\"bl-roles-matrix-seed-menu\", seedMenu.current);\n return;\n }\n\n if (!target.closest(\".array-actions__remove\")) return;\n if (!seedMenu.current) return;\n event.preventDefault();\n event.stopPropagation();\n }, []);\n\n return (\n <div\n className={[\"bl-roles-matrix\", hideDeveloper && \"bl-roles-matrix--hide-developer\"]\n .filter(Boolean)\n .join(\" \")}\n ref={rootRef}\n onClickCapture={onClickCapture}\n >\n <style href=\"bl-roles-matrix\" precedence=\"default\">\n {HIDE_ROW_CHROME}\n </style>\n <div className=\"bl-roles-matrix__toolbar\">\n <button type=\"button\" className=\"bl-roles-matrix__reset\" onClick={() => setValue(resetRolesMatrix(value))}>\n Reset to defaults\n </button>\n </div>\n <ArrayField {...props} />\n </div>\n );\n};\n","import { useRowLabel } from \"@payloadcms/ui\";\n\nimport { isRole, roleLabel } from \"../roles/types\";\n\n/**\n * Array row header. Shows the current display name, not “Role 01”.\n */\nexport function RolesRowLabel() {\n const { data } = useRowLabel<{ label?: string | null; role?: string | null; seed?: string | null }>();\n const role = typeof data.role === \"string\" ? data.role : \"\";\n const seed = typeof data.seed === \"string\" && data.seed ? data.seed : isRole(role) ? role : \"\";\n const label = roleLabel(role, data.label) || \"Role\";\n return (\n <span data-role-slug={role} data-role-seed={seed}>\n {label}\n </span>\n );\n}\n","import { FieldDescription, FieldError, FieldLabel, fieldBaseClass, useField } from \"@payloadcms/ui\";\nimport type { TextFieldClientComponent } from \"payload\";\n\nimport { isRole } from \"../roles/types\";\n\n/**\n * Seed slugs stay read-only. A custom row's slug is typed here.\n */\nexport const RoleSlugField: TextFieldClientComponent = ({ field, path, readOnly }) => {\n const { value, setValue, showError, errorMessage } = useField<string>({ path });\n const locked = Boolean(readOnly) || isRole(value);\n const required = Boolean(field.required);\n const id = `field-${path.replace(/\\./g, \"__\")}`;\n\n return (\n <div className={[fieldBaseClass, \"text\", locked && \"read-only\"].filter(Boolean).join(\" \")}>\n <FieldLabel htmlFor={id} label={field.label} required={required} />\n <div className={`${fieldBaseClass}__wrap`}>\n <FieldError message={errorMessage} path={path} showError={showError} />\n <input\n id={id}\n data-role-slug={value ?? \"\"}\n type=\"text\"\n autoComplete=\"off\"\n spellCheck={false}\n readOnly={locked}\n disabled={locked}\n value={value ?? \"\"}\n onChange={(event) => {\n if (!locked) setValue(event.target.value);\n }}\n />\n </div>\n <FieldDescription description={field.admin?.description} path={path} />\n </div>\n );\n};\n","import type {\n CheckboxField,\n CollectionBeforeChangeHook,\n CollectionSlug,\n Field,\n FieldAccess,\n PayloadRequest,\n TextField,\n TextFieldSingleValidation,\n Where,\n} from \"payload\";\nimport { ValidationError, validations } from \"payload\";\n\nexport const SLUG_FIELD = \"@bison-lab/payload-core/admin#SlugField\";\n\nexport const SLUG_UNLOCK_WARNING =\n \"This page is live. Changing the address will send visitors from the old URL to the new one.\";\n\nexport interface SlugFieldOptions {\n /** The collection the field sits on — what the duplicate check searches. */\n collection: CollectionSlug;\n /**\n * True when a slug belongs to something the CMS does not own: a path the app\n * already serves from code, or one reserved for the framework. Which paths\n * those are is knowable only to the site, so it arrives as an option.\n */\n isReserved: (slug: string) => boolean;\n}\n\ninterface SlugCheckArgs extends SlugFieldOptions {\n id: number | string | undefined;\n req: PayloadRequest | undefined;\n}\n\nfunction slugifySegment(segment: string): string {\n return segment\n .normalize(\"NFKD\")\n .replace(/\\p{M}/gu, \"\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n}\n\n/**\n * A stored slug from whatever was typed: NFKD, hyphenated, slash segments\n * kept, so `Café / About Us` becomes `cafe/about-us`.\n */\nexport function normalizeSlug(value: string): string {\n return value.split(\"/\").map(slugifySegment).filter(Boolean).join(\"/\");\n}\n\nfunction isLockedDoc(doc: { slugLocked?: unknown; publishedSlug?: unknown } | undefined): boolean {\n return Boolean(doc?.slugLocked || doc?.publishedSlug);\n}\n\nfunction isUnlocking(data: { slugUnlock?: unknown } | undefined): boolean {\n return Boolean(data?.slugUnlock);\n}\n\nasync function slugProblem(\n slug: string,\n { collection, id, isReserved, req }: SlugCheckArgs,\n): Promise<string | undefined> {\n if (!slug) return undefined;\n\n if (isReserved(slug)) {\n return `\"/${slug}\" is a built-in page on this site, so a page here cannot use it. Please choose a different address.`;\n }\n\n if (typeof req?.payload?.find !== \"function\") return undefined;\n\n const where: Where = { slug: { equals: slug } };\n if (id !== undefined) {\n where.id = { not_equals: id };\n }\n\n const query = {\n collection,\n depth: 0,\n limit: 1,\n overrideAccess: true,\n pagination: false,\n req,\n where,\n };\n\n const live = await req.payload.find(query);\n const taken =\n live.docs.length > 0 || (await req.payload.find({ ...query, draft: true })).docs.length > 0;\n\n return taken ? `Another page is already using \"/${slug}\". Please choose a different address.` : undefined;\n}\n\nconst slugUpdateAccess =\n (collection: CollectionSlug): FieldAccess =>\n async ({ doc, id, req, siblingData }) => {\n if (isUnlocking(siblingData)) return true;\n if (isLockedDoc(doc)) return false;\n if (id === undefined || typeof req?.payload?.findByID !== \"function\") return true;\n try {\n const published = await req.payload.findByID({\n collection,\n id,\n depth: 0,\n draft: false,\n overrideAccess: true,\n req,\n });\n return published?._status !== \"published\";\n } catch {\n return true;\n }\n };\n\n/**\n * Locks the slug on first publish and remembers the live path so a later\n * change can write a redirect. Unlock is a one-save flag and is cleared here.\n */\nexport const lockSlugOnPublish: CollectionBeforeChangeHook = ({ data }) => {\n if (!data) return data;\n data.slugUnlock = false;\n if (data._status === \"published\") {\n data.slugLocked = true;\n if (typeof data.slug === \"string\") data.publishedSlug = data.slug;\n }\n return data;\n};\n\nfunction hiddenCheckbox(name: string, label: string): CheckboxField {\n return {\n name,\n type: \"checkbox\",\n label,\n defaultValue: false,\n admin: { hidden: true },\n };\n}\n\n/**\n * The path a document is published at, normalised on the way in. Unique\n * across the collection. Follows `title` until first publish, then locks.\n * `validate` is the message under the field; `beforeChange` is the enforcement\n * on a draft save, where Payload skips field validation.\n */\nexport function slugField({ collection, isReserved }: SlugFieldOptions): Field[] {\n const validate: TextFieldSingleValidation = async (value, options) => {\n try {\n const builtIn = await validations.text(value, options);\n if (builtIn !== true) return builtIn;\n } catch {\n // form-state without a request still runs the reserved / duplicate checks\n }\n\n const problem = await slugProblem(typeof value === \"string\" ? value : \"\", {\n collection,\n id: options.id,\n isReserved,\n req: options.req,\n });\n return problem ?? true;\n };\n\n const slug: TextField = {\n name: \"slug\",\n type: \"text\",\n required: true,\n unique: true,\n access: { update: slugUpdateAccess(collection) },\n admin: {\n description: 'Path under the site root, no leading slash: \"about-us\" or \"patients/stories\".',\n components: { Field: SLUG_FIELD },\n },\n hooks: {\n beforeValidate: [\n ({ data, originalDoc, siblingData, value }) => {\n const title = typeof data?.title === \"string\" ? data.title : \"\";\n if (!isLockedDoc(originalDoc) && !isUnlocking(data) && !isUnlocking(siblingData) && title) {\n return normalizeSlug(title);\n }\n return typeof value === \"string\" ? normalizeSlug(value) : value;\n },\n ],\n beforeChange: [\n async ({ data, originalDoc, req, value }) => {\n if (typeof value !== \"string\") return value;\n\n const problem = await slugProblem(value, {\n collection,\n id: originalDoc?.id ?? data?.id,\n isReserved,\n req,\n });\n if (problem) {\n throw new ValidationError(\n { collection, errors: [{ message: problem, path: \"slug\" }], req },\n req?.t,\n );\n }\n return value;\n },\n ],\n },\n validate,\n };\n\n return [\n slug,\n hiddenCheckbox(\"slugLocked\", \"Slug locked\"),\n hiddenCheckbox(\"slugUnlock\", \"Unlock slug\"),\n {\n name: \"publishedSlug\",\n type: \"text\",\n label: \"Published slug\",\n admin: { hidden: true },\n },\n ];\n}\n","import { Button } from \"@bison-lab/admin-ui\";\nimport { FieldDescription, FieldError, FieldLabel, fieldBaseClass, useField, useFormFields } from \"@payloadcms/ui\";\nimport type { TextFieldClientComponent } from \"payload\";\nimport { useEffect } from \"react\";\n\nimport { normalizeSlug, SLUG_UNLOCK_WARNING } from \"../fields/slug\";\n\n/**\n * Slug follows the title until first publish. After that it is read-only\n * until Unlock, which warns that the old address will redirect.\n */\nexport const SlugField: TextFieldClientComponent = ({ field, path, readOnly }) => {\n const { value, setValue, showError, errorMessage } = useField<string>({ path });\n const { value: unlock, setValue: setUnlock } = useField<boolean>({ path: \"slugUnlock\" });\n const title = useFormFields(([fields]) => fields.title?.value);\n const slugLocked = Boolean(useFormFields(([fields]) => fields.slugLocked?.value));\n const locked = Boolean(readOnly) || (slugLocked && !unlock);\n const required = Boolean(field.required);\n const id = `field-${path.replace(/\\./g, \"__\")}`;\n\n useEffect(() => {\n if (slugLocked || typeof title !== \"string\") return;\n const next = normalizeSlug(title);\n if (next !== (value ?? \"\")) setValue(next);\n }, [setValue, slugLocked, title, value]);\n\n return (\n <div className={[fieldBaseClass, \"text\", locked && \"read-only\"].filter(Boolean).join(\" \")}>\n <FieldLabel htmlFor={id} label={field.label} required={required} />\n <div className={`${fieldBaseClass}__wrap`}>\n <FieldError message={errorMessage} path={path} showError={showError} />\n <input\n id={id}\n type=\"text\"\n autoComplete=\"off\"\n spellCheck={false}\n readOnly={locked}\n disabled={locked}\n value={value ?? \"\"}\n onChange={(event) => {\n if (!locked) setValue(event.target.value);\n }}\n />\n {slugLocked && !unlock ? (\n <Button variant=\"outline\" onClick={() => setUnlock(true)}>\n Unlock\n </Button>\n ) : null}\n </div>\n {unlock ? <p>{SLUG_UNLOCK_WARNING}</p> : null}\n <FieldDescription description={field.admin?.description} path={path} />\n </div>\n );\n};\n","import { FieldDescription, FieldError, FieldLabel, fieldBaseClass, useField } from \"@payloadcms/ui\";\nimport type { TextFieldClientComponent } from \"payload\";\n\nimport { sanitizeRoleNameInput } from \"../roles/types\";\n\n/**\n * Role name. Letters and spaces only, so the hidden slug stays\n * `the-greatest-designer` from `The Greatest Designer`.\n */\nexport const RoleNameField: TextFieldClientComponent = ({ field, path, readOnly }) => {\n const { value, setValue, showError, errorMessage } = useField<string>({ path });\n const required = Boolean(field.required);\n const id = `field-${path.replace(/\\./g, \"__\")}`;\n\n return (\n <div className={[fieldBaseClass, \"text\", readOnly && \"read-only\"].filter(Boolean).join(\" \")}>\n <FieldLabel htmlFor={id} label={field.label} required={required} />\n <div className={`${fieldBaseClass}__wrap`}>\n <FieldError message={errorMessage} path={path} showError={showError} />\n <input\n id={id}\n type=\"text\"\n autoComplete=\"off\"\n spellCheck={false}\n readOnly={Boolean(readOnly)}\n disabled={Boolean(readOnly)}\n value={value ?? \"\"}\n onChange={(event) => {\n if (!readOnly) setValue(sanitizeRoleNameInput(event.target.value));\n }}\n />\n </div>\n <FieldDescription description={field.admin?.description} path={path} />\n </div>\n );\n};\n","import type { OptionObject, SelectFieldClientComponent, Validate } from \"payload\";\nimport {\n CheckboxInput,\n FieldDescription,\n FieldError,\n FieldLabel,\n fieldBaseClass,\n useConfig,\n useField,\n} from \"@payloadcms/ui\";\nimport { useCallback, useEffect, useState } from \"react\";\n\nimport { parseRolesMatrix, roleDescription, roleSelectOptions, ROLES_SLUG } from \"../roles/matrix\";\nimport { roleLabel } from \"../roles/types\";\n\nconst GRID_CSS = `.bl-roles__grid{display:grid;gap:.75rem;grid-template-columns:repeat(auto-fit,minmax(12rem,1fr));margin-block:.35rem 0}.bl-roles__option{display:flex;flex-direction:column;gap:.25rem;padding:.65rem .75rem;border:1px solid var(--theme-elevation-150,#e2e8f0);border-radius:8px}.bl-roles__option.is-checked{border-color:var(--theme-elevation-400,#94a3b8)}.bl-roles__option.is-included{opacity:.7}.bl-roles__what{font-size:.8rem;line-height:1.35;color:var(--theme-elevation-500,#64748b)}`;\n\nfunction optionValue(option: string | OptionObject): string {\n return typeof option === \"string\" ? option : String(option.value);\n}\n\nfunction optionLabel(option: string | OptionObject): string {\n return typeof option === \"string\" ? option : String(option.label);\n}\n\nfunction useOfferedRoles(fallback: { value: string; label: string }[]) {\n const { config } = useConfig();\n const [live, setLive] = useState<typeof fallback | null>(null);\n const api = config?.routes?.api;\n const serverURL = config?.serverURL ?? \"\";\n\n useEffect(() => {\n if (!api) return;\n let cancelled = false;\n fetch(`${serverURL}${api}/globals/${ROLES_SLUG}?depth=0`, { credentials: \"include\" })\n .then((response) => (response.ok ? response.json() : null))\n .then((doc: { roles?: unknown } | null) => {\n if (cancelled || !doc) return;\n const parsed = parseRolesMatrix(doc.roles);\n if (parsed.ok) setLive(roleSelectOptions(parsed.rows));\n })\n .catch(() => undefined);\n return () => {\n cancelled = true;\n };\n }, [api, serverURL]);\n\n return live ?? fallback;\n}\n\n/**\n * Users Roles checklist. Order and labels come from the field options (the\n * Roles Global, or the seed plus extras). Copy is `roleDescription`.\n * Developer is exclusive; a custom role does not clear Designer.\n */\nexport const RolesField: SelectFieldClientComponent = ({\n field,\n path: pathFromProps,\n readOnly,\n validate,\n}) => {\n const { admin: { description } = {}, label, localized, options = [], required } = field;\n const fallback = (options.length ? options : roleSelectOptions()).map((option) => ({\n value: optionValue(option),\n label: optionLabel(option),\n }));\n const offered = useOfferedRoles(fallback);\n\n const memoizedValidate = useCallback<Validate>(\n (value, validationOptions) => {\n if (typeof validate === \"function\") {\n return validate(value, {\n ...validationOptions,\n hasMany: true,\n options,\n required,\n } as Parameters<typeof validate>[1]);\n }\n return true;\n },\n [validate, options, required],\n );\n\n const { disabled, errorMessage, path, setValue, showError, value } = useField<string[]>({\n potentiallyStalePath: pathFromProps,\n validate: memoizedValidate,\n });\n\n const selected: string[] = Array.isArray(value) ? value : [];\n const exclusive = selected.includes(\"developer\") ? \"developer\" : null;\n const locked = Boolean(readOnly) || disabled;\n\n function toggle(role: string): void {\n if (locked) return;\n if (role === \"developer\") {\n setValue(selected.includes(role) ? [] : [\"developer\"]);\n return;\n }\n if (exclusive) return;\n setValue(selected.includes(role) ? selected.filter((entry) => entry !== role) : [...selected, role]);\n }\n\n const groupLabel = typeof label === \"string\" ? label : \"Roles\";\n\n return (\n <div\n className={[fieldBaseClass, \"select\", \"bl-roles\", showError && \"error\", locked && \"read-only\"]\n .filter(Boolean)\n .join(\" \")}\n id={`field-${path.replace(/\\./g, \"__\")}`}\n >\n <style href=\"bl-roles\" precedence=\"default\">\n {GRID_CSS}\n </style>\n <FieldLabel as=\"span\" label={label} localized={localized} path={path} required={required} />\n <div className={`${fieldBaseClass}__wrap`}>\n <FieldError message={errorMessage} path={path} showError={showError} />\n <div aria-label={groupLabel} className=\"bl-roles__grid\" role=\"group\">\n {offered.map((option) => {\n const role = option.value;\n if (!role) return null;\n const included = exclusive !== null && role !== exclusive;\n const checked = selected.includes(role);\n return (\n <div\n className={[\"bl-roles__option\", checked && \"is-checked\", included && \"is-included\"]\n .filter(Boolean)\n .join(\" \")}\n key={role}\n >\n <CheckboxInput\n checked={checked}\n id={`${path}-${role}`}\n label={option.label || roleLabel(role)}\n onToggle={() => toggle(role)}\n readOnly={locked || included}\n />\n <span className=\"bl-roles__what\">\n {included ? \"Included in Developer\" : roleDescription(role)}\n </span>\n </div>\n );\n })}\n </div>\n </div>\n <FieldDescription description={description} path={path} />\n </div>\n );\n};\n","import { useConfig, useField } from \"@payloadcms/ui\";\nimport type { JSONFieldClientComponent } from \"payload\";\nimport { useEffect, useState } from \"react\";\n\nimport { defaultFeaturesFieldValue, featureGroupLabel, parseFeaturesMatrix } from \"../features/matrix\";\nimport { FEATURE_GROUPS, FEATURES_SLUG, type FeatureRow } from \"../features/types\";\n\nconst LIST_CSS = `.bl-role-grants{margin-block:.2rem 0;font-size:16px}.bl-role-grants__group{margin-block:.75rem 0}.bl-role-grants__group-title{font-size:13px;letter-spacing:.02em;color:var(--theme-elevation-400,#94a3b8);font-weight:650;margin-block-end:.25rem}.bl-role-grants__row{display:flex;align-items:center;gap:.65rem;padding:.35rem 0}.bl-role-grants__row.is-implicit{opacity:.85}.bl-role-grants input{inline-size:1.15rem;block-size:1.15rem}.bl-role-grants input:disabled{cursor:default}.bl-role-grants__note{margin-block:.35rem 0;font-size:13px;color:var(--theme-elevation-500,#64748b)}`;\n\nfunction asGrants(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.filter((entry): entry is string => typeof entry === \"string\");\n}\n\nfunction rolePathFromGrants(path: string): string {\n return path.replace(/\\.grants$/, \".role\");\n}\n\n/**\n * Released catalogue rows as ticks. Unreleased features do not appear,\n * except on Developer: every catalogue row is shown granted and locked\n * so a new Feature is visibly included.\n */\nexport const RolesGrantsField: JSONFieldClientComponent = (props) => {\n const { setValue, value } = useField({ path: props.path });\n const { value: role } = useField({ path: rolePathFromGrants(props.path) });\n const { config } = useConfig();\n const [catalogue, setCatalogue] = useState<FeatureRow[]>(defaultFeaturesFieldValue());\n const api = config?.routes?.api;\n const serverURL = config?.serverURL ?? \"\";\n const implicitAll = role === \"developer\";\n\n useEffect(() => {\n if (!api) return;\n let cancelled = false;\n fetch(`${serverURL}${api}/globals/${FEATURES_SLUG}?depth=0`, { credentials: \"include\" })\n .then((response) => (response.ok ? response.json() : null))\n .then((doc: { features?: unknown } | null) => {\n if (cancelled || !doc) return;\n const parsed = parseFeaturesMatrix(doc.features);\n if (parsed.ok) setCatalogue(parsed.rows);\n })\n .catch(() => undefined);\n return () => {\n cancelled = true;\n };\n }, [api, serverURL]);\n\n const grants = asGrants(value);\n const shown = implicitAll ? catalogue : catalogue.filter((row) => row.released);\n\n function toggle(slug: string, checked: boolean) {\n if (implicitAll) return;\n const next = new Set(grants);\n if (checked) next.add(slug);\n else next.delete(slug);\n setValue([...next]);\n }\n\n return (\n <div className=\"bl-role-grants\">\n <style href=\"bl-role-grants\" precedence=\"default\">\n {LIST_CSS}\n </style>\n {implicitAll ? (\n <p className=\"bl-role-grants__note\">Always granted, including features not yet released.</p>\n ) : null}\n {FEATURE_GROUPS.map((group) => {\n const members = shown.filter((row) => (row.group ?? \"users\") === group);\n if (members.length === 0) return null;\n return (\n <div key={group} className=\"bl-role-grants__group\">\n <div className=\"bl-role-grants__group-title\">{featureGroupLabel(group)}</div>\n {members.map((row) => (\n <label\n key={row.slug}\n className={[\"bl-role-grants__row\", implicitAll && \"is-implicit\"].filter(Boolean).join(\" \")}\n >\n <input\n type=\"checkbox\"\n aria-label={`${row.label || row.slug}`}\n checked={implicitAll || grants.includes(row.slug)}\n disabled={implicitAll}\n onChange={(event) => toggle(row.slug, event.target.checked)}\n />\n <span>{row.label || row.slug}</span>\n </label>\n ))}\n </div>\n );\n })}\n </div>\n );\n};\n","import { useConfig, useField } from \"@payloadcms/ui\";\nimport type { ArrayFieldClientComponent } from \"payload\";\nimport { useEffect } from \"react\";\n\nimport { featureGroupLabel } from \"../features/matrix\";\nimport { FEATURE_GROUPS, FEATURES_SLUG, type FeatureRow } from \"../features/types\";\n\nconst LIST_CSS = `.bl-features{margin-block:.35rem 0;font-size:16px}.bl-features__group{margin-block:1rem 0}.bl-features__group-title{font-size:14px;letter-spacing:.02em;color:var(--theme-elevation-400,#94a3b8);font-weight:650;margin-block-end:.35rem}.bl-features__row{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:.55rem 0;border-bottom:1px solid var(--theme-elevation-150,#e2e8f0)}.bl-features__row:last-child{border-bottom:0}.bl-features input{inline-size:1.15rem;block-size:1.15rem}`;\n\nfunction asRows(value: unknown): FeatureRow[] {\n return Array.isArray(value) ? (value as FeatureRow[]) : [];\n}\n\nfunction FeatureReleaseRow({\n path,\n index,\n row,\n rows,\n setRows,\n}: {\n path: string;\n index: number;\n row: FeatureRow;\n rows: FeatureRow[];\n setRows: (next: FeatureRow[]) => void;\n}) {\n const { setValue: setReleased } = useField({ path: `${path}.${index}.released` });\n\n return (\n <div className=\"bl-features__row\">\n <span>{row.label || row.slug}</span>\n <input\n type=\"checkbox\"\n aria-label={`Release ${row.label || row.slug}`}\n checked={Boolean(row.released)}\n onChange={(event) => {\n const released = event.target.checked;\n setReleased(released);\n setRows(rows.map((entry) => (entry.slug === row.slug ? { ...entry, released } : entry)));\n }}\n />\n </div>\n );\n}\n\n/**\n * One release switch per catalogue row, grouped. Off hides the tick on\n * Roles; Developer still has the feature.\n *\n * Writes both the array value and each row's `released` checkbox path.\n * Payload still registers those child fields; toggling only the parent\n * array leaves them false and Save stores the old flags.\n */\nexport const FeaturesMatrixField: ArrayFieldClientComponent = (props) => {\n const { setValue, value } = useField({ path: props.path });\n const { config } = useConfig();\n const api = config?.routes?.api;\n const serverURL = config?.serverURL ?? \"\";\n\n useEffect(() => {\n if (!api || asRows(value).length > 0) return;\n let cancelled = false;\n fetch(`${serverURL}${api}/globals/${FEATURES_SLUG}?depth=0`, { credentials: \"include\" })\n .then((response) => (response.ok ? response.json() : null))\n .then((doc: { features?: unknown } | null) => {\n if (cancelled || !doc) return;\n const incoming = asRows(doc.features);\n if (incoming.length > 0) setValue(incoming, true);\n })\n .catch(() => undefined);\n return () => {\n cancelled = true;\n };\n }, [api, serverURL, setValue, value]);\n\n const rows = asRows(value);\n\n return (\n <div className=\"bl-features\">\n <style href=\"bl-features\" precedence=\"default\">\n {LIST_CSS}\n </style>\n {FEATURE_GROUPS.map((group) => {\n const members = rows\n .map((row, index) => ({ row, index }))\n .filter(({ row }) => (row.group ?? \"users\") === group);\n if (members.length === 0) return null;\n return (\n <div key={group} className=\"bl-features__group\">\n <div className=\"bl-features__group-title\">{featureGroupLabel(group)}</div>\n {members.map(({ row, index }) => (\n <FeatureReleaseRow\n key={row.slug}\n path={props.path}\n index={index}\n row={row}\n rows={rows}\n setRows={(next) => setValue(next)}\n />\n ))}\n </div>\n );\n })}\n </div>\n );\n};\n","\"use client\";\n\nimport { KitProvider } from \"@bison-lab/admin-ui\";\nimport { isThemeHex } from \"@bison-lab/tokens\";\nimport { useConfig } from \"@payloadcms/ui\";\nimport { useEffect, useState, type ReactNode } from \"react\";\n\nfunction primaryHex(doc: { colors?: { brand?: { primary?: { hex?: string } } } } | null): string | undefined {\n const hex = doc?.colors?.brand?.primary?.hex;\n return typeof hex === \"string\" && isThemeHex(hex) ? hex : undefined;\n}\n\n/**\n * Site Theme primary → `--bl-kit-accent`. Saved value for the whole\n * admin; the Primary color card also writes the live hex so pickers\n * and kit chrome update as the field is edited.\n */\nexport function ThemeKitAccent({ children }: { children: ReactNode }) {\n const { config } = useConfig();\n const [accent, setAccent] = useState<string | undefined>();\n\n useEffect(() => {\n const url = `${config.serverURL}${config.routes.api}/globals/theme?depth=0`;\n let cancelled = false;\n\n function load() {\n void fetch(url, { credentials: \"include\" })\n .then((response) => (response.ok ? response.json() : null))\n .then((doc) => {\n const hex = primaryHex(doc);\n if (!cancelled && hex) setAccent(hex);\n })\n .catch(() => undefined);\n }\n\n load();\n const onVis = () => {\n if (document.visibilityState === \"visible\") load();\n };\n document.addEventListener(\"visibilitychange\", onVis);\n return () => {\n cancelled = true;\n document.removeEventListener(\"visibilitychange\", onVis);\n };\n }, [config.serverURL, config.routes.api]);\n\n return <KitProvider accent={accent}>{children}</KitProvider>;\n}\n","\"use client\";\n\nimport { useLayoutEffect, type ReactNode } from \"react\";\n\nimport { ThemeKitAccent } from \"./theme-kit-accent\";\n\n/**\n * Shared document header: title on the left, primary actions on the\n * right — the same slot collection lists use for Create New.\n *\n * Payload parks Edit / Versions / API in that slot and puts Save one\n * row down. This moves `.doc-controls__controls-wrapper` (Save,\n * Preview, Create New, and the kebab) onto the title row, hides the\n * active Edit tab (you are already on the form), and collapses the\n * leftover controls band when it has no meta.\n *\n * Mounted as `admin.components.providers` so Account and every\n * collection / global share one lift. A MutationObserver re-applies\n * after Payload redraws the controls.\n */\nconst TITLE_ACTIONS_CSS = `\n.doc-header__header{display:flex;align-items:center;justify-content:flex-start;width:100%;gap:10px}\n.doc-header__title{flex:0 1 auto;min-width:0}\n.doc-header__header > .doc-controls__controls-wrapper{margin-left:auto;display:flex;align-items:center;gap:8px}\n.doc-tab.doc-tab--active.btn--disabled{display:none}\n.doc-tabs:not(:has(.doc-tab:not(.doc-tab--active))){display:none}\n.doc-controls:has(.doc-controls__meta:empty):not(:has(.doc-controls__controls-wrapper)){height:0;min-height:0;padding:0;overflow:hidden}\n.doc-controls:has(.doc-controls__meta:empty):not(:has(.doc-controls__controls-wrapper)) .doc-controls__divider{display:none}\n`;\n\nfunction liftTitleActions() {\n const header = document.querySelector(\".doc-header__header\");\n const wrapper = document.querySelector(\".doc-controls__controls-wrapper\");\n if (!header || !wrapper) return;\n if (wrapper.parentElement === header) return;\n header.appendChild(wrapper);\n}\n\nexport function DocumentTitleActions({ children }: { children?: ReactNode }) {\n useLayoutEffect(() => {\n liftTitleActions();\n const observer = new MutationObserver(liftTitleActions);\n observer.observe(document.body, { childList: true, subtree: true });\n return () => observer.disconnect();\n }, []);\n\n return (\n <ThemeKitAccent>\n <style href=\"bl-doc-title-actions\" precedence=\"default\">\n {TITLE_ACTIONS_CSS}\n </style>\n {children}\n </ThemeKitAccent>\n );\n}\n","\"use client\";\n\nimport { Button, useForm } from \"@payloadcms/ui\";\n\n/**\n * Same words as a collection list Create New — no icon, no \"Area\" or\n * \"Role.\" The page title already says what is created. Primary so a\n * site's admin skin can paint it with Theme `--primary`.\n *\n * Hides the array's own Add while this control is mounted so the\n * action is not offered twice.\n */\nconst HIDE_FIELD_ADD = `.array-field__add-row{display:none}`;\n\nexport function DocumentCreateNew({ path }: { path: string }) {\n const { addFieldRow, disabled } = useForm();\n\n return (\n <>\n <style href=\"bl-doc-create-new\" precedence=\"default\">\n {HIDE_FIELD_ADD}\n </style>\n <Button\n buttonStyle=\"primary\"\n size=\"medium\"\n type=\"button\"\n disabled={disabled}\n onClick={() => {\n addFieldRow({ path, schemaPath: path });\n }}\n >\n Create New\n </Button>\n </>\n );\n}\n","/**\n * Developer-owned admin sidebar. SPI-10 skins this with AppSidebarBlock;\n * this package ships the document and the default Nav. A consuming site\n * waits for SPI-97 after this and BIS-110 publish.\n */\n\nexport const ADMIN_NAV_SLUG = \"admin-nav\";\n\nexport type AdminNavEntityType = \"collection\" | \"global\";\n\nexport interface AdminNavItem {\n type: AdminNavEntityType;\n slug: string;\n label: string;\n}\n\nexport interface AdminNavGroup {\n label: string;\n items: AdminNavItem[];\n}\n\nexport interface AdminNavDoc {\n groups?: Array<{\n id?: string | null;\n label?: string | null;\n items?: Array<{\n id?: string | null;\n type?: string | null;\n slug?: string | null;\n }> | null;\n }> | null;\n}\n\nexport interface AdminNavVisibleEntities {\n collections?: readonly string[];\n globals?: readonly string[];\n}\n\nexport interface AdminNavEntityConfig {\n slug: string;\n admin?: { group?: unknown };\n label?: unknown;\n labels?: { plural?: unknown; singular?: unknown };\n}\n\nexport interface AdminNavConfig {\n collections?: readonly AdminNavEntityConfig[];\n globals?: readonly AdminNavEntityConfig[];\n}\n\nexport interface ResolveAdminNavArgs {\n config: AdminNavConfig;\n doc?: AdminNavDoc | null;\n visibleEntities?: AdminNavVisibleEntities;\n}\n","import type {\n AdminNavConfig,\n AdminNavDoc,\n AdminNavEntityConfig,\n AdminNavEntityType,\n AdminNavGroup,\n AdminNavItem,\n ResolveAdminNavArgs,\n} from \"./types\";\n\nfunction sidebarGroup(group: unknown): string | false {\n if (group === false) return false;\n if (typeof group === \"string\") return group;\n return \"\";\n}\n\nfunction asLabel(value: unknown, fallback: string): string {\n return typeof value === \"string\" && value ? value : fallback;\n}\n\nfunction entityLabel(entity: AdminNavEntityConfig, type: AdminNavEntityType): string {\n if (type === \"collection\") {\n return asLabel(entity.labels?.plural, asLabel(entity.labels?.singular, entity.slug));\n }\n return asLabel(entity.label, entity.slug);\n}\n\nfunction keyOf(type: AdminNavEntityType, slug: string): string {\n return `${type}:${slug}`;\n}\n\ninterface CatalogEntry {\n type: AdminNavEntityType;\n slug: string;\n label: string;\n group: string | false;\n}\n\nfunction catalog(config: AdminNavConfig): CatalogEntry[] {\n const collections = (config.collections ?? []).map((entity) => ({\n type: \"collection\" as const,\n slug: entity.slug,\n label: entityLabel(entity, \"collection\"),\n group: sidebarGroup(entity.admin?.group),\n }));\n const globals = (config.globals ?? []).map((entity) => ({\n type: \"global\" as const,\n slug: entity.slug,\n label: entityLabel(entity, \"global\"),\n group: sidebarGroup(entity.admin?.group),\n }));\n return [...collections, ...globals];\n}\n\nfunction defaultGroups(entities: readonly CatalogEntry[]): AdminNavGroup[] {\n const groups: AdminNavGroup[] = [];\n for (const entity of entities) {\n if (entity.group === false) continue;\n let group = groups.find((entry) => entry.label === entity.group);\n if (!group) {\n group = { label: entity.group, items: [] };\n groups.push(group);\n }\n group.items.push({ type: entity.type, slug: entity.slug, label: entity.label });\n }\n return groups;\n}\n\nfunction itemFromSaved(\n item: { type?: string | null; slug?: string | null },\n byKey: Map<string, CatalogEntry>,\n): AdminNavItem | null {\n const type = item.type === \"global\" || item.type === \"collection\" ? item.type : null;\n const slug = typeof item.slug === \"string\" ? item.slug : \"\";\n if (!type || !slug) return null;\n const entity = byKey.get(keyOf(type, slug));\n if (!entity || entity.group === false) return null;\n return { type, slug, label: entity.label };\n}\n\nfunction fromDocument(doc: AdminNavDoc, entities: readonly CatalogEntry[]): AdminNavGroup[] {\n const byKey = new Map(entities.map((entity) => [keyOf(entity.type, entity.slug), entity]));\n return (doc.groups ?? []).map((row) => ({\n label: typeof row.label === \"string\" ? row.label : \"\",\n items: (row.items ?? []).flatMap((item) => {\n const resolved = itemFromSaved(item ?? {}, byKey);\n return resolved ? [resolved] : [];\n }),\n }));\n}\n\n/**\n * Layout for the package Nav (and later SPI-10). Permissions are\n * `visibleEntities` — this function does not re-derive access.\n */\nexport function resolveAdminNav({ config, doc, visibleEntities }: ResolveAdminNavArgs): AdminNavGroup[] {\n const entities = catalog(config);\n const saved = Array.isArray(doc?.groups) ? doc.groups : [];\n let groups = saved.length === 0 ? defaultGroups(entities) : fromDocument({ groups: saved }, entities);\n\n if (visibleEntities) {\n const collections = new Set(visibleEntities.collections ?? []);\n const globals = new Set(visibleEntities.globals ?? []);\n groups = groups.map((group) => ({\n ...group,\n items: group.items.filter((item) =>\n item.type === \"collection\" ? collections.has(item.slug) : globals.has(item.slug),\n ),\n }));\n }\n\n return groups;\n}\n","import { useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { Link, Logout, NavGroup, NavToggler, useConfig, useNav } from \"@payloadcms/ui\";\n\nimport { ADMIN_NAV_SLUG } from \"../admin-nav/types\";\nimport { resolveAdminNav } from \"../admin-nav/resolve\";\nimport type { AdminNavDoc, AdminNavVisibleEntities } from \"../admin-nav/types\";\n\nexport interface AdminNavProps {\n visibleEntities?: AdminNavVisibleEntities;\n}\n\nconst BASE = \"nav\";\n\n/** Survives AdminNav remounting on every admin route so the first-seen walk does not flash. */\nlet cachedDoc: AdminNavDoc | null | undefined;\n\nexport function resetAdminNavCache() {\n cachedDoc = undefined;\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof DOMException\n ? error.name === \"AbortError\"\n : error instanceof Error && error.name === \"AbortError\";\n}\n\n/**\n * Payload's DefaultNav roots in an `@internal` NavWrapper. Copy the\n * class contract here — this package does not depend on `@payloadcms/next`.\n * Without `nav--nav-open`, Payload's CSS keeps `.nav` at opacity 0.\n */\nfunction AdminNavShell({ children }: { children: ReactNode }) {\n const { hydrated, navOpen, navRef, shouldAnimate } = useNav();\n const className = [\n BASE,\n navOpen && `${BASE}--nav-open`,\n shouldAnimate && `${BASE}--nav-animate`,\n hydrated && `${BASE}--nav-hydrated`,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <aside className={className} inert={navOpen ? undefined : true}>\n <div className={`${BASE}__scroll`} ref={navRef}>\n {children}\n </div>\n </aside>\n );\n}\n\n/**\n * Default admin sidebar. Reads the Admin nav Global and paints\n * `resolveAdminNav`. SPI-10 may replace this component; it should keep\n * calling that function so the document stays the one layout source.\n */\nexport function AdminNav({ visibleEntities }: AdminNavProps) {\n const { config } = useConfig();\n const [doc, setDoc] = useState<AdminNavDoc | null>(() => cachedDoc ?? null);\n const adminRoute = config.routes.admin ?? \"/admin\";\n const apiRoute = config.routes.api ?? \"/api\";\n\n useEffect(() => {\n const controller = new AbortController();\n const url = `${config.serverURL ?? \"\"}${apiRoute}/globals/${ADMIN_NAV_SLUG}`;\n void fetch(url, { credentials: \"include\", signal: controller.signal })\n .then((response) => (response.ok ? response.json() : null))\n .then((payload: AdminNavDoc | null) => {\n if (controller.signal.aborted) return;\n cachedDoc = payload;\n setDoc(payload);\n })\n .catch((error: unknown) => {\n if (isAbortError(error) || controller.signal.aborted) return;\n if (cachedDoc !== undefined) return;\n cachedDoc = null;\n setDoc(null);\n });\n return () => controller.abort();\n }, [apiRoute, config.serverURL]);\n\n const groups = useMemo(\n () => resolveAdminNav({ config, doc, visibleEntities }),\n [config, doc, visibleEntities],\n );\n\n return (\n <AdminNavShell>\n <nav className={`${BASE}__wrap`} aria-label=\"Admin\">\n <div className={`${BASE}__links`}>\n {groups.map((group, index) => {\n const items = group.items.map((item) => {\n const href =\n item.type === \"collection\"\n ? `${adminRoute}/collections/${item.slug}`\n : `${adminRoute}/globals/${item.slug}`;\n return (\n <Link\n key={`${item.type}:${item.slug}`}\n className={`${BASE}__link`}\n href={href}\n prefetch={false}\n >\n <span className={`${BASE}__link-label`}>{item.label}</span>\n </Link>\n );\n });\n if (!group.label) {\n return (\n <div key={`ungrouped-${index}`} className={`${BASE}__ungrouped`}>\n {items}\n </div>\n );\n }\n return (\n <NavGroup key={`${group.label}-${index}`} label={group.label}>\n {items}\n </NavGroup>\n );\n })}\n </div>\n <div className={`${BASE}__controls`}>\n <Logout />\n </div>\n </nav>\n <div className={`${BASE}__header`}>\n <div className={`${BASE}__header-content`}>\n <NavToggler />\n </div>\n </div>\n </AdminNavShell>\n );\n}\n","import { useRowLabel } from \"@payloadcms/ui\";\n\n/**\n * Array row header. Shows the group label, or “Group” when empty.\n */\nexport function AdminNavRowLabel() {\n const { data } = useRowLabel<{ label?: string | null }>();\n const label = typeof data.label === \"string\" && data.label.trim() ? data.label.trim() : \"Group\";\n return <span>{label}</span>;\n}\n","import type { AdminNavConfig, AdminNavEntityType } from \"./types\";\n\nexport interface AdminNavEntityOption {\n value: string;\n label: string;\n}\n\nfunction entityType(type: unknown): AdminNavEntityType {\n return type === \"global\" ? \"global\" : \"collection\";\n}\n\n/**\n * Collections or globals a Developer may pin. Sibling Type decides which\n * list. `group: false` stays off — those entities are not on the sidebar.\n */\nexport function adminNavEntityOptions(\n config: AdminNavConfig,\n type: unknown,\n): AdminNavEntityOption[] {\n const kind = entityType(type);\n const entities = kind === \"global\" ? (config.globals ?? []) : (config.collections ?? []);\n return entities\n .filter((entity) => entity.admin?.group !== false)\n .map((entity) => ({\n value: entity.slug,\n label:\n kind === \"global\"\n ? typeof entity.label === \"string\" && entity.label\n ? entity.label\n : entity.slug\n : typeof entity.labels?.plural === \"string\" && entity.labels.plural\n ? entity.labels.plural\n : entity.slug,\n }));\n}\n\n/** Array row title. Empty slug falls back to “Item”, never “Item 01”. */\nexport function adminNavEntityLabel(config: AdminNavConfig, type: unknown, slug: unknown): string {\n if (typeof slug !== \"string\" || !slug) return \"Item\";\n return adminNavEntityOptions(config, type).find((option) => option.value === slug)?.label ?? slug;\n}\n","import { useConfig, useRowLabel } from \"@payloadcms/ui\";\n\nimport { adminNavEntityLabel } from \"../admin-nav/entity-options\";\n\n/**\n * Item accordion title. Shows the chosen collection or global name\n * (Pages), or “Item” when the row is still empty.\n */\nexport function AdminNavItemRowLabel() {\n const { data } = useRowLabel<{ type?: string | null; slug?: string | null }>();\n const { config } = useConfig();\n return <span>{adminNavEntityLabel(config, data.type, data.slug)}</span>;\n}\n","import { SelectField, useConfig, useField } from \"@payloadcms/ui\";\nimport type { SelectFieldClient, TextFieldClientComponent } from \"payload\";\n\nimport { adminNavEntityOptions } from \"../admin-nav/entity-options\";\n\n/**\n * Payload's select of collections or globals. Subscribes to sibling Type\n * with `useField` so the list updates when Type changes — `getDataByPath`\n * does not re-render this field.\n */\nexport const AdminNavEntityField: TextFieldClientComponent = ({\n field,\n path,\n permissions,\n readOnly,\n schemaPath,\n}) => {\n const { value: type } = useField<string>({ path: path.replace(/\\.slug$/, \".type\") });\n const { config } = useConfig();\n const options = adminNavEntityOptions(config, type);\n\n return (\n <SelectField\n field={\n {\n name: field.name,\n label: field.label,\n required: field.required,\n admin: {\n ...field.admin,\n isClearable: false,\n isSortable: false,\n placeholder: \"Select…\",\n },\n type: \"select\",\n hasMany: false,\n options,\n } as SelectFieldClient\n }\n path={path}\n permissions={permissions}\n readOnly={readOnly}\n schemaPath={schemaPath}\n />\n );\n};\n"],"mappings":"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"}
|