import type { InjectionKey, Ref } from 'vue';
export type FormState = Record<string, unknown>;
/**
 * Sentinel binding meaning "the bag's state itself", not a key inside it.
 * Used by `list` rows that hold scalar items: the inner field's `binding: '.'`
 * tells the bag to read/replace `state.value` wholesale instead of walking
 * into it as a dot-prop path. dot-prop has no notion of a self-path, so the
 * bag intercepts this before delegating.
 */
export declare const SELF_BINDING: ".";
/**
 * What kind of scope a bag represents.
 *
 * - `'form'`: a `<Form>` host — the user-facing record being edited.
 * - `'row'`: a single record inside an array slot (a table row provider, a
 *   list-field row). Functionally a form bag with array-position context.
 *
 * Used by `state.write` to resolve "commit out of the form I'm in": it skips
 * the nearest bag when it's `'form'`-kind, so a submit button living inside
 * a modal-opened sub-form writes through to the row/outer form that opened
 * it, not back into the about-to-close inner form. `'row'`-kind bags are
 * never skipped — a row-level action button writing to its own row is the
 * intended semantics (per-row "fill defaults / recalc this row").
 */
export type FormStateBagKind = 'form' | 'row';
export type FormStateBag = {
    kind: FormStateBagKind;
    /**
     * The bag one scope up the inject chain, or `undefined` at the root. Set
     * by `provideFormState` from whatever it inherits at provide time. Lets
     * `state.write` walk past a `'form'`-kind nearest without a second
     * inject — Vue exposes only the nearest, so the chain has to be threaded
     * through the bags themselves.
     */
    parent: FormStateBag | undefined;
    state: Ref<unknown>;
    getAt: (path: string) => unknown;
    /**
     * Write a value at `path` on behalf of a **user interaction**. Besides
     * writing, it marks the binding dirty — see `dirty`. Every field runtime
     * writes its bound value through this.
     */
    setAt: (path: string, value: unknown) => void;
    /**
     * Write a value at `path` **without** touching the dirty set — a system
     * write. Used by the derived-value engine (`useDerived`) and by the remote
     * combobox's stale-selection clear: neither is a user intent, so neither
     * may flip a `prefill` binding to "user-owned".
     */
    setAtSilent: (path: string, value: unknown) => void;
    /**
     * Bindings the user has touched. A `prefill`-mode derived value stops
     * filling a binding the moment it appears here — the user has taken over.
     * `setAt` adds to it (an explicit clear counts as a touch too); it is never
     * cleared during normal operation. Only undo/redo rolls it back, by
     * snapshotting it alongside `state` — see `history.ts`.
     */
    dirty: Ref<Set<string>>;
    isDirty: (path: string) => boolean;
    /**
     * Mark a binding dirty without writing a value — used by `useDerived` at
     * startup to claim every `initial`-seeded / loaded value, so a `prefill`
     * expression will not overwrite it.
     */
    markDirty: (path: string) => void;
};
export declare const FORM_STATE_KEY: InjectionKey<FormStateBag>;
export declare function provideFormState(state: Ref<unknown>, kind?: FormStateBagKind): FormStateBag;
export declare function useFormState(): FormStateBag;
