import { IArrayDidChange, IArrayWillChange, IArrayWillSplice, IAtom, IObjectDidChange, IObjectWillChange, ObservableSet } from 'mobx';
import { Dispose } from '../utils/disposable';
type ParentNode = {
    object: object;
    path: string;
};
export type NodeChange = IObjectDidChange | IArrayDidChange;
export type NodeChangeListener = (change: NodeChange) => void;
/**
 * Represents a change that is about to happen to a node during the intercept phase.
 */
export type NodeInterceptedChange = IObjectWillChange | IArrayWillChange<any> | IArrayWillSplice<any>;
/**
 * Listener for intercepted changes. Must return:
 * - The change object (possibly modified) to accept the change
 * - null to cancel the change and stop propagation to parent listeners
 */
export type NodeInterceptedChangeListener = (change: NodeInterceptedChange) => NodeInterceptedChange | null;
type NodeData = {
    parent: ParentNode | undefined;
    parentAtom: IAtom | undefined;
    onChangeListeners: NodeChangeListener[] | undefined;
    onInterceptedChangeListeners: NodeInterceptedChangeListener[] | undefined;
    childrenObjects: ObservableSet<object> | undefined;
    frozen: boolean;
    observeDisposer: Dispose | undefined;
    ancestorChangeListenerRefCount: number;
};
export declare function getNodeData(node: object): NodeData;
export declare function reportNodeParentObserved(node: object): void;
/**
 * Checks if the given object is a MobX-Bonsai node.
 *
 * @param struct The object to check.
 * @returns `true` if the object is a MobX-Bonsai node, `false` otherwise.
 */
export declare function isNode(struct: unknown): boolean;
/**
 * Checks if the given node is frozen.
 * A frozen node is a node that cannot be modified.
 *
 * @param node - The object to check.
 * @returns `true` if the object is a node and is frozen, `false` otherwise.
 */
export declare function isFrozenNode(node: object): boolean;
/**
 * Asserts that the given object is a mobx-bonsai node.
 *
 * @param node The object to check.
 * @param argName The name of the argument being checked. This is used in the error message.
 * @throws If the object is not a mobx-bonsai node.
 */
export declare function assertIsNode(node: object, argName: string): void;
/**
 * Registers a deep change listener on the provided node that is called BEFORE changes are committed.
 *
 * The listener is invoked whenever the node is about to undergo a change, such as additions,
 * updates, or removals within its observable structure. This is called during the intercept phase,
 * before the change is actually applied. This includes receiving events from both object and array mutations.
 *
 * Note: The listener is called before the change is committed, so the node still has its old state.
 *
 * The listener must return one of the following:
 * - The received change object (possibly modified) to accept and apply the change
 * - null to cancel the change and stop propagation to parent listeners
 *
 * The listener can also throw an exception to prevent the change (e.g., if an invariant isn't met).
 *
 * @param node - The node to attach the intercepted change listener to.
 * @param listener - The callback function that is called when a change is about to occur.
 *   The listener receives a NodeInterceptedChange parameter and must return either the change
 *   object (to accept it) or null (to cancel it).
 *
 * @returns A disposer function that, when invoked, unregisters the listener.
 */
export declare function onDeepInterceptedChange(node: object, listener: NodeInterceptedChangeListener): Dispose;
/**
 * Registers a deep change listener on the provided node.
 *
 * The listener is invoked whenever the node undergoes a change, such as additions,
 * updates, or removals within its observable structure. This includes receiving
 * events from both object and array mutations.
 *
 * @param node - The node to attach the change listener to.
 * @param listener - The callback function that is called when a change occurs.
 *   The listener receives two parameters:
 *   - changeTarget: The node where the change occurred.
 *   - change: The change event, which is a NodeChange.
 *
 * @returns A disposer function that, when invoked, unregisters the listener.
 */
export declare function onDeepChange(node: object, listener: NodeChangeListener): Dispose;
export declare const runDetachingDuplicatedNodes: (fn: () => void) => void;
/**
 * Converts a plain/observable object or array into a mobx-bonsai node.
 * If the data is already a node it is returned as is.
 * If the data contains a type and key and they match an already existing node
 * then that node is reconciled with the new data and the existing node is returned.
 *
 * @param struct - The object or array to be converted.
 * @param options - Optional configuration object.
 * @property {boolean} [skipInit] - If true, skips the initialization phase.
 *
 * @returns The node, an enhanced observable structure.
 */
export declare const node: <T extends object>(struct: T, options?: {
    skipInit?: boolean;
}) => T;
export {};
