@nonext/husk 0.2.3
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/CHANGELOG.md +148 -0
- package/LICENSE +166 -0
- package/README.md +140 -0
- package/api/public-api.md +1070 -0
- package/dist/adapter-C_0mhENy.d.ts +320 -0
- package/dist/admin/admin.css +5 -0
- package/dist/admin/index.d.ts +265 -0
- package/dist/admin/index.js +393 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/tokens.css +597 -0
- package/dist/admin/ui.d.ts +3013 -0
- package/dist/admin/ui.js +9783 -0
- package/dist/admin/ui.js.map +1 -0
- package/dist/auth/index.d.ts +4 -0
- package/dist/auth/index.js +9 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth-B2gBtHl5.d.ts +28 -0
- package/dist/can-Chy7zmx7.d.ts +69 -0
- package/dist/chunk-3I6337WJ.js +83 -0
- package/dist/chunk-3I6337WJ.js.map +1 -0
- package/dist/chunk-4Z6P3XCE.js +62 -0
- package/dist/chunk-4Z6P3XCE.js.map +1 -0
- package/dist/chunk-6E3ZS5Z5.js +1007 -0
- package/dist/chunk-6E3ZS5Z5.js.map +1 -0
- package/dist/chunk-77JDRXXU.js +3 -0
- package/dist/chunk-77JDRXXU.js.map +1 -0
- package/dist/chunk-FHYWJCG6.js +171 -0
- package/dist/chunk-FHYWJCG6.js.map +1 -0
- package/dist/chunk-JAE7HHMM.js +506 -0
- package/dist/chunk-JAE7HHMM.js.map +1 -0
- package/dist/chunk-NPDBQBLW.js +68 -0
- package/dist/chunk-NPDBQBLW.js.map +1 -0
- package/dist/chunk-ORMYARXD.js +6 -0
- package/dist/chunk-ORMYARXD.js.map +1 -0
- package/dist/chunk-R4O7APIX.js +51 -0
- package/dist/chunk-R4O7APIX.js.map +1 -0
- package/dist/chunk-ROLKRJWI.js +187 -0
- package/dist/chunk-ROLKRJWI.js.map +1 -0
- package/dist/chunk-SOTQ3WP5.js +31 -0
- package/dist/chunk-SOTQ3WP5.js.map +1 -0
- package/dist/chunk-TCFFHTY3.js +97 -0
- package/dist/chunk-TCFFHTY3.js.map +1 -0
- package/dist/chunk-TS7Y7GEZ.js +7 -0
- package/dist/chunk-TS7Y7GEZ.js.map +1 -0
- package/dist/chunk-VLGR5PZX.js +3 -0
- package/dist/chunk-VLGR5PZX.js.map +1 -0
- package/dist/chunk-ZW2PUSVS.js +40 -0
- package/dist/chunk-ZW2PUSVS.js.map +1 -0
- package/dist/chunk-ZYNBMYJ6.js +392 -0
- package/dist/chunk-ZYNBMYJ6.js.map +1 -0
- package/dist/cli/nonext-husk.js +3360 -0
- package/dist/cli/nonext-husk.js.map +1 -0
- package/dist/cli/templates/firestore.rules +393 -0
- package/dist/cli/templates/storage.rules +165 -0
- package/dist/client/index.d.ts +27 -0
- package/dist/client/index.js +15 -0
- package/dist/client/index.js.map +1 -0
- package/dist/cms-9fSA3uQV.d.ts +158 -0
- package/dist/core/index.d.ts +1267 -0
- package/dist/core/index.js +12 -0
- package/dist/core/index.js.map +1 -0
- package/dist/entry-D3kiE8T1.d.ts +163 -0
- package/dist/field-Diyf5siF.d.ts +158 -0
- package/dist/field-type-D25Vojb0.d.ts +157 -0
- package/dist/firebase/index.d.ts +251 -0
- package/dist/firebase/index.js +991 -0
- package/dist/firebase/index.js.map +1 -0
- package/dist/index-5ylaMBUH.d.ts +155 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/permissions/index.d.ts +101 -0
- package/dist/permissions/index.js +7 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/registry-CUC25qay.d.ts +59 -0
- package/dist/richtext/index.d.ts +85 -0
- package/dist/richtext/index.js +127 -0
- package/dist/richtext/index.js.map +1 -0
- package/dist/schema/index.d.ts +50 -0
- package/dist/schema/index.js +5 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/server/index.d.ts +39 -0
- package/dist/server/index.js +25 -0
- package/dist/server/index.js.map +1 -0
- package/dist/types/index.d.ts +36 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/write-limits-Djmm6L3R.d.ts +215 -0
- package/package.json +136 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/admin/components/class-names.ts","../../src/admin/components/avatar.tsx","../../src/admin/components/icon-names.ts","../../src/admin/components/icon.tsx","../../src/admin/components/badge.tsx","../../src/admin/components/breadcrumb.tsx","../../src/admin/components/spinner.tsx","../../src/admin/components/button.tsx","../../src/admin/components/checkbox.tsx","../../src/admin/components/empty-state.tsx","../../src/admin/components/field.tsx","../../src/admin/components/form-error.tsx","../../src/core/errors.ts","../../src/core/error-taxonomy.ts","../../src/admin/components/morph-icon.tsx","../../src/admin/components/tooltip.tsx","../../src/admin/components/icon-button.tsx","../../src/admin/components/toast.tsx","../../src/admin/components/error-capture.tsx","../../src/admin/components/error-notice.tsx","../../src/admin/components/menu.tsx","../../src/admin/components/panel.tsx","../../src/admin/components/skeleton.tsx","../../src/admin/components/metric.tsx","../../src/admin/components/focusable.ts","../../src/admin/components/modal.tsx","../../src/admin/components/pagination.tsx","../../src/admin/components/page-header.tsx","../../src/admin/components/progress.tsx","../../src/admin/components/section.tsx","../../src/admin/components/select.tsx","../../src/admin/components/search-input.tsx","../../src/admin/components/switch.tsx","../../src/admin/components/textarea.tsx","../../src/admin/components/table.tsx","../../src/admin/components/unsaved-changes.tsx","../../src/types/auth.ts","../../src/permissions/can.ts","../../src/admin/navigation/navigation.ts","../../src/admin/shell/admin-sidebar.tsx","../../src/admin/shell/admin-shell.tsx","../../src/admin/format.ts","../../src/core/adapter.ts","../../src/core/entry-title.ts","../../src/types/content-type.ts","../../src/permissions/matrix.ts","../../src/types/field.ts","../../src/core/define-content-type.ts","../../src/core/reorder.ts","../../src/core/schema-fields.ts","../../src/core/schema-editor.ts","../../src/core/list-view.ts","../../src/types/entry.ts","../../src/admin/screens/collection-list.tsx","../../src/core/content-kind.ts","../../src/core/delete-confirmation.ts","../../src/admin/screens/delete-entries-dialog.tsx","../../src/core/entry-form.ts","../../src/core/entry-status.ts","../../src/core/slug-field.ts","../../src/core/entry-unique.ts","../../src/schema/field-type.ts","../../src/fields/values.ts","../../src/fields/field-shell.tsx","../../src/fields/boolean/input.tsx","../../src/fields/boolean/index.ts","../../src/fields/date/datetime.ts","../../src/fields/date/input.tsx","../../src/fields/date/index.ts","../../src/fields/media/reference.ts","../../src/fields/media/picker-context.tsx","../../src/fields/media/media-input.tsx","../../src/fields/file/input.tsx","../../src/fields/media/spec.ts","../../src/fields/file/index.ts","../../src/fields/image/input.tsx","../../src/fields/image/index.ts","../../src/fields/number/input.tsx","../../src/fields/number/index.ts","../../src/fields/relation/source-context.tsx","../../src/fields/relation/picker.tsx","../../src/fields/relation/input.tsx","../../src/fields/relation/source.ts","../../src/fields/relation/index.ts","../../src/fields/repeater/rows.ts","../../src/fields/repeater/input.tsx","../../src/fields/repeater/index.ts","../../src/fields/richtext/schema.ts","../../src/fields/richtext/document.ts","../../src/fields/richtext/extensions.ts","../../src/fields/richtext/toolbar.tsx","../../src/fields/richtext/editor.tsx","../../src/fields/richtext/input.tsx","../../src/fields/richtext/index.ts","../../src/fields/select/input.tsx","../../src/fields/select/index.ts","../../src/fields/form-context.tsx","../../src/fields/slug/slugify.ts","../../src/fields/slug/input.tsx","../../src/fields/slug/index.ts","../../src/fields/text/input.tsx","../../src/fields/text/index.ts","../../src/fields/textarea/input.tsx","../../src/fields/textarea/index.ts","../../src/fields/index.ts","../../src/schema/validate.ts","../../src/admin/screens/entry-metadata.tsx","../../src/admin/screens/error-screen.tsx","../../src/admin/screens/entry-editor.tsx","../../src/admin/screens/dashboard-data.ts","../../src/admin/screens/dashboard.tsx","../../src/core/media-constraints.ts","../../src/admin/media/library.ts","../../src/admin/media/usage-list.tsx","../../src/admin/media/media-delete-dialog.tsx","../../src/admin/media/clipboard.ts","../../src/admin/media/media-detail.tsx","../../src/admin/media/media-tile.tsx","../../src/admin/media/media-uploads.tsx","../../src/admin/media/media-library.tsx","../../src/admin/media/media-picker-provider.tsx","../../src/admin/registry/use-live-registry.ts","../../src/core/registry.ts","../../src/core/schema-version.ts","../../src/core/schema-builder.ts","../../src/admin/schema/create-content-type-dialog.tsx","../../src/admin/schema/content-types-screen.tsx","../../src/admin/schema/field-editor.tsx","../../src/admin/schema/permission-matrix-editor.tsx","../../src/admin/schema/purge-field-dialog.tsx","../../src/admin/schema/remove-field-dialog.tsx","../../src/admin/schema/content-type-editor.tsx","../../src/admin/screens/route-error.tsx","../../src/admin/screens/not-found-screen.tsx","../../src/admin/screens/login-screen.tsx","../../src/admin/screens/unauthorized-screen.tsx"],"names":["jsx","jsxs","Link","SIZES","describedBy","error","useId","Menu","X","ChevronRight","ChevronDown","Copy","Check","useRef","useEffect","useState","useCallback","createContext","useContext","FIELD_KEY_PATTERN","useMemo","page","Fragment","DATE_ONLY","missingError","Bold","Italic","toggle","SKELETON_ROWS","contentTypeLabel","SLUG_PATTERN","dataTransferOf","ICON_OPTIONS"],"mappings":"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","file":"ui.js","sourcesContent":["/**\n * Joins class strings, dropping anything falsy.\n *\n * Deliberately not a merge utility: it does not know that `bg-surface-hover` and\n * `bg-surface-active` conflict, and it must not, because resolving a conflict silently is\n * how a component ends up with two competing appearances and nobody notices which won.\n * Conditional classes are chosen at the call site instead.\n */\nexport function cx(...parts: Array<string | false | null | undefined>): string {\n return parts.filter(Boolean).join(\" \")\n}\n","import { cx } from \"./class-names.js\"\n\n/**\n * The avatar. Canonical source: .docs/styleguide/04-components.md section 9.\n *\n * Three sizes, nothing else. The fallback is initials rather than a generic silhouette,\n * because a sidebar full of identical silhouettes tells a reader nothing.\n */\nexport type AvatarSize = 20 | 24 | 32\n\nconst SIZES: Record<AvatarSize, string> = {\n 20: \"size-5\",\n 24: \"size-6\",\n 32: \"size-8\",\n}\n\nexport interface AvatarProps {\n /** The display name or email the initials come from, and the image's alt text. */\n name: string\n src?: string\n size?: AvatarSize\n}\n\n/** At most two letters, from the first two words, so a long name stays inside the circle. */\nexport function initials(name: string): string {\n const words = name.trim().split(/\\s+/).filter(Boolean)\n const letters = words.slice(0, 2).map((word) => word.charAt(0))\n return letters.join(\"\").toUpperCase()\n}\n\nexport function Avatar({ name, src, size = 24 }: AvatarProps) {\n const shape = cx(\n \"flex shrink-0 items-center justify-center overflow-hidden rounded-full border border-border-default bg-surface-raised\",\n SIZES[size],\n )\n\n if (src !== undefined) {\n // Not next/image: the admin is behind a login, the sizes are fixed and tiny, and the\n // package must not force a loader configuration onto the host app.\n return <img src={src} alt={name} className={cx(shape, \"object-cover\")} />\n }\n\n return (\n <span className={shape} aria-hidden>\n <span className=\"text-caption uppercase text-text-muted\">{initials(name)}</span>\n </span>\n )\n}\n","/**\n * The icon vocabulary as plain data, with no Lucide import.\n *\n * `icon.tsx` maps every name here to a glyph, and the admin only ever asks for a name. The\n * list lives in its own module because things that are not components need it: the\n * navigation builder resolves a content type's declared icon against this vocabulary, and\n * it runs on the server, where dragging a React component module in would put the icon set\n * into a bundle that never renders one.\n *\n * Canonical source: .docs/styleguide/05-icons.md section 1.3.\n */\nexport const ICON_NAMES = [\n \"brand\",\n \"create\",\n \"edit\",\n \"delete\",\n \"save\",\n \"close\",\n \"search\",\n \"filter\",\n \"sort-asc\",\n \"sort-desc\",\n \"navigate-into\",\n \"page-previous\",\n \"page-next\",\n \"expand\",\n \"collapse\",\n \"selected\",\n \"indeterminate\",\n \"more-actions\",\n \"drag-handle\",\n \"locked\",\n \"dashboard\",\n \"collection\",\n \"singleton\",\n \"media\",\n \"settings\",\n \"users\",\n \"permissions\",\n \"content-types\",\n \"system\",\n \"success\",\n \"warning\",\n \"error\",\n \"info\",\n \"external-link\",\n \"upload\",\n \"copy\",\n \"retry\",\n \"open-navigation\",\n \"bold\",\n \"italic\",\n \"strikethrough\",\n \"link\",\n \"unlink\",\n \"bullet-list\",\n \"numbered-list\",\n \"quote\",\n \"undo\",\n \"redo\",\n] as const\n\nexport type IconName = (typeof ICON_NAMES)[number]\n\n/**\n * Whether a string names an icon in the vocabulary.\n *\n * A database-defined content type carries whatever icon name an editor typed into the\n * Schema Builder, so the name is untrusted input and a lookup against it has to be able to\n * fail without taking the sidebar down.\n */\nexport function isIconName(value: string): value is IconName {\n return (ICON_NAMES as readonly string[]).includes(value)\n}\n","import {\n ArrowUpRight,\n Bold,\n Check,\n ChevronDown,\n ChevronLeft,\n ChevronRight,\n ChevronUp,\n CircleCheck,\n CircleX,\n Copy,\n Database,\n EllipsisVertical,\n FileText,\n GripVertical,\n Image,\n Info,\n Italic,\n Layers,\n LayoutDashboard,\n Link,\n List,\n ListOrdered,\n Lock,\n Menu,\n Minus,\n Pencil,\n Plus,\n Quote,\n Redo2,\n RotateCcw,\n Search,\n Settings,\n ShieldCheck,\n SlidersHorizontal,\n Sprout,\n Strikethrough,\n Terminal,\n TriangleAlert,\n Trash2,\n Undo2,\n Unlink,\n Upload,\n Users,\n X,\n} from \"lucide-react\"\nimport type { LucideIcon } from \"lucide-react\"\n\nimport { ICON_NAMES, isIconName } from \"./icon-names.js\"\nimport type { IconName } from \"./icon-names.js\"\n\n/**\n * The only place in the admin that may import from lucide-react.\n *\n * Two things are enforced here rather than trusted to a reviewer. Stroke width is 1.5\n * (Lucide defaults to 2), and size is one of the six the guide allows, so no screen can\n * introduce a seventh by typing a number. Canonical source:\n * .docs/styleguide/05-icons.md sections 1 and 1.1.\n *\n * Icons are keyed by concept, not by drawing. A screen asks for `delete`, not for\n * `trash-2`, so the same concept cannot pick up two different glyphs in two places, and\n * changing the glyph for a concept is one edit here instead of a search across the app.\n */\nexport const ICONS = {\n brand: Sprout,\n create: Plus,\n edit: Pencil,\n delete: Trash2,\n save: Check,\n close: X,\n search: Search,\n filter: SlidersHorizontal,\n \"sort-asc\": ChevronUp,\n \"sort-desc\": ChevronDown,\n \"navigate-into\": ChevronRight,\n \"page-previous\": ChevronLeft,\n \"page-next\": ChevronRight,\n expand: ChevronDown,\n collapse: ChevronUp,\n selected: Check,\n indeterminate: Minus,\n \"more-actions\": EllipsisVertical,\n \"drag-handle\": GripVertical,\n locked: Lock,\n dashboard: LayoutDashboard,\n collection: Layers,\n singleton: FileText,\n media: Image,\n settings: Settings,\n users: Users,\n permissions: ShieldCheck,\n \"content-types\": Database,\n system: Terminal,\n success: CircleCheck,\n warning: TriangleAlert,\n error: CircleX,\n info: Info,\n \"external-link\": ArrowUpRight,\n upload: Upload,\n copy: Copy,\n retry: RotateCcw,\n \"open-navigation\": Menu,\n bold: Bold,\n italic: Italic,\n strikethrough: Strikethrough,\n link: Link,\n unlink: Unlink,\n \"bullet-list\": List,\n \"numbered-list\": ListOrdered,\n quote: Quote,\n undo: Undo2,\n redo: Redo2,\n} as const satisfies Record<IconName, LucideIcon>\n\nexport { ICON_NAMES, isIconName }\nexport type { IconName }\n\n/** 12 badge and check, 14 compact controls, 16 default, 18 section heading, 20 page header, 24 empty state. */\nexport type IconSize = 12 | 14 | 16 | 18 | 20 | 24\n\nexport interface IconProps {\n name: IconName\n size?: IconSize\n /**\n * Set only where the icon is the whole message. An icon next to a text label is\n * decorative and stays hidden from assistive technology.\n */\n label?: string\n className?: string\n}\n\nexport function Icon({ name, size = 16, label, className }: IconProps) {\n const Glyph = ICONS[name]\n\n return (\n <Glyph\n size={size}\n strokeWidth={1.5}\n // Lucide sizes with width and height attributes, which a flex parent is free to\n // shrink. The icon box must never change, or every row it sits in shifts.\n className={className === undefined ? \"shrink-0\" : `shrink-0 ${className}`}\n aria-hidden={label === undefined ? true : undefined}\n aria-label={label}\n role={label === undefined ? undefined : \"img\"}\n />\n )\n}\n","import type { ReactNode } from \"react\"\n\nimport { cx } from \"./class-names.js\"\nimport { Icon } from \"./icon.js\"\nimport type { IconName } from \"./icon.js\"\n\n/**\n * The badge. Canonical source: .docs/styleguide/04-components.md section 7.\n *\n * Not interactive, ever. A badge that needs a click is a button or a filter chip, and\n * neither of those exists in this system yet.\n */\nexport type BadgeVariant =\n \"neutral\" | \"success\" | \"warning\" | \"danger\" | \"info\" | \"accent\"\n\nconst VARIANTS: Record<BadgeVariant, string> = {\n neutral: \"bg-surface-raised text-text-muted\",\n success: \"bg-success-muted text-success\",\n warning: \"bg-warning-muted text-warning\",\n danger: \"bg-danger-muted text-danger\",\n info: \"bg-info-muted text-info\",\n accent: \"bg-accent-soft text-accent-primary\",\n}\n\n/**\n * Entry status maps fixed, so no screen decides for itself what colour Published is.\n * Canonical source: .docs/styleguide/04-components.md section 7.\n */\nexport const ENTRY_STATUS_VARIANT = {\n draft: \"neutral\",\n published: \"success\",\n archived: \"warning\",\n error: \"danger\",\n} as const satisfies Record<string, BadgeVariant>\n\n/**\n * How a status is written on screen. Stored lowercase, displayed capitalized, decided once\n * so two screens cannot disagree about whether it is \"Published\" or \"published\".\n */\nexport const ENTRY_STATUS_LABEL = {\n draft: \"Draft\",\n published: \"Published\",\n archived: \"Archived\",\n} as const satisfies Record<string, string>\n\nexport interface BadgeProps {\n children: ReactNode\n variant?: BadgeVariant\n icon?: IconName\n}\n\nexport function Badge({ children, variant = \"neutral\", icon }: BadgeProps) {\n return (\n <span\n className={cx(\n \"inline-flex h-5.5 items-center gap-1 whitespace-nowrap rounded-full px-2 py-1 text-caption\",\n VARIANTS[variant],\n )}\n >\n {icon === undefined ? null : <Icon name={icon} size={12} />}\n {children}\n </span>\n )\n}\n\n/**\n * The status dot. Canonical source: .docs/styleguide/04-components.md section 8.\n * Never larger, never animated.\n */\nexport type StatusTone = \"neutral\" | \"success\" | \"warning\" | \"danger\" | \"info\"\n\nconst TONES: Record<StatusTone, string> = {\n neutral: \"bg-text-faint\",\n success: \"bg-success\",\n warning: \"bg-warning\",\n danger: \"bg-danger\",\n info: \"bg-info\",\n}\n\nexport interface StatusDotProps {\n tone?: StatusTone\n /** Set only where the dot is the whole message; otherwise the text beside it says it. */\n label?: string\n}\n\nexport function StatusDot({ tone = \"neutral\", label }: StatusDotProps) {\n return (\n <span\n role={label === undefined ? undefined : \"img\"}\n aria-label={label}\n aria-hidden={label === undefined ? true : undefined}\n className={cx(\"inline-block size-1.5 shrink-0 rounded-full\", TONES[tone])}\n />\n )\n}\n","\"use client\"\n\nimport Link from \"next/link\"\n\nimport { cx } from \"./class-names.js\"\nimport { Icon } from \"./icon.js\"\n\n/**\n * The breadcrumb. Canonical source: .docs/styleguide/03-layout.md section 3.1.\n *\n * `caption`, `text-faint`, a `chevron-right` separator at 14px. It sits above the page\n * title and is part of the page header, never a free-standing element: a trail with no\n * destination under it is decoration.\n *\n * Items are data, not nodes, so the page header cannot be handed a styled link that\n * disagrees with the trail beside it. The last item is the current page and is never a\n * link, because a link to the page you are on is a dead control.\n */\nexport interface BreadcrumbItem {\n label: string\n /** Absent on the last item, and on any ancestor that has no screen of its own. */\n href?: string\n}\n\nexport interface BreadcrumbProps {\n items: readonly BreadcrumbItem[]\n className?: string\n}\n\nexport function Breadcrumb({ items, className }: BreadcrumbProps) {\n if (items.length === 0) return null\n\n return (\n <nav aria-label=\"Breadcrumb\" className={className}>\n <ol className=\"flex items-center gap-1 text-caption text-text-faint\">\n {items.map((item, index) => {\n const last = index === items.length - 1\n\n return (\n <li\n key={`${item.label}:${item.href ?? \"\"}`}\n className=\"flex min-w-0 items-center gap-1\"\n >\n {index === 0 ? null : (\n <Icon name=\"navigate-into\" size={14} className=\"text-text-faint\" />\n )}\n {item.href === undefined || last ? (\n <span\n aria-current={last ? \"page\" : undefined}\n // Truncation is the default for text in a fixed-width control.\n // Canonical source: .docs/styleguide/01-foundations.md section 3.6.\n className={cx(\"truncate\", last && \"text-text-muted\")}\n >\n {item.label}\n </span>\n ) : (\n <Link\n href={item.href}\n className=\"truncate cursor-pointer state-transition hover:text-text-muted focus-visible:focus-ring\"\n >\n {item.label}\n </Link>\n )}\n </li>\n )\n })}\n </ol>\n </nav>\n )\n}\n","/**\n * The only spinner in the system.\n *\n * A spinner is allowed where the final structure is unknown or the wait sits inside a\n * control: skeletons cover everything else. See .docs/styleguide/04-components.md\n * section 16.\n */\nexport interface SpinnerProps {\n /** 14px inside a field, 16px inside a button. The guide allows no other size. */\n size?: 14 | 16\n label?: string\n}\n\nexport function Spinner({ size = 16, label }: SpinnerProps) {\n const dimension = size === 14 ? \"size-3.5\" : \"size-4\"\n\n return (\n <svg\n className={`${dimension} motion-safe:animate-spinner`}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={1.5}\n role={label === undefined ? \"presentation\" : \"status\"}\n aria-hidden={label === undefined}\n aria-label={label}\n >\n <circle cx=\"8\" cy=\"8\" r=\"6.25\" className=\"opacity-25\" />\n <path d=\"M14.25 8A6.25 6.25 0 0 0 8 1.75\" strokeLinecap=\"round\" />\n </svg>\n )\n}\n","import type { ButtonHTMLAttributes, Ref } from \"react\"\n\nimport { cx } from \"./class-names.js\"\nimport { Icon } from \"./icon.js\"\nimport type { IconName } from \"./icon.js\"\nimport { Spinner } from \"./spinner.js\"\n\n/**\n * The button, with the four variants and three sizes the style guide allows and nothing\n * else. Canonical source: .docs/styleguide/04-components.md section 2.\n *\n * A screen that needs a fifth appearance is a style guide change, not a prop.\n *\n * The leading icon is named, not passed as a node, so a caller cannot hand it a 20px\n * glyph or an icon outside the vocabulary. Size follows the button size: 14px at `sm`,\n * 16px otherwise.\n */\nexport type ButtonVariant = \"primary\" | \"secondary\" | \"ghost\" | \"danger\"\nexport type ButtonSize = \"sm\" | \"md\" | \"lg\"\n\n/**\n * Shared by Button and IconButton.\n *\n * `disabled:pointer-events-none` is deliberately absent. It was here, and it silently\n * cancelled the line above it: an element that is not hit-tested does not get its cursor\n * applied, so a disabled control showed the default arrow rather than the `not-allowed`\n * that .docs/styleguide/01-foundations.md section 9 requires. Found in the M10\n * accessibility audit. Nothing is lost by removing it: a disabled button does not dispatch\n * a click in any browser, and letting the pointer reach it is also what lets an icon-only\n * control keep its tooltip while it is disabled, which is when the reason for the disabled\n * state is most worth reading.\n */\nexport const BUTTON_BASE =\n \"inline-flex items-center justify-center rounded-sm border whitespace-nowrap select-none cursor-pointer state-transition focus-visible:focus-ring disabled:cursor-not-allowed\"\n\nexport const BUTTON_VARIANTS: Record<ButtonVariant, string> = {\n primary:\n \"bg-text-primary text-text-inverse border-text-primary hover:opacity-92 active:opacity-84 disabled:bg-surface-disabled disabled:text-text-disabled disabled:border-border-subtle disabled:opacity-100\",\n secondary:\n \"bg-surface-raised text-text-primary border-border-default hover:bg-surface-hover hover:border-border-strong active:bg-surface-active disabled:bg-surface-disabled disabled:text-text-disabled disabled:border-border-subtle\",\n ghost:\n \"bg-transparent text-text-secondary border-transparent hover:bg-surface-hover hover:text-text-primary active:bg-surface-active disabled:bg-transparent disabled:text-text-disabled\",\n danger:\n \"bg-danger-muted text-danger border-transparent hover:border-danger active:bg-danger active:text-text-inverse disabled:bg-surface-disabled disabled:text-text-disabled disabled:border-border-subtle\",\n}\n\n/** Icon size and spinner size per button size, from section 2.1. */\nexport const BUTTON_ICON_SIZE: Record<ButtonSize, 14 | 16> = {\n sm: 14,\n md: 16,\n lg: 16,\n}\n\nconst SIZES: Record<ButtonSize, string> = {\n sm: \"h-7.5 px-2.5 text-body-sm gap-1.5\",\n md: \"h-9 px-3.5 text-body-medium gap-2\",\n lg: \"h-10 px-4 text-body-medium gap-2\",\n}\n\nexport interface ButtonProps extends Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n \"type\"\n> {\n variant?: ButtonVariant\n size?: ButtonSize\n /** Replaces the leading icon with a spinner and takes the control out of the tab flow. */\n loading?: boolean\n icon?: IconName\n type?: \"button\" | \"submit\" | \"reset\"\n ref?: Ref<HTMLButtonElement>\n}\n\nexport function Button({\n variant = \"secondary\",\n size = \"md\",\n loading = false,\n icon,\n children,\n className,\n disabled,\n type = \"button\",\n ref,\n ...rest\n}: ButtonProps) {\n const iconSize = BUTTON_ICON_SIZE[size]\n\n return (\n <button\n ref={ref}\n type={type}\n // The label stays while loading, so the button keeps its width and the user keeps\n // the sentence they clicked.\n disabled={disabled === true || loading}\n aria-busy={loading || undefined}\n className={cx(\n BUTTON_BASE,\n SIZES[size],\n BUTTON_VARIANTS[variant],\n loading && \"cursor-wait\",\n className,\n )}\n {...rest}\n >\n {loading ? (\n <Spinner size={iconSize} />\n ) : icon === undefined ? null : (\n <Icon name={icon} size={iconSize} />\n )}\n {children}\n </button>\n )\n}\n","\"use client\"\n\nimport { useEffect, useId, useRef } from \"react\"\n\nimport { cx } from \"./class-names.js\"\nimport { Icon } from \"./icon.js\"\n\n/**\n * The checkbox. Canonical source: .docs/styleguide/04-components.md section 3.4.\n *\n * Controlled only, and `checked` carries the third state rather than a separate\n * `indeterminate` prop, because \"indeterminate and unchecked\" is not a state a table\n * header selection can be in and a two-prop API lets a caller express it anyway.\n *\n * The visible box is a span; the real input stays in the accessibility tree and keeps the\n * native label association, Space activation and form participation. Hiding it visually\n * rather than replacing it is what makes the whole label a click target for free.\n */\nexport interface CheckboxProps {\n checked: boolean | \"indeterminate\"\n onChange: (checked: boolean) => void\n /** Sits to the right of the box. Omit it only when a nearby cell header names the column. */\n label?: string\n /** Required when there is no visible label, for example the selection cell in a table. */\n ariaLabel?: string\n name?: string\n value?: string\n disabled?: boolean\n id?: string\n \"aria-describedby\"?: string | undefined\n}\n\nexport function Checkbox({\n checked,\n onChange,\n label,\n ariaLabel,\n name,\n value,\n disabled = false,\n id,\n \"aria-describedby\": describedBy,\n}: CheckboxProps) {\n const generatedId = useId()\n const inputId = id ?? generatedId\n const inputRef = useRef<HTMLInputElement>(null)\n const indeterminate = checked === \"indeterminate\"\n const on = checked === true || indeterminate\n\n // `indeterminate` is a DOM property with no attribute, so React cannot set it from JSX.\n // Without this the mixed state is invisible to assistive technology.\n useEffect(() => {\n if (inputRef.current !== null) inputRef.current.indeterminate = indeterminate\n }, [indeterminate])\n\n return (\n <label\n htmlFor={inputId}\n className={cx(\n \"inline-flex items-center gap-2 text-body-sm\",\n disabled\n ? \"cursor-not-allowed text-text-disabled\"\n : \"cursor-pointer text-text-secondary\",\n )}\n >\n <input\n ref={inputRef}\n id={inputId}\n type=\"checkbox\"\n name={name}\n value={value}\n checked={checked === true}\n disabled={disabled}\n aria-label={ariaLabel}\n aria-describedby={describedBy}\n aria-checked={indeterminate ? \"mixed\" : checked === true}\n onChange={(event) => onChange(event.target.checked)}\n className=\"peer sr-only\"\n />\n <span\n aria-hidden=\"true\"\n className={cx(\n \"flex size-4 shrink-0 items-center justify-center rounded-xs border state-transition peer-focus-visible:focus-ring\",\n disabled\n ? on\n ? \"border-text-disabled bg-text-disabled\"\n : \"border-border-subtle bg-surface-disabled\"\n : on\n ? \"border-text-primary bg-text-primary text-text-inverse\"\n : \"border-border-strong bg-surface-input hover:border-border-active\",\n )}\n >\n {indeterminate ? (\n <Icon name=\"indeterminate\" size={12} />\n ) : checked === true ? (\n <Icon name=\"selected\" size={12} />\n ) : null}\n </span>\n {label === undefined ? null : <span>{label}</span>}\n </label>\n )\n}\n","import type { ReactNode } from \"react\"\n\nimport { Icon } from \"./icon.js\"\nimport type { IconName } from \"./icon.js\"\n\n/**\n * The empty state. Canonical source: .docs/styleguide/04-components.md section 15.\n *\n * One icon, one heading, one description, at most one action. `action` is a single node\n * rather than an array on purpose: the guide calls a second action a design error, and a\n * type that cannot express it is cheaper than a review that has to catch it.\n */\nexport interface EmptyStateProps {\n icon?: IconName\n heading: string\n description?: string\n /** One primary or secondary button. */\n action?: ReactNode\n}\n\nexport function EmptyState({ icon, heading, description, action }: EmptyStateProps) {\n return (\n <div className=\"flex flex-col items-center px-6 py-12 text-center\">\n {icon === undefined ? null : (\n <span className=\"text-text-faint\">\n <Icon name={icon} size={24} />\n </span>\n )}\n <h2\n className={\n icon === undefined\n ? \"text-heading-sm text-text-primary\"\n : \"mt-3 text-heading-sm text-text-primary\"\n }\n >\n {heading}\n </h2>\n {description === undefined ? null : (\n <p className=\"mt-1 max-w-empty-state text-body-sm text-text-muted\">\n {description}\n </p>\n )}\n {action === undefined ? null : <div className=\"mt-4\">{action}</div>}\n </div>\n )\n}\n","import { useId } from \"react\"\nimport type { InputHTMLAttributes, ReactNode } from \"react\"\n\nimport { cx } from \"./class-names.js\"\nimport { Spinner } from \"./spinner.js\"\n\n/**\n * Field composition: label, 8px, control, 6px, help or error.\n * Canonical source: .docs/styleguide/04-components.md section 3.1.\n *\n * The error replaces the help text rather than joining it, so a field never shows two\n * competing sentences about the same value.\n */\nexport interface FieldProps {\n label: string\n /** Renders the `*` marker and wires `aria-required` on the control. */\n required?: boolean\n /** Renders the right-aligned \"Optional\" marker. Ignored when `required` is set. */\n optional?: boolean\n help?: string | undefined\n error?: string | undefined\n children: (control: {\n id: string\n describedBy: string | undefined\n invalid: boolean\n }) => ReactNode\n}\n\nexport function Field({\n label,\n required = false,\n optional = false,\n help,\n error,\n children,\n}: FieldProps) {\n const id = useId()\n const messageId = `${id}-message`\n const message = error ?? help\n const describedBy = message === undefined ? undefined : messageId\n\n return (\n <div className=\"flex flex-col\">\n <div className=\"flex items-baseline justify-between gap-2\">\n <label htmlFor={id} className=\"text-label text-text-secondary\">\n {label}\n {required ? (\n <span className=\"ml-1 text-danger\" aria-hidden=\"true\">\n *\n </span>\n ) : null}\n </label>\n {optional && !required ? (\n <span className=\"text-caption text-text-faint\">Optional</span>\n ) : null}\n </div>\n <div className=\"mt-2\">\n {children({ id, describedBy, invalid: error !== undefined })}\n </div>\n {message === undefined ? null : (\n <p\n id={messageId}\n className={cx(\n \"mt-1.5 text-caption\",\n error === undefined ? \"text-text-muted\" : \"text-danger\",\n )}\n >\n {message}\n </p>\n )}\n </div>\n )\n}\n\n/**\n * The single-line text control, shared by text, number, email, password and search.\n * Canonical source: .docs/styleguide/04-components.md section 3.2.\n *\n * Exported because the select trigger has to match it exactly, and a second copy of the\n * string would drift the moment one of them is corrected.\n */\nexport const INPUT_BASE =\n \"h-9 w-full rounded-sm border bg-surface-input px-3 text-body text-text-primary state-transition placeholder:text-text-faint hover:border-border-strong focus-visible:focus-field-ring disabled:bg-surface-disabled disabled:text-text-disabled disabled:cursor-not-allowed\"\n\nexport interface TextInputProps extends InputHTMLAttributes<HTMLInputElement> {\n invalid?: boolean\n /**\n * Inline validation in flight. Shows the spinner inside the trailing edge and takes the\n * control read-only rather than disabled, so the value stays selectable and the label\n * stays associated.\n */\n loading?: boolean\n}\n\nexport function TextInput({\n invalid = false,\n loading = false,\n className,\n readOnly,\n ...rest\n}: TextInputProps) {\n const input = (\n <input\n className={cx(\n INPUT_BASE,\n \"cursor-text\",\n // The error border survives focus; only the ring is added on top of it.\n invalid ? \"border-danger focus-visible:border-danger\" : \"border-border-default\",\n readOnly === true || loading ? \"bg-surface-disabled text-text-secondary\" : \"\",\n loading && \"pe-8.5\",\n className,\n )}\n aria-invalid={invalid || undefined}\n aria-busy={loading || undefined}\n readOnly={readOnly === true || loading}\n {...rest}\n />\n )\n\n if (!loading) return input\n\n return (\n <div className=\"relative flex items-center\">\n {input}\n <span className=\"pointer-events-none absolute end-3 text-text-muted\">\n <Spinner size={14} />\n </span>\n </div>\n )\n}\n","import type { ReactNode } from \"react\"\n\n/**\n * Form-level error: the failure that belongs to the submission rather than to one field.\n * Canonical source: .docs/styleguide/04-components.md section 3.8.\n *\n * It is a live region because it usually appears after a submit, when focus is still on\n * the button and nothing else on screen announces the refusal.\n */\nexport function FormError({ children }: { children: ReactNode }) {\n return (\n <p\n role=\"alert\"\n className=\"rounded-sm bg-danger-muted px-3 py-2 text-body-sm text-danger\"\n >\n {children}\n </p>\n )\n}\n","import type { FieldError } from \"../types/entry.js\"\n\n/**\n * A content type, field map, or registry is malformed. Thrown at definition time, which\n * for a code-defined type means at module load, so the mistake surfaces before any data\n * is written.\n */\nexport class SchemaError extends Error {\n override readonly name = \"SchemaError\"\n\n constructor(message: string) {\n super(message)\n }\n}\n\n/** Entry data failed the compiled validator. Carries one error per offending field path. */\nexport class ValidationError extends Error {\n override readonly name = \"ValidationError\"\n readonly errors: readonly FieldError[]\n\n constructor(errors: readonly FieldError[]) {\n super(\n errors.length === 1 && errors[0]\n ? `${errors[0].path}: ${errors[0].message}`\n : `${errors.length} fields failed validation`,\n )\n this.errors = errors\n }\n}\n\n/** A schema write was attempted against a content type that does not accept one. */\nexport class LockedTypeError extends Error {\n override readonly name = \"LockedTypeError\"\n readonly slug: string\n\n constructor(slug: string, reason?: string) {\n super(\n reason ??\n `Content type \"${slug}\" is locked. It is defined in code and cannot be changed through the Schema Builder or the adapter.`,\n )\n this.slug = slug\n }\n}\n\n/** A singleton was asked to hold more than the one entry it is allowed. */\nexport class SingletonError extends Error {\n override readonly name = \"SingletonError\"\n readonly slug: string\n\n constructor(slug: string, message: string) {\n super(message)\n this.slug = slug\n }\n}\n\n/**\n * The caller is not allowed to do this. Thrown by the adapter, from the same `can()` the\n * UI asked before it drew the button and the same matrix firestore.rules enforces.\n *\n * It exists as its own class because \"you may not\" and \"that is malformed\" need different\n * answers: a permission refusal is never fixed by editing the value. Carrying the action\n * and the content type lets a caller say which one without parsing the message.\n */\nexport class PermissionError extends Error {\n override readonly name = \"PermissionError\"\n readonly action: string\n /** Content type slug. Absent for an action that is not scoped to one. */\n readonly contentType: string | undefined\n\n constructor(action: string, contentType?: string, message?: string) {\n super(\n message ??\n (contentType === undefined\n ? `This account may not ${action}.`\n : `This account may not ${action} entries of \"${contentType}\".`),\n )\n this.action = action\n this.contentType = contentType\n }\n}\n\n/**\n * A write was refused for its size, its shape, or its timing rather than its content.\n * See core/write-limits.ts for which of these the security rules enforce as well and\n * which are the adapter's alone.\n */\nexport class WriteLimitError extends Error {\n override readonly name = \"WriteLimitError\"\n readonly code: string\n readonly path: string\n\n constructor(rejection: { code: string; path: string; message: string }) {\n super(rejection.message)\n this.code = rejection.code\n this.path = rejection.path\n }\n}\n","import type { Role } from \"../types/auth.js\"\nimport type { FieldError } from \"../types/entry.js\"\n\nimport {\n PermissionError,\n SchemaError,\n ValidationError,\n WriteLimitError,\n} from \"./errors.js\"\n\n/**\n * The one error taxonomy the admin renders from.\n *\n * Before this existed the treatments were real but scattered: the entry editor routed a\n * `ValidationError` to the offending field and fell back to a form-level message, the\n * Schema Builder put every failure in one banner, the media screens put every failure in a\n * toast, and a permission refusal read as \"something went wrong\" in all three. Each of\n * those was defensible on its own and none of them agreed with the others.\n *\n * This module is not a second system layered over them. It is the first one, factored out:\n * the M6 rule that a validation error lands on the field and only an unroutable path\n * reaches the form is preserved exactly, as the `field` treatment, and every other screen\n * now asks the same question instead of answering it privately.\n *\n * Five categories, one treatment each:\n *\n * | category | treatment | what the user sees |\n * |--------------|-----------|-----------------------------------------------------------|\n * | `validation` | `field` | the message on the control that owns the path; never a bare toast |\n * | `permission` | `banner` | a form-level notice naming the action, the subject and the role |\n * | `not-found` | `state` | an empty state with a way back; no alert, no red |\n * | `conflict` | `resolve` | a banner that names both resolutions and offers them |\n * | `transport` | `retry` | a banner or state carrying the one action that can help |\n *\n * `unknown` is the sixth, for a failure that fits none of them. It takes the `banner`\n * treatment and says plainly that the cause is unknown, rather than guessing at a category\n * and offering a retry that cannot work.\n *\n * The toast is deliberately not a treatment. It is the announcement channel for a failure\n * whose surface has already closed (a dialog that dismissed itself, a background upload),\n * and when it is used it prints this same `title` and `message`, so a failure can never be\n * worded twice.\n *\n * No React and no Firebase here, so the classification is testable in the node project and\n * callable from the adapter as well as from a render.\n */\n\nexport const ERROR_CATEGORIES = [\n \"validation\",\n \"permission\",\n \"not-found\",\n \"conflict\",\n \"transport\",\n \"unknown\",\n] as const\n\nexport type ErrorCategory = (typeof ERROR_CATEGORIES)[number]\n\n/** The chrome a category is rendered in. Exactly one per category; see the table above. */\nexport type ErrorTreatment = \"field\" | \"banner\" | \"state\" | \"resolve\" | \"retry\"\n\nconst TREATMENTS: Readonly<Record<ErrorCategory, ErrorTreatment>> = {\n validation: \"field\",\n permission: \"banner\",\n \"not-found\": \"state\",\n conflict: \"resolve\",\n transport: \"retry\",\n unknown: \"banner\",\n}\n\n/** The treatment a category must be rendered in. The single mapping, used by every screen. */\nexport function treatmentFor(category: ErrorCategory): ErrorTreatment {\n return TREATMENTS[category]\n}\n\nexport interface ClassifiedError {\n category: ErrorCategory\n treatment: ErrorTreatment\n /** A short heading. Used as the banner's first line and as a toast title. */\n title: string\n /** One or two sentences: what happened, and what the user can do about it. */\n message: string\n /**\n * The field errors, for `validation` only. Every other category leaves this empty, which\n * is what stops a non-validation failure from being routed onto a control.\n */\n fieldErrors: readonly FieldError[]\n /** True only for `transport`. A retry of anything else repeats the same refusal. */\n retryable: boolean\n /** What was thrown, kept for a boundary that wants to log it. Never rendered. */\n cause: unknown\n}\n\nexport interface ErrorContext {\n /** The signed-in role, so a permission refusal can name who was refused. */\n role?: Role | undefined\n /**\n * What the user was doing, as a verb phrase that completes \"could not ...\": \"save this\n * entry\", \"delete these entries\". Used for transport and unknown failures, where the\n * error itself says nothing a reader can act on.\n */\n action?: string | undefined\n /** What was acted on, named the way the UI names it: a content type label, a file name. */\n subject?: string | undefined\n}\n\n/**\n * Firestore error codes that mean the request never got a verdict.\n *\n * Duck-typed off `error.code` rather than caught by class, because nothing under\n * `src/core` or `src/admin` may import Firebase and a `FirebaseError` is therefore not\n * nameable here. Only these five are transport: everything else Firestore reports is a\n * verdict about the request, and telling a user to try again after a verdict is a lie.\n */\nconst TRANSPORT_CODES: readonly string[] = [\n \"unavailable\",\n \"deadline-exceeded\",\n \"cancelled\",\n \"internal\",\n \"resource-exhausted\",\n]\n\nconst PERMISSION_CODES: readonly string[] = [\"permission-denied\", \"unauthenticated\"]\n\nconst NOT_FOUND_CODES: readonly string[] = [\"not-found\"]\n\nconst CONFLICT_CODES: readonly string[] = [\n \"aborted\",\n \"already-exists\",\n \"failed-precondition\",\n]\n\n/** `firestore/unavailable` and `unavailable` are the same code from two Firebase versions. */\nfunction codeOf(thrown: unknown): string | undefined {\n if (typeof thrown !== \"object\" || thrown === null) return undefined\n const code: unknown = (thrown as { code?: unknown }).code\n if (typeof code !== \"string\") return undefined\n const slash = code.lastIndexOf(\"/\")\n return slash === -1 ? code : code.slice(slash + 1)\n}\n\n/**\n * A network failure with no code at all.\n *\n * `fetch` rejects with a bare `TypeError` whose message is the only evidence there is.\n * Matching on it is unpleasant and it is still better than filing a dropped connection\n * under \"unknown\", which offers no retry.\n */\nfunction looksLikeNetworkFailure(thrown: unknown): boolean {\n if (!(thrown instanceof Error)) return false\n return /network|fetch failed|failed to fetch|offline|connection/i.test(thrown.message)\n}\n\nfunction withRole(sentence: string, role: Role | undefined): string {\n return role === undefined ? sentence : `${sentence} You are signed in as ${role}.`\n}\n\n/**\n * Classifies anything that was thrown into exactly one category with its treatment.\n *\n * Order matters and is by certainty. A class the package defines is conclusive, a\n * Firestore code is strong evidence, and a message match is the last resort.\n */\nexport function classifyError(\n thrown: unknown,\n context: ErrorContext = {},\n): ClassifiedError {\n const target = context.subject === undefined ? \"\" : ` \"${context.subject}\"`\n\n if (thrown instanceof ValidationError) {\n return {\n category: \"validation\",\n treatment: TREATMENTS.validation,\n title:\n thrown.errors.length === 1\n ? \"One field needs attention\"\n : `${String(thrown.errors.length)} fields need attention`,\n message:\n \"The values were refused before anything was saved. Each problem is shown on the field it belongs to.\",\n fieldErrors: thrown.errors,\n retryable: false,\n cause: thrown,\n }\n }\n\n if (thrown instanceof PermissionError) {\n return {\n category: \"permission\",\n treatment: TREATMENTS.permission,\n title: \"You are not allowed to do that\",\n // The brief for this category: say what is denied and by whom. PermissionError\n // already carries the action and the content type; the role comes from the caller.\n message: withRole(thrown.message, context.role),\n fieldErrors: [],\n retryable: false,\n cause: thrown,\n }\n }\n\n if (thrown instanceof WriteLimitError) {\n // A size or shape rejection is about the content, so it is validation and it carries a\n // path. A rate rejection is about timing alone and clears by itself, so it is the one\n // write limit a retry actually fixes.\n if (thrown.code === \"too-fast\") {\n return {\n category: \"transport\",\n treatment: TREATMENTS.transport,\n title: \"Too many writes at once\",\n message: `${thrown.message} Wait a moment and try again.`,\n fieldErrors: [],\n retryable: true,\n cause: thrown,\n }\n }\n\n return {\n category: \"validation\",\n treatment: TREATMENTS.validation,\n title: \"This is too large to save\",\n message: thrown.message,\n fieldErrors: [{ path: thrown.path, rule: thrown.code, message: thrown.message }],\n retryable: false,\n cause: thrown,\n }\n }\n\n if (thrown instanceof SchemaError) {\n return {\n category: \"validation\",\n treatment: TREATMENTS.validation,\n title: \"This definition was refused\",\n message: thrown.message,\n fieldErrors: [],\n retryable: false,\n cause: thrown,\n }\n }\n\n const code = codeOf(thrown)\n\n if (code !== undefined && PERMISSION_CODES.includes(code)) {\n return {\n category: \"permission\",\n treatment: TREATMENTS.permission,\n title: \"You are not allowed to do that\",\n message: withRole(\n code === \"unauthenticated\"\n ? \"Your session is no longer valid, so the database refused the request. Sign in again.\"\n : `The database refused this request${target}. Your account does not have permission for it.`,\n context.role,\n ),\n fieldErrors: [],\n retryable: false,\n cause: thrown,\n }\n }\n\n if (code !== undefined && NOT_FOUND_CODES.includes(code)) {\n return {\n category: \"not-found\",\n treatment: TREATMENTS[\"not-found\"],\n title: \"Not found\",\n message: `What this page refers to${target} does not exist. It may have been deleted, or the address may be wrong.`,\n fieldErrors: [],\n retryable: false,\n cause: thrown,\n }\n }\n\n if (code !== undefined && CONFLICT_CODES.includes(code)) {\n return {\n category: \"conflict\",\n treatment: TREATMENTS.conflict,\n title: \"This changed somewhere else\",\n message:\n \"Someone else wrote to this while you were working on it, so nothing was saved. Reload to see their version, or save again to overwrite it.\",\n fieldErrors: [],\n retryable: false,\n cause: thrown,\n }\n }\n\n if (\n (code !== undefined && TRANSPORT_CODES.includes(code)) ||\n looksLikeNetworkFailure(thrown)\n ) {\n return {\n category: \"transport\",\n treatment: TREATMENTS.transport,\n title: \"Could not reach the database\",\n message: `The request did not get through${\n context.action === undefined\n ? \"\"\n : `, so nothing was changed while trying to ${context.action}`\n }. Check your connection and try again.`,\n fieldErrors: [],\n retryable: true,\n cause: thrown,\n }\n }\n\n return {\n category: \"unknown\",\n treatment: TREATMENTS.unknown,\n title:\n context.action === undefined\n ? \"Something went wrong\"\n : `Could not ${context.action}`,\n message:\n thrown instanceof Error && thrown.message !== \"\"\n ? thrown.message\n : \"No further detail was reported. Nothing is known to have changed.\",\n fieldErrors: [],\n retryable: false,\n cause: thrown,\n }\n}\n\n/**\n * The conflict the entry editor detects for itself.\n *\n * A stale write is noticed by comparing timestamps before the write, not by catching\n * something, so there is nothing to classify. It still has to arrive as a `ClassifiedError`\n * or the editor would be writing its own sentence for a category this module owns, which is\n * exactly the split this module exists to close.\n */\nexport function staleWriteError(subject: string): ClassifiedError {\n return {\n category: \"conflict\",\n treatment: TREATMENTS.conflict,\n title: \"Someone else saved this first\",\n message: `${subject} was changed after you opened it. Reload to see their version, or save again to overwrite it with yours.`,\n fieldErrors: [],\n retryable: false,\n cause: null,\n }\n}\n\n/** The other locally detected case: the thing being edited is gone. A state, not an error. */\nexport function missingError(subject: string): ClassifiedError {\n return {\n category: \"not-found\",\n treatment: TREATMENTS[\"not-found\"],\n title: `This ${subject} no longer exists`,\n message:\n \"It was deleted, or the address points at something this project does not hold. Nothing was changed.\",\n fieldErrors: [],\n retryable: false,\n cause: null,\n }\n}\n\n/** The locally detected permission refusal, for a screen that asked `can()` and got false. */\nexport function deniedError(what: string, role: Role | undefined): ClassifiedError {\n return {\n category: \"permission\",\n treatment: TREATMENTS.permission,\n title: \"You are not allowed to do that\",\n message: withRole(`Your account may not ${what}.`, role),\n fieldErrors: [],\n retryable: false,\n cause: null,\n }\n}\n","\"use client\"\n\nimport { Check, ChevronDown, ChevronRight, Copy, Menu, X } from \"lucide\"\nimport { MorphIcon } from \"morphicons/react\"\nimport type { IconNode } from \"morphicons/react\"\n\nimport type { IconName } from \"./icon-names.js\"\n\n/**\n * The animated half of the icon system. Canonical source:\n * .docs/styleguide/05-icons.md section 2.\n *\n * Morphicons is not a second icon family: it animates between two Lucide drawings. It\n * consumes icon *data* rather than components, which is why this is the one file that\n * imports the vanilla `lucide` package as well as `lucide-react` in `icon.tsx`. Both are\n * pinned to the same version, so a morph and the static icon next to it are the same\n * drawing.\n *\n * A morph is allowed only in the cases section 2.1 lists, so the glyph map is a closed set\n * of four names rather than the whole vocabulary: a screen cannot animate an icon the\n * guide says should not move. Names are checked against the static vocabulary, so a morph\n * pair can never drift onto a concept that does not exist.\n */\nconst MORPH_GLYPHS = {\n \"open-navigation\": Menu,\n close: X,\n \"navigate-into\": ChevronRight,\n expand: ChevronDown,\n // The copy-to-clipboard pair. Section 2.1 names it explicitly: `copy` becomes `check`\n // and reverts after 1200ms, which is the one place in the admin where an icon reports\n // that something invisible succeeded.\n copy: Copy,\n save: Check,\n} as const satisfies Partial<Record<IconName, IconNode>>\n\nexport type MorphIconName = keyof typeof MORPH_GLYPHS\n\nexport interface MorphingIconProps {\n name: MorphIconName\n /** The same six sizes the static icon allows. */\n size?: 12 | 14 | 16 | 18 | 20 | 24\n /** Set only where the icon is the whole message; otherwise it stays decorative. */\n label?: string\n className?: string\n}\n\nexport function MorphingIcon({ name, size = 16, label, className }: MorphingIconProps) {\n return (\n <MorphIcon\n icon={MORPH_GLYPHS[name]}\n size={size}\n // Matching the static icons exactly. The guide allows one stroke width in Husk.\n strokeWidth={1.5}\n // The calmest preset the library ships: critically damped, no overshoot, and it\n // settles inside motion-slow. `bouncy` is never used in Husk.\n spring=\"smooth\"\n // Under prefers-reduced-motion the morph degrades to an instant swap.\n reducedMotion=\"user\"\n className={className === undefined ? \"shrink-0\" : `shrink-0 ${className}`}\n {...(label === undefined ? {} : { label })}\n />\n )\n}\n","\"use client\"\n\nimport { cloneElement, useCallback, useEffect, useId, useRef, useState } from \"react\"\nimport type { KeyboardEvent, ReactElement } from \"react\"\n\nimport { cx } from \"./class-names.js\"\n\n/**\n * The tooltip. Canonical source: .docs/styleguide/04-components.md section 13.\n *\n * It explains, it never holds the only copy of anything, and it contains nothing\n * interactive. That is why the content prop is a string: a node would invite a link or a\n * button inside a surface the keyboard cannot reach.\n *\n * It opens on hover and on focus, because a keyboard user reaches an icon-only control by\n * focusing it and would otherwise never learn what it does. The 300ms open delay keeps it\n * from firing while the pointer crosses a toolbar; the 100ms close delay keeps it from\n * flickering between two adjacent triggers.\n */\nconst OPEN_DELAY_MS = 300\nconst CLOSE_DELAY_MS = 100\n\nexport interface TooltipProps {\n content: string\n /** Placed above by default; `bottom` is for triggers near the top edge of the viewport. */\n placement?: \"top\" | \"bottom\"\n /** A single element that can receive `aria-describedby`, normally a button. */\n children: ReactElement<{ \"aria-describedby\"?: string | undefined }>\n}\n\n/**\n * Merges the tooltip into whatever the trigger already pointed at, instead of replacing it.\n *\n * Found in the M10 accessibility audit: a trigger that carried its own `aria-describedby`\n * (the reorder handles point at a line of keyboard instructions) lost that description for\n * as long as the tooltip was open, which is exactly while someone is reading it.\n */\nfunction describedBy(\n children: ReactElement<{ \"aria-describedby\"?: string | undefined }>,\n open: boolean,\n id: string,\n): string | undefined {\n const own = children.props[\"aria-describedby\"]\n if (!open) return own\n return own === undefined || own === \"\" ? id : `${own} ${id}`\n}\n\nexport function Tooltip({ content, placement = \"top\", children }: TooltipProps) {\n const id = useId()\n const [open, setOpen] = useState(false)\n const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n\n const schedule = useCallback((next: boolean, delay: number) => {\n clearTimeout(timer.current)\n timer.current = setTimeout(() => setOpen(next), delay)\n }, [])\n\n // A trigger that unmounts while its timer is pending would otherwise set state on a\n // component that is gone.\n useEffect(() => () => clearTimeout(timer.current), [])\n\n function handleKeyDown(event: KeyboardEvent<HTMLSpanElement>) {\n if (event.key !== \"Escape\" || !open) return\n // Not stopped from propagating: Escape belongs to the topmost overlay, and a tooltip\n // inside an open menu must not swallow the key that closes the menu.\n clearTimeout(timer.current)\n setOpen(false)\n }\n\n return (\n <span\n className=\"relative inline-flex\"\n onPointerEnter={() => schedule(true, OPEN_DELAY_MS)}\n onPointerLeave={() => schedule(false, CLOSE_DELAY_MS)}\n onFocus={() => schedule(true, OPEN_DELAY_MS)}\n onBlur={() => schedule(false, CLOSE_DELAY_MS)}\n onKeyDown={handleKeyDown}\n >\n {cloneElement(children, { \"aria-describedby\": describedBy(children, open, id) })}\n {open ? (\n <span\n id={id}\n role=\"tooltip\"\n className={cx(\n \"pointer-events-none absolute left-1/2 -translate-x-1/2 max-w-tooltip w-max\",\n \"rounded-sm border border-border-default bg-surface-overlay px-2 py-1.5\",\n \"text-caption text-text-secondary shadow-overlay z-tooltip\",\n placement === \"top\" ? \"bottom-full mb-2\" : \"top-full mt-2\",\n )}\n >\n {content}\n </span>\n ) : null}\n </span>\n )\n}\n","import type { ButtonHTMLAttributes, Ref } from \"react\"\n\nimport { BUTTON_BASE, BUTTON_ICON_SIZE, BUTTON_VARIANTS } from \"./button.js\"\nimport type { ButtonSize, ButtonVariant } from \"./button.js\"\nimport { cx } from \"./class-names.js\"\nimport { Icon } from \"./icon.js\"\nimport type { IconName } from \"./icon.js\"\nimport { MorphingIcon } from \"./morph-icon.js\"\nimport type { MorphIconName } from \"./morph-icon.js\"\nimport { Spinner } from \"./spinner.js\"\nimport { Tooltip } from \"./tooltip.js\"\n\n/**\n * The square, icon-only button. Canonical source:\n * .docs/styleguide/04-components.md section 2.3.\n *\n * `label` is required and is not optional by accident: the guide says every icon-only\n * control carries an aria-label and a tooltip, so this component provides both from one\n * value rather than letting a caller supply one and forget the other. A caller that wants\n * different wording in the tooltip passes `tooltip` as well.\n *\n * `morph` animates the change from one icon to the other instead of swapping it. It is a\n * separate prop, and it narrows `icon` to the four names the morph set contains, because\n * .docs/styleguide/05-icons.md section 2.1 lists the only controls allowed to animate. A\n * boolean on a button cannot be turned on for a table action by accident if the icon that\n * action uses is not in the set.\n *\n * `pressed` is the toggle state, and it is a tri-state on purpose: leaving it undefined emits\n * no `aria-pressed` at all, so an ordinary action button is not announced as an unpressed\n * toggle.\n */\nconst SIZES: Record<ButtonSize, string> = {\n sm: \"size-7.5\",\n md: \"size-9\",\n lg: \"size-10\",\n}\n\n/**\n * The pressed toggle appearance from section 2.3.\n *\n * It replaces the variant classes instead of being layered on top of them, because the ghost\n * variant's `hover:bg-surface-hover` and this state's `surface-active` would otherwise be two\n * utilities of equal specificity and the winner would be whichever Tailwind emitted last. The\n * guide says a pressed control keeps `surface-active` on hover, so the hover rule simply is\n * not there while it is pressed.\n */\nconst PRESSED =\n \"bg-surface-active text-text-primary border-transparent disabled:bg-transparent disabled:text-text-disabled\"\n\ninterface IconButtonBase extends Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n \"type\" | \"children\" | \"aria-label\"\n> {\n /** The accessible name, and the tooltip text unless `tooltip` overrides it. */\n label: string\n tooltip?: string\n tooltipPlacement?: \"top\" | \"bottom\"\n variant?: ButtonVariant\n size?: ButtonSize\n /**\n * Turns the button into a toggle that reports a state: `aria-pressed` plus the pressed\n * appearance from .docs/styleguide/04-components.md section 2.3. The guide allows it on the\n * `ghost` variant only, which is the default here.\n */\n pressed?: boolean\n loading?: boolean\n ref?: Ref<HTMLButtonElement>\n type?: \"button\" | \"submit\" | \"reset\"\n}\n\nexport type IconButtonProps = IconButtonBase &\n ({ icon: IconName; morph?: false } | { icon: MorphIconName; morph: true })\n\nexport function IconButton(props: IconButtonProps) {\n const {\n label,\n tooltip,\n tooltipPlacement = \"top\",\n variant = \"ghost\",\n size = \"md\",\n pressed,\n loading = false,\n className,\n disabled,\n type = \"button\",\n ref,\n // Pulled out of `rest` by name: neither belongs on the DOM node, and the union has to\n // stay intact for the narrowing below.\n icon: _icon,\n morph: _morph,\n ...rest\n } = props\n\n const iconSize = BUTTON_ICON_SIZE[size]\n\n const glyph =\n props.morph === true ? (\n <MorphingIcon name={props.icon} size={iconSize} />\n ) : (\n <Icon name={props.icon} size={iconSize} />\n )\n\n return (\n <Tooltip content={tooltip ?? label} placement={tooltipPlacement}>\n <button\n ref={ref}\n type={type}\n aria-label={label}\n aria-pressed={pressed}\n disabled={disabled === true || loading}\n aria-busy={loading || undefined}\n className={cx(\n BUTTON_BASE,\n SIZES[size],\n pressed === true ? PRESSED : BUTTON_VARIANTS[variant],\n loading && \"cursor-wait\",\n className,\n )}\n {...rest}\n >\n {loading ? <Spinner size={iconSize} /> : glyph}\n </button>\n </Tooltip>\n )\n}\n","\"use client\"\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\"\nimport type { ReactNode } from \"react\"\n\nimport { cx } from \"./class-names.js\"\nimport { IconButton } from \"./icon-button.js\"\nimport { Icon } from \"./icon.js\"\nimport type { IconName } from \"./icon.js\"\n\n/**\n * Toasts. Canonical source: .docs/styleguide/04-components.md section 14.\n *\n * A provider plus a hook rather than a component a screen renders, because the thing that\n * raises a toast is usually a save handler three levels down from the region that shows\n * it, and threading state up through those levels is how toast stacks end up duplicated.\n *\n * Error toasts do not auto-dismiss and are announced as alerts. Everything else disappears\n * after five seconds and is announced politely, so a background save does not interrupt\n * what the user is reading.\n */\nexport type ToastTone = \"success\" | \"warning\" | \"error\" | \"info\"\n\nconst AUTO_DISMISS_MS = 5000\n\nconst TONE_ICON: Record<ToastTone, IconName> = {\n success: \"success\",\n warning: \"warning\",\n error: \"error\",\n info: \"info\",\n}\n\nconst TONE_COLOR: Record<ToastTone, string> = {\n success: \"text-success border-l-success\",\n warning: \"text-warning border-l-warning\",\n error: \"text-danger border-l-danger\",\n info: \"text-info border-l-info\",\n}\n\nexport interface ToastOptions {\n title: string\n description?: string\n tone?: ToastTone\n}\n\ninterface ToastRecord extends ToastOptions {\n id: string\n tone: ToastTone\n}\n\nexport interface ToastApi {\n /** Returns the id, so a long-running action can dismiss its own toast when it finishes. */\n notify: (options: ToastOptions) => string\n dismiss: (id: string) => void\n}\n\nconst ToastContext = createContext<ToastApi | null>(null)\n\nexport function useToast(): ToastApi {\n const api = useContext(ToastContext)\n if (api === null) {\n throw new Error(\"useToast must be called inside a ToastProvider.\")\n }\n return api\n}\n\n/**\n * The toast API, or null when no provider is mounted.\n *\n * For a screen where a toast is the secondary channel rather than the message itself: the\n * entry editor renders every failure it can attribute on the field that owns it and every\n * other failure at form level, and raises a toast on top of that. A host that forgot the\n * provider should lose the toast, not the screen.\n */\nexport function useOptionalToast(): ToastApi | null {\n return useContext(ToastContext)\n}\n\nexport function ToastProvider({ children }: { children: ReactNode }) {\n const [toasts, setToasts] = useState<readonly ToastRecord[]>([])\n const counter = useRef(0)\n const timers = useRef(new Map<string, ReturnType<typeof setTimeout>>())\n\n const dismiss = useCallback((id: string) => {\n const timer = timers.current.get(id)\n if (timer !== undefined) {\n clearTimeout(timer)\n timers.current.delete(id)\n }\n setToasts((current) => current.filter((toast) => toast.id !== id))\n }, [])\n\n const notify = useCallback(\n (options: ToastOptions) => {\n counter.current += 1\n const id = `husk-toast-${counter.current}`\n const tone = options.tone ?? \"info\"\n setToasts((current) => [...current, { ...options, id, tone }])\n\n // An error stays until it is read and dismissed. Anything else is a confirmation,\n // and a confirmation that needs a click is worse than no confirmation.\n if (tone !== \"error\") {\n timers.current.set(\n id,\n setTimeout(() => dismiss(id), AUTO_DISMISS_MS),\n )\n }\n return id\n },\n [dismiss],\n )\n\n // A provider that unmounts with toasts still pending would otherwise leave their timers\n // running and let them call setState on a component that is gone.\n useEffect(() => {\n const pending = timers.current\n return () => {\n for (const timer of pending.values()) clearTimeout(timer)\n pending.clear()\n }\n }, [])\n\n const api = useMemo<ToastApi>(() => ({ notify, dismiss }), [notify, dismiss])\n\n return (\n <ToastContext.Provider value={api}>\n {children}\n <div className=\"pointer-events-none fixed bottom-6 right-6 z-toast flex flex-col gap-2\">\n {toasts.map((toast) => (\n <Toast key={toast.id} toast={toast} onDismiss={() => dismiss(toast.id)} />\n ))}\n </div>\n </ToastContext.Provider>\n )\n}\n\nfunction Toast({ toast, onDismiss }: { toast: ToastRecord; onDismiss: () => void }) {\n return (\n <div\n role={toast.tone === \"error\" ? \"alert\" : \"status\"}\n className={cx(\n \"pointer-events-auto flex w-full max-w-toast items-start gap-2 rounded-md border border-border-default border-l-2 bg-surface-overlay px-3.5 py-3 shadow-overlay\",\n \"motion-safe:animate-toast-in\",\n TONE_COLOR[toast.tone],\n )}\n >\n <Icon name={TONE_ICON[toast.tone]} />\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-body-medium text-text-primary\">{toast.title}</p>\n {toast.description === undefined ? null : (\n <p className=\"mt-1 text-body-sm text-text-muted\">{toast.description}</p>\n )}\n </div>\n <IconButton icon=\"close\" label=\"Dismiss\" size=\"sm\" onClick={onDismiss} />\n </div>\n )\n}\n","\"use client\"\n\nimport { useEffect } from \"react\"\n\nimport { classifyError } from \"../../core/error-taxonomy.js\"\nimport type { ClassifiedError } from \"../../core/error-taxonomy.js\"\n\nimport { useOptionalToast } from \"./toast.js\"\n\n/**\n * What covers the failure a React error boundary cannot see.\n *\n * A boundary catches a throw during render, in an effect, or in a lifecycle. It does not\n * catch a rejected promise, and almost everything the admin does is a rejected promise: an\n * adapter call, an upload, a listener. Every one of those is inside a `try`/`catch` today,\n * but \"every one\" is a property of the code as it stands, not a mechanism, and the first\n * handler somebody forgets is a failure that reaches nobody. The browser's own answer to\n * an unhandled rejection is a console line the user will never see.\n *\n * So the admin listens at the window. An unhandled rejection is classified through the same\n * taxonomy as a caught one and raised as an error toast, which does not auto-dismiss.\n * `preventDefault` stops the default console report, because the toast now owns it.\n *\n * `error` is listened to for the same reason: a throw inside a `setTimeout` or an event\n * handler registered outside React is not on any component's stack either.\n *\n * This is a net, not a treatment. Anything it catches is a missing `catch` somewhere, and\n * the toast says so in the one place that was not meant to have to.\n */\nexport interface ErrorCaptureProps {\n /**\n * Called for every captured failure, before the toast. For a host that ships errors to\n * a reporter; the admin itself does not, because it has no service to ship them to.\n */\n onCapture?: ((error: ClassifiedError) => void) | undefined\n}\n\nexport function ErrorCapture({ onCapture }: ErrorCaptureProps) {\n const toast = useOptionalToast()\n\n useEffect(() => {\n function report(thrown: unknown): void {\n const classified = classifyError(thrown)\n onCapture?.(classified)\n toast?.notify({\n tone: \"error\",\n title: classified.title,\n description: classified.message,\n })\n }\n\n function onRejection(event: PromiseRejectionEvent): void {\n // Claimed: the toast reports it now, so the browser's console report would be a\n // second, less useful copy of the same failure.\n event.preventDefault()\n report(event.reason)\n }\n\n function onError(event: ErrorEvent): void {\n // A failed image or stylesheet fires this with no error object. It is not an\n // application failure and a toast about it would be noise over a broken thumbnail.\n if (event.error === null || event.error === undefined) return\n report(event.error)\n }\n\n window.addEventListener(\"unhandledrejection\", onRejection)\n window.addEventListener(\"error\", onError)\n\n return () => {\n window.removeEventListener(\"unhandledrejection\", onRejection)\n window.removeEventListener(\"error\", onError)\n }\n }, [toast, onCapture])\n\n return null\n}\n","\"use client\"\n\nimport type { ReactNode } from \"react\"\n\nimport type { ClassifiedError } from \"../../core/error-taxonomy.js\"\n\nimport { Button } from \"./button.js\"\nimport { cx } from \"./class-names.js\"\n\n/**\n * The in-place treatment for a classified error that is not a field error.\n * Canonical source: .docs/styleguide/04-components.md section 19.\n *\n * One component for the `banner`, `resolve` and `retry` treatments, because they are one\n * piece of chrome with a different actions slot, not three designs. Splitting them would\n * be how a permission refusal and a transport failure end up looking like two products.\n *\n * `validation` never reaches here. Its treatment is the field itself, and the entry editor\n * routes each error to the control that owns its path; only a path naming no rendered field\n * falls back to a banner, which is the M6 rule this component inherits rather than replaces.\n * `not-found` never reaches here either: it is a state, rendered by `ErrorScreen`.\n */\nexport interface ErrorNoticeProps {\n error: ClassifiedError\n /**\n * The retry. Rendered only when the taxonomy says a retry is meaningful, so a screen\n * cannot offer one for a refusal that will refuse again.\n */\n onRetry?: (() => void) | undefined\n /** The resolutions for a `conflict`, which has two and must name both. */\n actions?: ReactNode\n className?: string\n}\n\nexport function ErrorNotice({ error, onRetry, actions, className }: ErrorNoticeProps) {\n const showRetry = error.retryable && onRetry !== undefined\n\n return (\n <div\n // Announced, because it almost always appears while focus is still on the control\n // that triggered the failed action and nothing else on screen reports it.\n role=\"alert\"\n data-error-category={error.category}\n className={cx(\n \"flex flex-wrap items-start justify-between gap-3 rounded-sm bg-danger-muted px-3 py-2\",\n className,\n )}\n >\n <div className=\"min-w-0\">\n <p className=\"text-body-medium text-danger\">{error.title}</p>\n <p className=\"mt-1 text-body-sm text-danger\">{error.message}</p>\n </div>\n {actions === undefined && !showRetry ? null : (\n <div className=\"flex shrink-0 items-center gap-2\">\n {actions}\n {showRetry ? (\n <Button size=\"sm\" variant=\"secondary\" icon=\"retry\" onClick={onRetry}>\n Try again\n </Button>\n ) : null}\n </div>\n )}\n </div>\n )\n}\n","\"use client\"\n\nimport { useEffect, useId, useRef, useState } from \"react\"\nimport type { KeyboardEvent } from \"react\"\n\nimport { Button } from \"./button.js\"\nimport type { ButtonSize, ButtonVariant } from \"./button.js\"\nimport { cx } from \"./class-names.js\"\nimport { IconButton } from \"./icon-button.js\"\nimport { Icon } from \"./icon.js\"\nimport type { IconName } from \"./icon.js\"\n\n/**\n * The dropdown menu. Canonical source: .docs/styleguide/04-components.md section 11.\n *\n * Items are data rather than children, because every menu in the admin is generated: the\n * row actions come from what the user may do to that entry, the sidebar overflow comes\n * from the registry. A children-based API would invite a screen to hand-build one.\n *\n * Keyboard behaviour follows the menu button pattern: the trigger opens on Enter, Space or\n * ArrowDown, focus moves into the list, arrows move the highlight past disabled items and\n * separators, Escape closes and returns focus to the trigger, and Tab closes without\n * grabbing focus back so the page's tab order is preserved.\n */\nexport type MenuEntry =\n | {\n kind: \"item\"\n id: string\n label: string\n icon?: IconName\n /** Renders the trailing check from section 11. */\n selected?: boolean\n destructive?: boolean\n disabled?: boolean\n /** Right-aligned hint, for example \"Ctrl S\". Display only; the menu binds nothing. */\n shortcut?: string\n }\n | { kind: \"separator\"; id: string }\n | { kind: \"section\"; id: string; label: string }\n\nexport interface MenuProps {\n items: readonly MenuEntry[]\n onSelect: (id: string) => void\n /** The trigger's accessible name, and its tooltip when the trigger is icon-only. */\n label: string\n /** Set to render a labelled trigger instead of the icon-only default. */\n triggerLabel?: string\n triggerIcon?: IconName\n triggerVariant?: ButtonVariant\n triggerSize?: ButtonSize\n /** Which edge of the trigger the menu lines up with. */\n align?: \"start\" | \"end\"\n /**\n * Which side of the trigger the menu opens toward. Defaults to `\"bottom\"`, unchanged from\n * every existing call site. Set to `\"top\"` for a trigger pinned to the bottom of a\n * scrollable region, for example the sidebar's account menu, so the panel opens into the\n * viewport instead of past it.\n */\n side?: \"top\" | \"bottom\"\n}\n\nfunction isSelectable(entry: MenuEntry | undefined): boolean {\n return entry?.kind === \"item\" && entry.disabled !== true\n}\n\nexport function Menu({\n items,\n onSelect,\n label,\n triggerLabel,\n triggerIcon = \"more-actions\",\n triggerVariant = \"ghost\",\n triggerSize = \"md\",\n align = \"end\",\n side = \"bottom\",\n}: MenuProps) {\n const baseId = useId()\n const menuId = `${baseId}-menu`\n const [open, setOpen] = useState(false)\n const [active, setActive] = useState(-1)\n const triggerRef = useRef<HTMLButtonElement>(null)\n const menuRef = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n if (!open) return\n menuRef.current?.focus()\n }, [open])\n\n useEffect(() => {\n if (!open) return\n function handlePointerDown(event: MouseEvent) {\n const target = event.target\n if (!(target instanceof Node)) return\n if (menuRef.current?.contains(target) === true) return\n if (triggerRef.current?.contains(target) === true) return\n setOpen(false)\n }\n document.addEventListener(\"mousedown\", handlePointerDown)\n return () => document.removeEventListener(\"mousedown\", handlePointerDown)\n }, [open])\n\n function step(from: number, direction: 1 | -1): number {\n for (let i = from; i >= 0 && i < items.length; i += direction) {\n if (isSelectable(items[i])) return i\n }\n return from\n }\n\n function openMenu(fromEnd = false) {\n setActive(fromEnd ? step(items.length - 1, -1) : step(0, 1))\n setOpen(true)\n }\n\n function close(restoreFocus: boolean) {\n setOpen(false)\n setActive(-1)\n if (restoreFocus) triggerRef.current?.focus()\n }\n\n function commit(index: number) {\n const entry = items[index]\n if (entry === undefined || !isSelectable(entry) || entry.kind !== \"item\") return\n close(true)\n onSelect(entry.id)\n }\n\n function handleTriggerKeyDown(event: KeyboardEvent<HTMLButtonElement>) {\n if (event.key === \"ArrowDown\") {\n event.preventDefault()\n openMenu()\n return\n }\n if (event.key === \"ArrowUp\") {\n event.preventDefault()\n openMenu(true)\n }\n }\n\n function handleMenuKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault()\n setActive((current) => step(Math.min(current + 1, items.length - 1), 1))\n return\n case \"ArrowUp\":\n event.preventDefault()\n setActive((current) => step(Math.max(current - 1, 0), -1))\n return\n case \"Home\":\n event.preventDefault()\n setActive(step(0, 1))\n return\n case \"End\":\n event.preventDefault()\n setActive(step(items.length - 1, -1))\n return\n case \"Enter\":\n case \" \":\n event.preventDefault()\n commit(active)\n return\n case \"Escape\":\n event.preventDefault()\n close(true)\n return\n case \"Tab\":\n close(false)\n return\n default:\n }\n }\n\n const triggerProps = {\n ref: triggerRef,\n \"aria-haspopup\": \"menu\",\n \"aria-expanded\": open,\n \"aria-controls\": open ? menuId : undefined,\n onClick: () => (open ? close(false) : openMenu()),\n onKeyDown: handleTriggerKeyDown,\n } as const\n\n return (\n <div className=\"relative inline-flex\">\n {triggerLabel === undefined ? (\n <IconButton\n icon={triggerIcon}\n label={label}\n variant={triggerVariant}\n size={triggerSize}\n {...triggerProps}\n />\n ) : (\n <Button\n icon={triggerIcon}\n variant={triggerVariant}\n size={triggerSize}\n aria-label={label}\n {...triggerProps}\n >\n {triggerLabel}\n </Button>\n )}\n\n {open ? (\n <div\n ref={menuRef}\n id={menuId}\n role=\"menu\"\n tabIndex={-1}\n aria-label={label}\n aria-activedescendant={active === -1 ? undefined : `${baseId}-${active}`}\n onKeyDown={handleMenuKeyDown}\n className={cx(\n \"absolute z-dropdown min-w-menu rounded-md border border-border-default bg-surface-overlay p-1.5 shadow-overlay\",\n \"focus-visible:focus-ring\",\n side === \"top\"\n ? \"bottom-full mb-1 motion-safe:animate-menu-in-up\"\n : \"top-full mt-1 motion-safe:animate-menu-in\",\n align === \"end\" ? \"right-0\" : \"left-0\",\n )}\n >\n {items.map((entry, index) => {\n if (entry.kind === \"separator\") {\n return (\n <div\n key={entry.id}\n role=\"separator\"\n className=\"my-1 border-t border-border-subtle\"\n />\n )\n }\n if (entry.kind === \"section\") {\n return (\n <div\n key={entry.id}\n role=\"presentation\"\n className=\"px-2.5 py-1.5 text-micro uppercase text-text-faint\"\n >\n {entry.label}\n </div>\n )\n }\n\n const disabled = entry.disabled === true\n return (\n <div\n key={entry.id}\n id={`${baseId}-${index}`}\n role=\"menuitem\"\n aria-disabled={disabled || undefined}\n onMouseEnter={() => !disabled && setActive(index)}\n onClick={() => commit(index)}\n className={cx(\n \"flex h-8.5 items-center gap-2 rounded-sm px-2.5 text-body-sm state-transition\",\n disabled\n ? \"cursor-not-allowed text-text-disabled\"\n : entry.destructive === true\n ? \"cursor-pointer text-danger\"\n : \"cursor-pointer text-text-secondary\",\n !disabled &&\n index === active &&\n (entry.destructive === true\n ? \"bg-danger-muted\"\n : \"bg-surface-hover text-text-primary\"),\n )}\n >\n {entry.icon === undefined ? null : <Icon name={entry.icon} />}\n <span className=\"flex-1 truncate\">{entry.label}</span>\n {entry.shortcut === undefined ? null : (\n <span className=\"text-caption text-text-faint\">{entry.shortcut}</span>\n )}\n {entry.selected === true ? (\n <span className=\"text-text-primary\">\n <Icon name=\"selected\" size={14} />\n </span>\n ) : null}\n </div>\n )\n })}\n </div>\n ) : null}\n </div>\n )\n}\n","import type { ReactNode } from \"react\"\n\nimport { cx } from \"./class-names.js\"\n\n/**\n * The panel, in the two forms the system has.\n * Canonical source: .docs/styleguide/03-layout.md sections 4.1, 4.2 and 4.3.\n *\n * Standard is the content container; `raised` is the metric tile. Neither carries a\n * shadow, and the raised one always carries `border-subtle`, so a panel edge stays legible\n * against `surface-base`.\n *\n * A panel is the second and last level of container the system allows. Nesting one inside\n * another inside a third is a design error, not a layout choice.\n */\nexport type PanelPadding = \"none\" | \"compact\" | \"standard\" | \"large\"\n\nconst PADDING: Record<PanelPadding, string> = {\n none: \"\",\n compact: \"p-4\",\n standard: \"p-5\",\n large: \"p-6\",\n}\n\nexport interface PanelProps {\n children: ReactNode\n /**\n * `none` is for a body that supplies its own inset: a table, or a row list separated by\n * `border-subtle`. Padding there would sit on top of the row padding and double it.\n */\n padding?: PanelPadding\n /** The raised metric panel from section 4.2. */\n raised?: boolean\n className?: string\n}\n\nexport function Panel({\n children,\n padding = \"standard\",\n raised = false,\n className,\n}: PanelProps) {\n return (\n <div\n className={cx(\n raised\n ? \"bg-surface-raised border border-border-subtle rounded-sm\"\n : \"bg-surface-card border border-border-default rounded-md\",\n PADDING[padding],\n className,\n )}\n >\n {children}\n </div>\n )\n}\n","import { cx } from \"./class-names.js\"\n\n/**\n * The skeleton. Canonical source: .docs/styleguide/04-components.md section 16.\n *\n * Skeletons are the default loading treatment and spinners are the exception, so this\n * component mirrors the shape of what it replaces rather than offering a generic grey\n * box: a text line is as tall as its type token's line height, a block carries the radius\n * of the component it stands in for.\n *\n * The pulse is behind `motion-safe`, because a reduced-motion user gets the layout\n * without the animation, which is the whole benefit of a skeleton anyway.\n */\nexport type SkeletonLine =\n | \"heading-md\"\n | \"heading-sm\"\n | \"body\"\n | \"body-sm\"\n | \"label\"\n | \"caption\"\n | \"micro\"\n | \"metric-lg\"\n | \"metric-md\"\n\n/** Line height per type token, from .docs/styleguide/01-foundations.md section 3.3. */\nconst LINE_HEIGHTS: Record<SkeletonLine, string> = {\n \"heading-md\": \"h-6\",\n \"heading-sm\": \"h-5\",\n body: \"h-5\",\n \"body-sm\": \"h-4.5\",\n label: \"h-4\",\n caption: \"h-3.75\",\n micro: \"h-3.5\",\n \"metric-lg\": \"h-8.5\",\n \"metric-md\": \"h-7.25\",\n}\n\nconst RADII = {\n xs: \"rounded-xs\",\n sm: \"rounded-sm\",\n md: \"rounded-md\",\n lg: \"rounded-lg\",\n full: \"rounded-full\",\n} as const\n\nexport interface SkeletonProps {\n /** Renders a text line at the given type token's line height and `radius-xs`. */\n line?: SkeletonLine\n /** Ignored when `line` is set, which always uses `radius-xs`. */\n radius?: keyof typeof RADII\n /** Width and, for a block, height. Token utilities only. */\n className?: string\n /**\n * Announces the wait. Set it once per loading region, not once per skeleton, or a\n * screen reader reads \"Loading\" for every line on the page.\n */\n label?: string\n}\n\nexport function Skeleton({ line, radius = \"sm\", className, label }: SkeletonProps) {\n return (\n <span\n role={label === undefined ? undefined : \"status\"}\n aria-label={label}\n aria-hidden={label === undefined ? true : undefined}\n className={cx(\n \"block bg-surface-raised motion-safe:animate-skeleton\",\n line === undefined ? RADII[radius] : `rounded-xs ${LINE_HEIGHTS[line]}`,\n className,\n )}\n />\n )\n}\n","import { cx } from \"./class-names.js\"\nimport { Icon } from \"./icon.js\"\nimport type { IconName } from \"./icon.js\"\nimport { Panel } from \"./panel.js\"\nimport { Skeleton } from \"./skeleton.js\"\n\n/**\n * The metric tile: one label, one number.\n * Canonical source: .docs/styleguide/03-layout.md section 4.2, with the internal spacing\n * added to that section in the same change that added this component.\n *\n * Three states, and the third is the point. A figure the data layer could not produce\n * renders as `Unavailable` with the reason beside it, because a plausible-looking wrong\n * number on a dashboard is worse than an admitted gap: nobody checks a number that looks\n * right.\n *\n * The value row keeps the `metric-lg` line height in every state, so a tile that is\n * loading, resolved or unavailable occupies the same box and the grid never reflows.\n */\nexport interface MetricProps {\n label: string\n /** Ignored while `loading`, and when `unavailable` is set. */\n value?: string | number\n /** One line under the value: the unit, or what the number counts. */\n caption?: string\n icon?: IconName\n loading?: boolean\n /** Why there is no figure. Replaces the value and is shown in place of the caption. */\n unavailable?: string\n className?: string\n}\n\nexport function Metric({\n label,\n value,\n caption,\n icon,\n loading = false,\n unavailable,\n className,\n}: MetricProps) {\n const note = unavailable ?? caption\n\n return (\n <Panel raised padding=\"compact\" {...(className === undefined ? {} : { className })}>\n <div className=\"flex items-center gap-2 text-text-muted\">\n {icon === undefined ? null : <Icon name={icon} size={14} />}\n <span className=\"truncate text-label\">{label}</span>\n </div>\n\n {/* h-8.5 is the metric-lg line height, from .docs/styleguide/01-foundations.md 3.4. */}\n <div className=\"mt-2 flex h-8.5 items-end\">\n {loading ? (\n <Skeleton line=\"metric-lg\" className=\"w-16\" />\n ) : unavailable !== undefined ? (\n <span className=\"text-body-sm text-text-muted\">Unavailable</span>\n ) : (\n <span className=\"text-metric-lg tabular-nums text-text-primary\">\n {value ?? 0}\n </span>\n )}\n </div>\n\n {loading ? (\n <Skeleton line=\"caption\" className=\"mt-1 w-20\" />\n ) : note === undefined ? null : (\n <p\n className={cx(\n \"mt-1 truncate text-caption\",\n unavailable === undefined ? \"text-text-faint\" : \"text-text-muted\",\n )}\n >\n {note}\n </p>\n )}\n </Panel>\n )\n}\n","/**\n * What counts as focusable inside an overlay.\n *\n * Shared by every component that has to keep Tab inside itself (the modal, the navigation\n * drawer). One selector, because two copies drift and the divergence only shows up as a\n * keyboard user walking out of a dialog into the page behind it.\n */\nexport const FOCUSABLE_SELECTOR =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n\nexport function focusableWithin(root: HTMLElement | null): HTMLElement[] {\n if (root === null) return []\n return Array.from(root.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR))\n}\n\n/**\n * Keeps Tab and Shift+Tab inside `root`. Returns true when it handled the event, so a\n * caller can tell a cycled Tab apart from one it should let through.\n */\nexport function cycleTabWithin(\n root: HTMLElement | null,\n event: { key: string; shiftKey: boolean; preventDefault: () => void },\n): boolean {\n if (event.key !== \"Tab\") return false\n\n const elements = focusableWithin(root)\n const first = elements[0]\n const last = elements[elements.length - 1]\n\n if (first === undefined || last === undefined) {\n event.preventDefault()\n return true\n }\n\n if (event.shiftKey && document.activeElement === first) {\n event.preventDefault()\n last.focus()\n return true\n }\n\n if (!event.shiftKey && document.activeElement === last) {\n event.preventDefault()\n first.focus()\n return true\n }\n\n return false\n}\n","\"use client\"\n\nimport { useCallback, useEffect, useId, useRef } from \"react\"\nimport { createPortal } from \"react-dom\"\nimport type { KeyboardEvent, ReactNode } from \"react\"\n\nimport { cx } from \"./class-names.js\"\nimport { focusableWithin } from \"./focusable.js\"\nimport { IconButton } from \"./icon-button.js\"\n\n/**\n * The modal. Canonical source: .docs/styleguide/04-components.md section 12.\n *\n * The visual half is small; the behaviour is the component. Focus lands on the first\n * interactive element, Tab cycles inside the dialog instead of walking out into the page\n * behind it, Escape closes, closing returns focus to whatever opened it, and page scroll\n * is locked while it is open.\n *\n * `dismissible` is false for destructive dialogs, which is what the guide means by \"the\n * backdrop click closes a non-destructive dialog only\". Escape still works there: a user\n * who wants out must always have a way out, and cancelling a delete is the safe outcome.\n */\nexport type ModalWidth = \"sm\" | \"md\" | \"lg\" | \"xl\"\n\nconst WIDTHS: Record<ModalWidth, string> = {\n sm: \"max-w-modal-sm\",\n md: \"max-w-modal-md\",\n lg: \"max-w-modal-lg\",\n xl: \"max-w-modal-xl\",\n}\n\nexport interface ModalProps {\n open: boolean\n onClose: () => void\n title: string\n description?: string\n width?: ModalWidth\n /** Whether a backdrop click closes. False for destructive confirmations. */\n dismissible?: boolean\n /** Right-aligned actions: cancel as secondary, confirm last. */\n footer?: ReactNode\n children?: ReactNode\n}\n\nexport function Modal({\n open,\n onClose,\n title,\n description,\n width = \"md\",\n dismissible = true,\n footer,\n children,\n}: ModalProps) {\n const baseId = useId()\n const titleId = `${baseId}-title`\n const descriptionId = `${baseId}-description`\n const dialogRef = useRef<HTMLDivElement>(null)\n const restoreTo = useRef<HTMLElement | null>(null)\n\n const focusable = useCallback(\n (): HTMLElement[] => focusableWithin(dialogRef.current),\n [],\n )\n\n useEffect(() => {\n if (!open) return\n\n // Captured before focus moves, so closing hands it back to the exact control that\n // opened the dialog rather than to the top of the document.\n restoreTo.current =\n document.activeElement instanceof HTMLElement ? document.activeElement : null\n\n const first = focusable()[0]\n if (first === undefined) dialogRef.current?.focus()\n else first.focus()\n\n const { overflow } = document.body.style\n document.body.style.overflow = \"hidden\"\n\n return () => {\n document.body.style.overflow = overflow\n restoreTo.current?.focus()\n }\n }, [open, focusable])\n\n if (!open) return null\n\n function handleKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n if (event.key === \"Escape\") {\n event.stopPropagation()\n onClose()\n return\n }\n if (event.key !== \"Tab\") return\n\n const elements = focusable()\n const first = elements[0]\n const last = elements[elements.length - 1]\n if (first === undefined || last === undefined) {\n event.preventDefault()\n return\n }\n\n if (event.shiftKey && document.activeElement === first) {\n event.preventDefault()\n last.focus()\n return\n }\n if (!event.shiftKey && document.activeElement === last) {\n event.preventDefault()\n first.focus()\n }\n }\n\n const dialog = (\n // The backdrop is the click surface, so the handler sits here and checks the target\n // rather than on a sibling element the dialog would have to be layered over.\n <div\n className=\"fixed inset-0 z-overlay flex items-center justify-center bg-backdrop p-6\"\n onMouseDown={(event) => {\n if (!dismissible) return\n if (event.target === event.currentTarget) onClose()\n }}\n >\n <div\n ref={dialogRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n aria-describedby={description === undefined ? undefined : descriptionId}\n tabIndex={-1}\n onKeyDown={handleKeyDown}\n className={cx(\n \"relative z-modal flex w-full flex-col modal-max-height overflow-hidden rounded-lg border border-border-default bg-surface-overlay p-6 shadow-overlay\",\n WIDTHS[width],\n )}\n >\n <div className=\"absolute right-4 top-4\">\n <IconButton icon=\"close\" label=\"Close\" size=\"sm\" onClick={onClose} />\n </div>\n\n <h2 id={titleId} className=\"text-heading-md text-text-primary\">\n {title}\n </h2>\n {description === undefined ? null : (\n <p id={descriptionId} className=\"mt-2 text-body-sm text-text-muted\">\n {description}\n </p>\n )}\n\n {children === undefined ? null : (\n <div className=\"mt-5 min-h-0 flex-1 overflow-y-auto\">{children}</div>\n )}\n\n {footer === undefined ? null : (\n <div className=\"mt-6 flex justify-end gap-2\">{footer}</div>\n )}\n </div>\n </div>\n )\n\n // Portalled so an ancestor's overflow or stacking context cannot clip or reorder it.\n return createPortal(dialog, document.body)\n}\n","\"use client\"\n\nimport { IconButton } from \"./icon-button.js\"\n\n/**\n * The pagination row under a table.\n * Canonical source: .docs/styleguide/04-components.md section 6.\n *\n * Cursor paging, not page numbers: the guide rules numbered page lists out, and Firestore\n * cannot answer \"page 7\" anyway without reading the six pages before it. Previous and next\n * are therefore the only moves, and the caller holds the cursors.\n *\n * The range reads \"1-25 of 248\" when the total is known and \"1-25\" when it is not. A total\n * is a separate count read that can be refused on its own, and inventing one would mislead\n * the reader about how much is behind the list.\n */\nexport interface PaginationProps {\n /** 1-based index of the first row on this page. */\n from: number\n /** 1-based index of the last row on this page. */\n to: number\n total?: number | undefined\n hasPrevious: boolean\n hasNext: boolean\n onPrevious: () => void\n onNext: () => void\n /** Names what is being paged, for the arrows' accessible names. */\n label: string\n}\n\nexport function Pagination({\n from,\n to,\n total,\n hasPrevious,\n hasNext,\n onPrevious,\n onNext,\n label,\n}: PaginationProps) {\n // An empty page reads \"0\", not \"0-0\" and not \"1-0\": there is no first row to number.\n const range = from < 1 || to < from ? \"0\" : `${String(from)}-${String(to)}`\n\n return (\n <nav\n aria-label={`${label} pagination`}\n className=\"flex items-center justify-between border-t border-border-subtle px-4 py-3\"\n >\n <p className=\"text-caption tabular-nums text-text-faint\">\n {total === undefined ? range : `${range} of ${String(total)}`}\n </p>\n <div className=\"flex items-center gap-2\">\n <IconButton\n icon=\"page-previous\"\n label={`Previous page of ${label}`}\n variant=\"ghost\"\n size=\"sm\"\n disabled={!hasPrevious}\n onClick={onPrevious}\n />\n <IconButton\n icon=\"page-next\"\n label={`Next page of ${label}`}\n variant=\"ghost\"\n size=\"sm\"\n disabled={!hasNext}\n onClick={onNext}\n />\n </div>\n </nav>\n )\n}\n","import type { ReactNode } from \"react\"\n\nimport { Breadcrumb } from \"./breadcrumb.js\"\nimport type { BreadcrumbItem } from \"./breadcrumb.js\"\nimport { cx } from \"./class-names.js\"\n\n/**\n * The page header every admin screen opens with.\n * Canonical source: .docs/styleguide/03-layout.md section 3.1.\n *\n * It owns the 24px gap to the first section, so a screen never restates it, and it is the\n * only place the breadcrumb may appear. The title is an `h1`: one per document, and the\n * shell around it contributes none.\n *\n * Title and description are strings rather than nodes. Every later screen is generated\n * from the registry, and a header that accepts arbitrary markup is an invitation for one\n * content type to look different from the rest.\n */\nexport interface PageHeaderProps {\n title: string\n description?: string\n /** The trail above the title. The last item is the current page. */\n breadcrumb?: readonly BreadcrumbItem[]\n /** Right side. Primary action last, per the guide. */\n actions?: ReactNode\n className?: string\n}\n\nexport function PageHeader({\n title,\n description,\n breadcrumb,\n actions,\n className,\n}: PageHeaderProps) {\n return (\n <header className={cx(\"mb-6 flex items-start justify-between gap-4\", className)}>\n <div className=\"min-w-0\">\n {breadcrumb === undefined || breadcrumb.length === 0 ? null : (\n <Breadcrumb items={breadcrumb} className=\"mb-2\" />\n )}\n <h1 className=\"text-heading-lg text-text-primary\">{title}</h1>\n {description === undefined ? null : (\n <p className=\"mt-1 max-w-reading text-body-sm text-text-muted\">{description}</p>\n )}\n </div>\n {actions === undefined ? null : (\n <div className=\"flex shrink-0 items-center gap-2\">{actions}</div>\n )}\n </header>\n )\n}\n","import { cx } from \"./class-names.js\"\n\n/**\n * The upload progress bar.\n * Canonical source: .docs/styleguide/04-components.md section 16.\n *\n * Uploads are the only thing in the system that gets one. Everywhere else the wait has no\n * measurable length and a skeleton or a spinner is the honest control.\n *\n * The fill width is an inline style rather than a class, because it is a measured value\n * and not a design decision: there is no token for \"43 percent\", and writing one as an\n * arbitrary Tailwind class would be exactly the ad-hoc styling the lint rule forbids.\n * Every other value on this element is a token.\n */\nexport interface ProgressProps {\n /** 0 to 1. Clamped, because a transferred byte count can briefly exceed the total. */\n value: number\n /** Names what is progressing, for a reader who cannot see the bar. */\n label: string\n className?: string\n}\n\nexport function Progress({ value, label, className }: ProgressProps) {\n const fraction = Math.min(Math.max(Number.isFinite(value) ? value : 0, 0), 1)\n const percent = Math.round(fraction * 100)\n\n return (\n <div\n role=\"progressbar\"\n aria-label={label}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={percent}\n className={cx(\n \"h-1 w-full overflow-hidden rounded-full bg-surface-active\",\n className,\n )}\n >\n <div\n className=\"h-full rounded-full bg-text-primary progress-transition\"\n style={{ width: `${String(percent)}%` }}\n />\n </div>\n )\n}\n","import type { ReactNode } from \"react\"\n\nimport { cx } from \"./class-names.js\"\n\n/**\n * Sections and the vertical rhythm between them.\n * Canonical source: .docs/styleguide/03-layout.md sections 3.1 and 3.2.\n *\n * The rhythm is owned in exactly two places: the page header carries the 24px to the first\n * section, and `PageSections` carries the 32px between two sections. A `Section` therefore\n * has no outer margin of its own, which is what stops a screen from adding one and drifting\n * out of the system.\n */\nexport function PageSections({\n children,\n className,\n}: {\n children: ReactNode\n className?: string\n}) {\n return <div className={cx(\"space-y-8\", className)}>{children}</div>\n}\n\nexport interface SectionProps {\n /** Omitted for a section that needs no heading; the rhythm is unchanged either way. */\n heading?: string\n description?: string\n /** Section-level controls, right-aligned beside the heading. */\n actions?: ReactNode\n children: ReactNode\n className?: string\n}\n\nexport function Section({\n heading,\n description,\n actions,\n children,\n className,\n}: SectionProps) {\n return (\n <section className={className}>\n {heading === undefined ? null : (\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"min-w-0\">\n <h2 className=\"text-heading-md text-text-primary\">{heading}</h2>\n {description === undefined ? null : (\n <p className=\"mt-1 max-w-reading text-body-sm text-text-muted\">\n {description}\n </p>\n )}\n </div>\n {actions === undefined ? null : (\n <div className=\"flex shrink-0 items-center gap-2\">{actions}</div>\n )}\n </div>\n )}\n <div className={heading === undefined ? undefined : \"mt-4\"}>{children}</div>\n </section>\n )\n}\n","\"use client\"\n\nimport { useEffect, useId, useRef, useState } from \"react\"\nimport type { KeyboardEvent } from \"react\"\n\nimport { cx } from \"./class-names.js\"\nimport { INPUT_BASE } from \"./field.js\"\nimport { Icon } from \"./icon.js\"\n\n/**\n * The select. Canonical source: .docs/styleguide/04-components.md section 3.3.\n *\n * It is a listbox rather than a native `<select>`, because the guide requires the trigger\n * to match the text input exactly and the open list to be the menu surface from section\n * 11 with a check on the selected option. A native select renders the operating system's\n * popup, which no stylesheet reaches.\n *\n * That trade has a cost: everything the platform gives away for free (focus, typeahead,\n * Escape, activedescendant) has to be implemented here, which is why the keyboard handler\n * is the longest part of the file. A hidden input carries the value so the control still\n * submits inside a plain form.\n */\nexport interface SelectOption {\n value: string\n label: string\n disabled?: boolean\n}\n\nexport interface SelectProps {\n options: readonly SelectOption[]\n value: string | null\n onChange: (value: string) => void\n id?: string\n name?: string\n placeholder?: string\n invalid?: boolean\n disabled?: boolean\n \"aria-describedby\"?: string | undefined\n \"aria-label\"?: string | undefined\n}\n\nfunction nextEnabled(\n options: readonly SelectOption[],\n from: number,\n step: 1 | -1,\n): number {\n for (let i = from; i >= 0 && i < options.length; i += step) {\n if (options[i]?.disabled !== true) return i\n }\n return from\n}\n\nexport function Select({\n options,\n value,\n onChange,\n id,\n name,\n placeholder = \"Select an option\",\n invalid = false,\n disabled = false,\n \"aria-describedby\": describedBy,\n \"aria-label\": ariaLabel,\n}: SelectProps) {\n const generatedId = useId()\n const triggerId = id ?? generatedId\n const listId = `${generatedId}-list`\n const [open, setOpen] = useState(false)\n const [active, setActive] = useState(0)\n const triggerRef = useRef<HTMLButtonElement>(null)\n const listRef = useRef<HTMLUListElement>(null)\n\n const selectedIndex = options.findIndex((option) => option.value === value)\n const selected = selectedIndex === -1 ? undefined : options[selectedIndex]\n\n useEffect(() => {\n if (!open) return\n listRef.current?.focus()\n }, [open])\n\n useEffect(() => {\n if (!open) return\n function handlePointerDown(event: MouseEvent) {\n const target = event.target\n if (!(target instanceof Node)) return\n if (listRef.current?.contains(target) === true) return\n if (triggerRef.current?.contains(target) === true) return\n setOpen(false)\n }\n document.addEventListener(\"mousedown\", handlePointerDown)\n return () => document.removeEventListener(\"mousedown\", handlePointerDown)\n }, [open])\n\n function openList() {\n setActive(selectedIndex === -1 ? nextEnabled(options, 0, 1) : selectedIndex)\n setOpen(true)\n }\n\n function close(restoreFocus: boolean) {\n setOpen(false)\n if (restoreFocus) triggerRef.current?.focus()\n }\n\n function commit(index: number) {\n const option = options[index]\n if (option === undefined || option.disabled === true) return\n onChange(option.value)\n close(true)\n }\n\n function handleTriggerKeyDown(event: KeyboardEvent<HTMLButtonElement>) {\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\" || event.key === \"Enter\") {\n event.preventDefault()\n openList()\n }\n }\n\n function handleListKeyDown(event: KeyboardEvent<HTMLUListElement>) {\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault()\n setActive((current) =>\n nextEnabled(options, Math.min(current + 1, options.length - 1), 1),\n )\n return\n case \"ArrowUp\":\n event.preventDefault()\n setActive((current) => nextEnabled(options, Math.max(current - 1, 0), -1))\n return\n case \"Home\":\n event.preventDefault()\n setActive(nextEnabled(options, 0, 1))\n return\n case \"End\":\n event.preventDefault()\n setActive(nextEnabled(options, options.length - 1, -1))\n return\n case \"Enter\":\n case \" \":\n event.preventDefault()\n commit(active)\n return\n case \"Escape\":\n event.preventDefault()\n close(true)\n return\n case \"Tab\":\n // Tab leaves the control rather than moving inside it, so the list closes without\n // stealing focus back to the trigger.\n close(false)\n return\n default:\n }\n }\n\n return (\n <div className=\"relative\">\n {name === undefined ? null : (\n <input type=\"hidden\" name={name} value={value ?? \"\"} />\n )}\n <button\n ref={triggerRef}\n id={triggerId}\n type=\"button\"\n role=\"combobox\"\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n aria-controls={open ? listId : undefined}\n aria-describedby={describedBy}\n aria-label={ariaLabel}\n aria-invalid={invalid || undefined}\n disabled={disabled}\n onClick={() => (open ? close(false) : openList())}\n onKeyDown={handleTriggerKeyDown}\n className={cx(\n INPUT_BASE,\n \"flex cursor-pointer items-center justify-between gap-2 pe-8.5 text-left\",\n invalid ? \"border-danger focus-visible:border-danger\" : \"border-border-default\",\n )}\n >\n <span\n className={cx(\n \"truncate\",\n selected === undefined ? \"text-text-faint\" : \"text-text-primary\",\n )}\n >\n {selected?.label ?? placeholder}\n </span>\n <span className=\"pointer-events-none absolute end-3 text-text-muted\">\n <Icon name=\"expand\" />\n </span>\n </button>\n\n {open ? (\n <ul\n ref={listRef}\n id={listId}\n role=\"listbox\"\n tabIndex={-1}\n aria-labelledby={triggerId}\n aria-activedescendant={`${listId}-${active}`}\n onKeyDown={handleListKeyDown}\n className=\"absolute left-0 top-full z-dropdown mt-1 w-full rounded-md border border-border-default bg-surface-overlay p-1.5 shadow-overlay motion-safe:animate-menu-in focus-visible:focus-ring\"\n >\n {options.map((option, index) => (\n <li\n key={option.value}\n id={`${listId}-${index}`}\n role=\"option\"\n aria-selected={option.value === value}\n aria-disabled={option.disabled === true || undefined}\n onMouseEnter={() => option.disabled !== true && setActive(index)}\n onClick={() => commit(index)}\n className={cx(\n \"flex h-8.5 items-center justify-between gap-2 rounded-sm px-2.5 text-body-sm state-transition\",\n option.disabled === true\n ? \"cursor-not-allowed text-text-disabled\"\n : \"cursor-pointer text-text-secondary\",\n option.disabled !== true &&\n index === active &&\n \"bg-surface-hover text-text-primary\",\n )}\n >\n <span className=\"truncate\">{option.label}</span>\n {option.value === value ? (\n <span className=\"text-text-primary\">\n <Icon name=\"selected\" size={14} />\n </span>\n ) : null}\n </li>\n ))}\n </ul>\n ) : null}\n </div>\n )\n}\n","\"use client\"\n\nimport { cx } from \"./class-names.js\"\nimport { INPUT_BASE } from \"./field.js\"\nimport { Icon } from \"./icon.js\"\nimport { IconButton } from \"./icon-button.js\"\n\n/**\n * The search field. Canonical source: .docs/styleguide/04-components.md section 3.2,\n * placed by .docs/styleguide/03-layout.md section 5.1.\n *\n * The text input with a leading `search` icon and a trailing clear button that appears\n * once there is something to clear. It holds no state and runs no query: what a search\n * means is the screen's business, and the screen is the one that has to be honest about\n * what its query can match.\n */\nexport interface SearchInputProps {\n value: string\n onChange: (value: string) => void\n /** The accessible name. There is no visible label in a toolbar. */\n label: string\n placeholder?: string\n disabled?: boolean\n /** Id of the caption that states what the search matches. */\n describedBy?: string | undefined\n className?: string\n}\n\nexport function SearchInput({\n value,\n onChange,\n label,\n placeholder,\n disabled = false,\n describedBy,\n className,\n}: SearchInputProps) {\n return (\n <div className={cx(\"relative min-w-60\", className)}>\n <span\n aria-hidden=\"true\"\n className={cx(\n \"pointer-events-none absolute inset-y-0 start-3 flex items-center\",\n disabled ? \"text-text-disabled\" : \"text-text-faint\",\n )}\n >\n <Icon name=\"search\" />\n </span>\n <input\n type=\"search\"\n role=\"searchbox\"\n value={value}\n disabled={disabled}\n aria-label={label}\n aria-describedby={describedBy}\n placeholder={placeholder}\n onChange={(event) => onChange(event.target.value)}\n className={cx(\n INPUT_BASE,\n \"cursor-text border-border-default ps-8.5\",\n // Room for the clear button, so a long term does not run underneath it.\n value === \"\" ? \"\" : \"pe-8.5\",\n // The platform's own clear affordance would be a second, unstyled control.\n \"[&::-webkit-search-cancel-button]:appearance-none\",\n )}\n />\n {value === \"\" || disabled ? null : (\n <span className=\"absolute inset-y-0 end-1 flex items-center\">\n <IconButton\n icon=\"close\"\n label=\"Clear search\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => onChange(\"\")}\n />\n </span>\n )}\n </div>\n )\n}\n","\"use client\"\n\nimport { useId } from \"react\"\n\nimport { cx } from \"./class-names.js\"\n\n/**\n * The switch. Canonical source: .docs/styleguide/04-components.md section 3.6.\n *\n * Use it only for a boolean that takes effect the moment it is flipped. A boolean that is\n * saved with a form is a checkbox, because a switch promises the change already happened\n * and a pending form has not.\n *\n * It is a button with `role=\"switch\"`, not a checkbox: screen readers announce \"on\" and\n * \"off\" for a switch and \"checked\" for a checkbox, and the difference is the whole point\n * of the control.\n */\nexport interface SwitchProps {\n checked: boolean\n onChange: (checked: boolean) => void\n /** The accessible name. Required, since the track carries no text. */\n label: string\n /** Renders `label` next to the track. Leave false where a field label already names it. */\n showLabel?: boolean\n disabled?: boolean\n id?: string\n \"aria-describedby\"?: string | undefined\n}\n\nexport function Switch({\n checked,\n onChange,\n label,\n showLabel = false,\n disabled = false,\n id,\n \"aria-describedby\": describedBy,\n}: SwitchProps) {\n const labelId = `${useId()}-label`\n\n const control = (\n <button\n id={id}\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n aria-label={showLabel ? undefined : label}\n aria-labelledby={showLabel ? labelId : undefined}\n aria-describedby={describedBy}\n disabled={disabled}\n onClick={() => onChange(!checked)}\n className={cx(\n \"relative inline-flex h-4.5 w-8 shrink-0 rounded-full border state-transition focus-visible:focus-ring\",\n disabled\n ? \"cursor-not-allowed border-border-subtle bg-surface-disabled\"\n : checked\n ? \"cursor-pointer border-text-primary bg-text-primary\"\n : \"cursor-pointer border-border-default bg-surface-active\",\n )}\n >\n <span\n aria-hidden=\"true\"\n className={cx(\n \"absolute left-0.5 top-0.5 size-3.5 rounded-full switch-transition\",\n checked && \"translate-x-3.5\",\n disabled ? \"bg-text-disabled\" : checked ? \"bg-text-inverse\" : \"bg-text-muted\",\n )}\n />\n </button>\n )\n\n if (!showLabel) return control\n\n return (\n <span className=\"inline-flex items-center gap-2\">\n {control}\n <span\n id={labelId}\n className={cx(\n \"text-body-sm\",\n disabled ? \"text-text-disabled\" : \"text-text-secondary\",\n )}\n >\n {label}\n </span>\n </span>\n )\n}\n","import type { TextareaHTMLAttributes } from \"react\"\n\nimport { cx } from \"./class-names.js\"\n\n/**\n * The multi-line text control.\n * Canonical source: .docs/styleguide/04-components.md section 3.2.\n *\n * It repeats the input's box rather than reusing `INPUT_BASE`, because the guide gives the\n * textarea a different height, block padding and resize behaviour, and a shared base string\n * plus four overrides is harder to read than the eight declarations it replaces.\n *\n * Resize is vertical only: a control that can be dragged wider than its column breaks the\n * form grid, and no editor has ever wanted that.\n */\nexport interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {\n invalid?: boolean\n}\n\nexport function Textarea({\n invalid = false,\n className,\n readOnly,\n rows = 4,\n ...rest\n}: TextareaProps) {\n return (\n <textarea\n rows={rows}\n className={cx(\n \"min-h-24 w-full cursor-text resize-y rounded-sm border bg-surface-input px-3 py-2 text-body text-text-primary state-transition placeholder:text-text-faint hover:border-border-strong focus-visible:focus-field-ring disabled:bg-surface-disabled disabled:text-text-disabled disabled:cursor-not-allowed\",\n invalid ? \"border-danger focus-visible:border-danger\" : \"border-border-default\",\n readOnly === true ? \"bg-surface-disabled text-text-secondary\" : \"\",\n className,\n )}\n aria-invalid={invalid || undefined}\n readOnly={readOnly}\n {...rest}\n />\n )\n}\n","import type { ReactNode, ThHTMLAttributes, TdHTMLAttributes } from \"react\"\n\nimport { cx } from \"./class-names.js\"\nimport { Icon } from \"./icon.js\"\n\n/**\n * The table shell. Canonical source: .docs/styleguide/04-components.md section 5.\n *\n * A shell, not a data grid: it fixes geometry, density and state styling, and knows\n * nothing about content types, sorting logic or selection logic. The list view generated\n * from the registry owns all of that and composes these parts.\n *\n * Density is fixed by the guide, so there is no size prop and no comfortable/compact\n * toggle. The table carries no outer border either: it lives inside a panel and shares\n * the panel's edge.\n */\nexport interface TableProps {\n children: ReactNode\n /** Names the table for screen readers when no caption is visible. */\n label?: string\n className?: string\n}\n\nexport function Table({ children, label, className }: TableProps) {\n return (\n <table\n aria-label={label}\n className={cx(\"w-full border-collapse text-body-sm\", className)}\n >\n {children}\n </table>\n )\n}\n\nexport function TableHead({ children }: { children: ReactNode }) {\n return <thead>{children}</thead>\n}\n\nexport function TableBody({ children }: { children: ReactNode }) {\n return <tbody>{children}</tbody>\n}\n\nexport type SortDirection = \"asc\" | \"desc\"\n\nexport interface TableHeaderCellProps extends Omit<\n ThHTMLAttributes<HTMLTableCellElement>,\n \"onClick\"\n> {\n children?: ReactNode\n /** Numeric columns are right-aligned so their cells line up under the header. */\n numeric?: boolean\n /** Fixed-width columns: the selection cell and the action cell. */\n width?: \"selection\" | \"action\"\n /** Passing this makes the header a sort button. `null` is the unsorted state. */\n sort?: { direction: SortDirection | null; onSort: () => void }\n}\n\nexport function TableHeaderCell({\n children,\n numeric = false,\n width,\n sort,\n className,\n ...rest\n}: TableHeaderCellProps) {\n const base = cx(\n \"h-9 px-4 text-micro uppercase text-text-faint border-b border-border-subtle\",\n // Sticky only bites when the body scrolls; when it does not, it costs nothing.\n \"sticky top-0 z-sticky bg-surface-card\",\n numeric ? \"text-right\" : \"text-left\",\n width === \"selection\" && \"w-10 px-0 text-center\",\n width === \"action\" && \"w-24 text-right\",\n className,\n )\n\n if (sort === undefined) {\n return (\n <th scope=\"col\" className={base} {...rest}>\n {children}\n </th>\n )\n }\n\n return (\n <th\n scope=\"col\"\n aria-sort={\n sort.direction === null\n ? \"none\"\n : sort.direction === \"asc\"\n ? \"ascending\"\n : \"descending\"\n }\n className={base}\n {...rest}\n >\n <button\n type=\"button\"\n onClick={sort.onSort}\n className={cx(\n \"inline-flex cursor-pointer items-center gap-1 state-transition hover:text-text-muted focus-visible:focus-ring\",\n numeric && \"flex-row-reverse\",\n )}\n >\n {children}\n {sort.direction === null ? null : (\n <Icon name={sort.direction === \"asc\" ? \"sort-asc\" : \"sort-desc\"} size={12} />\n )}\n </button>\n </th>\n )\n}\n\nexport interface TableRowProps {\n children: ReactNode\n selected?: boolean\n disabled?: boolean\n /** Set only when the whole row performs one action; it is what earns the pointer cursor. */\n onActivate?: () => void\n className?: string\n}\n\nexport function TableRow({\n children,\n selected = false,\n disabled = false,\n onActivate,\n className,\n}: TableRowProps) {\n const interactive = onActivate !== undefined && !disabled\n\n return (\n <tr\n // A row is only in the tab order when it does something. Enter matches what a click\n // does, and Space is left alone so a selection checkbox inside the row keeps it.\n tabIndex={interactive ? 0 : undefined}\n onClick={interactive ? onActivate : undefined}\n onKeyDown={\n interactive\n ? (event) => {\n if (event.key !== \"Enter\") return\n event.preventDefault()\n onActivate()\n }\n : undefined\n }\n aria-selected={selected || undefined}\n aria-disabled={disabled || undefined}\n className={cx(\n // The named group is what lets the action cell reveal itself on row hover.\n \"group/row border-t border-border-subtle state-transition focus-visible:focus-ring-inset\",\n disabled && \"text-text-disabled\",\n !disabled && selected && \"bg-surface-raised\",\n !disabled && !selected && \"hover:bg-surface-hover\",\n interactive && \"cursor-pointer\",\n className,\n )}\n >\n {children}\n </tr>\n )\n}\n\nexport interface TableCellProps extends TdHTMLAttributes<HTMLTableCellElement> {\n children?: ReactNode\n /** The title column: brighter and medium weight. */\n primary?: boolean\n /** Right-aligned, tabular figures. */\n numeric?: boolean\n /** Muted, tabular figures. */\n date?: boolean\n width?: \"selection\" | \"action\"\n}\n\nexport function TableCell({\n children,\n primary = false,\n numeric = false,\n date = false,\n width,\n className,\n ...rest\n}: TableCellProps) {\n return (\n <td\n className={cx(\n \"min-h-10 px-4 py-2.5 align-middle text-text-secondary\",\n primary && \"text-text-primary font-medium\",\n numeric && \"text-right tabular-nums\",\n date && \"text-text-muted tabular-nums\",\n width === \"selection\" && \"w-10 px-0 text-center\",\n // Action icons stay out of the way until the row is hovered, and come back the\n // moment anything inside the row takes focus, so the keyboard never loses them.\n width === \"action\" &&\n \"w-24 text-right opacity-0 group-hover/row:opacity-100 focus-within:opacity-100\",\n className,\n )}\n {...rest}\n >\n {children}\n </td>\n )\n}\n\n/** The empty state spanning the whole table body. */\nexport function TableEmptyRow({\n colSpan,\n children,\n}: {\n colSpan: number\n children: ReactNode\n}) {\n return (\n <tr>\n <td colSpan={colSpan} className=\"border-t border-border-subtle\">\n {children}\n </td>\n </tr>\n )\n}\n","\"use client\"\n\nimport { createContext, useCallback, useContext, useEffect, useState } from \"react\"\nimport type { ReactNode } from \"react\"\n\nimport { Button } from \"./button.js\"\nimport { Modal } from \"./modal.js\"\n\n/**\n * The unsaved-changes guard.\n *\n * Leaving an editor with unsaved work has two halves and they are two different\n * mechanisms, so they are written separately here rather than pretended to be one thing:\n *\n * - **Closing the tab or reloading** is `beforeunload`. The browser owns the wording, the\n * buttons and whether it asks at all; all a page can do is say that it has something to\n * lose. It is attached only while the form is dirty, because a listener that is always\n * attached makes every reload of a clean page ask a question nobody needed.\n * - **Navigating inside the admin** is ours. A sidebar link, the cancel button and any\n * other in-app route change are intercepted, the user is asked in the admin's own\n * dialog, and the navigation is resumed or dropped by their answer.\n *\n * The done criterion this exists to satisfy is exact: leaving a dirty form warns, leaving\n * a clean form does not. Which means a save has to make the warning stop. It does, because\n * `dirty` is a comparison against the values the adapter confirmed (`valuesChanged` in\n * core/entry-form.ts) and not a flag somebody has to remember to clear: the save writes\n * the new baseline, the comparison goes false, and both halves detach on the same render.\n */\n\n/**\n * Warns before the tab closes or reloads while there is unsaved work.\n *\n * Standalone, so an editor still guards the unload path in a host that mounted no\n * provider. The listener exists only while `dirty` is true.\n */\nexport function useBeforeUnloadWarning(dirty: boolean): void {\n useEffect(() => {\n if (!dirty) return\n\n function warn(event: BeforeUnloadEvent): void {\n // Both, because the modern signal and the legacy one are honoured by different\n // browsers. Neither carries a message: since 2017 no major browser shows one.\n event.preventDefault()\n event.returnValue = \"\"\n }\n\n window.addEventListener(\"beforeunload\", warn)\n return () => window.removeEventListener(\"beforeunload\", warn)\n }, [dirty])\n}\n\ninterface UnsavedChangesContextValue {\n /** Reported by the form on every change of its dirty state, and false on unmount. */\n setDirty: (dirty: boolean) => void\n /** Runs `proceed` now when the form is clean, after a confirmation when it is not. */\n confirmLeave: (proceed: () => void) => void\n}\n\nconst UnsavedChangesContext = createContext<UnsavedChangesContextValue | null>(null)\n\nexport interface UnsavedChangesProviderProps {\n /**\n * Resumes an intercepted link navigation. The admin cannot know the host's router, and\n * a host that supplies none falls back to a full document load, which is correct but\n * slower. The playground passes `router.push`.\n */\n navigate?: ((href: string) => void) | undefined\n children: ReactNode\n}\n\nexport function UnsavedChangesProvider({\n navigate,\n children,\n}: UnsavedChangesProviderProps) {\n const [dirty, setDirty] = useState(false)\n /** The navigation waiting on an answer. Null when nothing is being asked. */\n const [pending, setPending] = useState<{ run: () => void } | null>(null)\n\n const confirmLeave = useCallback(\n (proceed: () => void) => {\n if (!dirty) {\n proceed()\n return\n }\n setPending({ run: proceed })\n },\n [dirty],\n )\n\n useEffect(() => {\n if (!dirty) return\n\n function intercept(event: MouseEvent): void {\n // Everything a browser treats as \"open this somewhere else\" is left alone: a new\n // tab, a download and a modified click all keep this page, and this page keeps its\n // unsaved work.\n if (event.defaultPrevented || event.button !== 0) return\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return\n\n const target = event.target\n if (!(target instanceof Element)) return\n const anchor = target.closest(\"a[href]\")\n if (!(anchor instanceof HTMLAnchorElement)) return\n if (anchor.target !== \"\" && anchor.target !== \"_self\") return\n if (anchor.hasAttribute(\"download\")) return\n\n const href = anchor.href\n if (new URL(href, window.location.href).origin !== window.location.origin) return\n\n // Capture phase plus stopPropagation, because the router's own handler sits on the\n // anchor: letting the event reach it would navigate behind the dialog.\n event.preventDefault()\n event.stopPropagation()\n setPending({\n run: () => {\n if (navigate === undefined) window.location.assign(href)\n else navigate(href)\n },\n })\n }\n\n document.addEventListener(\"click\", intercept, true)\n return () => document.removeEventListener(\"click\", intercept, true)\n }, [dirty, navigate])\n\n function discard(): void {\n const proceed = pending?.run\n setPending(null)\n // The user chose to lose the changes, so the guard stops guarding before the\n // navigation runs. Otherwise the resumed navigation would be intercepted again.\n setDirty(false)\n proceed?.()\n }\n\n return (\n <UnsavedChangesContext.Provider value={{ setDirty, confirmLeave }}>\n {children}\n <Modal\n open={pending !== null}\n onClose={() => setPending(null)}\n title=\"Leave without saving?\"\n description=\"This entry has changes that were never written. Leaving now loses them.\"\n width=\"sm\"\n // Losing work is not undoable, so a stray click on the backdrop must not do it.\n // Escape closes, and closing means staying, which is the safe outcome.\n dismissible={false}\n footer={\n <>\n <Button variant=\"secondary\" onClick={() => setPending(null)}>\n Keep editing\n </Button>\n <Button variant=\"danger\" onClick={discard}>\n Discard changes\n </Button>\n </>\n }\n />\n </UnsavedChangesContext.Provider>\n )\n}\n\n/**\n * Registers a form's dirty state with the guard, and warns on unload while it is set.\n *\n * Called by the editor with the same `dirty` the save bar reads, so the two can never\n * disagree about whether there is anything to lose. Unmounting clears the registration:\n * a form that is gone has nothing left unsaved, and leaving the flag set would make every\n * later navigation ask.\n */\nexport function useUnsavedChanges(dirty: boolean): void {\n const context = useContext(UnsavedChangesContext)\n const setDirty = context?.setDirty\n\n useBeforeUnloadWarning(dirty)\n\n useEffect(() => {\n if (setDirty === undefined) return\n setDirty(dirty)\n return () => setDirty(false)\n }, [dirty, setDirty])\n}\n\n/** Module level, so a component without a provider gets a stable identity to depend on. */\nconst LEAVE_UNGUARDED = (proceed: () => void): void => proceed()\n\n/**\n * The gate an in-app navigation goes through.\n *\n * Without a provider it is the identity: the navigation happens. A host that mounted no\n * guard gets no dialog, not a broken button.\n */\nexport function useConfirmLeave(): (proceed: () => void) => void {\n const context = useContext(UnsavedChangesContext)\n return context?.confirmLeave ?? LEAVE_UNGUARDED\n}\n","export const ROLES = [\"admin\", \"editor\", \"author\"] as const\n\nexport type Role = (typeof ROLES)[number]\n\n/** Actions performed on the entries of one content type. */\nexport type EntryAction = \"read\" | \"create\" | \"update\" | \"delete\"\n\n/** Actions that are not scoped to a content type. */\nexport type AdminAction =\n \"manage-schema\" | \"manage-users\" | \"manage-settings\" | \"manage-media\"\n\nexport type Action = EntryAction | AdminAction\n\nexport const ENTRY_ACTIONS = [\"read\", \"create\", \"update\", \"delete\"] as const\n\n/**\n * Who may do what with one content type. A missing action falls back to the role defaults\n * in `can()`, so an empty matrix means \"use the defaults\", not \"deny everything\".\n */\nexport type PermissionMatrix = Partial<Record<EntryAction, readonly Role[]>>\n\n/** One resolved permission question, as the UI, the adapter, and the tests all phrase it. */\nexport interface Permission {\n action: Action\n /** Content type slug. Absent for an `AdminAction`. */\n contentType?: string\n}\n\nexport interface AuthUser {\n uid: string\n email: string\n displayName: string | null\n role: Role\n disabled: boolean\n}\n","import type { Action, AdminAction, AuthUser, EntryAction, Role } from \"../types/auth.js\"\nimport { ENTRY_ACTIONS, ROLES } from \"../types/auth.js\"\nimport type { ContentTypeLike } from \"../types/content-type.js\"\nimport type { EntryMeta } from \"../types/entry.js\"\n\n/**\n * The one permission resolver.\n *\n * The admin UI calls it to hide what a user may not do, the adapter calls it again to\n * refuse the call when the UI is bypassed, and the security rules encode the same matrix a\n * third time. Three layers, one truth table. Keep this pure and synchronous: it has to run\n * inside a render, inside a write path, and inside a test, with no Firebase and no IO.\n */\n\nexport const ADMIN_ACTIONS = [\n \"manage-schema\",\n \"manage-users\",\n \"manage-settings\",\n \"manage-media\",\n] as const satisfies readonly AdminAction[]\n\n/** Every action the resolver answers for. The test cross-checks it against the table. */\nexport const ACTIONS: readonly Action[] = [...ENTRY_ACTIONS, ...ADMIN_ACTIONS]\n\n/**\n * An allow that still depends on who created the entry. Kept as a third state rather than\n * resolved to a boolean early, so an ownership-gated action can be told apart from a plain\n * denial and answered against the entry the caller passed in.\n */\nexport type Decision = \"allow\" | \"deny\" | \"own-entry-only\"\n\n/**\n * The role defaults, exhaustive by construction: `Record<Role, Record<Action, Decision>>`\n * fails to typecheck the moment a role or an action is added without a decision here.\n */\nexport const PERMISSION_DEFAULTS: Readonly<\n Record<Role, Readonly<Record<Action, Decision>>>\n> = {\n admin: {\n read: \"allow\",\n create: \"allow\",\n update: \"allow\",\n delete: \"allow\",\n \"manage-schema\": \"allow\",\n \"manage-users\": \"allow\",\n \"manage-settings\": \"allow\",\n \"manage-media\": \"allow\",\n },\n editor: {\n read: \"allow\",\n create: \"allow\",\n update: \"allow\",\n delete: \"allow\",\n // Structure and user accounts stay with an admin: an editor who could change either\n // could grant themselves everything else.\n \"manage-schema\": \"deny\",\n \"manage-users\": \"deny\",\n \"manage-settings\": \"allow\",\n \"manage-media\": \"allow\",\n },\n author: {\n read: \"allow\",\n create: \"allow\",\n update: \"own-entry-only\",\n delete: \"deny\",\n \"manage-schema\": \"deny\",\n \"manage-users\": \"deny\",\n \"manage-settings\": \"deny\",\n \"manage-media\": \"deny\",\n },\n}\n\n/** Just enough of an entry to answer an ownership question. */\nexport type EntryOwnership = Pick<EntryMeta, \"createdBy\">\n\nexport interface PermissionContext {\n /** The content type the action targets. Carries the per-type permission matrix, if any. */\n type?: ContentTypeLike\n /**\n * The entry the action targets. Absent means the caller does not know which entry, which\n * denies an ownership-gated action rather than guessing in the user's favour.\n */\n entry?: EntryOwnership\n}\n\nexport function isEntryAction(action: Action): action is EntryAction {\n return (ENTRY_ACTIONS as readonly Action[]).includes(action)\n}\n\n/**\n * Answers one permission question.\n *\n * Ownership is resolved against `context.entry`, not against the content type, because an\n * author's `update` is a question about one entry and cannot be answered honestly without\n * it. A caller that does not pass the entry gets `false`: \"I cannot tell\" has to read as a\n * denial at the UI layer, since the adapter and the rules will deny it too.\n *\n * `context.type.permissions` narrows the role defaults for entry actions on that type. An\n * absent matrix, and an action absent from it, mean \"use the defaults\", never \"deny\n * everything\", so adding a matrix for one action does not silently lock out the rest.\n *\n * A matrix narrows and never widens. Three things follow, and M10 settled all three by\n * making the security rules agree with them rather than by softening them here. It cannot\n * restrict an admin. It cannot lift an author's ownership rule, so ticking `author` under\n * `update` grants that action on the author's own entries only. And it cannot grant an\n * action the role's own default denies, so ticking `author` under `delete` changes nothing:\n * firestore.rules resolves the role defaults from the token alone and only consults the\n * matrix to narrow further, because a rule that widened a privilege from a stored document\n * would be trusting the document to grant it. See permissions/matrix.ts.\n */\nexport function can(\n user: AuthUser,\n action: Action,\n context: PermissionContext = {},\n): boolean {\n if (user.disabled) return false\n\n // The role arrives from a stored user document or a custom claim, both untrusted input.\n if (!ROLES.includes(user.role)) return false\n\n if (user.role === \"admin\") return true\n\n const decision = resolveDecision(user.role, action, context.type)\n\n if (decision === \"allow\") return true\n if (decision === \"deny\") return false\n\n return context.entry !== undefined && context.entry.createdBy === user.uid\n}\n\n/**\n * The truth table lookup on its own, without the entry.\n *\n * Exported because `permissions/matrix.ts` labels the Developer area's table with it and a\n * second implementation of the same lookup would be a second place for the three layers to\n * drift apart. `can()` is this plus the ownership question.\n */\nexport function resolveDecision(\n role: Role,\n action: Action,\n type: Pick<ContentTypeLike, \"permissions\"> | undefined,\n): Decision {\n // An admin is never restricted by a matrix, so there is nothing to look up.\n if (role === \"admin\") return PERMISSION_DEFAULTS.admin[action]\n\n const fallback = PERMISSION_DEFAULTS[role][action]\n const matrixRoles =\n isEntryAction(action) && type?.permissions !== undefined\n ? type.permissions[action]\n : undefined\n\n if (matrixRoles === undefined) return fallback\n // Narrowing only. A role the defaults deny stays denied however the matrix is written,\n // because firestore.rules will deny it from the token without reading the matrix at all.\n if (fallback === \"deny\") return \"deny\"\n\n return matrixRoles.includes(role) ? fallback : \"deny\"\n}\n","import type { Registry } from \"../../core/registry.js\"\nimport { can } from \"../../permissions/can.js\"\nimport type { Action, AuthUser } from \"../../types/auth.js\"\nimport type { ContentTypeKind, ContentTypeLike } from \"../../types/content-type.js\"\nimport { isIconName } from \"../components/icon-names.js\"\nimport type { IconName } from \"../components/icon-names.js\"\n\n/**\n * The sidebar as data. Canonical source: .docs/styleguide/03-layout.md section 2.1.\n *\n * The whole point of the registry is that nothing in the interface knows the name of a\n * content type. This builder is the only place navigation is decided, it reads the\n * registry and `can()`, and it returns plain serializable data so a server component can\n * compute it and hand it to the client shell. Adding a content type therefore changes\n * data and nothing else: no route table, no switch, no new file.\n *\n * It is deliberately free of React, so the server entry can export it without pulling a\n * component into a module graph that never renders one.\n */\n\nexport interface AdminNavItem {\n /** Stable across renders and unique inside the whole navigation. */\n key: string\n label: string\n href: string\n icon: IconName\n /**\n * Active on an exact path match only. The dashboard owns the admin root, so every\n * deeper route would otherwise light it up as well.\n */\n exact?: boolean\n}\n\nexport interface AdminNavGroup {\n key: string\n /** Absent for the leading group and the static group, which carry no heading. */\n label?: string\n items: readonly AdminNavItem[]\n}\n\nexport interface BuildNavigationOptions {\n registry: Registry\n user: AuthUser\n /** Where the admin is mounted in the host app. */\n basePath?: string\n}\n\nconst KIND_ICON: Record<ContentTypeKind, IconName> = {\n collection: \"collection\",\n singleton: \"singleton\",\n}\n\n/**\n * The icon a content type renders with.\n *\n * `type.icon` is untrusted: a database-defined type carries whatever an editor typed into\n * the Schema Builder, and a code-defined one carries whatever the customer wrote. An\n * unknown name falls back to the icon for the kind, so the row still reads as a collection\n * or a singleton. Neither a crash nor a blank gap is an acceptable answer to a typo.\n */\nexport function contentTypeIcon(type: ContentTypeLike): IconName {\n if (type.icon !== undefined && isIconName(type.icon)) return type.icon\n return KIND_ICON[type.kind]\n}\n\n/** A collection is listed by its plural; a singleton is one document and has no plural. */\nexport function contentTypeLabel(type: ContentTypeLike): string {\n if (type.kind === \"singleton\") return type.label\n return type.labelPlural ?? type.label\n}\n\n/** The Developer area, item by item, each with the permission that reveals it. */\nconst DEVELOPER_ITEMS: readonly (Omit<AdminNavItem, \"href\"> & {\n path: string\n action: Action\n})[] = [\n {\n key: \"content-types\",\n label: \"Content Types\",\n icon: \"content-types\",\n path: \"/developer/content-types\",\n action: \"manage-schema\",\n },\n {\n key: \"users\",\n label: \"Users\",\n icon: \"users\",\n path: \"/developer/users\",\n action: \"manage-users\",\n },\n {\n key: \"permissions\",\n label: \"Permissions\",\n icon: \"permissions\",\n path: \"/developer/permissions\",\n action: \"manage-users\",\n },\n {\n key: \"system\",\n label: \"System\",\n icon: \"system\",\n path: \"/developer/system\",\n action: \"manage-schema\",\n },\n]\n\nexport function buildAdminNavigation({\n registry,\n user,\n basePath = \"/admin\",\n}: BuildNavigationOptions): readonly AdminNavGroup[] {\n const href = (path: string) => `${basePath}${path}`\n\n const content: AdminNavItem[] = registry.types\n // A per-type permission matrix can take read away from a role, and a row that leads to\n // a screen the adapter will refuse is worse than no row.\n .filter((entry) => can(user, \"read\", { type: entry.type }))\n .map((entry) => ({\n key: `content:${entry.type.slug}`,\n label: contentTypeLabel(entry.type),\n href: href(`/content/${entry.type.slug}`),\n icon: contentTypeIcon(entry.type),\n }))\n\n const developer: AdminNavItem[] = DEVELOPER_ITEMS.filter((item) =>\n can(user, item.action),\n ).map(({ key, label, icon, path }) => ({ key, label, icon, href: href(path) }))\n\n const groups: AdminNavGroup[] = [\n {\n key: \"primary\",\n items: [\n {\n key: \"dashboard\",\n label: \"Dashboard\",\n href: href(\"\"),\n icon: \"dashboard\",\n exact: true,\n },\n ],\n },\n { key: \"content\", label: \"Content\", items: content },\n {\n key: \"library\",\n items: [\n { key: \"media\", label: \"Media\", href: href(\"/media\"), icon: \"media\" },\n { key: \"settings\", label: \"Settings\", href: href(\"/settings\"), icon: \"settings\" },\n ],\n },\n { key: \"developer\", label: \"Developer\", items: developer },\n ]\n\n // An empty group would render a heading over nothing. The Developer group disappearing\n // for an editor is the visible consequence; hiding it is presentation only, and the\n // adapter and the security rules refuse the same actions on their own.\n return groups.filter((group) => group.items.length > 0)\n}\n\n/** The product name, and the suffix every admin document title carries. */\nexport const ADMIN_TITLE = \"Husk\"\n\n/**\n * The navigation item a route belongs to, or undefined outside the navigation.\n *\n * The longest matching href wins, so a nested route resolves to the deepest item that\n * claims it rather than to whichever one the groups happened to list first.\n */\nexport function navItemForPath(\n navigation: readonly AdminNavGroup[],\n pathname: string,\n): AdminNavItem | undefined {\n let best: AdminNavItem | undefined\n\n for (const group of navigation) {\n for (const item of group.items) {\n if (!isNavItemActive(item, pathname)) continue\n if (best === undefined || item.href.length > best.href.length) best = item\n }\n }\n\n return best\n}\n\n/**\n * The document title for an admin route, taken from the same data that drew the sidebar.\n *\n * Titles are generated for the same reason screens are: a content type that appears in the\n * navigation gets a correct browser tab without anybody writing a route-specific string,\n * and a renamed type renames its tab. Returns undefined outside the navigation, which is\n * the caller's cue to fall back to the layout's default title.\n */\nexport function adminPageTitle(\n navigation: readonly AdminNavGroup[],\n pathname: string,\n): string | undefined {\n return navItemForPath(navigation, pathname)?.label\n}\n\n/** Whether a navigation item matches the route the browser is on. */\nexport function isNavItemActive(item: AdminNavItem, pathname: string): boolean {\n if (item.exact === true) return pathname === item.href\n return pathname === item.href || pathname.startsWith(`${item.href}/`)\n}\n","\"use client\"\n\nimport Link from \"next/link\"\nimport { useState } from \"react\"\nimport type { KeyboardEvent, ReactNode, Ref } from \"react\"\n\nimport { Avatar } from \"../components/avatar.js\"\nimport { cx } from \"../components/class-names.js\"\nimport { Icon } from \"../components/icon.js\"\nimport { MorphingIcon } from \"../components/morph-icon.js\"\nimport { isNavItemActive } from \"../navigation/navigation.js\"\nimport type { AdminNavGroup, AdminNavItem } from \"../navigation/navigation.js\"\nimport type { AuthUser } from \"../../types/auth.js\"\n\n/**\n * The sidebar. Canonical source: .docs/styleguide/03-layout.md section 2.\n *\n * It renders whatever `navigation` contains and knows nothing else. There is no branch on\n * a content type anywhere below this line: a new type is one more entry in the array the\n * builder produced, and the Developer group is absent rather than disabled because the\n * builder already dropped the items `can()` denied.\n */\n\n/** 36px row, 8px inset, 12px gap, radius-sm, body-sm. Section 2.3. */\nconst ITEM_BASE =\n \"flex h-9 cursor-pointer items-center gap-3 rounded-sm px-2 text-body-sm state-transition focus-visible:focus-ring\"\n\nconst ITEM_IDLE = \"text-text-muted hover:bg-surface-hover hover:text-text-secondary\"\n\n/** Surface and weight only. No accent, no left border. Section 2.3 and the contract. */\nconst ITEM_ACTIVE =\n \"bg-surface-hover font-semibold text-text-primary hover:bg-surface-active\"\n\n/** Section 2.2. As a button it also needs a cursor, a hover and a focus ring. */\nconst GROUP_LABEL =\n \"mb-1 flex w-full cursor-pointer items-center justify-between rounded-sm px-2 text-micro uppercase text-text-faint state-transition hover:text-text-muted focus-visible:focus-ring\"\n\nexport interface AdminSidebarProps {\n navigation: readonly AdminNavGroup[]\n /** The route the browser is on, for the active item. */\n pathname: string\n user: AuthUser\n /** The footer row's menu trigger. The host owns it: signing out is the host's session. */\n accountMenu?: ReactNode\n /** Display and position only. The shell decides whether this is a grid column or a drawer. */\n className?: string\n /** Set while the sidebar is the open drawer, so Escape and Tab can be handled there. */\n panelRef?: Ref<HTMLElement>\n /** Called when a navigation item is followed, so the drawer can close behind it. */\n onNavigate?: () => void\n /** Set while the sidebar is the open drawer, to keep Tab inside it. */\n onKeyDown?: (event: KeyboardEvent<HTMLElement>) => void\n}\n\nfunction NavLink({\n item,\n pathname,\n onNavigate,\n}: {\n item: AdminNavItem\n pathname: string\n onNavigate?: () => void\n}) {\n const active = isNavItemActive(item, pathname)\n\n return (\n <li>\n <Link\n href={item.href}\n aria-current={active ? \"page\" : undefined}\n {...(onNavigate === undefined ? {} : { onClick: onNavigate })}\n className={cx(ITEM_BASE, active ? ITEM_ACTIVE : ITEM_IDLE)}\n >\n <Icon name={item.icon} />\n <span className=\"truncate\">{item.label}</span>\n </Link>\n </li>\n )\n}\n\nfunction NavGroup({\n group,\n pathname,\n onNavigate,\n}: {\n group: AdminNavGroup\n pathname: string\n onNavigate?: () => void\n}) {\n const [expanded, setExpanded] = useState(true)\n const listId = `husk-nav-${group.key}`\n\n const list = (\n <ul id={listId} className=\"flex flex-col gap-0.5\">\n {group.items.map((item) => (\n <NavLink\n key={item.key}\n item={item}\n pathname={pathname}\n {...(onNavigate === undefined ? {} : { onNavigate })}\n />\n ))}\n </ul>\n )\n\n // A group without a heading has nothing to collapse from, so it stays plain. A labelled\n // group is one of the two collapsible cases 05-icons section 2.1 allows a morph in.\n if (group.label === undefined) return list\n\n return (\n <div>\n <button\n type=\"button\"\n aria-expanded={expanded}\n aria-controls={listId}\n onClick={() => setExpanded((open) => !open)}\n className={GROUP_LABEL}\n >\n {group.label}\n <MorphingIcon name={expanded ? \"expand\" : \"navigate-into\"} size={12} />\n </button>\n {expanded ? list : null}\n </div>\n )\n}\n\nexport function AdminSidebar({\n navigation,\n pathname,\n user,\n accountMenu,\n className,\n panelRef,\n onNavigate,\n onKeyDown,\n}: AdminSidebarProps) {\n const name = user.displayName ?? user.email\n\n return (\n <aside\n ref={panelRef}\n id=\"husk-sidebar\"\n tabIndex={-1}\n aria-label=\"Sidebar\"\n onKeyDown={onKeyDown}\n className={cx(\n // 28px top padding is the brand row's optical offset and the only place it appears.\n \"h-dvh w-sidebar flex-col overflow-y-auto border-r border-border-subtle bg-surface-sidebar px-6 pt-7 pb-6\",\n className,\n )}\n >\n <div className=\"mb-6 flex h-9 items-center gap-2 text-heading-sm text-text-primary\">\n <Icon name=\"brand\" size={18} />\n Husk\n </div>\n\n <nav aria-label=\"Main\" className=\"flex flex-col gap-4\">\n {navigation.map((group) => (\n <NavGroup\n key={group.key}\n group={group}\n pathname={pathname}\n {...(onNavigate === undefined ? {} : { onNavigate })}\n />\n ))}\n </nav>\n\n <div className=\"mt-auto flex items-center gap-3 border-t border-border-subtle pt-3\">\n <Avatar name={name} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-body-sm text-text-primary\">{name}</div>\n <div className=\"text-caption capitalize text-text-faint\">{user.role}</div>\n </div>\n {accountMenu}\n </div>\n </aside>\n )\n}\n","\"use client\"\n\nimport { usePathname } from \"next/navigation\"\nimport { useEffect, useRef, useState } from \"react\"\nimport type { KeyboardEvent, ReactNode } from \"react\"\n\nimport { cx } from \"../components/class-names.js\"\nimport { cycleTabWithin, focusableWithin } from \"../components/focusable.js\"\nimport { IconButton } from \"../components/icon-button.js\"\nimport type { AdminNavGroup } from \"../navigation/navigation.js\"\nimport type { AuthUser } from \"../../types/auth.js\"\n\nimport { AdminSidebar } from \"./admin-sidebar.js\"\n\n/**\n * The application shell. Canonical source: .docs/styleguide/03-layout.md sections 1 and 3.\n *\n * Two columns from `lg` up, one column below it with the sidebar as an off-canvas drawer.\n * The sidebar is one element in both cases rather than two that hide each other: a second\n * copy would duplicate every link in the accessibility tree and let the two drift apart.\n *\n * The drawer is modal while it is open, so it takes focus, keeps Tab inside itself, locks\n * page scroll, and closes on Escape, on a backdrop click, and on following a link. It also\n * closes when the viewport reaches `lg`, because at that width the same element is a\n * static column and a trapped focus or a locked scrollbar would be a bug with no visible\n * cause.\n */\n\n/**\n * The `lg` breakpoint as a media query. The one place the shell may name a pixel width.\n * Canonical source: .docs/styleguide/01-foundations.md section 11 (`--breakpoint-lg`).\n */\nconst LG_QUERY = \"(min-width: 1024px)\"\n\nexport interface AdminShellProps {\n navigation: readonly AdminNavGroup[]\n user: AuthUser\n /** The sidebar footer's menu trigger. The host owns it: the session is the host's. */\n accountMenu?: ReactNode\n children: ReactNode\n}\n\nexport function AdminShell({ navigation, user, accountMenu, children }: AdminShellProps) {\n // Null outside a Next router, which is the shape a unit render has. An empty path simply\n // matches no item, which is the honest answer when there is no route.\n const pathname = usePathname() ?? \"\"\n const [drawerOpen, setDrawerOpen] = useState(false)\n const panelRef = useRef<HTMLElement>(null)\n const triggerRef = useRef<HTMLButtonElement>(null)\n\n useEffect(() => {\n if (!drawerOpen) return\n\n focusableWithin(panelRef.current)[0]?.focus()\n\n const { overflow } = document.body.style\n document.body.style.overflow = \"hidden\"\n\n function onKeyDown(event: globalThis.KeyboardEvent) {\n // On the document rather than the panel: the trigger sits outside the drawer and\n // stays clickable above the backdrop, so focus is not guaranteed to be inside.\n if (event.key !== \"Escape\") return\n setDrawerOpen(false)\n // Focus goes back to what opened it, or it lands on the document body and a keyboard\n // user has to tab in from the top of the page again.\n triggerRef.current?.focus()\n }\n\n document.addEventListener(\"keydown\", onKeyDown)\n\n const wide = window.matchMedia(LG_QUERY)\n function onWide(event: MediaQueryListEvent) {\n if (event.matches) setDrawerOpen(false)\n }\n wide.addEventListener(\"change\", onWide)\n\n return () => {\n document.body.style.overflow = overflow\n document.removeEventListener(\"keydown\", onKeyDown)\n wide.removeEventListener(\"change\", onWide)\n }\n }, [drawerOpen])\n\n function closeDrawer() {\n setDrawerOpen(false)\n triggerRef.current?.focus()\n }\n\n function handlePanelKeyDown(event: KeyboardEvent<HTMLElement>) {\n if (!drawerOpen) return\n cycleTabWithin(panelRef.current, event)\n }\n\n return (\n <div className=\"min-h-dvh bg-surface-base text-body text-text-secondary lg:grid lg:shell-grid\">\n {drawerOpen ? (\n <div\n // The backdrop precedes the panel in the DOM, so the panel paints over it\n // without either of them naming a second z-index.\n className=\"fixed inset-0 z-overlay bg-backdrop lg:hidden\"\n onMouseDown={closeDrawer}\n aria-hidden\n />\n ) : null}\n\n <AdminSidebar\n navigation={navigation}\n pathname={pathname}\n user={user}\n panelRef={panelRef}\n onNavigate={() => setDrawerOpen(false)}\n {...(accountMenu === undefined ? {} : { accountMenu })}\n className={cx(\n \"lg:sticky lg:top-0 lg:z-base lg:flex\",\n drawerOpen ? \"fixed inset-y-0 left-0 z-overlay flex\" : \"hidden\",\n )}\n {...(drawerOpen ? { onKeyDown: handlePanelKeyDown } : {})}\n />\n\n <main className=\"min-w-0 px-6 pt-8 pb-12 lg:px-8 xl:px-12\">\n <div className={cx(\"mb-4 lg:hidden\", drawerOpen && \"relative z-modal\")}>\n <IconButton\n ref={triggerRef}\n morph\n icon={drawerOpen ? \"close\" : \"open-navigation\"}\n label={drawerOpen ? \"Close navigation\" : \"Open navigation\"}\n aria-expanded={drawerOpen}\n aria-controls=\"husk-sidebar\"\n onClick={() => (drawerOpen ? closeDrawer() : setDrawerOpen(true))}\n />\n </div>\n {children}\n </main>\n </div>\n )\n}\n","import type { ColumnAlign } from \"../core/list-view.js\"\n\n/**\n * Display formatting shared by admin screens.\n *\n * Numbers and dates are formatted in one place so two screens cannot disagree about what\n * 1536 bytes or an ISO timestamp looks like. Everything here is presentation only: nothing\n * in this file decides what is read or written.\n */\n\n/** Decimal units, which is how storage is quoted by every provider Husk sits on top of. */\nconst BYTE_UNITS = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"] as const\n\n/**\n * Bytes as a short human-readable string: `0 B`, `940 B`, `1.5 KB`, `12 MB`.\n *\n * One decimal below ten so a small library does not round to a flat `1 MB`, none above it\n * where the extra digit is noise in a dashboard tile.\n */\nexport function formatBytes(bytes: number): string {\n if (!Number.isFinite(bytes) || bytes <= 0) return \"0 B\"\n\n let value = bytes\n let unit = 0\n while (value >= 1000 && unit < BYTE_UNITS.length - 1) {\n value /= 1000\n unit += 1\n }\n\n const label = BYTE_UNITS[unit] ?? \"B\"\n if (unit === 0) return `${Math.round(value)} ${label}`\n return `${value < 10 ? value.toFixed(1) : Math.round(value)} ${label}`\n}\n\n/** The interface is English, so the locale is fixed rather than read from the browser. */\nconst DATE_TIME = new Intl.DateTimeFormat(\"en-US\", {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n})\n\n/**\n * An ISO 8601 timestamp as a date and time.\n *\n * An unparsable value comes back unchanged instead of as `Invalid Date`: a timestamp the\n * adapter could not convert is a data problem, and showing the raw value is what lets\n * somebody diagnose it.\n */\nexport function formatDateTime(iso: string): string {\n const date = new Date(iso)\n if (Number.isNaN(date.getTime())) return iso\n return DATE_TIME.format(date)\n}\n\n/** Date without a time, for a value that stores a day rather than an instant. */\nconst DATE_ONLY = new Intl.DateTimeFormat(\"en-US\", { dateStyle: \"medium\" })\n\n/** A stored date field is either `YYYY-MM-DD` or a full ISO instant. */\nconst DAY_ONLY = /^\\d{4}-\\d{2}-\\d{2}$/\n\n/**\n * A date value as a reader sees it, at the precision it was stored with.\n *\n * A day-only value is formatted as a day: turning `2026-09-18` into a time would invent a\n * midnight nobody chose, and would move the date across a timezone boundary.\n */\nexport function formatDate(value: string): string {\n if (!DAY_ONLY.test(value)) return formatDateTime(value)\n\n // Parsed as UTC by spec; formatted from its parts so the day cannot shift westwards.\n const date = new Date(`${value}T00:00:00Z`)\n if (Number.isNaN(date.getTime())) return value\n return DATE_ONLY.format(\n new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()),\n )\n}\n\n/**\n * One field value as one table cell, decided by the value it got rather than by the field\n * type that produced it.\n *\n * This is why the list view has no `switch (field.type)`: the column already knows how it\n * is typeset (core/list-view.ts decides that once, from the schema), and the cell only has\n * to turn whatever the adapter returned into a line of text. A value the column cannot\n * render, and a value that was never set, both come back as `null`, which the cell renders\n * as its \"not set\" state rather than as a blank nobody can interpret.\n */\nexport function formatCellValue(value: unknown, align: ColumnAlign): string | null {\n if (value === null || value === undefined || value === \"\") return null\n if (typeof value === \"boolean\") return value ? \"Yes\" : \"No\"\n if (typeof value === \"number\") return Number.isFinite(value) ? String(value) : null\n\n if (typeof value === \"string\") {\n return align === \"date\" ? formatDate(value) : value\n }\n\n if (Array.isArray(value)) {\n const parts = value.filter((item): item is string => typeof item === \"string\")\n return parts.length === 0 ? null : parts.join(\", \")\n }\n\n return null\n}\n","import type { ContentTypeLike } from \"../types/content-type.js\"\nimport type { Entry, EntryStatus } from \"../types/entry.js\"\nimport type { MediaItem } from \"../types/media.js\"\n\n/**\n * The seam between the CMS and its storage.\n *\n * Everything above this interface (the admin, the SDK, the registry, the validator) is\n * written against `CmsAdapter` and knows nothing about Firestore. Everything below it lives\n * under `src/firebase/**`, which is the only place the Firebase SDK may be imported. If a\n * screen or an SDK method needs something this interface does not offer, the interface\n * grows; it is never bypassed.\n *\n * Values crossing this boundary are already in their read shape: timestamps are ISO 8601\n * strings, references are ids, and field values match what `FieldValues` describes. The\n * converters on the Firestore side own the translation in both directions.\n */\n\nexport type FilterOperator =\n | \"==\"\n | \"!=\"\n | \"<\"\n | \"<=\"\n | \">\"\n | \">=\"\n | \"in\"\n | \"not-in\"\n | \"array-contains\"\n | \"array-contains-any\"\n\nexport interface EntryFilter {\n field: string\n op: FilterOperator\n value: unknown\n}\n\nexport interface SortSpec {\n field: string\n direction: \"asc\" | \"desc\"\n}\n\nexport interface ListQuery {\n filters?: readonly EntryFilter[]\n sort?: SortSpec\n /**\n * Free text matched against the content type's `titleField`, as a prefix.\n *\n * What it does, exactly, because a search box that promises more than it delivers is\n * worse than one that says what it is: the adapter turns the term into a range scan\n * (`>= term`, `<= term + U+F8FF`) over the title field. That matches from the beginning\n * of the title and it is case sensitive, because Firestore compares strings by their\n * UTF-8 bytes and offers no substring, no fuzzy and no case-insensitive operator.\n * \"Portfolio\" is found by \"Port\", not by \"port\" and not by \"folio\".\n *\n * Two consequences a caller has to know about:\n *\n * - A range filter forces the first ordering onto the field it ranges over, so a search\n * is always ordered by title ascending and `sort` is ignored while one is active.\n * - A content type with no `titleField` has nothing to match against, so the adapter\n * rejects the query instead of silently returning everything. Ask `canSearch()` in\n * core/list-view.ts before offering the box.\n */\n search?: string\n /** Page size. The adapter caps it; see DEFAULT_PAGE_SIZE and MAX_PAGE_SIZE. */\n limit?: number\n /** Opaque cursor from a previous page. Never constructed by a caller. */\n cursor?: string | null\n /**\n * `\"any\"` reads every status and is the admin default. The public SDK passes\n * `\"published\"`, which is what keeps drafts off a customer's website.\n */\n status?: EntryStatus | \"any\"\n}\n\nexport interface Page<TItem> {\n items: readonly TItem[]\n /** Pass back as `ListQuery.cursor` to read the next page. Null when the page is the last. */\n cursor: string | null\n hasMore: boolean\n}\n\nexport interface MediaQuery {\n limit?: number\n cursor?: string | null\n /** MIME prefix, for example `image/`. */\n type?: string\n}\n\nexport interface MediaInput {\n name: string\n type: string\n size: number\n url: string\n path: string\n alt?: string | null\n width?: number | null\n height?: number | null\n}\n\n/**\n * What the media library occupies, summed from the metadata documents.\n *\n * `bytes` is the sum of the `size` recorded on each media document, not a reading of the\n * Storage bucket itself. Everything Husk uploads records its size, so the two agree; an\n * object placed in the bucket by something other than Husk is not counted, because Husk\n * has no document for it. Stated rather than hidden: a dashboard figure that silently\n * means something narrower than its label is worse than no figure.\n */\nexport interface MediaUsage {\n /** Media documents. */\n count: number\n /** Total bytes across those documents. */\n bytes: number\n}\n\n/**\n * One entry that references a media item.\n *\n * `title` is what the warning prints. It is null when the entry's content type declares no\n * title field, or when the value is empty: the dialog then prints the id, which is the one\n * name that is always correct.\n */\nexport interface MediaUsageReference {\n contentType: string\n entryId: string\n title: string | null\n}\n\nexport interface MediaUsageQuery {\n /** How many referencing entries to name. Defaults to MEDIA_USAGE_LIMIT. */\n limit?: number\n}\n\n/**\n * How many referencing entries a usage lookup names.\n *\n * A delete warning exists to be read. Twenty-five names already say \"this is used a lot\",\n * and the caller compares the length against this number to know the list was cut rather\n * than complete.\n */\nexport const MEDIA_USAGE_LIMIT = 25\n\n/** What a reference refresh managed to rewrite, and what it did not. */\nexport interface MediaRefreshResult {\n updated: number\n /** Entries whose denormalized url could not be rewritten. Named, never swallowed. */\n failed: readonly MediaUsageReference[]\n}\n\nexport interface MediaAdapter {\n list(query?: MediaQuery): Promise<Page<MediaItem>>\n getById(mediaId: string): Promise<MediaItem | null>\n getMany(mediaIds: readonly string[]): Promise<readonly MediaItem[]>\n /**\n * Allocates a media id without writing anything.\n *\n * The upload path needs the id before the document exists, because the Storage object\n * path contains it and the bytes are written first. Nothing is reserved on the server:\n * the id is generated locally, and an id that is never used costs nothing.\n */\n reserveId(): string\n /**\n * Writes the metadata document. With `mediaId`, it is written at that id, which is how\n * an upload's bytes and its document end up naming each other.\n */\n create(input: MediaInput, mediaId?: string): Promise<MediaItem>\n update(mediaId: string, patch: Partial<MediaInput>): Promise<MediaItem>\n delete(mediaId: string): Promise<void>\n /**\n * Entries referencing this media item, so a delete can warn instead of breaking pages.\n *\n * Answered from the `mediaRefs` reverse index each entry write maintains, not from a\n * scan: see core/media-references.ts for what that costs and where it is blind.\n */\n usages(\n mediaId: string,\n query?: MediaUsageQuery,\n ): Promise<readonly MediaUsageReference[]>\n /**\n * Rewrites the denormalized `url` on every entry that references this media item.\n *\n * Only replace needs it. Overwriting the bytes of an existing item mints a new download\n * URL, and the copy of the old one denormalized into each entry would otherwise stay\n * until that entry is next saved. `mediaId` remains the source of truth either way, so a\n * refresh that fails degrades a stale convenience rather than breaking a reference.\n */\n refreshReferences(mediaId: string, url: string): Promise<MediaRefreshResult>\n /**\n * Count and total size of the whole library, for the dashboard's storage figure.\n * One aggregate read, not a walk over every page of media.\n */\n usage(): Promise<MediaUsage>\n}\n\n/**\n * Schema operations act on `schemas/`, never on entries. A locked or code-defined type is\n * rejected here as well as in the UI, so bypassing the Schema Builder changes nothing.\n */\nexport interface SchemaAdapter {\n list(): Promise<readonly ContentTypeLike[]>\n get(slug: string): Promise<ContentTypeLike | null>\n create(type: ContentTypeLike): Promise<ContentTypeLike>\n update(slug: string, type: ContentTypeLike): Promise<ContentTypeLike>\n delete(slug: string): Promise<void>\n /**\n * Live view of every database-defined type, so the sidebar and the routes follow a\n * structure change without a rebuild and without a reload.\n *\n * One listener for the whole collection, feeding `RegistryStore.setDatabaseTypes`. What\n * it costs is written down on that interface. `onError` is called rather than thrown,\n * because a listener that dies silently leaves an admin quietly stale.\n */\n watch(\n listener: (types: readonly ContentTypeLike[]) => void,\n onError?: (error: Error) => void,\n ): () => void\n}\n\nexport interface FieldPurgeOptions {\n /** How many entries to clear in one call. Capped at MAX_FIELD_PURGE. */\n limit?: number\n}\n\nexport interface FieldPurgeResult {\n /** Entries whose stored value was deleted by this call. */\n purged: number\n /** True when the cap was hit and another call is needed to finish. */\n remaining: boolean\n}\n\n/** One call clears at most this many entries, so a purge cannot become an unbounded write. */\nexport const MAX_FIELD_PURGE = 250\n\n/**\n * The stored values of a **removed** field, which is the only data the Schema Builder is\n * ever allowed to reach.\n *\n * It is a separate interface, and not two more methods on `SchemaAdapter`, so the M8\n * guardrail is structural rather than a comment: `SchemaAdapter` has no method that can\n * touch an entry, and this one refuses any key the content type still declares. The Schema\n * Builder writes schemas; purging is a different, separately named, separately confirmed\n * operation that happens to be reachable from the same screen.\n */\nexport interface FieldDataAdapter {\n /**\n * How many entries of this content type hold a non-null value for this top-level field\n * key, so the removal warning can say \"14 entries\" rather than \"some entries\".\n *\n * One count aggregation, not a walk: `where(key, \"!=\", null)` plus `count()`. Firestore\n * indexes every top-level field automatically, so no composite index is needed, and an\n * aggregation is billed per thousand matched index entries rather than per document.\n *\n * Two limits, stated rather than hidden. A key nested inside a repeater row is not a\n * top-level field and cannot be counted this way, so `count` rejects one instead of\n * answering zero. And an entry written before the field existed simply has no such key,\n * which Firestore treats as not matching, which is the answer the warning wants.\n */\n count(slug: string, key: string): Promise<number>\n /**\n * Deletes the stored values of a removed field. The only destructive schema operation.\n *\n * Refused unless the content type lists the key under `removedFields`: a key that is\n * still live, or that the type has never heard of, is never purged. Admin only, and\n * bounded per call.\n */\n purge(slug: string, key: string, options?: FieldPurgeOptions): Promise<FieldPurgeResult>\n}\n\n/**\n * One stored entry as the migration runner sees it: its id, the version it is stamped at,\n * and its values in their stored form.\n *\n * Deliberately not an `Entry`. Reading an entry runs it through the content type's field\n * specs, and the whole point of a migration is that the stored document does not match\n * those specs yet, so converting it first would either fail or quietly drop the values the\n * migration was written to move.\n */\nexport interface StoredEntryRecord {\n id: string\n schemaVersion: number\n values: Record<string, unknown>\n}\n\nexport interface MigrationWrite {\n /** The stored version the transform read. The write is refused if it has moved. */\n expectedVersion: number\n nextVersion: number\n}\n\n/**\n * The storage half of the migration runner. See core/migrations.ts for the runner itself.\n *\n * Kept off `SchemaAdapter` for the same reason `FieldDataAdapter` is: a schema operation\n * must not be able to reach an entry. A migration reaches every entry of a type, which is\n * precisely why it is a separately named, separately permissioned port rather than two\n * more methods on the interface the Schema Builder holds.\n */\nexport interface MigrationAdapter {\n /** How many entries are stamped below the target version. One aggregation. */\n countBehind(slug: string, targetVersion: number): Promise<number>\n /** A page of entries stamped below the target version, oldest version first. */\n listBehind(\n slug: string,\n targetVersion: number,\n query?: { limit?: number },\n ): Promise<Page<StoredEntryRecord>>\n /**\n * Writes migrated values and restamps the entry, but only while the stored version is\n * still the one the transform read.\n *\n * Returns false when it has moved, which is a second runner having got there first and\n * is not an error. That conditional is what makes a migration safe to run twice and safe\n * to run from two places at once.\n */\n applyMigration(\n slug: string,\n entryId: string,\n values: Record<string, unknown>,\n write: MigrationWrite,\n ): Promise<boolean>\n}\n\nexport interface SettingsAdapter {\n get(key: string): Promise<Record<string, unknown> | null>\n set(key: string, value: Record<string, unknown>): Promise<void>\n}\n\nexport interface EntryInputData {\n /** Field values, already validated by the caller and validated again by the adapter. */\n values: Record<string, unknown>\n status?: EntryStatus\n}\n\nexport interface CmsAdapter {\n list(slug: string, query?: ListQuery): Promise<Page<Entry>>\n get(slug: string, entryId: string): Promise<Entry | null>\n /**\n * Looks an entry up by the value of the content type's `slug` field, not by document id.\n *\n * `status` narrows the lookup at the storage layer rather than after it, and on a public\n * website that is not an optimization. A visitor's read is unauthenticated, and the\n * security rules only let an unauthenticated query through when the query itself says\n * `status == \"published\"`; a lookup that asked for any status and filtered afterwards\n * would be refused outright. Defaults to `\"any\"`, which is the admin's uniqueness check.\n */\n getBySlug(\n slug: string,\n value: string,\n options?: Pick<ListQuery, \"status\">,\n ): Promise<Entry | null>\n /** Reads the one entry of a singleton. Rejects a collection. */\n getSingle(slug: string): Promise<Entry | null>\n create(slug: string, input: EntryInputData): Promise<Entry>\n update(slug: string, entryId: string, input: EntryInputData): Promise<Entry>\n delete(slug: string, entryId: string): Promise<void>\n /**\n * How many entries the same narrowing would return. Takes `search` as well, so the\n * list view's \"1-25 of 248\" counts the rows the reader is actually paging through.\n */\n count(\n slug: string,\n query?: Pick<ListQuery, \"filters\" | \"status\" | \"search\">,\n ): Promise<number>\n readonly media: MediaAdapter\n readonly schemas: SchemaAdapter\n readonly fieldData: FieldDataAdapter\n readonly migrations: MigrationAdapter\n readonly settings: SettingsAdapter\n}\n\nexport const DEFAULT_PAGE_SIZE = 25\n/** Above this, a list view is the wrong tool and a query is a denial-of-service risk. */\nexport const MAX_PAGE_SIZE = 100\n\nexport function normalizeLimit(limit: number | undefined): number {\n if (limit === undefined || !Number.isFinite(limit)) return DEFAULT_PAGE_SIZE\n return Math.min(Math.max(Math.trunc(limit), 1), MAX_PAGE_SIZE)\n}\n","import type { ContentTypeLike } from \"../types/content-type.js\"\nimport type { Entry } from \"../types/entry.js\"\n\n/** What an entry is called when its title field is empty or was never declared. */\nexport const UNTITLED_ENTRY = \"Untitled\"\n\n/**\n * The one-line name of an entry, resolved from the content type rather than guessed.\n *\n * Every screen that lists entries needs this: the dashboard, the collection list, a\n * relation picker, a delete confirmation. Resolving it in one place is what keeps an entry\n * from being called two different things on two screens.\n *\n * `titleField` is optional and its stored value is untrusted, so a missing field, a\n * non-string value and a blank string all fall back to `UNTITLED_ENTRY`. An entry with no\n * usable title still has to be nameable, or it cannot be listed at all.\n */\nexport function entryTitle(type: ContentTypeLike, entry: Entry): string {\n const key = type.titleField\n if (key === undefined) return UNTITLED_ENTRY\n\n const value = (entry as Record<string, unknown>)[key]\n if (typeof value !== \"string\") return UNTITLED_ENTRY\n\n const trimmed = value.trim()\n return trimmed === \"\" ? UNTITLED_ENTRY : trimmed\n}\n","import type { FieldDefinition, FieldInputValues, FieldMap, FieldValues } from \"./field.js\"\nimport type { PermissionMatrix } from \"./auth.js\"\n\nexport type ContentTypeKind = \"collection\" | \"singleton\"\n\n/**\n * A field that was removed from a content type while its stored values were kept.\n *\n * Removal is a state, not an absence. The definition is parked here instead of being\n * deleted, so the admin can name the field in a warning, offer it back unchanged, and so a\n * later purge knows what it is about to destroy. Nothing downstream of the registry reads\n * this map: forms, validation, list columns and the SDK all read `fields`, which is why a\n * removed field is inert everywhere without a single consumer having to filter it out.\n */\nexport interface RemovedField {\n /** Exactly the definition the field had at the moment it was removed. */\n field: FieldDefinition\n /** ISO 8601. A plain string, because a stored content type is plain JSON. */\n removedAt: string\n /** uid of whoever removed it. */\n removedBy: string\n}\n\nexport type RemovedFieldMap = { readonly [key: string]: RemovedField }\n\n/** Where a content type came from. Code always wins a slug conflict. See the registry. */\nexport type ContentTypeSource = \"code\" | \"database\"\n\nexport interface ContentType<TFields extends FieldMap = FieldMap> {\n slug: string\n kind: ContentTypeKind\n label: string\n /** Plural label for a collection. Defaults to `label` when absent. */\n labelPlural?: string\n description?: string\n /** Lucide icon name from the fixed vocabulary in .docs/styleguide/05-icons.md. */\n icon?: string\n fields: TFields\n /**\n * The order the fields are shown in, as a list of field keys.\n *\n * It exists because `fields` is a map, and object key order is not a place to store\n * meaning: it is not a documented Firestore guarantee, Firestore's own ordering of map\n * values compares keys sorted, and any re-serialization on the way through may change it.\n * An array has one order and keeps it. A code-defined type never round trips and keeps its\n * literal's order, so this key is absent there and the object order is used; the Schema\n * Builder writes it on every save, which is what makes a reorder survive a reload.\n *\n * It is a hint, not a second source of truth. An unknown key in it is ignored and a field\n * missing from it is appended, so a `fieldOrder` that has drifted from `fields` still\n * renders every field exactly once.\n */\n fieldOrder?: readonly string[]\n /**\n * Fields removed from `fields` whose stored values are still on the entries. Absent on a\n * type that has never had a field removed.\n */\n removedFields?: RemovedFieldMap\n /**\n * A locked type cannot be edited or deleted through the Schema Builder, and the adapter\n * rejects schema writes against it even when the UI is bypassed. Only meaningful for a\n * code-defined type; a database-defined type is never locked.\n */\n locked?: boolean\n /** Field key shown as the entry's title in lists and pickers. */\n titleField?: keyof TFields & string\n /** Default sort for list views, as a field key with a direction. */\n defaultSort?: { field: keyof TFields & string; direction: \"asc\" | \"desc\" }\n permissions?: PermissionMatrix\n /** Bumped when the stored shape changes. Read by the M10 migration runner. */\n schemaVersion?: number\n}\n\n/**\n * A content type with its field map erased to `FieldMap`.\n *\n * `ContentType<TFields>` is invariant in `TFields`, so a concrete content type produced by\n * `defineContentType` is not assignable to `ContentType<FieldMap>`. Everything that handles\n * content types generically (the registry, the adapter, the Schema Builder) takes this\n * structural shape instead, which a concrete content type does satisfy. Authoring and\n * inference keep the generic form.\n */\nexport interface ContentTypeLike {\n slug: string\n kind: ContentTypeKind\n label: string\n labelPlural?: string\n description?: string\n icon?: string\n fields: FieldMap\n /**\n * The order the fields are shown in, as a list of field keys.\n *\n * It exists because `fields` is a map and a map does not keep an order once it has been\n * through Firestore: a stored document returns its map keys sorted, not in the order they\n * were written. A code-defined type never round trips and keeps its literal's order, so\n * this key is absent there and the object order is used; the Schema Builder writes it on\n * every save, which is what makes a reorder survive a reload.\n *\n * It is a hint, not a second source of truth. An unknown key in it is ignored and a field\n * missing from it is appended, so a `fieldOrder` that has drifted from `fields` still\n * renders every field exactly once.\n */\n fieldOrder?: readonly string[]\n removedFields?: RemovedFieldMap\n locked?: boolean\n titleField?: string\n defaultSort?: { field: string; direction: \"asc\" | \"desc\" }\n permissions?: PermissionMatrix\n schemaVersion?: number\n}\n\n/** Field keys the entry metadata already owns; a content type may not redefine them. */\nexport const RESERVED_FIELD_KEYS = [\n \"id\",\n \"status\",\n \"createdAt\",\n \"createdBy\",\n \"updatedAt\",\n \"updatedBy\",\n \"publishedAt\",\n \"schemaVersion\",\n] as const\n\nexport type ReservedFieldKey = (typeof RESERVED_FIELD_KEYS)[number]\n\nexport type ContentTypeValues<TType extends { fields: FieldMap }> = FieldValues<\n TType[\"fields\"]\n>\n\nexport type ContentTypeInputValues<TType extends { fields: FieldMap }> = FieldInputValues<\n TType[\"fields\"]\n>\n","import { SchemaError } from \"../core/errors.js\"\nimport { ENTRY_ACTIONS, ROLES } from \"../types/auth.js\"\nimport type { EntryAction, PermissionMatrix, Role } from \"../types/auth.js\"\nimport type { ContentTypeLike } from \"../types/content-type.js\"\n\nimport { PERMISSION_DEFAULTS, resolveDecision } from \"./can.js\"\nimport type { Decision } from \"./can.js\"\n\n/**\n * The per-content-type permission matrix: the editable half of the truth table.\n *\n * `can()` is the resolver. This module is everything around it that is not a decision: what\n * a stored matrix is allowed to look like, what one means once the role defaults are\n * applied, and how an editing screen turns a checkbox into the next matrix. It is here\n * rather than in `can.ts` so the resolver stays a pure lookup that a render can call in a\n * loop.\n *\n * The one rule that governs the whole module: **a matrix narrows, it never widens.** The\n * effective answer is the intersection of the role default and the matrix, so listing\n * `author` under `delete` does not give an author a delete. That is not a simplification\n * for its own sake. The security rules enforce the role defaults directly from the token,\n * and only consult the matrix to narrow further, because widening in the rules would mean\n * trusting a document to grant a privilege. A matrix that could widen would therefore be\n * accepted by this resolver and refused by the database, which is the one thing a\n * permission system must never do.\n */\n\n/** Every action a matrix can speak about. An admin action is never per content type. */\nexport const MATRIX_ACTIONS: readonly EntryAction[] = ENTRY_ACTIONS\n\n/** What a role may do with an action once the defaults and the matrix are both applied. */\nexport type MatrixDecision = Decision\n\n/**\n * The limitations the Developer area has to state rather than imply.\n *\n * A screen that draws a checkbox for something no layer enforces is worse than a screen\n * that omits it: it reads as a guarantee. These are the exact gaps, in the words the\n * screen should use.\n */\nexport const MATRIX_LIMITS = {\n admin:\n \"An admin is never restricted by a matrix. Removing every other role from an action leaves it admin-only; there is no way to lock an admin out of their own project.\",\n ownership:\n \"An author may only ever update or delete entries they created. Ticking an author here grants the action on their own entries, never on somebody else's.\",\n narrowing:\n \"A matrix can only take permissions away. Ticking a role that its own role does not grant changes nothing, and the row says so.\",\n publicRead:\n \"Denying read hides entries from the admin, not from the public website. A published entry is readable by anyone with its address by design; unpublish it to take it down.\",\n} as const\n\nfunction isEntryActionKey(value: string): value is EntryAction {\n return (ENTRY_ACTIONS as readonly string[]).includes(value)\n}\n\nfunction isRole(value: unknown): value is Role {\n return typeof value === \"string\" && (ROLES as readonly string[]).includes(value)\n}\n\n/**\n * Refuses a malformed matrix before it is stored.\n *\n * Called from `assertValidContentType`, so a database-defined type read back out of\n * Firestore goes through exactly the same check as a code-defined one. A matrix that named\n * an unknown role would be read by the security rules as a list that simply never matches,\n * which denies silently; better to refuse the write than to ship a rule nobody can explain.\n */\nexport function assertValidPermissionMatrix(slug: string, matrix: unknown): void {\n if (matrix === undefined) return\n\n if (typeof matrix !== \"object\" || matrix === null || Array.isArray(matrix)) {\n throw new SchemaError(\n `Content type \"${slug}\" has a permissions matrix that is not an object.`,\n )\n }\n\n for (const [action, roles] of Object.entries(matrix as Record<string, unknown>)) {\n if (!isEntryActionKey(action)) {\n throw new SchemaError(\n `Content type \"${slug}\" has a permissions entry for \"${action}\", which is not an entry action. Use one of: ${ENTRY_ACTIONS.join(\", \")}.`,\n )\n }\n\n if (!Array.isArray(roles)) {\n throw new SchemaError(\n `Content type \"${slug}\" lists permissions for \"${action}\" as something other than a list of roles.`,\n )\n }\n\n const seen = new Set<string>()\n for (const role of roles as readonly unknown[]) {\n if (!isRole(role)) {\n throw new SchemaError(\n `Content type \"${slug}\" grants \"${action}\" to \"${String(role)}\", which is not a role. Known roles: ${ROLES.join(\", \")}.`,\n )\n }\n if (seen.has(role)) {\n throw new SchemaError(\n `Content type \"${slug}\" lists \"${role}\" twice under \"${action}\".`,\n )\n }\n seen.add(role)\n }\n }\n}\n\n/**\n * The stored form: known actions only, roles deduplicated and in a fixed order.\n *\n * Fixed order because the matrix is written to Firestore and read back by the Schema\n * Builder, and a list whose order changes on every save shows a diff where nothing changed.\n * An action whose list matches the roles the defaults already allow is dropped, so an\n * untouched matrix is stored as absent rather than as a copy of the defaults that would\n * silently stop tracking them.\n */\nexport function normalizePermissionMatrix(\n matrix: PermissionMatrix | undefined,\n): PermissionMatrix | undefined {\n if (matrix === undefined) return undefined\n\n const normalized: { -readonly [K in EntryAction]?: readonly Role[] } = {}\n\n for (const action of MATRIX_ACTIONS) {\n const roles = matrix[action]\n if (roles === undefined) continue\n\n const kept = ROLES.filter((role) => roles.includes(role))\n if (sameRoles(kept, defaultRoles(action))) continue\n\n normalized[action] = kept\n }\n\n return Object.keys(normalized).length === 0 ? undefined : normalized\n}\n\n/** The roles whose own defaults allow an action at all, ownership aside. */\nexport function defaultRoles(action: EntryAction): readonly Role[] {\n return ROLES.filter((role) => PERMISSION_DEFAULTS[role][action] !== \"deny\")\n}\n\nfunction sameRoles(left: readonly Role[], right: readonly Role[]): boolean {\n return left.length === right.length && left.every((role) => right.includes(role))\n}\n\n/**\n * The effective decision for one role and one action on one content type.\n *\n * Exactly what `can()` resolves, minus the entry lookup, so a screen can label a row\n * without inventing a user. Keep the two in step: a test drives both over the same inputs.\n */\nexport function matrixDecision(\n type: Pick<ContentTypeLike, \"permissions\"> | undefined,\n role: Role,\n action: EntryAction,\n): MatrixDecision {\n // Delegated rather than reimplemented. The screen must label a cell with the answer the\n // adapter and the rules will give, not with a second opinion that happens to agree today.\n return resolveDecision(role, action, type)\n}\n\n/** One role's cell in the Developer area's table. */\nexport interface MatrixCell {\n role: Role\n /** Whether the checkbox is ticked: the role is listed, or the matrix is silent. */\n listed: boolean\n /** What the three layers will actually do. */\n decision: MatrixDecision\n /**\n * True when the checkbox cannot change the outcome: an admin, who is never restricted,\n * or a role whose own defaults deny the action regardless of the matrix. The screen\n * disables the control and says why rather than offering a lie.\n */\n fixed: boolean\n}\n\nexport interface MatrixRow {\n action: EntryAction\n cells: readonly MatrixCell[]\n}\n\n/** The whole table, in a fixed order, ready to render. */\nexport function permissionMatrixRows(\n type: Pick<ContentTypeLike, \"permissions\"> | undefined,\n): readonly MatrixRow[] {\n return MATRIX_ACTIONS.map((action) => ({\n action,\n cells: ROLES.map((role) => {\n const listed = type?.permissions?.[action]\n return {\n role,\n listed: listed === undefined ? true : listed.includes(role),\n decision: matrixDecision(type, role, action),\n fixed: role === \"admin\" || PERMISSION_DEFAULTS[role][action] === \"deny\",\n }\n }),\n }))\n}\n\n/**\n * The next matrix after one checkbox is toggled.\n *\n * Unticking a role while the matrix is silent about the action has to materialize the\n * action first, from the defaults rather than from nothing: an empty list means \"nobody but\n * an admin\", and a screen that produced one from a single untick would revoke two roles for\n * one click. Toggling a fixed cell returns the matrix unchanged, so a UI bug cannot store a\n * row that claims something no layer will do.\n */\nexport function withMatrixRole(\n matrix: PermissionMatrix | undefined,\n action: EntryAction,\n role: Role,\n listed: boolean,\n): PermissionMatrix | undefined {\n if (role === \"admin\" || PERMISSION_DEFAULTS[role][action] === \"deny\") return matrix\n\n const current = matrix?.[action] ?? defaultRoles(action)\n const next = listed\n ? ROLES.filter((candidate) => candidate === role || current.includes(candidate))\n : current.filter((candidate) => candidate !== role)\n\n return normalizePermissionMatrix({ ...matrix, [action]: next })\n}\n","import type { MediaReference } from \"./media.js\"\n\nexport const FIELD_TYPES = [\n \"text\",\n \"textarea\",\n \"number\",\n \"boolean\",\n \"select\",\n \"date\",\n \"slug\",\n \"richtext\",\n \"image\",\n \"file\",\n \"relation\",\n \"repeater\",\n] as const\n\nexport type FieldType = (typeof FIELD_TYPES)[number]\n\n/**\n * The full rule vocabulary. Every rule compiles to the same runtime validator, which the\n * admin form and the adapter both run, so a rule can never be enforced in one place only.\n */\nexport interface ValidationRules {\n required?: boolean\n minLength?: number\n maxLength?: number\n min?: number\n max?: number\n /** Serialized as a string, not a RegExp, because rules travel through Firestore. */\n pattern?: string\n /** Rejects a value already held by another entry of the same content type. */\n unique?: boolean\n}\n\ninterface FieldCommon {\n label: string\n description?: string\n placeholder?: string\n validation?: ValidationRules\n /** Hidden fields still store and validate; they are simply not rendered in the form. */\n hidden?: boolean\n readonly?: boolean\n}\n\nexport interface TextField extends FieldCommon {\n type: \"text\"\n defaultValue?: string\n}\n\nexport interface TextareaField extends FieldCommon {\n type: \"textarea\"\n rows?: number\n defaultValue?: string\n}\n\nexport interface NumberField extends FieldCommon {\n type: \"number\"\n step?: number\n defaultValue?: number\n}\n\nexport interface BooleanField extends FieldCommon {\n type: \"boolean\"\n defaultValue?: boolean\n}\n\nexport interface SelectOption<TValue extends string = string> {\n value: TValue\n label: string\n}\n\nexport interface SelectField<TValue extends string = string> extends FieldCommon {\n type: \"select\"\n options: readonly SelectOption<TValue>[]\n multiple?: boolean\n defaultValue?: TValue\n}\n\nexport interface DateField extends FieldCommon {\n type: \"date\"\n /** `date` stores `YYYY-MM-DD`; `datetime` stores a full ISO 8601 instant. */\n precision?: \"date\" | \"datetime\"\n}\n\nexport interface SlugField extends FieldCommon {\n type: \"slug\"\n /** Field key the slug is derived from until the editor overrides it. */\n from?: string\n}\n\n/**\n * Rich text is stored as a serialized document, not as an HTML string, so the editor choice\n * (settled in M5) stays an implementation detail and the value can be re-rendered rather\n * than re-parsed.\n */\nexport interface RichTextValue {\n format: \"husk-richtext-v1\"\n content: unknown\n}\n\nexport interface RichtextField extends FieldCommon {\n type: \"richtext\"\n /** Marks and blocks the toolbar offers. Absent means the default set. */\n features?: readonly string[]\n}\n\nexport interface ImageField extends FieldCommon {\n type: \"image\"\n accept?: readonly string[]\n}\n\nexport interface FileField extends FieldCommon {\n type: \"file\"\n accept?: readonly string[]\n}\n\nexport interface RelationField<TTo extends string = string> extends FieldCommon {\n type: \"relation\"\n /** Slug of the referenced content type. */\n to: TTo\n many?: boolean\n}\n\nexport interface RepeaterField<TFields extends FieldMap = FieldMap> extends FieldCommon {\n type: \"repeater\"\n fields: TFields\n min?: number\n max?: number\n}\n\nexport type FieldDefinition =\n | TextField\n | TextareaField\n | NumberField\n | BooleanField\n | SelectField\n | DateField\n | SlugField\n | RichtextField\n | ImageField\n | FileField\n | RelationField\n | RepeaterField\n\nexport type FieldMap = { readonly [key: string]: FieldDefinition }\n\n/** The value one field definition produces, before required-ness is applied. */\nexport type FieldValue<TField extends FieldDefinition> = TField extends\n TextField | TextareaField | SlugField\n ? string\n : TField extends NumberField\n ? number\n : TField extends BooleanField\n ? boolean\n : TField extends DateField\n ? string\n : TField extends SelectField<infer TOption>\n ? TField extends { multiple: true }\n ? TOption[]\n : TOption\n : TField extends RichtextField\n ? RichTextValue\n : TField extends ImageField | FileField\n ? MediaReference\n : TField extends RelationField\n ? TField extends { many: true }\n ? string[]\n : string\n : TField extends RepeaterField<infer TFields>\n ? FieldValues<TFields>[]\n : never\n\ntype IsRequired<TField extends FieldDefinition> = TField extends {\n validation: { required: true }\n}\n ? true\n : false\n\n/**\n * Read shape: every key is present. An optional field reads as `null` rather than\n * `undefined`, so a consumer never has to distinguish \"absent\" from \"empty\".\n */\nexport type FieldValues<TFields extends FieldMap> = {\n [K in keyof TFields]: IsRequired<TFields[K]> extends true\n ? FieldValue<TFields[K]>\n : FieldValue<TFields[K]> | null\n}\n\n/** Write shape: optional fields may be omitted entirely. */\nexport type FieldInputValues<TFields extends FieldMap> = {\n [K in keyof TFields as IsRequired<TFields[K]> extends true ? K : never]: FieldValue<\n TFields[K]\n >\n} & {\n [K in keyof TFields as IsRequired<TFields[K]> extends true ? never : K]?: FieldValue<\n TFields[K]\n > | null\n}\n","import { assertValidPermissionMatrix } from \"../permissions/matrix.js\"\nimport { RESERVED_FIELD_KEYS } from \"../types/content-type.js\"\nimport type { ContentType, RemovedFieldMap } from \"../types/content-type.js\"\nimport { FIELD_TYPES } from \"../types/field.js\"\nimport type { FieldDefinition, FieldMap } from \"../types/field.js\"\n\nimport { SchemaError } from \"./errors.js\"\n\n/** Lowercase, digits, and single hyphens. The same shape the admin routes use. */\nconst SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\n/** A field key becomes a TypeScript property and a Firestore field name. */\nconst FIELD_KEY_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/\n\nconst FIELD_TYPE_SET: ReadonlySet<string> = new Set(FIELD_TYPES)\nconst RESERVED_SET: ReadonlySet<string> = new Set(RESERVED_FIELD_KEYS)\n\nfunction assertFieldMap(fields: FieldMap, slug: string, path: string): void {\n const keys = Object.keys(fields)\n if (keys.length === 0) {\n throw new SchemaError(\n `Content type \"${slug}\" defines no fields at ${path || \"the root\"}.`,\n )\n }\n\n for (const key of keys) {\n const at = path ? `${path}.${key}` : key\n\n if (!FIELD_KEY_PATTERN.test(key)) {\n throw new SchemaError(\n `Content type \"${slug}\" has an invalid field key \"${at}\". A field key must be a valid identifier: letters, digits, and underscores, not starting with a digit.`,\n )\n }\n\n // Entry metadata owns these keys. Allowing a field to shadow one would make\n // `entry.status` mean two different things depending on the content type.\n if (!path && RESERVED_SET.has(key)) {\n throw new SchemaError(\n `Content type \"${slug}\" defines a field named \"${key}\", which is reserved for entry metadata. Reserved keys: ${RESERVED_FIELD_KEYS.join(\", \")}.`,\n )\n }\n\n const field = fields[key] as FieldDefinition | undefined\n if (!field) continue\n\n if (!FIELD_TYPE_SET.has(field.type)) {\n throw new SchemaError(\n `Field \"${at}\" of content type \"${slug}\" has unknown type \"${field.type}\". Known types: ${FIELD_TYPES.join(\", \")}.`,\n )\n }\n\n if (field.type === \"select\" && field.options.length === 0) {\n throw new SchemaError(\n `Select field \"${at}\" of content type \"${slug}\" has no options.`,\n )\n }\n\n if (field.type === \"slug\" && field.from !== undefined && !(field.from in fields)) {\n throw new SchemaError(\n `Slug field \"${at}\" of content type \"${slug}\" derives from \"${field.from}\", which is not a field of the same level.`,\n )\n }\n\n if (field.type === \"repeater\") {\n assertFieldMap(field.fields, slug, at)\n }\n }\n}\n\n/**\n * Declares a content type and infers its entry shape from its field map.\n *\n * The `const` type parameter is what makes inference work: without it, `required: true`\n * widens to `boolean` and every field would read as nullable, and select options would\n * widen to `string` instead of the union of the declared values.\n *\n * Structural mistakes throw here rather than at first write, so a code-defined type fails\n * at module load and never reaches Firestore.\n */\nexport function defineContentType<const TFields extends FieldMap>(\n definition: ContentType<TFields>,\n): ContentType<TFields> {\n assertValidContentType(definition)\n return definition\n}\n\n/**\n * The structural checks, separated from `defineContentType` so that a database-defined type\n * read out of Firestore goes through exactly the same guards as a code-defined one. The\n * registry calls this; it must never trust a stored definition more than a written one.\n */\nexport function assertValidContentType(definition: {\n slug: string\n kind: unknown\n fields: FieldMap\n removedFields?: RemovedFieldMap | undefined\n titleField?: string | undefined\n defaultSort?: { field: string; direction: \"asc\" | \"desc\" } | undefined\n permissions?: unknown\n}): void {\n const { slug, kind, fields, removedFields, titleField, defaultSort } = definition\n\n if (!SLUG_PATTERN.test(slug)) {\n throw new SchemaError(\n `Content type slug \"${slug}\" is invalid. Use lowercase letters, digits, and single hyphens, for example \"blog-posts\".`,\n )\n }\n\n if (kind !== \"collection\" && kind !== \"singleton\") {\n throw new SchemaError(\n `Content type \"${slug}\" has kind \"${String(kind)}\". Use \"collection\" or \"singleton\".`,\n )\n }\n\n assertFieldMap(fields, slug, \"\")\n\n if (removedFields !== undefined) {\n for (const [key, removed] of Object.entries(removedFields)) {\n // A key cannot be live and removed at once. If it could, every consumer would have to\n // decide which of the two definitions wins, and the answer would differ per consumer.\n if (key in fields) {\n throw new SchemaError(\n `Content type \"${slug}\" lists \"${key}\" as a removed field and as a live field. Re-adding a removed key must take it out of removedFields.`,\n )\n }\n\n if (!FIELD_KEY_PATTERN.test(key) || RESERVED_SET.has(key)) {\n throw new SchemaError(\n `Content type \"${slug}\" has an invalid removed field key \"${key}\".`,\n )\n }\n\n if (!removed || typeof removed.removedAt !== \"string\") {\n throw new SchemaError(\n `Removed field \"${key}\" of content type \"${slug}\" has no removedAt timestamp.`,\n )\n }\n\n // The parked definition goes through the same field checks a live one does, so a\n // corrupted record surfaces here rather than when it is offered back to an editor.\n // Merged with the live fields so a parked `slug` field can still resolve its\n // `from` sibling. The live half was validated above and cannot fail twice.\n assertFieldMap({ ...fields, [key]: removed.field }, slug, \"removedFields\")\n }\n }\n\n if (titleField !== undefined && !(titleField in fields)) {\n throw new SchemaError(\n `Content type \"${slug}\" names \"${titleField}\" as its titleField, but has no such field.`,\n )\n }\n\n if (defaultSort !== undefined && !(defaultSort.field in fields)) {\n throw new SchemaError(\n `Content type \"${slug}\" sorts by \"${defaultSort.field}\", but has no such field.`,\n )\n }\n\n // The matrix is stored on the content type and copied onto `content/{slug}`, where the\n // security rules read it. A malformed one would be read by a rule as a list that never\n // matches, which denies without ever saying why, so it is refused at the write instead.\n assertValidPermissionMatrix(slug, definition.permissions)\n\n // A singleton has no list view, so list affordances would be dead configuration.\n if (kind === \"singleton\" && defaultSort !== undefined) {\n throw new SchemaError(\n `Content type \"${slug}\" is a singleton and cannot declare a defaultSort. A singleton has exactly one entry and no list view.`,\n )\n }\n}\n","/**\n * Moving one item of a list, as a pure function.\n *\n * It lives in core rather than beside either of its callers because both of them reorder\n * for the same reason and must behave identically: the repeater field moves a row, and the\n * Schema Builder moves a field. A drag and an arrow key are two ways to call this, never\n * two implementations of it.\n */\n\n/**\n * Returns a new list with the item at `from` placed at `to`.\n *\n * An out-of-range index returns the list unchanged rather than throwing. Every caller is an\n * event handler (the last row pressing ArrowDown, a drop outside the list), and none of\n * them has anything useful to do with an exception.\n */\nexport function moveItem<TItem>(\n items: readonly TItem[],\n from: number,\n to: number,\n): TItem[] {\n const next = [...items]\n if (from === to) return next\n if (from < 0 || from >= next.length || to < 0 || to >= next.length) return next\n\n const [moved] = next.splice(from, 1)\n if (moved === undefined) return [...items]\n next.splice(to, 0, moved)\n return next\n}\n","import type {\n ContentTypeLike,\n RemovedField,\n RemovedFieldMap,\n} from \"../types/content-type.js\"\nimport type { FieldDefinition, FieldMap } from \"../types/field.js\"\n\nimport { assertValidContentType } from \"./define-content-type.js\"\nimport { SchemaError } from \"./errors.js\"\n\n/**\n * Adding, removing, re-adding and purging one field of a database-defined content type.\n *\n * The rule the whole file exists for: **removing a field never destroys its values.** The\n * definition moves from `fields` to `removedFields` and the stored values stay on every\n * entry until somebody explicitly purges them. Two properties elsewhere are what make that\n * work, and both are asserted by tests rather than assumed:\n *\n * - `schema/validate.ts` only validates keys the schema declares, so a value left behind by\n * a removed field cannot make an entry unsaveable.\n * - `firebase/converters.ts#valuesToStored` carries keys it does not recognise through\n * untouched, so saving an entry after a removal rewrites the declared fields and leaves\n * the parked one exactly where it was.\n *\n * Every function here is pure and returns a new content type. Nothing writes.\n */\n\nexport interface RemovalContext {\n /** uid recorded on the parked definition. */\n removedBy: string\n /** ISO 8601. Injected so a test and a migration can both be deterministic. */\n removedAt?: string\n}\n\n/** What a key currently is on a content type. Drives what the field editor may offer. */\nexport type FieldKeyState = \"free\" | \"live\" | \"removed\"\n\nexport function fieldKeyState(type: ContentTypeLike, key: string): FieldKeyState {\n if (key in type.fields) return \"live\"\n if (type.removedFields !== undefined && key in type.removedFields) return \"removed\"\n return \"free\"\n}\n\nexport function removedFieldEntries(\n type: ContentTypeLike,\n): readonly (RemovedField & { key: string })[] {\n return Object.entries(type.removedFields ?? {})\n .map(([key, removed]) => ({ key, ...removed }))\n .sort((left, right) => left.key.localeCompare(right.key))\n}\n\nfunction withoutKey<TValue>(\n map: { readonly [key: string]: TValue },\n key: string,\n): { [key: string]: TValue } {\n const next: { [key: string]: TValue } = {}\n for (const [existing, value] of Object.entries(map)) {\n if (existing !== key) next[existing] = value\n }\n return next\n}\n\n/**\n * Rebuilds a content type with new field maps, dropping `removedFields` when it is empty.\n *\n * An empty map is deleted rather than stored, so a type that has never lost a field and a\n * type whose last removal was purged look identical. Otherwise every stored document would\n * accumulate an empty object that means nothing.\n */\nfunction rebuild(\n type: ContentTypeLike,\n fields: FieldMap,\n removedFields: RemovedFieldMap,\n): ContentTypeLike {\n const { removedFields: _dropped, ...rest } = type\n const next: ContentTypeLike = {\n ...rest,\n fields,\n ...(Object.keys(removedFields).length > 0 ? { removedFields } : {}),\n }\n\n assertValidContentType(next)\n return next\n}\n\n/**\n * Removes a field and parks its definition.\n *\n * Refuses to remove the last field, because a content type with no fields is invalid, and\n * refuses to remove the field the type names as its title or its default sort: a list view\n * that sorts by a field nobody can edit any more is a broken screen, and pointing the type\n * elsewhere silently would be a change the editor did not ask for. Repoint the type first.\n */\nexport function removeField(\n type: ContentTypeLike,\n key: string,\n context: RemovalContext,\n): ContentTypeLike {\n const field = type.fields[key]\n\n if (!field) {\n throw new SchemaError(\n fieldKeyState(type, key) === \"removed\"\n ? `Field \"${key}\" of content type \"${type.slug}\" is already removed.`\n : `Content type \"${type.slug}\" has no field \"${key}\".`,\n )\n }\n\n if (Object.keys(type.fields).length === 1) {\n throw new SchemaError(\n `Field \"${key}\" is the only field of content type \"${type.slug}\". A content type must keep at least one field; delete the type instead.`,\n )\n }\n\n if (type.titleField === key) {\n throw new SchemaError(\n `Field \"${key}\" is the title field of content type \"${type.slug}\". Choose another title field before removing it.`,\n )\n }\n\n if (type.defaultSort?.field === key) {\n throw new SchemaError(\n `Field \"${key}\" is the default sort of content type \"${type.slug}\". Choose another sort before removing it.`,\n )\n }\n\n const removed: RemovedField = {\n field,\n removedAt: context.removedAt ?? new Date().toISOString(),\n removedBy: context.removedBy,\n }\n\n return rebuild(type, withoutKey(type.fields, key), {\n ...(type.removedFields ?? {}),\n [key]: removed,\n })\n}\n\n/** Adds a field. Rejects a key that is live, and routes a removed key to `restoreField`. */\nexport function addField(\n type: ContentTypeLike,\n key: string,\n field: FieldDefinition,\n): ContentTypeLike {\n const state = fieldKeyState(type, key)\n\n if (state === \"live\") {\n throw new SchemaError(`Content type \"${type.slug}\" already has a field \"${key}\".`)\n }\n\n if (state === \"removed\") {\n throw new SchemaError(\n `Field \"${key}\" of content type \"${type.slug}\" was removed and its values are still stored. Restore it to get those values back, or purge them first.`,\n )\n }\n\n return rebuild(type, { ...type.fields, [key]: field }, type.removedFields ?? {})\n}\n\nexport interface RestoreOptions {\n /**\n * A definition to restore under, instead of the one that was parked.\n *\n * Only accepted when it stores values the same way, which in practice means the same\n * `type` and the same cardinality. Restoring a `text` key as a `number` would leave every\n * preserved value the wrong shape, and the entry would fail validation the next time\n * anyone opened it, on data they never touched. Purge first, then add it fresh.\n */\n field?: FieldDefinition\n}\n\n/**\n * Re-adds a removed key, and with it the values that were preserved.\n *\n * This is the whole point of parking the definition rather than deleting it: the values\n * were never dropped, so declaring the key again makes them readable exactly as they were.\n * Nothing is written to any entry.\n */\nexport function restoreField(\n type: ContentTypeLike,\n key: string,\n options: RestoreOptions = {},\n): ContentTypeLike {\n const removed = type.removedFields?.[key]\n\n if (!removed) {\n throw new SchemaError(`Content type \"${type.slug}\" has no removed field \"${key}\".`)\n }\n\n const field = options.field ?? removed.field\n\n if (!storesTheSameWay(removed.field, field)) {\n throw new SchemaError(\n `Field \"${key}\" of content type \"${type.slug}\" was removed as \"${removed.field.type}\" and cannot be restored as \"${field.type}\": the preserved values are stored in the old shape. Purge the values first, then add the field fresh.`,\n )\n }\n\n return rebuild(\n type,\n { ...type.fields, [key]: field },\n withoutKey(type.removedFields ?? {}, key),\n )\n}\n\n/**\n * Drops the parked definition, after the values have been purged from the entries.\n *\n * The definition side of a purge only. The data side is `CmsAdapter.fieldData.purge`, and\n * the adapter runs both in that order: values first, then this, so an interrupted purge\n * leaves the field still listed as removed with some values gone, which is recoverable,\n * rather than unlisted with values nobody can see, which is not.\n */\nexport function forgetRemovedField(type: ContentTypeLike, key: string): ContentTypeLike {\n if (type.removedFields?.[key] === undefined) {\n throw new SchemaError(`Content type \"${type.slug}\" has no removed field \"${key}\".`)\n }\n\n return rebuild(type, type.fields, withoutKey(type.removedFields, key))\n}\n\n/**\n * Do two definitions put the same shape in Firestore?\n *\n * Deliberately about storage, not about presentation: a label, a description, a\n * placeholder or a validation rule may change freely across a restore, because none of them\n * changes what is already in the document.\n */\nexport function storesTheSameWay(left: FieldDefinition, right: FieldDefinition): boolean {\n return storageSignatureOf(left) === storageSignatureOf(right)\n}\n\n/**\n * The storage-relevant part of one field definition, as a string.\n *\n * What is in it: the type, and every option that changes the stored value. `multiple` and\n * `many` turn a scalar into an array. `to` decides which content type a stored relation id\n * points at. A repeater's nested map is the shape of each stored row. A date's precision\n * decides between `YYYY-MM-DD` and a full instant.\n *\n * What is deliberately not in it: label, description, placeholder, hidden, readonly,\n * validation, select option labels, and the order of the keys. Changing any of those\n * changes the form, not the document, and a version stamp that moved for them would tell a\n * migration runner nothing.\n */\nexport function storageSignatureOf(field: FieldDefinition): string {\n switch (field.type) {\n case \"select\":\n // The option *values* are what a document can hold; their labels are chrome.\n return `select:${field.multiple === true ? \"many\" : \"one\"}:${field.options\n .map((option) => option.value)\n .sort()\n .join(\"|\")}`\n case \"relation\":\n return `relation:${field.to}:${field.many === true ? \"many\" : \"one\"}`\n case \"date\":\n return `date:${field.precision ?? \"date\"}`\n case \"repeater\":\n return `repeater:{${fieldMapSignature(field.fields)}}`\n default:\n return field.type\n }\n}\n\nexport function fieldMapSignature(fields: FieldMap): string {\n return Object.entries(fields)\n .map(([key, field]) => `${key}=${storageSignatureOf(field)}`)\n .sort()\n .join(\",\")\n}\n","import type { FieldTypeRegistry } from \"../schema/field-type.js\"\nimport { RESERVED_FIELD_KEYS } from \"../types/content-type.js\"\nimport type { ContentTypeLike } from \"../types/content-type.js\"\nimport type {\n FieldDefinition,\n FieldMap,\n FieldType,\n ValidationRules,\n} from \"../types/field.js\"\n\nimport { assertValidContentType } from \"./define-content-type.js\"\nimport { SchemaError } from \"./errors.js\"\nimport { moveItem } from \"./reorder.js\"\nimport { fieldKeyState } from \"./schema-fields.js\"\n\n/**\n * The field editor as data: the order fields are shown in, what a new field starts as,\n * whether a key may be used, and which options are still unanswered.\n *\n * Nothing here renders and nothing here writes. The Schema Builder screen calls it to\n * decide what to show and what to enable, and the same functions are callable from a test\n * or a script without a DOM.\n *\n * None of it switches on a field type. The per-type answers come from each field type's own\n * `editor` spec through the registry, which is why adding a thirteenth field type adds it\n * to the Schema Builder with no edit in this file and none in any screen.\n */\n\nexport interface FieldRow {\n key: string\n field: FieldDefinition\n}\n\n/**\n * The field keys of a content type, in display order.\n *\n * `fieldOrder` leads, then any field it does not mention, in map order. Both halves are\n * needed: a stored type's map order is whatever came back from storage, which is not a\n * guarantee to build on, and a `fieldOrder` written before a field was added does not\n * mention that field. An unknown key in `fieldOrder` is skipped rather than trusted, so a\n * stale entry cannot conjure a field.\n */\nexport function orderedFieldKeys(\n type: Pick<ContentTypeLike, \"fields\" | \"fieldOrder\">,\n): readonly string[] {\n const declared: readonly unknown[] = Array.isArray(type.fieldOrder)\n ? type.fieldOrder\n : []\n const ordered: string[] = []\n\n for (const key of declared) {\n if (typeof key === \"string\" && key in type.fields && !ordered.includes(key)) {\n ordered.push(key)\n }\n }\n\n for (const key of Object.keys(type.fields)) {\n if (!ordered.includes(key)) ordered.push(key)\n }\n\n return ordered\n}\n\n/** The fields of a content type as an ordered list, which is what a form renders. */\nexport function orderedFields(\n type: Pick<ContentTypeLike, \"fields\" | \"fieldOrder\">,\n): readonly FieldRow[] {\n const rows: FieldRow[] = []\n\n for (const key of orderedFieldKeys(type)) {\n const field = type.fields[key]\n if (field !== undefined) rows.push({ key, field })\n }\n\n return rows\n}\n\n/** Moves one field. An out-of-range index is a no-op; see `moveItem`. */\nexport function moveFieldRow(\n rows: readonly FieldRow[],\n from: number,\n to: number,\n): FieldRow[] {\n return moveItem(rows, from, to)\n}\n\n/**\n * Rebuilds a content type from an ordered list of fields.\n *\n * Writes both halves: the map, because that is what every consumer reads, and `fieldOrder`,\n * because a map's key order carries no promise across a round trip. Validated here, so the\n * editor fails on the form rather than on the round trip.\n */\nexport function withFieldRows(\n type: ContentTypeLike,\n rows: readonly FieldRow[],\n): ContentTypeLike {\n const seen = new Set<string>()\n const fields: { [key: string]: FieldDefinition } = {}\n\n for (const row of rows) {\n if (seen.has(row.key)) {\n throw new SchemaError(\n `Content type \"${type.slug}\" would have two fields called \"${row.key}\".`,\n )\n }\n seen.add(row.key)\n fields[row.key] = row.field\n }\n\n const next: ContentTypeLike = {\n ...type,\n fields,\n fieldOrder: rows.map((row) => row.key),\n }\n\n assertValidContentType(next)\n return next\n}\n\n/**\n * Deep equality for two stored definitions, independent of key order.\n *\n * `JSON.stringify` is not enough on its own, and the reason is the same one `fieldOrder`\n * exists for: a field map is an object, the editor rebuilds it in display order, and the\n * stored copy is in whatever order it came back in. Comparing the two literally would\n * report a difference after a load that reordered nothing, and leave the Save button\n * enabled on a draft nobody has touched.\n *\n * Arrays keep their order, which is what makes a reorder, an option list and a\n * `fieldOrder` change all register as real differences.\n */\nexport function sameDefinition(left: ContentTypeLike, right: ContentTypeLike): boolean {\n return canonical(left) === canonical(right)\n}\n\nfunction canonical(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(canonical).join(\",\")}]`\n\n if (typeof value === \"object\" && value !== null) {\n return `{${Object.entries(value)\n .filter(([, member]) => member !== undefined)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, member]) => `${JSON.stringify(key)}:${canonical(member)}`)\n .join(\",\")}}`\n }\n\n return JSON.stringify(value) ?? \"null\"\n}\n\n/** A field key becomes a TypeScript property and a Firestore field name. */\nconst FIELD_KEY_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/\n\nexport type FieldKeyRejection = \"invalid\" | \"reserved\" | \"live\" | \"removed\"\n\nexport interface FieldKeyAvailability {\n available: boolean\n reason?: FieldKeyRejection\n /** Ready to print, and it names what is in the way. */\n message?: string\n}\n\nconst KEY_AVAILABLE: FieldKeyAvailability = { available: true }\n\n/**\n * May this content type take this field key?\n *\n * The removed case is the one that matters. A key whose values are still stored is not\n * free, and saying only \"already used\" would send an editor looking for a field that is not\n * on the screen; the message points at the restore instead.\n */\nexport function checkFieldKey(type: ContentTypeLike, key: string): FieldKeyAvailability {\n if (!FIELD_KEY_PATTERN.test(key)) {\n return {\n available: false,\n reason: \"invalid\",\n message: `\"${key}\" is not a valid field key. Use letters, digits and underscores, starting with a letter, for example \"jobTitle\".`,\n }\n }\n\n if ((RESERVED_FIELD_KEYS as readonly string[]).includes(key)) {\n return {\n available: false,\n reason: \"reserved\",\n message: `\"${key}\" is reserved for entry metadata. Reserved keys: ${RESERVED_FIELD_KEYS.join(\", \")}.`,\n }\n }\n\n const state = fieldKeyState(type, key)\n\n if (state === \"live\") {\n return {\n available: false,\n reason: \"live\",\n message: `\"${key}\" is already a field of this content type.`,\n }\n }\n\n if (state === \"removed\") {\n return {\n available: false,\n reason: \"removed\",\n message: `\"${key}\" was removed and its values are still stored. Restore it to get those values back, or purge them first.`,\n }\n }\n\n return KEY_AVAILABLE\n}\n\n/**\n * The same question one level down, inside a repeater's nested map.\n *\n * Reserved keys are not checked here, and deliberately so: `status` is entry metadata at\n * the top level and an ordinary key inside a row, and the validator agrees. Nothing is\n * parked at this level either, because `removedFields` describes top-level keys only.\n */\nexport function checkNestedFieldKey(fields: FieldMap, key: string): FieldKeyAvailability {\n if (!FIELD_KEY_PATTERN.test(key)) {\n return {\n available: false,\n reason: \"invalid\",\n message: `\"${key}\" is not a valid field key. Use letters, digits and underscores, starting with a letter.`,\n }\n }\n\n return key in fields\n ? { available: false, reason: \"live\", message: `\"${key}\" is already a field here.` }\n : KEY_AVAILABLE\n}\n\n/**\n * A field key suggested from a label, so an editor types \"Job title\" and gets \"jobTitle\".\n *\n * A suggestion only: the editor can overwrite it, and `checkFieldKey` answers whether what\n * ends up in the box is usable. A label with nothing usable in it yields an empty string\n * rather than a made-up key, and the form then asks for one.\n */\nexport function suggestFieldKey(label: string): string {\n const words = label\n .normalize(\"NFKD\")\n .replace(/[^a-zA-Z0-9]+/g, \" \")\n .trim()\n .split(/\\s+/)\n .filter((word) => word.length > 0)\n\n const [first, ...rest] = words\n if (first === undefined) return \"\"\n\n const key =\n first.toLowerCase() +\n rest\n .map((word) => `${(word[0] ?? \"\").toUpperCase()}${word.slice(1).toLowerCase()}`)\n .join(\"\")\n\n // A key may not start with a digit, and prefixing rather than dropping keeps \"2024 note\"\n // distinguishable from \"note\".\n return /^[0-9]/.test(key) ? `f${key}` : key\n}\n\n/**\n * What a newly added field of this type starts as.\n *\n * The per-type part comes from the field type's own `editor.defaults`, so a select starts\n * with one option and a repeater with one nested field without this function knowing that\n * either of them exists. An unregistered type is refused rather than guessed at.\n */\nexport function newFieldDefinition(\n registry: FieldTypeRegistry,\n type: FieldType,\n label: string,\n): FieldDefinition {\n const spec = registry.require(type)\n return { ...spec.editor.defaults, type, label } as FieldDefinition\n}\n\nexport interface FieldOptionIssue {\n /** The option key the issue belongs to, so the control can show it. */\n option: string\n message: string\n}\n\n/** Is this option value empty, whatever shape the option happens to have? */\nfunction isBlank(value: unknown): boolean {\n if (value === undefined || value === null) return true\n if (typeof value === \"string\") return value.trim() === \"\"\n if (Array.isArray(value)) return value.length === 0\n if (typeof value === \"object\") return Object.keys(value).length === 0\n return false\n}\n\n/**\n * The options of one field that are still unanswered, named by option.\n *\n * Generic: a descriptor marked `required` whose value is empty is an issue, and that is the\n * whole rule. A relation with no target and a select with no options are both reported by\n * it, and a field type added later gets the same treatment from its own descriptors.\n */\nexport function fieldOptionIssues(\n registry: FieldTypeRegistry,\n field: FieldDefinition,\n): readonly FieldOptionIssue[] {\n const spec = registry.get(field.type)\n if (spec === undefined) return []\n\n const values = field as unknown as Record<string, unknown>\n\n return spec.editor.options\n .filter((option) => option.required === true && isBlank(values[option.key]))\n .map((option) => ({\n option: option.key,\n message: `${option.label} is required for a ${field.type} field.`,\n }))\n}\n\n/** Every unanswered option across a whole draft, each carrying the field it belongs to. */\nexport function draftIssues(\n registry: FieldTypeRegistry,\n rows: readonly FieldRow[],\n): readonly (FieldOptionIssue & { key: string })[] {\n return rows.flatMap((row) =>\n fieldOptionIssues(registry, row.field).map((issue) => ({ key: row.key, ...issue })),\n )\n}\n\nexport type ValidationRuleName = keyof ValidationRules\n\nexport interface ValidationRuleControl {\n label: string\n control: \"boolean\" | \"number\" | \"text\"\n help: string\n}\n\n/**\n * How each shared validation rule is edited, and what it means.\n *\n * Keyed by the rule rather than by the field type: `maxLength` is the same rule and the\n * same control wherever it is offered. Which of them a given field type offers is that\n * field type's own answer, on `editor.rules`.\n */\nexport const VALIDATION_RULE_CONTROLS: {\n readonly [TRule in ValidationRuleName]: ValidationRuleControl\n} = {\n required: {\n label: \"Required\",\n control: \"boolean\",\n help: \"An entry cannot be saved while this field is empty.\",\n },\n minLength: {\n label: \"Minimum length\",\n control: \"number\",\n help: \"Fewest characters allowed.\",\n },\n maxLength: {\n label: \"Maximum length\",\n control: \"number\",\n help: \"Most characters allowed.\",\n },\n min: { label: \"Minimum\", control: \"number\", help: \"Smallest value allowed.\" },\n max: { label: \"Maximum\", control: \"number\", help: \"Largest value allowed.\" },\n pattern: {\n label: \"Pattern\",\n control: \"text\",\n help: \"A regular expression the value must match.\",\n },\n unique: {\n label: \"Unique\",\n control: \"boolean\",\n help: \"No other entry of this content type may hold the same value.\",\n },\n}\n\n/** Sets or clears one rule, dropping `validation` entirely once nothing is left in it. */\nexport function withValidationRule(\n field: FieldDefinition,\n rule: ValidationRuleName,\n value: string | number | boolean | undefined,\n): FieldDefinition {\n const { validation, ...rest } = field\n const next: { [key: string]: unknown } = { ...validation }\n\n // An off switch and an empty box both mean \"no rule\". Storing `false` or `\"\"` would\n // leave a rule in the document that reads as configured and does nothing.\n if (value === undefined || value === \"\" || value === false) {\n delete next[rule]\n } else {\n next[rule] = value\n }\n\n return (Object.keys(next).length === 0\n ? rest\n : { ...rest, validation: next }) as unknown as FieldDefinition\n}\n\n/** Sets or clears one per-type option, dropping the key when the value is empty. */\nexport function withFieldOption(\n field: FieldDefinition,\n option: string,\n value: unknown,\n): FieldDefinition {\n const next: { [key: string]: unknown } = { ...field }\n\n if (value === undefined || value === \"\") {\n delete next[option]\n } else {\n next[option] = value\n }\n\n return next as unknown as FieldDefinition\n}\n","import type { EntryFilter, ListQuery, SortSpec } from \"./adapter.js\"\nimport { normalizeLimit } from \"./adapter.js\"\nimport type { ContentTypeLike } from \"../types/content-type.js\"\nimport type { EntryStatus } from \"../types/entry.js\"\nimport type { FieldDefinition, FieldType } from \"../types/field.js\"\n\nimport { orderedFields } from \"./schema-editor.js\"\n\n/**\n * What a collection list is, derived from a content type.\n *\n * The screen renders this; it never decides it. Columns, the sortable set, the filter\n * controls and the query that reads a page are all computed here from the schema, which is\n * what makes a new content type a data change and not a screen change.\n *\n * Nothing in this file imports React, Firebase or the field registry, so it is domain\n * logic: it runs in the node test project, in the SDK, and in a server component.\n */\n\n/** How a column's cells are typeset. The cell itself never inspects the field type. */\nexport type ColumnAlign = \"text\" | \"numeric\" | \"date\"\n\n/**\n * What a field type contributes to a table.\n *\n * `Record<FieldType, ...>` on purpose: adding a thirteenth field type fails to typecheck\n * until somebody decides whether it fits in a table cell. This is the one place that\n * decision lives, the same way `fieldTypes` is the one place a field type is registered.\n * `\"none\"` means the value cannot be reduced to one readable line, so it gets no column:\n * a rich text document, an uploaded file, a repeater of rows.\n */\nconst COLUMN_ALIGN: Record<FieldType, ColumnAlign | \"none\"> = {\n text: \"text\",\n textarea: \"none\",\n number: \"numeric\",\n boolean: \"text\",\n select: \"text\",\n date: \"date\",\n slug: \"text\",\n richtext: \"none\",\n image: \"none\",\n file: \"none\",\n relation: \"none\",\n repeater: \"none\",\n}\n\n/**\n * What a field type can be filtered by.\n *\n * \"Simple\" means a closed set of values the schema already names, matched by equality.\n * `select` carries its options, and `boolean` has exactly two; both produce a filter\n * control with no free text and a query Firestore answers from one index. Everything else\n * is excluded and the reasons differ: a `text`, `slug` or `richtext` value is open-ended,\n * so equality on it is useless and substring matching is not on offer (see `search`);\n * `number` and `date` want ranges, which need an interval control and a second index axis;\n * `image`, `file` and `relation` are ids, which a reader cannot pick from a dropdown; a\n * `repeater` has no single value at all.\n */\nconst FILTERABLE: readonly FieldType[] = [\"select\", \"boolean\"]\n\nexport type ColumnKind = \"title\" | \"field\" | \"status\" | \"updated\"\n\nexport interface ListColumn {\n /** Field key, or `status` / `updatedAt` for the two metadata columns. */\n key: string\n label: string\n kind: ColumnKind\n align: ColumnAlign\n /**\n * Whether the header offers sorting. Bounded on purpose: every sortable column costs a\n * pair of composite indexes per filter combination, so the list sorts by title, by the\n * type's declared default sort field, and by last update, and not by every column it\n * shows. See `sortableFieldKeys` and core/indexes.ts.\n */\n sortable: boolean\n}\n\nexport interface ListFilterOption {\n value: string\n label: string\n}\n\nexport interface ListFilterDescriptor {\n /** Field key the filter applies to. */\n key: string\n label: string\n options: readonly ListFilterOption[]\n /**\n * `array-contains` for a multi-select, whose stored value is an array; `==` otherwise.\n * The screen passes this straight through, so it never decides an operator.\n */\n op: EntryFilter[\"op\"]\n /** Filter values are strings in the UI; a boolean field converts back on the way out. */\n valueType: \"string\" | \"boolean\"\n}\n\n/** Everything the reader has narrowed the list to, as one serializable value. */\nexport interface ListViewState {\n /** Prefix term for the title field. Empty means no search. */\n search: string\n status: EntryStatus | \"any\"\n /** Field key to selected option value. A key absent means that filter is off. */\n filters: Readonly<Record<string, string>>\n sort: SortSpec\n /** Opaque, from a previous page. The UI stores it and never builds one. */\n cursor: string | null\n}\n\n/** Last touched first: what an editor who just saved something expects to see at the top. */\nexport const FALLBACK_SORT: SortSpec = { field: \"updatedAt\", direction: \"desc\" }\n\nexport function defaultListSort(type: ContentTypeLike): SortSpec {\n return type.defaultSort === undefined\n ? FALLBACK_SORT\n : { field: type.defaultSort.field, direction: type.defaultSort.direction }\n}\n\nexport function initialListState(type: ContentTypeLike): ListViewState {\n return {\n search: \"\",\n status: \"any\",\n filters: {},\n sort: defaultListSort(type),\n cursor: null,\n }\n}\n\n/** A content type can only be searched when it names the field to match against. */\nexport function canSearch(type: ContentTypeLike): boolean {\n return type.titleField !== undefined\n}\n\n/** True while a term is narrowing the list, which is also when sorting is not on offer. */\nexport function isSearching(state: ListViewState): boolean {\n return state.search.trim() !== \"\"\n}\n\n/**\n * The keys a list may sort by: the title, the type's own default sort field, and the last\n * update. Kept small deliberately; see `ListColumn.sortable`.\n */\nexport function sortableFieldKeys(type: ContentTypeLike): readonly string[] {\n const keys = new Set<string>()\n if (type.titleField !== undefined) keys.add(type.titleField)\n if (type.defaultSort !== undefined) keys.add(type.defaultSort.field)\n keys.add(\"updatedAt\")\n return [...keys]\n}\n\n/** How many schema fields get their own column before the row would stop being readable. */\nexport const MAX_FIELD_COLUMNS = 2\n\nexport interface ListColumnOptions {\n maxFieldColumns?: number\n}\n\n/**\n * The columns, in reading order: title, up to two field columns, status, updated.\n *\n * Hidden fields are skipped because the form does not show them either, and the title\n * field is not repeated as a field column. A type with no `titleField` still gets a title\n * column: `entryTitle` names the entry \"Untitled\" and the row remains clickable, which is\n * better than a list whose rows have no handle at all.\n */\nexport function listColumns(\n type: ContentTypeLike,\n { maxFieldColumns = MAX_FIELD_COLUMNS }: ListColumnOptions = {},\n): readonly ListColumn[] {\n const sortable = new Set(sortableFieldKeys(type))\n const titleKey = type.titleField\n const titleField = titleKey === undefined ? undefined : type.fields[titleKey]\n\n const columns: ListColumn[] = [\n {\n key: titleKey ?? \"title\",\n label: titleField?.label ?? \"Title\",\n kind: \"title\",\n align: \"text\",\n sortable: titleKey !== undefined && sortable.has(titleKey),\n },\n ]\n\n for (const { key, field } of orderedFields(type)) {\n if (columns.length > maxFieldColumns) break\n if (key === titleKey || field.hidden === true) continue\n\n const align = COLUMN_ALIGN[field.type]\n if (align === \"none\") continue\n\n columns.push({\n key,\n label: field.label,\n kind: \"field\",\n align,\n sortable: sortable.has(key),\n })\n }\n\n columns.push(\n { key: \"status\", label: \"Status\", kind: \"status\", align: \"text\", sortable: false },\n {\n key: \"updatedAt\",\n label: \"Updated\",\n kind: \"updated\",\n align: \"date\",\n sortable: true,\n },\n )\n\n return columns\n}\n\n/** Whether a field definition can back a filter control. */\nexport function isFilterableField(field: FieldDefinition): boolean {\n return FILTERABLE.includes(field.type)\n}\n\n/**\n * The field filters a content type offers, in schema order.\n *\n * Status is not among them: it is entry metadata rather than a field, every content type\n * has it, and the adapter takes it as its own argument.\n */\nexport function listFilters(type: ContentTypeLike): readonly ListFilterDescriptor[] {\n const descriptors: ListFilterDescriptor[] = []\n\n for (const { key, field } of orderedFields(type)) {\n if (field.hidden === true || !isFilterableField(field)) continue\n\n if (field.type === \"select\") {\n descriptors.push({\n key,\n label: field.label,\n options: field.options.map((option) => ({\n value: option.value,\n label: option.label,\n })),\n // A multi-select stores an array, so equality would only match an entry whose\n // whole array is that one value.\n op: field.multiple === true ? \"array-contains\" : \"==\",\n valueType: \"string\",\n })\n continue\n }\n\n descriptors.push({\n key,\n label: field.label,\n options: [\n { value: \"true\", label: \"Yes\" },\n { value: \"false\", label: \"No\" },\n ],\n op: \"==\",\n valueType: \"boolean\",\n })\n }\n\n return descriptors\n}\n\n/**\n * The active filters as adapter filters.\n *\n * A stored value the schema no longer offers is dropped rather than sent: a filter for a\n * select option that was removed from the content type would return nothing and read as\n * \"there are no entries\".\n */\nexport function listFilterQuery(\n type: ContentTypeLike,\n filters: Readonly<Record<string, string>>,\n): readonly EntryFilter[] {\n const active: EntryFilter[] = []\n\n for (const descriptor of listFilters(type)) {\n const chosen = filters[descriptor.key]\n if (chosen === undefined || chosen === \"\") continue\n if (!descriptor.options.some((option) => option.value === chosen)) continue\n\n active.push({\n field: descriptor.key,\n op: descriptor.op,\n value: descriptor.valueType === \"boolean\" ? chosen === \"true\" : chosen,\n })\n }\n\n return active\n}\n\nexport interface BuildListQueryOptions {\n pageSize?: number\n}\n\n/**\n * The read for one page.\n *\n * The sort is omitted while a search is active rather than sent and ignored: the adapter\n * forces title order for a prefix range, and a query object that still claimed another\n * order would be a lie the caller could act on.\n */\nexport function buildListQuery(\n type: ContentTypeLike,\n state: ListViewState,\n { pageSize }: BuildListQueryOptions = {},\n): ListQuery {\n const term = state.search.trim()\n const searching = term !== \"\" && canSearch(type)\n\n return {\n filters: listFilterQuery(type, state.filters),\n ...(searching ? { search: term } : { sort: state.sort }),\n limit: normalizeLimit(pageSize),\n cursor: state.cursor,\n status: state.status,\n }\n}\n\n/** The same narrowing as a count: no order, no cursor, no page size. */\nexport function buildCountQuery(\n type: ContentTypeLike,\n state: ListViewState,\n): Pick<ListQuery, \"filters\" | \"status\" | \"search\"> {\n const term = state.search.trim()\n\n return {\n filters: listFilterQuery(type, state.filters),\n status: state.status,\n ...(term !== \"\" && canSearch(type) ? { search: term } : {}),\n }\n}\n\n/** Whether anything is narrowing the list, which is what tells an empty result apart. */\nexport function isNarrowed(state: ListViewState): boolean {\n return (\n isSearching(state) ||\n state.status !== \"any\" ||\n Object.values(state.filters).some((value) => value !== \"\")\n )\n}\n\n/**\n * The next sort after a header is clicked.\n *\n * Clicking the sorted column flips it. Clicking another column starts in the direction\n * that column is usually read in: newest first for a date, A to Z for everything else.\n */\nexport function nextSort(\n current: SortSpec,\n column: ListColumn,\n key = column.key,\n): SortSpec {\n if (current.field === key) {\n return { field: key, direction: current.direction === \"asc\" ? \"desc\" : \"asc\" }\n }\n return { field: key, direction: column.align === \"date\" ? \"desc\" : \"asc\" }\n}\n","import type { ContentTypeInputValues, ContentTypeValues } from \"./content-type.js\"\nimport type { FieldMap } from \"./field.js\"\n\nexport const ENTRY_STATUSES = [\"draft\", \"published\", \"archived\"] as const\n\nexport type EntryStatus = (typeof ENTRY_STATUSES)[number]\n\n/**\n * Everything the adapter owns on an entry. Written on every mutation, never by a form.\n * Timestamps are ISO 8601 strings at this boundary; the Firestore converter turns them\n * into Timestamps on the way in and back on the way out.\n */\nexport interface EntryMeta {\n id: string\n status: EntryStatus\n createdAt: string\n createdBy: string\n updatedAt: string\n updatedBy: string\n publishedAt: string | null\n schemaVersion: number\n}\n\n/** What a read returns: the metadata plus the typed field values. */\nexport type Entry<TType extends AnyContentTypeShape = AnyContentTypeShape> = EntryMeta &\n ContentTypeValues<TType>\n\n/** What a write accepts: required field values, optional ones omittable, no metadata. */\nexport type EntryInput<TType extends AnyContentTypeShape = AnyContentTypeShape> =\n ContentTypeInputValues<TType> & {\n status?: EntryStatus\n }\n\n/**\n * Structural stand-in for `ContentType<TFields>`. `ContentType` is invariant in its field\n * map (it uses `keyof TFields` for titleField and defaultSort), so a concrete content type\n * is not assignable to `ContentType<FieldMap>` and cannot be used as a constraint here.\n */\nexport type AnyContentTypeShape = { fields: FieldMap }\n\nexport interface FieldError {\n /** Dotted path, so a repeater reports `blocks.2.title` rather than `blocks`. */\n path: string\n rule: string\n message: string\n}\n","\"use client\"\n\nimport { useCallback, useEffect, useMemo, useState } from \"react\"\n\nimport type { CmsAdapter, Page } from \"../../core/adapter.js\"\nimport { DEFAULT_PAGE_SIZE } from \"../../core/adapter.js\"\nimport { entryTitle } from \"../../core/entry-title.js\"\nimport {\n buildCountQuery,\n buildListQuery,\n canSearch,\n initialListState,\n isNarrowed,\n isSearching,\n listColumns,\n listFilters,\n nextSort,\n} from \"../../core/list-view.js\"\nimport type {\n ListColumn,\n ListFilterDescriptor,\n ListViewState,\n} from \"../../core/list-view.js\"\nimport { can } from \"../../permissions/can.js\"\nimport { classifyError } from \"../../core/error-taxonomy.js\"\nimport type { ClassifiedError } from \"../../core/error-taxonomy.js\"\nimport type { AuthUser } from \"../../types/auth.js\"\nimport type { ContentTypeLike } from \"../../types/content-type.js\"\nimport type { Entry, EntryStatus } from \"../../types/entry.js\"\nimport { ENTRY_STATUSES } from \"../../types/entry.js\"\nimport { Badge, ENTRY_STATUS_LABEL, ENTRY_STATUS_VARIANT } from \"../components/badge.js\"\nimport { Button } from \"../components/button.js\"\nimport { Checkbox } from \"../components/checkbox.js\"\nimport { EmptyState } from \"../components/empty-state.js\"\nimport { Menu } from \"../components/menu.js\"\nimport type { MenuEntry } from \"../components/menu.js\"\nimport { PageHeader } from \"../components/page-header.js\"\nimport { Pagination } from \"../components/pagination.js\"\nimport { Panel } from \"../components/panel.js\"\nimport { SearchInput } from \"../components/search-input.js\"\nimport { Skeleton } from \"../components/skeleton.js\"\nimport {\n Table,\n TableBody,\n TableCell,\n TableEmptyRow,\n TableHead,\n TableHeaderCell,\n TableRow,\n} from \"../components/table.js\"\nimport { formatCellValue, formatDateTime } from \"../format.js\"\nimport { contentTypeLabel } from \"../navigation/navigation.js\"\n\n/**\n * The collection list, generated from the content type.\n *\n * Columns, sortable headers, filter controls and the query behind them all come from\n * `core/list-view.ts`, which reads the schema. This file names no content type and no\n * field: adding a content type adds a list, and nothing here changes.\n *\n * Three things it is deliberately explicit about, because each of them is a place where a\n * list view can quietly lie to its reader:\n *\n * - The search matches the start of the title and is case sensitive. The caption under\n * the toolbar says so, in the interface, not only in a comment.\n * - Selecting everything selects this page, not the collection. The selection bar says\n * how many of what, and paging or refiltering clears it.\n * - Row actions are `can()` answers, per entry. Hiding one is presentation; the adapter\n * and the security rules refuse the same action again.\n */\n\n/** Rows of skeleton while the first read is in flight. */\nconst SKELETON_ROWS = [0, 1, 2, 3, 4]\n\nconst STATUS_ANY = \"any\"\n\n/**\n * How long the search box waits before it queries.\n *\n * Every keystroke would otherwise be a Firestore read and a count, and the reader would\n * page through half-typed terms. Long enough to swallow a word, short enough that the list\n * feels tied to the box.\n */\nconst SEARCH_DEBOUNCE_MS = 250\n\nexport interface CollectionListProps {\n adapter: CmsAdapter\n type: ContentTypeLike\n /** The signed-in user, for the permission answers behind the actions. */\n user: AuthUser\n /** Opens an entry. Absent means the list is read-only in this host. */\n onOpen?: (entryId: string) => void\n /** Starts a new entry. Shown only when `can()` allows creating one. */\n onCreate?: () => void\n /**\n * Deletes entries. The list never deletes anything itself: it collects the selection,\n * checks the permission per entry, and hands the ids to the host's confirmation flow.\n */\n onDelete?: (entryIds: readonly string[]) => void\n /**\n * Re-reads the current page when it changes.\n *\n * A delete happens outside this screen (the confirmation dialog is the host's to mount,\n * because only the host knows where the flow lands), so the list needs a way to be told\n * that what it is showing is stale. A changed token re-runs the same query with the same\n * cursor, which is the honest refresh: remounting would silently drop the reader's\n * search, filters and page.\n */\n refreshToken?: unknown\n pageSize?: number\n}\n\ntype ListState =\n | { status: \"loading\" }\n | { status: \"ready\"; page: Page<Entry>; total: number | null }\n | { status: \"error\"; error: ClassifiedError }\n\nexport function CollectionList({\n adapter,\n type,\n user,\n onOpen,\n onCreate,\n onDelete,\n refreshToken,\n pageSize = DEFAULT_PAGE_SIZE,\n}: CollectionListProps) {\n const [view, setView] = useState<ListViewState>(() => initialListState(type))\n /** One cursor per page visited, `null` for the first. The UI stores, never builds. */\n const [cursors, setCursors] = useState<readonly (string | null)[]>([null])\n const [pageIndex, setPageIndex] = useState(0)\n const [selected, setSelected] = useState<readonly string[]>([])\n const [state, setState] = useState<ListState>({ status: \"loading\" })\n const [attempt, setAttempt] = useState(0)\n /** What is in the box right now, which is ahead of what has been queried. */\n const [draft, setDraft] = useState(\"\")\n\n // A refresh means the rows the reader is looking at are no longer what is stored, so the\n // selection built from them is stale too. Keeping it would let a second bulk action\n // address ids that have already been deleted. Reset during render rather than in an\n // effect, so the stale selection is never painted for a frame.\n const [seenRefresh, setSeenRefresh] = useState(refreshToken)\n if (seenRefresh !== refreshToken) {\n setSeenRefresh(refreshToken)\n setSelected([])\n }\n\n const columns = useMemo(() => listColumns(type), [type])\n const filters = useMemo(() => listFilters(type), [type])\n const searchable = canSearch(type)\n const searching = isSearching(view)\n const narrowed = isNarrowed(view)\n const label = contentTypeLabel(type)\n\n const cursor = cursors[pageIndex] ?? null\n const query = useMemo(\n () => buildListQuery(type, { ...view, cursor }, { pageSize }),\n [type, view, cursor, pageSize],\n )\n const countQuery = useMemo(() => buildCountQuery(type, view), [type, view])\n\n useEffect(() => {\n let cancelled = false\n\n async function read(): Promise<void> {\n const page = await adapter.list(type.slug, query)\n // The total is its own read and its own failure. A list that cannot be counted is\n // still a list; a range that claims a total it never read is not.\n const total = await adapter\n .count(type.slug, countQuery)\n .then((value) => value)\n .catch(() => null)\n\n if (!cancelled) setState({ status: \"ready\", page, total })\n }\n\n read().catch((error: unknown) => {\n if (cancelled) return\n setState({\n status: \"error\",\n error: classifyError(error, {\n role: user.role,\n action: \"read these entries\",\n subject: type.label,\n }),\n })\n })\n\n return () => {\n cancelled = true\n }\n }, [\n adapter,\n type.slug,\n type.label,\n user.role,\n query,\n countQuery,\n attempt,\n refreshToken,\n ])\n\n /**\n * Any change to what is being listed puts the reader back on the first page and drops\n * the selection. Keeping a selection across a filter change would let a bulk action\n * reach entries the reader can no longer see.\n */\n const narrow = useCallback((patch: Partial<ListViewState>) => {\n setView((current) => ({ ...current, ...patch }))\n setCursors([null])\n setPageIndex(0)\n setSelected([])\n setState({ status: \"loading\" })\n }, [])\n\n useEffect(() => {\n if (draft === view.search) return\n const timer = setTimeout(() => narrow({ search: draft }), SEARCH_DEBOUNCE_MS)\n return () => clearTimeout(timer)\n }, [draft, view.search, narrow])\n\n const page = state.status === \"ready\" ? state.page : undefined\n const rows = page?.items ?? []\n const selectable = rows.filter((entry) => canDelete(user, type, entry))\n const allSelected = selected.length > 0 && selected.length === selectable.length\n\n function toggleRow(entryId: string, checked: boolean): void {\n setSelected((current) =>\n checked\n ? current.includes(entryId)\n ? current\n : [...current, entryId]\n : current.filter((id) => id !== entryId),\n )\n }\n\n function togglePage(checked: boolean): void {\n setSelected(checked ? selectable.map((entry) => entry.id) : [])\n }\n\n const from = pageIndex * pageSize + 1\n const to = pageIndex * pageSize + rows.length\n\n return (\n <>\n <PageHeader\n title={label}\n {...(type.description === undefined ? {} : { description: type.description })}\n actions={\n onCreate !== undefined && can(user, \"create\", { type }) ? (\n <Button variant=\"primary\" icon=\"create\" onClick={onCreate}>\n {`New ${type.label}`}\n </Button>\n ) : undefined\n }\n />\n\n <Toolbar\n type={type}\n view={view}\n search={draft}\n onSearch={setDraft}\n filters={filters}\n searchable={searchable}\n narrowed={narrowed}\n onNarrow={narrow}\n />\n\n {selected.length === 0 ? null : (\n <SelectionBar\n count={selected.length}\n pageCount={rows.length}\n label={label}\n onClear={() => setSelected([])}\n {...(onDelete === undefined ? {} : { onDelete: () => onDelete(selected) })}\n />\n )}\n\n <Panel padding=\"none\">\n <Table label={label}>\n <TableHead>\n <TableRow>\n {onDelete === undefined ? null : (\n <TableHeaderCell width=\"selection\">\n <Checkbox\n checked={\n allSelected ? true : selected.length > 0 ? \"indeterminate\" : false\n }\n onChange={togglePage}\n disabled={selectable.length === 0}\n // Named for what it does: this page, not the collection.\n ariaLabel={`Select the ${String(selectable.length)} entries on this page`}\n />\n </TableHeaderCell>\n )}\n {columns.map((column) => (\n <TableHeaderCell\n key={column.key}\n numeric={column.align === \"numeric\"}\n // A prefix search is ordered by title and cannot be reordered, so the\n // headers stop offering something the query will not honour.\n {...(column.sortable && !searching\n ? {\n sort: {\n direction:\n view.sort.field === column.key ? view.sort.direction : null,\n onSort: () => narrow({ sort: nextSort(view.sort, column) }),\n },\n }\n : {})}\n >\n {column.label}\n </TableHeaderCell>\n ))}\n <TableHeaderCell width=\"action\">\n <span className=\"sr-only\">Actions</span>\n </TableHeaderCell>\n </TableRow>\n </TableHead>\n <TableBody>\n <Rows\n state={state}\n columns={columns}\n type={type}\n user={user}\n selected={selected}\n selectable={onDelete !== undefined}\n narrowed={narrowed}\n onToggleRow={toggleRow}\n onRetry={() => {\n setState({ status: \"loading\" })\n setAttempt((value) => value + 1)\n }}\n onClearFilters={() => {\n setDraft(\"\")\n narrow(initialListState(type))\n }}\n {...(onOpen === undefined ? {} : { onOpen })}\n {...(onDelete === undefined ? {} : { onDelete })}\n {...(onCreate !== undefined && can(user, \"create\", { type })\n ? { onCreate }\n : {})}\n />\n </TableBody>\n </Table>\n\n {page === undefined ? null : (\n <Pagination\n from={rows.length === 0 ? 0 : from}\n to={to}\n {...(state.status === \"ready\" && state.total !== null\n ? { total: state.total }\n : {})}\n label={label}\n hasPrevious={pageIndex > 0}\n hasNext={page.hasMore}\n onPrevious={() => {\n setSelected([])\n setState({ status: \"loading\" })\n setPageIndex((index) => Math.max(index - 1, 0))\n }}\n onNext={() => {\n setSelected([])\n setState({ status: \"loading\" })\n setCursors((current) =>\n current.length > pageIndex + 1 ? current : [...current, page.cursor],\n )\n setPageIndex((index) => index + 1)\n }}\n />\n )}\n </Panel>\n </>\n )\n}\n\n/** Whether this user may delete this entry. Ownership is answered against the entry. */\nfunction canDelete(user: AuthUser, type: ContentTypeLike, entry: Entry): boolean {\n return can(user, \"delete\", { type, entry: { createdBy: entry.createdBy } })\n}\n\nfunction canUpdate(user: AuthUser, type: ContentTypeLike, entry: Entry): boolean {\n return can(user, \"update\", { type, entry: { createdBy: entry.createdBy } })\n}\n\ninterface ToolbarProps {\n type: ContentTypeLike\n view: ListViewState\n /** The uncommitted term in the box, which the debounce has not queried yet. */\n search: string\n onSearch: (value: string) => void\n filters: readonly ListFilterDescriptor[]\n searchable: boolean\n narrowed: boolean\n onNarrow: (patch: Partial<ListViewState>) => void\n}\n\n/**\n * Search, status, field filters, and the caption that states what the search can do.\n * Canonical source: .docs/styleguide/03-layout.md section 5.1.\n */\nfunction Toolbar({\n type,\n view,\n search,\n onSearch,\n filters,\n searchable,\n narrowed,\n onNarrow,\n}: ToolbarProps) {\n const captionId = `${type.slug}-search-caption`\n const statusEntries: readonly MenuEntry[] = [\n {\n kind: \"item\",\n id: STATUS_ANY,\n label: \"Any status\",\n selected: view.status === STATUS_ANY,\n },\n ...ENTRY_STATUSES.map((status): MenuEntry => ({\n kind: \"item\",\n id: status,\n label: ENTRY_STATUS_LABEL[status],\n selected: view.status === status,\n })),\n ]\n\n return (\n <div className=\"mb-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <SearchInput\n value={search}\n onChange={onSearch}\n label={`Search ${contentTypeLabel(type)} by title`}\n placeholder={searchable ? \"Title starts with\" : \"Search unavailable\"}\n disabled={!searchable}\n describedBy={captionId}\n />\n\n <Menu\n items={statusEntries}\n onSelect={(id) =>\n onNarrow({ status: id === STATUS_ANY ? \"any\" : (id as EntryStatus) })\n }\n label=\"Filter by status\"\n triggerIcon=\"filter\"\n triggerVariant=\"secondary\"\n triggerLabel={\n view.status === STATUS_ANY\n ? \"Status\"\n : `Status: ${ENTRY_STATUS_LABEL[view.status]}`\n }\n />\n\n {filters.map((filter) => {\n const chosen = view.filters[filter.key]\n const option = filter.options.find((entry) => entry.value === chosen)\n\n return (\n <Menu\n key={filter.key}\n label={`Filter by ${filter.label}`}\n triggerIcon=\"filter\"\n triggerVariant=\"secondary\"\n triggerLabel={\n option === undefined ? filter.label : `${filter.label}: ${option.label}`\n }\n items={[\n {\n kind: \"item\",\n id: \"\",\n label: `Any ${filter.label.toLowerCase()}`,\n selected: option === undefined,\n },\n ...filter.options.map((entry): MenuEntry => ({\n kind: \"item\",\n id: entry.value,\n label: entry.label,\n selected: entry.value === chosen,\n })),\n ]}\n onSelect={(id) =>\n onNarrow({ filters: { ...view.filters, [filter.key]: id } })\n }\n />\n )\n })}\n\n {narrowed ? (\n <Button\n variant=\"ghost\"\n icon=\"close\"\n onClick={() => {\n onSearch(\"\")\n onNarrow(initialListState(type))\n }}\n >\n Clear\n </Button>\n ) : null}\n </div>\n\n <p id={captionId} className=\"mt-2 text-caption text-text-faint\">\n {!searchable\n ? \"This content type names no title field, so its entries cannot be searched.\"\n : isSearching(view)\n ? \"Matching titles that start with your term, case sensitive, ordered by title.\"\n : \"Search matches the start of the title and is case sensitive.\"}\n </p>\n </div>\n )\n}\n\ninterface SelectionBarProps {\n count: number\n pageCount: number\n label: string\n onClear: () => void\n onDelete?: () => void\n}\n\n/**\n * The bulk selection bar.\n * Canonical source: .docs/styleguide/03-layout.md section 5.1, \"Selection bar\".\n *\n * It states the scope rather than assuming the reader infers it: a selection covers the\n * rows on this page, and there is no \"select all 248\" affordance, because a bulk write\n * over a collection nobody has looked at is not an action this admin offers.\n */\nfunction SelectionBar({ count, pageCount, label, onClear, onDelete }: SelectionBarProps) {\n return (\n <div\n role=\"status\"\n className=\"mb-4 flex flex-wrap items-center justify-between gap-3 rounded-sm border border-border-subtle bg-surface-raised px-4 py-3\"\n >\n <p className=\"text-body-sm text-text-secondary\">\n {`${String(count)} of ${String(pageCount)} ${label.toLowerCase()} on this page selected. Selection covers this page only.`}\n </p>\n <div className=\"flex items-center gap-2\">\n <Button variant=\"ghost\" onClick={onClear}>\n Clear selection\n </Button>\n {onDelete === undefined ? null : (\n <Button variant=\"danger\" icon=\"delete\" onClick={onDelete}>\n {`Delete ${String(count)}`}\n </Button>\n )}\n </div>\n </div>\n )\n}\n\ninterface RowsProps {\n state: ListState\n columns: readonly ListColumn[]\n type: ContentTypeLike\n user: AuthUser\n selected: readonly string[]\n selectable: boolean\n narrowed: boolean\n onToggleRow: (entryId: string, checked: boolean) => void\n onRetry: () => void\n onClearFilters: () => void\n onOpen?: (entryId: string) => void\n onDelete?: (entryIds: readonly string[]) => void\n onCreate?: () => void\n}\n\nfunction Rows({\n state,\n columns,\n type,\n user,\n selected,\n selectable,\n narrowed,\n onToggleRow,\n onRetry,\n onClearFilters,\n onOpen,\n onDelete,\n onCreate,\n}: RowsProps) {\n // Selection column plus the generated columns plus the action column.\n const span = columns.length + (selectable ? 2 : 1)\n\n if (state.status === \"loading\") {\n return (\n <>\n {SKELETON_ROWS.map((row) => (\n <TableRow key={row}>\n {selectable ? <TableCell width=\"selection\" /> : null}\n {columns.map((column, index) => (\n <TableCell key={column.key} primary={column.kind === \"title\"}>\n <Skeleton\n line=\"body-sm\"\n className={column.kind === \"title\" ? \"w-48\" : \"w-24\"}\n {...(row === 0 && index === 0 ? { label: \"Loading entries\" } : {})}\n />\n </TableCell>\n ))}\n <TableCell width=\"action\" />\n </TableRow>\n ))}\n </>\n )\n }\n\n if (state.status === \"error\") {\n return (\n <TableEmptyRow colSpan={span}>\n {/* The taxonomy's state treatment, inside the table body so the columns, the\n search and the filters stay where they were. Only a transport failure gets the\n retry: re-reading after a refusal is refused again. */}\n <div data-error-category={state.error.category}>\n <EmptyState\n icon={state.error.category === \"permission\" ? \"permissions\" : \"error\"}\n heading={state.error.title}\n description={state.error.message}\n {...(state.error.retryable\n ? {\n action: (\n <Button variant=\"secondary\" icon=\"retry\" onClick={onRetry}>\n Try again\n </Button>\n ),\n }\n : {})}\n />\n </div>\n </TableEmptyRow>\n )\n }\n\n if (state.page.items.length === 0) {\n return (\n <TableEmptyRow colSpan={span}>\n {narrowed ? (\n <EmptyState\n icon=\"filter\"\n heading=\"No entries match\"\n description=\"No entry matches this search and these filters. Remember that the search matches the start of the title and is case sensitive.\"\n action={\n <Button variant=\"secondary\" onClick={onClearFilters}>\n Clear filters\n </Button>\n }\n />\n ) : (\n <EmptyState\n icon=\"collection\"\n heading={`No ${contentTypeLabel(type).toLowerCase()} yet`}\n description={`Entries of this type appear here as soon as the first one is created.`}\n {...(onCreate === undefined\n ? {}\n : {\n action: (\n <Button variant=\"primary\" icon=\"create\" onClick={onCreate}>\n {`New ${type.label}`}\n </Button>\n ),\n })}\n />\n )}\n </TableEmptyRow>\n )\n }\n\n return (\n <>\n {state.page.items.map((entry) => {\n const values = entry as unknown as Record<string, unknown>\n const deletable = onDelete !== undefined && canDelete(user, type, entry)\n const editable = onOpen !== undefined && canUpdate(user, type, entry)\n const actions: MenuEntry[] = [\n ...(editable\n ? [\n {\n kind: \"item\" as const,\n id: \"edit\",\n label: \"Edit\",\n icon: \"edit\" as const,\n },\n ]\n : []),\n ...(deletable\n ? [\n {\n kind: \"item\" as const,\n id: \"delete\",\n label: \"Delete\",\n icon: \"delete\" as const,\n destructive: true,\n },\n ]\n : []),\n ]\n\n return (\n <TableRow\n key={entry.id}\n selected={selected.includes(entry.id)}\n {...(onOpen === undefined ? {} : { onActivate: () => onOpen(entry.id) })}\n >\n {selectable ? (\n // The row navigates on click; the controls inside it must not, or ticking a\n // checkbox would open the entry the reader was about to act on in bulk.\n <TableCell width=\"selection\" onClick={(event) => event.stopPropagation()}>\n <Checkbox\n checked={selected.includes(entry.id)}\n disabled={!deletable}\n onChange={(checked) => onToggleRow(entry.id, checked)}\n ariaLabel={`Select ${entryTitle(type, entry)}`}\n />\n </TableCell>\n ) : null}\n\n {columns.map((column) => {\n if (column.kind === \"title\") {\n return (\n <TableCell key={column.key} primary>\n {entryTitle(type, entry)}\n </TableCell>\n )\n }\n\n if (column.kind === \"status\") {\n return (\n <TableCell key={column.key}>\n <Badge variant={ENTRY_STATUS_VARIANT[entry.status]}>\n {ENTRY_STATUS_LABEL[entry.status]}\n </Badge>\n </TableCell>\n )\n }\n\n if (column.kind === \"updated\") {\n return (\n <TableCell key={column.key} date>\n {formatDateTime(entry.updatedAt)}\n </TableCell>\n )\n }\n\n const text = formatCellValue(values[column.key], column.align)\n\n return (\n <TableCell\n key={column.key}\n numeric={column.align === \"numeric\"}\n date={column.align === \"date\"}\n >\n {text === null ? (\n <span className=\"text-text-faint\">Not set</span>\n ) : (\n text\n )}\n </TableCell>\n )\n })}\n\n <TableCell width=\"action\" onClick={(event) => event.stopPropagation()}>\n {actions.length === 0 ? null : (\n <Menu\n items={actions}\n label={`Actions for ${entryTitle(type, entry)}`}\n triggerSize=\"sm\"\n onSelect={(id) => {\n if (id === \"edit\" && onOpen !== undefined) onOpen(entry.id)\n if (id === \"delete\" && onDelete !== undefined) onDelete([entry.id])\n }}\n />\n )}\n </TableCell>\n </TableRow>\n )\n })}\n </>\n )\n}\n","import type { ContentTypeKind } from \"../types/content-type.js\"\n\nimport { SingletonError } from \"./errors.js\"\n\n/** The minimum a kind guard needs to know about a content type. */\nexport interface KindShape {\n slug: string\n kind: ContentTypeKind\n}\n\nexport function isCollection(type: KindShape): boolean {\n return type.kind === \"collection\"\n}\n\nexport function isSingleton(type: KindShape): boolean {\n return type.kind === \"singleton\"\n}\n\n/**\n * The one document id a singleton is allowed to use.\n *\n * Derived from the slug rather than generated, so \"exactly one entry\" is a property of the\n * path itself: a second create targets the same document and is a write conflict rather\n * than a second entry. See .docs/decisions/2026-09-18-firestore-layout.md.\n */\nexport function singletonEntryId(slug: string): string {\n return slug\n}\n\n/**\n * Guards a create against a singleton.\n *\n * `exists` is what the adapter read a moment ago. The path-derived id makes the race\n * harmless: two concurrent creates address the same document, so the second is an\n * overwrite of the first rather than a duplicate entry.\n */\nexport function assertSingletonCreatable(type: KindShape, exists: boolean): void {\n if (!isSingleton(type)) return\n if (exists) {\n throw new SingletonError(\n type.slug,\n `Content type \"${type.slug}\" is a singleton and already has its entry. Update it instead of creating another.`,\n )\n }\n}\n\n/** Guards an addressed write or read against a singleton. */\nexport function assertSingletonEntryId(type: KindShape, entryId: string): void {\n if (!isSingleton(type)) return\n\n const expected = singletonEntryId(type.slug)\n if (entryId !== expected) {\n throw new SingletonError(\n type.slug,\n `Content type \"${type.slug}\" is a singleton, so its entry id is always \"${expected}\". Received \"${entryId}\".`,\n )\n }\n}\n\n/** Guards list-shaped operations, which a singleton does not have. */\nexport function assertListable(type: KindShape): void {\n if (isSingleton(type)) {\n throw new SingletonError(\n type.slug,\n `Content type \"${type.slug}\" is a singleton and cannot be listed, filtered, or paginated. Read it with single(\"${type.slug}\").get().`,\n )\n }\n}\n\n/** Guards deletion, which would leave a singleton in a state the schema does not describe. */\nexport function assertDeletable(type: KindShape): void {\n if (isSingleton(type)) {\n throw new SingletonError(\n type.slug,\n `Content type \"${type.slug}\" is a singleton and its entry cannot be deleted. Clear its fields instead.`,\n )\n }\n}\n","import type { ContentTypeLike } from \"../types/content-type.js\"\nimport type { Entry } from \"../types/entry.js\"\n\nimport { entryTitle, UNTITLED_ENTRY } from \"./entry-title.js\"\n\n/**\n * The phrase a destructive confirmation asks the user to type, and what counts as typing\n * it. Canonical source: .docs/styleguide/04-components.md section 12, \"Destructive\n * confirmation\".\n *\n * Two failure modes bound this, and they pull in opposite directions. A phrase the user\n * cannot produce is a trap: the delete becomes impossible and the only way out is the\n * cancel button. A phrase any keypress satisfies is theatre: it costs a gesture and buys\n * no attention. So the phrase is always printed in the dialog, always typeable, and always\n * specific to what is about to be destroyed.\n *\n * None of it renders, so all of it is testable without a DOM, and the dialog and any\n * future bulk flow cannot disagree about what \"the name\" is.\n */\n\n/**\n * What to type to delete one entry.\n *\n * The entry's title, when it has one. When it does not (no `titleField`, a non-string\n * value, or a blank string) `entryTitle` answers \"Untitled\", and \"Untitled\" is a\n * placeholder rather than a name: it is the same word for every untitled entry in the\n * collection, so typing it proves nothing about which entry is meant. The document id is\n * used instead. It is ugly and it is unique, and the dialog prints it, so it is typeable.\n *\n * Two entries can still legitimately share a title. That ambiguity is harmless here,\n * because the dialog is already pointed at one entry: the phrase is a gate on attention,\n * not a lookup key.\n */\nexport function deleteConfirmationName(type: ContentTypeLike, entry: Entry): string {\n const title = entryTitle(type, entry)\n return title === UNTITLED_ENTRY ? entry.id : title\n}\n\n/**\n * What to type to delete several entries at once.\n *\n * Not a list of names: ten names is a transcription exercise, and an editor would paste it\n * or give up. The count and the content type is the fact worth confirming, because the\n * mistake a bulk delete actually makes is about how many rows were selected.\n */\nexport function deleteConfirmationPhrase(type: ContentTypeLike, count: number): string {\n const noun = count === 1 ? type.label : (type.labelPlural ?? `${type.label}s`)\n return `${String(count)} ${noun.toLowerCase()}`\n}\n\n/**\n * The comparison form of a confirmation phrase.\n *\n * Forgiving of whitespace: leading and trailing space, and any run of spaces, tabs or\n * newlines inside, collapse to one space. None of that is visible in the input, so\n * refusing it would fail a user who typed the phrase correctly and cannot see why it was\n * rejected. Unicode is normalized to NFC for the same reason: an accented character typed\n * on one keyboard and stored from another can be two byte sequences that read identically.\n *\n * Deliberately not forgiving of case. Case is visible, the phrase is printed right above\n * the input, and matching it is the deliberate act the gate exists to require. This is the\n * same choice GitHub makes for deleting a repository, and it is the line between a\n * confirmation and a formality.\n */\nexport function normalizeConfirmation(value: string): string {\n return value.normalize(\"NFC\").replace(/\\s+/gu, \" \").trim()\n}\n\n/**\n * Whether what was typed confirms the phrase.\n *\n * An empty expected phrase never matches. A caller that cannot name what it is about to\n * delete has no business unlocking the button, and an empty input would otherwise satisfy\n * an empty phrase on an empty dialog.\n */\nexport function confirmationMatches(expected: string, typed: string): boolean {\n const target = normalizeConfirmation(expected)\n if (target === \"\") return false\n return normalizeConfirmation(typed) === target\n}\n","\"use client\"\n\nimport { useEffect, useState } from \"react\"\n\nimport type { CmsAdapter } from \"../../core/adapter.js\"\nimport { isSingleton } from \"../../core/content-kind.js\"\nimport {\n confirmationMatches,\n deleteConfirmationName,\n deleteConfirmationPhrase,\n} from \"../../core/delete-confirmation.js\"\nimport { classifyError } from \"../../core/error-taxonomy.js\"\nimport type { ClassifiedError } from \"../../core/error-taxonomy.js\"\nimport type { Role } from \"../../types/auth.js\"\nimport type { ContentTypeLike } from \"../../types/content-type.js\"\nimport type { Entry } from \"../../types/entry.js\"\nimport { Button } from \"../components/button.js\"\nimport { Field, TextInput } from \"../components/field.js\"\nimport { ErrorNotice } from \"../components/error-notice.js\"\nimport { Modal } from \"../components/modal.js\"\nimport { Skeleton } from \"../components/skeleton.js\"\nimport { useOptionalToast } from \"../components/toast.js\"\n\n/**\n * The destructive confirmation for deleting entries.\n * Canonical source: .docs/styleguide/04-components.md section 12, \"Destructive\n * confirmation\".\n *\n * One dialog for every content type and for both the row action and the bulk selection,\n * because the only thing that differs between them is what is printed and how many\n * documents the adapter is asked to remove.\n *\n * What it is deliberate about:\n *\n * - **The phrase.** One entry asks for its name (its title, or its id when it has no\n * usable title); several ask for the count and the content type. `core/delete-\n * confirmation.ts` decides both and decides what counts as typing them.\n * - **The way out.** `dismissible` is false, so a stray backdrop click cannot start a\n * delete flow's only irreversible step. Escape still closes, because cancelling a\n * delete is the safe outcome and a user must always have a way out.\n * - **Partial failure.** Several deletes are several writes, and the second can fail\n * after the first succeeded. What did go through is reported to the caller anyway, so\n * the list does not keep showing rows that are gone, and the dialog stays open naming\n * what did not.\n */\n\nexport interface DeleteEntriesDialogProps {\n adapter: CmsAdapter\n type: ContentTypeLike\n /** The entries to delete. Empty means the dialog is closed. */\n entryIds: readonly string[]\n onCancel: () => void\n /**\n * The ids the adapter actually removed, and whether that was the whole batch.\n *\n * A batch is several writes and the second can fail after the first succeeded, so what\n * did go through is reported either way: the caller drops those rows, and leaves the\n * dialog open when `complete` is false, because it is still naming what did not.\n */\n onDeleted: (entryIds: readonly string[], complete: boolean) => void\n /** The signed-in role, so a refused delete can name who was refused. */\n role?: Role | undefined\n}\n\ntype NameState =\n | { kind: \"loading\" }\n | { kind: \"known\"; phrase: string }\n /** The entry was already gone when the dialog read it. Nothing left to confirm. */\n | { kind: \"gone\" }\n\nexport function DeleteEntriesDialog({\n adapter,\n type,\n entryIds,\n onCancel,\n onDeleted,\n role,\n}: DeleteEntriesDialogProps) {\n const open = entryIds.length > 0\n\n return open ? (\n <DeleteDialogBody\n // Each batch is its own dialog, with its own typed confirmation and its own read.\n // Remounting is what keeps a confirmed phrase from unlocking the next delete.\n key={entryIds.join(\",\")}\n adapter={adapter}\n type={type}\n entryIds={entryIds}\n onCancel={onCancel}\n onDeleted={onDeleted}\n {...(role === undefined ? {} : { role })}\n />\n ) : null\n}\n\nfunction DeleteDialogBody({\n adapter,\n type,\n entryIds,\n onCancel,\n onDeleted,\n role,\n}: DeleteEntriesDialogProps) {\n const toast = useOptionalToast()\n const single = entryIds[0]\n const bulk = entryIds.length > 1\n\n const [name, setName] = useState<NameState>(() =>\n bulk\n ? { kind: \"known\", phrase: deleteConfirmationPhrase(type, entryIds.length) }\n : { kind: \"loading\" },\n )\n const [typed, setTyped] = useState(\"\")\n const [deleting, setDeleting] = useState(false)\n const [failure, setFailure] = useState<ClassifiedError | null>(null)\n\n useEffect(() => {\n if (bulk || single === undefined) return\n let cancelled = false\n\n adapter\n .get(type.slug, single)\n .then((entry: Entry | null) => {\n if (cancelled) return\n setName(\n entry === null\n ? { kind: \"gone\" }\n : { kind: \"known\", phrase: deleteConfirmationName(type, entry) },\n )\n })\n .catch(() => {\n // The read failing is not proof the entry is gone, and the delete may still work.\n // The id is the one name that is certainly correct, so it becomes the phrase.\n if (!cancelled) setName({ kind: \"known\", phrase: single })\n })\n\n return () => {\n cancelled = true\n }\n }, [adapter, type, single, bulk])\n\n const phrase = name.kind === \"known\" ? name.phrase : \"\"\n const confirmed = confirmationMatches(phrase, typed)\n\n async function remove(): Promise<void> {\n if (!confirmed || deleting) return\n\n setDeleting(true)\n setFailure(null)\n\n const done: string[] = []\n let error: unknown = null\n\n for (const entryId of entryIds) {\n try {\n await adapter.delete(type.slug, entryId)\n done.push(entryId)\n } catch (thrown: unknown) {\n error = thrown\n break\n }\n }\n\n setDeleting(false)\n if (done.length > 0) onDeleted(done, error === null)\n\n if (error === null) {\n toast?.notify({\n tone: \"success\",\n title: bulk\n ? `${String(done.length)} ${(type.labelPlural ?? type.label).toLowerCase()} deleted`\n : `${type.label} deleted`,\n })\n return\n }\n\n // Classified, so a refused delete says who was refused and what for, and a dropped\n // connection offers the retry that a refusal must not.\n setFailure(\n classifyError(error, {\n ...(role === undefined ? {} : { role }),\n action: `delete ${bulk ? \"these entries\" : `this ${type.label.toLowerCase()}`}`,\n subject: type.label,\n }),\n )\n }\n\n const title = bulk\n ? `Delete ${deleteConfirmationPhrase(type, entryIds.length)}?`\n : `Delete this ${type.label.toLowerCase()}?`\n\n return (\n <Modal\n open\n onClose={onCancel}\n title={title}\n description={\n bulk\n ? \"Deleting is permanent. The entries and their field values are removed, and nothing here can bring them back.\"\n : \"Deleting is permanent. The entry and its field values are removed, and nothing here can bring them back.\"\n }\n width=\"sm\"\n // The backdrop click is disabled for a destructive dialog. Escape is not.\n dismissible={false}\n footer={\n <>\n <Button variant=\"secondary\" onClick={onCancel} disabled={deleting}>\n Cancel\n </Button>\n {name.kind === \"gone\" ? null : (\n <Button\n variant=\"danger\"\n icon=\"delete\"\n loading={deleting}\n disabled={!confirmed}\n onClick={() => void remove()}\n >\n {bulk ? `Delete ${String(entryIds.length)}` : \"Delete\"}\n </Button>\n )}\n </>\n }\n >\n <div className=\"flex flex-col gap-4\">\n {failure === null ? null : (\n <ErrorNotice error={failure} onRetry={() => void remove()} />\n )}\n\n {name.kind === \"loading\" ? (\n <Skeleton line=\"body\" className=\"w-48\" label=\"Reading the entry\" />\n ) : name.kind === \"gone\" ? (\n <p className=\"text-body-sm text-text-muted\">\n This entry no longer exists. Someone deleted it already, so there is nothing\n left to remove.\n </p>\n ) : (\n <>\n <p className=\"text-body-sm text-text-muted\">\n Type{\" \"}\n <span className=\"text-body-medium text-text-primary\">{name.phrase}</span> to\n confirm.\n </p>\n <Field label=\"Confirmation\">\n {({ id }) => (\n <TextInput\n id={id}\n value={typed}\n autoComplete=\"off\"\n disabled={deleting}\n onChange={(event) => setTyped(event.target.value)}\n />\n )}\n </Field>\n </>\n )}\n </div>\n </Modal>\n )\n}\n\n/**\n * Whether this content type may be deleted at all.\n *\n * A singleton exists exactly once and its absence is not a state the schema describes, so\n * it has no delete flow. The domain guard `assertDeletable` refuses the write as well;\n * this only keeps the admin from offering a button the adapter would reject.\n */\nexport function isDeletableType(type: ContentTypeLike): boolean {\n return !isSingleton(type)\n}\n","import type { FieldTypeRegistry } from \"../schema/field-type.js\"\nimport type { ContentTypeLike } from \"../types/content-type.js\"\nimport type { Entry, EntryMeta, FieldError } from \"../types/entry.js\"\nimport type { FieldDefinition } from \"../types/field.js\"\n\nimport { orderedFields } from \"./schema-editor.js\"\n\n/**\n * The entry form as data: which fields it renders, what it starts from, which error\n * belongs to which control, and whether anything has changed.\n *\n * None of it renders, so all of it is testable in the node project, and the create screen\n * and the edit screen cannot drift apart by deriving the same answers twice. The field\n * type registry arrives as an argument rather than as an import, because `src/fields`\n * pulls in React and core must not.\n */\n\nexport interface FormField {\n key: string\n field: FieldDefinition\n}\n\n/**\n * The fields the form renders, in the order the schema declares them.\n *\n * A hidden field is skipped: it still stores and still validates (see the note on\n * `hidden` in types/field.ts), it simply has no control. That is exactly why an error on\n * a hidden field is reported at form level by `unroutableIssues` instead of vanishing.\n */\nexport function formFields(type: ContentTypeLike): readonly FormField[] {\n // `orderedFields` rather than the map's own order: a stored content type comes back from\n // Firestore with its field map sorted, so the order an editor arranged in the Schema\n // Builder lives in `fieldOrder` and nowhere else.\n return orderedFields(type).filter(({ field }) => field.hidden !== true)\n}\n\n/** What a new entry starts with: every field at its own field type's default. */\nexport function initialFormValues(\n type: ContentTypeLike,\n registry: FieldTypeRegistry,\n): Record<string, unknown> {\n const values: Record<string, unknown> = {}\n\n for (const [key, field] of Object.entries(type.fields)) {\n const spec = registry.get(field.type)\n values[key] = spec === undefined ? null : spec.defaultValue(field)\n }\n\n return values\n}\n\n/**\n * The values of a stored entry, narrowed to the fields the schema declares.\n *\n * Metadata is deliberately dropped: `status`, `createdBy` and the timestamps belong to the\n * adapter, and a form that carried them in its value map could write one back. A field the\n * entry predates falls back to the field type's default rather than to `undefined`, so the\n * control is not handed a value it has no state for.\n */\nexport function formValuesFromEntry(\n type: ContentTypeLike,\n entry: Entry,\n registry: FieldTypeRegistry,\n): Record<string, unknown> {\n const stored = entry as unknown as Record<string, unknown>\n const values: Record<string, unknown> = {}\n\n for (const [key, field] of Object.entries(type.fields)) {\n if (key in stored && stored[key] !== undefined) {\n values[key] = stored[key]\n continue\n }\n const spec = registry.get(field.type)\n values[key] = spec === undefined ? null : spec.defaultValue(field)\n }\n\n return values\n}\n\n/**\n * The errors belonging to one field and everything nested under it.\n *\n * Path-based, which is what lets a server error reach the control that owns it: the\n * validator and the adapter both report `blocks.1.items.0.text`, and passing that whole\n * subtree to the `blocks` input lets the repeater hand it down row by row. A prefix match\n * on the dot is required, or `title` would also claim `titleImage`.\n */\nexport function errorsUnder<TError extends FieldError>(\n errors: readonly TError[],\n path: string,\n): TError[] {\n return errors.filter(\n (error) => error.path === path || error.path.startsWith(`${path}.`),\n )\n}\n\n/** Where an error came from. The two are told apart because they expire differently. */\nexport type ErrorOrigin = \"client\" | \"server\"\n\nexport interface FormIssue extends FieldError {\n origin: ErrorOrigin\n}\n\n/**\n * The errors on screen, from the two sources that produce them.\n *\n * A client error is recomputed from the current values on every keystroke, so it is always\n * about what is in the form right now. A server error is a verdict about the values that\n * were submitted, and only another submission can retract it: uniqueness is the clearest\n * case, because nothing in the browser can know that a slug is free.\n *\n * So they cannot simply be concatenated. A client error wins its own path, because it is\n * the more current statement about that value; a server error survives on every path the\n * client has nothing to say about, which is what keeps \"that slug is taken\" on screen\n * while the editor types the next character.\n */\nexport function mergeIssues(\n client: readonly FieldError[],\n server: readonly FieldError[],\n): readonly FormIssue[] {\n const claimed = new Set(client.map((error) => error.path))\n\n return [\n ...client.map((error): FormIssue => ({ ...error, origin: \"client\" })),\n ...server\n .filter((error) => !claimed.has(error.path))\n .map((error): FormIssue => ({ ...error, origin: \"server\" })),\n ]\n}\n\n/**\n * Issues no control will render, which is the only case where a toast or a form-level\n * message is the right answer.\n *\n * Three ways an error gets here: it names a hidden field, it names a field the schema no\n * longer declares, or it names nothing at all. In each case the form has to say it\n * somewhere, and saying it next to an unrelated control would be worse than saying it at\n * the top.\n */\nexport function unroutableIssues<TError extends FieldError>(\n issues: readonly TError[],\n type: ContentTypeLike,\n): readonly TError[] {\n const rendered = new Set(formFields(type).map((entry) => entry.key))\n\n return issues.filter((issue) => {\n const root = issue.path.split(\".\")[0]\n return root === undefined || root === \"\" || !rendered.has(root)\n })\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true\n if (a === null || b === null) return false\n if (typeof a !== \"object\" || typeof b !== \"object\") return false\n\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b)) return false\n return a.length === b.length && a.every((item, index) => deepEqual(item, b[index]))\n }\n\n const left = a as Record<string, unknown>\n const right = b as Record<string, unknown>\n const keys = new Set([...Object.keys(left), ...Object.keys(right)])\n\n for (const key of keys) {\n if (!deepEqual(left[key], right[key])) return false\n }\n return true\n}\n\n/**\n * Whether the form holds anything the baseline does not.\n *\n * Structural rather than by reference, because every field input replaces the value it\n * owns on each edit, and a repeater rebuilds its whole array to move one row. Reference\n * equality would call an entry dirty for having been touched and untouched again, and the\n * unsaved-changes guard is only worth having if it is quiet when nothing changed.\n */\nexport function valuesChanged(\n baseline: Record<string, unknown>,\n current: Record<string, unknown>,\n): boolean {\n return !deepEqual(baseline, current)\n}\n\n/**\n * Whether the stored entry moved since the editor read it.\n *\n * `updatedAt` is stamped by the adapter on every write, so a difference means somebody\n * else saved. The editor asks this immediately before its own write rather than\n * subscribing: a live listener would be a second read path, a second failure mode, and an\n * interruption in the middle of typing. It closes the wide window, not the narrow one; two\n * writes in the same second still resolve last-write-wins, which the adapter's document\n * semantics already decide.\n */\nexport function entryChangedSince(\n baseline: Pick<EntryMeta, \"updatedAt\">,\n current: Pick<EntryMeta, \"updatedAt\">,\n): boolean {\n return baseline.updatedAt !== current.updatedAt\n}\n","import { can } from \"../permissions/can.js\"\nimport type { AuthUser } from \"../types/auth.js\"\nimport type { ContentTypeLike } from \"../types/content-type.js\"\nimport type { EntryMeta, EntryStatus } from \"../types/entry.js\"\n\n/**\n * What the status control may offer, and to whom.\n *\n * Status is the one piece of entry metadata an editor writes, so it is not a display: it\n * is a set of transitions out of the status the entry is in, each one answered by `can()`\n * against the entry itself. A denied transition keeps its reason rather than disappearing,\n * because \"you cannot publish this\" is information and an empty panel is not.\n *\n * Hiding or disabling a transition here is presentation. The adapter validates the write\n * and the security rules check the same matrix again, so a user who reaches past this list\n * gains nothing.\n */\n\nexport interface StatusTransition {\n to: EntryStatus\n /** Imperative label for the control: \"Publish\", \"Unpublish\", \"Archive\". */\n label: string\n /** What it does to the public site, in one sentence. */\n effect: string\n allowed: boolean\n /** Why it is not offered. Null when it is. */\n reason: string | null\n}\n\n/** Just enough of an entry to answer a transition question. */\nexport type StatusSubject = Pick<EntryMeta, \"status\" | \"createdBy\">\n\ninterface TransitionShape {\n to: EntryStatus\n label: string\n effect: string\n}\n\n/**\n * The legal moves, keyed by where the entry is now.\n *\n * Exhaustive by construction, so a fourth status cannot be added to `ENTRY_STATUSES`\n * without deciding what leads into and out of it. The wording follows what the adapter\n * actually does with `publishedAt`: first publish stamps it, republishing keeps it, and\n * moving back to draft clears it.\n */\nconst TRANSITIONS: Readonly<Record<EntryStatus, readonly TransitionShape[]>> = {\n draft: [\n {\n to: \"published\",\n label: \"Publish\",\n effect: \"Makes this entry readable on the public site.\",\n },\n {\n to: \"archived\",\n label: \"Archive\",\n effect: \"Keeps the entry but takes it out of the public site.\",\n },\n ],\n published: [\n {\n to: \"draft\",\n label: \"Unpublish\",\n effect: \"Takes the entry off the public site and clears its publication date.\",\n },\n {\n to: \"archived\",\n label: \"Archive\",\n effect: \"Keeps the entry but takes it out of the public site.\",\n },\n ],\n archived: [\n {\n to: \"draft\",\n label: \"Restore as draft\",\n effect: \"Brings the entry back into editing. It stays off the public site.\",\n },\n {\n to: \"published\",\n label: \"Publish\",\n effect: \"Makes this entry readable on the public site again.\",\n },\n ],\n}\n\n/** How a status reads in the sidebar, under the badge. */\nexport const STATUS_EFFECT: Readonly<Record<EntryStatus, string>> = {\n draft: \"Not visible on the public site.\",\n published: \"Visible on the public site.\",\n archived: \"Kept out of the public site and out of the way.\",\n}\n\n/**\n * The transitions for one entry, in a fixed order.\n *\n * `entry` is null for an entry that has not been created yet. A new entry is a draft that\n * does not exist, so the only move it has is the one that brings it into existence\n * published, and the permission question is `create` rather than `update`.\n */\nexport function statusTransitions(\n user: AuthUser,\n type: ContentTypeLike,\n entry: StatusSubject | null,\n): readonly StatusTransition[] {\n const from = entry?.status ?? \"draft\"\n const shapes =\n entry === null\n ? TRANSITIONS.draft.filter((shape) => shape.to === \"published\")\n : TRANSITIONS[from]\n\n const allowed =\n entry === null\n ? can(user, \"create\", { type })\n : can(user, \"update\", { type, entry: { createdBy: entry.createdBy } })\n\n const reason = allowed ? null : denial(user, entry)\n\n return shapes.map((shape) => ({ ...shape, allowed, reason }))\n}\n\nfunction denial(user: AuthUser, entry: StatusSubject | null): string {\n if (user.role === \"author\" && entry !== null && entry.createdBy !== user.uid) {\n return \"An author can only change the status of their own entries.\"\n }\n return \"Your role cannot change the status of this entry.\"\n}\n\n/**\n * Whether this user may save the values of this entry at all.\n *\n * Separate from the transitions because saving without changing the status is its own\n * action, and because the create screen asks the question before an entry exists.\n */\nexport function canSaveEntry(\n user: AuthUser,\n type: ContentTypeLike,\n entry: StatusSubject | null,\n): boolean {\n return entry === null\n ? can(user, \"create\", { type })\n : can(user, \"update\", { type, entry: { createdBy: entry.createdBy } })\n}\n","import type { ContentTypeLike } from \"../types/content-type.js\"\n\n/**\n * The field a content type is addressed by in a URL, if it has one.\n *\n * It lives in core rather than in the adapter because two callers need it and only one of\n * them may import Firebase: the adapter looks an entry up by its slug value, and the entry\n * form asks whether a field is the one it can answer a uniqueness question about without a\n * composite index. A second copy of this rule would let the two disagree about which field\n * the slug is.\n */\nexport function slugFieldKey(type: ContentTypeLike): string | null {\n for (const [key, field] of Object.entries(type.fields)) {\n if (field.type === \"slug\") return key\n }\n return \"slug\" in type.fields ? \"slug\" : null\n}\n","import type { CmsAdapter } from \"./adapter.js\"\nimport { slugFieldKey } from \"./slug-field.js\"\nimport type { ContentTypeLike } from \"../types/content-type.js\"\n\n/**\n * The live uniqueness answer the form hands to the field layer.\n *\n * `unique` is the one validation rule that cannot be answered without reading other\n * entries, so the shared validator leaves it to the adapter, which checks it again on\n * every write. This is only the hint in front of that check, and it is deliberately narrow.\n *\n * It answers for the content type's slug field and for nothing else. That is not a\n * shortcut: `getBySlug` is a single equality query that Firestore serves from an automatic\n * single-field index, while asking the same question about an arbitrary field would need a\n * composite index per field, generated per content type, for a hint. Any other path is\n * rejected rather than answered \"free\", because telling an editor a value is available\n * when nobody looked is worse than telling them nothing. The rejection is what the slug\n * input reads as \"no answer\", and it then shows no availability hint at all.\n */\nexport interface EntryUniqueOptions {\n adapter: CmsAdapter\n type: ContentTypeLike\n /** The entry being edited, so its own value does not count as taken. Null on create. */\n entryId: string | null\n}\n\nexport function entryUniqueCheck(\n options: EntryUniqueOptions,\n): (path: string, value: string) => Promise<boolean> {\n const { adapter, type, entryId } = options\n const key = slugFieldKey(type)\n\n return async (path, value) => {\n if (key === null || path !== key) {\n throw new Error(\n `Uniqueness of \"${path}\" cannot be checked from the form. The adapter checks it before the write.`,\n )\n }\n\n const found = await adapter.getBySlug(type.slug, value)\n return found === null || found.id === entryId\n }\n}\n","import type { ComponentType } from \"react\"\n\nimport { SchemaError } from \"../core/errors.js\"\nimport type { AnyContentTypeShape, FieldError } from \"../types/entry.js\"\nimport type {\n FieldDefinition,\n FieldMap,\n FieldType,\n ValidationRules,\n} from \"../types/field.js\"\n\n/** Props every admin field input receives. Field types never read from a store directly. */\nexport interface FieldInputProps<\n TValue,\n TField extends FieldDefinition = FieldDefinition,\n> {\n /** Dotted path, unique within the form: `title`, `blocks.2.heading`. */\n path: string\n field: TField\n value: TValue | null\n onChange: (value: TValue | null) => void\n // Spelled with the explicit `| undefined` that `exactOptionalPropertyTypes` requires of a\n // caller forwarding an optional prop. A repeater passes its own `onBlur` straight down to\n // every nested input, and without this it could not.\n onBlur?: (() => void) | undefined\n errors: readonly FieldError[]\n disabled?: boolean | undefined\n readonly?: boolean | undefined\n}\n\nexport type FieldInputComponent<\n TValue,\n TField extends FieldDefinition = FieldDefinition,\n> = ComponentType<FieldInputProps<TValue, TField>>\n\n/** Everything a validator may know without touching the database. */\nexport interface ValidateCtx {\n path: string\n contentType: AnyContentTypeShape\n /** All values of the entry being validated, for cross-field rules. */\n entry: Record<string, unknown>\n}\n\n/**\n * Recursion, for the two field types that contain other fields.\n *\n * `repeater` holds a whole field map, and it cannot convert or name what is inside it\n * without applying the same field type contract one level down. It must not reach for the\n * registry itself: the registry imports every spec, so a spec that imports the registry\n * closes a cycle. The caller that already holds the registry passes the recursion in\n * instead, and both members below are optional, so a spec that nests nothing ignores them\n * and a caller that has no registry still gets a working round trip.\n */\nexport interface NestedConverter {\n toStored(fields: FieldMap, values: Record<string, unknown>): Record<string, unknown>\n fromStored(fields: FieldMap, data: Record<string, unknown>): Record<string, unknown>\n}\n\n/** Names the SDK-facing type of any field definition, one level down. */\nexport type TsTypeResolver = (field: FieldDefinition) => string\n\n/**\n * Layer 5, as a value or as a function of the field.\n *\n * A plain string is the common case and stays exactly as it was. A function is what lets a\n * field type whose SDK type depends on its own options say so: `select` narrows on\n * `multiple`, `relation` on `many`, and `repeater` names the object its rows actually\n * hold. `FieldValue<TField>` in types/field.ts already narrows all three for a code-defined\n * type; this is what codegen can say for a type created in the Schema Builder, where the\n * field definition exists only at runtime.\n */\nexport type FieldTsType<TField extends FieldDefinition = FieldDefinition> =\n string | ((field: TField, resolve: TsTypeResolver) => string)\n\n/**\n * How one per-type option is edited in the Schema Builder.\n *\n * A control, not a field type: `\"choice\"` is a fixed list of values, `\"content-type\"` is a\n * slug picked from the live registry, `\"field-key\"` is a sibling field of the same level.\n * The field editor implements this small vocabulary once, and every field type describes\n * its own options in it, which is what keeps `switch (field.type)` out of the screen.\n */\nexport type FieldOptionControl =\n | \"text\"\n | \"number\"\n | \"boolean\"\n | \"choice\"\n | \"select-options\"\n | \"content-type\"\n | \"field-key\"\n | \"string-list\"\n | \"fields\"\n\nexport interface FieldOptionDescriptor {\n /** The property this option writes on the field definition. */\n key: string\n label: string\n control: FieldOptionControl\n help?: string\n /** A field of this type is incomplete until the option has a value. */\n required?: boolean\n /** The values a `\"choice\"` control offers. */\n choices?: readonly { value: string; label: string }[]\n}\n\n/**\n * Layer 7: what the Schema Builder may configure on this field type, and what it starts as.\n *\n * It exists so that the field editor is generated from the registry exactly as every other\n * admin screen is. Without it, one screen would hold a list of which options belong to\n * which field type, and a field type added later would render as a bare label until\n * somebody remembered to edit that list.\n */\nexport interface FieldEditorSpec {\n /** Name shown in the field type picker. */\n label: string\n /** One line, shown under the name in the picker. */\n description: string\n /** The shared validation rules this field type honours. See VALIDATION_RULE_CONTROLS. */\n rules: readonly (keyof ValidationRules)[]\n /** The per-type options, in the order the editor shows them. */\n options: readonly FieldOptionDescriptor[]\n /**\n * Everything a new field of this type needs besides `type` and `label`.\n *\n * A select with no options and a repeater with no nested fields are both invalid, so a\n * newly added field cannot start as `{ type, label }` alone.\n */\n defaults: Record<string, unknown>\n}\n\n/**\n * The seven-layer contract. A field type is not \"added\" until every member here is\n * implemented; a partial field type is a field type that behaves differently in the form\n * than it does on the server.\n *\n * 1. `name` schema definition: the discriminator a content type writes\n * 2. `toStored` /\n * `fromStored` stored shape: the round trip through Firestore\n * 3. `Input` admin input component\n * 4. `validate` validation, run identically by the form and by the adapter\n * 5. `tsType` SDK-facing type, used by codegen and by the Developer area\n * 6. `defaultValue` registration data: what a new entry starts with\n * 7. `editor` Schema Builder data: the options, rules and defaults of the type\n */\nexport interface FieldTypeSpec<TValue, TField extends FieldDefinition = FieldDefinition> {\n name: FieldType\n toStored(value: TValue | null, field: TField, nested?: NestedConverter): unknown\n fromStored(raw: unknown, field: TField, nested?: NestedConverter): TValue | null\n Input: FieldInputComponent<TValue, TField>\n validate(\n value: TValue | null,\n rules: ValidationRules,\n ctx: ValidateCtx,\n field: TField,\n ): FieldError[]\n tsType: FieldTsType<TField>\n defaultValue(field: TField): TValue | null\n editor: FieldEditorSpec\n}\n\n/**\n * A spec whose value and field types have been erased, for storage in the registry.\n *\n * The registry is heterogeneous by construction: one spec per field type, each with a\n * different value type. The erasure stops at this alias; every consumer goes back through\n * the typed `FieldTypeSpec` for the field it is actually handling.\n */\n/* eslint-disable-next-line @typescript-eslint/no-explicit-any */\nexport type AnyFieldTypeSpec = FieldTypeSpec<any, any>\n\nexport interface FieldTypeRegistry {\n get(name: string): AnyFieldTypeSpec | undefined\n require(name: string): AnyFieldTypeSpec\n has(name: string): boolean\n readonly names: readonly FieldType[]\n}\n\n/**\n * Builds the single registration point for field types.\n *\n * The admin never switches on a field name: it looks the spec up here and renders\n * `spec.Input`. If a screen needs `switch (field.type)`, the abstraction has failed.\n */\nexport function registerFieldTypes(\n specs: readonly AnyFieldTypeSpec[],\n): FieldTypeRegistry {\n const byName = new Map<string, AnyFieldTypeSpec>()\n\n for (const spec of specs) {\n if (byName.has(spec.name)) {\n throw new SchemaError(\n `Field type \"${spec.name}\" is registered twice. Each field type has exactly one spec.`,\n )\n }\n byName.set(spec.name, spec)\n }\n\n return {\n get: (name) => byName.get(name),\n has: (name) => byName.has(name),\n require(name) {\n const spec = byName.get(name)\n if (!spec) {\n throw new SchemaError(\n `Unknown field type \"${name}\". Registered types: ${[...byName.keys()].join(\", \") || \"none\"}.`,\n )\n }\n return spec\n },\n names: [...byName.keys()] as FieldType[],\n }\n}\n\n/** What codegen writes for a field whose type nothing has registered. */\nexport const UNKNOWN_TS_TYPE = \"unknown\"\n\n/**\n * Layer 5 for one field definition, resolved through the registry.\n *\n * The one place that knows a `tsType` may be a function, so no caller has to branch on it,\n * and the one place that supplies the recursion a nesting field type asks for. An\n * unregistered field type resolves to `unknown` rather than throwing: codegen for a\n * database-defined content type must not fail on one field it does not recognise.\n */\nexport function resolveTsType(\n registry: FieldTypeRegistry,\n field: FieldDefinition,\n): string {\n const spec = registry.get(field.type)\n if (spec === undefined) return UNKNOWN_TS_TYPE\n\n const declared: FieldTsType = spec.tsType\n if (typeof declared === \"string\") return declared\n\n return declared(field, (nested) => resolveTsType(registry, nested))\n}\n","/**\n * Shared stored-shape helpers.\n *\n * Every spec converts on a \"keep it or drop it\" basis rather than coercing. A text field\n * whose document holds a number is corrupt data, and turning it into `\"42\"` would hide the\n * corruption from the validator that is there to report it, while making the SDK's declared\n * `string` type a lie on the way out.\n */\nexport function storedString(raw: unknown): string | null {\n return typeof raw === \"string\" ? raw : null\n}\n\nexport function storedNumber(raw: unknown): number | null {\n return typeof raw === \"number\" && Number.isFinite(raw) ? raw : null\n}\n\nexport function storedBoolean(raw: unknown): boolean | null {\n return typeof raw === \"boolean\" ? raw : null\n}\n\nexport function storedStrings(raw: unknown): string[] | null {\n if (!Array.isArray(raw)) return null\n return raw.filter((item): item is string => typeof item === \"string\")\n}\n","\"use client\"\n\nimport { Field } from \"../admin/components/field.js\"\nimport type { FieldProps } from \"../admin/components/field.js\"\nimport type { FieldError } from \"../types/entry.js\"\nimport type { FieldDefinition } from \"../types/field.js\"\n\n/**\n * The label, help text and error wrapper every field type renders.\n *\n * It is one component rather than five copies of the same six lines, so the composition\n * from .docs/styleguide/04-components.md section 3.1 cannot drift between field types.\n * Only the control inside it differs.\n *\n * The first error wins: the guide allows exactly one sentence under a field, and a field\n * that is both too short and badly formatted is not clearer for saying so twice.\n */\nexport interface FieldShellProps {\n field: FieldDefinition\n errors: readonly FieldError[]\n /** Replaces `field.description`, for a field type that has something better to say. */\n help?: string | undefined\n children: FieldProps[\"children\"]\n}\n\nexport function FieldShell({ field, errors, help, children }: FieldShellProps) {\n return (\n <Field\n label={field.label}\n required={field.validation?.required === true}\n help={help ?? field.description}\n error={errors[0]?.message}\n >\n {children}\n </Field>\n )\n}\n","\"use client\"\n\nimport { Checkbox } from \"../../admin/components/checkbox.js\"\nimport type { FieldInputProps } from \"../../schema/field-type.js\"\nimport { FieldShell } from \"../field-shell.js\"\nimport type { BooleanField } from \"../../types/field.js\"\n\n/**\n * A checkbox, not a switch. The style guide reserves the switch for a boolean that takes\n * effect the moment it is flipped, and an entry field takes effect when the form is saved.\n */\nexport function BooleanFieldInput({\n field,\n value,\n onChange,\n errors,\n disabled = false,\n readonly = false,\n}: FieldInputProps<boolean, BooleanField>) {\n const locked = disabled || readonly || field.readonly === true\n\n return (\n <FieldShell field={field} errors={errors}>\n {({ id, describedBy }) => (\n <Checkbox\n id={id}\n checked={value === true}\n disabled={locked}\n aria-describedby={describedBy}\n ariaLabel={field.label}\n onChange={(checked) => onChange(checked)}\n />\n )}\n </FieldShell>\n )\n}\n","import type { FieldError } from \"../../types/entry.js\"\nimport type { FieldTypeSpec } from \"../../schema/field-type.js\"\nimport type { BooleanField } from \"../../types/field.js\"\nimport { storedBoolean } from \"../values.js\"\nimport { BooleanFieldInput } from \"./input.js\"\n\n/**\n * A boolean stores `true` or `false`, and `null` only when it has never been set. Defaulting\n * an unset value to `false` on read would erase the difference between \"off\" and \"this field\n * did not exist when the entry was written\", which matters the first time a boolean is added\n * to a content type that already has entries.\n */\nexport const booleanField: FieldTypeSpec<boolean, BooleanField> = {\n name: \"boolean\",\n toStored: (value) => storedBoolean(value),\n fromStored: (raw) => storedBoolean(raw),\n Input: BooleanFieldInput,\n validate: (): FieldError[] => [],\n tsType: \"boolean\",\n // A new entry starts at a decided `false` rather than at null: a checkbox has no third\n // state, so the form would show `false` regardless and saving would write it anyway.\n defaultValue: (field) => field.defaultValue ?? false,\n editor: {\n label: \"Yes or no\",\n description: \"A switch with two states.\",\n rules: [\"required\"],\n options: [{ key: \"defaultValue\", label: \"On by default\", control: \"boolean\" }],\n defaults: {},\n },\n}\n","/**\n * Conversions between what a date field stores and what the browser controls speak.\n *\n * A `date` is a calendar day, so it is stored as the `YYYY-MM-DD` the editor picked and\n * never touched again: turning it into an instant moves it across a time-zone boundary and\n * a birthday becomes the day before. A `datetime` is a real instant, so it is stored as a\n * full ISO 8601 string with a zone, and the wall-clock conversion happens here, in the\n * browser, where the editor's own zone is the right one to use. The server never guesses.\n */\n\nconst DATE_ONLY = /^\\d{4}-\\d{2}-\\d{2}$/\n\nexport function isCalendarDate(value: string): boolean {\n if (!DATE_ONLY.test(value)) return false\n const parsed = new Date(`${value}T00:00:00Z`)\n if (Number.isNaN(parsed.getTime())) return false\n // Rejects 2026-02-31, which `Date` would roll forward into March rather than refuse.\n return parsed.toISOString().slice(0, 10) === value\n}\n\nexport function isInstant(value: string): boolean {\n return !Number.isNaN(new Date(value).getTime())\n}\n\nfunction pad(value: number): string {\n return String(value).padStart(2, \"0\")\n}\n\n/** ISO instant to the `YYYY-MM-DDTHH:mm` a `datetime-local` control renders. */\nexport function instantToLocalInput(value: string): string {\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return \"\"\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`\n}\n\n/** The `datetime-local` wall clock back to an ISO instant, read in the browser's zone. */\nexport function localInputToInstant(value: string): string | null {\n if (value === \"\") return null\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? null : date.toISOString()\n}\n\n/** Tolerates a value a date control cannot show, such as an instant in a `date` field. */\nexport function toDateInput(value: string): string {\n if (isCalendarDate(value)) return value\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return \"\"\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`\n}\n","\"use client\"\n\nimport { TextInput } from \"../../admin/components/field.js\"\nimport type { FieldInputProps } from \"../../schema/field-type.js\"\nimport { FieldShell } from \"../field-shell.js\"\nimport type { DateField } from \"../../types/field.js\"\nimport { instantToLocalInput, localInputToInstant, toDateInput } from \"./datetime.js\"\n\nexport function DateFieldInput({\n field,\n value,\n onChange,\n onBlur,\n errors,\n disabled = false,\n readonly = false,\n}: FieldInputProps<string, DateField>) {\n const datetime = field.precision === \"datetime\"\n const shown =\n value === null ? \"\" : datetime ? instantToLocalInput(value) : toDateInput(value)\n\n return (\n <FieldShell field={field} errors={errors}>\n {({ id, describedBy, invalid }) => (\n <TextInput\n id={id}\n type={datetime ? \"datetime-local\" : \"date\"}\n value={shown}\n invalid={invalid}\n aria-describedby={describedBy}\n disabled={disabled}\n readOnly={readonly || field.readonly === true}\n className=\"tabular-nums\"\n onChange={(event) => {\n const next = event.target.value\n if (next === \"\") {\n onChange(null)\n return\n }\n onChange(datetime ? localInputToInstant(next) : next)\n }}\n onBlur={onBlur}\n />\n )}\n </FieldShell>\n )\n}\n","import type { FieldError } from \"../../types/entry.js\"\nimport type { FieldTypeSpec } from \"../../schema/field-type.js\"\nimport type { DateField } from \"../../types/field.js\"\nimport { storedString } from \"../values.js\"\nimport { isCalendarDate, isInstant } from \"./datetime.js\"\nimport { DateFieldInput } from \"./input.js\"\n\n/** Duck typing rather than `instanceof Timestamp`: Firebase stays behind the adapter. */\nfunction timestampToIso(raw: unknown): string | null {\n if (typeof raw !== \"object\" || raw === null) return null\n const candidate = raw as { toDate?: () => Date }\n if (typeof candidate.toDate !== \"function\") return null\n const date = candidate.toDate()\n return date instanceof Date && !Number.isNaN(date.getTime()) ? date.toISOString() : null\n}\n\n/**\n * Stored as the string the editor chose, in the precision the field declares. See\n * `datetime.ts` for why a calendar day never becomes an instant.\n */\nexport const dateField: FieldTypeSpec<string, DateField> = {\n name: \"date\",\n toStored: (value) => storedString(value),\n fromStored: (raw, field) => {\n const iso = timestampToIso(raw)\n if (iso !== null) {\n // An entry written by an older version, or by hand in the Firestore console.\n return field.precision === \"datetime\" ? iso : iso.slice(0, 10)\n }\n return storedString(raw)\n },\n Input: DateFieldInput,\n /**\n * The shared validator only knows the value is a string. Whether that string is a date is\n * this field type's business, and `min`/`max` are numeric rules that never reach it.\n */\n validate: (value, _rules, ctx, field): FieldError[] => {\n if (value === null || value === \"\") return []\n\n if (field.precision === \"datetime\") {\n return isInstant(value)\n ? []\n : [\n {\n path: ctx.path,\n rule: \"format\",\n message: `${field.label} must be a date and time.`,\n },\n ]\n }\n\n return isCalendarDate(value)\n ? []\n : [\n {\n path: ctx.path,\n rule: \"format\",\n message: `${field.label} must be a date in the format YYYY-MM-DD.`,\n },\n ]\n },\n tsType: \"string\",\n defaultValue: () => null,\n editor: {\n label: \"Date\",\n description: \"A calendar day, or a day with a time.\",\n rules: [\"required\"],\n options: [\n {\n key: \"precision\",\n label: \"Precision\",\n control: \"choice\",\n choices: [\n { value: \"date\", label: \"Date\" },\n { value: \"datetime\", label: \"Date and time\" },\n ],\n help: \"Changing it changes how every entry is stored.\",\n },\n ],\n defaults: {},\n },\n}\n","import type { MediaReference } from \"../../types/media.js\"\n\n/**\n * The stored shape of `image` and `file`, shared by both.\n *\n * Both field types store a `MediaReference` and differ only in what the picker offers and\n * in whether the control previews the item. Everything below is therefore written once.\n */\n\n/**\n * Whether a stored value is a media reference at all.\n *\n * `mediaId` is the only required part: it is the source of truth, and `url` is a\n * denormalized read convenience the adapter refreshes. A document written by hand in the\n * Firestore console, or by a version that did not denormalize the url yet, still holds a\n * usable reference and must not be thrown away for missing it.\n */\nexport function isMediaReference(\n raw: unknown,\n): raw is { mediaId: string; url?: unknown } {\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) return false\n const candidate = raw as { mediaId?: unknown }\n return typeof candidate.mediaId === \"string\"\n}\n\n/**\n * Reads a stored value as a media reference, or reports that it is not one.\n *\n * Deliberately not coercing: a bare string, a number or an object without a `mediaId` is\n * corrupt data, and inventing a reference from it would hide the corruption from the\n * validator that exists to report it.\n */\nexport function storedMediaReference(raw: unknown): MediaReference | null {\n if (!isMediaReference(raw)) return null\n return { mediaId: raw.mediaId, url: typeof raw.url === \"string\" ? raw.url : \"\" }\n}\n\n/** Whether the picker may offer an item of this MIME type, given the field's `accept`. */\nexport function acceptsType(\n accept: readonly string[] | undefined,\n type: string,\n): boolean {\n if (accept === undefined || accept.length === 0) return true\n\n return accept.some((pattern) => {\n if (pattern === \"*/*\") return true\n // `image/*` is the wildcard form the HTML accept attribute already uses, so a schema\n // author writes the string they would write on an `<input type=\"file\">`.\n if (pattern.endsWith(\"/*\")) return type.startsWith(pattern.slice(0, -1))\n return pattern === type\n })\n}\n","\"use client\"\n\nimport { createContext, useContext, useEffect, useState } from \"react\"\nimport type { ReactNode } from \"react\"\n\nimport type { MediaItem, MediaReference } from \"../../types/media.js\"\n\n/**\n * The seam between the `image` and `file` field types and the media library.\n *\n * The library itself is M7. The field types are M5, and they must be complete before it\n * exists, so they are written against this interface rather than against Storage, the\n * `MediaAdapter`, or a screen. Two consequences, both deliberate:\n *\n * 1. The field type never learns that Firebase exists. It asks for an item by id and asks\n * someone else to open a picker; whoever supplies the context decides how.\n * 2. Until M7 supplies one, the context is absent, and the control renders the\n * \"library not available\" state instead of a dead button. A stored reference is still\n * shown and still saved, so an entry edited in that window loses nothing.\n */\nexport interface MediaPickRequest {\n /** MIME patterns the field accepts, for example `[\"image/*\"]`. Absent means anything. */\n accept?: readonly string[] | undefined\n}\n\nexport interface MediaPickerApi {\n /**\n * Resolves stored references. Ids with no media document are simply absent from the\n * result, which is how the control learns a reference is broken.\n */\n resolve(mediaIds: readonly string[]): Promise<readonly MediaItem[]>\n /** Opens the library and resolves to the chosen item, or null when the editor cancels. */\n pick(request: MediaPickRequest): Promise<MediaItem | null>\n}\n\nconst MediaPickerContext = createContext<MediaPickerApi | null>(null)\n\nexport interface MediaPickerProviderProps {\n value: MediaPickerApi\n children: ReactNode\n}\n\nexport function MediaPickerProvider({ value, children }: MediaPickerProviderProps) {\n return (\n <MediaPickerContext.Provider value={value}>{children}</MediaPickerContext.Provider>\n )\n}\n\n/** The installed picker, or null while the media library has not been mounted. */\nexport function useMediaPicker(): MediaPickerApi | null {\n return useContext(MediaPickerContext)\n}\n\n/**\n * What the control knows about the item behind the stored reference.\n *\n * `missing` and `loading` are separate states for one reason: a control that showed\n * \"missing\" while the lookup was still in flight would accuse every reference of being\n * broken for as long as the network takes.\n */\nexport type MediaLookup =\n | { kind: \"empty\" }\n | { kind: \"unavailable\" }\n | { kind: \"loading\" }\n | { kind: \"found\"; item: MediaItem }\n | { kind: \"missing\" }\n\n/**\n * Resolves one stored reference to its media item.\n *\n * The resolved item is never written back into the value. A lookup is a read, and a field\n * whose lookup failed must save exactly what it was given: see the `missing` state in\n * `media-input.tsx`, which keeps the reference and never calls `onChange`.\n */\nexport function useMediaLookup(reference: MediaReference | null): MediaLookup {\n const picker = useMediaPicker()\n const mediaId = reference?.mediaId ?? null\n // Only the answer is state, and it carries the id it is about. \"Loading\" is derived from\n // the absence of an answer for the id currently on screen, so nothing has to be reset when\n // the reference changes and a late answer for an old id simply no longer matches.\n const [answer, setAnswer] = useState<{\n mediaId: string\n item: MediaItem | null\n } | null>(null)\n\n useEffect(() => {\n if (picker === null || mediaId === null) return\n let cancelled = false\n\n picker\n .resolve([mediaId])\n .then((items) => {\n if (cancelled) return\n setAnswer({ mediaId, item: items.find((item) => item.id === mediaId) ?? null })\n })\n .catch(() => {\n // A failed lookup is not proof the item is gone, but the control has to render\n // something. It reports `missing`, which is the state that keeps the value and asks\n // a person to look, rather than spinning forever.\n if (!cancelled) setAnswer({ mediaId, item: null })\n })\n\n return () => {\n cancelled = true\n }\n }, [picker, mediaId])\n\n if (mediaId === null) return { kind: \"empty\" }\n if (picker === null) return { kind: \"unavailable\" }\n if (answer === null || answer.mediaId !== mediaId) return { kind: \"loading\" }\n return answer.item === null ? { kind: \"missing\" } : { kind: \"found\", item: answer.item }\n}\n","\"use client\"\n\nimport { useState } from \"react\"\n\nimport { Button } from \"../../admin/components/button.js\"\nimport { cx } from \"../../admin/components/class-names.js\"\nimport { Icon } from \"../../admin/components/icon.js\"\nimport { IconButton } from \"../../admin/components/icon-button.js\"\nimport { Skeleton } from \"../../admin/components/skeleton.js\"\nimport { formatBytes } from \"../../admin/format.js\"\nimport { FieldShell } from \"../field-shell.js\"\nimport { acceptsType } from \"./reference.js\"\nimport { useMediaLookup, useMediaPicker } from \"./picker-context.js\"\nimport type { FieldError } from \"../../types/entry.js\"\nimport type { FileField, ImageField } from \"../../types/field.js\"\nimport type { MediaReference } from \"../../types/media.js\"\n\n/**\n * The control behind both `image` and `file`.\n *\n * Canonical source: .docs/styleguide/04-components.md section 3.10. The two field types\n * differ in what the picker offers and in whether the item is previewed, and in nothing\n * else, so there is one control rather than two that drift.\n *\n * The rule this control exists to keep: a reference it cannot resolve is shown, named, and\n * saved unchanged. It never calls `onChange` on its own. A media document deleted out from\n * under an entry must not turn into an empty field on the next save, and a broken `<img>`\n * that renders nothing is worse than a sentence saying what happened.\n */\nexport interface MediaFieldInputProps {\n path: string\n field: ImageField | FileField\n value: MediaReference | null\n onChange: (value: MediaReference | null) => void\n onBlur?: (() => void) | undefined\n errors: readonly FieldError[]\n disabled?: boolean | undefined\n readonly?: boolean | undefined\n /** MIME patterns offered to the picker, already defaulted by the field type. */\n accept?: readonly string[] | undefined\n /** Images preview the item; a file shows its type tile instead. */\n preview: boolean\n}\n\nexport function MediaFieldInput({\n path,\n field,\n value,\n onChange,\n onBlur,\n errors,\n disabled = false,\n readonly = false,\n accept,\n preview,\n}: MediaFieldInputProps) {\n const picker = useMediaPicker()\n const lookup = useMediaLookup(value)\n const [busy, setBusy] = useState(false)\n const [rejected, setRejected] = useState<string | null>(null)\n\n const locked = disabled || readonly || field.readonly === true\n const noun = preview ? \"image\" : \"file\"\n\n async function choose() {\n if (picker === null) return\n setBusy(true)\n try {\n const item = await picker.pick({ accept })\n if (item === null) return\n if (!acceptsType(accept, item.type)) {\n // The picker was told what this field accepts; if it offers something else anyway,\n // refusing here is what keeps the schema's promise rather than the picker's.\n setRejected(item.type)\n return\n }\n setRejected(null)\n onChange({ mediaId: item.id, url: item.url })\n onBlur?.()\n } finally {\n setBusy(false)\n }\n }\n\n const missingError: FieldError = {\n path,\n rule: \"reference\",\n message: `This ${noun} is no longer in the media library.`,\n }\n const rejectedError: FieldError = {\n path,\n rule: \"accept\",\n message: `This field does not accept ${rejected ?? \"\"} files.`,\n }\n\n const shown: readonly FieldError[] = [\n ...errors,\n ...(lookup.kind === \"missing\" ? [missingError] : []),\n ...(rejected === null ? [] : [rejectedError]),\n ]\n\n const broken = lookup.kind === \"missing\"\n\n return (\n <FieldShell\n field={field}\n errors={shown}\n help={\n picker === null && lookup.kind !== \"missing\"\n ? `The media library is not available yet. ${\n value === null\n ? `This ${noun} cannot be chosen here.`\n : \"The stored reference is kept as it is.\"\n }`\n : undefined\n }\n >\n {/* A group rather than a single labelled control: this field is a button plus a\n summary, and `Field`'s `htmlFor` would otherwise hand the button the field's label\n as its accessible name. Same composition the multiple `select` uses. */}\n {({ describedBy, invalid }) => (\n <div\n role=\"group\"\n aria-label={field.label}\n aria-describedby={describedBy}\n className={cx(\n \"flex items-center gap-3 rounded-sm border bg-surface-input p-3 state-transition\",\n invalid || broken ? \"border-danger\" : \"border-border-default\",\n )}\n >\n {lookup.kind === \"loading\" ? (\n <>\n <Skeleton className=\"size-16\" label={`Loading the ${noun}`} />\n <div className=\"flex min-w-0 flex-1 flex-col gap-1.5\">\n <Skeleton line=\"body-sm\" className=\"w-40\" />\n <Skeleton line=\"caption\" className=\"w-24\" />\n </div>\n </>\n ) : null}\n\n {lookup.kind === \"found\" ? (\n <>\n {preview && lookup.item.type.startsWith(\"image/\") ? (\n // The alt text of the media item, not of the field: the same image carries\n // the same description everywhere it is used.\n <img\n src={lookup.item.url}\n alt={lookup.item.alt ?? \"\"}\n className=\"size-16 shrink-0 rounded-sm border border-border-subtle object-cover\"\n />\n ) : (\n <span className=\"flex size-16 shrink-0 items-center justify-center rounded-sm bg-surface-raised text-text-muted\">\n <Icon name={preview ? \"media\" : \"singleton\"} size={24} />\n </span>\n )}\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <span className=\"truncate text-body-sm text-text-primary\">\n {lookup.item.name}\n </span>\n <span className=\"text-caption text-text-muted\">\n {lookup.item.type} · {formatBytes(lookup.item.size)}\n </span>\n </div>\n </>\n ) : null}\n\n {broken ? (\n <>\n <span className=\"flex size-16 shrink-0 items-center justify-center rounded-sm bg-danger-muted text-danger\">\n <Icon name=\"warning\" size={24} />\n </span>\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <span className=\"text-body-sm text-text-secondary\">\n The reference is kept, so saving this entry does not lose it.\n </span>\n <span className=\"truncate text-caption text-text-faint\">\n {value?.mediaId}\n </span>\n </div>\n </>\n ) : null}\n\n {lookup.kind === \"unavailable\" && value !== null ? (\n <>\n <span className=\"flex size-16 shrink-0 items-center justify-center rounded-sm bg-surface-raised text-text-faint\">\n <Icon name={preview ? \"media\" : \"singleton\"} size={24} />\n </span>\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <span className=\"text-body-sm text-text-secondary\">\n Stored {noun} reference\n </span>\n <span className=\"truncate text-caption text-text-faint\">\n {value.mediaId}\n </span>\n </div>\n </>\n ) : null}\n\n {value === null ? (\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <span className=\"text-body-sm text-text-faint\">\n {field.placeholder ?? `No ${noun} chosen`}\n </span>\n </div>\n ) : null}\n\n <div className=\"flex shrink-0 items-center gap-2\">\n <Button\n size=\"sm\"\n icon={preview ? \"media\" : \"upload\"}\n loading={busy}\n disabled={locked || picker === null}\n onClick={() => void choose()}\n >\n {value === null ? `Choose ${noun}` : `Replace ${noun}`}\n </Button>\n {value === null ? null : (\n <IconButton\n icon=\"delete\"\n label={`Remove ${noun}`}\n size=\"sm\"\n disabled={locked}\n // The only route out of a broken reference, and a person has to take it.\n onClick={() => {\n setRejected(null)\n onChange(null)\n onBlur?.()\n }}\n />\n )}\n </div>\n </div>\n )}\n </FieldShell>\n )\n}\n","\"use client\"\n\nimport { MediaFieldInput } from \"../media/media-input.js\"\nimport type { FieldInputProps } from \"../../schema/field-type.js\"\nimport type { FileField } from \"../../types/field.js\"\nimport type { MediaReference } from \"../../types/media.js\"\n\n/**\n * The `file` field input: the shared media control without the preview. A PDF has no\n * thumbnail worth showing, so the tile carries its type icon and the name does the work.\n */\nexport function FileFieldInput(props: FieldInputProps<MediaReference, FileField>) {\n return <MediaFieldInput {...props} accept={props.field.accept} preview={false} />\n}\n","import { storedMediaReference } from \"./reference.js\"\nimport type { FieldError } from \"../../types/entry.js\"\nimport type { FieldInputComponent, FieldTypeSpec } from \"../../schema/field-type.js\"\nimport type { FileField, ImageField } from \"../../types/field.js\"\nimport type { MediaReference } from \"../../types/media.js\"\n\n/** What an `image` field offers the picker when its schema names nothing narrower. */\nexport const IMAGE_ACCEPT = [\"image/*\"] as const\n\n/**\n * The spec shared by `image` and `file`.\n *\n * Both store a `MediaReference`, both round trip it the same way, and both validate the\n * same thing. Writing it once is what keeps the two from disagreeing about what an empty\n * reference means. They differ only in the name, the picker default, and the control.\n */\nexport function mediaFieldSpec<TField extends ImageField | FileField>(\n name: TField[\"type\"],\n Input: FieldInputComponent<MediaReference, TField>,\n): FieldTypeSpec<MediaReference, TField> {\n return {\n name,\n\n /**\n * Stores the reference, never the media item.\n *\n * `url` is denormalized for the SDK to read without a second lookup; `mediaId` is the\n * source of truth. Renaming a file or fixing its alt text therefore rewrites one media\n * document, not every entry that points at it.\n */\n toStored: (value) =>\n value === null ? null : { mediaId: value.mediaId, url: value.url },\n\n /**\n * Anything carrying a string `mediaId` is a reference, whatever else it carries.\n *\n * A document written before `url` was denormalized, or edited by hand in the Firestore\n * console, still points at a real item and must survive a round trip. What it does not\n * do is invent a reference out of a value that has no id: that is corrupt data, and the\n * shared validator is there to report it rather than have it quietly become `null`.\n */\n fromStored: (raw) => storedMediaReference(raw),\n\n Input,\n\n /**\n * The shared validator already checks that the value is an object with a `mediaId`,\n * which is everything about the shape. What it cannot see is an id that is blank:\n * `isEmpty` reports `false` for any object, so `{ mediaId: \"\" }` would otherwise pass\n * `required` while pointing at nothing.\n *\n * Whether the id resolves, and whether the item's MIME type satisfies `accept`, are not\n * checked here. Both need the media document, validation runs without a database by\n * design, and a validator that refused an entry because a lookup was unavailable would\n * block saves for a reason that has nothing to do with the entry.\n */\n validate: (value, _rules, ctx, field): FieldError[] => {\n if (value === null || value.mediaId.trim() !== \"\") return []\n\n return [\n {\n path: ctx.path,\n rule: \"reference\",\n message: `${field.label} does not name an item in the media library.`,\n },\n ]\n },\n\n tsType: \"MediaReference\",\n\n /** A new entry starts with no reference; there is no sensible default media item. */\n defaultValue: () => null,\n /**\n * `image` and `file` differ here in wording and in what the picker defaults to, which\n * is the whole reason they are two field types rather than one.\n */\n editor: {\n label: name === \"image\" ? \"Image\" : \"File\",\n description:\n name === \"image\"\n ? \"An image from the media library.\"\n : \"Any file from the media library.\",\n rules: [\"required\"],\n options: [\n {\n key: \"accept\",\n label: \"Accepted types\",\n control: \"string-list\",\n help:\n name === \"image\"\n ? \"MIME types the picker offers. Leave empty for every image type.\"\n : \"MIME types the picker offers. Leave empty for every type.\",\n },\n ],\n defaults: {},\n },\n }\n}\n","import { FileFieldInput } from \"./input.js\"\nimport { mediaFieldSpec } from \"../media/spec.js\"\nimport type { FieldTypeSpec } from \"../../schema/field-type.js\"\nimport type { FileField } from \"../../types/field.js\"\nimport type { MediaReference } from \"../../types/media.js\"\n\n/**\n * Any file from the media library: a PDF, an archive, a document.\n *\n * Shares its whole stored shape and validator with `image` (see `../media/spec.ts`) and\n * differs only in that it previews nothing and offers the picker every MIME type unless\n * the schema narrows it with `accept`.\n */\nexport const fileField: FieldTypeSpec<MediaReference, FileField> = mediaFieldSpec(\n \"file\",\n FileFieldInput,\n)\n","\"use client\"\n\nimport { MediaFieldInput } from \"../media/media-input.js\"\nimport { IMAGE_ACCEPT } from \"../media/spec.js\"\nimport type { FieldInputProps } from \"../../schema/field-type.js\"\nimport type { ImageField } from \"../../types/field.js\"\nimport type { MediaReference } from \"../../types/media.js\"\n\n/**\n * The `image` field input: the shared media control with the preview turned on and the\n * picker narrowed to images unless the schema names something narrower still.\n */\nexport function ImageFieldInput(props: FieldInputProps<MediaReference, ImageField>) {\n return (\n <MediaFieldInput {...props} accept={props.field.accept ?? IMAGE_ACCEPT} preview />\n )\n}\n","import { ImageFieldInput } from \"./input.js\"\nimport { mediaFieldSpec } from \"../media/spec.js\"\nimport type { FieldTypeSpec } from \"../../schema/field-type.js\"\nimport type { ImageField } from \"../../types/field.js\"\nimport type { MediaReference } from \"../../types/media.js\"\n\n/**\n * An image from the media library.\n *\n * Identical to `file` in everything the stored shape and the validator care about; see\n * `../media/spec.ts`. It exists as its own field type because the schema author's\n * intention differs: an `image` field previews its item, defaults its picker to images,\n * and tells a consuming frontend that this value is safe to put in an `<img>`.\n */\nexport const imageField: FieldTypeSpec<MediaReference, ImageField> = mediaFieldSpec(\n \"image\",\n ImageFieldInput,\n)\n","\"use client\"\n\nimport { useState } from \"react\"\n\nimport { TextInput } from \"../../admin/components/field.js\"\nimport type { FieldInputProps } from \"../../schema/field-type.js\"\nimport { FieldShell } from \"../field-shell.js\"\nimport type { NumberField } from \"../../types/field.js\"\n\n/** What the form gets for a given piece of typed text. `-` and `1.` are not numbers yet. */\nfunction parse(text: string): number | null {\n if (text.trim() === \"\") return null\n const parsed = Number(text)\n return Number.isFinite(parsed) ? parsed : null\n}\n\n/**\n * The number input keeps the typed text alongside the parsed value.\n *\n * Rendering `String(value)` straight back would delete the keystroke the moment someone\n * types `-`, `1.` or `0.10`, because none of those survives a parse-and-reformat round\n * trip. The text is the editor's; the number is the form's.\n *\n * The draft is not synchronised with an effect. It is used only while it still parses to\n * the value the form holds, and ignored otherwise, so a value that changes from outside\n * wins without anything having to be reset.\n */\nexport function NumberFieldInput({\n field,\n value,\n onChange,\n onBlur,\n errors,\n disabled = false,\n readonly = false,\n}: FieldInputProps<number, NumberField>) {\n const [draft, setDraft] = useState<string | null>(null)\n const text =\n draft !== null && parse(draft) === value ? draft : value === null ? \"\" : String(value)\n\n function handleChange(next: string) {\n setDraft(next)\n onChange(parse(next))\n }\n\n return (\n <FieldShell field={field} errors={errors}>\n {({ id, describedBy, invalid }) => (\n <TextInput\n id={id}\n type=\"number\"\n inputMode=\"decimal\"\n step={field.step}\n min={field.validation?.min}\n max={field.validation?.max}\n value={text}\n placeholder={field.placeholder}\n invalid={invalid}\n aria-describedby={describedBy}\n disabled={disabled}\n readOnly={readonly || field.readonly === true}\n className=\"text-left tabular-nums\"\n onChange={(event) => handleChange(event.target.value)}\n onBlur={onBlur}\n />\n )}\n </FieldShell>\n )\n}\n","import type { FieldError } from \"../../types/entry.js\"\nimport type { FieldTypeSpec } from \"../../schema/field-type.js\"\nimport type { NumberField } from \"../../types/field.js\"\nimport { storedNumber } from \"../values.js\"\nimport { NumberFieldInput } from \"./input.js\"\n\n/** Floating point leaves 0.1 + 0.2 just off 0.3, so step alignment compares with slack. */\nconst STEP_TOLERANCE = 1e-9\n\nexport const numberField: FieldTypeSpec<number, NumberField> = {\n name: \"number\",\n toStored: (value) => storedNumber(value),\n fromStored: (raw) => storedNumber(raw),\n Input: NumberFieldInput,\n /**\n * `min` and `max` belong to the shared validator. Step alignment is the one numeric rule\n * it cannot express, because the step lives on the field rather than in the rules.\n */\n validate: (value, _rules, ctx, field): FieldError[] => {\n if (value === null) return []\n const step = field.step\n if (step === undefined || step <= 0) return []\n\n const steps = value / step\n if (Math.abs(steps - Math.round(steps)) <= STEP_TOLERANCE) return []\n\n return [\n {\n path: ctx.path,\n rule: \"step\",\n message: `${field.label} must be a multiple of ${step}.`,\n },\n ]\n },\n tsType: \"number\",\n defaultValue: (field) => field.defaultValue ?? null,\n editor: {\n label: \"Number\",\n description: \"A numeric value.\",\n rules: [\"required\", \"min\", \"max\", \"unique\"],\n options: [\n {\n key: \"step\",\n label: \"Step\",\n control: \"number\",\n help: \"The value must be a multiple of this.\",\n },\n { key: \"placeholder\", label: \"Placeholder\", control: \"text\" },\n ],\n defaults: {},\n },\n}\n","\"use client\"\n\nimport { createContext, useContext } from \"react\"\nimport type { ReactNode } from \"react\"\n\nimport type { RelationSource } from \"./source.js\"\n\n/**\n * How the `relation` input reaches entries of another content type.\n *\n * Same seam as the media picker, for the same reason: the field type is written against an\n * interface, and the admin supplies the implementation built over the `CmsAdapter`. Absent\n * context means no picker, and the control then shows the stored references read-only\n * rather than an empty field. A reference is never dropped because nobody was listening.\n */\nconst RelationSourceContext = createContext<RelationSource | null>(null)\n\nexport interface RelationSourceProviderProps {\n value: RelationSource\n children: ReactNode\n}\n\nexport function RelationSourceProvider({ value, children }: RelationSourceProviderProps) {\n return (\n <RelationSourceContext.Provider value={value}>\n {children}\n </RelationSourceContext.Provider>\n )\n}\n\nexport function useRelationSource(): RelationSource | null {\n return useContext(RelationSourceContext)\n}\n","\"use client\"\n\nimport { useEffect, useRef, useState } from \"react\"\n\nimport {\n Badge,\n ENTRY_STATUS_LABEL,\n ENTRY_STATUS_VARIANT,\n} from \"../../admin/components/badge.js\"\nimport { Button } from \"../../admin/components/button.js\"\nimport { EmptyState } from \"../../admin/components/empty-state.js\"\nimport { Icon } from \"../../admin/components/icon.js\"\nimport { Modal } from \"../../admin/components/modal.js\"\nimport { Skeleton } from \"../../admin/components/skeleton.js\"\nimport { TextInput } from \"../../admin/components/field.js\"\nimport { useRelationSource } from \"./source-context.js\"\nimport type { RelationOption } from \"./source.js\"\n\n/** Long enough not to query per keystroke, short enough to feel like typing filters. */\nconst SEARCH_DELAY_MS = 250\n\n/** One page. The picker never asks for the whole content type, at any size. */\nconst PAGE_SIZE = 25\n\ninterface Answer {\n /** The search this answer belongs to, so a stale one is never shown for a newer query. */\n query: string\n items: readonly RelationOption[]\n cursor: string | null\n hasMore: boolean\n failed: boolean\n}\n\nconst EMPTY: readonly RelationOption[] = []\n\nexport interface EntryPickerProps {\n open: boolean\n onClose: () => void\n contentType: string\n /** Already linked, so the same entry cannot be added twice from the picker. */\n chosen: readonly string[]\n onPick: (option: RelationOption) => void\n}\n\n/**\n * The searchable entry picker behind the `relation` field.\n * Canonical source: .docs/styleguide/04-components.md section 3.11.\n *\n * It reads one bounded page at a time and pages forward with a cursor. A content type with\n * thousands of entries costs exactly the same first render as one with three, which is the\n * whole reason the search is a query rather than a filter over a loaded list.\n */\nexport function EntryPicker({\n open,\n onClose,\n contentType,\n chosen,\n onPick,\n}: EntryPickerProps) {\n const source = useRelationSource()\n const [term, setTerm] = useState(\"\")\n const [query, setQuery] = useState(\"\")\n // One answer, carrying the query it belongs to. \"Loading\" is derived from the absence of\n // an answer for the query currently typed, so the effect never sets state synchronously\n // and a slow answer for an abandoned query cannot overwrite a newer one.\n const [answer, setAnswer] = useState<Answer | null>(null)\n const [paging, setPaging] = useState(false)\n // Only the newest request may write state; an earlier, slower answer is discarded.\n const request = useRef(0)\n\n const info = source?.describe(contentType)\n const loading = source !== null && (answer === null || answer.query !== query)\n const options = answer?.query === query ? answer.items : EMPTY\n const failed = !loading && answer?.failed === true\n\n useEffect(() => {\n if (!open) return\n const timer = setTimeout(() => setQuery(term), SEARCH_DELAY_MS)\n return () => clearTimeout(timer)\n }, [open, term])\n\n useEffect(() => {\n if (!open || source === null) return\n const ticket = request.current + 1\n request.current = ticket\n let cancelled = false\n\n source\n .search({ contentType, search: query, limit: PAGE_SIZE })\n .then((page) => {\n if (cancelled || request.current !== ticket) return\n setAnswer({\n query,\n items: page.items,\n cursor: page.cursor,\n hasMore: page.hasMore,\n failed: false,\n })\n })\n .catch(() => {\n if (cancelled || request.current !== ticket) return\n setAnswer({ query, items: EMPTY, cursor: null, hasMore: false, failed: true })\n })\n\n return () => {\n cancelled = true\n }\n }, [open, source, contentType, query])\n\n function loadMore() {\n const cursor = answer?.cursor ?? null\n if (source === null || cursor === null) return\n const ticket = request.current + 1\n request.current = ticket\n setPaging(true)\n\n source\n .search({ contentType, search: query, limit: PAGE_SIZE, cursor })\n .then((page) => {\n if (request.current !== ticket) return\n setPaging(false)\n setAnswer((current) =>\n current === null\n ? current\n : {\n query,\n items: [...current.items, ...page.items],\n cursor: page.cursor,\n hasMore: page.hasMore,\n failed: false,\n },\n )\n })\n .catch(() => {\n if (request.current !== ticket) return\n setPaging(false)\n setAnswer((current) =>\n current === null ? current : { ...current, failed: true },\n )\n })\n }\n\n const noun = info?.label ?? contentType\n\n return (\n <Modal\n open={open}\n onClose={onClose}\n title={`Choose ${noun}`}\n {...(info?.searchable === false\n ? {\n description: `${noun} entries have no title field, so they cannot be searched by name.`,\n }\n : {})}\n width=\"md\"\n >\n <div className=\"flex flex-col gap-4\">\n {info?.searchable === false ? null : (\n <div className=\"relative flex items-center\">\n <span className=\"pointer-events-none absolute start-3 text-text-faint\">\n <Icon name=\"search\" />\n </span>\n <TextInput\n type=\"search\"\n value={term}\n aria-label={`Search ${noun}`}\n placeholder=\"Search by title\"\n className=\"ps-8.5\"\n onChange={(event) => setTerm(event.target.value)}\n />\n </div>\n )}\n\n {failed ? (\n <p\n role=\"alert\"\n className=\"rounded-sm bg-danger-muted px-3 py-2 text-body-sm text-danger\"\n >\n These entries could not be loaded. Nothing has been changed.\n </p>\n ) : null}\n\n {loading ? (\n <div className=\"flex flex-col gap-2\" aria-busy=\"true\">\n <Skeleton line=\"body\" className=\"w-full\" label={`Loading ${noun}`} />\n <Skeleton line=\"body\" className=\"w-full\" />\n <Skeleton line=\"body\" className=\"w-full\" />\n </div>\n ) : null}\n\n {!loading && !failed && options.length === 0 ? (\n <EmptyState\n icon=\"collection\"\n heading=\"Nothing to link\"\n description={\n query === \"\"\n ? `There are no ${noun} entries yet.`\n : `No ${noun} entry starts with what you typed.`\n }\n />\n ) : null}\n\n {options.length === 0 ? null : (\n <ul className=\"flex flex-col\">\n {options.map((option) => {\n const already = chosen.includes(option.id)\n return (\n <li\n key={option.id}\n className=\"border-b border-border-subtle last:border-b-0\"\n >\n <button\n type=\"button\"\n disabled={already}\n onClick={() => onPick(option)}\n className=\"flex w-full cursor-pointer items-center justify-between gap-3 px-2 py-2.5 text-left state-transition hover:bg-surface-hover focus-visible:focus-ring-inset disabled:cursor-not-allowed disabled:text-text-disabled\"\n >\n <span className=\"truncate text-body-sm text-text-primary\">\n {option.title}\n </span>\n <span className=\"flex shrink-0 items-center gap-2\">\n {already ? (\n <span className=\"text-caption text-text-faint\">Linked</span>\n ) : null}\n <Badge variant={ENTRY_STATUS_VARIANT[option.status]}>\n {ENTRY_STATUS_LABEL[option.status]}\n </Badge>\n </span>\n </button>\n </li>\n )\n })}\n </ul>\n )}\n\n {answer?.hasMore === true && !loading ? (\n <div className=\"flex justify-center\">\n <Button size=\"sm\" loading={paging} onClick={loadMore}>\n Load more\n </Button>\n </div>\n ) : null}\n </div>\n </Modal>\n )\n}\n","\"use client\"\n\nimport { useEffect, useState } from \"react\"\n\nimport {\n Badge,\n ENTRY_STATUS_LABEL,\n ENTRY_STATUS_VARIANT,\n} from \"../../admin/components/badge.js\"\nimport { Button } from \"../../admin/components/button.js\"\nimport { cx } from \"../../admin/components/class-names.js\"\nimport { Icon } from \"../../admin/components/icon.js\"\nimport { IconButton } from \"../../admin/components/icon-button.js\"\nimport { Skeleton } from \"../../admin/components/skeleton.js\"\nimport { EntryPicker } from \"./picker.js\"\nimport { FieldShell } from \"../field-shell.js\"\nimport { useRelationSource } from \"./source-context.js\"\nimport type { FieldError } from \"../../types/entry.js\"\nimport type { FieldInputProps } from \"../../schema/field-type.js\"\nimport type { RelationField } from \"../../types/field.js\"\nimport type { RelationOption } from \"./source.js\"\n\ninterface Resolution {\n /** Keyed by id. An id that is absent once `resolving` is false has no entry. */\n byId: ReadonlyMap<string, RelationOption>\n resolving: boolean\n}\n\nconst NOTHING: ReadonlyMap<string, RelationOption> = new Map()\n\n/**\n * Resolves the stored ids to their titles.\n *\n * Only the answer is state, and it carries the id list it is about, so \"resolving\" is\n * derived rather than toggled: nothing has to be reset when the ids change, and an answer\n * that arrives for an older list simply no longer matches what is on screen.\n *\n * The result is never written back into the value. Resolution is a read: a title is what the\n * target entry is called right now, and caching it into this entry would go stale the moment\n * the target is renamed.\n */\nfunction useResolution(contentType: string, ids: readonly string[]): Resolution {\n const source = useRelationSource()\n // A stable string key, so the effect re-runs when the ids change and not when the array\n // identity does. Serialized rather than joined: an entry id is opaque and may contain\n // whatever separator we picked.\n const key = JSON.stringify(ids)\n const [answer, setAnswer] = useState<{\n key: string\n byId: ReadonlyMap<string, RelationOption>\n } | null>(null)\n\n useEffect(() => {\n const wanted = JSON.parse(key) as string[]\n if (source === null || wanted.length === 0) return\n\n let cancelled = false\n source\n .resolve(contentType, wanted)\n .then((options) => {\n if (cancelled) return\n setAnswer({ key, byId: new Map(options.map((option) => [option.id, option])) })\n })\n .catch(() => {\n // A failed lookup is answered as \"resolved nothing\" rather than left spinning. The\n // value is untouched either way, so the worst case is a title that is missing.\n if (!cancelled) setAnswer({ key, byId: NOTHING })\n })\n\n return () => {\n cancelled = true\n }\n }, [source, contentType, key])\n\n if (source === null || ids.length === 0) return { byId: NOTHING, resolving: false }\n if (answer === null || answer.key !== key) return { byId: NOTHING, resolving: true }\n return { byId: answer.byId, resolving: false }\n}\n\n/**\n * What is known about one stored id.\n *\n * `missing` and `unresolvable` are not the same thing and must not look the same. The first\n * means the database answered and the entry is gone; the second means nobody could ask.\n * Rendering a broken state for the second would accuse a perfectly good link of being dead.\n */\ntype RowState = \"resolving\" | \"found\" | \"missing\" | \"unresolvable\"\n\ninterface RowProps {\n id: string\n option: RelationOption | undefined\n state: RowState\n onRemove: (() => void) | undefined\n}\n\nfunction RelationRow({ id, option, state, onRemove }: RowProps) {\n return (\n <li\n className={cx(\n \"flex items-center gap-3 rounded-sm border bg-surface-input px-3 py-2\",\n state === \"missing\" ? \"border-danger\" : \"border-border-default\",\n )}\n >\n {state === \"resolving\" ? (\n <Skeleton line=\"body-sm\" className=\"w-40\" label=\"Resolving the linked entry\" />\n ) : state === \"unresolvable\" ? (\n <span className=\"flex min-w-0 flex-col\">\n <span className=\"text-body-sm text-text-secondary\">Linked entry</span>\n <span className=\"truncate text-caption text-text-faint\">{id}</span>\n </span>\n ) : option === undefined ? (\n <>\n <span className=\"shrink-0 text-danger\">\n <Icon name=\"warning\" size={14} />\n </span>\n <span className=\"flex min-w-0 flex-col\">\n <span className=\"text-body-sm text-text-secondary\">\n This entry no longer exists.\n </span>\n <span className=\"truncate text-caption text-text-faint\">{id}</span>\n </span>\n </>\n ) : (\n <>\n <span className=\"min-w-0 flex-1 truncate text-body-sm text-text-primary\">\n {option.title}\n </span>\n <Badge variant={ENTRY_STATUS_VARIANT[option.status]}>\n {ENTRY_STATUS_LABEL[option.status]}\n </Badge>\n </>\n )}\n <span className=\"ms-auto shrink-0\">\n {onRemove === undefined ? null : (\n <IconButton icon=\"close\" label=\"Remove link\" size=\"sm\" onClick={onRemove} />\n )}\n </span>\n </li>\n )\n}\n\n/**\n * The `relation` field input.\n * Canonical source: .docs/styleguide/04-components.md section 3.11.\n *\n * Three behaviours worth stating.\n *\n * 1. **Referential display.** A linked entry is shown by its title, resolved through\n * `entryTitle` from the target content type, so it reads the same here as it does in the\n * list view and in the dashboard.\n * 2. **Broken reference.** An id that resolves to nothing is shown as a named, explicit\n * missing row carrying the raw id. The control never calls `onChange` to clean it up: an\n * entry deleted out from under this one must not turn into a silently shorter list on the\n * next save. Removing it is a deliberate click.\n * 3. **No source, no damage.** Without a `RelationSourceProvider` the ids are shown as they\n * are stored and the picker is disabled. The field still saves exactly what it holds.\n */\nexport function RelationFieldInput({\n path,\n field,\n value,\n onChange,\n onBlur,\n errors,\n disabled = false,\n readonly = false,\n}: FieldInputProps<string | string[], RelationField>) {\n const source = useRelationSource()\n const [picking, setPicking] = useState(false)\n const many = field.many === true\n const locked = disabled || readonly || field.readonly === true\n\n const ids = many\n ? Array.isArray(value)\n ? value\n : []\n : typeof value === \"string\" && value !== \"\"\n ? [value]\n : []\n\n const { byId, resolving } = useResolution(field.to, ids)\n // Nobody could ask, so nothing is broken. Only an answered lookup can call a link dead.\n const brokenCount =\n resolving || source === null\n ? 0\n : ids.filter((id) => byId.get(id) === undefined).length\n\n function rowState(id: string): RowState {\n if (source === null) return \"unresolvable\"\n if (resolving) return \"resolving\"\n return byId.get(id) === undefined ? \"missing\" : \"found\"\n }\n\n function remove(id: string) {\n onChange(many ? ids.filter((current) => current !== id) : null)\n onBlur?.()\n }\n\n function pick(option: RelationOption) {\n onChange(many ? [...ids.filter((id) => id !== option.id), option.id] : option.id)\n setPicking(false)\n onBlur?.()\n }\n\n const brokenError: FieldError = {\n path,\n rule: \"reference\",\n message:\n brokenCount === 1\n ? `${field.label} links an entry that no longer exists.`\n : `${field.label} links ${brokenCount} entries that no longer exist.`,\n }\n const shown: readonly FieldError[] = [\n ...errors,\n ...(brokenCount > 0 ? [brokenError] : []),\n ]\n\n const label = source?.describe(field.to).label ?? field.to\n const atMax =\n many && field.validation?.maxLength !== undefined\n ? ids.length >= field.validation.maxLength\n : false\n\n return (\n <FieldShell\n field={field}\n errors={shown}\n help={\n source === null\n ? \"Entries of the linked type cannot be browsed here yet. The stored links are kept as they are.\"\n : undefined\n }\n >\n {/* A group, not a single control: `Field`'s `htmlFor` would otherwise give the picker\n button the field's label as its accessible name. */}\n {({ describedBy }) => (\n <div\n role=\"group\"\n aria-label={field.label}\n aria-describedby={describedBy}\n className=\"flex flex-col gap-2\"\n >\n {ids.length === 0 ? null : (\n <ul className=\"flex flex-col gap-2\">\n {ids.map((entryId) => (\n <RelationRow\n key={entryId}\n id={entryId}\n option={byId.get(entryId)}\n state={rowState(entryId)}\n onRemove={locked ? undefined : () => remove(entryId)}\n />\n ))}\n </ul>\n )}\n\n <div>\n <Button\n size=\"sm\"\n icon=\"create\"\n disabled={locked || source === null || atMax}\n onClick={() => setPicking(true)}\n >\n {many\n ? `Link ${label}`\n : ids.length > 0\n ? `Replace ${label}`\n : `Choose ${label}`}\n </Button>\n </div>\n\n {source === null ? null : (\n <EntryPicker\n open={picking}\n onClose={() => setPicking(false)}\n contentType={field.to}\n chosen={ids}\n onPick={pick}\n />\n )}\n </div>\n )}\n </FieldShell>\n )\n}\n","import { entryTitle } from \"../../core/entry-title.js\"\nimport { DEFAULT_PAGE_SIZE, normalizeLimit } from \"../../core/adapter.js\"\nimport type { CmsAdapter, EntryFilter, ListQuery, Page } from \"../../core/adapter.js\"\nimport type { ContentTypeLike } from \"../../types/content-type.js\"\nimport type { Entry, EntryStatus } from \"../../types/entry.js\"\n\n/**\n * Where the `relation` field type gets its entries.\n *\n * The field type never touches Firestore, and it never touches the `CmsAdapter` directly\n * either: it asks this interface, and the admin supplies an implementation. That is what\n * lets the picker be rendered in a test, in the Schema Builder preview, or against a\n * different backend without the field type knowing.\n */\n\n/** One row in the picker: the entry as it is named on screen, not the entry itself. */\nexport interface RelationOption {\n id: string\n title: string\n status: EntryStatus\n}\n\nexport interface RelationSearchRequest {\n contentType: string\n /** Free text. An empty string asks for the first page unfiltered. */\n search: string\n limit?: number\n cursor?: string | null\n}\n\nexport interface RelationTypeInfo {\n /** Singular label of the target type, for \"Choose an Article\". */\n label: string\n /**\n * Whether `search` narrows the result server-side. False when the target type declares\n * no `titleField`, because there is then no field to match against and the picker must\n * say so rather than silently ignore what was typed.\n */\n searchable: boolean\n /** False when the schema names a content type that does not exist. */\n known: boolean\n}\n\nexport interface RelationSource {\n describe(contentType: string): RelationTypeInfo\n search(request: RelationSearchRequest): Promise<Page<RelationOption>>\n /**\n * Resolves stored ids to their display titles. Ids with no entry are absent from the\n * result, which is how the control learns a reference is broken.\n */\n resolve(contentType: string, ids: readonly string[]): Promise<readonly RelationOption[]>\n}\n\n/** Sorts after every printable character, which is what makes the range a prefix match. */\nconst PREFIX_END = \"\"\n\nexport interface RelationSourceOptions {\n adapter: CmsAdapter\n /** The content type registry, as a lookup. Unknown slugs return undefined. */\n getType: (slug: string) => ContentTypeLike | undefined\n}\n\nfunction optionFrom(type: ContentTypeLike, entry: Entry): RelationOption {\n return { id: entry.id, title: entryTitle(type, entry), status: entry.status }\n}\n\n/**\n * The real source, over the adapter.\n *\n * Two things it deliberately does not do.\n *\n * It never lists a whole content type. Every read is one bounded page with a cursor, so a\n * picker over a type with fifty thousand entries costs the same as one over ten. The\n * search is a prefix range on the type's `titleField`, which Firestore answers from the\n * automatic single-field index; it is therefore case-sensitive and matches from the start\n * of the title, and `describe()` reports when it cannot narrow at all so the picker can say\n * so instead of appearing to ignore the box.\n *\n * It never resolves more ids than it was given. A single relation asks about one id and a\n * `many` relation asks about the ids already stored on the entry, which the field's\n * `maxLength` bounds. Nothing here fans out per customer project.\n */\nexport function relationSourceFromAdapter({\n adapter,\n getType,\n}: RelationSourceOptions): RelationSource {\n return {\n describe(contentType) {\n const type = getType(contentType)\n if (type === undefined) {\n return { label: contentType, searchable: false, known: false }\n }\n return {\n label: type.label,\n searchable: type.titleField !== undefined,\n known: true,\n }\n },\n\n async search({ contentType, search, limit, cursor }) {\n const type = getType(contentType)\n if (type === undefined) return { items: [], cursor: null, hasMore: false }\n\n const titleField = type.titleField\n const term = search.trim()\n const filters: EntryFilter[] =\n term === \"\" || titleField === undefined\n ? []\n : [\n { field: titleField, op: \">=\", value: term },\n { field: titleField, op: \"<=\", value: `${term}${PREFIX_END}` },\n ]\n\n const query: ListQuery = {\n filters,\n // Sorting by the field being range-filtered is a Firestore requirement, not a\n // preference: a range filter forces the first orderBy onto the same field.\n ...(titleField === undefined\n ? type.defaultSort === undefined\n ? {}\n : { sort: type.defaultSort }\n : { sort: { field: titleField, direction: \"asc\" as const } }),\n limit: normalizeLimit(limit ?? DEFAULT_PAGE_SIZE),\n cursor: cursor ?? null,\n // The admin picks from drafts as well: an editor linking an article that is not\n // published yet is normal, and the SDK filters by status on the way out anyway.\n status: \"any\",\n }\n\n const page = await adapter.list(contentType, query)\n\n return {\n items: page.items.map((entry) => optionFrom(type, entry)),\n cursor: page.cursor,\n hasMore: page.hasMore,\n }\n },\n\n async resolve(contentType, ids) {\n const type = getType(contentType)\n if (type === undefined || ids.length === 0) return []\n\n const found = await Promise.all(\n ids.map(async (id) => {\n try {\n return await adapter.get(contentType, id)\n } catch {\n // A failed read is not proof the entry is gone, but the control has to render\n // something. It renders the broken state, which keeps the value.\n return null\n }\n }),\n )\n\n return found\n .filter((entry): entry is Entry => entry !== null)\n .map((entry) => optionFrom(type, entry))\n },\n }\n}\n","import { RelationFieldInput } from \"./input.js\"\nimport { storedString, storedStrings } from \"../values.js\"\nimport type { FieldError } from \"../../types/entry.js\"\nimport type { FieldTypeSpec } from \"../../schema/field-type.js\"\nimport type { RelationField } from \"../../types/field.js\"\n\n/**\n * A reference to one or many entries of another content type.\n *\n * The stored value is the entry id, and nothing else. No denormalized title, no embedded\n * copy of the entry: a relation that cached what it pointed at would go stale the moment\n * the target was renamed, and every entry holding it would have to be rewritten to fix it.\n * The title shown in the admin is resolved at render time through `entryTitle`, from the\n * same content type definition the list view uses, so an entry is never called two\n * different things on two screens.\n *\n * That also keeps the promise a consuming frontend needs: `cms.collection(\"posts\")` returns\n * `author: string`, and one further `cms.collection(\"authors\").findById(author)` resolves\n * it. No bespoke query per customer project, and no join the SDK cannot express.\n */\nexport const relationField: FieldTypeSpec<string | string[], RelationField> = {\n name: \"relation\",\n\n toStored: (value, field) =>\n field.many === true ? storedStrings(value) : storedString(value),\n\n /**\n * An id whose entry has since been deleted still round trips. Whether it resolves is a\n * question only the database can answer, it is asked once by the input, and the answer\n * never changes the value: see the broken-reference state in `input.tsx`.\n */\n fromStored: (raw, field) =>\n field.many === true ? storedStrings(raw) : storedString(raw),\n\n Input: RelationFieldInput,\n\n /**\n * Two things the shared validator cannot see.\n *\n * A blank id passes its shape check (`typeof value === \"string\"`) while pointing at\n * nothing, and the same entry linked twice is not a set. Whether an id resolves is\n * deliberately not checked: validation runs without a database, in the form and again in\n * the adapter, and refusing a save because a lookup was unavailable would block an edit\n * for a reason that has nothing to do with the edit.\n */\n validate: (value, _rules, ctx, field): FieldError[] => {\n const errors: FieldError[] = []\n const ids = typeof value === \"string\" ? [value] : Array.isArray(value) ? value : []\n\n if (ids.some((id) => id.trim() === \"\")) {\n errors.push({\n path: ctx.path,\n rule: \"reference\",\n message: `${field.label} has a reference that names no entry.`,\n })\n }\n\n if (field.many === true && new Set(ids).size !== ids.length) {\n errors.push({\n path: ctx.path,\n rule: \"duplicate\",\n message: `${field.label} links the same entry twice.`,\n })\n }\n\n return errors\n },\n\n // Narrowed on `many`, so codegen over a database-defined type says what\n // `FieldValue<TField>` already says for a code-defined one.\n tsType: (field) => (field.many === true ? \"string[]\" : \"string\"),\n\n defaultValue: (field) => (field.many === true ? [] : null),\n editor: {\n label: \"Relation\",\n description: \"A reference to one or more entries of another content type.\",\n rules: [\"required\"],\n options: [\n {\n key: \"to\",\n label: \"Target content type\",\n control: \"content-type\",\n required: true,\n },\n {\n key: \"many\",\n label: \"Allow several\",\n control: \"boolean\",\n help: \"Stores a list of ids instead of one. Changing it changes how every entry is stored.\",\n },\n ],\n // Deliberately empty rather than guessing at a target: a relation pointing at the\n // wrong content type looks configured and reads nothing.\n defaults: { to: \"\" },\n },\n}\n\nexport { relationSourceFromAdapter } from \"./source.js\"\nexport type {\n RelationOption,\n RelationSearchRequest,\n RelationSource,\n RelationSourceOptions,\n RelationTypeInfo,\n} from \"./source.js\"\nexport { RelationSourceProvider, useRelationSource } from \"./source-context.js\"\nexport type { RelationSourceProviderProps } from \"./source-context.js\"\n","import { moveItem } from \"../../core/reorder.js\"\nimport type { FieldTypeRegistry } from \"../../schema/field-type.js\"\nimport type { FieldMap } from \"../../types/field.js\"\n\n/**\n * Row helpers for the `repeater` field type. Pure, so the reorder logic the keyboard and\n * the drag handle share is testable without rendering anything.\n */\n\n/** A row the form can edit. Anything else stored in the array is kept but not editable. */\nexport type RepeaterRow = Record<string, unknown>\n\nexport function isRow(value: unknown): value is RepeaterRow {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\n/**\n * Moves one row, returning a new array.\n *\n * Delegates to `moveItem` in core, which the Schema Builder's field editor uses as well, so\n * a repeater row and a schema field cannot disagree about what a move is.\n */\nexport function moveRow<TRow>(rows: readonly TRow[], from: number, to: number): TRow[] {\n return moveItem(rows, from, to)\n}\n\n/**\n * A new row, with each nested field at its own field type's default.\n *\n * The registry arrives as an argument rather than as an import. A spec that imported the\n * registry would close a cycle, because the registry imports every spec; and a nested field\n * type that is not registered simply starts at `null`, which is what every field type reads\n * as empty anyway.\n */\nexport function emptyRow(fields: FieldMap, registry: FieldTypeRegistry): RepeaterRow {\n const row: RepeaterRow = {}\n\n for (const [key, field] of Object.entries(fields)) {\n const spec = registry.get(field.type)\n row[key] = spec === undefined ? null : spec.defaultValue(field)\n }\n\n return row\n}\n","\"use client\"\n\nimport { useState } from \"react\"\nimport type { DragEvent } from \"react\"\n\nimport { Button } from \"../../admin/components/button.js\"\nimport { cx } from \"../../admin/components/class-names.js\"\nimport { Icon } from \"../../admin/components/icon.js\"\nimport { IconButton } from \"../../admin/components/icon-button.js\"\nimport { Tooltip } from \"../../admin/components/tooltip.js\"\nimport { emptyRow, isRow, moveRow } from \"./rows.js\"\nimport { FieldShell } from \"../field-shell.js\"\n// The registry, imported by the one field type that contains other field types. This closes\n// a module cycle (the registry imports every spec, including this one), which is safe here\n// and only here: `fieldTypes` is read inside the component body, long after every module in\n// the cycle has finished evaluating. Reading it at module scope would not be safe, and\n// nothing in this file does.\nimport { fieldTypes } from \"../index.js\"\nimport type { FieldError } from \"../../types/entry.js\"\nimport type { FieldInputProps } from \"../../schema/field-type.js\"\nimport type { RepeaterField } from \"../../types/field.js\"\n\n/**\n * Row identity, so reordering moves a row rather than moving its values between rows.\n *\n * The stored value is a plain array with nothing to key on, and an index key would leave a\n * nested rich text editor showing the previous row's document after a move, because it\n * reads its content once on mount.\n */\n/**\n * `DragEvent.dataTransfer` is `DataTransfer | null` in the DOM specification, but React's\n * types declare it always present. Narrowing it back is what keeps a drag event dispatched\n * without one from throwing outside React, where nothing catches it.\n */\nfunction dataTransferOf(event: DragEvent<HTMLElement>): DataTransfer | undefined {\n const transfer: DataTransfer | undefined | null = event.dataTransfer\n return transfer ?? undefined\n}\n\nlet keySeed = 0\nfunction nextKey(): string {\n keySeed += 1\n return `row-${keySeed}`\n}\n\n/**\n * The `repeater` field input.\n * Canonical source: .docs/styleguide/04-components.md section 3.12.\n *\n * Nested fields are rendered through the registry, never through a switch: this component\n * does not know that `date` or `richtext` exist, and a field type added later works inside\n * a repeater on the day it is registered, with no edit here.\n *\n * Reordering is available two ways, and the keyboard one is not a fallback. A pointer drag\n * is unusable for anyone who cannot drag, so the handle is a real button that answers to\n * the arrow keys, moves focus with the row it moved, and announces the new position.\n */\nexport function RepeaterFieldInput({\n path,\n field,\n value,\n onChange,\n onBlur,\n errors,\n disabled = false,\n readonly = false,\n}: FieldInputProps<unknown[], RepeaterField>) {\n const rows: readonly unknown[] = Array.isArray(value) ? value : []\n const locked = disabled || readonly || field.readonly === true\n\n const [keys, setKeys] = useState<string[]>(() => rows.map(() => nextKey()))\n const [dragging, setDragging] = useState<number | null>(null)\n const [announcement, setAnnouncement] = useState(\"\")\n\n // The value can also change from outside this control: a reload, a discard, a server\n // response. Keys follow the length rather than fight it; identity is only worth keeping\n // for the edits this control made itself.\n if (keys.length !== rows.length) {\n setKeys(rows.map((_, index) => keys[index] ?? nextKey()))\n }\n\n function commit(nextRows: unknown[], nextKeys: string[]) {\n setKeys(nextKeys)\n onChange(nextRows)\n onBlur?.()\n }\n\n function add() {\n commit([...rows, emptyRow(field.fields, fieldTypes)], [...keys, nextKey()])\n }\n\n function removeAt(index: number) {\n commit(\n rows.filter((_, current) => current !== index),\n keys.filter((_, current) => current !== index),\n )\n }\n\n function move(from: number, to: number) {\n if (to < 0 || to >= rows.length || from === to) return\n commit(moveRow(rows, from, to), moveRow(keys, from, to))\n setAnnouncement(\n `${field.label} ${from + 1} moved to position ${to + 1} of ${rows.length}.`,\n )\n // Focus is not restored by hand. The rows are keyed by identity, so React moves the\n // existing DOM node rather than rebuilding it, and the focused handle travels with the\n // row it just moved. That is also why the keys exist at all.\n }\n\n function setCell(index: number, key: string, next: unknown) {\n onChange(\n rows.map((row, current) =>\n current === index ? { ...(isRow(row) ? row : {}), [key]: next } : row,\n ),\n )\n }\n\n /** This field's own errors. A row's and a cell's belong to the row and the cell. */\n const own = errors.filter((error) => error.path === path)\n function under(prefix: string): FieldError[] {\n return errors.filter(\n (error) => error.path === prefix || error.path.startsWith(`${prefix}.`),\n )\n }\n\n const atMax = field.max !== undefined && rows.length >= field.max\n const atMin = field.min !== undefined && rows.length <= field.min\n\n return (\n <FieldShell field={field} errors={own}>\n {/* A group, not a single control: `Field`'s `htmlFor` would otherwise give the add\n button the field's label as its accessible name. */}\n {({ id, describedBy }) => (\n <div\n role=\"group\"\n aria-label={field.label}\n aria-describedby={describedBy}\n className=\"flex flex-col gap-3\"\n >\n <p id={`${id}-reorder`} className=\"sr-only\">\n Press the up and down arrow keys to move this entry.\n </p>\n <p aria-live=\"polite\" className=\"sr-only\">\n {announcement}\n </p>\n\n {rows.length === 0 ? (\n <p className=\"rounded-sm border border-border-subtle bg-surface-input px-3 py-4 text-center text-body-sm text-text-faint\">\n {field.placeholder ?? \"No entries yet.\"}\n </p>\n ) : (\n <ul className=\"flex flex-col gap-3\">\n {rows.map((row, index) => {\n const rowErrors = under(`${path}.${index}`)\n const readable = isRow(row)\n\n return (\n <li\n key={keys[index] ?? index}\n onDragOver={(event) => {\n if (dragging === null) return\n event.preventDefault()\n // `DragEvent.dataTransfer` is nullable in the DOM specification even\n // though React's types declare it present, and it really is absent on\n // a drag event dispatched without one. Reading through it unguarded\n // throws outside React's error boundary, which no assertion catches.\n const transfer = dataTransferOf(event)\n if (transfer !== undefined) transfer.dropEffect = \"move\"\n }}\n onDrop={(event) => {\n if (dragging === null) return\n event.preventDefault()\n move(dragging, index)\n setDragging(null)\n }}\n className={cx(\n \"overflow-hidden rounded-sm border bg-surface-card state-transition\",\n dragging === index\n ? \"cursor-grabbing border-border-active\"\n : readable\n ? \"border-border-default\"\n : \"border-danger\",\n )}\n >\n <div className=\"flex items-center gap-2 border-b border-border-subtle bg-surface-raised px-2 py-1.5\">\n {/* Icon-only: the guide requires a tooltip as well as a name. */}\n <Tooltip content=\"Drag to reorder, or press the up and down arrow keys\">\n <button\n type=\"button\"\n draggable={!locked}\n disabled={locked}\n aria-label={`Reorder ${field.label} ${index + 1}`}\n aria-describedby={`${id}-reorder`}\n onDragStart={(event) => {\n setDragging(index)\n const transfer = dataTransferOf(event)\n if (transfer === undefined) return\n transfer.effectAllowed = \"move\"\n transfer.setData(\"text/plain\", String(index))\n }}\n onDragEnd={() => setDragging(null)}\n onKeyDown={(event) => {\n if (event.key === \"ArrowUp\") {\n event.preventDefault()\n move(index, index - 1)\n } else if (event.key === \"ArrowDown\") {\n event.preventDefault()\n move(index, index + 1)\n }\n }}\n className=\"flex size-7.5 shrink-0 cursor-grab items-center justify-center rounded-sm text-text-muted state-transition hover:bg-surface-hover hover:text-text-primary focus-visible:focus-ring active:cursor-grabbing disabled:cursor-not-allowed disabled:text-text-disabled\"\n >\n <Icon name=\"drag-handle\" size={14} />\n </button>\n </Tooltip>\n\n <span className=\"min-w-0 flex-1 truncate text-label text-text-secondary\">\n {field.label} {index + 1}\n </span>\n\n <IconButton\n icon=\"delete\"\n label={`Remove ${field.label} ${index + 1}`}\n size=\"sm\"\n disabled={locked || atMin}\n onClick={() => removeAt(index)}\n />\n </div>\n\n {readable ? (\n <div className=\"flex flex-col gap-5 p-3\">\n {Object.entries(field.fields).map(([key, nested]) => {\n if (nested.hidden === true) return null\n\n const spec = fieldTypes.get(nested.type)\n if (spec === undefined) {\n return (\n <p key={key} className=\"text-body-sm text-text-muted\">\n {nested.label} uses the field type "{nested.type}\n ", which this version cannot render.\n </p>\n )\n }\n\n const NestedInput = spec.Input\n return (\n <NestedInput\n key={key}\n path={`${path}.${index}.${key}`}\n field={nested}\n value={row[key] ?? null}\n onChange={(next: unknown) => setCell(index, key, next)}\n onBlur={onBlur}\n errors={under(`${path}.${index}.${key}`)}\n disabled={locked}\n readonly={readonly || field.readonly === true}\n />\n )\n })}\n </div>\n ) : (\n // Same principle as the unreadable rich text document: what cannot be\n // opened is shown, kept, and saved unchanged rather than replaced with\n // an empty row that would overwrite it.\n <div className=\"flex flex-col gap-1 p-3\">\n <p className=\"text-body-sm text-text-secondary\">\n This entry cannot be opened here and is kept exactly as it is\n stored.\n </p>\n <p className=\"text-caption text-text-faint\">\n Remove it only if you mean to lose it.\n </p>\n </div>\n )}\n\n {rowErrors.length === 0 || readable ? null : (\n <p className=\"border-t border-border-subtle px-3 py-2 text-caption text-danger\">\n {rowErrors[0]?.message}\n </p>\n )}\n </li>\n )\n })}\n </ul>\n )}\n\n <div>\n <Button size=\"sm\" icon=\"create\" disabled={locked || atMax} onClick={add}>\n Add {field.label}\n </Button>\n </div>\n </div>\n )}\n </FieldShell>\n )\n}\n","import { RepeaterFieldInput } from \"./input.js\"\nimport { isRow } from \"./rows.js\"\nimport type { FieldError } from \"../../types/entry.js\"\nimport type { FieldTypeSpec } from \"../../schema/field-type.js\"\nimport type { RepeaterField } from \"../../types/field.js\"\n\n/** A key that can be written bare in a TypeScript object type. */\nconst PLAIN_KEY = /^[A-Za-z_$][A-Za-z0-9_$]*$/\n\nfunction tsKey(key: string): string {\n return PLAIN_KEY.test(key) ? key : JSON.stringify(key)\n}\n\n/**\n * A repeating set of nested fields: the CMS answer to \"a page has several teaser blocks\".\n *\n * Every layer of this field type is the same layer applied one level down. The rows round\n * trip through the nested fields' own specs, the validator walks into each row, the input\n * renders each nested field through the registry, and `tsType` names the object a row\n * actually holds. Nothing here knows what a text field or a date field is.\n *\n * Two deliberate refusals.\n *\n * It does not flatten. A row is stored as a map from field key to value, exactly as a\n * top-level entry is, so `entry.blocks[0].heading` in a customer frontend reads the same as\n * `entry.heading`, with no bespoke unpacking per project.\n *\n * It does not repair. A row that is not an object is kept verbatim rather than replaced\n * with `null` or dropped: the shared validator already reports it as an invalid row, and\n * turning corrupt data into an empty row would destroy exactly the evidence needed to fix\n * it. The input renders such a row as an unreadable row and offers no editor for it.\n */\nexport const repeaterField: FieldTypeSpec<unknown[], RepeaterField> = {\n name: \"repeater\",\n\n toStored: (value, field, nested) => {\n if (!Array.isArray(value)) return null\n return value.map((row) =>\n isRow(row) && nested !== undefined ? nested.toStored(field.fields, row) : row,\n )\n },\n\n fromStored: (raw, field, nested) => {\n if (!Array.isArray(raw)) return null\n return raw.map((row) =>\n isRow(row) && nested !== undefined ? nested.fromStored(field.fields, row) : row,\n )\n },\n\n Input: RepeaterFieldInput,\n\n /**\n * Row counts, which are the repeater's own `min` and `max` rather than the shared\n * `ValidationRules` keys. `checkRules` reads `min` and `max` as numeric bounds on a\n * number and never applies them to an array, and `minLength`/`maxLength` are already\n * checked there for the list length, so this is the only place `field.min` is enforced.\n *\n * Nothing here walks into the rows: `validateEntry` does that itself, with the same rules\n * and the same field type specs, so a nested field is validated exactly once.\n */\n validate: (value, _rules, ctx, field): FieldError[] => {\n if (!Array.isArray(value)) return []\n\n const errors: FieldError[] = []\n\n if (field.min !== undefined && value.length < field.min) {\n errors.push({\n path: ctx.path,\n rule: \"min\",\n message: `${field.label} needs at least ${field.min} ${\n field.min === 1 ? \"entry\" : \"entries\"\n }.`,\n })\n }\n if (field.max !== undefined && value.length > field.max) {\n errors.push({\n path: ctx.path,\n rule: \"max\",\n message: `${field.label} allows at most ${field.max} ${\n field.max === 1 ? \"entry\" : \"entries\"\n }.`,\n })\n }\n\n return errors\n },\n\n /**\n * The row object, named field by field through the same resolver.\n *\n * This is why `tsType` had to stop being a static string. A repeater's SDK type is not\n * knowable from the field type; it is knowable only from this field's nested map, and for\n * a content type created in the Schema Builder that map exists only at runtime.\n */\n tsType: (field, resolve) => {\n const members = Object.entries(field.fields).map(([key, nested]) => {\n const nullable = nested.validation?.required === true ? \"\" : \" | null\"\n return `${tsKey(key)}: ${resolve(nested)}${nullable}`\n })\n\n return members.length === 0\n ? \"Record<string, never>[]\"\n : `{ ${members.join(\"; \")} }[]`\n },\n\n /** A new entry starts with no rows, not with one empty row nobody asked for. */\n defaultValue: () => [],\n editor: {\n label: \"Repeater\",\n description: \"A repeating group of fields, for example a list of teasers.\",\n rules: [],\n options: [\n { key: \"fields\", label: \"Fields\", control: \"fields\", required: true },\n { key: \"min\", label: \"Minimum entries\", control: \"number\" },\n { key: \"max\", label: \"Maximum entries\", control: \"number\" },\n ],\n defaults: { fields: { text: { type: \"text\", label: \"Text\" } } },\n },\n}\n\nexport { emptyRow, isRow, moveRow } from \"./rows.js\"\nexport type { RepeaterRow } from \"./rows.js\"\n","/**\n * The Husk rich text schema, as plain data.\n *\n * This is the contract `format: \"husk-richtext-v1\"` names. It is the full set of ProseMirror\n * node and mark types a stored document may contain, and it does not change with a field's\n * `features` list: see .docs/decisions/2026-09-18-richtext-editor.md. Adding a name here is a\n * format change and needs `husk-richtext-v2` plus a migration, not an edit.\n *\n * It lives in its own module with no imports, because two very different callers need it.\n * `document.ts` checks a stored document against it on the server, where dragging in the\n * editor's extension modules would put ProseMirror into a bundle that never renders an\n * editor; `extensions.ts` builds the matching extension array in the browser.\n */\n\nexport const RICHTEXT_FORMAT = \"husk-richtext-v1\"\n\nexport const RICHTEXT_NODES = [\n \"doc\",\n \"paragraph\",\n \"text\",\n \"heading\",\n \"bulletList\",\n \"orderedList\",\n \"listItem\",\n \"blockquote\",\n \"hardBreak\",\n] as const\n\nexport const RICHTEXT_MARKS = [\"bold\", \"italic\", \"strike\", \"link\"] as const\n\n/** The only heading levels in the schema. A rich text field is body copy, not a page. */\nexport const RICHTEXT_HEADING_LEVELS = [2, 3] as const\n\nexport type RichtextNodeName = (typeof RICHTEXT_NODES)[number]\nexport type RichtextMarkName = (typeof RICHTEXT_MARKS)[number]\n\n/**\n * What a `RichtextField.features` list may name.\n *\n * A feature hides a toolbar control. It never removes a node or a mark from the schema, so a\n * document written while a feature was on stays readable, storable and renderable after it is\n * switched off. Undo and redo are not features: an editor always gets them.\n */\nexport const RICHTEXT_FEATURES = [\n \"bold\",\n \"italic\",\n \"strike\",\n \"heading\",\n \"blockquote\",\n \"bulletList\",\n \"orderedList\",\n \"link\",\n] as const\n\nexport type RichtextFeature = (typeof RICHTEXT_FEATURES)[number]\n\nexport function isRichtextFeature(value: string): value is RichtextFeature {\n return (RICHTEXT_FEATURES as readonly string[]).includes(value)\n}\n\n/**\n * Resolves the feature list a field asks for.\n *\n * An absent list means every feature, per `RichtextField`. An unknown name is dropped rather\n * than thrown on, because the Schema Builder lets an editor type one in and a typo must not\n * take the entry form down. An empty result is legitimate: a field with `features: []` is a\n * plain-paragraph field, and the toolbar still renders undo and redo.\n */\nexport function resolveFeatures(\n features: readonly string[] | undefined,\n): readonly RichtextFeature[] {\n if (features === undefined) return RICHTEXT_FEATURES\n return features.filter(isRichtextFeature)\n}\n","import { RICHTEXT_FORMAT, RICHTEXT_MARKS, RICHTEXT_NODES } from \"./schema.js\"\nimport type { RichTextValue } from \"../../types/field.js\"\n\n/**\n * Reading a stored rich text document without the editor.\n *\n * Everything here is a pure function over JSON, so the server can answer the same questions\n * the browser does without loading ProseMirror, and so the answers are testable in the node\n * project rather than only through a mounted editor.\n *\n * The rule the whole module exists for: nothing here ever rewrites a document it does not\n * understand. Reading an unreadable document reports why; it does not repair, truncate, or\n * empty it. See .docs/decisions/2026-09-18-richtext-editor.md.\n */\n\n/** A ProseMirror node in Tiptap's JSON form, which is what `RichTextValue.content` holds. */\nexport interface RichTextNodeJSON {\n type?: string\n attrs?: Record<string, unknown>\n content?: RichTextNodeJSON[]\n marks?: { type: string; attrs?: Record<string, unknown> }[]\n text?: string\n}\n\n/** Node types that carry no meaning of their own when they hold no text. */\nconst STRUCTURAL_ONLY = new Set([\"doc\", \"paragraph\", \"text\", \"hardBreak\"])\n\n/** Node types that end a line when their text is read out. */\nconst BLOCK_NODES = new Set([\"paragraph\", \"heading\", \"listItem\", \"blockquote\"])\n\nconst NODE_NAMES: ReadonlySet<string> = new Set(RICHTEXT_NODES)\nconst MARK_NAMES: ReadonlySet<string> = new Set(RICHTEXT_MARKS)\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\n/** The document a new rich text field starts on, and the one the editor produces when cleared. */\nexport function emptyRichTextContent(): RichTextNodeJSON {\n return { type: \"doc\", content: [{ type: \"paragraph\" }] }\n}\n\n/** Whether a stored value is the `husk-richtext-v1` envelope, regardless of what is inside it. */\nexport function isRichTextValue(raw: unknown): raw is RichTextValue {\n return isRecord(raw) && raw[\"format\"] === RICHTEXT_FORMAT && \"content\" in raw\n}\n\n/**\n * The document's text, with block boundaries as newlines.\n *\n * This is what `minLength` and `maxLength` measure. Counting the JSON, or the rendered HTML,\n * would count markup an editor never typed and cannot see.\n */\nexport function richTextToPlainText(content: unknown): string {\n if (!isRecord(content)) return \"\"\n\n const parts: string[] = []\n\n function walk(node: Record<string, unknown>): void {\n if (typeof node[\"text\"] === \"string\") parts.push(node[\"text\"])\n else if (node[\"type\"] === \"hardBreak\") parts.push(\"\\n\")\n\n const children = node[\"content\"]\n if (Array.isArray(children)) {\n for (const child of children) if (isRecord(child)) walk(child)\n }\n\n // A block ends a line, so two paragraphs do not measure as one run-on word.\n if (typeof node[\"type\"] === \"string\" && BLOCK_NODES.has(node[\"type\"]))\n parts.push(\"\\n\")\n }\n\n walk(content)\n return parts\n .join(\"\")\n .replace(/\\n{2,}/g, \"\\n\")\n .replace(/^\\n+|\\n+$/g, \"\")\n}\n\n/**\n * Whether the document says nothing.\n *\n * The editor's cleared state is `{ type: \"doc\", content: [{ type: \"paragraph\" }] }`, not an\n * absent value, and the shared validator's `isEmpty` reports `false` for any object. Without\n * this, `required` on a rich text field would be unenforceable. A structure an editor built\n * deliberately, an empty list or an empty quote, is not empty even when it holds no text.\n */\nexport function isEmptyRichTextContent(content: unknown): boolean {\n if (!isRecord(content)) return true\n if (richTextToPlainText(content).trim() !== \"\") return false\n\n let structuralOnly = true\n function walk(node: Record<string, unknown>): void {\n const type = node[\"type\"]\n if (typeof type === \"string\" && !STRUCTURAL_ONLY.has(type)) structuralOnly = false\n const children = node[\"content\"]\n if (Array.isArray(children)) {\n for (const child of children) if (isRecord(child)) walk(child)\n }\n }\n walk(content)\n\n return structuralOnly\n}\n\nexport type RichTextReadState =\n { kind: \"readable\"; content: RichTextNodeJSON } | { kind: \"unreadable\"; reason: string }\n\n/**\n * Can this document be opened in the editor without losing anything?\n *\n * Every node and mark name has to be one the Husk schema declares. A name outside it would be\n * dropped silently by ProseMirror on parse, and the next save would write the stripped version\n * over the original. Reporting it instead is the entire point.\n *\n * `null` is readable: an unset field opens on an empty document.\n */\nexport function inspectRichText(value: RichTextValue | null): RichTextReadState {\n if (value === null) return { kind: \"readable\", content: emptyRichTextContent() }\n\n const { content } = value\n if (!isRecord(content)) {\n return { kind: \"unreadable\", reason: \"its content is not a document\" }\n }\n if (content[\"type\"] !== \"doc\") {\n return {\n kind: \"unreadable\",\n reason:\n typeof content[\"type\"] === \"string\"\n ? `it starts with \"${content[\"type\"]}\" instead of a document`\n : \"it has no document at its root\",\n }\n }\n\n const unknown = findUnknownName(content)\n if (unknown !== null) {\n return {\n kind: \"unreadable\",\n reason: `it uses ${unknown}, which this version cannot open`,\n }\n }\n\n return { kind: \"readable\", content: content as RichTextNodeJSON }\n}\n\nfunction findUnknownName(node: Record<string, unknown>): string | null {\n const type = node[\"type\"]\n if (typeof type !== \"string\") return \"a node with no type\"\n if (!NODE_NAMES.has(type)) return `the node type \"${type}\"`\n\n const marks = node[\"marks\"]\n if (Array.isArray(marks)) {\n for (const mark of marks) {\n if (!isRecord(mark)) return \"a mark with no type\"\n const markType = mark[\"type\"]\n if (typeof markType !== \"string\") return \"a mark with no type\"\n if (!MARK_NAMES.has(markType)) return `the mark \"${markType}\"`\n }\n }\n\n const children = node[\"content\"]\n if (Array.isArray(children)) {\n for (const child of children) {\n if (!isRecord(child)) return \"a node that is not an object\"\n const found = findUnknownName(child)\n if (found !== null) return found\n }\n }\n\n return null\n}\n","import Blockquote from \"@tiptap/extension-blockquote\"\nimport Bold from \"@tiptap/extension-bold\"\nimport Document from \"@tiptap/extension-document\"\nimport HardBreak from \"@tiptap/extension-hard-break\"\nimport Heading from \"@tiptap/extension-heading\"\nimport Italic from \"@tiptap/extension-italic\"\nimport Link from \"@tiptap/extension-link\"\nimport Paragraph from \"@tiptap/extension-paragraph\"\nimport Strike from \"@tiptap/extension-strike\"\nimport Text from \"@tiptap/extension-text\"\nimport { BulletList, ListItem, OrderedList } from \"@tiptap/extension-list\"\nimport { UndoRedo } from \"@tiptap/extensions\"\nimport type { Extensions } from \"@tiptap/core\"\n\nimport { RICHTEXT_HEADING_LEVELS } from \"./schema.js\"\n\n/**\n * The Husk rich text schema as Tiptap extensions.\n *\n * Written out one extension at a time rather than composed from `@tiptap/starter-kit`. The\n * list defines the stored format, so it has to be something this repo changes deliberately:\n * `StarterKit` assembles its contents in a package we do not control, and a minor upgrade\n * there could add a node to `husk-richtext-v1` without a line changing here. It must stay in\n * step with `RICHTEXT_NODES` and `RICHTEXT_MARKS` in schema.ts, which is asserted by a test.\n *\n * The list does not vary with a field's `features`. A feature hides a toolbar control; it\n * never narrows the schema, because narrowing it would make ProseMirror strip an existing mark\n * the moment a customer switched a button off. See\n * .docs/decisions/2026-09-18-richtext-editor.md.\n */\nexport const HUSK_RICHTEXT_EXTENSIONS: Extensions = [\n Document,\n Paragraph,\n Text,\n Bold,\n Italic,\n Strike,\n Heading.configure({ levels: [...RICHTEXT_HEADING_LEVELS] }),\n Blockquote,\n HardBreak,\n BulletList,\n OrderedList,\n ListItem,\n // Links are written through the toolbar, never auto-detected while typing: a URL pasted\n // into body copy is not always meant to be a link, and an editor cannot undo a decision\n // they did not make.\n Link.configure({ openOnClick: false, autolink: false }),\n UndoRedo,\n]\n","\"use client\"\n\nimport { useRef, useState } from \"react\"\nimport type { KeyboardEvent } from \"react\"\n\nimport { IconButton } from \"../../admin/components/icon-button.js\"\nimport { Menu } from \"../../admin/components/menu.js\"\nimport type { IconName } from \"../../admin/components/icon.js\"\nimport type { MenuEntry } from \"../../admin/components/menu.js\"\nimport type { RichtextFeature } from \"./schema.js\"\n\n/**\n * The rich text toolbar. Canonical source: .docs/styleguide/04-components.md section 3.9.\n *\n * It knows nothing about ProseMirror. What it gets is the state to display and a callback per\n * command, which is what makes the chrome testable without mounting an editor, and what stops\n * a second editor-shaped abstraction from growing inside the field type.\n *\n * Every control is a `sm` ghost icon button from section 2.3 with the guide's pressed state,\n * the block control is the menu from section 11, and the group separators are the vertical\n * divider from section 10. Nothing here draws anything the guide has not already drawn.\n */\nexport type RichTextBlock = \"paragraph\" | \"heading2\" | \"heading3\" | \"blockquote\"\n\nexport type RichTextCommand =\n | \"bold\"\n | \"italic\"\n | \"strike\"\n | \"bulletList\"\n | \"orderedList\"\n | \"link\"\n | \"unlink\"\n | \"undo\"\n | \"redo\"\n\nexport interface RichTextToolbarState {\n block: RichTextBlock\n bold: boolean\n italic: boolean\n strike: boolean\n bulletList: boolean\n orderedList: boolean\n /** Whether the caret sits inside a link, which is what enables \"Remove link\". */\n link: boolean\n canUndo: boolean\n canRedo: boolean\n}\n\nexport interface RichTextToolbarProps {\n features: readonly RichtextFeature[]\n state: RichTextToolbarState\n disabled?: boolean\n onCommand: (command: RichTextCommand) => void\n onBlock: (block: RichTextBlock) => void\n}\n\nconst BLOCK_LABEL: Record<RichTextBlock, string> = {\n paragraph: \"Paragraph\",\n heading2: \"Heading 2\",\n heading3: \"Heading 3\",\n blockquote: \"Quote\",\n}\n\ninterface ToggleSpec {\n command: RichTextCommand\n feature: RichtextFeature | null\n icon: IconName\n label: string\n /** Which group the control belongs to; a change of group draws a separator. */\n group: number\n pressed: (state: RichTextToolbarState) => boolean\n enabled: (state: RichTextToolbarState) => boolean\n}\n\nconst ALWAYS = (): boolean => true\nconst NEVER = (): boolean => false\n\nconst TOGGLES: readonly ToggleSpec[] = [\n {\n command: \"bold\",\n feature: \"bold\",\n icon: \"bold\",\n label: \"Bold\",\n group: 1,\n pressed: (s) => s.bold,\n enabled: ALWAYS,\n },\n {\n command: \"italic\",\n feature: \"italic\",\n icon: \"italic\",\n label: \"Italic\",\n group: 1,\n pressed: (s) => s.italic,\n enabled: ALWAYS,\n },\n {\n command: \"strike\",\n feature: \"strike\",\n icon: \"strikethrough\",\n label: \"Strikethrough\",\n group: 1,\n pressed: (s) => s.strike,\n enabled: ALWAYS,\n },\n {\n command: \"bulletList\",\n feature: \"bulletList\",\n icon: \"bullet-list\",\n label: \"Bulleted list\",\n group: 2,\n pressed: (s) => s.bulletList,\n enabled: ALWAYS,\n },\n {\n command: \"orderedList\",\n feature: \"orderedList\",\n icon: \"numbered-list\",\n label: \"Numbered list\",\n group: 2,\n pressed: (s) => s.orderedList,\n enabled: ALWAYS,\n },\n {\n command: \"link\",\n feature: \"link\",\n icon: \"link\",\n label: \"Add or edit a link\",\n group: 3,\n pressed: (s) => s.link,\n enabled: ALWAYS,\n },\n {\n command: \"unlink\",\n feature: \"link\",\n icon: \"unlink\",\n label: \"Remove link\",\n group: 3,\n // Removing a link is an action, not a state: it never looks held down.\n pressed: NEVER,\n enabled: (s) => s.link,\n },\n {\n command: \"undo\",\n feature: null,\n icon: \"undo\",\n label: \"Undo\",\n group: 4,\n pressed: NEVER,\n enabled: (s) => s.canUndo,\n },\n {\n command: \"redo\",\n feature: null,\n icon: \"redo\",\n label: \"Redo\",\n group: 4,\n pressed: NEVER,\n enabled: (s) => s.canRedo,\n },\n]\n\n/** The block choices a feature list allows, always including the paragraph to return to. */\nfunction blockChoices(features: readonly RichtextFeature[]): RichTextBlock[] {\n const choices: RichTextBlock[] = [\"paragraph\"]\n if (features.includes(\"heading\")) choices.push(\"heading2\", \"heading3\")\n if (features.includes(\"blockquote\")) choices.push(\"blockquote\")\n return choices\n}\n\nexport function RichTextToolbar({\n features,\n state,\n disabled = false,\n onCommand,\n onBlock,\n}: RichTextToolbarProps) {\n const listRef = useRef<HTMLDivElement>(null)\n const [roving, setRoving] = useState(0)\n\n const toggles = TOGGLES.filter(\n (toggle) => toggle.feature === null || features.includes(toggle.feature),\n )\n const blocks = blockChoices(features)\n const showBlocks = blocks.length > 1\n\n /**\n * Roving tab index across the toolbar's buttons, per section 3.9.\n *\n * The focus move reads the rendered buttons out of the container rather than holding a ref\n * per control, because the control list changes with the field's feature list and an array\n * of refs would have to be resized in step with it.\n */\n function move(delta: 1 | -1) {\n const buttons = listRef.current?.querySelectorAll(\"button\")\n if (buttons === undefined || buttons.length === 0) return\n const next = (roving + delta + buttons.length) % buttons.length\n setRoving(next)\n buttons.item(next)?.focus()\n }\n\n function handleKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n if (event.key === \"ArrowRight\") {\n event.preventDefault()\n move(1)\n return\n }\n if (event.key === \"ArrowLeft\") {\n event.preventDefault()\n move(-1)\n }\n }\n\n const blockItems: MenuEntry[] = blocks.map((block) => ({\n kind: \"item\",\n id: block,\n label: BLOCK_LABEL[block],\n selected: state.block === block,\n }))\n\n return (\n <div\n role=\"toolbar\"\n aria-label=\"Text formatting\"\n aria-orientation=\"horizontal\"\n className=\"flex h-9 items-center gap-0.5 border-b border-border-subtle bg-surface-raised px-1.5\"\n >\n {showBlocks ? (\n <>\n {/* The reserved measure keeps the buttons to the right still when the label\n changes from \"Paragraph\" to \"Heading 2\". */}\n <div className=\"flex min-w-30 *:flex-1\">\n <Menu\n items={blockItems}\n onSelect={(id) => {\n const chosen = blocks.find((block) => block === id)\n if (chosen !== undefined) onBlock(chosen)\n }}\n label=\"Text style\"\n triggerLabel={BLOCK_LABEL[state.block]}\n triggerIcon=\"expand\"\n triggerSize=\"sm\"\n align=\"start\"\n />\n </div>\n <Separator />\n </>\n ) : null}\n\n <div ref={listRef} className=\"flex items-center gap-0.5\" onKeyDown={handleKeyDown}>\n {toggles.map((toggle, index) => {\n const previous = toggles[index - 1]\n const enabled = toggle.enabled(state)\n return (\n <span key={toggle.command} className=\"contents\">\n {previous !== undefined && previous.group !== toggle.group ? (\n <Separator />\n ) : null}\n <IconButton\n icon={toggle.icon}\n label={toggle.label}\n size=\"sm\"\n pressed={toggle.pressed(state)}\n disabled={disabled || !enabled}\n tabIndex={index === roving ? 0 : -1}\n onFocus={() => setRoving(index)}\n // The editor loses its selection the moment focus leaves the contenteditable,\n // so a toolbar button must never take focus on mousedown. Without this, every\n // command would run against an empty selection.\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onCommand(toggle.command)}\n />\n </span>\n )\n })}\n </div>\n </div>\n )\n}\n\n/** The vertical divider from section 10, at the toolbar's 6px margin. */\nfunction Separator() {\n return (\n <span\n role=\"separator\"\n aria-orientation=\"vertical\"\n className=\"mx-1.5 h-5 w-px shrink-0 bg-border-subtle\"\n />\n )\n}\n","\"use client\"\n\nimport { useEffect, useState } from \"react\"\nimport { EditorContent, useEditor, useEditorState } from \"@tiptap/react\"\nimport { Placeholder } from \"@tiptap/extensions\"\nimport type { Editor } from \"@tiptap/core\"\n\nimport { Button } from \"../../admin/components/button.js\"\nimport { cx } from \"../../admin/components/class-names.js\"\nimport { Modal } from \"../../admin/components/modal.js\"\nimport { TextInput } from \"../../admin/components/field.js\"\nimport { HUSK_RICHTEXT_EXTENSIONS } from \"./extensions.js\"\nimport { RICHTEXT_FORMAT } from \"./schema.js\"\nimport { RichTextToolbar } from \"./toolbar.js\"\nimport type { RichTextBlock, RichTextCommand, RichTextToolbarState } from \"./toolbar.js\"\nimport type { RichTextNodeJSON } from \"./document.js\"\nimport type { RichTextValue } from \"../../types/field.js\"\nimport type { RichtextFeature } from \"./schema.js\"\n\n/**\n * The editor half of the `richtext` field: Tiptap, the toolbar, and the link dialog.\n *\n * It is a separate component from the field input on purpose. The input decides whether the\n * stored document can be opened at all, and only mounts this when the answer is yes, so there\n * is no path through which an editor exists over a document it could not read. See\n * .docs/decisions/2026-09-18-richtext-editor.md.\n */\nexport interface RichTextEditorProps {\n /** The id the field's label points at; it lands on the editable element. */\n id: string\n label: string\n describedBy: string | undefined\n invalid: boolean\n placeholder: string | undefined\n features: readonly RichtextFeature[]\n /**\n * The document to open. Read once, at mount: pushing every external change back into a\n * live editor is what makes a caret jump to the top of the document mid-sentence.\n */\n initialContent: RichTextNodeJSON\n disabled: boolean\n readonly: boolean\n onChange: (value: RichTextValue | null) => void\n onBlur?: (() => void) | undefined\n}\n\nconst IDLE: RichTextToolbarState = {\n block: \"paragraph\",\n bold: false,\n italic: false,\n strike: false,\n bulletList: false,\n orderedList: false,\n link: false,\n canUndo: false,\n canRedo: false,\n}\n\nfunction readToolbarState(editor: Editor): RichTextToolbarState {\n const block: RichTextBlock = editor.isActive(\"heading\", { level: 2 })\n ? \"heading2\"\n : editor.isActive(\"heading\", { level: 3 })\n ? \"heading3\"\n : editor.isActive(\"blockquote\")\n ? \"blockquote\"\n : \"paragraph\"\n\n return {\n block,\n bold: editor.isActive(\"bold\"),\n italic: editor.isActive(\"italic\"),\n strike: editor.isActive(\"strike\"),\n bulletList: editor.isActive(\"bulletList\"),\n orderedList: editor.isActive(\"orderedList\"),\n link: editor.isActive(\"link\"),\n canUndo: editor.can().undo(),\n canRedo: editor.can().redo(),\n }\n}\n\nexport function RichTextEditor({\n id,\n label,\n describedBy,\n invalid,\n placeholder,\n features,\n initialContent,\n disabled,\n readonly,\n onChange,\n onBlur,\n}: RichTextEditorProps) {\n const [linkDraft, setLinkDraft] = useState<string | null>(null)\n const editable = !disabled && !readonly\n\n const editor = useEditor({\n // Placeholder is appended here rather than in the extension list, because it draws a\n // decoration and contributes no node and no mark. Keeping it out of extensions.ts keeps\n // that file a truthful statement of the stored format.\n extensions: [\n ...HUSK_RICHTEXT_EXTENSIONS,\n Placeholder.configure({ placeholder: placeholder ?? \"\" }),\n ],\n content: initialContent,\n editable,\n // Next renders this on the server first. Rendering the editor immediately there produces\n // markup the client then disagrees with, which is a hydration error on every entry form.\n immediatelyRender: false,\n editorProps: {\n attributes: {\n id,\n class: \"richtext-content focus-visible:outline-none\",\n role: \"textbox\",\n \"aria-multiline\": \"true\",\n \"aria-label\": label,\n ...(describedBy === undefined ? {} : { \"aria-describedby\": describedBy }),\n ...(invalid ? { \"aria-invalid\": \"true\" } : {}),\n },\n },\n onUpdate({ editor: current }) {\n // An empty document is stored as no value at all, so `required` can see it and so a\n // cleared field and a never-filled field are the same thing. Mirrors `toStored`.\n onChange(\n current.isEmpty ? null : { format: RICHTEXT_FORMAT, content: current.getJSON() },\n )\n },\n onBlur() {\n onBlur?.()\n },\n })\n\n useEffect(() => {\n editor?.setEditable(editable)\n }, [editor, editable])\n\n // `useEditorState` answers null until the editor exists, which it does not on the server\n // render or on the first client render, because `immediatelyRender` is false.\n const toolbarState =\n useEditorState({\n editor,\n selector: ({ editor: current }) =>\n current === null ? IDLE : readToolbarState(current),\n }) ?? IDLE\n\n function runCommand(command: RichTextCommand) {\n if (editor === null) return\n const chain = editor.chain().focus()\n\n switch (command) {\n case \"bold\":\n chain.toggleBold().run()\n return\n case \"italic\":\n chain.toggleItalic().run()\n return\n case \"strike\":\n chain.toggleStrike().run()\n return\n case \"bulletList\":\n chain.toggleBulletList().run()\n return\n case \"orderedList\":\n chain.toggleOrderedList().run()\n return\n case \"unlink\":\n chain.extendMarkRange(\"link\").unsetLink().run()\n return\n case \"undo\":\n chain.undo().run()\n return\n case \"redo\":\n chain.redo().run()\n return\n case \"link\": {\n const href = editor.getAttributes(\"link\")[\"href\"]\n setLinkDraft(typeof href === \"string\" ? href : \"\")\n return\n }\n }\n }\n\n function applyBlock(block: RichTextBlock) {\n if (editor === null) return\n const chain = editor.chain().focus()\n\n // Leaving a quote and leaving a heading are different commands, so the block control\n // clears the one that is active before setting the one that was chosen.\n if (editor.isActive(\"blockquote\") && block !== \"blockquote\") chain.lift(\"blockquote\")\n\n switch (block) {\n case \"paragraph\":\n chain.setParagraph().run()\n return\n case \"heading2\":\n chain.setHeading({ level: 2 }).run()\n return\n case \"heading3\":\n chain.setHeading({ level: 3 }).run()\n return\n case \"blockquote\":\n chain.setParagraph().setBlockquote().run()\n return\n }\n }\n\n function commitLink() {\n if (editor === null || linkDraft === null) return\n const href = linkDraft.trim()\n const chain = editor.chain().focus().extendMarkRange(\"link\")\n\n // An emptied field is how a link is removed from inside the dialog, which is the same\n // outcome as the toolbar's Remove link and has to behave identically.\n if (href === \"\") chain.unsetLink().run()\n else chain.setLink({ href }).run()\n\n setLinkDraft(null)\n }\n\n return (\n <div\n className={cx(\n \"overflow-hidden rounded-sm border state-transition focus-within:focus-field-ring\",\n editable ? \"bg-surface-input\" : \"bg-surface-disabled text-text-secondary\",\n disabled && \"cursor-not-allowed\",\n invalid\n ? \"border-danger focus-within:border-danger\"\n : \"border-border-default hover:border-border-strong\",\n )}\n >\n {/* Read-only renders no toolbar at all, per section 3.9: a row of dead buttons above\n uneditable text is chrome that says nothing. Disabled keeps the row and disables it,\n so the field still looks like the control it is. */}\n {readonly ? null : (\n <RichTextToolbar\n features={features}\n state={toolbarState}\n disabled={disabled}\n onCommand={runCommand}\n onBlock={applyBlock}\n />\n )}\n\n <EditorContent editor={editor} />\n\n <Modal\n open={linkDraft !== null}\n onClose={() => setLinkDraft(null)}\n title=\"Link\"\n description=\"The address this text points at.\"\n width=\"sm\"\n footer={\n <>\n <Button onClick={() => setLinkDraft(null)}>Cancel</Button>\n <Button variant=\"primary\" onClick={commitLink}>\n Apply\n </Button>\n </>\n }\n >\n <TextInput\n type=\"url\"\n value={linkDraft ?? \"\"}\n placeholder=\"https://\"\n aria-label=\"Link address\"\n onChange={(event) => setLinkDraft(event.target.value)}\n />\n </Modal>\n </div>\n )\n}\n","\"use client\"\n\nimport { Button } from \"../../admin/components/button.js\"\nimport { FieldShell } from \"../field-shell.js\"\nimport { RichTextEditor } from \"./editor.js\"\nimport { inspectRichText } from \"./document.js\"\nimport { resolveFeatures } from \"./schema.js\"\nimport type { FieldError } from \"../../types/entry.js\"\nimport type { FieldInputProps } from \"../../schema/field-type.js\"\nimport type { RichTextValue, RichtextField } from \"../../types/field.js\"\n\n/**\n * The `richtext` field input.\n *\n * Its one job beyond composition is the guard: a document this version cannot open never\n * reaches the editor. See .docs/styleguide/04-components.md section 3.9 for the state, and\n * .docs/decisions/2026-09-18-richtext-editor.md for why it exists.\n */\nexport function RichtextFieldInput({\n path,\n field,\n value,\n onChange,\n onBlur,\n errors,\n disabled = false,\n readonly = false,\n}: FieldInputProps<RichTextValue, RichtextField>) {\n const read = inspectRichText(value)\n const features = resolveFeatures(field.features)\n\n if (read.kind === \"unreadable\") {\n const unreadable: FieldError = {\n path,\n rule: \"format\",\n message: `This text cannot be opened here because ${read.reason}.`,\n }\n\n // A server-reported error still wins the one line the guide allows under a field, exactly\n // as it does on every other field type.\n return (\n <FieldShell field={field} errors={[...errors, unreadable]}>\n {() => (\n <div className=\"overflow-hidden rounded-sm border border-danger bg-surface-input\">\n <div className=\"flex flex-col items-start gap-3 p-3\">\n <p className=\"text-body-sm text-text-secondary\">\n The stored text is left exactly as it is. Saving this entry keeps it, so\n nothing is lost while the field is locked.\n </p>\n <Button\n size=\"sm\"\n variant=\"danger\"\n icon=\"delete\"\n disabled={disabled || readonly}\n // The only route from \"cannot read this\" to an empty document, and a person\n // has to take it deliberately. Nothing else in the field type writes over an\n // unreadable value.\n onClick={() => onChange(null)}\n >\n Replace with an empty text\n </Button>\n </div>\n </div>\n )}\n </FieldShell>\n )\n }\n\n return (\n <FieldShell field={field} errors={errors}>\n {({ id, describedBy, invalid }) => (\n <RichTextEditor\n id={id}\n label={field.label}\n describedBy={describedBy}\n invalid={invalid}\n placeholder={field.placeholder}\n features={features}\n initialContent={read.content}\n disabled={disabled}\n readonly={readonly || field.readonly === true}\n onChange={onChange}\n onBlur={onBlur}\n />\n )}\n </FieldShell>\n )\n}\n","import {\n isEmptyRichTextContent,\n isRichTextValue,\n richTextToPlainText,\n} from \"./document.js\"\nimport { RICHTEXT_FORMAT } from \"./schema.js\"\nimport { RichtextFieldInput } from \"./input.js\"\nimport type { FieldError } from \"../../types/entry.js\"\nimport type { FieldTypeSpec } from \"../../schema/field-type.js\"\nimport type { RichTextValue, RichtextField } from \"../../types/field.js\"\n\n/**\n * Rich text, stored as a serialized ProseMirror document rather than as HTML.\n *\n * Editor choice, the exact contents of `content`, and why an unreadable document is handled\n * in the input rather than here: .docs/decisions/2026-09-18-richtext-editor.md.\n */\nexport const richtextField: FieldTypeSpec<RichTextValue, RichtextField> = {\n name: \"richtext\",\n\n /**\n * An empty document stores as `null`.\n *\n * `{ type: \"doc\", content: [{ type: \"paragraph\" }] }` is what the editor holds after an\n * editor deletes everything, and the shared validator's `isEmpty` reports `false` for any\n * object. Storing that shape would make `required` unenforceable on this field type, so\n * \"cleared\" and \"never filled in\" are one value here, exactly as `\"\"` and unset are one\n * value on a text field.\n */\n toStored: (value) => {\n if (value === null) return null\n if (isEmptyRichTextContent(value.content)) return null\n return { format: RICHTEXT_FORMAT, content: value.content }\n },\n\n /**\n * Keeps the envelope verbatim, `content` uninspected.\n *\n * This is the one converter that deliberately does not check what it is reading. A document\n * this version cannot open still has to round trip byte for byte, because the alternative,\n * returning `null`, would hand the edit form an empty value and the next save would write\n * that emptiness over the stored document. Whether the document can be opened is asked once,\n * by the input, and it never changes the value.\n */\n fromStored: (raw) =>\n isRichTextValue(raw) ? { format: RICHTEXT_FORMAT, content: raw.content } : null,\n\n Input: RichtextFieldInput,\n\n /**\n * Length rules, measured in the document's text.\n *\n * These are `ValidationRules` keys, which normally belong to the shared validator, but\n * `checkRules` can only measure a string or an array and a rich text value is an object.\n * Nothing else in the product knows that a rich text document has a length, so the field\n * type answers it. The shape of the envelope is already checked by the shared validator and\n * is not re-checked here.\n *\n * An unrecognised node or mark is deliberately not an error. A document written by a newer\n * version of the package than the one deployed must stay saveable; a validator that refuses\n * forward-compatible data turns an upgrade into an outage.\n */\n validate: (value, rules, ctx, field): FieldError[] => {\n if (value === null) return []\n\n const text = richTextToPlainText(value.content)\n const errors: FieldError[] = []\n const { minLength, maxLength } = rules\n\n if (minLength !== undefined && text.length < minLength) {\n errors.push({\n path: ctx.path,\n rule: \"minLength\",\n message: `${field.label} must be at least ${minLength} characters.`,\n })\n }\n if (maxLength !== undefined && text.length > maxLength) {\n errors.push({\n path: ctx.path,\n rule: \"maxLength\",\n message: `${field.label} must be at most ${maxLength} characters.`,\n })\n }\n\n return errors\n },\n\n tsType: \"RichTextValue\",\n editor: {\n label: \"Rich text\",\n description: \"Formatted text with headings, lists and links.\",\n rules: [\"required\", \"minLength\", \"maxLength\"],\n options: [\n {\n key: \"features\",\n label: \"Toolbar features\",\n control: \"string-list\",\n help: \"Leave empty for the default toolbar.\",\n },\n ],\n defaults: {},\n },\n\n /**\n * A new entry starts unset rather than on an empty document, so the stored shape of a rich\n * text field that was never touched matches the stored shape of one that was cleared.\n */\n defaultValue: () => null,\n}\n\nexport {\n emptyRichTextContent,\n inspectRichText,\n isEmptyRichTextContent,\n isRichTextValue,\n richTextToPlainText,\n} from \"./document.js\"\nexport type { RichTextNodeJSON, RichTextReadState } from \"./document.js\"\nexport {\n RICHTEXT_FEATURES,\n RICHTEXT_FORMAT,\n RICHTEXT_HEADING_LEVELS,\n RICHTEXT_MARKS,\n RICHTEXT_NODES,\n isRichtextFeature,\n resolveFeatures,\n} from \"./schema.js\"\nexport type { RichtextFeature } from \"./schema.js\"\n","\"use client\"\n\nimport { Checkbox } from \"../../admin/components/checkbox.js\"\nimport { Select } from \"../../admin/components/select.js\"\nimport type { SelectOption as SelectControlOption } from \"../../admin/components/select.js\"\nimport type { FieldInputProps } from \"../../schema/field-type.js\"\nimport { FieldShell } from \"../field-shell.js\"\nimport type { SelectField } from \"../../types/field.js\"\n\n/** Empty is a real choice for an optional select, and a listbox offers no way back out. */\nconst CLEAR_VALUE = \"\"\n\nexport function SelectFieldInput({\n field,\n value,\n onChange,\n onBlur,\n errors,\n disabled = false,\n readonly = false,\n}: FieldInputProps<string | string[], SelectField>) {\n const locked = disabled || readonly || field.readonly === true\n\n if (field.multiple === true) {\n const selected = Array.isArray(value) ? value : []\n\n function toggle(option: string, checked: boolean) {\n const next = checked\n ? [...selected, option]\n : selected.filter((item) => item !== option)\n // Option order, not click order, so two editors who picked the same options produce\n // the same document and the diff between two saves stays readable.\n const ordered = field.options\n .map((item) => item.value)\n .filter((item) => next.includes(item))\n onChange(ordered)\n }\n\n return (\n <FieldShell field={field} errors={errors}>\n {({ describedBy }) => (\n <div\n role=\"group\"\n aria-label={field.label}\n aria-describedby={describedBy}\n className=\"flex flex-col gap-2\"\n >\n {field.options.map((option) => (\n <Checkbox\n key={option.value}\n label={option.label}\n value={option.value}\n checked={selected.includes(option.value)}\n disabled={locked}\n onChange={(checked) => toggle(option.value, checked)}\n />\n ))}\n </div>\n )}\n </FieldShell>\n )\n }\n\n const options: SelectControlOption[] = [\n ...(field.validation?.required === true\n ? []\n : [{ value: CLEAR_VALUE, label: \"None\" }]),\n ...field.options.map((option) => ({ value: option.value, label: option.label })),\n ]\n\n return (\n <FieldShell field={field} errors={errors}>\n {({ id, describedBy, invalid }) => (\n <Select\n id={id}\n options={options}\n value={typeof value === \"string\" ? value : null}\n placeholder={field.placeholder ?? \"Select an option\"}\n invalid={invalid}\n disabled={locked}\n aria-describedby={describedBy}\n onChange={(next) => {\n onChange(next === CLEAR_VALUE ? null : next)\n onBlur?.()\n }}\n />\n )}\n </FieldShell>\n )\n}\n","import type { FieldError } from \"../../types/entry.js\"\nimport type { FieldTypeSpec } from \"../../schema/field-type.js\"\nimport type { SelectField } from \"../../types/field.js\"\nimport { storedString, storedStrings } from \"../values.js\"\nimport { SelectFieldInput } from \"./input.js\"\n\n/**\n * One value, or a list of them when the field sets `multiple`.\n *\n * A stored option that the schema no longer offers is kept rather than dropped: the editor\n * removed an option, they did not ask for every entry using it to be silently rewritten. The\n * shared validator reports it as an unallowed option on the next save, which is a decision\n * someone can act on.\n */\nexport const selectField: FieldTypeSpec<string | string[], SelectField> = {\n name: \"select\",\n toStored: (value, field) =>\n field.multiple === true ? storedStrings(value) : storedString(value),\n fromStored: (raw, field) =>\n field.multiple === true ? storedStrings(raw) : storedString(raw),\n Input: SelectFieldInput,\n /**\n * Option membership belongs to the shared validator, which checks it for both shapes.\n * What it cannot see is the same option selected twice, which is not a set.\n */\n validate: (value, _rules, ctx, field): FieldError[] => {\n if (field.multiple !== true || !Array.isArray(value)) return []\n if (new Set(value).size === value.length) return []\n\n return [\n {\n path: ctx.path,\n rule: \"duplicate\",\n message: `${field.label} lists the same option twice.`,\n },\n ]\n },\n // Narrowed on `multiple`, so codegen over a database-defined type says the same thing\n // `FieldValue<TField>` says for a code-defined one instead of the union of both shapes.\n tsType: (field) => (field.multiple === true ? \"string[]\" : \"string\"),\n defaultValue: (field) => {\n if (field.multiple !== true) return field.defaultValue ?? null\n return field.defaultValue === undefined ? [] : [field.defaultValue]\n },\n editor: {\n label: \"Select\",\n description: \"One value, or several, from a fixed list.\",\n rules: [\"required\"],\n options: [\n { key: \"options\", label: \"Options\", control: \"select-options\", required: true },\n {\n key: \"multiple\",\n label: \"Allow several\",\n control: \"boolean\",\n help: \"Stores a list instead of one value. Changing it changes how every entry is stored.\",\n },\n ],\n defaults: { options: [{ value: \"option-1\", label: \"Option 1\" }] },\n },\n}\n","\"use client\"\n\nimport { createContext, useContext } from \"react\"\nimport type { ReactNode } from \"react\"\n\nimport type { FieldMap } from \"../types/field.js\"\n\n/**\n * What a field input may know about the form around it.\n *\n * `FieldInputProps` deliberately carries only one field's value, because a field type that\n * reaches into the form is a field type that cannot be rendered anywhere else. Two field\n * types genuinely need more than their own value: `slug` derives from a sibling, and any\n * field carrying `unique` needs someone who can ask the database. Both arrive through this\n * context rather than through props, so every other field type keeps its narrow surface.\n *\n * The context has a working default: no sibling values, no uniqueness check. A field type\n * rendered without a provider degrades to manual entry rather than throwing.\n */\n\n/** Resolves to `true` when no other entry of this content type holds the value. */\nexport type UniqueCheck = (path: string, value: string) => Promise<boolean>\n\nexport interface FieldFormContextValue {\n /** Current values of the entry being edited, keyed by field key. */\n values: Record<string, unknown>\n /** The content type's fields, so a field can name the sibling it derives from. */\n fields?: FieldMap | undefined\n checkUnique?: UniqueCheck | undefined\n}\n\nconst NO_FORM: FieldFormContextValue = { values: {} }\n\nconst FieldFormContext = createContext<FieldFormContextValue>(NO_FORM)\n\nexport interface FieldFormProviderProps {\n value: FieldFormContextValue\n children: ReactNode\n}\n\nexport function FieldFormProvider({ value, children }: FieldFormProviderProps) {\n return <FieldFormContext.Provider value={value}>{children}</FieldFormContext.Provider>\n}\n\nexport function useFieldForm(): FieldFormContextValue {\n return useContext(FieldFormContext)\n}\n","/**\n * Slug derivation.\n *\n * German is the language of most Nonext customer content, so the umlauts and the eszett are\n * transliterated the way German readers expect (\"Grüße\" to \"gruesse\") before the generic\n * accent stripping runs. Letting `NFKD` handle them would produce \"gruse\" and \"gru\", which\n * is wrong in the one language this CMS is used in most.\n */\nconst GERMAN: Record<string, string> = {\n \"\\u00e4\": \"ae\",\n \"\\u00f6\": \"oe\",\n \"\\u00fc\": \"ue\",\n \"\\u00df\": \"ss\",\n}\n\n/** Matches PATTERN_PRESETS.slug: lowercase words joined by single hyphens. */\nconst SLUG = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\n\nexport function slugify(input: string): string {\n return input\n .toLowerCase()\n .replace(/[\\u00e4\\u00f6\\u00fc\\u00df]/g, (char) => GERMAN[char] ?? char)\n .normalize(\"NFKD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+/, \"\")\n .replace(/-+$/, \"\")\n}\n\nexport function isSlug(value: string): boolean {\n return SLUG.test(value)\n}\n","\"use client\"\n\nimport { useEffect, useState } from \"react\"\n\nimport { TextInput } from \"../../admin/components/field.js\"\nimport type { FieldInputProps } from \"../../schema/field-type.js\"\nimport type { FieldError } from \"../../types/entry.js\"\nimport type { SlugField } from \"../../types/field.js\"\nimport { FieldShell } from \"../field-shell.js\"\nimport { useFieldForm } from \"../form-context.js\"\nimport { isSlug, slugify } from \"./slugify.js\"\n\n/**\n * Long enough that a typist is not asking the database a question per keystroke, short\n * enough that the answer is on screen before the save button is reached.\n */\nconst CHECK_DELAY_MS = 400\n\ninterface UniqueAnswer {\n /** The value the answer is about, so a stale one is never shown next to a new value. */\n value: string\n free: boolean\n}\n\n/**\n * The slug input.\n *\n * Three behaviours, each with a rule about what it is not allowed to do:\n *\n * 1. **Derivation.** While the slug is still linked to its source field, typing a title\n * writes the slug. Clearing the slug re-links it, which is the only way back.\n * 2. **Manual override.** The first keystroke in the slug unlinks it for good, and an entry\n * that arrives with a slug already set starts unlinked. A published URL is not something\n * a later title edit gets to change quietly.\n * 3. **Uniqueness feedback.** Only the database knows, so the input says only what it has\n * been told: nothing until a check has come back for the value currently on screen. The\n * check is debounced and its answer is discarded if the value moved on.\n *\n * Without a `FieldFormProvider` there is no source value and no way to ask about\n * uniqueness, so the control degrades to a plain, fully working manual slug input.\n */\nexport function SlugFieldInput({\n path,\n field,\n value,\n onChange,\n onBlur,\n errors,\n disabled = false,\n readonly = false,\n}: FieldInputProps<string, SlugField>) {\n const { values, fields, checkUnique } = useFieldForm()\n const current = value ?? \"\"\n\n const source = field.from === undefined ? undefined : values[field.from]\n const derived = typeof source === \"string\" ? slugify(source) : \"\"\n\n // An entry that already has a slug is never re-derived, in this session or any later one.\n const [manual, setManual] = useState(() => current !== \"\")\n const linked = field.from !== undefined && !manual\n\n useEffect(() => {\n if (!linked) return\n const next = derived === \"\" ? null : derived\n if (next === value) return\n onChange(next)\n }, [linked, derived, value, onChange])\n\n // Nothing to ask about an empty slug, or one this field type already rejects: the answer\n // would be \"available\" for a value that cannot be saved anyway.\n const asking =\n field.validation?.unique === true &&\n checkUnique !== undefined &&\n current !== \"\" &&\n isSlug(current)\n\n // Only the answer is state. \"Checking\" is derived from the absence of one, so nothing has\n // to be reset when the value changes, and a late answer for an old value simply no longer\n // matches what is on screen.\n const [answer, setAnswer] = useState<UniqueAnswer | null>(null)\n const settled = answer !== null && answer.value === current ? answer : null\n\n useEffect(() => {\n // The `checkUnique` half of `asking` again, for the type narrowing inside the closure.\n if (!asking || checkUnique === undefined) return\n let cancelled = false\n\n const timer = setTimeout(() => {\n void checkUnique(path, current)\n .then((free) => {\n if (!cancelled) setAnswer({ value: current, free })\n })\n .catch(() => {\n // A failed lookup is not a verdict. The adapter checks uniqueness again before the\n // write, so staying quiet here loses nothing but a hint.\n if (!cancelled) setAnswer(null)\n })\n }, CHECK_DELAY_MS)\n\n return () => {\n cancelled = true\n clearTimeout(timer)\n }\n }, [asking, checkUnique, current, path])\n\n const taken = settled?.free === false\n const takenError: FieldError = {\n path,\n rule: \"unique\",\n message: `${field.label} is already used by another entry.`,\n }\n const shown: readonly FieldError[] =\n errors.length > 0 ? errors : taken ? [takenError] : []\n\n const sourceLabel =\n field.from === undefined ? undefined : (fields?.[field.from]?.label ?? field.from)\n\n const help =\n asking && settled === null\n ? \"Checking availability.\"\n : settled?.free === true\n ? \"Available.\"\n : linked && sourceLabel !== undefined\n ? `Generated from ${sourceLabel}. Type here to set it yourself.`\n : field.description\n\n return (\n <FieldShell field={field} errors={shown} help={help}>\n {({ id, describedBy, invalid }) => (\n <TextInput\n id={id}\n type=\"text\"\n value={current}\n placeholder={field.placeholder}\n spellCheck={false}\n autoComplete=\"off\"\n invalid={invalid}\n aria-describedby={describedBy}\n disabled={disabled}\n readOnly={readonly || field.readonly === true}\n onChange={(event) => {\n const next = event.target.value\n // Clearing it hands the slug back to the source field.\n setManual(next !== \"\")\n onChange(next === \"\" ? null : next)\n }}\n onBlur={onBlur}\n />\n )}\n </FieldShell>\n )\n}\n","import type { FieldError } from \"../../types/entry.js\"\nimport type { FieldTypeSpec } from \"../../schema/field-type.js\"\nimport type { SlugField } from \"../../types/field.js\"\nimport { storedString } from \"../values.js\"\nimport { SlugFieldInput } from \"./input.js\"\nimport { isSlug } from \"./slugify.js\"\n\n/**\n * A URL segment. Stored as the plain string it is, because a slug that needed unwrapping to\n * be put in a route would not be a slug.\n *\n * Uniqueness is not checked here and cannot be: it is a question about other entries.\n * `uniqueFieldPaths()` tells the adapter which fields to check, and the adapter reports the\n * failure as the same `FieldError` shape, so the form renders it like any other error.\n */\nexport const slugField: FieldTypeSpec<string, SlugField> = {\n name: \"slug\",\n toStored: (value) => storedString(value),\n fromStored: (raw) => storedString(raw),\n Input: SlugFieldInput,\n /**\n * Slug shape is a property of the field type, not of its rules, so it is checked even\n * when the schema sets none. A schema that does set `pattern` has said something more\n * specific and wins outright: two sentences about the same character are not twice as\n * helpful.\n */\n validate: (value, rules, ctx, field): FieldError[] => {\n if (value === null || value === \"\") return []\n if (rules.pattern !== undefined) return []\n if (isSlug(value)) return []\n\n return [\n {\n path: ctx.path,\n rule: \"format\",\n message: `${field.label} may use lowercase letters, numbers and single hyphens only.`,\n },\n ]\n },\n tsType: \"string\",\n defaultValue: () => null,\n editor: {\n label: \"Slug\",\n description: \"A URL segment, derived from another field until it is edited.\",\n rules: [\"required\", \"unique\", \"maxLength\", \"pattern\"],\n options: [\n {\n key: \"from\",\n label: \"Derived from\",\n control: \"field-key\",\n help: \"The field the slug is suggested from.\",\n },\n ],\n // A slug that is not unique is a routing bug waiting to happen, so a new one starts\n // unique and the editor turns it off deliberately rather than forgetting to turn it on.\n defaults: { validation: { unique: true } },\n },\n}\n","\"use client\"\n\nimport { TextInput } from \"../../admin/components/field.js\"\nimport type { FieldInputProps } from \"../../schema/field-type.js\"\nimport { FieldShell } from \"../field-shell.js\"\nimport type { TextField } from \"../../types/field.js\"\n\nexport function TextFieldInput({\n field,\n value,\n onChange,\n onBlur,\n errors,\n disabled = false,\n readonly = false,\n}: FieldInputProps<string, TextField>) {\n return (\n <FieldShell field={field} errors={errors}>\n {({ id, describedBy, invalid }) => (\n <TextInput\n id={id}\n type=\"text\"\n value={value ?? \"\"}\n placeholder={field.placeholder}\n maxLength={field.validation?.maxLength}\n invalid={invalid}\n aria-describedby={describedBy}\n disabled={disabled}\n readOnly={readonly || field.readonly === true}\n onChange={(event) =>\n // \"\" is emitted as null: empty has one representation in a Husk entry, and the\n // shared validator treats a blank string as empty anyway.\n onChange(event.target.value === \"\" ? null : event.target.value)\n }\n onBlur={onBlur}\n />\n )}\n </FieldShell>\n )\n}\n","import type { FieldError } from \"../../types/entry.js\"\nimport type { FieldTypeSpec } from \"../../schema/field-type.js\"\nimport type { TextField } from \"../../types/field.js\"\nimport { storedString } from \"../values.js\"\nimport { TextFieldInput } from \"./input.js\"\n\n/**\n * The single-line text field.\n *\n * It adds no rule of its own: `required`, `minLength`, `maxLength` and `pattern` are all\n * shared-validator rules, and re-checking them here would report every failure twice.\n */\nexport const textField: FieldTypeSpec<string, TextField> = {\n name: \"text\",\n toStored: (value) => storedString(value),\n fromStored: (raw) => storedString(raw),\n Input: TextFieldInput,\n validate: (): FieldError[] => [],\n tsType: \"string\",\n defaultValue: (field) => field.defaultValue ?? null,\n editor: {\n label: \"Text\",\n description: \"A single line of plain text.\",\n rules: [\"required\", \"minLength\", \"maxLength\", \"pattern\", \"unique\"],\n options: [\n { key: \"defaultValue\", label: \"Default value\", control: \"text\" },\n { key: \"placeholder\", label: \"Placeholder\", control: \"text\" },\n ],\n defaults: {},\n },\n}\n","\"use client\"\n\nimport { Textarea } from \"../../admin/components/textarea.js\"\nimport type { FieldInputProps } from \"../../schema/field-type.js\"\nimport { FieldShell } from \"../field-shell.js\"\nimport type { TextareaField } from \"../../types/field.js\"\n\nexport function TextareaFieldInput({\n field,\n value,\n onChange,\n onBlur,\n errors,\n disabled = false,\n readonly = false,\n}: FieldInputProps<string, TextareaField>) {\n return (\n <FieldShell field={field} errors={errors}>\n {({ id, describedBy, invalid }) => (\n <Textarea\n id={id}\n rows={field.rows}\n value={value ?? \"\"}\n placeholder={field.placeholder}\n maxLength={field.validation?.maxLength}\n invalid={invalid}\n aria-describedby={describedBy}\n disabled={disabled}\n readOnly={readonly || field.readonly === true}\n onChange={(event) =>\n onChange(event.target.value === \"\" ? null : event.target.value)\n }\n onBlur={onBlur}\n />\n )}\n </FieldShell>\n )\n}\n","import type { FieldError } from \"../../types/entry.js\"\nimport type { FieldTypeSpec } from \"../../schema/field-type.js\"\nimport type { TextareaField } from \"../../types/field.js\"\nimport { storedString } from \"../values.js\"\nimport { TextareaFieldInput } from \"./input.js\"\n\n/**\n * Multi-line plain text. Same value as `text`; only the control differs, which is the whole\n * reason it is a separate field type rather than an option on `text`.\n */\nexport const textareaField: FieldTypeSpec<string, TextareaField> = {\n name: \"textarea\",\n toStored: (value) => storedString(value),\n fromStored: (raw) => storedString(raw),\n Input: TextareaFieldInput,\n validate: (): FieldError[] => [],\n tsType: \"string\",\n defaultValue: (field) => field.defaultValue ?? null,\n editor: {\n label: \"Long text\",\n description: \"Several lines of plain text, with no formatting.\",\n rules: [\"required\", \"minLength\", \"maxLength\"],\n options: [\n { key: \"rows\", label: \"Rows\", control: \"number\", help: \"How tall the box is.\" },\n { key: \"placeholder\", label: \"Placeholder\", control: \"text\" },\n ],\n defaults: {},\n },\n}\n","import { registerFieldTypes } from \"../schema/field-type.js\"\n\nimport { booleanField } from \"./boolean/index.js\"\nimport { dateField } from \"./date/index.js\"\nimport { fileField } from \"./file/index.js\"\nimport { imageField } from \"./image/index.js\"\nimport { numberField } from \"./number/index.js\"\nimport { relationField } from \"./relation/index.js\"\nimport { repeaterField } from \"./repeater/index.js\"\nimport { richtextField } from \"./richtext/index.js\"\nimport { selectField } from \"./select/index.js\"\nimport { slugField } from \"./slug/index.js\"\nimport { textField } from \"./text/index.js\"\nimport { textareaField } from \"./textarea/index.js\"\n\n/**\n * The one registration point.\n *\n * The admin looks a field up here and renders `spec.Input`; it never switches on a field\n * name. Adding a field type means adding it to this array and nowhere else, and a screen\n * that needs `switch (field.type)` is telling you the abstraction has failed.\n *\n * Every field type the MVP promises is now here, which is what makes the rule checkable\n * rather than aspirational.\n *\n * `repeater` imports this module back, because it renders its nested fields through the\n * registry. The cycle is deliberate and safe: see the note in `repeater/input.tsx`.\n */\nexport const fieldTypes = registerFieldTypes([\n textField,\n textareaField,\n numberField,\n booleanField,\n selectField,\n dateField,\n slugField,\n richtextField,\n imageField,\n fileField,\n relationField,\n repeaterField,\n])\n\nexport {\n booleanField,\n dateField,\n fileField,\n imageField,\n numberField,\n relationField,\n repeaterField,\n richtextField,\n selectField,\n slugField,\n textField,\n textareaField,\n}\nexport { FieldFormProvider, useFieldForm } from \"./form-context.js\"\nexport type {\n FieldFormContextValue,\n FieldFormProviderProps,\n UniqueCheck,\n} from \"./form-context.js\"\nexport { FieldShell } from \"./field-shell.js\"\nexport type { FieldShellProps } from \"./field-shell.js\"\nexport { isSlug, slugify } from \"./slug/slugify.js\"\nexport {\n RICHTEXT_FEATURES,\n RICHTEXT_FORMAT,\n RICHTEXT_HEADING_LEVELS,\n RICHTEXT_MARKS,\n RICHTEXT_NODES,\n emptyRichTextContent,\n inspectRichText,\n isEmptyRichTextContent,\n isRichTextValue,\n isRichtextFeature,\n resolveFeatures,\n richTextToPlainText,\n} from \"./richtext/index.js\"\nexport type {\n RichTextNodeJSON,\n RichTextReadState,\n RichtextFeature,\n} from \"./richtext/index.js\"\nexport { acceptsType, isMediaReference, storedMediaReference } from \"./media/reference.js\"\nexport { IMAGE_ACCEPT } from \"./media/spec.js\"\nexport {\n MediaPickerProvider,\n useMediaLookup,\n useMediaPicker,\n} from \"./media/picker-context.js\"\nexport type {\n MediaLookup,\n MediaPickerApi,\n MediaPickerProviderProps,\n MediaPickRequest,\n} from \"./media/picker-context.js\"\nexport { relationSourceFromAdapter } from \"./relation/source.js\"\nexport type {\n RelationOption,\n RelationSearchRequest,\n RelationSource,\n RelationSourceOptions,\n RelationTypeInfo,\n} from \"./relation/source.js\"\nexport { RelationSourceProvider, useRelationSource } from \"./relation/source-context.js\"\nexport type { RelationSourceProviderProps } from \"./relation/source-context.js\"\nexport { emptyRow, isRow, moveRow } from \"./repeater/rows.js\"\nexport type { RepeaterRow } from \"./repeater/rows.js\"\n","import type { FieldTypeRegistry } from \"./field-type.js\"\nimport type { AnyContentTypeShape, FieldError } from \"../types/entry.js\"\nimport type { FieldDefinition, FieldMap, ValidationRules } from \"../types/field.js\"\n\n/**\n * One validation pass over an entry.\n *\n * This is the only validator in the product. The admin form runs it on change and on\n * submit; the adapter runs it again before every write. A rule enforced in one place only\n * is a rule that is not enforced.\n *\n * `unique` cannot be answered without reading other entries, so it is not checked here.\n * `uniqueFieldPaths()` lists the fields the adapter must check, and the adapter reports the\n * failure with the same `FieldError` shape, so the form renders it identically.\n */\nexport interface ValidateOptions {\n /**\n * Skip `required`. Used when saving a draft, where an incomplete entry is the point.\n * Every other rule still applies: a value that is present must still be valid.\n */\n skipRequired?: boolean\n /**\n * The registered field types, so each field's own `validate` runs alongside the shared\n * rules. Optional, because the rules below stand on their own and a database-defined type\n * using an unregistered field type must still validate rather than throw.\n *\n * The two halves do not overlap by construction: everything expressible as a\n * `ValidationRules` key is checked here, once, and a spec adds only what its own field\n * definition knows (a number's `step`, a date's precision, a slug's shape).\n */\n fieldTypes?: FieldTypeRegistry\n}\n\nfunction isEmpty(value: unknown): boolean {\n if (value === null || value === undefined) return true\n if (typeof value === \"string\") return value.trim() === \"\"\n if (Array.isArray(value)) return value.length === 0\n return false\n}\n\nfunction error(path: string, rule: string, message: string): FieldError {\n return { path, rule, message }\n}\n\n/** Generic shape check, independent of the field type specs that arrive in M5. */\nfunction checkType(\n value: unknown,\n field: FieldDefinition,\n path: string,\n label: string,\n): FieldError | null {\n switch (field.type) {\n case \"text\":\n case \"textarea\":\n case \"slug\":\n case \"date\":\n return typeof value === \"string\"\n ? null\n : error(path, \"type\", `${label} must be text.`)\n\n case \"number\":\n return typeof value === \"number\" && Number.isFinite(value)\n ? null\n : error(path, \"type\", `${label} must be a number.`)\n\n case \"boolean\":\n return typeof value === \"boolean\"\n ? null\n : error(path, \"type\", `${label} must be true or false.`)\n\n case \"select\": {\n const allowed: string[] = field.options.map((option) => option.value)\n if (field.multiple === true) {\n if (!Array.isArray(value)) {\n return error(path, \"type\", `${label} must be a list of options.`)\n }\n const bad = value.find(\n (entry) => typeof entry !== \"string\" || !allowed.includes(entry),\n )\n return bad === undefined\n ? null\n : error(path, \"option\", `${label} does not allow the option ${String(bad)}.`)\n }\n return typeof value === \"string\" && allowed.includes(value)\n ? null\n : error(path, \"option\", `${label} does not allow the option ${String(value)}.`)\n }\n\n case \"richtext\":\n return typeof value === \"object\" &&\n value !== null &&\n (value as { format?: unknown }).format === \"husk-richtext-v1\"\n ? null\n : error(path, \"type\", `${label} must be a rich text document.`)\n\n case \"image\":\n case \"file\":\n return typeof value === \"object\" &&\n value !== null &&\n typeof (value as { mediaId?: unknown }).mediaId === \"string\"\n ? null\n : error(path, \"type\", `${label} must reference an item in the media library.`)\n\n case \"relation\":\n if (field.many === true) {\n return Array.isArray(value) && value.every((entry) => typeof entry === \"string\")\n ? null\n : error(path, \"type\", `${label} must be a list of entry references.`)\n }\n return typeof value === \"string\"\n ? null\n : error(path, \"type\", `${label} must be an entry reference.`)\n\n case \"repeater\":\n return Array.isArray(value) ? null : error(path, \"type\", `${label} must be a list.`)\n }\n}\n\nfunction checkRules(\n value: unknown,\n rules: ValidationRules,\n path: string,\n label: string,\n): FieldError[] {\n const errors: FieldError[] = []\n const { minLength, maxLength, min, max, pattern } = rules\n\n const measurable =\n typeof value === \"string\" ? value.length : Array.isArray(value) ? value.length : null\n\n if (measurable !== null) {\n if (minLength !== undefined && measurable < minLength) {\n errors.push(\n error(\n path,\n \"minLength\",\n typeof value === \"string\"\n ? `${label} must be at least ${minLength} characters.`\n : `${label} must have at least ${minLength} entries.`,\n ),\n )\n }\n if (maxLength !== undefined && measurable > maxLength) {\n errors.push(\n error(\n path,\n \"maxLength\",\n typeof value === \"string\"\n ? `${label} must be at most ${maxLength} characters.`\n : `${label} must have at most ${maxLength} entries.`,\n ),\n )\n }\n }\n\n if (typeof value === \"number\") {\n if (min !== undefined && value < min) {\n errors.push(error(path, \"min\", `${label} must be ${min} or more.`))\n }\n if (max !== undefined && value > max) {\n errors.push(error(path, \"max\", `${label} must be ${max} or less.`))\n }\n }\n\n if (pattern !== undefined && typeof value === \"string\") {\n let regex: RegExp\n try {\n regex = new RegExp(pattern)\n } catch {\n errors.push(\n error(\n path,\n \"pattern\",\n `${label} has an invalid pattern in its schema: ${pattern}`,\n ),\n )\n return errors\n }\n if (!regex.test(value)) {\n errors.push(error(path, \"pattern\", `${label} has the wrong format.`))\n }\n }\n\n return errors\n}\n\n/** The whole entry, kept for the cross-field context a spec's `validate` receives. */\ninterface ValidateRoot {\n type: AnyContentTypeShape\n values: Record<string, unknown>\n}\n\nfunction validateFieldMap(\n fields: FieldMap,\n values: Record<string, unknown>,\n prefix: string,\n options: ValidateOptions,\n root: ValidateRoot,\n): FieldError[] {\n const errors: FieldError[] = []\n\n for (const [key, field] of Object.entries(fields)) {\n const path = prefix ? `${prefix}.${key}` : key\n const label = field.label\n const rules = field.validation ?? {}\n const value = values[key]\n\n if (isEmpty(value)) {\n if (rules.required === true && options.skipRequired !== true) {\n errors.push(error(path, \"required\", `${label} is required.`))\n }\n // Nothing else is meaningful about an empty value. An optional empty field is valid\n // by definition, and a required empty one has already been reported.\n continue\n }\n\n const typeError = checkType(value, field, path, label)\n if (typeError) {\n errors.push(typeError)\n continue\n }\n\n errors.push(...checkRules(value, rules, path, label))\n\n const spec = options.fieldTypes?.get(field.type)\n if (spec) {\n errors.push(\n ...spec.validate(\n value,\n rules,\n { path, contentType: root.type, entry: root.values },\n field,\n ),\n )\n }\n\n if (field.type === \"repeater\" && Array.isArray(value)) {\n value.forEach((row: unknown, index: number) => {\n if (typeof row !== \"object\" || row === null || Array.isArray(row)) {\n errors.push(\n error(\n `${path}.${index}`,\n \"type\",\n `${label} entry ${index + 1} is not valid.`,\n ),\n )\n return\n }\n errors.push(\n ...validateFieldMap(\n field.fields,\n row as Record<string, unknown>,\n `${path}.${index}`,\n options,\n root,\n ),\n )\n })\n }\n }\n\n // Values for fields the schema no longer declares are left alone on purpose. M8 removes a\n // field by marking it removed and keeping its data until an explicit purge, so an unknown\n // key is expected state, not an error.\n\n return errors\n}\n\nexport function validateEntry(\n type: AnyContentTypeShape,\n values: Record<string, unknown>,\n options: ValidateOptions = {},\n): FieldError[] {\n return validateFieldMap(type.fields, values, \"\", options, { type, values })\n}\n\n/**\n * Field keys carrying `unique`, for the adapter to check against stored entries. Fields\n * nested in a repeater are excluded: uniqueness across repeater rows is not a constraint\n * this CMS offers, and pretending otherwise would need a query no index supports.\n */\nexport function uniqueFieldPaths(type: AnyContentTypeShape): string[] {\n return Object.entries(type.fields)\n .filter(([, field]) => field.validation?.unique === true)\n .map(([key]) => key)\n}\n\n/** Patterns the Schema Builder offers as presets, so editors do not hand-write regexes. */\nexport const PATTERN_PRESETS = {\n email: \"^[^\\\\s@]+@[^\\\\s@]+\\\\.[^\\\\s@]+$\",\n slug: \"^[a-z0-9]+(?:-[a-z0-9]+)*$\",\n url: \"^https?://[^\\\\s]+$\",\n} as const\n","\"use client\"\n\nimport { useEffect, useState } from \"react\"\nimport type { ReactNode } from \"react\"\n\nimport type { StatusTransition } from \"../../core/entry-status.js\"\nimport { STATUS_EFFECT } from \"../../core/entry-status.js\"\nimport type { AuthUser } from \"../../types/auth.js\"\nimport type { Entry, EntryStatus } from \"../../types/entry.js\"\nimport { Badge, ENTRY_STATUS_LABEL, ENTRY_STATUS_VARIANT } from \"../components/badge.js\"\nimport { Button } from \"../components/button.js\"\nimport { Panel } from \"../components/panel.js\"\nimport { Skeleton } from \"../components/skeleton.js\"\nimport { formatDateTime } from \"../format.js\"\n\n/**\n * The entry editor metadata sidebar.\n * Canonical source: .docs/styleguide/03-layout.md section 5.2.1.\n *\n * Everything on it is owned by the adapter rather than by the form: status, the three\n * timestamps, and the uid that created the entry. The one control is the status\n * transition, and it is a control rather than a display because status is the single piece\n * of entry metadata an editor writes.\n */\n\n/** What the admin can say about a uid. Enough to name someone, and nothing more. */\nexport interface AuthorInfo {\n uid: string\n displayName?: string | null\n email?: string | null\n}\n\n/**\n * Resolves a uid to a person.\n *\n * An entry stores who created it as a uid, and a uid is not a name. Turning one into a\n * name is a read against the user documents, which the `CmsAdapter` does not expose and\n * the Users area (M9) owns. So it is a seam: a host that can answer supplies this, and a\n * host that cannot simply does not.\n */\nexport type AuthorLookup = (uid: string) => Promise<AuthorInfo | null>\n\ntype AuthorState =\n | { kind: \"loading\" }\n | { kind: \"named\"; name: string; hint: string | undefined }\n | { kind: \"unresolved\"; uid: string }\n\nfunction nameOf(info: AuthorInfo): string | null {\n const name = info.displayName?.trim()\n if (name !== undefined && name !== \"\") return name\n const email = info.email?.trim()\n return email !== undefined && email !== \"\" ? email : null\n}\n\n/**\n * Who created this entry.\n *\n * The signed-in user is answered without a read, because the form already knows them and\n * the most common author of an entry someone is editing is themselves. Everyone else needs\n * the lookup, and when there is no lookup, or it comes back empty, the sidebar says\n * \"Unknown user\" and prints the uid underneath. That is the honest answer: the entry does\n * record an author, the admin just cannot name them, and the raw id is what somebody would\n * need to find out who it was.\n */\nexport function useAuthor(\n uid: string | null,\n user: AuthUser,\n resolve: AuthorLookup | undefined,\n): AuthorState {\n const isSelf = uid !== null && uid === user.uid\n const [answer, setAnswer] = useState<{ uid: string; info: AuthorInfo | null } | null>(\n null,\n )\n\n useEffect(() => {\n if (uid === null || isSelf || resolve === undefined) return\n let cancelled = false\n\n resolve(uid)\n .then((info) => {\n if (!cancelled) setAnswer({ uid, info })\n })\n .catch(() => {\n // A failed lookup is not proof the user is gone, but the row has to render\n // something, and \"Unknown user\" with the id under it is what somebody can act on.\n if (!cancelled) setAnswer({ uid, info: null })\n })\n\n return () => {\n cancelled = true\n }\n }, [uid, isSelf, resolve])\n\n const self = nameOf({\n uid: user.uid,\n displayName: user.displayName,\n email: user.email,\n })\n\n if (uid === null) {\n return {\n kind: \"named\",\n name: self ?? user.uid,\n hint: \"You, once this entry is saved\",\n }\n }\n\n if (isSelf) return { kind: \"named\", name: self ?? user.uid, hint: \"You\" }\n\n if (resolve === undefined) return { kind: \"unresolved\", uid }\n if (answer === null || answer.uid !== uid) return { kind: \"loading\" }\n if (answer.info === null) return { kind: \"unresolved\", uid }\n\n const name = nameOf(answer.info)\n return name === null\n ? { kind: \"unresolved\", uid }\n : { kind: \"named\", name, hint: undefined }\n}\n\ninterface MetadataRowProps {\n label: string\n children: ReactNode\n /** Second line, for the raw id behind a value the admin could not resolve. */\n hint?: string | undefined\n}\n\nfunction MetadataRow({ label, children, hint }: MetadataRowProps) {\n return (\n <div className=\"flex flex-col gap-0.5\">\n <span className=\"text-caption text-text-faint\">{label}</span>\n <span className=\"text-body-sm text-text-secondary\">{children}</span>\n {hint === undefined ? null : (\n <span className=\"text-caption text-text-faint\">{hint}</span>\n )}\n </div>\n )\n}\n\nfunction AuthorValue({ state }: { state: AuthorState }) {\n if (state.kind === \"loading\") {\n return <Skeleton line=\"body-sm\" className=\"w-32\" label=\"Looking up the author\" />\n }\n\n if (state.kind === \"unresolved\") {\n return <span className=\"text-text-muted\">Unknown user</span>\n }\n\n return <>{state.name}</>\n}\n\n/** The second line under the author, which differs by how the name was arrived at. */\nfunction authorHint(state: AuthorState): string | undefined {\n if (state.kind === \"unresolved\") return state.uid\n if (state.kind === \"named\") return state.hint\n return undefined\n}\n\nexport interface EntryMetadataProps {\n user: AuthUser\n /** Null while the entry has not been created yet. */\n entry: Entry | null\n /** The stored status. The badge reports what is saved, never what is intended. */\n status: EntryStatus\n /**\n * The status the next save will write, when that is not the stored one. Set only after a\n * transition was refused by validation, so the editor can see why the badge has not\n * moved.\n */\n pending?: EntryStatus | null\n transitions: readonly StatusTransition[]\n onTransition: (to: EntryStatus) => void\n /** A write is in flight, so no transition may start a second one. */\n busy?: boolean\n resolveAuthor?: AuthorLookup | undefined\n /**\n * The destructive actions, below the rule. A seam: the delete flow supplies the button,\n * and a host without one renders no section rather than a button that does nothing.\n */\n actions?: ReactNode\n}\n\nexport function EntryMetadata({\n user,\n entry,\n status,\n pending = null,\n transitions,\n onTransition,\n busy = false,\n resolveAuthor,\n actions,\n}: EntryMetadataProps) {\n const author = useAuthor(entry?.createdBy ?? null, user, resolveAuthor)\n const offered = transitions.filter((transition) => transition.allowed)\n // Every transition carries the same answer, so the first reason is the only reason.\n const refusal = transitions.find((transition) => !transition.allowed)?.reason ?? null\n\n return (\n <Panel raised padding=\"compact\">\n <section aria-label=\"Status\">\n <Badge variant={ENTRY_STATUS_VARIANT[status]}>{ENTRY_STATUS_LABEL[status]}</Badge>\n <p className=\"mt-2 text-caption text-text-faint\">{STATUS_EFFECT[status]}</p>\n\n {pending === null || pending === status ? null : (\n <p className=\"mt-2 text-caption text-warning\">\n {`This save will set the status to ${ENTRY_STATUS_LABEL[pending]}.`}\n </p>\n )}\n\n {offered.length > 0 ? (\n <div className=\"mt-3 flex flex-col gap-3\">\n {offered.map((transition) => (\n <div key={transition.to} className=\"flex flex-col gap-1\">\n <Button\n variant=\"secondary\"\n disabled={busy}\n onClick={() => onTransition(transition.to)}\n >\n {transition.label}\n </Button>\n <span className=\"text-caption text-text-faint\">{transition.effect}</span>\n </div>\n ))}\n </div>\n ) : refusal === null ? null : (\n <p className=\"mt-3 text-caption text-text-muted\">{refusal}</p>\n )}\n </section>\n\n <hr className=\"my-4 border-0 border-t border-border-subtle\" />\n\n <section aria-label=\"Details\" className=\"flex flex-col gap-3\">\n <MetadataRow label=\"Author\" hint={authorHint(author)}>\n <AuthorValue state={author} />\n </MetadataRow>\n\n {entry === null ? (\n <MetadataRow label=\"Created\">\n <span className=\"text-text-muted\">Not saved yet</span>\n </MetadataRow>\n ) : (\n <>\n <MetadataRow label=\"Created\">{formatDateTime(entry.createdAt)}</MetadataRow>\n <MetadataRow label=\"Last updated\">\n {formatDateTime(entry.updatedAt)}\n </MetadataRow>\n {/* An entry that was never published has no publication date, so it shows no\n row. A placeholder would imply the field exists and is empty. */}\n {entry.publishedAt === null ? null : (\n <MetadataRow label=\"Published\">\n {formatDateTime(entry.publishedAt)}\n </MetadataRow>\n )}\n </>\n )}\n </section>\n\n {actions === undefined ? null : (\n <>\n <hr className=\"my-4 border-0 border-t border-border-subtle\" />\n <section aria-label=\"Entry actions\">{actions}</section>\n </>\n )}\n </Panel>\n )\n}\n","\"use client\"\n\nimport type { ReactNode } from \"react\"\n\nimport type { ClassifiedError, ErrorCategory } from \"../../core/error-taxonomy.js\"\nimport { Button } from \"../components/button.js\"\nimport { EmptyState } from \"../components/empty-state.js\"\nimport type { IconName } from \"../components/icon.js\"\nimport { PageHeader } from \"../components/page-header.js\"\nimport { Panel } from \"../components/panel.js\"\n\n/**\n * The whole-screen treatment for a classified error.\n * Canonical source: .docs/styleguide/04-components.md section 19.\n *\n * Used where the failure took the screen's content with it: a read that did not return, a\n * route that resolved to nothing, and every route error boundary. An in-place failure that\n * still has a form around it uses `ErrorNotice` instead.\n *\n * It renders inside whatever chrome it was mounted in, so an admin route boundary keeps the\n * sidebar and the user keeps a way out. The one thing it never does is show a stack trace:\n * a boundary that prints one has replaced a blank screen with an unreadable one.\n */\nconst CATEGORY_ICON: Readonly<Record<ErrorCategory, IconName>> = {\n validation: \"error\",\n permission: \"permissions\",\n // Not an error. The search glyph says \"we looked and it is not here\", which is what the\n // 404 screen already uses, and it keeps the red reserved for things that actually broke.\n \"not-found\": \"search\",\n conflict: \"warning\",\n transport: \"error\",\n unknown: \"error\",\n}\n\nexport interface ErrorScreenProps {\n error: ClassifiedError\n /** Shown above the panel. Omitted inside a boundary that already sits under a header. */\n title?: string | undefined\n /** Rendered only when the taxonomy says a retry can help. */\n onRetry?: (() => void) | undefined\n /** One action at most, per the empty-state rule: a link back, or a sign-out. */\n children?: ReactNode\n}\n\nexport function ErrorScreen({ error, title, onRetry, children }: ErrorScreenProps) {\n const retry =\n error.retryable && onRetry !== undefined ? (\n <Button variant=\"secondary\" icon=\"retry\" onClick={onRetry}>\n Try again\n </Button>\n ) : undefined\n\n // One action, never two: the guide calls a second one a design error. A retry outranks a\n // way back, because it is the action that can resolve the failure rather than leave it.\n const action = retry ?? children\n\n return (\n <>\n {title === undefined ? null : <PageHeader title={title} />}\n <Panel>\n <div data-error-category={error.category}>\n <EmptyState\n icon={CATEGORY_ICON[error.category]}\n heading={error.title}\n description={error.message}\n {...(action === undefined ? {} : { action })}\n />\n </div>\n </Panel>\n </>\n )\n}\n","\"use client\"\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport type { ReactNode } from \"react\"\n\nimport type { CmsAdapter } from \"../../core/adapter.js\"\nimport { isSingleton, singletonEntryId } from \"../../core/content-kind.js\"\nimport {\n entryChangedSince,\n errorsUnder,\n formFields,\n formValuesFromEntry,\n initialFormValues,\n mergeIssues,\n unroutableIssues,\n valuesChanged,\n} from \"../../core/entry-form.js\"\nimport type { FormIssue } from \"../../core/entry-form.js\"\nimport { canSaveEntry, statusTransitions } from \"../../core/entry-status.js\"\nimport type { StatusTransition } from \"../../core/entry-status.js\"\nimport { entryTitle } from \"../../core/entry-title.js\"\nimport { entryUniqueCheck } from \"../../core/entry-unique.js\"\nimport {\n classifyError,\n missingError,\n staleWriteError,\n} from \"../../core/error-taxonomy.js\"\nimport type { ClassifiedError } from \"../../core/error-taxonomy.js\"\nimport { fieldTypes } from \"../../fields/index.js\"\nimport { FieldFormProvider } from \"../../fields/form-context.js\"\nimport { RelationSourceProvider } from \"../../fields/relation/source-context.js\"\nimport { relationSourceFromAdapter } from \"../../fields/relation/source.js\"\nimport { can } from \"../../permissions/can.js\"\nimport type { FieldTypeRegistry } from \"../../schema/field-type.js\"\nimport { validateEntry } from \"../../schema/validate.js\"\nimport type { AuthUser } from \"../../types/auth.js\"\nimport type { ContentTypeLike } from \"../../types/content-type.js\"\nimport type { Entry, EntryStatus, FieldError } from \"../../types/entry.js\"\nimport type { FieldDefinition } from \"../../types/field.js\"\nimport { Button } from \"../components/button.js\"\nimport { ErrorNotice } from \"../components/error-notice.js\"\nimport { FormError } from \"../components/form-error.js\"\nimport { Panel } from \"../components/panel.js\"\nimport { Skeleton } from \"../components/skeleton.js\"\nimport { useOptionalToast } from \"../components/toast.js\"\nimport { useConfirmLeave, useUnsavedChanges } from \"../components/unsaved-changes.js\"\nimport { PageHeader } from \"../components/page-header.js\"\nimport { contentTypeLabel } from \"../navigation/navigation.js\"\nimport { EntryMetadata } from \"./entry-metadata.js\"\nimport { ErrorScreen } from \"./error-screen.js\"\nimport type { AuthorLookup } from \"./entry-metadata.js\"\n\n/**\n * The entry editor, generated from the content type.\n * Canonical source: .docs/styleguide/03-layout.md section 5.2.\n *\n * One screen shape serves creating and editing, because they differ in exactly two things:\n * whether there is an entry behind the form, and which adapter method the save calls.\n * Everything else (which fields exist, what they start at, what is valid, what the status\n * control offers) is read from the schema and from `can()`.\n *\n * There is no `switch (field.type)` here and there never may be. A field is rendered by\n * looking its spec up in the registry and mounting `spec.Input`, so a field type added in\n * `src/fields/index.ts` works in this form the day it is registered.\n *\n * Three things it is deliberate about:\n *\n * - **Where an error lands.** The shared validator and the adapter both report a\n * `FieldError` with a dotted path, and every input is mounted at its path, so an error\n * is routed to the control that owns it, including one inside a repeater row. Only an\n * error naming a field this form does not render reaches the form-level message, and\n * only a failure that is not about a field at all reaches a toast.\n * - **Which error is newer.** A client error is recomputed on every keystroke; a server\n * error is a verdict about what was submitted and no keystroke can retract it. See\n * `mergeIssues` in core/entry-form.ts.\n * - **Draft versus published.** A draft skips `required` and nothing else, and that is the\n * same option the adapter passes to the same validator on the write path.\n *\n * A singleton is the same screen with two answers changed, not a second screen. It reads\n * through `getSingle` instead of `get`, and a singleton that was never saved is a form with\n * no entry behind it rather than a missing-entry state: the document simply does not exist\n * yet, and the first save is the `create` that brings it into being at the id\n * `singletonEntryId` derives from the slug. It offers no delete, because `assertDeletable`\n * refuses one, and no list to go back to, because `assertListable` refuses that too.\n *\n * One thing is optimistic and it is named here so the rest is known not to be: a status\n * transition paints the new badge before the adapter answers, and a failure puts the exact\n * stored status back. See `optimistic` in EntryForm.\n */\n\nexport interface EntryEditorProps {\n adapter: CmsAdapter\n type: ContentTypeLike\n user: AuthUser\n /** Absent for a create screen. Present for an edit screen. */\n entryId?: string | undefined\n /** Called after a successful write, so the host can route from create to edit. */\n onSaved?: ((entry: Entry, created: boolean) => void) | undefined\n onCancel?: (() => void) | undefined\n /** The seam the unsaved-changes guard attaches to. */\n onDirtyChange?: ((dirty: boolean) => void) | undefined\n /** The seam the delete flow attaches to. No callback means no destructive action. */\n onDelete?: ((entryId: string) => void) | undefined\n resolveAuthor?: AuthorLookup | undefined\n /** Resolves a relation target slug, for the relation picker. */\n getType?: ((slug: string) => ContentTypeLike | undefined) | undefined\n /** The field type registry. Defaults to the one every field type registers into. */\n registry?: FieldTypeRegistry | undefined\n}\n\ntype LoadState =\n | { status: \"loading\" }\n | { status: \"ready\"; entry: Entry | null }\n // Both of these are a `ClassifiedError` rather than a string, so the read path uses the\n // one taxonomy the save path uses and neither invents its own wording or its own chrome.\n | { status: \"missing\"; error: ClassifiedError }\n | { status: \"failed\"; error: ClassifiedError }\n\nexport function EntryEditor({\n adapter,\n type,\n user,\n entryId,\n onSaved,\n onCancel,\n onDirtyChange,\n onDelete,\n resolveAuthor,\n getType,\n registry = fieldTypes,\n}: EntryEditorProps) {\n const singleton = isSingleton(type)\n // A singleton is addressed by the id its slug derives, never by a route parameter, so a\n // host does not have to know the derivation and cannot pass the wrong one.\n const target = singleton ? singletonEntryId(type.slug) : entryId\n\n const [state, setState] = useState<LoadState>(() =>\n target === undefined ? { status: \"ready\", entry: null } : { status: \"loading\" },\n )\n const [attempt, setAttempt] = useState(0)\n const [reading, setReading] = useState(target)\n\n // The entry being edited is a prop, and the load state is derived from it. Resetting\n // during render rather than in an effect is what keeps a route change from painting the\n // previous entry for one frame before the effect catches up.\n if (reading !== target) {\n setReading(target)\n setState(\n target === undefined ? { status: \"ready\", entry: null } : { status: \"loading\" },\n )\n }\n\n useEffect(() => {\n if (target === undefined) return\n\n let cancelled = false\n\n const read = singleton ? adapter.getSingle(type.slug) : adapter.get(type.slug, target)\n\n read\n .then((entry) => {\n if (cancelled) return\n if (entry !== null) {\n setState({ status: \"ready\", entry })\n return\n }\n // A collection entry that is not there was deleted or never existed, and saying so\n // is the only honest answer. A singleton that is not there has simply never been\n // saved, and the right screen for that is the empty form that creates it.\n setState(\n singleton\n ? { status: \"ready\", entry: null }\n : { status: \"missing\", error: missingError(type.label.toLowerCase()) },\n )\n })\n .catch((thrown: unknown) => {\n if (cancelled) return\n setState({\n status: \"failed\",\n error: classifyError(thrown, {\n role: user.role,\n action: `open this ${type.label.toLowerCase()}`,\n subject: type.label,\n }),\n })\n })\n\n return () => {\n cancelled = true\n }\n }, [adapter, type.slug, type.label, user.role, target, singleton, attempt])\n\n if (state.status === \"loading\") {\n return (\n <>\n <PageHeader title={`Loading ${type.label.toLowerCase()}`} />\n <Panel padding=\"large\">\n <div className=\"flex flex-col gap-5\">\n <Skeleton line=\"body\" className=\"w-64\" label=\"Loading the entry\" />\n <Skeleton line=\"body\" className=\"w-full\" />\n <Skeleton line=\"body\" className=\"w-full\" />\n </div>\n </Panel>\n </>\n )\n }\n\n // A missing entry is a state, not an error: no alert, no danger colour, one way back.\n // A failed read is whatever the taxonomy makes of it, and only a transport failure gets\n // the retry, because re-reading after a permission refusal is refused again.\n if (state.status === \"missing\" || state.status === \"failed\") {\n return (\n <ErrorScreen\n error={state.error}\n title={type.label}\n onRetry={() => {\n setState({ status: \"loading\" })\n setAttempt((n) => n + 1)\n }}\n >\n {onCancel === undefined ? undefined : (\n <Button variant=\"secondary\" onClick={onCancel}>\n {`Back to ${contentTypeLabel(type)}`}\n </Button>\n )}\n </ErrorScreen>\n )\n }\n\n return (\n <EntryForm\n onReload={() => {\n setState({ status: \"loading\" })\n setAttempt((n) => n + 1)\n }}\n // A different entry is a different form, with its own values, its own touched set\n // and its own baseline. Remounting is what keeps them from leaking across a route\n // change that reuses this component.\n key={state.entry?.id ?? \"new\"}\n adapter={adapter}\n type={type}\n user={user}\n entry={state.entry}\n registry={registry}\n onSaved={onSaved}\n onCancel={onCancel}\n onDirtyChange={onDirtyChange}\n onDelete={onDelete}\n resolveAuthor={resolveAuthor}\n getType={getType}\n />\n )\n}\n\ninterface EntryFormProps {\n adapter: CmsAdapter\n type: ContentTypeLike\n user: AuthUser\n entry: Entry | null\n registry: FieldTypeRegistry\n onSaved?: ((entry: Entry, created: boolean) => void) | undefined\n onCancel?: (() => void) | undefined\n onDirtyChange?: ((dirty: boolean) => void) | undefined\n onDelete?: ((entryId: string) => void) | undefined\n resolveAuthor?: AuthorLookup | undefined\n getType?: ((slug: string) => ContentTypeLike | undefined) | undefined\n /** Re-reads the stored entry. The conflict banner's \"discard mine\" resolution. */\n onReload: () => void\n}\n\n/** The root field key a dotted path belongs to. `blocks.1.title` is owned by `blocks`. */\nfunction rootOf(path: string): string {\n return path.split(\".\")[0] ?? path\n}\n\nfunction EntryForm({\n adapter,\n type,\n user,\n entry,\n registry,\n onSaved,\n onCancel,\n onDirtyChange,\n onDelete,\n resolveAuthor,\n getType,\n onReload,\n}: EntryFormProps) {\n const toast = useOptionalToast()\n const confirmLeave = useConfirmLeave()\n const singleton = isSingleton(type)\n const fields = useMemo(() => formFields(type), [type])\n\n /** The last state the adapter confirmed. Null until a create succeeds. */\n const [baseline, setBaseline] = useState<Entry | null>(entry)\n const [values, setValues] = useState<Record<string, unknown>>(() =>\n entry === null\n ? initialFormValues(type, registry)\n : formValuesFromEntry(type, entry, registry),\n )\n /** The values behind `baseline`, so \"dirty\" is a comparison and not a flag. */\n const [saved, setSaved] = useState<Record<string, unknown>>(values)\n /**\n * The status the next save writes.\n *\n * It equals the stored status except in one window: a transition that the validator\n * refused leaves the intent behind, so the editor can fix the fields and press save\n * rather than having to find the transition again. The badge keeps reporting the stored\n * status, because a badge that showed the intent would claim the entry is published\n * when it is not.\n */\n const [pending, setPending] = useState<EntryStatus>(entry?.status ?? \"draft\")\n const [touched, setTouched] = useState<ReadonlySet<string>>(() => new Set())\n const [submitted, setSubmitted] = useState(false)\n const [serverErrors, setServerErrors] = useState<readonly FieldError[]>([])\n /**\n * The failure that belongs to the submission rather than to one field, classified.\n *\n * One piece of state for permission, conflict, transport and unknown alike, because the\n * taxonomy already decided which chrome each of them gets; the form no longer picks.\n */\n const [failure, setFailure] = useState<ClassifiedError | null>(null)\n /** Set when the stored entry moved under the editor. The next save overwrites. */\n const [conflict, setConflict] = useState(false)\n const [saving, setSaving] = useState(false)\n /**\n * The status painted while a transition is in flight, before the adapter has answered.\n *\n * The one thing in this editor that is optimistic, and it is optimistic because the new\n * value is entirely knowable here: a transition writes a status the client picked, so\n * there is nothing to wait for except confirmation. Two things deliberately are not.\n * Creating an entry is not, because an entry has no id until the server assigns one and\n * a screen cannot route to a URL it invented. Saving field values is not, because the\n * values the editor typed are already on screen; there is nothing an optimistic render\n * would add except the chance of showing them as saved when they were refused.\n *\n * Rollback is exact rather than approximate because nothing is overwritten to begin\n * with: `baseline` is untouched until the adapter confirms, so clearing this one piece\n * of state restores the stored status itself, not a copy of it taken beforehand.\n */\n const [optimistic, setOptimistic] = useState<EntryStatus | null>(null)\n\n const editable = canSaveEntry(user, type, baseline)\n const transitions = useMemo(\n () => statusTransitions(user, type, baseline),\n [user, type, baseline],\n )\n\n const clientErrors = useMemo(\n () =>\n validateEntry(type, values, {\n // The rule the whole draft concept rests on, and the same option the adapter\n // passes on the write path: a draft may be incomplete, it may not be wrong.\n skipRequired: pending === \"draft\",\n fieldTypes: registry,\n }),\n [type, values, pending, registry],\n )\n\n /**\n * A client error is only shown once the editor has been in that field, or once a save\n * has been refused. Otherwise an empty create form would open covered in complaints\n * about values nobody has been asked for yet.\n */\n const visibleClient = useMemo(\n () =>\n submitted\n ? clientErrors\n : clientErrors.filter((error) => touched.has(rootOf(error.path))),\n [clientErrors, submitted, touched],\n )\n\n const issues = useMemo(\n () => mergeIssues(visibleClient, serverErrors),\n [visibleClient, serverErrors],\n )\n const orphans = useMemo(() => unroutableIssues(issues, type), [issues, type])\n\n const stored: EntryStatus = baseline?.status ?? \"draft\"\n const dirty = valuesChanged(saved, values) || pending !== stored\n\n // Both halves of the unsaved-changes guard, from the same comparison the save bar reads.\n useUnsavedChanges(dirty)\n\n useEffect(() => {\n onDirtyChange?.(dirty)\n }, [dirty, onDirtyChange])\n\n const checkUnique = useMemo(\n () => entryUniqueCheck({ adapter, type, entryId: baseline?.id ?? null }),\n [adapter, type, baseline],\n )\n\n const relationSource = useMemo(\n () =>\n relationSourceFromAdapter({\n adapter,\n getType: getType ?? ((slug) => (slug === type.slug ? type : undefined)),\n }),\n [adapter, getType, type],\n )\n\n const change = useCallback((key: string, next: unknown) => {\n setValues((current) => ({ ...current, [key]: next }))\n }, [])\n\n const markTouched = useCallback((key: string) => {\n setTouched((current) => (current.has(key) ? current : new Set([...current, key])))\n }, [])\n\n /**\n * Cmd/Ctrl+S saves the open entry editor.\n *\n * .docs/styleguide/04-components.md section 18 has listed it as a keyboard contract\n * since the guide was written, and nothing implemented it until the M10 accessibility\n * audit went looking. On the document rather than on the form, because the shortcut has\n * to work while focus is in the metadata sidebar or on the status control, and neither\n * is inside the form element.\n *\n * The ref is refreshed every render so the listener always calls the current save with\n * the current values; a closure captured once would save the form as it was on mount.\n */\n const saveShortcut = useRef<() => void>(() => undefined)\n\n useEffect(() => {\n function onKeyDown(event: globalThis.KeyboardEvent) {\n if (event.key !== \"s\" && event.key !== \"S\") return\n if (!event.metaKey && !event.ctrlKey) return\n // The browser's own Save-page dialog is never what someone wants over an editor.\n event.preventDefault()\n saveShortcut.current()\n }\n\n document.addEventListener(\"keydown\", onKeyDown)\n return () => document.removeEventListener(\"keydown\", onKeyDown)\n }, [])\n\n // Refreshed on every render, deliberately without a dependency array.\n useEffect(() => {\n saveShortcut.current = () => {\n void save(baseline === null ? \"draft\" : pending)\n }\n })\n\n async function save(target: EntryStatus): Promise<void> {\n if (saving || !editable) return\n\n setPending(target)\n setSubmitted(true)\n setFailure(null)\n\n const errors = validateEntry(type, values, {\n skipRequired: target === \"draft\",\n fieldTypes: registry,\n })\n if (errors.length > 0) {\n // Nothing is sent. The errors are already on their fields through `clientErrors`,\n // which recomputes from the same values with the same options.\n return\n }\n\n setSaving(true)\n\n try {\n if (baseline !== null && !conflict) {\n // Read the way this content type is read. A singleton is addressed through\n // `getSingle`, never by an id a caller had to derive for itself.\n const current = singleton\n ? await adapter.getSingle(type.slug)\n : await adapter.get(type.slug, baseline.id)\n if (current === null) {\n setFailure(missingError(type.label.toLowerCase()))\n return\n }\n if (entryChangedSince(baseline, current)) {\n // Not a write. The editor is told, and a second press goes through: refusing\n // twice would trap someone with no way to land their work.\n setConflict(true)\n setFailure(staleWriteError(`This ${type.label.toLowerCase()}`))\n return\n }\n }\n\n const created = baseline === null\n // Set here rather than at the top of the save, so a refused validation or a detected\n // conflict never moves the badge for a write that was not attempted.\n if (!created && target !== baseline.status) setOptimistic(target)\n\n const written = created\n ? await adapter.create(type.slug, { values, status: target })\n : await adapter.update(type.slug, baseline.id, { values, status: target })\n\n setBaseline(written)\n setSaved(values)\n setPending(written.status)\n setServerErrors([])\n setConflict(false)\n setSubmitted(false)\n setTouched(new Set())\n toast?.notify({\n tone: \"success\",\n title: created ? `${type.label} created` : `${type.label} saved`,\n })\n onSaved?.(written, created)\n } catch (thrown: unknown) {\n const classified = classifyError(thrown, {\n role: user.role,\n action: `save this ${type.label.toLowerCase()}`,\n subject: type.label,\n })\n\n if (classified.category === \"validation\" && classified.fieldErrors.length > 0) {\n // The M6 rule, now stated by the taxonomy rather than by this catch: a validation\n // failure lands on the control that owns its path, and only a path naming no\n // rendered field reaches the banner above. It is never a bare toast.\n setServerErrors(classified.fieldErrors)\n return\n }\n\n // No toast. The banner is this category's one treatment and the screen it belongs to\n // is still open; a toast on top of it would be the same failure worded twice, which\n // is the split this taxonomy exists to close.\n setFailure(classified)\n } finally {\n setSaving(false)\n // On success `baseline` already carries the written status, so clearing this shows\n // the confirmed value. On failure it shows the stored one again, unchanged.\n setOptimistic(null)\n }\n }\n\n // A singleton is always itself, saved or not: there is no \"New site settings\", there is\n // only the one document, which either exists yet or does not.\n const title = singleton\n ? type.label\n : baseline === null\n ? `New ${type.label}`\n : entryTitle(type, baseline)\n const shown: EntryStatus = optimistic ?? stored\n const errorCount = new Set(clientErrors.map((error) => error.path)).size\n const serverCount = serverErrors.length\n\n return (\n <>\n <PageHeader\n title={title}\n {...(singleton && baseline === null\n ? { description: \"This entry has never been saved. Saving creates it.\" }\n : {})}\n breadcrumb={\n // A singleton has no list above it, so its own label is the whole trail.\n singleton\n ? [{ label: contentTypeLabel(type) }]\n : [{ label: contentTypeLabel(type) }, { label: title }]\n }\n />\n\n <div className=\"grid grid-cols-1 gap-6 xl:entry-grid\">\n <div className=\"min-w-0\">\n {failure === null && orphans.length === 0 ? null : (\n <div className=\"mb-4 flex flex-col gap-2\">\n {failure === null ? null : (\n <ErrorNotice\n error={failure}\n onRetry={() => void save(pending)}\n {...(failure.category === \"conflict\"\n ? {\n // The `resolve` treatment: a conflict has two resolutions and the\n // banner has to offer both. Saving again overwrites, which is what\n // the save button already does now that `conflict` is set, so the\n // one this banner has to supply is the other.\n actions: (\n <Button size=\"sm\" variant=\"secondary\" onClick={onReload}>\n Discard mine and reload\n </Button>\n ),\n }\n : {})}\n />\n )}\n {orphans.map((issue) => (\n <FormError key={`${issue.path}-${issue.rule}`}>\n {issue.path === \"\" ? issue.message : `${issue.path}: ${issue.message}`}\n </FormError>\n ))}\n </div>\n )}\n\n <Panel padding=\"large\">\n <FieldFormProvider value={{ values, fields: type.fields, checkUnique }}>\n <RelationSourceProvider value={relationSource}>\n <div className=\"flex flex-col gap-5\">\n {fields.map(({ key, field }) => (\n <FieldSlot\n key={key}\n path={key}\n registry={registry}\n field={field}\n value={values[key] ?? null}\n issues={errorsUnder(issues, key)}\n disabled={saving || !editable}\n readonly={!editable}\n onChange={(next) => change(key, next)}\n onBlur={() => markTouched(key)}\n />\n ))}\n </div>\n </RelationSourceProvider>\n </FieldFormProvider>\n </Panel>\n\n <SaveBar\n failed={failure !== null}\n dirty={dirty}\n saving={saving}\n editable={editable}\n creating={baseline === null}\n transitions={transitions}\n problems={submitted ? errorCount + serverCount : 0}\n onSave={() => void save(baseline === null ? \"draft\" : pending)}\n onPublish={() => void save(\"published\")}\n {...(onCancel === undefined\n ? {}\n : { onCancel: () => confirmLeave(onCancel) })}\n />\n </div>\n\n <EntryMetadata\n user={user}\n entry={baseline}\n status={shown}\n pending={pending}\n transitions={transitions}\n busy={saving}\n onTransition={(to) => void save(to)}\n resolveAuthor={resolveAuthor}\n {...(baseline !== null &&\n onDelete !== undefined &&\n // A singleton cannot be deleted. `assertDeletable` refuses the write; this only\n // keeps the sidebar from offering a button that leads nowhere.\n !singleton &&\n can(user, \"delete\", { type, entry: { createdBy: baseline.createdBy } })\n ? {\n actions: (\n <Button\n variant=\"danger\"\n icon=\"delete\"\n className=\"w-full\"\n disabled={saving}\n onClick={() => onDelete(baseline.id)}\n >\n {`Delete ${type.label.toLowerCase()}`}\n </Button>\n ),\n }\n : {})}\n />\n </div>\n </>\n )\n}\n\ninterface FieldSlotProps {\n path: string\n registry: FieldTypeRegistry\n field: FieldDefinition\n value: unknown\n issues: readonly FormIssue[]\n disabled: boolean\n readonly: boolean\n onChange: (next: unknown) => void\n onBlur: () => void\n}\n\n/**\n * One field, rendered through the registry.\n *\n * The only place the form touches a field type, and it does so without naming one. A field\n * type the registry does not know (a database-defined type built before this deployment\n * shipped its input) renders as a statement rather than as a gap, and its stored value is\n * carried through the save untouched.\n */\nfunction FieldSlot({\n path,\n registry,\n field,\n value,\n issues,\n disabled,\n readonly,\n onChange,\n onBlur,\n}: FieldSlotProps): ReactNode {\n const spec = registry.get(field.type)\n\n if (spec === undefined) {\n return (\n <p className=\"text-body-sm text-text-muted\">\n {`${field.label}: this build has no input for the field type \"${field.type}\". Its stored value is kept and saved unchanged.`}\n </p>\n )\n }\n\n const Input = spec.Input\n\n return (\n <Input\n path={path}\n field={field}\n value={value}\n onChange={onChange}\n onBlur={onBlur}\n errors={issues}\n disabled={disabled}\n readonly={readonly}\n />\n )\n}\n\ninterface SaveBarProps {\n /** A form-level failure is on screen. The bar points at it rather than repeating it. */\n failed: boolean\n dirty: boolean\n saving: boolean\n editable: boolean\n creating: boolean\n transitions: readonly StatusTransition[]\n /** Fields standing between the editor and a save, counted after a refused submit. */\n problems: number\n onSave: () => void\n onPublish: () => void\n onCancel?: () => void\n}\n\n/**\n * The sticky save bar.\n * Canonical source: .docs/styleguide/03-layout.md section 5.2.\n *\n * Sticky to the bottom of the main column rather than fixed to the viewport, so it never\n * covers the metadata sidebar when the two columns collapse into one.\n */\nfunction SaveBar({\n failed,\n dirty,\n saving,\n editable,\n creating,\n transitions,\n problems,\n onSave,\n onPublish,\n onCancel,\n}: SaveBarProps) {\n const canPublish =\n creating && transitions.some((entry) => entry.to === \"published\" && entry.allowed)\n\n return (\n <div className=\"sticky bottom-0 z-sticky mt-6 flex flex-wrap items-center justify-between gap-3 border-t border-border-subtle bg-surface-base py-3\">\n <p\n className={\n problems > 0 || failed\n ? \"text-body-sm text-danger\"\n : \"text-body-sm text-text-muted\"\n }\n role={problems > 0 || failed ? \"status\" : undefined}\n >\n {problems > 0\n ? `${String(problems)} ${problems === 1 ? \"field needs\" : \"fields need\"} attention.`\n : failed\n ? // Deliberately not the failure's own sentence: that is printed once, at the\n // top of the form, and a second copy down here would be the same treatment\n // twice in one screen.\n \"Not saved. See the message above the fields.\"\n : !editable\n ? \"You can read this entry, but not change it.\"\n : dirty\n ? \"Unsaved changes.\"\n : \"\"}\n </p>\n\n <div className=\"flex items-center gap-2\">\n {onCancel === undefined ? null : (\n <Button variant=\"ghost\" onClick={onCancel} disabled={saving}>\n Cancel\n </Button>\n )}\n <Button\n variant={canPublish ? \"secondary\" : \"primary\"}\n loading={saving}\n disabled={!editable}\n onClick={onSave}\n >\n {creating ? \"Save as draft\" : \"Save changes\"}\n </Button>\n {canPublish ? (\n <Button variant=\"primary\" loading={saving} onClick={onPublish}>\n Publish\n </Button>\n ) : null}\n </div>\n </div>\n )\n}\n","import type { CmsAdapter, MediaUsage } from \"../../core/adapter.js\"\nimport { entryTitle } from \"../../core/entry-title.js\"\nimport type { ContentTypeKind, ContentTypeLike } from \"../../types/content-type.js\"\nimport type { EntryStatus } from \"../../types/entry.js\"\nimport { contentTypeIcon, contentTypeLabel } from \"../navigation/navigation.js\"\nimport type { IconName } from \"../components/icon-names.js\"\n\n/**\n * What the dashboard reads, and how.\n *\n * Separated from the component on purpose: this is the only part of the dashboard with a\n * data path, it goes through `CmsAdapter` and nothing else, and it is testable against a\n * stub adapter without rendering anything.\n *\n * Nothing here knows the name of a content type. The tiles and the recent list\n * are derived from the types it is handed, so a new content type changes the dashboard by\n * appearing in the registry and in no other way.\n */\n\nexport interface DashboardCount {\n slug: string\n label: string\n kind: ContentTypeKind\n icon: IconName\n count: number\n}\n\nexport interface DashboardRecentEntry {\n /** Unique across content types, which an entry id alone is not. */\n key: string\n entryId: string\n title: string\n typeSlug: string\n typeLabel: string\n status: EntryStatus\n updatedAt: string\n}\n\nexport interface DashboardData {\n counts: readonly DashboardCount[]\n recent: readonly DashboardRecentEntry[]\n /**\n * Null when the adapter could not answer. The tile then says the figure is unavailable\n * rather than showing a zero that reads like an empty library.\n */\n media: MediaUsage | null\n}\n\nexport interface LoadDashboardOptions {\n /** How many recent entries the list shows. */\n recentLimit?: number\n}\n\nexport const DEFAULT_RECENT_LIMIT = 8\n\n/**\n * Reads everything the dashboard shows.\n *\n * Counts are one aggregate read per content type, including singletons: a singleton counts\n * 0 or 1, which is exactly the \"is it filled in yet\" answer its tile is asking.\n *\n * Recent entries are one small page per collection, merged and re-sorted here. The adapter\n * has no cross-content-type query and should not grow one for a dashboard: entries live in\n * a subcollection per type, so a single query over all of them would need a collection\n * group index and a shape the security rules cannot gate per type. Singletons are excluded\n * because they cannot be listed at all.\n *\n * A failure in any count or list rejects, and the screen shows its error state. A\n * dashboard that silently drops the one content type the reader came to check is worse\n * than one that says it could not load.\n */\nexport async function loadDashboard(\n adapter: CmsAdapter,\n types: readonly ContentTypeLike[],\n { recentLimit = DEFAULT_RECENT_LIMIT }: LoadDashboardOptions = {},\n): Promise<DashboardData> {\n const collections = types.filter((type) => type.kind === \"collection\")\n\n const [counts, pages, media] = await Promise.all([\n Promise.all(\n types.map(async (type): Promise<DashboardCount> => {\n const count = await adapter.count(type.slug)\n return {\n slug: type.slug,\n label: contentTypeLabel(type),\n kind: type.kind,\n icon: contentTypeIcon(type),\n count,\n }\n }),\n ),\n Promise.all(\n collections.map(async (type) => {\n const page = await adapter.list(type.slug, {\n sort: { field: \"updatedAt\", direction: \"desc\" },\n limit: recentLimit,\n status: \"any\",\n })\n return page.items.map((entry): DashboardRecentEntry => ({\n key: `${type.slug}:${entry.id}`,\n entryId: entry.id,\n title: entryTitle(type, entry),\n typeSlug: type.slug,\n typeLabel: type.label,\n status: entry.status,\n updatedAt: entry.updatedAt,\n }))\n }),\n ),\n readMediaUsage(adapter),\n ])\n\n const recent = pages\n .flat()\n // Descending by last touch, the same order each page came back in, now across types.\n .sort((left, right) => right.updatedAt.localeCompare(left.updatedAt))\n .slice(0, recentLimit)\n\n return { counts, recent, media }\n}\n\n/**\n * The storage figure, or null.\n *\n * This is the one read the dashboard is allowed to lose. Media is the only part of the\n * library a role can be denied without being denied the admin itself, and the figure is\n * informational, so a refusal turns into an unavailable tile rather than an error screen.\n */\nasync function readMediaUsage(adapter: CmsAdapter): Promise<MediaUsage | null> {\n try {\n return await adapter.media.usage()\n } catch {\n return null\n }\n}\n","\"use client\"\n\nimport { useEffect, useState } from \"react\"\nimport type { ReactNode } from \"react\"\n\nimport type { CmsAdapter } from \"../../core/adapter.js\"\nimport type { ContentTypeLike } from \"../../types/content-type.js\"\nimport { Badge, ENTRY_STATUS_LABEL, ENTRY_STATUS_VARIANT } from \"../components/badge.js\"\nimport { Button } from \"../components/button.js\"\nimport { EmptyState } from \"../components/empty-state.js\"\nimport { Metric } from \"../components/metric.js\"\nimport { PageHeader } from \"../components/page-header.js\"\nimport { Panel } from \"../components/panel.js\"\nimport { PageSections, Section } from \"../components/section.js\"\nimport { Skeleton } from \"../components/skeleton.js\"\nimport {\n Table,\n TableBody,\n TableCell,\n TableEmptyRow,\n TableHead,\n TableHeaderCell,\n TableRow,\n} from \"../components/table.js\"\nimport { contentTypeIcon, contentTypeLabel } from \"../navigation/navigation.js\"\nimport { formatBytes, formatDateTime } from \"../format.js\"\n\nimport { loadDashboard } from \"./dashboard-data.js\"\nimport type { DashboardCount, DashboardData } from \"./dashboard-data.js\"\n\n/**\n * The dashboard.\n *\n * Every figure on it comes from `CmsAdapter`, and every tile comes from the registry: the\n * screen contains no content-type name, no fixture and no placeholder number. Adding a\n * content type adds a tile.\n *\n * Reads happen in the browser through the signed-in Firebase session, so the security\n * rules apply to the dashboard exactly as they apply to everything else. That is also why\n * it has a loading state at all: there is no server-rendered data to hand it.\n */\n\n/** The table has four columns; the empty row spans all of them. */\nconst RECENT_COLUMNS = 4\n\n/** Rows of skeleton while the first read is in flight. Enough to show the shape. */\nconst SKELETON_ROWS = [0, 1, 2, 3]\n\nexport interface DashboardProps {\n adapter: CmsAdapter\n /**\n * The content types this user may read. The caller filters with `can()`; a tile counting\n * something the adapter will refuse is a broken promise, not a preview.\n */\n types: readonly ContentTypeLike[]\n /** How many recent entries to list. */\n recentLimit?: number\n}\n\ntype DashboardState =\n | { status: \"loading\" }\n | { status: \"ready\"; data: DashboardData }\n | { status: \"error\"; message: string }\n\nexport function Dashboard({ adapter, types, recentLimit }: DashboardProps) {\n const [state, setState] = useState<DashboardState>({ status: \"loading\" })\n // Bumped by the error state's retry, which is the only way to re-run the read.\n const [attempt, setAttempt] = useState(0)\n\n useEffect(() => {\n let cancelled = false\n\n // The effect never sets \"loading\" itself: React refuses a synchronous setState in an\n // effect body, and the two entries into a read already cover it. The first render\n // starts in \"loading\", and the retry switches back to it in its own click handler.\n loadDashboard(adapter, types, recentLimit === undefined ? {} : { recentLimit })\n .then((data) => {\n if (!cancelled) setState({ status: \"ready\", data })\n })\n .catch((error: unknown) => {\n if (cancelled) return\n setState({\n status: \"error\",\n message:\n error instanceof Error\n ? error.message\n : \"The content could not be read. Check that you are still signed in.\",\n })\n })\n\n // A resolved read from a previous render must not overwrite a newer one, and a state\n // update after unmount is a React warning nobody can trace back to here.\n return () => {\n cancelled = true\n }\n }, [adapter, types, recentLimit, attempt])\n\n return (\n <>\n <PageHeader\n title=\"Dashboard\"\n description=\"What this project holds right now, read straight from the content store.\"\n />\n\n {state.status === \"error\" ? (\n <Panel>\n <EmptyState\n icon=\"error\"\n heading=\"The dashboard could not load\"\n description={state.message}\n action={\n <Button\n variant=\"secondary\"\n icon=\"dashboard\"\n onClick={() => {\n setState({ status: \"loading\" })\n setAttempt((value) => value + 1)\n }}\n >\n Try again\n </Button>\n }\n />\n </Panel>\n ) : (\n <PageSections>\n <Section heading=\"Content\">\n <ContentTiles\n types={types}\n counts={state.status === \"ready\" ? state.data.counts : undefined}\n />\n </Section>\n\n <Section heading=\"Library\">\n <LibraryTiles\n usage={state.status === \"ready\" ? state.data.media : undefined}\n />\n </Section>\n\n <Section heading=\"Recent entries\">\n <Panel padding=\"none\">\n <RecentTable state={state} />\n </Panel>\n </Section>\n </PageSections>\n )}\n </>\n )\n}\n\n/** The tile grid. Cards in a grid sit 16px apart (03-layout 3.2). */\nfunction TileGrid({ children }: { children: ReactNode }) {\n return (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4\">{children}</div>\n )\n}\n\nfunction ContentTiles({\n types,\n counts,\n}: {\n types: readonly ContentTypeLike[]\n counts: readonly DashboardCount[] | undefined\n}) {\n if (types.length === 0) {\n return (\n <Panel>\n <EmptyState\n icon=\"content-types\"\n heading=\"No content types yet\"\n description=\"A content type describes what this project stores. An admin creates one in the Developer area, and it appears here and in the sidebar immediately.\"\n />\n </Panel>\n )\n }\n\n // While the read is in flight the tiles are already known: the registry names them, only\n // their numbers are missing. The skeleton is therefore the final layout, not a stand-in.\n if (counts === undefined) {\n return (\n <TileGrid>\n {types.map((type) => (\n <Metric\n key={type.slug}\n // The same label the resolved tile will carry, so the text does not change\n // under the reader when the number lands.\n label={contentTypeLabel(type)}\n icon={contentTypeIcon(type)}\n loading\n />\n ))}\n </TileGrid>\n )\n }\n\n return (\n <TileGrid>\n {counts.map((count) => (\n <Metric\n key={count.slug}\n label={count.label}\n icon={count.icon}\n value={count.count}\n caption={\n count.kind === \"singleton\"\n ? count.count === 0\n ? \"Not created yet\"\n : \"Single document\"\n : count.count === 1\n ? \"entry\"\n : \"entries\"\n }\n />\n ))}\n </TileGrid>\n )\n}\n\nfunction LibraryTiles({\n usage,\n}: {\n usage: { count: number; bytes: number } | null | undefined\n}) {\n if (usage === undefined) {\n return (\n <TileGrid>\n <Metric label=\"Media files\" icon=\"media\" loading />\n <Metric label=\"Storage used\" icon=\"upload\" loading />\n </TileGrid>\n )\n }\n\n if (usage === null) {\n // No invented number. The media library refused the read, and the tile says so.\n return (\n <TileGrid>\n <Metric\n label=\"Media files\"\n icon=\"media\"\n unavailable=\"The media library could not be read.\"\n />\n <Metric\n label=\"Storage used\"\n icon=\"upload\"\n unavailable=\"The media library could not be read.\"\n />\n </TileGrid>\n )\n }\n\n return (\n <TileGrid>\n <Metric\n label=\"Media files\"\n icon=\"media\"\n value={usage.count}\n caption={usage.count === 1 ? \"file\" : \"files\"}\n />\n <Metric\n label=\"Storage used\"\n icon=\"upload\"\n value={formatBytes(usage.bytes)}\n caption=\"recorded on the media library\"\n />\n </TileGrid>\n )\n}\n\nfunction RecentTable({ state }: { state: DashboardState }) {\n return (\n <Table label=\"Recent entries\">\n <TableHead>\n <TableRow>\n <TableHeaderCell>Title</TableHeaderCell>\n <TableHeaderCell>Type</TableHeaderCell>\n <TableHeaderCell>Status</TableHeaderCell>\n <TableHeaderCell>Updated</TableHeaderCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {state.status !== \"ready\" ? (\n SKELETON_ROWS.map((row) => (\n <TableRow key={row}>\n <TableCell primary>\n <Skeleton\n line=\"body-sm\"\n className=\"w-40\"\n {...(row === 0 ? { label: \"Loading recent entries\" } : {})}\n />\n </TableCell>\n <TableCell>\n <Skeleton line=\"body-sm\" className=\"w-20\" />\n </TableCell>\n <TableCell>\n <Skeleton line=\"body-sm\" className=\"w-16\" />\n </TableCell>\n <TableCell date>\n <Skeleton line=\"body-sm\" className=\"w-28\" />\n </TableCell>\n </TableRow>\n ))\n ) : state.data.recent.length === 0 ? (\n <TableEmptyRow colSpan={RECENT_COLUMNS}>\n <EmptyState\n icon=\"collection\"\n heading=\"No entries yet\"\n description=\"Entries you or your team create appear here, newest first, across every content type.\"\n />\n </TableEmptyRow>\n ) : (\n state.data.recent.map((entry) => (\n <TableRow key={entry.key}>\n <TableCell primary>{entry.title}</TableCell>\n <TableCell>{entry.typeLabel}</TableCell>\n <TableCell>\n <Badge variant={ENTRY_STATUS_VARIANT[entry.status]}>\n {ENTRY_STATUS_LABEL[entry.status]}\n </Badge>\n </TableCell>\n <TableCell date>{formatDateTime(entry.updatedAt)}</TableCell>\n </TableRow>\n ))\n )}\n </TableBody>\n </Table>\n )\n}\n","/**\n * What the media library accepts, in one place.\n *\n * This file is the single definition of the allowed MIME types, their file extensions and\n * their size ceilings. Three things read it and they must not drift apart:\n *\n * 1. The upload path in `firebase/media-upload.ts`, which refuses a bad file before it\n * spends a customer's bandwidth on it.\n * 2. The admin's file input, which sets `accept` and says why a file was refused.\n * 3. `storage.rules` and the `media/{mediaId}` block of `firestore.rules`, which are the\n * actual enforcement. A rule cannot import TypeScript, so the two are kept in step by\n * `media-constraints.test.ts`, which reads the rules files and fails when a type or a\n * limit is present here and absent there.\n *\n * It deliberately contains no Firebase import: the constraint is a product rule, not a\n * storage detail, and the admin has to be able to state it without crossing the adapter\n * boundary.\n */\n\nconst MB = 1024 * 1024\n\nexport type MediaCategory = \"image\" | \"video\" | \"audio\" | \"document\"\n\nexport interface MediaTypeRule {\n /** The exact MIME type. No wildcards: see the note on `image/*` below. */\n readonly type: string\n readonly category: MediaCategory\n readonly maxBytes: number\n /** Lowercase, with the dot. The first one is what a sanitized name is given. */\n readonly extensions: readonly string[]\n}\n\n/**\n * The hard ceiling, whatever the type. Large enough for a brochure or a short clip, small\n * enough that one mistaken upload cannot fill a customer's bucket.\n */\nexport const MAX_MEDIA_BYTES = 25 * MB\n\n/**\n * Images are held to a lower ceiling than the rest.\n *\n * A 25 MB image is never what a website wants, and since Husk stores originals only (see\n * .docs/decisions/2026-09-18-media-variants.md) the original is what a visitor's browser\n * eventually fetches. The limit is the one place that fact is enforced rather than hoped\n * for.\n */\nexport const MAX_IMAGE_BYTES = 10 * MB\n\n/**\n * The allowlist.\n *\n * Note what is missing, because each absence is a decision rather than an oversight:\n *\n * - `image/svg+xml`. An SVG is a script container. It is served from the Storage host, so\n * it cannot reach a customer's own origin, but it can still be handed to a visitor as an\n * executable document under the customer's brand. Nothing in the CMS needs it.\n * - `image/tiff`, `image/bmp`, `video/quicktime`. No browser renders the first two and the\n * third is a phone-camera container that no `<video>` tag can be pointed at. A file that\n * cannot be displayed on the site it was uploaded for is a support ticket in waiting.\n * - Everything else, including archives and office documents. Adding one is a line here,\n * a line in `storage.rules`, and a test; that friction is the point.\n */\nexport const ALLOWED_MEDIA_TYPES: readonly MediaTypeRule[] = [\n {\n type: \"image/jpeg\",\n category: \"image\",\n maxBytes: MAX_IMAGE_BYTES,\n extensions: [\".jpg\", \".jpeg\"],\n },\n {\n type: \"image/png\",\n category: \"image\",\n maxBytes: MAX_IMAGE_BYTES,\n extensions: [\".png\"],\n },\n {\n type: \"image/webp\",\n category: \"image\",\n maxBytes: MAX_IMAGE_BYTES,\n extensions: [\".webp\"],\n },\n {\n type: \"image/avif\",\n category: \"image\",\n maxBytes: MAX_IMAGE_BYTES,\n extensions: [\".avif\"],\n },\n {\n type: \"image/gif\",\n category: \"image\",\n maxBytes: MAX_IMAGE_BYTES,\n extensions: [\".gif\"],\n },\n {\n type: \"application/pdf\",\n category: \"document\",\n maxBytes: MAX_MEDIA_BYTES,\n extensions: [\".pdf\"],\n },\n {\n type: \"video/mp4\",\n category: \"video\",\n maxBytes: MAX_MEDIA_BYTES,\n extensions: [\".mp4\"],\n },\n {\n type: \"video/webm\",\n category: \"video\",\n maxBytes: MAX_MEDIA_BYTES,\n extensions: [\".webm\"],\n },\n {\n type: \"audio/mpeg\",\n category: \"audio\",\n maxBytes: MAX_MEDIA_BYTES,\n extensions: [\".mp3\"],\n },\n {\n type: \"audio/ogg\",\n category: \"audio\",\n maxBytes: MAX_MEDIA_BYTES,\n extensions: [\".ogg\"],\n },\n {\n type: \"audio/wav\",\n category: \"audio\",\n maxBytes: MAX_MEDIA_BYTES,\n extensions: [\".wav\"],\n },\n]\n\n/** Value for an `<input type=\"file\">` accept attribute. The UI courtesy, not the rule. */\nexport const MEDIA_ACCEPT_ATTRIBUTE = ALLOWED_MEDIA_TYPES.map((rule) => rule.type).join(\n \",\",\n)\n\n/**\n * The rule for a declared MIME type, or null when the type is not accepted.\n *\n * Parameters are stripped (`text/plain; charset=utf-8`) and the type is lowercased, because\n * a browser is free to report either form and neither is the user's doing.\n */\nexport function mediaTypeRule(type: string): MediaTypeRule | null {\n const normalized = normalizeMediaType(type)\n return ALLOWED_MEDIA_TYPES.find((rule) => rule.type === normalized) ?? null\n}\n\nexport function normalizeMediaType(type: string): string {\n const [base] = type.split(\";\")\n return (base ?? \"\").trim().toLowerCase()\n}\n\n/** The extension including the dot, lowercased, or the empty string when there is none. */\nexport function fileExtension(name: string): string {\n const index = name.lastIndexOf(\".\")\n return index <= 0 ? \"\" : name.slice(index).toLowerCase()\n}\n\nexport type MediaRejectionCode =\n \"type-not-allowed\" | \"too-large\" | \"empty\" | \"extension-mismatch\"\n\nexport interface MediaRejection {\n code: MediaRejectionCode\n /** Written for an editor to read, because it is what the upload row will show. */\n message: string\n}\n\nexport interface MediaFileFacts {\n name: string\n type: string\n size: number\n}\n\n/**\n * Why this file may not be uploaded, or null when it may.\n *\n * Every check here is repeated in `storage.rules`. This one exists so a refusal is\n * immediate and explains itself; the rule exists because this one runs on the client and a\n * client can be replaced.\n */\nexport function checkMediaFile(file: MediaFileFacts): MediaRejection | null {\n const rule = mediaTypeRule(file.type)\n\n if (rule === null) {\n return {\n code: \"type-not-allowed\",\n message: `Files of type ${file.type || \"unknown\"} cannot be uploaded.`,\n }\n }\n\n if (file.size <= 0) {\n return { code: \"empty\", message: \"The file is empty.\" }\n }\n\n if (file.size > rule.maxBytes) {\n return {\n code: \"too-large\",\n message: `${describeBytes(file.size)} is over the ${describeBytes(rule.maxBytes)} limit for ${rule.type} files.`,\n }\n }\n\n // The name is part of the Storage path and the rules check it against the declared type,\n // so a mismatch here would be accepted by the client and refused by the bucket. Catching\n // it now turns a permission error into a sentence.\n if (!rule.extensions.includes(fileExtension(file.name))) {\n return {\n code: \"extension-mismatch\",\n message: `A ${rule.type} file must be named ${rule.extensions.join(\" or \")}.`,\n }\n }\n\n return null\n}\n\n/**\n * A file name safe to put in a Storage path.\n *\n * Lowercased, stripped of anything outside `[a-z0-9._-]`, with the extension preserved\n * because the rules match on it. A name that sanitizes to nothing becomes `file`, so an\n * upload never produces an object path ending in a bare dot.\n */\nexport function safeFileName(name: string, type: string): string {\n const extension = mediaTypeRule(type)?.extensions[0] ?? fileExtension(name)\n const base = (\n extension !== \"\" && name.toLowerCase().endsWith(extension)\n ? name.slice(0, -extension.length)\n : name\n )\n .toLowerCase()\n .replace(/[^a-z0-9._-]+/g, \"-\")\n // A run of dots is collapsed, so no object path ever contains a `..` segment fragment.\n .replace(/\\.{2,}/g, \".\")\n .replace(/^[-.]+|[-.]+$/g, \"\")\n .slice(0, 80)\n\n return `${base === \"\" ? \"file\" : base}${extension}`\n}\n\nfunction describeBytes(bytes: number): string {\n if (bytes >= MB) return `${Math.round((bytes / MB) * 10) / 10} MB`\n if (bytes >= 1024) return `${Math.round(bytes / 1024)} KB`\n return `${bytes} bytes`\n}\n","import type { MediaUsageReference } from \"../../core/adapter.js\"\nimport { MEDIA_USAGE_LIMIT } from \"../../core/adapter.js\"\nimport {\n ALLOWED_MEDIA_TYPES,\n MEDIA_ACCEPT_ATTRIBUTE,\n} from \"../../core/media-constraints.js\"\nimport { acceptsType } from \"../../fields/media/reference.js\"\nimport { can } from \"../../permissions/can.js\"\nimport type { AuthUser } from \"../../types/auth.js\"\nimport type { MediaItem } from \"../../types/media.js\"\n\n/**\n * The decisions the media library makes that are not rendering.\n *\n * They live outside the components so each one can be tested without a DOM, and so the\n * picker and the standalone library cannot answer the same question two different ways.\n */\n\n/**\n * The `accept` attribute for the library's file input, narrowed by what a field asks for.\n *\n * Two constraints meet here and both are real: `core/media-constraints.ts` says what the\n * product accepts at all, and a field's `accept` says what this particular slot accepts.\n * The intersection is what the browser's file chooser should offer. An intersection that\n * comes out empty falls back to the full product allowlist rather than to `accept=\"\"`,\n * which browsers read as \"anything\": a chooser that offers everything and a refusal\n * afterwards is friendlier than a chooser that offers nothing and explains nothing.\n */\nexport function uploadAccept(accept: readonly string[] | undefined): string {\n if (accept === undefined || accept.length === 0) return MEDIA_ACCEPT_ATTRIBUTE\n\n const allowed = ALLOWED_MEDIA_TYPES.filter((rule) =>\n acceptsType(accept, rule.type),\n ).map((rule) => rule.type)\n\n return allowed.length === 0 ? MEDIA_ACCEPT_ATTRIBUTE : allowed.join(\",\")\n}\n\n/**\n * The MIME prefix the adapter can narrow its query by, or undefined when it cannot.\n *\n * `MediaQuery.type` is a prefix range, which is the only \"starts with\" Firestore offers, so\n * it can serve `image/*` and nothing else. A field accepting exactly `image/jpeg`, or a mix\n * of families, gets no server-side narrowing and is filtered per page instead.\n *\n * This is an optimization and never the enforcement. `pickableItems` filters every page it\n * renders, whatever the query did, which is why a field's own re-check on the way back is\n * never the thing that catches a wrong type.\n */\nexport function queryTypeFilter(\n accept: readonly string[] | undefined,\n): string | undefined {\n if (accept === undefined || accept.length !== 1) return undefined\n const only = accept[0]\n if (only === undefined || only === \"*/*\" || !only.endsWith(\"/*\")) return undefined\n return only.slice(0, -1)\n}\n\n/**\n * The items a picker may offer, out of a page it just read.\n *\n * The filter is applied to what is rendered rather than to what is chosen, so a field's\n * `accept` is honoured by the picker rather than merely passed to it. A page that filters\n * down to nothing is a short page, not an error: the cursor still points past it and the\n * next page is read on demand.\n */\nexport function pickableItems(\n items: readonly MediaItem[],\n accept: readonly string[] | undefined,\n): readonly MediaItem[] {\n if (accept === undefined || accept.length === 0) return items\n return items.filter((item) => acceptsType(accept, item.type))\n}\n\n/** Whether the tile shows an image preview or its concept icon. */\nexport function isImageItem(item: MediaItem): boolean {\n return item.type.startsWith(\"image/\")\n}\n\n/**\n * Whether this account may delete library items.\n *\n * Mirrors `allow delete: if isEditor()` in firestore.rules. Hiding the button is\n * presentation only; the rules refuse the write regardless of what the UI renders.\n */\nexport function canDeleteMedia(user: AuthUser): boolean {\n return can(user, \"delete\")\n}\n\n/**\n * Whether this account may put new bytes over an existing item.\n *\n * Mirrors `mayWrite` in storage.rules: an editor may overwrite any object, an author only\n * one whose custom metadata names them, which for a Husk upload is the account that\n * created the media document.\n */\nexport function canReplaceMedia(user: AuthUser, item: MediaItem): boolean {\n return can(user, \"delete\") || item.createdBy === user.uid\n}\n\n/** `1600 x 900`, or null for an item whose dimensions were never recorded. */\nexport function formatDimensions(item: MediaItem): string | null {\n if (item.width === null || item.height === null) return null\n return `${String(item.width)} x ${String(item.height)}`\n}\n\n/**\n * What the usage list says, in one sentence.\n *\n * The count is deliberately phrased as \"at least\" once the list hit its limit, because the\n * lookup stopped counting there and claiming an exact number it did not count would be the\n * one thing a delete warning must not do.\n */\nexport function describeUsage(\n usages: readonly MediaUsageReference[],\n limit: number = MEDIA_USAGE_LIMIT,\n): string {\n if (usages.length === 0) return \"No entry references this file.\"\n if (usages.length >= limit) {\n return `At least ${String(limit)} entries reference this file.`\n }\n return usages.length === 1\n ? \"1 entry references this file.\"\n : `${String(usages.length)} entries reference this file.`\n}\n\n/** The phase of an upload, said in words for the row under the file name. */\nexport function describePhase(phase: string, fraction: number, attempt: number): string {\n switch (phase) {\n case \"uploading\":\n return attempt > 1\n ? `Uploading, attempt ${String(attempt)} (${String(Math.round(fraction * 100))}%)`\n : `Uploading ${String(Math.round(fraction * 100))}%`\n case \"storing\":\n return \"Recording it in the library\"\n case \"done\":\n return \"Done\"\n case \"cancelled\":\n return \"Cancelled\"\n case \"failed\":\n return \"Failed\"\n default:\n return \"Waiting\"\n }\n}\n\n/**\n * The type filter the library toolbar offers.\n *\n * Each value is a MIME prefix, which is what `MediaQuery.type` narrows by: a range scan is\n * the only \"starts with\" Firestore has. The categories are the ones `ALLOWED_MEDIA_TYPES`\n * actually contains, so no option can come back empty for a structural reason.\n */\nexport const MEDIA_FILTERS: readonly { value: string; label: string }[] = [\n { value: \"\", label: \"All files\" },\n { value: \"image/\", label: \"Images\" },\n { value: \"video/\", label: \"Video\" },\n { value: \"audio/\", label: \"Audio\" },\n { value: \"application/\", label: \"Documents\" },\n]\n","import type { MediaUsageReference } from \"../../core/adapter.js\"\n\n/**\n * The entries that reference a media item, by name.\n *\n * Shared by the detail panel and the delete confirmation, because a warning that lists\n * three entries and a panel that lists four would be two different claims about the same\n * question.\n *\n * An entry with no usable title prints its id. A content type the registry no longer knows\n * prints its slug. Neither case is hidden: a reference the admin cannot name is still a\n * reference, and \"one of these is somewhere\" is more useful than a shorter list.\n */\nexport interface UsageListProps {\n usages: readonly MediaUsageReference[]\n contentTypeLabel?: ((slug: string) => string) | undefined\n}\n\nexport function UsageList({ usages, contentTypeLabel }: UsageListProps) {\n if (usages.length === 0) return null\n\n return (\n <ul className=\"flex flex-col gap-1\">\n {usages.map((usage) => (\n <li\n key={`${usage.contentType}/${usage.entryId}`}\n className=\"flex items-baseline justify-between gap-3\"\n >\n <span className=\"truncate text-body-sm text-text-secondary\">\n {usage.title ?? usage.entryId}\n </span>\n <span className=\"shrink-0 text-caption text-text-faint\">\n {contentTypeLabel?.(usage.contentType) ?? usage.contentType}\n </span>\n </li>\n ))}\n </ul>\n )\n}\n","\"use client\"\n\nimport { useEffect, useState } from \"react\"\n\nimport type { CmsAdapter, MediaUsageReference } from \"../../core/adapter.js\"\nimport { confirmationMatches } from \"../../core/delete-confirmation.js\"\nimport type { MediaItem } from \"../../types/media.js\"\nimport { classifyError } from \"../../core/error-taxonomy.js\"\nimport type { ClassifiedError } from \"../../core/error-taxonomy.js\"\nimport { Button } from \"../components/button.js\"\nimport { Field, TextInput } from \"../components/field.js\"\nimport { ErrorNotice } from \"../components/error-notice.js\"\nimport { Modal } from \"../components/modal.js\"\nimport { Skeleton } from \"../components/skeleton.js\"\nimport { useOptionalToast } from \"../components/toast.js\"\nimport { describeUsage } from \"./library.js\"\nimport { UsageList } from \"./usage-list.js\"\n\n/**\n * The destructive confirmation for deleting a media item.\n * Canonical source: .docs/styleguide/04-components.md section 12, \"Destructive\n * confirmation\".\n *\n * It differs from the entry version in the one way that matters: a media item can be\n * referenced from somewhere else, and deleting it breaks whatever referenced it. The\n * dialog therefore reads the reverse index before it offers the button, and names every\n * entry it finds. A file with references is not refused, because sometimes removing it is\n * exactly the intention; it is made impossible to do by accident.\n *\n * Two things it says out loud rather than implies:\n *\n * - Where the list comes from. The count is the `mediaRefs` index each entry write\n * maintains, so an entry that has not been saved since the index existed will not be in\n * it. Claiming an unqualified \"nothing uses this\" would be a stronger statement than\n * the data supports.\n * - What deleting does not do. It removes the library record. The bytes in Storage are a\n * separate object with its own rules, and the caller is told whether that part also\n * went through.\n *\n * The typed confirmation is the file name, the same mechanic the entry dialog uses.\n */\nexport interface MediaDeleteDialogProps {\n adapter: CmsAdapter\n /** The item to delete. Null means the dialog is closed. */\n item: MediaItem | null\n onCancel: () => void\n onDeleted: (mediaId: string) => void\n contentTypeLabel?: ((slug: string) => string) | undefined\n}\n\nexport function MediaDeleteDialog({\n adapter,\n item,\n onCancel,\n onDeleted,\n contentTypeLabel,\n}: MediaDeleteDialogProps) {\n return item === null ? null : (\n // Remounted per item, so a phrase typed for one file cannot unlock the next.\n <DeleteBody\n key={item.id}\n adapter={adapter}\n item={item}\n onCancel={onCancel}\n onDeleted={onDeleted}\n contentTypeLabel={contentTypeLabel}\n />\n )\n}\n\ntype UsageState =\n | { kind: \"loading\" }\n | { kind: \"known\"; usages: readonly MediaUsageReference[] }\n | { kind: \"failed\" }\n\nfunction DeleteBody({\n adapter,\n item,\n onCancel,\n onDeleted,\n contentTypeLabel,\n}: MediaDeleteDialogProps & { item: MediaItem }) {\n const toast = useOptionalToast()\n // Null until the lookup answers. The dialog is remounted per item, so the answer cannot\n // belong to a different file than the one on screen.\n const [usages, setUsages] = useState<readonly MediaUsageReference[] | null | undefined>(\n undefined,\n )\n const [typed, setTyped] = useState(\"\")\n const [deleting, setDeleting] = useState(false)\n const [failure, setFailure] = useState<ClassifiedError | null>(null)\n\n useEffect(() => {\n let cancelled = false\n\n adapter.media\n .usages(item.id)\n .then((found) => {\n if (!cancelled) setUsages(found)\n })\n .catch(() => {\n // Null means the check could not run, which is not the same claim as \"unused\".\n if (!cancelled) setUsages(null)\n })\n\n return () => {\n cancelled = true\n }\n }, [adapter, item.id])\n\n const usage: UsageState =\n usages === undefined\n ? { kind: \"loading\" }\n : usages === null\n ? { kind: \"failed\" }\n : { kind: \"known\", usages }\n\n const confirmed = confirmationMatches(item.name, typed)\n const referenced = usage.kind === \"known\" && usage.usages.length > 0\n\n async function remove(): Promise<void> {\n if (!confirmed || deleting) return\n setDeleting(true)\n setFailure(null)\n\n try {\n await adapter.media.delete(item.id)\n onDeleted(item.id)\n toast?.notify({ tone: \"success\", title: `${item.name} deleted` })\n } catch (thrown: unknown) {\n setFailure(\n classifyError(thrown, { action: \"delete this file\", subject: item.name }),\n )\n } finally {\n setDeleting(false)\n }\n }\n\n return (\n <Modal\n open\n onClose={onCancel}\n title={`Delete ${item.name}?`}\n description=\"Deleting removes the file from the library. Any entry that still points at it will show a broken reference until somebody repairs it.\"\n width=\"sm\"\n dismissible={false}\n footer={\n <>\n <Button variant=\"secondary\" onClick={onCancel} disabled={deleting}>\n Cancel\n </Button>\n <Button\n variant=\"danger\"\n icon=\"delete\"\n loading={deleting}\n disabled={!confirmed || usage.kind === \"loading\"}\n onClick={() => void remove()}\n >\n Delete\n </Button>\n </>\n }\n >\n <div className=\"flex flex-col gap-4\">\n {failure === null ? null : <ErrorNotice error={failure} />}\n\n {usage.kind === \"loading\" ? (\n <Skeleton\n line=\"body\"\n className=\"w-56\"\n label=\"Checking which entries use this file\"\n />\n ) : usage.kind === \"failed\" ? (\n <p\n role=\"alert\"\n className=\"rounded-sm bg-warning-muted px-3 py-2 text-body-sm text-warning\"\n >\n The usage check could not run, so it is not known which entries reference this\n file. Deleting it now may break a page.\n </p>\n ) : referenced ? (\n <div\n role=\"alert\"\n className=\"flex flex-col gap-2 rounded-sm bg-warning-muted px-3 py-2 text-warning\"\n >\n <p className=\"text-body-sm\">{describeUsage(usage.usages)}</p>\n <UsageList usages={usage.usages} contentTypeLabel={contentTypeLabel} />\n </div>\n ) : (\n <p className=\"text-body-sm text-text-muted\">\n No entry references this file, according to the reference index that every\n save writes. An entry that has not been saved since this project was set up is\n not in that index.\n </p>\n )}\n\n <p className=\"text-body-sm text-text-muted\">\n Type <span className=\"text-body-medium text-text-primary\">{item.name}</span> to\n confirm.\n </p>\n <Field label=\"Confirmation\">\n {({ id }) => (\n <TextInput\n id={id}\n value={typed}\n autoComplete=\"off\"\n disabled={deleting}\n onChange={(event) => setTyped(event.target.value)}\n />\n )}\n </Field>\n </div>\n </Modal>\n )\n}\n","/**\n * Copying a string to the clipboard, and admitting when it did not happen.\n *\n * `navigator.clipboard` is not always there. It is undefined outside a secure context,\n * which includes a customer previewing their admin over plain http on a LAN address, and\n * `writeText` rejects when the document is not focused or when the browser's permission\n * prompt is refused. A \"Copied\" toast in any of those cases is a lie the reader only\n * discovers after pasting nothing, so the result is reported instead of assumed.\n *\n * The fallback is the old `document.execCommand(\"copy\")` path over an off-screen textarea.\n * It is deprecated and it is still the only thing that works without the async API, so it\n * is tried second rather than not at all. When both fail the caller is told, and the\n * library shows the URL in a field the reader can select by hand.\n */\n\nexport type ClipboardOutcome = \"copied\" | \"unavailable\"\n\nexport async function copyText(text: string): Promise<ClipboardOutcome> {\n const api = globalThis.navigator?.clipboard\n if (api !== undefined) {\n try {\n await api.writeText(text)\n return \"copied\"\n } catch {\n // Refused permission, or an unfocused document. The fallback below may still work.\n }\n }\n\n return legacyCopy(text)\n}\n\nfunction legacyCopy(text: string): ClipboardOutcome {\n const documentRef = globalThis.document as Document | undefined\n if (documentRef?.body === undefined || documentRef.body === null) return \"unavailable\"\n\n const field = documentRef.createElement(\"textarea\")\n field.value = text\n // Off-screen rather than hidden: a display:none element cannot be selected, and the\n // copy would silently produce an empty clipboard.\n field.setAttribute(\"aria-hidden\", \"true\")\n field.style.position = \"fixed\"\n field.style.top = \"-9999px\"\n field.style.opacity = \"0\"\n documentRef.body.append(field)\n\n try {\n field.select()\n const legacy = documentRef as Document & {\n execCommand?: (command: string) => boolean\n }\n return legacy.execCommand?.(\"copy\") === true ? \"copied\" : \"unavailable\"\n } catch {\n return \"unavailable\"\n } finally {\n field.remove()\n }\n}\n","\"use client\"\n\nimport { useEffect, useRef, useState } from \"react\"\n\nimport type { CmsAdapter, MediaUsageReference } from \"../../core/adapter.js\"\nimport { classifyError } from \"../../core/error-taxonomy.js\"\nimport type { ClassifiedError } from \"../../core/error-taxonomy.js\"\nimport type { AuthUser } from \"../../types/auth.js\"\nimport type { MediaItem } from \"../../types/media.js\"\nimport { Button } from \"../components/button.js\"\nimport { Field, TextInput } from \"../components/field.js\"\nimport { ErrorNotice } from \"../components/error-notice.js\"\nimport { Icon } from \"../components/icon.js\"\nimport { IconButton } from \"../components/icon-button.js\"\nimport { Modal } from \"../components/modal.js\"\nimport { Skeleton } from \"../components/skeleton.js\"\nimport { Textarea } from \"../components/textarea.js\"\nimport { useOptionalToast } from \"../components/toast.js\"\nimport { formatBytes, formatDateTime } from \"../format.js\"\nimport { copyText } from \"./clipboard.js\"\nimport {\n canDeleteMedia,\n canReplaceMedia,\n describeUsage,\n formatDimensions,\n isImageItem,\n} from \"./library.js\"\nimport { UsageList } from \"./usage-list.js\"\n\n/** How long the copy button's `check` stays before reverting. Fixed by 05-icons.md 2.1. */\nconst COPY_FEEDBACK_MS = 1200\n\n/**\n * One media item, opened from the grid.\n * Canonical source: .docs/styleguide/03-layout.md section 5.3.\n *\n * A modal rather than a third column, because the grid is already the widest thing on the\n * page and a column would squeeze the tiles below their minimum measure.\n *\n * What it is deliberate about:\n *\n * - **Alt text is the only editable field.** Everything else about a media item is a fact\n * about the file: changing the name, the type or the size here would describe bytes\n * that did not change. Replacing the bytes is a separate, named action.\n * - **Usage is read once, when the panel opens, and shown whether or not it is zero.**\n * An orphan is surfaced, never swept: a file nothing references today may be exactly\n * what tomorrow's entry needs, and the CMS does not get to decide that for an editor.\n * - **Copy reports what happened.** `navigator.clipboard` is absent outside a secure\n * context and rejects on a refused permission, so the button says \"Copied\" only when\n * the clipboard confirmed it, and points at the URL field otherwise.\n */\nexport interface MediaDetailProps {\n adapter: CmsAdapter\n user: AuthUser\n item: MediaItem\n onClose: () => void\n /** Called with the updated item after alt text is saved. */\n onUpdated: (item: MediaItem) => void\n /** Opens the destructive confirmation. Absent when this account may not delete. */\n onDelete?: ((item: MediaItem) => void) | undefined\n /** Starts a replace. Absent when no uploader was supplied. */\n onReplace?: ((item: MediaItem) => void) | undefined\n /** Names a content type in the usage list. Defaults to the raw slug. */\n contentTypeLabel?: ((slug: string) => string) | undefined\n}\n\n/**\n * The usage answer, carrying the media id it is about.\n *\n * \"Loading\" is derived from the absence of an answer for the item currently on screen, so\n * the effect sets state only from its own callback and a late answer for a previous item\n * can never be shown under a new one.\n */\ntype UsageState =\n | { kind: \"loading\" }\n | { kind: \"known\"; usages: readonly MediaUsageReference[] }\n | { kind: \"failed\" }\n\ntype UsageAnswer = {\n mediaId: string\n usages: readonly MediaUsageReference[] | null\n}\n\nexport function MediaDetail({\n adapter,\n user,\n item,\n onClose,\n onUpdated,\n onDelete,\n onReplace,\n contentTypeLabel,\n}: MediaDetailProps) {\n const toast = useOptionalToast()\n const [alt, setAlt] = useState(item.alt ?? \"\")\n const [saving, setSaving] = useState(false)\n const [failure, setFailure] = useState<ClassifiedError | null>(null)\n const [copied, setCopied] = useState(false)\n const [answer, setAnswer] = useState<UsageAnswer | null>(null)\n const revert = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n useEffect(() => {\n let cancelled = false\n const mediaId = item.id\n\n adapter.media\n .usages(mediaId)\n .then((usages) => {\n if (!cancelled) setAnswer({ mediaId, usages })\n })\n .catch(() => {\n // A failed lookup is not proof the file is unused, and the panel must not imply it\n // is. `usages: null` says the check could not run, which is what the reader needs\n // to know before pressing Delete.\n if (!cancelled) setAnswer({ mediaId, usages: null })\n })\n\n return () => {\n cancelled = true\n }\n }, [adapter, item.id])\n\n const usage: UsageState =\n answer === null || answer.mediaId !== item.id\n ? { kind: \"loading\" }\n : answer.usages === null\n ? { kind: \"failed\" }\n : { kind: \"known\", usages: answer.usages }\n\n useEffect(\n () => () => {\n if (revert.current !== null) clearTimeout(revert.current)\n },\n [],\n )\n\n const dimensions = formatDimensions(item)\n const dirty = alt.trim() !== (item.alt ?? \"\")\n\n async function saveAlt(): Promise<void> {\n if (saving || !dirty) return\n setSaving(true)\n setFailure(null)\n\n try {\n // Written as null rather than \"\" when cleared: the stored shape says alt is a string\n // or absent, and an empty string in a document means \"described as nothing\", which is\n // not the same claim as \"not described\".\n const trimmed = alt.trim()\n const updated = await adapter.media.update(item.id, {\n alt: trimmed === \"\" ? null : trimmed,\n })\n onUpdated(updated)\n toast?.notify({ tone: \"success\", title: \"Alt text saved\" })\n } catch (thrown: unknown) {\n setFailure(\n classifyError(thrown, {\n role: user.role,\n action: \"save the alt text\",\n subject: item.name,\n }),\n )\n } finally {\n setSaving(false)\n }\n }\n\n async function copyUrl(): Promise<void> {\n const outcome = await copyText(item.url)\n if (outcome === \"copied\") {\n setCopied(true)\n if (revert.current !== null) clearTimeout(revert.current)\n revert.current = setTimeout(() => setCopied(false), COPY_FEEDBACK_MS)\n return\n }\n\n toast?.notify({\n tone: \"error\",\n title: \"The clipboard is not available\",\n description: \"Select the URL in the field and copy it by hand.\",\n })\n }\n\n return (\n <Modal\n open\n onClose={onClose}\n title={item.name}\n width=\"md\"\n footer={\n <>\n {onDelete === undefined || !canDeleteMedia(user) ? null : (\n <Button variant=\"danger\" icon=\"delete\" onClick={() => onDelete(item)}>\n Delete\n </Button>\n )}\n {onReplace === undefined || !canReplaceMedia(user, item) ? null : (\n <Button icon=\"upload\" onClick={() => onReplace(item)}>\n Replace\n </Button>\n )}\n <Button\n variant=\"primary\"\n loading={saving}\n disabled={!dirty}\n onClick={() => void saveAlt()}\n >\n Save alt text\n </Button>\n </>\n }\n >\n <div className=\"flex flex-col gap-5\">\n {failure === null ? null : <ErrorNotice error={failure} />}\n\n <div className=\"flex aspect-media w-full items-center justify-center overflow-hidden rounded-sm border border-border-subtle bg-surface-raised\">\n {isImageItem(item) ? (\n <img\n src={item.url}\n alt={item.alt ?? \"\"}\n className=\"size-full object-contain\"\n />\n ) : (\n <span className=\"text-text-muted\">\n <Icon name=\"singleton\" size={24} />\n </span>\n )}\n </div>\n\n <Field\n label=\"Alt text\"\n help=\"What the image shows, for a reader who cannot see it. Leave it empty only when the image is decorative.\"\n >\n {({ id, describedBy }) => (\n <Textarea\n id={id}\n rows={2}\n value={alt}\n aria-describedby={describedBy}\n disabled={saving}\n onChange={(event) => setAlt(event.target.value)}\n />\n )}\n </Field>\n\n <Field label=\"URL\">\n {({ id }) => (\n <div className=\"flex items-center gap-2\">\n <TextInput id={id} value={item.url} readOnly />\n <IconButton\n icon={copied ? \"save\" : \"copy\"}\n morph\n label={copied ? \"Copied\" : \"Copy the URL\"}\n onClick={() => void copyUrl()}\n />\n </div>\n )}\n </Field>\n\n <dl className=\"flex flex-col gap-3\">\n <Fact term=\"Type\" value={item.type} />\n <Fact term=\"Size\" value={formatBytes(item.size)} />\n {/* An item with no recorded dimensions omits the row rather than printing a\n placeholder, the same rule the entry metadata sidebar follows. */}\n {dimensions === null ? null : <Fact term=\"Dimensions\" value={dimensions} />}\n <Fact term=\"Uploaded\" value={formatDateTime(item.createdAt)} />\n </dl>\n\n <div className=\"flex flex-col gap-2 border-t border-border-subtle pt-4\">\n {usage.kind === \"loading\" ? (\n <Skeleton\n line=\"caption\"\n className=\"w-56\"\n label=\"Checking which entries use this file\"\n />\n ) : usage.kind === \"failed\" ? (\n <p className=\"text-caption text-warning\">\n The usage check could not run, so it is not known whether any entry uses\n this file.\n </p>\n ) : (\n <>\n <p className=\"text-caption text-text-muted\">\n {describeUsage(usage.usages)}\n </p>\n <UsageList usages={usage.usages} contentTypeLabel={contentTypeLabel} />\n </>\n )}\n </div>\n </div>\n </Modal>\n )\n}\n\nfunction Fact({ term, value }: { term: string; value: string }) {\n return (\n <div className=\"flex items-baseline justify-between gap-4\">\n <dt className=\"text-caption text-text-faint\">{term}</dt>\n <dd className=\"truncate text-body-sm text-text-secondary\">{value}</dd>\n </div>\n )\n}\n","\"use client\"\n\nimport type { MediaItem } from \"../../types/media.js\"\nimport { Badge } from \"../components/badge.js\"\nimport { cx } from \"../components/class-names.js\"\nimport { Icon } from \"../components/icon.js\"\nimport { formatBytes } from \"../format.js\"\nimport { isImageItem } from \"./library.js\"\n\n/**\n * One item in the media grid.\n * Canonical source: .docs/styleguide/03-layout.md section 5.3.\n *\n * The whole tile is one button, not a card with a button in it: the only thing a tile does\n * is open the item, and a click target that is smaller than the thing it represents is a\n * click target people miss.\n *\n * The preview is the original file. Husk stores originals only and resizes at render time\n * through `next/image` on a customer's site (see .docs/decisions/2026-09-18-media-variants.md),\n * so there is no thumbnail to point at here. `loading=\"lazy\"` is what keeps a grid of\n * originals from being a page of full-size downloads.\n */\nexport interface MediaTileProps {\n item: MediaItem\n selected?: boolean\n /** True when a usage check ran and found no entry referencing this item. */\n unused?: boolean\n onOpen: (item: MediaItem) => void\n}\n\nexport function MediaTile({\n item,\n selected = false,\n unused = false,\n onOpen,\n}: MediaTileProps) {\n return (\n <button\n type=\"button\"\n onClick={() => onOpen(item)}\n aria-pressed={selected}\n className={cx(\n \"group flex cursor-pointer flex-col overflow-hidden rounded-md border text-left state-transition focus-visible:focus-ring-inset\",\n selected\n ? \"border-border-active\"\n : \"border-border-default hover:border-border-strong\",\n )}\n >\n <span className=\"relative flex aspect-media w-full items-center justify-center bg-surface-raised\">\n {isImageItem(item) ? (\n <img\n src={item.url}\n alt={item.alt ?? \"\"}\n loading=\"lazy\"\n className=\"size-full object-cover\"\n />\n ) : (\n <span className=\"text-text-muted\">\n <Icon name=\"singleton\" size={24} />\n </span>\n )}\n {unused ? (\n <span className=\"absolute end-2 top-2\">\n <Badge>Unused</Badge>\n </span>\n ) : null}\n </span>\n <span className=\"flex flex-col gap-1 p-3\">\n <span className=\"truncate text-body-sm text-text-secondary\">{item.name}</span>\n <span className=\"truncate text-caption text-text-faint\">\n {item.type} · {formatBytes(item.size)}\n </span>\n </span>\n </button>\n )\n}\n","\"use client\"\n\nimport type { MediaUploadProgress } from \"./uploader.js\"\nimport { IconButton } from \"../components/icon-button.js\"\nimport { Progress } from \"../components/progress.js\"\nimport { describePhase } from \"./library.js\"\n\n/**\n * The uploads currently in flight, above the grid.\n * Canonical source: .docs/styleguide/03-layout.md section 5.3.\n *\n * Every upload handle offers progress, cancel and retry, so every one of the three is on\n * screen. A failed upload's row stays until somebody retries or dismisses it, with the\n * reason attached: an upload that disappears without saying why is the one outcome that\n * loses an editor's work silently.\n */\nexport interface UploadRow {\n /** Stable for the life of the row, across retries. */\n key: string\n fileName: string\n /** Set when the row is replacing an existing item rather than adding one. */\n replacing: string | null\n progress: MediaUploadProgress\n error: string | null\n}\n\nexport interface MediaUploadsProps {\n rows: readonly UploadRow[]\n onCancel: (key: string) => void\n onRetry: (key: string) => void\n onDismiss: (key: string) => void\n}\n\nexport function MediaUploads({ rows, onCancel, onRetry, onDismiss }: MediaUploadsProps) {\n if (rows.length === 0) return null\n\n return (\n <ul className=\"mb-4 flex flex-col gap-3\">\n {rows.map((row) => {\n const running =\n row.progress.phase === \"uploading\" || row.progress.phase === \"storing\"\n\n return (\n <li\n key={row.key}\n className=\"flex flex-col gap-2 rounded-sm border border-border-subtle bg-surface-raised px-4 py-3\"\n >\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"flex min-w-0 flex-col\">\n <span className=\"truncate text-body-sm text-text-primary\">\n {row.replacing === null\n ? row.fileName\n : `${row.fileName} (replacing ${row.replacing})`}\n </span>\n <span className=\"text-caption text-text-muted\">\n {describePhase(\n row.progress.phase,\n row.progress.fraction,\n row.progress.attempt,\n )}\n </span>\n </div>\n {running ? (\n <IconButton\n icon=\"close\"\n label={`Cancel uploading ${row.fileName}`}\n size=\"sm\"\n onClick={() => onCancel(row.key)}\n />\n ) : (\n <div className=\"flex shrink-0 items-center gap-2\">\n <IconButton\n icon=\"retry\"\n label={`Try uploading ${row.fileName} again`}\n size=\"sm\"\n onClick={() => onRetry(row.key)}\n />\n <IconButton\n icon=\"close\"\n label={`Dismiss ${row.fileName}`}\n size=\"sm\"\n onClick={() => onDismiss(row.key)}\n />\n </div>\n )}\n </div>\n\n {running ? (\n <Progress\n value={row.progress.fraction}\n label={`Uploading ${row.fileName}`}\n />\n ) : null}\n\n {row.error === null ? null : (\n <p className=\"text-caption text-danger\">{row.error}</p>\n )}\n </li>\n )\n })}\n </ul>\n )\n}\n","\"use client\"\n\nimport { useCallback, useEffect, useRef, useState } from \"react\"\n\nimport type { CmsAdapter } from \"../../core/adapter.js\"\nimport { DEFAULT_PAGE_SIZE } from \"../../core/adapter.js\"\nimport { classifyError } from \"../../core/error-taxonomy.js\"\nimport type { ClassifiedError } from \"../../core/error-taxonomy.js\"\nimport type { AuthUser } from \"../../types/auth.js\"\nimport type { MediaItem } from \"../../types/media.js\"\nimport { Button } from \"../components/button.js\"\nimport { EmptyState } from \"../components/empty-state.js\"\nimport { ErrorNotice } from \"../components/error-notice.js\"\nimport { PageHeader } from \"../components/page-header.js\"\nimport { Panel } from \"../components/panel.js\"\nimport { Select } from \"../components/select.js\"\nimport { Skeleton } from \"../components/skeleton.js\"\nimport { Switch } from \"../components/switch.js\"\nimport { useOptionalToast } from \"../components/toast.js\"\nimport {\n canDeleteMedia,\n canReplaceMedia,\n MEDIA_FILTERS,\n pickableItems,\n queryTypeFilter,\n uploadAccept,\n} from \"./library.js\"\nimport { MediaDeleteDialog } from \"./media-delete-dialog.js\"\nimport { MediaDetail } from \"./media-detail.js\"\nimport { MediaTile } from \"./media-tile.js\"\nimport { MediaUploads } from \"./media-uploads.js\"\nimport type { UploadRow } from \"./media-uploads.js\"\nimport type { MediaUploader, MediaUploadHandle, MediaUploadProgress } from \"./uploader.js\"\n\n/**\n * The media library, and the body of the media picker.\n * Canonical source: .docs/styleguide/03-layout.md section 5.3.\n *\n * One screen serves both because they differ in exactly two things: whether choosing an\n * item does anything, and whether a field's `accept` narrows what is offered. Everything\n * else (the grid, the upload rows, the detail panel, the delete flow) is the same code, so\n * the picker cannot fall behind the library or offer something the library would not.\n *\n * `accept` is honoured here and not only passed along. Every page the picker renders is\n * filtered through `pickableItems`, so a file of the wrong type is never on screen to be\n * clicked. The field re-checks the item that comes back, and that check is a backstop for\n * a picker somebody else supplied, not the thing that catches this one.\n *\n * Orphans are surfaced, never swept. \"Unused only\" runs a usage lookup for each item the\n * grid has loaded and marks the ones nothing references. Nothing is deleted as a\n * consequence, and nothing is deleted on a schedule: a file that no entry uses today may\n * be what tomorrow's entry needs, and that is not a judgement a CMS gets to make.\n */\nexport interface MediaLibraryProps {\n adapter: CmsAdapter\n user: AuthUser\n /** Absent means the library is read-only: no upload, no replace. */\n uploader?: MediaUploader | undefined\n /** Picker mode: the MIME patterns this slot accepts. */\n accept?: readonly string[] | undefined\n /** Picker mode: choosing a tile calls this instead of opening the detail panel. */\n onPick?: ((item: MediaItem) => void) | undefined\n /** Names a content type in a usage list. Defaults to the raw slug. */\n contentTypeLabel?: ((slug: string) => string) | undefined\n}\n\ninterface PageState {\n /** The type filter this answer was read for. `\"\"` means no filter. */\n filter: string\n items: readonly MediaItem[]\n cursor: string | null\n hasMore: boolean\n /** Why the read failed, or null. A failure is an answer too, and it has to be shown. */\n failure: ClassifiedError | null\n}\n\nexport function MediaLibrary({\n adapter,\n user,\n uploader,\n accept,\n onPick,\n contentTypeLabel,\n}: MediaLibraryProps) {\n const picking = onPick !== undefined\n const toast = useOptionalToast()\n\n const [filter, setFilter] = useState(\"\")\n // One answer, carrying the filter it belongs to. \"Loading\" is derived from the absence of\n // an answer for the filter currently on screen, so the effect never sets state\n // synchronously and a slow answer for an abandoned filter cannot overwrite a newer one.\n // Same shape the relation picker uses, for the same reason.\n const [page, setPage] = useState<PageState | null>(null)\n const [paging, setPaging] = useState(false)\n const [selected, setSelected] = useState<MediaItem | null>(null)\n const [deleting, setDeleting] = useState<MediaItem | null>(null)\n const [uploads, setUploads] = useState<readonly UploadRow[]>([])\n const [unusedOnly, setUnusedOnly] = useState(false)\n const [scanning, setScanning] = useState(false)\n /** Media id to reference count, for the items a usage scan has already answered for. */\n const [usageCounts, setUsageCounts] = useState<ReadonlyMap<string, number>>(new Map())\n\n /** Upload handles, keyed by row. Not state: a handle is an object, not a rendered value. */\n const handles = useRef(new Map<string, MediaUploadHandle>())\n const chooseFile = useRef<HTMLInputElement>(null)\n /** The item a pending file choice will replace, or null for a plain upload. */\n const replacing = useRef<MediaItem | null>(null)\n /** Media id per upload row, for the rows that are replacing rather than adding. */\n const uploadTargets = useRef(new Map<string, string>())\n /** Only the newest read may write state; a slower earlier one is discarded. */\n const request = useRef(0)\n\n // In picker mode the field's accept narrows the query where Firestore can narrow it;\n // everything else is filtered per page. In library mode the toolbar filter applies.\n const typeFilter = picking\n ? queryTypeFilter(accept)\n : filter === \"\"\n ? undefined\n : filter\n\n const read = useCallback(\n async (cursor: string | null): Promise<void> => {\n const ticket = request.current + 1\n request.current = ticket\n const forFilter = typeFilter ?? \"\"\n\n try {\n const result = await adapter.media.list({\n limit: DEFAULT_PAGE_SIZE,\n cursor,\n ...(typeFilter === undefined ? {} : { type: typeFilter }),\n })\n if (request.current !== ticket) return\n\n setPaging(false)\n setPage((current) => ({\n filter: forFilter,\n items:\n cursor === null || current === null\n ? result.items\n : [...current.items, ...result.items],\n cursor: result.cursor,\n hasMore: result.hasMore,\n failure: null,\n }))\n } catch (thrown: unknown) {\n if (request.current !== ticket) return\n setPaging(false)\n setPage((current) => ({\n filter: forFilter,\n items: cursor === null || current === null ? [] : current.items,\n cursor: null,\n hasMore: false,\n failure: classifyError(thrown, {\n role: user.role,\n action: \"read the media library\",\n }),\n }))\n }\n },\n [adapter, typeFilter, user.role],\n )\n\n useEffect(() => {\n void read(null)\n }, [read])\n\n const loading = page === null || page.filter !== (typeFilter ?? \"\")\n const failure = loading ? null : page.failure\n const visible = pickableItems(\n loading || page === null ? [] : page.items,\n picking ? accept : undefined,\n )\n const shown = unusedOnly\n ? visible.filter((item) => usageCounts.get(item.id) === 0)\n : visible\n\n /**\n * Runs a usage lookup for every loaded item that has not been asked about yet.\n *\n * One query per item, answered from the reverse index, so the cost is the number of\n * tiles on screen and not the size of the database. It is behind a switch rather than\n * automatic because it is still a per-item cost, and a grid nobody asked a question\n * about should not spend it.\n */\n async function scanUsage(): Promise<void> {\n setScanning(true)\n const answers = new Map(usageCounts)\n\n try {\n for (const item of visible) {\n if (answers.has(item.id)) continue\n const usages = await adapter.media.usages(item.id, { limit: 1 })\n answers.set(item.id, usages.length)\n }\n setUsageCounts(answers)\n } catch {\n // A failed scan must not mark anything unused. Whatever was answered before the\n // failure is kept; the rest simply stays unknown and its tile carries no badge.\n setUsageCounts(answers)\n toast?.notify({\n tone: \"error\",\n title: \"The usage check could not finish\",\n description: \"Some files are not marked either way.\",\n })\n } finally {\n setScanning(false)\n }\n }\n\n function toggleUnusedOnly(next: boolean): void {\n setUnusedOnly(next)\n if (next) void scanUsage()\n }\n\n function track(key: string, progress: MediaUploadProgress, error: string | null): void {\n setUploads((rows) =>\n rows.map((row) => (row.key === key ? { ...row, progress, error } : row)),\n )\n }\n\n async function runUpload(key: string, handle: MediaUploadHandle, retry: boolean) {\n const target = uploadTargets.current.get(key) ?? null\n\n try {\n const item = retry ? await handle.retry() : await handle.start()\n handles.current.delete(key)\n setUploads((rows) => rows.filter((row) => row.key !== key))\n\n setPage((current) =>\n current === null\n ? current\n : {\n ...current,\n items:\n target === null\n ? [item, ...current.items]\n : current.items.map((existing) =>\n existing.id === item.id ? item : existing,\n ),\n },\n )\n // A replaced item's bytes changed, so anything derived from them is stale.\n setUsageCounts((counts) => {\n const next = new Map(counts)\n next.delete(item.id)\n return next\n })\n setSelected((current) => (current?.id === item.id ? item : current))\n\n if (target === null) {\n toast?.notify({ tone: \"success\", title: `${item.name} uploaded` })\n return\n }\n\n // Overwriting an object mints a new download URL, so the copy denormalized into every\n // referencing entry is stale until it is rewritten. Reported either way: a partial\n // refresh is a fact the editor needs, not a detail to swallow.\n const refreshed = await adapter.media.refreshReferences(item.id, item.url)\n toast?.notify({\n tone: refreshed.failed.length === 0 ? \"success\" : \"warning\",\n title: `${item.name} replaced`,\n description:\n refreshed.failed.length === 0\n ? `${String(refreshed.updated)} ${refreshed.updated === 1 ? \"entry\" : \"entries\"} now point at the new file. The alt text was kept, so check that it still describes it.`\n : `${String(refreshed.updated)} updated, ${String(refreshed.failed.length)} could not be updated and still link to the old file.`,\n })\n } catch (thrown: unknown) {\n track(\n key,\n handle.progress(),\n thrown instanceof Error ? thrown.message : \"The upload failed.\",\n )\n }\n }\n\n function startUploads(files: readonly File[], target: MediaItem | null): void {\n if (uploader === undefined) return\n\n for (const file of files) {\n const key = `${String(Date.now())}-${file.name}-${String(Math.random())}`\n const handle =\n target === null\n ? uploader.create(file, {\n onProgress: (progress) => track(key, progress, null),\n })\n : uploader.replace(target, file, {\n onProgress: (progress) => track(key, progress, null),\n })\n\n handles.current.set(key, handle)\n if (target !== null) uploadTargets.current.set(key, target.id)\n\n setUploads((rows) => [\n ...rows,\n {\n key,\n fileName: file.name,\n replacing: target?.name ?? null,\n progress: handle.progress(),\n error: null,\n },\n ])\n\n void runUpload(key, handle, false)\n }\n }\n\n const accepted = uploadAccept(accept)\n\n return (\n <>\n {picking ? null : (\n <PageHeader\n title=\"Media\"\n description=\"Every file uploaded to this project. Images are stored as originals and resized where they are used.\"\n actions={\n uploader === undefined ? undefined : (\n <Button\n variant=\"primary\"\n icon=\"upload\"\n onClick={() => {\n replacing.current = null\n chooseFile.current?.click()\n }}\n >\n Upload\n </Button>\n )\n }\n />\n )}\n\n <input\n ref={chooseFile}\n type=\"file\"\n accept={accepted}\n multiple\n className=\"hidden\"\n onChange={(event) => {\n const files = Array.from(event.target.files ?? [])\n const target = replacing.current\n replacing.current = null\n // Cleared so choosing the same file twice in a row still fires a change event.\n event.target.value = \"\"\n if (files.length > 0)\n startUploads(target === null ? files : files.slice(0, 1), target)\n }}\n />\n\n <div className=\"mb-4 flex flex-wrap items-center justify-between gap-3\">\n <div className=\"w-48\">\n {picking ? null : (\n <Select\n aria-label=\"Filter by file type\"\n value={filter}\n options={MEDIA_FILTERS.map(({ value, label }) => ({ value, label }))}\n onChange={(value) => setFilter(value)}\n />\n )}\n </div>\n {picking ? null : (\n <Switch\n checked={unusedOnly}\n onChange={toggleUnusedOnly}\n label=\"Unused only\"\n showLabel\n disabled={scanning}\n />\n )}\n </div>\n\n {failure === null ? null : (\n <ErrorNotice error={failure} onRetry={() => void read(null)} />\n )}\n\n <Panel padding=\"compact\">\n <MediaUploads\n rows={uploads}\n onCancel={(key) => {\n handles.current.get(key)?.cancel()\n }}\n onRetry={(key) => {\n const handle = handles.current.get(key)\n if (handle !== undefined) void runUpload(key, handle, true)\n }}\n onDismiss={(key) => {\n handles.current.delete(key)\n uploadTargets.current.delete(key)\n setUploads((rows) => rows.filter((row) => row.key !== key))\n }}\n />\n\n {loading ? (\n <div className=\"grid gap-4 media-grid\" aria-busy=\"true\">\n {[0, 1, 2, 3, 4, 5].map((slot) => (\n <Skeleton\n key={slot}\n className=\"aspect-media w-full\"\n {...(slot === 0 ? { label: \"Loading the media library\" } : {})}\n />\n ))}\n </div>\n ) : shown.length === 0 ? (\n <EmptyState\n icon=\"media\"\n heading={unusedOnly ? \"Every file is in use\" : \"Nothing in the library yet\"}\n description={\n unusedOnly\n ? \"No loaded file is without a reference. Load more files to check them too.\"\n : uploader === undefined\n ? \"Files uploaded to this project will appear here.\"\n : \"Upload an image, a document, a video or an audio file to get started.\"\n }\n />\n ) : (\n <div className=\"grid gap-4 media-grid\">\n {shown.map((item) => (\n <MediaTile\n key={item.id}\n item={item}\n selected={selected?.id === item.id}\n unused={usageCounts.get(item.id) === 0}\n onOpen={(chosen) => {\n if (onPick === undefined) setSelected(chosen)\n else onPick(chosen)\n }}\n />\n ))}\n </div>\n )}\n\n {page !== null && page.hasMore && !loading ? (\n <div className=\"mt-4 flex justify-center\">\n <Button\n size=\"sm\"\n loading={paging}\n onClick={() => {\n setPaging(true)\n void read(page.cursor)\n }}\n >\n Load more\n </Button>\n </div>\n ) : null}\n </Panel>\n\n {selected === null ? null : (\n <MediaDetail\n adapter={adapter}\n user={user}\n item={selected}\n contentTypeLabel={contentTypeLabel}\n onClose={() => setSelected(null)}\n onUpdated={(updated) => {\n setSelected(updated)\n setPage((current) =>\n current === null\n ? current\n : {\n ...current,\n items: current.items.map((item) =>\n item.id === updated.id ? updated : item,\n ),\n },\n )\n }}\n {...(canDeleteMedia(user) ? { onDelete: (item) => setDeleting(item) } : {})}\n {...(uploader !== undefined && canReplaceMedia(user, selected)\n ? {\n onReplace: (item) => {\n replacing.current = item\n chooseFile.current?.click()\n },\n }\n : {})}\n />\n )}\n\n <MediaDeleteDialog\n adapter={adapter}\n item={deleting}\n contentTypeLabel={contentTypeLabel}\n onCancel={() => setDeleting(null)}\n onDeleted={(mediaId) => {\n setDeleting(null)\n setSelected(null)\n setPage((current) =>\n current === null\n ? current\n : {\n ...current,\n items: current.items.filter((item) => item.id !== mediaId),\n },\n )\n }}\n />\n </>\n )\n}\n","\"use client\"\n\nimport { useCallback, useMemo, useRef, useState } from \"react\"\nimport type { ReactNode } from \"react\"\n\nimport type { CmsAdapter } from \"../../core/adapter.js\"\nimport { MediaPickerProvider } from \"../../fields/media/picker-context.js\"\nimport type {\n MediaPickerApi,\n MediaPickRequest,\n} from \"../../fields/media/picker-context.js\"\nimport type { AuthUser } from \"../../types/auth.js\"\nimport type { MediaItem } from \"../../types/media.js\"\nimport { Modal } from \"../components/modal.js\"\nimport { MediaLibrary } from \"./media-library.js\"\nimport type { MediaUploader } from \"./uploader.js\"\n\n/**\n * The real media picker, over the adapter and the library UI.\n *\n * The `image` and `file` field types have been written against `MediaPickerApi` since M5,\n * with an absent provider as a deliberate, rendered state. This is the implementation that\n * makes the seam real:\n *\n * - `resolve` is `adapter.media.getMany`. Ids with no document are simply absent from the\n * result, which is exactly how the control learns a reference is broken.\n * - `pick` opens the library in a modal and resolves when a tile is chosen, or with null\n * when the editor closes it. The promise is settled exactly once in either direction,\n * so a field that awaited it never hangs: the deferred is cleared the moment it is\n * settled, and closing the modal settles it.\n *\n * `accept` is honoured by the library itself, which filters every page it renders through\n * `pickableItems`. The field re-checks the item that comes back, and that check exists for\n * a picker somebody else supplied; against this one it can never be the thing that catches\n * a wrong type, because a wrong type was never on screen.\n */\nexport interface AdminMediaPickerProviderProps {\n adapter: CmsAdapter\n user: AuthUser\n /** Absent means the picker can choose but not upload. */\n uploader?: MediaUploader | undefined\n contentTypeLabel?: ((slug: string) => string) | undefined\n children: ReactNode\n}\n\ninterface OpenPick {\n accept: readonly string[] | undefined\n}\n\nexport function AdminMediaPickerProvider({\n adapter,\n user,\n uploader,\n contentTypeLabel,\n children,\n}: AdminMediaPickerProviderProps) {\n const [open, setOpen] = useState<OpenPick | null>(null)\n // The resolver of the promise currently awaited, so closing the modal from anywhere\n // settles it. A picker that resolved nothing would leave the field's button spinning.\n const pending = useRef<((item: MediaItem | null) => void) | null>(null)\n\n const settle = useCallback((item: MediaItem | null) => {\n const resolve = pending.current\n pending.current = null\n setOpen(null)\n resolve?.(item)\n }, [])\n\n const api = useMemo<MediaPickerApi>(\n () => ({\n resolve: (mediaIds) => adapter.media.getMany(mediaIds),\n pick: (request: MediaPickRequest) =>\n new Promise<MediaItem | null>((resolve) => {\n // A second pick while one is open cancels the first rather than queueing it: the\n // editor pressed a different field's button, and the answer they give now belongs\n // to that field.\n pending.current?.(null)\n pending.current = resolve\n setOpen({ accept: request.accept })\n }),\n }),\n [adapter],\n )\n\n return (\n <MediaPickerProvider value={api}>\n {children}\n\n {open === null ? null : (\n <Modal\n open\n onClose={() => settle(null)}\n title=\"Choose a file\"\n description=\"Pick an existing file, or upload a new one. Only files this field accepts are shown.\"\n width=\"xl\"\n >\n <MediaLibrary\n adapter={adapter}\n user={user}\n uploader={uploader}\n accept={open.accept}\n contentTypeLabel={contentTypeLabel}\n onPick={(item) => settle(item)}\n />\n </Modal>\n )}\n </MediaPickerProvider>\n )\n}\n","\"use client\"\n\nimport { useCallback, useEffect, useState, useSyncExternalStore } from \"react\"\n\nimport type { Registry } from \"../../core/registry.js\"\nimport type { RegistryStore } from \"../../core/registry-store.js\"\nimport type { ContentTypeLike } from \"../../types/content-type.js\"\n\n/**\n * The React half of the live registry. The store itself is in core and knows no React.\n *\n * This is what makes the M8 promise concrete: a content type created in the Schema Builder\n * reaches the sidebar, the routes and every screen of every open tab without a rebuild and\n * without a reload, because the registry the admin renders from is a subscription rather\n * than a value computed once on the server.\n *\n * Firebase does not appear here. `watch` arrives as an argument, exactly as the media\n * uploader and the relation source do, so nothing under `src/admin/**` imports the SDK.\n */\n\n/** The shape of `SchemaAdapter.watch`, without naming the adapter. */\nexport type SchemaWatch = (\n listener: (types: readonly ContentTypeLike[]) => void,\n onError?: (error: Error) => void,\n) => () => void\n\nexport interface LiveRegistry {\n registry: Registry\n /**\n * Whether the database half has been read at least once.\n *\n * It matters for exactly one question, and it is the question a generated admin has to\n * get right: a slug that is in no content type yet may be an unknown route or may be a\n * database-defined type whose first snapshot has not landed. Answering 404 before the\n * listener has spoken would show a not-found screen for a content type that exists.\n * True immediately when no listener is running, because then there is nothing to wait for.\n */\n synced: boolean\n /**\n * The last listener error, or null.\n *\n * Surfaced rather than swallowed: a dead listener leaves the admin quietly stale, which\n * looks exactly like a working admin until somebody wonders where their content type\n * went.\n */\n error: Error | null\n}\n\n/**\n * Subscribes to a registry store, and feeds it from a schema listener when one is given.\n *\n * `watch` must be stable across renders (memoize it, or take it from a memoized adapter):\n * a new function every render would close and reopen the Firestore listener every render.\n */\nexport function useLiveRegistry(store: RegistryStore, watch?: SchemaWatch): LiveRegistry {\n const subscribe = useCallback(\n (onStoreChange: () => void) => store.subscribe(() => onStoreChange()),\n [store],\n )\n\n // The registry object is replaced, never mutated, so its identity is a valid snapshot and\n // the server snapshot is the same value: a server render sees the code half only, which\n // is exactly what it can know.\n const registry = useSyncExternalStore(\n subscribe,\n () => store.registry,\n () => store.registry,\n )\n\n const [error, setError] = useState<Error | null>(null)\n const [synced, setSynced] = useState(watch === undefined)\n\n useEffect(() => {\n if (watch === undefined) return\n\n return watch(\n (types) => {\n store.setDatabaseTypes(types)\n setSynced(true)\n // A snapshot after an error means the listener recovered, and a stale warning about\n // a listener that is working again is worse than none.\n setError(null)\n },\n (failure) => setError(failure),\n )\n }, [store, watch])\n\n return { registry, error, synced }\n}\n","import type { ContentTypeLike, ContentTypeSource } from \"../types/content-type.js\"\n\nimport { assertValidContentType } from \"./define-content-type.js\"\nimport { LockedTypeError, SchemaError } from \"./errors.js\"\n\n/** A database-defined type that failed validation. Surfaced, never silently dropped. */\nexport interface InvalidContentType {\n slug: string\n reason: string\n definition: unknown\n}\n\nexport interface RegistryEntry {\n type: ContentTypeLike\n source: ContentTypeSource\n locked: boolean\n /**\n * A database-defined type with the same slug as this code-defined one. Code wins, but the\n * database copy is kept so the admin can show the collision instead of silently\n * discarding what an editor created.\n */\n conflict?: { source: \"database\"; type: ContentTypeLike }\n}\n\nexport interface Registry {\n readonly types: readonly RegistryEntry[]\n readonly conflicts: readonly RegistryEntry[]\n readonly invalid: readonly InvalidContentType[]\n get(slug: string): RegistryEntry | undefined\n require(slug: string): RegistryEntry\n has(slug: string): boolean\n /** Entries whose winning definition came from this source. */\n bySource(source: ContentTypeSource): readonly RegistryEntry[]\n}\n\n/**\n * Merges the two schema sources into one list of content types.\n *\n * Precedence is deterministic and one-directional: **code always wins**. A code-defined\n * type is the customer's committed, reviewable, deployable definition; a database-defined\n * one was created in the admin at runtime. When both define the same slug, the code\n * definition is the live one and the database definition is attached as a conflict so the\n * Schema Builder can show it and offer a resolution. Discarding it silently would lose an\n * editor's work with no trace.\n *\n * A code-defined type that is malformed throws: that is a programming error and should\n * fail at startup. A database-defined type that is malformed is collected into `invalid`\n * instead, because one corrupt stored document must not take the whole admin down.\n */\nexport function buildRegistry(\n code: readonly ContentTypeLike[],\n database: readonly ContentTypeLike[],\n): Registry {\n const bySlug = new Map<string, RegistryEntry>()\n const invalid: InvalidContentType[] = []\n\n for (const type of code) {\n assertValidContentType(type)\n\n if (bySlug.has(type.slug)) {\n throw new SchemaError(\n `Content type \"${type.slug}\" is defined twice in code. A slug identifies exactly one content type.`,\n )\n }\n\n bySlug.set(type.slug, {\n type,\n source: \"code\",\n locked: type.locked ?? false,\n })\n }\n\n for (const type of database) {\n try {\n assertValidContentType(type)\n } catch (thrown) {\n invalid.push({\n slug: typeof type?.slug === \"string\" ? type.slug : \"(unknown)\",\n reason: thrown instanceof Error ? thrown.message : String(thrown),\n definition: type,\n })\n continue\n }\n\n const existing = bySlug.get(type.slug)\n\n if (!existing) {\n // A database-defined type is never locked. Locking exists to protect a definition\n // that lives in git, and this one does not.\n bySlug.set(type.slug, { type, source: \"database\", locked: false })\n continue\n }\n\n if (existing.source === \"database\") {\n invalid.push({\n slug: type.slug,\n reason: `Content type \"${type.slug}\" appears twice in the database. Only the first was loaded.`,\n definition: type,\n })\n continue\n }\n\n bySlug.set(type.slug, { ...existing, conflict: { source: \"database\", type } })\n }\n\n const types = [...bySlug.values()]\n\n return {\n types,\n conflicts: types.filter((entry) => entry.conflict !== undefined),\n invalid,\n get: (slug) => bySlug.get(slug),\n has: (slug) => bySlug.has(slug),\n require(slug) {\n const entry = bySlug.get(slug)\n if (!entry) {\n throw new SchemaError(\n `Unknown content type \"${slug}\". Known types: ${types.map((known) => known.type.slug).join(\", \") || \"none\"}.`,\n )\n }\n return entry\n },\n bySource: (source) => types.filter((entry) => entry.source === source),\n }\n}\n\n/**\n * Domain-level lock enforcement.\n *\n * A locked type may not have its *definition* changed: not from the Schema Builder, not\n * through a direct adapter call, not by a request that skipped the UI. Its entries are\n * edited normally; locking protects the schema, not the content.\n */\nexport function assertSchemaWritable(registry: Registry, slug: string): RegistryEntry {\n const entry = registry.require(slug)\n\n if (entry.locked) {\n throw new LockedTypeError(slug)\n }\n\n if (entry.source === \"code\") {\n throw new LockedTypeError(\n slug,\n `Content type \"${slug}\" is defined in code. The Schema Builder writes database-defined types only; change the TypeScript definition and deploy.`,\n )\n }\n\n return entry\n}\n\n/** True when the Schema Builder should render this type read-only. */\nexport function isSchemaReadOnly(entry: RegistryEntry): boolean {\n return entry.locked || entry.source === \"code\"\n}\n","import type { ContentTypeLike } from \"../types/content-type.js\"\n\nimport { fieldMapSignature } from \"./schema-fields.js\"\n\n/**\n * The schema version stamp, and the one question it answers.\n *\n * `content/{slug}.schemaVersion` is what the M10 migration runner reads, and every entry\n * carries the version it was last written at. The runner's only question is: *is this entry\n * stored in the shape the type declares today?* So the stamp has to move exactly when the\n * answer can change, and not otherwise. A stamp that moves on every save tells the runner\n * nothing, because every entry is then behind; a stamp that never moves tells it nothing\n * either, because no entry is ever behind.\n *\n * **Bumps:** adding a field, removing a field, changing a field's type, changing a select's\n * option values or its `multiple`, changing a relation's target or its `many`, changing a\n * date's precision, changing a repeater's nested field map.\n *\n * **Does not bump:** label, plural, description, icon, placeholder, hidden, readonly,\n * validation rules, select option labels, field order, title field, default sort,\n * permissions, and lock state. None of them changes a stored document, so an entry written\n * before the change is still stored exactly as the type describes.\n *\n * Purging a removed field's values does not bump either. The purge deletes data that the\n * type had already stopped declaring, so the declared shape is the same before and after.\n */\n\n/** Everything the stamp is computed from. Anything absent from here cannot move it. */\nexport function storageSignature(type: Pick<ContentTypeLike, \"kind\" | \"fields\">): string {\n // Kind is in it because a singleton stores its one entry at a derived document id and a\n // collection does not, so flipping it relocates every document.\n return `${type.kind}|${fieldMapSignature(type.fields)}`\n}\n\nexport const INITIAL_SCHEMA_VERSION = 1\n\nexport function schemaVersionOf(type: Pick<ContentTypeLike, \"schemaVersion\">): number {\n const version = type.schemaVersion\n return typeof version === \"number\" && Number.isInteger(version) && version >= 1\n ? version\n : INITIAL_SCHEMA_VERSION\n}\n\n/**\n * The version the next write should carry.\n *\n * Computed from the stored definition and the new one, never supplied by a caller, so a\n * client cannot stamp a version that does not describe what it is writing.\n */\nexport function nextSchemaVersion(\n previous: ContentTypeLike | null,\n next: ContentTypeLike,\n): number {\n if (previous === null) return INITIAL_SCHEMA_VERSION\n\n const current = schemaVersionOf(previous)\n return storageSignature(previous) === storageSignature(next) ? current : current + 1\n}\n\n/** True when the two definitions would be stamped differently. Drives the \"this is a breaking change\" warning. */\nexport function storageShapeChanged(\n previous: ContentTypeLike,\n next: ContentTypeLike,\n): boolean {\n return storageSignature(previous) !== storageSignature(next)\n}\n","import type {\n ContentTypeKind,\n ContentTypeLike,\n ContentTypeSource,\n} from \"../types/content-type.js\"\nimport type { FieldDefinition } from \"../types/field.js\"\n\nimport { assertValidContentType } from \"./define-content-type.js\"\nimport { SchemaError } from \"./errors.js\"\nimport type { Registry } from \"./registry.js\"\n\n/**\n * Creating a database-defined content type: the domain half.\n *\n * Everything here is pure. The Schema Builder screen calls it to decide what to enable and\n * what to say; the adapter calls the same functions again before it writes, so a request\n * that skipped the screen is answered identically.\n */\n\n/**\n * Slugs a content type may not take.\n *\n * Under the layout in .docs/decisions/2026-09-18-firestore-layout.md a content type slug\n * never becomes a top-level collection, so none of these can actually collide today. They\n * are reserved anyway: the names are the CMS's own vocabulary, a type called `users` or\n * `settings` would read as the admin's own section in every sidebar and URL, and a future\n * layout change must not be blocked by a customer having taken the name.\n *\n * `src/firebase/paths.ts` re-exports this as `RESERVED_COLLECTIONS`, so the list is written\n * once and the storage layer and the Schema Builder cannot drift apart.\n */\nexport const RESERVED_TYPE_SLUGS: readonly string[] = [\n \"schemas\",\n \"content\",\n \"entries\",\n \"media\",\n \"users\",\n \"settings\",\n]\n\nexport type SlugRejection = \"invalid\" | \"reserved\" | \"taken-by-code\" | \"taken-by-database\"\n\nexport interface SlugAvailability {\n available: boolean\n reason?: SlugRejection\n /** Ready to print. Names the source, because \"that slug is taken\" is a dead end. */\n message?: string\n /** Which source holds the slug already. Absent for `invalid` and `reserved`. */\n source?: ContentTypeSource\n}\n\nconst AVAILABLE: SlugAvailability = { available: true }\n\n/** Same shape the routes and `assertValidContentType` use. Kept in step by a test. */\nconst SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\n\n/**\n * Is this slug free for a new database-defined content type?\n *\n * Checked against **both** sources. A slug defined in code is not available even though\n * `schemas/` is empty and the Schema Builder's own list shows nothing, which is precisely\n * why the message has to say where the collision is: an editor looking at an empty list and\n * being told the name is taken has nowhere to go.\n */\nexport function checkTypeSlug(registry: Registry, slug: string): SlugAvailability {\n if (!SLUG_PATTERN.test(slug)) {\n return {\n available: false,\n reason: \"invalid\",\n message: `\"${slug}\" is not a valid slug. Use lowercase letters, digits, and single hyphens, for example \"blog-posts\".`,\n }\n }\n\n if (RESERVED_TYPE_SLUGS.includes(slug)) {\n return {\n available: false,\n reason: \"reserved\",\n message: `\"${slug}\" is reserved by the CMS. Reserved slugs: ${RESERVED_TYPE_SLUGS.join(\", \")}.`,\n }\n }\n\n const existing = registry.get(slug)\n if (!existing) return AVAILABLE\n\n if (existing.source === \"code\") {\n return {\n available: false,\n reason: \"taken-by-code\",\n source: \"code\",\n message: `\"${slug}\" is already defined in code as \"${existing.type.label}\". Code-defined types are not listed in the Schema Builder; change the TypeScript definition and deploy, or choose another slug.`,\n }\n }\n\n return {\n available: false,\n reason: \"taken-by-database\",\n source: \"database\",\n message: `\"${slug}\" is already used by the content type \"${existing.type.label}\", created here in the Schema Builder.`,\n }\n}\n\n/** Throws the message `checkTypeSlug` would have printed. The adapter's create guard. */\nexport function assertTypeSlugAvailable(registry: Registry, slug: string): void {\n const availability = checkTypeSlug(registry, slug)\n if (!availability.available) {\n throw new SchemaError(availability.message ?? `Slug \"${slug}\" is not available.`)\n }\n}\n\nexport interface NewContentTypeInput {\n name: string\n slug: string\n kind: ContentTypeKind\n /** Lucide icon name from the vocabulary in .docs/styleguide/05-icons.md. */\n icon?: string\n namePlural?: string\n description?: string\n}\n\n/**\n * The single field every new content type starts with.\n *\n * A content type with no fields is invalid, so creation has to seed one. A required title\n * is the one field that is right for every content type: it is what the list view, the\n * relation picker and the entry header all print, and an editor who wanted something else\n * renames it rather than starting from an unusable empty type.\n */\nexport const INITIAL_FIELD_KEY = \"title\"\n\nconst INITIAL_FIELD: FieldDefinition = {\n type: \"text\",\n label: \"Title\",\n validation: { required: true },\n}\n\n/**\n * Builds the content type document a create writes, stamped at version 1.\n *\n * Validated here rather than at the write, so the Schema Builder fails on the form instead\n * of on the round trip.\n */\nexport function newContentType(input: NewContentTypeInput): ContentTypeLike {\n const label = input.name.trim()\n\n if (label.length === 0) {\n throw new SchemaError(`Content type \"${input.slug}\" needs a name.`)\n }\n\n const type: ContentTypeLike = {\n slug: input.slug,\n kind: input.kind,\n label,\n ...(input.namePlural !== undefined && input.namePlural.trim().length > 0\n ? { labelPlural: input.namePlural.trim() }\n : {}),\n ...(input.description !== undefined && input.description.trim().length > 0\n ? { description: input.description.trim() }\n : {}),\n ...(input.icon !== undefined && input.icon.length > 0 ? { icon: input.icon } : {}),\n fields: { [INITIAL_FIELD_KEY]: INITIAL_FIELD },\n titleField: INITIAL_FIELD_KEY,\n schemaVersion: 1,\n }\n\n assertValidContentType(type)\n return type\n}\n\n/**\n * The create path in one call: collision check against both sources, then the draft.\n *\n * The adapter runs this again before writing, which is what makes a bypassed UI change\n * nothing.\n */\nexport function createContentType(\n registry: Registry,\n input: NewContentTypeInput,\n): ContentTypeLike {\n assertTypeSlugAvailable(registry, input.slug)\n return newContentType(input)\n}\n","\"use client\"\n\nimport { useState } from \"react\"\n\nimport type { CmsAdapter } from \"../../core/adapter.js\"\nimport type { Registry } from \"../../core/registry.js\"\nimport { checkTypeSlug, newContentType } from \"../../core/schema-builder.js\"\nimport { slugify } from \"../../fields/slug/slugify.js\"\nimport type { ContentTypeKind } from \"../../types/content-type.js\"\nimport { classifyError } from \"../../core/error-taxonomy.js\"\nimport type { ClassifiedError } from \"../../core/error-taxonomy.js\"\nimport { Button } from \"../components/button.js\"\nimport { Field, TextInput } from \"../components/field.js\"\nimport { ErrorNotice } from \"../components/error-notice.js\"\nimport { ICON_NAMES } from \"../components/icon-names.js\"\nimport { Modal } from \"../components/modal.js\"\nimport { Select } from \"../components/select.js\"\nimport type { SelectOption } from \"../components/select.js\"\nimport { useOptionalToast } from \"../components/toast.js\"\n\n/**\n * Creating a database-defined content type: name, slug, icon, and collection or singleton.\n *\n * The slug check is not this dialog's opinion. `checkTypeSlug` answers it against **both**\n * sources and returns the message, so a slug taken by a code-defined type is refused here\n * with an explanation, even though the Schema Builder's own list does not contain it and an\n * editor staring at that list has no way to work out what is in the way.\n *\n * The same check runs again inside the adapter. What is on this screen is a courtesy; what\n * the adapter answers is the rule, and its error is rendered here rather than swallowed,\n * because a collision created between the keystroke and the write is real.\n */\n\nconst KIND_OPTIONS: readonly SelectOption[] = [\n { value: \"collection\", label: \"Collection: many entries\" },\n { value: \"singleton\", label: \"Singleton: exactly one entry\" },\n]\n\n/** The icon vocabulary, offered by name. An empty choice falls back to the kind's icon. */\nconst ICON_OPTIONS: readonly SelectOption[] = [\n { value: \"\", label: \"Default for the kind\" },\n ...ICON_NAMES.map((name) => ({ value: name, label: name })),\n]\n\nexport interface CreateContentTypeDialogProps {\n open: boolean\n registry: Registry\n adapter: CmsAdapter\n onClose: () => void\n onCreated: (slug: string) => void\n}\n\nexport function CreateContentTypeDialog(props: CreateContentTypeDialogProps) {\n // Remounted per opening, so a cancelled attempt does not leave its half-typed name and\n // its stale error behind for the next one.\n return props.open ? <CreateDialogBody {...props} /> : null\n}\n\nfunction CreateDialogBody({\n registry,\n adapter,\n onClose,\n onCreated,\n}: CreateContentTypeDialogProps) {\n const toast = useOptionalToast()\n const [name, setName] = useState(\"\")\n const [slug, setSlug] = useState(\"\")\n /** True once the slug box has been edited by hand, after which the name stops driving it. */\n const [slugEdited, setSlugEdited] = useState(false)\n const [kind, setKind] = useState<ContentTypeKind>(\"collection\")\n const [icon, setIcon] = useState(\"\")\n const [saving, setSaving] = useState(false)\n const [failure, setFailure] = useState<ClassifiedError | null>(null)\n\n const trimmedName = name.trim()\n const availability = slug === \"\" ? undefined : checkTypeSlug(registry, slug)\n const slugError = availability?.available === false ? availability.message : undefined\n const ready = trimmedName !== \"\" && slug !== \"\" && slugError === undefined\n\n async function create(): Promise<void> {\n if (!ready || saving) return\n\n setSaving(true)\n setFailure(null)\n\n try {\n // Built and validated before the write, so a malformed draft fails on the form.\n const draft = newContentType({\n name: trimmedName,\n slug,\n kind,\n ...(icon === \"\" ? {} : { icon }),\n })\n const created = await adapter.schemas.create(draft)\n toast?.notify({ tone: \"success\", title: `${created.label} created` })\n onCreated(created.slug)\n } catch (thrown: unknown) {\n setFailure(classifyError(thrown, { action: \"create this content type\" }))\n } finally {\n setSaving(false)\n }\n }\n\n return (\n <Modal\n open\n onClose={onClose}\n title=\"New content type\"\n description=\"It appears in the sidebar as soon as it is created. No deploy, no restart.\"\n width=\"md\"\n footer={\n <>\n <Button variant=\"secondary\" onClick={onClose} disabled={saving}>\n Cancel\n </Button>\n <Button\n variant=\"primary\"\n icon=\"create\"\n loading={saving}\n disabled={!ready}\n onClick={() => void create()}\n >\n Create\n </Button>\n </>\n }\n >\n <div className=\"flex flex-col gap-5\">\n {failure === null ? null : <ErrorNotice error={failure} />}\n\n <Field label=\"Name\" required help=\"The singular name, for example Team member.\">\n {({ id, invalid }) => (\n <TextInput\n id={id}\n value={name}\n invalid={invalid}\n autoFocus\n onChange={(event) => {\n setName(event.target.value)\n // The slug follows the name until somebody edits it, and then it stops:\n // a slug that keeps rewriting itself under an editor's cursor is a trap.\n if (!slugEdited) setSlug(slugify(event.target.value))\n }}\n />\n )}\n </Field>\n\n <Field\n label=\"Slug\"\n required\n help=\"Used in the URL and as the name of the stored collection. It cannot be changed later.\"\n {...(slugError === undefined ? {} : { error: slugError })}\n >\n {({ id, invalid }) => (\n <TextInput\n id={id}\n value={slug}\n invalid={invalid}\n onChange={(event) => {\n setSlugEdited(true)\n setSlug(event.target.value)\n }}\n />\n )}\n </Field>\n\n <Field\n label=\"Kind\"\n required\n help=\"A collection holds many entries. A singleton exists exactly once, like a homepage.\"\n >\n {({ id }) => (\n <Select\n id={id}\n options={KIND_OPTIONS}\n value={kind}\n onChange={(value) =>\n setKind(value === \"singleton\" ? \"singleton\" : \"collection\")\n }\n />\n )}\n </Field>\n\n <Field label=\"Icon\" optional help=\"Shown in the sidebar beside the name.\">\n {({ id }) => (\n <Select id={id} options={ICON_OPTIONS} value={icon} onChange={setIcon} />\n )}\n </Field>\n </div>\n </Modal>\n )\n}\n","\"use client\"\n\nimport { useState } from \"react\"\n\nimport type { CmsAdapter } from \"../../core/adapter.js\"\nimport type { Registry, RegistryEntry } from \"../../core/registry.js\"\nimport { isSchemaReadOnly } from \"../../core/registry.js\"\nimport { schemaVersionOf } from \"../../core/schema-version.js\"\nimport { can } from \"../../permissions/can.js\"\nimport type { AuthUser } from \"../../types/auth.js\"\nimport { Badge } from \"../components/badge.js\"\nimport { Button } from \"../components/button.js\"\nimport { EmptyState } from \"../components/empty-state.js\"\nimport { Icon } from \"../components/icon.js\"\nimport { PageHeader } from \"../components/page-header.js\"\nimport { Panel } from \"../components/panel.js\"\nimport { PageSections, Section } from \"../components/section.js\"\nimport {\n Table,\n TableBody,\n TableCell,\n TableEmptyRow,\n TableHead,\n TableHeaderCell,\n TableRow,\n} from \"../components/table.js\"\nimport { Tooltip } from \"../components/tooltip.js\"\nimport { contentTypeLabel } from \"../navigation/navigation.js\"\n\nimport { CreateContentTypeDialog } from \"./create-content-type-dialog.js\"\n\n/**\n * The Developer area's Content Types list.\n *\n * Every content type the admin knows about, from either source, in one table. The two\n * columns that only exist here are the point of the screen: **source** says whether a\n * definition lives in git or in the database, and **lock** says whether the Schema Builder\n * may touch it. Both are answered by the registry, never by the row.\n *\n * Two things that are easy to hide and must not be:\n *\n * - A slug defined in both sources. Code wins, the database definition is preserved on\n * `entry.conflict`, and the editor who created it is told it exists, is not live, and\n * why.\n * - A stored definition that failed validation. It is in `registry.invalid` rather than in\n * the table, and a definition that silently disappeared is indistinguishable from one\n * that was deleted.\n */\n\nexport interface ContentTypesScreenProps {\n registry: Registry\n adapter: CmsAdapter\n user: AuthUser\n /** Opens one content type. Read-only for a code-defined one; the screen says so. */\n onOpen: (slug: string) => void\n /** Called with the slug of a freshly created type, so the host can route to it. */\n onCreated?: (slug: string) => void\n /**\n * A listener error from the live registry, if the host is running one.\n *\n * Shown here rather than swallowed, because this screen is where somebody creates a type\n * and then waits for it to appear.\n */\n liveError?: Error | null\n}\n\nexport function ContentTypesScreen({\n registry,\n adapter,\n user,\n onOpen,\n onCreated,\n liveError = null,\n}: ContentTypesScreenProps) {\n const [creating, setCreating] = useState(false)\n\n // `manage-schema` is admin only. Hiding the button is presentation: the adapter and the\n // security rules refuse the write again for a caller that never saw this screen.\n const mayCreate = can(user, \"manage-schema\")\n const conflicts = registry.conflicts\n\n return (\n <>\n <PageHeader\n title=\"Content Types\"\n description=\"Every content type in this project, from code and from the database.\"\n breadcrumb={[{ label: \"Developer\" }, { label: \"Content Types\" }]}\n actions={\n mayCreate ? (\n <Button variant=\"primary\" icon=\"create\" onClick={() => setCreating(true)}>\n New content type\n </Button>\n ) : undefined\n }\n />\n\n <PageSections>\n {liveError === null ? null : (\n <Panel padding=\"compact\">\n <p className=\"text-body-sm text-warning\">\n Live updates stopped: {liveError.message}\n </p>\n <p className=\"mt-1 text-caption text-text-muted\">\n What is on this screen may be out of date. Reload to read the schemas again.\n </p>\n </Panel>\n )}\n\n <Section>\n <Panel padding=\"none\">\n <Table label=\"Content types\">\n <TableHead>\n <TableRow>\n <TableHeaderCell>Name</TableHeaderCell>\n <TableHeaderCell>Slug</TableHeaderCell>\n <TableHeaderCell>Kind</TableHeaderCell>\n <TableHeaderCell numeric>Fields</TableHeaderCell>\n <TableHeaderCell>Source</TableHeaderCell>\n <TableHeaderCell numeric>Schema version</TableHeaderCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {registry.types.length === 0 ? (\n <TableEmptyRow colSpan={6}>\n <EmptyState\n icon=\"content-types\"\n heading=\"No content types yet\"\n description=\"A content type defines one structure: its fields, its list view and its form.\"\n {...(mayCreate\n ? {\n action: (\n <Button\n variant=\"primary\"\n icon=\"create\"\n onClick={() => setCreating(true)}\n >\n New content type\n </Button>\n ),\n }\n : {})}\n />\n </TableEmptyRow>\n ) : (\n registry.types.map((entry) => (\n <ContentTypeRow\n key={entry.type.slug}\n entry={entry}\n onOpen={() => onOpen(entry.type.slug)}\n />\n ))\n )}\n </TableBody>\n </Table>\n </Panel>\n </Section>\n\n {conflicts.length === 0 ? null : <ConflictSection entries={conflicts} />}\n\n {registry.invalid.length === 0 ? null : (\n <Section\n heading=\"Stored definitions that could not be loaded\"\n description=\"These documents are in the database and are not in use. Nothing was deleted; each is kept exactly as it is stored.\"\n >\n <Panel padding=\"compact\">\n <ul className=\"flex flex-col gap-3\">\n {registry.invalid.map((invalid) => (\n <li key={`${invalid.slug}-${invalid.reason}`}>\n <p className=\"text-body-sm text-text-primary\">{invalid.slug}</p>\n <p className=\"mt-1 text-caption text-danger\">{invalid.reason}</p>\n </li>\n ))}\n </ul>\n </Panel>\n </Section>\n )}\n </PageSections>\n\n <CreateContentTypeDialog\n open={creating}\n registry={registry}\n adapter={adapter}\n onClose={() => setCreating(false)}\n onCreated={(slug) => {\n setCreating(false)\n onCreated?.(slug)\n }}\n />\n </>\n )\n}\n\nconst KIND_LABEL = {\n collection: \"Collection\",\n singleton: \"Singleton\",\n} as const\n\nfunction ContentTypeRow({ entry, onOpen }: { entry: RegistryEntry; onOpen: () => void }) {\n const { type } = entry\n const readOnly = isSchemaReadOnly(entry)\n\n return (\n <TableRow onActivate={onOpen}>\n <TableCell primary>\n <span className=\"flex items-center gap-2\">\n <Icon name={type.kind === \"singleton\" ? \"singleton\" : \"collection\"} size={14} />\n <span className=\"truncate\">{contentTypeLabel(type)}</span>\n {readOnly ? <LockMark entry={entry} /> : null}\n </span>\n </TableCell>\n <TableCell>{type.slug}</TableCell>\n <TableCell>{KIND_LABEL[type.kind]}</TableCell>\n <TableCell numeric>{Object.keys(type.fields).length}</TableCell>\n <TableCell>\n <Badge variant={entry.source === \"code\" ? \"info\" : \"neutral\"}>\n {entry.source === \"code\" ? \"Code\" : \"Database\"}\n </Badge>\n </TableCell>\n <TableCell numeric>{schemaVersionOf(type)}</TableCell>\n </TableRow>\n )\n}\n\n/**\n * The lock mark, with the reason behind it.\n *\n * Two different facts read as one icon, so the tooltip distinguishes them: a type marked\n * `locked` is protected on purpose, and a code-defined type is not the Schema Builder's to\n * edit at all. Both are read-only here; only one of them is a decision somebody made.\n */\nexport function LockMark({ entry }: { entry: RegistryEntry }) {\n const reason = entry.locked\n ? \"Locked. Its definition is protected and cannot be changed here.\"\n : \"Defined in code. Change the TypeScript definition and deploy.\"\n\n return (\n <Tooltip content={reason}>\n <span className=\"inline-flex text-text-faint\">\n <Icon name=\"locked\" size={14} />\n <span className=\"sr-only\">{reason}</span>\n </span>\n </Tooltip>\n )\n}\n\n/**\n * A slug defined in both sources.\n *\n * The rule is `buildRegistry`'s and it is one-directional: code wins. What this section\n * exists for is the other half of that sentence, which no editor can infer from a sidebar\n * that simply shows one type: the definition they created is still stored, it is not the\n * one in use, and nothing was deleted.\n */\nfunction ConflictSection({ entries }: { entries: readonly RegistryEntry[] }) {\n return (\n <Section\n heading=\"Slugs defined twice\"\n description=\"These slugs exist in code and in the database. The code definition is the one in use.\"\n >\n <Panel padding=\"compact\">\n <ul className=\"flex flex-col gap-4\">\n {entries.map((entry) => (\n <li key={entry.type.slug}>\n <p className=\"flex items-center gap-2 text-body-sm text-text-primary\">\n <Icon name=\"warning\" size={14} />\n <span>{entry.type.slug}</span>\n </p>\n <p className=\"mt-1 text-body-sm text-text-secondary\">\n Live: <strong className=\"text-text-primary\">{entry.type.label}</strong>,\n defined in code with {String(Object.keys(entry.type.fields).length)}{\" \"}\n fields.\n </p>\n <p className=\"mt-1 text-body-sm text-text-secondary\">\n Not live:{\" \"}\n <strong className=\"text-text-primary\">\n {entry.conflict?.type.label}\n </strong>\n , created here in the Schema Builder with{\" \"}\n {String(Object.keys(entry.conflict?.type.fields ?? {}).length)} fields. It\n is still stored and nothing has been deleted, but it is not what the admin\n or the SDK reads.\n </p>\n <p className=\"mt-1 text-caption text-text-muted\">\n To make it live, rename it to a free slug, or remove the code definition\n and deploy. Its entries are stored under this slug either way.\n </p>\n </li>\n ))}\n </ul>\n </Panel>\n </Section>\n )\n}\n","\"use client\"\n\nimport { useState } from \"react\"\nimport type { DragEvent } from \"react\"\n\nimport type {\n FieldKeyAvailability,\n FieldOptionIssue,\n FieldRow,\n} from \"../../core/schema-editor.js\"\nimport {\n VALIDATION_RULE_CONTROLS,\n checkNestedFieldKey,\n moveFieldRow,\n newFieldDefinition,\n suggestFieldKey,\n withFieldOption,\n withValidationRule,\n} from \"../../core/schema-editor.js\"\nimport type { FieldOptionDescriptor, FieldTypeRegistry } from \"../../schema/field-type.js\"\nimport type { FieldDefinition, FieldMap, FieldType } from \"../../types/field.js\"\nimport { Badge } from \"../components/badge.js\"\nimport { Button } from \"../components/button.js\"\nimport { Checkbox } from \"../components/checkbox.js\"\nimport { cx } from \"../components/class-names.js\"\nimport { Field, TextInput } from \"../components/field.js\"\nimport { Icon } from \"../components/icon.js\"\nimport { IconButton } from \"../components/icon-button.js\"\nimport { Modal } from \"../components/modal.js\"\nimport { Select } from \"../components/select.js\"\nimport { Tooltip } from \"../components/tooltip.js\"\nimport type { SelectOption } from \"../components/select.js\"\nimport { Switch } from \"../components/switch.js\"\n\n/**\n * The field editor: one list of fields, reorderable, each expanding into its own options.\n *\n * It renders no field type. It renders **descriptors**: every per-type option and every\n * validation rule on this screen comes from the field type's own `editor` spec through the\n * registry, and the only switch in this file is over the small control vocabulary those\n * descriptors are written in. Adding a thirteenth field type therefore adds its options\n * here with no edit to this file, which is the same rule that makes the list views and the\n * entry forms generated rather than written.\n *\n * Reordering works from the pointer and from the keyboard, and neither is a fallback for\n * the other: the handle is a real button, the arrow keys move the field, focus travels with\n * the row because the rows are keyed by field key, and every move is announced.\n *\n * A read-only field list has no handles, no inputs and no remove buttons. Not disabled\n * controls that still look like controls: a code-defined type is not edited here at all,\n * and the banner above the list says why.\n */\n\nexport interface FieldRowsProps {\n rows: readonly FieldRow[]\n registry: FieldTypeRegistry\n /** Relation targets, from the live registry. The editor never reads the registry itself. */\n contentTypes: readonly SelectOption[]\n readOnly: boolean\n /**\n * Whether a row can be moved.\n *\n * False for a repeater's nested fields: their order has nowhere to be stored, because\n * `fieldOrder` describes a content type and a nested map is part of one field.\n */\n reorderable?: boolean\n /** Whether a key may be used here. Differs at the top level and inside a repeater. */\n checkKey: (key: string) => FieldKeyAvailability\n onChange: (rows: readonly FieldRow[]) => void\n /**\n * Removal, when it is not a plain list edit.\n *\n * At the top level it never is: removing a field has to go through the warning that\n * counts the entries holding a value, so the owner handles it. Inside a repeater the row\n * simply leaves the list.\n */\n onRemove?: (key: string) => void\n /** Names the group for assistive technology, and the add button. */\n label: string\n issues?: readonly (FieldOptionIssue & { key: string })[]\n}\n\nexport function FieldRows({\n rows,\n registry,\n contentTypes,\n readOnly,\n reorderable = true,\n checkKey,\n onChange,\n onRemove,\n label,\n issues = [],\n}: FieldRowsProps) {\n const [dragging, setDragging] = useState<number | null>(null)\n const [expanded, setExpanded] = useState<readonly string[]>([])\n const [adding, setAdding] = useState(false)\n const [announcement, setAnnouncement] = useState(\"\")\n\n function move(from: number, to: number): void {\n if (to < 0 || to >= rows.length || from === to) return\n const moved = rows[from]\n onChange(moveFieldRow(rows, from, to))\n setAnnouncement(\n `${moved?.field.label ?? \"Field\"} moved to position ${String(to + 1)} of ${String(rows.length)}.`,\n )\n // Focus is not restored by hand: the rows are keyed by field key, so React moves the\n // existing node and the focused handle travels with the row it just moved.\n }\n\n function replace(index: number, field: FieldDefinition): void {\n onChange(rows.map((row, current) => (current === index ? { ...row, field } : row)))\n }\n\n const siblingKeys: readonly SelectOption[] = rows.map((row) => ({\n value: row.key,\n label: `${row.field.label} (${row.key})`,\n }))\n\n return (\n <div className=\"flex flex-col gap-3\">\n {reorderable && !readOnly ? (\n <>\n <p id={`${label}-reorder-help`} className=\"sr-only\">\n Press the up and down arrow keys to move this field.\n </p>\n <p aria-live=\"polite\" className=\"sr-only\">\n {announcement}\n </p>\n </>\n ) : null}\n\n <ul className=\"flex flex-col gap-2\" aria-label={label}>\n {rows.map((row, index) => (\n <li\n key={row.key}\n onDragOver={(event) => {\n if (dragging === null) return\n event.preventDefault()\n const transfer = dataTransferOf(event)\n if (transfer !== undefined) transfer.dropEffect = \"move\"\n }}\n onDrop={(event) => {\n if (dragging === null) return\n event.preventDefault()\n move(dragging, index)\n setDragging(null)\n }}\n className={cx(\n \"overflow-hidden rounded-sm border bg-surface-card state-transition\",\n dragging === index ? \"border-border-active\" : \"border-border-default\",\n )}\n >\n <div className=\"flex items-center gap-2 border-b border-border-subtle bg-surface-raised px-2 py-1.5\">\n {readOnly ? (\n <span className=\"flex size-7.5 shrink-0 items-center justify-center text-text-faint\">\n <Icon name=\"locked\" size={14} />\n <span className=\"sr-only\">Read-only</span>\n </span>\n ) : reorderable ? (\n // Icon-only, so it carries a tooltip as well as a name. The style guide\n // requires both, and the M10 audit found this handle had only the name.\n <Tooltip content=\"Drag to reorder, or press the up and down arrow keys\">\n <button\n type=\"button\"\n draggable\n aria-label={`Reorder ${row.field.label}`}\n aria-describedby={`${label}-reorder-help`}\n onDragStart={(event) => {\n setDragging(index)\n const transfer = dataTransferOf(event)\n if (transfer === undefined) return\n transfer.effectAllowed = \"move\"\n transfer.setData(\"text/plain\", String(index))\n }}\n onDragEnd={() => setDragging(null)}\n onKeyDown={(event) => {\n if (event.key === \"ArrowUp\") {\n event.preventDefault()\n move(index, index - 1)\n } else if (event.key === \"ArrowDown\") {\n event.preventDefault()\n move(index, index + 1)\n }\n }}\n className=\"flex size-7.5 shrink-0 cursor-grab items-center justify-center rounded-sm text-text-muted state-transition hover:bg-surface-hover hover:text-text-primary focus-visible:focus-ring active:cursor-grabbing\"\n >\n <Icon name=\"drag-handle\" size={14} />\n </button>\n </Tooltip>\n ) : (\n <span className=\"size-7.5 shrink-0\" />\n )}\n\n <span className=\"min-w-0 flex-1 truncate text-label text-text-secondary\">\n {row.field.label}\n </span>\n <span className=\"shrink-0 text-caption text-text-faint\">{row.key}</span>\n <Badge>\n {registry.get(row.field.type)?.editor.label ?? row.field.type}\n </Badge>\n\n <IconButton\n icon={expanded.includes(row.key) ? \"collapse\" : \"expand\"}\n label={\n expanded.includes(row.key)\n ? `Hide the options of ${row.field.label}`\n : `Show the options of ${row.field.label}`\n }\n size=\"sm\"\n onClick={() =>\n setExpanded((current) =>\n current.includes(row.key)\n ? current.filter((key) => key !== row.key)\n : [...current, row.key],\n )\n }\n />\n\n {readOnly ? null : (\n <IconButton\n icon=\"delete\"\n label={`Remove ${row.field.label}`}\n size=\"sm\"\n onClick={() => {\n if (onRemove !== undefined) {\n onRemove(row.key)\n return\n }\n onChange(rows.filter((current) => current.key !== row.key))\n }}\n />\n )}\n </div>\n\n {expanded.includes(row.key) ? (\n <FieldOptions\n row={row}\n registry={registry}\n contentTypes={contentTypes}\n siblingKeys={siblingKeys.filter((option) => option.value !== row.key)}\n readOnly={readOnly}\n issues={issues.filter((issue) => issue.key === row.key)}\n onChange={(field) => replace(index, field)}\n />\n ) : null}\n </li>\n ))}\n </ul>\n\n {readOnly ? null : (\n <div>\n <Button size=\"sm\" icon=\"create\" onClick={() => setAdding(true)}>\n Add field\n </Button>\n </div>\n )}\n\n <AddFieldDialog\n open={adding}\n registry={registry}\n checkKey={checkKey}\n onClose={() => setAdding(false)}\n onAdd={(key, type, fieldLabel) => {\n onChange([\n ...rows,\n { key, field: newFieldDefinition(registry, type, fieldLabel) },\n ])\n setExpanded((current) => [...current, key])\n setAdding(false)\n }}\n />\n </div>\n )\n}\n\n/**\n * `DragEvent.dataTransfer` is nullable in the DOM specification even though React's types\n * declare it present, and it really is absent on an event dispatched without one. Reading\n * through it unguarded throws where nothing catches it.\n */\nfunction dataTransferOf(event: DragEvent<HTMLElement>): DataTransfer | undefined {\n const transfer: DataTransfer | undefined | null = event.dataTransfer\n return transfer ?? undefined\n}\n\ninterface FieldOptionsProps {\n row: FieldRow\n registry: FieldTypeRegistry\n contentTypes: readonly SelectOption[]\n siblingKeys: readonly SelectOption[]\n readOnly: boolean\n issues: readonly FieldOptionIssue[]\n onChange: (field: FieldDefinition) => void\n}\n\n/**\n * One field's options: the shared ones, then the type's own, then its validation rules.\n *\n * The middle and the last block are both generated. Neither knows what a select or a\n * relation is; they read `spec.editor.options` and `spec.editor.rules`.\n */\nfunction FieldOptions({\n row,\n registry,\n contentTypes,\n siblingKeys,\n readOnly,\n issues,\n onChange,\n}: FieldOptionsProps) {\n const spec = registry.get(row.field.type)\n const values = row.field as unknown as Record<string, unknown>\n const rules = row.field.validation ?? {}\n\n if (spec === undefined) {\n return (\n <div className=\"p-3\">\n <p className=\"text-body-sm text-text-muted\">\n This field uses the type "{row.field.type}", which this version cannot\n edit. It is kept exactly as it is stored.\n </p>\n </div>\n )\n }\n\n if (readOnly) {\n return (\n <dl className=\"flex flex-col gap-2 p-3 text-body-sm\">\n <ReadOnlyRow term=\"Key\" value={row.key} />\n <ReadOnlyRow term=\"Type\" value={spec.editor.label} />\n {row.field.description === undefined ? null : (\n <ReadOnlyRow term=\"Description\" value={row.field.description} />\n )}\n {spec.editor.options.map((option) => (\n <ReadOnlyRow\n key={option.key}\n term={option.label}\n value={describeValue(values[option.key])}\n />\n ))}\n {spec.editor.rules.map((rule) => (\n <ReadOnlyRow\n key={rule}\n term={VALIDATION_RULE_CONTROLS[rule].label}\n value={describeValue(rules[rule])}\n />\n ))}\n </dl>\n )\n }\n\n return (\n <div className=\"flex flex-col gap-5 p-3\">\n <Field label=\"Label\" required help=\"What the form calls this field.\">\n {({ id }) => (\n <TextInput\n id={id}\n value={row.field.label}\n onChange={(event) => onChange({ ...row.field, label: event.target.value })}\n />\n )}\n </Field>\n\n <Field\n label=\"Description\"\n optional\n help=\"Shown under the control, for whoever fills the form in.\"\n >\n {({ id }) => (\n <TextInput\n id={id}\n value={row.field.description ?? \"\"}\n onChange={(event) =>\n onChange(withFieldOption(row.field, \"description\", event.target.value))\n }\n />\n )}\n </Field>\n\n {spec.editor.options.map((option) => (\n <OptionControl\n key={option.key}\n descriptor={option}\n field={row.field}\n registry={registry}\n contentTypes={contentTypes}\n siblingKeys={siblingKeys}\n issue={issues.find((entry) => entry.option === option.key)?.message}\n onChange={onChange}\n />\n ))}\n\n {spec.editor.rules.length === 0 ? null : (\n <fieldset className=\"flex flex-col gap-5 border-t border-border-subtle pt-4\">\n <legend className=\"text-label text-text-secondary\">Validation</legend>\n {spec.editor.rules.map((rule) => {\n const control = VALIDATION_RULE_CONTROLS[rule]\n const current = rules[rule]\n\n if (control.control === \"boolean\") {\n return (\n <Switch\n key={rule}\n checked={current === true}\n label={control.label}\n showLabel\n onChange={(checked) =>\n onChange(withValidationRule(row.field, rule, checked))\n }\n />\n )\n }\n\n const numeric = control.control === \"number\"\n\n return (\n <Field key={rule} label={control.label} optional help={control.help}>\n {({ id }) => (\n <TextInput\n id={id}\n type={numeric ? \"number\" : \"text\"}\n value={current === undefined ? \"\" : String(current)}\n onChange={(event) =>\n onChange(\n withValidationRule(\n row.field,\n rule,\n numericOrText(numeric ? \"number\" : \"text\", event.target.value),\n ),\n )\n }\n />\n )}\n </Field>\n )\n })}\n </fieldset>\n )}\n\n <div className=\"flex flex-wrap gap-6 border-t border-border-subtle pt-4\">\n <Checkbox\n checked={row.field.hidden === true}\n label=\"Hidden in the form\"\n onChange={(checked) =>\n onChange(withFieldOption(row.field, \"hidden\", checked === true ? true : \"\"))\n }\n />\n <Checkbox\n checked={row.field.readonly === true}\n label=\"Read-only in the form\"\n onChange={(checked) =>\n onChange(withFieldOption(row.field, \"readonly\", checked === true ? true : \"\"))\n }\n />\n </div>\n </div>\n )\n}\n\nfunction numericOrText(\n control: \"number\" | \"text\",\n raw: string,\n): string | number | undefined {\n if (raw === \"\") return undefined\n if (control !== \"number\") return raw\n const parsed = Number(raw)\n return Number.isFinite(parsed) ? parsed : undefined\n}\n\nfunction ReadOnlyRow({ term, value }: { term: string; value: string }) {\n return (\n <div className=\"flex gap-2\">\n <dt className=\"w-40 shrink-0 text-text-muted\">{term}</dt>\n <dd className=\"min-w-0 text-text-secondary\">{value}</dd>\n </div>\n )\n}\n\nfunction describeValue(value: unknown): string {\n if (value === undefined || value === null) return \"Not set\"\n if (typeof value === \"boolean\") return value ? \"Yes\" : \"No\"\n if (Array.isArray(value)) {\n return value.length === 0\n ? \"Not set\"\n : value\n .map((item) =>\n typeof item === \"object\" && item !== null && \"value\" in item\n ? String((item as { value: unknown }).value)\n : String(item),\n )\n .join(\", \")\n }\n if (typeof value === \"object\") return Object.keys(value).join(\", \")\n return String(value)\n}\n\ninterface OptionControlProps {\n descriptor: FieldOptionDescriptor\n field: FieldDefinition\n registry: FieldTypeRegistry\n contentTypes: readonly SelectOption[]\n siblingKeys: readonly SelectOption[]\n issue?: string | undefined\n onChange: (field: FieldDefinition) => void\n}\n\n/**\n * One option, rendered by its control.\n *\n * This switch is over the control vocabulary, not over field types. That distinction is the\n * whole design: a new field type reuses these controls, and a new *control* is a deliberate\n * addition to the vocabulary that every field type can then declare.\n */\nfunction OptionControl({\n descriptor,\n field,\n registry,\n contentTypes,\n siblingKeys,\n issue,\n onChange,\n}: OptionControlProps) {\n const values = field as unknown as Record<string, unknown>\n const value = values[descriptor.key]\n const common = {\n label: descriptor.label,\n ...(descriptor.required === true ? { required: true } : { optional: true }),\n ...(descriptor.help === undefined ? {} : { help: descriptor.help }),\n ...(issue === undefined ? {} : { error: issue }),\n }\n\n switch (descriptor.control) {\n case \"boolean\":\n return (\n <Switch\n checked={value === true}\n label={descriptor.label}\n showLabel\n onChange={(checked) =>\n onChange(withFieldOption(field, descriptor.key, checked === true ? true : \"\"))\n }\n />\n )\n\n case \"number\":\n case \"text\":\n return (\n <Field {...common}>\n {({ id, invalid }) => (\n <TextInput\n id={id}\n invalid={invalid}\n type={descriptor.control === \"number\" ? \"number\" : \"text\"}\n value={value === undefined || value === null ? \"\" : String(value)}\n onChange={(event) =>\n onChange(\n withFieldOption(\n field,\n descriptor.key,\n numericOrText(\n descriptor.control === \"number\" ? \"number\" : \"text\",\n event.target.value,\n ) ?? \"\",\n ),\n )\n }\n />\n )}\n </Field>\n )\n\n case \"choice\":\n case \"content-type\":\n case \"field-key\": {\n const options: readonly SelectOption[] =\n descriptor.control === \"choice\"\n ? (descriptor.choices ?? [])\n : descriptor.control === \"content-type\"\n ? contentTypes\n : siblingKeys\n\n return (\n <Field {...common}>\n {({ id, invalid }) => (\n <Select\n id={id}\n invalid={invalid}\n options={\n descriptor.required === true\n ? options\n : [{ value: \"\", label: \"Not set\" }, ...options]\n }\n value={typeof value === \"string\" ? value : \"\"}\n placeholder=\"Choose\"\n onChange={(next) => onChange(withFieldOption(field, descriptor.key, next))}\n />\n )}\n </Field>\n )\n }\n\n case \"string-list\":\n return (\n <Field {...common} help={descriptor.help ?? \"Separate several with a comma.\"}>\n {({ id, invalid }) => (\n <TextInput\n id={id}\n invalid={invalid}\n value={Array.isArray(value) ? value.join(\", \") : \"\"}\n onChange={(event) =>\n onChange(\n withFieldOption(\n field,\n descriptor.key,\n event.target.value\n .split(\",\")\n .map((item) => item.trim())\n .filter((item) => item !== \"\"),\n ),\n )\n }\n />\n )}\n </Field>\n )\n\n case \"select-options\":\n return (\n <SelectOptionsEditor\n label={descriptor.label}\n {...(issue === undefined ? {} : { issue })}\n options={Array.isArray(value) ? (value as readonly SelectOptionValue[]) : []}\n onChange={(next) => onChange(withFieldOption(field, descriptor.key, next))}\n />\n )\n\n case \"fields\": {\n const nested: FieldMap =\n typeof value === \"object\" && value !== null ? (value as FieldMap) : {}\n\n return (\n <div className=\"flex flex-col gap-2\">\n <p className=\"text-label text-text-secondary\">{descriptor.label}</p>\n <p className=\"text-caption text-text-muted\">\n The fields of each row. They are shown in the order they are stored; a\n row's fields cannot be reordered.\n </p>\n {issue === undefined ? null : (\n <p className=\"text-caption text-danger\">{issue}</p>\n )}\n <FieldRows\n rows={Object.entries(nested).map(([key, definition]) => ({\n key,\n field: definition,\n }))}\n registry={registry}\n contentTypes={contentTypes}\n readOnly={false}\n reorderable={false}\n label={`${descriptor.label} of this row`}\n checkKey={(key) => checkNestedFieldKey(nested, key)}\n onChange={(rows) =>\n onChange(\n withFieldOption(\n field,\n descriptor.key,\n Object.fromEntries(rows.map((row) => [row.key, row.field])),\n ),\n )\n }\n />\n </div>\n )\n }\n }\n}\n\ninterface SelectOptionValue {\n value: string\n label: string\n}\n\n/**\n * The value/label list of a select.\n *\n * The value is what entries store and the label is what the form shows, so they are edited\n * separately: renaming a label is free, and changing a value is a change to every entry\n * that holds it, which is also what moves the schema version stamp.\n */\nfunction SelectOptionsEditor({\n label,\n options,\n issue,\n onChange,\n}: {\n label: string\n options: readonly SelectOptionValue[]\n issue?: string\n onChange: (options: readonly SelectOptionValue[]) => void\n}) {\n return (\n <div className=\"flex flex-col gap-2\">\n <p className=\"text-label text-text-secondary\">{label}</p>\n {issue === undefined ? null : <p className=\"text-caption text-danger\">{issue}</p>}\n\n <ul className=\"flex flex-col gap-2\">\n {options.map((option, index) => (\n <li key={`${String(index)}-${option.value}`} className=\"flex items-end gap-2\">\n <div className=\"flex-1\">\n <Field label=\"Value\" help=\"Stored on the entry.\">\n {({ id }) => (\n <TextInput\n id={id}\n value={option.value}\n onChange={(event) =>\n onChange(\n options.map((current, position) =>\n position === index\n ? { ...current, value: event.target.value }\n : current,\n ),\n )\n }\n />\n )}\n </Field>\n </div>\n <div className=\"flex-1\">\n <Field label=\"Label\" help=\"Shown in the form.\">\n {({ id }) => (\n <TextInput\n id={id}\n value={option.label}\n onChange={(event) =>\n onChange(\n options.map((current, position) =>\n position === index\n ? { ...current, label: event.target.value }\n : current,\n ),\n )\n }\n />\n )}\n </Field>\n </div>\n <IconButton\n icon=\"delete\"\n label={`Remove the option ${option.label}`}\n size=\"sm\"\n onClick={() =>\n onChange(options.filter((_current, position) => position !== index))\n }\n />\n </li>\n ))}\n </ul>\n\n <div>\n <Button\n size=\"sm\"\n icon=\"create\"\n onClick={() =>\n onChange([\n ...options,\n {\n value: `option-${String(options.length + 1)}`,\n label: `Option ${String(options.length + 1)}`,\n },\n ])\n }\n >\n Add option\n </Button>\n </div>\n </div>\n )\n}\n\ninterface AddFieldDialogProps {\n open: boolean\n registry: FieldTypeRegistry\n checkKey: (key: string) => FieldKeyAvailability\n onClose: () => void\n onAdd: (key: string, type: FieldType, label: string) => void\n}\n\n/**\n * Adding one field: its label, its key, and its type.\n *\n * The key is settled here and nowhere else. Renaming it later would mean moving the stored\n * values of every entry, which is a migration rather than an edit, so the editor offers it\n * once, explains what it is, and then leaves it alone.\n */\nfunction AddFieldDialog(props: AddFieldDialogProps) {\n return props.open ? <AddFieldBody {...props} /> : null\n}\n\nfunction AddFieldBody({ registry, checkKey, onClose, onAdd }: AddFieldDialogProps) {\n const [label, setLabel] = useState(\"\")\n const [key, setKey] = useState(\"\")\n const [keyEdited, setKeyEdited] = useState(false)\n const [type, setType] = useState<FieldType>(\"text\")\n\n const availability = key === \"\" ? undefined : checkKey(key)\n const keyError = availability?.available === false ? availability.message : undefined\n const ready = label.trim() !== \"\" && key !== \"\" && keyError === undefined\n\n const typeOptions: readonly SelectOption[] = registry.names.map((name) => ({\n value: name,\n label: registry.require(name).editor.label,\n }))\n const chosen = registry.get(type)\n\n return (\n <Modal\n open\n onClose={onClose}\n title=\"Add field\"\n width=\"md\"\n footer={\n <>\n <Button variant=\"secondary\" onClick={onClose}>\n Cancel\n </Button>\n <Button\n variant=\"primary\"\n icon=\"create\"\n disabled={!ready}\n onClick={() => onAdd(key, type, label.trim())}\n >\n Add field\n </Button>\n </>\n }\n >\n <div className=\"flex flex-col gap-5\">\n <Field label=\"Label\" required help=\"What the form calls this field.\">\n {({ id }) => (\n <TextInput\n id={id}\n value={label}\n autoFocus\n onChange={(event) => {\n setLabel(event.target.value)\n if (!keyEdited) setKey(suggestFieldKey(event.target.value))\n }}\n />\n )}\n </Field>\n\n <Field\n label=\"Key\"\n required\n help=\"Where the value is stored, and how the SDK names it. It cannot be changed later.\"\n {...(keyError === undefined ? {} : { error: keyError })}\n >\n {({ id, invalid }) => (\n <TextInput\n id={id}\n value={key}\n invalid={invalid}\n onChange={(event) => {\n setKeyEdited(true)\n setKey(event.target.value)\n }}\n />\n )}\n </Field>\n\n <Field\n label=\"Type\"\n required\n {...(chosen === undefined ? {} : { help: chosen.editor.description })}\n >\n {({ id }) => (\n <Select\n id={id}\n options={typeOptions}\n value={type}\n onChange={(next) => setType(next as FieldType)}\n />\n )}\n </Field>\n </div>\n </Modal>\n )\n}\n","\"use client\"\n\nimport {\n MATRIX_LIMITS,\n permissionMatrixRows,\n withMatrixRole,\n} from \"../../permissions/matrix.js\"\nimport type { MatrixCell, MatrixDecision } from \"../../permissions/matrix.js\"\nimport { ROLES } from \"../../types/auth.js\"\nimport type { EntryAction, PermissionMatrix, Role } from \"../../types/auth.js\"\nimport type { ContentTypeLike } from \"../../types/content-type.js\"\nimport { Checkbox } from \"../components/checkbox.js\"\nimport { Panel } from \"../components/panel.js\"\nimport { Section } from \"../components/section.js\"\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeaderCell,\n TableRow,\n} from \"../components/table.js\"\n\n/**\n * The per-content-type permission matrix, as an editable table.\n *\n * Every cell is `permissionMatrixRows`. The screen decides nothing: whether a checkbox is\n * ticked, what the three layers will actually do with it, and whether it can change\n * anything at all are all answered by `permissions/matrix.ts`, which delegates the decision\n * itself to the same `can()` the adapter and the security rules encode. A second opinion\n * rendered here would be a fourth copy of the truth table and the one nobody tests against\n * the database.\n *\n * Toggling goes through `withMatrixRole` for the same reason, and because unticking a role\n * while the matrix is silent has to materialize the action from the defaults first: an\n * empty list means \"admin only\", and a screen that produced one from a single untick would\n * revoke two roles for one click.\n *\n * **What this table cannot do is stated on it, not implied.** `MATRIX_LIMITS` is printed\n * under the table verbatim. The one that matters most is `publicRead`: denying `read` hides\n * a content type from the admin and hides its drafts, and it does not take a published\n * entry off the customer's website, because the public read carve-out is what makes the\n * website work at all. Taking content off the web is unpublishing it. A checkbox that\n * looked like a publishing control would be read as a guarantee, so the screen says the\n * opposite out loud.\n *\n * **A code-defined or locked type renders read-only**, like the rest of its definition.\n * The matrix is a property of the content type and is stored in the same document, so the\n * adapter refuses a write to it for exactly the reason it refuses a field change, and the\n * Schema Builder already shows such a type read-only throughout. Giving the matrix its own\n * writable side-channel would mean `locked: true` no longer covers the whole definition:\n * an admin could narrow a locked type's permissions through a door the lock was meant to\n * close, and the stored definition would stop matching the code it came from. A\n * code-defined type's matrix is changed where the rest of it is changed, in the code.\n */\n\nconst ROLE_LABEL: Readonly<Record<Role, string>> = {\n admin: \"Admin\",\n editor: \"Editor\",\n author: \"Author\",\n}\n\nconst ACTION_LABEL: Readonly<Record<EntryAction, string>> = {\n read: \"Read\",\n create: \"Create\",\n update: \"Update\",\n delete: \"Delete\",\n}\n\nconst ACTION_HELP: Readonly<Record<EntryAction, string>> = {\n read: \"See these entries in the admin, including drafts.\",\n create: \"Add a new entry of this type.\",\n update: \"Change an entry that already exists.\",\n delete: \"Remove an entry permanently.\",\n}\n\n/** What the three layers will actually do, in words rather than in a tick. */\nconst DECISION_LABEL: Readonly<Record<MatrixDecision, string>> = {\n allow: \"Allowed\",\n deny: \"Denied\",\n \"own-entry-only\": \"Own entries only\",\n}\n\n/** Why a checkbox cannot change anything, so a disabled control is never unexplained. */\nfunction fixedReason(cell: MatrixCell, action: EntryAction): string {\n if (cell.role === \"admin\") {\n return `An admin may always ${action} these entries.`\n }\n return `An ${cell.role} may never ${action} these entries, whatever this matrix says.`\n}\n\nexport interface PermissionMatrixEditorProps {\n /** The content type being edited. Only `permissions` and the labels are read. */\n type: ContentTypeLike\n /** True for a code-defined or locked type, and for a user without manage-schema. */\n readOnly: boolean\n /** The next matrix, already normalized. `undefined` means \"back to the role defaults\". */\n onChange: (next: PermissionMatrix | undefined) => void\n}\n\nexport function PermissionMatrixEditor({\n type,\n readOnly,\n onChange,\n}: PermissionMatrixEditorProps) {\n const rows = permissionMatrixRows(type)\n const subject = (type.labelPlural ?? type.label).toLowerCase()\n\n return (\n <Section\n heading=\"Permissions\"\n description={`Who may do what with ${subject}. Unticking a role takes the action away from it; ticking one never adds an action its own role does not already have.`}\n >\n {/* `none`: the table supplies its own cell inset, and panel padding would double it. */}\n <Panel padding=\"none\">\n <Table label={`Permissions for ${type.label}`}>\n <TableHead>\n <TableRow>\n <TableHeaderCell>Action</TableHeaderCell>\n {ROLES.map((role) => (\n <TableHeaderCell key={role}>{ROLE_LABEL[role]}</TableHeaderCell>\n ))}\n </TableRow>\n </TableHead>\n <TableBody>\n {rows.map((row) => (\n <TableRow key={row.action}>\n <TableCell primary>\n <span className=\"block\">{ACTION_LABEL[row.action]}</span>\n <span className=\"mt-1 block text-caption font-normal text-text-muted\">\n {ACTION_HELP[row.action]}\n </span>\n </TableCell>\n {row.cells.map((cell) => (\n <TableCell key={cell.role}>\n <Checkbox\n checked={cell.listed}\n disabled={readOnly || cell.fixed}\n // The whole sentence, because a bare tick in a grid reads as nothing\n // at all when the column header is three cells away.\n ariaLabel={`${ROLE_LABEL[cell.role]} may ${row.action} ${subject}`}\n onChange={(next) =>\n onChange(\n withMatrixRole(type.permissions, row.action, cell.role, next),\n )\n }\n />\n <span\n className={\n cell.decision === \"deny\"\n ? \"mt-1 block text-caption text-text-faint\"\n : \"mt-1 block text-caption text-text-muted\"\n }\n >\n {cell.fixed\n ? `${DECISION_LABEL[cell.decision]}. ${fixedReason(cell, row.action)}`\n : DECISION_LABEL[cell.decision]}\n </span>\n </TableCell>\n ))}\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </Panel>\n\n <MatrixLimits />\n </Section>\n )\n}\n\n/**\n * The four things a matrix cannot do, printed rather than implied.\n *\n * Taken from `MATRIX_LIMITS` verbatim so the screen and the domain cannot drift into two\n * different promises. `publicRead` leads, because it is the one whose absence would be read\n * as a guarantee: an admin looking at a `read` column has every reason to assume unticking\n * it takes the content off the website, and it does not.\n */\nfunction MatrixLimits() {\n return (\n <div className=\"mt-3 flex flex-col gap-2\">\n <p className=\"text-body-sm text-warning\">{MATRIX_LIMITS.publicRead}</p>\n <p className=\"text-caption text-text-muted\">{MATRIX_LIMITS.narrowing}</p>\n <p className=\"text-caption text-text-muted\">{MATRIX_LIMITS.admin}</p>\n <p className=\"text-caption text-text-muted\">{MATRIX_LIMITS.ownership}</p>\n </div>\n )\n}\n","\"use client\"\n\nimport { useState } from \"react\"\n\nimport type { CmsAdapter } from \"../../core/adapter.js\"\nimport { confirmationMatches } from \"../../core/delete-confirmation.js\"\nimport type { ContentTypeLike } from \"../../types/content-type.js\"\nimport { classifyError } from \"../../core/error-taxonomy.js\"\nimport type { ClassifiedError } from \"../../core/error-taxonomy.js\"\nimport { Button } from \"../components/button.js\"\nimport { Field, TextInput } from \"../components/field.js\"\nimport { ErrorNotice } from \"../components/error-notice.js\"\nimport { Modal } from \"../components/modal.js\"\n\n/**\n * Deleting the stored values of a removed field. The only destructive schema operation.\n *\n * It is its own dialog, reached from its own place, with its own typed confirmation. That\n * separation is the design: removal and purge are two decisions with as much time between\n * them as the user wants, and no single confirmation can take a field from \"this exists\" to\n * \"its data is gone\".\n *\n * One bounded call clears at most `MAX_FIELD_PURGE` entries and reports whether more\n * remain, so a large purge is resumed rather than run as one unbounded write. The dialog\n * says how many went and offers the next pass rather than looping silently.\n */\n\nexport interface PurgeFieldDialogProps {\n adapter: CmsAdapter\n type: ContentTypeLike\n /** The removed field whose values are being deleted. Null means the dialog is closed. */\n fieldKey: string | null\n onCancel: () => void\n /** Every value is gone: the caller drops the parked definition and saves. */\n onPurged: (fieldKey: string) => void\n}\n\nexport function PurgeFieldDialog(props: PurgeFieldDialogProps) {\n return props.fieldKey === null ? null : (\n <PurgeFieldBody key={props.fieldKey} {...props} />\n )\n}\n\nfunction PurgeFieldBody({\n adapter,\n type,\n fieldKey,\n onCancel,\n onPurged,\n}: PurgeFieldDialogProps) {\n const [typed, setTyped] = useState(\"\")\n const [running, setRunning] = useState(false)\n const [failure, setFailure] = useState<ClassifiedError | null>(null)\n const [cleared, setCleared] = useState(0)\n const [more, setMore] = useState(false)\n\n if (fieldKey === null) return null\n const confirmed = confirmationMatches(fieldKey, typed)\n\n async function purge(): Promise<void> {\n if (fieldKey === null || !confirmed || running) return\n\n setRunning(true)\n setFailure(null)\n\n try {\n const result = await adapter.fieldData.purge(type.slug, fieldKey)\n setCleared((total) => total + result.purged)\n setMore(result.remaining)\n if (!result.remaining) onPurged(fieldKey)\n } catch (thrown: unknown) {\n setFailure(classifyError(thrown, { action: \"delete these values\" }))\n } finally {\n setRunning(false)\n }\n }\n\n return (\n <Modal\n open\n onClose={onCancel}\n title={`Delete the stored values of ${fieldKey}?`}\n description=\"This is permanent. The values of this removed field are deleted from every entry, and nothing here can bring them back.\"\n width=\"sm\"\n dismissible={false}\n footer={\n <>\n <Button variant=\"secondary\" onClick={onCancel} disabled={running}>\n Cancel\n </Button>\n <Button\n variant=\"danger\"\n icon=\"delete\"\n loading={running}\n disabled={!confirmed}\n onClick={() => void purge()}\n >\n {more ? \"Delete the rest\" : \"Delete the values\"}\n </Button>\n </>\n }\n >\n <div className=\"flex flex-col gap-4\">\n {failure === null ? null : <ErrorNotice error={failure} />}\n\n {cleared === 0 ? null : (\n <p className=\"text-body-sm text-text-secondary\">\n {String(cleared)} {cleared === 1 ? \"entry\" : \"entries\"} cleared.\n {more\n ? \" More remain: a purge is bounded per call, so run it again to continue.\"\n : \"\"}\n </p>\n )}\n\n <p className=\"text-body-sm text-text-muted\">\n An entry that was saved while the field was empty holds an explicit empty value\n rather than a value, and is neither counted nor cleared.\n </p>\n\n <p className=\"text-body-sm text-text-muted\">\n Type <span className=\"text-body-medium text-text-primary\">{fieldKey}</span> to\n confirm.\n </p>\n <Field label=\"Confirmation\">\n {({ id }) => (\n <TextInput\n id={id}\n value={typed}\n autoFocus\n onChange={(event) => setTyped(event.target.value)}\n />\n )}\n </Field>\n </div>\n </Modal>\n )\n}\n","\"use client\"\n\nimport { useEffect, useState } from \"react\"\n\nimport type { CmsAdapter } from \"../../core/adapter.js\"\nimport type { ContentTypeLike } from \"../../types/content-type.js\"\nimport { Button } from \"../components/button.js\"\nimport { FormError } from \"../components/form-error.js\"\nimport { Modal } from \"../components/modal.js\"\nimport { Skeleton } from \"../components/skeleton.js\"\n\n/**\n * The removal warning, with a number in it.\n *\n * \"Some entries may hold data\" is not a warning, it is a shrug. `fieldData.count` asks\n * Firestore how many entries of this content type actually hold a value for this key, and\n * the dialog prints that number, because it is also exactly the number a later purge would\n * destroy: count and purge describe the same population by construction. See\n * .docs/decisions/2026-09-18-schema-field-removal.md.\n *\n * The promise the copy makes is the one the code keeps: removing a field changes the\n * definition and touches no entry. Deleting the values is a separate, separately confirmed\n * action, which is why there is no checkbox here that does it in passing.\n */\n\nexport interface RemoveFieldDialogProps {\n adapter: CmsAdapter\n type: ContentTypeLike\n /** The field to remove. Null means the dialog is closed. */\n fieldKey: string | null\n onCancel: () => void\n /** The definition change is the caller's: this dialog reads and confirms, never writes. */\n onConfirm: (fieldKey: string) => void\n}\n\nexport function RemoveFieldDialog(props: RemoveFieldDialogProps) {\n // One dialog per field, so a count read for one field can never be shown for another.\n return props.fieldKey === null ? null : (\n <RemoveFieldBody key={props.fieldKey} {...props} />\n )\n}\n\ntype CountState =\n | { kind: \"counting\" }\n | { kind: \"known\"; entries: number }\n /** The count failed. The removal is still safe; what is unknown is only the number. */\n | { kind: \"unknown\"; reason: string }\n\nfunction RemoveFieldBody({\n adapter,\n type,\n fieldKey,\n onCancel,\n onConfirm,\n}: RemoveFieldDialogProps) {\n const [count, setCount] = useState<CountState>({ kind: \"counting\" })\n const field = fieldKey === null ? undefined : type.fields[fieldKey]\n\n useEffect(() => {\n if (fieldKey === null) return\n let cancelled = false\n\n adapter.fieldData\n .count(type.slug, fieldKey)\n .then((entries) => {\n if (!cancelled) setCount({ kind: \"known\", entries })\n })\n .catch((error: unknown) => {\n if (cancelled) return\n setCount({\n kind: \"unknown\",\n reason:\n error instanceof Error ? error.message : \"The entries could not be counted.\",\n })\n })\n\n return () => {\n cancelled = true\n }\n }, [adapter, type.slug, fieldKey])\n\n if (fieldKey === null || field === undefined) return null\n\n return (\n <Modal\n open\n onClose={onCancel}\n title={`Remove ${field.label}?`}\n width=\"sm\"\n footer={\n <>\n <Button variant=\"secondary\" onClick={onCancel}>\n Cancel\n </Button>\n <Button variant=\"primary\" icon=\"delete\" onClick={() => onConfirm(fieldKey)}>\n Remove field\n </Button>\n </>\n }\n >\n <div className=\"flex flex-col gap-4\">\n {count.kind === \"counting\" ? (\n <Skeleton line=\"body\" className=\"w-64\" label=\"Counting the entries\" />\n ) : count.kind === \"unknown\" ? (\n <FormError>\n The entries could not be counted: {count.reason} Removing the field still\n keeps whatever is stored.\n </FormError>\n ) : (\n <p className=\"text-body-sm text-text-secondary\">\n {count.entries === 0\n ? `No entry holds a value for ${field.label} right now.`\n : `${String(count.entries)} ${count.entries === 1 ? \"entry holds\" : \"entries hold\"} a value for ${field.label}.`}\n </p>\n )}\n\n <p className=\"text-body-sm text-text-secondary\">\n Removing the field keeps every stored value. The field stops appearing in the\n form, in the list view and in the SDK, and no entry is written.\n </p>\n <p className=\"text-body-sm text-text-muted\">\n You can restore it later and the values come back unchanged. Deleting the values\n is a separate action, on this content type's screen, under Removed fields.\n </p>\n </div>\n </Modal>\n )\n}\n","\"use client\"\n\nimport { useState } from \"react\"\n\nimport type { CmsAdapter } from \"../../core/adapter.js\"\nimport { classifyError } from \"../../core/error-taxonomy.js\"\nimport type { ClassifiedError } from \"../../core/error-taxonomy.js\"\nimport type { Registry, RegistryEntry } from \"../../core/registry.js\"\nimport { isSchemaReadOnly } from \"../../core/registry.js\"\nimport type { FieldKeyAvailability, FieldRow } from \"../../core/schema-editor.js\"\nimport {\n checkFieldKey,\n draftIssues,\n orderedFields,\n sameDefinition,\n withFieldRows,\n} from \"../../core/schema-editor.js\"\nimport {\n forgetRemovedField,\n removeField,\n removedFieldEntries,\n restoreField,\n} from \"../../core/schema-fields.js\"\nimport { SchemaError } from \"../../core/errors.js\"\nimport { schemaVersionOf, storageShapeChanged } from \"../../core/schema-version.js\"\nimport { fieldTypes } from \"../../fields/index.js\"\nimport { can } from \"../../permissions/can.js\"\nimport type { AuthUser, PermissionMatrix } from \"../../types/auth.js\"\nimport type { ContentTypeLike } from \"../../types/content-type.js\"\nimport { Badge } from \"../components/badge.js\"\nimport { Button } from \"../components/button.js\"\nimport { Field, TextInput } from \"../components/field.js\"\nimport { ErrorNotice } from \"../components/error-notice.js\"\nimport { Icon } from \"../components/icon.js\"\nimport { ICON_NAMES } from \"../components/icon-names.js\"\nimport { PageHeader } from \"../components/page-header.js\"\nimport { Panel } from \"../components/panel.js\"\nimport { PageSections, Section } from \"../components/section.js\"\nimport { Select } from \"../components/select.js\"\nimport type { SelectOption } from \"../components/select.js\"\nimport { useOptionalToast } from \"../components/toast.js\"\nimport { formatDateTime } from \"../format.js\"\nimport { contentTypeLabel } from \"../navigation/navigation.js\"\n\nimport { FieldRows } from \"./field-editor.js\"\nimport { PermissionMatrixEditor } from \"./permission-matrix-editor.js\"\nimport { PurgeFieldDialog } from \"./purge-field-dialog.js\"\nimport { RemoveFieldDialog } from \"./remove-field-dialog.js\"\n\n/**\n * One content type in the Schema Builder: its settings, its fields, and what it has lost.\n *\n * `isSchemaReadOnly` is the single question this screen asks about whether it may edit\n * anything, and it is true for every code-sourced type, not only the ones marked `locked`.\n * A read-only type renders as a read-only type: the lock icon, a banner that says which of\n * the two reasons applies, no drag handles, no inputs, no remove buttons. The adapter\n * refuses the same writes independently, so the UI half is presentation and the rule lives\n * below it.\n *\n * Everything else on this screen is generated. The field list, the per-type options and the\n * validation controls all come from the field type registry, so this file names no field\n * type.\n */\n\nexport interface ContentTypeEditorProps {\n adapter: CmsAdapter\n registry: Registry\n entry: RegistryEntry\n user: AuthUser\n /** Where the Content Types list is, for the breadcrumb. */\n backHref?: string\n}\n\nconst ICON_OPTIONS: readonly SelectOption[] = [\n { value: \"\", label: \"Default for the kind\" },\n ...ICON_NAMES.map((name) => ({ value: name, label: name })),\n]\n\nexport function ContentTypeEditor({\n adapter,\n registry,\n entry,\n user,\n backHref,\n}: ContentTypeEditorProps) {\n const toast = useOptionalToast()\n const readOnly = isSchemaReadOnly(entry) || !can(user, \"manage-schema\")\n\n /** The stored definition this draft started from, and what a reload compares against. */\n const [source, setSource] = useState<ContentTypeLike>(entry.type)\n const [draft, setDraft] = useState<ContentTypeLike>(entry.type)\n const [rows, setRows] = useState<readonly FieldRow[]>(() => orderedFields(entry.type))\n const [saving, setSaving] = useState(false)\n const [failure, setFailure] = useState<ClassifiedError | null>(null)\n const [removing, setRemoving] = useState<string | null>(null)\n const [purging, setPurging] = useState<string | null>(null)\n\n const built = buildDraft(draft, rows)\n // Key-order independent, because the draft rebuilds the field map in display order and\n // the stored copy came back from Firestore sorted. A literal comparison would call an\n // untouched draft dirty.\n const dirty = built.ok && !sameDefinition(built.type, source)\n\n // The definition can also change from outside this screen: another tab, another admin,\n // or this screen's own save coming back through the listener. An untouched draft follows\n // it; a touched one is left alone, because silently discarding an edit is worse than\n // showing one that is behind.\n if (source !== entry.type && !dirty) {\n setSource(entry.type)\n setDraft(entry.type)\n setRows(orderedFields(entry.type))\n }\n\n const issues = draftIssues(fieldTypes, rows)\n const removed = removedFieldEntries(draft)\n const shapeChanged = built.ok && storageShapeChanged(source, built.type)\n\n /**\n * Applies one domain transform to the current draft.\n *\n * Removal, restore and forget are all functions of a whole content type, so the draft is\n * folded back into one first. A transform that refuses (the last field, the title field,\n * a restore that would change how values are stored) reports its own message rather than\n * leaving the screen in a state the domain would not accept.\n */\n function apply(transform: (type: ContentTypeLike) => ContentTypeLike): void {\n try {\n const next = transform(withFieldRows(draft, rows))\n setDraft(next)\n setRows(orderedFields(next))\n setFailure(null)\n } catch (thrown: unknown) {\n setFailure(classifyError(thrown, { role: user.role, subject: draft.label }))\n }\n }\n\n async function save(type?: ContentTypeLike): Promise<void> {\n const next = type ?? (built.ok ? built.type : undefined)\n if (next === undefined || saving) {\n // A draft that cannot even be folded into a content type is a schema refusal, which\n // the taxonomy files as validation: nothing was sent and a retry would not help.\n if (next === undefined && !built.ok) {\n setFailure(classifyError(new SchemaError(built.reason), { role: user.role }))\n }\n return\n }\n\n setSaving(true)\n setFailure(null)\n\n try {\n // The adapter validates again, refuses a code-defined or locked type again, and\n // stamps the version itself. Whatever it says is what the reader is shown.\n const written = await adapter.schemas.update(next.slug, next)\n setSource(written)\n setDraft(written)\n setRows(orderedFields(written))\n toast?.notify({ tone: \"success\", title: `${written.label} saved` })\n } catch (thrown: unknown) {\n setFailure(\n classifyError(thrown, {\n role: user.role,\n action: `save \"${next.label}\"`,\n subject: next.label,\n }),\n )\n } finally {\n setSaving(false)\n }\n }\n\n function discard(): void {\n setDraft(source)\n setRows(orderedFields(source))\n setFailure(null)\n }\n\n const contentTypeOptions: readonly SelectOption[] = registry.types.map((known) => ({\n value: known.type.slug,\n label: `${contentTypeLabel(known.type)} (${known.type.slug})`,\n }))\n\n const titleOptions: readonly SelectOption[] = [\n { value: \"\", label: \"Not set\" },\n ...rows.map((row) => ({ value: row.key, label: `${row.field.label} (${row.key})` })),\n ]\n\n return (\n <>\n <PageHeader\n title={draft.label}\n {...(draft.description === undefined ? {} : { description: draft.description })}\n breadcrumb={[\n { label: \"Developer\" },\n {\n label: \"Content Types\",\n ...(backHref === undefined ? {} : { href: backHref }),\n },\n { label: draft.label },\n ]}\n actions={\n readOnly ? undefined : (\n <>\n <Button variant=\"secondary\" onClick={discard} disabled={!dirty || saving}>\n Discard\n </Button>\n <Button\n variant=\"primary\"\n icon=\"save\"\n loading={saving}\n disabled={!dirty || issues.length > 0}\n onClick={() => void save()}\n >\n Save\n </Button>\n </>\n )\n }\n />\n\n <PageSections>\n {failure === null ? null : (\n <Section>\n <ErrorNotice error={failure} onRetry={() => void save()} />\n </Section>\n )}\n\n {issues.length === 0 ? null : (\n <Section>\n <Panel padding=\"compact\">\n <p className=\"text-body-sm text-danger\">\n {issues.length === 1\n ? \"One field is not finished yet:\"\n : `${String(issues.length)} fields are not finished yet:`}\n </p>\n <ul className=\"mt-2 flex flex-col gap-1\">\n {issues.map((issue) => (\n <li\n key={`${issue.key}-${issue.option}`}\n className=\"text-caption text-text-secondary\"\n >\n {issue.key}: {issue.message}\n </li>\n ))}\n </ul>\n </Panel>\n </Section>\n )}\n\n {readOnly ? <ReadOnlyBanner entry={entry} /> : null}\n\n <Section\n heading=\"Settings\"\n description={`${entry.source === \"code\" ? \"Defined in code\" : \"Created in the Schema Builder\"}, stored as \"${draft.slug}\", schema version ${String(schemaVersionOf(source))}.`}\n >\n <Panel>\n {readOnly ? (\n <dl className=\"flex flex-col gap-2 text-body-sm\">\n <SettingRow term=\"Name\" value={draft.label} />\n <SettingRow term=\"Plural\" value={draft.labelPlural ?? draft.label} />\n <SettingRow term=\"Slug\" value={draft.slug} />\n <SettingRow\n term=\"Kind\"\n value={draft.kind === \"singleton\" ? \"Singleton\" : \"Collection\"}\n />\n <SettingRow term=\"Icon\" value={draft.icon ?? \"Default for the kind\"} />\n <SettingRow term=\"Title field\" value={draft.titleField ?? \"Not set\"} />\n </dl>\n ) : (\n <div className=\"flex flex-col gap-5\">\n <Field label=\"Name\" required help=\"The singular name.\">\n {({ id }) => (\n <TextInput\n id={id}\n value={draft.label}\n onChange={(event) =>\n setDraft({ ...draft, label: event.target.value })\n }\n />\n )}\n </Field>\n\n {draft.kind === \"collection\" ? (\n <Field\n label=\"Plural\"\n optional\n help=\"Used for the list view and the sidebar.\"\n >\n {({ id }) => (\n <TextInput\n id={id}\n value={draft.labelPlural ?? \"\"}\n onChange={(event) =>\n setDraft(\n withContentTypeOption(\n draft,\n \"labelPlural\",\n event.target.value,\n ),\n )\n }\n />\n )}\n </Field>\n ) : null}\n\n <Field label=\"Description\" optional>\n {({ id }) => (\n <TextInput\n id={id}\n value={draft.description ?? \"\"}\n onChange={(event) =>\n setDraft(\n withContentTypeOption(draft, \"description\", event.target.value),\n )\n }\n />\n )}\n </Field>\n\n <Field label=\"Icon\" optional help=\"Shown in the sidebar beside the name.\">\n {({ id }) => (\n <Select\n id={id}\n options={ICON_OPTIONS}\n value={draft.icon ?? \"\"}\n onChange={(value) =>\n setDraft(withContentTypeOption(draft, \"icon\", value))\n }\n />\n )}\n </Field>\n\n <Field\n label=\"Title field\"\n optional\n help=\"What lists, pickers and entry headers print.\"\n >\n {({ id }) => (\n <Select\n id={id}\n options={titleOptions}\n value={draft.titleField ?? \"\"}\n onChange={(value) =>\n setDraft(withContentTypeOption(draft, \"titleField\", value))\n }\n />\n )}\n </Field>\n\n <p className=\"text-caption text-text-muted\">\n The slug and the kind cannot be changed. Both decide where every entry\n is stored, so changing one moves documents, which is a migration rather\n than an edit.\n </p>\n </div>\n )}\n </Panel>\n </Section>\n\n <Section\n heading=\"Fields\"\n description={\n readOnly\n ? \"The fields of this content type, as its code defines them.\"\n : \"Drag a field to reorder it, or focus its handle and press the up and down arrow keys.\"\n }\n >\n <FieldRows\n rows={rows}\n registry={fieldTypes}\n contentTypes={contentTypeOptions}\n readOnly={readOnly}\n label=\"Fields\"\n issues={issues}\n checkKey={(key) => checkKeyAgainstDraft(draft, rows, key)}\n onChange={setRows}\n onRemove={(key) => setRemoving(key)}\n />\n\n {shapeChanged ? (\n <p className=\"mt-3 text-caption text-warning\">\n These changes alter how entries are stored, so saving moves the schema\n version from {String(schemaVersionOf(source))} to{\" \"}\n {String(schemaVersionOf(source) + 1)}.\n </p>\n ) : null}\n </Section>\n\n {/* Part of the definition, so it saves with the rest of it: one Save button for\n one document, rather than a second write path an admin has to remember. */}\n <PermissionMatrixEditor\n type={draft}\n readOnly={readOnly}\n onChange={(next) => setDraft(withPermissions(draft, next))}\n />\n\n {removed.length === 0 ? null : (\n <Section\n heading=\"Removed fields\"\n description=\"Their definitions are parked here and their values are still stored on the entries.\"\n >\n <Panel padding=\"compact\">\n <ul className=\"flex flex-col gap-4\">\n {removed.map((entryRemoved) => (\n <li\n key={entryRemoved.key}\n className=\"flex flex-wrap items-center justify-between gap-3\"\n >\n <div className=\"min-w-0\">\n <p className=\"text-body-sm text-text-primary\">\n {entryRemoved.field.label}{\" \"}\n <span className=\"text-text-faint\">({entryRemoved.key})</span>\n </p>\n <p className=\"mt-1 text-caption text-text-muted\">\n Removed {formatDateTime(entryRemoved.removedAt)}. Its values are\n kept.\n </p>\n </div>\n {readOnly ? null : (\n <div className=\"flex items-center gap-2\">\n <Button\n size=\"sm\"\n variant=\"secondary\"\n icon=\"retry\"\n onClick={() =>\n apply((type) => restoreField(type, entryRemoved.key))\n }\n >\n Restore\n </Button>\n <Button\n size=\"sm\"\n variant=\"danger\"\n icon=\"delete\"\n disabled={dirty}\n onClick={() => setPurging(entryRemoved.key)}\n >\n Delete values\n </Button>\n </div>\n )}\n </li>\n ))}\n </ul>\n {dirty ? (\n <p className=\"mt-3 text-caption text-text-muted\">\n Save your changes before deleting any values: a purge acts on the stored\n definition, not on this draft.\n </p>\n ) : null}\n </Panel>\n </Section>\n )}\n </PageSections>\n\n <RemoveFieldDialog\n adapter={adapter}\n type={draft}\n fieldKey={removing}\n onCancel={() => setRemoving(null)}\n onConfirm={(key) => {\n apply((type) => removeField(type, key, { removedBy: user.uid }))\n setRemoving(null)\n }}\n />\n\n <PurgeFieldDialog\n adapter={adapter}\n type={source}\n fieldKey={purging}\n onCancel={() => setPurging(null)}\n onPurged={(key) => {\n setPurging(null)\n // Values first, then the parked definition, and the order is the adapter's rule\n // rather than this screen's preference: an interrupted purge must leave the field\n // listed as removed rather than unlisted with values nobody can see.\n try {\n void save(forgetRemovedField(withFieldRows(draft, rows), key))\n } catch (thrown: unknown) {\n setFailure(classifyError(thrown, { role: user.role, subject: draft.label }))\n }\n }}\n />\n </>\n )\n}\n\ntype BuiltDraft = { ok: true; type: ContentTypeLike } | { ok: false; reason: string }\n\n/** Folds the draft and its field rows into one content type, or says why it cannot. */\nfunction buildDraft(draft: ContentTypeLike, rows: readonly FieldRow[]): BuiltDraft {\n try {\n return { ok: true, type: withFieldRows(draft, rows) }\n } catch (thrown: unknown) {\n return {\n ok: false,\n reason: thrown instanceof Error ? thrown.message : String(thrown),\n }\n }\n}\n\n/**\n * Whether a key is free, asked against the draft rather than against the stored type.\n *\n * A key added a moment ago is not in `draft.fields` yet, only in `rows`, and offering it a\n * second time would produce two fields with one key.\n */\nfunction checkKeyAgainstDraft(\n draft: ContentTypeLike,\n rows: readonly FieldRow[],\n key: string,\n): FieldKeyAvailability {\n const inRows = rows.some((row) => row.key === key)\n if (inRows) {\n return {\n available: false,\n reason: \"live\",\n message: `\"${key}\" is already a field of this content type.`,\n }\n }\n\n return checkFieldKey(draft, key)\n}\n\n/**\n * Sets or clears one optional content type setting.\n *\n * An empty box deletes the key rather than storing `\"\"`. A `titleField` of `\"\"` names no\n * field and would fail validation; a `labelPlural` of `\"\"` would make the sidebar print\n * nothing at all.\n */\nfunction withContentTypeOption(\n type: ContentTypeLike,\n key: \"labelPlural\" | \"description\" | \"icon\" | \"titleField\",\n value: string,\n): ContentTypeLike {\n const next: { [property: string]: unknown } = { ...type }\n\n if (value === \"\") {\n delete next[key]\n } else {\n next[key] = value\n }\n\n return next as unknown as ContentTypeLike\n}\n\n/**\n * Sets or clears the permission matrix.\n *\n * `normalizePermissionMatrix` returns `undefined` for a matrix that matches the role\n * defaults, and that has to delete the key rather than store `undefined`: a stored copy of\n * the defaults would silently stop tracking them the day a default changes, and Firestore\n * refuses an undefined value outright.\n */\nfunction withPermissions(\n type: ContentTypeLike,\n matrix: PermissionMatrix | undefined,\n): ContentTypeLike {\n const next: { [property: string]: unknown } = { ...type }\n\n if (matrix === undefined) {\n delete next[\"permissions\"]\n } else {\n next[\"permissions\"] = matrix\n }\n\n return next as unknown as ContentTypeLike\n}\n\nfunction SettingRow({ term, value }: { term: string; value: string }) {\n return (\n <div className=\"flex gap-2\">\n <dt className=\"w-40 shrink-0 text-text-muted\">{term}</dt>\n <dd className=\"min-w-0 text-text-secondary\">{value}</dd>\n </div>\n )\n}\n\n/**\n * Why this content type cannot be edited here.\n *\n * Two different facts, and conflating them would leave an admin looking for a lock switch\n * that does not exist: a locked type is protected on purpose, and a code-defined type is\n * simply not the Schema Builder's to edit, locked or not.\n */\nfunction ReadOnlyBanner({ entry }: { entry: RegistryEntry }) {\n return (\n <Section>\n <Panel padding=\"compact\">\n <p className=\"flex items-center gap-2 text-body-sm text-text-primary\">\n <Icon name=\"locked\" size={14} />\n {entry.locked ? \"Locked\" : \"Defined in code\"}\n <Badge variant=\"info\">Read-only</Badge>\n </p>\n <p className=\"mt-2 text-body-sm text-text-secondary\">\n {entry.locked\n ? \"This content type is marked locked. Its definition is protected: it cannot be changed here, and the adapter refuses a schema write against it even when this screen is bypassed.\"\n : \"This content type is defined in TypeScript and lives in the project's code. Change the definition there and deploy. The Schema Builder writes database-defined types only, and the adapter refuses a schema write against a code-defined type even when this screen is bypassed.\"}\n </p>\n <p className=\"mt-2 text-caption text-text-muted\">\n Its entries are edited normally. Locking protects the structure, not the\n content.\n </p>\n </Panel>\n </Section>\n )\n}\n","\"use client\"\n\nimport type { ReactNode } from \"react\"\n\nimport { classifyError } from \"../../core/error-taxonomy.js\"\nimport type { Role } from \"../../types/auth.js\"\n\nimport { ErrorScreen } from \"./error-screen.js\"\n\n/**\n * The body of an admin route's error boundary.\n * Canonical source: .docs/styleguide/04-components.md section 19.\n *\n * A host mounts it from an `error.tsx`, which is where Next puts the boundary; this is the\n * fallback the boundary renders, classified through the same taxonomy as an error a screen\n * caught for itself. The host supplies one `error.tsx` per route segment so a failure in\n * the media library does not blank the whole admin, plus a `global-error.tsx` for the one\n * case a segment boundary cannot cover: a throw in the root layout itself.\n *\n * Two things it deliberately does not do:\n *\n * - **It never prints a stack trace or a raw digest string on its own line.** A boundary\n * that shows a blank page is bad; one that shows a stack is worse, because it looks\n * like the product broke open. In production Next replaces a server error's message\n * with a generic one and a digest, and the digest is appended to the sentence as a\n * reference rather than displayed as an error.\n * - **It never offers a retry the taxonomy refuses.** `reset` re-renders the segment,\n * which resolves a dropped connection and does nothing at all for a permission refusal.\n * Only a `transport` failure gets the button; everything else gets the way back the\n * host passed in, and the sidebar, which a route boundary keeps.\n */\nexport interface RouteErrorProps {\n /** Exactly what Next hands an `error.tsx`. */\n error: Error & { digest?: string }\n /** Next's re-render of the failed segment. */\n reset: () => void\n /** Shown above the panel. Name the area, so a boundary says where it fired. */\n title?: string | undefined\n /** The signed-in role, so a permission refusal can name who was refused. */\n role?: Role | undefined\n /** One way out, for a failure a retry cannot fix. A link back to the dashboard. */\n children?: ReactNode\n}\n\nexport function RouteError({ error, reset, title, role, children }: RouteErrorProps) {\n const classified = classifyError(error, {\n ...(role === undefined ? {} : { role }),\n action: \"load this page\",\n })\n\n const described =\n error.digest === undefined\n ? classified\n : {\n ...classified,\n message: `${classified.message} Reference: ${error.digest}.`,\n }\n\n return (\n <ErrorScreen\n error={described}\n {...(title === undefined ? {} : { title })}\n onRetry={reset}\n >\n {children}\n </ErrorScreen>\n )\n}\n","import type { ReactNode } from \"react\"\n\nimport { EmptyState } from \"../components/empty-state.js\"\nimport { PageHeader } from \"../components/page-header.js\"\nimport { Panel } from \"../components/panel.js\"\n\n/**\n * The 404 inside the admin.\n *\n * It renders inside the shell, with the sidebar still there, because a missing admin page\n * is a wrong turn inside the product and not an exit from it. Dropping someone onto a bare\n * framework error page takes away the one thing they need, which is a way back.\n *\n * Built from the empty state, centered in a panel, per .docs/styleguide/03-layout.md\n * section 5.5. The description deliberately says nothing about what does exist: a 404 is\n * also what an unauthenticated probe gets, and a list of real routes is an answer.\n */\nexport interface NotFoundScreenProps {\n /** One action: a link back to the dashboard. */\n children?: ReactNode\n}\n\nexport function NotFoundScreen({ children }: NotFoundScreenProps) {\n return (\n <>\n <PageHeader title=\"Page not found\" />\n <Panel>\n <EmptyState\n icon=\"search\"\n heading=\"This page does not exist\"\n description=\"The address may be mistyped, or the page may have been removed. Nothing was changed.\"\n action={children}\n />\n </Panel>\n </>\n )\n}\n","\"use client\"\n\nimport { useState } from \"react\"\nimport type { FormEvent } from \"react\"\n\nimport { Button } from \"../components/button.js\"\nimport { Field, TextInput } from \"../components/field.js\"\nimport { FormError } from \"../components/form-error.js\"\n\n/**\n * The Husk login screen.\n *\n * It owns no auth. The host passes `onSignIn`, which is expected to reject with an error\n * whose message can be shown, so the same screen serves the emulator, a real project, and\n * a test double without branching.\n *\n * Errors arrive from two directions and are rendered differently on purpose: a missing\n * field is the field's problem, a refused credential is the form's.\n */\nexport interface LoginCredentials {\n email: string\n password: string\n}\n\nexport interface LoginScreenProps {\n onSignIn: (credentials: LoginCredentials) => Promise<void>\n /** Set when the guard bounced an expired session here, so the user is told why. */\n expired?: boolean\n}\n\ninterface FieldErrors {\n email?: string\n password?: string\n}\n\nexport function LoginScreen({ onSignIn, expired = false }: LoginScreenProps) {\n const [email, setEmail] = useState(\"\")\n const [password, setPassword] = useState(\"\")\n const [fieldErrors, setFieldErrors] = useState<FieldErrors>({})\n const [formError, setFormError] = useState<string | null>(null)\n const [submitting, setSubmitting] = useState(false)\n\n async function handleSubmit(event: FormEvent<HTMLFormElement>) {\n event.preventDefault()\n\n const errors: FieldErrors = {}\n if (email.trim().length === 0) errors.email = \"Enter your email address.\"\n if (password.length === 0) errors.password = \"Enter your password.\"\n\n setFieldErrors(errors)\n if (errors.email !== undefined || errors.password !== undefined) return\n\n setFormError(null)\n setSubmitting(true)\n try {\n await onSignIn({ email: email.trim(), password })\n } catch (thrown) {\n // Whatever the server said, verbatim. The auth layer already phrases its refusals\n // for a person (\"Email or password is incorrect.\"), and rewriting them here would\n // hide the ones it has not phrased yet.\n setFormError(\n thrown instanceof Error ? thrown.message : \"Sign-in failed. Please try again.\",\n )\n setSubmitting(false)\n return\n }\n\n // No success branch that clears `submitting`: a successful sign-in navigates, and a\n // button that re-enables underneath a navigation invites a second submit.\n }\n\n return (\n <main className=\"flex min-h-dvh items-center justify-center bg-surface-base p-6\">\n <div className=\"w-full max-w-sm rounded-md border border-border-subtle bg-surface-card p-6\">\n <h1 className=\"text-heading-md text-text-primary\">Sign in to Husk</h1>\n <p className=\"mt-2 text-body-sm text-text-muted\">\n Use the email and password for this project.\n </p>\n\n <form className=\"mt-6 flex flex-col gap-5\" onSubmit={handleSubmit} noValidate>\n {expired && formError === null ? (\n <FormError>Your session expired. Sign in again to continue.</FormError>\n ) : null}\n {formError === null ? null : <FormError>{formError}</FormError>}\n\n <Field label=\"Email\" required error={fieldErrors.email}>\n {({ id, describedBy, invalid }) => (\n <TextInput\n id={id}\n name=\"email\"\n type=\"email\"\n autoComplete=\"username\"\n value={email}\n invalid={invalid}\n aria-describedby={describedBy}\n disabled={submitting}\n onChange={(event) => setEmail(event.target.value)}\n />\n )}\n </Field>\n\n <Field label=\"Password\" required error={fieldErrors.password}>\n {({ id, describedBy, invalid }) => (\n <TextInput\n id={id}\n name=\"password\"\n type=\"password\"\n autoComplete=\"current-password\"\n value={password}\n invalid={invalid}\n aria-describedby={describedBy}\n disabled={submitting}\n onChange={(event) => setPassword(event.target.value)}\n />\n )}\n </Field>\n\n <Button type=\"submit\" variant=\"primary\" loading={submitting} className=\"w-full\">\n Sign in\n </Button>\n </form>\n </div>\n </main>\n )\n}\n","import type { ReactNode } from \"react\"\n\nimport type { Action } from \"../../types/auth.js\"\nimport { EmptyState } from \"../components/empty-state.js\"\n\n/**\n * What a signed-in user sees where they are not allowed.\n *\n * Built on the empty state from .docs/styleguide/04-components.md section 15: one icon,\n * one heading, one description, at most one action.\n *\n * It says what was denied and to whom, and nothing about what would have been there. A\n * user who may not manage schemas does not need to learn what the schema list contains.\n */\nconst ACTION_COPY: Record<Action, string> = {\n read: \"view this content\",\n create: \"create entries here\",\n update: \"edit this entry\",\n delete: \"delete this entry\",\n \"manage-schema\": \"open the Developer area\",\n \"manage-users\": \"manage users\",\n \"manage-settings\": \"change settings\",\n \"manage-media\": \"manage media\",\n}\n\nexport interface UnauthorizedScreenProps {\n /** The permission that was denied, used only to phrase the sentence. */\n action?: Action\n /** The signed-in role, so the user can tell an access problem from a wrong account. */\n role?: string\n /** One action at most: a link back, or a sign-out. */\n children?: ReactNode\n}\n\nexport function UnauthorizedScreen({ action, role, children }: UnauthorizedScreenProps) {\n const what = action === undefined ? \"open this page\" : ACTION_COPY[action]\n\n return (\n <EmptyState\n icon=\"permissions\"\n heading=\"You do not have access\"\n description={`Your account is not allowed to ${what}.${\n role === undefined ? \"\" : ` You are signed in as ${role}.`\n }`}\n action={children}\n />\n )\n}\n"]}
|