import { ContentItem, ContentType, CustomFieldDef, CustomFieldType, FieldRule, FieldRules, PopupModal } from './types'; /** * Everything needed to resolve a field's rules: the per-type rules the host * passed, plus its custom fields (which carry their own `lockKey` / `max` / * `pinned`). Both are optional — a host that passes neither gets the * unconstrained editor it has today. */ export interface FieldRuleContext { rules?: FieldRules; customFields?: CustomFieldDef[]; } /** * The host field an item came from, if any. Prefers the explicit `fieldKey` * written by the picker, and falls back to matching the submit key so forms * saved before `fieldKey` existed still resolve their rules. */ export declare function fieldOfItem(item: ContentItem, customFields: CustomFieldDef[] | undefined): CustomFieldDef | undefined; /** * The rule governing one item. A custom field's own flags win over the per-type * rule, since the host was specific about that field; anything the field leaves * unset falls through to the type rule. */ export declare function ruleForItem(item: ContentItem, ctx: FieldRuleContext): FieldRule | undefined; /** A pinned field is implicitly capped at one, unless the host asked for more. */ export declare function effectiveMax(rule: FieldRule | undefined): number | undefined; /** Whether the author may edit this item's submit key. */ export declare function isKeyLocked(item: ContentItem, ctx: FieldRuleContext): boolean; /** Whether this item is always required, with no toggle to turn it off. */ export declare function isRequiredLocked(item: ContentItem, ctx: FieldRuleContext): boolean; /** Whether this item is barred from being made private. */ export declare function isPrivateLocked(item: ContentItem, ctx: FieldRuleContext): boolean; /** * What this item is to the host, for the chip on its card: the host field's * `roleLabel` (or its label), or a type rule's `roleLabel`. Undefined for an * item that isn't bound to anything the host declared, which is most of them. */ export declare function roleLabelForItem(item: ContentItem, ctx: FieldRuleContext): string | undefined; /** Whether this item is pinned, and so has no delete button. */ export declare function isPinned(item: ContentItem, ctx: FieldRuleContext): boolean; /** * A field the host recommends that the form doesn't have yet. The editor turns * each of these into a prompt with a one-click Add, so an author who needs the * integration to work is told rather than left to guess. Nothing is enforced: * ignoring the prompt is a valid form. */ export interface RecommendedPrompt { /** Stable identity for keys: the host field's key, or the content type. */ id: string; /** The type the added item will be. */ type: ContentType; /** The host field to add, when the recommendation came from one. */ field?: CustomFieldDef; /** The host's own explanation. Undefined falls back to the editor's copy. */ hint?: string; } /** * The recommended fields missing from a form, in the order a host declared them: * its own fields first, then per-type rules. A recommendation whose field is * already on the form (or already at its cap) doesn't prompt. */ export declare function missingRecommended(items: ContentItem[], ctx: FieldRuleContext): RecommendedPrompt[]; /** How many items in the form belong to a given host field. */ export declare function countField(items: ContentItem[], field: CustomFieldDef): number; /** How many items in the form are of a given type, whatever their origin. */ export declare function countType(items: ContentItem[], type: ContentType): number; /** * Whether another instance of a host field may be added. A field is at its cap * either through its own `max` or through the rule on the type it maps onto. * * A host field stands for one thing the backend stores ("First name"), and it * submits under one key, so the default cap is one: a second copy would collect * the same answer twice and overwrite itself on submit. A host that genuinely * wants repeats says so with an explicit `max`. */ export declare function fieldAtMax(field: CustomFieldDef, items: ContentItem[], ctx: FieldRuleContext): boolean; /** * Whether an author may create a new field of this type. Read only by the * picker's create form: a host that owns the type says `creatable: false` and * supplies the field itself. */ export declare function isCreatableType(type: CustomFieldType, ctx: FieldRuleContext): boolean; /** Whether another item of a built-in type may be added. */ export declare function typeAtMax(type: ContentType, items: ContentItem[], ctx: FieldRuleContext): boolean; /** * Stamp a rule's fixed submit key onto a freshly created item. Only applies to * new items: an existing form keeps whatever key it was saved with, so turning * a rule on never silently rewrites live forms. */ export declare function applyRuleKey(item: ContentItem, rule: FieldRule | undefined): ContentItem; /** A blank item of `type`, with any fixed key from the rules already applied. */ export declare function makeRuledContentItem(type: ContentType, order: number, ctx: FieldRuleContext): ContentItem; /** * Bring a form's items in line with the rules the host locked: `lockRequired` * forces `required: true`, `lockPrivate` clears `private`. Without this the * editor would hide the toggles while the stored JSON still said otherwise, and * the renderer follows the JSON. * * It matters for forms that predate a rule, and for forms a host assembled * itself. Returns the same object when everything already conforms. */ export declare function withEnforcedFieldRules(popup: PopupModal, ctx: FieldRuleContext): PopupModal; /** * Fill in the pinned fields a form is missing, so a form loaded from storage, * or handed back after a template swap, always carries them. Returns the same * object when nothing is missing, which is what lets callers use identity to * decide whether the host needs telling. * * New items land just above the submit button, which always sinks to the bottom. */ export declare function withPinnedFields(popup: PopupModal, ctx: FieldRuleContext): PopupModal;