/* Types for adminSchema.js: the client half of the descriptor-driven admin CRUD engine. Rows are whatever columns the server-side descriptor in server/src/admin-schema.js declares, so they stay a string-keyed record; the descriptors are what's fixed. */ /** A row from /api/admin/:entity or /:entity/:id. Nested paths * ('region.scope') are side-table objects under their key, and * child collections are arrays of rows under theirs. */ export type AdminRow = Record; /** One row of an OPTION_QUERIES result. `kind` and `org_id` ride * along on the lists that filterBy narrows. */ export type AdminOption = { id: string; label: string; kind?: string; org_id?: string | null; }; /** GET /api/admin/options, keyed by OPTION_QUERIES name. */ export type AdminOptions = Record; export type FieldWidget = | "text" | "textarea" | "select" | "checkbox" | "color" | "number" | "date" | "time"; /** A bare value, or [value, label]. */ export type SelectOption = string | readonly [string, string]; /** Show a group or collection only when another field has this value. */ export type FieldCondition = { path: string; value: unknown }; export type AdminFieldSpec = { path: string; label: string; widget?: FieldWidget; required?: boolean; full?: boolean; help?: string; options?: readonly SelectOption[]; optionsFrom?: string; blankLabel?: string; filterBy?: (option: AdminOption, row: AdminRow) => boolean; /* Set by EntityEdit on the id field rather than in a manifest. */ readOnly?: boolean; prefix?: string; prefixPending?: boolean; placeholder?: string; }; export type FieldGroupSpec = { legend: string; note?: string; when?: FieldCondition; fields: AdminFieldSpec[]; }; export type CollectionSpec = { key: string; label: string; addLabel?: string; note?: string; when?: FieldCondition; title?: (row: AdminRow, options: AdminOptions | null | undefined) => string; blank: AdminRow; fields: AdminFieldSpec[]; children?: CollectionSpec[]; }; export type ListColumn = { key: string; label: string; primary?: boolean; widget?: "bool"; }; export type ListFilter = { key: string; label: string; options?: readonly SelectOption[]; optionsFrom?: string; }; export type EntitySpec = { key: string; label: string; singular: string; idLabel: string; /** "auto": the table assigns the id, so the form shows it rather than asking. */ idKind?: "auto"; /** Field(s) the slug is composed from. Absent when idKind is "auto". */ slugFrom?: string | string[]; titleFrom?: string; list: { columns: ListColumn[]; filters: ListFilter[] }; groups: FieldGroupSpec[]; children?: CollectionSpec[]; }; export type AdminEntityKey = | "organizations" | "events" | "people" | "teams" | "awards" | "timeline"; /* Indexed by route param as often as by name, so any other string reads as possibly missing. */ export declare const ADMIN_ENTITIES: { readonly [K in AdminEntityKey]: EntitySpec } & { readonly [key: string]: EntitySpec | undefined; }; export declare function slugify(value: unknown): string;