import type { Field, FormAdminConfig, GroupDefinition, LayoutDefinition, RowDefinition, TabSetDefinition } from '@byline/core'; /** Which tab set + tab a schema field is placed under. */ export interface TabPath { tabSetName: string; tabName: string; } /** * Derived lookup tables that drive the form's layout walk and per-tab error * badges. All are pure derivations of `adminConfig` + `fields`; the startup * validator guarantees every reachable name resolves and every schema field is * placed at most once, so the consuming render-time lookups stay unguarded. */ export interface FormLayout { /** Schema field name → field definition. */ fieldByName: Map; tabSetByName: Map; rowByName: Map; groupByName: Map; /** Region placement; synthesised to `{ main: }` when omitted. */ layout: LayoutDefinition; /** Reverse index: schema field name → which tab set + tab it lives in. */ fieldToTabPath: Map; } /** * Build the reverse index from schema field name to its enclosing tab set + * tab. Fields not under any tab set (e.g. raw-field placement directly in * `layout.main`) are absent from the map. Rows and groups are recursed into; * the `seen` set guards against a config that references a row/group cycle. */ export declare function buildFieldToTabPath(adminConfig: FormAdminConfig | undefined, fieldByName: Map, rowByName: Map, groupByName: Map): Map; /** * Memoise the layout primitives + lookup tables the form renderer walks. * Rebuilt only when `adminConfig` / `fields` change. */ export declare function useFormLayout(adminConfig: FormAdminConfig | undefined, fields: Field[]): FormLayout;