@bison-lab/payload-core 3.19.0 → 3.19.1
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 +4 -3
- package/dist/admin.d.mts +12 -9
- package/dist/admin.d.mts.map +1 -1
- package/dist/admin.mjs +68 -51
- package/dist/admin.mjs.map +1 -1
- package/dist/index.d.mts +4 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +31 -43
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["payloadSeoPlugin","isAccessArgs","requireAccess","catalog"],"sources":["../src/seo/fields.ts","../src/seo/text.ts","../src/seo/plugin.ts","../src/theme/appearance-labels.ts","../src/theme/color-usages.ts","../src/theme/color-usage-endpoints.ts","../src/features/types.ts","../src/features/matrix.ts","../src/roles/types.ts","../src/roles/matrix.ts","../src/roles/access.ts","../src/features/access.ts","../src/theme/global.ts","../src/brand-assets/sanitize.ts","../src/brand-assets/collection.ts","../src/theme/seed.ts","../src/theme/preview.ts","../src/theme/publish.ts","../src/admin/document-controls.ts","../src/roles/fields.ts","../src/roles/global.ts","../src/roles/seed.ts","../src/features/fields.ts","../src/features/global.ts","../src/features/seed.ts","../src/fields/slug.ts","../src/collections/pages.ts","../src/collections/users.ts","../src/collections/media.ts","../src/admin-nav/fields.ts","../src/admin-nav/types.ts","../src/admin-nav/validate.ts","../src/admin-nav/global.ts","../src/admin-nav/plugin.ts","../src/admin-nav/resolve.ts","../src/navigation/link.ts","../src/navigation/global.ts","../src/plugins/admin-only-api-tab.ts","../src/plugins/document-title-actions.ts"],"sourcesContent":["import type { CheckboxField } from \"payload\";\n\n/**\n * The index switch, last in the SEO tab. Off by default: a page is public\n * unless an editor says otherwise. `pageMetadata` turns it into\n * `noindex, nofollow`; a site's sitemap should filter on it too.\n */\nexport const noIndexField: CheckboxField = {\n name: \"noIndex\",\n type: \"checkbox\",\n label: \"Hide this page from search engines\",\n defaultValue: false,\n admin: {\n description:\n \"Search engines will not list this page and the sitemap will leave it out. Anyone with the link can still open it.\",\n },\n};\n","/** The length a search result shows of a description before it is cut. */\nexport const DESCRIPTION_LENGTH = 155;\n\n/**\n * Prose cut to `max` characters at a word, with an ellipsis, so a generated\n * description does not end mid-syllable. Text that fits is returned trimmed\n * and whole. A first word longer than `max` is cut mid-word, since there is\n * no boundary to cut at.\n */\nexport function truncateAtWord(text: string, max = DESCRIPTION_LENGTH): string {\n const trimmed = text.trim();\n if (trimmed.length <= max) return trimmed;\n const cut = trimmed.slice(0, max);\n const lastSpace = cut.lastIndexOf(\" \");\n return `${lastSpace > 0 ? cut.slice(0, lastSpace) : cut}…`;\n}\n","import { seoPlugin as payloadSeoPlugin } from \"@payloadcms/plugin-seo\";\nimport type {\n GenerateDescription,\n GenerateImage,\n GenerateTitle,\n GenerateURL,\n} from \"@payloadcms/plugin-seo/types\";\nimport type { CollectionSlug, Plugin, UploadCollectionSlug } from \"payload\";\n\nimport { noIndexField } from \"./fields\";\nimport { truncateAtWord } from \"./text\";\nimport { documentTitle } from \"./title\";\nimport type { MediaId } from \"./types\";\n\n/**\n * What the plugin reads off a document: its title, for the generated meta\n * title. The site's generated `Page` is assignable to this; the `urlFor`,\n * `describeFrom` and `imageFor` callbacks read the rest, typed as the site\n * chooses through `TDoc`.\n */\nexport interface SeoDoc {\n title?: string | null;\n}\n\nexport interface SeoPluginOptions<TDoc extends SeoDoc = SeoDoc> {\n /** Appended to every generated title: `<page title> | <siteName>`. */\n siteName: string;\n /**\n * The absolute public URL of a document from the form's data, for the\n * search-result preview and the Generate button beside it. `undefined`\n * when the document has no address yet (a slug not typed), which leaves\n * the preview empty rather than pointing at the home page.\n */\n urlFor: (doc: TDoc) => string | undefined;\n /**\n * Prose to cut a generated description from, the first plain-text field a\n * page always has near the top (a hero's body, say). Cut at a word near\n * 155 characters. Without it the Generate button fills in nothing.\n */\n describeFrom?: (doc: TDoc) => string | null | undefined;\n /**\n * An image already on the page, for the Meta Image Generate button, so an\n * editor need not upload a second copy of the hero picture. `firstImageIn`\n * walks block rows for one. The upload chooser stays, so any other media\n * row can still be picked.\n */\n imageFor?: (doc: TDoc) => MediaId | null | undefined;\n /** Collections that get the SEO tab. Default `['pages']`. */\n collections?: CollectionSlug[];\n /** The upload collection the meta image comes from. Default `'media'`. */\n uploadsCollection?: UploadCollectionSlug;\n}\n\n/**\n * `@payloadcms/plugin-seo` configured the Bison Lab way: an SEO tab beside a\n * Content tab (never below the block editor), holding the overview with its\n * character counts, meta title, description and image with Generate buttons,\n * the search-result preview, and the `noIndex` switch.\n *\n * Every string the tab generates comes from the options, so a site spells\n * its name and its URL scheme once. Pin `@payloadcms/plugin-seo` to the same\n * version as `payload` in the site; the plugin's admin components are\n * resolved from the site's import map, so run `payload generate:importmap`\n * after adding it.\n */\nexport function seoPlugin<TDoc extends SeoDoc = SeoDoc>({\n siteName,\n urlFor,\n describeFrom,\n imageFor,\n collections = [\"pages\"],\n uploadsCollection = \"media\",\n}: SeoPluginOptions<TDoc>): Plugin {\n const generateTitle: GenerateTitle<TDoc> = ({ doc }) =>\n doc?.title ? documentTitle(siteName, doc.title) : \"\";\n const generateDescription: GenerateDescription<TDoc> = ({ doc }) =>\n truncateAtWord(describeFrom?.(doc) ?? \"\");\n const generateURL: GenerateURL<TDoc> = ({ doc }) => urlFor(doc) ?? \"\";\n // Only when the site can name one: the button appears with the function.\n const generateImage: GenerateImage<TDoc> | undefined = imageFor\n ? ({ doc }) => imageFor(doc) ?? \"\"\n : undefined;\n\n return payloadSeoPlugin({\n collections,\n uploadsCollection,\n tabbedUI: true,\n generateTitle,\n generateDescription,\n generateURL,\n ...(generateImage ? { generateImage } : {}),\n fields: ({ defaultFields }) => [...defaultFields, noIndexField],\n });\n}\n\n/**\n * The first image among some block rows, as a media id, for `imageFor`. Each\n * row is checked for `field` holding either a bare id or a populated upload\n * document; rows without one are skipped. Pass the page's hero and layout\n * together (`[...doc.hero, ...doc.layout]`) to search in reading order.\n */\nexport function firstImageIn(\n blocks: unknown,\n field = \"image\",\n): MediaId | undefined {\n if (!Array.isArray(blocks)) return undefined;\n for (const block of blocks) {\n if (typeof block !== \"object\" || block === null) continue;\n const value = (block as Record<string, unknown>)[field];\n const id =\n typeof value === \"object\" && value !== null && \"id\" in value\n ? (value as { id: unknown }).id\n : value;\n if (typeof id === \"number\" || (typeof id === \"string\" && id !== \"\"))\n return id;\n }\n return undefined;\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 { 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 type { Access, Endpoint, PayloadRequest } from \"payload\";\n\nimport {\n COLOR_USAGES_PATH,\n findColorUsages,\n replacementKeys,\n rewriteColorUsages,\n type ColorUsagePayload,\n type ColorUsagesOption,\n} from \"./color-usages\";\n\nexport { COLOR_USAGES_PATH };\n\nexport function colorUsageEndpoints(\n access: { update: Access },\n scopes: ColorUsagesOption | undefined,\n): Endpoint[] {\n return [\n {\n path: COLOR_USAGES_PATH,\n method: \"get\",\n handler: async (req) => {\n const denied = await denyUnlessUpdate(req, access.update);\n if (denied) return denied;\n const key = queryKey(req);\n if (!key) return Response.json({ error: \"key is required\" }, { status: 400 });\n const usages = await findColorUsages(req.payload as unknown as ColorUsagePayload, scopes, key);\n return Response.json({ usages });\n },\n },\n {\n path: COLOR_USAGES_PATH,\n method: \"post\",\n handler: async (req) => {\n const denied = await denyUnlessUpdate(req, access.update);\n if (denied) return denied;\n const body = (await readJson(req)) as { key?: unknown; replacement?: unknown } | null;\n const key = typeof body?.key === \"string\" ? body.key : \"\";\n const replacement = typeof body?.replacement === \"string\" ? body.replacement : \"\";\n if (!key || !replacement) {\n return Response.json({ error: \"key and replacement are required\" }, { status: 400 });\n }\n const live = await replacementKeys(req.payload as unknown as ColorUsagePayload, key);\n if (!live.includes(replacement)) {\n return Response.json(\n { error: \"Replacement must be a different live system or remaining custom key\" },\n { status: 400 },\n );\n }\n await rewriteColorUsages(req.payload as unknown as ColorUsagePayload, scopes, key, replacement);\n return Response.json({ ok: true });\n },\n },\n ];\n}\n\nasync function denyUnlessUpdate(req: PayloadRequest, update: Access): Promise<Response | null> {\n const allowed = await update({ req });\n if (allowed) return null;\n return Response.json({ error: \"Forbidden\" }, { status: 403 });\n}\n\nfunction queryKey(req: PayloadRequest): string {\n const fromQuery = req.query?.key;\n if (typeof fromQuery === \"string\") return fromQuery;\n if (Array.isArray(fromQuery) && typeof fromQuery[0] === \"string\") return fromQuery[0];\n if (req.url) {\n try {\n return new URL(req.url, \"http://local\").searchParams.get(\"key\") ?? \"\";\n } catch {\n return \"\";\n }\n }\n return \"\";\n}\n\nasync function readJson(req: PayloadRequest): Promise<unknown> {\n if (typeof req.json === \"function\") return req.json();\n return null;\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 type { Access, PayloadRequest } from \"payload\";\n\nimport { DEFAULT_ROLE_MATRIX, parseRolesMatrix, roleHasCapability, roleHasGrant, ROLES_SLUG, seedRoleRows } from \"./matrix\";\nimport { type Capability, type MaybeUser, type RoleExtra, type RoleRow } from \"./types\";\n\nexport type { MaybeUser } from \"./types\";\n\ntype AccessArgs = {\n req: {\n user?: MaybeUser;\n payload?: Pick<NonNullable<PayloadRequest[\"payload\"]>, \"findGlobal\">;\n };\n};\n\ntype CapabilityPredicate = {\n (user: MaybeUser, matrix?: readonly RoleRow[]): boolean;\n (args: AccessArgs): boolean | Promise<boolean>;\n};\n\nfunction isAccessArgs(value: unknown): value is AccessArgs {\n return typeof value === \"object\" && value !== null && \"req\" in value;\n}\n\nexport function storedRoles(user: MaybeUser): readonly string[] {\n return Array.isArray(user?.roles) ? user.roles : [];\n}\n\nexport function hasRole(user: MaybeUser, role: string): boolean {\n return storedRoles(user).includes(role);\n}\n\n/** Not a tick. True only when `developer` is stored on the row. */\nexport function isDeveloper(user: MaybeUser): boolean {\n return hasRole(user, \"developer\");\n}\n\nexport function hasCapability(\n user: MaybeUser,\n capability: Capability,\n matrix: readonly RoleRow[] = DEFAULT_ROLE_MATRIX,\n): boolean {\n if (isDeveloper(user)) return true;\n return storedRoles(user).some((role) => {\n const row = matrix.find((entry) => entry.role === role);\n return row ? roleHasCapability(row, capability) : false;\n });\n}\n\nexport function hasGrant(\n user: MaybeUser,\n slug: string,\n matrix: readonly RoleRow[] = DEFAULT_ROLE_MATRIX,\n): boolean {\n if (isDeveloper(user)) return true;\n return storedRoles(user).some((role) => {\n const row = matrix.find((entry) => entry.role === role);\n return row ? roleHasGrant(row, slug) : false;\n });\n}\n\n/**\n * Reads the saved Roles Global, falling back to the seed when the row is\n * empty, missing, or unreadable. Always override-access so a Designer\n * evaluating Theme does not have to read Settings → Roles.\n */\nexport async function getRolesMatrix(\n req: AccessArgs[\"req\"] = {},\n extras: readonly RoleExtra[] = [],\n): Promise<RoleRow[]> {\n const fallback = seedRoleRows(extras);\n const findGlobal = req.payload?.findGlobal;\n if (typeof findGlobal !== \"function\") return fallback;\n try {\n const doc = await findGlobal({\n slug: ROLES_SLUG,\n overrideAccess: true,\n req: req as PayloadRequest,\n });\n const parsed = parseRolesMatrix(doc && typeof doc === \"object\" && \"roles\" in doc ? doc.roles : undefined);\n return parsed.ok ? parsed.rows : fallback;\n } catch {\n return fallback;\n }\n}\n\nfunction capabilityPredicate(capability: Capability): CapabilityPredicate {\n function predicate(\n userOrArgs: MaybeUser | AccessArgs,\n matrix?: readonly RoleRow[],\n ): boolean | Promise<boolean> {\n if (isAccessArgs(userOrArgs)) {\n const user = userOrArgs.req.user as MaybeUser;\n if (matrix) return hasCapability(user, capability, matrix);\n return getRolesMatrix(userOrArgs.req).then((rows) => hasCapability(user, capability, rows));\n }\n return hasCapability(userOrArgs, capability, matrix ?? DEFAULT_ROLE_MATRIX);\n }\n return predicate as CapabilityPredicate;\n}\n\nexport const canManageContent = capabilityPredicate(\"content\");\nexport const canManageBrand = capabilityPredicate(\"brand\");\nexport const canPublish = capabilityPredicate(\"publish\");\n\n/** Users grant on any held role (Developer is implicit). */\nexport const isAdmin = capabilityPredicate(\"users\");\n\n/** This role id currently has the Users grant, or is Developer. */\nexport function isPrivilegedRole(\n role: unknown,\n matrix: readonly RoleRow[] = DEFAULT_ROLE_MATRIX,\n): boolean {\n if (typeof role !== \"string\") return false;\n if (role === \"developer\") return true;\n const row = matrix.find((entry) => entry.role === role);\n return row ? roleHasGrant(row, \"users\") : false;\n}\n\nexport function isAuthenticated(user: MaybeUser): boolean;\nexport function isAuthenticated(args: AccessArgs): boolean;\nexport function isAuthenticated(userOrArgs: MaybeUser | AccessArgs): boolean {\n if (isAccessArgs(userOrArgs)) return Boolean(userOrArgs.req.user);\n return Boolean(userOrArgs);\n}\n\nexport const isAdminOrSelf: Access = async ({ req }) => {\n if (!req.user) return false;\n if (await isAdmin({ req })) return true;\n return { id: { equals: req.user.id } };\n};\n\nexport const authenticatedOrPublished: Access = ({ req: { user } }) => {\n if (isAuthenticated(user as MaybeUser)) return true;\n return { _status: { equals: \"published\" } };\n};\n\n/**\n * API tab condition. Code-locked to the `developer` slug — not a Features\n * row and not a Role tick a client can grant.\n */\nexport function isDeveloperTab({ req }: AccessArgs): boolean {\n return isDeveloper(req.user as MaybeUser);\n}\n\n/** Access for chrome globals (Features, Better Editor settings). */\nexport function developerOnlyAccess(): { read: Access; update: Access } {\n return {\n read: ({ req }) => isDeveloper(req.user as MaybeUser),\n update: ({ req }) => isDeveloper(req.user as MaybeUser),\n };\n}\n\n/** `admin.hidden`: hide unless the login is Developer. */\nexport function hideUnlessDeveloper({ user }: { user?: MaybeUser }): boolean {\n return !isDeveloper(user);\n}\n","import type { PayloadRequest } from \"payload\";\n\nimport { getRolesMatrix, hasGrant, isDeveloper, type MaybeUser } from \"../roles/access\";\nimport { DEFAULT_ROLE_MATRIX } from \"../roles/matrix\";\nimport type { RoleRow } from \"../roles/types\";\nimport { defaultFeaturesFieldValue, isGroupOnlySlug, parseFeaturesMatrix } from \"./matrix\";\nimport { FEATURE_GROUPS, FEATURES_SLUG, type FeatureRow } from \"./types\";\n\ntype AccessArgs = {\n req: {\n user?: MaybeUser;\n payload?: Pick<NonNullable<PayloadRequest[\"payload\"]>, \"findGlobal\">;\n };\n};\n\ntype FeaturePredicate = {\n (user: MaybeUser, features?: readonly FeatureRow[] | null, roles?: readonly RoleRow[]): boolean;\n (args: AccessArgs): boolean | Promise<boolean>;\n};\n\nfunction isAccessArgs(value: unknown): value is AccessArgs {\n return typeof value === \"object\" && value !== null && \"req\" in value;\n}\n\nfunction grantedOnReleased(\n user: MaybeUser,\n slug: string,\n row: FeatureRow,\n matrix: readonly RoleRow[],\n): boolean {\n if (!row.released) return false;\n return hasGrant(user, slug, matrix);\n}\n\n/**\n * True when the feature is released and a held role is granted it.\n * Developer is always allowed. An empty Global falls back to catalogue\n * defaults. A group slug (`pages`, `theme`) is true when any child is.\n */\nexport function hasFeature(\n user: MaybeUser,\n slug: string,\n features: readonly FeatureRow[] | null = null,\n matrix: readonly RoleRow[] = DEFAULT_ROLE_MATRIX,\n): boolean {\n if (isDeveloper(user)) return true;\n if (!user) return false;\n const rows = features && features.length > 0 ? features : defaultFeaturesFieldValue();\n const leaf = rows.find((entry) => entry.slug === slug);\n if (leaf) return grantedOnReleased(user, slug, leaf, matrix);\n if (!isGroupOnlySlug(slug)) return false;\n return rows.some((entry) => entry.group === slug && grantedOnReleased(user, entry.slug, entry, matrix));\n}\n\n/**\n * Reads the saved Features Global. `null` means empty or unreadable — callers\n * fall back to catalogue defaults. Always override-access.\n */\nexport async function getFeaturesMatrix(req: AccessArgs[\"req\"] = {}): Promise<FeatureRow[] | null> {\n const findGlobal = req.payload?.findGlobal;\n if (typeof findGlobal !== \"function\") return null;\n try {\n const doc = await findGlobal({\n slug: FEATURES_SLUG,\n overrideAccess: true,\n req: req as PayloadRequest,\n });\n const parsed = parseFeaturesMatrix(\n doc && typeof doc === \"object\" && \"features\" in doc ? doc.features : undefined,\n );\n return parsed.ok ? parsed.rows : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Access / nav helper for one catalogue slug. Sync against a passed grid;\n * async when given `req` so it can read both Globals.\n */\nexport function canUseFeature(slug: string): FeaturePredicate {\n function predicate(\n userOrArgs: MaybeUser | AccessArgs,\n features?: readonly FeatureRow[] | null,\n roles?: readonly RoleRow[],\n ): boolean | Promise<boolean> {\n if (isAccessArgs(userOrArgs)) {\n const user = userOrArgs.req.user as MaybeUser;\n if (features !== undefined) return hasFeature(user, slug, features, roles ?? DEFAULT_ROLE_MATRIX);\n return Promise.all([getFeaturesMatrix(userOrArgs.req), getRolesMatrix(userOrArgs.req)]).then(\n ([grid, matrix]) => hasFeature(user, slug, grid, matrix),\n );\n }\n return hasFeature(userOrArgs, slug, features ?? null, roles ?? DEFAULT_ROLE_MATRIX);\n }\n return predicate as FeaturePredicate;\n}\n\n/**\n * Feature slugs (and group slugs) this login may use. Written onto the\n * user at afterRead so `admin.hidden({ user })` can follow the saved\n * Features and Roles Globals without a `req`.\n */\nexport async function allowedFeaturesForUser(\n user: MaybeUser,\n req: AccessArgs[\"req\"] = {},\n): Promise<string[]> {\n const [features, roles] = await Promise.all([getFeaturesMatrix(req), getRolesMatrix(req)]);\n const rows = features && features.length > 0 ? features : defaultFeaturesFieldValue();\n const slugs = [...rows.map((row) => row.slug), ...FEATURE_GROUPS];\n return slugs.filter((slug) => hasFeature(user, slug, features, roles));\n}\n\nfunction userHasAllowedFeature(user: MaybeUser, slug: string): boolean {\n if (isDeveloper(user)) return true;\n const allowed = user?.allowedFeatures;\n if (!Array.isArray(allowed)) return false;\n return allowed.includes(slug);\n}\n\n/** `admin.hidden`: hide when the login cannot use the feature. */\nexport function hideUnlessFeature(slug: string) {\n return (args: { user?: MaybeUser; req?: AccessArgs[\"req\"] }) => {\n const user = args.user ?? null;\n if (isDeveloper(user)) return false;\n if (user && Array.isArray(user.allowedFeatures)) {\n return !userHasAllowedFeature(user, slug);\n }\n if (args.req) {\n const result = canUseFeature(slug)({ req: { ...args.req, user } });\n if (result instanceof Promise) return result.then((ok) => !ok);\n return !result;\n }\n return !canUseFeature(slug)(user);\n };\n}\n","import { catalog, type FontEntry } from \"@bison-lab/fonts\";\nimport { DESTRUCTIVE_SCALE_HEX, presetHints, SHADE_STEPS } from \"@bison-lab/tokens\";\n\n/** Same value as tokens `SUCCESS_SCALE_HEX`. Inlined so an older tokens peer still boots. */\nconst LIBRARY_SUCCESS_HEX = \"#22c55e\";\nimport type { Field, GlobalConfig, SelectField } from \"payload\";\n\nimport {\n SAME_AS_BODY,\n THEME_APPEARANCE_FIELD,\n THEME_COLOR_SCALE_FIELD,\n THEME_FONT_FIELD,\n THEME_GREY_SCALE_FIELD,\n THEME_LIBRARY_FIELD,\n THEME_PAIRING_FIELD,\n THEME_DOCUMENT_CONTROLS,\n THEME_SECTION_HEADING,\n headingSelectValue,\n} from \"./fields\";\nimport { APPEARANCE_CHOICES } from \"./appearance-labels\";\nimport { themeConfigFromDoc, validateSourceIncluded, validateThemeHex } from \"./map\";\nimport { colorUsageEndpoints } from \"./color-usage-endpoints\";\nimport { READABILITY_TARGET } from \"./readability\";\nimport { hideUnlessFeature } from \"../features/access\";\nimport { THEME_SLUG, type CreateThemeOptions, type ThemeDoc } from \"./types\";\n\nfunction requireAccess(options: CreateThemeOptions): CreateThemeOptions[\"access\"] {\n const read = options.access?.read;\n const update = options.access?.update;\n if (!read || !update) {\n throw new Error(\n \"createTheme requires access.read and access.update. Pass canManageBrand from this package as update.\",\n );\n }\n return { read, update };\n}\n\nfunction requireDestructive(options: CreateThemeOptions): string {\n return options.destructive ?? options.seed.brandDestructive ?? DESTRUCTIVE_SCALE_HEX;\n}\n\nfunction namedSelect<K extends string>(\n name: string,\n label: string,\n choices: Record<K, { label: string; hint: string }>,\n defaultValue: K,\n field?: string,\n): SelectField {\n return {\n name,\n type: \"select\",\n label,\n required: true,\n defaultValue,\n options: (Object.entries(choices) as [K, { label: string; hint: string }][]).map(\n ([value, { label: optionLabel, hint }]) => ({\n label: `${optionLabel} — ${hint}`,\n value,\n }),\n ),\n ...(field ? { admin: { components: { Field: field } } } : {}),\n };\n}\n\nconst STEP_OPTIONS = SHADE_STEPS.map((step) => ({ label: String(step), value: String(step) }));\n\nfunction colorScaleFields(hexDefault?: string): Field[] {\n const hidden = { hidden: true } as const;\n return [\n {\n name: \"hex\",\n type: \"text\",\n label: \"Hex\",\n required: true,\n ...(hexDefault ? { defaultValue: hexDefault } : {}),\n validate: validateThemeHex,\n admin: hidden,\n },\n {\n name: \"sourceStep\",\n type: \"select\",\n label: \"Source step\",\n required: true,\n defaultValue: \"500\",\n options: STEP_OPTIONS,\n admin: hidden,\n },\n {\n name: \"scale\",\n type: \"json\",\n label: \"Scale\",\n admin: hidden,\n },\n {\n name: \"stale\",\n type: \"checkbox\",\n label: \"Stale\",\n defaultValue: false,\n admin: hidden,\n },\n {\n name: \"include\",\n type: \"select\",\n label: \"Include\",\n required: true,\n defaultValue: \"all\",\n options: [\n { label: \"Include all\", value: \"all\" },\n { label: \"Source only\", value: \"source\" },\n { label: \"Custom\", value: \"custom\" },\n ],\n admin: hidden,\n },\n {\n name: \"includedSteps\",\n type: \"select\",\n label: \"Included steps\",\n hasMany: true,\n options: STEP_OPTIONS,\n validate: validateSourceIncluded,\n admin: hidden,\n },\n ];\n}\n\nfunction systemColorGroup(name: string, label: string, hexDefault: string): Field {\n return {\n name,\n type: \"group\",\n label,\n fields: colorScaleFields(hexDefault),\n admin: { components: { Field: THEME_COLOR_SCALE_FIELD }, hideGutter: true },\n };\n}\n\nfunction fontField(\n name: string,\n label: string,\n defaultValue: string,\n fonts: readonly FontEntry[],\n fontsBaseUrl: string,\n sameAsBody: boolean,\n): SelectField {\n const options = fonts.map((font) => ({ label: font.family, value: font.id }));\n return {\n name,\n type: \"select\",\n label,\n required: !sameAsBody,\n defaultValue,\n options: sameAsBody ? [{ label: \"Same as body\", value: SAME_AS_BODY }, ...options] : options,\n admin: {\n components: { Field: THEME_FONT_FIELD },\n custom: { fontsBaseUrl, ids: fonts.map((font) => font.id), sameAsBody },\n },\n };\n}\n\nfunction colorsFields(seed: CreateThemeOptions[\"seed\"], destructive: string): Field[] {\n return [\n {\n name: \"colors\",\n type: \"group\",\n label: false,\n admin: { hideGutter: true, width: \"100%\" },\n fields: [\n {\n name: \"brand\",\n type: \"group\",\n label: false,\n admin: { hideGutter: true, width: \"100%\" },\n fields: [\n {\n name: \"themeColorsHeading\",\n type: \"ui\",\n admin: {\n components: { Field: THEME_SECTION_HEADING },\n custom: {\n title: \"Brand colors\",\n hint: \"These colors define the visual identity of the site. Adjust them freely to match the brand.\",\n },\n },\n },\n systemColorGroup(\"primary\", \"Primary\", seed.brandPrimary),\n systemColorGroup(\"secondary\", \"Secondary\", seed.brandSecondary),\n systemColorGroup(\"accent\", \"Accent\", seed.brandAccent),\n systemColorGroup(\"highlight\", \"Highlight\", seed.brandHighlight),\n {\n name: \"libraryPlacement\",\n type: \"ui\",\n admin: {\n components: { Field: THEME_LIBRARY_FIELD },\n custom: { dataPath: \"colors.library\" },\n },\n },\n {\n name: \"greyPlacement\",\n type: \"ui\",\n admin: {\n components: { Field: THEME_GREY_SCALE_FIELD },\n custom: { dataPath: \"colors.greyScale\" },\n },\n },\n {\n name: \"statusColorsHeading\",\n type: \"ui\",\n admin: {\n components: { Field: THEME_SECTION_HEADING },\n custom: {\n title: \"Status colors\",\n hint: \"These colors communicate meaning across the site. You can adjust them to fit your brand, but we'll help keep them recognizable as success and error states.\",\n },\n },\n },\n systemColorGroup(\"success\", \"Success\", seed.brandSuccess || LIBRARY_SUCCESS_HEX),\n systemColorGroup(\"destructive\", \"Destructive\", destructive),\n ],\n },\n {\n ...namedSelect(\"greyScale\", \"Gray family\", presetHints.greyScale, seed.greyScale, THEME_GREY_SCALE_FIELD),\n admin: { hidden: true, components: { Field: THEME_GREY_SCALE_FIELD } },\n },\n {\n name: \"library\",\n type: \"array\",\n label: \"Additional colors\",\n labels: { singular: \"Color\", plural: \"Colors\" },\n fields: [\n { name: \"key\", type: \"text\", label: \"Key\", required: true, admin: { hidden: true } },\n { name: \"label\", type: \"text\", label: \"Name\", required: true, admin: { hidden: true } },\n ...colorScaleFields(),\n ],\n admin: { hidden: true, components: { Field: THEME_LIBRARY_FIELD }, width: \"100%\" },\n },\n ],\n },\n ];\n}\n\nfunction typographyFields(\n seed: CreateThemeOptions[\"seed\"],\n fonts: readonly FontEntry[],\n fontsBaseUrl: string,\n): Field[] {\n return [\n {\n name: \"typography\",\n type: \"group\",\n label: \"Typography\",\n fields: [\n fontField(\n \"heading\",\n \"Heading font\",\n headingSelectValue(seed.fontHeading),\n fonts,\n fontsBaseUrl,\n true,\n ),\n fontField(\"body\", \"Body font\", seed.fontBody, fonts, fontsBaseUrl, false),\n {\n name: \"pairing\",\n type: \"ui\",\n admin: { components: { Field: THEME_PAIRING_FIELD }, custom: { fontsBaseUrl } },\n },\n ],\n },\n ];\n}\n\nfunction appearanceFields(seed: CreateThemeOptions[\"seed\"]): Field[] {\n return [\n {\n name: \"appearance\",\n type: \"group\",\n label: \"Appearance\",\n fields: [\n namedSelect(\"defaultTheme\", \"Default theme\", APPEARANCE_CHOICES.defaultTheme, seed.defaultTheme),\n namedSelect(\"radius\", \"Corner style\", APPEARANCE_CHOICES.radius, seed.radius),\n namedSelect(\"shadow\", \"Depth\", APPEARANCE_CHOICES.shadow, seed.shadow),\n namedSelect(\"motion\", \"Motion\", APPEARANCE_CHOICES.motion, seed.motion),\n namedSelect(\"density\", \"Spacing\", APPEARANCE_CHOICES.density, seed.density),\n ],\n admin: { components: { Field: THEME_APPEARANCE_FIELD } },\n },\n ];\n}\n\nfunction identityFields(collection: string): Field[] {\n return [\n {\n name: \"logo\",\n type: \"upload\",\n relationTo: collection,\n label: \"Logo\",\n admin: {\n description: \"The full wordmark used in the header and footer.\",\n },\n },\n {\n name: \"favicon\",\n type: \"upload\",\n relationTo: collection,\n label: \"Favicon\",\n admin: {\n description: \"The small icon in the browser tab. PNG or SVG.\",\n },\n },\n {\n name: \"logoMark\",\n type: \"upload\",\n relationTo: collection,\n label: \"Mobile menu logo\",\n admin: {\n description:\n \"Optional. Used when the full logo is too wide for the mobile menu — typically the mark.\",\n },\n },\n ];\n}\n\n/**\n * One Theme Global. Colors, Typography, Appearance, and Identity are\n * tabs on that document. Save writes the whole form — Payload hydrates\n * every tab from the live row, so an untouched tab does not revert.\n * Locking is off. No draft mode, no preview pane.\n */\nexport function createTheme(options: CreateThemeOptions): GlobalConfig[] {\n const access = requireAccess(options);\n const destructive = requireDestructive(options);\n const {\n seed,\n fonts = catalog,\n fontsBaseUrl = \"/fonts\",\n contrastTarget = READABILITY_TARGET,\n logo,\n identity,\n onPublish,\n colorUsages,\n } = options;\n\n const adminCustom = { contrastTarget, fontsBaseUrl, identityFallback: identity?.fallback };\n const colorFields = colorsFields(seed, destructive);\n const typeFields = typographyFields(seed, fonts, fontsBaseUrl);\n const lookFields = appearanceFields(seed);\n const markFields = logo ? identityFields(logo.collection) : [];\n\n return [\n {\n slug: THEME_SLUG,\n label: \"Theme\",\n lockDocuments: false,\n admin: {\n group: \"Theme\",\n hidden: hideUnlessFeature(\"theme\") as (args: { user: unknown }) => boolean,\n hideAPIURL: true,\n custom: adminCustom,\n components: {\n elements: { beforeDocumentControls: [THEME_DOCUMENT_CONTROLS] },\n },\n },\n access: {\n read: access.read,\n update: access.update,\n },\n fields: [\n {\n type: \"tabs\",\n tabs: [\n { label: \"Colors\", fields: colorFields },\n { label: \"Typography\", fields: typeFields },\n { label: \"Appearance\", fields: lookFields },\n ...(logo ? [{ label: \"Identity\" as const, fields: markFields }] : []),\n ],\n },\n ],\n endpoints: colorUsageEndpoints(access, colorUsages),\n hooks: {\n afterChange: [\n async ({ doc }) => {\n if (!onPublish) return;\n const themeDoc = doc as ThemeDoc;\n await onPublish(themeConfigFromDoc(themeDoc, seed), themeDoc);\n },\n ],\n },\n },\n ];\n}\n","const DANGEROUS_TAGS = [\"script\", \"foreignObject\", \"iframe\", \"embed\", \"object\"] as const;\n\n/**\n * Strips the SVG features a lockup does not need and an attacker would\n * use: script, foreignObject, iframe/embed/object, event handlers,\n * javascript: / data:text/html URLs, and xml-stylesheet. Internal `#`\n * refs and ordinary drawing elements stay.\n */\nexport function sanitizeSvg(source: string): string {\n if (!/<svg[\\s>]/i.test(source)) {\n throw new Error(\"Not an SVG\");\n }\n\n let out = source.replace(/<\\?xml-stylesheet[\\s\\S]*?\\?>/gi, \"\");\n\n for (const tag of DANGEROUS_TAGS) {\n out = out.replace(new RegExp(`<${tag}\\\\b[^>]*>[\\\\s\\\\S]*?<\\\\/${tag}\\\\s*>`, \"gi\"), \"\");\n out = out.replace(new RegExp(`<${tag}\\\\b[^>]*\\\\/>`, \"gi\"), \"\");\n }\n\n out = out.replace(/\\s+on[a-z][a-z0-9-]*\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s>]+)/gi, \"\");\n out = out.replace(\n /((?:href|src|xlink:href)\\s*=\\s*)([\"'])\\s*(?:javascript:|data:text\\/html)[^\"']*\\2/gi,\n \"$1$2$2\",\n );\n\n return out;\n}\n\nexport function isSvgUpload(file: { mimetype?: string; name?: string; data?: Buffer }): boolean {\n if (file.mimetype === \"image/svg+xml\") return true;\n if (typeof file.name === \"string\" && file.name.toLowerCase().endsWith(\".svg\")) return true;\n return false;\n}\n","import type { Access, CollectionConfig } from \"payload\";\n\nimport { hideUnlessFeature } from \"../features/access\";\nimport { isSvgUpload, sanitizeSvg } from \"./sanitize\";\n\nexport const BRAND_ASSETS_SLUG = \"brand-assets\";\n\n/** SVG preferred; PNG allowed. ICO is for the favicon slot. */\nexport const BRAND_ASSETS_MIME_TYPES = [\n \"image/svg+xml\",\n \"image/png\",\n \"image/x-icon\",\n \"image/vnd.microsoft.icon\",\n] as const;\n\nexport interface CreateBrandAssetsOptions {\n /**\n * Required, no default — same shape as `createTheme`. `read` is typically\n * public so the live site can load the lockup; `update` is `canManageBrand`\n * and covers create, update, delete, and version history. This collection\n * does not read the Roles Global.\n */\n access: { read: Access; update: Access };\n /** Default `brand-assets`. Pass the same slug to `createTheme({ logo })`. */\n slug?: string;\n}\n\nfunction requireAccess(options: CreateBrandAssetsOptions): CreateBrandAssetsOptions[\"access\"] {\n const read = options.access?.read;\n const update = options.access?.update;\n if (!read || !update) {\n throw new Error(\n \"createBrandAssets requires access.read and access.update. Pass canManageBrand from this package as update.\",\n );\n }\n return { read, update };\n}\n\n/**\n * Locked cupboard for lockup and mark. Not ordinary Media — only a brand\n * manager writes it. Theme's `logo` / `logoMark` point here when the site\n * passes this slug as `logo.collection`.\n */\nexport function createBrandAssets(options: CreateBrandAssetsOptions): CollectionConfig {\n const access = requireAccess(options);\n const slug = options.slug ?? BRAND_ASSETS_SLUG;\n\n return {\n slug,\n labels: { singular: \"Brand asset\", plural: \"Brand assets\" },\n admin: {\n group: \"Settings\",\n useAsTitle: \"label\",\n hidden: hideUnlessFeature(\"brand-assets\") as (args: { user: unknown }) => boolean,\n description: \"Logo, favicon, and mobile-menu mark. SVG preferred; PNG and ICO allowed.\",\n },\n upload: {\n mimeTypes: [...BRAND_ASSETS_MIME_TYPES],\n crop: false,\n focalPoint: false,\n },\n versions: true,\n access: {\n read: access.read,\n create: access.update,\n update: access.update,\n delete: access.update,\n readVersions: access.update,\n },\n fields: [\n { name: \"label\", type: \"text\", label: \"Label\" },\n { name: \"notes\", type: \"textarea\", label: \"Usage notes\" },\n { name: \"alt\", type: \"text\", label: \"Alt text\", required: true },\n ],\n hooks: {\n beforeOperation: [\n ({ req, operation }) => {\n if (operation !== \"create\" && operation !== \"update\") return;\n const file = req.file;\n if (!file || !isSvgUpload(file)) return;\n file.data = Buffer.from(sanitizeSvg(file.data.toString(\"utf8\")), \"utf8\");\n },\n ],\n },\n };\n}\n","import type { ThemeConfig } from \"@bison-lab/tokens\";\n\nimport { docFromConfig } from \"./map\";\nimport { THEME_SLUG } from \"./types\";\nimport type { ThemeDoc } from \"./types\";\n\nexport interface SeedThemePayload {\n updateGlobal: (args: {\n slug: string;\n data: ThemeDoc;\n draft?: boolean;\n }) => Promise<unknown>;\n}\n\n/**\n * Writes a published Theme from the seed. For a site's migration `up()`,\n * so the row exists on deploy and renders what `bison-theme.css` rendered.\n */\nexport async function seedTheme(payload: SeedThemePayload, seed: ThemeConfig): Promise<unknown> {\n return payload.updateGlobal({\n slug: THEME_SLUG,\n data: docFromConfig(seed),\n draft: false,\n });\n}\n","/**\n * Device sizes the Theme (and, later, Pages) live-preview toolbar offers.\n * One list so the panes match.\n */\nexport const THEME_PREVIEW_BREAKPOINTS = [\n { label: \"Mobile\", name: \"mobile\", width: 375, height: 667 },\n { label: \"Tablet\", name: \"tablet\", width: 768, height: 1024 },\n { label: \"Desktop\", name: \"desktop\", width: 1440, height: 900 },\n] as const;\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","/**\n * Import-map keys and helpers for the shared document header.\n * `documentTitleActions()` injects one admin provider so every\n * document shares the title-row lift. One-list Globals pass\n * `documentCreateNew` so Create New sits in that same slot.\n */\n\nexport const DOCUMENT_TITLE_ACTIONS = \"@bison-lab/payload-core/admin#DocumentTitleActions\";\nexport const DOCUMENT_CREATE_NEW = \"@bison-lab/payload-core/admin#DocumentCreateNew\";\n\nexport function documentCreateNew(path: string) {\n return { path: DOCUMENT_CREATE_NEW, clientProps: { path } };\n}\n","export const ROLES_MATRIX_FIELD = \"@bison-lab/payload-core/admin#RolesMatrixField\";\nexport const ROLES_ROW_LABEL = \"@bison-lab/payload-core/admin#RolesRowLabel\";\nexport const ROLE_SLUG_FIELD = \"@bison-lab/payload-core/admin#RoleSlugField\";\nexport const ROLE_NAME_FIELD = \"@bison-lab/payload-core/admin#RoleNameField\";\nexport const ROLES_FIELD = \"@bison-lab/payload-core/admin#RolesField\";\nexport const ROLES_GRANTS_FIELD = \"@bison-lab/payload-core/admin#RolesGrantsField\";\n","import type { ArrayField, GlobalConfig, TextFieldSingleValidation } from \"payload\";\n\nimport { documentCreateNew } from \"../admin/document-controls\";\nimport { canUseFeature, hideUnlessFeature } from \"../features/access\";\nimport { isAdmin } from \"./access\";\nimport { ROLE_NAME_FIELD, ROLES_GRANTS_FIELD, ROLES_MATRIX_FIELD, ROLES_ROW_LABEL } from \"./fields\";\nimport {\n applyRoleSlugsFromNames,\n defaultRolesFieldValue,\n DUPLICATE_ROLE_SLUG_MESSAGE,\n INVALID_ROLE_NAME_MESSAGE,\n ROLES_FIELD_DESCRIPTION,\n ROLES_GLOBAL_DESCRIPTION,\n ROLES_SLUG,\n validateRolesMatrix,\n} from \"./matrix\";\nimport { isRoleName, isRoleSlug, type RoleExtra } from \"./types\";\n\nexport interface CreateRolesOptions {\n /**\n * Extra catalogue rows after the first-run defaults. Each is a slug, a\n * display label, and default grants. A site that passes nothing still\n * gets Developer / Admin / Designer / Author; an Admin may later remove\n * every row except Developer.\n */\n extras?: readonly RoleExtra[];\n}\n\nconst roleSlugValidate: TextFieldSingleValidation = (value) => {\n // Empty is fine while Create New is in progress; the name fills it on save.\n if (typeof value !== \"string\" || value === \"\") return true;\n return isRoleSlug(value) || DUPLICATE_ROLE_SLUG_MESSAGE;\n};\n\nconst roleNameValidate: TextFieldSingleValidation = (value) => {\n if (typeof value !== \"string\" || value.trim() === \"\") return true;\n return isRoleName(value) || INVALID_ROLE_NAME_MESSAGE;\n};\n\n/**\n * Settings → Roles. Rank is the array order (Payload's drag handle).\n * Ticks are released catalogue rows. Developer is implicit and shown\n * only to a Developer, with every catalogue tick locked on.\n */\nexport function createRoles({ extras = [] }: CreateRolesOptions = {}): GlobalConfig {\n const rolesField: ArrayField = {\n name: \"roles\",\n type: \"array\",\n label: \"Roles\",\n labels: { singular: \"Role\", plural: \"Roles\" },\n minRows: 1,\n required: true,\n defaultValue: defaultRolesFieldValue(extras),\n validate: validateRolesMatrix,\n hooks: {\n beforeChange: [({ value }) => applyRoleSlugsFromNames(value)],\n },\n admin: {\n components: { Field: ROLES_MATRIX_FIELD, RowLabel: ROLES_ROW_LABEL },\n description: ROLES_FIELD_DESCRIPTION,\n initCollapsed: false,\n },\n fields: [\n {\n name: \"role\",\n type: \"text\",\n label: \"Slug\",\n validate: roleSlugValidate,\n admin: { hidden: true },\n },\n {\n name: \"label\",\n type: \"text\",\n label: \"Name\",\n required: true,\n validate: roleNameValidate,\n admin: { components: { Field: ROLE_NAME_FIELD } },\n },\n {\n name: \"grants\",\n type: \"json\",\n label: \"Grants\",\n defaultValue: [],\n admin: {\n components: { Field: ROLES_GRANTS_FIELD },\n },\n },\n ],\n };\n\n return {\n slug: ROLES_SLUG,\n label: \"Roles\",\n admin: {\n group: \"Settings\",\n hidden: hideUnlessFeature(\"roles\") as (args: { user: unknown }) => boolean,\n description: ROLES_GLOBAL_DESCRIPTION,\n components: {\n elements: {\n beforeDocumentControls: [documentCreateNew(\"roles\")],\n },\n },\n },\n access: {\n read: (args) => canUseFeature(\"roles\")(args),\n update: (args) => isAdmin(args),\n },\n fields: [rolesField],\n };\n}\n","import { defaultRolesFieldValue, ROLES_SLUG } from \"./matrix\";\nimport type { RoleExtra, RolesDoc } from \"./types\";\n\nexport interface SeedRolesPayload {\n updateGlobal: (args: { slug: string; data: RolesDoc }) => Promise<unknown>;\n}\n\n/**\n * Writes the default matrix (Developer, Admin, Designer, Author plus any\n * site extras). For a site's migration `up()`. Never writes a user row —\n * seeding `developer` on a person stays a site concern.\n */\nexport async function seedRoles(\n payload: SeedRolesPayload,\n extras: readonly RoleExtra[] = [],\n): Promise<unknown> {\n return payload.updateGlobal({\n slug: ROLES_SLUG,\n data: { roles: defaultRolesFieldValue(extras) },\n });\n}\n","export const FEATURES_MATRIX_FIELD = \"@bison-lab/payload-core/admin#FeaturesMatrixField\";\n","import type { ArrayField, GlobalConfig } from \"payload\";\n\nimport { developerOnlyAccess, hideUnlessDeveloper } from \"../roles/access\";\nimport { FEATURES_MATRIX_FIELD } from \"./fields\";\nimport { defaultFeaturesFieldValue, featureCatalogue, stampFeatureCatalogue, validateFeaturesMatrix } from \"./matrix\";\nimport { FEATURES_SLUG, type FeatureExtra } from \"./types\";\n\nexport interface CreateFeaturesOptions {\n /**\n * Site-only rows after the package catalogue. A second `createFeatures()`\n * without these extras never includes them.\n */\n extras?: readonly FeatureExtra[];\n}\n\n/**\n * Settings → Features. One release switch per catalogue row. Off hides\n * the tick on Roles; Developer still has the feature. This screen is\n * not itself a row.\n */\nexport function createFeatures({ extras = [] }: CreateFeaturesOptions = {}): GlobalConfig {\n const catalogue = featureCatalogue(extras);\n const featuresField: ArrayField = {\n name: \"features\",\n type: \"array\",\n label: \"Features\",\n labels: { singular: \"Feature\", plural: \"Features\" },\n minRows: catalogue.length,\n maxRows: catalogue.length,\n required: true,\n defaultValue: defaultFeaturesFieldValue(extras),\n validate: (value) => validateFeaturesMatrix(value, extras),\n hooks: {\n beforeChange: [\n ({ value }) => {\n if (!Array.isArray(value)) return value;\n return stampFeatureCatalogue(value, extras);\n },\n ],\n },\n admin: {\n components: { Field: FEATURES_MATRIX_FIELD },\n description:\n \"Release a feature so it can be assigned on Roles. Off keeps it Developer-only.\",\n initCollapsed: false,\n },\n fields: [\n { name: \"slug\", type: \"text\", label: \"Slug\", required: true, admin: { readOnly: true } },\n { name: \"label\", type: \"text\", label: \"Name\", required: true, admin: { readOnly: true } },\n { name: \"group\", type: \"text\", label: \"Group\", admin: { hidden: true } },\n { name: \"released\", type: \"checkbox\", label: \"Released\", admin: { hidden: true } },\n ],\n };\n\n return {\n slug: FEATURES_SLUG,\n label: \"Features\",\n admin: {\n group: \"Settings\",\n hidden: hideUnlessDeveloper,\n description: \"Which features other people may be granted on Roles.\",\n },\n access: developerOnlyAccess(),\n fields: [featuresField],\n };\n}\n","import { defaultFeaturesFieldValue } from \"./matrix\";\nimport { FEATURES_SLUG, type FeatureExtra, type FeaturesDoc } from \"./types\";\n\nexport interface SeedFeaturesPayload {\n updateGlobal: (args: { slug: string; data: FeaturesDoc }) => Promise<unknown>;\n}\n\n/**\n * Writes the default switchboard (package rows plus any site extras).\n * For a site's migration `up()`.\n */\nexport async function seedFeatures(\n payload: SeedFeaturesPayload,\n extras: readonly FeatureExtra[] = [],\n): Promise<unknown> {\n return payload.updateGlobal({\n slug: FEATURES_SLUG,\n data: { features: defaultFeaturesFieldValue(extras) },\n });\n}\n","import type {\n CollectionSlug,\n PayloadRequest,\n TextField,\n TextFieldSingleValidation,\n Where,\n} from \"payload\";\nimport { ValidationError, validations } from \"payload\";\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\n/**\n * A stored slug from whatever was typed: lowercased, with any run of\n * whitespace and slashes stripped from either end in one pass, so `/ about-us /`\n * does not keep the inner spaces a trim-then-strip would leave.\n */\nexport function normalizeSlug(value: string): string {\n return value.replace(/^[\\s/]+|[\\s/]+$/g, \"\").toLowerCase();\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\n/**\n * The path a document is published at, normalised on the way in. Unique\n * across the collection. `validate` is the message under the field;\n * `beforeChange` is the enforcement on a draft save, where Payload skips\n * field validation.\n */\nexport function slugField({ collection, isReserved }: SlugFieldOptions): TextField {\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 return {\n name: \"slug\",\n type: \"text\",\n required: true,\n unique: true,\n admin: {\n description: 'Path under the site root, no leading slash: \"about-us\" or \"patients/stories\".',\n },\n hooks: {\n beforeValidate: [({ value }) => (typeof value === \"string\" ? normalizeSlug(value) : value)],\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","import type { Access, Block, CollectionConfig } from \"payload\";\n\nimport { canUseFeature, hideUnlessFeature } from \"../features/access\";\nimport { authenticatedOrPublished, canPublish, isAdmin, isAuthenticated } from \"../roles/access\";\nimport { slugField } from \"../fields/slug\";\n\n/**\n * Content to create or save a draft; Publish to publish or edit a live\n * page. Without Publish, update is constrained to `_status: draft`.\n */\nconst pagesUpdate: Access = async (args) => {\n const canEdit = await Promise.resolve(canUseFeature(\"content\")(args));\n if (!canEdit) return false;\n if (await Promise.resolve(canPublish(args))) return true;\n return { _status: { equals: \"draft\" } };\n};\n\nexport interface PagesOptions {\n /**\n * What a page may open with. One row, so this is the site's hero variants,\n * not a list a page picks several from.\n */\n heroBlocks: Block[];\n /** The sections a page body can be built out of. */\n layoutBlocks: Block[];\n /**\n * True when a slug is not the CMS's to hand out — a path the app already\n * serves from code, or one the framework reserves.\n */\n isReservedSlug: (slug: string) => boolean;\n /**\n * Public path of a page from its stored slug — the site's own route helper.\n * Drives the page preview overlay's iframe.\n */\n previewPath: (slug: string) => string;\n /**\n * Component path for Payload's native Preview button, as a key into the\n * site's committed `importMap.js`. Omit it for Payload's own button.\n */\n previewButton?: string;\n}\n\n/**\n * CMS-managed pages: one required hero, then a reorderable body of sections.\n * The CMS owns copy and the order of sections; what a section looks like is\n * code-owned, which is why the blocks are an argument.\n */\nexport function createPages({\n heroBlocks,\n isReservedSlug,\n layoutBlocks,\n previewPath,\n previewButton,\n}: PagesOptions): CollectionConfig {\n const [defaultHero] = heroBlocks;\n if (!defaultHero) throw new Error(\"createPages needs at least one hero block\");\n\n return {\n slug: \"pages\",\n admin: {\n useAsTitle: \"title\",\n group: \"Content\",\n defaultColumns: [\"title\", \"slug\", \"_status\", \"updatedAt\"],\n hidden: hideUnlessFeature(\"content\") as (args: { user: unknown }) => boolean,\n preview: (doc) => previewPath(typeof doc.slug === \"string\" ? doc.slug : \"\"),\n ...(previewButton ? { components: { edit: { PreviewButton: previewButton } } } : {}),\n },\n access: {\n read: authenticatedOrPublished,\n readVersions: isAuthenticated,\n create: canUseFeature(\"content\"),\n update: pagesUpdate,\n delete: isAdmin,\n },\n versions: {\n drafts: { autosave: { interval: 375 } },\n maxPerDoc: 50,\n },\n fields: [\n { name: \"title\", type: \"text\", required: true },\n slugField({ collection: \"pages\", isReserved: isReservedSlug }),\n {\n name: \"hero\",\n type: \"blocks\",\n required: true,\n minRows: 1,\n maxRows: 1,\n blocks: heroBlocks,\n defaultValue: [{ blockType: defaultHero.slug }],\n admin: {\n description: \"Every page opens with one hero. A page cannot be published without one.\",\n },\n },\n {\n name: \"layout\",\n type: \"blocks\",\n required: true,\n minRows: 1,\n blocks: layoutBlocks,\n labels: { singular: \"Section\", plural: \"Sections\" },\n },\n ],\n };\n}\n","import type {\n CollectionConfig,\n PayloadRequest,\n SelectFieldManyValidation,\n TextField,\n TextFieldSingleValidation,\n Where,\n} from \"payload\";\nimport { APIError } from \"payload\";\nimport { select, text } from \"payload/shared\";\n\nimport { allowedFeaturesForUser, canUseFeature, hideUnlessFeature } from \"../features/access\";\nimport { getRolesMatrix, isAdmin, isAdminOrSelf, isPrivilegedRole } from \"../roles/access\";\nimport { ROLES_FIELD } from \"../roles/fields\";\nimport { normalizeStoredRoles, roleSelectOptions, seedRoleRows } from \"../roles/matrix\";\nimport type { RoleExtra, RoleRow } from \"../roles/types\";\n\nconst nameValidate: TextFieldSingleValidation = (value, options) => {\n if (options.operation === \"update\" && value === \"\" && options.previousValue === \"\") return true;\n return text(value, options);\n};\n\nfunction nameField(name: \"firstName\" | \"lastName\"): TextField {\n return { name, type: \"text\", required: true, validate: nameValidate };\n}\n\n/** Refuses the save that would remove Users from the only privileged user. */\nexport const LAST_ADMIN_DEMOTE_MESSAGE = \"Make another user an admin before removing it from this one.\";\n/** Refuses the delete that would remove the only privileged user. */\nexport const LAST_ADMIN_DELETE_MESSAGE = \"Make another user an admin before deleting this one.\";\n\ninterface TransactionalAdapter {\n execute?: (args: { db?: unknown; raw?: string }) => Promise<unknown>;\n sessions?: Record<string, { db: unknown } | undefined>;\n}\n\nconst LAST_ADMIN_LOCK = \"select pg_advisory_xact_lock(hashtext('users:last-admin'))\";\n\nasync function lockLastAdminDecision(req: PayloadRequest): Promise<void> {\n const { execute, sessions } = req.payload.db as unknown as TransactionalAdapter;\n const id = req.transactionID;\n const session = typeof id === \"string\" || typeof id === \"number\" ? sessions?.[id] : undefined;\n if (!session || typeof execute !== \"function\") return;\n await execute({ db: session.db, raw: LAST_ADMIN_LOCK });\n}\n\nfunction privilegedRoles(matrix: readonly RoleRow[]): string[] {\n return matrix.filter((row) => isPrivilegedRole(row.role, matrix)).map((row) => row.role);\n}\n\nfunction holdsPrivilegedRole(roles: unknown, matrix: readonly RoleRow[]): boolean {\n return Array.isArray(roles) && roles.some((role) => isPrivilegedRole(role, matrix));\n}\n\nfunction privilegedWhere(matrix: readonly RoleRow[]): Where {\n const roles = privilegedRoles(matrix);\n if (roles.length === 0) return { id: { equals: \"__none__\" } };\n return { or: roles.map((role) => ({ roles: { contains: role } })) };\n}\n\nasync function adminCount(req: PayloadRequest, excluding?: number | string): Promise<number> {\n await lockLastAdminDecision(req);\n const matrix = await getRolesMatrix(req);\n const holdsPrivileged = privilegedWhere(matrix);\n const { totalDocs } = await req.payload.count({\n collection: \"users\",\n overrideAccess: true,\n req,\n where:\n excluding === undefined\n ? holdsPrivileged\n : { and: [holdsPrivileged, { id: { not_equals: excluding } }] },\n });\n return totalDocs;\n}\n\nfunction rolesValidate(extras: readonly RoleExtra[]): SelectFieldManyValidation {\n return async (value, options) => {\n const matrix = await getRolesMatrix(options.req, extras);\n const builtIn = select(value, { ...options, options: roleSelectOptions(matrix) });\n if (builtIn !== true) return builtIn;\n if (options.operation !== \"update\" || options.id === undefined) return true;\n if (holdsPrivilegedRole(value, matrix) || !holdsPrivilegedRole(options.previousValue, matrix)) {\n return true;\n }\n return (await adminCount(options.req, options.id)) > 0 ? true : LAST_ADMIN_DEMOTE_MESSAGE;\n };\n}\n\nexport interface UsersOptions {\n /**\n * Whether the auth cookie is marked Secure. Passed in rather than read from\n * the environment here: which env var means \"served over HTTPS\" is the\n * host's business, not the CMS's.\n */\n secureCookies: boolean;\n /**\n * Component path for the roles field, as a key into the site's committed\n * `importMap.js`. Defaults to the package checklist. A value nothing\n * resolves renders the field as nothing.\n */\n rolesField?: string;\n /**\n * Same extras passed to `createRoles`. Offered on Users when the Global\n * is empty; a saved Global (including Admin-added rows) wins.\n */\n extras?: readonly RoleExtra[];\n}\n\nexport function createUsers({ secureCookies, rolesField, extras = [] }: UsersOptions): CollectionConfig {\n const fallback = seedRoleRows(extras);\n return {\n slug: \"users\",\n auth: {\n maxLoginAttempts: 5,\n lockTime: 10 * 60 * 1000,\n tokenExpiration: 2 * 60 * 60,\n cookies: {\n sameSite: \"Lax\",\n secure: secureCookies,\n },\n },\n admin: {\n group: \"Settings\",\n useAsTitle: \"email\",\n defaultColumns: [\"email\", \"firstName\", \"lastName\", \"roles\"],\n hidden: hideUnlessFeature(\"users\") as (args: { user: unknown }) => boolean,\n },\n access: {\n create: isAdmin,\n delete: isAdmin,\n unlock: isAdmin,\n read: async (args) => {\n if (await Promise.resolve(canUseFeature(\"users\")(args))) return true;\n return isAdminOrSelf(args);\n },\n update: isAdminOrSelf,\n },\n hooks: {\n beforeDelete: [\n async ({ id, req }) => {\n const doomed = await req.payload.findByID({\n collection: \"users\",\n id,\n depth: 0,\n disableErrors: true,\n overrideAccess: true,\n req,\n });\n const matrix = await getRolesMatrix(req, extras);\n if (!isAdmin(doomed, matrix) || (await adminCount(req, id)) > 0) return;\n throw new APIError(LAST_ADMIN_DELETE_MESSAGE, 400);\n },\n ],\n afterOperation: [\n async (arg) => {\n const { operation, req } = arg;\n const touchesRoles =\n (operation === \"update\" || operation === \"updateByID\") &&\n arg.args.data?.roles !== undefined;\n const deletes = operation === \"delete\" || operation === \"deleteByID\";\n if ((touchesRoles || deletes) && (await adminCount(req)) === 0) {\n throw new APIError(deletes ? LAST_ADMIN_DELETE_MESSAGE : LAST_ADMIN_DEMOTE_MESSAGE, 400);\n }\n return arg.result;\n },\n ],\n },\n fields: [\n {\n type: \"row\",\n fields: [nameField(\"firstName\"), nameField(\"lastName\")],\n },\n {\n name: \"roles\",\n type: \"select\",\n hasMany: true,\n required: true,\n saveToJWT: true,\n // Seed plus site extras. filterOptions replaces this with the saved\n // Global (labels and Admin-added slugs) when that row is readable.\n options: roleSelectOptions(fallback),\n admin: {\n components: { Field: rolesField ?? ROLES_FIELD },\n description: \"One person can hold several, e.g. Author + Designer.\",\n },\n access: {\n update: isAdmin,\n },\n validate: rolesValidate(extras),\n hooks: {\n beforeValidate: [\n async ({ value, req }) => {\n if (!Array.isArray(value)) return value;\n return normalizeStoredRoles(value, await getRolesMatrix(req, extras));\n },\n ],\n },\n },\n {\n name: \"allowedFeatures\",\n type: \"json\",\n admin: { hidden: true, readOnly: true },\n access: { update: () => false },\n saveToJWT: true,\n hooks: {\n afterRead: [\n async ({ siblingData, data, req }) =>\n allowedFeaturesForUser(\n {\n id: (siblingData?.id ?? data?.id) as string | number | undefined,\n roles: (siblingData?.roles ?? data?.roles) as readonly string[] | undefined,\n },\n req ?? {},\n ),\n ],\n },\n },\n ],\n };\n}\n","import type { CollectionConfig, ImageSize } from \"payload\";\n\nimport { canUseFeature, hideUnlessFeature } from \"../features/access\";\nimport { isAdmin } from \"../roles/access\";\n\nexport interface MediaOptions {\n /** Where uploads land, relative to the app root. */\n staticDir?: string;\n mimeTypes?: string[];\n /**\n * Renditions sharp cuts on upload, each served at its own URL under\n * `sizes.<name>` on the document. Which sizes a site needs is the site's\n * call. A file uploaded before a size was added has no rendition for it.\n */\n imageSizes?: ImageSize[];\n}\n\n/**\n * Uploads, readable by anyone: the public site serves these files. Writing is\n * an editorial action, deleting is not — removing an asset a live page\n * references breaks that page.\n */\nexport function createMedia({\n staticDir = \"media\",\n mimeTypes = [\"image/*\"],\n imageSizes,\n}: MediaOptions = {}): CollectionConfig {\n return {\n slug: \"media\",\n admin: {\n hidden: hideUnlessFeature(\"media\") as (args: { user: unknown }) => boolean,\n },\n access: {\n read: () => true,\n create: canUseFeature(\"media\"),\n update: canUseFeature(\"media\"),\n delete: isAdmin,\n },\n upload: { staticDir, mimeTypes, imageSizes },\n fields: [\n {\n name: \"alt\",\n type: \"text\",\n required: true,\n },\n ],\n };\n}\n","export const ADMIN_NAV = \"@bison-lab/payload-core/admin#AdminNav\";\nexport const ADMIN_NAV_ROW_LABEL = \"@bison-lab/payload-core/admin#AdminNavRowLabel\";\nexport const ADMIN_NAV_ENTITY_FIELD = \"@bison-lab/payload-core/admin#AdminNavEntityField\";\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 { TextFieldSingleValidation } from \"payload\";\n\nconst UNKNOWN_ENTITY_MESSAGE = \"Not in this site's config.\";\n\n/**\n * A Developer cannot invent a collection or global that is not registered.\n */\nexport const validateAdminNavSlug: TextFieldSingleValidation = (value, { req, siblingData }) => {\n if (typeof value !== \"string\" || value === \"\") return true;\n const type = siblingData && typeof siblingData === \"object\" && \"type\" in siblingData ? siblingData.type : null;\n const list =\n type === \"global\" ? req.payload?.config?.globals : type === \"collection\" ? req.payload?.config?.collections : [];\n const slugs = (list ?? []).map((entity) => entity.slug);\n return slugs.includes(value) || UNKNOWN_ENTITY_MESSAGE;\n};\n","import type { ArrayField, GlobalConfig } from \"payload\";\n\nimport { hideUnlessDeveloper, isAuthenticated, isDeveloper, type MaybeUser } from \"../roles/access\";\nimport { ADMIN_NAV_ENTITY_FIELD, ADMIN_NAV_ROW_LABEL } from \"./fields\";\nimport { ADMIN_NAV_SLUG } from \"./types\";\nimport { validateAdminNavSlug } from \"./validate\";\n\nconst groupsField: ArrayField = {\n name: \"groups\",\n type: \"array\",\n label: \"Groups\",\n labels: { singular: \"Group\", plural: \"Groups\" },\n admin: {\n components: { RowLabel: ADMIN_NAV_ROW_LABEL },\n description: \"Sidebar headers and the collections or globals under each. Drag to reorder. An empty header still shows.\",\n initCollapsed: false,\n },\n fields: [\n {\n name: \"label\",\n type: \"text\",\n label: \"Header\",\n },\n {\n name: \"items\",\n type: \"array\",\n label: \"Items\",\n labels: { singular: \"Item\", plural: \"Items\" },\n fields: [\n {\n name: \"type\",\n type: \"select\",\n label: \"Type\",\n required: true,\n defaultValue: \"collection\",\n options: [\n { label: \"Collection\", value: \"collection\" },\n { label: \"Global\", value: \"global\" },\n ],\n },\n {\n name: \"slug\",\n type: \"text\",\n label: \"Slug\",\n required: true,\n validate: validateAdminNavSlug,\n admin: { components: { Field: ADMIN_NAV_ENTITY_FIELD } },\n },\n ],\n },\n ],\n};\n\n/**\n * Settings → Admin nav. Developer chrome, not a Features row. Save writes\n * immediately. The package Nav reads this document; an empty row falls\n * back to Payload's first-seen walk.\n */\nexport function createAdminNav(): GlobalConfig {\n return {\n slug: ADMIN_NAV_SLUG,\n label: \"Admin nav\",\n admin: {\n group: \"Settings\",\n hidden: hideUnlessDeveloper,\n description: \"Sidebar group headers and order. A site that never opens this screen looks the way Payload ordered it.\",\n },\n access: {\n read: isAuthenticated,\n update: ({ req }) => isDeveloper(req.user as MaybeUser),\n },\n fields: [groupsField],\n };\n}\n","import type { Config } from \"payload\";\nimport { definePlugin } from \"payload\";\n\nimport { ADMIN_NAV } from \"./fields\";\n\n/**\n * Sets `admin.components.Nav` to the package Nav. A consuming site must\n * not write its own Nav — SPI-10 is the later skin, and it reads\n * `resolveAdminNav` rather than a second layout source.\n */\nexport const adminNav = definePlugin({\n slug: \"admin-nav\",\n order: 1000,\n plugin: ({ config }): Config => ({\n ...config,\n admin: {\n ...config.admin,\n components: {\n ...config.admin?.components,\n Nav: ADMIN_NAV,\n },\n },\n }),\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 const groups: AdminNavGroup[] = (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 const seen = new Set(groups.flatMap((group) => group.items.map((item) => keyOf(item.type, item.slug))));\n for (const entity of entities) {\n if (entity.group === false) continue;\n const key = keyOf(entity.type, entity.slug);\n if (seen.has(key)) 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 seen.add(key);\n }\n return groups;\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 type { Condition, Field, GroupField, RowField } from \"payload\";\n\n/**\n * Same import-map string as `@bison-lab/payload-blocks`. A site that\n * already generates the blocks admin map gets the picker; a missing\n * entry renders the row as nothing, so `payload generate:importmap` is\n * part of adopting this factory.\n */\nconst LINK_FIELD = \"@bison-lab/payload-blocks/admin#LinkField\";\n\ntype LinkType = \"page\" | \"external\";\n\ninterface LinkDestination {\n type?: LinkType | null;\n href?: string | null;\n}\n\nfunction linkTypeOf(link: LinkDestination | null | undefined): LinkType {\n if (link?.type === \"external\") return \"external\";\n if (link?.type === \"page\") return \"page\";\n return link?.href ? \"external\" : \"page\";\n}\n\nconst whenPage: Condition = (_data, siblingData) => linkTypeOf(siblingData as LinkDestination) === \"page\";\nconst whenExternal: Condition = (_data, siblingData) =>\n linkTypeOf(siblingData as LinkDestination) === \"external\";\n\nfunction linkDestinationFields({\n required = false,\n pagesCollection = \"pages\",\n}: {\n required?: boolean;\n pagesCollection?: string;\n} = {}): RowField[] {\n return [\n {\n type: \"row\",\n admin: { components: { Field: LINK_FIELD } },\n fields: [\n {\n name: \"type\",\n type: \"radio\",\n label: \"Goes to\",\n defaultValue: \"page\",\n options: [\n { label: \"Page\", value: \"page\" },\n { label: \"URL\", value: \"external\" },\n ],\n admin: { layout: \"horizontal\" },\n },\n {\n name: \"page\",\n type: \"relationship\",\n relationTo: pagesCollection,\n required,\n filterOptions: { _status: { equals: \"published\" } },\n admin: { condition: whenPage },\n },\n {\n name: \"href\",\n type: \"text\",\n label: \"URL\",\n required,\n admin: {\n condition: whenExternal,\n description:\n 'A full URL (\"https://example.com\"), \"mailto:\" or \"tel:\", or a site path (\"/contact\").',\n },\n },\n ],\n },\n ];\n}\n\nfunction linkFields({\n required = false,\n pagesCollection,\n}: {\n required?: boolean;\n pagesCollection?: string;\n} = {}): Field[] {\n return [\n ...linkDestinationFields({ required, pagesCollection }),\n { name: \"label\", type: \"text\", label: \"Label\", required },\n {\n name: \"newTab\",\n type: \"checkbox\",\n label: \"Open in a new tab\",\n defaultValue: false,\n },\n ];\n}\n\nexport function linkField({\n name = \"link\",\n label,\n admin,\n required,\n pagesCollection,\n}: {\n name?: string;\n label?: GroupField[\"label\"];\n admin?: GroupField[\"admin\"];\n required?: boolean;\n pagesCollection?: string;\n} = {}): GroupField {\n return {\n name,\n type: \"group\",\n fields: linkFields({ required, pagesCollection }),\n ...(label === undefined ? {} : { label }),\n ...(admin === undefined ? {} : { admin }),\n };\n}\n\nexport function footerLinkFields({\n required = false,\n pagesCollection,\n}: {\n required?: boolean;\n pagesCollection?: string;\n} = {}): Field[] {\n return linkFields({ required, pagesCollection });\n}\n","import { Forbidden, type GlobalBeforeChangeHook, type GlobalConfig } from \"payload\";\n\nimport { canUseFeature, hideUnlessFeature } from \"../features/access\";\nimport { canPublish, isAuthenticated } from \"../roles/access\";\nimport { footerLinkFields, linkField } from \"./link\";\nimport {\n NAVIGATION_DB_NAME,\n NAVIGATION_FEATURE,\n NAVIGATION_FOOTER_DB_NAME,\n NAVIGATION_FOOTER_SLUG,\n NAVIGATION_SLUG,\n type CreateNavigationOptions,\n} from \"./types\";\n\nconst refusePublishWithoutTick: GlobalBeforeChangeHook = async ({ data, req }) => {\n if (data._status !== \"published\") return data;\n if (!req.user) return data;\n if (await Promise.resolve(canPublish({ req } as never))) return data;\n throw new Forbidden();\n};\n\n/**\n * Header (`navigation` / `nav`) and Footer (`navigation-footer` / `navf`).\n * One Features tick (`navigation`). Independent Save / Publish / drafts —\n * a draft header does not publish the footer.\n */\nexport function createNavigation({\n blocks,\n footerColumnRowLabel,\n footerLinkRowLabel,\n preview,\n livePreview,\n previewButton,\n pagesCollection,\n}: CreateNavigationOptions): [GlobalConfig, GlobalConfig] {\n if (blocks.length === 0) {\n throw new Error(\"createNavigation needs at least one header block\");\n }\n\n const hidden = hideUnlessFeature(NAVIGATION_FEATURE);\n const update = canUseFeature(NAVIGATION_FEATURE);\n const previewAdmin = {\n ...(preview ? { preview } : {}),\n ...(livePreview ? { livePreview } : {}),\n ...(previewButton\n ? { components: { elements: { PreviewButton: previewButton } } }\n : {}),\n };\n\n const header: GlobalConfig = {\n slug: NAVIGATION_SLUG,\n dbName: NAVIGATION_DB_NAME,\n label: \"Header\",\n admin: {\n group: \"Navigation\",\n hidden: hidden as (args: { user: unknown }) => boolean,\n description: \"The public header. A draft never reaches the live site until you publish.\",\n ...previewAdmin,\n },\n access: {\n read: () => true,\n readVersions: isAuthenticated,\n update,\n },\n versions: {\n drafts: { autosave: { interval: 375 } },\n },\n hooks: {\n beforeChange: [refusePublishWithoutTick],\n },\n fields: [\n {\n name: \"header\",\n type: \"group\",\n label: false,\n fields: [\n {\n name: \"items\",\n type: \"blocks\",\n labels: { singular: \"Item\", plural: \"Items\" },\n blocks,\n admin: {\n description:\n \"Bar items, left to right. A mega menu leads with the choice a visitor has to make and keeps the other groups as named lists. A plain link is a bar item with nothing to open. Column widths in a panel must add up to 100%.\",\n },\n },\n linkField({\n name: \"cta\",\n label: \"Header button\",\n required: true,\n pagesCollection,\n admin: {\n description: \"The pill on the right of the bar.\",\n },\n }),\n ],\n },\n ],\n };\n\n const footer: GlobalConfig = {\n slug: NAVIGATION_FOOTER_SLUG,\n dbName: NAVIGATION_FOOTER_DB_NAME,\n label: \"Footer\",\n admin: {\n group: \"Navigation\",\n hidden: hidden as (args: { user: unknown }) => boolean,\n description:\n \"The public footer shortcut columns. A draft never reaches the live site until you publish.\",\n ...previewAdmin,\n },\n access: {\n read: () => true,\n readVersions: isAuthenticated,\n update,\n },\n versions: {\n drafts: { autosave: { interval: 375 } },\n },\n hooks: {\n beforeChange: [refusePublishWithoutTick],\n },\n fields: [\n {\n name: \"footer\",\n type: \"group\",\n label: false,\n fields: [\n {\n name: \"columns\",\n type: \"array\",\n dbName: \"c\",\n labels: { singular: \"Column\", plural: \"Columns\" },\n admin: {\n description:\n \"A shortcut strip, not a sitemap. One entry per heading plus the few pages worth a standing link. Everything omitted here is still reachable from the header. Adding a link back to \\\"complete\\\" a column is the wrong instinct — the omissions are the point.\",\n components: footerColumnRowLabel ? { RowLabel: footerColumnRowLabel } : undefined,\n },\n fields: [\n {\n name: \"heading\",\n type: \"text\",\n required: true,\n label: \"Heading\",\n },\n {\n name: \"links\",\n type: \"array\",\n labels: { singular: \"Link\", plural: \"Links\" },\n admin: {\n components: footerLinkRowLabel ? { RowLabel: footerLinkRowLabel } : undefined,\n },\n fields: footerLinkFields({ required: true, pagesCollection }),\n },\n ],\n },\n ],\n },\n ],\n };\n\n return [header, footer];\n}\n","import type { CollectionConfig, GlobalConfig } from \"payload\";\nimport { definePlugin } from \"payload\";\n\nimport { isDeveloperTab } from \"../roles/access\";\n\ntype Entity = CollectionConfig | GlobalConfig;\n\nfunction gateApiTab<T extends Entity>(entity: T): T {\n const components = entity.admin?.components;\n const edit = components?.views?.edit;\n const api = edit && \"api\" in edit ? edit.api : undefined;\n return {\n ...entity,\n admin: {\n ...entity.admin,\n components: {\n ...components,\n views: {\n ...components?.views,\n edit: {\n ...edit,\n api: { ...api, tab: { ...api?.tab, condition: isDeveloperTab } },\n },\n },\n },\n },\n };\n}\n\n/**\n * Gates the document API tab to Developer, config-wide. After plugins that\n * use `definePlugin` order (MCP is 10), so a collection those plugins\n * register is still covered.\n */\nexport const adminOnlyApiTab = definePlugin({\n slug: \"admin-only-api-tab\",\n order: 1000,\n plugin: ({ config }) => ({\n ...config,\n collections: config.collections?.map(gateApiTab),\n globals: config.globals?.map(gateApiTab),\n }),\n});\n","import type { Config } from \"payload\";\nimport { definePlugin } from \"payload\";\n\nimport { DOCUMENT_TITLE_ACTIONS } from \"../admin/document-controls\";\n\ntype AdminProviders = NonNullable<\n NonNullable<NonNullable<Config[\"admin\"]>[\"components\"]>[\"providers\"]\n>;\n\nfunction asList(value: AdminProviders | undefined): AdminProviders {\n if (!value) return [];\n return value;\n}\n\nfunction alreadyHasTitleActions(providers: AdminProviders): boolean {\n return providers.some((entry) => {\n if (typeof entry === \"string\") return entry === DOCUMENT_TITLE_ACTIONS;\n if (entry && typeof entry === \"object\" && \"path\" in entry) {\n return entry.path === DOCUMENT_TITLE_ACTIONS;\n }\n return false;\n });\n}\n\nfunction withTitleActions(config: Config): Config {\n const providers = asList(config.admin?.components?.providers);\n if (alreadyHasTitleActions(providers)) return config;\n return {\n ...config,\n admin: {\n ...config.admin,\n components: {\n ...config.admin?.components,\n providers: [DOCUMENT_TITLE_ACTIONS, ...providers],\n },\n },\n };\n}\n\n/**\n * Puts every document's primary actions on the title row — the same\n * slot collection lists use for Create New — and hides the dead Edit\n * tab when it has no sibling. One admin provider so Roles, Theme,\n * Features, Account, and a site's own Globals cannot drift.\n */\nexport const documentTitleActions = definePlugin({\n slug: \"document-title-actions\",\n order: 1000,\n plugin: ({ config }) => withTitleActions(config),\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["payloadSeoPlugin","isAccessArgs","requireAccess","catalog"],"sources":["../src/seo/fields.ts","../src/seo/text.ts","../src/seo/plugin.ts","../src/theme/appearance-labels.ts","../src/theme/color-usages.ts","../src/theme/color-usage-endpoints.ts","../src/features/types.ts","../src/features/matrix.ts","../src/roles/types.ts","../src/roles/matrix.ts","../src/roles/access.ts","../src/features/access.ts","../src/theme/global.ts","../src/brand-assets/sanitize.ts","../src/brand-assets/collection.ts","../src/theme/seed.ts","../src/theme/preview.ts","../src/theme/publish.ts","../src/admin/document-controls.ts","../src/roles/fields.ts","../src/roles/global.ts","../src/roles/seed.ts","../src/features/fields.ts","../src/features/global.ts","../src/features/seed.ts","../src/fields/slug.ts","../src/collections/pages.ts","../src/collections/users.ts","../src/collections/media.ts","../src/admin-nav/fields.ts","../src/admin-nav/types.ts","../src/admin-nav/validate.ts","../src/admin-nav/global.ts","../src/admin-nav/plugin.ts","../src/admin-nav/resolve.ts","../src/navigation/link.ts","../src/navigation/global.ts","../src/plugins/admin-only-api-tab.ts","../src/plugins/document-title-actions.ts"],"sourcesContent":["import type { CheckboxField } from \"payload\";\n\n/**\n * The index switch, last in the SEO tab. Off by default: a page is public\n * unless an editor says otherwise. `pageMetadata` turns it into\n * `noindex, nofollow`; a site's sitemap should filter on it too.\n */\nexport const noIndexField: CheckboxField = {\n name: \"noIndex\",\n type: \"checkbox\",\n label: \"Hide this page from search engines\",\n defaultValue: false,\n admin: {\n description:\n \"Search engines will not list this page and the sitemap will leave it out. Anyone with the link can still open it.\",\n },\n};\n","/** The length a search result shows of a description before it is cut. */\nexport const DESCRIPTION_LENGTH = 155;\n\n/**\n * Prose cut to `max` characters at a word, with an ellipsis, so a generated\n * description does not end mid-syllable. Text that fits is returned trimmed\n * and whole. A first word longer than `max` is cut mid-word, since there is\n * no boundary to cut at.\n */\nexport function truncateAtWord(text: string, max = DESCRIPTION_LENGTH): string {\n const trimmed = text.trim();\n if (trimmed.length <= max) return trimmed;\n const cut = trimmed.slice(0, max);\n const lastSpace = cut.lastIndexOf(\" \");\n return `${lastSpace > 0 ? cut.slice(0, lastSpace) : cut}…`;\n}\n","import { seoPlugin as payloadSeoPlugin } from \"@payloadcms/plugin-seo\";\nimport type {\n GenerateDescription,\n GenerateImage,\n GenerateTitle,\n GenerateURL,\n} from \"@payloadcms/plugin-seo/types\";\nimport type { CollectionSlug, Plugin, UploadCollectionSlug } from \"payload\";\n\nimport { noIndexField } from \"./fields\";\nimport { truncateAtWord } from \"./text\";\nimport { documentTitle } from \"./title\";\nimport type { MediaId } from \"./types\";\n\n/**\n * What the plugin reads off a document: its title, for the generated meta\n * title. The site's generated `Page` is assignable to this; the `urlFor`,\n * `describeFrom` and `imageFor` callbacks read the rest, typed as the site\n * chooses through `TDoc`.\n */\nexport interface SeoDoc {\n title?: string | null;\n}\n\nexport interface SeoPluginOptions<TDoc extends SeoDoc = SeoDoc> {\n /** Appended to every generated title: `<page title> | <siteName>`. */\n siteName: string;\n /**\n * The absolute public URL of a document from the form's data, for the\n * search-result preview and the Generate button beside it. `undefined`\n * when the document has no address yet (a slug not typed), which leaves\n * the preview empty rather than pointing at the home page.\n */\n urlFor: (doc: TDoc) => string | undefined;\n /**\n * Prose to cut a generated description from, the first plain-text field a\n * page always has near the top (a hero's body, say). Cut at a word near\n * 155 characters. Without it the Generate button fills in nothing.\n */\n describeFrom?: (doc: TDoc) => string | null | undefined;\n /**\n * An image already on the page, for the Meta Image Generate button, so an\n * editor need not upload a second copy of the hero picture. `firstImageIn`\n * walks block rows for one. The upload chooser stays, so any other media\n * row can still be picked.\n */\n imageFor?: (doc: TDoc) => MediaId | null | undefined;\n /** Collections that get the SEO tab. Default `['pages']`. */\n collections?: CollectionSlug[];\n /** The upload collection the meta image comes from. Default `'media'`. */\n uploadsCollection?: UploadCollectionSlug;\n}\n\n/**\n * `@payloadcms/plugin-seo` configured the Bison Lab way: an SEO tab beside a\n * Content tab (never below the block editor), holding the overview with its\n * character counts, meta title, description and image with Generate buttons,\n * the search-result preview, and the `noIndex` switch.\n *\n * Every string the tab generates comes from the options, so a site spells\n * its name and its URL scheme once. Pin `@payloadcms/plugin-seo` to the same\n * version as `payload` in the site; the plugin's admin components are\n * resolved from the site's import map, so run `payload generate:importmap`\n * after adding it.\n */\nexport function seoPlugin<TDoc extends SeoDoc = SeoDoc>({\n siteName,\n urlFor,\n describeFrom,\n imageFor,\n collections = [\"pages\"],\n uploadsCollection = \"media\",\n}: SeoPluginOptions<TDoc>): Plugin {\n const generateTitle: GenerateTitle<TDoc> = ({ doc }) =>\n doc?.title ? documentTitle(siteName, doc.title) : \"\";\n const generateDescription: GenerateDescription<TDoc> = ({ doc }) =>\n truncateAtWord(describeFrom?.(doc) ?? \"\");\n const generateURL: GenerateURL<TDoc> = ({ doc }) => urlFor(doc) ?? \"\";\n // Only when the site can name one: the button appears with the function.\n const generateImage: GenerateImage<TDoc> | undefined = imageFor\n ? ({ doc }) => imageFor(doc) ?? \"\"\n : undefined;\n\n return payloadSeoPlugin({\n collections,\n uploadsCollection,\n tabbedUI: true,\n generateTitle,\n generateDescription,\n generateURL,\n ...(generateImage ? { generateImage } : {}),\n fields: ({ defaultFields }) => [...defaultFields, noIndexField],\n });\n}\n\n/**\n * The first image among some block rows, as a media id, for `imageFor`. Each\n * row is checked for `field` holding either a bare id or a populated upload\n * document; rows without one are skipped. Pass the page's hero and layout\n * together (`[...doc.hero, ...doc.layout]`) to search in reading order.\n */\nexport function firstImageIn(\n blocks: unknown,\n field = \"image\",\n): MediaId | undefined {\n if (!Array.isArray(blocks)) return undefined;\n for (const block of blocks) {\n if (typeof block !== \"object\" || block === null) continue;\n const value = (block as Record<string, unknown>)[field];\n const id =\n typeof value === \"object\" && value !== null && \"id\" in value\n ? (value as { id: unknown }).id\n : value;\n if (typeof id === \"number\" || (typeof id === \"string\" && id !== \"\"))\n return id;\n }\n return undefined;\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 { 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 type { Access, Endpoint, PayloadRequest } from \"payload\";\n\nimport {\n COLOR_USAGES_PATH,\n findColorUsages,\n replacementKeys,\n rewriteColorUsages,\n type ColorUsagePayload,\n type ColorUsagesOption,\n} from \"./color-usages\";\n\nexport { COLOR_USAGES_PATH };\n\nexport function colorUsageEndpoints(\n access: { update: Access },\n scopes: ColorUsagesOption | undefined,\n): Endpoint[] {\n return [\n {\n path: COLOR_USAGES_PATH,\n method: \"get\",\n handler: async (req) => {\n const denied = await denyUnlessUpdate(req, access.update);\n if (denied) return denied;\n const key = queryKey(req);\n if (!key) return Response.json({ error: \"key is required\" }, { status: 400 });\n const usages = await findColorUsages(req.payload as unknown as ColorUsagePayload, scopes, key);\n return Response.json({ usages });\n },\n },\n {\n path: COLOR_USAGES_PATH,\n method: \"post\",\n handler: async (req) => {\n const denied = await denyUnlessUpdate(req, access.update);\n if (denied) return denied;\n const body = (await readJson(req)) as { key?: unknown; replacement?: unknown } | null;\n const key = typeof body?.key === \"string\" ? body.key : \"\";\n const replacement = typeof body?.replacement === \"string\" ? body.replacement : \"\";\n if (!key || !replacement) {\n return Response.json({ error: \"key and replacement are required\" }, { status: 400 });\n }\n const live = await replacementKeys(req.payload as unknown as ColorUsagePayload, key);\n if (!live.includes(replacement)) {\n return Response.json(\n { error: \"Replacement must be a different live system or remaining custom key\" },\n { status: 400 },\n );\n }\n await rewriteColorUsages(req.payload as unknown as ColorUsagePayload, scopes, key, replacement);\n return Response.json({ ok: true });\n },\n },\n ];\n}\n\nasync function denyUnlessUpdate(req: PayloadRequest, update: Access): Promise<Response | null> {\n const allowed = await update({ req });\n if (allowed) return null;\n return Response.json({ error: \"Forbidden\" }, { status: 403 });\n}\n\nfunction queryKey(req: PayloadRequest): string {\n const fromQuery = req.query?.key;\n if (typeof fromQuery === \"string\") return fromQuery;\n if (Array.isArray(fromQuery) && typeof fromQuery[0] === \"string\") return fromQuery[0];\n if (req.url) {\n try {\n return new URL(req.url, \"http://local\").searchParams.get(\"key\") ?? \"\";\n } catch {\n return \"\";\n }\n }\n return \"\";\n}\n\nasync function readJson(req: PayloadRequest): Promise<unknown> {\n if (typeof req.json === \"function\") return req.json();\n return null;\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 type { Access, PayloadRequest } from \"payload\";\n\nimport { DEFAULT_ROLE_MATRIX, parseRolesMatrix, roleHasCapability, roleHasGrant, ROLES_SLUG, seedRoleRows } from \"./matrix\";\nimport { type Capability, type MaybeUser, type RoleExtra, type RoleRow } from \"./types\";\n\nexport type { MaybeUser } from \"./types\";\n\ntype AccessArgs = {\n req: {\n user?: MaybeUser;\n payload?: Pick<NonNullable<PayloadRequest[\"payload\"]>, \"findGlobal\">;\n };\n};\n\ntype CapabilityPredicate = {\n (user: MaybeUser, matrix?: readonly RoleRow[]): boolean;\n (args: AccessArgs): boolean | Promise<boolean>;\n};\n\nfunction isAccessArgs(value: unknown): value is AccessArgs {\n return typeof value === \"object\" && value !== null && \"req\" in value;\n}\n\nexport function storedRoles(user: MaybeUser): readonly string[] {\n return Array.isArray(user?.roles) ? user.roles : [];\n}\n\nexport function hasRole(user: MaybeUser, role: string): boolean {\n return storedRoles(user).includes(role);\n}\n\n/** Not a tick. True only when `developer` is stored on the row. */\nexport function isDeveloper(user: MaybeUser): boolean {\n return hasRole(user, \"developer\");\n}\n\nexport function hasCapability(\n user: MaybeUser,\n capability: Capability,\n matrix: readonly RoleRow[] = DEFAULT_ROLE_MATRIX,\n): boolean {\n if (isDeveloper(user)) return true;\n return storedRoles(user).some((role) => {\n const row = matrix.find((entry) => entry.role === role);\n return row ? roleHasCapability(row, capability) : false;\n });\n}\n\nexport function hasGrant(\n user: MaybeUser,\n slug: string,\n matrix: readonly RoleRow[] = DEFAULT_ROLE_MATRIX,\n): boolean {\n if (isDeveloper(user)) return true;\n return storedRoles(user).some((role) => {\n const row = matrix.find((entry) => entry.role === role);\n return row ? roleHasGrant(row, slug) : false;\n });\n}\n\n/**\n * Reads the saved Roles Global, falling back to the seed when the row is\n * empty, missing, or unreadable. Always override-access so a Designer\n * evaluating Theme does not have to read Settings → Roles.\n */\nexport async function getRolesMatrix(\n req: AccessArgs[\"req\"] = {},\n extras: readonly RoleExtra[] = [],\n): Promise<RoleRow[]> {\n const fallback = seedRoleRows(extras);\n const findGlobal = req.payload?.findGlobal;\n if (typeof findGlobal !== \"function\") return fallback;\n try {\n const doc = await findGlobal({\n slug: ROLES_SLUG,\n overrideAccess: true,\n req: req as PayloadRequest,\n });\n const parsed = parseRolesMatrix(doc && typeof doc === \"object\" && \"roles\" in doc ? doc.roles : undefined);\n return parsed.ok ? parsed.rows : fallback;\n } catch {\n return fallback;\n }\n}\n\nfunction capabilityPredicate(capability: Capability): CapabilityPredicate {\n function predicate(\n userOrArgs: MaybeUser | AccessArgs,\n matrix?: readonly RoleRow[],\n ): boolean | Promise<boolean> {\n if (isAccessArgs(userOrArgs)) {\n const user = userOrArgs.req.user as MaybeUser;\n if (matrix) return hasCapability(user, capability, matrix);\n return getRolesMatrix(userOrArgs.req).then((rows) => hasCapability(user, capability, rows));\n }\n return hasCapability(userOrArgs, capability, matrix ?? DEFAULT_ROLE_MATRIX);\n }\n return predicate as CapabilityPredicate;\n}\n\nexport const canManageContent = capabilityPredicate(\"content\");\nexport const canManageBrand = capabilityPredicate(\"brand\");\nexport const canPublish = capabilityPredicate(\"publish\");\n\n/** Users grant on any held role (Developer is implicit). */\nexport const isAdmin = capabilityPredicate(\"users\");\n\n/** This role id currently has the Users grant, or is Developer. */\nexport function isPrivilegedRole(\n role: unknown,\n matrix: readonly RoleRow[] = DEFAULT_ROLE_MATRIX,\n): boolean {\n if (typeof role !== \"string\") return false;\n if (role === \"developer\") return true;\n const row = matrix.find((entry) => entry.role === role);\n return row ? roleHasGrant(row, \"users\") : false;\n}\n\nexport function isAuthenticated(user: MaybeUser): boolean;\nexport function isAuthenticated(args: AccessArgs): boolean;\nexport function isAuthenticated(userOrArgs: MaybeUser | AccessArgs): boolean {\n if (isAccessArgs(userOrArgs)) return Boolean(userOrArgs.req.user);\n return Boolean(userOrArgs);\n}\n\nexport const isAdminOrSelf: Access = async ({ req }) => {\n if (!req.user) return false;\n if (await isAdmin({ req })) return true;\n return { id: { equals: req.user.id } };\n};\n\nexport const authenticatedOrPublished: Access = ({ req: { user } }) => {\n if (isAuthenticated(user as MaybeUser)) return true;\n return { _status: { equals: \"published\" } };\n};\n\n/**\n * API tab condition. Code-locked to the `developer` slug — not a Features\n * row and not a Role tick a client can grant.\n */\nexport function isDeveloperTab({ req }: AccessArgs): boolean {\n return isDeveloper(req.user as MaybeUser);\n}\n\n/** Access for chrome globals (Features, Better Editor settings). */\nexport function developerOnlyAccess(): { read: Access; update: Access } {\n return {\n read: ({ req }) => isDeveloper(req.user as MaybeUser),\n update: ({ req }) => isDeveloper(req.user as MaybeUser),\n };\n}\n\n/** `admin.hidden`: hide unless the login is Developer. */\nexport function hideUnlessDeveloper({ user }: { user?: MaybeUser }): boolean {\n return !isDeveloper(user);\n}\n","import type { PayloadRequest } from \"payload\";\n\nimport { getRolesMatrix, hasGrant, isDeveloper, type MaybeUser } from \"../roles/access\";\nimport { DEFAULT_ROLE_MATRIX } from \"../roles/matrix\";\nimport type { RoleRow } from \"../roles/types\";\nimport { defaultFeaturesFieldValue, isGroupOnlySlug, parseFeaturesMatrix } from \"./matrix\";\nimport { FEATURE_GROUPS, FEATURES_SLUG, type FeatureRow } from \"./types\";\n\ntype AccessArgs = {\n req: {\n user?: MaybeUser;\n payload?: Pick<NonNullable<PayloadRequest[\"payload\"]>, \"findGlobal\">;\n };\n};\n\ntype FeaturePredicate = {\n (user: MaybeUser, features?: readonly FeatureRow[] | null, roles?: readonly RoleRow[]): boolean;\n (args: AccessArgs): boolean | Promise<boolean>;\n};\n\nfunction isAccessArgs(value: unknown): value is AccessArgs {\n return typeof value === \"object\" && value !== null && \"req\" in value;\n}\n\nfunction grantedOnReleased(\n user: MaybeUser,\n slug: string,\n row: FeatureRow,\n matrix: readonly RoleRow[],\n): boolean {\n if (!row.released) return false;\n return hasGrant(user, slug, matrix);\n}\n\n/**\n * True when the feature is released and a held role is granted it.\n * Developer is always allowed. An empty Global falls back to catalogue\n * defaults. A group slug (`pages`, `theme`) is true when any child is.\n */\nexport function hasFeature(\n user: MaybeUser,\n slug: string,\n features: readonly FeatureRow[] | null = null,\n matrix: readonly RoleRow[] = DEFAULT_ROLE_MATRIX,\n): boolean {\n if (isDeveloper(user)) return true;\n if (!user) return false;\n const rows = features && features.length > 0 ? features : defaultFeaturesFieldValue();\n const leaf = rows.find((entry) => entry.slug === slug);\n if (leaf) return grantedOnReleased(user, slug, leaf, matrix);\n if (!isGroupOnlySlug(slug)) return false;\n return rows.some((entry) => entry.group === slug && grantedOnReleased(user, entry.slug, entry, matrix));\n}\n\n/**\n * Reads the saved Features Global. `null` means empty or unreadable — callers\n * fall back to catalogue defaults. Always override-access.\n */\nexport async function getFeaturesMatrix(req: AccessArgs[\"req\"] = {}): Promise<FeatureRow[] | null> {\n const findGlobal = req.payload?.findGlobal;\n if (typeof findGlobal !== \"function\") return null;\n try {\n const doc = await findGlobal({\n slug: FEATURES_SLUG,\n overrideAccess: true,\n req: req as PayloadRequest,\n });\n const parsed = parseFeaturesMatrix(\n doc && typeof doc === \"object\" && \"features\" in doc ? doc.features : undefined,\n );\n return parsed.ok ? parsed.rows : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Access / nav helper for one catalogue slug. Sync against a passed grid;\n * async when given `req` so it can read both Globals.\n */\nexport function canUseFeature(slug: string): FeaturePredicate {\n function predicate(\n userOrArgs: MaybeUser | AccessArgs,\n features?: readonly FeatureRow[] | null,\n roles?: readonly RoleRow[],\n ): boolean | Promise<boolean> {\n if (isAccessArgs(userOrArgs)) {\n const user = userOrArgs.req.user as MaybeUser;\n if (features !== undefined) return hasFeature(user, slug, features, roles ?? DEFAULT_ROLE_MATRIX);\n return Promise.all([getFeaturesMatrix(userOrArgs.req), getRolesMatrix(userOrArgs.req)]).then(\n ([grid, matrix]) => hasFeature(user, slug, grid, matrix),\n );\n }\n return hasFeature(userOrArgs, slug, features ?? null, roles ?? DEFAULT_ROLE_MATRIX);\n }\n return predicate as FeaturePredicate;\n}\n\n/**\n * Feature slugs (and group slugs) this login may use. Written onto the\n * user at afterRead so `admin.hidden({ user })` can follow the saved\n * Features and Roles Globals without a `req`.\n */\nexport async function allowedFeaturesForUser(\n user: MaybeUser,\n req: AccessArgs[\"req\"] = {},\n): Promise<string[]> {\n const [features, roles] = await Promise.all([getFeaturesMatrix(req), getRolesMatrix(req)]);\n const rows = features && features.length > 0 ? features : defaultFeaturesFieldValue();\n const slugs = [...rows.map((row) => row.slug), ...FEATURE_GROUPS];\n return slugs.filter((slug) => hasFeature(user, slug, features, roles));\n}\n\nfunction userHasAllowedFeature(user: MaybeUser, slug: string): boolean {\n if (isDeveloper(user)) return true;\n const allowed = user?.allowedFeatures;\n if (!Array.isArray(allowed)) return false;\n return allowed.includes(slug);\n}\n\n/** `admin.hidden`: hide when the login cannot use the feature. */\nexport function hideUnlessFeature(slug: string) {\n return (args: { user?: MaybeUser; req?: AccessArgs[\"req\"] }) => {\n const user = args.user ?? null;\n if (isDeveloper(user)) return false;\n if (user && Array.isArray(user.allowedFeatures)) {\n return !userHasAllowedFeature(user, slug);\n }\n if (args.req) {\n const result = canUseFeature(slug)({ req: { ...args.req, user } });\n if (result instanceof Promise) return result.then((ok) => !ok);\n return !result;\n }\n return !canUseFeature(slug)(user);\n };\n}\n","import { catalog, type FontEntry } from \"@bison-lab/fonts\";\nimport { DESTRUCTIVE_SCALE_HEX, presetHints, SHADE_STEPS } from \"@bison-lab/tokens\";\n\n/** Same value as tokens `SUCCESS_SCALE_HEX`. Inlined so an older tokens peer still boots. */\nconst LIBRARY_SUCCESS_HEX = \"#22c55e\";\nimport type { Field, GlobalConfig, SelectField } from \"payload\";\n\nimport {\n SAME_AS_BODY,\n THEME_APPEARANCE_FIELD,\n THEME_COLOR_SCALE_FIELD,\n THEME_FONT_FIELD,\n THEME_GREY_SCALE_FIELD,\n THEME_LIBRARY_FIELD,\n THEME_PAIRING_FIELD,\n THEME_DOCUMENT_CONTROLS,\n THEME_SECTION_HEADING,\n headingSelectValue,\n} from \"./fields\";\nimport { APPEARANCE_CHOICES } from \"./appearance-labels\";\nimport { themeConfigFromDoc, validateSourceIncluded, validateThemeHex } from \"./map\";\nimport { colorUsageEndpoints } from \"./color-usage-endpoints\";\nimport { READABILITY_TARGET } from \"./readability\";\nimport { hideUnlessFeature } from \"../features/access\";\nimport { THEME_SLUG, type CreateThemeOptions, type ThemeDoc } from \"./types\";\n\nfunction requireAccess(options: CreateThemeOptions): CreateThemeOptions[\"access\"] {\n const read = options.access?.read;\n const update = options.access?.update;\n if (!read || !update) {\n throw new Error(\n \"createTheme requires access.read and access.update. Pass canManageBrand from this package as update.\",\n );\n }\n return { read, update };\n}\n\nfunction requireDestructive(options: CreateThemeOptions): string {\n return options.destructive ?? options.seed.brandDestructive ?? DESTRUCTIVE_SCALE_HEX;\n}\n\nfunction namedSelect<K extends string>(\n name: string,\n label: string,\n choices: Record<K, { label: string; hint: string }>,\n defaultValue: K,\n field?: string,\n): SelectField {\n return {\n name,\n type: \"select\",\n label,\n required: true,\n defaultValue,\n options: (Object.entries(choices) as [K, { label: string; hint: string }][]).map(\n ([value, { label: optionLabel, hint }]) => ({\n label: `${optionLabel} — ${hint}`,\n value,\n }),\n ),\n ...(field ? { admin: { components: { Field: field } } } : {}),\n };\n}\n\nconst STEP_OPTIONS = SHADE_STEPS.map((step) => ({ label: String(step), value: String(step) }));\n\nfunction colorScaleFields(hexDefault?: string): Field[] {\n const hidden = { hidden: true } as const;\n return [\n {\n name: \"hex\",\n type: \"text\",\n label: \"Hex\",\n required: true,\n ...(hexDefault ? { defaultValue: hexDefault } : {}),\n validate: validateThemeHex,\n admin: hidden,\n },\n {\n name: \"sourceStep\",\n type: \"select\",\n label: \"Source step\",\n required: true,\n defaultValue: \"500\",\n options: STEP_OPTIONS,\n admin: hidden,\n },\n {\n name: \"scale\",\n type: \"json\",\n label: \"Scale\",\n admin: hidden,\n },\n {\n name: \"stale\",\n type: \"checkbox\",\n label: \"Stale\",\n defaultValue: false,\n admin: hidden,\n },\n {\n name: \"include\",\n type: \"select\",\n label: \"Include\",\n required: true,\n defaultValue: \"all\",\n options: [\n { label: \"Include all\", value: \"all\" },\n { label: \"Source only\", value: \"source\" },\n { label: \"Custom\", value: \"custom\" },\n ],\n admin: hidden,\n },\n {\n name: \"includedSteps\",\n type: \"select\",\n label: \"Included steps\",\n hasMany: true,\n options: STEP_OPTIONS,\n validate: validateSourceIncluded,\n admin: hidden,\n },\n ];\n}\n\nfunction systemColorGroup(name: string, label: string, hexDefault: string): Field {\n return {\n name,\n type: \"group\",\n label,\n fields: colorScaleFields(hexDefault),\n admin: { components: { Field: THEME_COLOR_SCALE_FIELD }, hideGutter: true },\n };\n}\n\nfunction fontField(\n name: string,\n label: string,\n defaultValue: string,\n fonts: readonly FontEntry[],\n fontsBaseUrl: string,\n sameAsBody: boolean,\n): SelectField {\n const options = fonts.map((font) => ({ label: font.family, value: font.id }));\n return {\n name,\n type: \"select\",\n label,\n required: !sameAsBody,\n defaultValue,\n options: sameAsBody ? [{ label: \"Same as body\", value: SAME_AS_BODY }, ...options] : options,\n admin: {\n components: { Field: THEME_FONT_FIELD },\n custom: { fontsBaseUrl, ids: fonts.map((font) => font.id), sameAsBody },\n },\n };\n}\n\nfunction colorsFields(seed: CreateThemeOptions[\"seed\"], destructive: string): Field[] {\n return [\n {\n name: \"colors\",\n type: \"group\",\n label: false,\n admin: { hideGutter: true, width: \"100%\" },\n fields: [\n {\n name: \"brand\",\n type: \"group\",\n label: false,\n admin: { hideGutter: true, width: \"100%\" },\n fields: [\n {\n name: \"themeColorsHeading\",\n type: \"ui\",\n admin: {\n components: { Field: THEME_SECTION_HEADING },\n custom: {\n title: \"Brand colors\",\n hint: \"These colors define the visual identity of the site. Adjust them freely to match the brand.\",\n },\n },\n },\n systemColorGroup(\"primary\", \"Primary\", seed.brandPrimary),\n systemColorGroup(\"secondary\", \"Secondary\", seed.brandSecondary),\n systemColorGroup(\"accent\", \"Accent\", seed.brandAccent),\n systemColorGroup(\"highlight\", \"Highlight\", seed.brandHighlight),\n {\n name: \"libraryPlacement\",\n type: \"ui\",\n admin: {\n components: { Field: THEME_LIBRARY_FIELD },\n custom: { dataPath: \"colors.library\" },\n },\n },\n {\n name: \"greyPlacement\",\n type: \"ui\",\n admin: {\n components: { Field: THEME_GREY_SCALE_FIELD },\n custom: { dataPath: \"colors.greyScale\" },\n },\n },\n {\n name: \"statusColorsHeading\",\n type: \"ui\",\n admin: {\n components: { Field: THEME_SECTION_HEADING },\n custom: {\n title: \"Status colors\",\n hint: \"These colors communicate meaning across the site. You can adjust them to fit your brand, but we'll help keep them recognizable as success and error states.\",\n },\n },\n },\n systemColorGroup(\"success\", \"Success\", seed.brandSuccess || LIBRARY_SUCCESS_HEX),\n systemColorGroup(\"destructive\", \"Destructive\", destructive),\n ],\n },\n {\n ...namedSelect(\"greyScale\", \"Gray family\", presetHints.greyScale, seed.greyScale, THEME_GREY_SCALE_FIELD),\n admin: { hidden: true, components: { Field: THEME_GREY_SCALE_FIELD } },\n },\n {\n name: \"library\",\n type: \"array\",\n label: \"Additional colors\",\n labels: { singular: \"Color\", plural: \"Colors\" },\n fields: [\n { name: \"key\", type: \"text\", label: \"Key\", required: true, admin: { hidden: true } },\n { name: \"label\", type: \"text\", label: \"Name\", required: true, admin: { hidden: true } },\n ...colorScaleFields(),\n ],\n admin: { hidden: true, components: { Field: THEME_LIBRARY_FIELD }, width: \"100%\" },\n },\n ],\n },\n ];\n}\n\nfunction typographyFields(\n seed: CreateThemeOptions[\"seed\"],\n fonts: readonly FontEntry[],\n fontsBaseUrl: string,\n): Field[] {\n return [\n {\n name: \"typography\",\n type: \"group\",\n label: \"Typography\",\n fields: [\n fontField(\n \"heading\",\n \"Heading font\",\n headingSelectValue(seed.fontHeading),\n fonts,\n fontsBaseUrl,\n true,\n ),\n fontField(\"body\", \"Body font\", seed.fontBody, fonts, fontsBaseUrl, false),\n {\n name: \"pairing\",\n type: \"ui\",\n admin: { components: { Field: THEME_PAIRING_FIELD }, custom: { fontsBaseUrl } },\n },\n ],\n },\n ];\n}\n\nfunction appearanceFields(seed: CreateThemeOptions[\"seed\"]): Field[] {\n return [\n {\n name: \"appearance\",\n type: \"group\",\n label: \"Appearance\",\n fields: [\n namedSelect(\"defaultTheme\", \"Default theme\", APPEARANCE_CHOICES.defaultTheme, seed.defaultTheme),\n namedSelect(\"radius\", \"Corner style\", APPEARANCE_CHOICES.radius, seed.radius),\n namedSelect(\"shadow\", \"Depth\", APPEARANCE_CHOICES.shadow, seed.shadow),\n namedSelect(\"motion\", \"Motion\", APPEARANCE_CHOICES.motion, seed.motion),\n namedSelect(\"density\", \"Spacing\", APPEARANCE_CHOICES.density, seed.density),\n ],\n admin: { components: { Field: THEME_APPEARANCE_FIELD } },\n },\n ];\n}\n\nfunction identityFields(collection: string): Field[] {\n return [\n {\n name: \"logo\",\n type: \"upload\",\n relationTo: collection,\n label: \"Logo\",\n admin: {\n description: \"The full wordmark used in the header and footer.\",\n },\n },\n {\n name: \"favicon\",\n type: \"upload\",\n relationTo: collection,\n label: \"Favicon\",\n admin: {\n description: \"The small icon in the browser tab. PNG or SVG.\",\n },\n },\n {\n name: \"logoMark\",\n type: \"upload\",\n relationTo: collection,\n label: \"Mobile menu logo\",\n admin: {\n description:\n \"Optional. Used when the full logo is too wide for the mobile menu — typically the mark.\",\n },\n },\n ];\n}\n\n/**\n * One Theme Global. Colors, Typography, Appearance, and Identity are\n * tabs on that document. Save writes the whole form — Payload hydrates\n * every tab from the live row, so an untouched tab does not revert.\n * Locking is off. No draft mode, no preview pane.\n */\nexport function createTheme(options: CreateThemeOptions): GlobalConfig[] {\n const access = requireAccess(options);\n const destructive = requireDestructive(options);\n const {\n seed,\n fonts = catalog,\n fontsBaseUrl = \"/fonts\",\n contrastTarget = READABILITY_TARGET,\n logo,\n identity,\n onPublish,\n colorUsages,\n } = options;\n\n const adminCustom = { contrastTarget, fontsBaseUrl, identityFallback: identity?.fallback };\n const colorFields = colorsFields(seed, destructive);\n const typeFields = typographyFields(seed, fonts, fontsBaseUrl);\n const lookFields = appearanceFields(seed);\n const markFields = logo ? identityFields(logo.collection) : [];\n\n return [\n {\n slug: THEME_SLUG,\n label: \"Theme\",\n lockDocuments: false,\n admin: {\n group: \"Theme\",\n hidden: hideUnlessFeature(\"theme\") as (args: { user: unknown }) => boolean,\n hideAPIURL: true,\n custom: adminCustom,\n components: {\n elements: { beforeDocumentControls: [THEME_DOCUMENT_CONTROLS] },\n },\n },\n access: {\n read: access.read,\n update: access.update,\n },\n fields: [\n {\n type: \"tabs\",\n tabs: [\n { label: \"Colors\", fields: colorFields },\n { label: \"Typography\", fields: typeFields },\n { label: \"Appearance\", fields: lookFields },\n ...(logo ? [{ label: \"Identity\" as const, fields: markFields }] : []),\n ],\n },\n ],\n endpoints: colorUsageEndpoints(access, colorUsages),\n hooks: {\n afterChange: [\n async ({ doc }) => {\n if (!onPublish) return;\n const themeDoc = doc as ThemeDoc;\n await onPublish(themeConfigFromDoc(themeDoc, seed), themeDoc);\n },\n ],\n },\n },\n ];\n}\n","const DANGEROUS_TAGS = [\"script\", \"foreignObject\", \"iframe\", \"embed\", \"object\"] as const;\n\n/**\n * Strips the SVG features a lockup does not need and an attacker would\n * use: script, foreignObject, iframe/embed/object, event handlers,\n * javascript: / data:text/html URLs, and xml-stylesheet. Internal `#`\n * refs and ordinary drawing elements stay.\n */\nexport function sanitizeSvg(source: string): string {\n if (!/<svg[\\s>]/i.test(source)) {\n throw new Error(\"Not an SVG\");\n }\n\n let out = source.replace(/<\\?xml-stylesheet[\\s\\S]*?\\?>/gi, \"\");\n\n for (const tag of DANGEROUS_TAGS) {\n out = out.replace(new RegExp(`<${tag}\\\\b[^>]*>[\\\\s\\\\S]*?<\\\\/${tag}\\\\s*>`, \"gi\"), \"\");\n out = out.replace(new RegExp(`<${tag}\\\\b[^>]*\\\\/>`, \"gi\"), \"\");\n }\n\n out = out.replace(/\\s+on[a-z][a-z0-9-]*\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s>]+)/gi, \"\");\n out = out.replace(\n /((?:href|src|xlink:href)\\s*=\\s*)([\"'])\\s*(?:javascript:|data:text\\/html)[^\"']*\\2/gi,\n \"$1$2$2\",\n );\n\n return out;\n}\n\nexport function isSvgUpload(file: { mimetype?: string; name?: string; data?: Buffer }): boolean {\n if (file.mimetype === \"image/svg+xml\") return true;\n if (typeof file.name === \"string\" && file.name.toLowerCase().endsWith(\".svg\")) return true;\n return false;\n}\n","import type { Access, CollectionConfig } from \"payload\";\n\nimport { hideUnlessFeature } from \"../features/access\";\nimport { isSvgUpload, sanitizeSvg } from \"./sanitize\";\n\nexport const BRAND_ASSETS_SLUG = \"brand-assets\";\n\n/** SVG preferred; PNG allowed. ICO is for the favicon slot. */\nexport const BRAND_ASSETS_MIME_TYPES = [\n \"image/svg+xml\",\n \"image/png\",\n \"image/x-icon\",\n \"image/vnd.microsoft.icon\",\n] as const;\n\nexport interface CreateBrandAssetsOptions {\n /**\n * Required, no default — same shape as `createTheme`. `read` is typically\n * public so the live site can load the lockup; `update` is `canManageBrand`\n * and covers create, update, delete, and version history. This collection\n * does not read the Roles Global.\n */\n access: { read: Access; update: Access };\n /** Default `brand-assets`. Pass the same slug to `createTheme({ logo })`. */\n slug?: string;\n}\n\nfunction requireAccess(options: CreateBrandAssetsOptions): CreateBrandAssetsOptions[\"access\"] {\n const read = options.access?.read;\n const update = options.access?.update;\n if (!read || !update) {\n throw new Error(\n \"createBrandAssets requires access.read and access.update. Pass canManageBrand from this package as update.\",\n );\n }\n return { read, update };\n}\n\n/**\n * Locked cupboard for lockup and mark. Not ordinary Media — only a brand\n * manager writes it. Theme's `logo` / `logoMark` point here when the site\n * passes this slug as `logo.collection`.\n */\nexport function createBrandAssets(options: CreateBrandAssetsOptions): CollectionConfig {\n const access = requireAccess(options);\n const slug = options.slug ?? BRAND_ASSETS_SLUG;\n\n return {\n slug,\n labels: { singular: \"Brand asset\", plural: \"Brand assets\" },\n admin: {\n group: \"Settings\",\n useAsTitle: \"label\",\n hidden: hideUnlessFeature(\"brand-assets\") as (args: { user: unknown }) => boolean,\n description: \"Logo, favicon, and mobile-menu mark. SVG preferred; PNG and ICO allowed.\",\n },\n upload: {\n mimeTypes: [...BRAND_ASSETS_MIME_TYPES],\n crop: false,\n focalPoint: false,\n },\n versions: true,\n access: {\n read: access.read,\n create: access.update,\n update: access.update,\n delete: access.update,\n readVersions: access.update,\n },\n fields: [\n { name: \"label\", type: \"text\", label: \"Label\" },\n { name: \"notes\", type: \"textarea\", label: \"Usage notes\" },\n { name: \"alt\", type: \"text\", label: \"Alt text\", required: true },\n ],\n hooks: {\n beforeOperation: [\n ({ req, operation }) => {\n if (operation !== \"create\" && operation !== \"update\") return;\n const file = req.file;\n if (!file || !isSvgUpload(file)) return;\n file.data = Buffer.from(sanitizeSvg(file.data.toString(\"utf8\")), \"utf8\");\n },\n ],\n },\n };\n}\n","import type { ThemeConfig } from \"@bison-lab/tokens\";\n\nimport { docFromConfig } from \"./map\";\nimport { THEME_SLUG } from \"./types\";\nimport type { ThemeDoc } from \"./types\";\n\nexport interface SeedThemePayload {\n updateGlobal: (args: {\n slug: string;\n data: ThemeDoc;\n draft?: boolean;\n }) => Promise<unknown>;\n}\n\n/**\n * Writes a published Theme from the seed. For a site's migration `up()`,\n * so the row exists on deploy and renders what `bison-theme.css` rendered.\n */\nexport async function seedTheme(payload: SeedThemePayload, seed: ThemeConfig): Promise<unknown> {\n return payload.updateGlobal({\n slug: THEME_SLUG,\n data: docFromConfig(seed),\n draft: false,\n });\n}\n","/**\n * Device sizes the Theme (and, later, Pages) live-preview toolbar offers.\n * One list so the panes match.\n */\nexport const THEME_PREVIEW_BREAKPOINTS = [\n { label: \"Mobile\", name: \"mobile\", width: 375, height: 667 },\n { label: \"Tablet\", name: \"tablet\", width: 768, height: 1024 },\n { label: \"Desktop\", name: \"desktop\", width: 1440, height: 900 },\n] as const;\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","/**\n * Import-map keys and helpers for the shared document header.\n * `documentTitleActions()` injects one admin provider so every\n * document shares the title-row lift. One-list Globals pass\n * `documentCreateNew` so Create New sits in that same slot.\n */\n\nexport const DOCUMENT_TITLE_ACTIONS = \"@bison-lab/payload-core/admin#DocumentTitleActions\";\nexport const DOCUMENT_CREATE_NEW = \"@bison-lab/payload-core/admin#DocumentCreateNew\";\n\nexport function documentCreateNew(path: string) {\n return { path: DOCUMENT_CREATE_NEW, clientProps: { path } };\n}\n","export const ROLES_MATRIX_FIELD = \"@bison-lab/payload-core/admin#RolesMatrixField\";\nexport const ROLES_ROW_LABEL = \"@bison-lab/payload-core/admin#RolesRowLabel\";\nexport const ROLE_SLUG_FIELD = \"@bison-lab/payload-core/admin#RoleSlugField\";\nexport const ROLE_NAME_FIELD = \"@bison-lab/payload-core/admin#RoleNameField\";\nexport const ROLES_FIELD = \"@bison-lab/payload-core/admin#RolesField\";\nexport const ROLES_GRANTS_FIELD = \"@bison-lab/payload-core/admin#RolesGrantsField\";\n","import type { ArrayField, GlobalConfig, TextFieldSingleValidation } from \"payload\";\n\nimport { documentCreateNew } from \"../admin/document-controls\";\nimport { canUseFeature, hideUnlessFeature } from \"../features/access\";\nimport { isAdmin } from \"./access\";\nimport { ROLE_NAME_FIELD, ROLES_GRANTS_FIELD, ROLES_MATRIX_FIELD, ROLES_ROW_LABEL } from \"./fields\";\nimport {\n applyRoleSlugsFromNames,\n defaultRolesFieldValue,\n DUPLICATE_ROLE_SLUG_MESSAGE,\n INVALID_ROLE_NAME_MESSAGE,\n ROLES_FIELD_DESCRIPTION,\n ROLES_GLOBAL_DESCRIPTION,\n ROLES_SLUG,\n validateRolesMatrix,\n} from \"./matrix\";\nimport { isRoleName, isRoleSlug, type RoleExtra } from \"./types\";\n\nexport interface CreateRolesOptions {\n /**\n * Extra catalogue rows after the first-run defaults. Each is a slug, a\n * display label, and default grants. A site that passes nothing still\n * gets Developer / Admin / Designer / Author; an Admin may later remove\n * every row except Developer.\n */\n extras?: readonly RoleExtra[];\n}\n\nconst roleSlugValidate: TextFieldSingleValidation = (value) => {\n // Empty is fine while Create New is in progress; the name fills it on save.\n if (typeof value !== \"string\" || value === \"\") return true;\n return isRoleSlug(value) || DUPLICATE_ROLE_SLUG_MESSAGE;\n};\n\nconst roleNameValidate: TextFieldSingleValidation = (value) => {\n if (typeof value !== \"string\" || value.trim() === \"\") return true;\n return isRoleName(value) || INVALID_ROLE_NAME_MESSAGE;\n};\n\n/**\n * Settings → Roles. Rank is the array order (Payload's drag handle).\n * Ticks are released catalogue rows. Developer is implicit and shown\n * only to a Developer, with every catalogue tick locked on.\n */\nexport function createRoles({ extras = [] }: CreateRolesOptions = {}): GlobalConfig {\n const rolesField: ArrayField = {\n name: \"roles\",\n type: \"array\",\n label: \"Roles\",\n labels: { singular: \"Role\", plural: \"Roles\" },\n minRows: 1,\n required: true,\n defaultValue: defaultRolesFieldValue(extras),\n validate: validateRolesMatrix,\n hooks: {\n beforeChange: [({ value }) => applyRoleSlugsFromNames(value)],\n },\n admin: {\n components: { Field: ROLES_MATRIX_FIELD, RowLabel: ROLES_ROW_LABEL },\n description: ROLES_FIELD_DESCRIPTION,\n initCollapsed: false,\n },\n fields: [\n {\n name: \"role\",\n type: \"text\",\n label: \"Slug\",\n validate: roleSlugValidate,\n admin: { hidden: true },\n },\n {\n name: \"label\",\n type: \"text\",\n label: \"Name\",\n required: true,\n validate: roleNameValidate,\n admin: { components: { Field: ROLE_NAME_FIELD } },\n },\n {\n name: \"grants\",\n type: \"json\",\n label: \"Grants\",\n defaultValue: [],\n admin: {\n components: { Field: ROLES_GRANTS_FIELD },\n },\n },\n ],\n };\n\n return {\n slug: ROLES_SLUG,\n label: \"Roles\",\n admin: {\n group: \"Settings\",\n hidden: hideUnlessFeature(\"roles\") as (args: { user: unknown }) => boolean,\n description: ROLES_GLOBAL_DESCRIPTION,\n components: {\n elements: {\n beforeDocumentControls: [documentCreateNew(\"roles\")],\n },\n },\n },\n access: {\n read: (args) => canUseFeature(\"roles\")(args),\n update: (args) => isAdmin(args),\n },\n fields: [rolesField],\n };\n}\n","import { defaultRolesFieldValue, ROLES_SLUG } from \"./matrix\";\nimport type { RoleExtra, RolesDoc } from \"./types\";\n\nexport interface SeedRolesPayload {\n updateGlobal: (args: { slug: string; data: RolesDoc }) => Promise<unknown>;\n}\n\n/**\n * Writes the default matrix (Developer, Admin, Designer, Author plus any\n * site extras). For a site's migration `up()`. Never writes a user row —\n * seeding `developer` on a person stays a site concern.\n */\nexport async function seedRoles(\n payload: SeedRolesPayload,\n extras: readonly RoleExtra[] = [],\n): Promise<unknown> {\n return payload.updateGlobal({\n slug: ROLES_SLUG,\n data: { roles: defaultRolesFieldValue(extras) },\n });\n}\n","export const FEATURES_MATRIX_FIELD = \"@bison-lab/payload-core/admin#FeaturesMatrixField\";\n","import type { ArrayField, GlobalConfig } from \"payload\";\n\nimport { developerOnlyAccess, hideUnlessDeveloper } from \"../roles/access\";\nimport { FEATURES_MATRIX_FIELD } from \"./fields\";\nimport { defaultFeaturesFieldValue, featureCatalogue, stampFeatureCatalogue, validateFeaturesMatrix } from \"./matrix\";\nimport { FEATURES_SLUG, type FeatureExtra } from \"./types\";\n\nexport interface CreateFeaturesOptions {\n /**\n * Site-only rows after the package catalogue. A second `createFeatures()`\n * without these extras never includes them.\n */\n extras?: readonly FeatureExtra[];\n}\n\n/**\n * Settings → Features. One release switch per catalogue row. Off hides\n * the tick on Roles; Developer still has the feature. This screen is\n * not itself a row.\n */\nexport function createFeatures({ extras = [] }: CreateFeaturesOptions = {}): GlobalConfig {\n const catalogue = featureCatalogue(extras);\n const featuresField: ArrayField = {\n name: \"features\",\n type: \"array\",\n label: \"Features\",\n labels: { singular: \"Feature\", plural: \"Features\" },\n minRows: catalogue.length,\n maxRows: catalogue.length,\n required: true,\n defaultValue: defaultFeaturesFieldValue(extras),\n validate: (value) => validateFeaturesMatrix(value, extras),\n hooks: {\n beforeChange: [\n ({ value }) => {\n if (!Array.isArray(value)) return value;\n return stampFeatureCatalogue(value, extras);\n },\n ],\n },\n admin: {\n components: { Field: FEATURES_MATRIX_FIELD },\n description:\n \"Release a feature so it can be assigned on Roles. Off keeps it Developer-only.\",\n initCollapsed: false,\n },\n fields: [\n { name: \"slug\", type: \"text\", label: \"Slug\", required: true, admin: { readOnly: true } },\n { name: \"label\", type: \"text\", label: \"Name\", required: true, admin: { readOnly: true } },\n { name: \"group\", type: \"text\", label: \"Group\", admin: { hidden: true } },\n { name: \"released\", type: \"checkbox\", label: \"Released\", admin: { hidden: true } },\n ],\n };\n\n return {\n slug: FEATURES_SLUG,\n label: \"Features\",\n admin: {\n group: \"Settings\",\n hidden: hideUnlessDeveloper,\n description: \"Which features other people may be granted on Roles.\",\n },\n access: developerOnlyAccess(),\n fields: [featuresField],\n };\n}\n","import { defaultFeaturesFieldValue } from \"./matrix\";\nimport { FEATURES_SLUG, type FeatureExtra, type FeaturesDoc } from \"./types\";\n\nexport interface SeedFeaturesPayload {\n updateGlobal: (args: { slug: string; data: FeaturesDoc }) => Promise<unknown>;\n}\n\n/**\n * Writes the default switchboard (package rows plus any site extras).\n * For a site's migration `up()`.\n */\nexport async function seedFeatures(\n payload: SeedFeaturesPayload,\n extras: readonly FeatureExtra[] = [],\n): Promise<unknown> {\n return payload.updateGlobal({\n slug: FEATURES_SLUG,\n data: { features: defaultFeaturesFieldValue(extras) },\n });\n}\n","import type {\n CollectionSlug,\n PayloadRequest,\n TextField,\n TextFieldSingleValidation,\n Where,\n} from \"payload\";\nimport { ValidationError, validations } from \"payload\";\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\n/**\n * A stored slug from whatever was typed: lowercased, with any run of\n * whitespace and slashes stripped from either end in one pass, so `/ about-us /`\n * does not keep the inner spaces a trim-then-strip would leave.\n */\nexport function normalizeSlug(value: string): string {\n return value.replace(/^[\\s/]+|[\\s/]+$/g, \"\").toLowerCase();\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\n/**\n * The path a document is published at, normalised on the way in. Unique\n * across the collection. `validate` is the message under the field;\n * `beforeChange` is the enforcement on a draft save, where Payload skips\n * field validation.\n */\nexport function slugField({ collection, isReserved }: SlugFieldOptions): TextField {\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 return {\n name: \"slug\",\n type: \"text\",\n required: true,\n unique: true,\n admin: {\n description: 'Path under the site root, no leading slash: \"about-us\" or \"patients/stories\".',\n },\n hooks: {\n beforeValidate: [({ value }) => (typeof value === \"string\" ? normalizeSlug(value) : value)],\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","import type { Access, Block, CollectionConfig } from \"payload\";\n\nimport { canUseFeature, hideUnlessFeature } from \"../features/access\";\nimport { authenticatedOrPublished, canPublish, isAdmin, isAuthenticated } from \"../roles/access\";\nimport { slugField } from \"../fields/slug\";\n\n/**\n * Content to create or save a draft; Publish to publish or edit a live\n * page. Without Publish, update is constrained to `_status: draft`.\n */\nconst pagesUpdate: Access = async (args) => {\n const canEdit = await Promise.resolve(canUseFeature(\"content\")(args));\n if (!canEdit) return false;\n if (await Promise.resolve(canPublish(args))) return true;\n return { _status: { equals: \"draft\" } };\n};\n\nexport interface PagesOptions {\n /**\n * What a page may open with. One row, so this is the site's hero variants,\n * not a list a page picks several from.\n */\n heroBlocks: Block[];\n /** The sections a page body can be built out of. */\n layoutBlocks: Block[];\n /**\n * True when a slug is not the CMS's to hand out — a path the app already\n * serves from code, or one the framework reserves.\n */\n isReservedSlug: (slug: string) => boolean;\n /**\n * Public path of a page from its stored slug — the site's own route helper.\n * Drives the page preview overlay's iframe.\n */\n previewPath: (slug: string) => string;\n /**\n * Component path for Payload's native Preview button, as a key into the\n * site's committed `importMap.js`. Omit it for Payload's own button.\n */\n previewButton?: string;\n}\n\n/**\n * CMS-managed pages: one required hero, then a reorderable body of sections.\n * The CMS owns copy and the order of sections; what a section looks like is\n * code-owned, which is why the blocks are an argument.\n */\nexport function createPages({\n heroBlocks,\n isReservedSlug,\n layoutBlocks,\n previewPath,\n previewButton,\n}: PagesOptions): CollectionConfig {\n const [defaultHero] = heroBlocks;\n if (!defaultHero) throw new Error(\"createPages needs at least one hero block\");\n\n return {\n slug: \"pages\",\n admin: {\n useAsTitle: \"title\",\n group: \"Content\",\n defaultColumns: [\"title\", \"slug\", \"_status\", \"updatedAt\"],\n hidden: hideUnlessFeature(\"content\") as (args: { user: unknown }) => boolean,\n preview: (doc) => previewPath(typeof doc.slug === \"string\" ? doc.slug : \"\"),\n ...(previewButton ? { components: { edit: { PreviewButton: previewButton } } } : {}),\n },\n access: {\n read: authenticatedOrPublished,\n readVersions: isAuthenticated,\n create: canUseFeature(\"content\"),\n update: pagesUpdate,\n delete: isAdmin,\n },\n versions: {\n drafts: { autosave: { interval: 375 } },\n maxPerDoc: 50,\n },\n fields: [\n { name: \"title\", type: \"text\", required: true },\n slugField({ collection: \"pages\", isReserved: isReservedSlug }),\n {\n name: \"hero\",\n type: \"blocks\",\n required: true,\n minRows: 1,\n maxRows: 1,\n blocks: heroBlocks,\n defaultValue: [{ blockType: defaultHero.slug }],\n admin: {\n description: \"Every page opens with one hero. A page cannot be published without one.\",\n },\n },\n {\n name: \"layout\",\n type: \"blocks\",\n required: true,\n minRows: 1,\n blocks: layoutBlocks,\n labels: { singular: \"Section\", plural: \"Sections\" },\n },\n ],\n };\n}\n","import type {\n CollectionConfig,\n PayloadRequest,\n SelectFieldManyValidation,\n TextField,\n TextFieldSingleValidation,\n Where,\n} from \"payload\";\nimport { APIError } from \"payload\";\nimport { select, text } from \"payload/shared\";\n\nimport { allowedFeaturesForUser, canUseFeature, hideUnlessFeature } from \"../features/access\";\nimport { getRolesMatrix, isAdmin, isAdminOrSelf, isPrivilegedRole } from \"../roles/access\";\nimport { ROLES_FIELD } from \"../roles/fields\";\nimport { normalizeStoredRoles, roleSelectOptions, seedRoleRows } from \"../roles/matrix\";\nimport type { RoleExtra, RoleRow } from \"../roles/types\";\n\nconst nameValidate: TextFieldSingleValidation = (value, options) => {\n if (options.operation === \"update\" && value === \"\" && options.previousValue === \"\") return true;\n return text(value, options);\n};\n\nfunction nameField(name: \"firstName\" | \"lastName\"): TextField {\n return { name, type: \"text\", required: true, validate: nameValidate };\n}\n\n/** Refuses the save that would remove Users from the only privileged user. */\nexport const LAST_ADMIN_DEMOTE_MESSAGE = \"Make another user an admin before removing it from this one.\";\n/** Refuses the delete that would remove the only privileged user. */\nexport const LAST_ADMIN_DELETE_MESSAGE = \"Make another user an admin before deleting this one.\";\n\ninterface TransactionalAdapter {\n execute?: (args: { db?: unknown; raw?: string }) => Promise<unknown>;\n sessions?: Record<string, { db: unknown } | undefined>;\n}\n\nconst LAST_ADMIN_LOCK = \"select pg_advisory_xact_lock(hashtext('users:last-admin'))\";\n\nasync function lockLastAdminDecision(req: PayloadRequest): Promise<void> {\n const { execute, sessions } = req.payload.db as unknown as TransactionalAdapter;\n const id = req.transactionID;\n const session = typeof id === \"string\" || typeof id === \"number\" ? sessions?.[id] : undefined;\n if (!session || typeof execute !== \"function\") return;\n await execute({ db: session.db, raw: LAST_ADMIN_LOCK });\n}\n\nfunction privilegedRoles(matrix: readonly RoleRow[]): string[] {\n return matrix.filter((row) => isPrivilegedRole(row.role, matrix)).map((row) => row.role);\n}\n\nfunction holdsPrivilegedRole(roles: unknown, matrix: readonly RoleRow[]): boolean {\n return Array.isArray(roles) && roles.some((role) => isPrivilegedRole(role, matrix));\n}\n\nfunction privilegedWhere(matrix: readonly RoleRow[]): Where {\n const roles = privilegedRoles(matrix);\n if (roles.length === 0) return { id: { equals: \"__none__\" } };\n return { or: roles.map((role) => ({ roles: { contains: role } })) };\n}\n\nasync function adminCount(req: PayloadRequest, excluding?: number | string): Promise<number> {\n await lockLastAdminDecision(req);\n const matrix = await getRolesMatrix(req);\n const holdsPrivileged = privilegedWhere(matrix);\n const { totalDocs } = await req.payload.count({\n collection: \"users\",\n overrideAccess: true,\n req,\n where:\n excluding === undefined\n ? holdsPrivileged\n : { and: [holdsPrivileged, { id: { not_equals: excluding } }] },\n });\n return totalDocs;\n}\n\nfunction rolesValidate(extras: readonly RoleExtra[]): SelectFieldManyValidation {\n return async (value, options) => {\n const matrix = await getRolesMatrix(options.req, extras);\n const builtIn = select(value, { ...options, options: roleSelectOptions(matrix) });\n if (builtIn !== true) return builtIn;\n if (options.operation !== \"update\" || options.id === undefined) return true;\n if (holdsPrivilegedRole(value, matrix) || !holdsPrivilegedRole(options.previousValue, matrix)) {\n return true;\n }\n return (await adminCount(options.req, options.id)) > 0 ? true : LAST_ADMIN_DEMOTE_MESSAGE;\n };\n}\n\nexport interface UsersOptions {\n /**\n * Whether the auth cookie is marked Secure. Passed in rather than read from\n * the environment here: which env var means \"served over HTTPS\" is the\n * host's business, not the CMS's.\n */\n secureCookies: boolean;\n /**\n * Component path for the roles field, as a key into the site's committed\n * `importMap.js`. Defaults to the package checklist. A value nothing\n * resolves renders the field as nothing.\n */\n rolesField?: string;\n /**\n * Same extras passed to `createRoles`. Offered on Users when the Global\n * is empty; a saved Global (including Admin-added rows) wins.\n */\n extras?: readonly RoleExtra[];\n}\n\nexport function createUsers({ secureCookies, rolesField, extras = [] }: UsersOptions): CollectionConfig {\n const fallback = seedRoleRows(extras);\n return {\n slug: \"users\",\n auth: {\n maxLoginAttempts: 5,\n lockTime: 10 * 60 * 1000,\n tokenExpiration: 2 * 60 * 60,\n cookies: {\n sameSite: \"Lax\",\n secure: secureCookies,\n },\n },\n admin: {\n group: \"Settings\",\n useAsTitle: \"email\",\n defaultColumns: [\"email\", \"firstName\", \"lastName\", \"roles\"],\n hidden: hideUnlessFeature(\"users\") as (args: { user: unknown }) => boolean,\n },\n access: {\n create: isAdmin,\n delete: isAdmin,\n unlock: isAdmin,\n read: async (args) => {\n if (await Promise.resolve(canUseFeature(\"users\")(args))) return true;\n return isAdminOrSelf(args);\n },\n update: isAdminOrSelf,\n },\n hooks: {\n beforeDelete: [\n async ({ id, req }) => {\n const doomed = await req.payload.findByID({\n collection: \"users\",\n id,\n depth: 0,\n disableErrors: true,\n overrideAccess: true,\n req,\n });\n const matrix = await getRolesMatrix(req, extras);\n if (!isAdmin(doomed, matrix) || (await adminCount(req, id)) > 0) return;\n throw new APIError(LAST_ADMIN_DELETE_MESSAGE, 400);\n },\n ],\n afterOperation: [\n async (arg) => {\n const { operation, req } = arg;\n const touchesRoles =\n (operation === \"update\" || operation === \"updateByID\") &&\n arg.args.data?.roles !== undefined;\n const deletes = operation === \"delete\" || operation === \"deleteByID\";\n if ((touchesRoles || deletes) && (await adminCount(req)) === 0) {\n throw new APIError(deletes ? LAST_ADMIN_DELETE_MESSAGE : LAST_ADMIN_DEMOTE_MESSAGE, 400);\n }\n return arg.result;\n },\n ],\n },\n fields: [\n {\n type: \"row\",\n fields: [nameField(\"firstName\"), nameField(\"lastName\")],\n },\n {\n name: \"roles\",\n type: \"select\",\n hasMany: true,\n required: true,\n saveToJWT: true,\n // Seed plus site extras. filterOptions replaces this with the saved\n // Global (labels and Admin-added slugs) when that row is readable.\n options: roleSelectOptions(fallback),\n admin: {\n components: { Field: rolesField ?? ROLES_FIELD },\n description: \"One person can hold several, e.g. Author + Designer.\",\n },\n access: {\n update: isAdmin,\n },\n validate: rolesValidate(extras),\n hooks: {\n beforeValidate: [\n async ({ value, req }) => {\n if (!Array.isArray(value)) return value;\n return normalizeStoredRoles(value, await getRolesMatrix(req, extras));\n },\n ],\n },\n },\n {\n name: \"allowedFeatures\",\n type: \"json\",\n admin: { hidden: true, readOnly: true },\n access: { update: () => false },\n saveToJWT: true,\n hooks: {\n afterRead: [\n async ({ siblingData, data, req }) =>\n allowedFeaturesForUser(\n {\n id: (siblingData?.id ?? data?.id) as string | number | undefined,\n roles: (siblingData?.roles ?? data?.roles) as readonly string[] | undefined,\n },\n req ?? {},\n ),\n ],\n },\n },\n ],\n };\n}\n","import type { CollectionConfig, ImageSize } from \"payload\";\n\nimport { canUseFeature, hideUnlessFeature } from \"../features/access\";\nimport { isAdmin } from \"../roles/access\";\n\nexport interface MediaOptions {\n /** Where uploads land, relative to the app root. */\n staticDir?: string;\n mimeTypes?: string[];\n /**\n * Renditions sharp cuts on upload, each served at its own URL under\n * `sizes.<name>` on the document. Which sizes a site needs is the site's\n * call. A file uploaded before a size was added has no rendition for it.\n */\n imageSizes?: ImageSize[];\n}\n\n/**\n * Uploads, readable by anyone: the public site serves these files. Writing is\n * an editorial action, deleting is not — removing an asset a live page\n * references breaks that page.\n */\nexport function createMedia({\n staticDir = \"media\",\n mimeTypes = [\"image/*\"],\n imageSizes,\n}: MediaOptions = {}): CollectionConfig {\n return {\n slug: \"media\",\n admin: {\n hidden: hideUnlessFeature(\"media\") as (args: { user: unknown }) => boolean,\n },\n access: {\n read: () => true,\n create: canUseFeature(\"media\"),\n update: canUseFeature(\"media\"),\n delete: isAdmin,\n },\n upload: { staticDir, mimeTypes, imageSizes },\n fields: [\n {\n name: \"alt\",\n type: \"text\",\n required: true,\n },\n ],\n };\n}\n","export const ADMIN_NAV = \"@bison-lab/payload-core/admin#AdminNav\";\nexport const ADMIN_NAV_ROW_LABEL = \"@bison-lab/payload-core/admin#AdminNavRowLabel\";\nexport const ADMIN_NAV_ITEM_ROW_LABEL = \"@bison-lab/payload-core/admin#AdminNavItemRowLabel\";\nexport const ADMIN_NAV_ENTITY_FIELD = \"@bison-lab/payload-core/admin#AdminNavEntityField\";\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 { TextFieldSingleValidation } from \"payload\";\n\nconst UNKNOWN_ENTITY_MESSAGE = \"Not in this site's config.\";\n\n/**\n * A Developer cannot invent a collection or global that is not registered.\n */\nexport const validateAdminNavSlug: TextFieldSingleValidation = (value, { req, siblingData }) => {\n if (typeof value !== \"string\" || value === \"\") return true;\n const type = siblingData && typeof siblingData === \"object\" && \"type\" in siblingData ? siblingData.type : null;\n const list =\n type === \"global\" ? req.payload?.config?.globals : type === \"collection\" ? req.payload?.config?.collections : [];\n const slugs = (list ?? []).map((entity) => entity.slug);\n return slugs.includes(value) || UNKNOWN_ENTITY_MESSAGE;\n};\n","import type { ArrayField, GlobalConfig } from \"payload\";\n\nimport { hideUnlessDeveloper, isAuthenticated, isDeveloper, type MaybeUser } from \"../roles/access\";\nimport { ADMIN_NAV_ENTITY_FIELD, ADMIN_NAV_ITEM_ROW_LABEL, ADMIN_NAV_ROW_LABEL } from \"./fields\";\nimport { ADMIN_NAV_SLUG } from \"./types\";\nimport { validateAdminNavSlug } from \"./validate\";\n\nconst groupsField: ArrayField = {\n name: \"groups\",\n type: \"array\",\n label: \"Groups\",\n labels: { singular: \"Group\", plural: \"Groups\" },\n admin: {\n components: { RowLabel: ADMIN_NAV_ROW_LABEL },\n description: \"Sidebar headers and the collections or globals under each. Drag to reorder. An empty header still shows.\",\n initCollapsed: false,\n },\n fields: [\n {\n name: \"label\",\n type: \"text\",\n label: \"Header\",\n },\n {\n name: \"items\",\n type: \"array\",\n label: \"Items\",\n labels: { singular: \"Item\", plural: \"Items\" },\n admin: { components: { RowLabel: ADMIN_NAV_ITEM_ROW_LABEL } },\n fields: [\n {\n type: \"row\",\n fields: [\n {\n name: \"type\",\n type: \"select\",\n label: \"Type\",\n required: true,\n defaultValue: \"collection\",\n options: [\n { label: \"Collection\", value: \"collection\" },\n { label: \"Global\", value: \"global\" },\n ],\n admin: { width: \"40%\" },\n },\n {\n name: \"slug\",\n type: \"text\",\n label: \"Slug\",\n required: true,\n validate: validateAdminNavSlug,\n admin: { width: \"60%\", components: { Field: ADMIN_NAV_ENTITY_FIELD } },\n },\n ],\n },\n ],\n },\n ],\n};\n\n/**\n * Settings → Admin nav. Developer chrome, not a Features row. Save writes\n * immediately. The package Nav reads this document. An empty row falls\n * back to Payload's first-seen walk; a saved row is the sidebar.\n */\nexport function createAdminNav(): GlobalConfig {\n return {\n slug: ADMIN_NAV_SLUG,\n label: \"Admin nav\",\n admin: {\n group: \"Settings\",\n hidden: hideUnlessDeveloper,\n description:\n \"Sidebar group headers and order. An empty document falls back to Payload's first-seen walk. Once you save, only the groups and items you listed appear — omitted collections and globals stay off the sidebar.\",\n },\n access: {\n read: isAuthenticated,\n update: ({ req }) => isDeveloper(req.user as MaybeUser),\n },\n fields: [groupsField],\n };\n}\n","import type { Config } from \"payload\";\nimport { definePlugin } from \"payload\";\n\nimport { ADMIN_NAV } from \"./fields\";\n\n/**\n * Sets `admin.components.Nav` to the package Nav. A consuming site must\n * not write its own Nav — SPI-10 is the later skin, and it reads\n * `resolveAdminNav` rather than a second layout source.\n */\nexport const adminNav = definePlugin({\n slug: \"admin-nav\",\n order: 1000,\n plugin: ({ config }): Config => ({\n ...config,\n admin: {\n ...config.admin,\n components: {\n ...config.admin?.components,\n Nav: ADMIN_NAV,\n },\n },\n }),\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 type { Condition, Field, GroupField, RowField } from \"payload\";\n\n/**\n * Same import-map string as `@bison-lab/payload-blocks`. A site that\n * already generates the blocks admin map gets the picker; a missing\n * entry renders the row as nothing, so `payload generate:importmap` is\n * part of adopting this factory.\n */\nconst LINK_FIELD = \"@bison-lab/payload-blocks/admin#LinkField\";\n\ntype LinkType = \"page\" | \"external\";\n\ninterface LinkDestination {\n type?: LinkType | null;\n href?: string | null;\n}\n\nfunction linkTypeOf(link: LinkDestination | null | undefined): LinkType {\n if (link?.type === \"external\") return \"external\";\n if (link?.type === \"page\") return \"page\";\n return link?.href ? \"external\" : \"page\";\n}\n\nconst whenPage: Condition = (_data, siblingData) => linkTypeOf(siblingData as LinkDestination) === \"page\";\nconst whenExternal: Condition = (_data, siblingData) =>\n linkTypeOf(siblingData as LinkDestination) === \"external\";\n\nfunction linkDestinationFields({\n required = false,\n pagesCollection = \"pages\",\n}: {\n required?: boolean;\n pagesCollection?: string;\n} = {}): RowField[] {\n return [\n {\n type: \"row\",\n admin: { components: { Field: LINK_FIELD } },\n fields: [\n {\n name: \"type\",\n type: \"radio\",\n label: \"Goes to\",\n defaultValue: \"page\",\n options: [\n { label: \"Page\", value: \"page\" },\n { label: \"URL\", value: \"external\" },\n ],\n admin: { layout: \"horizontal\" },\n },\n {\n name: \"page\",\n type: \"relationship\",\n relationTo: pagesCollection,\n required,\n filterOptions: { _status: { equals: \"published\" } },\n admin: { condition: whenPage },\n },\n {\n name: \"href\",\n type: \"text\",\n label: \"URL\",\n required,\n admin: {\n condition: whenExternal,\n description:\n 'A full URL (\"https://example.com\"), \"mailto:\" or \"tel:\", or a site path (\"/contact\").',\n },\n },\n ],\n },\n ];\n}\n\nfunction linkFields({\n required = false,\n pagesCollection,\n}: {\n required?: boolean;\n pagesCollection?: string;\n} = {}): Field[] {\n return [\n ...linkDestinationFields({ required, pagesCollection }),\n { name: \"label\", type: \"text\", label: \"Label\", required },\n {\n name: \"newTab\",\n type: \"checkbox\",\n label: \"Open in a new tab\",\n defaultValue: false,\n },\n ];\n}\n\nexport function linkField({\n name = \"link\",\n label,\n admin,\n required,\n pagesCollection,\n}: {\n name?: string;\n label?: GroupField[\"label\"];\n admin?: GroupField[\"admin\"];\n required?: boolean;\n pagesCollection?: string;\n} = {}): GroupField {\n return {\n name,\n type: \"group\",\n fields: linkFields({ required, pagesCollection }),\n ...(label === undefined ? {} : { label }),\n ...(admin === undefined ? {} : { admin }),\n };\n}\n\nexport function footerLinkFields({\n required = false,\n pagesCollection,\n}: {\n required?: boolean;\n pagesCollection?: string;\n} = {}): Field[] {\n return linkFields({ required, pagesCollection });\n}\n","import { Forbidden, type GlobalBeforeChangeHook, type GlobalConfig } from \"payload\";\n\nimport { canUseFeature, hideUnlessFeature } from \"../features/access\";\nimport { canPublish, isAuthenticated } from \"../roles/access\";\nimport { footerLinkFields, linkField } from \"./link\";\nimport {\n NAVIGATION_DB_NAME,\n NAVIGATION_FEATURE,\n NAVIGATION_FOOTER_DB_NAME,\n NAVIGATION_FOOTER_SLUG,\n NAVIGATION_SLUG,\n type CreateNavigationOptions,\n} from \"./types\";\n\nconst refusePublishWithoutTick: GlobalBeforeChangeHook = async ({ data, req }) => {\n if (data._status !== \"published\") return data;\n if (!req.user) return data;\n if (await Promise.resolve(canPublish({ req } as never))) return data;\n throw new Forbidden();\n};\n\n/**\n * Header (`navigation` / `nav`) and Footer (`navigation-footer` / `navf`).\n * One Features tick (`navigation`). Independent Save / Publish / drafts —\n * a draft header does not publish the footer.\n */\nexport function createNavigation({\n blocks,\n footerColumnRowLabel,\n footerLinkRowLabel,\n preview,\n livePreview,\n previewButton,\n pagesCollection,\n}: CreateNavigationOptions): [GlobalConfig, GlobalConfig] {\n if (blocks.length === 0) {\n throw new Error(\"createNavigation needs at least one header block\");\n }\n\n const hidden = hideUnlessFeature(NAVIGATION_FEATURE);\n const update = canUseFeature(NAVIGATION_FEATURE);\n const previewAdmin = {\n ...(preview ? { preview } : {}),\n ...(livePreview ? { livePreview } : {}),\n ...(previewButton\n ? { components: { elements: { PreviewButton: previewButton } } }\n : {}),\n };\n\n const header: GlobalConfig = {\n slug: NAVIGATION_SLUG,\n dbName: NAVIGATION_DB_NAME,\n label: \"Header\",\n admin: {\n group: \"Navigation\",\n hidden: hidden as (args: { user: unknown }) => boolean,\n description: \"The public header. A draft never reaches the live site until you publish.\",\n ...previewAdmin,\n },\n access: {\n read: () => true,\n readVersions: isAuthenticated,\n update,\n },\n versions: {\n drafts: { autosave: { interval: 375 } },\n },\n hooks: {\n beforeChange: [refusePublishWithoutTick],\n },\n fields: [\n {\n name: \"header\",\n type: \"group\",\n label: false,\n fields: [\n {\n name: \"items\",\n type: \"blocks\",\n labels: { singular: \"Item\", plural: \"Items\" },\n blocks,\n admin: {\n description:\n \"Bar items, left to right. A mega menu leads with the choice a visitor has to make and keeps the other groups as named lists. A plain link is a bar item with nothing to open. Column widths in a panel must add up to 100%.\",\n },\n },\n linkField({\n name: \"cta\",\n label: \"Header button\",\n required: true,\n pagesCollection,\n admin: {\n description: \"The pill on the right of the bar.\",\n },\n }),\n ],\n },\n ],\n };\n\n const footer: GlobalConfig = {\n slug: NAVIGATION_FOOTER_SLUG,\n dbName: NAVIGATION_FOOTER_DB_NAME,\n label: \"Footer\",\n admin: {\n group: \"Navigation\",\n hidden: hidden as (args: { user: unknown }) => boolean,\n description:\n \"The public footer shortcut columns. A draft never reaches the live site until you publish.\",\n ...previewAdmin,\n },\n access: {\n read: () => true,\n readVersions: isAuthenticated,\n update,\n },\n versions: {\n drafts: { autosave: { interval: 375 } },\n },\n hooks: {\n beforeChange: [refusePublishWithoutTick],\n },\n fields: [\n {\n name: \"footer\",\n type: \"group\",\n label: false,\n fields: [\n {\n name: \"columns\",\n type: \"array\",\n dbName: \"c\",\n labels: { singular: \"Column\", plural: \"Columns\" },\n admin: {\n description:\n \"A shortcut strip, not a sitemap. One entry per heading plus the few pages worth a standing link. Everything omitted here is still reachable from the header. Adding a link back to \\\"complete\\\" a column is the wrong instinct — the omissions are the point.\",\n components: footerColumnRowLabel ? { RowLabel: footerColumnRowLabel } : undefined,\n },\n fields: [\n {\n name: \"heading\",\n type: \"text\",\n required: true,\n label: \"Heading\",\n },\n {\n name: \"links\",\n type: \"array\",\n labels: { singular: \"Link\", plural: \"Links\" },\n admin: {\n components: footerLinkRowLabel ? { RowLabel: footerLinkRowLabel } : undefined,\n },\n fields: footerLinkFields({ required: true, pagesCollection }),\n },\n ],\n },\n ],\n },\n ],\n };\n\n return [header, footer];\n}\n","import type { CollectionConfig, GlobalConfig } from \"payload\";\nimport { definePlugin } from \"payload\";\n\nimport { isDeveloperTab } from \"../roles/access\";\n\ntype Entity = CollectionConfig | GlobalConfig;\n\nfunction gateApiTab<T extends Entity>(entity: T): T {\n const components = entity.admin?.components;\n const edit = components?.views?.edit;\n const api = edit && \"api\" in edit ? edit.api : undefined;\n return {\n ...entity,\n admin: {\n ...entity.admin,\n components: {\n ...components,\n views: {\n ...components?.views,\n edit: {\n ...edit,\n api: { ...api, tab: { ...api?.tab, condition: isDeveloperTab } },\n },\n },\n },\n },\n };\n}\n\n/**\n * Gates the document API tab to Developer, config-wide. After plugins that\n * use `definePlugin` order (MCP is 10), so a collection those plugins\n * register is still covered.\n */\nexport const adminOnlyApiTab = definePlugin({\n slug: \"admin-only-api-tab\",\n order: 1000,\n plugin: ({ config }) => ({\n ...config,\n collections: config.collections?.map(gateApiTab),\n globals: config.globals?.map(gateApiTab),\n }),\n});\n","import type { Config } from \"payload\";\nimport { definePlugin } from \"payload\";\n\nimport { DOCUMENT_TITLE_ACTIONS } from \"../admin/document-controls\";\n\ntype AdminProviders = NonNullable<\n NonNullable<NonNullable<Config[\"admin\"]>[\"components\"]>[\"providers\"]\n>;\n\nfunction asList(value: AdminProviders | undefined): AdminProviders {\n if (!value) return [];\n return value;\n}\n\nfunction alreadyHasTitleActions(providers: AdminProviders): boolean {\n return providers.some((entry) => {\n if (typeof entry === \"string\") return entry === DOCUMENT_TITLE_ACTIONS;\n if (entry && typeof entry === \"object\" && \"path\" in entry) {\n return entry.path === DOCUMENT_TITLE_ACTIONS;\n }\n return false;\n });\n}\n\nfunction withTitleActions(config: Config): Config {\n const providers = asList(config.admin?.components?.providers);\n if (alreadyHasTitleActions(providers)) return config;\n return {\n ...config,\n admin: {\n ...config.admin,\n components: {\n ...config.admin?.components,\n providers: [DOCUMENT_TITLE_ACTIONS, ...providers],\n },\n },\n };\n}\n\n/**\n * Puts every document's primary actions on the title row — the same\n * slot collection lists use for Create New — and hides the dead Edit\n * tab when it has no sibling. One admin provider so Roles, Theme,\n * Features, Account, and a site's own Globals cannot drift.\n */\nexport const documentTitleActions = definePlugin({\n slug: \"document-title-actions\",\n order: 1000,\n plugin: ({ config }) => withTitleActions(config),\n});\n"],"mappings":";;;;;;;;;;;;;;AAOA,MAAa,eAA8B;CACzC,MAAM;CACN,MAAM;CACN,OAAO;CACP,cAAc;CACd,OAAO,EACL,aACE,qHACH;CACF;;;;ACfD,MAAa,qBAAqB;;;;;;;AAQlC,SAAgB,eAAe,MAAc,MAAA,KAAkC;CAC7E,MAAM,UAAU,KAAK,MAAM;AAC3B,KAAI,QAAQ,UAAU,IAAK,QAAO;CAClC,MAAM,MAAM,QAAQ,MAAM,GAAG,IAAI;CACjC,MAAM,YAAY,IAAI,YAAY,IAAI;AACtC,QAAO,GAAG,YAAY,IAAI,IAAI,MAAM,GAAG,UAAU,GAAG,IAAI;;;;;;;;;;;;;;;;ACmD1D,SAAgB,UAAwC,EACtD,UACA,QACA,cACA,UACA,cAAc,CAAC,QAAQ,EACvB,oBAAoB,WACa;CACjC,MAAM,iBAAsC,EAAE,UAC5C,KAAK,QAAQ,cAAc,UAAU,IAAI,MAAM,GAAG;CACpD,MAAM,uBAAkD,EAAE,UACxD,eAAe,eAAe,IAAI,IAAI,GAAG;CAC3C,MAAM,eAAkC,EAAE,UAAU,OAAO,IAAI,IAAI;CAEnE,MAAM,gBAAiD,YAClD,EAAE,UAAU,SAAS,IAAI,IAAI,KAC9B,KAAA;AAEJ,QAAOA,YAAiB;EACtB;EACA;EACA,UAAU;EACV;EACA;EACA;EACA,GAAI,gBAAgB,EAAE,eAAe,GAAG,EAAE;EAC1C,SAAS,EAAE,oBAAoB,CAAC,GAAG,eAAe,aAAa;EAChE,CAAC;;;;;;;;AASJ,SAAgB,aACd,QACA,QAAQ,SACa;AACrB,KAAI,CAAC,MAAM,QAAQ,OAAO,CAAE,QAAO,KAAA;AACnC,MAAK,MAAM,SAAS,QAAQ;AAC1B,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM;EACjD,MAAM,QAAS,MAAkC;EACjD,MAAM,KACJ,OAAO,UAAU,YAAY,UAAU,QAAQ,QAAQ,QAClD,MAA0B,KAC3B;AACN,MAAI,OAAO,OAAO,YAAa,OAAO,OAAO,YAAY,OAAO,GAC9D,QAAO;;;;;;;;;;AC7Gb,MAAa,qBAAqB;CAChC,cAAc;EACZ,OAAO;GAAE,OAAO;GAAS,MAAM;GAA8B;EAC7D,MAAM;GAAE,OAAO;GAAQ,MAAM;GAA6B;EAC1D,QAAQ;GAAE,OAAO;GAAiB,MAAM;GAAwC;EACjF;CACD,QAAQ;EACN,OAAO;GAAE,OAAO;GAAS,MAAM;GAAwB;EACvD,QAAQ;GAAE,OAAO;GAAU,MAAM;GAAgC;EACjE,SAAS;GAAE,OAAO;GAAW,MAAM;GAA6B;EAChE,MAAM;GAAE,OAAO;GAAQ,MAAM;GAA+B;EAC7D;CACD,QAAQ;EACN,MAAM;GAAE,OAAO;GAAQ,MAAM;GAAwB;EACrD,QAAQ;GAAE,OAAO;GAAU,MAAM;GAAqC;EACtE,UAAU;GAAE,OAAO;GAAY,MAAM;GAAsC;EAC5E;CACD,QAAQ;EACN,QAAQ;GAAE,OAAO;GAAS,MAAM;GAAuB;EACvD,QAAQ;GAAE,OAAO;GAAU,MAAM;GAAwB;EACzD,SAAS;GAAE,OAAO;GAAU,MAAM;GAA2B;EAC9D;CACD,SAAS;EACP,SAAS;GAAE,OAAO;GAAW,MAAM;GAA+B;EAClE,SAAS;GAAE,OAAO;GAAY,MAAM;GAA8B;EAClE,UAAU;GAAE,OAAO;GAAY,MAAM;GAA2C;EACjF;CACF;;;;AC3BD,MAAa,oBAAoB;;;;;AAkEjC,eAAsB,gBACpB,SACA,QACA,KACuB;CACvB,MAAM,EAAE,aAAa,YAAY,cAAc,SAAS,OAAO;CAC/D,MAAM,SAAuB,EAAE;AAC/B,MAAK,MAAM,cAAc,YACvB,YAAW,MAAM,OAAO,kBAAkB,SAAS,WAAW,CAC5D,MAAK,MAAM,OAAO,gBAAgB,KAAK,IAAI,CACzC,QAAO,KAAK;EAAE;EAAY,IAAI,KAAK,IAAI;EAAE,MAAM,IAAI;EAAM,OAAO,IAAI;EAAO,CAAC;AAIlF,MAAK,MAAM,QAAQ,SAAS;EAC1B,MAAM,MAAM,MAAM,WAAW,SAAS,KAAK;AAC3C,MAAI,CAAC,IAAK;AACV,OAAK,MAAM,OAAO,gBAAgB,KAAK,IAAI,CACzC,QAAO,KAAK;GAAE,QAAQ;GAAM,MAAM,IAAI;GAAM,OAAO,IAAI;GAAO,CAAC;;AAGnE,QAAO;;AAGT,eAAsB,mBACpB,SACA,QACA,SACA,OACe;CACf,MAAM,EAAE,aAAa,YAAY,cAAc,SAAS,OAAO;AAC/D,MAAK,MAAM,cAAc,YACvB,YAAW,MAAM,OAAO,kBAAkB,SAAS,WAAW,EAAE;AAC9D,MAAI,gBAAgB,KAAK,QAAQ,CAAC,WAAW,EAAG;EAChD,MAAM,EAAE,IAAI,KAAK,GAAG,SAAS,mBAAmB,KAAK,SAAS,MAAM;EACpE,MAAM,KAAK,KAAK,IAAI;AACpB,MAAI,MAAM,KAAM;AAChB,QAAM,QAAQ,OAAO;GACnB;GACA;GACA;GACA,OAAO;GACP,gBAAgB;GACjB,CAAC;;AAGN,MAAK,MAAM,QAAQ,SAAS;EAC1B,MAAM,MAAM,MAAM,WAAW,SAAS,KAAK;AAC3C,MAAI,CAAC,OAAO,gBAAgB,KAAK,QAAQ,CAAC,WAAW,EAAG;AACxD,QAAM,QAAQ,aAAa;GACzB;GACA,MAAM,mBAAmB,KAAK,SAAS,MAAM;GAC7C,OAAO;GACP,gBAAgB;GACjB,CAAC;;;AAIN,eAAsB,gBAAgB,SAA4B,QAAmC;AAMnG,QAAO,gBALM,MAAM,QAAQ,WAAW;EACpC,MAAM;EACN,OAAO;EACP,gBAAgB;EACjB,CAAC,CACyB,CACxB,KAAK,SAAS,KAAK,MAAM,CACzB,QAAQ,QAAQ,QAAQ,OAAO;;AAGpC,SAAgB,cACd,SACA,QACgE;AAChE,KAAI,WAAW,KAAM,QAAO,iBAAiB,QAAQ;AACrD,QAAO;EACL,aAAa,QAAQ,eAAe,EAAE;EACtC,SAAS,QAAQ,WAAW,EAAE;EAC/B;;AAGH,SAAS,iBAAiB,SAA0E;AAClG,QAAO;EACL,aAAa,QAAQ,QAAQ,QAAQ,eAAe,QAAQ,YAAY,CAAC,QACtE,SAAS,CAAC,KAAK,WAAW,WAAW,CACvC;EACD,SAAS,QAAQ,QAAQ,QAAQ,WAAW,QAAQ,SAAS,OAAO,CAAC,QAClE,SAAS,SAAS,WACpB;EACF;;AAGH,SAAS,QAAQ,OAAkE;AACjF,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO,MAAM,KAAK,SAAS,MAAM,KAAK,CAAC,QAAQ,SAAyB,QAAQ,KAAK,CAAC;AAExF,KAAI,SAAS,OAAO,UAAU,SAAU,QAAO,OAAO,KAAK,MAAM;AACjE,QAAO,EAAE;;AAGX,eAAe,WACb,SACA,MACgE;AAChE,KAAI;AACF,SAAO,MAAM,QAAQ,WAAW;GAAE;GAAM,OAAO;GAAM,OAAO;GAAG,gBAAgB;GAAM,CAAC;SAChF;AAEN,SAAO;;;AAIX,gBAAgB,kBACd,SACA,YACyC;CACzC,IAAI,OAAO;AACX,UAAS;EACP,IAAI;AACJ,MAAI;AACF,YAAS,MAAM,QAAQ,KAAK;IAC1B;IACA,OAAO;IACP,OAAO;IACP,OAAO;IACP;IACA,gBAAgB;IACjB,CAAC;UACI;AACN;;AAEF,OAAK,MAAM,OAAO,OAAO,KAAM,OAAM;EACrC,MAAM,aAAa,OAAO,eAAe,OAAO,KAAK,SAAS,MAAM,OAAO,OAAO;AAClF,MAAI,QAAQ,cAAc,OAAO,KAAK,WAAW,EAAG;AACpD,UAAQ;;;AAIZ,SAAS,KAAK,KAA2D;CACvE,MAAM,KAAK,IAAI;AACf,QAAO,OAAO,OAAO,YAAY,OAAO,OAAO,WAAW,KAAK,KAAA;;;;ACrMjE,SAAgB,oBACd,QACA,QACY;AACZ,QAAO,CACL;EACE,MAAM;EACN,QAAQ;EACR,SAAS,OAAO,QAAQ;GACtB,MAAM,SAAS,MAAM,iBAAiB,KAAK,OAAO,OAAO;AACzD,OAAI,OAAQ,QAAO;GACnB,MAAM,MAAM,SAAS,IAAI;AACzB,OAAI,CAAC,IAAK,QAAO,SAAS,KAAK,EAAE,OAAO,mBAAmB,EAAE,EAAE,QAAQ,KAAK,CAAC;GAC7E,MAAM,SAAS,MAAM,gBAAgB,IAAI,SAAyC,QAAQ,IAAI;AAC9F,UAAO,SAAS,KAAK,EAAE,QAAQ,CAAC;;EAEnC,EACD;EACE,MAAM;EACN,QAAQ;EACR,SAAS,OAAO,QAAQ;GACtB,MAAM,SAAS,MAAM,iBAAiB,KAAK,OAAO,OAAO;AACzD,OAAI,OAAQ,QAAO;GACnB,MAAM,OAAQ,MAAM,SAAS,IAAI;GACjC,MAAM,MAAM,OAAO,MAAM,QAAQ,WAAW,KAAK,MAAM;GACvD,MAAM,cAAc,OAAO,MAAM,gBAAgB,WAAW,KAAK,cAAc;AAC/E,OAAI,CAAC,OAAO,CAAC,YACX,QAAO,SAAS,KAAK,EAAE,OAAO,oCAAoC,EAAE,EAAE,QAAQ,KAAK,CAAC;AAGtF,OAAI,EADS,MAAM,gBAAgB,IAAI,SAAyC,IAAI,EAC1E,SAAS,YAAY,CAC7B,QAAO,SAAS,KACd,EAAE,OAAO,uEAAuE,EAChF,EAAE,QAAQ,KAAK,CAChB;AAEH,SAAM,mBAAmB,IAAI,SAAyC,QAAQ,KAAK,YAAY;AAC/F,UAAO,SAAS,KAAK,EAAE,IAAI,MAAM,CAAC;;EAErC,CACF;;AAGH,eAAe,iBAAiB,KAAqB,QAA0C;AAE7F,KADgB,MAAM,OAAO,EAAE,KAAK,CAAC,CACxB,QAAO;AACpB,QAAO,SAAS,KAAK,EAAE,OAAO,aAAa,EAAE,EAAE,QAAQ,KAAK,CAAC;;AAG/D,SAAS,SAAS,KAA6B;CAC7C,MAAM,YAAY,IAAI,OAAO;AAC7B,KAAI,OAAO,cAAc,SAAU,QAAO;AAC1C,KAAI,MAAM,QAAQ,UAAU,IAAI,OAAO,UAAU,OAAO,SAAU,QAAO,UAAU;AACnF,KAAI,IAAI,IACN,KAAI;AACF,SAAO,IAAI,IAAI,IAAI,KAAK,eAAe,CAAC,aAAa,IAAI,MAAM,IAAI;SAC7D;AACN,SAAO;;AAGX,QAAO;;AAGT,eAAe,SAAS,KAAuC;AAC7D,KAAI,OAAO,IAAI,SAAS,WAAY,QAAO,IAAI,MAAM;AACrD,QAAO;;;;AC9ET,MAAa,gBAAgB;AAE7B,MAAa,iBAAiB;CAAC;CAAS;CAAS;CAAS;CAAQ;AAIlE,MAAa,uBAAuD;CAClE,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACR;AAED,MAAa,wBAAwB;CACnC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;;;;AAeD,MAAa,mBAA8C;CACzD;EAAE,MAAM;EAAW,OAAO;EAAW,OAAO;EAAS,iBAAiB;EAAM;CAC5E;EAAE,MAAM;EAAW,OAAO;EAAW,OAAO;EAAS,iBAAiB;EAAM;CAC5E;EAAE,MAAM;EAAS,OAAO;EAAS,OAAO;EAAS,iBAAiB;EAAM;CACxE;EAAE,MAAM;EAAgB,OAAO;EAAU,OAAO;EAAS,iBAAiB;EAAM;CAChF;EAAE,MAAM;EAAoB,OAAO;EAAc,OAAO;EAAS,iBAAiB;EAAM;CACxF;EAAE,MAAM;EAAoB,OAAO;EAAc,OAAO;EAAS,iBAAiB;EAAM;CACxF;EAAE,MAAM;EAAkB,OAAO;EAAY,OAAO;EAAS,iBAAiB;EAAM;CACpF;EAAE,MAAM;EAAgB,OAAO;EAAgB,OAAO;EAAS,iBAAiB;EAAM;CACtF;EAAE,MAAM;EAAS,OAAO;EAAS,OAAO;EAAS,iBAAiB;EAAM;CACxE;EAAE,MAAM;EAAS,OAAO;EAAS,OAAO;EAAS,iBAAiB;EAAM;CACzE;AAsBD,SAAgB,iBAAiB,OAAyC;AACxE,QAAO,OAAO,UAAU,YAAa,eAAqC,SAAS,MAAM;;AAG3F,SAAgB,qBAAqB,OAA6C;AAChF,QAAO,OAAO,UAAU,YAAa,sBAA4C,SAAS,MAAM;;AAGlG,SAAgB,cAAc,OAAiC;AAC7D,QAAO,OAAO,UAAU,YAAY,gCAAgC,KAAK,MAAM;;;AAIjF,SAAgB,gBAAgB,OAAe,SAAmC;AAChF,QAAO;;;;AC3ET,MAAa,mCACX;AASF,SAAgB,iBAAiB,SAAkC,EAAE,EAA2B;AAC9F,QAAO,CACL,GAAG,iBAAiB,KAAK,aAAa,EAAE,GAAG,SAAS,EAAE,EACtD,GAAG,OAAO,KAAK,WAAW;EACxB,MAAM,MAAM;EACZ,OAAO,MAAM;EACb,OAAO,MAAM,SAAS;EACtB,iBAAiB,MAAM,mBAAmB;EAC3C,EAAE,CACJ;;AAGH,SAAgB,0BAA0B,SAAkC,EAAE,EAAgB;AAC5F,QAAO,iBAAiB,OAAO,CAAC,KAAK,aAAa;EAChD,IAAI,QAAQ;EACZ,MAAM,QAAQ;EACd,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,UAAU,QAAQ;EACnB,EAAE;;AAGL,SAAgB,sBACd,OACA,SAAkC,EAAE,EACtB;CACd,MAAM,SAAS,IAAI,IAAI,iBAAiB,OAAO,CAAC,KAAK,YAAY,CAAC,QAAQ,MAAM,QAAQ,CAAC,CAAC;AAC1F,KAAI,CAAC,MAAM,QAAQ,MAAM,CAAE,QAAO,0BAA0B,OAAO;AACnE,QAAO,MAAM,SAAS,SAAS;AAC7B,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO,EAAE;EAChD,MAAM,OAAO,UAAU,QAAQ,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO;EAC3E,MAAM,UAAU,OAAO,IAAI,KAAK;AAChC,MAAI,CAAC,QAAS,QAAO,EAAE;AACvB,SAAO,CACL;GACE,IAAI,QAAQ;GACZ,MAAM,QAAQ;GACd,OAAO,QAAQ;GACf,OAAO,QAAQ;GACf,UAAU,QAAQ,cAAc,QAAQ,KAAK,SAAS;GACvD,CACF;GACD;;AAGJ,SAAgB,oBACd,OACmE;AACnE,KAAI,CAAC,MAAM,QAAQ,MAAM,IAAI,MAAM,WAAW,EAC5C,QAAO;EAAE,IAAI;EAAO,SAAS;EAAkC;CAGjE,MAAM,OAAqB,EAAE;CAC7B,MAAM,uBAAO,IAAI,KAAa;AAE9B,MAAK,MAAM,QAAQ,OAAO;AACxB,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;EACvC,MAAM,OAAO,UAAU,OAAO,KAAK,OAAO,KAAA;AAC1C,MAAI,CAAC,cAAc,KAAK,IAAI,KAAK,IAAI,KAAK,CAAE;AAC5C,OAAK,IAAI,KAAK;EACd,MAAM,OAAO,iBAAiB,MAAM,YAAY,QAAQ,SAAS,KAAK;EACtE,MAAM,QACJ,WAAW,QAAQ,OAAO,KAAK,UAAU,WACrC,KAAK,QACJ,MAAM,SAAS;EACtB,MAAM,QACJ,WAAW,QAAQ,iBAAiB,KAAK,MAAM,GAAG,KAAK,QAAS,MAAM,SAAS;AACjF,OAAK,KAAK;GACR,IAAI;GACJ;GACA;GACA;GACA,UAAU,QAAQ,cAAc,QAAQ,KAAK,SAAS;GACvD,CAAC;;AAGJ,KAAI,iBAAiB,MAAM,YAAY,CAAC,KAAK,IAAI,QAAQ,KAAK,CAAC,CAC7D,QAAO;EAAE,IAAI;EAAO,SAAS;EAAkC;AAEjE,QAAO;EAAE,IAAI;EAAM;EAAM;;AAG3B,SAAgB,uBACd,OACA,SAAkC,EAAE,EACrB;CACf,MAAM,SAAS,oBAAoB,MAAM;AACzC,KAAI,CAAC,OAAO,GAAI,QAAO,OAAO;CAC9B,MAAM,UAAU,IAAI,IAAI,iBAAiB,OAAO,CAAC,KAAK,YAAY,QAAQ,KAAK,CAAC;AAChF,KAAI,OAAO,KAAK,MAAM,QAAQ,CAAC,QAAQ,IAAI,IAAI,KAAK,CAAC,CAAE,QAAO;AAC9D,QAAO;;AAGT,SAAgB,kBAAkB,OAAuB;AACvD,QAAO,iBAAiB,MAAM,GAAG,qBAAqB,SAAS;;AAGjE,SAAgB,oBAAoB,MAAc,SAAkC,EAAE,EAAU;CAC9F,MAAM,OAAO,iBAAiB,MAAM,YAAY,QAAQ,SAAS,KAAK;AACtE,KAAI,KAAM,QAAO,KAAK;AAEtB,QADc,OAAO,MAAM,YAAY,QAAQ,SAAS,KAAK,EAC/C,SAAS;;AAGzB,SAAgB,gBAAgB,MAAuB;AACrD,QAAO,iBAAiB,KAAK,IAAI,CAAC,iBAAiB,MAAM,YAAY,QAAQ,SAAS,KAAK;;;;;;;;;ACxH7F,MAAa,QAAQ;CAAC;CAAa;CAAS;CAAY;CAAS;AAIjE,MAAa,cAAoC;CAC/C,WAAW;CACX,OAAO;CACP,UAAU;CACV,QAAQ;CACT;;AAGD,MAAa,eAAe;CAAC;CAAW;CAAS;CAAW;CAAQ;AAIpE,MAAa,sBAAsB;CACjC;CACA;CACA;CACA;CACA;CACD;AAED,MAAa,sBAA6D;CACxE,SAAS,CAAC,UAAU;CACpB,SAAS,CAAC,UAAU;CACpB,OAAO,CAAC,QAAQ;CAChB,OAAO;CACR;AAED,MAAa,sBAAuD;CAClE,WAAW,EAAE;CACb,OAAO;EAAC;EAAW;EAAW;EAAS;EAAS;EAAQ;CACxD,UAAU;EACR;EACA;EACA,GAAG;EACH;EACA;EACD;CACD,QAAQ,CAAC,WAAW,QAAQ;CAC7B;AAmCD,SAAgB,OAAO,OAA+B;AACpD,QAAO,OAAO,UAAU,YAAa,MAA4B,SAAS,MAAM;;;AAIlF,SAAgB,WAAW,OAAiC;AAC1D,QAAO,OAAO,UAAU,YAAY,qBAAqB,KAAK,MAAM;;;AAItE,SAAgB,WAAW,OAAiC;AAC1D,QAAO,OAAO,UAAU,YAAY,6BAA6B,KAAK,MAAM,MAAM,CAAC;;;AAIrF,SAAgB,sBAAsB,OAAuB;AAC3D,QAAO,MAAM,QAAQ,eAAe,GAAG,CAAC,QAAQ,UAAU,IAAI;;;AAIhE,SAAgB,gBAAgB,OAAwB;AACtD,KAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAO,MACJ,MAAM,CACN,aAAa,CACb,QAAQ,YAAY,IAAI,CACxB,QAAQ,UAAU,GAAG;;AAG1B,SAAgB,UAAU,MAAc,OAA+B;CACrE,MAAM,UAAU,OAAO,UAAU,WAAW,MAAM,MAAM,GAAG;AAC3D,KAAI,QAAS,QAAO;AACpB,QAAO,OAAO,KAAK,GAAG,YAAY,QAAQ;;AAG5C,SAAgB,qBAAqB,MAAc,aAA2C;AAC5F,KAAI,OAAO,KAAK,CAAE,QAAO,CAAC,GAAG,oBAAoB,MAAM;AACvD,QAAO,cAAc,CAAC,GAAG,YAAY,GAAG,EAAE;;;;ACtG5C,MAAa,aAAa;AAE1B,MAAa,2BAA2B;AAExC,MAAa,0BACX;;;;;AAMF,MAAa,sBAA0C,MAAM,KAAK,UAAU;CAC1E;CACA,QAAQ,qBAAqB,KAAK;CACnC,EAAE;AAEH,MAAa,wBACX;AAEF,MAAa,0BACX;AAEF,MAAa,6BAA6B;AAE1C,MAAa,8BAA8B;AAE3C,MAAa,8BAA8B;AAE3C,MAAa,4BAA4B;AAEzC,SAAS,YAAY,QAAsC;CACzD,MAAM,QAAkB,EAAE;AAC1B,MAAK,MAAM,SAAS,OAClB,KAAI,OAAO,UAAU,YAAY,cAAc,MAAM,IAAI,CAAC,MAAM,SAAS,MAAM,CAAE,OAAM,KAAK,MAAM;AAEpG,QAAO;;;AAIT,SAAgB,qBAAqB,MAAwB;AAC3D,KAAI,YAAY,QAAQ,MAAM,QAAQ,KAAK,OAAO,CAAE,QAAO,YAAY,KAAK,OAAO;CACnF,MAAM,SAAmB,EAAE;AAC3B,KAAI,aAAa,QAAQ,KAAK,QAC5B,QAAO,KAAK,WAAW,QAAQ;AAEjC,KAAI,aAAa,QAAQ,KAAK,QAAS,QAAO,KAAK,UAAU;AAC7D,KAAI,WAAW,QAAQ,KAAK,MAAO,QAAO,KAAK,SAAS,QAAQ;AAChE,KAAI,WAAW,QAAQ,KAAK,MAAO,QAAO,KAAK,GAAG,oBAAoB;AACtE,QAAO,YAAY,OAAO;;AAG5B,SAAgB,aAAa,SAA+B,EAAE,EAAa;AACzE,QAAO,CACL,GAAG,oBAAoB,KAAK,SAAS;EACnC,GAAG;EACH,QAAQ,CAAC,GAAG,IAAI,OAAO;EACvB,OAAO,OAAO,IAAI,KAAK,GAAG,YAAY,IAAI,QAAQ,IAAI;EACvD,EAAE,EACH,GAAG,OAAO,KAAK,WAAW;EACxB,MAAM,MAAM;EACZ,OAAO,MAAM;EACb,QAAQ,MAAM,SAAS,CAAC,GAAG,MAAM,OAAO,GAAG,EAAE;EAC9C,EAAE,CACJ;;AAGH,SAAgB,uBAAuB,SAA+B,EAAE,EAAa;AACnF,QAAO,aAAa,OAAO,CAAC,KAAK,SAAS;EAAE,IAAI,IAAI;EAAM,GAAG;EAAK,EAAE;;AAGtE,SAAS,YAAY,MAA2C;CAC9D,MAAM,OAAO,UAAU,OAAO,KAAK,OAAO,KAAA;AAC1C,KAAI,OAAO,SAAS,YAAY,KAAK,MAAM,KAAK,GAAI,QAAO,EAAE,OAAO,6BAA6B;AACjG,KAAI,CAAC,WAAW,KAAK,CAAE,QAAO,EAAE,OAAO,6BAA6B;AAEpE,QAAO;EACL,IAAI;EACJ;EACA,OAAO,UAAU,MAJL,WAAW,QAAQ,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,KAAA,EAIhD;EAC7B,QAAQ,qBAAqB,KAAK;EACnC;;AAGH,SAAgB,iBACd,OACgE;AAChE,KAAI,CAAC,MAAM,QAAQ,MAAM,CACvB,QAAO;EAAE,IAAI;EAAO,SAAS;EAA4B;CAG3D,MAAM,OAAkB,EAAE;CAC1B,MAAM,uBAAO,IAAI,KAAa;AAC9B,MAAK,MAAM,QAAQ,OAAO;AACxB,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;EAGvC,MAAM,OAAO,UAAU,OAAO,KAAK,OAAO,KAAA;AAC1C,MAAI,OAAO,SAAS,YAAY,KAAK,MAAM,KAAK,GAAI;EACpD,MAAM,SAAS,YAAY,KAAK;AAChC,MAAI,WAAW,OAAQ,QAAO;GAAE,IAAI;GAAO,SAAS,OAAO;GAAO;AAClE,MAAI,KAAK,IAAI,OAAO,KAAK,CAAE,QAAO;GAAE,IAAI;GAAO,SAAS;GAA6B;AACrF,OAAK,IAAI,OAAO,KAAK;AACrB,OAAK,KAAK,OAAO;;AAGnB,KAAI,CAAC,KAAK,IAAI,YAAY,CACxB,QAAO;EAAE,IAAI;EAAO,SAAS;EAA4B;AAE3D,QAAO;EAAE,IAAI;EAAM;EAAM;;AAG3B,SAAgB,aAAa,KAAc,MAAuB;AAChE,KAAI,IAAI,SAAS,YAAa,QAAO;AACrC,QAAO,IAAI,OAAO,SAAS,KAAK;;AAGlC,SAAgB,kBAAkB,KAAc,YAAiC;AAC/E,KAAI,IAAI,SAAS,YAAa,QAAO;AACrC,QAAO,oBAAoB,YAAY,MAAM,SAAS,IAAI,OAAO,SAAS,KAAK,CAAC;;;;;;AAOlF,SAAgB,wBAAwB,OAAyB;AAC/D,KAAI,CAAC,MAAM,QAAQ,MAAM,CAAE,QAAO;AAClC,QAAO,MAAM,KAAK,SAAS;AACzB,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;EAC9C,MAAM,MAAM;AACZ,MAAI,WAAW,IAAI,KAAK,CAAE,QAAO;EACjC,MAAM,OAAO,gBAAgB,IAAI,MAAM;AACvC,SAAO,WAAW,KAAK,GAAG;GAAE,GAAG;GAAK,MAAM;GAAM,GAAG;GACnD;;AAGJ,SAAS,sBAAsB,OAAyB;AACtD,KAAI,CAAC,MAAM,QAAQ,MAAM,CAAE,QAAO;CAClC,MAAM,uBAAO,IAAI,KAAa;AAC9B,MAAK,MAAM,QAAQ,OAAO;AACxB,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;EACvC,MAAM,OAAO,UAAU,QAAQ,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO;EAE3E,MAAM,QADM,WAAW,QAAQ,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,IAC5D,MAAM,KAAK,OAAO,KAAK,GAAG,YAAY,QAAQ;AAC/D,MAAI,CAAC,KAAM;EACX,MAAM,MAAM,KAAK,aAAa;AAC9B,MAAI,KAAK,IAAI,IAAI,CAAE,QAAO;AAC1B,OAAK,IAAI,IAAI;;AAEf,QAAO;;AAGT,SAAS,mBAAmB,OAAyB;AACnD,KAAI,CAAC,MAAM,QAAQ,MAAM,CAAE,QAAO;AAClC,MAAK,MAAM,QAAQ,OAAO;AACxB,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;EACvC,MAAM,QAAQ,WAAW,QAAQ,OAAO,KAAK,UAAU,WAAW,KAAK,MAAM,MAAM,GAAG;AACtF,MAAI,CAAC,MAAO;AACZ,MAAI,CAAC,WAAW,MAAM,CAAE,QAAO;;AAEjC,QAAO;;AAGT,SAAgB,oBAAoB,OAA+B;AACjE,KAAI,sBAAsB,MAAM,CAAE,QAAO;AACzC,KAAI,mBAAmB,MAAM,CAAE,QAAO;CACtC,MAAM,SAAS,iBAAiB,wBAAwB,MAAM,CAAC;AAC/D,KAAI,CAAC,OAAO,GAAI,QAAO,OAAO;AAC9B,QAAO;;;;;;;AAQT,SAAgB,qBACd,OACA,SAA6B,qBACnB;AACV,KAAI,CAAC,MAAM,QAAQ,MAAM,CAAE,QAAO,EAAE;CACpC,MAAM,UAAU,IAAI,IAAI,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC;CACtD,MAAM,QAAQ,CAAC,GAAG,IAAI,IAAI,MAAM,QAAQ,UAA2B,OAAO,UAAU,YAAY,QAAQ,IAAI,MAAM,CAAC,CAAC,CAAC;AACrH,KAAI,MAAM,SAAS,YAAY,CAAE,QAAO,CAAC,YAAY;AACrD,QAAO;;AAGT,SAAgB,kBAAkB,SAA6B,qBAAqB;AAClF,QAAO,OAAO,KAAK,SAAS;EAAE,OAAO,UAAU,IAAI,MAAM,IAAI,MAAM;EAAE,OAAO,IAAI;EAAM,EAAE;;;AAI1F,SAAgB,gBAAgB,MAAc,SAA6B,qBAA6B;AACtG,KAAI,SAAS,YAAa,QAAO;CACjC,MAAM,MAAM,OAAO,MAAM,UAAU,MAAM,SAAS,KAAK;AACvD,KAAI,CAAC,IAAK,QAAO;AAEjB,QADc,IAAI,OAAO,KAAK,SAAS,oBAAoB,KAAK,CAAC,CACpD,KAAK,KAAK,IAAI;;;;;AAM7B,SAAgB,iBAAiB,SAA6B;CAC5D,MAAM,SAAoB,EAAE;AAC5B,KAAI,MAAM,QAAQ,QAAQ,CACxB,MAAK,MAAM,QAAQ,SAAS;AAC1B,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;EACvC,MAAM,SAAS,YAAY,KAAK;AAChC,MAAI,WAAW,UAAU,OAAO,OAAO,KAAK,CAAE;AAC9C,SAAO,KAAK,OAAO;;AAGvB,QAAO,CAAC,GAAG,wBAAwB,EAAE,GAAG,OAAO;;;;ACpNjD,SAASC,eAAa,OAAqC;AACzD,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,SAAS;;AAGjE,SAAgB,YAAY,MAAoC;AAC9D,QAAO,MAAM,QAAQ,MAAM,MAAM,GAAG,KAAK,QAAQ,EAAE;;AAGrD,SAAgB,QAAQ,MAAiB,MAAuB;AAC9D,QAAO,YAAY,KAAK,CAAC,SAAS,KAAK;;;AAIzC,SAAgB,YAAY,MAA0B;AACpD,QAAO,QAAQ,MAAM,YAAY;;AAGnC,SAAgB,cACd,MACA,YACA,SAA6B,qBACpB;AACT,KAAI,YAAY,KAAK,CAAE,QAAO;AAC9B,QAAO,YAAY,KAAK,CAAC,MAAM,SAAS;EACtC,MAAM,MAAM,OAAO,MAAM,UAAU,MAAM,SAAS,KAAK;AACvD,SAAO,MAAM,kBAAkB,KAAK,WAAW,GAAG;GAClD;;AAGJ,SAAgB,SACd,MACA,MACA,SAA6B,qBACpB;AACT,KAAI,YAAY,KAAK,CAAE,QAAO;AAC9B,QAAO,YAAY,KAAK,CAAC,MAAM,SAAS;EACtC,MAAM,MAAM,OAAO,MAAM,UAAU,MAAM,SAAS,KAAK;AACvD,SAAO,MAAM,aAAa,KAAK,KAAK,GAAG;GACvC;;;;;;;AAQJ,eAAsB,eACpB,MAAyB,EAAE,EAC3B,SAA+B,EAAE,EACb;CACpB,MAAM,WAAW,aAAa,OAAO;CACrC,MAAM,aAAa,IAAI,SAAS;AAChC,KAAI,OAAO,eAAe,WAAY,QAAO;AAC7C,KAAI;EACF,MAAM,MAAM,MAAM,WAAW;GAC3B,MAAM;GACN,gBAAgB;GACX;GACN,CAAC;EACF,MAAM,SAAS,iBAAiB,OAAO,OAAO,QAAQ,YAAY,WAAW,MAAM,IAAI,QAAQ,KAAA,EAAU;AACzG,SAAO,OAAO,KAAK,OAAO,OAAO;SAC3B;AACN,SAAO;;;AAIX,SAAS,oBAAoB,YAA6C;CACxE,SAAS,UACP,YACA,QAC4B;AAC5B,MAAIA,eAAa,WAAW,EAAE;GAC5B,MAAM,OAAO,WAAW,IAAI;AAC5B,OAAI,OAAQ,QAAO,cAAc,MAAM,YAAY,OAAO;AAC1D,UAAO,eAAe,WAAW,IAAI,CAAC,MAAM,SAAS,cAAc,MAAM,YAAY,KAAK,CAAC;;AAE7F,SAAO,cAAc,YAAY,YAAY,UAAU,oBAAoB;;AAE7E,QAAO;;AAGT,MAAa,mBAAmB,oBAAoB,UAAU;AAC9D,MAAa,iBAAiB,oBAAoB,QAAQ;AAC1D,MAAa,aAAa,oBAAoB,UAAU;;AAGxD,MAAa,UAAU,oBAAoB,QAAQ;;AAGnD,SAAgB,iBACd,MACA,SAA6B,qBACpB;AACT,KAAI,OAAO,SAAS,SAAU,QAAO;AACrC,KAAI,SAAS,YAAa,QAAO;CACjC,MAAM,MAAM,OAAO,MAAM,UAAU,MAAM,SAAS,KAAK;AACvD,QAAO,MAAM,aAAa,KAAK,QAAQ,GAAG;;AAK5C,SAAgB,gBAAgB,YAA6C;AAC3E,KAAIA,eAAa,WAAW,CAAE,QAAO,QAAQ,WAAW,IAAI,KAAK;AACjE,QAAO,QAAQ,WAAW;;AAG5B,MAAa,gBAAwB,OAAO,EAAE,UAAU;AACtD,KAAI,CAAC,IAAI,KAAM,QAAO;AACtB,KAAI,MAAM,QAAQ,EAAE,KAAK,CAAC,CAAE,QAAO;AACnC,QAAO,EAAE,IAAI,EAAE,QAAQ,IAAI,KAAK,IAAI,EAAE;;AAGxC,MAAa,4BAAoC,EAAE,KAAK,EAAE,aAAa;AACrE,KAAI,gBAAgB,KAAkB,CAAE,QAAO;AAC/C,QAAO,EAAE,SAAS,EAAE,QAAQ,aAAa,EAAE;;;;;;AAO7C,SAAgB,eAAe,EAAE,OAA4B;AAC3D,QAAO,YAAY,IAAI,KAAkB;;;AAI3C,SAAgB,sBAAwD;AACtE,QAAO;EACL,OAAO,EAAE,UAAU,YAAY,IAAI,KAAkB;EACrD,SAAS,EAAE,UAAU,YAAY,IAAI,KAAkB;EACxD;;;AAIH,SAAgB,oBAAoB,EAAE,QAAuC;AAC3E,QAAO,CAAC,YAAY,KAAK;;;;ACtI3B,SAAS,aAAa,OAAqC;AACzD,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,SAAS;;AAGjE,SAAS,kBACP,MACA,MACA,KACA,QACS;AACT,KAAI,CAAC,IAAI,SAAU,QAAO;AAC1B,QAAO,SAAS,MAAM,MAAM,OAAO;;;;;;;AAQrC,SAAgB,WACd,MACA,MACA,WAAyC,MACzC,SAA6B,qBACpB;AACT,KAAI,YAAY,KAAK,CAAE,QAAO;AAC9B,KAAI,CAAC,KAAM,QAAO;CAClB,MAAM,OAAO,YAAY,SAAS,SAAS,IAAI,WAAW,2BAA2B;CACrF,MAAM,OAAO,KAAK,MAAM,UAAU,MAAM,SAAS,KAAK;AACtD,KAAI,KAAM,QAAO,kBAAkB,MAAM,MAAM,MAAM,OAAO;AAC5D,KAAI,CAAC,gBAAgB,KAAK,CAAE,QAAO;AACnC,QAAO,KAAK,MAAM,UAAU,MAAM,UAAU,QAAQ,kBAAkB,MAAM,MAAM,MAAM,OAAO,OAAO,CAAC;;;;;;AAOzG,eAAsB,kBAAkB,MAAyB,EAAE,EAAgC;CACjG,MAAM,aAAa,IAAI,SAAS;AAChC,KAAI,OAAO,eAAe,WAAY,QAAO;AAC7C,KAAI;EACF,MAAM,MAAM,MAAM,WAAW;GAC3B,MAAM;GACN,gBAAgB;GACX;GACN,CAAC;EACF,MAAM,SAAS,oBACb,OAAO,OAAO,QAAQ,YAAY,cAAc,MAAM,IAAI,WAAW,KAAA,EACtE;AACD,SAAO,OAAO,KAAK,OAAO,OAAO;SAC3B;AACN,SAAO;;;;;;;AAQX,SAAgB,cAAc,MAAgC;CAC5D,SAAS,UACP,YACA,UACA,OAC4B;AAC5B,MAAI,aAAa,WAAW,EAAE;GAC5B,MAAM,OAAO,WAAW,IAAI;AAC5B,OAAI,aAAa,KAAA,EAAW,QAAO,WAAW,MAAM,MAAM,UAAU,SAAS,oBAAoB;AACjG,UAAO,QAAQ,IAAI,CAAC,kBAAkB,WAAW,IAAI,EAAE,eAAe,WAAW,IAAI,CAAC,CAAC,CAAC,MACrF,CAAC,MAAM,YAAY,WAAW,MAAM,MAAM,MAAM,OAAO,CACzD;;AAEH,SAAO,WAAW,YAAY,MAAM,YAAY,MAAM,SAAS,oBAAoB;;AAErF,QAAO;;;;;;;AAQT,eAAsB,uBACpB,MACA,MAAyB,EAAE,EACR;CACnB,MAAM,CAAC,UAAU,SAAS,MAAM,QAAQ,IAAI,CAAC,kBAAkB,IAAI,EAAE,eAAe,IAAI,CAAC,CAAC;AAG1F,QADc,CAAC,IADF,YAAY,SAAS,SAAS,IAAI,WAAW,2BAA2B,EAC9D,KAAK,QAAQ,IAAI,KAAK,EAAE,GAAG,eAAe,CACpD,QAAQ,SAAS,WAAW,MAAM,MAAM,UAAU,MAAM,CAAC;;AAGxE,SAAS,sBAAsB,MAAiB,MAAuB;AACrE,KAAI,YAAY,KAAK,CAAE,QAAO;CAC9B,MAAM,UAAU,MAAM;AACtB,KAAI,CAAC,MAAM,QAAQ,QAAQ,CAAE,QAAO;AACpC,QAAO,QAAQ,SAAS,KAAK;;;AAI/B,SAAgB,kBAAkB,MAAc;AAC9C,SAAQ,SAAwD;EAC9D,MAAM,OAAO,KAAK,QAAQ;AAC1B,MAAI,YAAY,KAAK,CAAE,QAAO;AAC9B,MAAI,QAAQ,MAAM,QAAQ,KAAK,gBAAgB,CAC7C,QAAO,CAAC,sBAAsB,MAAM,KAAK;AAE3C,MAAI,KAAK,KAAK;GACZ,MAAM,SAAS,cAAc,KAAK,CAAC,EAAE,KAAK;IAAE,GAAG,KAAK;IAAK;IAAM,EAAE,CAAC;AAClE,OAAI,kBAAkB,QAAS,QAAO,OAAO,MAAM,OAAO,CAAC,GAAG;AAC9D,UAAO,CAAC;;AAEV,SAAO,CAAC,cAAc,KAAK,CAAC,KAAK;;;;;;ACjIrC,MAAM,sBAAsB;AAsB5B,SAASC,gBAAc,SAA2D;CAChF,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,SAAS,QAAQ,QAAQ;AAC/B,KAAI,CAAC,QAAQ,CAAC,OACZ,OAAM,IAAI,MACR,uGACD;AAEH,QAAO;EAAE;EAAM;EAAQ;;AAGzB,SAAS,mBAAmB,SAAqC;AAC/D,QAAO,QAAQ,eAAe,QAAQ,KAAK,oBAAoB;;AAGjE,SAAS,YACP,MACA,OACA,SACA,cACA,OACa;AACb,QAAO;EACL;EACA,MAAM;EACN;EACA,UAAU;EACV;EACA,SAAU,OAAO,QAAQ,QAAQ,CAA4C,KAC1E,CAAC,OAAO,EAAE,OAAO,aAAa,aAAa;GAC1C,OAAO,GAAG,YAAY,KAAK;GAC3B;GACD,EACF;EACD,GAAI,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,OAAO,EAAE,EAAE,GAAG,EAAE;EAC7D;;AAGH,MAAM,eAAe,YAAY,KAAK,UAAU;CAAE,OAAO,OAAO,KAAK;CAAE,OAAO,OAAO,KAAK;CAAE,EAAE;AAE9F,SAAS,iBAAiB,YAA8B;CACtD,MAAM,SAAS,EAAE,QAAQ,MAAM;AAC/B,QAAO;EACL;GACE,MAAM;GACN,MAAM;GACN,OAAO;GACP,UAAU;GACV,GAAI,aAAa,EAAE,cAAc,YAAY,GAAG,EAAE;GAClD,UAAU;GACV,OAAO;GACR;EACD;GACE,MAAM;GACN,MAAM;GACN,OAAO;GACP,UAAU;GACV,cAAc;GACd,SAAS;GACT,OAAO;GACR;EACD;GACE,MAAM;GACN,MAAM;GACN,OAAO;GACP,OAAO;GACR;EACD;GACE,MAAM;GACN,MAAM;GACN,OAAO;GACP,cAAc;GACd,OAAO;GACR;EACD;GACE,MAAM;GACN,MAAM;GACN,OAAO;GACP,UAAU;GACV,cAAc;GACd,SAAS;IACP;KAAE,OAAO;KAAe,OAAO;KAAO;IACtC;KAAE,OAAO;KAAe,OAAO;KAAU;IACzC;KAAE,OAAO;KAAU,OAAO;KAAU;IACrC;GACD,OAAO;GACR;EACD;GACE,MAAM;GACN,MAAM;GACN,OAAO;GACP,SAAS;GACT,SAAS;GACT,UAAU;GACV,OAAO;GACR;EACF;;AAGH,SAAS,iBAAiB,MAAc,OAAe,YAA2B;AAChF,QAAO;EACL;EACA,MAAM;EACN;EACA,QAAQ,iBAAiB,WAAW;EACpC,OAAO;GAAE,YAAY,EAAE,OAAO,yBAAyB;GAAE,YAAY;GAAM;EAC5E;;AAGH,SAAS,UACP,MACA,OACA,cACA,OACA,cACA,YACa;CACb,MAAM,UAAU,MAAM,KAAK,UAAU;EAAE,OAAO,KAAK;EAAQ,OAAO,KAAK;EAAI,EAAE;AAC7E,QAAO;EACL;EACA,MAAM;EACN;EACA,UAAU,CAAC;EACX;EACA,SAAS,aAAa,CAAC;GAAE,OAAO;GAAgB,OAAA;GAAqB,EAAE,GAAG,QAAQ,GAAG;EACrF,OAAO;GACL,YAAY,EAAE,OAAO,kBAAkB;GACvC,QAAQ;IAAE;IAAc,KAAK,MAAM,KAAK,SAAS,KAAK,GAAG;IAAE;IAAY;GACxE;EACF;;AAGH,SAAS,aAAa,MAAkC,aAA8B;AACpF,QAAO,CACL;EACE,MAAM;EACN,MAAM;EACN,OAAO;EACP,OAAO;GAAE,YAAY;GAAM,OAAO;GAAQ;EAC1C,QAAQ;GACN;IACE,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;KAAE,YAAY;KAAM,OAAO;KAAQ;IAC1C,QAAQ;KACN;MACE,MAAM;MACN,MAAM;MACN,OAAO;OACL,YAAY,EAAE,OAAO,uBAAuB;OAC5C,QAAQ;QACN,OAAO;QACP,MAAM;QACP;OACF;MACF;KACD,iBAAiB,WAAW,WAAW,KAAK,aAAa;KACzD,iBAAiB,aAAa,aAAa,KAAK,eAAe;KAC/D,iBAAiB,UAAU,UAAU,KAAK,YAAY;KACtD,iBAAiB,aAAa,aAAa,KAAK,eAAe;KAC/D;MACE,MAAM;MACN,MAAM;MACN,OAAO;OACL,YAAY,EAAE,OAAO,qBAAqB;OAC1C,QAAQ,EAAE,UAAU,kBAAkB;OACvC;MACF;KACD;MACE,MAAM;MACN,MAAM;MACN,OAAO;OACL,YAAY,EAAE,OAAO,wBAAwB;OAC7C,QAAQ,EAAE,UAAU,oBAAoB;OACzC;MACF;KACD;MACE,MAAM;MACN,MAAM;MACN,OAAO;OACL,YAAY,EAAE,OAAO,uBAAuB;OAC5C,QAAQ;QACN,OAAO;QACP,MAAM;QACP;OACF;MACF;KACD,iBAAiB,WAAW,WAAW,KAAK,gBAAgB,oBAAoB;KAChF,iBAAiB,eAAe,eAAe,YAAY;KAC5D;IACF;GACD;IACE,GAAG,YAAY,aAAa,eAAe,YAAY,WAAW,KAAK,WAAW,uBAAuB;IACzG,OAAO;KAAE,QAAQ;KAAM,YAAY,EAAE,OAAO,wBAAwB;KAAE;IACvE;GACD;IACE,MAAM;IACN,MAAM;IACN,OAAO;IACP,QAAQ;KAAE,UAAU;KAAS,QAAQ;KAAU;IAC/C,QAAQ;KACN;MAAE,MAAM;MAAO,MAAM;MAAQ,OAAO;MAAO,UAAU;MAAM,OAAO,EAAE,QAAQ,MAAM;MAAE;KACpF;MAAE,MAAM;MAAS,MAAM;MAAQ,OAAO;MAAQ,UAAU;MAAM,OAAO,EAAE,QAAQ,MAAM;MAAE;KACvF,GAAG,kBAAkB;KACtB;IACD,OAAO;KAAE,QAAQ;KAAM,YAAY,EAAE,OAAO,qBAAqB;KAAE,OAAO;KAAQ;IACnF;GACF;EACF,CACF;;AAGH,SAAS,iBACP,MACA,OACA,cACS;AACT,QAAO,CACL;EACE,MAAM;EACN,MAAM;EACN,OAAO;EACP,QAAQ;GACN,UACE,WACA,gBACA,mBAAmB,KAAK,YAAY,EACpC,OACA,cACA,KACD;GACD,UAAU,QAAQ,aAAa,KAAK,UAAU,OAAO,cAAc,MAAM;GACzE;IACE,MAAM;IACN,MAAM;IACN,OAAO;KAAE,YAAY,EAAE,OAAO,qBAAqB;KAAE,QAAQ,EAAE,cAAc;KAAE;IAChF;GACF;EACF,CACF;;AAGH,SAAS,iBAAiB,MAA2C;AACnE,QAAO,CACL;EACE,MAAM;EACN,MAAM;EACN,OAAO;EACP,QAAQ;GACN,YAAY,gBAAgB,iBAAiB,mBAAmB,cAAc,KAAK,aAAa;GAChG,YAAY,UAAU,gBAAgB,mBAAmB,QAAQ,KAAK,OAAO;GAC7E,YAAY,UAAU,SAAS,mBAAmB,QAAQ,KAAK,OAAO;GACtE,YAAY,UAAU,UAAU,mBAAmB,QAAQ,KAAK,OAAO;GACvE,YAAY,WAAW,WAAW,mBAAmB,SAAS,KAAK,QAAQ;GAC5E;EACD,OAAO,EAAE,YAAY,EAAE,OAAO,wBAAwB,EAAE;EACzD,CACF;;AAGH,SAAS,eAAe,YAA6B;AACnD,QAAO;EACL;GACE,MAAM;GACN,MAAM;GACN,YAAY;GACZ,OAAO;GACP,OAAO,EACL,aAAa,oDACd;GACF;EACD;GACE,MAAM;GACN,MAAM;GACN,YAAY;GACZ,OAAO;GACP,OAAO,EACL,aAAa,kDACd;GACF;EACD;GACE,MAAM;GACN,MAAM;GACN,YAAY;GACZ,OAAO;GACP,OAAO,EACL,aACE,2FACH;GACF;EACF;;;;;;;;AASH,SAAgB,YAAY,SAA6C;CACvE,MAAM,SAASA,gBAAc,QAAQ;CACrC,MAAM,cAAc,mBAAmB,QAAQ;CAC/C,MAAM,EACJ,MACA,QAAQ,SACR,eAAe,UACf,iBAAA,GACA,MACA,UACA,WACA,gBACE;CAEJ,MAAM,cAAc;EAAE;EAAgB;EAAc,kBAAkB,UAAU;EAAU;CAC1F,MAAM,cAAc,aAAa,MAAM,YAAY;CACnD,MAAM,aAAa,iBAAiB,MAAM,OAAO,aAAa;CAC9D,MAAM,aAAa,iBAAiB,KAAK;CACzC,MAAM,aAAa,OAAO,eAAe,KAAK,WAAW,GAAG,EAAE;AAE9D,QAAO,CACL;EACE,MAAM;EACN,OAAO;EACP,eAAe;EACf,OAAO;GACL,OAAO;GACP,QAAQ,kBAAkB,QAAQ;GAClC,YAAY;GACZ,QAAQ;GACR,YAAY,EACV,UAAU,EAAE,wBAAwB,CAAC,wBAAwB,EAAE,EAChE;GACF;EACD,QAAQ;GACN,MAAM,OAAO;GACb,QAAQ,OAAO;GAChB;EACD,QAAQ,CACN;GACE,MAAM;GACN,MAAM;IACJ;KAAE,OAAO;KAAU,QAAQ;KAAa;IACxC;KAAE,OAAO;KAAc,QAAQ;KAAY;IAC3C;KAAE,OAAO;KAAc,QAAQ;KAAY;IAC3C,GAAI,OAAO,CAAC;KAAE,OAAO;KAAqB,QAAQ;KAAY,CAAC,GAAG,EAAE;IACrE;GACF,CACF;EACD,WAAW,oBAAoB,QAAQ,YAAY;EACnD,OAAO,EACL,aAAa,CACX,OAAO,EAAE,UAAU;AACjB,OAAI,CAAC,UAAW;GAChB,MAAM,WAAW;AACjB,SAAM,UAAU,mBAAmB,UAAU,KAAK,EAAE,SAAS;IAEhE,EACF;EACF,CACF;;;;AClYH,MAAM,iBAAiB;CAAC;CAAU;CAAiB;CAAU;CAAS;CAAS;;;;;;;AAQ/E,SAAgB,YAAY,QAAwB;AAClD,KAAI,CAAC,aAAa,KAAK,OAAO,CAC5B,OAAM,IAAI,MAAM,aAAa;CAG/B,IAAI,MAAM,OAAO,QAAQ,kCAAkC,GAAG;AAE9D,MAAK,MAAM,OAAO,gBAAgB;AAChC,QAAM,IAAI,QAAQ,IAAI,OAAO,IAAI,IAAI,yBAAyB,IAAI,QAAQ,KAAK,EAAE,GAAG;AACpF,QAAM,IAAI,QAAQ,IAAI,OAAO,IAAI,IAAI,eAAe,KAAK,EAAE,GAAG;;AAGhE,OAAM,IAAI,QAAQ,4DAA4D,GAAG;AACjF,OAAM,IAAI,QACR,sFACA,SACD;AAED,QAAO;;AAGT,SAAgB,YAAY,MAAoE;AAC9F,KAAI,KAAK,aAAa,gBAAiB,QAAO;AAC9C,KAAI,OAAO,KAAK,SAAS,YAAY,KAAK,KAAK,aAAa,CAAC,SAAS,OAAO,CAAE,QAAO;AACtF,QAAO;;;;AC3BT,MAAa,oBAAoB;;AAGjC,MAAa,0BAA0B;CACrC;CACA;CACA;CACA;CACD;AAcD,SAAS,cAAc,SAAuE;CAC5F,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,SAAS,QAAQ,QAAQ;AAC/B,KAAI,CAAC,QAAQ,CAAC,OACZ,OAAM,IAAI,MACR,6GACD;AAEH,QAAO;EAAE;EAAM;EAAQ;;;;;;;AAQzB,SAAgB,kBAAkB,SAAqD;CACrF,MAAM,SAAS,cAAc,QAAQ;AAGrC,QAAO;EACL,MAHW,QAAQ,QAAA;EAInB,QAAQ;GAAE,UAAU;GAAe,QAAQ;GAAgB;EAC3D,OAAO;GACL,OAAO;GACP,YAAY;GACZ,QAAQ,kBAAkB,eAAe;GACzC,aAAa;GACd;EACD,QAAQ;GACN,WAAW,CAAC,GAAG,wBAAwB;GACvC,MAAM;GACN,YAAY;GACb;EACD,UAAU;EACV,QAAQ;GACN,MAAM,OAAO;GACb,QAAQ,OAAO;GACf,QAAQ,OAAO;GACf,QAAQ,OAAO;GACf,cAAc,OAAO;GACtB;EACD,QAAQ;GACN;IAAE,MAAM;IAAS,MAAM;IAAQ,OAAO;IAAS;GAC/C;IAAE,MAAM;IAAS,MAAM;IAAY,OAAO;IAAe;GACzD;IAAE,MAAM;IAAO,MAAM;IAAQ,OAAO;IAAY,UAAU;IAAM;GACjE;EACD,OAAO,EACL,iBAAiB,EACd,EAAE,KAAK,gBAAgB;AACtB,OAAI,cAAc,YAAY,cAAc,SAAU;GACtD,MAAM,OAAO,IAAI;AACjB,OAAI,CAAC,QAAQ,CAAC,YAAY,KAAK,CAAE;AACjC,QAAK,OAAO,OAAO,KAAK,YAAY,KAAK,KAAK,SAAS,OAAO,CAAC,EAAE,OAAO;IAE3E,EACF;EACF;;;;;;;;AClEH,eAAsB,UAAU,SAA2B,MAAqC;AAC9F,QAAO,QAAQ,aAAa;EAC1B,MAAM;EACN,MAAM,cAAc,KAAK;EACzB,OAAO;EACR,CAAC;;;;;;;;ACnBJ,MAAa,4BAA4B;CACvC;EAAE,OAAO;EAAU,MAAM;EAAU,OAAO;EAAK,QAAQ;EAAK;CAC5D;EAAE,OAAO;EAAU,MAAM;EAAU,OAAO;EAAK,QAAQ;EAAM;CAC7D;EAAE,OAAO;EAAW,MAAM;EAAW,OAAO;EAAM,QAAQ;EAAK;CAChE;;;;;;;;;;ACKD,SAAgB,kBAAkB,QAAkB,UAAoB,OAA6B;AACnG,KAAI,UAAU,SAAU,QAAO;EAAE,GAAG;EAAQ,QAAQ,SAAS;EAAQ;AACrE,KAAI,UAAU,aAAc,QAAO;EAAE,GAAG;EAAQ,YAAY,SAAS;EAAY;AACjF,KAAI,UAAU,aAAc,QAAO;EAAE,GAAG;EAAQ,YAAY,SAAS;EAAY;AACjF,QAAO;EAAE,GAAG;EAAQ,MAAM,SAAS;EAAM,SAAS,SAAS;EAAS,UAAU,SAAS;EAAU;;;;;;AA6CnG,eAAsB,kBACpB,SACA,UACA,OACmB;CAOnB,MAAM,OAAO,kBALV,MAAM,QAAQ,WAAW;EACxB,MAAA;EACA,OAAO;EACP,gBAAgB;EACjB,CAAC,IAAK,EAAE,EAC4B,UAAU,MAAM;AACvD,OAAM,QAAQ,aAAa;EAAE,MAAM;EAAY,MAAM;EAAM,OAAO;EAAO,CAAC;AAC1E,QAAO;;;;;;;;;;ACpET,MAAa,yBAAyB;AACtC,MAAa,sBAAsB;AAEnC,SAAgB,kBAAkB,MAAc;AAC9C,QAAO;EAAE,MAAM;EAAqB,aAAa,EAAE,MAAM;EAAE;;;;ACX7D,MAAa,qBAAqB;AAClC,MAAa,kBAAkB;AAC/B,MAAa,kBAAkB;AAC/B,MAAa,kBAAkB;AAC/B,MAAa,cAAc;AAC3B,MAAa,qBAAqB;;;ACuBlC,MAAM,oBAA+C,UAAU;AAE7D,KAAI,OAAO,UAAU,YAAY,UAAU,GAAI,QAAO;AACtD,QAAO,WAAW,MAAM,IAAA;;AAG1B,MAAM,oBAA+C,UAAU;AAC7D,KAAI,OAAO,UAAU,YAAY,MAAM,MAAM,KAAK,GAAI,QAAO;AAC7D,QAAO,WAAW,MAAM,IAAA;;;;;;;AAQ1B,SAAgB,YAAY,EAAE,SAAS,EAAE,KAAyB,EAAE,EAAgB;CAClF,MAAM,aAAyB;EAC7B,MAAM;EACN,MAAM;EACN,OAAO;EACP,QAAQ;GAAE,UAAU;GAAQ,QAAQ;GAAS;EAC7C,SAAS;EACT,UAAU;EACV,cAAc,uBAAuB,OAAO;EAC5C,UAAU;EACV,OAAO,EACL,cAAc,EAAE,EAAE,YAAY,wBAAwB,MAAM,CAAC,EAC9D;EACD,OAAO;GACL,YAAY;IAAE,OAAO;IAAoB,UAAU;IAAiB;GACpE,aAAa;GACb,eAAe;GAChB;EACD,QAAQ;GACN;IACE,MAAM;IACN,MAAM;IACN,OAAO;IACP,UAAU;IACV,OAAO,EAAE,QAAQ,MAAM;IACxB;GACD;IACE,MAAM;IACN,MAAM;IACN,OAAO;IACP,UAAU;IACV,UAAU;IACV,OAAO,EAAE,YAAY,EAAE,OAAO,iBAAiB,EAAE;IAClD;GACD;IACE,MAAM;IACN,MAAM;IACN,OAAO;IACP,cAAc,EAAE;IAChB,OAAO,EACL,YAAY,EAAE,OAAO,oBAAoB,EAC1C;IACF;GACF;EACF;AAED,QAAO;EACL,MAAM;EACN,OAAO;EACP,OAAO;GACL,OAAO;GACP,QAAQ,kBAAkB,QAAQ;GAClC,aAAa;GACb,YAAY,EACV,UAAU,EACR,wBAAwB,CAAC,kBAAkB,QAAQ,CAAC,EACrD,EACF;GACF;EACD,QAAQ;GACN,OAAO,SAAS,cAAc,QAAQ,CAAC,KAAK;GAC5C,SAAS,SAAS,QAAQ,KAAK;GAChC;EACD,QAAQ,CAAC,WAAW;EACrB;;;;;;;;;AChGH,eAAsB,UACpB,SACA,SAA+B,EAAE,EACf;AAClB,QAAO,QAAQ,aAAa;EAC1B,MAAM;EACN,MAAM,EAAE,OAAO,uBAAuB,OAAO,EAAE;EAChD,CAAC;;;;ACnBJ,MAAa,wBAAwB;;;;;;;;ACoBrC,SAAgB,eAAe,EAAE,SAAS,EAAE,KAA4B,EAAE,EAAgB;CACxF,MAAM,YAAY,iBAAiB,OAAO;CAC1C,MAAM,gBAA4B;EAChC,MAAM;EACN,MAAM;EACN,OAAO;EACP,QAAQ;GAAE,UAAU;GAAW,QAAQ;GAAY;EACnD,SAAS,UAAU;EACnB,SAAS,UAAU;EACnB,UAAU;EACV,cAAc,0BAA0B,OAAO;EAC/C,WAAW,UAAU,uBAAuB,OAAO,OAAO;EAC1D,OAAO,EACL,cAAc,EACX,EAAE,YAAY;AACb,OAAI,CAAC,MAAM,QAAQ,MAAM,CAAE,QAAO;AAClC,UAAO,sBAAsB,OAAO,OAAO;IAE9C,EACF;EACD,OAAO;GACL,YAAY,EAAE,OAAO,uBAAuB;GAC5C,aACE;GACF,eAAe;GAChB;EACD,QAAQ;GACN;IAAE,MAAM;IAAQ,MAAM;IAAQ,OAAO;IAAQ,UAAU;IAAM,OAAO,EAAE,UAAU,MAAM;IAAE;GACxF;IAAE,MAAM;IAAS,MAAM;IAAQ,OAAO;IAAQ,UAAU;IAAM,OAAO,EAAE,UAAU,MAAM;IAAE;GACzF;IAAE,MAAM;IAAS,MAAM;IAAQ,OAAO;IAAS,OAAO,EAAE,QAAQ,MAAM;IAAE;GACxE;IAAE,MAAM;IAAY,MAAM;IAAY,OAAO;IAAY,OAAO,EAAE,QAAQ,MAAM;IAAE;GACnF;EACF;AAED,QAAO;EACL,MAAM;EACN,OAAO;EACP,OAAO;GACL,OAAO;GACP,QAAQ;GACR,aAAa;GACd;EACD,QAAQ,qBAAqB;EAC7B,QAAQ,CAAC,cAAc;EACxB;;;;;;;;ACrDH,eAAsB,aACpB,SACA,SAAkC,EAAE,EAClB;AAClB,QAAO,QAAQ,aAAa;EAC1B,MAAM;EACN,MAAM,EAAE,UAAU,0BAA0B,OAAO,EAAE;EACtD,CAAC;;;;;;;;;ACYJ,SAAgB,cAAc,OAAuB;AACnD,QAAO,MAAM,QAAQ,oBAAoB,GAAG,CAAC,aAAa;;AAG5D,eAAe,YACb,MACA,EAAE,YAAY,IAAI,YAAY,OACD;AAC7B,KAAI,CAAC,KAAM,QAAO,KAAA;AAElB,KAAI,WAAW,KAAK,CAClB,QAAO,KAAK,KAAK;AAGnB,KAAI,OAAO,KAAK,SAAS,SAAS,WAAY,QAAO,KAAA;CAErD,MAAM,QAAe,EAAE,MAAM,EAAE,QAAQ,MAAM,EAAE;AAC/C,KAAI,OAAO,KAAA,EACT,OAAM,KAAK,EAAE,YAAY,IAAI;CAG/B,MAAM,QAAQ;EACZ;EACA,OAAO;EACP,OAAO;EACP,gBAAgB;EAChB,YAAY;EACZ;EACA;EACD;AAMD,SAJa,MAAM,IAAI,QAAQ,KAAK,MAAM,EAEnC,KAAK,SAAS,MAAM,MAAM,IAAI,QAAQ,KAAK;EAAE,GAAG;EAAO,OAAO;EAAM,CAAC,EAAE,KAAK,SAAS,IAE7E,mCAAmC,KAAK,yCAAyC,KAAA;;;;;;;;AASlG,SAAgB,UAAU,EAAE,YAAY,cAA2C;CACjF,MAAM,WAAsC,OAAO,OAAO,YAAY;AACpE,MAAI;GACF,MAAM,UAAU,MAAM,YAAY,KAAK,OAAO,QAAQ;AACtD,OAAI,YAAY,KAAM,QAAO;UACvB;AAUR,SANgB,MAAM,YAAY,OAAO,UAAU,WAAW,QAAQ,IAAI;GACxE;GACA,IAAI,QAAQ;GACZ;GACA,KAAK,QAAQ;GACd,CAAC,IACgB;;AAGpB,QAAO;EACL,MAAM;EACN,MAAM;EACN,UAAU;EACV,QAAQ;EACR,OAAO,EACL,aAAa,qFACd;EACD,OAAO;GACL,gBAAgB,EAAE,EAAE,YAAa,OAAO,UAAU,WAAW,cAAc,MAAM,GAAG,MAAO;GAC3F,cAAc,CACZ,OAAO,EAAE,MAAM,aAAa,KAAK,YAAY;AAC3C,QAAI,OAAO,UAAU,SAAU,QAAO;IAEtC,MAAM,UAAU,MAAM,YAAY,OAAO;KACvC;KACA,IAAI,aAAa,MAAM,MAAM;KAC7B;KACA;KACD,CAAC;AACF,QAAI,QACF,OAAM,IAAI,gBACR;KAAE;KAAY,QAAQ,CAAC;MAAE,SAAS;MAAS,MAAM;MAAQ,CAAC;KAAE;KAAK,EACjE,KAAK,EACN;AAEH,WAAO;KAEV;GACF;EACD;EACD;;;;;;;;ACjHH,MAAM,cAAsB,OAAO,SAAS;AAE1C,KAAI,CADY,MAAM,QAAQ,QAAQ,cAAc,UAAU,CAAC,KAAK,CAAC,CACvD,QAAO;AACrB,KAAI,MAAM,QAAQ,QAAQ,WAAW,KAAK,CAAC,CAAE,QAAO;AACpD,QAAO,EAAE,SAAS,EAAE,QAAQ,SAAS,EAAE;;;;;;;AAiCzC,SAAgB,YAAY,EAC1B,YACA,gBACA,cACA,aACA,iBACiC;CACjC,MAAM,CAAC,eAAe;AACtB,KAAI,CAAC,YAAa,OAAM,IAAI,MAAM,4CAA4C;AAE9E,QAAO;EACL,MAAM;EACN,OAAO;GACL,YAAY;GACZ,OAAO;GACP,gBAAgB;IAAC;IAAS;IAAQ;IAAW;IAAY;GACzD,QAAQ,kBAAkB,UAAU;GACpC,UAAU,QAAQ,YAAY,OAAO,IAAI,SAAS,WAAW,IAAI,OAAO,GAAG;GAC3E,GAAI,gBAAgB,EAAE,YAAY,EAAE,MAAM,EAAE,eAAe,eAAe,EAAE,EAAE,GAAG,EAAE;GACpF;EACD,QAAQ;GACN,MAAM;GACN,cAAc;GACd,QAAQ,cAAc,UAAU;GAChC,QAAQ;GACR,QAAQ;GACT;EACD,UAAU;GACR,QAAQ,EAAE,UAAU,EAAE,UAAU,KAAK,EAAE;GACvC,WAAW;GACZ;EACD,QAAQ;GACN;IAAE,MAAM;IAAS,MAAM;IAAQ,UAAU;IAAM;GAC/C,UAAU;IAAE,YAAY;IAAS,YAAY;IAAgB,CAAC;GAC9D;IACE,MAAM;IACN,MAAM;IACN,UAAU;IACV,SAAS;IACT,SAAS;IACT,QAAQ;IACR,cAAc,CAAC,EAAE,WAAW,YAAY,MAAM,CAAC;IAC/C,OAAO,EACL,aAAa,2EACd;IACF;GACD;IACE,MAAM;IACN,MAAM;IACN,UAAU;IACV,SAAS;IACT,QAAQ;IACR,QAAQ;KAAE,UAAU;KAAW,QAAQ;KAAY;IACpD;GACF;EACF;;;;ACrFH,MAAM,gBAA2C,OAAO,YAAY;AAClE,KAAI,QAAQ,cAAc,YAAY,UAAU,MAAM,QAAQ,kBAAkB,GAAI,QAAO;AAC3F,QAAO,KAAK,OAAO,QAAQ;;AAG7B,SAAS,UAAU,MAA2C;AAC5D,QAAO;EAAE;EAAM,MAAM;EAAQ,UAAU;EAAM,UAAU;EAAc;;;AAIvE,MAAa,4BAA4B;;AAEzC,MAAa,4BAA4B;AAOzC,MAAM,kBAAkB;AAExB,eAAe,sBAAsB,KAAoC;CACvE,MAAM,EAAE,SAAS,aAAa,IAAI,QAAQ;CAC1C,MAAM,KAAK,IAAI;CACf,MAAM,UAAU,OAAO,OAAO,YAAY,OAAO,OAAO,WAAW,WAAW,MAAM,KAAA;AACpF,KAAI,CAAC,WAAW,OAAO,YAAY,WAAY;AAC/C,OAAM,QAAQ;EAAE,IAAI,QAAQ;EAAI,KAAK;EAAiB,CAAC;;AAGzD,SAAS,gBAAgB,QAAsC;AAC7D,QAAO,OAAO,QAAQ,QAAQ,iBAAiB,IAAI,MAAM,OAAO,CAAC,CAAC,KAAK,QAAQ,IAAI,KAAK;;AAG1F,SAAS,oBAAoB,OAAgB,QAAqC;AAChF,QAAO,MAAM,QAAQ,MAAM,IAAI,MAAM,MAAM,SAAS,iBAAiB,MAAM,OAAO,CAAC;;AAGrF,SAAS,gBAAgB,QAAmC;CAC1D,MAAM,QAAQ,gBAAgB,OAAO;AACrC,KAAI,MAAM,WAAW,EAAG,QAAO,EAAE,IAAI,EAAE,QAAQ,YAAY,EAAE;AAC7D,QAAO,EAAE,IAAI,MAAM,KAAK,UAAU,EAAE,OAAO,EAAE,UAAU,MAAM,EAAE,EAAE,EAAE;;AAGrE,eAAe,WAAW,KAAqB,WAA8C;AAC3F,OAAM,sBAAsB,IAAI;CAEhC,MAAM,kBAAkB,gBADT,MAAM,eAAe,IAAI,CACO;CAC/C,MAAM,EAAE,cAAc,MAAM,IAAI,QAAQ,MAAM;EAC5C,YAAY;EACZ,gBAAgB;EAChB;EACA,OACE,cAAc,KAAA,IACV,kBACA,EAAE,KAAK,CAAC,iBAAiB,EAAE,IAAI,EAAE,YAAY,WAAW,EAAE,CAAC,EAAE;EACpE,CAAC;AACF,QAAO;;AAGT,SAAS,cAAc,QAAyD;AAC9E,QAAO,OAAO,OAAO,YAAY;EAC/B,MAAM,SAAS,MAAM,eAAe,QAAQ,KAAK,OAAO;EACxD,MAAM,UAAU,OAAO,OAAO;GAAE,GAAG;GAAS,SAAS,kBAAkB,OAAO;GAAE,CAAC;AACjF,MAAI,YAAY,KAAM,QAAO;AAC7B,MAAI,QAAQ,cAAc,YAAY,QAAQ,OAAO,KAAA,EAAW,QAAO;AACvE,MAAI,oBAAoB,OAAO,OAAO,IAAI,CAAC,oBAAoB,QAAQ,eAAe,OAAO,CAC3F,QAAO;AAET,SAAQ,MAAM,WAAW,QAAQ,KAAK,QAAQ,GAAG,GAAI,IAAI,OAAO;;;AAwBpE,SAAgB,YAAY,EAAE,eAAe,YAAY,SAAS,EAAE,IAAoC;CACtG,MAAM,WAAW,aAAa,OAAO;AACrC,QAAO;EACL,MAAM;EACN,MAAM;GACJ,kBAAkB;GAClB,UAAU,MAAU;GACpB,iBAAiB;GACjB,SAAS;IACP,UAAU;IACV,QAAQ;IACT;GACF;EACD,OAAO;GACL,OAAO;GACP,YAAY;GACZ,gBAAgB;IAAC;IAAS;IAAa;IAAY;IAAQ;GAC3D,QAAQ,kBAAkB,QAAQ;GACnC;EACD,QAAQ;GACN,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR,MAAM,OAAO,SAAS;AACpB,QAAI,MAAM,QAAQ,QAAQ,cAAc,QAAQ,CAAC,KAAK,CAAC,CAAE,QAAO;AAChE,WAAO,cAAc,KAAK;;GAE5B,QAAQ;GACT;EACD,OAAO;GACL,cAAc,CACZ,OAAO,EAAE,IAAI,UAAU;AAUrB,QAAI,CAAC,QATU,MAAM,IAAI,QAAQ,SAAS;KACxC,YAAY;KACZ;KACA,OAAO;KACP,eAAe;KACf,gBAAgB;KAChB;KACD,CAAC,EACa,MAAM,eAAe,KAAK,OAAO,CACpB,IAAK,MAAM,WAAW,KAAK,GAAG,GAAI,EAAG;AACjE,UAAM,IAAI,SAAS,2BAA2B,IAAI;KAErD;GACD,gBAAgB,CACd,OAAO,QAAQ;IACb,MAAM,EAAE,WAAW,QAAQ;IAC3B,MAAM,gBACH,cAAc,YAAY,cAAc,iBACzC,IAAI,KAAK,MAAM,UAAU,KAAA;IAC3B,MAAM,UAAU,cAAc,YAAY,cAAc;AACxD,SAAK,gBAAgB,YAAa,MAAM,WAAW,IAAI,KAAM,EAC3D,OAAM,IAAI,SAAS,UAAU,4BAA4B,2BAA2B,IAAI;AAE1F,WAAO,IAAI;KAEd;GACF;EACD,QAAQ;GACN;IACE,MAAM;IACN,QAAQ,CAAC,UAAU,YAAY,EAAE,UAAU,WAAW,CAAC;IACxD;GACD;IACE,MAAM;IACN,MAAM;IACN,SAAS;IACT,UAAU;IACV,WAAW;IAGX,SAAS,kBAAkB,SAAS;IACpC,OAAO;KACL,YAAY,EAAE,OAAO,cAAA,4CAA2B;KAChD,aAAa;KACd;IACD,QAAQ,EACN,QAAQ,SACT;IACD,UAAU,cAAc,OAAO;IAC/B,OAAO,EACL,gBAAgB,CACd,OAAO,EAAE,OAAO,UAAU;AACxB,SAAI,CAAC,MAAM,QAAQ,MAAM,CAAE,QAAO;AAClC,YAAO,qBAAqB,OAAO,MAAM,eAAe,KAAK,OAAO,CAAC;MAExE,EACF;IACF;GACD;IACE,MAAM;IACN,MAAM;IACN,OAAO;KAAE,QAAQ;KAAM,UAAU;KAAM;IACvC,QAAQ,EAAE,cAAc,OAAO;IAC/B,WAAW;IACX,OAAO,EACL,WAAW,CACT,OAAO,EAAE,aAAa,MAAM,UAC1B,uBACE;KACE,IAAK,aAAa,MAAM,MAAM;KAC9B,OAAQ,aAAa,SAAS,MAAM;KACrC,EACD,OAAO,EAAE,CACV,CACJ,EACF;IACF;GACF;EACF;;;;;;;;;ACrMH,SAAgB,YAAY,EAC1B,YAAY,SACZ,YAAY,CAAC,UAAU,EACvB,eACgB,EAAE,EAAoB;AACtC,QAAO;EACL,MAAM;EACN,OAAO,EACL,QAAQ,kBAAkB,QAAQ,EACnC;EACD,QAAQ;GACN,YAAY;GACZ,QAAQ,cAAc,QAAQ;GAC9B,QAAQ,cAAc,QAAQ;GAC9B,QAAQ;GACT;EACD,QAAQ;GAAE;GAAW;GAAW;GAAY;EAC5C,QAAQ,CACN;GACE,MAAM;GACN,MAAM;GACN,UAAU;GACX,CACF;EACF;;;;AC9CH,MAAa,YAAY;AACzB,MAAa,sBAAsB;AACnC,MAAa,2BAA2B;AACxC,MAAa,yBAAyB;;;;;;;;ACGtC,MAAa,iBAAiB;;;ACJ9B,MAAM,yBAAyB;;;;AAK/B,MAAa,wBAAmD,OAAO,EAAE,KAAK,kBAAkB;AAC9F,KAAI,OAAO,UAAU,YAAY,UAAU,GAAI,QAAO;CACtD,MAAM,OAAO,eAAe,OAAO,gBAAgB,YAAY,UAAU,cAAc,YAAY,OAAO;AAI1G,UAFE,SAAS,WAAW,IAAI,SAAS,QAAQ,UAAU,SAAS,eAAe,IAAI,SAAS,QAAQ,cAAc,EAAE,KAC3F,EAAE,EAAE,KAAK,WAAW,OAAO,KAAK,CAC1C,SAAS,MAAM,IAAI;;;;ACNlC,MAAM,cAA0B;CAC9B,MAAM;CACN,MAAM;CACN,OAAO;CACP,QAAQ;EAAE,UAAU;EAAS,QAAQ;EAAU;CAC/C,OAAO;EACL,YAAY,EAAE,UAAU,qBAAqB;EAC7C,aAAa;EACb,eAAe;EAChB;CACD,QAAQ,CACN;EACE,MAAM;EACN,MAAM;EACN,OAAO;EACR,EACD;EACE,MAAM;EACN,MAAM;EACN,OAAO;EACP,QAAQ;GAAE,UAAU;GAAQ,QAAQ;GAAS;EAC7C,OAAO,EAAE,YAAY,EAAE,UAAU,0BAA0B,EAAE;EAC7D,QAAQ,CACN;GACE,MAAM;GACN,QAAQ,CACN;IACE,MAAM;IACN,MAAM;IACN,OAAO;IACP,UAAU;IACV,cAAc;IACd,SAAS,CACP;KAAE,OAAO;KAAc,OAAO;KAAc,EAC5C;KAAE,OAAO;KAAU,OAAO;KAAU,CACrC;IACD,OAAO,EAAE,OAAO,OAAO;IACxB,EACD;IACE,MAAM;IACN,MAAM;IACN,OAAO;IACP,UAAU;IACV,UAAU;IACV,OAAO;KAAE,OAAO;KAAO,YAAY,EAAE,OAAO,wBAAwB;KAAE;IACvE,CACF;GACF,CACF;EACF,CACF;CACF;;;;;;AAOD,SAAgB,iBAA+B;AAC7C,QAAO;EACL,MAAM;EACN,OAAO;EACP,OAAO;GACL,OAAO;GACP,QAAQ;GACR,aACE;GACH;EACD,QAAQ;GACN,MAAM;GACN,SAAS,EAAE,UAAU,YAAY,IAAI,KAAkB;GACxD;EACD,QAAQ,CAAC,YAAY;EACtB;;;;;;;;;ACtEH,MAAa,WAAW,aAAa;CACnC,MAAM;CACN,OAAO;CACP,SAAS,EAAE,cAAsB;EAC/B,GAAG;EACH,OAAO;GACL,GAAG,OAAO;GACV,YAAY;IACV,GAAG,OAAO,OAAO;IACjB,KAAK;IACN;GACF;EACF;CACF,CAAC;;;ACbF,SAAS,aAAa,OAAgC;AACpD,KAAI,UAAU,MAAO,QAAO;AAC5B,KAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAO;;AAGT,SAAS,QAAQ,OAAgB,UAA0B;AACzD,QAAO,OAAO,UAAU,YAAY,QAAQ,QAAQ;;AAGtD,SAAS,YAAY,QAA8B,MAAkC;AACnF,KAAI,SAAS,aACX,QAAO,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,OAAO,QAAQ,UAAU,OAAO,KAAK,CAAC;AAEtF,QAAO,QAAQ,OAAO,OAAO,OAAO,KAAK;;AAG3C,SAAS,MAAM,MAA0B,MAAsB;AAC7D,QAAO,GAAG,KAAK,GAAG;;AAUpB,SAASC,UAAQ,QAAwC;CACvD,MAAM,eAAe,OAAO,eAAe,EAAE,EAAE,KAAK,YAAY;EAC9D,MAAM;EACN,MAAM,OAAO;EACb,OAAO,YAAY,QAAQ,aAAa;EACxC,OAAO,aAAa,OAAO,OAAO,MAAM;EACzC,EAAE;CACH,MAAM,WAAW,OAAO,WAAW,EAAE,EAAE,KAAK,YAAY;EACtD,MAAM;EACN,MAAM,OAAO;EACb,OAAO,YAAY,QAAQ,SAAS;EACpC,OAAO,aAAa,OAAO,OAAO,MAAM;EACzC,EAAE;AACH,QAAO,CAAC,GAAG,aAAa,GAAG,QAAQ;;AAGrC,SAAS,cAAc,UAAoD;CACzE,MAAM,SAA0B,EAAE;AAClC,MAAK,MAAM,UAAU,UAAU;AAC7B,MAAI,OAAO,UAAU,MAAO;EAC5B,IAAI,QAAQ,OAAO,MAAM,UAAU,MAAM,UAAU,OAAO,MAAM;AAChE,MAAI,CAAC,OAAO;AACV,WAAQ;IAAE,OAAO,OAAO;IAAO,OAAO,EAAE;IAAE;AAC1C,UAAO,KAAK,MAAM;;AAEpB,QAAM,MAAM,KAAK;GAAE,MAAM,OAAO;GAAM,MAAM,OAAO;GAAM,OAAO,OAAO;GAAO,CAAC;;AAEjF,QAAO;;AAGT,SAAS,cACP,MACA,OACqB;CACrB,MAAM,OAAO,KAAK,SAAS,YAAY,KAAK,SAAS,eAAe,KAAK,OAAO;CAChF,MAAM,OAAO,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO;AACzD,KAAI,CAAC,QAAQ,CAAC,KAAM,QAAO;CAC3B,MAAM,SAAS,MAAM,IAAI,MAAM,MAAM,KAAK,CAAC;AAC3C,KAAI,CAAC,UAAU,OAAO,UAAU,MAAO,QAAO;AAC9C,QAAO;EAAE;EAAM;EAAM,OAAO,OAAO;EAAO;;AAG5C,SAAS,aAAa,KAAkB,UAAoD;CAC1F,MAAM,QAAQ,IAAI,IAAI,SAAS,KAAK,WAAW,CAAC,MAAM,OAAO,MAAM,OAAO,KAAK,EAAE,OAAO,CAAC,CAAC;AAC1F,SAAQ,IAAI,UAAU,EAAE,EAAE,KAAK,SAAS;EACtC,OAAO,OAAO,IAAI,UAAU,WAAW,IAAI,QAAQ;EACnD,QAAQ,IAAI,SAAS,EAAE,EAAE,SAAS,SAAS;GACzC,MAAM,WAAW,cAAc,QAAQ,EAAE,EAAE,MAAM;AACjD,UAAO,WAAW,CAAC,SAAS,GAAG,EAAE;IACjC;EACH,EAAE;;;;;;AAOL,SAAgB,gBAAgB,EAAE,QAAQ,KAAK,mBAAyD;CACtG,MAAM,WAAWA,UAAQ,OAAO;CAChC,MAAM,QAAQ,MAAM,QAAQ,KAAK,OAAO,GAAG,IAAI,SAAS,EAAE;CAC1D,IAAI,SAAS,MAAM,WAAW,IAAI,cAAc,SAAS,GAAG,aAAa,EAAE,QAAQ,OAAO,EAAE,SAAS;AAErG,KAAI,iBAAiB;EACnB,MAAM,cAAc,IAAI,IAAI,gBAAgB,eAAe,EAAE,CAAC;EAC9D,MAAM,UAAU,IAAI,IAAI,gBAAgB,WAAW,EAAE,CAAC;AACtD,WAAS,OAAO,KAAK,WAAW;GAC9B,GAAG;GACH,OAAO,MAAM,MAAM,QAAQ,SACzB,KAAK,SAAS,eAAe,YAAY,IAAI,KAAK,KAAK,GAAG,QAAQ,IAAI,KAAK,KAAK,CACjF;GACF,EAAE;;AAGL,QAAO;;;;;;;;;;ACvGT,MAAM,aAAa;AASnB,SAAS,WAAW,MAAoD;AACtE,KAAI,MAAM,SAAS,WAAY,QAAO;AACtC,KAAI,MAAM,SAAS,OAAQ,QAAO;AAClC,QAAO,MAAM,OAAO,aAAa;;AAGnC,MAAM,YAAuB,OAAO,gBAAgB,WAAW,YAA+B,KAAK;AACnG,MAAM,gBAA2B,OAAO,gBACtC,WAAW,YAA+B,KAAK;AAEjD,SAAS,sBAAsB,EAC7B,WAAW,OACX,kBAAkB,YAIhB,EAAE,EAAc;AAClB,QAAO,CACL;EACE,MAAM;EACN,OAAO,EAAE,YAAY,EAAE,OAAO,YAAY,EAAE;EAC5C,QAAQ;GACN;IACE,MAAM;IACN,MAAM;IACN,OAAO;IACP,cAAc;IACd,SAAS,CACP;KAAE,OAAO;KAAQ,OAAO;KAAQ,EAChC;KAAE,OAAO;KAAO,OAAO;KAAY,CACpC;IACD,OAAO,EAAE,QAAQ,cAAc;IAChC;GACD;IACE,MAAM;IACN,MAAM;IACN,YAAY;IACZ;IACA,eAAe,EAAE,SAAS,EAAE,QAAQ,aAAa,EAAE;IACnD,OAAO,EAAE,WAAW,UAAU;IAC/B;GACD;IACE,MAAM;IACN,MAAM;IACN,OAAO;IACP;IACA,OAAO;KACL,WAAW;KACX,aACE;KACH;IACF;GACF;EACF,CACF;;AAGH,SAAS,WAAW,EAClB,WAAW,OACX,oBAIE,EAAE,EAAW;AACf,QAAO;EACL,GAAG,sBAAsB;GAAE;GAAU;GAAiB,CAAC;EACvD;GAAE,MAAM;GAAS,MAAM;GAAQ,OAAO;GAAS;GAAU;EACzD;GACE,MAAM;GACN,MAAM;GACN,OAAO;GACP,cAAc;GACf;EACF;;AAGH,SAAgB,UAAU,EACxB,OAAO,QACP,OACA,OACA,UACA,oBAOE,EAAE,EAAc;AAClB,QAAO;EACL;EACA,MAAM;EACN,QAAQ,WAAW;GAAE;GAAU;GAAiB,CAAC;EACjD,GAAI,UAAU,KAAA,IAAY,EAAE,GAAG,EAAE,OAAO;EACxC,GAAI,UAAU,KAAA,IAAY,EAAE,GAAG,EAAE,OAAO;EACzC;;AAGH,SAAgB,iBAAiB,EAC/B,WAAW,OACX,oBAIE,EAAE,EAAW;AACf,QAAO,WAAW;EAAE;EAAU;EAAiB,CAAC;;;;AC5GlD,MAAM,2BAAmD,OAAO,EAAE,MAAM,UAAU;AAChF,KAAI,KAAK,YAAY,YAAa,QAAO;AACzC,KAAI,CAAC,IAAI,KAAM,QAAO;AACtB,KAAI,MAAM,QAAQ,QAAQ,WAAW,EAAE,KAAK,CAAU,CAAC,CAAE,QAAO;AAChE,OAAM,IAAI,WAAW;;;;;;;AAQvB,SAAgB,iBAAiB,EAC/B,QACA,sBACA,oBACA,SACA,aACA,eACA,mBACwD;AACxD,KAAI,OAAO,WAAW,EACpB,OAAM,IAAI,MAAM,mDAAmD;CAGrE,MAAM,SAAS,kBAAkB,mBAAmB;CACpD,MAAM,SAAS,cAAc,mBAAmB;CAChD,MAAM,eAAe;EACnB,GAAI,UAAU,EAAE,SAAS,GAAG,EAAE;EAC9B,GAAI,cAAc,EAAE,aAAa,GAAG,EAAE;EACtC,GAAI,gBACA,EAAE,YAAY,EAAE,UAAU,EAAE,eAAe,eAAe,EAAE,EAAE,GAC9D,EAAE;EACP;AAkHD,QAAO,CAhHsB;EAC3B,MAAM;EACN,QAAA;EACA,OAAO;EACP,OAAO;GACL,OAAO;GACC;GACR,aAAa;GACb,GAAG;GACJ;EACD,QAAQ;GACN,YAAY;GACZ,cAAc;GACd;GACD;EACD,UAAU,EACR,QAAQ,EAAE,UAAU,EAAE,UAAU,KAAK,EAAE,EACxC;EACD,OAAO,EACL,cAAc,CAAC,yBAAyB,EACzC;EACD,QAAQ,CACN;GACE,MAAM;GACN,MAAM;GACN,OAAO;GACP,QAAQ,CACN;IACE,MAAM;IACN,MAAM;IACN,QAAQ;KAAE,UAAU;KAAQ,QAAQ;KAAS;IAC7C;IACA,OAAO,EACL,aACE,+NACH;IACF,EACD,UAAU;IACR,MAAM;IACN,OAAO;IACP,UAAU;IACV;IACA,OAAO,EACL,aAAa,qCACd;IACF,CAAC,CACH;GACF,CACF;EACF,EAE4B;EAC3B,MAAM;EACN,QAAQ;EACR,OAAO;EACP,OAAO;GACL,OAAO;GACC;GACR,aACE;GACF,GAAG;GACJ;EACD,QAAQ;GACN,YAAY;GACZ,cAAc;GACd;GACD;EACD,UAAU,EACR,QAAQ,EAAE,UAAU,EAAE,UAAU,KAAK,EAAE,EACxC;EACD,OAAO,EACL,cAAc,CAAC,yBAAyB,EACzC;EACD,QAAQ,CACN;GACE,MAAM;GACN,MAAM;GACN,OAAO;GACP,QAAQ,CACN;IACE,MAAM;IACN,MAAM;IACN,QAAQ;IACR,QAAQ;KAAE,UAAU;KAAU,QAAQ;KAAW;IACjD,OAAO;KACL,aACE;KACF,YAAY,uBAAuB,EAAE,UAAU,sBAAsB,GAAG,KAAA;KACzE;IACD,QAAQ,CACN;KACE,MAAM;KACN,MAAM;KACN,UAAU;KACV,OAAO;KACR,EACD;KACE,MAAM;KACN,MAAM;KACN,QAAQ;MAAE,UAAU;MAAQ,QAAQ;MAAS;KAC7C,OAAO,EACL,YAAY,qBAAqB,EAAE,UAAU,oBAAoB,GAAG,KAAA,GACrE;KACD,QAAQ,iBAAiB;MAAE,UAAU;MAAM;MAAiB,CAAC;KAC9D,CACF;IACF,CACF;GACF,CACF;EACF,CAEsB;;;;AC1JzB,SAAS,WAA6B,QAAc;CAClD,MAAM,aAAa,OAAO,OAAO;CACjC,MAAM,OAAO,YAAY,OAAO;CAChC,MAAM,MAAM,QAAQ,SAAS,OAAO,KAAK,MAAM,KAAA;AAC/C,QAAO;EACL,GAAG;EACH,OAAO;GACL,GAAG,OAAO;GACV,YAAY;IACV,GAAG;IACH,OAAO;KACL,GAAG,YAAY;KACf,MAAM;MACJ,GAAG;MACH,KAAK;OAAE,GAAG;OAAK,KAAK;QAAE,GAAG,KAAK;QAAK,WAAW;QAAgB;OAAE;MACjE;KACF;IACF;GACF;EACF;;;;;;;AAQH,MAAa,kBAAkB,aAAa;CAC1C,MAAM;CACN,OAAO;CACP,SAAS,EAAE,cAAc;EACvB,GAAG;EACH,aAAa,OAAO,aAAa,IAAI,WAAW;EAChD,SAAS,OAAO,SAAS,IAAI,WAAW;EACzC;CACF,CAAC;;;ACjCF,SAAS,OAAO,OAAmD;AACjE,KAAI,CAAC,MAAO,QAAO,EAAE;AACrB,QAAO;;AAGT,SAAS,uBAAuB,WAAoC;AAClE,QAAO,UAAU,MAAM,UAAU;AAC/B,MAAI,OAAO,UAAU,SAAU,QAAO,UAAU;AAChD,MAAI,SAAS,OAAO,UAAU,YAAY,UAAU,MAClD,QAAO,MAAM,SAAS;AAExB,SAAO;GACP;;AAGJ,SAAS,iBAAiB,QAAwB;CAChD,MAAM,YAAY,OAAO,OAAO,OAAO,YAAY,UAAU;AAC7D,KAAI,uBAAuB,UAAU,CAAE,QAAO;AAC9C,QAAO;EACL,GAAG;EACH,OAAO;GACL,GAAG,OAAO;GACV,YAAY;IACV,GAAG,OAAO,OAAO;IACjB,WAAW,CAAC,wBAAwB,GAAG,UAAU;IAClD;GACF;EACF;;;;;;;;AASH,MAAa,uBAAuB,aAAa;CAC/C,MAAM;CACN,OAAO;CACP,SAAS,EAAE,aAAa,iBAAiB,OAAO;CACjD,CAAC"}
|